/*see archive.js in same dir for source*/ /* Copyright(c)2008-2018 Internet Archive. Software license AGPL version 3. */ 'use strict'; var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } (function jquery_no_conflict($) { // convenient, no? Stateless function, global to all Play objects // eslint-disable-next-line no-console var log = location.host.substr(0, 4) !== 'www-' ? function () {} : console.log.bind(console); /** * Replaces a BookReader fragment string in a URL path with a new fragment, * or adds the path string to the end of the URL if it's not set * * NOTE: BookReader "fragments" are not necessarily URL hash fragments, * though they may be stored in the hash. * * @param {String} pathString * @param {String} newFragment * @returns {String} */ function replaceBookReaderFragment(pathString, newFragment) { // See http://openlibrary.org/dev/docs/bookurls var fragmentRegex = /(\/((page|mode|search)\/[^/?$]+))+\/?(?=\?|$)/g; if (pathString.match(fragmentRegex)) return pathString.replace(fragmentRegex, '/' + newFragment); return (pathString + '/' + newFragment).replace(/\/+/g, '/'); } // class memnonic: Archive JS var AJS = function () { function AJS() { _classCallCheck(this, AJS); } _createClass(AJS, null, [{ key: 'tvAD', // NOTE: needs to stay in sync w/ archive.less value: function tvAD(elm) { var in_show = $(elm).parents('.shows'); var id = void 0; var chan = void 0; var show = void 0; if (in_show.length) { // see if we've already gotten and displayed the "Air date" section... var opened = $(elm).parent().find('.shows'); if (opened.length) { // ... yes, simply close/open it opened.toggle(); return false; } chan = in_show.attr('data-chan'); show = $(elm).text(); } else { chan = $(elm).text(); id = 'menu-chan-'.concat(chan); var div = $('#' + id); if (div.length) { div.toggle(); return false; } } var url = location.href + '?channel=' + chan; if (in_show.length) url += '&program='.concat(encodeURIComponent(show)); log(url); $.get(url, function (htm) { if (in_show.length) { $(elm).parent().append('
Air date
' + htm + '
'); } else { $(elm).parent().append('

Show

' + htm + '
'); } }); return false; } // NOTE: needs to stay in sync w/ archive.less /* global archive_analytics jwplayer */ /* eslint no-underscore-dangle: ["error", { "allow": ["_modal_add"] }] */ }, { key: 'nav_tophat_setup', value: function nav_tophat_setup() { if (!$('#nav-tophat').length) return; if (AJS.isTouchDevice()) $('body').addClass('touch');else AJS.logoText(); $('#nav-tophat').on('show.bs.collapse', function () { return $('#navwrap1').addClass('hatted'); }).on('hide.bs.collapse', function () { return $('#navwrap1').removeClass('hatted'); }); $('.navbar a.navia-link').on('click', function navhat_click(evt) { // are we in "mobile nav / xs width" mode? var xs = !$('#nav-tophat-helper:visible').length; var hat_open = $('#nav-tophat').hasClass('in'); var navlink = this; // determine mediatype from either: (1) user hit text or (2) user hit icon var mt = $(evt.target).attr('data-top-kind') || $(evt.currentTarget).attr('data-top-kind'); var isnow = $('.navbar .dropdown-ia.hatted a').attr('data-top-kind'); if (!(xs && hat_open && isnow !== mt)) { // show the links for mediatype clicked $('.toprow').hide(); $('.toprow.' + mt).show(); } if (!hat_open) { $('#nav-tophat').collapse('show' // .. top hat is *not* open. clicked, so open tophat );if (AJS.tophat_dont_count_first_open) { delete AJS.tophat_dont_count_first_open; } else if (typeof archive_analytics !== 'undefined') { // log that a user has opened the nav tophat, yayz archive_analytics.send_ping({ kind: 'event', ec: 'page_action', ea: 'nav_tophat_galactica', el: location.pathname, cache_bust: Math.random() }); } } if (typeof isnow !== 'undefined') log('isnow', isnow); log('shouldB', mt); if (isnow === mt) { // 2nd click on same mediatype dropdown -- close tophat! $('#nav-tophat').collapse('hide'); return false; } if (xs && hat_open && isnow !== mt) { // Mobile/xs nav and user has clicked on *another* nav/MT icon. // So we want to (animate) close the tophat, and when closed, // reopen (animate) to the right open tophat -- this is because // mobile/xs makes the tophat heights much more arbitrary // and it looks weird hard jumping to other open area at another height! $('#nav-tophat').one('hidden.bs.collapse', function () { setTimeout(function () { return $(navlink).click(); }, 100); }); $('#nav-tophat').collapse('hide'); return false; } $('.navbar .dropdown-ia').removeClass('hatted').has('.' + mt).addClass('hatted'); $('#nav-tophat').on('hidden.bs.collapse', function () { return $('.navbar .dropdown-ia').removeClass('hatted'); } // any click makes tophat hide... );$(document).one('click.tophat.nixer', function (event) { var $e = $(event.target // log($e) );if ($e.attr('id') === 'nav-wb-url') return; // ... except clicking on wayback machine form input if ($e.is('a')) return; // ... except clicking on a link if ($e.hasClass('item-img') || $e.hasClass('item-ia')) return; // NOTE: if not open, we wont hide $('#nav-tophat.in').collapse('hide'); }); return false; }); } }, { key: 'isTouchDevice', value: function isTouchDevice() { return 'ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch; } }, { key: 'footer', value: function footer() { if (!AJS.isTouchDevice() && typeof $.fn.tooltip !== 'undefined') { $('.navbar [data-toggle="tooltip"], .container-ia [data-toggle="tooltip"], #cols [data-toggle="tooltip"], #tvbanner [data-toggle="tooltip"]').tooltip({} // $('body').addClass('glyphs-as-text') ); } } }, { key: 'wrapdark_watcher', value: function wrapdark_watcher() { // no longer needed/used but has some handy techniques... if (!AJS.$sharedown) { AJS.$sharedown = $('#sharedown'); AJS.$wrapdark = $('#wrapdark'); } // every second, sigh, check/adjust for the wrapdark height if (!AJS.wrapdark_watcher_ptr) AJS.wrapdark_watcher_ptr = setInterval(AJS.wrapdark_watcher, 1000); if (!AJS.$sharedown.length || !AJS.$wrapdark.length) { clearInterval(AJS.wrapdark_watcher_ptr); return; } var wrapdarkHT = AJS.$sharedown.offset().top + AJS.$sharedown.find('.panel-heading').innerHeight(); if (parseInt(AJS.$wrapdark.css('height'), 10) !== wrapdarkHT) { AJS.$wrapdark.css({ height: wrapdarkHT }).show(); log(' WRAPDARK-ED to ', wrapdarkHT); } } }, { key: 'flash_click', value: function flash_click(flashy) { $.cookie('avpref2', flashy ? null : 'flash', { path: '/' }); window.top.location.href = location.href; return false; } }, { key: 'mute_click', value: function mute_click() { var mutedNOW = !$.cookie('unmute'); if (this.emulator) { this.emulator.setMute(!mutedNOW); } else { var player = jwplayer('jw6'); if (player) { var volnow = player.getVolume(); if (volnow) { AJS.mute_click_prior_volume = volnow; player.setVolume(0); } else { player.setVolume(typeof AJS.mute_click_prior_volume === 'undefined' ? 100 : AJS.mute_click_prior_volume); } } } $('#theatre-ia .iconochive-mute, #theatre-ia .iconochive-unmute').toggle(); if (mutedNOW) { // sounds is off. make it loud $.cookie('unmute', 1, { path: '/details', expires: 30 }); } else { // sounds is on. mute it! $.cookie('unmute', null, { path: '/details' }); } return false; } }, { key: 'emulate_setup', value: function emulate_setup(game) { // eslint-disable-next-line no-param-reassign game.toString = function () { return game.identifier; }; AJS.emulator = new IALoader($('#canvas').get(0), game, null, game.scale ? parseFloat(game.scale) : 1, game.module.indexOf('dosbox') === 0 ? '/images/dosbox.png' : '/images/mame.png'); $('#theatre-ia .iconochive-unmute, #theatre-ia .iconochive-mute').hide(); if ($.cookie('unmute')) { $('#theatre-ia .iconochive-unmute').show(); AJS.emulator.unmute(); } else { $('#theatre-ia .iconochive-mute').show(); AJS.emulator.mute(); } AJS.theatre_controls_position(); $(window).on('resize orientationchange', function () { clearTimeout(AJS.theatre_controls_position_throttler); AJS.theatre_controls_position_throttler = setTimeout(AJS.theatre_controls_position, 250); }); } }, { key: 'emulate', value: function emulate() { /* global canvas IALoader DOSBOX JSMESS Module */ // move the virtual keyboard thing and give it a "go away!" button $('.ui-keyboard').prepend('\n ').appendTo($('#emulate .posrel')).addClass('showing'); $('#jsmessSS').fadeOut('slow'); $('#canvasholder').css('visibility', 'visible'); AJS.emulator.start({ hasCustomCSS: true } // setup the theatre-ia fullscreen button );var EM = JSMESS || DOSBOX || false; if (EM && (canvas.webkitRequestFullScreen || canvas.mozRequestFullScreen || canvas.requestFullScreen)) { $('#gofullscreen').on('click', function () { return Module.requestFullScreen(1, 0); } /**/);if ('onfullscreenchange' in document) document.addEventListener('fullscreenchange', EM.fullScreenChangeHandler);else if ('onmozfullscreenchange' in document) document.addEventListener('mozfullscreenchange', EM.fullScreenChangeHandler);else if ('onwebkitfullscreenchange' in document) document.addEventListener('webkitfullscreenchange', EM.fullScreenChangeHandler); } setTimeout(AJS.theatre_controls_position, 100); setTimeout(AJS.theatre_controls_position, 500); setTimeout(AJS.theatre_controls_position, 3000); setTimeout(AJS.theatre_controls_position, 10000); return false; } }, { key: 'theatre_controls_position', value: function theatre_controls_position($selectorIn, pegTop, widthIn, heightIn) { // We have lots of callers! video, software, texts. // So sort out our args and where we gonna "peg"/glue things to... var $selector = $selectorIn; var video = heightIn && !$selectorIn; if (!video) { if (!$selectorIn) $selector = $('#canvas' // software emulation );if (!$selector.length) return; // protect against emulated embeds and undef... } var height = video ? heightIn : $selector.height(); var width = video ? widthIn : $selector.width(); if (!video && typeof pegTop !== 'undefined') $('#theatre-controls').offset({ top: pegTop } // Subtract out the width of the controls to get total amount of black pixels // to the right of the theatre object. // We want to position the controls in the middle of the dark pixels / right gutter! );var right_gutter_width = Math.round(($('#theatre-ia-wrap').width() - $('#theatre-controls').width() - width) / 2); log('width', width); log('right_gutter_width', right_gutter_width); $('#theatre-controls').css({ height: height, visibility: 'visible', right: Math.max(20, right_gutter_width / 2) }); } }, { key: 'booksize', value: function booksize() { if (!$('#texty').length) return; // Use the standard theatresize function AJS.theatresize(); var pollingMillis = 200; // Change the bg in the iframe var $textyiframe = $('#texty iframe'); var changeBgColor = function changeBgColor() { var $contentDom = $($textyiframe.get(0).contentDocument); var $match = $contentDom.find('#BookReader'); if ($match.length > 0) { $contentDom.find('body, #BookReader').css('background-color', 'transparent'); return true; } return false; }; if (!changeBgColor()) { var bgColorInterval = setInterval(function () { if (changeBgColor()) clearInterval(bgColorInterval); }, pollingMillis); } // Setup the controls // NOTE The attribute data-lendable-book is added in Details.inc var isLendableBook = typeof $('#texty').data('lendable-book') !== 'undefined'; if (!isLendableBook && !AJS.booksize_controls_hidden) { AJS.booksize_controls(); var bookSizeInterval = setInterval(function () { if (!AJS.booksize_controls_hidden) AJS.booksize_controls();else clearInterval(bookSizeInterval); }, pollingMillis); } } // Hides the book controls, per david! // Also positions the "theatre controls" }, { key: 'booksize_controls', value: function booksize_controls() { var $iframe = $('iframe:first'); if (!$iframe.length) return; var $iframeDOM = $($iframe.get(0).contentDocument); if (!$iframeDOM.length) return; if (!AJS.booksize_controls_hidden) { if (!$iframeDOM.find('#BRnav').length) { log('BOOK NOT READY YET'); return; } if ($iframeDOM.find('#BRtwopageview').length > 0) { // Only hide nav in 2up. Show it in 1up $iframeDOM.find('#BRnav').hide(); } AJS.booksize_controls_hidden = true; $('#texty iframe').css('visibility', 'visible'); log('BOOK CONTROLS HIDDEN!'); } $iframeDOM.find('body, #BookReader').css('background-color', 'transparent' // now position the theatre controls );var $book = $iframeDOM.find('#BRtwopageview, #BRpageview' // compute where the logical top point should be for the book and for the controls // (which is comparable to A/V items) );var $navbar = $('.navbar' // NOTE: we *do* check the nav top (almost always 0!) for rare cases we have a banner // *ABOVE* the navbar, eg: EOY donate banner campaign (which is above the nav)! );var pegTop = $navbar.offset().top + $navbar.height() + parseInt($('#texty').css('padding-top'), 10); AJS.theatre_controls_position($book, pegTop); log('book top', $iframe.offset().top + $book.offset().top, ' -v- pegTop', pegTop // and now dont overflow negative margin-bottom blackness into metadata section );$('#theatre-ia').css({ overflow: 'hidden' }); } }, { key: 'popcornsize', value: function popcornsize() { var resizer = function resizer() { var metadataHeight = 100; // metadata peekaboo min height! var maxH = $(window).height() - $('iframe:first').offset().top - metadataHeight; var maxW = $('#theatre-ia .row').outerWidth // make max height at most 16x9 ratio (43px is the popcorn controls height) ();var WH = { width: maxW, height: Math.min(maxH, maxW * 9 / 16 + 43) }; log('popcorn resize: ', WH); $('iframe:first').css(WH // resize popcorn ); }; resizer // page load event is now ();$(window).on('resize orientationchange', function () { clearTimeout(AJS.popcorn_throttler); AJS.popcorn_throttler = setTimeout(resizer, 250); }); } /** * A general purpose theatre sizing function. * It keeps the metadata below the theatre partially visible. * @param {function} onChange - called when size changes * @global AJS.theatresize_maxheight if this is set by another * part of the code, it will contrain to this max height. */ }, { key: 'theatresize', value: function theatresize(onChange) { if (!AJS.theatresize_maxheight) AJS.theatresize_maxheight = null; var resizer = function resizer() { var metadataHeight = 100; // metadata peekaboo min height! var maximumHeight = 1000; // don't get larger than this var minHeight = Math.min($(window).width(), 400); var targetHeight = $(window).height() - $('#navwrap1').height() - metadataHeight; if (AJS.theatresize_maxheight) targetHeight = Math.min(targetHeight, AJS.theatresize_maxheight); targetHeight = Math.max(targetHeight, minHeight); var height = Math.min(targetHeight, maximumHeight); $('#theatre-ia-wrap').addClass('resized').css('height', height); if (onChange) onChange($('#theatre-ia-wrap').height()); }; resizer // page load event is now ();$(window).on('resize orientationchange', function () { clearTimeout(AJS.theatresize_throttler); AJS.theatresize_throttler = setTimeout(resizer, 250); }); } /** * Will reduce the vertical size of the carousel once all the images have * downloaded and only if they are all smaller than the current size. * This is a progressive enhancement * @param string selector * @param bool enableThreatreChange */ }, { key: 'carouselsize', value: function carouselsize(selector, enableThreatreChange) { var $carousel = $(selector); var imagePromises = $carousel.find('img.carousel-image').map(function (i, img) { var promise = $.Deferred(); var result = void 0; if (img.complete) { result = promise.resolve(img.naturalHeight).promise(); } else { img.addEventListener('load', function () { promise.resolve(img.naturalHeight); }); result = promise; } return result; }); $.when.apply($, _toConsumableArray(imagePromises)).then(function () { var currHeight = $carousel.height(); var maxImageHeight = Math.max.apply(Math, arguments); if (currHeight > maxImageHeight) { $carousel.css('maxHeight', maxImageHeight); if (enableThreatreChange) { AJS.theatresize_maxheight = maxImageHeight; $(window).trigger('resize'); } } }); } }, { key: 'pause', value: function pause() { var id = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'jw6'; var jw = jwplayer(id); if (jw && jw.getState && jw.getState().toLowerCase() === 'playing') // JW8 jw.pause(); } }, { key: 'morf', value: function morf(lnk, switchToA2Z) { // MORe Facets var href = $(lnk).attr('href'); if (switchToA2Z && switchToA2Z[0] === '-') $.cookie(switchToA2Z.substr(1).concat('A2Z'), 1, { path: '/', expires: 1 });else if (switchToA2Z) $.cookie(switchToA2Z.concat('A2Z'), null, { path: '/', expires: 1 }); var props = { selectorID: 'morf-modal' }; var selector = '#' + props.selectorID; var contents = React.createElement( 'div', { className: 'modal-dialog' }, React.createElement( 'div', { className: 'modal-content' }, React.createElement( 'div', { className: 'modal-header modal-header-std' }, React.createElement( 'button', { type: 'button', className: 'close', 'data-dismiss': 'modal', 'aria-hidden': 'true' }, React.createElement('span', { className: 'iconochive-remove-circle' }) ), React.createElement('h2', { className: 'modal-title' }) ), React.createElement('div', { className: 'modal-body', id: props.selectorID.concat('-body') }) ) ); if (!$(selector).length) $('body').prepend($('
' : ''; str += '\n\n ' + monthName + '\n\n
'; } // make header/a that shows/hides a hidden div after it with the page data if (day === undefined || day === '') skip_day = true; if (skip_day) { str += '
'; } else { str += '\n
\n \n ' + day + '\n \n
'; } // drop in the individual page links var offset = 1; var page = void 0; var pnum = void 0; for (var j = 0; j < pages.length; j++) { page = pages[j]; if (!page) // eslint-disable-next-line no-continue continue; if (offset > 0) offset = 1 - page; pnum = parseInt(page, 10) + offset; // left 0-pad to 4 digits as needed page = '0000'.concat(page); page = page.substr(page.length - 4, 4); var url = urlstart.concat(page, '.pdf'); str += '[' + pnum + '] '; } if (skip_day) str += '
';else str += '
'; lastyearmonth = yearmonth; } str += '
'; // replace the "pdfs" empty div with our hefty HTML $('#pdfs .replaced').html(str); } // for collection pages, [About] tab }, { key: 'grafs', value: function grafs() { var $grafs1 = $('#grafs1'); var $grafs2 = $('#grafs2'); if (!$grafs1.length) return; if (typeof $grafs1.attr('data-id') === 'undefined') return; var identifier = $grafs1.attr('data-id'); $grafs1.attr('data-id', null); log('loading grafs'); $grafs1.html('loading graph ').show(); $grafs2.html('loading graph ').show(); var tok = '

'; $.get('/details/'.concat(identifier, '&grafs=1&v=3'), function (htm) { var a = htm.split(tok); if (a.length >= 3) { $('#activity-reviewsN').html(a[1]).parents('.activity-box').show(); $('#activity-forumN ').html(a[2]).parents('.activity-box').show(); } if (a.length === 5) { $grafs1.html(tok + a[3]); $grafs2.html(tok + a[4]); } else { $grafs1.html('(graph data not available)'); $grafs2.html('(graph data not available)'); } }); AJS.setUpTopRegionsTable(); } }, { key: 'quick_down', value: function quick_down(id, target) { var idsel = '#' + id; if (!$('.format-group.in').length) { // no set of files for a single format showing... yet! var format = $(target).text(); var $formatGroup = $(idsel).parents('.format-group'); $('.download-button').html(format.concat(' FILES')); $formatGroup.addClass('in' // hide the other summary formats (one-liner) clickables );$('.format-group:not(.in)').slideUp(); $(idsel).slideDown(); } else { // re-open all the summary formats (one-liner) clickables $('.format-group').slideDown(400 // close the open set of single files );setTimeout(function () { // ftw, thx for nothing jquery $('.format-group.in').removeClass('in'); $('.download-button').html('DOWNLOAD OPTIONS'); }, 400); $(idsel).slideUp(); } return false; } // parse a CGI arg }, { key: 'arg', value: function arg(theArgName, try_full) { var sArgs = try_full && location.search === '' ? location.href.slice(1).split('&') : location.search.slice(1).split('&'); for (var i = 0; i < sArgs.length; i++) { if (sArgs[i].slice(0, sArgs[i].indexOf('=')) === theArgName) { var r = sArgs[i].slice(sArgs[i].indexOf('=') + 1); return r.length > 0 ? unescape(r).split(',') : ''; } } return ''; } // setup trigger on 1/2 second of hovering over the nav IA logo }, { key: 'logoText', value: function logoText() { var hideLogoText = function hideLogoText() { $('#internet-archive').fadeOut('slow', function () { $('#internet-archive').remove(); $('#exit-er').show(); }); }; var mousetimer = false; // axxx make sure when it opens on TAB, the about li is in the DOM *next* $('.navbar-nav:first').on('mouseenter focusin', function (evt) { // Only proceed if user is interacting with the logo elements. if (!$(evt.target).is('ul, .navbar-brand, .iconochive-logo, .logo-text-hider')) return; mousetimer = setTimeout(function () { if ($('#internet-archive').length) { hideLogoText(); return; } $('#exit-er').hide // (gets in the way of xs/mobile!) // flank the IA logo! ();$('.navbar-nav:first').prepend($('\n