harness/app-assets/templates/assets/js/bootstraps/liveblog.js (463 lines of code) (raw):

/*global window,define */ define([ 'modules/relativeDates', 'modules/twitter', 'modules/MyScroll', 'bootstraps/common' ], function ( relativeDates, twitter, MyScroll, common ) { 'use strict'; var initialised, newBlockHtml, liveblogStartPos; function updateBlocksOnScroll() { if (liveblogStartPos.top > window.scrollY) { liveblogNewBlockDump(); } } function addNewBlockToBlog(insertAfterElem, block) { var insertBeforeElem = insertAfterElem.nextSibling; block.classList.add('animated'); block.classList.add('slideinright'); while (insertBeforeElem && insertBeforeElem.nodeType !== 1) { insertBeforeElem = insertBeforeElem.nextSibling; } if (!insertBeforeElem) { insertAfterElem.parentNode.appendChild(block); } else { insertAfterElem.parentNode.insertBefore(block, insertBeforeElem); } } function liveblogNewBlockDump() { var articleBody = document.getElementsByClassName('article__body')[0], images = [], blocks, counter = 0, insertAfterElem = document.getElementsByClassName('article__body--liveblog__pinned')[0], newBlockElems, i; if (newBlockHtml) { newBlockElems = GU.util.getElemsFromHTML(newBlockHtml); for (i = newBlockElems.length; i > 0; i--) { addNewBlockToBlog(insertAfterElem, newBlockElems[i - 1]); } blocks = articleBody.getElementsByClassName('block'); while (counter !== newBlockElems.length) { images.push.apply(images, blocks[counter].getElementsByTagName('img')); counter++; } common.formatImages(images); common.loadEmbeds(); common.loadInteractives(); // Move mpu ads if (window.updateLiveblogAdPlaceholders) { window.updateLiveblogAdPlaceholders(true); } window.liveblogTime(); // check for tweets twitter.checkForTweets(); newBlockHtml = ''; } } function liveMore() { var liveMoreElem = document.getElementsByClassName('more--live-blogs')[0]; if (liveMoreElem) { liveMoreElem.addEventListener('click', onLiveMoreClick.bind(null, liveMoreElem)); } } function onLiveMoreClick(liveMoreElem) { var loadingElem = document.getElementsByClassName('loading--liveblog')[0]; liveMoreElem.style.display = 'none'; if (loadingElem) { loadingElem.classList.add('loading--visible'); } GU.util.signalDevice('showmore'); } function liveblogDeleteBlock(blockID) { var block = document.getElementById(blockID); if (block) { block.parentNode.removeChild(block); } } function liveblogUpdateBlock(blockID, html) { var block = document.getElementById(blockID), newBlock = GU.util.getElemsFromHTML(html)[0]; if (block && newBlock) { block.parentNode.replaceChild(newBlock, block); } } function liveblogLoadMore(html) { var i, images = [], blocks, articleBody = document.getElementsByClassName('article__body')[0], oldBlockCount = articleBody.getElementsByClassName('block').length, newBlockElems = GU.util.getElemsFromHTML(html); document.getElementsByClassName('loading--liveblog')[0].classList.remove('loading--visible'); for (i = 0; i < newBlockElems.length; i++) { articleBody.appendChild(newBlockElems[i]); } blocks = articleBody.getElementsByClassName('block'); for (i = blocks.length; i > oldBlockCount; i--) { images.push.apply(images, blocks[i-1].getElementsByTagName('img')); } common.formatImages(images); common.loadEmbeds(); common.loadInteractives(); window.liveblogTime(); // check for tweets twitter.checkForTweets(); } function liveblogTime() { var i, blockTimes, isLive = false, toneLiveBlogElems = document.getElementsByClassName('tone--liveBlog'); for (i = 0; i < toneLiveBlogElems.length; i++) { if (toneLiveBlogElems[i].classList.contains('is-live')) { isLive = true; break; } } if (isLive) { relativeDates.init('.key-event__time, .block__time', 'title'); } else { blockTimes = document.getElementsByClassName('block__time'); for (i = 0; i < blockTimes.length; i++) { blockTimes[i].innerHTML = blockTimes[i].getAttribute('title'); } } } function showLiveMore(show) { var liveMoreElem = document.getElementsByClassName('more--live-blogs')[0]; if (liveMoreElem) { if (show) { liveMoreElem.style.display = 'block'; } else { liveMoreElem.style.display = 'none'; } } } function liveblogNewBlock(html) { newBlockHtml = html + newBlockHtml; if (liveblogStartPos.top > window.scrollY) { liveblogNewBlockDump(); } } function setupGlobals() { // Global function to handle liveblogs, called by native code window.liveblogDeleteBlock = liveblogDeleteBlock; window.liveblogUpdateBlock = liveblogUpdateBlock; window.liveblogLoadMore = liveblogLoadMore; window.liveblogTime = liveblogTime; window.showLiveMore = showLiveMore; window.liveblogNewBlock = liveblogNewBlock; window.liveblogNewKeyEvent = liveblogNewKeyEvent; window.applyNativeFunctionCall('liveblogNewBlock'); window.applyNativeFunctionCall('liveblogDeleteBlock'); window.applyNativeFunctionCall('liveblogUpdateBlock'); window.applyNativeFunctionCall('liveblogNewKeyEvent'); } function setupTheMinute() { var blocks = document.getElementsByClassName('block'); addClassesToMinuteBlocks(blocks); updateMinuteBlockTitles(blocks); if (document.body.classList.contains('advert-config--tablet')) { adjustMinuteBlocks(blocks); // update dimensions on orientation change window.addEventListener('resize', GU.util.debounce(adjustMinuteBlocks.bind(null, blocks), 100)); } else { // If windows add background images to minute blocks if (document.body.classList.contains('windows')) { addBackgroundImagesToMinuteBlocks(blocks); } initScroller(); } } function moveFigcaption(figure, figInner) { var figCaption = figure.getElementsByTagName('figcaption')[0]; if (figCaption && figCaption.parentNode === figure) { if (figInner) { figInner.insertBefore(figCaption, figInner.firstChild); } } } function adjustMinuteBlocks(blocks) { var i, figure, figInner, tweet, marginTop = 48; for (i = 0; i < blocks.length; i++) { if (!blocks[i].classList.contains('is-textonly')) { figure = blocks[i].getElementsByTagName('figure')[0]; if (figure) { figInner = figure.getElementsByClassName('figure__inner')[0]; if (GU.opts.isOffline) { if (figInner) { figInner.style.height = common.getDesiredImageHeight(figure) + 'px'; } } if (blocks[i].classList.contains('is-coverimage')) { moveFigcaption(figure, figInner); } blocks[i].classList.remove('flex-block'); blocks[i].style.height = 'auto'; if (blocks[i].offsetHeight < (figure.offsetHeight + marginTop)) { blocks[i].style.height = figure.offsetHeight + marginTop + 'px'; blocks[i].classList.add('flex-block'); } } } else { tweet = blocks[i].getElementsByClassName('element-tweet')[0]; if (tweet) { adjustTweetForMinute(tweet); } } } } function adjustTweetForMinute(tweet) { var i, childNode, twitterLink = 'https://twitter.com/', twitterUser, twitterHandle, twitterWrapperElem, nameElem, linkElem, blockQuote = tweet.getElementsByClassName('twitter-tweet')[0]; if (blockQuote) { for (i = 0; i < blockQuote.childNodes.length; i++) { childNode = blockQuote.childNodes[i]; if (childNode.nodeType === 3 && childNode.nodeValue && childNode.nodeValue.indexOf('@') !== -1) { twitterHandle = childNode.nodeValue.match(/\(([^)]*)\)/g); if (twitterHandle.length) { twitterUser = childNode.nodeValue.replace(twitterHandle[0], '').replace(/\W+/g, ' '); twitterHandle = twitterHandle[0].substring(1, twitterHandle[0].length - 1); twitterLink += twitterHandle.replace('@', ''); twitterWrapperElem = document.createElement('div'); twitterWrapperElem.classList.add('twitter-wrapper'); nameElem = document.createElement('span'); nameElem.innerText = twitterUser; linkElem = document.createElement('a'); linkElem.href = twitterLink; linkElem.innerText = twitterHandle; twitterWrapperElem.appendChild(nameElem); twitterWrapperElem.appendChild(linkElem); blockQuote.insertBefore(twitterWrapperElem, blockQuote.firstChild); blockQuote.removeChild(childNode); i--; } } else if (childNode.tagName === 'A') { blockQuote.removeChild(childNode); i--; } } } } function updateMinuteBlockTitles(blocks) { var i, blockTitle, titleString; for (i = 0; i < blocks.length; i++) { blockTitle = blocks[i].getElementsByClassName('block__title')[0]; if (blockTitle) { titleString = blockTitle.innerHTML.replace(/^([0-9]+)[.]*[ ]*/g, '<span class="counter">$1</span>'); blockTitle.innerHTML = titleString; } } } function addClassesToMinuteBlocks(blocks) { var i, block; for (i = 0; i < blocks.length; i++) { block = blocks[i]; if (block.getElementsByClassName('element--thumbnail').length) { block.classList.add('is-thumbnail'); } else if (block.getElementsByClassName('element-image').length) { block.classList.add('is-coverimage'); } else if (block.getElementsByClassName('video-URL').length) { block.classList.add('is-video'); } else { block.classList.add('is-textonly'); } if (block.getElementsByClassName('quoted').length) { block.classList.add('has-quote'); } else if (block.getElementsByClassName('twitter-tweet').length) { block.classList.add('has-tweet'); } } } function addBackgroundImagesToMinuteBlocks(blocks) { var i, j, figureInners, figureImage; for (i = 0; i < blocks.length; i++) { figureInners = blocks[i].getElementsByClassName('figure__inner'); for (j = 0; j < figureInners.length; j++) { figureImage = figureInners[j].getElementsByTagName('img')[0]; if (figureImage) { figureInners[j].classList.add('the-minute__background-media'); figureInners[j].style.backgroundImage = 'url(' + figureImage.getAttribute('src') + ')'; figureImage.parentNode.removeChild(figureImage); } } } } function initScroller() { var scroller, liveblogElem, minuteNavElem = document.getElementsByClassName('the-minute__nav')[0], wrapperElem = document.getElementsByClassName('article--liveblog')[0], options = { scrollX: false, scrollY: true, momentum: false, snap: true, bounce: false, snapSpeed: 600, disablePointer: true }; if (wrapperElem) { liveblogElem = wrapperElem.getElementsByClassName('article__body--liveblog')[0]; // liveblogElem must be first child of wrapperElem wrapperElem.insertBefore(liveblogElem, wrapperElem.children[0]); removeTabletElems(); setScrollDimensions(liveblogElem, wrapperElem); // initialise scroller scroller = new MyScroll(wrapperElem, options); // onScrollEnd show hide minuteNavElem scroller.on('scrollEnd', onScrollEnd.bind(null, minuteNavElem, scroller)); // add click event handler to minuteNavElem minuteNavElem.addEventListener('click', scrollToNextCard.bind(null, minuteNavElem, scroller)); // update scroll dimensions on orientation change window.addEventListener('resize', GU.util.debounce(onWindowResize.bind(null, liveblogElem, wrapperElem, scroller), 100)); } } function onWindowResize(liveblogElem, wrapperElem, scroller) { setScrollDimensions(liveblogElem, wrapperElem); setTimeout(function () { scroller.refresh(); }, 0); } function setScrollDimensions(liveblogElem, wrapperElem) { var i, elemHeight, scrollHeight = 0, windowHeight = window.innerHeight; // set height of scrollers wrapper wrapperElem.style.height = windowHeight + 'px'; // set heights of each card within scroller for (i = 0; i < liveblogElem.children.length; i++) { elemHeight = liveblogElem.children[i].offsetHeight; if (elemHeight) { scrollHeight += windowHeight; liveblogElem.children[i].style.height = windowHeight + 'px'; } } // set height of scrollable area liveblogElem.style.height = scrollHeight + 'px'; } function scrollToNextCard(minuteNavElem, scroller) { if ((scroller.currentPage.pageY + 1) !== scroller.pages[0].length) { scroller.goToPage(0, scroller.currentPage.pageY + 1, 600); onScrollEnd(minuteNavElem, scroller); } } function onScrollEnd(minuteNavElem, scroller) { if ((scroller.currentPage.pageY + 1) === scroller.pages[0].length) { minuteNavElem.classList.add('hide'); } else { minuteNavElem.classList.remove('hide'); } } function removeTabletElems() { var i, elems = document.querySelectorAll('.minute-logo-container, .minute-vertical-rule'); for (i = 0; i < elems.length; i++) { elems[i].parentNode.removeChild(elems[i]); } } function keyEvents() { var keyEventsToggle = document.getElementsByClassName('key-events__toggle')[0], keyEventLinks = document.getElementsByClassName('key-event__link'); if (keyEventsToggle) { keyEventsToggle.addEventListener('click', showHideKeyEvents); } if (keyEventLinks.length) { captureKeyEventClicks(keyEventLinks); } } function liveblogNewKeyEvent(html) { var i, j, keyEventsList = document.getElementsByClassName('key-events__list')[0], newKeyEventLinks; if (!keyEventsList) { return; } newKeyEventLinks = GU.util.getElemsFromHTML(html); for (i = newKeyEventLinks.length; i > 0; i--) { newKeyEventLinks[i - 1].classList.add('key-event--highlighted'); for (j = 0; j < newKeyEventLinks[i - 1].children.length; j++) { newKeyEventLinks[i - 1].children[j].classList.add('flipInX'); newKeyEventLinks[i - 1].children[j].classList.add('animated'); } keyEventsList.insertBefore(newKeyEventLinks[i - 1], keyEventsList.firstChild); setTimeout(unhighlightKeyEventLink.bind(null, newKeyEventLinks[i - 1]), 15000); } captureKeyEventClicks(newKeyEventLinks); updateKeyEventCount(keyEventsList.children.length); window.liveblogTime(); } function unhighlightKeyEventLink(link) { link.classList.remove('key-event--highlighted'); } function updateKeyEventCount(count) { var i, keyEventsCounter = document.getElementsByClassName('key-events__counter')[0], keyEvents = document.getElementsByClassName('key-events')[0]; keyEventsCounter.innerHTML = '(' + count + ')'; for (i = keyEvents.classList.length; i > 0; i--) { if (keyEvents.classList[i - 1].match(/(key-events--)+[0-9]/g)) { keyEvents.classList.remove(keyEvents.classList[i - 1]); } } keyEvents.classList.add('key-events--' + count); } function captureKeyEventClicks(links) { var i; for (i = 0; i < links.length; i++) { links[i].addEventListener('click', handleKeyEventClick); } } function handleKeyEventClick(evt) { evt.preventDefault(); } function showHideKeyEvents() { var keyEvents = document.getElementsByClassName('key-events')[0]; if (keyEvents.classList.contains('key-events--expanded')) { keyEvents.classList.remove('key-events--expanded'); } else { keyEvents.classList.add('key-events--expanded'); } } function ready() { var minuteHeaderElem, minuteNavElem; if (!initialised) { initialised = true; newBlockHtml = ''; liveblogStartPos = GU.util.getElementOffset(document.getElementsByClassName('article__body--liveblog')[0]); setupGlobals(); keyEvents(); window.liveblogTime(); window.addEventListener('scroll', GU.util.debounce(updateBlocksOnScroll, 100, true)); liveMore(); if (document.body.classList.contains('the-minute')) { setupTheMinute(); } else { twitter.init(); setInterval(window.liveblogTime, 30000); if (minuteHeaderElem) { minuteHeaderElem.parentNode.removeChild(minuteHeaderElem); } if (minuteNavElem) { minuteNavElem.parentNode.removeChild(minuteNavElem); } } } } return { init: ready }; });