system-7/index_files/play8.js

2 lines
47 KiB
JavaScript

!function(e){var n={};function t(i){if(n[i])return n[i].exports;var a=n[i]={i:i,l:!1,exports:{}};return e[i].call(a.exports,a,a.exports,t),a.l=!0,a.exports}t.m=e,t.c=n,t.d=function(e,n,i){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:i})},t.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=141)}({139:function(e,n){e.exports="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; }; }();\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n// Video/Audio/TV related playback javascript - wrapping and extensions to jwplayer\n// For /details/[IDENTIFIER] and /embed/[IDENTIFIER] and TV pages and more\n\n/* TBD?\n- psuedostreaming\n- chapter marks!\n- more responsive\n*/\n\n/* DONE:\n- 'related items' shows at end of last vid in playlist\n- airplay / chrome casting\n- video /embed/ sharing button click\n- /embed/ logo in control bar\n- playback speed in control bar settings\n- tooltip images\n- webvtt\n- SPACE, left, right, up, down chars\n- caption styling (FCC compliance)\n- flash is only used to play A/V if html5 doesnt work (used to be flash could to UI/UX too)\n*/\n\n/* global jwplayer */\n(function jquery_no_conflict($) {\n // any methods or vars here are like private-to-outside globals and same for all \"Play objects\"\n var stash = {};\n\n // global config, for all Play objects\n\n // playing video size for normal /details/ pages\n var VIDEO_HEIGHT = 480;\n var VIDEO_WIDTH = 640; // (for 4:3 aspect -- scales for other aspects)\n\n var CONTROLS_HEIGHT = 30;\n var AUDIO_WIDTH = 350;\n var AUDIO_HEIGHT = CONTROLS_HEIGHT; // NOTE: may change\n var AUDIO_HEIGHT_WITH_WAVEFORM = 140;\n var AUDIO_HEIGHT_MAX = 240;\n\n var CONTROLS_MAX_WIDTH = 800;\n\n var PLAYLIST_ENTRY_HEIGHT = 20;\n var HEIGHT_ALIST = 370; // NOTE: max height; if few list entries, will be less\n var HEIGHT_VLIST = 100; // NOTE: max height; if few list entries, will be less\n\n var METADATA_HEIGHT = 100; // metadata peekaboo min height! (for \"responsive\")\n\n\n var Play = function () {\n // [playlist] should by an array, something like (ideally) one of:\n // [ {\"file\":\"chapter1.mp4\"}, {\"file\":\"chapter2.mp4\"}, .. ]\n // [ {\"sources\":[{\"file\":\"video.mp4\"},{\"file\":\"video.ogv\"},{..}]}, .. ]\n function Play(jid, playlist) {\n var _this = this;\n\n var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},\n _ref$start = _ref.start,\n start = _ref$start === undefined ? 0 : _ref$start,\n _ref$embed = _ref.embed,\n embed = _ref$embed === undefined ? false : _ref$embed,\n _ref$hide_list = _ref.hide_list,\n hide_list = _ref$hide_list === undefined ? false : _ref$hide_list,\n _ref$autoplay = _ref.autoplay,\n autoplay = _ref$autoplay === undefined ? false : _ref$autoplay,\n _ref$audio = _ref.audio,\n audio = _ref$audio === undefined ? false : _ref$audio,\n _ref$width = _ref.width,\n width = _ref$width === undefined ? 0 : _ref$width,\n _ref$height = _ref.height,\n height = _ref$height === undefined ? 0 : _ref$height,\n _ref$responsive = _ref.responsive,\n responsive = _ref$responsive === undefined ? false : _ref$responsive,\n _ref$aspectratio = _ref.aspectratio,\n aspectratio = _ref$aspectratio === undefined ? false : _ref$aspectratio,\n _ref$noshare = _ref.noshare,\n noshare = _ref$noshare === undefined ? false : _ref$noshare,\n _ref$nolinks = _ref.nolinks,\n nolinks = _ref$nolinks === undefined ? false : _ref$nolinks,\n _ref$logo = _ref.logo,\n logo = _ref$logo === undefined ? false : _ref$logo,\n _ref$so = _ref.so,\n so = _ref$so === undefined ? false : _ref$so,\n _ref$tv = _ref.tv,\n tv = _ref$tv === undefined ? false : _ref$tv,\n _ref$tvStart = _ref.tvStart,\n tvStart = _ref$tvStart === undefined ? 0 : _ref$tvStart,\n _ref$tvEnd = _ref.tvEnd,\n tvEnd = _ref$tvEnd === undefined ? 0 : _ref$tvEnd,\n _ref$tvContributor = _ref.tvContributor,\n tvContributor = _ref$tvContributor === undefined ? false : _ref$tvContributor,\n _ref$tvSource = _ref.tvSource,\n tvSource = _ref$tvSource === undefined ? false : _ref$tvSource,\n _ref$play_just = _ref.play_just1,\n play_just1 = _ref$play_just === undefined ? false : _ref$play_just,\n _ref$list_height = _ref.list_height,\n list_height = _ref$list_height === undefined ? 0 : _ref$list_height,\n _ref$identifier = _ref.identifier,\n identifier = _ref$identifier === undefined ? false : _ref$identifier,\n _ref$onTime = _ref.onTime,\n onTime = _ref$onTime === undefined ? false : _ref$onTime,\n _ref$onComplete = _ref.onComplete,\n onComplete = _ref$onComplete === undefined ? false : _ref$onComplete,\n _ref$onDisplayClick = _ref.onDisplayClick,\n onDisplayClick = _ref$onDisplayClick === undefined ? false : _ref$onDisplayClick,\n _ref$onReady = _ref.onReady,\n onReady = _ref$onReady === undefined ? false : _ref$onReady,\n _ref$collection = _ref.collection,\n collection = _ref$collection === undefined ? false : _ref$collection,\n _ref$waveformer = _ref.waveformer,\n waveformer = _ref$waveformer === undefined ? false : _ref$waveformer,\n _ref$speed = _ref.speed,\n speed = _ref$speed === undefined ? 1.0 : _ref$speed,\n _ref$details = _ref.details,\n details = _ref$details === undefined ? location.href : _ref$details;\n\n _classCallCheck(this, Play);\n\n // xxxx should wrap innards with try/catch\n // eslint-disable-next-line no-alert\n if (!jid) return alert('please pass in a unique identifier for this object');\n if (typeof stash[jid] !== 'undefined') {\n if (typeof playlist === 'undefined') return stash[jid]; // return prior created object\n delete stash[jid]; // new jwplayer + playlist for prior jid\n }\n stash[jid] = this; // stash a pointer so that a repeat call to Play(jid) returns prior object\n\n\n // more (per instance) variables (cant be overridden/changed/seen by caller):\n var self = this;\n var tvTitle = tv && playlist.length === 1 ? playlist[0].title : '';\n var list_2cols = responsive && audio;\n var jidsel = '#' + jid;\n var jidlist = '#' + jid + '__list';\n var readyIA = false;\n var DAR = 4 / 3;\n var first_seeked_playlist = false;\n var first_onmeta = false;\n var jwwidth = 0;\n var waveformed = false;\n var pause_first_seek = embed && !tv && !audio && !autoplay && start;\n var update_url_onload = true;\n var onCompleteStop = false; // playlists by default keep going to song B when song A is done\n var jwaudioWD = 0;\n var jwaudioPercentDone = 0;\n\n // convenient, no? Stateless function, global to all Play objects\n // eslint-disable-next-line no-console\n var log = location.host.substr(0, 4) !== 'www-' ? function () {} : console.log.bind(console);\n\n // eslint-disable-next-line prefer-rest-params\n log('PLAY CONFIG:', arguments[2]);\n\n // xxx v6.8 for /details/anamorphic has wrong width in flash mode! so squishface unlike v6.1\n self.adjustVideoWidth = function (player, onMetaSizing) {\n if (onMetaSizing.height && onMetaSizing.width && onMetaSizing.height > 0 && onMetaSizing.width > 0 && parseInt(onMetaSizing.height, 10) > 0) {\n DAR = parseInt(onMetaSizing.width, 10) / parseInt(onMetaSizing.height, 10);\n log('DAR: ', DAR, onMetaSizing.width, 'x', onMetaSizing.height);\n }\n\n if (embed) self.embedResize();\n };\n\n self.embedResize = function () {\n if (!jwplayer || !jwplayer(jid)) return;\n\n if (audio) {\n jwplayer(jid).resize(Math.min(CONTROLS_MAX_WIDTH, $(window).width()), AUDIO_HEIGHT);\n return;\n }\n\n // window max avail width and height for us\n var WW = $(window).width();\n var WH = $(window).height() - list_height;\n\n jwplayer(jid).resize(WW, WH);\n };\n\n self.playN = function (idx, onPLI) {\n var $rows = $(jidlist).find('.jwrow, .jwrowV2');\n\n $rows.removeClass('playing');\n if (!readyIA) return false;\n\n $($rows.get(idx)).addClass('playing');\n if (!onPLI) jwplayer(jid).playlistItem(idx);\n\n return false;\n };\n\n // xxx suck, ubuntu new firefox re-seeks to start w/o double doing this, etc....\n self.seeker_playlist = function () {\n if (first_seeked_playlist) return;\n\n first_seeked_playlist = true;\n\n if (pause_first_seek) {\n // oh cry/facepalm...\n // /embed/ia20thanniversaryevent?start=2150\n // is now NOT wanted to autoplay ( unless _also_ has \"\"&autoplay=1\" )\n jwplayer(jid).on('play', function () {\n if (!pause_first_seek) return;\n\n log('onPlay()');\n pause_first_seek = false;\n self.pause();\n log('... paused first seek!');\n });\n }\n\n if (!start) return;\n\n // NOTE: special since phantomJS testing looks for this logging in production\n // eslint-disable-next-line no-console\n if (typeof console !== 'undefined' && console.log)\n // eslint-disable-next-line no-console\n console.log('seeker_playlist() to ', start, pause_first_seek ? ' NOSTART' : ' AUTOSTART');\n\n self.pause();\n jwplayer(jid).seek(start);\n };\n\n self.embed_setup = function () {\n $(window).on('resize orientationchange', function () {\n // Bind window resize to resize the player\n clearTimeout(Play.throttler2);\n Play.throttler2 = setTimeout(function () {\n // resize/orient flip -- resize and reflow elements\n new Play(jid).embedResize();\n }, 250);\n });\n };\n\n self.details_setup = function () {\n var startPlaylistIdx = 0;\n\n var re = '^/details/' + identifier + '/([^&?]+)';\n var mat = location.pathname.match(re);\n if (mat) {\n var file = decodeURIComponent(mat[1].replace(/\\+/g, '%20'));\n log('looking for: ', file);\n // log(playlist)\n // eslint-disable-next-line guard-for-in\n for (var ii in playlist) {\n var idx = Number(ii); // convert from string!\n if (playlist[idx].orig === file) {\n log('player should seek to track #', idx);\n startPlaylistIdx = idx;\n break;\n }\n }\n }\n\n if (!startPlaylistIdx && !start && !autoplay) update_url_onload = false;\n\n if (!start && !autoplay && !tv && startPlaylistIdx) pause_first_seek = true;\n\n if (!autoplay && (startPlaylistIdx || start)) {\n log('seek #', startPlaylistIdx, ' to ', start);\n var jw = jwplayer(jid);\n jw.playlistItem(startPlaylistIdx);\n }\n };\n\n self.pause = function () {\n var jw = jwplayer(jid);\n if (readyIA && jw && jw.getState && jw.getState() === 'playing') jw.pause();\n };\n self.remove = function () {\n self.pause();\n var jw = jwplayer(jid);\n if (readyIA && jw && jw.getConfig()) jw.remove();\n delete stash[jid];\n };\n\n self.speed = function (valIn) {\n // xxx audio items still need some cosmetic work\n if (typeof valIn === 'undefined') {\n var close = false;\n if (audio) {\n // allows playback rates theatre icon click to show picker menu\n $('.jw-controls').css('overflow', 'initial');\n\n close = $(jidsel).height() === AUDIO_HEIGHT_MAX;\n $(jidsel).css('height', close ? AUDIO_HEIGHT_WITH_WAVEFORM : AUDIO_HEIGHT_MAX);\n }\n\n close = close || $(jidsel + ' .jw-controls').hasClass('jw-settings-open');\n\n // facepalm, pls unsuck API..\n if (close) {\n $(jidsel + ' .jw-controls').removeClass('jw-settings-open');\n if (audio) $('.jw-controls').css('overflow', '');\n } else {\n $(jidsel + ' .jw-controls').toggleClass('jw-settings-open');\n }\n\n $(jidsel + ' .jw-settings-topbar .jw-icon').attr('aria-checked', 'false');\n $(jidsel + ' .jw-settings-playbackRates').attr('aria-checked', 'true');\n\n var $xxx = $('.jw-settings-content-item:contains(\"0.5x\")').parent();\n $(jidsel + ' .jw-settings-submenu').attr('aria-expanded', 'false').removeClass('jw-settings-submenu-active');\n $xxx.attr('aria-expanded', 'true').addClass('jw-settings-submenu-active');\n return false;\n }\n\n var val = valIn;\n if (typeof val === 'undefined' || isNaN(val)) val = 1.0;\n\n var vid = $('#' + jid + ' video').get(0);\n vid.playbackRate = val;\n log('speed to ' + val);\n return false;\n };\n\n self.add_buttons = function (player) {\n var prv = '<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"jw-svg-icon jw-svg-icon-next\" style=\"transform: rotate(180deg)\" viewBox=\"0 0 240 240\"><path d=\"M165,60v53.3L59.2,42.8C56.9,41.3,55,42.3,55,45v150c0,2.7,1.9,3.8,4.2,2.2L165,126.6v53.3h20v-120L165,60L165,60z\"></path></svg>';\n\n var nxt = '<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"jw-svg-icon jw-svg-icon-next\" viewBox=\"0 0 240 240\"><path d=\"M165,60v53.3L59.2,42.8C56.9,41.3,55,42.3,55,45v150c0,2.7,1.9,3.8,4.2,2.2L165,126.6v53.3h20v-120L165,60L165,60z\"></path></svg>';\n\n var shr = '<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"jw-svg-icon jw-svg-icon-next\" viewBox=\"0 25 75 50\"><path d=\"M67.5,18c-5.1,0-9.3,4.2-9.3,9.3c0,0.5,0.1,1.1,0.2,1.6l-23,12.9c-1.7-1.8-4.1-3-6.8-3,c-5.1,0-9.3,4.1-9.3,9.3c0,5.1,4.1,9.3,9.3,9.3c2.7,0,5.2-1.2,6.9-3.1l22.8,13.4c0,0.4-0.1,0.7-0.1,1.1c0,5.1,4.1,9.3,9.3,9.3,c5.1,0,9.3-4.1,9.3-9.3c0-5.1-4.1-9.3-9.3-9.3c-2.8,0-5.4,1.3-7.1,3.3L37.7,49.4c0.1-0.4,0.1-0.9,0.1-1.3c0-0.5,0-1-0.1-1.5,l23.1-13c1.7,1.8,4.1,3,6.8,3c5.1,0,9.3-4.1,9.3-9.3C76.8,22.2,72.6,18,67.5,18L67.5,18z\"></path></svg>';\n\n var airplay = '<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"jw-svg-icon jw-svg-icon-airplay-on\" viewBox=\"0 0 240 240\"><path d=\"M229.9,40v130c0.2,2.6-1.8,4.8-4.4,5c-0.2,0-0.4,0-0.6,0h-44l-17-20h46V55H30v100h47l-17,20h-45c-2.6,0.2-4.8-1.8-5-4.4c0-0.2,0-0.4,0-0.6V40c-0.2-2.6,1.8-4.8,4.4-5c0.2,0,0.4,0,0.6,0h209.8c2.6-0.2,4.8,1.8,5,4.4C229.9,39.7,229.9,39.9,229.9,40z M104.9,122l15-18l15,18l11,13h44V75H50v60h44L104.9,122z M179.9,205l-60-70l-60,70H179.9z\"/></svg>';\n\n if (embed && !nolinks) {\n var ttl = tvTitle ? tvTitle.replace(/ : /g, '\\n') + '\\n\\nClick above for more information and clips\\nat the Internet Archive' : 'More Formats from Internet Archive';\n\n player.addButton('/images/glogo-jw.png', ttl, function () {\n window.top.location.href = details;\n }, 'btn-ia');\n }\n\n if (embed && !audio && !noshare && !tv) {\n if (identifier !== false) {\n player.addButton('/jw/embed.png', 'Embedding Examples and Help', function () {\n window.top.location.href = '/help/video.php?identifier=' + identifier;\n }, 'btn-mbd');\n }\n\n if (typeof AJS !== 'undefined') {\n player.addButton(shr, 'share', function () {\n // user clicked on sharing toolbar icon -- we dont get the button/link so find it\n var lnk = $('.jw-icon[button=btn-shr]').get(0);\n // now show the sharing modal!\n // eslint-disable-next-line no-undef\n AJS.modal_go(lnk, { ignore_lnk: 1, shown: AJS.embed_codes_adjust });\n }, 'btn-shr');\n // now that the button is added, add needed-by-sharing-modal attributes to it\n $('.jw-icon[button=btn-shr]').attr('href', 'ignored').attr('data-target', '#cher-modal');\n }\n }\n\n if (tv && embed && tvSource !== false) {\n player.addButton('/images/tv/' + identifier.split('_')[0] + '.png', 'Look for this show on ' + tvContributor + ' website', function () {\n window.top.location.href = tvSource;\n }, 'btn-tv');\n }\n\n if (!audio && collection && !tv) {\n player.addButton('/jw/8/related.png', 'Related Videos', function () {\n self.related_items_click();\n }, 'btn-rel');\n }\n\n if (self.castable()) {\n if (window.chrome) Play.cast_sender_setup();\n\n player.addButton(airplay, 'Cast media with AirPlay / Chromecast', function () {\n self.cast();\n }, 'btn-cast');\n }\n\n // NOTE: added last, so it's closest to the scrubber and play/pause normal controls, etc.\n if (!tv && playlist.length > 1) {\n /* eslint-disable */\n player.addButton(nxt, 'next', function () {\n player.playlistNext();\n }, 'btn-nxt');\n player.addButton(prv, 'previous', function () {\n player.playlistPrev();\n }, 'btn-prv');\n /* eslint-enable */\n }\n };\n\n self.castable = function () {\n return window.WebKitPlaybackTargetAvailabilityEvent || window.chrome;\n };\n\n self.cast = function () {\n if (window.WebKitPlaybackTargetAvailabilityEvent) {\n $('#' + jid + ' video').get(0).webkitShowPlaybackTargetPicker();\n return;\n }\n\n if (!window.chrome) return;\n\n var onMediaDiscovered = function onMediaDiscovered(how, media) {\n media.play( // xxx pause / stop /seek all similar -- hook into jw controls!\n null, function (e) {\n log('media play success', how, media, e);\n }, function (e) {\n log('media play fail', e);\n });\n };\n\n self.cast_retries = 0;\n var cast_setup = function cast_setup() {\n log('cast_setup #', self.cast_retries);\n\n self.cast_retries += 1;\n if (self.cast_retries > 3) return false;\n\n if (!window.chrome.cast) return setTimeout(cast_setup, self.cast_retries * 1000);\n\n /* Adapted from:\n https://developers.google.com/cast/v2/chrome_sender\n */\n var cast = window.chrome.cast;\n\n var sessionRequest = new cast.SessionRequest(cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID);\n var apiConfig = new cast.ApiConfig(sessionRequest, function (e) {\n if (e.media.length) onMediaDiscovered('onRequestSessionSuccess', e.media[0]);\n }, function (e) {\n log('receiver listener fail', e);\n });\n cast.initialize(apiConfig, function () {\n log('cast init success');\n // launch cast destination picker\n cast.requestSession(function (session) {\n log('request session success', session);\n // NOTE: avoid CORS issues and use A/V file from same host\n var src = $(jidsel + ' video').attr('src');\n var mediaURL = location.protocol + '//' + location.host + src;\n var mediaInfo = new cast.media.MediaInfo(mediaURL);\n var request = new cast.media.LoadRequest(mediaInfo);\n session.loadMedia(request, onMediaDiscovered.bind(_this, 'loadMedia'), function (e) {\n log('onMediaError', e);\n });\n }, function (e) {\n log('request session fail', e);\n setTimeout(cast_setup, 500);\n });\n }, function () {\n return log('cast init failure');\n });\n return true;\n };\n\n cast_setup();\n };\n\n self.related_items_click = function () {\n var controlbar_click_closes = function controlbar_click_closes() {\n $(jidsel + ' .jw-controlbar').one('click', function (evt) {\n $('#related-items-bg').hide();\n evt.preventDefault();\n });\n };\n\n if (typeof AJS !== 'undefined' && !$('#related-items').length) {\n $('' + jidsel).prepend('\\n<div id=\"related-items-bg\" onclick=\"$(\\'#related-items-bg\\').hide()\" style=\"display:none\">\\n <div id=\"related-items\">\\n </div>\\n</div>\\n');\n\n // eslint-disable-next-line no-undef\n AJS.getRelatedItems(identifier, 9).then(function (data) {\n var htm = '';\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = data[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var val = _step.value;\n\n htm += '\\n<div>\\n <a href=\"/details/' + val.identifier + '\">\\n <div class=\"related-ttl\">\\n ' + (val.title && val.title.length ? val.title[0] : '') + '\\n ' + (val.creator ? '<br/>&nbsp;&nbsp;<small>by:</small>&nbsp;' + val.creator : '') + '\\n ' + (val.downloads && val.downloads.length ? '<div>' + val.downloads[0] + ' views</div>' : '') + '\\n </div>\\n <img src=\"/services/img/' + val.identifier + '\"/>\\n </a>\\n</div>\\n';\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n\n $('#related-items').html(htm);\n\n $('#related-items-bg').show();\n controlbar_click_closes();\n });\n } else {\n var showing_now = $('#related-items-bg:visible').length;\n if (showing_now) {\n $('#related-items-bg').hide();\n } else {\n $('#related-items-bg').show();\n setTimeout(controlbar_click_closes, 500); // xxx sigh jw gets in the way w/o delay..\n }\n }\n };\n\n self.addClickablePlaylist = function () {\n if (hide_list) return; // nothing to do!\n\n var jwlist = jwplayer(jid).getPlaylist();\n var same_len = true;\n if (jwlist.length !== playlist.length) {\n log('NOTE: jw playlist filtered down -- ', playlist.length, '==>', jwlist.length, ' items');\n same_len = false;\n }\n\n var ialist = '';\n var ialistC1 = '';\n var ialistC2 = '';\n $.each(jwlist, function (idx, val) {\n var ttl = typeof val.title === 'undefined' ? '' : val.title.replace(/^\\d+\\. /, ''); // xxx \"1. Camaro\" ==> \"Camaro\"\"\n\n // In v6.8 flash mode (only), duration no longer is passed back via \"getPlaylist()\" 8-(\n // so try the original list sent to jwplayer config if we can...\n var duration = typeof val.duration !== 'undefined' ? val.duration : false;\n if (duration === false) {\n duration = same_len && typeof playlist[idx] !== 'undefined' && typeof playlist[idx].duration !== 'undefined' ? playlist[idx].duration : 0;\n }\n if (duration <= 0) duration = false;\n\n if (list_2cols) {\n var str = '\\n<a href=\"#\" onclick=\"return Play(\\'' + jid + '\\').playN(' + idx + ')\">\\n <div class=\"jwrowV2\">\\n <b>' + (idx + 1) + '</b>\\n <span class=\"ttl\">\\n ' + ttl + '\\n </span>\\n -\\n <span class=\"tm\">\\n ' + (duration ? Play.sec2hms(duration) : '') + '\\n </span>\\n </div>\\n</a>';\n if (idx < playlist.length / 2) ialistC1 += str;else ialistC2 += str;\n } else {\n ialist += '\\n<a href=\"#\" onclick=\"return Play(\\'' + jid + '\\').playN(' + idx + ')\">\\n <div class=\"jwrow\">\\n <div class=\"tm\">\\n ' + (duration ? Play.sec2hms(duration) : '') + '\\n </div>\\n <div class=\"n\">\\n ' + (idx + 1) + '\\n </div>\\n <div class=\"ttl\">\\n ' + ttl + '\\n </div>\\n </div>\\n</a>';\n }\n });\n\n if (list_2cols) {\n ialist = '<div class=\"row\">\\n <div class=\"col-sm-6\">\\n ' + ialistC1 + '\\n </div>\\n <div class=\"col-sm-6\">\\n ' + ialistC2 + '\\n </div>\\n </div>';\n }\n\n var css = {};\n if (responsive) {\n css.width = width;\n css.margin = 'auto';\n if (!audio) $(jidsel).css('margin', 'auto');\n }\n\n $(jidlist).addClass(list_2cols ? 'jwlistV2' : 'jwlist').css(css).html(ialist);\n\n log(playlist);\n // log(JSON.stringify(playlist,undefined,2))\n };\n\n self.debug = function () {\n // eslint-disable-next-line no-debugger\n debugger;\n };\n\n /* eslint-disable no-param-reassign */\n // ^^^ this class was designed _deliberately_ using scoping techniques _outside_ of the\n // methods to allow them to be set/manipulated _per instance_ but auto binding closure\n // around each instance/object -- so from here for awhile, disabling that eslint rule...\n\n\n self.responsiveResize = function (first) {\n if (!responsive) return;\n\n var playoff = $(jidsel).offset();\n var maxH = $(window).height() - playoff.top - METADATA_HEIGHT;\n if (audio) {\n if (playlist && playlist.length > 0 && playlist[0].image) AUDIO_HEIGHT = AUDIO_HEIGHT_WITH_WAVEFORM; // (typically png is 800x200 now)\n // OK, so we will be using \"maxH\" for the **playlist**.\n // Reduce by player/waveform height now...\n // but make sure at least ~8 rows (or 4 if oldtimeradio item ;-) always show\n // (eg: insanely short browser??)\n maxH -= AUDIO_HEIGHT;\n maxH = Math.max(AUDIO_HEIGHT_MAX, maxH);\n if (!embed) {\n log('responsiveResize() maxH:', maxH);\n list_height = maxH;\n log($(jidlist).length);\n $(jidlist).css({\n 'max-height': maxH,\n 'overflow-x': 'hidden',\n 'overflow-y': 'auto'\n });\n\n if (waveformer) {\n jwaudioWD = $('#' + waveformer).width();\n $('#waveformer').css({ width: Math.round(jwaudioWD * jwaudioPercentDone) });\n }\n }\n width = '100%';\n $('#theatre-controls .fave-share').removeClass('fave-share');\n $('#theatre-controls').offset({ top: playoff.top }).css({\n visibility: 'visible',\n 'background-color': 'black'\n });\n } else {\n var aspect = DAR;\n if (playlist && playlist.length > 0 && playlist[0].sources && playlist[0].sources.length > 0 && playlist[0].sources[0].width && playlist[0].sources[0].height) {\n aspect = playlist[0].sources[0].width / playlist[0].sources[0].height;\n log('aspect ratio appears to be: ', aspect);\n }\n\n var maxW = $('.container-ia:last').width();\n log('video max rect avail: ', maxW, 'x', maxH);\n\n var vidW = void 0;\n var vidH = void 0;\n var _arr = [960, 840, 720, 600, 480, 360, 240, 180];\n for (var _i = 0; _i < _arr.length; _i++) {\n vidH = _arr[_i];\n\n vidW = Math.round(vidH * aspect);\n log('video size try fit: ', vidW, 'x', vidH);\n if (vidW <= maxW && vidH <= maxH || vidW <= 320) break;\n }\n width = vidW; // '100%'\n height = vidH;\n\n if (typeof AJS !== 'undefined')\n // eslint-disable-next-line no-undef\n AJS.theatre_controls_position(false, 0, width, height);\n }\n\n if (first) {\n // we havent setup the player yet, but want to setup a watcher\n // for browser resize or mobile orientation changing\n $(window).on('resize orientationchange', function () {\n clearTimeout(Play.throttler);\n Play.throttler = setTimeout(function () {\n // resize/orient flip -- resize and reflow elements\n new Play(jid).responsiveResize();\n }, 250);\n });\n } else if (!audio) {\n jwplayer(jid).resize(width, height);\n }\n };\n\n // ---------- START OBJECT CONSTRUCTOR --------\n\n if (nolinks) {\n identifier = false;\n collection = false;\n noshare = true;\n }\n\n speed = parseFloat(speed);\n\n if (!$(jidsel).length) {\n log('play8.js requires #', jid, ' element on page -- not found');\n return false;\n }\n\n self.responsiveResize(true);\n\n if (identifier !== false) details = 'https://archive.org/details/' + identifier;\n if (tv && tvEnd) details += '/start/' + tvStart + '/end/' + tvEnd;\n\n if (typeof playlist === 'undefined') {\n playlist = [{\n sources: [{ file: '/download/family-rolled/family-rolled.mp4' }, { file: '/download/family-rolled/family-rolled.ogv' }],\n image: '/download/family-rolled/format=Thumbnail&ignore=x.jpg'\n }];\n start = true;\n hide_list = true;\n }\n\n if (!hide_list) {\n if (!list_height) // if user hasn't specified...\n list_height = audio ? HEIGHT_ALIST : HEIGHT_VLIST;\n // now drop down list_height if there aren't many playlist elements...\n list_height = Math.min(list_height, playlist.length * PLAYLIST_ENTRY_HEIGHT);\n }\n\n if (!responsive && !(width > 0 && height > 0)) {\n if (embed) {\n var winw = $(window).width();\n var winh = $(window).height();\n width = audio ? Math.min(winw, CONTROLS_MAX_WIDTH) : winw;\n height = audio ? AUDIO_HEIGHT + list_height : winh - list_height;\n } else if (!aspectratio) {\n width = audio ? AUDIO_WIDTH : VIDEO_WIDTH;\n height = audio ? AUDIO_HEIGHT + list_height : VIDEO_HEIGHT;\n }\n }\n jwwidth = width;\n\n $.each(playlist, function (idx, val) {\n // log(val.sources)\n\n if (typeof val.autoplay !== 'undefined') {\n // for playlist: A B C D; if C has autoplay=false\n // it means play A and (auto)play B -- but stop when B is done\n if (!onCompleteStop) onCompleteStop = [];\n onCompleteStop[idx - 1] = !val.autoplay;\n }\n\n if (typeof val.sources === 'undefined') {\n if (typeof val.file !== 'undefined') val.sources = [{ file: val.file, height: 480 }];\n }\n if (typeof val.sources === 'undefined') {\n // eslint-disable-next-line no-alert\n alert(idx + ': sources undefined!'); // xxx\n }\n\n // log(val.sources)\n });\n\n if (!hide_list) {\n var sty = list_2cols ? '' : 'style=\"height:' + list_height + 'px\"';\n var ialist = '<div id=\"' + jid + '__list\" ' + sty + '> </div>';\n $(ialist).insertAfter(jidsel);\n }\n\n if (tvTitle) {\n // remove the end time (for brevity) for the \"click to play\" center button\n playlist[0].title = playlist[0].title.replace(/( \\d+:\\d+[amp]+)-\\d+:\\d+[amp]+ /, '$1 ');\n }\n\n if (playlist[0].image) playlist[0].image = playlist[0].image.replace(/%2F/g, '/');\n\n var jwcfg = {\n // *could* consider this if we think jwplayer playlists are reasonble in v6.8 now....\n // \"listbar\":{layout:'basic',position:'bottom',size:list_height},\n playlist: JSON.parse(JSON.stringify(playlist)), // deep copy; jw v6.8 _changes_ our list!\n abouttext: 'this item, formats, and more at Internet Archive',\n aboutlink: details,\n startparam: 'start',\n logo: {},\n cast: {},\n playbackRateControls: true,\n playbackRates: [0.5, 1, 2, 3],\n autostart: autoplay,\n fallback: so,\n width: isNaN(jwwidth) ? '100%' : jwwidth,\n height: audio ? CONTROLS_HEIGHT : height\n // + list_height // *could* consider this if we think jw playlists are reasonble in v6.8 now\n\n // alert(width+' x '+height+'/'+list_height)\n\n };if (responsive && !embed) {\n jwcfg.displaytitle = false; // dont show title of 1st track next to big PLAY button\n } else if (aspectratio) {\n jwcfg.width = '100%';\n jwcfg.aspectratio = aspectratio;\n delete jwcfg.height;\n }\n\n if (identifier !== false) {\n var startend = tv && tvEnd ? '?start=' + tvStart + '&end=' + tvEnd : '';\n var embedcode = ('<iframe src=\"https://archive.org/embed/MEDIAID\"\\n width=\"' + (audio ? 500 : VIDEO_WIDTH) + '\"\\n height=\"' + (audio ? AUDIO_HEIGHT : VIDEO_HEIGHT) + '\"\\n frameborder=\"0\"\\n webkitallowfullscreen=\"true\"\\n mozallowfullscreen=\"true\"\\n allowfullscreen></iframe>').replace(/embed\\/MEDIAID/, 'embed/' + identifier + startend).replace(/\\s+/g, ' ');\n\n var embedcodeWP = '[archiveorg ' + identifier + startend + ' width=640 height=' + (audio ? AUDIO_HEIGHT : VIDEO_HEIGHT) + ' frameborder=0 webkitallowfullscreen=true mozallowfullscreen=true]';\n\n jwcfg.mediaid = identifier;\n\n // IFF these exist, fill them in!\n $('#embedcodehere').text(embedcode);\n $('#embedcodehereWP').text(embedcodeWP);\n }\n\n if (embed && !audio && !nolinks || logo) {\n jwcfg.logo = {\n file: '//archive.org/jw/glogo-ghost.png',\n link: details,\n position: 'top-right',\n margin: 2,\n hide: false\n };\n }\n\n if (play_just1 || onCompleteStop) {\n var onCompleteOrig = onComplete;\n\n onComplete = function onComplete(jw) {\n var evt = { done: play_just1 || onCompleteStop[jw.getPlaylistIndex()] };\n if (evt.done) jw.stop(); // dont wanna auto-advance to next track in playlist\n\n if (onCompleteOrig) onCompleteOrig(jw, evt);\n };\n }\n\n // this class was designed _deliberately_ using scoping techniques _outside_ of the\n // methods to allow them to be set/manipulated _per instance_ but auto binding closure\n // vvv around each instance/object -- we can now re-enable that eslint rule...\n /* eslint-enable no-param-reassign */\n\n log(jwcfg);\n jwplayer(jid).setup(jwcfg);\n jwplayer(jid).on('ready', function () {\n log('IA ', jid, ' is ready');\n\n var player = jwplayer(jid); // xxx revisit since arrow fn update made \"this\"!==player\n\n log('NOTE: JW version: ', jwplayer.version);\n if (onTime) log('NOTE: onTime() is in use!');\n\n if (onTime) player.on('time', function () {\n return onTime(player);\n });\n if (onComplete) player.on('complete', function () {\n return onComplete(player);\n });\n if (onDisplayClick) player.on('displayClick', function () {\n return onDisplayClick(player);\n });\n\n readyIA = true;\n\n // NOTE: we now do this here because jwplayer can shrink down the passed in playlist on us!\n self.addClickablePlaylist();\n\n if (audio && responsive && !embed) self.responsiveResize();\n\n if (onReady) onReady(player);\n\n if (responsive && !audio) $(jidsel).css('margin', 'auto'); // center video player\n\n self.add_buttons(player);\n\n if (responsive && !embed && !audio && typeof AJS !== 'undefined')\n // eslint-disable-next-line no-undef\n AJS.theatre_controls_position(false, 0, width, height);\n\n if (responsive && AUDIO_HEIGHT > CONTROLS_HEIGHT) $(jidsel).css('height', AUDIO_HEIGHT); // make space over controlbar for waveform\n\n\n if (!embed && responsive) self.details_setup();else if (embed && location.host.match(/archive\\.org$/) && location.pathname.match(/^\\/embed\\//)) self.embed_setup();\n }).on('meta', function (obj) {\n // only call all this once, because sometime between Feb and May 2014,\n // firefox+flash start sending onMeta() *very* frequently, not just once,\n // and we need to only \"first seek\" once, especially!\n if (!first_onmeta) {\n first_onmeta = true;\n\n log('onMeta() fired');\n $('body').addClass('responsive-playing');\n\n if (!audio && embed && obj.width && obj.height) self.adjustVideoWidth(_this, obj); // xxx this\n\n\n // xxx suck, ubuntu new firefox re-seeks to start w/o double doing this, etc....\n if (start) {\n log('SEEK TO: ', start);\n self.pause();\n jwplayer(jid).seek(start);\n }\n }\n }).on('playlistItem', function (obj) {\n log('onPlaylistItem: ', obj.index);\n\n var player = jwplayer(jid); // xxx revisit since arrow fn update made \"this\"!==player\n\n self.playN(obj.index, true);\n self.seeker_playlist();\n\n if (!tv && !embed && identifier && typeof history.replaceState !== 'undefined') {\n var config = player.getConfig();\n if (config && config.playlist && config.playlist.length > 1 && config.playlist[obj.index] && config.playlist[obj.index].orig) {\n if (update_url_onload) {\n var url = '/details/' + identifier + '/' + encodeURIComponent(config.playlist[obj.index].orig).replace(/%2F/g, '/').replace(/%20/g, '+');\n // eslint-disable-next-line no-undef\n var playset = typeof AJS !== 'undefined' && AJS.arg('playset', 1) ? '&playset=1&autoplay=1' : '';\n history.replaceState({}, null, url + playset);\n } else {\n log('looks like /details/ page loaded cold-state -- leave url AS IS');\n update_url_onload = true;\n }\n }\n }\n\n if (speed !== 1.0) setTimeout(function () {\n self.speed(speed);\n }, 1000);\n\n if (waveformer && !waveformed) {\n var flashy = player.getConfig().provider === 'flash'; // xxxxxxxxxxxxxx\n var $wrapme = $(jidsel);\n if (flashy) $wrapme = $wrapme.parent();\n $wrapme.wrap('<div id=\"' + waveformer + '\" style=\"position:relative\"></div>');\n\n jwaudioWD = $('#' + waveformer).width();\n $('#' + waveformer).prepend('<div id=\"waveformer\" style=\"background-color:rgb(19,160,216); position:absolute; width:0; top:0; bottom:0;\"></div>');\n\n player.on('time', function (evt) {\n if (!evt.duration) return;\n jwaudioPercentDone = evt.position / evt.duration;\n $('#waveformer').css({ width: Math.round(jwaudioWD * jwaudioPercentDone) });\n });\n\n waveformed = true;\n\n setTimeout(function () {\n if (!flashy) $(jidsel).css('background-color', 'transparent');\n $('#' + waveformer).css('background-color', '#ddd');\n }, 1000);\n }\n }).on('playlistComplete', function () {\n if (!audio && collection && !tv) self.related_items_click();\n }).on('error', function (obj) {\n log('err');\n log(obj);\n $(jidsel).css({ 'background-color': 'black' });\n // throw \"onError event\"\n });\n\n return this;\n } // END OF OBJECT CONSTRUCTOR\n\n\n // From here on down, these methods are \"class\"/static and not \"instance\" methods\n\n\n // returns number of seconds (may be float) as string \"hh:mm:ss\"\n // note will omit \"hh:\" if 0 (unless pass in truthy alwaysHH)\n // Stateless function, global to all Play objects\n\n\n _createClass(Play, null, [{\n key: 'sec2hms',\n value: function sec2hms(secIn, alwaysHH) {\n var sec = Math.round(secIn);\n var hr = Math.floor(sec / 3600);\n var min = Math.floor((sec - hr * 3600) / 60);\n sec -= hr * 3600 + min * 60;\n\n // left 0-pad to 2 digits as needed\n var hms = '';\n var tmp = '';\n if (alwaysHH || hr > 0) {\n tmp = '00' + hr;\n hms += tmp.substr(tmp.length - 2, 2);\n hms += ':';\n }\n tmp = '00' + min;\n hms += tmp.substr(tmp.length - 2, 2);\n hms += ':';\n\n tmp = '00' + sec;\n hms += tmp.substr(tmp.length - 2, 2);\n\n return hms;\n }\n\n // [nicked from jwplayer JS v6 code]\n // Converts a time-representing string to a number.\n // @param {String} The input string. Supported are 00:03:00.1 / 03:00.1 / 180.1s / 3.2m / 3.2h\n // @return {Number} The number of seconds.\n\n }, {\n key: 'seconds',\n value: function seconds(strIn) {\n var str = strIn.replace(',', '.');\n var arr = str.split(':');\n var sec = 0;\n if (str.substr(-1) === 's') {\n sec = Number(str.substr(0, str.length - 1));\n } else if (str.substr(-1) === 'm') {\n sec = Number(str.substr(0, str.length - 1)) * 60;\n } else if (str.substr(-1) === 'h') {\n sec = Number(str.substr(0, str.length - 1)) * 3600;\n } else if (arr.length > 1) {\n sec = Number(arr[arr.length - 1]);\n sec += Number(arr[arr.length - 2]) * 60;\n if (arr.length === 3) sec += Number(arr[arr.length - 3]) * 3600;\n } else {\n sec = Number(str);\n }\n return sec;\n }\n }, {\n key: 'seek',\n value: function seek(link) {\n var mat = (link.href + '/').match(/[/#]start\\/([\\d.]+)\\//) || link.href.match(/[?&]start=([\\d.]+)/);\n if (!mat) return true;\n\n var startsec = mat[1];\n jwplayer().seek(startsec);\n\n // if we have a relatively modern browser, simply update the browser url\n if (typeof history.pushState === 'undefined') location.href = link.href; // older browwser -- full page refresh\n else history.pushState({}, null, link.href); // newer!\n\n return false;\n }\n }, {\n key: 'cast_sender_setup',\n value: function cast_sender_setup() {\n if (!window.chrome || window.chrome.cast) return; // not chrome or already loaded -- noop!\n\n /* NOTE: the minified code below is pasted (Mar 2018) from:\n https://www.gstatic.com/cv/js/sender/v1/cast_sender.js\n */\n /* eslint-disable */\n (function () {\n var e = function e(a) {\n return !!document.currentScript && (-1 != document.currentScript.src.indexOf(\"?\" + a) || -1 != document.currentScript.src.indexOf(\"&\" + a));\n },\n f = e(\"loadGamesSDK\") ? \"/cast_game_sender.js\" : \"/cast_sender.js\",\n g = e(\"loadCastFramework\") || e(\"loadCastApplicationFramework\"),\n h = function h() {\n return \"function\" == typeof window.__onGCastApiAvailable ? window.__onGCastApiAvailable : null;\n },\n k = [\"pkedcjkdefgpdelpbcmbmeomcjbeemfm\", \"enhhojjnijigcajfphajepfemndkmdlo\"],\n m = function m(a) {\n a.length ? l(a.shift(), function () {\n m(a);\n }) : n();\n },\n p = function p(a) {\n return \"chrome-extension://\" + a + f;\n },\n l = function l(a, c, b) {\n var d = document.createElement(\"script\");d.onerror = c;b && (d.onload = b);d.src = a;(document.head || document.documentElement).appendChild(d);\n },\n q = function q(a) {\n return 0 <= window.navigator.userAgent.indexOf(a);\n },\n n = function n() {\n var a = h();a && a(!1, \"No cast extension found\");\n },\n r = function r() {\n if (g) {\n var a = 2,\n c = h(),\n b = function b() {\n a--;0 == a && c && c(!0);\n };window.__onGCastApiAvailable = b;l(\"//www.gstatic.com/cast/sdk/libs/sender/1.0/cast_framework.js\", n, b);\n }\n };if (q(\"CriOS\")) {\n var t = window.__gCrWeb && window.__gCrWeb.message && window.__gCrWeb.message.invokeOnHost;t && (r(), t({ command: \"cast.sender.init\" }));\n } else if (q(\"Android\") && q(\"Chrome/\") && window.navigator.presentation) {\n r();var u = window.navigator.userAgent.match(/Chrome\\/([0-9]+)/);m([\"//www.gstatic.com/eureka/clank/\" + (u ? parseInt(u[1], 10) : 0) + f, \"//www.gstatic.com/eureka/clank\" + f]);\n } else window.chrome && window.navigator.presentation && !q(\"Edge\") ? (r(), m(k.map(p))) : n();\n })();\n /* eslint-enable */\n }\n\n /* static except(e){\n // report back home an exception was thrown!\n const img = new Image(1,1)\n img.src =\n \"http://analytics.archive.org/e.gif\" +\n \"?a=\"+ encodeURIComponent(navigator.userAgent) +\n '&e='+ encodeURIComponent(e.toString()) +\n (e.stack && typeof(e.stack)=='string' ?\n '&s='+ encodeURIComponent(e.stack) : '')\n }\n */\n\n }]);\n\n return Play;\n }(); // end class Play\n\n /*\n // trap for ESCAPE key pressed to close a popup\n $(document).keydown(function(e) {\n if (e.keyCode==27)\n $('#jpop').remove()\n })\n */\n\n // allow \"Play(.., ..)\" globally:\n\n\n window.Play = function (id, playlist, options) {\n return new Play(id, playlist, options);\n };\n\n // only these (static) methods are available globally, eg: Play.seek(..)\n var _arr2 = ['sec2hms', 'seconds', 'seek'];\n for (var _i2 = 0; _i2 < _arr2.length; _i2++) {\n var meth = _arr2[_i2];\n window.Play[meth] = Play[meth];\n }\n})(jQuery);"},140:function(e,n,t){t(9)(t(139))},141:function(e,n,t){"use strict";t(140)},9:function(e,n){e.exports=function(e){function n(e){"undefined"!=typeof console&&(console.error||console.log)("[Script Loader]",e)}try{"undefined"!=typeof execScript&&"undefined"!=typeof attachEvent&&"undefined"==typeof addEventListener?execScript(e):"undefined"!=typeof eval?eval.call(null,e):n("EvalError: No eval function available")}catch(e){n(e)}}}});
//# sourceMappingURL=play8.min.js.map