videojs_rails 4.6.4 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
}
|