wp-plugin-swiss-football-ma.../assets/blocks.js
Reindl David (IT-PTR-CEN2-SL10) fbd595aa36 initial state
2026-03-18 19:58:24 +01:00

298 lines
11 KiB
JavaScript

// Swiss Football Blocks Frontend JavaScript
(function($) {
'use strict';
// Team selector functionality for blocks
window.swiFootSelectTeam = function(teamId, blockType) {
if (!teamId) return;
// This could be enhanced to use AJAX for dynamic loading
const url = new URL(window.location);
url.searchParams.set('swi_foot_team_' + blockType, teamId);
window.location.href = url.toString();
};
// Auto-refresh functionality for events shortcodes
$(document).ready(function() {
initEventRefresh();
setupShortcodeHelpers();
});
/**
* Initialize event refresh polling for all match event shortcodes on page
*
* Finds all `.swi-foot-events[data-match-id][data-refresh]` elements and sets up
* automatic polling based on the configured refresh interval. Respects match status
* (does not update UI until match starts, stops polling when match ends).
*
* @returns {void}
*/
function initEventRefresh() {
const $eventContainers = $('.swi-foot-events[data-match-id][data-refresh]');
if ($eventContainers.length === 0) return;
$eventContainers.each(function() {
const $container = $(this);
const matchId = $container.data('match-id');
const interval = parseInt($container.data('refresh')) || 30;
if (!matchId) return;
// Initial check: determine if match has started and if it should refresh
checkMatchStatusAndRefresh($container, matchId, interval);
});
}
/**
* Initialize polling interval for match events
*
* Sets up a setInterval that periodically fetches the latest events for a match.
* Automatically clears the interval when the match ends.
*
* @param {jQuery} $container - jQuery element for the event container
* @param {string} matchId - ID of the match to fetch events for
* @param {number} interval - Refresh interval in seconds (e.g., 30)
* @returns {void}
*/
function checkMatchStatusAndRefresh($container, matchId, interval) {
fetchMatchEvents($container, matchId);
// Set up polling - will stop automatically once match ends
const pollInterval = setInterval(function() {
const hasEnded = $container.data('match-ended');
// Stop polling if match has ended
if (hasEnded) {
clearInterval(pollInterval);
return;
}
fetchMatchEvents($container, matchId);
}, interval * 1000);
}
/**
* Fetch latest match events from REST API
*
* Makes an authenticated request to `/wp-json/swi-foot/v1/events/{matchId}` to
* retrieve the current list of match events. Updates container data with match
* status (started/ended). Only updates the DOM if the match has started.
*
* @param {jQuery} $container - jQuery element for the event container
* @param {string} matchId - Match ID to fetch events for
* @returns {void}
*/
function fetchMatchEvents($container, matchId) {
const restUrl = window.swiFootRest ? window.swiFootRest.rest_url : '/wp-json';
const nonce = window.swiFootRest ? window.swiFootRest.rest_nonce : '';
// Get event order from data attribute
const eventOrder = $container.data('event-order') || 'dynamic';
// Build URL with event_order parameter
let url = restUrl + 'swi-foot/v1/events/' + encodeURIComponent(matchId);
if (eventOrder && eventOrder !== 'dynamic') {
url += '?event_order=' + encodeURIComponent(eventOrder);
}
fetch(url, {
method: 'GET',
credentials: 'same-origin',
headers: {
'X-WP-Nonce': nonce
}
})
.then(function(resp) {
if (!resp.ok) throw new Error('Failed to fetch events');
return resp.json();
})
.then(function(data) {
if (!data) return;
// Track match status for polling control
$container.data('match-started', data.hasMatchStarted);
$container.data('match-ended', data.hasMatchEnded);
// Only update if match has started
if (!data.hasMatchStarted) {
return; // Don't update UI, match hasn't started yet
}
// Update events list
updateEventsList($container, data.events);
})
.catch(function(err) {
console.error('Error fetching match events:', err);
});
}
/**
* Update the events timeline display with new events
*
* Renders an HTML list of match events from the API response, sorted newest first.
* Handles empty event lists with a localized message. Updates the `.events-timeline`
* element within the container.
*
* @param {jQuery} $container - jQuery element for the event container
* @param {Array<Object>} events - Array of event objects with matchMinute, eventTypeName, playerName, teamName
* @returns {void}
*/
function updateEventsList($container, events) {
const $timeline = $container.find('.events-timeline');
if ($timeline.length === 0) return;
// Build HTML for events
let html = '';
if (events && events.length > 0) {
events.forEach(function(event) {
html += '<div class="event-item">';
html += '<div class="event-time">' + (event.matchMinute || '') + '\'</div>';
html += '<div class="event-content">';
html += '<div class="event-type">' + (event.eventTypeName || '') + '</div>';
html += '<div class="event-details">';
if (event.playerName) {
html += '<span class="player">' + event.playerName + '</span>';
}
if (event.teamName) {
html += '<span class="team">(' + event.teamName + ')</span>';
}
html += '</div></div></div>';
});
} else {
html = '<p>' + (window.swiFootNoEvents || 'No events recorded yet.') + '</p>';
}
$timeline.html(html);
}
function setupShortcodeHelpers() {
// Add copy functionality to shortcode examples in admin
if ($('.shortcode-group code').length > 0) {
$('.shortcode-group code').each(function() {
const $code = $(this);
$code.css('cursor', 'pointer');
$code.attr('title', 'Click to copy shortcode');
$code.on('click', function() {
const shortcode = $(this).text();
copyToClipboard(shortcode);
});
});
}
}
function copyToClipboard(text) {
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text).then(function() {
showNotification('Shortcode copied to clipboard!', 'success');
}).catch(function() {
fallbackCopyTextToClipboard(text);
});
} else {
fallbackCopyTextToClipboard(text);
}
}
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.left = '-999999px';
textArea.style.top = '-999999px';
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand('copy');
showNotification('Shortcode copied to clipboard!', 'success');
} catch (err) {
showNotification('Failed to copy shortcode', 'error');
}
document.body.removeChild(textArea);
}
function showNotification(message, type) {
const $notification = $('<div class="swi-foot-notification swi-foot-notification-' + type + '">' + message + '</div>');
$notification.css({
position: 'fixed',
top: '20px',
right: '20px',
padding: '10px 15px',
borderRadius: '4px',
color: '#fff',
fontSize: '14px',
zIndex: '10000',
opacity: '0',
transform: 'translateY(-20px)',
transition: 'all 0.3s ease'
});
if (type === 'success') {
$notification.css('backgroundColor', '#28a745');
} else {
$notification.css('backgroundColor', '#dc3545');
}
$('body').append($notification);
// Animate in
setTimeout(function() {
$notification.css({
opacity: '1',
transform: 'translateY(0)'
});
}, 100);
// Remove after 3 seconds
setTimeout(function() {
$notification.css({
opacity: '0',
transform: 'translateY(-20px)'
});
setTimeout(function() {
$notification.remove();
}, 300);
}, 3000);
}
// Initialize tooltips for match elements
$(document).ready(function() {
$('.swi-foot-match-container [title]').each(function() {
const $element = $(this);
$element.on('mouseenter', function() {
// Simple tooltip implementation
const title = $element.attr('title');
if (title) {
const $tooltip = $('<div class="swi-foot-tooltip">' + title + '</div>');
$tooltip.css({
position: 'absolute',
background: '#333',
color: '#fff',
padding: '5px 8px',
borderRadius: '4px',
fontSize: '12px',
zIndex: '1000',
whiteSpace: 'nowrap'
});
$('body').append($tooltip);
const rect = this.getBoundingClientRect();
$tooltip.css({
left: rect.left + (rect.width / 2) - ($tooltip.outerWidth() / 2),
top: rect.top - $tooltip.outerHeight() - 5
});
}
}).on('mouseleave', function() {
$('.swi-foot-tooltip').remove();
});
});
});
})(jQuery);