1
0
mirror of https://github.com/videojs/video.js.git synced 2024-11-28 08:58:46 +02:00

@mmcc switched to using button elements for button components. closes #2209

This commit is contained in:
Matthew McClure 2015-05-29 15:56:45 -07:00 committed by heff
parent c3c4046317
commit 9c33bd72c7
20 changed files with 107 additions and 68 deletions

View File

@ -39,6 +39,7 @@ CHANGELOG
* @heff fixed instances of tabIndex that did not have a capital I ([view](https://github.com/videojs/video.js/pull/2204)) * @heff fixed instances of tabIndex that did not have a capital I ([view](https://github.com/videojs/video.js/pull/2204))
* @heff fixed a number of IE8 and Flash related issues ([view](https://github.com/videojs/video.js/pull/2206)) * @heff fixed a number of IE8 and Flash related issues ([view](https://github.com/videojs/video.js/pull/2206))
* @heff Reverted .video-js inline-block style to fix Flash fullscreen ([view](https://github.com/videojs/video.js/pull/2217)) * @heff Reverted .video-js inline-block style to fix Flash fullscreen ([view](https://github.com/videojs/video.js/pull/2217))
* @mmcc switched to using button elements for button components ([view](https://github.com/videojs/video.js/pull/2209))
-------------------- --------------------

View File

@ -412,7 +412,7 @@ module.exports = function(grunt) {
grunt.registerTask('default', ['build', 'test-local']); grunt.registerTask('default', ['build', 'test-local']);
// Development watch task. Doing the minimum required. // Development watch task. Doing the minimum required.
grunt.registerTask('dev', ['connect:dev', 'jshint', 'sass', 'browserify:build', 'karma:chrome']); grunt.registerTask('dev', ['jshint', 'sass', 'browserify:build', 'karma:chrome']);
// Skin development watch task. // Skin development watch task.
grunt.registerTask('skin-dev', ['connect:dev', 'watch:skin']); grunt.registerTask('skin-dev', ['connect:dev', 'watch:skin']);

View File

@ -93,3 +93,12 @@
-webkit-order: $value; -webkit-order: $value;
order: $value; order: $value;
} }
%icon-default {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
text-align: center;
}

View File

@ -1,12 +1,14 @@
.video-js .vjs-big-play-button { .video-js .vjs-big-play-button {
font-size: 3em; font-size: 3em;
line-height: 1em; line-height: 1.5em;
height: 1.5em;
width: 3em; // Firefox bug: For some reason without width the icon wouldn't show up. Switched to using width and removed padding.
display: block; display: block;
z-index: 2; z-index: 2;
position: absolute; position: absolute;
top: 10px; top: 10px;
left: 10px; left: 10px;
padding: 0.2em 1em; padding: 0;
cursor: pointer; cursor: pointer;
opacity: 1; opacity: 1;
border: 2px solid $primary-text; border: 2px solid $primary-text;
@ -17,6 +19,12 @@
@include transition(all 0.4s); @include transition(all 0.4s);
@extend .vjs-icon-play; @extend .vjs-icon-play;
// Since the big play button doesn't inherit from vjs-control, we need to specify a bit more than
// other buttons for the icon.
&:before {
@extend %icon-default
}
} }
/* Hide if controls are disabled, the video is playing, or native controls are used. */ /* Hide if controls are disabled, the video is playing, or native controls are used. */

View File

@ -0,0 +1,13 @@
.video-js button {
background: none;
border: none;
color: $primary-text;
display: inline-block;
overflow: visible; // IE8
font-size: inherit; // IE in general. WTF.
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}

View File

@ -7,17 +7,13 @@
height: 100%; height: 100%;
width: 4em; width: 4em;
@include flex(none); @include flex(none);
}
.video-js .vjs-control:before { &:before {
font-size: 1.8em; font-size: 1.8em;
line-height: 1.67; line-height: 1.67;
position: absolute;
top: 0; @extend %icon-default;
left: 0; }
width: 100%;
height: 100%;
text-align: center;
} }
/* Replacement for focus outline */ /* Replacement for focus outline */

View File

@ -28,12 +28,12 @@
overflow: auto; overflow: auto;
} }
.video-js .vjs-menu-button:hover .vjs-control-content .vjs-menu, .video-js .vjs-menu-button:hover .vjs-menu,
.video-js .vjs-control-content .vjs-menu.vjs-lock-showing { .video-js .vjs-menu.vjs-lock-showing {
display: block; display: block;
} }
/* prevent menus from opening while scrubbing (FF, IE) */ /* prevent menus from opening while scrubbing (FF, IE) */
.video-js.vjs-scrubbing .vjs-menu-button:hover .vjs-control-content .vjs-menu { .video-js.vjs-scrubbing .vjs-menu-button:hover .vjs-menu {
display: none; display: none;
} }
.video-js .vjs-menu-button ul li { .video-js .vjs-menu-button ul li {

View File

@ -4,6 +4,7 @@
@import "components/icons"; @import "components/icons";
@import "components/layout"; @import "components/layout";
@import "components/big-play"; @import "components/big-play";
@import "components/button";
@import "components/control-bar"; @import "components/control-bar";
@import "components/control"; @import "components/control";
@import "components/progress"; @import "components/progress";

View File

@ -13,12 +13,8 @@ import Component from './component.js';
*/ */
class BigPlayButton extends Button { class BigPlayButton extends Button {
createEl() { buildCSSClass() {
return super.createEl('div', { return 'vjs-big-play-button';
className: 'vjs-big-play-button',
innerHTML: '<span aria-hidden="true"></span>',
'aria-label': 'play video'
});
} }
handleClick() { handleClick() {
@ -27,5 +23,7 @@ class BigPlayButton extends Button {
} }
BigPlayButton.prototype.controlText_ = 'Play Video';
Component.registerComponent('BigPlayButton', BigPlayButton); Component.registerComponent('BigPlayButton', BigPlayButton);
export default BigPlayButton; export default BigPlayButton;

View File

@ -27,7 +27,7 @@ class Button extends Component {
this.on('blur', this.handleBlur); this.on('blur', this.handleBlur);
} }
createEl(type, props) { createEl(type='button', props={}) {
// Add standard Aria and Tabindex info // Add standard Aria and Tabindex info
props = assign({ props = assign({
className: this.buildCSSClass(), className: this.buildCSSClass(),
@ -38,24 +38,26 @@ class Button extends Component {
let el = super.createEl(type, props); let el = super.createEl(type, props);
// if innerHTML hasn't been overridden (bigPlayButton), add content elements this.controlTextEl_ = Dom.createEl('span', {
if (!props.innerHTML) { className: 'vjs-control-text'
this.contentEl_ = Dom.createEl('div', { });
className: 'vjs-control-content'
});
this.controlText_ = Dom.createEl('span', { el.appendChild(this.controlTextEl_);
className: 'vjs-control-text',
innerHTML: this.localize(this.buttonText) || 'Need Text'
});
this.contentEl_.appendChild(this.controlText_); this.controlText(this.controlText_);
el.appendChild(this.contentEl_);
}
return el; return el;
} }
controlText(text) {
if (!text) return this.controlText_ || 'Need Text';
this.controlText_ = text;
this.controlTextEl_.innerHTML = this.localize(this.controlText_);
return this;
}
buildCSSClass() { buildCSSClass() {
return `vjs-control vjs-button ${super.buildCSSClass()}`; return `vjs-control vjs-button ${super.buildCSSClass()}`;
} }

View File

@ -17,16 +17,16 @@ class FullscreenToggle extends Button {
handleClick() { handleClick() {
if (!this.player_.isFullscreen()) { if (!this.player_.isFullscreen()) {
this.player_.requestFullscreen(); this.player_.requestFullscreen();
this.controlText_.innerHTML = this.localize('Non-Fullscreen'); this.controlText('Non-Fullscreen');
} else { } else {
this.player_.exitFullscreen(); this.player_.exitFullscreen();
this.controlText_.innerHTML = this.localize('Fullscreen'); this.controlText('Fullscreen');
} }
} }
} }
FullscreenToggle.prototype.buttonText = 'Fullscreen'; FullscreenToggle.prototype.controlText_ = 'Fullscreen';
Component.registerComponent('FullscreenToggle', FullscreenToggle); Component.registerComponent('FullscreenToggle', FullscreenToggle);
export default FullscreenToggle; export default FullscreenToggle;

View File

@ -30,13 +30,6 @@ class MuteToggle extends Button {
}); });
} }
createEl() {
return super.createEl('div', {
className: this.buildCSSClass(),
innerHTML: `<div><span class="vjs-control-text">${this.localize('Mute')}</span></div>`
});
}
buildCSSClass() { buildCSSClass() {
return `vjs-mute-control ${super.buildCSSClass()}`; return `vjs-mute-control ${super.buildCSSClass()}`;
} }
@ -62,8 +55,8 @@ class MuteToggle extends Button {
// This check is needed because this function gets called every time the volume level is changed. // This check is needed because this function gets called every time the volume level is changed.
let toMute = this.player_.muted() ? 'Unmute' : 'Mute'; let toMute = this.player_.muted() ? 'Unmute' : 'Mute';
let localizedMute = this.localize(toMute); let localizedMute = this.localize(toMute);
if (this.el_.children[0].children[0].innerHTML !== localizedMute) { if (this.controlText() !== localizedMute) {
this.el_.children[0].children[0].innerHTML = localizedMute; this.controlText(localizedMute);
} }
/* TODO improve muted icon classes */ /* TODO improve muted icon classes */
@ -75,5 +68,7 @@ class MuteToggle extends Button {
} }
MuteToggle.prototype.controlText_ = 'Mute';
Component.registerComponent('MuteToggle', MuteToggle); Component.registerComponent('MuteToggle', MuteToggle);
export default MuteToggle; export default MuteToggle;

View File

@ -34,19 +34,19 @@ class PlayToggle extends Button {
handlePlay() { handlePlay() {
this.removeClass('vjs-paused'); this.removeClass('vjs-paused');
this.addClass('vjs-playing'); this.addClass('vjs-playing');
this.el_.children[0].children[0].innerHTML = this.localize('Pause'); // change the button text to "Pause" this.controlText('Pause'); // change the button text to "Pause"
} }
// handlePause - Add the vjs-paused class to the element so it can change appearance // handlePause - Add the vjs-paused class to the element so it can change appearance
handlePause() { handlePause() {
this.removeClass('vjs-playing'); this.removeClass('vjs-playing');
this.addClass('vjs-paused'); this.addClass('vjs-paused');
this.el_.children[0].children[0].innerHTML = this.localize('Play'); // change the button text to "Play" this.controlText('Play'); // change the button text to "Play"
} }
} }
PlayToggle.prototype.buttonText = 'Play'; PlayToggle.prototype.controlText_ = 'Play';
Component.registerComponent('PlayToggle', PlayToggle); Component.registerComponent('PlayToggle', PlayToggle);
export default PlayToggle; export default PlayToggle;

View File

@ -36,6 +36,10 @@ class PlaybackRateMenuButton extends MenuButton {
return el; return el;
} }
buildCSSClass() {
return `vjs-playback-rate ${super.buildCSSClass()}`;
}
// Menu creation // Menu creation
createMenu() { createMenu() {
let menu = new Menu(this.player()); let menu = new Menu(this.player());
@ -102,8 +106,7 @@ class PlaybackRateMenuButton extends MenuButton {
} }
PlaybackRateMenuButton.prototype.buttonText = 'Playback Rate'; PlaybackRateMenuButton.prototype.controlText_ = 'Playback Rate';
PlaybackRateMenuButton.prototype.className = 'vjs-playback-rate';
Component.registerComponent('PlaybackRateMenuButton', PlaybackRateMenuButton); Component.registerComponent('PlaybackRateMenuButton', PlaybackRateMenuButton);
export default PlaybackRateMenuButton; export default PlaybackRateMenuButton;

View File

@ -14,6 +14,10 @@ class CaptionsButton extends TextTrackButton {
this.el_.setAttribute('aria-label','Captions Menu'); this.el_.setAttribute('aria-label','Captions Menu');
} }
buildCSSClass() {
return `vjs-captions-button ${super.buildCSSClass()}`;
}
update() { update() {
let threshold = 2; let threshold = 2;
super.update(); super.update();
@ -43,8 +47,7 @@ class CaptionsButton extends TextTrackButton {
} }
CaptionsButton.prototype.kind_ = 'captions'; CaptionsButton.prototype.kind_ = 'captions';
CaptionsButton.prototype.buttonText = 'Captions'; CaptionsButton.prototype.controlText_ = 'Captions';
CaptionsButton.prototype.className = 'vjs-captions-button';
Component.registerComponent('CaptionsButton', CaptionsButton); Component.registerComponent('CaptionsButton', CaptionsButton);
export default CaptionsButton; export default CaptionsButton;

View File

@ -22,6 +22,10 @@ class ChaptersButton extends TextTrackButton {
this.el_.setAttribute('aria-label','Chapters Menu'); this.el_.setAttribute('aria-label','Chapters Menu');
} }
buildCSSClass() {
return `vjs-chapters-button ${super.buildCSSClass()}`;
}
// Create a menu item for each text track // Create a menu item for each text track
createItems() { createItems() {
let items = []; let items = [];
@ -105,8 +109,7 @@ class ChaptersButton extends TextTrackButton {
} }
ChaptersButton.prototype.kind_ = 'chapters'; ChaptersButton.prototype.kind_ = 'chapters';
ChaptersButton.prototype.buttonText = 'Chapters'; ChaptersButton.prototype.controlText_ = 'Chapters';
ChaptersButton.prototype.className = 'vjs-chapters-button';
Component.registerComponent('ChaptersButton', ChaptersButton); Component.registerComponent('ChaptersButton', ChaptersButton);
export default ChaptersButton; export default ChaptersButton;

View File

@ -13,11 +13,14 @@ class SubtitlesButton extends TextTrackButton {
this.el_.setAttribute('aria-label','Subtitles Menu'); this.el_.setAttribute('aria-label','Subtitles Menu');
} }
buildCSSClass() {
return `vjs-subtitles-button ${super.buildCSSClass()}`;
}
} }
SubtitlesButton.prototype.kind_ = 'subtitles'; SubtitlesButton.prototype.kind_ = 'subtitles';
SubtitlesButton.prototype.buttonText = 'Subtitles'; SubtitlesButton.prototype.controlText_ = 'Subtitles';
SubtitlesButton.prototype.className = 'vjs-subtitles-button';
Component.registerComponent('SubtitlesButton', SubtitlesButton); Component.registerComponent('SubtitlesButton', SubtitlesButton);
export default SubtitlesButton; export default SubtitlesButton;

