Skip to content

Commit

Permalink
feat: easier configuration of buttons and components via options (#7611)
Browse files Browse the repository at this point in the history
  • Loading branch information
mister-ben committed Mar 21, 2022
1 parent 337ff2f commit 28bdc7d
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 6 deletions.
31 changes: 28 additions & 3 deletions docs/guides/components.md
Expand Up @@ -63,9 +63,10 @@ console.log(button.el());
The above code will output

```html
<div class="video-js">
<div class="vjs-button">Button</div>
</div>
<button class="vjs-control vjs-button" type="button" aria-disabled="false">
<span class="vjs-icon-placeholder" aria-hidden="true"></span>
<span class="vjs-control-text" aria-live="polite"></span>
</button>
```

Adding the new button to the player
Expand All @@ -79,6 +80,30 @@ console.log(button.el());
// will have the same html result as the previous example
```

The text of the button can be set as an option:

```js
const myButton = player.addChild('button', {controlText: 'abc'});
```

or set later:

```js
myButton.controlText('def');
```

The control text of a button is normally not visible (but present for screen readers) as the default buttons all display only an icon. The text can be displayed by adding a `vjs-text-visible` class to the button. This or any other class may be set as a setup option, or later by API.

```js
const myButton = player.addChild('button', {className: 'vjs-text-visible'});
```

or set later:

```js
myButton.addClass('vjs-text-visible');
```

## Component Children

Again, refer to [the component API docs][api] for complete details on methods available for managing component structures.
Expand Down
8 changes: 7 additions & 1 deletion src/css/components/_control.scss
Expand Up @@ -9,8 +9,14 @@
height: 100%;
width: 4em;
@include flex(none);
}

.video-js .vjs-control.vjs-visible-text {
width: auto;
padding-left: 1em;
padding-right: 1em;
}

.vjs-button > .vjs-icon-placeholder:before {
font-size: 1.8em;
line-height: 1.67;
Expand All @@ -30,7 +36,7 @@
}

// Hide control text visually, but have it available for screenreaders
.video-js .vjs-control-text {
.video-js *:not(.vjs-visible-text) > .vjs-control-text {
@include hide-visually;
}

Expand Down
14 changes: 13 additions & 1 deletion src/js/clickable-component.js
Expand Up @@ -22,14 +22,26 @@ class ClickableComponent extends Component {
* The `Player` that this class should be attached to.
*
* @param {Object} [options]
* The key/value store of player options.
* The key/value store of component options.
*
* @param {function} [options.clickHandler]
* The function to call when the button is clicked / activated
*
* @param {string} [options.controlText]
* The text to set on the button
*
* @param {string} [options.className]
* A class or space separated list of classes to add the component
*
*/
constructor(player, options) {

super(player, options);

if (this.options_.controlText) {
this.controlText(this.options_.controlText);
}

this.handleMouseOver_ = (e) => this.handleMouseOver(e);
this.handleMouseOut_ = (e) => this.handleMouseOut(e);
this.handleClick_ = (e) => this.handleClick(e);
Expand Down
9 changes: 8 additions & 1 deletion src/js/component.js
Expand Up @@ -41,13 +41,16 @@ class Component {
* The `Player` that this class should be attached to.
*
* @param {Object} [options]
* The key/value store of player options.
* The key/value store of component options.
*
* @param {Object[]} [options.children]
* An array of children objects to intialize this component with. Children objects have
* a name property that will be used if more than one component of the same type needs to be
* added.
*
* @param {string} [options.className]
* A class or space separated list of classes to add the component
*
* @param {Component~ReadyCallback} [ready]
* Function that gets called when the `Component` is ready.
*/
Expand Down Expand Up @@ -91,6 +94,10 @@ class Component {
this.el_ = this.createEl();
}

if (options.className && this.el_) {
options.className.split(' ').forEach(c => this.addClass(c));
}

// if evented is anything except false, we want to mixin in evented
if (options.evented !== false) {
// Make this an evented object and use `el_`, if available, as its event bus
Expand Down
14 changes: 14 additions & 0 deletions test/unit/clickable-component.test.js
Expand Up @@ -140,3 +140,17 @@ QUnit.test('language change should localize its text', function(assert) {
testClickableComponent.dispose();
player.dispose();
});

QUnit.test('class and text should be settable from options', function(assert) {
const player = TestHelpers.makePlayer({});
const testClickableComponent = new ClickableComponent(player, {
className: 'class1',
controlText: 'some text'
});

assert.equal(testClickableComponent.controlText(), 'some text', 'text was set');
assert.ok(testClickableComponent.hasClass('class1'), 'class was set');

testClickableComponent.dispose();
player.dispose();
});
15 changes: 15 additions & 0 deletions test/unit/component.test.js
Expand Up @@ -677,6 +677,21 @@ QUnit.test('should add and remove a CSS class', function(assert) {
comp.dispose();
});

QUnit.test('should add CSS class passed in options', function(assert) {
const comp = new Component(this.player, {className: 'class1 class2'});

assert.ok(comp.el().className.indexOf('class1') !== -1, 'first of multiple classes added');
assert.ok(comp.el().className.indexOf('class2') !== -1, 'second of multiple classes added');

comp.dispose();

const comp2 = new Component(this.player, {className: 'class1'});

assert.ok(comp2.el().className.indexOf('class1') !== -1, 'singe class added');

comp2.dispose();
});

QUnit.test('should show and hide an element', function(assert) {
const comp = new Component(this.player, {});

Expand Down

0 comments on commit 28bdc7d

Please sign in to comment.