var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
(function ($) {
'use strict';
var _defaults = {
dialRadius: 135,
outerRadius: 105,
innerRadius: 70,
tickRadius: 20,
duration: 350,
container: null,
defaultTime: 'now', // default time, 'now' or '13:14' e.g.
fromnow: 0, // Millisecond offset from the defaultTime
doneText: 'Ok', // done button text
clearText: 'Clear',
cancelText: 'Cancel',
autoClose: false, // auto close when minute is selected
twelveHour: true, // change to 12 hour AM/PM clock from 24 hour
vibrate: true // vibrate the device when dragging clock hand
};
/**
* @class
*
*/
var Timepicker = function (_Component) {
_inherits(Timepicker, _Component);
function Timepicker(el, options) {
_classCallCheck(this, Timepicker);
var _this = _possibleConstructorReturn(this, (Timepicker.__proto__ || Object.getPrototypeOf(Timepicker)).call(this, Timepicker, el, options));
_this.el.M_Timepicker = _this;
_this.options = $.extend({}, Timepicker.defaults, options);
_this.id = M.guid();
_this._insertHTMLIntoDOM();
_this._setupModal();
_this._setupVariables();
_this._setupEventHandlers();
_this._clockSetup();
_this._pickerSetup();
return _this;
}
_createClass(Timepicker, [{
key: 'destroy',
/**
* Teardown component
*/
value: function destroy() {
this._removeEventHandlers();
this.modal.destroy();
$(this.modalEl).remove();
this.el.M_Timepicker = undefined;
}
/**
* Setup Event Handlers
*/
}, {
key: '_setupEventHandlers',
value: function _setupEventHandlers() {
this._handleInputKeydownBound = this._handleInputKeydown.bind(this);
this._handleInputClickBound = this._handleInputClick.bind(this);
this._handleClockClickStartBound = this._handleClockClickStart.bind(this);
this._handleDocumentClickMoveBound = this._handleDocumentClickMove.bind(this);
this._handleDocumentClickEndBound = this._handleDocumentClickEnd.bind(this);
this.el.addEventListener('click', this._handleInputClickBound);
this.el.addEventListener('keydown', this._handleInputKeydownBound);
this.plate.addEventListener('mousedown', this._handleClockClickStartBound);
this.plate.addEventListener('touchstart', this._handleClockClickStartBound);
$(this.spanHours).on('click', this.showView.bind(this, 'hours'));
$(this.spanMinutes).on('click', this.showView.bind(this, 'minutes'));
}
}, {
key: '_removeEventHandlers',
value: function _removeEventHandlers() {
this.el.removeEventListener('click', this._handleInputClickBound);
this.el.removeEventListener('keydown', this._handleInputKeydownBound);
}
}, {
key: '_handleInputClick',
value: function _handleInputClick() {
this.open();
}
}, {
key: '_handleInputKeydown',
value: function _handleInputKeydown(e) {
if (e.which === M.keys.ENTER) {
e.preventDefault();
this.open();
}
}
}, {
key: '_handleClockClickStart',
value: function _handleClockClickStart(e) {
e.preventDefault();
var clockPlateBR = this.plate.getBoundingClientRect();
var offset = { x: clockPlateBR.left, y: clockPlateBR.top };
this.x0 = offset.x + this.options.dialRadius;
this.y0 = offset.y + this.options.dialRadius;
this.moved = false;
var clickPos = Timepicker._Pos(e);
this.dx = clickPos.x - this.x0;
this.dy = clickPos.y - this.y0;
// Set clock hands
this.setHand(this.dx, this.dy, false);
// Mousemove on document
document.addEventListener('mousemove', this._handleDocumentClickMoveBound);
document.addEventListener('touchmove', this._handleDocumentClickMoveBound);
// Mouseup on document
document.addEventListener('mouseup', this._handleDocumentClickEndBound);
document.addEventListener('touchend', this._handleDocumentClickEndBound);
}
}, {
key: '_handleDocumentClickMove',
value: function _handleDocumentClickMove(e) {
e.preventDefault();
var clickPos = Timepicker._Pos(e);
var x = clickPos.x - this.x0;
var y = clickPos.y - this.y0;
this.moved = true;
this.setHand(x, y, false, true);
}
}, {
key: '_handleDocumentClickEnd',
value: function _handleDocumentClickEnd(e) {
e.preventDefault();
document.removeEventListener('mouseup', this._handleDocumentClickEndBound);
document.removeEventListener('touchend', this._handleDocumentClickEndBound);
var clickPos = Timepicker._Pos(e);
var x = clickPos.x - this.x0;
var y = clickPos.y - this.y0;
if (this.moved && x === this.dx && y === this.dy) {
this.setHand(x, y);
}
if (this.currentView === 'hours') {
this.showView('minutes', this.options.duration / 2);
} else if (this.options.autoClose) {
this.minutesView.addClass('timepicker-dial-out');
setTimeout(function () {
this.done();
}, this.options.duration / 2);
}
// Unbind mousemove event
document.removeEventListener('mousemove', this._handleDocumentClickMoveBound);
document.removeEventListener('touchmove', this._handleDocumentClickMoveBound);
}
}, {
key: '_insertHTMLIntoDOM',
value: function _insertHTMLIntoDOM() {
this.$modalEl = $(Timepicker._template);
this.modalEl = this.$modalEl[0];
this.modalEl.id = 'modal-' + this.id;
// Append popover to input by default
var containerEl = document.querySelector(this.options.container);
if (this.options.container && !!containerEl) {
this.$modalEl.appendTo(containerEl);
} else {
this.$modalEl.insertBefore(this.el);
}
}
}, {
key: '_setupModal',
value: function _setupModal() {
var _this2 = this;
this.modal = M.Modal.init(this.modalEl, {
onCloseEnd: function () {
_this2.isOpen = false;
}
});
}
}, {
key: '_setupVariables',
value: function _setupVariables() {
this.currentView = 'hours';
this.vibrate = navigator.vibrate ? 'vibrate' : navigator.webkitVibrate ? 'webkitVibrate' : null;
this._canvas = this.modalEl.querySelector('.timepicker-canvas');
this.plate = this.modalEl.querySelector('.timepicker-plate');
this.hoursView = this.modalEl.querySelector('.timepicker-hours');
this.minutesView = this.modalEl.querySelector('.timepicker-minutes');
this.spanHours = this.modalEl.querySelector('.timepicker-span-hours');
this.spanMinutes = this.modalEl.querySelector('.timepicker-span-minutes');
this.spanAmPm = this.modalEl.querySelector('.timepicker-span-am-pm');
this.footer = this.modalEl.querySelector('.timepicker-footer');
this.amOrPm = 'PM';
}
}, {
key: '_pickerSetup',
value: function _pickerSetup() {
$('').appendTo(this.footer).on('click', this.clear.bind(this));
var confirmationBtnsContainer = $('
');
$('').appendTo(confirmationBtnsContainer).on('click', this.close.bind(this));
$('').appendTo(confirmationBtnsContainer).on('click', this.done.bind(this));
confirmationBtnsContainer.appendTo(this.footer);
}
}, {
key: '_clockSetup',
value: function _clockSetup() {
if (this.options.twelveHour) {
this.$amBtn = $('AM
');
this.$pmBtn = $('PM
');
this.$amBtn.on('click', this._handleAmPmClick.bind(this)).appendTo(this.spanAmPm);
this.$pmBtn.on('click', this._handleAmPmClick.bind(this)).appendTo(this.spanAmPm);
}
this._buildHoursView();
this._buildMinutesView();
this._buildSVGClock();
}
}, {
key: '_buildSVGClock',
value: function _buildSVGClock() {
// Draw clock hands and others
var dialRadius = this.options.dialRadius;
var tickRadius = this.options.tickRadius;
var diameter = dialRadius * 2;
var svg = Timepicker._createSVGEl('svg');
svg.setAttribute('class', 'timepicker-svg');
svg.setAttribute('width', diameter);
svg.setAttribute('height', diameter);
var g = Timepicker._createSVGEl('g');
g.setAttribute('transform', 'translate(' + dialRadius + ',' + dialRadius + ')');
var bearing = Timepicker._createSVGEl('circle');
bearing.setAttribute('class', 'timepicker-canvas-bearing');
bearing.setAttribute('cx', 0);
bearing.setAttribute('cy', 0);
bearing.setAttribute('r', 4);
var hand = Timepicker._createSVGEl('line');
hand.setAttribute('x1', 0);
hand.setAttribute('y1', 0);
var bg = Timepicker._createSVGEl('circle');
bg.setAttribute('class', 'timepicker-canvas-bg');
bg.setAttribute('r', tickRadius);
g.appendChild(hand);
g.appendChild(bg);
g.appendChild(bearing);
svg.appendChild(g);
this._canvas.appendChild(svg);
this.hand = hand;
this.bg = bg;
this.bearing = bearing;
this.g = g;
}
}, {
key: '_buildHoursView',
value: function _buildHoursView() {
var $tick = $('');
// Hours view
if (this.options.twelveHour) {
for (var i = 1; i < 13; i += 1) {
var tick = $tick.clone();
var radian = i / 6 * Math.PI;
var radius = this.options.outerRadius;
tick.css({
left: this.options.dialRadius + Math.sin(radian) * radius - this.options.tickRadius + 'px',
top: this.options.dialRadius - Math.cos(radian) * radius - this.options.tickRadius + 'px'
});
tick.html(i === 0 ? '00' : i);
this.hoursView.appendChild(tick[0]);
// tick.on(mousedownEvent, mousedown);
}
} else {
for (var _i = 0; _i < 24; _i += 1) {
var _tick = $tick.clone();
var _radian = _i / 6 * Math.PI;
var inner = _i > 0 && _i < 13;
var _radius = inner ? this.options.innerRadius : this.options.outerRadius;
_tick.css({
left: this.options.dialRadius + Math.sin(_radian) * _radius - this.options.tickRadius + 'px',
top: this.options.dialRadius - Math.cos(_radian) * _radius - this.options.tickRadius + 'px'
});
_tick.html(_i === 0 ? '00' : _i);
this.hoursView.appendChild(_tick[0]);
// tick.on(mousedownEvent, mousedown);
}
}
}
}, {
key: '_buildMinutesView',
value: function _buildMinutesView() {
var $tick = $('');
// Minutes view
for (var i = 0; i < 60; i += 5) {
var tick = $tick.clone();
var radian = i / 30 * Math.PI;
tick.css({
left: this.options.dialRadius + Math.sin(radian) * this.options.outerRadius - this.options.tickRadius + 'px',
top: this.options.dialRadius - Math.cos(radian) * this.options.outerRadius - this.options.tickRadius + 'px'
});
tick.html(Timepicker._addLeadingZero(i));
this.minutesView.appendChild(tick[0]);
}
}
}, {
key: '_handleAmPmClick',
value: function _handleAmPmClick(e) {
var $btnClicked = $(e.target);
this.amOrPm = $btnClicked.hasClass('am-btn') ? 'AM' : 'PM';
this._updateAmPmView();
}
}, {
key: '_updateAmPmView',
value: function _updateAmPmView() {
if (this.options.twelveHour) {
this.$amBtn.toggleClass('text-primary', this.amOrPm === 'AM');
this.$pmBtn.toggleClass('text-primary', this.amOrPm === 'PM');
}
}
}, {
key: '_updateTimeFromInput',
value: function _updateTimeFromInput() {
// Get the time
var value = ((this.el.value || this.options.defaultTime || '') + '').split(':');
if (this.options.twelveHour && !(typeof value[1] === 'undefined')) {
if (value[1].toUpperCase().indexOf("AM") > 0) {
this.amOrPm = 'AM';
} else {
this.amOrPm = 'PM';
}
value[1] = value[1].replace("AM", "").replace("PM", "");
}
if (value[0] === 'now') {
var now = new Date(+new Date() + this.options.fromnow);
value = [now.getHours(), now.getMinutes()];
if (this.options.twelveHour) {
this.amOrPm = value[0] >= 12 && value[0] < 24 ? 'PM' : 'AM';
}
}
this.hours = +value[0] || 0;
this.minutes = +value[1] || 0;
this.spanHours.innerHTML = this.hours;
this.spanMinutes.innerHTML = Timepicker._addLeadingZero(this.minutes);
this._updateAmPmView();
}
}, {
key: 'showView',
value: function showView(view, delay) {
if (view === 'minutes' && $(this.hoursView).css("visibility") === "visible") {
// raiseCallback(this.options.beforeHourSelect);
}
var isHours = view === 'hours',
nextView = isHours ? this.hoursView : this.minutesView,
hideView = isHours ? this.minutesView : this.hoursView;
this.currentView = view;
$(this.spanHours).toggleClass('text-primary', isHours);
$(this.spanMinutes).toggleClass('text-primary', !isHours);
// Transition view
hideView.classList.add('timepicker-dial-out');
$(nextView).css('visibility', 'visible').removeClass('timepicker-dial-out');
// Reset clock hand
this.resetClock(delay);
// After transitions ended
clearTimeout(this.toggleViewTimer);
this.toggleViewTimer = setTimeout(function () {
$(hideView).css('visibility', 'hidden');
}, this.options.duration);
}
}, {
key: 'resetClock',
value: function resetClock(delay) {
var view = this.currentView,
value = this[view],
isHours = view === 'hours',
unit = Math.PI / (isHours ? 6 : 30),
radian = value * unit,
radius = isHours && value > 0 && value < 13 ? this.options.innerRadius : this.options.outerRadius,
x = Math.sin(radian) * radius,
y = -Math.cos(radian) * radius,
self = this;
if (delay) {
$(this.canvas).addClass('timepicker-canvas-out');
setTimeout(function () {
$(self.canvas).removeClass('timepicker-canvas-out');
self.setHand(x, y);
}, delay);
} else {
this.setHand(x, y);
}
}
}, {
key: 'setHand',
value: function setHand(x, y, roundBy5) {
var _this3 = this;
var radian = Math.atan2(x, -y),
isHours = this.currentView === 'hours',
unit = Math.PI / (isHours || roundBy5 ? 6 : 30),
z = Math.sqrt(x * x + y * y),
inner = isHours && z < (this.options.outerRadius + this.options.innerRadius) / 2,
radius = inner ? this.options.innerRadius : this.options.outerRadius;
if (this.options.twelveHour) {
radius = this.options.outerRadius;
}
// Radian should in range [0, 2PI]
if (radian < 0) {
radian = Math.PI * 2 + radian;
}
// Get the round value
var value = Math.round(radian / unit);
// Get the round radian
radian = value * unit;
// Correct the hours or minutes
if (this.options.twelveHour) {
if (isHours) {
if (value === 0) value = 12;
} else {
if (roundBy5) value *= 5;
if (value === 60) value = 0;
}
} else {
if (isHours) {
if (value === 12) {
value = 0;
}
value = inner ? value === 0 ? 12 : value : value === 0 ? 0 : value + 12;
} else {
if (roundBy5) {
value *= 5;
}
if (value === 60) {
value = 0;
}
}
}
// Once hours or minutes changed, vibrate the device
if (this[this.currentView] !== value) {
if (this.vibrate && this.options.vibrate) {
// Do not vibrate too frequently
if (!this.vibrateTimer) {
navigator[this.vibrate](10);
this.vibrateTimer = setTimeout(function () {
_this3.vibrateTimer = null;
}, 100);
}
}
}
this[this.currentView] = value;
if (isHours) {
this['spanHours'].innerHTML = value;
} else {
this['spanMinutes'].innerHTML = Timepicker._addLeadingZero(value);
}
// Set clock hand and others' position
var cx1 = Math.sin(radian) * (radius - this.options.tickRadius),
cy1 = -Math.cos(radian) * (radius - this.options.tickRadius),
cx2 = Math.sin(radian) * radius,
cy2 = -Math.cos(radian) * radius;
this.hand.setAttribute('x2', cx1);
this.hand.setAttribute('y2', cy1);
this.bg.setAttribute('cx', cx2);
this.bg.setAttribute('cy', cy2);
}
}, {
key: 'open',
value: function open() {
if (this.isOpen) {
return;
}
this.isOpen = true;
this._updateTimeFromInput();
this.showView('hours');
this.modal.open();
}
}, {
key: 'close',
value: function close() {
if (!this.isOpen) {
return;
}
this.isOpen = false;
this.modal.close();
}
/**
* Finish timepicker selection.
*/
}, {
key: 'done',
value: function done(e, clearValue) {
// Set input value
var last = this.el.value;
var value = clearValue ? '' : Timepicker._addLeadingZero(this.hours) + ':' + Timepicker._addLeadingZero(this.minutes);
this.time = value;
if (!clearValue && this.options.twelveHour) {
value = value + ' ' + this.amOrPm;
}
this.el.value = value;
// Trigger change event
if (value !== last) {
this.$el.trigger('change');
}
this.close();
this.el.focus();
}
}, {
key: 'clear',
value: function clear() {
this.done(null, true);
}
}], [{
key: 'init',
value: function init(els, options) {
return _get(Timepicker.__proto__ || Object.getPrototypeOf(Timepicker), 'init', this).call(this, this, els, options);
}
}, {
key: '_addLeadingZero',
value: function _addLeadingZero(num) {
return (num < 10 ? '0' : '') + num;
}
}, {
key: '_createSVGEl',
value: function _createSVGEl(name) {
var svgNS = 'http://www.w3.org/2000/svg';
return document.createElementNS(svgNS, name);
}
/**
* @typedef {Object} Point
* @property {number} x The X Coordinate
* @property {number} y The Y Coordinate
*/
/**
* Get x position of mouse or touch event
* @param {Event} e
* @return {Point} x and y location
*/
}, {
key: '_Pos',
value: function _Pos(e) {
if (e.targetTouches && e.targetTouches.length >= 1) {
return { x: e.targetTouches[0].clientX, y: e.targetTouches[0].clientY };
}
// mouse event
return { x: e.clientX, y: e.clientY };
}
/**
* Get Instance
*/
}, {
key: 'getInstance',
value: function getInstance(el) {
var domElem = !!el.jquery ? el[0] : el;
return domElem.M_Timepicker;
}
}, {
key: 'defaults',
get: function () {
return _defaults;
}
}]);
return Timepicker;
}(Component);
Timepicker._template = ['', '
', '
', '
', '
', '', ':', '', '
', '
', '
', '
', '
', '
', '
'].join('');
M.Timepicker = Timepicker;
if (M.jQueryLoaded) {
M.initializeJqueryWrapper(Timepicker, 'timepicker', 'M_Timepicker');
}
})(cash);