View File

@ -31,6 +31,10 @@ class VolumeMenuButton extends MenuButton {
this.addClass('vjs-menu-button'); this.addClass('vjs-menu-button');
} }
buildCSSClass() {
return `vjs-volume-menu-button ${super.buildCSSClass()}`;
}
createMenu() { createMenu() {
let menu = new Menu(this.player_, { let menu = new Menu(this.player_, {
contentElType: 'div' contentElType: 'div'
@ -57,16 +61,10 @@ class VolumeMenuButton extends MenuButton {
super.handleClick(); super.handleClick();
} }
createEl() {
return super.createEl('div', {
className: 'vjs-volume-menu-button vjs-menu-button vjs-control vjs-button',
innerHTML: `<div><span class="vjs-control-text">${this.localize('Mute')}</span></div>`
});
}
} }
VolumeMenuButton.prototype.volumeUpdate = MuteToggle.prototype.update; VolumeMenuButton.prototype.volumeUpdate = MuteToggle.prototype.update;
VolumeMenuButton.prototype.controlText_ = 'Mute';
Component.registerComponent('VolumeMenuButton', VolumeMenuButton); Component.registerComponent('VolumeMenuButton', VolumeMenuButton);
export default VolumeMenuButton; export default VolumeMenuButton;

View File

@ -76,9 +76,15 @@ class MenuButton extends Button {
*/ */
createItems(){} createItems(){}
createEl() {
return super.createEl('div', {
className: this.buildCSSClass()
});
}
/** @inheritDoc */ /** @inheritDoc */
buildCSSClass() { buildCSSClass() {
return `${this.className} vjs-menu-button ${super.buildCSSClass()}`; return `vjs-menu-button ${super.buildCSSClass()}`;
} }
// Focus - Add keyboard functionality to element // Focus - Add keyboard functionality to element

View File

@ -18,8 +18,8 @@ test('should localize its text', function(){
}); });
testButton = new Button(player); testButton = new Button(player);
testButton.buttonText = 'Play'; testButton.controlText_ = 'Play';
el = testButton.createEl(); el = testButton.createEl();
ok(el.innerHTML, 'Juego', 'translation was successful'); ok(el.innerHTML.match('Juego'));
}); });