videojs_rails 4.6.4 → 4.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/videojs_rails/version.rb +1 -1
- data/vendor/assets/javascripts/video.js.erb +523 -376
- data/vendor/assets/stylesheets/video-js.css.erb +29 -13
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c91579dfef47310e8313775c8ce6e3802316052f
|
4
|
+
data.tar.gz: b6a514289bfd81adff7796b8d6cf352a62bd2dda
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7edd09f2fe6c10c64475e83a16f65f22349f3b11ddecd213ae23b26e83b0b68f6eb36dfa19925da0a1c3478869c6efd35138a760bc711731aa589e5f828a4281
|
7
|
+
data.tar.gz: 340981a79f646701e48ea8a986559ee7c8e6e2a6c102da3cb1bcaf9eeb843c2eebc1f79fde1dc2445d8a2837611b9ad22250b08d093e849cc57e81094c0e9d6e
|
@@ -60,11 +60,10 @@ var vjs = function(id, options, ready){
|
|
60
60
|
};
|
61
61
|
|
62
62
|
// Extended name, also available externally, window.videojs
|
63
|
-
var videojs = vjs;
|
64
|
-
window.videojs = window.vjs = vjs;
|
63
|
+
var videojs = window['videojs'] = vjs;
|
65
64
|
|
66
65
|
// CDN Version. Used to target right flash swf.
|
67
|
-
vjs.CDN_VERSION = '4.
|
66
|
+
vjs.CDN_VERSION = '4.7';
|
68
67
|
vjs.ACCESS_PROTOCOL = ('https:' == document.location.protocol ? 'https://' : 'http://');
|
69
68
|
|
70
69
|
/**
|
@@ -104,12 +103,17 @@ vjs.options = {
|
|
104
103
|
'errorDisplay': {}
|
105
104
|
},
|
106
105
|
|
106
|
+
'language': document.getElementsByTagName('html')[0].getAttribute('lang') || navigator.languages && navigator.languages[0] || navigator.userLanguage || navigator.language || 'en',
|
107
|
+
|
108
|
+
// locales and their language translations
|
109
|
+
'languages': {},
|
110
|
+
|
107
111
|
// Default message to show when a video cannot be played.
|
108
112
|
'notSupportedMessage': 'No compatible source was found for this video.'
|
109
113
|
};
|
110
114
|
|
111
115
|
// Set CDN Version of swf
|
112
|
-
// The added (+) blocks the replace from changing this 4.
|
116
|
+
// The added (+) blocks the replace from changing this 4.7 string
|
113
117
|
if (vjs.CDN_VERSION !== 'GENERATED'+'_CDN_VSN') {
|
114
118
|
videojs.options['flash']['swf'] = "<%= asset_path('video-js.swf') %>";
|
115
119
|
}
|
@@ -276,11 +280,15 @@ vjs.CoreObject.create = function(){
|
|
276
280
|
* and adds a generic handler to the element's event,
|
277
281
|
* along with a unique id (guid) to the element.
|
278
282
|
* @param {Element|Object} elem Element or object to bind listeners to
|
279
|
-
* @param {String} type Type of event to bind to.
|
283
|
+
* @param {String|Array} type Type of event to bind to.
|
280
284
|
* @param {Function} fn Event listener.
|
281
285
|
* @private
|
282
286
|
*/
|
283
287
|
vjs.on = function(elem, type, fn){
|
288
|
+
if (vjs.obj.isArray(type)) {
|
289
|
+
return _handleMultipleEvents(vjs.on, elem, type, fn);
|
290
|
+
}
|
291
|
+
|
284
292
|
var data = vjs.getData(elem);
|
285
293
|
|
286
294
|
// We need a place to store all our handler data
|
@@ -318,9 +326,9 @@ vjs.on = function(elem, type, fn){
|
|
318
326
|
}
|
319
327
|
|
320
328
|
if (data.handlers[type].length == 1) {
|
321
|
-
if (
|
329
|
+
if (elem.addEventListener) {
|
322
330
|
elem.addEventListener(type, data.dispatcher, false);
|
323
|
-
} else if (
|
331
|
+
} else if (elem.attachEvent) {
|
324
332
|
elem.attachEvent('on' + type, data.dispatcher);
|
325
333
|
}
|
326
334
|
}
|
@@ -329,7 +337,7 @@ vjs.on = function(elem, type, fn){
|
|
329
337
|
/**
|
330
338
|
* Removes event listeners from an element
|
331
339
|
* @param {Element|Object} elem Object to remove listeners from
|
332
|
-
* @param {String=} type Type of listener to remove. Don't include to remove all events from element.
|
340
|
+
* @param {String|Array=} type Type of listener to remove. Don't include to remove all events from element.
|
333
341
|
* @param {Function} fn Specific listener to remove. Don't incldue to remove listeners for an event type.
|
334
342
|
* @private
|
335
343
|
*/
|
@@ -342,6 +350,10 @@ vjs.off = function(elem, type, fn) {
|
|
342
350
|
// If no events exist, nothing to unbind
|
343
351
|
if (!data.handlers) { return; }
|
344
352
|
|
353
|
+
if (vjs.obj.isArray(type)) {
|
354
|
+
return _handleMultipleEvents(vjs.off, elem, type, fn);
|
355
|
+
}
|
356
|
+
|
345
357
|
// Utility function
|
346
358
|
var removeType = function(t){
|
347
359
|
data.handlers[t] = [];
|
@@ -393,9 +405,9 @@ vjs.cleanUpEvents = function(elem, type) {
|
|
393
405
|
// Setting to null was causing an error with data.handlers
|
394
406
|
|
395
407
|
// Remove the meta-handler from the element
|
396
|
-
if (
|
408
|
+
if (elem.removeEventListener) {
|
397
409
|
elem.removeEventListener(type, data.dispatcher, false);
|
398
|
-
} else if (
|
410
|
+
} else if (elem.detachEvent) {
|
399
411
|
elem.detachEvent('on' + type, data.dispatcher);
|
400
412
|
}
|
401
413
|
}
|
@@ -529,8 +541,8 @@ vjs.fixEvent = function(event) {
|
|
529
541
|
|
530
542
|
/**
|
531
543
|
* Trigger an event for an element
|
532
|
-
* @param {Element|Object}
|
533
|
-
* @param {String} event
|
544
|
+
* @param {Element|Object} elem Element to trigger an event on
|
545
|
+
* @param {Event|Object|String} event A string (the type) or an event object with a type attribute
|
534
546
|
* @private
|
535
547
|
*/
|
536
548
|
vjs.trigger = function(elem, event) {
|
@@ -602,18 +614,36 @@ vjs.trigger = function(elem, event) {
|
|
602
614
|
/**
|
603
615
|
* Trigger a listener only once for an event
|
604
616
|
* @param {Element|Object} elem Element or object to
|
605
|
-
* @param {String} type
|
617
|
+
* @param {String|Array} type
|
606
618
|
* @param {Function} fn
|
607
619
|
* @private
|
608
620
|
*/
|
609
621
|
vjs.one = function(elem, type, fn) {
|
622
|
+
if (vjs.obj.isArray(type)) {
|
623
|
+
return _handleMultipleEvents(vjs.one, elem, type, fn);
|
624
|
+
}
|
610
625
|
var func = function(){
|
611
626
|
vjs.off(elem, type, func);
|
612
627
|
fn.apply(this, arguments);
|
613
628
|
};
|
629
|
+
// copy the guid to the new function so it can removed using the original function's ID
|
614
630
|
func.guid = fn.guid = fn.guid || vjs.guid++;
|
615
631
|
vjs.on(elem, type, func);
|
616
632
|
};
|
633
|
+
|
634
|
+
/**
|
635
|
+
* Loops through an array of event types and calls the requested method for each type.
|
636
|
+
* @param {Function} fn The event method we want to use.
|
637
|
+
* @param {Element|Object} elem Element or object to bind listeners to
|
638
|
+
* @param {String} type Type of event to bind to.
|
639
|
+
* @param {Function} callback Event listener.
|
640
|
+
* @private
|
641
|
+
*/
|
642
|
+
function _handleMultipleEvents(fn, elem, type, callback) {
|
643
|
+
vjs.arr.forEach(type, function(type) {
|
644
|
+
fn(elem, type, callback); //Call the event method for each one of the types
|
645
|
+
});
|
646
|
+
}
|
617
647
|
var hasOwnProp = Object.prototype.hasOwnProperty;
|
618
648
|
|
619
649
|
/**
|
@@ -624,29 +654,29 @@ var hasOwnProp = Object.prototype.hasOwnProperty;
|
|
624
654
|
* @private
|
625
655
|
*/
|
626
656
|
vjs.createEl = function(tagName, properties){
|
627
|
-
var el
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
}
|
657
|
+
var el;
|
658
|
+
|
659
|
+
tagName = tagName || 'div';
|
660
|
+
properties = properties || {};
|
661
|
+
|
662
|
+
el = document.createElement(tagName);
|
663
|
+
|
664
|
+
vjs.obj.each(properties, function(propName, val){
|
665
|
+
// Not remembering why we were checking for dash
|
666
|
+
// but using setAttribute means you have to use getAttribute
|
667
|
+
|
668
|
+
// The check for dash checks for the aria-* attributes, like aria-label, aria-valuemin.
|
669
|
+
// The additional check for "role" is because the default method for adding attributes does not
|
670
|
+
// add the attribute "role". My guess is because it's not a valid attribute in some namespaces, although
|
671
|
+
// browsers handle the attribute just fine. The W3C allows for aria-* attributes to be used in pre-HTML5 docs.
|
672
|
+
// http://www.w3.org/TR/wai-aria-primer/#ariahtml. Using setAttribute gets around this problem.
|
673
|
+
if (propName.indexOf('aria-') !== -1 || propName == 'role') {
|
674
|
+
el.setAttribute(propName, val);
|
675
|
+
} else {
|
676
|
+
el[propName] = val;
|
648
677
|
}
|
649
|
-
}
|
678
|
+
});
|
679
|
+
|
650
680
|
return el;
|
651
681
|
};
|
652
682
|
|
@@ -776,6 +806,17 @@ vjs.obj.isPlain = function(obj){
|
|
776
806
|
&& obj.constructor === Object;
|
777
807
|
};
|
778
808
|
|
809
|
+
/**
|
810
|
+
* Check if an object is Array
|
811
|
+
* Since instanceof Array will not work on arrays created in another frame we need to use Array.isArray, but since IE8 does not support Array.isArray we need this shim
|
812
|
+
* @param {Object} obj Object to check
|
813
|
+
* @return {Boolean} True if plain, false otherwise
|
814
|
+
* @private
|
815
|
+
*/
|
816
|
+
vjs.obj.isArray = Array.isArray || function(arr) {
|
817
|
+
return Object.prototype.toString.call(arr) === '[object Array]';
|
818
|
+
};
|
819
|
+
|
779
820
|
/**
|
780
821
|
* Bind (a.k.a proxy or Context). A simple method for changing the context of a function
|
781
822
|
It also stores a unique id on the function so it can be easily removed from events
|
@@ -996,6 +1037,22 @@ vjs.IS_CHROME = (/Chrome/i).test(vjs.USER_AGENT);
|
|
996
1037
|
|
997
1038
|
vjs.TOUCH_ENABLED = !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch);
|
998
1039
|
|
1040
|
+
/**
|
1041
|
+
* Apply attributes to an HTML element.
|
1042
|
+
* @param {Element} el Target element.
|
1043
|
+
* @param {Object=} attributes Element attributes to be applied.
|
1044
|
+
* @private
|
1045
|
+
*/
|
1046
|
+
vjs.setElementAttributes = function(el, attributes){
|
1047
|
+
vjs.obj.each(attributes, function(attrName, attrValue) {
|
1048
|
+
if (attrValue === null || typeof attrValue === 'undefined' || attrValue === false) {
|
1049
|
+
el.removeAttribute(attrName);
|
1050
|
+
} else {
|
1051
|
+
el.setAttribute(attrName, (attrValue === true ? '' : attrValue));
|
1052
|
+
}
|
1053
|
+
});
|
1054
|
+
};
|
1055
|
+
|
999
1056
|
/**
|
1000
1057
|
* Get an element's attribute values, as defined on the HTML tag
|
1001
1058
|
* Attributs are not the same as properties. They're defined on the tag
|
@@ -1005,7 +1062,7 @@ vjs.TOUCH_ENABLED = !!(('ontouchstart' in window) || window.DocumentTouch && doc
|
|
1005
1062
|
* @return {Object}
|
1006
1063
|
* @private
|
1007
1064
|
*/
|
1008
|
-
vjs.
|
1065
|
+
vjs.getElementAttributes = function(tag){
|
1009
1066
|
var obj, knownBooleans, attrs, attrName, attrVal;
|
1010
1067
|
|
1011
1068
|
obj = {};
|
@@ -1448,6 +1505,31 @@ vjs.findPosition = function(el) {
|
|
1448
1505
|
top: vjs.round(top)
|
1449
1506
|
};
|
1450
1507
|
};
|
1508
|
+
|
1509
|
+
/**
|
1510
|
+
* Array functions container
|
1511
|
+
* @type {Object}
|
1512
|
+
* @private
|
1513
|
+
*/
|
1514
|
+
vjs.arr = {};
|
1515
|
+
|
1516
|
+
/*
|
1517
|
+
* Loops through an array and runs a function for each item inside it.
|
1518
|
+
* @param {Array} array The array
|
1519
|
+
* @param {Function} callback The function to be run for each item
|
1520
|
+
* @param {*} thisArg The `this` binding of callback
|
1521
|
+
* @returns {Array} The array
|
1522
|
+
* @private
|
1523
|
+
*/
|
1524
|
+
vjs.arr.forEach = function(array, callback, thisArg) {
|
1525
|
+
if (vjs.obj.isArray(array) && callback instanceof Function) {
|
1526
|
+
for (var i = 0, len = array.length; i < len; ++i) {
|
1527
|
+
callback.call(thisArg || vjs, array[i], i, array);
|
1528
|
+
}
|
1529
|
+
}
|
1530
|
+
|
1531
|
+
return array;
|
1532
|
+
};
|
1451
1533
|
/**
|
1452
1534
|
* Utility functions namespace
|
1453
1535
|
* @namespace
|
@@ -1456,10 +1538,9 @@ vjs.findPosition = function(el) {
|
|
1456
1538
|
vjs.util = {};
|
1457
1539
|
|
1458
1540
|
/**
|
1459
|
-
* Merge two options objects,
|
1460
|
-
*
|
1461
|
-
*
|
1462
|
-
*
|
1541
|
+
* Merge two options objects, recursively merging any plain object properties as
|
1542
|
+
* well. Previously `deepMerge`
|
1543
|
+
*
|
1463
1544
|
* @param {Object} obj1 Object to override values in
|
1464
1545
|
* @param {Object} obj2 Overriding object
|
1465
1546
|
* @return {Object} New object -- obj1 and obj2 will be untouched
|
@@ -1685,6 +1766,15 @@ vjs.Component.prototype.createEl = function(tagName, attributes){
|
|
1685
1766
|
return vjs.createEl(tagName, attributes);
|
1686
1767
|
};
|
1687
1768
|
|
1769
|
+
vjs.Component.prototype.localize = function(string){
|
1770
|
+
var lang = this.player_.language(),
|
1771
|
+
languages = this.player_.languages();
|
1772
|
+
if (languages && languages[lang] && languages[lang][string]) {
|
1773
|
+
return languages[lang][string];
|
1774
|
+
}
|
1775
|
+
return string;
|
1776
|
+
};
|
1777
|
+
|
1688
1778
|
/**
|
1689
1779
|
* Get the component's DOM element
|
1690
1780
|
*
|
@@ -1961,7 +2051,7 @@ vjs.Component.prototype.initChildren = function(){
|
|
1961
2051
|
|
1962
2052
|
if (children) {
|
1963
2053
|
// Allow for an array of children details to passed in the options
|
1964
|
-
if (children
|
2054
|
+
if (vjs.obj.isArray(children)) {
|
1965
2055
|
for (var i = 0; i < children.length; i++) {
|
1966
2056
|
child = children[i];
|
1967
2057
|
|
@@ -2053,13 +2143,13 @@ vjs.Component.prototype.one = function(type, fn) {
|
|
2053
2143
|
* Trigger an event on an element
|
2054
2144
|
*
|
2055
2145
|
* myComponent.trigger('eventName');
|
2146
|
+
* myComponent.trigger({'type':'eventName'});
|
2056
2147
|
*
|
2057
|
-
* @param {String}
|
2058
|
-
* @
|
2059
|
-
* @return {vjs.Component} self
|
2148
|
+
* @param {Event|Object|String} event A string (the type) or an event object with a type attribute
|
2149
|
+
* @return {vjs.Component} self
|
2060
2150
|
*/
|
2061
|
-
vjs.Component.prototype.trigger = function(
|
2062
|
-
vjs.trigger(this.el_,
|
2151
|
+
vjs.Component.prototype.trigger = function(event){
|
2152
|
+
vjs.trigger(this.el_, event);
|
2063
2153
|
return this;
|
2064
2154
|
};
|
2065
2155
|
|
@@ -2515,7 +2605,7 @@ vjs.Button.prototype.createEl = function(type, props){
|
|
2515
2605
|
|
2516
2606
|
this.controlText_ = vjs.createEl('span', {
|
2517
2607
|
className: 'vjs-control-text',
|
2518
|
-
innerHTML: this.buttonText || 'Need Text'
|
2608
|
+
innerHTML: this.localize(this.buttonText) || 'Need Text'
|
2519
2609
|
});
|
2520
2610
|
|
2521
2611
|
this.contentEl_.appendChild(this.controlText_);
|
@@ -2580,6 +2670,10 @@ vjs.Slider = vjs.Component.extend({
|
|
2580
2670
|
player.on(this.playerEvent, vjs.bind(this, this.update));
|
2581
2671
|
|
2582
2672
|
this.boundEvents = {};
|
2673
|
+
|
2674
|
+
|
2675
|
+
this.boundEvents.move = vjs.bind(this, this.onMouseMove);
|
2676
|
+
this.boundEvents.end = vjs.bind(this, this.onMouseUp);
|
2583
2677
|
}
|
2584
2678
|
});
|
2585
2679
|
|
@@ -2601,9 +2695,7 @@ vjs.Slider.prototype.createEl = function(type, props) {
|
|
2601
2695
|
vjs.Slider.prototype.onMouseDown = function(event){
|
2602
2696
|
event.preventDefault();
|
2603
2697
|
vjs.blockTextSelection();
|
2604
|
-
|
2605
|
-
this.boundEvents.move = vjs.bind(this, this.onMouseMove);
|
2606
|
-
this.boundEvents.end = vjs.bind(this, this.onMouseUp);
|
2698
|
+
this.addClass('vjs-sliding');
|
2607
2699
|
|
2608
2700
|
vjs.on(document, 'mousemove', this.boundEvents.move);
|
2609
2701
|
vjs.on(document, 'mouseup', this.boundEvents.end);
|
@@ -2613,8 +2705,13 @@ vjs.Slider.prototype.onMouseDown = function(event){
|
|
2613
2705
|
this.onMouseMove(event);
|
2614
2706
|
};
|
2615
2707
|
|
2708
|
+
// To be overridden by a subclass
|
2709
|
+
vjs.Slider.prototype.onMouseMove = function(){};
|
2710
|
+
|
2616
2711
|
vjs.Slider.prototype.onMouseUp = function() {
|
2617
2712
|
vjs.unblockTextSelection();
|
2713
|
+
this.removeClass('vjs-sliding');
|
2714
|
+
|
2618
2715
|
vjs.off(document, 'mousemove', this.boundEvents.move, false);
|
2619
2716
|
vjs.off(document, 'mouseup', this.boundEvents.end, false);
|
2620
2717
|
vjs.off(document, 'touchmove', this.boundEvents.move, false);
|
@@ -2670,7 +2767,9 @@ vjs.Slider.prototype.update = function(){
|
|
2670
2767
|
}
|
2671
2768
|
|
2672
2769
|
// Set the new bar width
|
2673
|
-
|
2770
|
+
if (bar) {
|
2771
|
+
bar.el().style.width = vjs.round(barProgress * 100, 2) + '%';
|
2772
|
+
}
|
2674
2773
|
};
|
2675
2774
|
|
2676
2775
|
vjs.Slider.prototype.calculateDistance = function(event){
|
@@ -2681,7 +2780,7 @@ vjs.Slider.prototype.calculateDistance = function(event){
|
|
2681
2780
|
boxW = boxH = el.offsetWidth;
|
2682
2781
|
handle = this.handle;
|
2683
2782
|
|
2684
|
-
if (this.
|
2783
|
+
if (this.options()['vertical']) {
|
2685
2784
|
boxY = box.top;
|
2686
2785
|
|
2687
2786
|
if (event.changedTouches) {
|
@@ -2727,10 +2826,10 @@ vjs.Slider.prototype.onFocus = function(){
|
|
2727
2826
|
};
|
2728
2827
|
|
2729
2828
|
vjs.Slider.prototype.onKeyPress = function(event){
|
2730
|
-
if (event.which == 37) { // Left
|
2829
|
+
if (event.which == 37 || event.which == 40) { // Left and Down Arrows
|
2731
2830
|
event.preventDefault();
|
2732
2831
|
this.stepBack();
|
2733
|
-
} else if (event.which == 39) { // Right
|
2832
|
+
} else if (event.which == 38 || event.which == 39) { // Up and Right Arrows
|
2734
2833
|
event.preventDefault();
|
2735
2834
|
this.stepForward();
|
2736
2835
|
}
|
@@ -3152,7 +3251,7 @@ for (var errNum = 0; errNum < vjs.MediaError.errorTypes.length; errNum++) {
|
|
3152
3251
|
* var myPlayer = videojs('example_video_1');
|
3153
3252
|
* ```
|
3154
3253
|
*
|
3155
|
-
* In the
|
3254
|
+
* In the following example, the `data-setup` attribute tells the Video.js library to create a player instance when the library is ready.
|
3156
3255
|
*
|
3157
3256
|
* ```html
|
3158
3257
|
* <video id="example_video_1" data-setup='{}' controls>
|
@@ -3182,6 +3281,9 @@ vjs.Player = vjs.Component.extend({
|
|
3182
3281
|
// Make sure tag ID exists
|
3183
3282
|
tag.id = tag.id || 'vjs_video_' + vjs.guid++;
|
3184
3283
|
|
3284
|
+
// Store the tag attributes used to restore html5 element
|
3285
|
+
this.tagAttributes = tag && vjs.getElementAttributes(tag);
|
3286
|
+
|
3185
3287
|
// Set Options
|
3186
3288
|
// The options argument overrides options set in the video tag
|
3187
3289
|
// which overrides globally set options.
|
@@ -3189,6 +3291,12 @@ vjs.Player = vjs.Component.extend({
|
|
3189
3291
|
// (tag must exist before Player)
|
3190
3292
|
options = vjs.obj.merge(this.getTagSettings(tag), options);
|
3191
3293
|
|
3294
|
+
// Update Current Language
|
3295
|
+
this.language_ = options['language'] || vjs.options['language'];
|
3296
|
+
|
3297
|
+
// Update Supported Languages
|
3298
|
+
this.languages_ = options['languages'] || vjs.options['languages'];
|
3299
|
+
|
3192
3300
|
// Cache for video property values.
|
3193
3301
|
this.cache_ = {};
|
3194
3302
|
|
@@ -3237,6 +3345,41 @@ vjs.Player = vjs.Component.extend({
|
|
3237
3345
|
}
|
3238
3346
|
});
|
3239
3347
|
|
3348
|
+
/**
|
3349
|
+
* The players's stored language code
|
3350
|
+
*
|
3351
|
+
* @type {String}
|
3352
|
+
* @private
|
3353
|
+
*/
|
3354
|
+
vjs.Player.prototype.language_;
|
3355
|
+
|
3356
|
+
/**
|
3357
|
+
* The player's language code
|
3358
|
+
* @param {String} languageCode The locale string
|
3359
|
+
* @return {String} The locale string when getting
|
3360
|
+
* @return {vjs.Player} self, when setting
|
3361
|
+
*/
|
3362
|
+
vjs.Player.prototype.language = function (languageCode) {
|
3363
|
+
if (languageCode === undefined) {
|
3364
|
+
return this.language_;
|
3365
|
+
}
|
3366
|
+
|
3367
|
+
this.language_ = languageCode;
|
3368
|
+
return this;
|
3369
|
+
};
|
3370
|
+
|
3371
|
+
/**
|
3372
|
+
* The players's stored language dictionary
|
3373
|
+
*
|
3374
|
+
* @type {Object}
|
3375
|
+
* @private
|
3376
|
+
*/
|
3377
|
+
vjs.Player.prototype.languages_;
|
3378
|
+
|
3379
|
+
vjs.Player.prototype.languages = function(){
|
3380
|
+
return this.languages_;
|
3381
|
+
};
|
3382
|
+
|
3240
3383
|
/**
|
3241
3384
|
* Player instance options, surfaced using vjs.options
|
3242
3385
|
* vjs.options = vjs.Player.prototype.options_
|
@@ -3282,7 +3425,7 @@ vjs.Player.prototype.getTagSettings = function(tag){
|
|
3282
3425
|
'tracks': []
|
3283
3426
|
};
|
3284
3427
|
|
3285
|
-
vjs.obj.merge(options, vjs.
|
3428
|
+
vjs.obj.merge(options, vjs.getElementAttributes(tag));
|
3286
3429
|
|
3287
3430
|
// Get tag children settings
|
3288
3431
|
if (tag.hasChildNodes()) {
|
@@ -3295,9 +3438,9 @@ vjs.Player.prototype.getTagSettings = function(tag){
|
|
3295
3438
|
// Change case needed: http://ejohn.org/blog/nodename-case-sensitivity/
|
3296
3439
|
childName = child.nodeName.toLowerCase();
|
3297
3440
|
if (childName === 'source') {
|
3298
|
-
options['sources'].push(vjs.
|
3441
|
+
options['sources'].push(vjs.getElementAttributes(child));
|
3299
3442
|
} else if (childName === 'track') {
|
3300
|
-
options['tracks'].push(vjs.
|
3443
|
+
options['tracks'].push(vjs.getElementAttributes(child));
|
3301
3444
|
}
|
3302
3445
|
}
|
3303
3446
|
}
|
@@ -3306,8 +3449,10 @@ vjs.Player.prototype.getTagSettings = function(tag){
|
|
3306
3449
|
};
|
3307
3450
|
|
3308
3451
|
vjs.Player.prototype.createEl = function(){
|
3309
|
-
var
|
3310
|
-
|
3452
|
+
var
|
3453
|
+
el = this.el_ = vjs.Component.prototype.createEl.call(this, 'div'),
|
3454
|
+
tag = this.tag,
|
3455
|
+
attrs;
|
3311
3456
|
|
3312
3457
|
// Remove width/height attrs from tag so CSS can make it 100% width/height
|
3313
3458
|
tag.removeAttribute('width');
|
@@ -3336,10 +3481,12 @@ vjs.Player.prototype.createEl = function(){
|
|
3336
3481
|
}
|
3337
3482
|
}
|
3338
3483
|
|
3339
|
-
//
|
3484
|
+
// Copy over all the attributes from the tag, including ID and class
|
3340
3485
|
// ID will now reference player box, not the video tag
|
3341
|
-
|
3342
|
-
|
3486
|
+
attrs = vjs.getElementAttributes(tag);
|
3487
|
+
vjs.obj.each(attrs, function(attr) {
|
3488
|
+
el.setAttribute(attr, attrs[attr]);
|
3489
|
+
});
|
3343
3490
|
|
3344
3491
|
// Update tag id/class for use as HTML5 playback tech
|
3345
3492
|
// Might think we should do this after embedding in container so .vjs-tech class
|
@@ -3371,6 +3518,10 @@ vjs.Player.prototype.createEl = function(){
|
|
3371
3518
|
// adding children
|
3372
3519
|
this.el_ = el;
|
3373
3520
|
this.on('loadstart', this.onLoadStart);
|
3521
|
+
this.on('waiting', this.onWaiting);
|
3522
|
+
this.on(['canplay', 'canplaythrough', 'playing', 'ended'], this.onWaitEnd);
|
3523
|
+
this.on('seeking', this.onSeeking);
|
3524
|
+
this.on('seeked', this.onSeeked);
|
3374
3525
|
this.on('ended', this.onEnded);
|
3375
3526
|
this.on('play', this.onPlay);
|
3376
3527
|
this.on('firstplay', this.onFirstPlay);
|
@@ -3422,6 +3573,7 @@ vjs.Player.prototype.loadTech = function(techName, source){
|
|
3422
3573
|
var techOptions = vjs.obj.merge({ 'source': source, 'parentEl': this.el_ }, this.options_[techName.toLowerCase()]);
|
3423
3574
|
|
3424
3575
|
if (source) {
|
3576
|
+
this.currentType_ = source.type;
|
3425
3577
|
if (source.src == this.cache_.src && this.cache_.currentTime > 0) {
|
3426
3578
|
techOptions['startTime'] = this.cache_.currentTime;
|
3427
3579
|
}
|
@@ -3437,13 +3589,14 @@ vjs.Player.prototype.loadTech = function(techName, source){
|
|
3437
3589
|
|
3438
3590
|
vjs.Player.prototype.unloadTech = function(){
|
3439
3591
|
this.isReady_ = false;
|
3440
|
-
this.tech.dispose();
|
3441
3592
|
|
3442
3593
|
// Turn off any manual progress or timeupdate tracking
|
3443
3594
|
if (this.manualProgress) { this.manualProgressOff(); }
|
3444
3595
|
|
3445
3596
|
if (this.manualTimeUpdates) { this.manualTimeUpdatesOff(); }
|
3446
3597
|
|
3598
|
+
this.tech.dispose();
|
3599
|
+
|
3447
3600
|
this.tech = false;
|
3448
3601
|
};
|
3449
3602
|
|
@@ -3496,13 +3649,17 @@ vjs.Player.prototype.trackProgress = function(){
|
|
3496
3649
|
|
3497
3650
|
this.progressInterval = setInterval(vjs.bind(this, function(){
|
3498
3651
|
// Don't trigger unless buffered amount is greater than last time
|
3499
|
-
|
3500
|
-
|
3501
|
-
|
3652
|
+
|
3653
|
+
var bufferedPercent = this.bufferedPercent();
|
3654
|
+
|
3655
|
+
if (this.cache_.bufferedPercent != bufferedPercent) {
|
3502
3656
|
this.trigger('progress');
|
3503
|
-
}
|
3657
|
+
}
|
3658
|
+
|
3659
|
+
this.cache_.bufferedPercent = bufferedPercent;
|
3660
|
+
|
3661
|
+
if (bufferedPercent == 1) {
|
3504
3662
|
this.stopTrackingProgress();
|
3505
|
-
this.trigger('progress'); // Last update
|
3506
3663
|
}
|
3507
3664
|
}), 500);
|
3508
3665
|
};
|
@@ -3619,8 +3776,40 @@ vjs.Player.prototype.onLoadedAllData;
|
|
3619
3776
|
* @event play
|
3620
3777
|
*/
|
3621
3778
|
vjs.Player.prototype.onPlay = function(){
|
3622
|
-
|
3623
|
-
|
3779
|
+
this.removeClass('vjs-paused');
|
3780
|
+
this.addClass('vjs-playing');
|
3781
|
+
};
|
3782
|
+
|
3783
|
+
/**
|
3784
|
+
* Fired whenever the media begins wating
|
3785
|
+
* @event waiting
|
3786
|
+
*/
|
3787
|
+
vjs.Player.prototype.onWaiting = function(){
|
3788
|
+
this.addClass('vjs-waiting');
|
3789
|
+
};
|
3790
|
+
|
3791
|
+
/**
|
3792
|
+
* A handler for events that signal that waiting has eneded
|
3793
|
+
* which is not consistent between browsers. See #1351
|
3794
|
+
*/
|
3795
|
+
vjs.Player.prototype.onWaitEnd = function(){
|
3796
|
+
this.removeClass('vjs-waiting');
|
3797
|
+
};
|
3798
|
+
|
3799
|
+
/**
|
3800
|
+
* Fired whenever the player is jumping to a new time
|
3801
|
+
* @event seeking
|
3802
|
+
*/
|
3803
|
+
vjs.Player.prototype.onSeeking = function(){
|
3804
|
+
this.addClass('vjs-seeking');
|
3805
|
+
};
|
3806
|
+
|
3807
|
+
/**
|
3808
|
+
* Fired when the player has finished jumping to a new time
|
3809
|
+
* @event seeked
|
3810
|
+
*/
|
3811
|
+
vjs.Player.prototype.onSeeked = function(){
|
3812
|
+
this.removeClass('vjs-seeking');
|
3624
3813
|
};
|
3625
3814
|
|
3626
3815
|
/**
|
@@ -3647,8 +3836,8 @@ vjs.Player.prototype.onFirstPlay = function(){
|
|
3647
3836
|
* @event pause
|
3648
3837
|
*/
|
3649
3838
|
vjs.Player.prototype.onPause = function(){
|
3650
|
-
|
3651
|
-
|
3839
|
+
this.removeClass('vjs-playing');
|
3840
|
+
this.addClass('vjs-paused');
|
3652
3841
|
};
|
3653
3842
|
|
3654
3843
|
/**
|
@@ -3889,7 +4078,6 @@ vjs.Player.prototype.remainingTime = function(){
|
|
3889
4078
|
// http://dev.w3.org/html5/spec/video.html#dom-media-buffered
|
3890
4079
|
// Buffered returns a timerange object.
|
3891
4080
|
// Kind of like an array of portions of the video that have been downloaded.
|
3892
|
-
// So far no browsers return more than one range (portion)
|
3893
4081
|
|
3894
4082
|
/**
|
3895
4083
|
* Get a TimeRange object with the times of the video that have been downloaded
|
@@ -3912,19 +4100,13 @@ vjs.Player.prototype.remainingTime = function(){
|
|
3912
4100
|
* @return {Object} A mock TimeRange object (following HTML spec)
|
3913
4101
|
*/
|
3914
4102
|
vjs.Player.prototype.buffered = function(){
|
3915
|
-
var buffered = this.techGet('buffered')
|
3916
|
-
start = 0,
|
3917
|
-
buflast = buffered.length - 1,
|
3918
|
-
// Default end to 0 and store in values
|
3919
|
-
end = this.cache_.bufferEnd = this.cache_.bufferEnd || 0;
|
4103
|
+
var buffered = this.techGet('buffered');
|
3920
4104
|
|
3921
|
-
if (buffered
|
3922
|
-
|
3923
|
-
// Storing values allows them be overridden by setBufferedFromProgress
|
3924
|
-
this.cache_.bufferEnd = end;
|
4105
|
+
if (!buffered || !buffered.length) {
|
4106
|
+
buffered = vjs.createTimeRange(0,0);
|
3925
4107
|
}
|
3926
4108
|
|
3927
|
-
return
|
4109
|
+
return buffered;
|
3928
4110
|
};
|
3929
4111
|
|
3930
4112
|
/**
|
@@ -3938,7 +4120,46 @@ vjs.Player.prototype.buffered = function(){
|
|
3938
4120
|
* @return {Number} A decimal between 0 and 1 representing the percent
|
3939
4121
|
*/
|
3940
4122
|
vjs.Player.prototype.bufferedPercent = function(){
|
3941
|
-
|
4123
|
+
var duration = this.duration(),
|
4124
|
+
buffered = this.buffered(),
|
4125
|
+
bufferedDuration = 0,
|
4126
|
+
start, end;
|
4127
|
+
|
4128
|
+
if (!duration) {
|
4129
|
+
return 0;
|
4130
|
+
}
|
4131
|
+
|
4132
|
+
for (var i=0; i<buffered.length; i++){
|
4133
|
+
start = buffered.start(i);
|
4134
|
+
end = buffered.end(i);
|
4135
|
+
|
4136
|
+
// buffered end can be bigger than duration by a very small fraction
|
4137
|
+
if (end > duration) {
|
4138
|
+
end = duration;
|
4139
|
+
}
|
4140
|
+
|
4141
|
+
bufferedDuration += end - start;
|
4142
|
+
}
|
4143
|
+
|
4144
|
+
return bufferedDuration / duration;
|
4145
|
+
};
|
4146
|
+
|
4147
|
+
/**
|
4148
|
+
* Get the ending time of the last buffered time range
|
4149
|
+
*
|
4150
|
+
* This is used in the progress bar to encapsulate all time ranges.
|
4151
|
+
* @return {Number} The end of the last buffered time range
|
4152
|
+
*/
|
4153
|
+
vjs.Player.prototype.bufferedEnd = function(){
|
4154
|
+
var buffered = this.buffered(),
|
4155
|
+
duration = this.duration(),
|
4156
|
+
end = buffered.end(buffered.length-1);
|
4157
|
+
|
4158
|
+
if (end > duration) {
|
4159
|
+
end = duration;
|
4160
|
+
}
|
4161
|
+
|
4162
|
+
return end;
|
3942
4163
|
};
|
3943
4164
|
|
3944
4165
|
/**
|
@@ -4249,64 +4470,69 @@ vjs.Player.prototype.src = function(source){
|
|
4249
4470
|
return this.techGet('src');
|
4250
4471
|
}
|
4251
4472
|
|
4252
|
-
//
|
4253
|
-
if (source
|
4254
|
-
|
4255
|
-
var sourceTech = this.selectSource(source),
|
4256
|
-
techName;
|
4473
|
+
// case: Array of source objects to choose from and pick the best to play
|
4474
|
+
if (vjs.obj.isArray(source)) {
|
4475
|
+
this.sourceList_(source);
|
4257
4476
|
|
4258
|
-
|
4259
|
-
|
4260
|
-
|
4477
|
+
// case: URL String (http://myvideo...)
|
4478
|
+
} else if (typeof source === 'string') {
|
4479
|
+
// create a source object from the string
|
4480
|
+
this.src({ src: source });
|
4261
4481
|
|
4262
|
-
|
4263
|
-
if (techName == this.techName) {
|
4264
|
-
this.src(source); // Passing the source object
|
4265
|
-
// Otherwise load this technology with chosen source
|
4266
|
-
} else {
|
4267
|
-
this.loadTech(techName, source);
|
4268
|
-
}
|
4269
|
-
} else {
|
4270
|
-
// this.el_.appendChild(vjs.createEl('p', {
|
4271
|
-
// innerHTML: this.options()['notSupportedMessage']
|
4272
|
-
// }));
|
4273
|
-
this.error({ code: 4, message: this.options()['notSupportedMessage'] });
|
4274
|
-
this.triggerReady(); // we could not find an appropriate tech, but let's still notify the delegate that this is it
|
4275
|
-
}
|
4276
|
-
|
4277
|
-
// Case: Source object { src: '', type: '' ... }
|
4482
|
+
// case: Source object { src: '', type: '' ... }
|
4278
4483
|
} else if (source instanceof Object) {
|
4279
|
-
|
4280
|
-
if
|
4281
|
-
|
4484
|
+
// check if the source has a type and the loaded tech cannot play the source
|
4485
|
+
// if there's no type we'll just try the current tech
|
4486
|
+
if (source.type && !window['videojs'][this.techName]['canPlaySource'](source)) {
|
4487
|
+
// create a source list with the current source and send through
|
4488
|
+
// the tech loop to check for a compatible technology
|
4489
|
+
this.sourceList_([source]);
|
4282
4490
|
} else {
|
4283
|
-
|
4284
|
-
this.
|
4285
|
-
}
|
4491
|
+
this.cache_.src = source.src;
|
4492
|
+
this.currentType_ = source.type || '';
|
4286
4493
|
|
4287
|
-
|
4288
|
-
} else {
|
4289
|
-
// Cache for getting last set source
|
4290
|
-
this.cache_.src = source;
|
4291
|
-
|
4292
|
-
if (!this.isReady_) {
|
4494
|
+
// wait until the tech is ready to set the source
|
4293
4495
|
this.ready(function(){
|
4294
|
-
this.src
|
4496
|
+
this.techCall('src', source.src);
|
4497
|
+
|
4498
|
+
if (this.options_['preload'] == 'auto') {
|
4499
|
+
this.load();
|
4500
|
+
}
|
4501
|
+
|
4502
|
+
if (this.options_['autoplay']) {
|
4503
|
+
this.play();
|
4504
|
+
}
|
4295
4505
|
});
|
4296
|
-
} else {
|
4297
|
-
this.techCall('src', source);
|
4298
|
-
if (this.options_['preload'] == 'auto') {
|
4299
|
-
this.load();
|
4300
|
-
}
|
4301
|
-
if (this.options_['autoplay']) {
|
4302
|
-
this.play();
|
4303
|
-
}
|
4304
4506
|
}
|
4305
4507
|
}
|
4306
4508
|
|
4307
4509
|
return this;
|
4308
4510
|
};
|
4309
4511
|
|
4512
|
+
/**
|
4513
|
+
* Handle an array of source objects
|
4514
|
+
* @param {[type]} sources Array of source objects
|
4515
|
+
* @private
|
4516
|
+
*/
|
4517
|
+
vjs.Player.prototype.sourceList_ = function(sources){
|
4518
|
+
var sourceTech = this.selectSource(sources);
|
4519
|
+
|
4520
|
+
if (sourceTech) {
|
4521
|
+
if (sourceTech.tech === this.techName) {
|
4522
|
+
// if this technology is already loaded, set the source
|
4523
|
+
this.src(sourceTech.source);
|
4524
|
+
} else {
|
4525
|
+
// load this technology with the chosen source
|
4526
|
+
this.loadTech(sourceTech.tech, sourceTech.source);
|
4527
|
+
}
|
4528
|
+
} else {
|
4529
|
+
this.error({ code: 4, message: this.options()['notSupportedMessage'] });
|
4530
|
+
// we could not find an appropriate tech, but let's still notify the delegate that this is it
|
4531
|
+
// this needs a better comment about why this is needed
|
4532
|
+
this.triggerReady();
|
4533
|
+
}
|
4534
|
+
};
|
4535
|
+
|
4310
4536
|
// Begin loading the src data
|
4311
4537
|
// http://dev.w3.org/html5/spec/video.html#dom-media-load
|
4312
4538
|
vjs.Player.prototype.load = function(){
|
@@ -4319,6 +4545,16 @@ vjs.Player.prototype.currentSrc = function(){
|
|
4319
4545
|
return this.techGet('currentSrc') || this.cache_.src || '';
|
4320
4546
|
};
|
4321
4547
|
|
4548
|
+
/**
|
4549
|
+
* Get the current source type e.g. video/mp4
|
4550
|
+
* This can allow you rebuild the current source object so that you could load the same
|
4551
|
+
* source and tech later
|
4552
|
+
* @return {String} The source MIME type
|
4553
|
+
*/
|
4554
|
+
vjs.Player.prototype.currentType = function(){
|
4555
|
+
return this.currentType_ || '';
|
4556
|
+
};
|
4557
|
+
|
4322
4558
|
// Attributes/Options
|
4323
4559
|
vjs.Player.prototype.preload = function(value){
|
4324
4560
|
if (value !== undefined) {
|
@@ -4731,7 +4967,7 @@ vjs.LiveDisplay.prototype.createEl = function(){
|
|
4731
4967
|
|
4732
4968
|
this.contentEl_ = vjs.createEl('div', {
|
4733
4969
|
className: 'vjs-live-display',
|
4734
|
-
innerHTML: '<span class="vjs-control-text">Stream Type </span>LIVE',
|
4970
|
+
innerHTML: '<span class="vjs-control-text">' + this.localize('Stream Type') + '</span>' + this.localize('LIVE'),
|
4735
4971
|
'aria-live': 'off'
|
4736
4972
|
});
|
4737
4973
|
|
@@ -4775,14 +5011,14 @@ vjs.PlayToggle.prototype.onClick = function(){
|
|
4775
5011
|
vjs.PlayToggle.prototype.onPlay = function(){
|
4776
5012
|
vjs.removeClass(this.el_, 'vjs-paused');
|
4777
5013
|
vjs.addClass(this.el_, 'vjs-playing');
|
4778
|
-
this.el_.children[0].children[0].innerHTML = 'Pause'; // change the button text to "Pause"
|
5014
|
+
this.el_.children[0].children[0].innerHTML = this.localize('Pause'); // change the button text to "Pause"
|
4779
5015
|
};
|
4780
5016
|
|
4781
5017
|
// OnPause - Add the vjs-paused class to the element so it can change appearance
|
4782
5018
|
vjs.PlayToggle.prototype.onPause = function(){
|
4783
5019
|
vjs.removeClass(this.el_, 'vjs-playing');
|
4784
5020
|
vjs.addClass(this.el_, 'vjs-paused');
|
4785
|
-
this.el_.children[0].children[0].innerHTML = 'Play'; // change the button text to "Play"
|
5021
|
+
this.el_.children[0].children[0].innerHTML = this.localize('Play'); // change the button text to "Play"
|
4786
5022
|
};
|
4787
5023
|
/**
|
4788
5024
|
* Displays the current time
|
@@ -4817,7 +5053,7 @@ vjs.CurrentTimeDisplay.prototype.createEl = function(){
|
|
4817
5053
|
vjs.CurrentTimeDisplay.prototype.updateContent = function(){
|
4818
5054
|
// Allows for smooth scrubbing, when player can't keep up.
|
4819
5055
|
var time = (this.player_.scrubbing) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
4820
|
-
this.contentEl_.innerHTML = '<span class="vjs-control-text">Current Time </span>' + vjs.formatTime(time, this.player_.duration());
|
5056
|
+
this.contentEl_.innerHTML = '<span class="vjs-control-text">' + this.localize('Current Time') + '</span> ' + vjs.formatTime(time, this.player_.duration());
|
4821
5057
|
};
|
4822
5058
|
|
4823
5059
|
/**
|
@@ -4847,7 +5083,7 @@ vjs.DurationDisplay.prototype.createEl = function(){
|
|
4847
5083
|
|
4848
5084
|
this.contentEl_ = vjs.createEl('div', {
|
4849
5085
|
className: 'vjs-duration-display',
|
4850
|
-
innerHTML: '<span class="vjs-control-text">Duration Time </span>' + '0:00', // label the duration time for screen reader users
|
5086
|
+
innerHTML: '<span class="vjs-control-text">' + this.localize('Duration Time') + '</span> ' + '0:00', // label the duration time for screen reader users
|
4851
5087
|
'aria-live': 'off' // tell screen readers not to automatically read the time as it changes
|
4852
5088
|
});
|
4853
5089
|
|
@@ -4858,7 +5094,7 @@ vjs.DurationDisplay.prototype.createEl = function(){
|
|
4858
5094
|
vjs.DurationDisplay.prototype.updateContent = function(){
|
4859
5095
|
var duration = this.player_.duration();
|
4860
5096
|
if (duration) {
|
4861
|
-
this.contentEl_.innerHTML = '<span class="vjs-control-text">Duration Time </span>' + vjs.formatTime(duration); // label the duration time for screen reader users
|
5097
|
+
this.contentEl_.innerHTML = '<span class="vjs-control-text">' + this.localize('Duration Time') + '</span> ' + vjs.formatTime(duration); // label the duration time for screen reader users
|
4862
5098
|
}
|
4863
5099
|
};
|
4864
5100
|
|
@@ -4907,7 +5143,7 @@ vjs.RemainingTimeDisplay.prototype.createEl = function(){
|
|
4907
5143
|
|
4908
5144
|
this.contentEl_ = vjs.createEl('div', {
|
4909
5145
|
className: 'vjs-remaining-time-display',
|
4910
|
-
innerHTML: '<span class="vjs-control-text">Remaining Time </span>' + '-0:00', // label the remaining time for screen reader users
|
5146
|
+
innerHTML: '<span class="vjs-control-text">' + this.localize('Remaining Time') + '</span> ' + '-0:00', // label the remaining time for screen reader users
|
4911
5147
|
'aria-live': 'off' // tell screen readers not to automatically read the time as it changes
|
4912
5148
|
});
|
4913
5149
|
|
@@ -4917,7 +5153,7 @@ vjs.RemainingTimeDisplay.prototype.createEl = function(){
|
|
4917
5153
|
|
4918
5154
|
vjs.RemainingTimeDisplay.prototype.updateContent = function(){
|
4919
5155
|
if (this.player_.duration()) {
|
4920
|
-
this.contentEl_.innerHTML = '<span class="vjs-control-text">Remaining Time </span>' + '-'+ vjs.formatTime(this.player_.remainingTime());
|
5156
|
+
this.contentEl_.innerHTML = '<span class="vjs-control-text">' + this.localize('Remaining Time') + '</span> ' + '-'+ vjs.formatTime(this.player_.remainingTime());
|
4921
5157
|
}
|
4922
5158
|
|
4923
5159
|
// Allows for smooth scrubbing, when player can't keep up.
|
@@ -4951,10 +5187,10 @@ vjs.FullscreenToggle.prototype.buildCSSClass = function(){
|
|
4951
5187
|
vjs.FullscreenToggle.prototype.onClick = function(){
|
4952
5188
|
if (!this.player_.isFullscreen()) {
|
4953
5189
|
this.player_.requestFullscreen();
|
4954
|
-
this.controlText_.innerHTML = 'Non-Fullscreen';
|
5190
|
+
this.controlText_.innerHTML = this.localize('Non-Fullscreen');
|
4955
5191
|
} else {
|
4956
5192
|
this.player_.exitFullscreen();
|
4957
|
-
this.controlText_.innerHTML = 'Fullscreen';
|
5193
|
+
this.controlText_.innerHTML = this.localize('Fullscreen');
|
4958
5194
|
}
|
4959
5195
|
};
|
4960
5196
|
/**
|
@@ -5066,7 +5302,6 @@ vjs.SeekBar.prototype.stepBack = function(){
|
|
5066
5302
|
this.player_.currentTime(this.player_.currentTime() - 5); // more quickly rewind for keyboard-only users
|
5067
5303
|
};
|
5068
5304
|
|
5069
|
-
|
5070
5305
|
/**
|
5071
5306
|
* Shows load progress
|
5072
5307
|
*
|
@@ -5085,14 +5320,45 @@ vjs.LoadProgressBar = vjs.Component.extend({
|
|
5085
5320
|
vjs.LoadProgressBar.prototype.createEl = function(){
|
5086
5321
|
return vjs.Component.prototype.createEl.call(this, 'div', {
|
5087
5322
|
className: 'vjs-load-progress',
|
5088
|
-
innerHTML: '<span class="vjs-control-text">Loaded
|
5323
|
+
innerHTML: '<span class="vjs-control-text"><span>' + this.localize('Loaded') + '</span>: 0%</span>'
|
5089
5324
|
});
|
5090
5325
|
};
|
5091
5326
|
|
5092
5327
|
vjs.LoadProgressBar.prototype.update = function(){
|
5093
|
-
|
5094
|
-
|
5328
|
+
var i, start, end, part,
|
5329
|
+
buffered = this.player_.buffered(),
|
5330
|
+
duration = this.player_.duration(),
|
5331
|
+
bufferedEnd = this.player_.bufferedEnd(),
|
5332
|
+
children = this.el_.children,
|
5333
|
+
// get the percent width of a time compared to the total end
|
5334
|
+
percentify = function (time, end){
|
5335
|
+
var percent = (time / end) || 0; // no NaN
|
5336
|
+
return (percent * 100) + '%';
|
5337
|
+
};
|
5338
|
+
|
5339
|
+
// update the width of the progress bar
|
5340
|
+
this.el_.style.width = percentify(bufferedEnd, duration);
|
5095
5341
|
|
5342
|
+
// add child elements to represent the individual buffered time ranges
|
5343
|
+
for (i = 0; i < buffered.length; i++) {
|
5344
|
+
start = buffered.start(i),
|
5345
|
+
end = buffered.end(i),
|
5346
|
+
part = children[i];
|
5347
|
+
|
5348
|
+
if (!part) {
|
5349
|
+
part = this.el_.appendChild(vjs.createEl())
|
5350
|
+
};
|
5351
|
+
|
5352
|
+
// set the percent based on the width of the progress bar (bufferedEnd)
|
5353
|
+
part.style.left = percentify(start, bufferedEnd);
|
5354
|
+
part.style.width = percentify(end - start, bufferedEnd);
|
5355
|
+
};
|
5356
|
+
|
5357
|
+
// remove unused buffered range elements
|
5358
|
+
for (i = children.length; i > buffered.length; i--) {
|
5359
|
+
this.el_.removeChild(children[i-1]);
|
5360
|
+
}
|
5361
|
+
};
|
5096
5362
|
|
5097
5363
|
/**
|
5098
5364
|
* Shows play progress
|
@@ -5111,7 +5377,7 @@ vjs.PlayProgressBar = vjs.Component.extend({
|
|
5111
5377
|
vjs.PlayProgressBar.prototype.createEl = function(){
|
5112
5378
|
return vjs.Component.prototype.createEl.call(this, 'div', {
|
5113
5379
|
className: 'vjs-play-progress',
|
5114
|
-
innerHTML: '<span class="vjs-control-text">Progress
|
5380
|
+
innerHTML: '<span class="vjs-control-text"><span>' + this.localize('Progress') + '</span>: 0%</span>'
|
5115
5381
|
});
|
5116
5382
|
};
|
5117
5383
|
|
@@ -5321,7 +5587,7 @@ vjs.MuteToggle = vjs.Button.extend({
|
|
5321
5587
|
vjs.MuteToggle.prototype.createEl = function(){
|
5322
5588
|
return vjs.Button.prototype.createEl.call(this, 'div', {
|
5323
5589
|
className: 'vjs-mute-control vjs-control',
|
5324
|
-
innerHTML: '<div><span class="vjs-control-text">Mute</span></div>'
|
5590
|
+
innerHTML: '<div><span class="vjs-control-text">' + this.localize('Mute') + '</span></div>'
|
5325
5591
|
});
|
5326
5592
|
};
|
5327
5593
|
|
@@ -5345,12 +5611,12 @@ vjs.MuteToggle.prototype.update = function(){
|
|
5345
5611
|
// This causes unnecessary and confusing information for screen reader users.
|
5346
5612
|
// This check is needed because this function gets called every time the volume level is changed.
|
5347
5613
|
if(this.player_.muted()){
|
5348
|
-
if(this.el_.children[0].children[0].innerHTML!='Unmute'){
|
5349
|
-
this.el_.children[0].children[0].innerHTML = 'Unmute'; // change the button text to "Unmute"
|
5614
|
+
if(this.el_.children[0].children[0].innerHTML!=this.localize('Unmute')){
|
5615
|
+
this.el_.children[0].children[0].innerHTML = this.localize('Unmute'); // change the button text to "Unmute"
|
5350
5616
|
}
|
5351
5617
|
} else {
|
5352
|
-
if(this.el_.children[0].children[0].innerHTML!='Mute'){
|
5353
|
-
this.el_.children[0].children[0].innerHTML = 'Mute'; // change the button text to "Mute"
|
5618
|
+
if(this.el_.children[0].children[0].innerHTML!=this.localize('Mute')){
|
5619
|
+
this.el_.children[0].children[0].innerHTML = this.localize('Mute'); // change the button text to "Mute"
|
5354
5620
|
}
|
5355
5621
|
}
|
5356
5622
|
|
@@ -5391,7 +5657,7 @@ vjs.VolumeMenuButton.prototype.createMenu = function(){
|
|
5391
5657
|
var menu = new vjs.Menu(this.player_, {
|
5392
5658
|
contentElType: 'div'
|
5393
5659
|
});
|
5394
|
-
var vc = new vjs.VolumeBar(this.player_, vjs.obj.merge({vertical: true}, this.options_.volumeBar));
|
5660
|
+
var vc = new vjs.VolumeBar(this.player_, vjs.obj.merge({'vertical': true}, this.options_.volumeBar));
|
5395
5661
|
menu.addChild(vc);
|
5396
5662
|
return menu;
|
5397
5663
|
};
|
@@ -5404,7 +5670,7 @@ vjs.VolumeMenuButton.prototype.onClick = function(){
|
|
5404
5670
|
vjs.VolumeMenuButton.prototype.createEl = function(){
|
5405
5671
|
return vjs.Button.prototype.createEl.call(this, 'div', {
|
5406
5672
|
className: 'vjs-volume-menu-button vjs-menu-button vjs-control',
|
5407
|
-
innerHTML: '<div><span class="vjs-control-text">Mute</span></div>'
|
5673
|
+
innerHTML: '<div><span class="vjs-control-text">' + this.localize('Mute') + '</span></div>'
|
5408
5674
|
});
|
5409
5675
|
};
|
5410
5676
|
vjs.VolumeMenuButton.prototype.update = vjs.MuteToggle.prototype.update;
|
@@ -5431,7 +5697,7 @@ vjs.PlaybackRateMenuButton = vjs.MenuButton.extend({
|
|
5431
5697
|
vjs.PlaybackRateMenuButton.prototype.createEl = function(){
|
5432
5698
|
var el = vjs.Component.prototype.createEl.call(this, 'div', {
|
5433
5699
|
className: 'vjs-playback-rate vjs-menu-button vjs-control',
|
5434
|
-
innerHTML: '<div class="vjs-control-content"><span class="vjs-control-text">Playback Rate</span></div>'
|
5700
|
+
innerHTML: '<div class="vjs-control-content"><span class="vjs-control-text">' + this.localize('Playback Rate') + '</span></div>'
|
5435
5701
|
});
|
5436
5702
|
|
5437
5703
|
this.labelEl_ = vjs.createEl('div', {
|
@@ -5629,23 +5895,25 @@ vjs.LoadingSpinner = vjs.Component.extend({
|
|
5629
5895
|
init: function(player, options){
|
5630
5896
|
vjs.Component.call(this, player, options);
|
5631
5897
|
|
5632
|
-
|
5633
|
-
|
5634
|
-
player.on('
|
5635
|
-
player.on('
|
5898
|
+
// MOVING DISPLAY HANDLING TO CSS
|
5899
|
+
|
5900
|
+
// player.on('canplay', vjs.bind(this, this.hide));
|
5901
|
+
// player.on('canplaythrough', vjs.bind(this, this.hide));
|
5902
|
+
// player.on('playing', vjs.bind(this, this.hide));
|
5903
|
+
// player.on('seeking', vjs.bind(this, this.show));
|
5636
5904
|
|
5637
5905
|
// in some browsers seeking does not trigger the 'playing' event,
|
5638
5906
|
// so we also need to trap 'seeked' if we are going to set a
|
5639
5907
|
// 'seeking' event
|
5640
|
-
player.on('seeked', vjs.bind(this, this.hide));
|
5908
|
+
// player.on('seeked', vjs.bind(this, this.hide));
|
5641
5909
|
|
5642
|
-
player.on('ended', vjs.bind(this, this.hide));
|
5910
|
+
// player.on('ended', vjs.bind(this, this.hide));
|
5643
5911
|
|
5644
5912
|
// Not showing spinner on stalled any more. Browsers may stall and then not trigger any events that would remove the spinner.
|
5645
5913
|
// Checked in Chrome 16 and Safari 5.1.2. http://help.videojs.com/discussions/problems/883-why-is-the-download-progress-showing
|
5646
5914
|
// player.on('stalled', vjs.bind(this, this.show));
|
5647
5915
|
|
5648
|
-
player.on('waiting', vjs.bind(this, this.show));
|
5916
|
+
// player.on('waiting', vjs.bind(this, this.show));
|
5649
5917
|
}
|
5650
5918
|
});
|
5651
5919
|
|
@@ -5705,7 +5973,7 @@ vjs.ErrorDisplay.prototype.createEl = function(){
|
|
5705
5973
|
|
5706
5974
|
vjs.ErrorDisplay.prototype.update = function(){
|
5707
5975
|
if (this.player().error()) {
|
5708
|
-
this.contentEl_.innerHTML = this.player().error().message;
|
5976
|
+
this.contentEl_.innerHTML = this.localize(this.player().error().message);
|
5709
5977
|
}
|
5710
5978
|
};
|
5711
5979
|
/**
|
@@ -5797,8 +6065,6 @@ vjs.MediaTechController.prototype.addControlsListeners = function(){
|
|
5797
6065
|
// so we'll check if the controls were already showing before reporting user
|
5798
6066
|
// activity
|
5799
6067
|
this.on('touchstart', function(event) {
|
5800
|
-
// Stop the mouse events from also happening
|
5801
|
-
event.preventDefault();
|
5802
6068
|
userWasActive = this.player_.userActive();
|
5803
6069
|
});
|
5804
6070
|
|
@@ -5808,6 +6074,11 @@ vjs.MediaTechController.prototype.addControlsListeners = function(){
|
|
5808
6074
|
}
|
5809
6075
|
});
|
5810
6076
|
|
6077
|
+
this.on('touchend', function(event) {
|
6078
|
+
// Stop the mouse events from also happening
|
6079
|
+
event.preventDefault();
|
6080
|
+
});
|
6081
|
+
|
5811
6082
|
// Turn on component tap events
|
5812
6083
|
this.emitTapEvents();
|
5813
6084
|
|
@@ -5942,6 +6213,7 @@ vjs.Html5 = vjs.MediaTechController.extend({
|
|
5942
6213
|
});
|
5943
6214
|
|
5944
6215
|
vjs.Html5.prototype.dispose = function(){
|
6216
|
+
vjs.Html5.disposeMediaElement(this.el_);
|
5945
6217
|
vjs.MediaTechController.prototype.dispose.call(this);
|
5946
6218
|
};
|
5947
6219
|
|
@@ -5964,10 +6236,13 @@ vjs.Html5.prototype.createEl = function(){
|
|
5964
6236
|
el = clone;
|
5965
6237
|
player.tag = null;
|
5966
6238
|
} else {
|
5967
|
-
el = vjs.createEl('video'
|
5968
|
-
|
5969
|
-
|
5970
|
-
|
6239
|
+
el = vjs.createEl('video');
|
6240
|
+
vjs.setElementAttributes(el,
|
6241
|
+
vjs.obj.merge(player.tagAttributes || {}, {
|
6242
|
+
id:player.id() + '_html5_api',
|
6243
|
+
'class':'vjs-tech'
|
6244
|
+
})
|
6245
|
+
);
|
5971
6246
|
}
|
5972
6247
|
// associate the player with the new tag
|
5973
6248
|
el['player'] = player;
|
@@ -5976,12 +6251,14 @@ vjs.Html5.prototype.createEl = function(){
|
|
5976
6251
|
}
|
5977
6252
|
|
5978
6253
|
// Update specific tag settings, in case they were overridden
|
5979
|
-
var
|
5980
|
-
for (var i =
|
5981
|
-
var attr =
|
5982
|
-
|
5983
|
-
|
6254
|
+
var settingsAttrs = ['autoplay','preload','loop','muted'];
|
6255
|
+
for (var i = settingsAttrs.length - 1; i >= 0; i--) {
|
6256
|
+
var attr = settingsAttrs[i];
|
6257
|
+
var overwriteAttrs = {};
|
6258
|
+
if (typeof player.options_[attr] !== 'undefined') {
|
6259
|
+
overwriteAttrs[attr] = player.options_[attr];
|
5984
6260
|
}
|
6261
|
+
vjs.setElementAttributes(el, overwriteAttrs);
|
5985
6262
|
}
|
5986
6263
|
|
5987
6264
|
return el;
|
@@ -6310,9 +6587,7 @@ vjs.Flash = vjs.MediaTechController.extend({
|
|
6310
6587
|
'id': objId,
|
6311
6588
|
'name': objId, // Both ID and Name needed or swf to identifty itself
|
6312
6589
|
'class': 'vjs-tech'
|
6313
|
-
}, options['attributes'])
|
6314
|
-
|
6315
|
-
lastSeekTarget
|
6590
|
+
}, options['attributes'])
|
6316
6591
|
;
|
6317
6592
|
|
6318
6593
|
// If source was supplied pass as a flash var.
|
@@ -6327,19 +6602,6 @@ vjs.Flash = vjs.MediaTechController.extend({
|
|
6327
6602
|
}
|
6328
6603
|
}
|
6329
6604
|
|
6330
|
-
this['setCurrentTime'] = function(time){
|
6331
|
-
lastSeekTarget = time;
|
6332
|
-
this.el_.vjs_setProperty('currentTime', time);
|
6333
|
-
};
|
6334
|
-
this['currentTime'] = function(time){
|
6335
|
-
// when seeking make the reported time keep up with the requested time
|
6336
|
-
// by reading the time we're seeking to
|
6337
|
-
if (this.seeking()) {
|
6338
|
-
return lastSeekTarget;
|
6339
|
-
}
|
6340
|
-
return this.el_.vjs_getProperty('currentTime');
|
6341
|
-
};
|
6342
|
-
|
6343
6605
|
// Add placeholder to player div
|
6344
6606
|
vjs.insertFirst(placeHolder, parentEl);
|
6345
6607
|
|
@@ -6349,7 +6611,7 @@ vjs.Flash = vjs.MediaTechController.extend({
|
|
6349
6611
|
this.ready(function(){
|
6350
6612
|
this.load();
|
6351
6613
|
this.play();
|
6352
|
-
this
|
6614
|
+
this['currentTime'](options['startTime']);
|
6353
6615
|
});
|
6354
6616
|
}
|
6355
6617
|
|
@@ -6364,134 +6626,11 @@ vjs.Flash = vjs.MediaTechController.extend({
|
|
6364
6626
|
});
|
6365
6627
|
}
|
6366
6628
|
|
6367
|
-
//
|
6368
|
-
//
|
6369
|
-
|
6370
|
-
// - Webkit when hiding the plugin
|
6371
|
-
// - Webkit and Firefox when using requestFullScreen on a parent element
|
6372
|
-
// Loading the flash plugin into a dynamically generated iFrame gets around most of these issues.
|
6373
|
-
// Issues that remain include hiding the element and requestFullScreen in Firefox specifically
|
6374
|
-
|
6375
|
-
// There's on particularly annoying issue with this method which is that Firefox throws a security error on an offsite Flash object loaded into a dynamically created iFrame.
|
6376
|
-
// Even though the iframe was inserted into a page on the web, Firefox + Flash considers it a local app trying to access an internet file.
|
6377
|
-
// I tried mulitple ways of setting the iframe src attribute but couldn't find a src that worked well. Tried a real/fake source, in/out of domain.
|
6378
|
-
// Also tried a method from stackoverflow that caused a security error in all browsers. http://stackoverflow.com/questions/2486901/how-to-set-document-domain-for-a-dynamically-generated-iframe
|
6379
|
-
// In the end the solution I found to work was setting the iframe window.location.href right before doing a document.write of the Flash object.
|
6380
|
-
// The only downside of this it seems to trigger another http request to the original page (no matter what's put in the href). Not sure why that is.
|
6381
|
-
|
6382
|
-
// NOTE (2012-01-29): Cannot get Firefox to load the remote hosted SWF into a dynamically created iFrame
|
6383
|
-
// Firefox 9 throws a security error, unleess you call location.href right before doc.write.
|
6384
|
-
// Not sure why that even works, but it causes the browser to look like it's continuously trying to load the page.
|
6385
|
-
// Firefox 3.6 keeps calling the iframe onload function anytime I write to it, causing an endless loop.
|
6386
|
-
|
6387
|
-
if (options['iFrameMode'] === true && !vjs.IS_FIREFOX) {
|
6388
|
-
|
6389
|
-
// Create iFrame with vjs-tech class so it's 100% width/height
|
6390
|
-
var iFrm = vjs.createEl('iframe', {
|
6391
|
-
'id': objId + '_iframe',
|
6392
|
-
'name': objId + '_iframe',
|
6393
|
-
'className': 'vjs-tech',
|
6394
|
-
'scrolling': 'no',
|
6395
|
-
'marginWidth': 0,
|
6396
|
-
'marginHeight': 0,
|
6397
|
-
'frameBorder': 0
|
6398
|
-
});
|
6399
|
-
|
6400
|
-
// Update ready function names in flash vars for iframe window
|
6401
|
-
flashVars['readyFunction'] = 'ready';
|
6402
|
-
flashVars['eventProxyFunction'] = 'events';
|
6403
|
-
flashVars['errorEventProxyFunction'] = 'errors';
|
6404
|
-
|
6405
|
-
// Tried multiple methods to get this to work in all browsers
|
6406
|
-
|
6407
|
-
// Tried embedding the flash object in the page first, and then adding a place holder to the iframe, then replacing the placeholder with the page object.
|
6408
|
-
// The goal here was to try to load the swf URL in the parent page first and hope that got around the firefox security error
|
6409
|
-
// var newObj = vjs.Flash.embed(options['swf'], placeHolder, flashVars, params, attributes);
|
6410
|
-
// (in onload)
|
6411
|
-
// var temp = vjs.createEl('a', { id:'asdf', innerHTML: 'asdf' } );
|
6412
|
-
// iDoc.body.appendChild(temp);
|
6413
|
-
|
6414
|
-
// Tried embedding the flash object through javascript in the iframe source.
|
6415
|
-
// This works in webkit but still triggers the firefox security error
|
6416
|
-
// iFrm.src = 'javascript: document.write('"+vjs.Flash.getEmbedCode(options['swf'], flashVars, params, attributes)+"');";
|
6417
|
-
|
6418
|
-
// Tried an actual local iframe just to make sure that works, but it kills the easiness of the CDN version if you require the user to host an iframe
|
6419
|
-
// We should add an option to host the iframe locally though, because it could help a lot of issues.
|
6420
|
-
// iFrm.src = "iframe.html";
|
6421
|
-
|
6422
|
-
// Wait until iFrame has loaded to write into it.
|
6423
|
-
vjs.on(iFrm, 'load', vjs.bind(this, function(){
|
6424
|
-
|
6425
|
-
var iDoc,
|
6426
|
-
iWin = iFrm.contentWindow;
|
6427
|
-
|
6428
|
-
// The one working method I found was to use the iframe's document.write() to create the swf object
|
6429
|
-
// This got around the security issue in all browsers except firefox.
|
6430
|
-
// I did find a hack where if I call the iframe's window.location.href='', it would get around the security error
|
6431
|
-
// However, the main page would look like it was loading indefinitely (URL bar loading spinner would never stop)
|
6432
|
-
// Plus Firefox 3.6 didn't work no matter what I tried.
|
6433
|
-
// if (vjs.USER_AGENT.match('Firefox')) {
|
6434
|
-
// iWin.location.href = '';
|
6435
|
-
// }
|
6436
|
-
|
6437
|
-
// Get the iFrame's document depending on what the browser supports
|
6438
|
-
iDoc = iFrm.contentDocument ? iFrm.contentDocument : iFrm.contentWindow.document;
|
6439
|
-
|
6440
|
-
// Tried ensuring both document domains were the same, but they already were, so that wasn't the issue.
|
6441
|
-
// Even tried adding /. that was mentioned in a browser security writeup
|
6442
|
-
// document.domain = document.domain+'/.';
|
6443
|
-
// iDoc.domain = document.domain+'/.';
|
6444
|
-
|
6445
|
-
// Tried adding the object to the iframe doc's innerHTML. Security error in all browsers.
|
6446
|
-
// iDoc.body.innerHTML = swfObjectHTML;
|
6447
|
-
|
6448
|
-
// Tried appending the object to the iframe doc's body. Security error in all browsers.
|
6449
|
-
// iDoc.body.appendChild(swfObject);
|
6450
|
-
|
6451
|
-
// Using document.write actually got around the security error that browsers were throwing.
|
6452
|
-
// Again, it's a dynamically generated (same domain) iframe, loading an external Flash swf.
|
6453
|
-
// Not sure why that's a security issue, but apparently it is.
|
6454
|
-
iDoc.write(vjs.Flash.getEmbedCode(options['swf'], flashVars, params, attributes));
|
6455
|
-
|
6456
|
-
// Setting variables on the window needs to come after the doc write because otherwise they can get reset in some browsers
|
6457
|
-
// So far no issues with swf ready event being called before it's set on the window.
|
6458
|
-
iWin['player'] = this.player_;
|
6459
|
-
|
6460
|
-
// Create swf ready function for iFrame window
|
6461
|
-
iWin['ready'] = vjs.bind(this.player_, function(currSwf){
|
6462
|
-
var el = iDoc.getElementById(currSwf),
|
6463
|
-
player = this,
|
6464
|
-
tech = player.tech;
|
6465
|
-
|
6466
|
-
// Update reference to playback technology element
|
6467
|
-
tech.el_ = el;
|
6468
|
-
|
6469
|
-
// Make sure swf is actually ready. Sometimes the API isn't actually yet.
|
6470
|
-
vjs.Flash.checkReady(tech);
|
6471
|
-
});
|
6472
|
-
|
6473
|
-
// Create event listener for all swf events
|
6474
|
-
iWin['events'] = vjs.bind(this.player_, function(swfID, eventName){
|
6475
|
-
var player = this;
|
6476
|
-
if (player && player.techName === 'flash') {
|
6477
|
-
player.trigger(eventName);
|
6478
|
-
}
|
6479
|
-
});
|
6480
|
-
|
6481
|
-
// Create error listener for all swf errors
|
6482
|
-
iWin['errors'] = vjs.bind(this.player_, function(swfID, eventName){
|
6483
|
-
vjs.log('Flash Error', eventName);
|
6484
|
-
});
|
6485
|
-
|
6486
|
-
}));
|
6487
|
-
|
6488
|
-
// Replace placeholder with iFrame (it will load now)
|
6489
|
-
placeHolder.parentNode.replaceChild(iFrm, placeHolder);
|
6629
|
+
// native click events on the SWF aren't triggered on IE11, Win8.1RT
|
6630
|
+
// use stageclick events triggered from inside the SWF instead
|
6631
|
+
player.on('stageclick', player.reportUserActivity);
|
6490
6632
|
|
6491
|
-
|
6492
|
-
} else {
|
6493
|
-
vjs.Flash.embed(options['swf'], placeHolder, flashVars, params, attributes);
|
6494
|
-
}
|
6633
|
+
this.el_ = vjs.Flash.embed(options['swf'], placeHolder, flashVars, params, attributes);
|
6495
6634
|
}
|
6496
6635
|
});
|
6497
6636
|
|
@@ -6509,7 +6648,7 @@ vjs.Flash.prototype.pause = function(){
|
|
6509
6648
|
|
6510
6649
|
vjs.Flash.prototype.src = function(src){
|
6511
6650
|
if (src === undefined) {
|
6512
|
-
return this
|
6651
|
+
return this['currentSrc']();
|
6513
6652
|
}
|
6514
6653
|
|
6515
6654
|
if (vjs.Flash.isStreamingSrc(src)) {
|
@@ -6530,7 +6669,21 @@ vjs.Flash.prototype.src = function(src){
|
|
6530
6669
|
}
|
6531
6670
|
};
|
6532
6671
|
|
6533
|
-
vjs.Flash.prototype
|
6672
|
+
vjs.Flash.prototype['setCurrentTime'] = function(time){
|
6673
|
+
this.lastSeekTarget_ = time;
|
6674
|
+
this.el_.vjs_setProperty('currentTime', time);
|
6675
|
+
};
|
6676
|
+
|
6677
|
+
vjs.Flash.prototype['currentTime'] = function(time){
|
6678
|
+
// when seeking make the reported time keep up with the requested time
|
6679
|
+
// by reading the time we're seeking to
|
6680
|
+
if (this.seeking()) {
|
6681
|
+
return this.lastSeekTarget_ || 0;
|
6682
|
+
}
|
6683
|
+
return this.el_.vjs_getProperty('currentTime');
|
6684
|
+
};
|
6685
|
+
|
6686
|
+
vjs.Flash.prototype['currentSrc'] = function(){
|
6534
6687
|
var src = this.el_.vjs_getProperty('currentSrc');
|
6535
6688
|
// no src, check and see if RTMP
|
6536
6689
|
if (src == null) {
|
@@ -6551,7 +6704,7 @@ vjs.Flash.prototype.load = function(){
|
|
6551
6704
|
vjs.Flash.prototype.poster = function(){
|
6552
6705
|
this.el_.vjs_getProperty('poster');
|
6553
6706
|
};
|
6554
|
-
vjs.Flash.prototype
|
6707
|
+
vjs.Flash.prototype['setPoster'] = function(){
|
6555
6708
|
// poster images are not handled by the Flash tech so make this a no-op
|
6556
6709
|
};
|
6557
6710
|
|
@@ -6567,31 +6720,22 @@ vjs.Flash.prototype.enterFullScreen = function(){
|
|
6567
6720
|
return false;
|
6568
6721
|
};
|
6569
6722
|
|
6570
|
-
|
6571
|
-
|
6723
|
+
(function(){
|
6724
|
+
// Create setters and getters for attributes
|
6725
|
+
var api = vjs.Flash.prototype,
|
6572
6726
|
readWrite = 'rtmpConnection,rtmpStream,preload,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted'.split(','),
|
6573
|
-
readOnly = 'error,networkState,readyState,seeking,initialTime,duration,startOffsetTime,paused,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks'.split(',')
|
6727
|
+
readOnly = 'error,networkState,readyState,seeking,initialTime,duration,startOffsetTime,paused,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks'.split(','),
|
6574
6728
|
// Overridden: buffered, currentTime, currentSrc
|
6729
|
+
i;
|
6575
6730
|
|
6576
|
-
|
6577
|
-
|
6578
|
-
|
6579
|
-
|
6580
|
-
|
6581
|
-
|
6582
|
-
|
6583
|
-
};
|
6584
|
-
|
6585
|
-
/**
|
6586
|
-
* @this {*}
|
6587
|
-
* @private
|
6588
|
-
*/
|
6589
|
-
var createGetter = function(attr){
|
6590
|
-
api[attr] = function(){ return this.el_.vjs_getProperty(attr); };
|
6591
|
-
};
|
6731
|
+
function createSetter(attr){
|
6732
|
+
var attrUpper = attr.charAt(0).toUpperCase() + attr.slice(1);
|
6733
|
+
api['set'+attrUpper] = function(val){ return this.el_.vjs_setProperty(attr, val); };
|
6734
|
+
};
|
6735
|
+
function createGetter(attr) {
|
6736
|
+
api[attr] = function(){ return this.el_.vjs_getProperty(attr); };
|
6737
|
+
};
|
6592
6738
|
|
6593
|
-
(function(){
|
6594
|
-
var i;
|
6595
6739
|
// Create getter and setters for all read/write attributes
|
6596
6740
|
for (i = 0; i < readWrite.length; i++) {
|
6597
6741
|
createGetter(readWrite[i]);
|
@@ -6637,39 +6781,40 @@ vjs.Flash.streamingFormats = {
|
|
6637
6781
|
};
|
6638
6782
|
|
6639
6783
|
vjs.Flash['onReady'] = function(currSwf){
|
6640
|
-
var el
|
6641
|
-
|
6642
|
-
// Get player from box
|
6643
|
-
// On firefox reloads, el might already have a player
|
6644
|
-
var player = el['player'] || el.parentNode['player'],
|
6645
|
-
tech = player.tech;
|
6784
|
+
var el, player;
|
6646
6785
|
|
6647
|
-
|
6648
|
-
el['player'] = player;
|
6786
|
+
el = vjs.el(currSwf);
|
6649
6787
|
|
6650
|
-
//
|
6651
|
-
|
6788
|
+
// get player from the player div property
|
6789
|
+
player = el && el.parentNode && el.parentNode['player'];
|
6652
6790
|
|
6653
|
-
|
6791
|
+
// if there is no el or player then the tech has been disposed
|
6792
|
+
// and the tech element was removed from the player div
|
6793
|
+
if (player) {
|
6794
|
+
// reference player on tech element
|
6795
|
+
el['player'] = player;
|
6796
|
+
// check that the flash object is really ready
|
6797
|
+
vjs.Flash['checkReady'](player.tech);
|
6798
|
+
}
|
6654
6799
|
};
|
6655
6800
|
|
6656
|
-
// The SWF isn't
|
6801
|
+
// The SWF isn't always ready when it says it is. Sometimes the API functions still need to be added to the object.
|
6657
6802
|
// If it's not ready, we set a timeout to check again shortly.
|
6658
|
-
vjs.Flash
|
6803
|
+
vjs.Flash['checkReady'] = function(tech){
|
6804
|
+
// stop worrying if the tech has been disposed
|
6805
|
+
if (!tech.el()) {
|
6806
|
+
return;
|
6807
|
+
}
|
6659
6808
|
|
6660
|
-
//
|
6809
|
+
// check if API property exists
|
6661
6810
|
if (tech.el().vjs_getProperty) {
|
6662
|
-
|
6663
|
-
// If so, tell tech it's ready
|
6811
|
+
// tell tech it's ready
|
6664
6812
|
tech.triggerReady();
|
6665
|
-
|
6666
|
-
// Otherwise wait longer.
|
6667
6813
|
} else {
|
6668
|
-
|
6814
|
+
// wait longer
|
6669
6815
|
setTimeout(function(){
|
6670
|
-
vjs.Flash
|
6816
|
+
vjs.Flash['checkReady'](tech);
|
6671
6817
|
}, 50);
|
6672
|
-
|
6673
6818
|
}
|
6674
6819
|
};
|
6675
6820
|
|
@@ -6925,7 +7070,7 @@ vjs.Player.prototype.addTextTrack = function(kind, label, language, options){
|
|
6925
7070
|
if (track.dflt()) {
|
6926
7071
|
this.ready(function(){
|
6927
7072
|
setTimeout(function(){
|
6928
|
-
track.
|
7073
|
+
track.player().showTextTrack(track.id());
|
6929
7074
|
}, 0);
|
6930
7075
|
});
|
6931
7076
|
}
|
@@ -7344,9 +7489,9 @@ vjs.TextTrack.prototype.parseCues = function(srcContent) {
|
|
7344
7489
|
};
|
7345
7490
|
|
7346
7491
|
// Timing line
|
7347
|
-
time = line.split(
|
7492
|
+
time = line.split(/[\t ]+/);
|
7348
7493
|
cue.startTime = this.parseCueTime(time[0]);
|
7349
|
-
cue.endTime = this.parseCueTime(time[
|
7494
|
+
cue.endTime = this.parseCueTime(time[2]);
|
7350
7495
|
|
7351
7496
|
// Additional lines - Cue Text
|
7352
7497
|
text = [];
|
@@ -7803,11 +7948,10 @@ vjs.ChaptersButton.prototype.createMenu = function(){
|
|
7803
7948
|
|
7804
7949
|
for (;i<j;i++) {
|
7805
7950
|
track = tracks[i];
|
7806
|
-
if (track.kind() == this.kind_
|
7807
|
-
if (track.readyState()
|
7808
|
-
|
7951
|
+
if (track.kind() == this.kind_) {
|
7952
|
+
if (track.readyState() === 0) {
|
7953
|
+
track.load();
|
7809
7954
|
track.on('loaded', vjs.bind(this, this.createMenu));
|
7810
|
-
return;
|
7811
7955
|
} else {
|
7812
7956
|
chaptersTrack = track;
|
7813
7957
|
break;
|
@@ -7815,13 +7959,15 @@ vjs.ChaptersButton.prototype.createMenu = function(){
|
|
7815
7959
|
}
|
7816
7960
|
}
|
7817
7961
|
|
7818
|
-
var menu = this.menu
|
7819
|
-
|
7820
|
-
|
7821
|
-
|
7822
|
-
|
7823
|
-
|
7824
|
-
|
7962
|
+
var menu = this.menu;
|
7963
|
+
if (menu === undefined) {
|
7964
|
+
menu = new vjs.Menu(this.player_);
|
7965
|
+
menu.contentEl().appendChild(vjs.createEl('li', {
|
7966
|
+
className: 'vjs-menu-title',
|
7967
|
+
innerHTML: vjs.capitalize(this.kind_),
|
7968
|
+
tabindex: -1
|
7969
|
+
}));
|
7970
|
+
}
|
7825
7971
|
|
7826
7972
|
if (chaptersTrack) {
|
7827
7973
|
var cues = chaptersTrack.cues_, cue, mi;
|
@@ -7840,6 +7986,7 @@ vjs.ChaptersButton.prototype.createMenu = function(){
|
|
7840
7986
|
|
7841
7987
|
menu.addChild(mi);
|
7842
7988
|
}
|
7989
|
+
this.addChild(menu);
|
7843
7990
|
}
|
7844
7991
|
|
7845
7992
|
if (this.items.length > 0) {
|
@@ -8015,7 +8162,7 @@ vjs.autoSetup = function(){
|
|
8015
8162
|
}
|
8016
8163
|
}
|
8017
8164
|
|
8018
|
-
// No videos were found, so keep looping unless page is
|
8165
|
+
// No videos were found, so keep looping unless page is finished loading.
|
8019
8166
|
} else if (!vjs.windowLoaded) {
|
8020
8167
|
vjs.autoSetupTimeout(1);
|
8021
8168
|
}
|