mirror of
https://github.com/videojs/video.js.git
synced 2024-11-24 08:42:25 +02:00
@mmcc switched to using button elements for button components. closes #2209
This commit is contained in:
parent
c3c4046317
commit
9c33bd72c7
@ -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 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))
|
||||
* @mmcc switched to using button elements for button components ([view](https://github.com/videojs/video.js/pull/2209))
|
||||
|
||||
--------------------
|
||||
|
||||
|
2
grunt.js
2
grunt.js
@ -412,7 +412,7 @@ module.exports = function(grunt) {
|
||||
grunt.registerTask('default', ['build', 'test-local']);
|
||||
|
||||
// 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.
|
||||
grunt.registerTask('skin-dev', ['connect:dev', 'watch:skin']);
|
||||
|
@ -93,3 +93,12 @@
|
||||
-webkit-order: $value;
|
||||
order: $value;
|
||||
}
|
||||
|
||||
%icon-default {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
.video-js .vjs-big-play-button {
|
||||
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;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
padding: 0.2em 1em;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
border: 2px solid $primary-text;
|
||||
@ -17,6 +19,12 @@
|
||||
@include transition(all 0.4s);
|
||||
|
||||
@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. */
|
||||
|
13
src/css/components/_button.scss
Normal file
13
src/css/components/_button.scss
Normal 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;
|
||||
}
|
@ -7,17 +7,13 @@
|
||||
height: 100%;
|
||||
width: 4em;
|
||||
@include flex(none);
|
||||
}
|
||||
|
||||
.video-js .vjs-control:before {
|
||||
font-size: 1.8em;
|
||||
line-height: 1.67;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
&:before {
|
||||
font-size: 1.8em;
|
||||
line-height: 1.67;
|
||||
|
||||
@extend %icon-default;
|
||||
}
|
||||
}
|
||||
|
||||
/* Replacement for focus outline */
|
||||
|
@ -28,12 +28,12 @@
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.video-js .vjs-menu-button:hover .vjs-control-content .vjs-menu,
|
||||
.video-js .vjs-control-content .vjs-menu.vjs-lock-showing {
|
||||
.video-js .vjs-menu-button:hover .vjs-menu,
|
||||
.video-js .vjs-menu.vjs-lock-showing {
|
||||
display: block;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
.video-js .vjs-menu-button ul li {
|
||||
|
@ -4,6 +4,7 @@
|
||||
@import "components/icons";
|
||||
@import "components/layout";
|
||||
@import "components/big-play";
|
||||
@import "components/button";
|
||||
@import "components/control-bar";
|
||||
@import "components/control";
|
||||
@import "components/progress";
|
||||
|
@ -13,12 +13,8 @@ import Component from './component.js';
|
||||
*/
|
||||
class BigPlayButton extends Button {
|
||||
|
||||
createEl() {
|
||||
return super.createEl('div', {
|
||||
className: 'vjs-big-play-button',
|
||||
innerHTML: '<span aria-hidden="true"></span>',
|
||||
'aria-label': 'play video'
|
||||
});
|
||||
buildCSSClass() {
|
||||
return 'vjs-big-play-button';
|
||||
}
|
||||
|
||||
handleClick() {
|
||||
@ -27,5 +23,7 @@ class BigPlayButton extends Button {
|
||||
|
||||
}
|
||||
|
||||
BigPlayButton.prototype.controlText_ = 'Play Video';
|
||||
|
||||
Component.registerComponent('BigPlayButton', BigPlayButton);
|
||||
export default BigPlayButton;
|
||||
|
@ -27,7 +27,7 @@ class Button extends Component {
|
||||
this.on('blur', this.handleBlur);
|
||||
}
|
||||
|
||||
createEl(type, props) {
|
||||
createEl(type='button', props={}) {
|
||||
// Add standard Aria and Tabindex info
|
||||
props = assign({
|
||||
className: this.buildCSSClass(),
|
||||
@ -38,24 +38,26 @@ class Button extends Component {
|
||||
|
||||
let el = super.createEl(type, props);
|
||||
|
||||
// if innerHTML hasn't been overridden (bigPlayButton), add content elements
|
||||
if (!props.innerHTML) {
|
||||
this.contentEl_ = Dom.createEl('div', {
|
||||
className: 'vjs-control-content'
|
||||
});
|
||||
this.controlTextEl_ = Dom.createEl('span', {
|
||||
className: 'vjs-control-text'
|
||||
});
|
||||
|
||||
this.controlText_ = Dom.createEl('span', {
|
||||
className: 'vjs-control-text',
|
||||
innerHTML: this.localize(this.buttonText) || 'Need Text'
|
||||
});
|
||||
el.appendChild(this.controlTextEl_);
|
||||
|
||||
this.contentEl_.appendChild(this.controlText_);
|
||||
el.appendChild(this.contentEl_);
|
||||
}
|
||||
this.controlText(this.controlText_);
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
controlText(text) {
|
||||
if (!text) return this.controlText_ || 'Need Text';
|
||||
|
||||
this.controlText_ = text;
|
||||
this.controlTextEl_.innerHTML = this.localize(this.controlText_);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
buildCSSClass() {
|
||||
return `vjs-control vjs-button ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
@ -17,16 +17,16 @@ class FullscreenToggle extends Button {
|
||||
handleClick() {
|
||||
if (!this.player_.isFullscreen()) {
|
||||
this.player_.requestFullscreen();
|
||||
this.controlText_.innerHTML = this.localize('Non-Fullscreen');
|
||||
this.controlText('Non-Fullscreen');
|
||||
} else {
|
||||
this.player_.exitFullscreen();
|
||||
this.controlText_.innerHTML = this.localize('Fullscreen');
|
||||
this.controlText('Fullscreen');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FullscreenToggle.prototype.buttonText = 'Fullscreen';
|
||||
FullscreenToggle.prototype.controlText_ = 'Fullscreen';
|
||||
|
||||
Component.registerComponent('FullscreenToggle', FullscreenToggle);
|
||||
export default FullscreenToggle;
|
||||
|
@ -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() {
|
||||
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.
|
||||
let toMute = this.player_.muted() ? 'Unmute' : 'Mute';
|
||||
let localizedMute = this.localize(toMute);
|
||||
if (this.el_.children[0].children[0].innerHTML !== localizedMute) {
|
||||
this.el_.children[0].children[0].innerHTML = localizedMute;
|
||||
if (this.controlText() !== localizedMute) {
|
||||
this.controlText(localizedMute);
|
||||
}
|
||||
|
||||
/* TODO improve muted icon classes */
|
||||
@ -75,5 +68,7 @@ class MuteToggle extends Button {
|
||||
|
||||
}
|
||||
|
||||
MuteToggle.prototype.controlText_ = 'Mute';
|
||||
|
||||
Component.registerComponent('MuteToggle', MuteToggle);
|
||||
export default MuteToggle;
|
||||
|
@ -34,19 +34,19 @@ class PlayToggle extends Button {
|
||||
handlePlay() {
|
||||
this.removeClass('vjs-paused');
|
||||
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() {
|
||||
this.removeClass('vjs-playing');
|
||||
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);
|
||||
export default PlayToggle;
|
||||
|
@ -36,6 +36,10 @@ class PlaybackRateMenuButton extends MenuButton {
|
||||
return el;
|
||||
}
|
||||
|
||||
buildCSSClass() {
|
||||
return `vjs-playback-rate ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
// Menu creation
|
||||
createMenu() {
|
||||
let menu = new Menu(this.player());
|
||||
@ -102,8 +106,7 @@ class PlaybackRateMenuButton extends MenuButton {
|
||||
|
||||
}
|
||||
|
||||
PlaybackRateMenuButton.prototype.buttonText = 'Playback Rate';
|
||||
PlaybackRateMenuButton.prototype.className = 'vjs-playback-rate';
|
||||
PlaybackRateMenuButton.prototype.controlText_ = 'Playback Rate';
|
||||
|
||||
Component.registerComponent('PlaybackRateMenuButton', PlaybackRateMenuButton);
|
||||
export default PlaybackRateMenuButton;
|
||||
|
@ -14,6 +14,10 @@ class CaptionsButton extends TextTrackButton {
|
||||
this.el_.setAttribute('aria-label','Captions Menu');
|
||||
}
|
||||
|
||||
buildCSSClass() {
|
||||
return `vjs-captions-button ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
update() {
|
||||
let threshold = 2;
|
||||
super.update();
|
||||
@ -43,8 +47,7 @@ class CaptionsButton extends TextTrackButton {
|
||||
}
|
||||
|
||||
CaptionsButton.prototype.kind_ = 'captions';
|
||||
CaptionsButton.prototype.buttonText = 'Captions';
|
||||
CaptionsButton.prototype.className = 'vjs-captions-button';
|
||||
CaptionsButton.prototype.controlText_ = 'Captions';
|
||||
|
||||
Component.registerComponent('CaptionsButton', CaptionsButton);
|
||||
export default CaptionsButton;
|
||||
|
@ -22,6 +22,10 @@ class ChaptersButton extends TextTrackButton {
|
||||
this.el_.setAttribute('aria-label','Chapters Menu');
|
||||
}
|
||||
|
||||
buildCSSClass() {
|
||||
return `vjs-chapters-button ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
// Create a menu item for each text track
|
||||
createItems() {
|
||||
let items = [];
|
||||
@ -105,8 +109,7 @@ class ChaptersButton extends TextTrackButton {
|
||||
}
|
||||
|
||||
ChaptersButton.prototype.kind_ = 'chapters';
|
||||
ChaptersButton.prototype.buttonText = 'Chapters';
|
||||
ChaptersButton.prototype.className = 'vjs-chapters-button';
|
||||
ChaptersButton.prototype.controlText_ = 'Chapters';
|
||||
|
||||
Component.registerComponent('ChaptersButton', ChaptersButton);
|
||||
export default ChaptersButton;
|
||||
|
@ -13,11 +13,14 @@ class SubtitlesButton extends TextTrackButton {
|
||||
this.el_.setAttribute('aria-label','Subtitles Menu');
|
||||
}
|
||||
|
||||
buildCSSClass() {
|
||||
return `vjs-subtitles-button ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SubtitlesButton.prototype.kind_ = 'subtitles';
|
||||
SubtitlesButton.prototype.buttonText = 'Subtitles';
|
||||
SubtitlesButton.prototype.className = 'vjs-subtitles-button';
|
||||
SubtitlesButton.prototype.controlText_ = 'Subtitles';
|
||||
|
||||
Component.registerComponent('SubtitlesButton', SubtitlesButton);
|
||||
export default SubtitlesButton;
|
||||
|
@ -31,6 +31,10 @@ class VolumeMenuButton extends MenuButton {
|
||||
this.addClass('vjs-menu-button');
|
||||
}
|
||||
|
||||
buildCSSClass() {
|
||||
return `vjs-volume-menu-button ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
createMenu() {
|
||||
let menu = new Menu(this.player_, {
|
||||
contentElType: 'div'
|
||||
@ -57,16 +61,10 @@ class VolumeMenuButton extends MenuButton {
|
||||
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.controlText_ = 'Mute';
|
||||
|
||||
Component.registerComponent('VolumeMenuButton', VolumeMenuButton);
|
||||
export default VolumeMenuButton;
|
||||
|
@ -76,9 +76,15 @@ class MenuButton extends Button {
|
||||
*/
|
||||
createItems(){}
|
||||
|
||||
createEl() {
|
||||
return super.createEl('div', {
|
||||
className: this.buildCSSClass()
|
||||
});
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
buildCSSClass() {
|
||||
return `${this.className} vjs-menu-button ${super.buildCSSClass()}`;
|
||||
return `vjs-menu-button ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
// Focus - Add keyboard functionality to element
|
||||
|
@ -18,8 +18,8 @@ test('should localize its text', function(){
|
||||
});
|
||||
|
||||
testButton = new Button(player);
|
||||
testButton.buttonText = 'Play';
|
||||
testButton.controlText_ = 'Play';
|
||||
el = testButton.createEl();
|
||||
|
||||
ok(el.innerHTML, 'Juego', 'translation was successful');
|
||||
ok(el.innerHTML.match('Juego'));
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user