Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
397
gaia/tv_apps/smart-system/js/value_selector/spin_date_picker.js
Executable file
397
gaia/tv_apps/smart-system/js/value_selector/spin_date_picker.js
Executable file
|
|
@ -0,0 +1,397 @@
|
|||
/* global ValuePicker */
|
||||
/**
|
||||
* SpinDatePicker is a html/js "widget" which enables users
|
||||
* pick a specific date. It display the date in the way based
|
||||
* on the language setting.
|
||||
*
|
||||
* The SpinDatePicker itself contains no UI for the controls.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* // All necessary UI elements are contained in the root element.
|
||||
* var picker = new SpinDatePicker(root);
|
||||
* picker.value = new Date();
|
||||
* // after users pick a date
|
||||
* var newDate = picker.value;
|
||||
*/
|
||||
window.SpinDatePicker = (function() {
|
||||
'use strict';
|
||||
|
||||
var GLOBAL_MIN_YEAR = 1900;
|
||||
var GLOBAL_MAX_YEAR = 2099;
|
||||
|
||||
var DateRange = (function DateRange(min, max) {
|
||||
var _minYear = min.getFullYear();
|
||||
var _maxYear = max.getFullYear();
|
||||
var _minMonth = min.getMonth();
|
||||
var _maxMonth = max.getMonth();
|
||||
var _minDate = min.getDate();
|
||||
var _maxDate = max.getDate();
|
||||
|
||||
return {
|
||||
get min() {
|
||||
return min;
|
||||
},
|
||||
get max() {
|
||||
return max;
|
||||
},
|
||||
get minYear() {
|
||||
return _minYear;
|
||||
},
|
||||
get maxYear() {
|
||||
return _maxYear;
|
||||
},
|
||||
get minMonth() {
|
||||
return _minMonth;
|
||||
},
|
||||
get maxMonth() {
|
||||
return _maxMonth;
|
||||
},
|
||||
get minDate() {
|
||||
return _minDate;
|
||||
},
|
||||
get maxDate() {
|
||||
return _maxDate;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
var _dateRange = new DateRange(new Date(GLOBAL_MIN_YEAR, 0, 1),
|
||||
new Date(GLOBAL_MAX_YEAR, 11, 31));
|
||||
|
||||
function getYearText() {
|
||||
var yearText = [];
|
||||
var dateTimeFormat = navigator.mozL10n.DateTimeFormat();
|
||||
|
||||
for (var i = GLOBAL_MIN_YEAR; i <= GLOBAL_MAX_YEAR; i++) {
|
||||
var date = new Date(i, 0, 1);
|
||||
yearText.push(dateTimeFormat.localeFormat(date, '%Y'));
|
||||
}
|
||||
|
||||
return yearText;
|
||||
}
|
||||
|
||||
function getMonthText() {
|
||||
var monthText = [];
|
||||
var date = new Date(1970, 0, 1);
|
||||
var dateTimeFormat = navigator.mozL10n.DateTimeFormat();
|
||||
|
||||
for (var i = 0; i < 12; i++) {
|
||||
date.setMonth(i);
|
||||
monthText.push(dateTimeFormat.localeFormat(date, '%B'));
|
||||
}
|
||||
|
||||
return monthText;
|
||||
}
|
||||
|
||||
function getDateText() {
|
||||
var dateText = [];
|
||||
var date = new Date(1970, 0, 1);
|
||||
var dateTimeFormat = navigator.mozL10n.DateTimeFormat();
|
||||
|
||||
for (var i = 1; i <= 31; i++) {
|
||||
date.setDate(i);
|
||||
dateText.push(dateTimeFormat.localeFormat(date, '%d'));
|
||||
}
|
||||
|
||||
return dateText;
|
||||
}
|
||||
|
||||
function getDaysInMonth(year, month) {
|
||||
var date = new Date(year, month + 1, 0);
|
||||
return date.getDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the order of date components.
|
||||
*
|
||||
* @param {String} date format.
|
||||
*/
|
||||
function getDateComponentOrder() {
|
||||
var format = navigator.mozL10n.get('dateTimeFormat_%x');
|
||||
var order = '';
|
||||
var tokens = format.match(/(%E.|%O.|%.)/g);
|
||||
|
||||
if (tokens) {
|
||||
tokens.forEach(function(token) {
|
||||
switch (token) {
|
||||
case '%Y':
|
||||
case '%y':
|
||||
case '%Oy':
|
||||
case 'Ey':
|
||||
case 'EY':
|
||||
order += 'Y';
|
||||
break;
|
||||
case '%B':
|
||||
case '%b':
|
||||
case '%m':
|
||||
case '%Om':
|
||||
order += 'M';
|
||||
break;
|
||||
case '%d':
|
||||
case '%e':
|
||||
case '%Od':
|
||||
case '%Oe':
|
||||
order += 'D';
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (order.length != 3) {
|
||||
order = 'DMY';
|
||||
}
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a date picker widget.
|
||||
*
|
||||
* @param {HTMLELement} element target of widget creation.
|
||||
*/
|
||||
function SpinDatePicker(element, minDate, maxDate) {
|
||||
this.element = element;
|
||||
|
||||
this.yearPicker = null;
|
||||
this.monthPicker = null;
|
||||
this.datePicker = null;
|
||||
|
||||
//XXX: When the document is localized again
|
||||
// we must also re-render the month because
|
||||
// the week days may have changed?
|
||||
// This will only happen when we change timezones
|
||||
// unless we add this information to the locales.
|
||||
|
||||
var pickerContainer =
|
||||
element.querySelector('.picker-container');
|
||||
var yearPickerContainer =
|
||||
element.querySelector('.value-picker-year');
|
||||
var monthPickerContainer =
|
||||
element.querySelector('.value-picker-month');
|
||||
var datePickerContainer =
|
||||
element.querySelector('.value-picker-date');
|
||||
|
||||
var updateCurrentValue = (function spd_updateCurrentValue() {
|
||||
var selectedYear = this.yearPicker.getSelectedIndex() + GLOBAL_MIN_YEAR;
|
||||
var selectedMonth = this.monthPicker.getSelectedIndex();
|
||||
var selectedDate = this.datePicker.getSelectedIndex() + 1;
|
||||
|
||||
this._value = new Date(selectedYear, selectedMonth, selectedDate);
|
||||
}).bind(this);
|
||||
|
||||
var updatePickersRange =
|
||||
(function spd_updatePickersRange() {
|
||||
var selectedYear = this.yearPicker.getSelectedIndex() + GLOBAL_MIN_YEAR;
|
||||
var selectedMonth = this.monthPicker.getSelectedIndex();
|
||||
|
||||
var minMonth = 0;
|
||||
var maxMonth = 11;
|
||||
var minDate = 1;
|
||||
var maxDate = 31;
|
||||
|
||||
if (selectedYear === _dateRange.minYear) {
|
||||
minMonth = _dateRange.minMonth;
|
||||
if (selectedMonth === _dateRange.minMonth) {
|
||||
minDate = _dateRange.minDate;
|
||||
}
|
||||
}
|
||||
if (selectedYear === _dateRange.maxYear) {
|
||||
maxMonth = _dateRange.maxMonth;
|
||||
if (selectedMonth === _dateRange.maxMonth) {
|
||||
maxDate = _dateRange.maxDate;
|
||||
}
|
||||
}
|
||||
|
||||
var days = getDaysInMonth(this.yearPicker.getSelectedIndex() +
|
||||
GLOBAL_MIN_YEAR, this.monthPicker.getSelectedIndex());
|
||||
minDate = Math.min(minDate, days);
|
||||
maxDate = Math.min(maxDate, days);
|
||||
|
||||
this.monthPicker.setRange(minMonth, maxMonth);
|
||||
this.datePicker.setRange(minDate - 1, maxDate - 1);
|
||||
}).bind(this);
|
||||
|
||||
var onvaluechangeInternal =
|
||||
(function spd_onvaluechangeInternal(newDateValue) {
|
||||
this.yearPicker.setSelectedIndex(
|
||||
newDateValue.getFullYear() - GLOBAL_MIN_YEAR);
|
||||
this.monthPicker.setSelectedIndex(newDateValue.getMonth());
|
||||
this.datePicker.setSelectedIndex(newDateValue.getDate() - 1);
|
||||
updatePickersRange.apply(this);
|
||||
updateCurrentValue.apply(this);
|
||||
}).bind(this);
|
||||
|
||||
var onSelectedYearChanged =
|
||||
function spd_onSelectedYearChanged(selectedYear) {
|
||||
updatePickersRange.apply(this);
|
||||
updateCurrentValue.apply(this);
|
||||
};
|
||||
|
||||
var onSelectedMonthChanged =
|
||||
function spd_onSelectedMonthChanged(selectedMonth) {
|
||||
updatePickersRange.apply(this);
|
||||
updateCurrentValue.apply(this);
|
||||
};
|
||||
|
||||
var onSelectedDateChanged =
|
||||
function spd_onSelectedDateChanged(selectedDate) {
|
||||
updateCurrentValue.apply(this);
|
||||
};
|
||||
|
||||
var unitClassName = 'picker-unit';
|
||||
|
||||
// year value picker
|
||||
var yearUnitStyle = {
|
||||
valueDisplayedText: getYearText(),
|
||||
className: unitClassName
|
||||
};
|
||||
if (this.yearPicker) {
|
||||
this.yearPicker.uninit();
|
||||
}
|
||||
this.yearPicker = new ValuePicker(yearPickerContainer, yearUnitStyle);
|
||||
this.yearPicker.onselectedindexchange = onSelectedYearChanged.bind(this);
|
||||
|
||||
// month value picker
|
||||
var monthUnitStyle = {
|
||||
valueDisplayedText: getMonthText(),
|
||||
className: unitClassName
|
||||
};
|
||||
if (this.monthPicker) {
|
||||
this.monthPicker.uninit();
|
||||
}
|
||||
this.monthPicker =
|
||||
new ValuePicker(monthPickerContainer, monthUnitStyle);
|
||||
this.monthPicker.onselectedindexchange = onSelectedMonthChanged.bind(this);
|
||||
|
||||
// date value picker
|
||||
var dateUnitStyle = {
|
||||
valueDisplayedText: getDateText(),
|
||||
className: unitClassName
|
||||
};
|
||||
if (this.datePicker) {
|
||||
this.datePicker.uninit();
|
||||
}
|
||||
this.datePicker = new ValuePicker(datePickerContainer, dateUnitStyle);
|
||||
this.datePicker.onselectedindexchange =
|
||||
onSelectedDateChanged.bind(this);
|
||||
|
||||
// set component order
|
||||
var dateComponentOrder = getDateComponentOrder();
|
||||
var pickerClassList = pickerContainer.classList;
|
||||
pickerClassList.remove('YMD');
|
||||
pickerClassList.remove('DMY');
|
||||
pickerClassList.remove('MDY');
|
||||
pickerClassList.add(dateComponentOrder);
|
||||
|
||||
// Prevent focus being taken away by us for time picker.
|
||||
// The event listener on outer box will not be triggered cause
|
||||
// there is a evt.stopPropagation() in value_picker.js
|
||||
this.pickerElements = [monthPickerContainer, yearPickerContainer,
|
||||
datePickerContainer];
|
||||
|
||||
this.pickerElements.forEach((function pickerElements_forEach(picker) {
|
||||
picker.addEventListener('mousedown', this);
|
||||
}).bind(this));
|
||||
|
||||
this.onvaluechangeInternal = onvaluechangeInternal.bind(this);
|
||||
}
|
||||
|
||||
SpinDatePicker.prototype = {
|
||||
|
||||
/**
|
||||
* Internal value not exposed so we can fire events
|
||||
* when the getter/setter's are used.
|
||||
*
|
||||
* @type Date
|
||||
*/
|
||||
_value: null,
|
||||
|
||||
/**
|
||||
* Gets current value
|
||||
*
|
||||
* @return {Null|Date} date or null.
|
||||
*/
|
||||
get value() {
|
||||
return this._value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the current value of the date picker.
|
||||
* When value differs from the currently set the
|
||||
* `onvaluechange` event will be fired with the new/old value.
|
||||
*/
|
||||
set value(value) {
|
||||
var old = this._value;
|
||||
if (old !== value) {
|
||||
this._value = value;
|
||||
this.onvaluechangeInternal(value);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Getter is used for date normalization.
|
||||
*/
|
||||
get year() {
|
||||
return this._value.getFullYear();
|
||||
},
|
||||
|
||||
/**
|
||||
* Getter is used for date normalization.
|
||||
*/
|
||||
get month() {
|
||||
return this._value.getMonth();
|
||||
},
|
||||
|
||||
get date() {
|
||||
return this._value.getDate();
|
||||
},
|
||||
|
||||
handleEvent: function vs_handleEvent(evt) {
|
||||
switch (evt.type) {
|
||||
case 'mousedown':
|
||||
// Prevent focus being taken away by us.
|
||||
evt.preventDefault();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
setRange: function vs_setRange(minDate, maxDate) {
|
||||
if (!minDate) {
|
||||
minDate = new Date(GLOBAL_MIN_YEAR, 0, 1);
|
||||
}
|
||||
if (!maxDate) {
|
||||
maxDate = new Date(GLOBAL_MAX_YEAR, 11, 31);
|
||||
}
|
||||
|
||||
_dateRange = new DateRange(minDate, maxDate);
|
||||
|
||||
// set date picker
|
||||
this.yearPicker.setRange(minDate.getFullYear() - GLOBAL_MIN_YEAR,
|
||||
maxDate.getFullYear() - GLOBAL_MIN_YEAR);
|
||||
},
|
||||
|
||||
uninit: function() {
|
||||
if (this.yearPicker) {
|
||||
this.yearPicker.uninit();
|
||||
}
|
||||
if (this.monthPicker) {
|
||||
this.monthPicker.uninit();
|
||||
}
|
||||
if (this.datePicker) {
|
||||
this.datePicker.uninit();
|
||||
}
|
||||
|
||||
this.pickerElements.forEach((function pickerElements_forEach(picker) {
|
||||
picker.removeEventListener('mousedown', this);
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the selected date changes.
|
||||
*/
|
||||
onvaluechangeInternal: function(date) {}
|
||||
};
|
||||
|
||||
return SpinDatePicker;
|
||||
}());
|
||||
284
gaia/tv_apps/smart-system/js/value_selector/value_picker.js
Executable file
284
gaia/tv_apps/smart-system/js/value_selector/value_picker.js
Executable file
|
|
@ -0,0 +1,284 @@
|
|||
/* global KeyEvent */
|
||||
/**
|
||||
* base widget used in ValueSelector and SpinDatePicker widget
|
||||
*/
|
||||
window.ValuePicker = (function() {
|
||||
'use strict';
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
function VP(e, unitStyle) {
|
||||
this.element = e;
|
||||
this.container = e.parentNode;
|
||||
this._valueDisplayedText = unitStyle.valueDisplayedText;
|
||||
this._unitClassName = unitStyle.className;
|
||||
this._top = 0;
|
||||
this._lower = 0;
|
||||
this._upper = unitStyle.valueDisplayedText.length - 1;
|
||||
this._range = unitStyle.valueDisplayedText.length;
|
||||
this._unitStyle = unitStyle;
|
||||
this._currentIndex = 0;
|
||||
this.init();
|
||||
}
|
||||
|
||||
//
|
||||
// Public methods
|
||||
//
|
||||
VP.prototype.getSelectedIndex = function() {
|
||||
var selectedIndex = this._currentIndex;
|
||||
return selectedIndex;
|
||||
};
|
||||
|
||||
VP.prototype.getSelectedDisplayedText = function() {
|
||||
var displayedText = this._valueDisplayedText[this._currentIndex];
|
||||
return displayedText;
|
||||
};
|
||||
|
||||
VP.prototype.setSelectedIndex = function(tunedIndex, ignorePicker) {
|
||||
if ((tunedIndex % 1) > 0.5) {
|
||||
tunedIndex = Math.floor(tunedIndex) + 1;
|
||||
} else {
|
||||
tunedIndex = Math.floor(tunedIndex);
|
||||
}
|
||||
|
||||
if (tunedIndex < this._lower) {
|
||||
tunedIndex = this._lower;
|
||||
}
|
||||
|
||||
if (tunedIndex > this._upper) {
|
||||
tunedIndex = this._upper;
|
||||
}
|
||||
|
||||
var beforeIndex = this._currentIndex;
|
||||
if (this._currentIndex != tunedIndex) {
|
||||
this._currentIndex = tunedIndex;
|
||||
this.onselectedindexchange(this._currentIndex);
|
||||
}
|
||||
this.updateUI(tunedIndex, ignorePicker);
|
||||
|
||||
var elementChildren = this.element.children;
|
||||
elementChildren[beforeIndex].classList.remove('selected');
|
||||
elementChildren[this._currentIndex].classList.add('selected');
|
||||
|
||||
return tunedIndex;
|
||||
};
|
||||
|
||||
VP.prototype.setSelectedIndexByDisplayedText = function(displayedText) {
|
||||
var newIndex = this._valueDisplayedText.indexOf(displayedText);
|
||||
if (newIndex != -1) {
|
||||
if (this._currentIndex != newIndex) {
|
||||
this.setSelectedIndex(newIndex);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VP.prototype.setRange = function(lower, upper) {
|
||||
if (lower !== null) {
|
||||
this._lower = lower;
|
||||
} else {
|
||||
this._lower = 0;
|
||||
}
|
||||
|
||||
if (upper !== null) {
|
||||
this._upper = upper;
|
||||
} else {
|
||||
this._upper = this._unitStyle.valueDisplayedText.length - 1;
|
||||
}
|
||||
|
||||
var unitElement = this.element.firstElementChild;
|
||||
var index = 0;
|
||||
while (unitElement) {
|
||||
unitElement.dataset.disabled =
|
||||
(index < this._lower || index > this._upper);
|
||||
unitElement = unitElement.nextElementSibling;
|
||||
index++;
|
||||
}
|
||||
|
||||
this.container.setAttribute('aria-valuemin', this._lower);
|
||||
this.container.setAttribute('aria-valuemax', this._upper);
|
||||
|
||||
this._range = this._upper - this._lower + 1;
|
||||
this.setSelectedIndex(this._currentIndex);
|
||||
};
|
||||
|
||||
//
|
||||
// Internal methods
|
||||
//
|
||||
VP.prototype.init = function() {
|
||||
this.initUI();
|
||||
this.setSelectedIndex(0); // Default Index is zero
|
||||
this.keypressHandler = vp_keypress.bind(this);
|
||||
this.touchstartHandler = vp_touchstart.bind(this);
|
||||
this.touchmoveHandler = vp_touchmove.bind(this);
|
||||
this.touchendHandler = vp_touchend.bind(this);
|
||||
this.addEventListeners();
|
||||
};
|
||||
|
||||
VP.prototype.initUI = function() {
|
||||
this.container.setAttribute('role', 'spinbutton');
|
||||
this.container.setAttribute('aria-valuemin', this._lower);
|
||||
this.container.setAttribute('aria-valuemax', this._upper);
|
||||
var unitCount = this._valueDisplayedText.length;
|
||||
for (var i = 0; i < unitCount; ++i) {
|
||||
this.addPickerUnit(i);
|
||||
}
|
||||
// cache the size of picker
|
||||
this._pickerUnits = this.element.children;
|
||||
this._pickerUnitsHeight = this._pickerUnits[0].clientHeight;
|
||||
this._pickerHeight = this._pickerUnits[0].clientHeight *
|
||||
this._pickerUnits.length;
|
||||
this._space = this._pickerHeight / this._range;
|
||||
};
|
||||
|
||||
VP.prototype.addPickerUnit = function(index) {
|
||||
var html = this._valueDisplayedText[index];
|
||||
var unit = document.createElement('div');
|
||||
unit.className = this._unitClassName;
|
||||
unit.textContent = html;
|
||||
this.element.appendChild(unit);
|
||||
};
|
||||
|
||||
VP.prototype.updateUI = function(index, ignorePicker) {
|
||||
if (true !== ignorePicker) {
|
||||
this._top = -index * this._space;
|
||||
this.element.style.transform = 'translateY(' + this._top + 'px)';
|
||||
this.container.setAttribute('aria-valuenow', index);
|
||||
this.container.setAttribute('aria-valuetext',
|
||||
this._valueDisplayedText[index]);
|
||||
}
|
||||
};
|
||||
|
||||
VP.prototype.addEventListeners = function() {
|
||||
this.container.addEventListener('keypress', this.keypressHandler, false);
|
||||
this.element.addEventListener('touchstart', this.touchstartHandler, false);
|
||||
};
|
||||
|
||||
VP.prototype.removeEventListeners = function() {
|
||||
this.element.removeEventListener('touchend', this.touchendHandler, false);
|
||||
this.element.removeEventListener('touchmove', this.touchmoveHandler, false);
|
||||
};
|
||||
|
||||
VP.prototype.uninit = function() {
|
||||
this._top = 0;
|
||||
this.element.removeEventListener(
|
||||
'touchstart', this.touchstartHandler, false);
|
||||
this.element.removeEventListener('touchend', this.touchendHandler, false);
|
||||
this.element.removeEventListener('touchmove', this.touchmoveHandler, false);
|
||||
this.element.style.transform = 'translateY(0px)';
|
||||
this.container.removeEventListener('keypress', this.keypressHandler, false);
|
||||
this.container.removeAttribute('role');
|
||||
this.container.removeAttribute('aria-valuemin');
|
||||
this.container.removeAttribute('aria-valuemax');
|
||||
this.container.removeAttribute('aria-valuenow');
|
||||
this.container.removeAttribute('aria-valuetext');
|
||||
this.onselectedindexchange = null;
|
||||
empty(this.element);
|
||||
};
|
||||
|
||||
VP.prototype.onselectedindexchange = function(index) {};
|
||||
|
||||
function cloneEvent(evt) {
|
||||
return {
|
||||
x: evt.touches[0].pageX,
|
||||
y: evt.touches[0].pageY,
|
||||
timestamp: evt.timeStamp
|
||||
};
|
||||
}
|
||||
|
||||
function empty(element) {
|
||||
while (element.hasChildNodes()) {
|
||||
element.removeChild(element.lastChild);
|
||||
}
|
||||
element.innerHTML = '';
|
||||
}
|
||||
|
||||
//
|
||||
// Tuneable parameters
|
||||
//
|
||||
var SPEED_THRESHOLD = 0.1;
|
||||
var currentEvent, startEvent, currentSpeed;
|
||||
var tunedIndex = 0;
|
||||
|
||||
function toFixed(value) {
|
||||
return parseFloat(value.toFixed(1));
|
||||
}
|
||||
|
||||
function calcSpeed() {
|
||||
var movingSpace = startEvent.y - currentEvent.y;
|
||||
var deltaTime = currentEvent.timestamp - startEvent.timestamp;
|
||||
var speed = movingSpace / deltaTime;
|
||||
currentSpeed = parseFloat(speed.toFixed(2));
|
||||
}
|
||||
|
||||
function calcTargetIndex(space) {
|
||||
return tunedIndex - getMovingSpace() / space;
|
||||
}
|
||||
|
||||
// If the user swap really slow, narrow down the moving space
|
||||
// So the user can fine tune value.
|
||||
function getMovingSpace() {
|
||||
var movingSpace = currentEvent.y - startEvent.y;
|
||||
var reValue = Math.abs(currentSpeed) > SPEED_THRESHOLD ?
|
||||
movingSpace : movingSpace / 4;
|
||||
return reValue;
|
||||
}
|
||||
|
||||
function vp_touchmove(event) {
|
||||
/*jshint validthis: true */
|
||||
event.stopPropagation();
|
||||
event.target.setCapture(true);
|
||||
currentEvent = cloneEvent(event);
|
||||
|
||||
calcSpeed();
|
||||
|
||||
// move selected index
|
||||
this._top = this._top + getMovingSpace();
|
||||
this.element.style.transform = 'translateY(' + this._top + 'px)';
|
||||
|
||||
tunedIndex = calcTargetIndex(this._space);
|
||||
var roundedIndex = Math.round(tunedIndex * 10) / 10;
|
||||
|
||||
if (roundedIndex != this._currentIndex) {
|
||||
this.setSelectedIndex(toFixed(roundedIndex), true);
|
||||
}
|
||||
|
||||
startEvent = currentEvent;
|
||||
}
|
||||
|
||||
function vp_touchend(event) {
|
||||
/*jshint validthis: true */
|
||||
event.stopPropagation();
|
||||
this.removeEventListeners();
|
||||
|
||||
// Add momentum if speed is higher than a given threshold.
|
||||
if (Math.abs(currentSpeed) > SPEED_THRESHOLD) {
|
||||
var direction = currentSpeed > 0 ? 1 : -1;
|
||||
tunedIndex += Math.min(Math.abs(currentSpeed) * 5, 5) * direction;
|
||||
}
|
||||
tunedIndex = this.setSelectedIndex(toFixed(tunedIndex));
|
||||
currentSpeed = 0;
|
||||
}
|
||||
|
||||
function vp_touchstart(event) {
|
||||
/*jshint validthis: true */
|
||||
event.stopPropagation();
|
||||
|
||||
startEvent = currentEvent = cloneEvent(event);
|
||||
tunedIndex = this._currentIndex;
|
||||
|
||||
this.removeEventListeners();
|
||||
this.element.addEventListener('touchmove', this.touchmoveHandler, false);
|
||||
this.element.addEventListener('touchend', this.touchendHandler, false);
|
||||
}
|
||||
|
||||
function vp_keypress(event) {
|
||||
/*jshint validthis: true */
|
||||
if (event.keyCode == KeyEvent.DOM_VK_DOWN) {
|
||||
this.setSelectedIndex(this._currentIndex - 1);
|
||||
} else {
|
||||
this.setSelectedIndex(this._currentIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return VP;
|
||||
}());
|
||||
648
gaia/tv_apps/smart-system/js/value_selector/value_selector.js
Executable file
648
gaia/tv_apps/smart-system/js/value_selector/value_selector.js
Executable file
|
|
@ -0,0 +1,648 @@
|
|||
/* global BaseUI, LazyLoader, InputParser, ValueSelector, SpinDatePicker,
|
||||
ValuePicker, Template */
|
||||
|
||||
'use strict';
|
||||
|
||||
(function(exports) {
|
||||
|
||||
var _id = 0;
|
||||
|
||||
function toCamelCase(str) {
|
||||
return str.replace(/\-(.)/g, function replacer(str, p1) {
|
||||
return p1.toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
exports.ValueSelector = function(app) {
|
||||
this.app = app;
|
||||
this.containerElement = app.element;
|
||||
this.instanceID = _id++;
|
||||
this._currentPickerType = null;
|
||||
this._currentInputType = null;
|
||||
this._currentDatetimeValue = '';
|
||||
this._injected = false;
|
||||
this._datePicker = null;
|
||||
this._timePicker = null;
|
||||
|
||||
app.element.addEventListener('_opening', this);
|
||||
app.element.addEventListener('_closing', this);
|
||||
app.element.addEventListener('_inputmethod-contextchange', this);
|
||||
app.element.addEventListener('_sheetsgesturebegin', this);
|
||||
app.element.addEventListener('_localized', this);
|
||||
window.addEventListener('timeformatchange', this);
|
||||
};
|
||||
|
||||
ValueSelector.prototype = Object.create(BaseUI.prototype);
|
||||
|
||||
ValueSelector.prototype.CLASS_NAME = 'ValueSelector';
|
||||
|
||||
ValueSelector.prototype.ELEMENT_PREFIX = 'value-selector-';
|
||||
|
||||
ValueSelector.prototype.EVENT_PREFIX = 'value-selector-';
|
||||
|
||||
ValueSelector.prototype.customID = function vs_customID() {
|
||||
if (this.app) {
|
||||
return '[' + this.app.origin + ']';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
ValueSelector.prototype._im = navigator.mozInputMethod;
|
||||
|
||||
ValueSelector.prototype.destroy = function() {
|
||||
window.removeEventListener('timeformatchange', this);
|
||||
};
|
||||
|
||||
ValueSelector.prototype.handleEvent = function vs_handleEvent(evt) {
|
||||
this.app.debug('handling ' + evt.type);
|
||||
var target = evt.target;
|
||||
switch (evt.type) {
|
||||
case 'submit':
|
||||
case 'mousedown':
|
||||
evt.preventDefault();
|
||||
break;
|
||||
case 'click':
|
||||
if (target.dataset.type === 'cancel') {
|
||||
this.cancel();
|
||||
} else if (target.dataset.type === 'ok') {
|
||||
this.confirm();
|
||||
} else {
|
||||
this.handleSelect(target);
|
||||
}
|
||||
break;
|
||||
case '_opening':
|
||||
case '_closing':
|
||||
if (this._injected) {
|
||||
this.hide();
|
||||
}
|
||||
break;
|
||||
case '_localized':
|
||||
// invalidate the current date and time picker when language setting
|
||||
// changes
|
||||
if (this._datePicker) {
|
||||
this._datePicker.uninit();
|
||||
this._datePicker = null;
|
||||
}
|
||||
if (this._timePicker) {
|
||||
this._timePicker.uninit();
|
||||
this._timePicker = null;
|
||||
}
|
||||
break;
|
||||
case 'timeformatchange':
|
||||
if (this._timePicker) {
|
||||
this._timePicker.uninit();
|
||||
this._timePicker = null;
|
||||
}
|
||||
break;
|
||||
case '_sheetsgesturebegin':
|
||||
// Only cancel if the value selector was rendered.
|
||||
if (this._injected) {
|
||||
this.cancel();
|
||||
}
|
||||
break;
|
||||
case '_inputmethod-contextchange':
|
||||
var typesToHandle = ['select-one', 'select-multiple', 'date', 'time',
|
||||
'datetime', 'datetime-local', 'blur'];
|
||||
// handle the <select> element and inputs with type of date/time
|
||||
// in system app for now
|
||||
if (typesToHandle.indexOf(evt.detail.inputType) < 0) {
|
||||
return;
|
||||
}
|
||||
if (this._injected) {
|
||||
this.show(evt.detail);
|
||||
} else {
|
||||
this.render(function afterRender() {
|
||||
this.show(evt.detail);
|
||||
}.bind(this));
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
ValueSelector.prototype.render = function vs_render(callback) {
|
||||
this.publish('willrender');
|
||||
LazyLoader.load('shared/js/template.js', function onTemplateLoaded(){
|
||||
this.containerElement.insertAdjacentHTML('beforeend', this.view());
|
||||
this._fetchElements();
|
||||
this._registerEvents();
|
||||
this._injected = true;
|
||||
this.publish('rendered');
|
||||
callback();
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ValueSelector.prototype._fetchElements = function vs__fetchElements() {
|
||||
this.element = document.getElementById(this.CLASS_NAME + this.instanceID);
|
||||
this.elements = {};
|
||||
|
||||
this.elementClasses = ['select-option-popup', 'container',
|
||||
'options-container', 'options-title', 'select-options-buttons',
|
||||
'time-picker-popup', 'time-picker', 'time-picker-container',
|
||||
'time-picker-buttons', 'spin-date-picker-popup', 'spin-date-picker',
|
||||
'spin-date-picker-buttons'];
|
||||
|
||||
// Loop and add element with camel style name to Value Selector attribute.
|
||||
this.elementClasses.forEach(function createElementRef(name) {
|
||||
this.elements[toCamelCase(name)] =
|
||||
this.element.querySelector('.' + this.ELEMENT_PREFIX + name);
|
||||
}, this);
|
||||
};
|
||||
|
||||
ValueSelector.prototype.view = function vs_view() {
|
||||
var template = new Template('value-selector-template');
|
||||
return template.interpolate({
|
||||
id: this.CLASS_NAME + this.instanceID
|
||||
});
|
||||
};
|
||||
|
||||
ValueSelector.prototype._registerEvents = function vs__registerEvents() {
|
||||
this.elements.container.addEventListener('click', this);
|
||||
// Prevent the form from submit.
|
||||
this.elements.selectOptionPopup.addEventListener('submit', this);
|
||||
this.element.addEventListener('mousedown', this);
|
||||
['selectOptionsButtons', 'timePickerButtons',
|
||||
'spinDatePickerButtons'].forEach(function(elementId) {
|
||||
this.elements[elementId].addEventListener('click', this);
|
||||
}, this);
|
||||
};
|
||||
|
||||
ValueSelector.prototype._format = function vs__format(date, format) {
|
||||
if (!date) {
|
||||
return '';
|
||||
}
|
||||
date = new Date(date);
|
||||
return date.toLocaleFormat(format);
|
||||
};
|
||||
|
||||
ValueSelector.prototype.show = function vs_show(detail) {
|
||||
var currentInputType = detail.inputType;
|
||||
var currentValue = detail.value;
|
||||
|
||||
this._currentDatetimeValue = currentValue;
|
||||
this._currentInputType = currentInputType;
|
||||
|
||||
if (currentInputType === 'blur') {
|
||||
this.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
this.publish('shown');
|
||||
var min = detail.min;
|
||||
var max = detail.max;
|
||||
|
||||
if (detail.choices) {
|
||||
detail.choices = JSON.parse(detail.choices);
|
||||
}
|
||||
|
||||
this.app._setVisibleForScreenReader(false);
|
||||
if (this.element.hidden) {
|
||||
this.element.hidden = false;
|
||||
}
|
||||
|
||||
switch (currentInputType) {
|
||||
case 'select-one':
|
||||
case 'select-multiple':
|
||||
this.app.debug('select triggered' + JSON.stringify(detail));
|
||||
this._currentPickerType = currentInputType;
|
||||
this.showOptions(detail);
|
||||
break;
|
||||
|
||||
case 'date':
|
||||
this.showDatePicker(currentValue, min, max);
|
||||
break;
|
||||
|
||||
case 'time':
|
||||
this.showTimePicker(currentValue);
|
||||
break;
|
||||
|
||||
case 'datetime':
|
||||
case 'datetime-local':
|
||||
this.showDatePicker(this._format(currentValue, '%Y-%m-%d'), min,
|
||||
max);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
ValueSelector.prototype.showPanel = function vs_showPanel(type) {
|
||||
['selectOptionPopup', 'timePickerPopup', 'spinDatePickerPopup'].forEach(
|
||||
function(elementId) {
|
||||
this.elements[elementId].hidden = (type !== elementId);
|
||||
}, this);
|
||||
},
|
||||
|
||||
ValueSelector.prototype.hide = function vs_hide() {
|
||||
this.app._setVisibleForScreenReader(true);
|
||||
if (this.element.hidden) {
|
||||
return;
|
||||
}
|
||||
this.element.blur();
|
||||
this.element.hidden = true;
|
||||
if (this.app) {
|
||||
this.app.focus();
|
||||
}
|
||||
this.publish('hidden');
|
||||
};
|
||||
|
||||
ValueSelector.prototype.handleSelect = function vs_handleSelect(target) {
|
||||
if (target.dataset === undefined ||
|
||||
(target.dataset.optionIndex === undefined &&
|
||||
target.dataset.optionValue === undefined)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var selectee;
|
||||
if (this._currentPickerType === 'select-one') {
|
||||
selectee = this.elements.container.querySelectorAll(
|
||||
'[aria-selected="true"]');
|
||||
for (var i = 0; i < selectee.length; i++) {
|
||||
selectee[i].removeAttribute('aria-selected');
|
||||
}
|
||||
|
||||
target.setAttribute('aria-selected', 'true');
|
||||
} else if (target.getAttribute('aria-selected') === 'true') {
|
||||
target.removeAttribute('aria-selected');
|
||||
} else {
|
||||
target.setAttribute('aria-selected', 'true');
|
||||
}
|
||||
|
||||
// setValue here to trigger change event
|
||||
var singleOptionIndex;
|
||||
var optionIndices = [];
|
||||
|
||||
selectee = this.elements.container.querySelectorAll(
|
||||
'[aria-selected="true"]');
|
||||
|
||||
if (this._currentPickerType === 'select-one') {
|
||||
|
||||
if (selectee.length > 0) {
|
||||
singleOptionIndex = selectee[0].dataset.optionIndex;
|
||||
}
|
||||
|
||||
this._im.setSelectedOption(singleOptionIndex);
|
||||
|
||||
} else if (this._currentPickerType === 'select-multiple') {
|
||||
// Multiple select case
|
||||
for (var i = 0; i < selectee.length; i++) { // jshint ignore:line
|
||||
|
||||
var index = parseInt(selectee[i].dataset.optionIndex);
|
||||
optionIndices.push(index);
|
||||
}
|
||||
|
||||
this._im.setSelectedOptions(optionIndices);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ValueSelector.prototype.cancel = function vs_cancel() {
|
||||
this.app.debug('cancel invoked');
|
||||
this._im.removeFocus();
|
||||
this.hide();
|
||||
};
|
||||
|
||||
ValueSelector.prototype.confirm = function vs_confirm() {
|
||||
var currentInputType = this._currentInputType;
|
||||
|
||||
switch (currentInputType) {
|
||||
case 'time':
|
||||
var timeValue = this._timePicker.getTimeValue();
|
||||
this.app.debug('output value: ' + timeValue);
|
||||
this._im.setValue(timeValue);
|
||||
break;
|
||||
case 'date':
|
||||
// The format should be 2012-09-19
|
||||
var dateValue = this._format(this._datePicker.value, '%Y-%m-%d');
|
||||
this.app.debug('output value: ' + dateValue);
|
||||
this._im.setValue(dateValue);
|
||||
break;
|
||||
case 'datetime':
|
||||
case 'datetime-local':
|
||||
var currentDatetimeValue = this._currentDatetimeValue;
|
||||
if (this._currentPickerType === 'date') {
|
||||
this.hide();
|
||||
this.showTimePicker(this._format(currentDatetimeValue, '%H:%M'));
|
||||
return;
|
||||
} else if (this._currentPickerType === 'time') {
|
||||
var selectedDate = this._datePicker.value;
|
||||
var hour = this._timePicker.getHour();
|
||||
var minute = this._timePicker.minute.getSelectedDisplayedText();
|
||||
var second = '';
|
||||
var millisecond = '';
|
||||
var date = null;
|
||||
// The second and millisecond values can't be selected by picker.
|
||||
// So set these values as same as
|
||||
// the current value of datetime/datetime-local input field
|
||||
// when currentDatetimeValue is not equal to ''(space),
|
||||
// or set the values as same as current time.
|
||||
if (currentDatetimeValue !== '') {
|
||||
date = new Date(this._currentDatetimeValue);
|
||||
} else {
|
||||
date = new Date();
|
||||
}
|
||||
second = date.getSeconds();
|
||||
millisecond = date.getMilliseconds();
|
||||
|
||||
selectedDate.setHours(hour);
|
||||
selectedDate.setMinutes(minute);
|
||||
selectedDate.setSeconds(second);
|
||||
selectedDate.setMilliseconds(millisecond);
|
||||
|
||||
var datetimeValue = '';
|
||||
if (currentInputType === 'datetime') {
|
||||
// The datetime format should be 1983-09-08T14:54:39.123Z
|
||||
datetimeValue = selectedDate.toISOString();
|
||||
} else { // if (currentInputType === 'datetime-local')
|
||||
// The datetime-local format should be 1983-09-08T14:54:39.123
|
||||
datetimeValue = selectedDate.toLocaleFormat('%Y-%m-%dT%H:%M:%S.') +
|
||||
selectedDate.getMilliseconds();
|
||||
}
|
||||
this.app.debug('output value: ' + datetimeValue);
|
||||
this._im.setValue(datetimeValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
this._im.removeFocus();
|
||||
this.hide();
|
||||
};
|
||||
|
||||
ValueSelector.prototype.showOptions = function vs_showOptions(detail) {
|
||||
var options = null;
|
||||
if (detail.choices && detail.choices.choices) {
|
||||
options = detail.choices.choices;
|
||||
}
|
||||
|
||||
if (options) {
|
||||
this.buildOptions(options);
|
||||
}
|
||||
|
||||
this.showPanel('selectOptionPopup');
|
||||
};
|
||||
|
||||
ValueSelector.prototype.buildOptions = function(options) {
|
||||
if (this.elements.optionsContainer) {
|
||||
this.elements.optionsContainer.innerHTML = '';
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
var groupTemplate = new Template('value-selector-groupoption-template');
|
||||
var template = new Template('value-selector-option-template');
|
||||
|
||||
// Add ARIA property to notify if this is a multi-select or not.
|
||||
this.elements.optionsContainer.setAttribute('aria-multiselectable',
|
||||
this._currentPickerType !== 'select-one');
|
||||
|
||||
options.forEach(function(option) {
|
||||
if (option.group) {
|
||||
this.elements.optionsContainer.insertAdjacentHTML('beforeend',
|
||||
groupTemplate.interpolate({
|
||||
text: option.text
|
||||
}));
|
||||
} else {
|
||||
this.elements.optionsContainer.insertAdjacentHTML('beforeend',
|
||||
template.interpolate({
|
||||
index: option.optionIndex.toString(10),
|
||||
checked: option.selected.toString(),
|
||||
for: 'gaia-option-' + option.optionIndex,
|
||||
text: option.text
|
||||
}));
|
||||
}
|
||||
}, this);
|
||||
|
||||
// Apply different style when the options are more than 1 page
|
||||
this.elements.container.classList.toggle('scrollable', options.length > 5);
|
||||
|
||||
// Change the title for multiple select
|
||||
var titleL10nId = this._currentPickerType === 'select-one' ?
|
||||
'choose-option' : 'choose-options';
|
||||
|
||||
if (this.elements.optionsTitle) {
|
||||
this.elements.optionsTitle.dataset.l10nId = titleL10nId;
|
||||
this.elements.optionsTitle.setAttribute('data-l10n-id', titleL10nId);
|
||||
}
|
||||
};
|
||||
|
||||
ValueSelector.prototype.showTimePicker =
|
||||
function vs_showTimePicker(currentValue) {
|
||||
this._currentPickerType = 'time';
|
||||
this.showPanel('timePickerPopup');
|
||||
|
||||
if (!this._timePicker) {
|
||||
this._timePicker = new TimePicker(this.elements.timePickerContainer);
|
||||
}
|
||||
|
||||
var time;
|
||||
if (!currentValue) {
|
||||
var now = new Date();
|
||||
time = {
|
||||
hours: now.getHours(),
|
||||
minutes: now.getMinutes()
|
||||
};
|
||||
} else {
|
||||
time = InputParser.importTime(currentValue);
|
||||
}
|
||||
|
||||
// Set the value of time picker according to the current value
|
||||
if (this._timePicker.is12hFormat) {
|
||||
var hour = (time.hours % 12);
|
||||
hour = (hour === 0) ? 12 : hour;
|
||||
// 24-hour state value selector: AM = 0, PM = 1
|
||||
var hour24State = (time.hours >= 12) ? 1 : 0;
|
||||
this._timePicker.hour.setSelectedIndexByDisplayedText(hour);
|
||||
this._timePicker.hour24State.setSelectedIndex(hour24State);
|
||||
} else {
|
||||
this._timePicker.hour.setSelectedIndex(time.hours);
|
||||
}
|
||||
|
||||
this._timePicker.minute.setSelectedIndex(time.minutes);
|
||||
};
|
||||
|
||||
ValueSelector.prototype._str2Date = function vs__str2Date(str) {
|
||||
if (!str) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var dcs = str.split('-');
|
||||
var date = new Date(dcs[0], parseInt(dcs[1]) - 1, dcs[2]);
|
||||
|
||||
if (isNaN(date.getTime())) {
|
||||
date = null;
|
||||
}
|
||||
|
||||
return date;
|
||||
};
|
||||
|
||||
ValueSelector.prototype.showDatePicker =
|
||||
function vs_showDatePicker(currentValue, min, max) {
|
||||
this._currentPickerType = 'date';
|
||||
this.showPanel('spinDatePickerPopup');
|
||||
|
||||
var minDate = null;
|
||||
var maxDate = null;
|
||||
|
||||
minDate = this._str2Date(min);
|
||||
maxDate = this._str2Date(max);
|
||||
|
||||
if (!this._datePicker) {
|
||||
this._datePicker = new SpinDatePicker(this.elements.spinDatePicker);
|
||||
}
|
||||
this._datePicker.setRange(minDate, maxDate);
|
||||
|
||||
// Show current date as default value
|
||||
var date = new Date();
|
||||
if (currentValue) {
|
||||
date = InputParser.formatInputDate(currentValue, '');
|
||||
}
|
||||
this._datePicker.value = date;
|
||||
};
|
||||
|
||||
function TimePicker(element) {
|
||||
this.element = element;
|
||||
this._fetchElements();
|
||||
var _ = navigator.mozL10n.get;
|
||||
var is12hFormat = navigator.mozHour12;
|
||||
var localeTimeFormat = is12hFormat ?
|
||||
_('shortTimeFormat12') : _('shortTimeFormat24');
|
||||
var startHour = is12hFormat ? 1 : 0;
|
||||
var endHour = is12hFormat ? (startHour + 12) : (startHour + 12 * 2);
|
||||
var unitClassName = 'picker-unit';
|
||||
|
||||
this.is12hFormat = is12hFormat;
|
||||
this.hour = new ValuePicker(this.elements.valuePickerHours, {
|
||||
valueDisplayedText: this._setDisplayedText(startHour, endHour),
|
||||
className: unitClassName
|
||||
});
|
||||
this.minute = new ValuePicker(this.elements.valuePickerMinutes, {
|
||||
valueDisplayedText: this._setDisplayedText(0, 60, function(value) {
|
||||
return (value < 10) ? '0' + value : value;
|
||||
}),
|
||||
className: unitClassName
|
||||
});
|
||||
if (is12hFormat) {
|
||||
this.hour24State = new ValuePicker(this.elements.valuePickerHour24State, {
|
||||
valueDisplayedText: [
|
||||
_('time_am'),
|
||||
_('time_pm')
|
||||
],
|
||||
className: unitClassName
|
||||
});
|
||||
}
|
||||
|
||||
var separator = ':';
|
||||
var minutesPosition = localeTimeFormat.indexOf('%M');
|
||||
if (minutesPosition > 0) {
|
||||
separator = localeTimeFormat.substr(minutesPosition - 1, 1);
|
||||
}
|
||||
this.elements.hoursMinutesSeparator.textContent = separator;
|
||||
this.setTimePickerStyle();
|
||||
|
||||
this._registerEvents();
|
||||
}
|
||||
|
||||
TimePicker.prototype = {
|
||||
_fetchElements: function tp__fetchElements() {
|
||||
this.elements = {};
|
||||
this.elementClasses = ['value-picker-hours', 'value-picker-minutes',
|
||||
'value-picker-hour24-state', 'hours-minutes-separator'];
|
||||
|
||||
// Loop and add element with camel style name to Time Picker attribute.
|
||||
this.elementClasses.forEach(function createElementRef(name) {
|
||||
this.elements[toCamelCase(name)] =
|
||||
this.element.querySelector('.' + name);
|
||||
}, this);
|
||||
},
|
||||
|
||||
_registerEvents: function tp__registerEvents() {
|
||||
// Prevent focus being taken away by us for time picker.
|
||||
// The event listener on outer box will not be triggered cause there is a
|
||||
// evt.stopPropagation() in value_picker.js
|
||||
['valuePickerHours', 'valuePickerMinutes',
|
||||
'valuePickerHour24State'].forEach(function(elementId) {
|
||||
this.elements[elementId].addEventListener('mousedown', this);
|
||||
}, this);
|
||||
},
|
||||
|
||||
handleEvent: function tp_handleEvent(evt) {
|
||||
evt.preventDefault();
|
||||
},
|
||||
|
||||
_unregisterEvents: function tp__unregisterEvents() {
|
||||
['valuePickerHours', 'valuePickerMinutes',
|
||||
'valuePickerHour24State'].forEach(function(elementId) {
|
||||
this.elements[elementId].removeEventListener('mousedown', this);
|
||||
}, this);
|
||||
},
|
||||
|
||||
_setDisplayedText: function tp__setDisplayedText(min, max, format) {
|
||||
var list = [];
|
||||
for (var i = min; i < max; ++i) {
|
||||
list.push(format ? format(i) : i);
|
||||
}
|
||||
return list;
|
||||
},
|
||||
|
||||
uninit: function tp_uninit() {
|
||||
this._unregisterEvents();
|
||||
this.minute.uninit();
|
||||
this.hour.uninit();
|
||||
if (this.hour24State) {
|
||||
this.hour24State.uninit();
|
||||
}
|
||||
},
|
||||
|
||||
setTimePickerStyle: function tp_setTimePickerStyle() {
|
||||
var style = 'format24h';
|
||||
if (this.is12hFormat) {
|
||||
var localeTimeFormat = navigator.mozL10n.get('shortTimeFormat12');
|
||||
// handle revert appearance
|
||||
var reversedPeriod =
|
||||
(localeTimeFormat.indexOf('%p') < localeTimeFormat.indexOf('%M'));
|
||||
style = (reversedPeriod) ? 'format12hrev' : 'format12h';
|
||||
|
||||
if ('format12' === style) {
|
||||
this.element.classList.remove('format12hrev');
|
||||
this.element.classList.remove('format24h');
|
||||
if (!this.element.classList.contains(style)) {
|
||||
this.element.classList.add(style);
|
||||
}
|
||||
} else {
|
||||
this.element.classList.remove('format12');
|
||||
this.element.classList.remove('format24h');
|
||||
if (!this.element.classList.contains(style)) {
|
||||
this.element.classList.add(style);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ('format24h' === style) {
|
||||
this.element.classList.remove('format12h');
|
||||
this.element.classList.remove('format12hrev');
|
||||
if (!this.element.classList.contains(style)) {
|
||||
this.element.classList.add(style);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getHour: function tp_getHours() {
|
||||
var hour = 0;
|
||||
if (this.is12hFormat) {
|
||||
var hour24Offset = 12 * this.hour24State.getSelectedIndex();
|
||||
hour = this.hour.getSelectedDisplayedText();
|
||||
hour = (hour == 12) ? 0 : hour;
|
||||
hour = hour + hour24Offset;
|
||||
} else {
|
||||
hour = this.hour.getSelectedIndex();
|
||||
}
|
||||
return hour;
|
||||
},
|
||||
|
||||
// return a string for the time value, format: "16:37"
|
||||
getTimeValue: function tp_getTimeValue() {
|
||||
var hour = this.getHour();
|
||||
var minute = this.minute.getSelectedDisplayedText();
|
||||
|
||||
return (hour < 10 ? '0' : '') + hour + ':' + minute;
|
||||
}
|
||||
};
|
||||
})(window);
|
||||
Loading…
Reference in a new issue