/*
Description:
Creates homepage slider (used in top of right column as of 2016/12/09).
Uses json data from RC Slides and creates a slideshow with it.
Dependencies:
google analytics for _gaq.push click events
/include/footer_includes_before_body.js?v=1 (as of 2016/12/09)
Table of Contents:
GET SCRIPT PARAMETERS
POLYFILLS
UTILITY FUNCTIONS
CROSS-SCRIPT VARIABLES
SCRIPT VARIABLES
SCRIPT FUNCTIONS
MAIN SCRIPT
Change Log:
3/13/2017 - Rowland - Mobile slideshow fix
*/
///////////////////////////
// GET SCRIPT PARAMETERS //
///////////////////////////
function get_slideshow_id() {
var scripts = document.getElementsByTagName('script');
var lastScript = scripts[scripts.length-1];
var scriptName = lastScript;
return scriptName.getAttribute('data-id');
}
var slideshow_id = get_slideshow_id();
///////////////
// POLYFILLS //
///////////////
// Polyfill for IE9 and below for third parameter on setTimeout function
/*\
|*|
|*| Polyfill which enables the passage of arbitrary arguments to the
|*| callback functions of JavaScript timers (HTML5 standard syntax).
|*|
|*| https://developer.mozilla.org/en-US/docs/DOM/window.setInterval
|*|
|*| Syntax:
|*| var timeoutID = window.setTimeout(func, delay[, param1, param2, ...]);
|*| var timeoutID = window.setTimeout(code, delay);
|*| var intervalID = window.setInterval(func, delay[, param1, param2, ...]);
|*| var intervalID = window.setInterval(code, delay);
|*|
\*/
(function() {
setTimeout(function(arg1) {
if (arg1 === 'test') {
// feature test is passed, no need for polyfill
return;
}
var __nativeST__ = window.setTimeout;
window.setTimeout = function(vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */ ) {
var aArgs = Array.prototype.slice.call(arguments, 2);
return __nativeST__(vCallback instanceof Function ? function() {
vCallback.apply(null, aArgs);
} : vCallback, nDelay);
};
}, 0, 'test');
var interval = setInterval(function(arg1) {
clearInterval(interval);
if (arg1 === 'test') {
// feature test is passed, no need for polyfill
return;
}
var __nativeSI__ = window.setInterval;
window.setInterval = function(vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */ ) {
var aArgs = Array.prototype.slice.call(arguments, 2);
return __nativeSI__(vCallback instanceof Function ? function() {
vCallback.apply(null, aArgs);
} : vCallback, nDelay);
};
}, 0, 'test');
}())
// getElementsByClassName(search)
if (!Element.prototype.getElementsByClassName) {
Element.prototype.getElementsByClassName = function (search) {
var d = this, elements, pattern, i, results = [];
if (d.querySelectorAll) { // IE8
return d.querySelectorAll("." + search);
}
if (d.evaluate) { // IE6, IE7
pattern = ".//*[contains(concat(' ', @class, ' '), ' " + search + " ')]";
elements = d.evaluate(pattern, d, null, 0, null);
while ((i = elements.iterateNext())) {
results.push(i);
}
} else {
elements = d.getElementsByTagName("*");
pattern = new RegExp("(^|\\s)" + search + "(\\s|$)");
for (i = 0; i < elements.length; i++) {
if (pattern.test(elements[i].className)) {
results.push(elements[i]);
}
}
}
return results;
}
}
///////////////////////
// UTILITY FUNCTIONS //
///////////////////////
// These help attach and remove events while supporting IE8
function addEvent(el, type, handler) {
if (el.attachEvent) el.attachEvent('on'+type, handler); else el.addEventListener(type, handler);
}
function removeEvent(el, type, handler) {
if (el.detachEvent) el.detachEvent('on'+type, handler); else el.removeEventListener(type, handler);
}
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
function hasClass(el, className) {
return el.classList ? el.classList.contains(className) : new RegExp('\\b'+ className+'\\b').test(el.className);
}
function addClass(el, className) {
if (el.classList) el.classList.add(className);
else if (!hasClass(el, className)) el.className += ' ' + className;
}
function removeClass(el, className) {
if (el.classList) el.classList.remove(className);
else el.className = el.className.replace(new RegExp('\\b'+ className+'\\b', 'g'), '');
}
function isInt(value) {
return !isNaN(value) && (function(x) { return (x | 0) === x; })(parseFloat(value))
}
//////////////////////
// SCRIPT VARIABLES //
//////////////////////
var ss_slide_time = 5000; // 50000
if(siteName == 'politics') {
var ss_slide_time = 50000; // 50000
}
var ss_transition_time = 500;
var ss_frame_time = 20;
var ss_opacity_perc_1 = 100;
var ss_opacity_perc_2 = 0;
var ss_current_slide = 1;
var ss_previous_slide = 1;
var ss_next_slide = ss_current_slide + 1;
var loading_bar_perc = 0;
var loading_bar_interval;
var play_or_pause = 'play';
var ss_transitioning = false;
var fade_or_slide = 'slide';
var hp_slideshow_started = false;
var hp_slideshow_second = false;
if(slideshow_id == null || !isInt(slideshow_id) ) {
slideshow_id = 15;
}
////////////////////////////
// CROSS-SCRIPT VARIABLES //
////////////////////////////
// Shared cache busting variable available to all scripts
if(typeof cache_bust === 'undefined') {
var cache_bust = Math.floor(new Date().getTime() / 1000);
}
// Used to override slideshow src if defined
if(typeof slideshow_src === 'undefined') {
var slideshow_src = '/widgets/slideshow_'+slideshow_id+'.json?cache='+cache_bust;
}
// Used to override slideshow callback function if defined
if(typeof slideshow_callback === 'undefined') {
var slideshow_callback = 'hp_slideshow_callback_'+slideshow_id;
}
// Used to add dark transparent background if defined
if(typeof slideshow_dark_back === 'undefined') {
var slideshow_dark_back = false;
}
//////////////////////
// SCRIPT FUNCTIONS //
//////////////////////
// Callback function for slideshow jsonp
window[slideshow_callback] = function(data) {
// Top level selector. Makes sure it's not the clone in the RCP homepage mobile duplicate
var ss_selector = '.beta-container:not(.clone) .hp_ss_container';
// keep checking for existance of container at an interval of 1 sec
if(document.querySelector(ss_selector+' .slides') == null) {
setTimeout(window[slideshow_callback].bind(null, data), 1000);
return false;
}
// Don't allow to be run more than once.
// Could be triggered again through another widget, like recommended
if(hp_slideshow_started) {
return false;
}
hp_slideshow_started = true;
// Create slides
var html = '';
for(var i = 0; i < data.slides.length; i++) {
var s = data.slides[i];
var img_url = s.image_url.replace('_1_', '_4_'); // Larger images
var dark_back_class = '';
if(typeof slideshow_dark_back !== 'undefined' && slideshow_dark_back) {
dark_back_class = 'dark_back';
}
html += '';
html += '
';
html += '';
}
document.querySelector(ss_selector+' .slides').innerHTML = html;
// Create slide previews
html = '';
for(var i = 0; i < data.slides.length; i++) {
var s = data.slides[i];
var img_url = s.image_url.replace('_1_', '_4_'); // Larger images
html += '
';
html += '
';
html += '';
html += '
';
html += '
';
html += '
'+s.title+'
';
html += '
';
html += '';
html += '
';
}
document.querySelector(ss_selector+' .slide_previews').innerHTML = html;
slide_tracking(ss_selector);
start_slideshow(ss_selector);
}
function slide_tracking(ss_selector) {
var ss_container = document.querySelector(ss_selector+' .slides');
var slides = ss_container.getElementsByClassName('slide');
for(var i = 0; i < slides.length; i++) {
delete slides[i].onclick;
slides[i].onclick = function() {
var this_slide_num = this.getAttribute('data-slide-num');
_gaq.push(['_trackEvent', 'HP_Carousel_Slider', 'Click', 'Slide: ' + this_slide_num]);
};
}
}
function start_slideshow(ss_selector) {
var ss_container = document.querySelector(ss_selector+' .slides');
var slides = ss_container.getElementsByClassName('slide');
if(slides.length <= 1) {
document.querySelector(ss_selector+' .loading_bar').style.display = 'none';
document.querySelector(ss_selector+' .navigation').style.display = 'none';
return;
}
// Build buttons
var html = '';
html += '
<
';
for(var i = 0; i < slides.length; i++) {
var active_class = '';
if(i == 0) {
active_class = 'active';
}
html += '
'+(i+1)+'
';
}
html += '
>
';
document.querySelector(ss_selector+' .navigation .buttons').innerHTML = html;
// Remove loading graphic
document.querySelector(ss_selector+' .slides_container').style.background = 'none';
// Hover on buttons
init_button_hover(ss_selector);
// Start autoplay
start_slideshow_autoplay(ss_selector);
// Play/Pause functionality
init_play_pause(ss_selector);
// Click for buttons
init_button_click(ss_selector);
// Click for arrows
init_arrow_click(ss_selector);
}
function start_slideshow_autoplay(ss_selector) {
if(play_or_pause == 'play') {
loading_bar_interval = setInterval(loading_bar_grow, ss_frame_time, ss_selector);
}
}
function loading_bar_grow(ss_selector) {
var loading_bar = document.querySelector(ss_selector+' .loading_bar .inner_bar');
loading_bar_perc += (ss_frame_time / ss_slide_time) * 100;
loading_bar.style.width = loading_bar_perc+'%';
if(loading_bar_perc >= 100) {
clearInterval(loading_bar_interval);
loading_bar_perc = 0;
slideshow_transition(ss_selector);
}
}
function slideshow_transition(ss_selector) {
ss_transitioning = true;
var slides = document.querySelectorAll(ss_selector+' .slides .slide');
// Permanently set base opacity of arrows by adding class
if(!hp_slideshow_second) {
addClass(document.querySelector(ss_selector+' .arrow.left'), 'active');
addClass(document.querySelector(ss_selector+' .arrow.right'), 'active');
hp_slideshow_second = true;
}
slides[ss_current_slide - 1].style.display = 'block';
slides[ss_next_slide - 1].style.display = 'block';
if(ss_opacity_perc_1 > 0) {
var perc_amount = (ss_frame_time / ss_transition_time) * 100;
ss_opacity_perc_1 -= perc_amount;
ss_opacity_perc_2 += perc_amount;
slides[ss_current_slide - 1].style.opacity = ss_opacity_perc_1 / 100;
slides[ss_next_slide - 1].style.opacity = ss_opacity_perc_2 / 100;
setTimeout(slideshow_transition, ss_frame_time, ss_selector);
} else {
// Restart slideshow transition
for(var i = 0; i < slides.length; i++) {
slides[i].style.display = 'none';
}
ss_previous_slide = ss_current_slide;
ss_current_slide = ss_next_slide;
ss_opacity_perc_1 = 100;
ss_opacity_perc_2 = 0;
ss_next_slide = ss_current_slide + 1;
if(ss_next_slide > slides.length) {
ss_next_slide = 1;
}
slides[ss_current_slide - 1].style.display = 'block';
var loading_bar = document.querySelector(ss_selector+' .loading_bar .inner_bar');
//loading_bar.style.width = '0%';
// Set new active button
var buttons = document.querySelectorAll(ss_selector+' .navigation .buttons .button');
removeClass(buttons[ss_previous_slide], 'active');
addClass(buttons[ss_current_slide], 'active');
init_button_hover(ss_selector);
// Set position of triangle for new active location
document.querySelector(ss_selector+' .navigation .active_arrow').style.left = (21+((ss_current_slide-1)*21))+'px';
ss_transitioning = false;
start_slideshow_autoplay(ss_selector);
}
}
function init_play_pause(ss_selector) {
// Set play button text
var play_pause = document.querySelector(ss_selector+' .navigation .play_pause');
if(play_or_pause == 'play') {
play_pause.innerHTML = 'Pause ❚❚';
} else {
play_pause.innerHTML = 'Play ►';
}
// Init click
delete play_pause.onclick;
play_pause.onclick = function() {
if(play_or_pause == 'play') {
// Pause slideshow
play_or_pause = 'pause';
play_pause.innerHTML = 'Play ►';
clearInterval(loading_bar_interval);
} else {
// Play slideshow
play_or_pause = 'play';
play_pause.innerHTML = 'Pause ❚❚';
start_slideshow_autoplay(ss_selector);
}
};
}
function init_arrow_click(ss_selector) {
var arrow_left = document.querySelector(ss_selector+' .arrow.left');
var arrow_right = document.querySelector(ss_selector+' .arrow.right');
delete arrow_left.onclick;
arrow_left.onclick = function() {
var ss_container = document.querySelector(ss_selector+' .slides');
var slides = ss_container.getElementsByClassName('slide');
var slide_num = ss_current_slide - 1;
if(slide_num < 1) {
slide_num = slides.length;
}
post_click_button_arrow(ss_selector, slide_num);
};
delete arrow_right.onclick;
arrow_right.onclick = function() {
var ss_container = document.querySelector(ss_selector+' .slides');
var slides = ss_container.getElementsByClassName('slide');
var slide_num = ss_current_slide + 1;
if(slide_num > slides.length) {
slide_num = 1;
}
post_click_button_arrow(ss_selector, slide_num);
};
}
function post_click_button_arrow(ss_selector, slide_num) {
// Fill and stop loading bar
ss_next_slide = slide_num;
if(play_or_pause == 'play') {
loading_bar_perc = 100;
} else {
slideshow_transition(ss_selector);
}
var slide_previews = document.querySelectorAll(ss_selector+' .slide_previews .slide_preview');
for(var i = 0; i < slide_previews.length; i++) {
slide_previews[i].style.display = 'none';
}
}
function init_button_click(ss_selector) {
var buttons = document.querySelectorAll(ss_selector+' .navigation .buttons .button');
for(var i = 0; i < buttons.length; i++) {
delete buttons[i].onclick;
buttons[i].onclick = function() {
if( (!isNumeric(this.innerHTML) && this.innerHTML != '>' && this.innerHTML != '<') || hasClass(this, 'active')) {
return false;
}
if(ss_transitioning) {
return false;
}
var slide_num = 1;
var ss_container = document.querySelector(ss_selector+' .slides');
var slides = ss_container.getElementsByClassName('slide');
if( isNumeric(this.innerHTML) ) {
slide_num = parseInt(this.innerHTML);
} else if(this.innerHTML == '>') {
slide_num = ss_current_slide + 1;
if(slide_num > slides.length) {
slide_num = 1;
}
} else if(this.innerHTML == '<') {
slide_num = ss_current_slide - 1;
if(slide_num < 1) {
slide_num = slides.length;
}
}
post_click_button_arrow(ss_selector, slide_num);
};
}
}
function init_button_hover(ss_selector) {
var buttons = document.querySelectorAll(ss_selector+' .navigation .buttons .button');
for(var i = 0; i < buttons.length; i++) {
delete buttons[i].onmouseover;
buttons[i].onmouseover = function() {
if(!isNumeric(this.innerHTML) || hasClass(this, 'active')) {
return false;
}
var slide_num = parseInt(this.innerHTML) - 1;
var slide_previews = document.querySelectorAll(ss_selector+' .slide_previews .slide_preview');
slide_previews[slide_num].style.display = 'block';
// Position of slide preview
slide_previews[slide_num].style.left = (this.offsetLeft - 66)+'px';
};
delete buttons[i].onmouseout;
buttons[i].onmouseout = function() {
if( !isNumeric(this.innerHTML) ) {
return false;
}
var slide_num = parseInt(this.innerHTML) - 1;
var slide_previews = document.querySelectorAll(ss_selector+' .slide_previews .slide_preview');
slide_previews[slide_num].style.display = 'none';
};
}
}
/////////////////
// MAIN SCRIPT //
/////////////////
var html = '';
// Styles for slideshow
html += '';
// Slideshow container markup
html += '
';
html += '
';
html += '';
html += '
';
html += '
';
html += '';
html += '
';
html += '
';
html += '';
html += '';
html += '';
html += '';
html += '
';
html += '';
html += '';
html += '
';
//document.write(html);
$('.rc-hp-slides').append(html);
// Get JSONP slideshow data
var script = document.createElement('script');
script.src = slideshow_src;
document.body.appendChild(script);