mirror of
https://github.com/videojs/video.js.git
synced 2025-01-10 23:30:03 +02:00
335 lines
11 KiB
JavaScript
335 lines
11 KiB
JavaScript
_V_.merge = function(obj1, obj2, safe){
|
|
// Make sure second object exists
|
|
if (!obj2) { obj2 = {}; };
|
|
|
|
for (var attrname in obj2){
|
|
if (obj2.hasOwnProperty(attrname) && (!safe || !obj1.hasOwnProperty(attrname))) { obj1[attrname]=obj2[attrname]; }
|
|
}
|
|
return obj1;
|
|
};
|
|
_V_.extend = function(obj){ this.merge(this, obj, true); };
|
|
|
|
_V_.extend({
|
|
tech: {}, // Holder for playback technology settings
|
|
controlSets: {}, // Holder for control set definitions
|
|
|
|
techSupports: function(tech, type, name){
|
|
if (_V_[tech].supports[type]) {
|
|
return _V_[tech].supports[type][name];
|
|
}
|
|
return false;
|
|
},
|
|
updateTechSupport: function(tech, type, name, value){
|
|
if (_V_[tech].supports[type] === undefined) { _V_[tech].supports[type] = {}; }
|
|
_V_[tech].supports[type][name] = value;
|
|
},
|
|
|
|
// Device Checks
|
|
isIE: function(){ return !+"\v1"; },
|
|
isIPad: function(){ return navigator.userAgent.match(/iPad/i) !== null; },
|
|
isIPhone: function(){ return navigator.userAgent.match(/iPhone/i) !== null; },
|
|
isIOS: function(){ return VideoJS.isIPhone() || VideoJS.isIPad(); },
|
|
iOSVersion: function() {
|
|
var match = navigator.userAgent.match(/OS (\d+)_/i);
|
|
if (match && match[1]) { return match[1]; }
|
|
},
|
|
isAndroid: function(){ return navigator.userAgent.match(/Android.*AppleWebKit/i) !== null; },
|
|
androidVersion: function() {
|
|
var match = navigator.userAgent.match(/Android (\d+)\./i);
|
|
if (match && match[1]) { return match[1]; }
|
|
},
|
|
//isAndroidBrowser
|
|
|
|
each: function(arr, fn){
|
|
if (!arr || arr.length === 0) { return; }
|
|
for (var i=0,j=arr.length; i<j; i++) {
|
|
fn.call(this, arr[i], i);
|
|
}
|
|
},
|
|
|
|
el: function(id){ return document.getElementById(id); },
|
|
createElement: function(tagName, attributes){
|
|
var el = document.createElement(tagName),
|
|
attrname;
|
|
for (attrname in attributes){
|
|
if (attributes.hasOwnProperty(attrname)) {
|
|
if (attrname.indexOf("-") !== -1) {
|
|
el.setAttribute(attrname, attributes[attrname]);
|
|
} else {
|
|
el[attrname] = attributes[attrname];
|
|
}
|
|
}
|
|
}
|
|
return el;
|
|
},
|
|
|
|
insertFirst: function(node, parent){
|
|
if (parent.firstChild) {
|
|
parent.insertBefore(node, parent.firstChild);
|
|
} else {
|
|
parent.appendChild(node);
|
|
}
|
|
},
|
|
|
|
addClass: function(element, classToAdd){
|
|
if ((" "+element.className+" ").indexOf(" "+classToAdd+" ") == -1) {
|
|
element.className = element.className === "" ? classToAdd : element.className + " " + classToAdd;
|
|
}
|
|
},
|
|
|
|
removeClass: function(element, classToRemove){
|
|
if (element.className.indexOf(classToRemove) == -1) { return; }
|
|
var classNames = element.className.split(" ");
|
|
classNames.splice(classNames.indexOf(classToRemove),1);
|
|
element.className = classNames.join(" ");
|
|
},
|
|
|
|
remove: function(item, array){
|
|
if (!array) return;
|
|
var i = array.indexOf(item);
|
|
if (i != -1) {
|
|
return array.splice(i, 1)
|
|
};
|
|
},
|
|
|
|
// Attempt to block the ability to select text while dragging controls
|
|
blockTextSelection: function(){
|
|
document.body.focus();
|
|
document.onselectstart = function () { return false; };
|
|
},
|
|
// Turn off text selection blocking
|
|
unblockTextSelection: function(){ document.onselectstart = function () { return true; }; },
|
|
|
|
// Return seconds as H:MM:SS or M:SS
|
|
// Supplying a guide (in seconds) will include enough leading zeros to cover the length of the guide
|
|
formatTime: function(seconds, guide) {
|
|
var guide = guide || seconds, // Default to using seconds as guide
|
|
s = Math.floor(seconds % 60),
|
|
m = Math.floor(seconds / 60 % 60),
|
|
h = Math.floor(seconds / 3600),
|
|
gm = Math.floor(guide / 60 % 60),
|
|
gh = Math.floor(guide / 3600);
|
|
|
|
// Check if we need to show hours
|
|
h = (h > 0 || gh > 0) ? h + ":" : "";
|
|
|
|
// If hours are showing, we may need to add a leading zero.
|
|
// Always show at least one digit of minutes.
|
|
m = (((h || gm >= 10) && m < 10) ? "0" + m : m) + ":";
|
|
|
|
// Check if leading zero is need for seconds
|
|
s = (s < 10) ? "0" + s : s;
|
|
|
|
return h + m + s;
|
|
},
|
|
|
|
capitalize: function(string){
|
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
},
|
|
|
|
// Return the relative horizonal position of an event as a value from 0-1
|
|
getRelativePosition: function(x, relativeElement){
|
|
return Math.max(0, Math.min(1, (x - _V_.findPosX(relativeElement)) / relativeElement.offsetWidth));
|
|
},
|
|
|
|
getComputedStyleValue: function(element, style){
|
|
return window.getComputedStyle(element, null).getPropertyValue(style);
|
|
},
|
|
|
|
trim: function(string){ return string.toString().replace(/^\s+/, "").replace(/\s+$/, ""); },
|
|
round: function(num, dec) {
|
|
if (!dec) { dec = 0; }
|
|
return Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
|
|
},
|
|
|
|
isEmpty: function(object) {
|
|
for (var prop in object) {
|
|
return false;
|
|
}
|
|
return true;
|
|
},
|
|
|
|
// Mimic HTML5 TimeRange Spec.
|
|
createTimeRange: function(start, end){
|
|
return {
|
|
length: 1,
|
|
start: function() { return start; },
|
|
end: function() { return end; }
|
|
};
|
|
},
|
|
|
|
/* Element Data Store. Allows for binding data to an element without putting it directly on the element.
|
|
Ex. Event listneres are stored here.
|
|
(also from jsninja.com)
|
|
================================================================================ */
|
|
cache: {}, // Where the data is stored
|
|
guid: 1, // Unique ID for the element
|
|
expando: "vdata" + (new Date).getTime(), // Unique attribute to store element's guid in
|
|
|
|
// Returns the cache object where data for the element is stored
|
|
getData: function(elem){
|
|
// _V_.log(arguments.callee.caller.arguments.callee.caller)
|
|
var id = elem[_V_.expando];
|
|
if (!id) {
|
|
id = elem[_V_.expando] = _V_.guid++;
|
|
_V_.cache[id] = {};
|
|
}
|
|
return _V_.cache[id];
|
|
},
|
|
// Delete data for the element from the cache and the guid attr from element
|
|
removeData: function(elem){
|
|
var id = elem[_V_.expando];
|
|
if (!id) { return; }
|
|
// Remove all stored data
|
|
delete _V_.cache[id];
|
|
// Remove the expando property from the DOM node
|
|
try {
|
|
delete elem[_V_.expando];
|
|
} catch(e) {
|
|
if (elem.removeAttribute) {
|
|
elem.removeAttribute(_V_.expando);
|
|
} else {
|
|
// IE doesn't appear to support removeAttribute on the document element
|
|
elem[_V_.expando] = null;
|
|
}
|
|
}
|
|
},
|
|
|
|
/* Proxy (a.k.a Bind or Context). A simple method for changing the context of a function
|
|
It also stores a unique id on the function so it can be easily removed from events
|
|
================================================================================ */
|
|
proxy: function(context, fn) {
|
|
// Make sure the function has a unique ID
|
|
if (!fn.guid) { fn.guid = _V_.guid++; }
|
|
// Create the new function that changes the context
|
|
var ret = function() {
|
|
return fn.apply(context, arguments);
|
|
};
|
|
|
|
// Give the new function the same ID
|
|
// (so that they are equivalent and can be easily removed)
|
|
ret.guid = fn.guid;
|
|
|
|
return ret;
|
|
},
|
|
|
|
get: function(url, onSuccess, onError){
|
|
// if (netscape.security.PrivilegeManager.enablePrivilege) {
|
|
// netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
|
|
// }
|
|
|
|
var local = (url.indexOf("file:") == 0 || (window.location.href.indexOf("file:") == 0 && url.indexOf("http:") == -1));
|
|
|
|
if (typeof XMLHttpRequest == "undefined") {
|
|
XMLHttpRequest = function () {
|
|
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) {}
|
|
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (f) {}
|
|
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (g) {}
|
|
throw new Error("This browser does not support XMLHttpRequest.");
|
|
};
|
|
}
|
|
|
|
var request = new XMLHttpRequest();
|
|
|
|
try {
|
|
request.open("GET", url);
|
|
} catch(e) {
|
|
_V_.log("VideoJS XMLHttpRequest (open)", e);
|
|
// onError(e);
|
|
return false;
|
|
}
|
|
|
|
request.onreadystatechange = _V_.proxy(this, function() {
|
|
if (request.readyState == 4) {
|
|
if (request.status == 200 || local && request.status == 0) {
|
|
onSuccess(request.responseText);
|
|
} else {
|
|
if (onError) {
|
|
onError();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
try {
|
|
request.send();
|
|
} catch(e) {
|
|
_V_.log("VideoJS XMLHttpRequest (send)", e);
|
|
if (onError) {
|
|
onError(e);
|
|
}
|
|
}
|
|
},
|
|
|
|
/* Local Storage
|
|
================================================================================ */
|
|
setLocalStorage: function(key, value){
|
|
// IE was throwing errors referencing the var anywhere without this
|
|
var localStorage = localStorage || false;
|
|
if (!localStorage) { return; }
|
|
try {
|
|
localStorage[key] = value;
|
|
} catch(e) {
|
|
if (e.code == 22 || e.code == 1014) { // Webkit == 22 / Firefox == 1014
|
|
_V_.log("LocalStorage Full (VideoJS)", e);
|
|
} else {
|
|
_V_.log("LocalStorage Error (VideoJS)", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
// usage: log('inside coolFunc', this, arguments);
|
|
// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
|
|
_V_.log = function(){
|
|
_V_.log.history = _V_.log.history || [];// store logs to an array for reference
|
|
_V_.log.history.push(arguments);
|
|
if(window.console) {
|
|
arguments.callee = arguments.callee.caller;
|
|
var newarr = [].slice.call(arguments);
|
|
(typeof console.log === 'object' ? _V_.log.apply.call(console.log, console, newarr) : console.log.apply(console, newarr));
|
|
}
|
|
};
|
|
|
|
// make it safe to use console.log always
|
|
(function(b){function c(){}for(var d="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,timeStamp,profile,profileEnd,time,timeEnd,trace,warn".split(","),a;a=d.pop();){b[a]=b[a]||c}})((function(){try
|
|
{console.log();return window.console;}catch(err){return window.console={};}})());
|
|
|
|
// Offset Left
|
|
// getBoundingClientRect technique from John Resig http://ejohn.org/blog/getboundingclientrect-is-awesome/
|
|
if ("getBoundingClientRect" in document.documentElement) {
|
|
_V_.findPosX = function(el) {
|
|
var box;
|
|
|
|
try {
|
|
box = el.getBoundingClientRect();
|
|
} catch(e) {}
|
|
|
|
if (!box) { return 0; }
|
|
|
|
var docEl = document.documentElement,
|
|
body = document.body,
|
|
clientLeft = docEl.clientLeft || body.clientLeft || 0,
|
|
scrollLeft = window.pageXOffset || body.scrollLeft,
|
|
left = box.left + scrollLeft - clientLeft;
|
|
|
|
return left;
|
|
};
|
|
} else {
|
|
_V_.findPosX = function(el) {
|
|
var curleft = el.offsetLeft;
|
|
// _V_.log(obj.className, obj.offsetLeft)
|
|
while(el = obj.offsetParent) {
|
|
if (el.className.indexOf("video-js") == -1) {
|
|
// _V_.log(el.offsetParent, "OFFSETLEFT", el.offsetLeft)
|
|
// _V_.log("-webkit-full-screen", el.webkitMatchesSelector("-webkit-full-screen"));
|
|
// _V_.log("-webkit-full-screen", el.querySelectorAll(".video-js:-webkit-full-screen"));
|
|
} else {
|
|
}
|
|
curleft += el.offsetLeft;
|
|
}
|
|
return curleft;
|
|
};
|
|
}
|