Skip to content

Commit

Permalink
Merge pull request #680 from jwplayer/feature/control-bar-compact-mode
Browse files Browse the repository at this point in the history
JW7-815 - Control Compact Mode and Menu Drawer
  • Loading branch information
robwalch committed Aug 26, 2015
2 parents 9d98d35 + a4059cf commit 07242dc
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 16 deletions.
9 changes: 9 additions & 0 deletions src/css/flags/compact-player.less
@@ -0,0 +1,9 @@
.jw-flag-compact-player {
.jw-icon-playlist,
.jw-icon-next,
.jw-icon-prev,
.jw-text-elapsed,
.jw-text-duration {
display: none;
}
}
5 changes: 5 additions & 0 deletions src/css/imports/controlbar.less
Expand Up @@ -12,6 +12,11 @@
.jw-hidden {
display: none;
}

&.jw-drawer-expanded .jw-controlbar-left-group,
&.jw-drawer-expanded .jw-controlbar-center-group {
opacity: 0;
}
}

.jw-background-color {
Expand Down
16 changes: 16 additions & 0 deletions src/css/imports/tooltip.less
@@ -1,4 +1,5 @@
@import "vars";
@import "icons";

.jw-icon-tooltip.jw-open .jw-overlay {
opacity: 1;
Expand All @@ -9,6 +10,21 @@
display: none;
}

.jw-overlay-horizontal {
display: none;
}

.jw-icon-tooltip.jw-open-drawer {
.jw-icon-close;
}

.jw-icon-tooltip.jw-open-drawer .jw-overlay-horizontal {
opacity: 1;
display: inline-block;
vertical-align: top;
}


.jw-overlay:after {
position: absolute;
bottom: -0.5em;
Expand Down
1 change: 1 addition & 0 deletions src/css/jwplayer.less
Expand Up @@ -34,6 +34,7 @@
@import "flags/rightclick-open";
@import "flags/controls-disabled";
@import "flags/touch";
@import "flags/compact-player";

// Skins
@import "skins/seven";
1 change: 1 addition & 0 deletions src/js/controller/model.js
Expand Up @@ -37,6 +37,7 @@ define([
// Initial state, upon setup
state: states.IDLE,
fullscreen: false,
compactUI: false,
scrubbing : false,
duration: 0,
position: 0,
Expand Down
67 changes: 67 additions & 0 deletions src/js/view/components/drawer.js
@@ -0,0 +1,67 @@
define([
'view/components/tooltip',
'utils/helpers',
'utils/underscore',
'utils/ui'
], function(Tooltip, utils, _, UI) {
var Drawer = Tooltip.extend({
constructor: function(name) {
Tooltip.call(this, name);

this.container.className = 'jw-overlay-horizontal jw-reset';
this.openClass = 'jw-open-drawer';
},
setup : function (list, isCompactMode) {
if(!this.iconUI){
this.iconUI = new UI(this.el);

this.toggleOpenStateListener = this.toggleOpenState.bind(this);
this.openTooltipListener = this.openTooltip.bind(this);
this.closeTooltipListener = this.closeTooltip.bind(this);
}

this.reset();

list = _.isArray(list) ? list : [];

var hasActiveContents = _.any(list, function (ele) {
return ele.hasContent();
});

utils.toggleClass(this.el, 'jw-hidden', !isCompactMode || !hasActiveContents);

if (isCompactMode && hasActiveContents) {
utils.removeClass(this.el, 'jw-off');

this.iconUI.on('tap', function (evt) {
if (evt.target === this.el) {
this.isOpen = !this.isOpen;
utils.toggleClass(this.el, this.openClass, this.isOpen);
this.trigger('drawer-open', {'isOpen': this.isOpen});
}
}, this);

this.el.addEventListener('mouseover', this.openTooltipListener);
this.el.addEventListener('mouseout', this.closeTooltipListener);

_.each(list, function (menu) {
this.container.appendChild(menu.el);
}, this);
}
// else, spit the menus back out
},
reset : function() {
utils.addClass(this.el, 'jw-off');
this.iconUI.off();
if(this.contentUI) {
this.contentUI.off().destroy();
}
this.removeContent();

this.el.removeEventListener('mouseover', this.openTooltipListener);
this.el.removeEventListener('mouseout', this.closeTooltipListener);
}
});

return Drawer;
});
11 changes: 8 additions & 3 deletions src/js/view/components/tooltip.js
Expand Up @@ -9,6 +9,8 @@ define([
this.el.className = 'jw-icon jw-icon-tooltip ' + name + ' jw-button-color jw-reset jw-hidden';
this.container = document.createElement('div');
this.container.className = 'jw-overlay jw-reset';
this.openClass = 'jw-open';

this.el.appendChild(this.container);
},

Expand All @@ -26,20 +28,23 @@ define([
this.content = null;
}
},
hasContent: function(){
return !!this.content;
},
element: function(){
return this.el;
},
openTooltip: function() {
this.isOpen = true;
utils.toggleClass(this.el, 'jw-open', this.isOpen);
utils.toggleClass(this.el, this.openClass, this.isOpen);
},
closeTooltip: function() {
this.isOpen = false;
utils.toggleClass(this.el, 'jw-open', this.isOpen);
utils.toggleClass(this.el, this.openClass, this.isOpen);
},
toggleOpenState: function(){
this.isOpen = !this.isOpen;
utils.toggleClass(this.el, 'jw-open', this.isOpen);
utils.toggleClass(this.el, this.openClass, this.isOpen);
}
});

Expand Down
90 changes: 80 additions & 10 deletions src/js/view/controlbar.js
Expand Up @@ -7,8 +7,9 @@ define([
'view/components/timeslider',
'view/components/menu',
'view/components/playlist',
'view/components/volumetooltip'
], function(utils, _, Events, UI, Slider, TimeSlider, Menu, Playlist, VolumeTooltip) {
'view/components/volumetooltip',
'view/components/drawer'
], function(utils, _, Events, UI, Slider, TimeSlider, Menu, Playlist, VolumeTooltip, Drawer) {

function button(icon, apiAction) {
var element = document.createElement('div');
Expand Down Expand Up @@ -63,6 +64,11 @@ define([
function Controlbar(_api, _model) {
this._api = _api;
this._model = _model;
this._isMobile = utils.isMobile();
this._compactModeMaxSize = 400;

this._leftGroupExpandedSize = false;
this._rightGroupExpandedSize = false;

this.setup();
}
Expand All @@ -76,18 +82,23 @@ define([

build : function() {
var timeSlider = new TimeSlider(this._model, this._api),
drawer = new Drawer('jw-icon-more'),
playlistTooltip,
volumeSlider,
volumeTooltip,
muteButton;

drawer.on('drawer-open', function(props){
utils.toggleClass(this.el, 'jw-drawer-expanded', props.isOpen);
}, this);

// Create the playlistTooltip as long as visualplaylist from the config is not false
if(this._model.get('visualplaylist') !== false) {
playlistTooltip = new Playlist('jw-icon-playlist');
}

// Do not initialize volume sliders on mobile.
if(!utils.isMobile()){
if(!this._isMobile){
muteButton = button('jw-icon-volume', this._api.setMute);
volumeSlider = new Slider('jw-slider-volume', 'horizontal');
volumeTooltip = new VolumeTooltip(this._model, 'jw-icon-volume');
Expand All @@ -102,6 +113,7 @@ define([
elapsed: text('jw-text-elapsed'),
time: timeSlider,
duration: text('jw-text-duration'),
drawer: drawer,
hd: menu('jw-icon-hd'),
cc: menu('jw-icon-cc'),
audiotracks: menu('jw-icon-audio-tracks'),
Expand Down Expand Up @@ -129,12 +141,21 @@ define([
this.elements.hd,
this.elements.cc,
this.elements.audiotracks,
this.elements.drawer,
this.elements.mute,
this.elements.cast,
this.elements.volume,
this.elements.volumetooltip,
// this.elements.cast, // hidden for jw7.0 release
this.elements.fullscreen
],
drawer: [
this.elements.hd,
this.elements.cc,
this.elements.audiotracks
//this.elements.mute,
//this.elements.volume,
//this.elements.volumetooltip
]
};

Expand All @@ -143,17 +164,18 @@ define([
this.layout.left = _.compact(this.layout.left);
this.layout.center = _.compact(this.layout.center);
this.layout.right = _.compact(this.layout.right);
this.layout.drawer = _.compact(this.layout.drawer);

this.el = document.createElement('div');
this.el.className = 'jw-controlbar jw-background-color jw-reset';

var leftGroup = buildGroup('left', this.layout.left);
var centerGroup = buildGroup('center', this.layout.center);
var rightGroup = buildGroup('right', this.layout.right);
this.elements.left = buildGroup('left', this.layout.left);
this.elements.center = buildGroup('center', this.layout.center);
this.elements.right = buildGroup('right', this.layout.right);

this.el.appendChild(leftGroup);
this.el.appendChild(centerGroup);
this.el.appendChild(rightGroup);
this.el.appendChild(this.elements.left);
this.el.appendChild(this.elements.center);
this.el.appendChild(this.elements.right);
},

initialize : function() {
Expand All @@ -180,6 +202,7 @@ define([
this._model.on('change:fullscreen', this.onFullscreen, this);
this._model.on('change:captionsList', this.onCaptionsList, this);
this._model.on('change:captionsIndex', this.onCaptionsIndex, this);
this._model.on('change:compactUI', this.onCompactUI, this);

// Event listeners

Expand Down Expand Up @@ -258,6 +281,10 @@ define([
this.elements.duration.innerHTML = '00:00';
this.elements.elapsed.innerHTML = '00:00';

this._leftGroupExpandedSize = false;
this._rightGroupExpandedSize = false;
this._model.set('compactUI', false);

var itemIdx = model.get('item');
if(this.elements.playlist) {
this.elements.playlist.selectItem(itemIdx);
Expand All @@ -278,6 +305,12 @@ define([
this._model.mediaModel.on('change:currentAudioTrack', function(model, currentAudioTrack) {
this.elements.audiotracks.selectItem(currentAudioTrack);
}, this);
this._model.mediaModel.on('change:state', function(model, state) {
if(state === 'complete') {
this.elements.drawer.closeTooltip();
utils.toggleClass(this.el, 'jw-drawer-expanded', false);
}
}, this);
},
onVolume : function(model, pct) {
this.renderVolume(model.get('mute'), pct);
Expand Down Expand Up @@ -354,8 +387,45 @@ define([
}, this);
this.elements.time.drawCues();
}
},
checkCompactMode : function(containerWidth) {
if(this.element().offsetWidth > 0){
if (!this._leftGroupExpandedSize && this.elements.left.offsetWidth) {
this._leftGroupExpandedSize = this.elements.left.offsetWidth;
this._rightGroupExpandedSize = this.elements.right.offsetWidth;
}

var timeSliderSize = this.elements.time.el.offsetWidth,
timeSliderShare = timeSliderSize / containerWidth,
containerRequiredSize = this._leftGroupExpandedSize + this._rightGroupExpandedSize +
(this.elements.center.offsetWidth - this.elements.time.el.offsetWidth);

if(this._model.get('compactUI')){
// If we're in compact mode and we have enough space to exit it, then do so
if( containerWidth > this._compactModeMaxSize &&
(containerWidth - containerRequiredSize) / containerWidth >= 0.275) {
this._model.set('compactUI', false);
}
} else {
// Enter if we're in a small player or our timeslider is too small.
if( containerWidth <= this._compactModeMaxSize || (timeSliderSize && timeSliderShare < 0.25) ){
this._model.set('compactUI', true);
}
}
}
},
onCompactUI : function(model, isCompact) {
utils.toggleClass(this.el, 'jw-drawer-expanded', false);

this.elements.drawer.setup(this.layout.drawer, isCompact);

if(!isCompact){
_.each(this.layout.drawer,function(ele){
this.elements.right.insertBefore(ele.el, this.elements.drawer.el);
}, this);
}
}
});

return Controlbar;
});
});

0 comments on commit 07242dc

Please sign in to comment.