diff --git a/src/js/lib.js b/src/js/lib.js
index 52abda9f87..4567926467 100644
--- a/src/js/lib.js
+++ b/src/js/lib.js
@@ -391,6 +391,22 @@ vjs.IS_CHROME = (/Chrome/i).test(vjs.USER_AGENT);
vjs.TOUCH_ENABLED = !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch);
+/**
+ * Apply attributes to an HTML element.
+ * @param {Element} el Target element.
+ * @param {Object=} attributes Element attributes to be applied.
+ * @private
+ */
+vjs.setElementAttributes = function(el, attributes){
+ vjs.obj.each(attributes, function(attrName, attrValue) {
+ if (attrValue === null || typeof attrValue === 'undefined' || attrValue === false) {
+ el.removeAttribute(attrName);
+ } else {
+ el.setAttribute(attrName,attrValue === true ? '' : attrValue);
+ }
+ });
+};
+
/**
* Get an element's attribute values, as defined on the HTML tag
* Attributs are not the same as properties. They're defined on the tag
@@ -400,7 +416,7 @@ vjs.TOUCH_ENABLED = !!(('ontouchstart' in window) || window.DocumentTouch && doc
* @return {Object}
* @private
*/
-vjs.getAttributeValues = function(tag){
+vjs.getElementAttributes = function(tag){
var obj, knownBooleans, attrs, attrName, attrVal;
obj = {};
diff --git a/src/js/media/html5.js b/src/js/media/html5.js
index 19dcc3cf7b..e6cc176e52 100644
--- a/src/js/media/html5.js
+++ b/src/js/media/html5.js
@@ -80,10 +80,13 @@ vjs.Html5.prototype.createEl = function(){
el = clone;
player.tag = null;
} else {
- el = vjs.createEl('video', {
- id:player.id() + '_html5_api',
- className:'vjs-tech'
- });
+ el = vjs.createEl('video', {});
+ vjs.setElementAttributes(el,
+ vjs.obj.merge(player.tagAttributes||{}, {
+ id:player.id() + '_html5_api',
+ 'class':'vjs-tech'
+ })
+ );
}
// associate the player with the new tag
el['player'] = player;
@@ -92,12 +95,14 @@ vjs.Html5.prototype.createEl = function(){
}
// Update specific tag settings, in case they were overridden
- var attrs = ['autoplay','preload','loop','muted'];
- for (var i = attrs.length - 1; i >= 0; i--) {
- var attr = attrs[i];
- if (player.options_[attr] !== null) {
- el[attr] = player.options_[attr];
+ var settingsAttrs = ['autoplay','preload','loop','muted'];
+ for (var i = settingsAttrs.length - 1; i >= 0; i--) {
+ var attr = settingsAttrs[i];
+ var overwriteAttrs = {};
+ if (typeof player.options_[attr] !== 'undefined') {
+ overwriteAttrs[attr] = player.options_[attr];
}
+ vjs.setElementAttributes(el, overwriteAttrs);
}
return el;
diff --git a/src/js/player.js b/src/js/player.js
index caa2e5d59d..c8a6bf000d 100644
--- a/src/js/player.js
+++ b/src/js/player.js
@@ -32,6 +32,8 @@ vjs.Player = vjs.Component.extend({
init: function(tag, options, ready){
this.tag = tag; // Store the original tag used to set options
+ this.tagAttributes = (tag) ? vjs.getElementAttributes(tag) : {}; // Store the tag attributes used to restore html5 tech
+
// Make sure tag ID exists
tag.id = tag.id || 'vjs_video_' + vjs.guid++;
@@ -135,7 +137,7 @@ vjs.Player.prototype.getTagSettings = function(tag){
'tracks': []
};
- vjs.obj.merge(options, vjs.getAttributeValues(tag));
+ vjs.obj.merge(options, vjs.getElementAttributes(tag));
// Get tag children settings
if (tag.hasChildNodes()) {
@@ -148,9 +150,9 @@ vjs.Player.prototype.getTagSettings = function(tag){
// Change case needed: http://ejohn.org/blog/nodename-case-sensitivity/
childName = child.nodeName.toLowerCase();
if (childName === 'source') {
- options['sources'].push(vjs.getAttributeValues(child));
+ options['sources'].push(vjs.getElementAttributes(child));
} else if (childName === 'track') {
- options['tracks'].push(vjs.getAttributeValues(child));
+ options['tracks'].push(vjs.getElementAttributes(child));
}
}
}
diff --git a/test/unit/lib.js b/test/unit/lib.js
index 1a24177c6d..a21cc35193 100644
--- a/test/unit/lib.js
+++ b/test/unit/lib.js
@@ -113,10 +113,10 @@ test('should read tag attributes from elements, including HTML5 in all browsers'
document.getElementById('qunit-fixture').innerHTML += tags;
- var vid1Vals = vjs.getAttributeValues(document.getElementById('vid1'));
- var vid2Vals = vjs.getAttributeValues(document.getElementById('vid2'));
- var sourceVals = vjs.getAttributeValues(document.getElementById('source'));
- var trackVals = vjs.getAttributeValues(document.getElementById('track'));
+ var vid1Vals = vjs.getElementAttributes(document.getElementById('vid1'));
+ var vid2Vals = vjs.getElementAttributes(document.getElementById('vid2'));
+ var sourceVals = vjs.getElementAttributes(document.getElementById('source'));
+ var trackVals = vjs.getElementAttributes(document.getElementById('track'));
// was using deepEqual, but ie8 would send all properties as attributes
@@ -152,6 +152,22 @@ test('should read tag attributes from elements, including HTML5 in all browsers'
equal(trackVals['title'], 'test');
});
+
+test('should set tag attributes from object', function(){
+
+ var tags = '';
+
+ document.getElementById('qunit-fixture').innerHTML += tags;
+ var el = document.getElementById('vid1');
+ vjs.setElementAttributes(el, {controls: false,'data-test': 'asdf'});
+
+ var vid1Vals = vjs.getElementAttributes(document.getElementById('vid1'));
+
+ equal(vid1Vals['controls'], undefined);
+ equal(vid1Vals['id'], 'vid1');
+ equal(vid1Vals['data-test'], 'asdf');
+});
+
test('should get the right style values for an element', function(){
var el = document.createElement('div');
var container = document.createElement('div');
diff --git a/test/unit/player.js b/test/unit/player.js
index 7eb6db94e6..09d67825db 100644
--- a/test/unit/player.js
+++ b/test/unit/player.js
@@ -73,7 +73,7 @@ test('should accept options from multiple sources and override in correct order'
});
test('should get tag, source, and track settings', function(){
- // Partially tested in lib->getAttributeValues
+ // Partially tested in lib->getElementAttributes
var fixture = document.getElementById('qunit-fixture');
@@ -482,3 +482,32 @@ test('player should handle different error types', function(){
vjs.log.error.restore();
});
+test('should restore all video tags attribute after a tech switch', function(){
+ var fixture = document.getElementById('qunit-fixture');
+ var html = '';
+ fixture.innerHTML += html;
+
+ var tag = document.getElementById('example_1');
+ var player = new videojs.Player(tag, {techOrder:['html5']});
+ var techOptions = vjs.obj.merge({ 'source': '', 'parentEl': player.el_ }, player.options_['html5']);
+ vjs.Html5.disposeMediaElement(player.tag);
+ player.tag = null;
+ player.tech = new vjs.Html5(player, techOptions);
+
+ PlayerTest.htmlEqualWithSort(player.tech.el_.outerHTML, html.replace('example_1','example_1_html5_api'));
+});
+
+test('should restore all video tags attribute after a tech switch and keep options', function(){
+ var fixture = document.getElementById('qunit-fixture');
+ var html = '';
+ fixture.innerHTML += html;
+
+ var tag = document.getElementById('example_1');
+ var player = new videojs.Player(tag, {techOrder:['html5'], autoplay:false});
+ var techOptions = vjs.obj.merge({ 'source': '', 'parentEl': player.el_ }, player.options_['html5']);
+ vjs.Html5.disposeMediaElement(player.tag);
+ player.tag = null;
+ player.tech = new vjs.Html5(player, techOptions);
+
+ PlayerTest.htmlEqualWithSort(player.tech.el_.outerHTML, html.replace('example_1','example_1_html5_api').replace(' autoplay=""',''));
+});
diff --git a/test/unit/test-helpers.js b/test/unit/test-helpers.js
index ee91ecb4c7..ac84970f94 100644
--- a/test/unit/test-helpers.js
+++ b/test/unit/test-helpers.js
@@ -17,5 +17,16 @@ var PlayerTest = {
playerOptions['techOrder'] = ['mediaFaker'];
return player = new videojs.Player(videoTag, playerOptions);
+ },
+ htmlEqualWithSort : function(htmlResult,htmlExpected) {
+ function htmlTransform(str) {
+ str = str.replace(/[<|>]/g,' ');
+ str = str.trim();
+ str = str.replace(/\s{2,}/g, ' ');
+ return str.split(' ').sort().join(' ');
+ }
+ htmlResult= htmlResult.split(' ').sort().join(' ');
+ equal(htmlTransform(htmlResult),htmlTransform(htmlExpected));
+
}
};