// The API key, dynamically changed every 5 minutes. var apiKey = '23b86f84584a6796125f8795f982b08e1c305d424fc3c6b219b815d1c98d12e2'; // Define of the timer for the long auto refresh var AUTO_REFRESH_TIMER_LONG = 60000; // Define of the timer for the short auto refresh var AUTO_REFRESH_TIMER_SHORT = 30000; // The limit on the day navigation on live page var DAY_NAV_LIMIT = 6; // Date variable used to avoid caching problems var d; // Holds the currently opened results var openResults = []; // Flag indicating if previous TV matches are shown or not before doing a refresh. var showPreviousTvMatches = false; // The previous WP TV ads if any. var previousWpTvAds = {}; // The default limits for number of latest/coming matches. var limitLatestMatches = 10; var limitComingMatches = 10; // The default totals of latest/coming matches. var totalLatestMatches = 20; var totalComingMatches = 20; // The title of the leage. var leagueTitle; // The selected season. var season; // The active season. var activeSeason; // The league base url i.e. permalink. var leagueBaseUrl; // The sport to render, applicable when rendering mathes for a day var sport; // The day to render matches for. var day = 0; // The id of the league to render. var leagueId = -1; // The api to call based on whether it's a regular league or a cup league var apiCall = 'league'; // The league renderer ready listener. var readyListener = null; $(document).ready(function () { // Hide dummy divs for live navigation initially. $("#live-nav-left-empty").hide(); $("#live-nav-right-empty").hide(); }); window.onpageshow = function(event) { // Hack to handle navigation from match box to page, and then pressing back. For some reason // the spinner would not go away. This make sure it will go away. $("#loading").removeClass("active"); }; /** * Set the id of the league to render. * * @param {String} id the league id. */ function setLeagueId(id) { leagueId = id; } /** * Set the API to call. * * @param {String} api the API to call. */ function setApiCall(api) { apiCall = api; } /** * Set a listener that will be called once the league * renderer is ready to be used. This is mainly for * the functionality related to more latest/comming * matches. * * @param {Function} onLeagueRendererReadyListener the function * that will receive the callback once the league renderer is * ready. */ function setLeagueRendererReadyListener(onLeagueRendererReadyListener) { readyListener = onLeagueRendererReadyListener; } /** * Add the match box listener. Called after the page has been refreshed. */ function addMatchBoxListener() { console.log("addMatchBoxListener - start"); // Set click listener for all match boxes. $('div.match-box a').click(function(e) { if ((location.hostname === this.hostname || !this.hostname.length) && !!this.href && (this.href.indexOf('#') === -1) && (this.href.indexOf('mailto:') === -1)) { $("#loading").addClass("active"); } }); console.log("addMatchBoxListener - end"); } /** * Store the current state of hide/show previous TV matches. So that it can be restored after * refreshing the page. */ function storeHideShowPreviousTvMatches() { console.log("soreHideShowPreviousTvMatches - start"); showPreviousTvMatches = !!$('.inactive.show').length; previousWpTvAds = {}; $("div.pr.wp-tv").each(function (i, obj) { previousWpTvAds[obj.id] = obj; }); previousWpTvAds console.log("soreHideShowPreviousTvMatches - end"); } /** * Restore the current state of hide/show previous TV matches. Called after the page has been * refreshed. */ function restoreHideShowPreviousTvMatches() { console.log("restoreHideShowPreviousTvMatches - start"); if (showPreviousTvMatches) { $('.inactive').addClass('show'); $('#hide-show-matches-text').text('Dölj avslutade matcher'); } else { $('.inactive').removeClass('show'); $('#hide-show-matches-text').text('Visa avslutade matcher'); } Object.keys(previousWpTvAds).forEach(function (id) { $("div#"+id).replaceWith(previousWpTvAds[id]); }); console.log("restoreHideShowPreviousTvMatches - end"); } /** * Check if there are more latest matches to show. * * @returns {Boolean} true if there are more latest * matches to show. */ function hasMoreLatestMatches() { return (leagueId !== -1) && (limitLatestMatches < totalLatestMatches); } /** * Check if there are more coming matches to show. * * @returns {Boolean} true if there are more coming * matches to show. */ function hasMoreComingMatches() { return (leagueId !== -1) && (limitComingMatches < totalComingMatches); } /** * Get the matches limit cookie. * * @param id the ID of the league. * @returns the matches limit cookie. */ function getLimitCookie(id) { var match = document.cookie.match(new RegExp('(^| )' + "limit\-" + id + '=([^;]+)')); if (match) return match[2].split(','); } /** * Set the matches limit cookie. * * @param id the ID of the league. * @param latest limit for the latest games. * @param coming limit for the coming games. * @param maxAge the max age of the cookie in seconds. */ var setLimitCookie = function(id, latest, coming, maxAge=600) { document.cookie = "limit-" + id + "=" + latest + "," + coming + "; max-age=" + maxAge; }; /** * Get the matches for day cookie. * * @param sport the sport ID. * @returns the matches for day cookie. */ function getDayCookie(sport) { var match = document.cookie.match(new RegExp('(^| )' + "sport\-" + sport + '=([^;]+)')); if (match) return match[2].split(',')[0]; return 0; } /** * Set the matches for day cookie. * * @param sport the sport ID. * @param day the day to set, 0 for today. * @param maxAge the max age of the cookie in seconds. */ var setDayCookie = function(sport, day, maxAge=600) { document.cookie = "sport-" + sport + "=" + day + "; max-age=" + maxAge; }; /** * Get more latest matches. * * @param {integer} latestLimit the limit of the total number * of latest matches to get. * @param {integer} comingLimit the limit of the total number * of coming matches to get. * @param {Function} onCompletedListener a callback function that will * be called once this function has completed. */ function getMoreLatestMatches(latestLimit, comingLimit, onCompletedListener) { if (hasMoreLatestMatches()) { // Store the new limit storedLatestLimit = !!getLimitCookie() ? getLimitCookie()[0] : 0; storedComingLimit = !!getLimitCookie() ? getLimitCookie()[1] : 0; limitLatestMatches = Math.max(latestLimit, storedLatestLimit, limitLatestMatches); limitComingMatches = Math.max(comingLimit, storedComingLimit, limitComingMatches); setLimitCookie(leagueId, limitLatestMatches, limitComingMatches); location.reload(); return; // This is old solutions, uncomment and remoe above reload to enable it. // // Fetch the result // var d = new Date(); // storeOpenResults(); // $.getJSON('/api/router.php', { // route: apiCall, id: leagueId, // latestMatchesOnly: true, // limitLatestMatches: limitLatestMatches, // dTime: d.getTime(), apiKey: apiKey // }, // function (result) { // // Store the total number of matches // totalLatestMatches = result.numberOfMatches; // if ((result.latest !== null) && isNonEmpty(result.matches)) { // $("section#latest-matches .area").empty().append(result.matches); // } // if (onCompletedListener) { // // Notify the caller that we are done // onCompletedListener(); // } // } // ); } else { if (onCompletedListener) { // Notify the caller that we are done onCompletedListener(); } } } /** * Get more upcoming matches. * * @param {integer} limit the limit of the total number * of coming matches to get. * @param {Function} onCompletedListener a callback function that will * be called once this function has completed. */ function getMoreUpcomingMatches(latestLimit, comingLimit, onCompletedListener) { if (hasMoreComingMatches()) { // Store the new limit storedLatestLimit = !!getLimitCookie() ? getLimitCookie()[0] : 0; storedComingLimit = !!getLimitCookie() ? getLimitCookie()[1] : 0; limitLatestMatches = Math.max(latestLimit, storedLatestLimit, limitLatestMatches); limitComingMatches = Math.max(comingLimit, storedComingLimit, limitComingMatches); setLimitCookie(leagueId, limitLatestMatches, limitComingMatches); location.reload(); return; // This is old solutions, uncomment and remoe above reload to enable it. // // Fetch the result // var d = new Date(); // storeOpenResults(); // $.getJSON('/api/router.php', { // route: apiCall, id: leagueId, // comingMatchesOnly: true, // limitComingMatches: limitComingMatches, // dTime: d.getTime(), apiKey: apiKey // }, // function (result) { // // Store the total number of matches // totalComingMatches = result.numberOfMatches; // if ((result.upcoming !== null) && isNonEmpty(result.matches)) { // $("section#coming-matches .area").empty().append(result.matches); // } // if (onCompletedListener) { // // Notify the caller that we are done // onCompletedListener(); // } // } // ); } else { if (onCompletedListener) { // Notify the caller that we are done onCompletedListener(); } } } /** * Get matches for the next day. */ function getNextDay() { day = !!getDayCookie(sport) ? getDayCookie(sport): day; setDayCookie(sport, ++day); $("#loading").addClass("active"); location.reload(); // This is old solutions, uncomment and remoe above reload to enable it. // d = new Date(); // $.get('/api/router.php', { // route: 'matches', sport: sport, day: day + 1, // dTime: d.getTime(), apiKey: apiKey // }, // function (response) { // // Increase the day parameter // day++; // setDayCookie(sport, day); // replaceLiveResultOnPage(response); // } // ); } /** * Get matches for the previous day. */ function getPreviousDay() { day = !!getDayCookie(sport) ? getDayCookie(sport): day; setDayCookie(sport, --day); $("#loading").addClass("active"); location.reload(); // This is old solutions, uncomment and remoe above reload to enable it. // d = new Date(); // $.get('/api/router.php', { // route: 'matches', sport: sport, day: day - 1, // dTime: d.getTime(), apiKey: apiKey // }, // function (response) { // // Decrease the day parameter // day--; // setDayCookie(sport, day); // replaceLiveResultOnPage(response); // } // ); } /** * Render the match details for a given match and start a timer to continuously refresh the result. */ function renderMatchDetails() { // Create function for updating match details. var updateMatchDetails = function () { if (!document.hidden) { d = new Date(); $.get('/api/router.php', { route: 'match-details', matchId: matchId, leagueLink: leagueLink, dTime: d.getTime(), apiKey: apiKey }, function (response) { replaceMatchDetailsOnPage(response); } ); } else { console.log("renderMatchDetails: Page does not have visibility."); } }; // Set a timer to update once each minute setInterval(function () { updateMatchDetails(); }, getRefreshTimerInterval()); setVisibilityChangeListener(updateMatchDetails); } /** * Render the tv matches for a sport and start a timer to continuously refresh the result. */ function renderTvMatches() { // Create function for updating match details. var updateTvMatches = function () { if (!document.hidden) { d = new Date(); storeHideShowPreviousTvMatches(); $.get('/api/router.php', { route: 'tv-matches', sport: sport, dTime: d.getTime(), apiKey: apiKey }, function (response) { replaceTvMatchesOnPage(response); restoreHideShowPreviousTvMatches(); } ); } else { console.log("renderTvMatches: Page does not have visibility."); } }; // Set a timer to update once each minute setInterval(function () { updateTvMatches(); }, getRefreshTimerInterval()); setVisibilityChangeListener(updateTvMatches); } /** * Render the result from an ordinary league and start * a timer to continuously refresh the result. * * @param {String} leagueId the id of the league as a string * @param limitLatest the limit of the latest matches to fetch. * @param limitComing the limit of the coming matches to fetch. */ function renderLeague(leagueId, limitLatest=0, limitComing=0) { storedLatestLimit = !!getLimitCookie(leagueId) ? getLimitCookie(leagueId)[0] : 0; storedComingLimit = !!getLimitCookie(leagueId) ? getLimitCookie(leagueId)[1] : 0; // Backup the league id setLeagueId(leagueId); // Backup the API call setApiCall('league'); limitLatestMatches = Math.max(limitLatest, storedLatestLimit, limitLatestMatches); limitComingMatches = Math.max(limitComing, storedComingLimit, limitComingMatches); console.log("limitLatestMatches=" + limitLatestMatches); console.log("storedLatestLimit=" + storedLatestLimit, getLimitCookie(leagueId)); console.log("limitLatest=" + limitLatest); // Create function for updating league var updateLeague = function (notifyReady) { if (!document.hidden) { var d = new Date(); $.getJSON('/api/router.php', { route: 'league', id: leagueId, limitLatestMatches: limitLatestMatches, limitComingMatches: limitComingMatches, leagueTitle: leagueTitle, season: season, activeSeason: activeSeason, leagueBaseUrl: leagueBaseUrl, dTime: d.getTime(), apiKey: apiKey }, function (response) { replaceLeagueResultOnPage(response); if (notifyReady && readyListener) { readyListener(); } } ); } else { console.log("renderLeague: Page does not have visibility."); } }; // Update the league and notify that we are ready // updateLeague(true); setTimeout(function () { if (readyListener) { readyListener(); } }, 500); // Set a timer to update once each minute setInterval(function () { updateLeague(false); }, getRefreshTimerInterval()); setVisibilityChangeListener(updateLeague); } /** * Render the matches for a given sport and day and start * a timer to continuously refresh the result. */ function renderMatchesForDay() { day = !!getDayCookie(sport) ? getDayCookie(sport): day; // Create function for updating matches var updateMatchesForDay = function () { if (!document.hidden) { d = new Date(); $.get('/api/router.php', { route: 'matches', sport: sport, day: day, dTime: d.getTime(), apiKey: apiKey }, function (response) { setDayCookie(sport, day); replaceLiveResultOnPage(response); } ); } else { console.log("renderMatchesForDay: Page does not have visibility."); } }; // Update the matches //updateMatchesForDay(); // Set a timer to update once each minute setInterval(function () { updateMatchesForDay(); }, getRefreshTimerInterval()); setVisibilityChangeListener(updateMatchesForDay); } /** * Replaces the results on a page for a league. * * @param {Object} result the new result that should be used * when populating the page. */ function replaceLeagueResultOnPage(result) { // Store the total number of matches totalLatestMatches = result.numberOfLatestMatches; totalComingMatches = result.numberOfUpcomingMatches; if ((result.ongoing !== null) && isNonEmpty(result.ongoing)) { $("section#ongoing-matches .area").empty().append(result.ongoing); $("div#ongoing-matches-pr").show(); $("section#ongoing-matches").show(); } else { $("div#ongoing-matches-pr").hide(); $("section#ongoing-matches").hide(); } if ((result.latest !== null) && isNonEmpty(result.latest)) { $("section#latest-matches .area").empty().append(result.latest); $("div#latest-matches-pr").show(); $("section#latest-matches").show(); } else { $("a#latest-results-button-desktop").hide(); $("a#latest-results-button-touch").hide(); $("div#latest-matches-pr").hide(); $("section#latest-matches").hide(); } if ((result.playoff !== null) && isNonEmpty(result.playoff)) { $("section#playoff .area").empty().append(result.playoff); $("div#playoff-pr").show(); $("section#playoff").show(); } else { $("div#playoff-pr").hide(); $("section#playoff").hide(); } if ((result.standings !== null) && isNonEmpty(result.standings)) { $("section#standings-table .area").empty().append(result.standings); $("div#standings-table-pr").show(); $("section#standings-table").show(); } else { $("a#table-button-desktop").hide(); $("a#table-button-touch").hide(); $("div#standings-table-pr").hide(); $("section#standings-table").hide(); } if ((result.scorers !== null) && isNonEmpty(result.scorers)) { $("section#top-scorers .area").empty().append(result.scorers); $("div#top-scorers-pr").show(); $("section#top-scorers").show(); } else { $("a#scorers-button-desktop").hide(); $("a#scorers-button-touch").hide(); $("div#standings-table-pr").hide(); $("section#top-scorers").hide(); } if ((result.upcoming !== null) && isNonEmpty(result.upcoming)) { $("section#coming-matches .area").empty().append(result.upcoming); $("div#coming-matches-pr").show(); $("section#coming-matches").show(); } else { console.log("No upcoming matches"); $("a#upcoming-matches-button-desktop").hide(); $("a#upcoming-matches-button-touch").hide(); $("div#top-scorers-pr").hide(); $("section#coming-matches").hide(); } if ((result.tv !== null) && isNonEmpty(result.tv)) { $("section#tv-matches .area").empty().append(result.tv); $("section#tv-matches").show(); } else { console.log("No tv matches"); $("a#tv-matches-button-desktop").hide(); $("a#tv-matches-button-touch").hide(); $("div#coming-matches-pr").hide(); $("section#coming-matches").hide(); } addMatchBoxListener(); } /** * Replaces the results on a page for the live matches. * * @param {Object} liveResults the new result that should be used * when populating the page. */ function replaceLiveResultOnPage(liveResults) { console.log("replaceLiveResultOnPage - start"); // Empty the old result and hide initially $("div#live-matches-container").empty(); $("div#live-matches-container").append(liveResults); $("div#live-matches-container").show(); if (day < -DAY_NAV_LIMIT) { $("#live-nav-left").hide(); $("#live-nav-right").show(); $("#live-nav-left-empty").show(); $("#live-nav-right-empty").hide(); } else if (day > DAY_NAV_LIMIT) { $("#live-nav-left").show(); $("#live-nav-right").hide(); $("#live-nav-left-empty").hide(); $("#live-nav-right-empty").show(); } else { $("#live-nav-left").show(); $("#live-nav-right").show(); $("#live-nav-right-empty").hide(); $("#live-nav-left-empty").hide(); } addMatchBoxListener(); console.log("replaceLiveResultOnPage - end"); } /** * Replaces the results on a page for the match details. * * @param {Object} matchDetails the new result that should be used when populating the page. */ function replaceMatchDetailsOnPage(tvMatches) { // Empty the old result and hide initially $("div#match-details-container").empty(); $("div#match-details-container").append(tvMatches); $("div#match-details-container").show(); addMatchBoxListener(); } /** * Replaces the results on a page for the tv matches. * * @param {Object} matchDetails the new result that should be used when populating the page. */ function replaceTvMatchesOnPage(matchDetails) { // Empty the old result and hide initially $("div#tv-matches-container").empty(); $("div#tv-matches-container").append(matchDetails); $("div#tv-matches-container").show(); addMatchBoxListener(); } /** * Check if a string is non empty. * * @param {String} value the string value to check. * * @returns {Boolean} true if the string is non empty, false * otherwise. */ function isNonEmpty(value) { return ((typeof value !== 'undefined') && (value.length > 0)); } /** * Get the refresh timer interval to use. * * @returns the refresh timer interval. */ function getRefreshTimerInterval() { if (sport == 4) { return AUTO_REFRESH_TIMER_SHORT; } else { return AUTO_REFRESH_TIMER_LONG; } } /** * Set the visibility on the menu buttons. * * @param showLatestButton indicates if latest results button should be shown. * @param showStandingsButton indicates if standings button should be shown. * @param showScorersButton indicates if scorers button should be shown. * @param showUpcomingButton indicates if upcoming matches button should be shown. * @param showTvButton indicates if tv button should be shown. */ function setVisibilityOnButtons(showLatestButton, showStandingsButton, showScorersButton, showUpcomingButton, showTvButton) { if (showLatestButton) { $("a#latest-results-button-desktop").show(); $("a#latest-results-button-touch").show(); } else { $("a#latest-results-button-desktop").hide(); $("a#latest-results-button-touch").hide(); } if (showStandingsButton) { $("a#table-button-desktop").show(); $("a#table-button-touch").show(); } else { $("a#table-button-desktop").hide(); $("a#table-button-touch").hide(); } if (showScorersButton) { $("a#scorers-button-desktop").show(); $("a#scorers-button-touch").show(); } else { $("a#scorers-button-desktop").hide(); $("a#scorers-button-touch").hide(); } if (showUpcomingButton) { $("a#upcoming-matches-button-desktop").show(); $("a#upcoming-matches-button-touch").show(); } else { $("a#upcoming-matches-button-desktop").hide(); $("a#upcoming-matches-button-touch").hide(); } if (showTvButton) { $("a#tv-matches-button-desktop").show(); $("a#tv-matches-button-touch").show(); } else { $("a#tv-matches-button-desktop").hide(); $("a#tv-matches-button-touch").hide(); } } // Holds the visibility change listener. var visibilityChangeListener; /** * Set a listener that will be called when the page becomes visible. * * @param {Function} listener the listener that should be called when the * page becomes visible. */ function setVisibilityChangeListener(listener) { visibilityChangeListener = listener; var hidden = "hidden"; // Standards: if (hidden in document) { document.addEventListener("visibilitychange", onchange); } else if ((hidden = "mozHidden") in document) { document.addEventListener("mozvisibilitychange", onchange); } else if ((hidden = "webkitHidden") in document) { document.addEventListener("webkitvisibilitychange", onchange); } else if ((hidden = "msHidden") in document) { document.addEventListener("msvisibilitychange", onchange); // IE 9 and lower: } else if ("onfocusin" in document) { document.onfocusin = document.onfocusout = onchange; // All others: } else { window.onpageshow = window.onpagehide = window.onfocus = window.onblur = onchange; } function onchange(evt) { var v = "visible", h = "hidden"; var evtMap = { focus: v, focusin: v, pageshow: v, blur: h, focusout: h, pagehide: h }; evt = evt || window.event; if (evt.type in evtMap) { if (evtMap[evt.type] === "visible") { visibilityChangeListener(); } } else { if (!this[hidden]) { visibilityChangeListener(); } } } // set the initial state (but only if browser supports the Page Visibility API) if (document[hidden] !== undefined) { // TODO disable this for now as we should not need an initial refresh. // onchange({ type: document[hidden] ? "blur" : "focus" }); } // Make an initial call to change listener in case returning to an already rendered page. if (!!window.performance && !!window.performance.getEntriesByType("navigation") && !!window.performance.getEntriesByType("navigation").length && (window.performance.getEntriesByType("navigation")[0].type === 'back_forward')) { visibilityChangeListener() } }; // Keep a map of all registered obserser so that we can disconnect them. observers = {}; /** * Responds to when the element with the given ID becomes visible by calling the provided callback * function. * * @param id the ID of the element that should be observed. * @param callback the callback that should be called when the element becomes visible. */ function respondToVisibility(id, callback) { if ("IntersectionObserver" in window) { // Disconnect any previous observer. if (observers[id]) { observers[id].disconnect(); delete observers[id]; } // Get element and setup options for the element. var element = document.getElementById(id); var options = { root: null, threshold: 0.5 }; // Create the observer. var observer = new IntersectionObserver((entries, observer) => { if (entries[0].intersectionRatio == 1) { callback(); observer.disconnect(); delete observers[id]; } }, options); // Start observing. observer.observe(element); observers[id] = observer; } else { // If no intersection observer is supported, then just run callback directly. callback(); } } /** * Load an Ad. * * @param adId the ad ID. * @param screenCondition the screen condition i.e. for which screen sizes it should be shown. * @param adShownClass the class to set on the ad when it has been shown. * @param adShownCheckBackoffTime the backoff time before checking if the ad has been shown. */ function loadAd(adId, screenCondition, adShownClass, adShownCheckBackoffTime) { enquire.register("screen and (" + screenCondition + ")", { match: function () { console.log("Loading ad with id: " + adId); lwhbed.cmd.push(function () { lwhbed.loadAd({ tagId: adId }); }); setTimeout(function () { var element = document.getElementById(adId); console.log("Check if ad was loaded for element", element); if (element && element.firstChild) { element.classList.add(adShownClass); } else if (element) { element.classList.remove(adShownClass); } }, adShownCheckBackoffTime); } }); }