Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added an 'attributes' arg to createEl() #2589

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"lodash-compat": "^3.9.3",
"object.assign": "^2.0.1",
"safe-json-parse": "^4.0.0",
"tsml": "1.0.1",
"videojs-font": "1.3.0",
"videojs-ie8": "1.1.0",
"videojs-swf": "5.0.0-rc1",
Expand Down
15 changes: 9 additions & 6 deletions src/js/button.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,20 @@ class Button extends Component {
* @return {Element}
* @method createEl
*/
createEl(tag='button', props={}) {
// Add standard Aria and Tabindex info
createEl(tag='button', props={}, attributes={}) {
props = assign({
className: this.buildCSSClass(),
'role': 'button',
'type': 'button', // Necessary since the default button type is "submit"
'aria-live': 'polite', // let the screen reader user know that the text of the button may change
tabIndex: 0
}, props);

let el = super.createEl(tag, props);
// Add standard Aria info
attributes = assign({
role: 'button',
type: 'button', // Necessary since the default button type is "submit"
'aria-live': 'polite' // let the screen reader user know that the text of the button may change
}, attributes);

let el = super.createEl(tag, props, attributes);

this.controlTextEl_ = Dom.createEl('span', {
className: 'vjs-control-text'
Expand Down
7 changes: 4 additions & 3 deletions src/js/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,12 +211,13 @@ class Component {
* Create the component's DOM element
*
* @param {String=} tagName Element's node type. e.g. 'div'
* @param {Object=} attributes An object of element attributes that should be set on the element
* @param {Object=} properties An object of properties that should be set
* @param {Object=} attributes An object of attributes that should be set
* @return {Element}
* @method createEl
*/
createEl(tagName, attributes) {
return Dom.createEl(tagName, attributes);
createEl(tagName, properties, attributes) {
return Dom.createEl(tagName, properties, attributes);
}

localize(string) {
Expand Down
3 changes: 2 additions & 1 deletion src/js/control-bar/live-display.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ class LiveDisplay extends Component {

this.contentEl_ = Dom.createEl('div', {
className: 'vjs-live-display',
innerHTML: `<span class="vjs-control-text">${this.localize('Stream Type')}</span>${this.localize('LIVE')}`,
innerHTML: `<span class="vjs-control-text">${this.localize('Stream Type')}</span>${this.localize('LIVE')}`
}, {
'aria-live': 'off'
});

Expand Down
3 changes: 2 additions & 1 deletion src/js/control-bar/progress-control/seek-bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class SeekBar extends Slider {
*/
createEl() {
return super.createEl('div', {
className: 'vjs-progress-holder',
className: 'vjs-progress-holder'
}, {
'aria-label': 'video progress bar'
});
}
Expand Down
3 changes: 1 addition & 2 deletions src/js/control-bar/spacer-controls/spacer.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@ class Spacer extends Component {
/**
* Create the component's DOM element
*
* @param {Object} props An object of properties
* @return {Element}
* @method createEl
*/
createEl(props) {
createEl() {
return super.createEl('div', {
className: this.buildCSSClass()
});
Expand Down
7 changes: 5 additions & 2 deletions src/js/control-bar/time-controls/current-time-display.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@ class CurrentTimeDisplay extends Component {

this.contentEl_ = Dom.createEl('div', {
className: 'vjs-current-time-display',
innerHTML: '<span class="vjs-control-text">Current Time </span>' + '0:00', // label the current time for screen reader users
'aria-live': 'off' // tell screen readers not to automatically read the time as it changes
// label the current time for screen reader users
innerHTML: '<span class="vjs-control-text">Current Time </span>' + '0:00',
}, {
// tell screen readers not to automatically read the time as it changes
'aria-live': 'off'
});

el.appendChild(this.contentEl_);
Expand Down
9 changes: 6 additions & 3 deletions src/js/control-bar/time-controls/duration-display.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,19 @@ class DurationDisplay extends Component {

this.contentEl_ = Dom.createEl('div', {
className: 'vjs-duration-display',
innerHTML: `<span class="vjs-control-text">${this.localize('Duration Time')}</span> 0:00`, // label the duration time for screen reader users
'aria-live': 'off' // tell screen readers not to automatically read the time as it changes
// label the duration time for screen reader users
innerHTML: `<span class="vjs-control-text">${this.localize('Duration Time')}</span> 0:00`
}, {
// tell screen readers not to automatically read the time as it changes
'aria-live': 'off'
});

el.appendChild(this.contentEl_);
return el;
}

/**
* Update duration time display
* Update duration time display
*
* @method updateContent
*/
Expand Down
7 changes: 5 additions & 2 deletions src/js/control-bar/time-controls/remaining-time-display.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@ class RemainingTimeDisplay extends Component {

this.contentEl_ = Dom.createEl('div', {
className: 'vjs-remaining-time-display',
innerHTML: `<span class="vjs-control-text">${this.localize('Remaining Time')}</span> -0:00`, // label the remaining time for screen reader users
'aria-live': 'off' // tell screen readers not to automatically read the time as it changes
// label the remaining time for screen reader users
innerHTML: `<span class="vjs-control-text">${this.localize('Remaining Time')}</span> -0:00`,
}, {
// tell screen readers not to automatically read the time as it changes
'aria-live': 'off'
});

el.appendChild(this.contentEl_);
Expand Down
3 changes: 2 additions & 1 deletion src/js/control-bar/volume-control/volume-bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class VolumeBar extends Slider {
*/
createEl() {
return super.createEl('div', {
className: 'vjs-volume-bar',
className: 'vjs-volume-bar'
}, {
'aria-label': 'volume level'
});
}
Expand Down
6 changes: 3 additions & 3 deletions src/js/menu/menu-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ class MenuItem extends Button {
* Create the component's DOM element
*
* @param {String=} type Desc
* @param {Object=} props Desc
* @param {Object=} props Desc
* @return {Element}
* @method createEl
*/
createEl(type, props) {
createEl(type, props, attrs) {
return super.createEl('li', assign({
className: 'vjs-menu-item',
innerHTML: this.localize(this.options_['label'])
}, props));
}, props), attrs);
}

/**
Expand Down
10 changes: 7 additions & 3 deletions src/js/slider/slider.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,22 @@ class Slider extends Component {
* @return {Element}
* @method createEl
*/
createEl(type, props={}) {
createEl(type, props={}, attributes={}) {
// Add the slider element class to all sub classes
props.className = props.className + ' vjs-slider';
props = assign({
tabIndex: 0
}, props);

attributes = assign({
'role': 'slider',
'aria-valuenow': 0,
'aria-valuemin': 0,
'aria-valuemax': 100,
tabIndex: 0
}, props);
}, attributes);

return super.createEl(type, props);
return super.createEl(type, props, attributes);
}

/**
Expand Down
37 changes: 21 additions & 16 deletions src/js/utils/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import document from 'global/document';
import window from 'global/window';
import * as Guid from './guid.js';
import log from './log.js';
import tsml from 'tsml';

/**
* Shorthand for document.getElementById()
Expand All @@ -29,25 +31,28 @@ export function getEl(id){
* @return {Element}
* @function createEl
*/
export function createEl(tagName='div', properties={}){
export function createEl(tagName='div', properties={}, attributes={}){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the jsdocs for this were never added.
Also, we should probably document exactly what the different between the two would be.

let el = document.createElement(tagName);

Object.getOwnPropertyNames(properties).forEach(function(propName){
let val = properties[propName];

// Not remembering why we were checking for dash
// but using setAttribute means you have to use getAttribute

// The check for dash checks for the aria- * attributes, like aria-label, aria-valuemin.
// The additional check for "role" is because the default method for adding attributes does not
// add the attribute "role". My guess is because it's not a valid attribute in some namespaces, although
// browsers handle the attribute just fine. The W3C allows for aria- * attributes to be used in pre-HTML5 docs.
// http://www.w3.org/TR/wai-aria-primer/#ariahtml. Using setAttribute gets around this problem.
if (propName.indexOf('aria-') !== -1 || propName === 'role' || propName === 'type') {
el.setAttribute(propName, val);
} else {
el[propName] = val;
}
let val = properties[propName];

// See #2176
// We originally were accepting both properties and attributes in the
// same object, but that doesn't work so well.
if (propName.indexOf('aria-') !== -1 || propName === 'role' || propName === 'type') {
log.warn(tsml(`Setting attributes in the second argument of createEl()
has been deprecated. Use the third argument instead.
createEl(type, properties, attributes). Attempting to set ${propName} to ${val}.`));
el.setAttribute(propName, val);
} else {
el[propName] = val;
}
});

Object.getOwnPropertyNames(attributes).forEach(function(attrName){
let val = attributes[attrName];
el.setAttribute(attrName, attributes[attrName]);
});

return el;
Expand Down
11 changes: 8 additions & 3 deletions test/unit/utils/dom.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,16 @@ test('should return the element with the ID', function(){
});

test('should create an element', function(){
var div = Dom.createEl();
var span = Dom.createEl('span', { 'data-test': 'asdf', innerHTML:'fdsa' });
let div = Dom.createEl();
let span = Dom.createEl('span', {
innerHTML: 'fdsa'
}, {
'data-test': 'asdf'
});

ok(div.nodeName === 'DIV');
ok(span.nodeName === 'SPAN');
ok(span['data-test'] === 'asdf');
ok(span.getAttribute('data-test') === 'asdf');
ok(span.innerHTML === 'fdsa');
});

Expand Down