diff options
author | Sam Potts <me@sampotts.me> | 2015-06-27 16:21:38 +1000 |
---|---|---|
committer | Sam Potts <me@sampotts.me> | 2015-06-27 16:21:38 +1000 |
commit | 240aa7aa5f77902fd8dbeebc1a7239e6f0e20c56 (patch) | |
tree | 648c5b057bb190f7ce0d858f845db71d3292d4e5 /src/js | |
parent | 398815857f05dad8c0b2d6b1d58c40eb90df2d11 (diff) | |
parent | 654e9cd623212a5bebf3930972ef04d5e2d2bbcb (diff) | |
download | plyr-240aa7aa5f77902fd8dbeebc1a7239e6f0e20c56.tar.lz plyr-240aa7aa5f77902fd8dbeebc1a7239e6f0e20c56.tar.xz plyr-240aa7aa5f77902fd8dbeebc1a7239e6f0e20c56.zip |
Merge branch 'master' into develop
# Conflicts:
# dist/plyr.css
# dist/plyr.js
Diffstat (limited to 'src/js')
-rw-r--r-- | src/js/plyr.js | 213 |
1 files changed, 161 insertions, 52 deletions
diff --git a/src/js/plyr.js b/src/js/plyr.js index 865bb9a9..5d43fb0b 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -1,6 +1,6 @@ // ========================================================================== // Plyr -// plyr.js v1.1.5 +// plyr.js v1.1.13 // https://github.com/selz/plyr // License: The MIT License (MIT) // ========================================================================== @@ -383,12 +383,28 @@ // append it to the parent. if (sibling) { parent.insertBefore(child, sibling); - } else { + } + else { parent.appendChild(child); } } } + // Unwrap an element + // http://plainjs.com/javascript/manipulation/unwrap-a-dom-element-35/ + function _unwrap(wrapper) { + // Get the element's parent node + var parent = wrapper.parentNode; + + // Move all children out of the element + while (wrapper.firstChild) { + parent.insertBefore(wrapper.firstChild, wrapper); + } + + // Remove the empty element + parent.removeChild(wrapper); + } + // Remove an element function _remove(element) { element.parentNode.removeChild(element); @@ -421,7 +437,7 @@ // Toggle event function _toggleHandler(element, events, callback, toggle) { - events = events.split(" "); + var eventList = events.split(" "); // If a nodelist is passed, call itself on each node if(element instanceof NodeList) { @@ -434,8 +450,8 @@ } // If a single node is passed, bind the event listener - for (var i = 0; i < events.length; i++) { - element[toggle ? "addEventListener" : "removeEventListener"](events[i], callback, false); + for (var i = 0; i < eventList.length; i++) { + element[toggle ? "addEventListener" : "removeEventListener"](eventList[i], callback, false); } } @@ -952,13 +968,13 @@ // Enable UI _showCaptions(player); - // If IE 10/11 or Firefox 31+ or Safari 7+, don"t use native captioning (still doesn"t work although they claim it"s now supported) - if ((player.browser.name === "IE" && player.browser.version === 10) || - (player.browser.name === "IE" && player.browser.version === 11) || - (player.browser.name === "Firefox" && player.browser.version >= 31) || - (player.browser.name === "Safari" && player.browser.version >= 7)) { + // Disable unsupported browsers than report false positive + if ((player.browser.name === "IE" && player.browser.version >= 10) || + (player.browser.name === "Firefox" && player.browser.version >= 31) || + (player.browser.name === "Chrome" && player.browser.version >= 43) || + (player.browser.name === "Safari" && player.browser.version >= 7)) { // Debugging - _log("Detected IE 10/11 or Firefox 31+ or Safari 7+."); + _log("Detected unsupported browser for HTML5 captions. Using fallback."); // Set to false so skips to "manual" captioning player.usingTextTracks = false; @@ -1078,6 +1094,22 @@ player.media.pause(); } + // Toggle playback + function _togglePlay(toggle) { + // Play + if(toggle === true) { + _play(); + } + // Pause + else if(toggle === false) { + _pause(); + } + // True toggle + else { + player.media[player.media.paused ? "play" : "pause"](); + } + } + // Rewind function _rewind(seekTime) { // Use default if needed @@ -1181,9 +1213,39 @@ // Set class hook _toggleClass(player.container, config.classes.fullscreen.active, player.isFullscreen); - // Remove hover class because mouseleave doesn't occur - if (player.isFullscreen) { + // Toggle controls visibility based on mouse movement and location + var hoverTimer, isMouseOver = false; + + // Show the player controls + function _showControls() { + // Set shown class + _toggleClass(player.controls, config.classes.hover, true); + + // Clear timer every movement + window.clearTimeout(hoverTimer); + + // If the mouse is not over the controls, set a timeout to hide them + if(!isMouseOver) { + hoverTimer = window.setTimeout(function() { + _toggleClass(player.controls, config.classes.hover, false); + }, 2000); + } + } + + // Check mouse is over the controls + function _setMouseOver (event) { + isMouseOver = (event.type === "mouseenter"); + } + + if(config.fullscreen.hideControls) { + // Hide on entering full screen _toggleClass(player.controls, config.classes.hover, false); + + // Keep an eye on the mouse location in relation to controls + _toggleHandler(player.controls, "mouseenter mouseleave", _setMouseOver, player.isFullscreen); + + // Show the controls on mouse move + _toggleHandler(player.container, "mousemove", _showControls, player.isFullscreen); } } @@ -1197,40 +1259,32 @@ // Set volume function _setVolume(volume) { - // Bail if there's no volume element - if(!player.volume) { - return; - } - - // Use default if needed + // Use default if no value specified if(typeof volume === "undefined") { if(config.storage.enabled && _storage().supported) { volume = window.localStorage[config.storage.key] || config.volume; } else { volume = config.volume; - } + } } + // Maximum is 10 if(volume > 10) { volume = 10; } - - // If the controls are there - if(player.supported.full) { - player.volume.value = volume; + // Minimum is 0 + if(volume < 0) { + volume = 0; } // Set the player volume player.media.volume = parseFloat(volume / 10); - // Update the UI - _checkMute(); - - // Store the volume in storage - if(config.storage.enabled && _storage().supported) { - window.localStorage.setItem(config.storage.key, volume); - } + // Toggle muted state + if(player.media.muted && volume > 0) { + _toggleMute(); + } } // Mute @@ -1240,16 +1294,32 @@ muted = !player.media.muted; } - // If the controls are there - if(player.supported.full) { - player.buttons.mute.checked = muted; - } - // Set mute on the player player.media.muted = muted; + } + + // Update volume UI and storage + function _updateVolume() { + // Get the current volume + var volume = player.media.muted ? 0 : (player.media.volume * 10); + + // Update the <input type="range"> if present + if(player.supported.full && player.volume) { + player.volume.value = volume; + } - // Update UI - _checkMute(); + // Store the volume in storage + if(config.storage.enabled && _storage().supported) { + window.localStorage.setItem(config.storage.key, volume); + } + + // Toggle class if muted + _toggleClass(player.container, config.classes.muted, (volume === 0)); + + // Update checkbox for mute state + if(player.supported.full && player.buttons.mute) { + player.buttons.mute.checked = (volume === 0); + } } // Toggle captions @@ -1268,11 +1338,6 @@ _toggleClass(player.container, config.classes.captions.active, show); } - // Check mute state - function _checkMute() { - _toggleClass(player.container, config.classes.muted, (player.media.volume === 0 || player.media.muted)); - } - // Check if media is loading function _checkLoading(event) { var loading = (event.type === "waiting"); @@ -1544,7 +1609,7 @@ _on(player.media, "playing", _updateProgress); // Handle native mute - _on(player.media, "volumechange", _checkMute); + _on(player.media, "volumechange", _updateVolume); // Handle native play/pause _on(player.media, "play pause", _checkPlaying); @@ -1570,16 +1635,52 @@ } }); } + } - // Bind to mouse hover - if(config.fullscreen.hideControls) { - _on(player.controls, "mouseenter mouseleave", function(event) { - _toggleClass(player.controls, config.classes.hover, (event.type === "mouseenter")); - }); + // Destroy an instance + function _destroy() { + // Bail if the element is not initialized + if(!player.init) { + return null; } + + // Reset container classname + player.container.setAttribute("class", config.selectors.container.replace(".", "")); + + // Event listeners are removed when elements are removed + // http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory + + // Remove controls + _remove(_getElement(config.selectors.controls)); + + // If video, we need to remove some more + if(player.type === "video") { + // Remove captions + _remove(_getElement(config.selectors.captions)); + + // Remove video wrapper + _unwrap(player.videoContainer); + } + + // Restore native video controls + player.media.setAttribute("controls", ""); + + // Clone the media element to remove listeners + // http://stackoverflow.com/questions/19469881/javascript-remove-all-event-listeners-of-specific-type + var clone = player.media.cloneNode(true); + player.media.parentNode.replaceChild(clone, player.media); + + // Remove init flag + player.init = false; } + // Setup a player function _init() { + // Bail if the element is initialized + if(player.init) { + return null; + } + // Setup the fullscreen api fullscreen = _fullscreen(); @@ -1631,6 +1732,7 @@ // Set volume _setVolume(); + _updateVolume(); // Setup fullscreen _setupFullscreen(); @@ -1640,10 +1742,14 @@ } // Successful setup - return true; + player.init = true; } - if(!_init()) { + // Initialize instance + _init(); + + // If init failed, return an empty object + if(!player.init) { return {}; } @@ -1658,11 +1764,14 @@ source: _parseSource, poster: _updatePoster, setVolume: _setVolume, + togglePlay: _togglePlay, toggleMute: _toggleMute, toggleCaptions: _toggleCaptions, toggleFullscreen: _toggleFullscreen, isFullscreen: function() { return player.isFullscreen || false; }, - support: function(mimeType) { return _supportMime(player, mimeType); } + support: function(mimeType) { return _supportMime(player, mimeType); }, + destroy: _destroy, + restore: _init } } |