wp-liveticker/scripts/liveticker.js
Stefan Kalscheuer 68efc83273 refactor frontend to use WP REST API instead of WP AJAX
Query new ticks using GET request to the REST API.
Also we now trigger one request per ticker, if more than one is
available on the same page.

HTML markup (list element, content container) is generated client side,
s.t. we can work on the generic response data model
2021-04-12 18:09:03 +02:00

179 lines
4.2 KiB
JavaScript

/**
* Contructor of the scLiveticker object.
*
* @class
*/
( function() {
var apiURL;
var pollInterval;
var ticker;
/**
* Initialize iveticker JS component.
*
* @return {void}
*/
var init = function() {
var updateNow = false;
// Opt out if AJAX pobject not present.
if ( 'undefined' === typeof scliveticker ) {
return;
}
// Extract settings.
apiURL = scliveticker.api + 'wp/v2/scliveticker_tick';
pollInterval = scliveticker.poll_interval;
// Get ticker elements.
ticker = [].map.call(
document.querySelectorAll( 'div.wp-block-scliveticker-ticker.sclt-ajax' ),
function( elem ) {
elem = parseElement( elem, false );
if ( '0' === elem.lastPoll ) {
updateNow = true;
}
return elem;
}
);
// Get widget elements.
ticker.concat(
[].map.call(
document.querySelectorAll( 'div.wp-widget-scliveticker-ticker.sclt-ajax' ),
function( elem ) {
elem = parseElement( elem, true );
if ( 0 === elem.lastPoll ) {
updateNow = true;
}
return elem;
}
)
);
// Trigger update, if necessary.
if ( ( 0 < ticker.length ) && 0 < pollInterval ) {
if ( updateNow ) {
update();
} else {
setTimeout( update, pollInterval );
}
}
};
/**
* Parse an HTML element containing a liveticker.
*
* @param {HTMLElement} elem The element.
* @param {boolean} widget Is the element a widget?
* @return {{ticker: string, lastPoll: number, ticks: any, limit: string, isWidget: *}} Ticker descriptor object.
*/
var parseElement = function( elem, widget ) {
var list = elem.querySelector( 'ul' );
var last = elem.getAttribute( 'data-sclt-last' );
if ( ! list ) {
list = document.createElement( 'ul' );
elem.appendChild( list );
}
return {
ticker: elem.getAttribute( 'data-sclt-ticker' ),
limit: elem.getAttribute( 'data-sclt-limit' ),
lastPoll: last,
ticks: list,
isWidget: widget,
};
};
/**
* Update liveticker on current page via REST API call.
*
* @return {void}
*/
var update = function() {
// Iterate over available tickers.
ticker.forEach(
function( t ) {
var xhr = new XMLHttpRequest();
var query = '?ticker=' + encodeURI( t.ticker ) +
'&limit=' + encodeURI( t.limit ) +
'&last=' + encodeURI( t.lastPoll );
xhr.open( 'GET', apiURL + query, true );
xhr.addEventListener(
'load',
function() {
var updateResp;
try {
updateResp = JSON.parse( this.responseText );
if ( updateResp ) {
updateResp.reverse();
updateResp.forEach(
function( u ) {
addTick( t, u );
}
);
}
setTimeout( update, pollInterval ); // Re-trigger update.
} catch ( e ) {
// eslint-disable-next-line no-console
console.warn( 'Liveticker AJAX update failed, stopping automatic updates.' );
}
}
);
xhr.send();
}
);
};
/**
* Do actual update of HTML code.
*
* @param {Object} t Ticker or Widget reference.
* @param {Object} u Update entity.
* @return {void}
*/
var addTick = function( t, u ) {
// Parse new DOM-part.
var li = document.createElement( 'li' );
var time = document.createElement( 'span' );
var title = document.createElement( 'span' );
var content = document.createElement( 'div' );
var cls = t.isWidget ? 'sclt-widget' : 'sclt-tick';
li.classList.add( cls );
time.classList.add( cls + '-time' );
time.innerText = u.modified_rendered;
title.classList.add( cls + '-title' );
title.innerText = u.title.rendered;
content.classList.add( cls + '-content' );
content.innerHTML = u.content.rendered;
li.appendChild( time );
li.appendChild( title );
li.appendChild( content );
// Prepend new tick to container.
t.ticks.prepend( li );
// Update last poll time.
t.lastPoll = u.date_gmt;
t.ticks.parentNode.setAttribute( 'data-sclt-last', u.date_gmt );
// Remove tail, if limit is set.
if ( 0 < t.limit ) {
[].slice.call( t.ticks.getElementsByTagName( 'li' ), t.limit ).forEach(
function( l ) {
l.remove();
}
);
}
};
document.addEventListener(
'DOMContentLoaded',
function() {
init(); // Trigger periodic update of livetickers.
}
);
}() );