aboutsummaryrefslogtreecommitdiffstats
path: root/assets/js/simple-media.js
diff options
context:
space:
mode:
Diffstat (limited to 'assets/js/simple-media.js')
-rw-r--r--assets/js/simple-media.js627
1 files changed, 627 insertions, 0 deletions
diff --git a/assets/js/simple-media.js b/assets/js/simple-media.js
new file mode 100644
index 00000000..954cc9b2
--- /dev/null
+++ b/assets/js/simple-media.js
@@ -0,0 +1,627 @@
+function InitPxVideo(options) {
+
+ "use strict";
+
+ // Replace all
+ // ---------------------------------
+ if (!String.prototype.replaceAll) {
+ Object.defineProperty(String.prototype, "replaceAll", {
+ value: function(find, replace) {
+ return this.replace(new RegExp(find.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"), "g"), replace);
+ }
+ });
+ }
+
+ // Utilities for caption time codes
+ function video_timecode_min(tc) {
+ var tcpair = [];
+ tcpair = tc.split(" --> ");
+ return videosub_tcsecs(tcpair[0]);
+ }
+
+ function video_timecode_max(tc) {
+ var tcpair = [];
+ tcpair = tc.split(" --> ");
+ return videosub_tcsecs(tcpair[1]);
+ }
+
+ function videosub_tcsecs(tc) {
+ if (tc === null || tc === undefined) {
+ return 0;
+ }
+ else {
+ var tc1 = [],
+ tc2 = [],
+ seconds;
+ tc1 = tc.split(",");
+ tc2 = tc1[0].split(":");
+ seconds = Math.floor(tc2[0]*60*60) + Math.floor(tc2[1]*60) + Math.floor(tc2[2]);
+ return seconds;
+ }
+ }
+
+ // For "manual" captions, adjust caption position when play time changed (via rewind, clicking progress bar, etc.)
+ function adjustManualCaptions(obj) {
+ obj.subcount = 0;
+ while (video_timecode_max(obj.captions[obj.subcount][0]) < obj.movie.currentTime.toFixed(1)) {
+ obj.subcount++;
+ if (obj.subcount > obj.captions.length-1) {
+ obj.subcount = obj.captions.length-1;
+ break;
+ }
+ }
+ }
+
+ // Display captions container and button (for initialization)
+ function showCaptionContainerAndButton(obj) {
+ //obj.captionsBtnContainer.className = "px-video-captions-btn-container show";
+ if (obj.isCaptionDefault) {
+ obj.captionsContainer.className = "px-video-captions show";
+ obj.captionsBtn.setAttribute("checked", "checked");
+ }
+ }
+
+ // Unfortunately, due to scattered support, browser sniffing is required
+ function browserSniff() {
+ var nAgt = navigator.userAgent,
+ browserName = navigator.appName,
+ fullVersion = ""+parseFloat(navigator.appVersion),
+ majorVersion = parseInt(navigator.appVersion,10),
+ nameOffset,
+ verOffset,
+ ix;
+
+ // MSIE 11
+ if ((navigator.appVersion.indexOf("Windows NT") !== -1) && (navigator.appVersion.indexOf("rv:11") !== -1)) {
+ browserName = "IE";
+ fullVersion = "11;";
+ }
+ // MSIE
+ else if ((verOffset=nAgt.indexOf("MSIE")) !== -1) {
+ browserName = "IE";
+ fullVersion = nAgt.substring(verOffset+5);
+ }
+ // Chrome
+ else if ((verOffset=nAgt.indexOf("Chrome")) !== -1) {
+ browserName = "Chrome";
+ fullVersion = nAgt.substring(verOffset+7);
+ }
+ // Safari
+ else if ((verOffset=nAgt.indexOf("Safari")) !== -1) {
+ browserName = "Safari";
+ fullVersion = nAgt.substring(verOffset+7);
+ if ((verOffset=nAgt.indexOf("Version")) !== -1) {
+ fullVersion = nAgt.substring(verOffset+8);
+ }
+ }
+ // Firefox
+ else if ((verOffset=nAgt.indexOf("Firefox")) !== -1) {
+ browserName = "Firefox";
+ fullVersion = nAgt.substring(verOffset+8);
+ }
+ // In most other browsers, "name/version" is at the end of userAgent
+ else if ( (nameOffset=nAgt.lastIndexOf(" ")+1) < (verOffset=nAgt.lastIndexOf("/")) ) {
+ browserName = nAgt.substring(nameOffset,verOffset);
+ fullVersion = nAgt.substring(verOffset+1);
+ if (browserName.toLowerCase()==browserName.toUpperCase()) {
+ browserName = navigator.appName;
+ }
+ }
+ // Trim the fullVersion string at semicolon/space if present
+ if ((ix=fullVersion.indexOf(";")) !== -1) {
+ fullVersion=fullVersion.substring(0,ix);
+ }
+ if ((ix=fullVersion.indexOf(" ")) !== -1) {
+ fullVersion=fullVersion.substring(0,ix);
+ }
+ // Get major version
+ majorVersion = parseInt(""+fullVersion,10);
+ if (isNaN(majorVersion)) {
+ fullVersion = ""+parseFloat(navigator.appVersion);
+ majorVersion = parseInt(navigator.appVersion,10);
+ }
+ // Return data
+ return [browserName, majorVersion];
+ }
+
+ // Global variable
+ var obj = {};
+
+ obj.arBrowserInfo = browserSniff();
+ obj.browserName = obj.arBrowserInfo[0];
+ obj.browserMajorVersion = obj.arBrowserInfo[1];
+
+ // If IE8, stop customization (use fallback)
+ // If IE9, stop customization (use native controls)
+ if (obj.browserName === "IE" && (obj.browserMajorVersion === 8 || obj.browserMajorVersion === 9) ) {
+ return false;
+ }
+
+ // If smartphone or tablet, stop customization as video (and captions in latest devices) are handled natively
+ obj.isSmartphoneOrTablet = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
+ if (obj.isSmartphoneOrTablet) {
+ return false;
+ }
+
+ // Set debug mode
+ if (typeof(options.debug)==="undefined") {
+ options.debug = false;
+ }
+ obj.debug = options.debug;
+
+ // Output browser info to log if debug on
+ if (options.debug) {
+ console.log(obj.browserName + " " + obj.browserMajorVersion);
+ }
+
+ // Set up aria-label for Play button with the videoTitle option
+ if ((typeof(options.videoTitle)==="undefined") || (options.videoTitle==="")) {
+ obj.playAriaLabel = "Play";
+ }
+ else {
+ obj.playAriaLabel = "Play video, " + options.videoTitle;
+ }
+
+ // Get the container, video element, and controls container
+ obj.container = document.getElementById(options.videoId);
+ obj.container.className = obj.container.className + " stopped";
+ obj.movie = obj.container.getElementsByTagName("video")[0];
+ obj.controls = obj.container.getElementsByClassName("px-video-controls")[0];
+
+ // Remove native video controls
+ obj.movie.removeAttribute("controls");
+
+ // Generate random number for ID/FOR attribute values for controls
+ obj.randomNum = Math.floor(Math.random() * (10000));
+
+ // Insert custom video controls
+ if (options.debug) {
+ console.log("Inserting custom video controls");
+ }
+ obj.controls.innerHTML = options.html
+ .replaceAll("{aria-label}", obj.playAriaLabel)
+ .replaceAll("{id}", obj.randomNum);
+
+ // Responsive ffs
+ // ----
+ // Adjust layout per width of video - container
+ //obj.movieWidth = obj.movie.width;
+ //if (obj.movieWidth < 360) {
+ // obj.movieWidth = 360;
+ //}
+ //obj.container.setAttribute("style", "width:" + obj.movieWidth + "px");
+
+ // Adjust layout per width of video - controls/mute offset
+ obj.labelMute = document.getElementById("labelMute" + obj.randomNum);
+ obj.labelMuteOffset = obj.movieWidth - 390;
+ if (obj.labelMuteOffset < 0) {
+ obj.labelMuteOffset = 0;
+ }
+ obj.labelMute.setAttribute("style", "margin-left:" + obj.labelMuteOffset + "px");
+
+ // Get URL of caption file if exists
+ var captionSrc = "",
+ kind,
+ children = obj.movie.childNodes;
+
+ for (var i = 0; i < children.length; i++) {
+ if (children[i].nodeName.toLowerCase() === "track") {
+ kind = children[i].getAttribute("kind");
+ if (kind === "captions") {
+ captionSrc = children[i].getAttribute("src");
+ }
+ }
+ }
+
+ // Record if caption file exists or not
+ obj.captionExists = true;
+ if (captionSrc === "") {
+ obj.captionExists = false;
+ if (options.debug) {
+ console.log("No caption track found.");
+ }
+ }
+ else {
+ if (options.debug) {
+ console.log("Caption track found; URI: " + captionSrc);
+ }
+ }
+
+ // Set captions on/off - on by default
+ if (typeof(options.captionsOnDefault) === "undefined") {
+ options.captionsOnDefault = true;
+ }
+ obj.isCaptionDefault = options.captionsOnDefault;
+
+ // Number of seconds for rewind and forward buttons
+ if (typeof(options.seekInterval) === "undefined") {
+ options.seekInterval = 10;
+ }
+ obj.seekInterval = options.seekInterval;
+
+ // Get the elements for the controls
+ obj.btnPlay = obj.container.getElementsByClassName("px-video-play")[0];
+ obj.btnPause = obj.container.getElementsByClassName("px-video-pause")[0];
+ obj.btnRestart = obj.container.getElementsByClassName("px-video-restart")[0];
+ obj.btnRewind = obj.container.getElementsByClassName("px-video-rewind")[0];
+ obj.btnForward = obj.container.getElementsByClassName("px-video-forward")[0];
+ obj.btnVolume = obj.container.getElementsByClassName("px-video-volume")[0];
+ obj.btnMute = obj.container.getElementsByClassName("px-video-mute")[0];
+ obj.progressBar = obj.container.getElementsByClassName("px-video-progress")[0];
+ obj.progressBarSpan = obj.progressBar.getElementsByTagName("span")[0];
+ obj.captionsContainer = obj.container.getElementsByClassName("px-video-captions")[0];
+ obj.captionsBtn = obj.container.getElementsByClassName("px-video-btnCaptions")[0];
+ obj.captionsBtnContainer = obj.container.getElementsByClassName("px-video-captions-btn-container")[0];
+ obj.duration = obj.container.getElementsByClassName("px-video-duration")[0];
+ obj.txtSeconds = obj.container.getElementsByClassName("px-seconds");
+
+ // Update number of seconds in rewind and fast forward buttons
+ obj.txtSeconds[0].innerHTML = obj.seekInterval;
+ obj.txtSeconds[1].innerHTML = obj.seekInterval;
+
+ // Determine if HTML5 textTracks is supported (for captions)
+ obj.isTextTracks = false;
+ if (obj.movie.textTracks) {
+ obj.isTextTracks = true;
+ }
+
+ // Play
+ obj.btnPlay.addEventListener("click", function() {
+ obj.movie.play();
+
+ obj.container.className = obj.container.className.replace("stopped", "playing");
+
+ obj.btnPlay.className = "px-video-play hide";
+ obj.btnPause.className = "px-video-pause px-video-show-inline";
+ obj.btnPause.focus();
+ }, false);
+
+ // Pause
+ obj.btnPause.addEventListener("click", function() {
+ obj.movie.pause();
+
+ obj.container.className = obj.container.className.replace("playing", "stopped");
+
+ obj.btnPlay.className = "px-video-play px-video-show-inline";
+ obj.btnPause.className = "px-video-pause hide";
+ obj.btnPlay.focus();
+ }, false);
+
+ // Restart
+ obj.btnRestart.addEventListener("click", function() {
+ // Move to beginning
+ obj.movie.currentTime = 0;
+
+ // Special handling for "manual" captions
+ if (!obj.isTextTracks) {
+ obj.subcount = 0;
+ }
+
+ // Play and ensure the play button is in correct state
+ obj.movie.play();
+ obj.btnPlay.className = "px-video-play hide";
+ obj.btnPause.className = "px-video-pause px-video-show-inline";
+
+ }, false);
+
+ // Rewind
+ obj.btnRewind.addEventListener("click", function() {
+ var targetTime = obj.movie.currentTime - obj.seekInterval;
+ if (targetTime < 0) {
+ obj.movie.currentTime = 0;
+ }
+ else {
+ obj.movie.currentTime = targetTime;
+ }
+ // Special handling for "manual" captions
+ if (!obj.isTextTracks) {
+ adjustManualCaptions(obj);
+ }
+ }, false);
+
+ // Fast forward
+ obj.btnForward.addEventListener("click", function() {
+ var targetTime = obj.movie.currentTime + obj.seekInterval;
+ if (targetTime > obj.movie.duration) {
+ obj.movie.currentTime = obj.movie.duration;
+ }
+ else {
+ obj.movie.currentTime = targetTime;
+ }
+ // Special handling for "manual" captions
+ if (!obj.isTextTracks) {
+ adjustManualCaptions(obj);
+ }
+ }, false);
+
+ // Get the HTML5 range input element and append audio volume adjustment on change
+ obj.btnVolume.addEventListener("change", function() {
+ obj.movie.volume = parseFloat(this.value / 10);
+ }, false);
+
+ // Mute
+ obj.btnMute.addEventListener("click", function() {
+ if (obj.movie.muted === true) {
+ obj.movie.muted = false;
+ }
+ else {
+ obj.movie.muted = true;
+ }
+ }, false);
+
+ // Duration
+ obj.movie.addEventListener("timeupdate", function() {
+ obj.secs = parseInt(obj.movie.currentTime % 60);
+ obj.mins = parseInt((obj.movie.currentTime / 60) % 60);
+
+ // Ensure it"s two digits. For example, 03 rather than 3.
+ obj.secs = ("0" + obj.secs).slice(-2);
+ obj.mins = ("0" + obj.mins).slice(-2);
+
+ // Render
+ obj.duration.innerHTML = obj.mins + ":" + obj.secs;
+ }, false);
+
+ // Progress bar
+ obj.movie.addEventListener("timeupdate", function() {
+ obj.percent = (100 / obj.movie.duration) * obj.movie.currentTime;
+ if (obj.percent > 0) {
+ obj.progressBar.value = obj.percent;
+ obj.progressBarSpan.innerHTML = obj.percent;
+ }
+ }, false);
+
+ // Skip when clicking progress bar
+ obj.progressBar.addEventListener("click", function(e) {
+ obj.pos = (e.pageX - this.offsetLeft) / this.offsetWidth;
+ obj.movie.currentTime = obj.pos * obj.movie.duration;
+
+ // Special handling for "manual" captions
+ if (!obj.isTextTracks) {
+ adjustManualCaptions(obj);
+ }
+ });
+
+ // Clear captions at end of video
+ obj.movie.addEventListener("ended", function() {
+ obj.captionsContainer.innerHTML = "";
+ });
+
+ // ***
+ // Captions
+ // ***
+
+ // Toggle display of captions via captions button
+ obj.captionsBtn.addEventListener("click", function() {
+ if (this.checked) {
+ obj.captionsContainer.className = "px-video-captions show";
+ } else {
+ obj.captionsContainer.className = "px-video-captions hide";
+ }
+ }, false);
+
+ // If no caption file exists, hide container for caption text
+ if (!obj.captionExists) {
+ obj.captionsContainer.className = "px-video-captions hide";
+ }
+
+ // If caption file exists, process captions
+ else {
+
+ // 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 ((obj.browserName==="IE" && obj.browserMajorVersion===10) ||
+ (obj.browserName==="IE" && obj.browserMajorVersion===11) ||
+ (obj.browserName==="Firefox" && obj.browserMajorVersion>=31) ||
+ (obj.browserName==="Safari" && obj.browserMajorVersion>=7)) {
+ if (options.debug) {
+ console.log("Detected IE 10/11 or Firefox 31+ or Safari 7+");
+ }
+ // set to false so skips to "manual" captioning
+ obj.isTextTracks = false;
+
+ // turn off native caption rendering to avoid double captions [doesn"t work in Safari 7; see patch below]
+ var track = {};
+ var tracks = obj.movie.textTracks;
+ for (var j=0; j < tracks.length; j++) {
+ track = obj.movie.textTracks[j];
+ track.mode = "hidden";
+ }
+ }
+
+ // Rendering caption tracks - native support required - http://caniuse.com/webvtt
+ if (obj.isTextTracks) {
+ if (options.debug) {
+ console.log("textTracks supported");
+ }
+ showCaptionContainerAndButton(obj);
+
+ var track = {};
+ var tracks = obj.movie.textTracks;
+ for (var j=0; j < tracks.length; j++) {
+ track = obj.movie.textTracks[j];
+ track.mode = "hidden";
+ if (track.kind === "captions") {
+ track.addEventListener("cuechange",function() {
+ if (this.activeCues[0]) {
+ if (this.activeCues[0].hasOwnProperty("text")) {
+ obj.captionsContainer.innerHTML = this.activeCues[0].text;
+ }
+ }
+ },false);
+ }
+ }
+ }
+ // Caption tracks not natively supported
+ else {
+ if (options.debug) {
+ console.log("textTracks not supported so rendering captions manually");
+ }
+ showCaptionContainerAndButton(obj);
+
+ // Render captions from array at appropriate time
+ obj.currentCaption = "";
+ obj.subcount = 0;
+ obj.captions = [];
+
+ obj.movie.addEventListener("timeupdate", function() {
+ // Check if the next caption is in the current time range
+ if (obj.movie.currentTime.toFixed(1) > video_timecode_min(obj.captions[obj.subcount][0]) &&
+ obj.movie.currentTime.toFixed(1) < video_timecode_max(obj.captions[obj.subcount][0])) {
+ obj.currentCaption = obj.captions[obj.subcount][1];
+ }
+ // Is there a next timecode?
+ if (obj.movie.currentTime.toFixed(1) > video_timecode_max(obj.captions[obj.subcount][0]) &&
+ obj.subcount < (obj.captions.length-1)) {
+ obj.subcount++;
+ }
+ // Render the caption
+ obj.captionsContainer.innerHTML = obj.currentCaption;
+ }, false);
+
+ if (captionSrc !== "") {
+ // Create XMLHttpRequest object
+ var xhr;
+ if (window.XMLHttpRequest) {
+ xhr = new XMLHttpRequest();
+ } else if (window.ActiveXObject) { // IE8
+ xhr = new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === 4) {
+ if (xhr.status === 200) {
+ if (options.debug) {
+ console.log("xhr = 200");
+ }
+
+ obj.captions = [];
+ var records = [],
+ record,
+ req = xhr.responseText;
+ records = req.split("\n\n");
+ for (var r=0; r < records.length; r++) {
+ record = records[r];
+ obj.captions[r] = [];
+ obj.captions[r] = record.split("\n");
+ }
+ // Remove first element ("VTT")
+ obj.captions.shift();
+
+ if (options.debug) {
+ console.log("Successfully loaded the caption file via ajax.");
+ }
+ } else {
+ if (options.debug) {
+ console.log("There was a problem loading the caption file via ajax.");
+ }
+ }
+ }
+ }
+ xhr.open("get", captionSrc, true);
+ xhr.send();
+ }
+ }
+
+ // If Safari 7, removing track from DOM [see "turn off native caption rendering" above]
+ if (obj.browserName === "Safari" && obj.browserMajorVersion === 7) {
+ console.log("Safari 7 detected; removing track from DOM");
+ var tracks = obj.movie.getElementsByTagName("track");
+ obj.movie.removeChild(tracks[0]);
+ }
+
+ }
+};
+
+
+
+/*$(function() {
+ $("video").simplePlayer();
+});*/
+
+// Simple player plugin
+// ---------------------------------
+/*;(function($) {
+ $.fn.simplePlayer = function (settings) {
+ // Config defaults
+ var config = {
+ wrapperClass: "media", // Class name added to replaced selects
+ shownClass: "in",
+ autoplay: false,
+ templates: {
+ controls: "<div class="media-controls js-media-controls"> \
+ <button type="button" class="play button-toggle-play js-button-toggle-play"> \
+ <span class="icon-play"></span> \
+ </button> \
+ <div class="progress progress-play js-progress-play" role="progress-bar"> \
+ <div class="progress-buffered js-progress-buffered"></div> \
+ <div class="progress-played js-progress-played"></div> \
+ </div> \
+ <div class="time js-time"> \
+ <span class="time-elapsed js-time-elapsed">88:88</span> \
+ <span class="time-seperator js-time-seperator">/</span> \
+ <span class="time-total js-time-total">88:88</span> \
+ </div> \
+ <div class="volume has-popover js-volume"> \
+ <button type="button" class="button-toggle-mute js-button-toggle-mute"> \
+ <span class="icon-volume-up"></span> \
+ </button> \
+ <div class="popover popover-volume js-popover-volume"> \
+ <div class="progress vertical-progress progress-audio-volume js-progress-audio-volume"> \
+ <div class="progress-volume js-progress-volume" style="height: 80%"></div> \
+ </div> \
+ <div class="volume-label js-volume-label">100%</div> \
+ </div> \
+ </div> \
+ <button type="button" class="fullscreen button-fullscreen js-button-fullscreen"> \
+ <span class="icon-resize-full"></span> \
+ </button> \
+ </div>",
+ overlay: "<div class="overlay overlay-play"><span><i class="icon-play"></i></span></div>"
+ }
+ };
+
+ // Extend settings if they"re passed
+ if (settings) {
+ $.extend(config, settings);
+ }
+
+ this.each(function() {
+ var player = this,
+ status = {},
+ $player = $(this).wrap("<div class="" + config.wrapperClass + (config.autoplay ? " playing" : " stopped") + "" />"),
+ $wrapper = $player.parents("." + config.wrapperClass),
+ supportMP4 = (function (v) { return (v.canPlayType && v.canPlayType("video/mp4")); }(document.createElement("video")));
+
+ console.log($wrapper);
+
+ // Inject the controls
+ $(config.templates.controls).insertAfter($player);
+ $(config.templates.overlay).insertAfter($player);
+
+ // Select controls
+ var $playbackToggle = $(".js-button-toggle-play"),
+ $muteToggle = $(".js-button-toggle-mute");
+
+ function togglePlayback() {
+ if(status.playing && status.playing == true) {
+ player.pause();
+ status.playing = false;
+ $wrapper.removeClass("playing").addClass("paused");
+ } else {
+ player.play();
+ status.playing = true;
+ $wrapper.removeClass("paused stopped").addClass("playing");
+ }
+ $("span", this).attr("class", "icon-" + (status.playing ? "pause" : "play"));
+ };
+
+ function toggleMute() {
+ player.muted = !status.muted;
+ status.muted = player.muted;
+ $("span", this).attr("class", "icon-" + (status.muted ? "mute" : "volume-up"));
+ };
+
+ $playbackToggle.on("click", togglePlayback);
+ $muteToggle.on("click", toggleMute);
+ });
+ };
+})(jQuery);*/ \ No newline at end of file