mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
replace sliders
This commit is contained in:
parent
09d4af3357
commit
1b74dbdfbf
13 changed files with 1359 additions and 1439 deletions
|
@ -58,428 +58,433 @@ Custom property | Description | Default
|
||||||
|
|
||||||
<dom-module id="paper-slider">
|
<dom-module id="paper-slider">
|
||||||
|
|
||||||
<link rel="import" type="css" href="paper-slider.css">
|
<link rel="import" type="css" href="paper-slider.css">
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="sliderContainer"
|
<div id="sliderContainer"
|
||||||
class$="[[_getClassNames(disabled, pin, snaps, immediateValue, min, expand, dragging, transiting, editable)]]">
|
class$="[[_getClassNames(disabled, pin, snaps, immediateValue, min, expand, dragging, transiting, editable)]]">
|
||||||
|
|
||||||
<div class="bar-container">
|
<div class="bar-container">
|
||||||
<paper-progress
|
<paper-progress id="sliderBar"
|
||||||
id="sliderBar"
|
aria-hidden="true"
|
||||||
aria-hidden="true"
|
min="[[min]]"
|
||||||
min="[[min]]"
|
max="[[max]]"
|
||||||
max="[[max]]"
|
step="[[step]]"
|
||||||
step="[[step]]"
|
value="[[immediateValue]]"
|
||||||
value="[[immediateValue]]"
|
secondary-progress="[[secondaryProgress]]"
|
||||||
secondary-progress="[[secondaryProgress]]"
|
on-down="_bardown"
|
||||||
on-down="_bardown"
|
on-up="_resetKnob"
|
||||||
on-up="_resetKnob"
|
on-track="_onTrack">
|
||||||
on-track="_onTrack">
|
</paper-progress>
|
||||||
</paper-progress>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<template is="dom-if" if="[[snaps]]">
|
<template is="dom-if" if="[[snaps]]">
|
||||||
<div class="slider-markers horizontal layout">
|
<div class="slider-markers horizontal layout">
|
||||||
<template is="dom-repeat" items="[[markers]]">
|
<template is="dom-repeat" items="[[markers]]">
|
||||||
<div class="slider-marker flex"></div>
|
<div class="slider-marker flex"></div>
|
||||||
</template>
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div id="sliderKnob"
|
||||||
|
class="center-justified center horizontal layout"
|
||||||
|
on-down="_knobdown"
|
||||||
|
on-up="_resetKnob"
|
||||||
|
on-track="_onTrack"
|
||||||
|
on-transitionend="_knobTransitionEnd">
|
||||||
|
<paper-ripple id="ink" class="circle" center hidden$="[[!receivedFocusFromKeyboard]]"></paper-ripple>
|
||||||
|
<div id="sliderKnobInner" value$="[[pinValue]]"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
|
||||||
|
|
||||||
<div id="sliderKnob"
|
<template is="dom-if" if="[[editable]]">
|
||||||
class="center-justified center horizontal layout"
|
<paper-input id="input"
|
||||||
on-down="_knobdown"
|
class="slider-input"
|
||||||
on-up="_resetKnob"
|
disabled$="[[disabled]]"
|
||||||
on-track="_onTrack"
|
on-change="_inputChange">
|
||||||
on-transitionend="_knobTransitionEnd">
|
</paper-input>
|
||||||
<paper-ripple id="ink" class="circle" center hidden$="[[!receivedFocusFromKeyboard]]"></paper-ripple>
|
</template>
|
||||||
<div id="sliderKnobInner" value$="[[immediateValue]]"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<template is="dom-if" if="[[editable]]">
|
|
||||||
<paper-input
|
|
||||||
id="input"
|
|
||||||
class="slider-input"
|
|
||||||
disabled$="[[disabled]]"
|
|
||||||
on-change="_inputChange">
|
|
||||||
</paper-input>
|
|
||||||
</template>
|
</template>
|
||||||
</template>
|
|
||||||
|
|
||||||
</dom-module>
|
</dom-module>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'paper-slider',
|
is: 'paper-slider',
|
||||||
|
|
||||||
behaviors: [
|
behaviors: [
|
||||||
Polymer.IronA11yKeysBehavior,
|
Polymer.IronA11yKeysBehavior,
|
||||||
Polymer.PaperInkyFocusBehavior,
|
Polymer.PaperInkyFocusBehavior,
|
||||||
Polymer.IronFormElementBehavior,
|
Polymer.IronFormElementBehavior,
|
||||||
Polymer.IronRangeBehavior
|
Polymer.IronRangeBehavior
|
||||||
],
|
],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, the slider thumb snaps to tick marks evenly spaced based
|
* If true, the slider thumb snaps to tick marks evenly spaced based
|
||||||
* on the `step` property value.
|
* on the `step` property value.
|
||||||
*/
|
*/
|
||||||
snaps: {
|
snaps: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
notify: true
|
notify: true
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, a pin with numeric value label is shown when the slider thumb
|
* If true, a pin with numeric value label is shown when the slider thumb
|
||||||
* is pressed. Use for settings for which users need to know the exact
|
* is pressed. Use for settings for which users need to know the exact
|
||||||
* value of the setting.
|
* value of the setting.
|
||||||
*/
|
*/
|
||||||
pin: {
|
pin: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
notify: true
|
notify: true
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number that represents the current secondary progress.
|
* The number that represents the current secondary progress.
|
||||||
*/
|
*/
|
||||||
secondaryProgress: {
|
secondaryProgress: {
|
||||||
type: Number,
|
type: Number,
|
||||||
value: 0,
|
value: 0,
|
||||||
notify: true,
|
notify: true,
|
||||||
observer: '_secondaryProgressChanged'
|
observer: '_secondaryProgressChanged'
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, an input is shown and user can use it to set the slider value.
|
* If true, an input is shown and user can use it to set the slider value.
|
||||||
*/
|
*/
|
||||||
editable: {
|
editable: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false
|
value: false
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The immediate value of the slider. This value is updated while the user
|
* The immediate value of the slider. This value is updated while the user
|
||||||
* is dragging the slider.
|
* is dragging the slider.
|
||||||
*/
|
*/
|
||||||
immediateValue: {
|
immediateValue: {
|
||||||
type: Number,
|
type: Number,
|
||||||
value: 0,
|
value: 0,
|
||||||
readOnly: true
|
readOnly: true
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum number of markers
|
* The maximum number of markers
|
||||||
*/
|
*/
|
||||||
maxMarkers: {
|
maxMarkers: {
|
||||||
type: Number,
|
type: Number,
|
||||||
value: 0,
|
value: 0,
|
||||||
notify: true,
|
notify: true,
|
||||||
observer: '_maxMarkersChanged'
|
observer: '_maxMarkersChanged'
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, the knob is expanded
|
* If true, the knob is expanded
|
||||||
*/
|
*/
|
||||||
expand: {
|
expand: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
readOnly: true
|
readOnly: true
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True when the user is dragging the slider.
|
* True when the user is dragging the slider.
|
||||||
*/
|
*/
|
||||||
dragging: {
|
dragging: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
readOnly: true
|
readOnly: true
|
||||||
},
|
},
|
||||||
|
|
||||||
transiting: {
|
transiting: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
readOnly: true
|
readOnly: true
|
||||||
},
|
},
|
||||||
|
|
||||||
markers: {
|
markers: {
|
||||||
type: Array,
|
type: Array,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
value: []
|
value: []
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
observers: [
|
observers: [
|
||||||
'_updateKnob(value, min, max, snaps, step)',
|
'_updateKnob(value, min, max, snaps, step)',
|
||||||
'_minChanged(min)',
|
'_minChanged(min)',
|
||||||
'_maxChanged(max)',
|
'_maxChanged(max)',
|
||||||
'_valueChanged(value)',
|
'_valueChanged(value)',
|
||||||
'_immediateValueChanged(immediateValue)'
|
'_immediateValueChanged(immediateValue)'
|
||||||
],
|
],
|
||||||
|
|
||||||
hostAttributes: {
|
hostAttributes: {
|
||||||
role: 'slider',
|
role: 'slider',
|
||||||
tabindex: 0
|
tabindex: 0
|
||||||
},
|
},
|
||||||
|
|
||||||
keyBindings: {
|
keyBindings: {
|
||||||
'left down pagedown home': '_decrementKey',
|
'left down pagedown home': '_decrementKey',
|
||||||
'right up pageup end': '_incrementKey'
|
'right up pageup end': '_incrementKey'
|
||||||
},
|
},
|
||||||
|
|
||||||
ready: function() {
|
ready: function () {
|
||||||
// issue polymer/polymer#1305
|
// issue polymer/polymer#1305
|
||||||
this.async(function() {
|
this.async(function () {
|
||||||
this._updateKnob(this.value);
|
this._updateKnob(this.value);
|
||||||
this._updateInputValue();
|
this._updateInputValue();
|
||||||
}, 1);
|
}, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increases value by `step` but not above `max`.
|
||||||
|
* @method increment
|
||||||
|
*/
|
||||||
|
increment: function () {
|
||||||
|
this.value = this._clampValue(this.value + this.step);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decreases value by `step` but not below `min`.
|
||||||
|
* @method decrement
|
||||||
|
*/
|
||||||
|
decrement: function () {
|
||||||
|
this.value = this._clampValue(this.value - this.step);
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateKnob: function (value) {
|
||||||
|
this._positionKnob(this._calcRatio(value));
|
||||||
|
},
|
||||||
|
|
||||||
|
_minChanged: function () {
|
||||||
|
this.setAttribute('aria-valuemin', this.min);
|
||||||
|
},
|
||||||
|
|
||||||
|
_maxChanged: function () {
|
||||||
|
this.setAttribute('aria-valuemax', this.max);
|
||||||
|
},
|
||||||
|
|
||||||
|
_valueChanged: function () {
|
||||||
|
this.setAttribute('aria-valuenow', this.value);
|
||||||
|
this.fire('value-change');
|
||||||
|
},
|
||||||
|
|
||||||
|
_immediateValueChanged: function () {
|
||||||
|
if (this.dragging) {
|
||||||
|
this.fire('immediate-value-change');
|
||||||
|
} else {
|
||||||
|
this.value = this.immediateValue;
|
||||||
|
}
|
||||||
|
this._updateInputValue();
|
||||||
|
},
|
||||||
|
|
||||||
|
_secondaryProgressChanged: function () {
|
||||||
|
this.secondaryProgress = this._clampValue(this.secondaryProgress);
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateInputValue: function () {
|
||||||
|
if (this.editable) {
|
||||||
|
this.$$('#input').value = this.immediateValue.toString();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_expandKnob: function () {
|
||||||
|
this._setExpand(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
_resetKnob: function () {
|
||||||
|
this.cancelDebouncer('expandKnob');
|
||||||
|
this._setExpand(false);
|
||||||
|
},
|
||||||
|
|
||||||
|
_positionKnob: function (ratio) {
|
||||||
|
this._setImmediateValue(this._calcStep(this._calcKnobPosition(ratio)));
|
||||||
|
this._setPinValue(this.immediateValue);
|
||||||
|
|
||||||
|
this._setRatio(this._calcRatio(this.immediateValue));
|
||||||
|
|
||||||
|
this.$.sliderKnob.style.left = (this.ratio * 100) + '%';
|
||||||
|
},
|
||||||
|
|
||||||
|
_inputChange: function () {
|
||||||
|
this.value = this.$$('#input').value;
|
||||||
|
this.fire('change');
|
||||||
|
},
|
||||||
|
|
||||||
|
_calcKnobPosition: function (ratio) {
|
||||||
|
return (this.max - this.min) * ratio + this.min;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onTrack: function (event) {
|
||||||
|
switch (event.detail.state) {
|
||||||
|
case 'start':
|
||||||
|
this._trackStart(event);
|
||||||
|
break;
|
||||||
|
case 'track':
|
||||||
|
this._trackX(event);
|
||||||
|
break;
|
||||||
|
case 'end':
|
||||||
|
this._trackEnd();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_trackStart: function (event) {
|
||||||
|
this._w = this.$.sliderBar.offsetWidth;
|
||||||
|
this._x = this.ratio * this._w;
|
||||||
|
this._startx = this._x || 0;
|
||||||
|
this._minx = -this._startx;
|
||||||
|
this._maxx = this._w - this._startx;
|
||||||
|
this.$.sliderKnob.classList.add('dragging');
|
||||||
|
|
||||||
|
this._setDragging(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
_trackX: function (e) {
|
||||||
|
if (!this.dragging) {
|
||||||
|
this._trackStart(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dx = Math.min(this._maxx, Math.max(this._minx, e.detail.dx));
|
||||||
|
this._x = this._startx + dx;
|
||||||
|
|
||||||
|
var immediateValue = this._calcStep(this._calcKnobPosition(this._x / this._w));
|
||||||
|
this._setImmediateValue(immediateValue);
|
||||||
|
this._setPinValue(immediateValue);
|
||||||
|
|
||||||
|
// update knob's position
|
||||||
|
var translateX = ((this._calcRatio(immediateValue) * this._w) - this._startx);
|
||||||
|
this.translate3d(translateX + 'px', 0, 0, this.$.sliderKnob);
|
||||||
|
},
|
||||||
|
|
||||||
|
_trackEnd: function () {
|
||||||
|
var s = this.$.sliderKnob.style;
|
||||||
|
|
||||||
|
this.$.sliderKnob.classList.remove('dragging');
|
||||||
|
this._setDragging(false);
|
||||||
|
this._resetKnob();
|
||||||
|
this.value = this.immediateValue;
|
||||||
|
|
||||||
|
s.transform = s.webkitTransform = '';
|
||||||
|
|
||||||
|
this.fire('change');
|
||||||
|
},
|
||||||
|
|
||||||
|
_knobdown: function (event) {
|
||||||
|
this._expandKnob();
|
||||||
|
|
||||||
|
// cancel selection
|
||||||
|
event.detail.sourceEvent.preventDefault();
|
||||||
|
|
||||||
|
// set the focus manually because we will called prevent default
|
||||||
|
this.focus();
|
||||||
|
},
|
||||||
|
|
||||||
|
_bardown: function (event) {
|
||||||
|
this._w = this.$.sliderBar.offsetWidth;
|
||||||
|
var rect = this.$.sliderBar.getBoundingClientRect();
|
||||||
|
var ratio = (event.detail.x - rect.left) / this._w;
|
||||||
|
var prevRatio = this.ratio;
|
||||||
|
|
||||||
|
this._setTransiting(true);
|
||||||
|
|
||||||
|
this._positionKnob(ratio);
|
||||||
|
|
||||||
|
this.debounce('expandKnob', this._expandKnob, 60);
|
||||||
|
|
||||||
|
// if the ratio doesn't change, sliderKnob's animation won't start
|
||||||
|
// and `_knobTransitionEnd` won't be called
|
||||||
|
// Therefore, we need to manually update the `transiting` state
|
||||||
|
|
||||||
|
if (prevRatio === this.ratio) {
|
||||||
|
this._setTransiting(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.async(function () {
|
||||||
|
this.fire('change');
|
||||||
|
});
|
||||||
|
|
||||||
|
// cancel selection
|
||||||
|
event.detail.sourceEvent.preventDefault();
|
||||||
|
},
|
||||||
|
|
||||||
|
_knobTransitionEnd: function (event) {
|
||||||
|
if (event.target === this.$.sliderKnob) {
|
||||||
|
this._setTransiting(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_maxMarkersChanged: function (maxMarkers) {
|
||||||
|
var l = (this.max - this.min) / this.step;
|
||||||
|
if (!this.snaps && l > maxMarkers) {
|
||||||
|
this._setMarkers([]);
|
||||||
|
} else {
|
||||||
|
this._setMarkers(new Array(l));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_getClassNames: function () {
|
||||||
|
var classes = {};
|
||||||
|
|
||||||
|
classes.disabled = this.disabled;
|
||||||
|
classes.pin = this.pin;
|
||||||
|
classes.snaps = this.snaps;
|
||||||
|
classes.ring = this.immediateValue <= this.min;
|
||||||
|
classes.expand = this.expand;
|
||||||
|
classes.dragging = this.dragging;
|
||||||
|
classes.transiting = this.transiting;
|
||||||
|
classes.editable = this.editable;
|
||||||
|
|
||||||
|
return Object.keys(classes).filter(
|
||||||
|
function (className) {
|
||||||
|
return classes[className];
|
||||||
|
}).join(' ');
|
||||||
|
},
|
||||||
|
|
||||||
|
_incrementKey: function (event) {
|
||||||
|
if (event.detail.key === 'end') {
|
||||||
|
this.value = this.max;
|
||||||
|
} else {
|
||||||
|
this.increment();
|
||||||
|
}
|
||||||
|
this.fire('change');
|
||||||
|
},
|
||||||
|
|
||||||
|
_decrementKey: function (event) {
|
||||||
|
if (event.detail.key === 'home') {
|
||||||
|
this.value = this.min;
|
||||||
|
} else {
|
||||||
|
this.decrement();
|
||||||
|
}
|
||||||
|
this.fire('change');
|
||||||
|
},
|
||||||
|
|
||||||
|
_setPinValue: function (value) {
|
||||||
|
this.pinValue = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increases value by `step` but not above `max`.
|
* Fired when the slider's value changes.
|
||||||
* @method increment
|
*
|
||||||
|
* @event value-change
|
||||||
*/
|
*/
|
||||||
increment: function() {
|
|
||||||
this.value = this._clampValue(this.value + this.step);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decreases value by `step` but not below `min`.
|
* Fired when the slider's immediateValue changes.
|
||||||
* @method decrement
|
*
|
||||||
|
* @event immediate-value-change
|
||||||
*/
|
*/
|
||||||
decrement: function() {
|
|
||||||
this.value = this._clampValue(this.value - this.step);
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateKnob: function(value) {
|
/**
|
||||||
this._positionKnob(this._calcRatio(value));
|
* Fired when the slider's value changes due to user interaction.
|
||||||
},
|
*
|
||||||
|
* Changes to the slider's value due to changes in an underlying
|
||||||
_minChanged: function() {
|
* bound variable will not trigger this event.
|
||||||
this.setAttribute('aria-valuemin', this.min);
|
*
|
||||||
},
|
* @event change
|
||||||
|
*/
|
||||||
_maxChanged: function() {
|
|
||||||
this.setAttribute('aria-valuemax', this.max);
|
|
||||||
},
|
|
||||||
|
|
||||||
_valueChanged: function() {
|
|
||||||
this.setAttribute('aria-valuenow', this.value);
|
|
||||||
this.fire('value-change');
|
|
||||||
},
|
|
||||||
|
|
||||||
_immediateValueChanged: function() {
|
|
||||||
if (this.dragging) {
|
|
||||||
this.fire('immediate-value-change');
|
|
||||||
} else {
|
|
||||||
this.value = this.immediateValue;
|
|
||||||
}
|
|
||||||
this._updateInputValue();
|
|
||||||
},
|
|
||||||
|
|
||||||
_secondaryProgressChanged: function() {
|
|
||||||
this.secondaryProgress = this._clampValue(this.secondaryProgress);
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateInputValue: function() {
|
|
||||||
if (this.editable) {
|
|
||||||
this.$$('#input').value = this.immediateValue.toString();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_expandKnob: function() {
|
|
||||||
this._setExpand(true);
|
|
||||||
},
|
|
||||||
|
|
||||||
_resetKnob: function() {
|
|
||||||
this.cancelDebouncer('expandKnob');
|
|
||||||
this._setExpand(false);
|
|
||||||
},
|
|
||||||
|
|
||||||
_positionKnob: function(ratio) {
|
|
||||||
this._setImmediateValue(this._calcStep(this._calcKnobPosition(ratio)));
|
|
||||||
this._setRatio(this._calcRatio(this.immediateValue));
|
|
||||||
|
|
||||||
this.$.sliderKnob.style.left = (this.ratio * 100) + '%';
|
|
||||||
},
|
|
||||||
|
|
||||||
_inputChange: function() {
|
|
||||||
this.value = this.$$('#input').value;
|
|
||||||
this.fire('change');
|
|
||||||
},
|
|
||||||
|
|
||||||
_calcKnobPosition: function(ratio) {
|
|
||||||
return (this.max - this.min) * ratio + this.min;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onTrack: function(event) {
|
|
||||||
switch (event.detail.state) {
|
|
||||||
case 'start':
|
|
||||||
this._trackStart(event);
|
|
||||||
break;
|
|
||||||
case 'track':
|
|
||||||
this._trackX(event);
|
|
||||||
break;
|
|
||||||
case 'end':
|
|
||||||
this._trackEnd();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_trackStart: function(event) {
|
|
||||||
this._w = this.$.sliderBar.offsetWidth;
|
|
||||||
this._x = this.ratio * this._w;
|
|
||||||
this._startx = this._x || 0;
|
|
||||||
this._minx = - this._startx;
|
|
||||||
this._maxx = this._w - this._startx;
|
|
||||||
this.$.sliderKnob.classList.add('dragging');
|
|
||||||
|
|
||||||
this._setDragging(true);
|
|
||||||
},
|
|
||||||
|
|
||||||
_trackX: function(e) {
|
|
||||||
if (!this.dragging) {
|
|
||||||
this._trackStart(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
var dx = Math.min(this._maxx, Math.max(this._minx, e.detail.dx));
|
|
||||||
this._x = this._startx + dx;
|
|
||||||
|
|
||||||
var immediateValue = this._calcStep(this._calcKnobPosition(this._x / this._w));
|
|
||||||
this._setImmediateValue(immediateValue);
|
|
||||||
|
|
||||||
// update knob's position
|
|
||||||
var translateX = ((this._calcRatio(immediateValue) * this._w) - this._startx);
|
|
||||||
this.translate3d(translateX + 'px', 0, 0, this.$.sliderKnob);
|
|
||||||
},
|
|
||||||
|
|
||||||
_trackEnd: function() {
|
|
||||||
var s = this.$.sliderKnob.style;
|
|
||||||
|
|
||||||
this.$.sliderKnob.classList.remove('dragging');
|
|
||||||
this._setDragging(false);
|
|
||||||
this._resetKnob();
|
|
||||||
this.value = this.immediateValue;
|
|
||||||
|
|
||||||
s.transform = s.webkitTransform = '';
|
|
||||||
|
|
||||||
this.fire('change');
|
|
||||||
},
|
|
||||||
|
|
||||||
_knobdown: function(event) {
|
|
||||||
this._expandKnob();
|
|
||||||
|
|
||||||
// cancel selection
|
|
||||||
event.detail.sourceEvent.preventDefault();
|
|
||||||
|
|
||||||
// set the focus manually because we will called prevent default
|
|
||||||
this.focus();
|
|
||||||
},
|
|
||||||
|
|
||||||
_bardown: function(event) {
|
|
||||||
this._w = this.$.sliderBar.offsetWidth;
|
|
||||||
var rect = this.$.sliderBar.getBoundingClientRect();
|
|
||||||
var ratio = (event.detail.x - rect.left) / this._w;
|
|
||||||
var prevRatio = this.ratio;
|
|
||||||
|
|
||||||
this._setTransiting(true);
|
|
||||||
|
|
||||||
this._positionKnob(ratio);
|
|
||||||
|
|
||||||
this.debounce('expandKnob', this._expandKnob, 60);
|
|
||||||
|
|
||||||
// if the ratio doesn't change, sliderKnob's animation won't start
|
|
||||||
// and `_knobTransitionEnd` won't be called
|
|
||||||
// Therefore, we need to manually update the `transiting` state
|
|
||||||
|
|
||||||
if (prevRatio === this.ratio) {
|
|
||||||
this._setTransiting(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.async(function() {
|
|
||||||
this.fire('change');
|
|
||||||
});
|
|
||||||
|
|
||||||
// cancel selection
|
|
||||||
event.detail.sourceEvent.preventDefault();
|
|
||||||
},
|
|
||||||
|
|
||||||
_knobTransitionEnd: function(event) {
|
|
||||||
if (event.target === this.$.sliderKnob) {
|
|
||||||
this._setTransiting(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_maxMarkersChanged: function(maxMarkers) {
|
|
||||||
var l = (this.max - this.min) / this.step;
|
|
||||||
if (!this.snaps && l > maxMarkers) {
|
|
||||||
this._setMarkers([]);
|
|
||||||
} else {
|
|
||||||
this._setMarkers(new Array(l));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_getClassNames: function() {
|
|
||||||
var classes = {};
|
|
||||||
|
|
||||||
classes.disabled = this.disabled;
|
|
||||||
classes.pin = this.pin;
|
|
||||||
classes.snaps = this.snaps;
|
|
||||||
classes.ring = this.immediateValue <= this.min;
|
|
||||||
classes.expand = this.expand;
|
|
||||||
classes.dragging = this.dragging;
|
|
||||||
classes.transiting = this.transiting;
|
|
||||||
classes.editable = this.editable;
|
|
||||||
|
|
||||||
return Object.keys(classes).filter(
|
|
||||||
function(className) {
|
|
||||||
return classes[className];
|
|
||||||
}).join(' ');
|
|
||||||
},
|
|
||||||
|
|
||||||
_incrementKey: function(event) {
|
|
||||||
if (event.detail.key === 'end') {
|
|
||||||
this.value = this.max;
|
|
||||||
} else {
|
|
||||||
this.increment();
|
|
||||||
}
|
|
||||||
this.fire('change');
|
|
||||||
},
|
|
||||||
|
|
||||||
_decrementKey: function(event) {
|
|
||||||
if (event.detail.key === 'home') {
|
|
||||||
this.value = this.min;
|
|
||||||
} else {
|
|
||||||
this.decrement();
|
|
||||||
}
|
|
||||||
this.fire('change');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when the slider's value changes.
|
|
||||||
*
|
|
||||||
* @event value-change
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when the slider's immediateValue changes.
|
|
||||||
*
|
|
||||||
* @event immediate-value-change
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when the slider's value changes due to user interaction.
|
|
||||||
*
|
|
||||||
* Changes to the slider's value due to changes in an underlying
|
|
||||||
* bound variable will not trigger this event.
|
|
||||||
*
|
|
||||||
* @event change
|
|
||||||
*/
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -59,19 +59,13 @@
|
||||||
.videoAdvancedControls {
|
.videoAdvancedControls {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
padding-top: .5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#slider-tooltip {
|
.videoAdvancedControls iron-icon {
|
||||||
z-index: 99999;
|
width: 32px;
|
||||||
position: absolute;
|
height: 32px;
|
||||||
top: -30px;
|
}
|
||||||
left: 0;
|
|
||||||
background-color: #eee;
|
|
||||||
border: 1px solid #333;
|
|
||||||
color: #333;
|
|
||||||
border-radius: 3px;
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nowPlayingInfo {
|
.nowPlayingInfo {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -158,7 +152,7 @@
|
||||||
.videoTopControlsLogo {
|
.videoTopControlsLogo {
|
||||||
float: left;
|
float: left;
|
||||||
/* Matches .mediaButton */
|
/* Matches .mediaButton */
|
||||||
padding-top: 16px;
|
padding: 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.videoTopControlsLogo img {
|
.videoTopControlsLogo img {
|
||||||
|
@ -184,29 +178,18 @@
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hack for safari because it doesn't allow clickable content over the video surface. */
|
/* Hack for safari because it doesn't allow clickable content over the video surface. */
|
||||||
/*.itemVideo { (;top: 9%!important;height: 91% !important;); }
|
/*.itemVideo { (;top: 9%!important;height: 91% !important;); }
|
||||||
.itemVideo { [;top: 9%!important;height: 91% !important;]; }*/
|
.itemVideo { [;top: 9%!important;height: 91% !important;]; }*/
|
||||||
|
|
||||||
#mediaPlayer .ui-slider-track, .nowPlayingBar .ui-slider-track, .nowPlayingPage .ui-slider-track {
|
#videoPlayer .inactive {
|
||||||
border-color: #2ad !important;
|
display: none !important;
|
||||||
height: 2px !important;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#videoPlayer .inactive {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.idlePlayer video {
|
.idlePlayer video {
|
||||||
cursor: none;
|
cursor: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mediaPlayer .sliderContainer {
|
|
||||||
position: relative;
|
|
||||||
top: 5px;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************/
|
/****************************************/
|
||||||
|
|
||||||
@media all and (max-width: 1200px), all and (max-height: 720px) {
|
@media all and (max-width: 1200px), all and (max-height: 720px) {
|
||||||
|
@ -216,13 +199,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 800px), all and (max-height: 460px) {
|
|
||||||
|
|
||||||
#mediaPlayer .sliderContainer {
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 1400px), all and (max-height: 800px) {
|
@media all and (max-width: 1400px), all and (max-height: 800px) {
|
||||||
|
|
||||||
#mediaPlayer .nowPlayingInfo {
|
#mediaPlayer .nowPlayingInfo {
|
||||||
|
@ -240,12 +216,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (min-width: 800px) {
|
|
||||||
.videoControls .positionSliderContainer {
|
|
||||||
width: 300px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (min-width: 1300px) {
|
@media all and (min-width: 1300px) {
|
||||||
.nowPlayingInfo {
|
.nowPlayingInfo {
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
|
|
|
@ -1,47 +1,4 @@
|
||||||
/* Now playing bar */
|
#mediaElement {
|
||||||
.nowPlayingBar {
|
|
||||||
padding: 8px 0;
|
|
||||||
border-top: 1px solid #444;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaButton {
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaButton, .nowPlayingBarUserDataButtons .btnUserItemRating {
|
|
||||||
vertical-align: middle;
|
|
||||||
color: #e8e8e8;
|
|
||||||
margin: 0;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaButton:not(paper-icon-button) {
|
|
||||||
padding: 16px 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
paper-icon-button.mediaButton {
|
|
||||||
padding: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaButton iron-icon {
|
|
||||||
height: 48px;
|
|
||||||
width: 48px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaButton.remoteControlButton iron-icon {
|
|
||||||
height: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.videoTopControls .mediaButton {
|
|
||||||
font-size: 27px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.videoControls .mediaButton {
|
|
||||||
padding: 0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#mediaElement {
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
@ -79,21 +36,6 @@ paper-icon-button.mediaButton {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.nowPlayingDoubleText {
|
|
||||||
top: -3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nowPlayingImage {
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nowPlayingImage img {
|
|
||||||
height: 60px;
|
|
||||||
margin-right: .5em;
|
|
||||||
vertical-align: bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaButton img {
|
.mediaButton img {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
}
|
}
|
||||||
|
@ -106,83 +48,10 @@ paper-icon-button.mediaButton {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mediaSlider {
|
|
||||||
position: relative;
|
|
||||||
top: -10px;
|
|
||||||
width: 50px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sliderContainer {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.positionSliderContainer {
|
|
||||||
width: 130px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nowPlayingBar .sliderContainer {
|
|
||||||
margin-top: 10px;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.volumeSliderContainer {
|
|
||||||
width: 90px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sliderContainer .ui-slider {
|
|
||||||
margin: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sliderContainer .ui-slider-track {
|
|
||||||
margin: 0 15px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.volumeSliderContainer .ui-slider-track {
|
|
||||||
margin-left: 5px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.volumeButton {
|
.volumeButton {
|
||||||
margin-right: .5em !important;
|
margin-right: .5em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 800px) {
|
|
||||||
|
|
||||||
.nowPlayingBar .mediaButton {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nowPlayingBar .mediaButton:not(.unpauseButton):not(.pauseButton):not(.remoteControlButton) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.remoteControlButton, .nowPlayingBar .unpauseButton, .nowPlayingBar .pauseButton {
|
|
||||||
float: right;
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.remoteControlButton {
|
|
||||||
position: relative;
|
|
||||||
top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nowPlayingBar .currentTime, .nowPlayingBar .positionSliderContainer, .nowPlayingBar .volumeSliderContainer, #nowPlayingBar .muteButton, #nowPlayingBar .unmuteButton {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nowPlayingBar {
|
|
||||||
padding: 10px 5px 10px 10px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1440px) {
|
|
||||||
#nowPlayingBar .positionSliderContainer {
|
|
||||||
width: 300px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaPlayerAudioContainer {
|
.mediaPlayerAudioContainer {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 40%;
|
top: 40%;
|
||||||
|
@ -195,15 +64,3 @@ paper-icon-button.mediaButton {
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
background: #222;
|
background: #222;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nowPlayingBarUserDataButtons {
|
|
||||||
display: inline-block;
|
|
||||||
margin-left: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 1200px) {
|
|
||||||
|
|
||||||
.nowPlayingBarUserDataButtons {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -172,7 +172,4 @@
|
||||||
.nowPlayingSelectedPlayer {
|
.nowPlayingSelectedPlayer {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.nowPlayingPositionSlider .pin > #sliderKnob > #sliderKnobInner::after {
|
|
||||||
}
|
|
230
dashboard-ui/css/nowplayingbar.css
Normal file
230
dashboard-ui/css/nowplayingbar.css
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
/* Now playing bar */
|
||||||
|
.nowPlayingBar {
|
||||||
|
border-top: 1px solid #444;
|
||||||
|
text-align: center;
|
||||||
|
/*box-shadow: 0 0 8px rgba(255,255,255,.4);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaButton, .nowPlayingBarUserDataButtons .btnUserItemRating {
|
||||||
|
vertical-align: middle;
|
||||||
|
color: #e8e8e8;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBar paper-icon-button.mediaButton {
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaButton iron-icon {
|
||||||
|
height: 40px;
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaButton.remoteControlButton iron-icon, .mediaButton.muteButton iron-icon, .mediaButton.unmuteButton iron-icon {
|
||||||
|
height: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingDoubleText {
|
||||||
|
top: -3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarInfoContainer {
|
||||||
|
vertical-align: middle;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingImage {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingImage img {
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBar, .nowPlayingImage img {
|
||||||
|
height: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarText {
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: normal;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
vertical-align: middle;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 14px;
|
||||||
|
max-width: 130px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 500px) {
|
||||||
|
.nowPlayingBarText {
|
||||||
|
max-width: 180px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 600px) {
|
||||||
|
.nowPlayingBarText {
|
||||||
|
max-width: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 700px) {
|
||||||
|
.nowPlayingBarText {
|
||||||
|
max-width: 240px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 800px) {
|
||||||
|
.nowPlayingBarText {
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 800px) {
|
||||||
|
.nowPlayingBarText {
|
||||||
|
margin-right: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarCenter {
|
||||||
|
vertical-align: middle;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarPositionContainer {
|
||||||
|
position: absolute;
|
||||||
|
left: 90px;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarPositionSlider paper-progress {
|
||||||
|
height: 4px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarPositionSlider #sliderBar {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarPositionSlider #sliderContainer {
|
||||||
|
width: 100%;
|
||||||
|
margin-left: -15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarPositionSlider #sliderKnob {
|
||||||
|
top: -14px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarPositionSlider #progressContainer {
|
||||||
|
background-color: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarPositionSlider #sliderKnobInner {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarRight {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 22px;
|
||||||
|
right: 10px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaButton img {
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarCurrentTime {
|
||||||
|
vertical-align: middle;
|
||||||
|
font-weight: normal;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 38px;
|
||||||
|
text-align: center;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding-left: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarVolumeSlider {
|
||||||
|
margin-left: -1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarUserDataButtons {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 2em;
|
||||||
|
margin-right: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media all and (max-width: 1200px) {
|
||||||
|
|
||||||
|
.nowPlayingBarUserDataButtons {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 1000px) {
|
||||||
|
|
||||||
|
.nowPlayingBarVolumeSlider, .nowPlayingBar .muteButton, .nowPlayingBar .unmuteButton {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBar .playlistButton {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarRight {
|
||||||
|
bottom: 26px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 800px) {
|
||||||
|
|
||||||
|
.nowPlayingBarCurrentTime {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarCenter > *:not(.nowPlayingBarCurrentTime) {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarRight {
|
||||||
|
bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBar, .nowPlayingImage img {
|
||||||
|
height: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarPositionContainer {
|
||||||
|
left: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarPositionSlider paper-progress {
|
||||||
|
height: 3px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarPositionSlider #sliderKnob {
|
||||||
|
top: -15px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 800px) {
|
||||||
|
|
||||||
|
.nowPlayingBarRight .pauseButton {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingBarRight .unpauseButton {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
|
@ -915,7 +915,7 @@ h1 .imageLink {
|
||||||
z-index: 1097;
|
z-index: 1097;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border: 0 !important;
|
border: 0 !important;
|
||||||
background-color: rgba(26,26,26,.9);
|
background-color: rgba(26,26,26,.93);
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerOverBottomTabs {
|
.footerOverBottomTabs {
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
(function () {
|
(function () {
|
||||||
|
|
||||||
function onClosed() {
|
|
||||||
$(this).remove();
|
|
||||||
$(document.body).removeClass('bodyWithPopupOpen');
|
|
||||||
}
|
|
||||||
function show(options) {
|
function show(options) {
|
||||||
|
|
||||||
require(['paperbuttonstyle'], function () {
|
require(['paperbuttonstyle'], function () {
|
||||||
|
@ -65,6 +61,11 @@
|
||||||
html += '<paper-dialog-scrollable>';
|
html += '<paper-dialog-scrollable>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If any items have an icon, give them all an icon just to make sure they're all lined up evenly
|
||||||
|
var renderIcon = options.items.filter(function (o) {
|
||||||
|
return o.ironIcon;
|
||||||
|
}).length;
|
||||||
|
|
||||||
for (var i = 0, length = options.items.length; i < length; i++) {
|
for (var i = 0, length = options.items.length; i < length; i++) {
|
||||||
|
|
||||||
var option = options.items[i];
|
var option = options.items[i];
|
||||||
|
@ -74,6 +75,9 @@
|
||||||
if (option.ironIcon) {
|
if (option.ironIcon) {
|
||||||
html += '<iron-icon icon="' + option.ironIcon + '"></iron-icon>';
|
html += '<iron-icon icon="' + option.ironIcon + '"></iron-icon>';
|
||||||
}
|
}
|
||||||
|
else if (renderIcon) {
|
||||||
|
html += '<iron-icon></iron-icon>';
|
||||||
|
}
|
||||||
html += '<span>' + option.name + '</span>';
|
html += '<span>' + option.name + '</span>';
|
||||||
html += '</paper-button>';
|
html += '</paper-button>';
|
||||||
}
|
}
|
||||||
|
@ -98,7 +102,9 @@
|
||||||
dlg.open();
|
dlg.open();
|
||||||
|
|
||||||
// Has to be assigned a z-index after the call to .open()
|
// Has to be assigned a z-index after the call to .open()
|
||||||
$(dlg).on('iron-overlay-closed', onClosed);
|
$(dlg).on('iron-overlay-closed', function () {
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
|
||||||
$('.btnOption', dlg).on('click', function () {
|
$('.btnOption', dlg).on('click', function () {
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
var unmuteButton = null;
|
var unmuteButton = null;
|
||||||
var volumeSlider = null;
|
var volumeSlider = null;
|
||||||
var positionSlider;
|
var positionSlider;
|
||||||
var isPositionSliderActive;
|
|
||||||
var currentTimeElement;
|
var currentTimeElement;
|
||||||
|
|
||||||
self.currentSubtitleStreamIndex = null;
|
self.currentSubtitleStreamIndex = null;
|
||||||
|
@ -59,20 +58,14 @@
|
||||||
return document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement ? true : false;
|
return document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement ? true : false;
|
||||||
};
|
};
|
||||||
|
|
||||||
function onFlyoutClose() {
|
|
||||||
$('.itemVideo').css('visibility', 'visible');
|
|
||||||
}
|
|
||||||
|
|
||||||
function onPopupOpen(elem) {
|
|
||||||
elem.popup("open").parents(".ui-popup-container").css("margin-top", 30);
|
|
||||||
|
|
||||||
if ($.browser.safari) {
|
|
||||||
//$('.itemVideo').css('visibility', 'hidden');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.showChaptersFlyout = function () {
|
self.showChaptersFlyout = function () {
|
||||||
|
|
||||||
|
function onFlyoutClose() {
|
||||||
|
$('.itemVideo').css('visibility', 'visible');
|
||||||
|
}
|
||||||
|
|
||||||
|
require(['jqmicons']);
|
||||||
|
|
||||||
var html = getChaptersFlyoutHtml();
|
var html = getChaptersFlyoutHtml();
|
||||||
|
|
||||||
var elem = $('.videoChaptersPopup').html(html)
|
var elem = $('.videoChaptersPopup').html(html)
|
||||||
|
@ -81,46 +74,187 @@
|
||||||
.off('popupafterclose', onFlyoutClose)
|
.off('popupafterclose', onFlyoutClose)
|
||||||
.on('popupafterclose', onFlyoutClose);
|
.on('popupafterclose', onFlyoutClose);
|
||||||
|
|
||||||
onPopupOpen(elem);
|
elem.popup("open").parents(".ui-popup-container").css("margin-top", 30);
|
||||||
};
|
};
|
||||||
|
|
||||||
self.showSubtitleMenu = function () {
|
self.showSubtitleMenu = function () {
|
||||||
|
|
||||||
var html = getSubtitleTracksHtml();
|
var streams = self.currentMediaSource.MediaStreams.filter(function (currentStream) {
|
||||||
|
return currentStream.Type == "Subtitle";
|
||||||
|
});
|
||||||
|
|
||||||
var elem = $('.videoSubtitlePopup').html(html)
|
var currentIndex = self.currentSubtitleStreamIndex || -1;
|
||||||
.trigger('create')
|
|
||||||
.popup("option", "positionTo", $('.videoSubtitleButton'))
|
|
||||||
.off('popupafterclose', onFlyoutClose)
|
|
||||||
.on('popupafterclose', onFlyoutClose);
|
|
||||||
|
|
||||||
onPopupOpen(elem);
|
streams.unshift({
|
||||||
|
Index: -1,
|
||||||
|
Language: "Off"
|
||||||
|
});
|
||||||
|
|
||||||
|
var menuItems = streams.map(function (stream) {
|
||||||
|
|
||||||
|
var attributes = [];
|
||||||
|
|
||||||
|
attributes.push(stream.Language || Globalize.translate('LabelUnknownLanguage'));
|
||||||
|
|
||||||
|
if (stream.Codec) {
|
||||||
|
attributes.push(stream.Codec);
|
||||||
|
}
|
||||||
|
|
||||||
|
var name = attributes.join(' - ');
|
||||||
|
|
||||||
|
if (stream.IsDefault) {
|
||||||
|
name += ' (D)';
|
||||||
|
}
|
||||||
|
if (stream.IsForced) {
|
||||||
|
name += ' (F)';
|
||||||
|
}
|
||||||
|
if (stream.External) {
|
||||||
|
name += ' (EXT)';
|
||||||
|
}
|
||||||
|
|
||||||
|
var opt = {
|
||||||
|
name: name,
|
||||||
|
id: stream.Index
|
||||||
|
};
|
||||||
|
|
||||||
|
if (stream.Index == currentIndex) {
|
||||||
|
opt.ironIcon = "check";
|
||||||
|
}
|
||||||
|
|
||||||
|
return opt;
|
||||||
|
});
|
||||||
|
|
||||||
|
require(['actionsheet'], function () {
|
||||||
|
|
||||||
|
ActionSheetElement.show({
|
||||||
|
items: menuItems,
|
||||||
|
positionTo: $('.videoSubtitleButton')[0],
|
||||||
|
callback: function (id) {
|
||||||
|
|
||||||
|
var index = parseInt(id);
|
||||||
|
if (index != currentIndex) {
|
||||||
|
self.onSubtitleOptionSelected(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
self.showQualityFlyout = function () {
|
self.showQualityFlyout = function () {
|
||||||
|
|
||||||
var html = getQualityFlyoutHtml();
|
var currentSrc = self.getCurrentSrc(self.currentMediaRenderer).toLowerCase();
|
||||||
|
var isStatic = currentSrc.indexOf('static=true') != -1;
|
||||||
|
|
||||||
var elem = $('.videoQualityPopup').html(html)
|
var videoStream = self.currentMediaSource.MediaStreams.filter(function (stream) {
|
||||||
.trigger('create')
|
return stream.Type == "Video";
|
||||||
.popup("option", "positionTo", $('.videoQualityButton'))
|
})[0];
|
||||||
.off('popupafterclose', onFlyoutClose)
|
var videoWidth = videoStream ? videoStream.Width : null;
|
||||||
.on('popupafterclose', onFlyoutClose);
|
var videoHeight = videoStream ? videoStream.Height : null;
|
||||||
|
|
||||||
onPopupOpen(elem);
|
var options = self.getVideoQualityOptions(videoWidth, videoHeight);
|
||||||
|
|
||||||
|
if (isStatic) {
|
||||||
|
options[0].name = "Direct";
|
||||||
|
}
|
||||||
|
|
||||||
|
var menuItems = options.map(function (o) {
|
||||||
|
|
||||||
|
var opt = {
|
||||||
|
name: o.name,
|
||||||
|
id: o.bitrate
|
||||||
|
};
|
||||||
|
|
||||||
|
if (o.selected) {
|
||||||
|
opt.ironIcon = "check";
|
||||||
|
}
|
||||||
|
|
||||||
|
return opt;
|
||||||
|
});
|
||||||
|
|
||||||
|
var selectedId = options.filter(function (o) {
|
||||||
|
return o.selected;
|
||||||
|
});
|
||||||
|
selectedId = selectedId.length ? selectedId[0].bitrate : null;
|
||||||
|
require(['actionsheet'], function () {
|
||||||
|
|
||||||
|
ActionSheetElement.show({
|
||||||
|
items: menuItems,
|
||||||
|
positionTo: $('.videoQualityButton')[0],
|
||||||
|
callback: function (id) {
|
||||||
|
|
||||||
|
var bitrate = parseInt(id);
|
||||||
|
if (bitrate != selectedId) {
|
||||||
|
self.onQualityOptionSelected(bitrate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
self.showAudioTracksFlyout = function () {
|
self.showAudioTracksFlyout = function () {
|
||||||
|
|
||||||
var html = getAudioTracksHtml();
|
var options = self.currentMediaSource.MediaStreams.filter(function (currentStream) {
|
||||||
|
return currentStream.Type == "Audio";
|
||||||
|
});
|
||||||
|
|
||||||
var elem = $('.videoAudioPopup').html(html)
|
var currentIndex = getParameterByName('AudioStreamIndex', self.getCurrentSrc(self.currentMediaRenderer));
|
||||||
.trigger('create')
|
|
||||||
.popup("option", "positionTo", $('.videoAudioButton'))
|
|
||||||
.off('popupafterclose', onFlyoutClose)
|
|
||||||
.on('popupafterclose', onFlyoutClose);
|
|
||||||
|
|
||||||
onPopupOpen(elem);
|
var menuItems = options.map(function (stream) {
|
||||||
|
|
||||||
|
var attributes = [];
|
||||||
|
|
||||||
|
attributes.push(stream.Language || Globalize.translate('LabelUnknownLanguage'));
|
||||||
|
|
||||||
|
if (stream.Codec) {
|
||||||
|
attributes.push(stream.Codec);
|
||||||
|
}
|
||||||
|
if (stream.Profile) {
|
||||||
|
attributes.push(stream.Profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream.BitRate) {
|
||||||
|
attributes.push((Math.floor(stream.BitRate / 1000)) + ' kbps');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream.Channels) {
|
||||||
|
attributes.push(stream.Channels + ' ch');
|
||||||
|
}
|
||||||
|
|
||||||
|
var name = attributes.join(' - ');
|
||||||
|
|
||||||
|
if (stream.IsDefault) {
|
||||||
|
name += ' (D)';
|
||||||
|
}
|
||||||
|
|
||||||
|
var opt = {
|
||||||
|
name: name,
|
||||||
|
id: stream.Index
|
||||||
|
};
|
||||||
|
|
||||||
|
if (stream.Index == currentIndex) {
|
||||||
|
opt.ironIcon = "check";
|
||||||
|
}
|
||||||
|
|
||||||
|
return opt;
|
||||||
|
});
|
||||||
|
|
||||||
|
require(['actionsheet'], function () {
|
||||||
|
|
||||||
|
ActionSheetElement.show({
|
||||||
|
items: menuItems,
|
||||||
|
positionTo: $('.videoAudioButton')[0],
|
||||||
|
callback: function (id) {
|
||||||
|
|
||||||
|
var index = parseInt(id);
|
||||||
|
if (index != currentIndex) {
|
||||||
|
self.onAudioOptionSelected(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
self.setAudioStreamIndex = function (index) {
|
self.setAudioStreamIndex = function (index) {
|
||||||
|
@ -438,8 +572,6 @@
|
||||||
|
|
||||||
function onPositionSliderChange() {
|
function onPositionSliderChange() {
|
||||||
|
|
||||||
isPositionSliderActive = false;
|
|
||||||
|
|
||||||
var newPercent = parseInt(this.value);
|
var newPercent = parseInt(this.value);
|
||||||
|
|
||||||
var newPositionTicks = (newPercent / 100) * self.currentMediaSource.RunTimeTicks;
|
var newPositionTicks = (newPercent / 100) * self.currentMediaSource.RunTimeTicks;
|
||||||
|
@ -457,92 +589,134 @@
|
||||||
$('.videoChaptersPopup').popup('close');
|
$('.videoChaptersPopup').popup('close');
|
||||||
};
|
};
|
||||||
|
|
||||||
self.onAudioOptionSelected = function (elem) {
|
self.onAudioOptionSelected = function (index) {
|
||||||
|
|
||||||
if (!$(elem).hasClass('selectedMediaPopupOption')) {
|
self.setAudioStreamIndex(index);
|
||||||
var index = parseInt(elem.getAttribute('data-value'));
|
|
||||||
|
|
||||||
self.setAudioStreamIndex(index);
|
|
||||||
}
|
|
||||||
$('.videoAudioPopup').popup('close');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.onSubtitleOptionSelected = function (elem) {
|
self.onSubtitleOptionSelected = function (index) {
|
||||||
|
|
||||||
if (!$(elem).hasClass('selectedMediaPopupOption')) {
|
self.setSubtitleStreamIndex(index);
|
||||||
var index = parseInt(elem.getAttribute('data-value'));
|
|
||||||
|
|
||||||
self.setSubtitleStreamIndex(index);
|
|
||||||
}
|
|
||||||
$('.videoSubtitlePopup').popup('close');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.onQualityOptionSelected = function (elem) {
|
self.onQualityOptionSelected = function (bitrate) {
|
||||||
|
|
||||||
if (!$(elem).hasClass('selectedMediaPopupOption')) {
|
AppSettings.maxStreamingBitrate(bitrate);
|
||||||
var bitrate = parseInt(elem.getAttribute('data-value'));
|
|
||||||
|
|
||||||
AppSettings.maxStreamingBitrate(bitrate);
|
$('.videoQualityPopup').popup('close');
|
||||||
|
|
||||||
$('.videoQualityPopup').popup('close');
|
self.changeStream(self.getCurrentTicks(), {
|
||||||
|
Bitrate: bitrate
|
||||||
self.changeStream(self.getCurrentTicks(), {
|
});
|
||||||
Bitrate: bitrate
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.videoSubtitlePopup').popup('close');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$(Dashboard).on('footercreated', function () {
|
function ensureVideoPlayerElements() {
|
||||||
|
|
||||||
|
var html = '<div id="mediaPlayer" data-theme="b" class="ui-bar-b" style="display: none;">';
|
||||||
|
|
||||||
|
html += '<div class="videoBackdrop">';
|
||||||
|
html += '<div id="videoPlayer">';
|
||||||
|
|
||||||
|
html += '<div id="videoElement">';
|
||||||
|
html += '<div id="play" class="status"></div>';
|
||||||
|
html += '<div id="pause" class="status"></div>';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '<div class="videoTopControls hiddenOnIdle">';
|
||||||
|
html += '<div class="videoTopControlsLogo"></div>';
|
||||||
|
html += '<div class="videoAdvancedControls">';
|
||||||
|
|
||||||
|
html += '<paper-icon-button icon="skip-previous" class="previousTrackButton mediaButton videoTrackControl" onclick="MediaPlayer.previousTrack();"></paper-icon-button>';
|
||||||
|
html += '<paper-icon-button icon="skip-next" class="nextTrackButton mediaButton videoTrackControl" onclick="MediaPlayer.nextTrack();"></paper-icon-button>';
|
||||||
|
|
||||||
|
// Embedding onclicks due to issues not firing in cordova safari
|
||||||
|
html += '<paper-icon-button icon="audiotrack" class="mediaButton videoAudioButton" onclick="MediaPlayer.showAudioTracksFlyout();"></paper-icon-button>';
|
||||||
|
html += '<div data-role="popup" class="videoAudioPopup videoPlayerPopup" data-history="false" data-theme="b"></div>';
|
||||||
|
|
||||||
|
html += '<paper-icon-button icon="subtitles" class="mediaButton videoSubtitleButton" onclick="MediaPlayer.showSubtitleMenu();"></paper-icon-button>';
|
||||||
|
html += '<div data-role="popup" class="videoSubtitlePopup videoPlayerPopup" data-history="false" data-theme="b"></div>';
|
||||||
|
|
||||||
|
html += '<paper-icon-button icon="videocam" class="mediaButton videoChaptersButton" onclick="MediaPlayer.showChaptersFlyout();"></paper-icon-button>';
|
||||||
|
html += '<div data-role="popup" class="videoChaptersPopup videoPlayerPopup" data-history="false" data-theme="b"></div>';
|
||||||
|
|
||||||
|
html += '<paper-icon-button icon="settings" class="mediaButton videoQualityButton" onclick="MediaPlayer.showQualityFlyout();"></paper-icon-button>';
|
||||||
|
|
||||||
|
html += '<paper-icon-button icon="close" class="mediaButton" onclick="MediaPlayer.stop();"></paper-icon-button>';
|
||||||
|
|
||||||
|
html += '</div>'; // videoAdvancedControls
|
||||||
|
html += '</div>'; // videoTopControls
|
||||||
|
|
||||||
|
// Create controls
|
||||||
|
html += '<div class="videoControls hiddenOnIdle">';
|
||||||
|
|
||||||
|
html += '<div class="nowPlayingInfo hiddenOnIdle">';
|
||||||
|
html += '<div class="nowPlayingImage"></div>';
|
||||||
|
html += '<div class="nowPlayingTabs"></div>';
|
||||||
|
html += '</div>'; // nowPlayingInfo
|
||||||
|
|
||||||
|
html += '<paper-icon-button icon="skip-previous" class="previousTrackButton mediaButton videoTrackControl" onclick="MediaPlayer.previousTrack();"></paper-icon-button>';
|
||||||
|
|
||||||
|
html += '<paper-icon-button id="video-playButton" icon="play-arrow" class="mediaButton unpauseButton" onclick="MediaPlayer.unpause();"></paper-icon-button>';
|
||||||
|
html += '<paper-icon-button id="video-pauseButton" icon="pause" class="mediaButton pauseButton" onclick="MediaPlayer.pause();"></paper-icon-button>';
|
||||||
|
|
||||||
|
html += '<paper-icon-button icon="skip-next" class="nextTrackButton mediaButton videoTrackControl" onclick="MediaPlayer.nextTrack();"></paper-icon-button>';
|
||||||
|
|
||||||
|
html += '<paper-slider pin step=".1" min="0" max="100" value="0" class="videoPositionSlider" style="width:300px;vertical-align:middle;margin-left:-1em;"></paper-slider>';
|
||||||
|
|
||||||
|
html += '<div class="currentTime">--:--</div>';
|
||||||
|
|
||||||
|
html += '<paper-icon-button icon="volume-up" class="muteButton mediaButton" onclick="MediaPlayer.mute();"></paper-icon-button>';
|
||||||
|
html += '<paper-icon-button icon="volume-off" class="unmuteButton mediaButton" onclick="MediaPlayer.unMute();"></paper-icon-button>';
|
||||||
|
|
||||||
|
html += '<paper-slider pin step="1" min="0" max="100" value="0" class="videoVolumeSlider" style="width:100px;vertical-align:middle;margin-left:-1em;"></paper-slider>';
|
||||||
|
|
||||||
|
html += '<paper-icon-button icon="fullscreen" class="mediaButton fullscreenButton" onclick="MediaPlayer.toggleFullscreen();" id="video-fullscreenButton"></paper-icon-button>';
|
||||||
|
|
||||||
|
html += '</div>'; // videoControls
|
||||||
|
|
||||||
|
html += '</div>'; // videoPlayer
|
||||||
|
html += '</div>'; // videoBackdrop
|
||||||
|
html += '</div>'; // mediaPlayer
|
||||||
|
|
||||||
|
$(document.body).append(html);
|
||||||
|
|
||||||
|
var mediaPlayerElem = $('#mediaPlayer', document.body);
|
||||||
|
mediaPlayerElem.trigger('create');
|
||||||
|
}
|
||||||
|
|
||||||
|
Dashboard.ready(function () {
|
||||||
|
|
||||||
|
ensureVideoPlayerElements();
|
||||||
|
|
||||||
var parent = $("#mediaPlayer");
|
var parent = $("#mediaPlayer");
|
||||||
|
|
||||||
muteButton = $('.muteButton', parent);
|
muteButton = $('.muteButton', parent);
|
||||||
unmuteButton = $('.unmuteButton', parent);
|
unmuteButton = $('.unmuteButton', parent);
|
||||||
currentTimeElement = $('.currentTime', parent);
|
currentTimeElement = $('.currentTime', parent);
|
||||||
positionSlider = $(".positionSlider", parent).on('slidestart', function (e) {
|
|
||||||
|
|
||||||
isPositionSliderActive = true;
|
positionSlider = $(".videoPositionSlider", parent).on('change', onPositionSliderChange)[0];
|
||||||
|
|
||||||
}).on('slidestop', onPositionSliderChange);
|
positionSlider._setPinValue = function (value) {
|
||||||
|
|
||||||
volumeSlider = $('.volumeSlider', parent).on('slidestop', function () {
|
if (!self.currentMediaSource || !self.currentMediaSource.RunTimeTicks) {
|
||||||
|
this.pinValue = '--:--';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ticks = self.currentMediaSource.RunTimeTicks;
|
||||||
|
ticks /= 100;
|
||||||
|
ticks *= value;
|
||||||
|
|
||||||
|
this.pinValue = Dashboard.getDisplayTime(ticks);
|
||||||
|
};
|
||||||
|
|
||||||
|
volumeSlider = $('.videoVolumeSlider', parent).on('change', function () {
|
||||||
|
|
||||||
var vol = this.value;
|
var vol = this.value;
|
||||||
|
|
||||||
updateVolumeButtons(vol);
|
updateVolumeButtons(vol);
|
||||||
self.setVolume(vol * 100);
|
self.setVolume(vol);
|
||||||
});
|
})[0];
|
||||||
|
|
||||||
var trackChange = false;
|
|
||||||
|
|
||||||
var tooltip = $('<div id="slider-tooltip"></div>');
|
|
||||||
|
|
||||||
$(".videoControls .positionSliderContainer .slider").on("change", function (e) {
|
|
||||||
if (!trackChange) return;
|
|
||||||
|
|
||||||
var pct = $(this).val();
|
|
||||||
|
|
||||||
var time = self.currentDurationTicks * (Number(pct) * .01);
|
|
||||||
|
|
||||||
var tooltext = Dashboard.getDisplayTime(time);
|
|
||||||
|
|
||||||
tooltip.text(tooltext);
|
|
||||||
|
|
||||||
Logger.log("slidin", pct, self.currentDurationTicks, time);
|
|
||||||
|
|
||||||
}).on("slidestart", function (e) {
|
|
||||||
trackChange = true;
|
|
||||||
|
|
||||||
var handle = $(".videoControls .positionSliderContainer .ui-slider-handle");
|
|
||||||
|
|
||||||
handle.after(tooltip);
|
|
||||||
}).on("slidestop", function (e) {
|
|
||||||
trackChange = false;
|
|
||||||
|
|
||||||
tooltip.remove();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var idleHandlerTimeout;
|
var idleHandlerTimeout;
|
||||||
|
@ -684,240 +858,6 @@
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAudioTracksHtml() {
|
|
||||||
|
|
||||||
var streams = self.currentMediaSource.MediaStreams.filter(function (currentStream) {
|
|
||||||
return currentStream.Type == "Audio";
|
|
||||||
});
|
|
||||||
|
|
||||||
var currentIndex = getParameterByName('AudioStreamIndex', self.getCurrentSrc(self.currentMediaRenderer));
|
|
||||||
|
|
||||||
var html = '';
|
|
||||||
html += '<div class="videoPlayerPopupContent">';
|
|
||||||
html += '<ul data-role="listview" data-inset="true"><li data-role="list-divider">' + Globalize.translate('HeaderAudioTracks') + '</li>';
|
|
||||||
html += '</ul>';
|
|
||||||
|
|
||||||
html += '<div class="videoPlayerPopupScroller">';
|
|
||||||
html += '<ul data-role="listview" data-inset="true">';
|
|
||||||
|
|
||||||
html += streams.map(function (stream) {
|
|
||||||
|
|
||||||
var cssClass = "mediaPopupOption";
|
|
||||||
|
|
||||||
var selected = stream.Index == currentIndex;
|
|
||||||
|
|
||||||
// Need to embed onclick handler due to delegation not working in iOS cordova
|
|
||||||
var onclick = '';
|
|
||||||
|
|
||||||
if (selected) {
|
|
||||||
cssClass += ' selectedMediaPopupOption';
|
|
||||||
} else {
|
|
||||||
onclick = ' onclick="MediaPlayer.onAudioOptionSelected(this);"';
|
|
||||||
}
|
|
||||||
|
|
||||||
var optionHtml = '<li><a' + onclick + ' data-value="' + stream.Index + '" class="' + cssClass + '" href="#">';
|
|
||||||
|
|
||||||
optionHtml += '<p style="margin:0;">';
|
|
||||||
|
|
||||||
if (selected) {
|
|
||||||
optionHtml += '<img src="css/images/checkmarkgreen.png" style="width:18px;border-radius:3px;margin-right:.5em;vertical-align:middle;" />';
|
|
||||||
}
|
|
||||||
|
|
||||||
var textLines = [];
|
|
||||||
textLines.push(stream.Language || Globalize.translate('LabelUnknownLanguage'));
|
|
||||||
|
|
||||||
var attributes = [];
|
|
||||||
|
|
||||||
if (stream.Codec) {
|
|
||||||
attributes.push(stream.Codec);
|
|
||||||
}
|
|
||||||
if (stream.Profile) {
|
|
||||||
attributes.push(stream.Profile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stream.BitRate) {
|
|
||||||
attributes.push((Math.floor(stream.BitRate / 1000)) + ' kbps');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stream.Channels) {
|
|
||||||
attributes.push(stream.Channels + ' ch');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stream.IsDefault) {
|
|
||||||
attributes.push('(D)');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attributes.length) {
|
|
||||||
textLines.push(attributes.join(' • '));
|
|
||||||
}
|
|
||||||
|
|
||||||
optionHtml += textLines.join('<br/>');
|
|
||||||
|
|
||||||
optionHtml += '</p>';
|
|
||||||
|
|
||||||
optionHtml += '</a></li>';
|
|
||||||
|
|
||||||
return optionHtml;
|
|
||||||
|
|
||||||
}).join('');
|
|
||||||
|
|
||||||
html += '</ul>';
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
return html;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSubtitleTracksHtml() {
|
|
||||||
|
|
||||||
var streams = self.currentMediaSource.MediaStreams.filter(function (currentStream) {
|
|
||||||
return currentStream.Type == "Subtitle";
|
|
||||||
});
|
|
||||||
|
|
||||||
var currentIndex = self.currentSubtitleStreamIndex || -1;
|
|
||||||
|
|
||||||
streams.unshift({
|
|
||||||
Index: -1,
|
|
||||||
Language: "Off"
|
|
||||||
});
|
|
||||||
|
|
||||||
var html = '';
|
|
||||||
html += '<div class="videoPlayerPopupContent">';
|
|
||||||
html += '<ul data-role="listview" data-inset="true"><li data-role="list-divider">' + Globalize.translate('HeaderSubtitles') + '</li>';
|
|
||||||
html += '</ul>';
|
|
||||||
|
|
||||||
html += '<div class="videoPlayerPopupScroller">';
|
|
||||||
html += '<ul data-role="listview" data-inset="true">';
|
|
||||||
|
|
||||||
html += streams.map(function (stream) {
|
|
||||||
|
|
||||||
var cssClass = "mediaPopupOption";
|
|
||||||
|
|
||||||
var selected = stream.Index == currentIndex;
|
|
||||||
|
|
||||||
// Need to embed onclick handler due to delegation not working in iOS cordova
|
|
||||||
var onclick = '';
|
|
||||||
|
|
||||||
if (selected) {
|
|
||||||
cssClass += ' selectedMediaPopupOption';
|
|
||||||
} else {
|
|
||||||
onclick = ' onclick="MediaPlayer.onSubtitleOptionSelected(this);"';
|
|
||||||
}
|
|
||||||
|
|
||||||
var optionHtml = '<li><a' + onclick + ' data-value="' + stream.Index + '" class="' + cssClass + '" href="#">';
|
|
||||||
|
|
||||||
optionHtml += '<p style="margin:0;">';
|
|
||||||
|
|
||||||
if (selected) {
|
|
||||||
optionHtml += '<img src="css/images/checkmarkgreen.png" style="width:18px;border-radius:3px;margin-right:.5em;vertical-align:middle;" />';
|
|
||||||
}
|
|
||||||
|
|
||||||
var textLines = [];
|
|
||||||
textLines.push(stream.Language || Globalize.translate('LabelUnknownLanguage'));
|
|
||||||
|
|
||||||
if (stream.Codec) {
|
|
||||||
textLines.push(stream.Codec);
|
|
||||||
}
|
|
||||||
|
|
||||||
var attributes = [];
|
|
||||||
|
|
||||||
if (stream.IsDefault) {
|
|
||||||
attributes.push('Default');
|
|
||||||
}
|
|
||||||
if (stream.IsForced) {
|
|
||||||
attributes.push('Forced');
|
|
||||||
}
|
|
||||||
if (stream.IsExternal) {
|
|
||||||
attributes.push('External');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attributes.length) {
|
|
||||||
textLines.push(attributes.join(' • '));
|
|
||||||
}
|
|
||||||
|
|
||||||
optionHtml += textLines.join('<br/>');
|
|
||||||
|
|
||||||
optionHtml += '</p>';
|
|
||||||
|
|
||||||
optionHtml += '</a></li>';
|
|
||||||
|
|
||||||
return optionHtml;
|
|
||||||
|
|
||||||
}).join('');
|
|
||||||
|
|
||||||
html += '</ul>';
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
return html;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getQualityFlyoutHtml() {
|
|
||||||
|
|
||||||
var currentSrc = self.getCurrentSrc(self.currentMediaRenderer).toLowerCase();
|
|
||||||
var isStatic = currentSrc.indexOf('static=true') != -1;
|
|
||||||
|
|
||||||
var videoStream = self.currentMediaSource.MediaStreams.filter(function (stream) {
|
|
||||||
return stream.Type == "Video";
|
|
||||||
})[0];
|
|
||||||
var videoWidth = videoStream ? videoStream.Width : null;
|
|
||||||
var videoHeight = videoStream ? videoStream.Height : null;
|
|
||||||
|
|
||||||
var options = self.getVideoQualityOptions(videoWidth, videoHeight);
|
|
||||||
|
|
||||||
if (isStatic) {
|
|
||||||
options[0].name = "Direct";
|
|
||||||
}
|
|
||||||
|
|
||||||
var html = '';
|
|
||||||
|
|
||||||
html += '<div class="videoPlayerPopupContent">';
|
|
||||||
html += '<ul data-role="listview" data-inset="true"><li data-role="list-divider">' + Globalize.translate('HeaderVideoQuality') + '</li>';
|
|
||||||
html += '</ul>';
|
|
||||||
|
|
||||||
html += '<div class="videoPlayerPopupScroller">';
|
|
||||||
html += '<ul data-role="listview" data-inset="true">';
|
|
||||||
|
|
||||||
html += options.map(function (option) {
|
|
||||||
|
|
||||||
var cssClass = "mediaPopupOption";
|
|
||||||
// Need to embed onclick handler due to delegation not working in iOS cordova
|
|
||||||
var onclick = '';
|
|
||||||
|
|
||||||
if (option.selected) {
|
|
||||||
cssClass += ' selectedMediaPopupOption';
|
|
||||||
} else {
|
|
||||||
onclick = ' onclick="MediaPlayer.onQualityOptionSelected(this);"';
|
|
||||||
}
|
|
||||||
|
|
||||||
var optionHtml = '<li><a' + onclick + ' data-value="' + option.bitrate + '" class="' + cssClass + '" href="#">';
|
|
||||||
|
|
||||||
optionHtml += '<p style="margin:0;">';
|
|
||||||
|
|
||||||
if (option.selected) {
|
|
||||||
optionHtml += '<img src="css/images/checkmarkgreen.png" style="width:18px;border-radius:3px;margin-right:.5em;vertical-align:middle;" />';
|
|
||||||
}
|
|
||||||
|
|
||||||
optionHtml += option.name;
|
|
||||||
|
|
||||||
optionHtml += '</p>';
|
|
||||||
|
|
||||||
optionHtml += '</a></li>';
|
|
||||||
|
|
||||||
return optionHtml;
|
|
||||||
|
|
||||||
}).join('');
|
|
||||||
|
|
||||||
html += '</ul>';
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
return html;
|
|
||||||
}
|
|
||||||
|
|
||||||
function bindEventsForPlayback() {
|
function bindEventsForPlayback() {
|
||||||
|
|
||||||
var hideElementsOnIdle = true;
|
var hideElementsOnIdle = true;
|
||||||
|
@ -1117,11 +1057,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AppInfo.hasPhysicalVolumeButtons) {
|
if (AppInfo.hasPhysicalVolumeButtons) {
|
||||||
$('.volumeSliderContainer', videoControls).addClass('hide');
|
$(volumeSlider).visible(false);
|
||||||
$('.muteButton', videoControls).addClass('hide');
|
$('.muteButton', videoControls).addClass('hide');
|
||||||
$('.unmuteButton', videoControls).addClass('hide');
|
$('.unmuteButton', videoControls).addClass('hide');
|
||||||
} else {
|
} else {
|
||||||
$('.volumeSliderContainer', videoControls).removeClass('hide');
|
$(volumeSlider).visible(true);
|
||||||
$('.muteButton', videoControls).removeClass('hide');
|
$('.muteButton', videoControls).removeClass('hide');
|
||||||
$('.unmuteButton', videoControls).removeClass('hide');
|
$('.unmuteButton', videoControls).removeClass('hide');
|
||||||
}
|
}
|
||||||
|
@ -1138,7 +1078,7 @@
|
||||||
|
|
||||||
mediaRenderer.volume(initialVolume);
|
mediaRenderer.volume(initialVolume);
|
||||||
|
|
||||||
volumeSlider.val(initialVolume).slider('refresh');
|
volumeSlider.value = initialVolume * 100;
|
||||||
updateVolumeButtons(initialVolume);
|
updateVolumeButtons(initialVolume);
|
||||||
|
|
||||||
$(mediaRenderer).on("volumechange.mediaplayerevent", function (e) {
|
$(mediaRenderer).on("volumechange.mediaplayerevent", function (e) {
|
||||||
|
@ -1173,7 +1113,7 @@
|
||||||
|
|
||||||
}).on("timeupdate.mediaplayerevent", function () {
|
}).on("timeupdate.mediaplayerevent", function () {
|
||||||
|
|
||||||
if (!isPositionSliderActive) {
|
if (!positionSlider.dragging) {
|
||||||
|
|
||||||
self.setCurrentTime(self.getCurrentTicks(this), positionSlider, currentTimeElement);
|
self.setCurrentTime(self.getCurrentTicks(this), positionSlider, currentTimeElement);
|
||||||
}
|
}
|
||||||
|
@ -1226,7 +1166,7 @@
|
||||||
|
|
||||||
self.currentSubtitleStreamIndex = mediaSource.DefaultSubtitleStreamIndex;
|
self.currentSubtitleStreamIndex = mediaSource.DefaultSubtitleStreamIndex;
|
||||||
|
|
||||||
$('body').addClass('bodyWithPopupOpen');
|
$(document.body).addClass('bodyWithPopupOpen');
|
||||||
|
|
||||||
self.currentMediaRenderer = mediaRenderer;
|
self.currentMediaRenderer = mediaRenderer;
|
||||||
self.currentDurationTicks = self.currentMediaSource.RunTimeTicks;
|
self.currentDurationTicks = self.currentMediaSource.RunTimeTicks;
|
||||||
|
|
|
@ -599,13 +599,14 @@
|
||||||
var percent = ticks / self.currentDurationTicks;
|
var percent = ticks / self.currentDurationTicks;
|
||||||
percent *= 100;
|
percent *= 100;
|
||||||
|
|
||||||
positionSlider.val(percent).slider('enable').slider('refresh');
|
positionSlider.disabled = false;
|
||||||
|
positionSlider.value = percent;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (positionSlider) {
|
if (positionSlider) {
|
||||||
|
|
||||||
positionSlider.slider('disable').slider('refresh');
|
positionSlider.disabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1552,7 +1553,7 @@
|
||||||
|
|
||||||
Logger.log('playback stopped');
|
Logger.log('playback stopped');
|
||||||
|
|
||||||
$('body').removeClass('bodyWithPopupOpen');
|
$(document.body).removeClass('bodyWithPopupOpen');
|
||||||
|
|
||||||
var mediaRenderer = this;
|
var mediaRenderer = this;
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,9 @@
|
||||||
var unmuteButton;
|
var unmuteButton;
|
||||||
var muteButton;
|
var muteButton;
|
||||||
var volumeSlider;
|
var volumeSlider;
|
||||||
var volumeSliderContainer;
|
|
||||||
var isVolumeSliderActive;
|
|
||||||
var unpauseButton;
|
var unpauseButton;
|
||||||
var pauseButton;
|
var pauseButton;
|
||||||
var positionSlider;
|
var positionSlider;
|
||||||
var isPositionSliderActive;
|
|
||||||
|
|
||||||
var lastPlayerState;
|
var lastPlayerState;
|
||||||
|
|
||||||
|
@ -25,12 +22,17 @@
|
||||||
// add return false because on iOS clicking the bar often ends up clicking the content underneath.
|
// add return false because on iOS clicking the bar often ends up clicking the content underneath.
|
||||||
html += '<div class="nowPlayingBar" style="display:none;">';
|
html += '<div class="nowPlayingBar" style="display:none;">';
|
||||||
|
|
||||||
|
html += '<div class="nowPlayingBarPositionContainer">';
|
||||||
|
html += '<paper-slider pin step=".1" min="0" max="100" value="0" class="nowPlayingBarPositionSlider"></paper-slider>';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '<div class="nowPlayingBarInfoContainer">';
|
||||||
html += '<div class="nowPlayingImage"></div>';
|
html += '<div class="nowPlayingImage"></div>';
|
||||||
html += '<div class="nowPlayingText"></div>';
|
html += '<div class="nowPlayingBarText"></div>';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
// The onclicks are needed due to the return false above
|
// The onclicks are needed due to the return false above
|
||||||
html += '<paper-icon-button icon="tablet-android" onclick="Dashboard.navigate(\'nowplaying.html\', false);" class="mediaButton remoteControlButton"></paper-icon-button>';
|
html += '<div class="nowPlayingBarCenter">';
|
||||||
html += '<paper-icon-button icon="view-list" onclick="Dashboard.navigate(\'nowplaying.html?tab=Playlist\', false);" class="mediaButton playlistButton"></paper-icon-button>';
|
|
||||||
|
|
||||||
html += '<paper-icon-button icon="skip-previous" class="previousTrackButton mediaButton"></paper-icon-button>';
|
html += '<paper-icon-button icon="skip-previous" class="previousTrackButton mediaButton"></paper-icon-button>';
|
||||||
|
|
||||||
|
@ -41,23 +43,26 @@
|
||||||
|
|
||||||
html += '<paper-icon-button icon="skip-next" class="nextTrackButton mediaButton"></paper-icon-button>';
|
html += '<paper-icon-button icon="skip-next" class="nextTrackButton mediaButton"></paper-icon-button>';
|
||||||
|
|
||||||
html += '<div id="mediaElement"></div>';
|
html += '<div class="nowPlayingBarCurrentTime"></div>';
|
||||||
|
|
||||||
html += '<div class="positionSliderContainer sliderContainer">';
|
|
||||||
html += '<input type="range" class="mediaSlider positionSlider slider" step=".001" min="0" max="100" value="0" style="display:none;" data-mini="true" data-theme="a" data-highlight="true" />';
|
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
html += '<div class="currentTime"></div>';
|
html += '<div class="nowPlayingBarRight">';
|
||||||
|
|
||||||
html += '<paper-icon-button icon="volume-up" class="muteButton mediaButton"></paper-icon-button>';
|
html += '<paper-icon-button icon="volume-up" class="muteButton mediaButton"></paper-icon-button>';
|
||||||
html += '<paper-icon-button icon="volume-off" class="unmuteButton mediaButton"></paper-icon-button>';
|
html += '<paper-icon-button icon="volume-off" class="unmuteButton mediaButton"></paper-icon-button>';
|
||||||
|
|
||||||
html += '<div class="volumeSliderContainer sliderContainer">';
|
html += '<paper-slider pin step="1" min="0" max="100" value="0" class="nowPlayingBarVolumeSlider" style="width:100px;vertical-align:middle;"></paper-slider>';
|
||||||
html += '<input type="range" class="mediaSlider volumeSlider slider" step=".05" min="0" max="100" value="0" style="display:none;" data-mini="true" data-theme="a" data-highlight="true" />';
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
html += '<div class="nowPlayingBarUserDataButtons">';
|
html += '<div class="nowPlayingBarUserDataButtons">';
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '<paper-icon-button icon="play-arrow" class="mediaButton unpauseButton"></paper-icon-button>';
|
||||||
|
html += '<paper-icon-button icon="pause" class="mediaButton pauseButton"></paper-icon-button>';
|
||||||
|
html += '<paper-icon-button icon="tablet-android" onclick="Dashboard.navigate(\'nowplaying.html\', false);" class="mediaButton remoteControlButton"></paper-icon-button>';
|
||||||
|
html += '<paper-icon-button icon="queue-music" onclick="Dashboard.navigate(\'nowplaying.html?tab=Playlist\', false);" class="mediaButton playlistButton"></paper-icon-button>';
|
||||||
|
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
return html;
|
return html;
|
||||||
|
@ -65,9 +70,9 @@
|
||||||
|
|
||||||
function bindEvents(elem) {
|
function bindEvents(elem) {
|
||||||
|
|
||||||
currentTimeElement = $('.currentTime', elem);
|
currentTimeElement = $('.nowPlayingBarCurrentTime', elem);
|
||||||
nowPlayingImageElement = $('.nowPlayingImage', elem);
|
nowPlayingImageElement = $('.nowPlayingImage', elem);
|
||||||
nowPlayingTextElement = $('.nowPlayingText', elem);
|
nowPlayingTextElement = $('.nowPlayingBarText', elem);
|
||||||
nowPlayingUserData = $('.nowPlayingBarUserDataButtons', elem);
|
nowPlayingUserData = $('.nowPlayingBarUserDataButtons', elem);
|
||||||
|
|
||||||
$(elem).on('swipeup', function () {
|
$(elem).on('swipeup', function () {
|
||||||
|
@ -123,28 +128,15 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
volumeSlider = $('.volumeSlider', elem).on('slidestart', function () {
|
volumeSlider = $('.nowPlayingBarVolumeSlider', elem).on('change', function () {
|
||||||
|
|
||||||
isVolumeSliderActive = true;
|
|
||||||
|
|
||||||
}).on('slidestop', function () {
|
|
||||||
|
|
||||||
isVolumeSliderActive = false;
|
|
||||||
|
|
||||||
if (currentPlayer) {
|
if (currentPlayer) {
|
||||||
currentPlayer.setVolume(this.value);
|
currentPlayer.setVolume(this.value);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
volumeSliderContainer = $('.volumeSliderContainer', elem);
|
})[0];
|
||||||
|
|
||||||
positionSlider = $('.positionSlider', elem).on('slidestart', function () {
|
positionSlider = $('.nowPlayingBarPositionSlider', elem).on('change', function () {
|
||||||
|
|
||||||
isPositionSliderActive = true;
|
|
||||||
|
|
||||||
}).on('slidestop', function () {
|
|
||||||
|
|
||||||
isPositionSliderActive = false;
|
|
||||||
|
|
||||||
if (currentPlayer && lastPlayerState) {
|
if (currentPlayer && lastPlayerState) {
|
||||||
|
|
||||||
|
@ -153,7 +145,24 @@
|
||||||
|
|
||||||
currentPlayer.seek(Math.floor(newPositionTicks));
|
currentPlayer.seek(Math.floor(newPositionTicks));
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
positionSlider._setPinValue = function (value) {
|
||||||
|
|
||||||
|
var state = lastPlayerState;
|
||||||
|
|
||||||
|
if (!state || !state.NowPlayingItem || !state.NowPlayingItem.RunTimeTicks) {
|
||||||
|
this.pinValue = '--:--';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ticks = state.NowPlayingItem.RunTimeTicks;
|
||||||
|
ticks /= 100;
|
||||||
|
ticks *= value;
|
||||||
|
|
||||||
|
this.pinValue = Dashboard.getDisplayTime(ticks);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNowPlayingBar() {
|
function getNowPlayingBar() {
|
||||||
|
@ -212,27 +221,21 @@
|
||||||
updatePlayerVolumeState(state, playerInfo);
|
updatePlayerVolumeState(state, playerInfo);
|
||||||
|
|
||||||
var nowPlayingItem = state.NowPlayingItem || {};
|
var nowPlayingItem = state.NowPlayingItem || {};
|
||||||
if (!isPositionSliderActive) {
|
if (!positionSlider.dragging) {
|
||||||
|
|
||||||
if (nowPlayingItem && nowPlayingItem.RunTimeTicks) {
|
if (nowPlayingItem && nowPlayingItem.RunTimeTicks) {
|
||||||
|
|
||||||
var pct = playState.PositionTicks / nowPlayingItem.RunTimeTicks;
|
var pct = playState.PositionTicks / nowPlayingItem.RunTimeTicks;
|
||||||
pct *= 100;
|
pct *= 100;
|
||||||
|
|
||||||
positionSlider.val(pct);
|
positionSlider.value = pct;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
positionSlider.val(0);
|
positionSlider.value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playState.CanSeek) {
|
positionSlider.disabled = !playState.CanSeek;
|
||||||
positionSlider.slider("enable");
|
|
||||||
} else {
|
|
||||||
positionSlider.slider("disable");
|
|
||||||
}
|
|
||||||
|
|
||||||
positionSlider.slider('refresh');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var timeText = Dashboard.getDisplayTime(playState.PositionTicks);
|
var timeText = Dashboard.getDisplayTime(playState.PositionTicks);
|
||||||
|
@ -263,12 +266,6 @@
|
||||||
var showUnmuteButton = true;
|
var showUnmuteButton = true;
|
||||||
var showVolumeSlider = true;
|
var showVolumeSlider = true;
|
||||||
|
|
||||||
//if (supportedCommands.indexOf('SetVolume') == -1) {
|
|
||||||
// volumeSlider.prop('disabled', 'disabled');
|
|
||||||
//} else {
|
|
||||||
// volumeSlider.prop('disabled', '');
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (supportedCommands.indexOf('Mute') == -1) {
|
if (supportedCommands.indexOf('Mute') == -1) {
|
||||||
showMuteButton = false;
|
showMuteButton = false;
|
||||||
}
|
}
|
||||||
|
@ -307,17 +304,11 @@
|
||||||
hideButton(unmuteButton);
|
hideButton(unmuteButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showVolumeSlider) {
|
$(volumeSlider).visible(showVolumeSlider);
|
||||||
volumeSliderContainer.show();
|
|
||||||
} else {
|
|
||||||
volumeSliderContainer.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isVolumeSliderActive) {
|
if (!volumeSlider.dragging) {
|
||||||
volumeSlider.val(playState.VolumeLevel || 0);
|
volumeSlider.value = playState.VolumeLevel || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
volumeSlider.slider('refresh');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentImgUrl;
|
var currentImgUrl;
|
||||||
|
@ -338,7 +329,7 @@
|
||||||
nowPlayingTextElement.html(nameHtml);
|
nowPlayingTextElement.html(nameHtml);
|
||||||
|
|
||||||
var url;
|
var url;
|
||||||
var imgHeight = 60;
|
var imgHeight = 90;
|
||||||
|
|
||||||
var nowPlayingItem = state.NowPlayingItem;
|
var nowPlayingItem = state.NowPlayingItem;
|
||||||
|
|
||||||
|
@ -386,9 +377,6 @@
|
||||||
|
|
||||||
var imgHtml = '<img src="' + url + '" />';
|
var imgHtml = '<img src="' + url + '" />';
|
||||||
|
|
||||||
if (state.NowPlayingItem.Id) {
|
|
||||||
imgHtml = '<a href="' + LibraryBrowser.getHref(state.NowPlayingItem) + '">' + imgHtml + '</a>';
|
|
||||||
}
|
|
||||||
nowPlayingImageElement.html(imgHtml);
|
nowPlayingImageElement.html(imgHtml);
|
||||||
|
|
||||||
if (nowPlayingItem.Id) {
|
if (nowPlayingItem.Id) {
|
||||||
|
|
|
@ -1844,80 +1844,6 @@ var AppInfo = {};
|
||||||
initFastClick();
|
initFastClick();
|
||||||
}
|
}
|
||||||
|
|
||||||
var videoPlayerHtml = '<div id="mediaPlayer" data-theme="b" class="ui-bar-b" style="display: none;">';
|
|
||||||
|
|
||||||
videoPlayerHtml += '<div class="videoBackdrop">';
|
|
||||||
videoPlayerHtml += '<div id="videoPlayer">';
|
|
||||||
|
|
||||||
videoPlayerHtml += '<div id="videoElement">';
|
|
||||||
videoPlayerHtml += '<div id="play" class="status"></div>';
|
|
||||||
videoPlayerHtml += '<div id="pause" class="status"></div>';
|
|
||||||
videoPlayerHtml += '</div>';
|
|
||||||
|
|
||||||
videoPlayerHtml += '<div class="videoTopControls hiddenOnIdle">';
|
|
||||||
videoPlayerHtml += '<div class="videoTopControlsLogo"></div>';
|
|
||||||
videoPlayerHtml += '<div class="videoAdvancedControls">';
|
|
||||||
|
|
||||||
videoPlayerHtml += '<button class="mediaButton videoTrackControl previousTrackButton imageButton" title="Previous video" type="button" onclick="MediaPlayer.previousTrack();" data-role="none"><i class="fa fa-step-backward"></i></button>';
|
|
||||||
videoPlayerHtml += '<button class="mediaButton videoTrackControl nextTrackButton imageButton" title="Next video" type="button" onclick="MediaPlayer.nextTrack();" data-role="none"><i class="fa fa-step-forward"></i></button>';
|
|
||||||
|
|
||||||
// Embedding onclicks due to issues not firing in cordova safari
|
|
||||||
videoPlayerHtml += '<button class="mediaButton videoAudioButton imageButton" title="Audio tracks" type="button" data-role="none" onclick="MediaPlayer.showAudioTracksFlyout();"><i class="fa fa-music"></i></button>';
|
|
||||||
videoPlayerHtml += '<div data-role="popup" class="videoAudioPopup videoPlayerPopup" data-history="false" data-theme="b"></div>';
|
|
||||||
|
|
||||||
videoPlayerHtml += '<button class="mediaButton videoSubtitleButton imageButton" title="Subtitles" type="button" data-role="none" onclick="MediaPlayer.showSubtitleMenu();"><i class="fa fa-text-width"></i></button>';
|
|
||||||
videoPlayerHtml += '<div data-role="popup" class="videoSubtitlePopup videoPlayerPopup" data-history="false" data-theme="b"></div>';
|
|
||||||
|
|
||||||
videoPlayerHtml += '<button class="mediaButton videoChaptersButton imageButton" title="Scenes" type="button" data-role="none" onclick="MediaPlayer.showChaptersFlyout();"><i class="fa fa-video-camera"></i></button>';
|
|
||||||
videoPlayerHtml += '<div data-role="popup" class="videoChaptersPopup videoPlayerPopup" data-history="false" data-theme="b"></div>';
|
|
||||||
|
|
||||||
videoPlayerHtml += '<button class="mediaButton videoQualityButton imageButton" title="Quality" type="button" data-role="none" onclick="MediaPlayer.showQualityFlyout();"><i class="fa fa-gear"></i></button>';
|
|
||||||
videoPlayerHtml += '<div data-role="popup" class="videoQualityPopup videoPlayerPopup" data-history="false" data-theme="b"></div>';
|
|
||||||
|
|
||||||
videoPlayerHtml += '<button class="mediaButton imageButton" title="Stop" type="button" onclick="MediaPlayer.stop();" data-role="none"><i class="fa fa-close"></i></button>';
|
|
||||||
|
|
||||||
videoPlayerHtml += '</div>'; // videoAdvancedControls
|
|
||||||
videoPlayerHtml += '</div>'; // videoTopControls
|
|
||||||
|
|
||||||
// Create controls
|
|
||||||
videoPlayerHtml += '<div class="videoControls hiddenOnIdle">';
|
|
||||||
|
|
||||||
videoPlayerHtml += '<div class="nowPlayingInfo hiddenOnIdle">';
|
|
||||||
videoPlayerHtml += '<div class="nowPlayingImage"></div>';
|
|
||||||
videoPlayerHtml += '<div class="nowPlayingTabs"></div>';
|
|
||||||
videoPlayerHtml += '</div>'; // nowPlayingInfo
|
|
||||||
|
|
||||||
videoPlayerHtml += '<button id="video-previousTrackButton" class="mediaButton previousTrackButton videoTrackControl imageButton" title="Previous Track" type="button" onclick="MediaPlayer.previousTrack();" data-role="none"><i class="fa fa-step-backward"></i></button>';
|
|
||||||
videoPlayerHtml += '<button id="video-playButton" class="mediaButton imageButton" title="Play" type="button" onclick="MediaPlayer.unpause();" data-role="none"><i class="fa fa-play"></i></button>';
|
|
||||||
videoPlayerHtml += '<button id="video-pauseButton" class="mediaButton imageButton" title="Pause" type="button" onclick="MediaPlayer.pause();" data-role="none"><i class="fa fa-pause"></i></button>';
|
|
||||||
videoPlayerHtml += '<button id="video-nextTrackButton" class="mediaButton nextTrackButton videoTrackControl imageButton" title="Next Track" type="button" onclick="MediaPlayer.nextTrack();" data-role="none"><i class="fa fa-step-forward"></i></button>';
|
|
||||||
|
|
||||||
videoPlayerHtml += '<div class="positionSliderContainer sliderContainer">';
|
|
||||||
videoPlayerHtml += '<input type="range" class="mediaSlider positionSlider slider" step=".001" min="0" max="100" value="0" style="display:none;" data-mini="true" data-theme="a" data-highlight="true" />';
|
|
||||||
videoPlayerHtml += '</div>';
|
|
||||||
|
|
||||||
videoPlayerHtml += '<div class="currentTime">--:--</div>';
|
|
||||||
|
|
||||||
videoPlayerHtml += '<button id="video-muteButton" class="mediaButton muteButton imageButton" title="Mute" type="button" onclick="MediaPlayer.mute();" data-role="none"><i class="fa fa-volume-up"></i></button>';
|
|
||||||
videoPlayerHtml += '<button id="video-unmuteButton" class="mediaButton unmuteButton imageButton" title="Unmute" type="button" onclick="MediaPlayer.unMute();" data-role="none"><i class="fa fa-volume-off"></i></button>';
|
|
||||||
|
|
||||||
videoPlayerHtml += '<div class="volumeSliderContainer sliderContainer">';
|
|
||||||
videoPlayerHtml += '<input type="range" class="mediaSlider volumeSlider slider" step=".05" min="0" max="1" value="0" style="display:none;" data-mini="true" data-theme="a" data-highlight="true" />';
|
|
||||||
videoPlayerHtml += '</div>';
|
|
||||||
|
|
||||||
videoPlayerHtml += '<button onclick="MediaPlayer.toggleFullscreen();" id="video-fullscreenButton" class="mediaButton fullscreenButton imageButton" title="Fullscreen" type="button" data-role="none"><i class="fa fa-expand"></i></button>';
|
|
||||||
|
|
||||||
videoPlayerHtml += '</div>'; // videoControls
|
|
||||||
|
|
||||||
videoPlayerHtml += '</div>'; // videoPlayer
|
|
||||||
videoPlayerHtml += '</div>'; // videoBackdrop
|
|
||||||
videoPlayerHtml += '</div>'; // mediaPlayer
|
|
||||||
|
|
||||||
$(document.body).append(videoPlayerHtml);
|
|
||||||
|
|
||||||
var mediaPlayerElem = $('#mediaPlayer', document.body);
|
|
||||||
mediaPlayerElem.trigger('create');
|
|
||||||
|
|
||||||
var footerHtml = '<div id="footer" class="footer" data-theme="b" class="ui-bar-b">';
|
var footerHtml = '<div id="footer" class="footer" data-theme="b" class="ui-bar-b">';
|
||||||
|
|
||||||
footerHtml += '<div id="footerNotifications"></div>';
|
footerHtml += '<div id="footerNotifications"></div>';
|
||||||
|
@ -1925,8 +1851,6 @@ var AppInfo = {};
|
||||||
|
|
||||||
$(document.body).append(footerHtml);
|
$(document.body).append(footerHtml);
|
||||||
|
|
||||||
$(Dashboard).trigger('footercreated');
|
|
||||||
|
|
||||||
$(window).on("beforeunload", function () {
|
$(window).on("beforeunload", function () {
|
||||||
|
|
||||||
var apiClient = window.ApiClient;
|
var apiClient = window.ApiClient;
|
||||||
|
|
1
dashboard-ui/thirdparty/emby-icons.html
vendored
1
dashboard-ui/thirdparty/emby-icons.html
vendored
|
@ -106,6 +106,7 @@ See [iron-iconset](#iron-iconset) and [iron-iconset-svg](#iron-iconset-svg) for
|
||||||
<g id="keyboard-arrow-left"><path d="M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z" /></g>
|
<g id="keyboard-arrow-left"><path d="M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z" /></g>
|
||||||
<g id="keyboard-arrow-right"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z" /></g>
|
<g id="keyboard-arrow-right"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z" /></g>
|
||||||
<g id="keyboard-arrow-up"><path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" /></g>
|
<g id="keyboard-arrow-up"><path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" /></g>
|
||||||
|
<g id="queue-music"><path d="M15 6H3v2h12V6zm0 4H3v2h12v-2zM3 16h8v-2H3v2zM17 6v8.18c-.31-.11-.65-.18-1-.18-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3V8h3V6h-5z" /></g>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
</iron-iconset-svg>
|
</iron-iconset-svg>
|
||||||
|
|
|
@ -16368,7 +16368,7 @@ iron-selector:not(.narrow-layout) #main ::content [paper-drawer-toggle] {
|
||||||
</script>
|
</script>
|
||||||
<dom-module id="paper-slider" assetpath="bower_components/paper-slider/">
|
<dom-module id="paper-slider" assetpath="bower_components/paper-slider/">
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/**
|
/**
|
||||||
@license
|
@license
|
||||||
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
|
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
|
||||||
|
@ -16629,414 +16629,414 @@ paper-ripple {
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="sliderContainer" class$="[[_getClassNames(disabled, pin, snaps, immediateValue, min, expand, dragging, transiting, editable)]]">
|
<div id="sliderContainer" class$="[[_getClassNames(disabled, pin, snaps, immediateValue, min, expand, dragging, transiting, editable)]]">
|
||||||
|
|
||||||
<div class="bar-container">
|
<div class="bar-container">
|
||||||
<paper-progress id="sliderBar" aria-hidden="true" min="[[min]]" max="[[max]]" step="[[step]]" value="[[immediateValue]]" secondary-progress="[[secondaryProgress]]" on-down="_bardown" on-up="_resetKnob" on-track="_onTrack">
|
<paper-progress id="sliderBar" aria-hidden="true" min="[[min]]" max="[[max]]" step="[[step]]" value="[[immediateValue]]" secondary-progress="[[secondaryProgress]]" on-down="_bardown" on-up="_resetKnob" on-track="_onTrack">
|
||||||
</paper-progress>
|
</paper-progress>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template is="dom-if" if="[[snaps]]">
|
<template is="dom-if" if="[[snaps]]">
|
||||||
<div class="slider-markers horizontal layout">
|
<div class="slider-markers horizontal layout">
|
||||||
<template is="dom-repeat" items="[[markers]]">
|
<template is="dom-repeat" items="[[markers]]">
|
||||||
<div class="slider-marker flex"></div>
|
<div class="slider-marker flex"></div>
|
||||||
</template>
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div id="sliderKnob" class="center-justified center horizontal layout" on-down="_knobdown" on-up="_resetKnob" on-track="_onTrack" on-transitionend="_knobTransitionEnd">
|
||||||
|
<paper-ripple id="ink" class="circle" center="" hidden$="[[!receivedFocusFromKeyboard]]"></paper-ripple>
|
||||||
|
<div id="sliderKnobInner" value$="[[pinValue]]"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
|
||||||
|
|
||||||
<div id="sliderKnob" class="center-justified center horizontal layout" on-down="_knobdown" on-up="_resetKnob" on-track="_onTrack" on-transitionend="_knobTransitionEnd">
|
<template is="dom-if" if="[[editable]]">
|
||||||
<paper-ripple id="ink" class="circle" center="" hidden$="[[!receivedFocusFromKeyboard]]"></paper-ripple>
|
<paper-input id="input" class="slider-input" disabled$="[[disabled]]" on-change="_inputChange">
|
||||||
<div id="sliderKnobInner" value$="[[pinValue]]"></div>
|
</paper-input>
|
||||||
</div>
|
</template>
|
||||||
</div>
|
|
||||||
|
|
||||||
<template is="dom-if" if="[[editable]]">
|
|
||||||
<paper-input id="input" class="slider-input" disabled$="[[disabled]]" on-change="_inputChange">
|
|
||||||
</paper-input>
|
|
||||||
</template>
|
</template>
|
||||||
</template>
|
|
||||||
|
|
||||||
</dom-module>
|
</dom-module>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'paper-slider',
|
is: 'paper-slider',
|
||||||
|
|
||||||
behaviors: [
|
behaviors: [
|
||||||
Polymer.IronA11yKeysBehavior,
|
Polymer.IronA11yKeysBehavior,
|
||||||
Polymer.PaperInkyFocusBehavior,
|
Polymer.PaperInkyFocusBehavior,
|
||||||
Polymer.IronFormElementBehavior,
|
Polymer.IronFormElementBehavior,
|
||||||
Polymer.IronRangeBehavior
|
Polymer.IronRangeBehavior
|
||||||
],
|
],
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, the slider thumb snaps to tick marks evenly spaced based
|
* If true, the slider thumb snaps to tick marks evenly spaced based
|
||||||
* on the `step` property value.
|
* on the `step` property value.
|
||||||
*/
|
*/
|
||||||
snaps: {
|
snaps: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
notify: true
|
notify: true
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, a pin with numeric value label is shown when the slider thumb
|
* If true, a pin with numeric value label is shown when the slider thumb
|
||||||
* is pressed. Use for settings for which users need to know the exact
|
* is pressed. Use for settings for which users need to know the exact
|
||||||
* value of the setting.
|
* value of the setting.
|
||||||
*/
|
*/
|
||||||
pin: {
|
pin: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
notify: true
|
notify: true
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number that represents the current secondary progress.
|
* The number that represents the current secondary progress.
|
||||||
*/
|
*/
|
||||||
secondaryProgress: {
|
secondaryProgress: {
|
||||||
type: Number,
|
type: Number,
|
||||||
value: 0,
|
value: 0,
|
||||||
notify: true,
|
notify: true,
|
||||||
observer: '_secondaryProgressChanged'
|
observer: '_secondaryProgressChanged'
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, an input is shown and user can use it to set the slider value.
|
* If true, an input is shown and user can use it to set the slider value.
|
||||||
*/
|
*/
|
||||||
editable: {
|
editable: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false
|
value: false
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The immediate value of the slider. This value is updated while the user
|
* The immediate value of the slider. This value is updated while the user
|
||||||
* is dragging the slider.
|
* is dragging the slider.
|
||||||
*/
|
*/
|
||||||
immediateValue: {
|
immediateValue: {
|
||||||
type: Number,
|
type: Number,
|
||||||
value: 0,
|
value: 0,
|
||||||
readOnly: true
|
readOnly: true
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum number of markers
|
* The maximum number of markers
|
||||||
*/
|
*/
|
||||||
maxMarkers: {
|
maxMarkers: {
|
||||||
type: Number,
|
type: Number,
|
||||||
value: 0,
|
value: 0,
|
||||||
notify: true,
|
notify: true,
|
||||||
observer: '_maxMarkersChanged'
|
observer: '_maxMarkersChanged'
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, the knob is expanded
|
* If true, the knob is expanded
|
||||||
*/
|
*/
|
||||||
expand: {
|
expand: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
readOnly: true
|
readOnly: true
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True when the user is dragging the slider.
|
* True when the user is dragging the slider.
|
||||||
*/
|
*/
|
||||||
dragging: {
|
dragging: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
readOnly: true
|
readOnly: true
|
||||||
},
|
},
|
||||||
|
|
||||||
transiting: {
|
transiting: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
readOnly: true
|
readOnly: true
|
||||||
},
|
},
|
||||||
|
|
||||||
markers: {
|
markers: {
|
||||||
type: Array,
|
type: Array,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
value: []
|
value: []
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
observers: [
|
observers: [
|
||||||
'_updateKnob(value, min, max, snaps, step)',
|
'_updateKnob(value, min, max, snaps, step)',
|
||||||
'_minChanged(min)',
|
'_minChanged(min)',
|
||||||
'_maxChanged(max)',
|
'_maxChanged(max)',
|
||||||
'_valueChanged(value)',
|
'_valueChanged(value)',
|
||||||
'_immediateValueChanged(immediateValue)'
|
'_immediateValueChanged(immediateValue)'
|
||||||
],
|
],
|
||||||
|
|
||||||
hostAttributes: {
|
hostAttributes: {
|
||||||
role: 'slider',
|
role: 'slider',
|
||||||
tabindex: 0
|
tabindex: 0
|
||||||
},
|
},
|
||||||
|
|
||||||
keyBindings: {
|
keyBindings: {
|
||||||
'left down pagedown home': '_decrementKey',
|
'left down pagedown home': '_decrementKey',
|
||||||
'right up pageup end': '_incrementKey'
|
'right up pageup end': '_incrementKey'
|
||||||
},
|
},
|
||||||
|
|
||||||
ready: function() {
|
ready: function () {
|
||||||
// issue polymer/polymer#1305
|
// issue polymer/polymer#1305
|
||||||
this.async(function() {
|
this.async(function () {
|
||||||
this._updateKnob(this.value);
|
this._updateKnob(this.value);
|
||||||
this._updateInputValue();
|
this._updateInputValue();
|
||||||
}, 1);
|
}, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increases value by `step` but not above `max`.
|
||||||
|
* @method increment
|
||||||
|
*/
|
||||||
|
increment: function () {
|
||||||
|
this.value = this._clampValue(this.value + this.step);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decreases value by `step` but not below `min`.
|
||||||
|
* @method decrement
|
||||||
|
*/
|
||||||
|
decrement: function () {
|
||||||
|
this.value = this._clampValue(this.value - this.step);
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateKnob: function (value) {
|
||||||
|
this._positionKnob(this._calcRatio(value));
|
||||||
|
},
|
||||||
|
|
||||||
|
_minChanged: function () {
|
||||||
|
this.setAttribute('aria-valuemin', this.min);
|
||||||
|
},
|
||||||
|
|
||||||
|
_maxChanged: function () {
|
||||||
|
this.setAttribute('aria-valuemax', this.max);
|
||||||
|
},
|
||||||
|
|
||||||
|
_valueChanged: function () {
|
||||||
|
this.setAttribute('aria-valuenow', this.value);
|
||||||
|
this.fire('value-change');
|
||||||
|
},
|
||||||
|
|
||||||
|
_immediateValueChanged: function () {
|
||||||
|
if (this.dragging) {
|
||||||
|
this.fire('immediate-value-change');
|
||||||
|
} else {
|
||||||
|
this.value = this.immediateValue;
|
||||||
|
}
|
||||||
|
this._updateInputValue();
|
||||||
|
},
|
||||||
|
|
||||||
|
_secondaryProgressChanged: function () {
|
||||||
|
this.secondaryProgress = this._clampValue(this.secondaryProgress);
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateInputValue: function () {
|
||||||
|
if (this.editable) {
|
||||||
|
this.$$('#input').value = this.immediateValue.toString();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_expandKnob: function () {
|
||||||
|
this._setExpand(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
_resetKnob: function () {
|
||||||
|
this.cancelDebouncer('expandKnob');
|
||||||
|
this._setExpand(false);
|
||||||
|
},
|
||||||
|
|
||||||
|
_positionKnob: function (ratio) {
|
||||||
|
this._setImmediateValue(this._calcStep(this._calcKnobPosition(ratio)));
|
||||||
|
this._setPinValue(this.immediateValue);
|
||||||
|
|
||||||
|
this._setRatio(this._calcRatio(this.immediateValue));
|
||||||
|
|
||||||
|
this.$.sliderKnob.style.left = (this.ratio * 100) + '%';
|
||||||
|
},
|
||||||
|
|
||||||
|
_inputChange: function () {
|
||||||
|
this.value = this.$$('#input').value;
|
||||||
|
this.fire('change');
|
||||||
|
},
|
||||||
|
|
||||||
|
_calcKnobPosition: function (ratio) {
|
||||||
|
return (this.max - this.min) * ratio + this.min;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onTrack: function (event) {
|
||||||
|
switch (event.detail.state) {
|
||||||
|
case 'start':
|
||||||
|
this._trackStart(event);
|
||||||
|
break;
|
||||||
|
case 'track':
|
||||||
|
this._trackX(event);
|
||||||
|
break;
|
||||||
|
case 'end':
|
||||||
|
this._trackEnd();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_trackStart: function (event) {
|
||||||
|
this._w = this.$.sliderBar.offsetWidth;
|
||||||
|
this._x = this.ratio * this._w;
|
||||||
|
this._startx = this._x || 0;
|
||||||
|
this._minx = -this._startx;
|
||||||
|
this._maxx = this._w - this._startx;
|
||||||
|
this.$.sliderKnob.classList.add('dragging');
|
||||||
|
|
||||||
|
this._setDragging(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
_trackX: function (e) {
|
||||||
|
if (!this.dragging) {
|
||||||
|
this._trackStart(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dx = Math.min(this._maxx, Math.max(this._minx, e.detail.dx));
|
||||||
|
this._x = this._startx + dx;
|
||||||
|
|
||||||
|
var immediateValue = this._calcStep(this._calcKnobPosition(this._x / this._w));
|
||||||
|
this._setImmediateValue(immediateValue);
|
||||||
|
this._setPinValue(immediateValue);
|
||||||
|
|
||||||
|
// update knob's position
|
||||||
|
var translateX = ((this._calcRatio(immediateValue) * this._w) - this._startx);
|
||||||
|
this.translate3d(translateX + 'px', 0, 0, this.$.sliderKnob);
|
||||||
|
},
|
||||||
|
|
||||||
|
_trackEnd: function () {
|
||||||
|
var s = this.$.sliderKnob.style;
|
||||||
|
|
||||||
|
this.$.sliderKnob.classList.remove('dragging');
|
||||||
|
this._setDragging(false);
|
||||||
|
this._resetKnob();
|
||||||
|
this.value = this.immediateValue;
|
||||||
|
|
||||||
|
s.transform = s.webkitTransform = '';
|
||||||
|
|
||||||
|
this.fire('change');
|
||||||
|
},
|
||||||
|
|
||||||
|
_knobdown: function (event) {
|
||||||
|
this._expandKnob();
|
||||||
|
|
||||||
|
// cancel selection
|
||||||
|
event.detail.sourceEvent.preventDefault();
|
||||||
|
|
||||||
|
// set the focus manually because we will called prevent default
|
||||||
|
this.focus();
|
||||||
|
},
|
||||||
|
|
||||||
|
_bardown: function (event) {
|
||||||
|
this._w = this.$.sliderBar.offsetWidth;
|
||||||
|
var rect = this.$.sliderBar.getBoundingClientRect();
|
||||||
|
var ratio = (event.detail.x - rect.left) / this._w;
|
||||||
|
var prevRatio = this.ratio;
|
||||||
|
|
||||||
|
this._setTransiting(true);
|
||||||
|
|
||||||
|
this._positionKnob(ratio);
|
||||||
|
|
||||||
|
this.debounce('expandKnob', this._expandKnob, 60);
|
||||||
|
|
||||||
|
// if the ratio doesn't change, sliderKnob's animation won't start
|
||||||
|
// and `_knobTransitionEnd` won't be called
|
||||||
|
// Therefore, we need to manually update the `transiting` state
|
||||||
|
|
||||||
|
if (prevRatio === this.ratio) {
|
||||||
|
this._setTransiting(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.async(function () {
|
||||||
|
this.fire('change');
|
||||||
|
});
|
||||||
|
|
||||||
|
// cancel selection
|
||||||
|
event.detail.sourceEvent.preventDefault();
|
||||||
|
},
|
||||||
|
|
||||||
|
_knobTransitionEnd: function (event) {
|
||||||
|
if (event.target === this.$.sliderKnob) {
|
||||||
|
this._setTransiting(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_maxMarkersChanged: function (maxMarkers) {
|
||||||
|
var l = (this.max - this.min) / this.step;
|
||||||
|
if (!this.snaps && l > maxMarkers) {
|
||||||
|
this._setMarkers([]);
|
||||||
|
} else {
|
||||||
|
this._setMarkers(new Array(l));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_getClassNames: function () {
|
||||||
|
var classes = {};
|
||||||
|
|
||||||
|
classes.disabled = this.disabled;
|
||||||
|
classes.pin = this.pin;
|
||||||
|
classes.snaps = this.snaps;
|
||||||
|
classes.ring = this.immediateValue <= this.min;
|
||||||
|
classes.expand = this.expand;
|
||||||
|
classes.dragging = this.dragging;
|
||||||
|
classes.transiting = this.transiting;
|
||||||
|
classes.editable = this.editable;
|
||||||
|
|
||||||
|
return Object.keys(classes).filter(
|
||||||
|
function (className) {
|
||||||
|
return classes[className];
|
||||||
|
}).join(' ');
|
||||||
|
},
|
||||||
|
|
||||||
|
_incrementKey: function (event) {
|
||||||
|
if (event.detail.key === 'end') {
|
||||||
|
this.value = this.max;
|
||||||
|
} else {
|
||||||
|
this.increment();
|
||||||
|
}
|
||||||
|
this.fire('change');
|
||||||
|
},
|
||||||
|
|
||||||
|
_decrementKey: function (event) {
|
||||||
|
if (event.detail.key === 'home') {
|
||||||
|
this.value = this.min;
|
||||||
|
} else {
|
||||||
|
this.decrement();
|
||||||
|
}
|
||||||
|
this.fire('change');
|
||||||
|
},
|
||||||
|
|
||||||
|
_setPinValue: function (value) {
|
||||||
|
this.pinValue = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increases value by `step` but not above `max`.
|
* Fired when the slider's value changes.
|
||||||
* @method increment
|
*
|
||||||
|
* @event value-change
|
||||||
*/
|
*/
|
||||||
increment: function() {
|
|
||||||
this.value = this._clampValue(this.value + this.step);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decreases value by `step` but not below `min`.
|
* Fired when the slider's immediateValue changes.
|
||||||
* @method decrement
|
*
|
||||||
|
* @event immediate-value-change
|
||||||
*/
|
*/
|
||||||
decrement: function() {
|
|
||||||
this.value = this._clampValue(this.value - this.step);
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateKnob: function(value) {
|
/**
|
||||||
this._positionKnob(this._calcRatio(value));
|
* Fired when the slider's value changes due to user interaction.
|
||||||
},
|
*
|
||||||
|
* Changes to the slider's value due to changes in an underlying
|
||||||
_minChanged: function() {
|
* bound variable will not trigger this event.
|
||||||
this.setAttribute('aria-valuemin', this.min);
|
*
|
||||||
},
|
* @event change
|
||||||
|
*/
|
||||||
_maxChanged: function() {
|
|
||||||
this.setAttribute('aria-valuemax', this.max);
|
|
||||||
},
|
|
||||||
|
|
||||||
_valueChanged: function() {
|
|
||||||
this.setAttribute('aria-valuenow', this.value);
|
|
||||||
this.fire('value-change');
|
|
||||||
},
|
|
||||||
|
|
||||||
_immediateValueChanged: function() {
|
|
||||||
if (this.dragging) {
|
|
||||||
this.fire('immediate-value-change');
|
|
||||||
} else {
|
|
||||||
this.value = this.immediateValue;
|
|
||||||
}
|
|
||||||
this._updateInputValue();
|
|
||||||
},
|
|
||||||
|
|
||||||
_secondaryProgressChanged: function() {
|
|
||||||
this.secondaryProgress = this._clampValue(this.secondaryProgress);
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateInputValue: function() {
|
|
||||||
if (this.editable) {
|
|
||||||
this.$$('#input').value = this.immediateValue.toString();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_expandKnob: function() {
|
|
||||||
this._setExpand(true);
|
|
||||||
},
|
|
||||||
|
|
||||||
_resetKnob: function() {
|
|
||||||
this.cancelDebouncer('expandKnob');
|
|
||||||
this._setExpand(false);
|
|
||||||
},
|
|
||||||
|
|
||||||
_positionKnob: function(ratio) {
|
|
||||||
this._setImmediateValue(this._calcStep(this._calcKnobPosition(ratio)));
|
|
||||||
this._setPinValue(this.immediateValue);
|
|
||||||
|
|
||||||
this._setRatio(this._calcRatio(this.immediateValue));
|
|
||||||
|
|
||||||
this.$.sliderKnob.style.left = (this.ratio * 100) + '%';
|
|
||||||
},
|
|
||||||
|
|
||||||
_inputChange: function() {
|
|
||||||
this.value = this.$$('#input').value;
|
|
||||||
this.fire('change');
|
|
||||||
},
|
|
||||||
|
|
||||||
_calcKnobPosition: function(ratio) {
|
|
||||||
return (this.max - this.min) * ratio + this.min;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onTrack: function(event) {
|
|
||||||
switch (event.detail.state) {
|
|
||||||
case 'start':
|
|
||||||
this._trackStart(event);
|
|
||||||
break;
|
|
||||||
case 'track':
|
|
||||||
this._trackX(event);
|
|
||||||
break;
|
|
||||||
case 'end':
|
|
||||||
this._trackEnd();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_trackStart: function(event) {
|
|
||||||
this._w = this.$.sliderBar.offsetWidth;
|
|
||||||
this._x = this.ratio * this._w;
|
|
||||||
this._startx = this._x || 0;
|
|
||||||
this._minx = - this._startx;
|
|
||||||
this._maxx = this._w - this._startx;
|
|
||||||
this.$.sliderKnob.classList.add('dragging');
|
|
||||||
|
|
||||||
this._setDragging(true);
|
|
||||||
},
|
|
||||||
|
|
||||||
_trackX: function(e) {
|
|
||||||
if (!this.dragging) {
|
|
||||||
this._trackStart(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
var dx = Math.min(this._maxx, Math.max(this._minx, e.detail.dx));
|
|
||||||
this._x = this._startx + dx;
|
|
||||||
|
|
||||||
var immediateValue = this._calcStep(this._calcKnobPosition(this._x / this._w));
|
|
||||||
this._setImmediateValue(immediateValue);
|
|
||||||
this._setPinValue(immediateValue);
|
|
||||||
|
|
||||||
// update knob's position
|
|
||||||
var translateX = ((this._calcRatio(immediateValue) * this._w) - this._startx);
|
|
||||||
this.translate3d(translateX + 'px', 0, 0, this.$.sliderKnob);
|
|
||||||
},
|
|
||||||
|
|
||||||
_trackEnd: function() {
|
|
||||||
var s = this.$.sliderKnob.style;
|
|
||||||
|
|
||||||
this.$.sliderKnob.classList.remove('dragging');
|
|
||||||
this._setDragging(false);
|
|
||||||
this._resetKnob();
|
|
||||||
this.value = this.immediateValue;
|
|
||||||
|
|
||||||
s.transform = s.webkitTransform = '';
|
|
||||||
|
|
||||||
this.fire('change');
|
|
||||||
},
|
|
||||||
|
|
||||||
_knobdown: function(event) {
|
|
||||||
this._expandKnob();
|
|
||||||
|
|
||||||
// cancel selection
|
|
||||||
event.detail.sourceEvent.preventDefault();
|
|
||||||
|
|
||||||
// set the focus manually because we will called prevent default
|
|
||||||
this.focus();
|
|
||||||
},
|
|
||||||
|
|
||||||
_bardown: function(event) {
|
|
||||||
this._w = this.$.sliderBar.offsetWidth;
|
|
||||||
var rect = this.$.sliderBar.getBoundingClientRect();
|
|
||||||
var ratio = (event.detail.x - rect.left) / this._w;
|
|
||||||
var prevRatio = this.ratio;
|
|
||||||
|
|
||||||
this._setTransiting(true);
|
|
||||||
|
|
||||||
this._positionKnob(ratio);
|
|
||||||
|
|
||||||
this.debounce('expandKnob', this._expandKnob, 60);
|
|
||||||
|
|
||||||
// if the ratio doesn't change, sliderKnob's animation won't start
|
|
||||||
// and `_knobTransitionEnd` won't be called
|
|
||||||
// Therefore, we need to manually update the `transiting` state
|
|
||||||
|
|
||||||
if (prevRatio === this.ratio) {
|
|
||||||
this._setTransiting(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.async(function() {
|
|
||||||
this.fire('change');
|
|
||||||
});
|
|
||||||
|
|
||||||
// cancel selection
|
|
||||||
event.detail.sourceEvent.preventDefault();
|
|
||||||
},
|
|
||||||
|
|
||||||
_knobTransitionEnd: function(event) {
|
|
||||||
if (event.target === this.$.sliderKnob) {
|
|
||||||
this._setTransiting(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_maxMarkersChanged: function(maxMarkers) {
|
|
||||||
var l = (this.max - this.min) / this.step;
|
|
||||||
if (!this.snaps && l > maxMarkers) {
|
|
||||||
this._setMarkers([]);
|
|
||||||
} else {
|
|
||||||
this._setMarkers(new Array(l));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_getClassNames: function() {
|
|
||||||
var classes = {};
|
|
||||||
|
|
||||||
classes.disabled = this.disabled;
|
|
||||||
classes.pin = this.pin;
|
|
||||||
classes.snaps = this.snaps;
|
|
||||||
classes.ring = this.immediateValue <= this.min;
|
|
||||||
classes.expand = this.expand;
|
|
||||||
classes.dragging = this.dragging;
|
|
||||||
classes.transiting = this.transiting;
|
|
||||||
classes.editable = this.editable;
|
|
||||||
|
|
||||||
return Object.keys(classes).filter(
|
|
||||||
function(className) {
|
|
||||||
return classes[className];
|
|
||||||
}).join(' ');
|
|
||||||
},
|
|
||||||
|
|
||||||
_incrementKey: function(event) {
|
|
||||||
if (event.detail.key === 'end') {
|
|
||||||
this.value = this.max;
|
|
||||||
} else {
|
|
||||||
this.increment();
|
|
||||||
}
|
|
||||||
this.fire('change');
|
|
||||||
},
|
|
||||||
|
|
||||||
_decrementKey: function(event) {
|
|
||||||
if (event.detail.key === 'home') {
|
|
||||||
this.value = this.min;
|
|
||||||
} else {
|
|
||||||
this.decrement();
|
|
||||||
}
|
|
||||||
this.fire('change');
|
|
||||||
},
|
|
||||||
|
|
||||||
_setPinValue: function (value) {
|
|
||||||
this.pinValue = value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when the slider's value changes.
|
|
||||||
*
|
|
||||||
* @event value-change
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when the slider's immediateValue changes.
|
|
||||||
*
|
|
||||||
* @event immediate-value-change
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when the slider's value changes due to user interaction.
|
|
||||||
*
|
|
||||||
* Changes to the slider's value due to changes in an underlying
|
|
||||||
* bound variable will not trigger this event.
|
|
||||||
*
|
|
||||||
* @event change
|
|
||||||
*/
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<iron-iconset-svg name="icons" size="24">
|
<iron-iconset-svg name="icons" size="24">
|
||||||
|
@ -17112,6 +17112,7 @@ paper-ripple {
|
||||||
<g id="keyboard-arrow-left"><path d="M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z"></path></g>
|
<g id="keyboard-arrow-left"><path d="M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z"></path></g>
|
||||||
<g id="keyboard-arrow-right"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></g>
|
<g id="keyboard-arrow-right"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></g>
|
||||||
<g id="keyboard-arrow-up"><path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path></g>
|
<g id="keyboard-arrow-up"><path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path></g>
|
||||||
|
<g id="queue-music"><path d="M15 6H3v2h12V6zm0 4H3v2h12v-2zM3 16h8v-2H3v2zM17 6v8.18c-.31-.11-.65-.18-1-.18-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3V8h3V6h-5z"></path></g>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
</iron-iconset-svg>
|
</iron-iconset-svg>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue