Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/apps/system/js/value_selector
diff options
context:
space:
mode:
Diffstat (limited to 'apps/system/js/value_selector')
-rw-r--r--apps/system/js/value_selector/date_picker.js568
-rw-r--r--apps/system/js/value_selector/input_parser.js160
-rw-r--r--apps/system/js/value_selector/spin_date_picker.js341
-rw-r--r--apps/system/js/value_selector/value_picker.js222
-rw-r--r--apps/system/js/value_selector/value_selector.js526
5 files changed, 0 insertions, 1817 deletions
diff --git a/apps/system/js/value_selector/date_picker.js b/apps/system/js/value_selector/date_picker.js
deleted file mode 100644
index 9cdd484..0000000
--- a/apps/system/js/value_selector/date_picker.js
+++ /dev/null
@@ -1,568 +0,0 @@
-/**
- * DatePicker is a html/js "widget" which will display
- * all the days of a given month and allow selection of
- * one specific day. It also implements controls to travel
- * between months and jump into arbitrary time.
- *
- * The DatePicker itself contains no UI for the controls.
- *
- * Example usage:
- *
- * // the container will have elements for the month
- * // added and removed from it.
- * var picker = new DatePicker(container);
- *
- * // EVENTS:
- *
- * // called when the user clicks a day in the calendar.
- * picker.onvaluechange = function(date) {}
- *
- * // called when the month of the calendar changes.
- * // NOTE: at this time this can only happen programmatically
- * // so there is only for control flow.
- * picker.onmonthchange = function(date) {}
- *
- * // display a given year/month/date on the calendar the month
- * // is zero based just like the JS date constructor.
- * picker.display(2012, 0, 2);
- *
- * // move to the next month.
- * picker.next();
- *
- * // move to the previous month
- * picker.previous();
- *
- */
-var DatePicker = (function() {
- 'use strict';
-
- const SELECTED = 'selected';
-
- var Calc = {
-
- NEXT_MONTH: 'next-month',
-
- OTHER_MONTH: 'other-month',
-
- PRESENT: 'present',
-
- FUTURE: 'future',
-
- PAST: 'past',
-
- get today() {
- return new Date();
- },
-
- daysInWeek: function() {
- //XXX: We need to localize this...
- return 7;
- },
-
- /**
- * Checks is given date is today.
- *
- * @param {Date} date compare.
- * @return {Boolean} true when today.
- */
- isToday: function(date) {
- return Calc.isSameDate(date, Calc.today);
- },
-
- /**
- * Checks if two date objects occur
- * on the same date (in the same month, year, day).
- * Disregards time.
- *
- * @param {Date} first date.
- * @param {Date} second date.
- * @return {Boolean} true when they are the same date.
- */
- isSameDate: function(first, second) {
- return first.getMonth() == second.getMonth() &&
- first.getDate() == second.getDate() &&
- first.getFullYear() == second.getFullYear();
- },
-
- /**
- * Returns an identifier for a specific
- * date in time for a given date
- *
- * @param {Date} date to get id for.
- * @return {String} identifier.
- */
- getDayId: function(date) {
- return [
- date.getFullYear(),
- date.getMonth(),
- date.getDate()
- ].join('-');
- },
-
- /**
- * Returns a date object from
- * a string id for a date.
- *
- * @param {String} id identifier for date.
- * @return {Date} date output.
- */
- dateFromId: function(id) {
- var parts = id.split('-');
- return new Date(parts[0], parts[1], parts[2]);
- },
-
- createDay: function(date, day, month, year) {
- return new Date(
- typeof year !== 'undefined' ? year : date.getFullYear(),
- typeof month !== 'undefined' ? month : date.getMonth(),
- typeof day !== 'undefined' ? day : date.getDate()
- );
- },
-
- /**
- * Finds localized week start date of given date.
- *
- * @param {Date} date any day the week.
- * @return {Date} first date in the week of given date.
- */
- getWeekStartDate: function(date) {
- var currentDay = date.getDay();
- var startDay = date.getDate() - currentDay;
-
- return Calc.createDay(date, startDay);
- },
-
- getWeekEndDate: function(date) {
- // TODO: There are localization problems
- // with this approach as we assume a 7 day week.
- var start = Calc.getWeekStartDate(date);
- start.setDate(start.getDate() + 7);
- start.setMilliseconds(-1);
-
- return start;
- },
-
- /**
- * Returns an array of dates objects.
- * Inclusive. First and last are
- * the given instances.
- *
- * @param {Date} start starting day.
- * @param {Date} end ending day.
- * @param {Boolean} includeTime include times start/end ?
- */
- daysBetween: function(start, end, includeTime) {
- if (!(start instanceof Date)) {
- throw new Error('start date must be an instanceof Date');
- }
-
- if (!(end instanceof Date)) {
- throw new Error('end date must be an instanceof Date');
- }
-
- if (start > end) {
- var tmp = end;
- end = start;
- start = tmp;
- tmp = null;
- }
-
- var list = [];
- var last = start.getDate();
- var cur;
-
- // for infinite loop protection.
- var max = 500;
- var macInc = 0;
-
- while (macInc++ < max) {
- var next = new Date(
- start.getFullYear(),
- start.getMonth(),
- ++last
- );
-
- if (next > end) {
- throw new Error(
- 'sanity fails next is greater then end'
- );
- }
-
- if (!Calc.isSameDate(next, end)) {
- list.push(next);
- continue;
- }
-
- break;
- }
-
- if (includeTime) {
- list.unshift(start);
- list.push(end);
- } else {
- list.unshift(this.createDay(start));
- list.push(this.createDay(end));
- }
-
- return list;
- },
-
- /**
- * Checks if date is in the past
- *
- * @param {Date} date to check.
- * @return {Boolean} true when date is in the past.
- */
- isPast: function(date) {
- return (date.valueOf() < Calc.today.valueOf());
- },
-
- /**
- * Checks if date is in the future
- *
- * @param {Date} date to check.
- * @return {Boolean} true when date is in the future.
- */
- isFuture: function(date) {
- return !Calc.isPast(date);
- },
-
- /**
- * Based on the input date
- * will return one of the following states
- *
- * past, present, future
- *
- * @param {Date} day for compare.
- * @param {Date} month comparison month.
- * @return {String} state.
- */
- relativeState: function(day, month) {
- var states;
- //var today = Calc.today;
-
- // 1. the date is today (real time)
- if (Calc.isToday(day)) {
- return Calc.PRESENT;
- }
-
- // 2. the date is in the past (real time)
- if (Calc.isPast(day)) {
- states = Calc.PAST;
- // 3. the date is in the future (real time)
- } else {
- states = Calc.FUTURE;
- }
-
- // 4. the date is not in the current month (relative time)
- if (day.getMonth() !== month.getMonth()) {
- states += ' ' + Calc.OTHER_MONTH;
- }
-
- return states;
- }
-
- };
-
- /* expose calc */
- DatePicker.Calc = Calc;
-
- /**
- * Initialize a date picker widget.
- *
- * @param {HTMLELement} element target of widget creation.
- */
- function DatePicker(element) {
- this.element = element;
- // default time is set so next/previous work
- // but we do not render the initial display here.
- this._position = new Date();
-
- // register events
- element.addEventListener('click', this);
-
- //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.
- }
-
- DatePicker.prototype = {
-
- /**
- * Internal value not exposed so we can fire events
- * when the getter/setter's are used.
- *
- * @type Date
- */
- _value: null,
-
- SELECTED: 'selected',
-
- /**
- * 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._clearSelectedDay(value);
- this.onvaluechange(value, old);
- }
- },
-
- /**
- * Clears the currently selected date of its 'selected' class.
- * @private
- */
- _clearSelectedDay: function(value) {
- var target = this.element.querySelector('.' + SELECTED);
- if (target) {
- target.classList.remove(SELECTED);
- }
- },
-
- handleEvent: function(e) {
- switch (e.type) {
- case 'click':
- var target = e.target;
- //XXX: if the html of the date elements changes
- // this may also need to be altered as it
- // assumes that there is no nesting of elements.
- if (target.dataset.date) {
- var date = Calc.dateFromId(target.dataset.date);
- // order here is important as setting value will
- // clear all the past selected dates...
- this.value = date;
- this._position = date;
- // must come after setting selected date
- target.classList.add(SELECTED);
- }
- break;
- }
- },
-
- /**
- * Getter is used for date normalization.
- */
- get year() {
- return this._position.getFullYear();
- },
-
- /**
- * Getter is used for date normalization.
- */
- get month() {
- return this._position.getMonth();
- },
-
- get date() {
- return this._position.getDate();
- },
-
- /**
- * Find the number of days in the given month/year.
- * Month is zero based like the JS date constructor.
- *
- * @param {Numeric} year year value.
- * @param {Numeric} month month value.
- * @return {Numeric} number of days in month.
- */
- _daysInMonth: function(year, month) {
- var end = new Date(year, month + 1);
- end.setMilliseconds(-1);
- return end.getDate();
- },
-
- /**
- * Build the container for a day element.
- * Each element has classes added to it based
- * on what date it is created for.
- *
- * _today_ is based on today's actual date.
- * Each date element also contains a data-date attribute
- * with its current date as a string represented in
- * the following format: "yyyy-mm-dd".
- *
- * Possible classes:
- * - past
- * - present (today)
- * - future
- * - other-month (day of another month but falls within same week)
- *
- * @param {Date} date date desired.
- * @return {HTMLElement} dom element for day.
- */
- _renderDay: function(date) {
- var dayContainer = document.createElement('li');
- var dayEl = document.createElement('span');
-
- dayContainer.className = Calc.relativeState(
- date,
- this._position
- );
-
- dayEl.dataset.date = Calc.getDayId(date);
- dayEl.textContent = date.getDate();
-
- dayContainer.appendChild(dayEl);
-
- return dayContainer;
- },
-
- /**
- * Renders a set of dates and returns an ol element
- * containing each date.
- *
- * @private
- * @param {Array[Date]} dates array of dates.
- * @return {HTMLELement} container for week.
- */
- _renderWeek: function(dates) {
- var container = document.createElement('ol');
- var i = 0;
- var len = dates.length;
-
- for (; i < len; i++) {
- container.appendChild(
- this._renderDay(dates[i])
- );
- }
-
- return container;
- },
-
- /**
- * Finds all dates in a given month by week.
- * Includes leading and trailing days that occur
- * outside the given year/month combination.
- *
- * @private
- * @param {Numeric} year target year.
- * @param {Numeric} month target month.
- * @return {Array[Date]} array of dates.
- */
- _getMonthDays: function(year, month) {
- var date = new Date(year, month);
- var dateEnd = new Date(year, month + 1);
- dateEnd.setMilliseconds(-1);
-
- var start = Calc.getWeekStartDate(date);
- var end = Calc.getWeekEndDate(dateEnd);
- return Calc.daysBetween(start, end);
- },
-
- /**
- * Returns a section element with all
- * the days of the given month/year pair.
- *
- * Each month has a class for the number of weeks
- * it contains.
- *
- * Possible values:
- * - weeks-4
- * - weeks-5
- * - weeks-6
- *
- * @private
- */
- _renderMonth: function(year, month) {
- var container = document.createElement('section');
- var days = this._getMonthDays(year, month);
- var daysInWeek = Calc.daysInWeek();
- var weeks = days.length / daysInWeek;
- var i = 0;
-
- container.classList.add('weeks-' + weeks);
-
- for (; i < weeks; i++) {
- container.appendChild(this._renderWeek(
- days.splice(0, daysInWeek)
- ));
- }
-
- return container;
- },
-
- /**
- * Moves calendar one month into the future.
- */
- next: function() {
- this.display(this.year, this.month + 1, this.date);
- },
-
- /**
- * Moves calendar one month into the past.
- */
- previous: function() {
- this.display(this.year, this.month - 1, this.date);
- },
-
- /**
- * Primary method to display given month.
- * Will remove the current display and replace
- * it with the given month.
- *
- * @param {Numeric} year year to display.
- * @param {Numeric} month month to display.
- * @param {Numeric} date date to display.
- */
- display: function(year, month, date) {
-
- // reset the date to the last date if overflow
- var lastDate = new Date(year, month + 1, 0).getDate();
- if (lastDate < date)
- date = lastDate;
-
- // Should come before render month
- this._position = new Date(year, month, date);
-
- var element = this._renderMonth(year, month);
-
- if (this.monthDisplay) {
- this.monthDisplay.parentNode.removeChild(
- this.monthDisplay
- );
- }
-
- this.monthDisplay = element;
- this.element.appendChild(this.monthDisplay);
-
- this.onmonthchange(this._position);
-
- // Set the date as selected if presented
- this._clearSelectedDay();
- if (date) {
- var dayId = Calc.getDayId(this._position);
- this.value = this._position;
- var selector = '[data-date="' + dayId + '"]';
- var dateElement = document.querySelector(selector);
- dateElement.classList.add(SELECTED);
- }
- },
-
- /**
- * Called when the month is changed.
- */
- onmonthchange: function(month, year) {},
-
- /**
- * Called when the selected day changes.
- */
- onvaluechange: function(date) {}
- };
-
- return DatePicker;
-}());
diff --git a/apps/system/js/value_selector/input_parser.js b/apps/system/js/value_selector/input_parser.js
deleted file mode 100644
index 5eef320..0000000
--- a/apps/system/js/value_selector/input_parser.js
+++ /dev/null
@@ -1,160 +0,0 @@
-/**
- * Stateless object for input parser functions..
- * The intent is the methods here will only relate to the parsing
- * of input[type="date|time"]
- */
-
-ValueSelector.InputParser = (function() {
-
- var InputParser = {
- _dateParts: ['year', 'month', 'date'],
- _timeParts: ['hours', 'minutes', 'seconds'],
-
- /**
- * Import HTML5 input[type="time"] string value
- *
- * @param {String} value 23:20:50.52, 17:39:57.
- * @return {Object} { hours: 23, minutes: 20, seconds: 50 }.
- */
- importTime: function(value) {
- var result = {
- hours: 0,
- minutes: 0,
- seconds: 0
- };
-
- var parts = value.split(':');
- var part;
- var partName;
-
- var i = 0;
- var len = InputParser._timeParts.length;
-
- for (; i < len; i++) {
- partName = InputParser._timeParts[i];
- part = parts[i];
- if (part) {
- result[partName] = parseInt(part.slice(0, 2), 10) || 0;
- }
- }
-
- return result;
- },
-
- /**
- * Export date to HTML5 input[type="time"]
- *
- * @param {Date} value export value.
- * @return {String} 17:39:57.
- */
- exportTime: function(value) {
- var hour = value.getHours();
- var minute = value.getMinutes();
- var second = value.getSeconds();
-
- var result = '';
-
- result += InputParser.padNumber(hour) + ':';
- result += InputParser.padNumber(minute) + ':';
- result += InputParser.padNumber(second);
-
- return result;
- },
-
- /**
- * Import HTML5 input[type="time"] to object.
- *
- * @param {String} value 1997-12-19.
- * @return {Object} { year: 1997, month: 12, date: 19 }.
- */
- importDate: function(value) {
- var result = {
- year: 0,
- month: 0,
- date: 0
- };
-
- var parts = value.split('-');
- var part;
- var partName;
-
- var i = 0;
- var len = InputParser._dateParts.length;
-
- for (; i < len; i++) {
- partName = InputParser._dateParts[i];
- part = parts[i];
- if (part) {
- result[partName] = parseInt(part, 10);
- }
- }
-
- if (result.month > 0) {
- result.month = result.month - 1;
- }
-
- result.date = result.date || 1;
-
- return result;
- },
-
- /**
- * Export js date to HTML5 input[type="date"]
- *
- * @param {Date} value export value.
- * @return {String} date string (1997-12-19).
- */
- exportDate: function(value) {
- var year = value.getFullYear();
- var month = value.getMonth() + 1;
- var date = value.getDate();
-
- var result = '';
-
- result += InputParser.padNumber(year) + '-';
- result += InputParser.padNumber(month) + '-';
- result += InputParser.padNumber(date);
-
- return result;
- },
-
- /**
- * Designed to take a date & time value from
- * html5 input types and returns a JS Date.
- *
- * @param {String} date input date.
- * @param {String} time input time.
- *
- * @return {Date} full date object from date/time.
- */
- formatInputDate: function(date, time) {
- time = InputParser.importTime(time);
- date = InputParser.importDate(date);
-
- return new Date(
- date.year,
- date.month,
- date.date,
- time.hours,
- time.minutes,
- time.seconds
- );
- },
-
- /**
- * @param {Numeric} numeric value.
- * @return {String} Pad the numeric with a leading zero if < 10.
- */
- padNumber: function(numeric) {
- var value = String(numeric);
- if (numeric < 10) {
- return '0' + value;
- }
-
- return value;
- }
- };
-
- return InputParser;
-
-}());
diff --git a/apps/system/js/value_selector/spin_date_picker.js b/apps/system/js/value_selector/spin_date_picker.js
deleted file mode 100644
index feb0602..0000000
--- a/apps/system/js/value_selector/spin_date_picker.js
+++ /dev/null
@@ -1,341 +0,0 @@
-/**
- * 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;
- */
-var SpinDatePicker = (function SpinDatePicker() {
- 'use strict';
-
- var FIRST_YEAR = 1900;
- var LAST_YEAR = 2099;
-
- function getYearText() {
- var yearText = [];
- var dateTimeFormat = navigator.mozL10n.DateTimeFormat();
-
- for (var i = FIRST_YEAR; i <= LAST_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(0);
- 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(days) {
- var dateText = [];
- var date = new Date(0);
- var dateTimeFormat = navigator.mozL10n.DateTimeFormat();
-
- for (var i = 1; i <= days; 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(format) {
- 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) {
- this.element = element;
-
- this.yearPicker = null;
- this.monthPicker = null;
- this.datePickers = {
- '28': null,
- '29': null,
- '30': null,
- '31': 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 tmpDatePickerContainers =
- element.querySelectorAll('.value-picker-date');
- var datePickerContainers = {
- '28': tmpDatePickerContainers[0],
- '29': tmpDatePickerContainers[1],
- '30': tmpDatePickerContainers[2],
- '31': tmpDatePickerContainers[3]
- };
-
- var updateCurrentValue = function spd_updateCurrentValue() {
- var selectedYear = this.yearPicker.getSelectedIndex() + FIRST_YEAR;
- var selectedMonth = this.monthPicker.getSelectedIndex();
- var days = getDaysInMonth(selectedYear, selectedMonth);
- var datePicker = this.datePickers[days];
- var selectedDate = datePicker.getSelectedIndex() + 1;
-
- this._value = new Date(selectedYear, selectedMonth, selectedDate);
- };
-
- var updateDatePickerVisibility =
- function spd_updateDatePickerVisibility() {
- var days = getDaysInMonth(this.yearPicker.getSelectedIndex() +
- FIRST_YEAR, this.monthPicker.getSelectedIndex());
- for (var i = 28; i <= 31; i++) {
- datePickerContainers[i].hidden = true;
- this.datePickers[i].setSelectedIndex(this._currentSelectedDateIndex);
- }
- datePickerContainers[days].hidden = false;
- };
-
- var onvaluechangeInternal =
- function spd_onvaluechangeInternal(newDateValue) {
- this.yearPicker.setSelectedIndex(newDateValue.getFullYear() - FIRST_YEAR);
- this.monthPicker.setSelectedIndex(newDateValue.getMonth());
- for (var i = 28; i <= 31; i++) {
- this.datePickers[i].setSelectedIndex(newDateValue.getDate() - 1);
- }
- updateDatePickerVisibility.apply(this);
- updateCurrentValue.apply(this);
- };
-
- var onSelectedYearChanged =
- function spd_onSelectedYearChanged(selectedYear) {
- updateDatePickerVisibility.apply(this);
- updateCurrentValue.apply(this);
- };
-
- var onSelectedMonthChanged =
- function spd_onSelectedMonthChanged(selectedMonth) {
- updateDatePickerVisibility.apply(this);
- updateCurrentValue.apply(this);
- };
-
- var onSelectedDateChanged =
- function spd_onSelectedDateChanged(selectedDate) {
- this._currentSelectedDateIndex = 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
- for (var i = 28; i <= 31; i++) {
- var datePickerContainer = datePickerContainers[i];
- var dateUnitStyle = {
- valueDisplayedText: getDateText(i),
- className: unitClassName
- };
- var datePicker = this.datePickers[i];
-
- if (datePicker)
- datePicker.uninit();
- datePickerContainer.hidden = false;
- this.datePickers[i] = new ValuePicker(datePickerContainer, dateUnitStyle);
- this.datePickers[i].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];
- for (var i = 28; i <= 31; i++) {
- this.pickerElements.push(datePickerContainers[i]);
- }
-
- 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;
- }
- },
-
- uninit: function() {
- if (this.yearPicker)
- this.yearPicker.uninit();
- if (this.monthPicker)
- this.monthPicker.uninit();
- if (this.datePickers) {
- for (var i = 28; i <= 31; i++) {
- var datePicker = this.datePickers[i];
- 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;
-}());
diff --git a/apps/system/js/value_selector/value_picker.js b/apps/system/js/value_selector/value_picker.js
deleted file mode 100644
index 34e686f..0000000
--- a/apps/system/js/value_selector/value_picker.js
+++ /dev/null
@@ -1,222 +0,0 @@
-var ValuePicker = (function() {
- //
- // Constructor
- //
- function VP(e, unitStyle) {
- this.element = e;
- this._valueDisplayedText = unitStyle.valueDisplayedText;
- this._unitClassName = unitStyle.className;
- this._lower = 0;
- this._upper = unitStyle.valueDisplayedText.length - 1;
- this._range = unitStyle.valueDisplayedText.length;
- 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;
- }
-
- if (this._currentIndex != tunedIndex) {
- this._currentIndex = tunedIndex;
- this.onselectedindexchange(this._currentIndex);
- }
- this.updateUI(tunedIndex, ignorePicker);
-
- return tunedIndex;
- };
-
- VP.prototype.setSelectedIndexByDisplayedText = function(displayedText) {
- var newIndex = this._valueDisplayedText.indexOf(displayedText);
- if (newIndex != -1) {
- if (this._currentIndex != newIndex) {
- this._currentIndex = newIndex;
- this.onselectedindexchange(this._currentIndex);
- }
- this.updateUI(newIndex);
- }
- };
-
- //
- // Internal methods
- //
- VP.prototype.init = function() {
- this.initUI();
- this.setSelectedIndex(0); // Default Index is zero
- this.mousedonwHandler = vp_mousedown.bind(this);
- this.mousemoveHandler = vp_mousemove.bind(this);
- this.mouseupHandler = vp_mouseup.bind(this);
- this.addEventListeners();
- };
-
- VP.prototype.initUI = function() {
- var lower = this._lower;
- var upper = 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.innerHTML = html;
- this.element.appendChild(unit);
- };
-
- VP.prototype.updateUI = function(index, ignorePicker) {
- if (true !== ignorePicker) {
- this.element.style.top =
- (this._lower - index) * this._space + 'px';
- }
- };
-
- VP.prototype.addEventListeners = function() {
- this.element.addEventListener('mousedown', this.mousedonwHandler, false);
- };
-
- VP.prototype.removeEventListeners = function() {
- this.element.removeEventListener('mouseup', this.mouseupHandler, false);
- this.element.removeEventListener('mousemove', this.mousemoveHandler, false);
- };
-
- VP.prototype.uninit = function() {
- this.element.removeEventListener('mousedown', this.mousedonwHandler, false);
- this.element.removeEventListener('mouseup', this.mouseupHandler, false);
- this.element.removeEventListener('mousemove', this.mousemoveHandler, false);
- this.element.style.top = '0px';
- this.onselectedindexchange = null;
- empty(this.element);
- };
-
- VP.prototype.onselectedindexchange = function(index) {};
-
- function cloneEvent(evt) {
- if ('touches' in evt) {
- evt = evt.touches[0];
- }
- return { x: evt.pageX, y: evt.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_mousemove(event) {
- event.stopPropagation();
- event.target.setCapture(true);
- currentEvent = cloneEvent(event);
-
- calcSpeed();
-
- // move selected index
- this.element.style.top = parseFloat(this.element.style.top) +
- getMovingSpace() + '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_mouseup(event) {
- event.stopPropagation();
- this.removeEventListeners();
-
- // Add animation back
- this.element.classList.add('animation-on');
-
- // 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_mousedown(event) {
- event.stopPropagation();
-
- // Stop animation
- this.element.classList.remove('animation-on');
-
- startEvent = currentEvent = cloneEvent(event);
- tunedIndex = this._currentIndex;
-
- this.removeEventListeners();
- this.element.addEventListener('mousemove', this.mousemoveHandler, false);
- this.element.addEventListener('mouseup', this.mouseupHandler, false);
- }
-
- return VP;
-}());
diff --git a/apps/system/js/value_selector/value_selector.js b/apps/system/js/value_selector/value_selector.js
deleted file mode 100644
index b3381b3..0000000
--- a/apps/system/js/value_selector/value_selector.js
+++ /dev/null
@@ -1,526 +0,0 @@
-/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-
-'use strict';
-
-var ValueSelector = {
-
- _containers: {},
- _popups: {},
- _buttons: {},
- _datePicker: null,
-
- debug: function(msg) {
- var debugFlag = false;
- if (debugFlag) {
- console.log('[ValueSelector] ', msg);
- }
- },
-
- init: function vs_init() {
-
- var self = this;
-
- window.navigator.mozKeyboard.onfocuschange = function onfocuschange(evt) {
- var typeToHandle = ['select-one', 'select-multiple', 'date',
- 'time', 'datetime', 'datetime-local', 'blur'];
-
- var type = evt.detail.type;
- // handle the <select> element and inputs with type of date/time
- // in system app for now
- if (typeToHandle.indexOf(type) == -1)
- return;
-
- var currentValue = evt.detail.value;
-
- switch (evt.detail.type) {
- case 'select-one':
- case 'select-multiple':
- self.debug('select triggered' + JSON.stringify(evt.detail));
- self._currentPickerType = evt.detail.type;
- self.showOptions(evt.detail);
- break;
-
- case 'date':
- self.showDatePicker(currentValue);
- break;
-
- case 'time':
- self.showTimePicker(currentValue);
- break;
-
- case 'datetime':
- case 'datetime-local':
- // TODO
- break;
- case 'blur':
- self.hide();
- break;
- }
- };
-
- this._element = document.getElementById('value-selector');
- this._element.addEventListener('mousedown', this);
- this._containers['select'] =
- document.getElementById('value-selector-container');
- this._containers['select'].addEventListener('click', this);
- ActiveEffectHelper.enableActive(this._containers['select']);
-
- this._popups['select'] =
- document.getElementById('select-option-popup');
- this._popups['select'].addEventListener('submit', this);
- this._popups['time'] =
- document.getElementById('time-picker-popup');
- this._popups['date'] =
- document.getElementById('spin-date-picker-popup');
-
- this._buttons['select'] = document.getElementById('select-options-buttons');
- this._buttons['select'].addEventListener('click', this);
-
- this._buttons['time'] = document.getElementById('time-picker-buttons');
- this._buttons['time'].addEventListener('click', this);
- this._buttons['date'] = document.getElementById('spin-date-picker-buttons');
-
- this._buttons['date'].addEventListener('click', this);
-
- this._containers['time'] = document.getElementById('picker-bar');
- this._containers['date'] = document.getElementById('spin-date-picker');
-
- ActiveEffectHelper.enableActive(this._buttons['select']);
- ActiveEffectHelper.enableActive(this._buttons['time']);
- ActiveEffectHelper.enableActive(this._buttons['date']);
-
- // 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
- var pickerElements = ['value-picker-hours', 'value-picker-minutes',
- 'value-picker-hour24-state'];
-
- pickerElements.forEach((function pickerElements_forEach(id) {
- var element = document.getElementById(id);
- element.addEventListener('mousedown', this);
- }).bind(this));
-
- window.addEventListener('appopen', this);
- window.addEventListener('appwillclose', this);
-
- // invalidate the current spin date picker when language setting changes
- navigator.mozSettings.addObserver('language.current',
- (function language_change(e) {
- if (this._datePicker) {
- this._datePicker.uninit();
- this._datePicker = null;
- }}).bind(this));
- },
-
- handleEvent: function vs_handleEvent(evt) {
- switch (evt.type) {
- case 'appopen':
- case 'appwillclose':
- this.hide();
- break;
-
- case 'click':
- var currentTarget = evt.currentTarget;
- switch (currentTarget) {
- case this._buttons['select']:
- case this._buttons['time']:
- case this._buttons['date']:
- var target = evt.target;
- if (target.dataset.type == 'cancel') {
- this.cancel();
- } else if (target.dataset.type == 'ok') {
- this.confirm();
- }
- break;
-
- case this._containers['select']:
- this.handleSelect(evt.target);
- break;
- }
- break;
-
- case 'submit':
- // Prevent the form from submit.
- case 'mousedown':
- // Prevent focus being taken away by us.
- evt.preventDefault();
- break;
-
- default:
- this.debug('no event handler defined for' + evt.type);
- break;
- }
- },
-
- handleSelect: function vs_handleSelect(target) {
-
- if (target.dataset === undefined ||
- (target.dataset.optionIndex === undefined &&
- target.dataset.optionValue === undefined))
- return;
-
- if (this._currentPickerType === 'select-one') {
- var selectee = this._containers['select'].
- querySelectorAll('[aria-checked="true"]');
- for (var i = 0; i < selectee.length; i++) {
- selectee[i].removeAttribute('aria-checked');
- }
-
- target.setAttribute('aria-checked', 'true');
- } else if (target.getAttribute('aria-checked') === 'true') {
- target.removeAttribute('aria-checked');
- } else {
- target.setAttribute('aria-checked', 'true');
- }
-
- // setValue here to trigger change event
- var singleOptionIndex;
- var optionIndices = [];
-
- var selectee = this._containers['select'].
- querySelectorAll('[aria-checked="true"]');
-
- if (this._currentPickerType === 'select-one') {
-
- if (selectee.length > 0)
- singleOptionIndex = selectee[0].dataset.optionIndex;
-
- window.navigator.mozKeyboard.setSelectedOption(singleOptionIndex);
-
- } else if (this._currentPickerType === 'select-multiple') {
- // Multiple select case
- for (var i = 0; i < selectee.length; i++) {
-
- var index = parseInt(selectee[i].dataset.optionIndex);
- optionIndices.push(index);
- }
-
- window.navigator.mozKeyboard.setSelectedOptions(optionIndices);
- }
-
- },
-
- show: function vs_show(detail) {
- this._element.hidden = false;
- },
-
- showPanel: function vs_showPanel(type) {
- for (var p in this._containers) {
- if (p === type) {
- this._popups[p].hidden = false;
- } else {
- this._popups[p].hidden = true;
- }
- }
- },
-
- hide: function vs_hide() {
- this._element.hidden = true;
- },
-
- cancel: function vs_cancel() {
- this.debug('cancel invoked');
- window.navigator.mozKeyboard.removeFocus();
- this.hide();
- },
-
- confirm: function vs_confirm() {
-
- if (this._currentPickerType === 'time') {
-
- var timeValue = TimePicker.getTimeValue();
- this.debug('output value: ' + timeValue);
-
- window.navigator.mozKeyboard.setValue(timeValue);
- } else if (this._currentPickerType === 'date') {
- var dateValue = this._datePicker.value;
- // The format should be 2012-09-19
- dateValue = dateValue.toLocaleFormat('%Y-%m-%d');
- this.debug('output value: ' + dateValue);
- window.navigator.mozKeyboard.setValue(dateValue);
- }
-
- window.navigator.mozKeyboard.removeFocus();
- this.hide();
- },
-
- showOptions: function vs_showOptions(detail) {
-
- var options = null;
- if (detail.choices && detail.choices.choices)
- options = detail.choices.choices;
-
- if (options)
- this.buildOptions(options);
-
- this.show();
- this.showPanel('select');
- },
-
- buildOptions: function(options) {
-
- var optionHTML = '';
-
- function escapeHTML(str) {
- var span = document.createElement('span');
- span.textContent = str;
- return span.innerHTML;
- }
-
- for (var i = 0, n = options.length; i < n; i++) {
-
- var checked = options[i].selected ? ' aria-checked="true"' : '';
-
- // This for attribute is created only to avoid applying
- // a general rule in building block
- var forAttribute = ' for="gaia-option-' + options[i].optionIndex + '"';
-
- optionHTML += '<li data-option-index="' + options[i].optionIndex + '"' +
- checked + '>' +
- '<label' + forAttribute + '> <span>' +
- escapeHTML(options[i].text) +
- '</span></label>' +
- '</li>';
- }
-
- var optionsContainer = document.querySelector(
- '#value-selector-container ol');
- if (!optionsContainer)
- return;
-
- optionsContainer.innerHTML = optionHTML;
-
-
- // Apply different style when the options are more than 1 page
- if (options.length > 5) {
- this._containers['select'].classList.add('scrollable');
- } else {
- this._containers['select'].classList.remove('scrollable');
- }
-
- // Change the title for multiple select
- var titleL10nId = 'choose-options';
- if (this._currentPickerType === 'select-one')
- titleL10nId = 'choose-option';
-
- var optionsTitle = document.querySelector(
- '#value-selector-container h1');
-
- if (optionsTitle) {
- optionsTitle.dataset.l10nId = titleL10nId;
- optionsTitle.textContent = navigator.mozL10n.get(titleL10nId);
- }
- },
-
- showTimePicker: function vs_showTimePicker(currentValue) {
- this._currentPickerType = 'time';
- this.show();
- this.showPanel('time');
-
- if (!this._timePickerInitialized) {
- TimePicker.initTimePicker();
- this._timePickerInitialized = true;
- }
-
- var time;
- if (!currentValue) {
- var now = new Date();
- time = {
- hours: now.getHours(),
- minutes: now.getMinutes()
- };
- } else {
- var inputParser = ValueSelector.InputParser;
- if (!inputParser)
- console.error('Cannot get input parser for value selector');
-
- time = inputParser.importTime(currentValue);
- }
-
- var timePicker = TimePicker.timePicker;
- // Set the value of time picker according to the current value
- if (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;
- timePicker.hour.setSelectedIndexByDisplayedText(hour);
- timePicker.hour24State.setSelectedIndex(hour24State);
- } else {
- timePicker.hour.setSelectedIndex(time.hours);
- }
-
- timePicker.minute.setSelectedIndex(time.minutes);
- },
-
- showDatePicker: function vs_showDatePicker(currentValue) {
- this._currentPickerType = 'date';
- this.show();
- this.showPanel('date');
-
- if (!this._datePicker) {
- this._datePicker = new SpinDatePicker(this._containers['date']);
- }
-
- // Show current date as default value
- var date = new Date();
- if (currentValue) {
- var inputParser = ValueSelector.InputParser;
- if (!inputParser)
- console.error('Cannot get input parser for value selector');
-
- date = inputParser.formatInputDate(currentValue, '');
- }
- this._datePicker.value = date;
- }
-
-};
-
-var TimePicker = {
- timePicker: {
- hour: null,
- minute: null,
- hour24State: null,
- is12hFormat: false
- },
-
- get hourSelector() {
- delete this.hourSelector;
- return this.hourSelector =
- document.getElementById('value-picker-hours');
- },
-
- get minuteSelector() {
- delete this.minuteSelector;
- return this.minuteSelector =
- document.getElementById('value-picker-minutes');
- },
-
- get hour24StateSelector() {
- delete this.hour24StateSelector;
- return this.hour24StateSelector =
- document.getElementById('value-picker-hour24-state');
- },
-
- initTimePicker: function tp_initTimePicker() {
- var localeTimeFormat = navigator.mozL10n.get('dateTimeFormat_%X');
- var is12hFormat = (localeTimeFormat.indexOf('%p') >= 0);
- this.timePicker.is12hFormat = is12hFormat;
- this.setTimePickerStyle();
- var startHour = is12hFormat ? 1 : 0;
- var endHour = is12hFormat ? (startHour + 12) : (startHour + 12 * 2);
- var unitClassName = 'picker-unit';
- var hourDisplayedText = [];
- for (var i = startHour; i < endHour; i++) {
- var value = i;
- hourDisplayedText.push(value);
- }
- var hourUnitStyle = {
- valueDisplayedText: hourDisplayedText,
- className: unitClassName
- };
- this.timePicker.hour = new ValuePicker(this.hourSelector, hourUnitStyle);
-
- var minuteDisplayedText = [];
- for (var i = 0; i < 60; i++) {
- var value = (i < 10) ? '0' + i : i;
- minuteDisplayedText.push(value);
- }
- var minuteUnitStyle = {
- valueDisplayedText: minuteDisplayedText,
- className: unitClassName
- };
- this.timePicker.minute =
- new ValuePicker(this.minuteSelector, minuteUnitStyle);
-
- if (is12hFormat) {
- var hour24StateUnitStyle = {
- valueDisplayedText: ['AM', 'PM'],
- className: unitClassName
- };
- this.timePicker.hour24State =
- new ValuePicker(this.hour24StateSelector, hour24StateUnitStyle);
- }
- },
-
- setTimePickerStyle: function tp_setTimePickerStyle() {
- var style = (this.timePicker.is12hFormat) ? 'format12h' : 'format24h';
- document.getElementById('picker-bar').classList.add(style);
- },
-
- // return a string for the time value, format: "16:37"
- getTimeValue: function tp_getTimeValue() {
- var hour = 0;
- if (this.timePicker.is12hFormat) {
- var hour24Offset = 12 * this.timePicker.hour24State.getSelectedIndex();
- hour = this.timePicker.hour.getSelectedDisplayedText();
- hour = (hour == 12) ? 0 : hour;
- hour = hour + hour24Offset;
- } else {
- hour = this.timePicker.hour.getSelectedIndex();
- }
- var minute = this.timePicker.minute.getSelectedDisplayedText();
-
- return hour + ':' + minute;
- }
-};
-
-var ActiveEffectHelper = (function() {
-
- var lastActiveElement = null;
-
- function _setActive(element, isActive) {
- if (isActive) {
- element.classList.add('active');
- lastActiveElement = element;
- } else {
- element.classList.remove('active');
- if (lastActiveElement) {
- lastActiveElement.classList.remove('active');
- lastActiveElement = null;
- }
- }
- }
-
- function _onMouseDown(evt) {
- var target = evt.target;
-
- _setActive(target, true);
- target.addEventListener('mouseleave', _onMouseLeave);
- }
-
- function _onMouseUp(evt) {
- var target = evt.target;
-
- _setActive(target, false);
- target.removeEventListener('mouseleave', _onMouseLeave);
- }
-
- function _onMouseLeave(evt) {
- var target = evt.target;
- _setActive(target, false);
- target.removeEventListener('mouseleave', _onMouseLeave);
- }
-
- var _events = {
- 'mousedown': _onMouseDown,
- 'mouseup': _onMouseUp
- };
-
- function _enableActive(element) {
- // Attach event listeners
- for (var event in _events) {
- var callback = _events[event] || null;
- if (callback)
- element.addEventListener(event, callback);
- }
- }
-
- return {
- enableActive: _enableActive
- };
-
-})();
-
-ValueSelector.init();