',
- monthHtml = void 0,
- yearHtml = void 0,
- prev = true,
- next = true;
-
- for (arr = [], i = 0; i < 12; i++) {
- arr.push('
');
- }
-
- monthHtml = '
';
-
- if ($.isArray(opts.yearRange)) {
- i = opts.yearRange[0];
- j = opts.yearRange[1] + 1;
- } else {
- i = year - opts.yearRange;
- j = 1 + year + opts.yearRange;
- }
-
- for (arr = []; i < j && i <= opts.maxYear; i++) {
- if (i >= opts.minYear) {
- arr.push("
");
- }
- }
- if (opts.yearRangeReverse) {
- arr.reverse();
- }
-
- yearHtml = "
";
-
- var leftArrow = '
';
- html += "
";
-
- html += '
';
- if (opts.showMonthAfterYear) {
- html += yearHtml + monthHtml;
- } else {
- html += monthHtml + yearHtml;
- }
- html += '
';
-
- if (isMinYear && (month === 0 || opts.minMonth >= month)) {
- prev = false;
- }
-
- if (isMaxYear && (month === 11 || opts.maxMonth <= month)) {
- next = false;
- }
-
- var rightArrow = '
';
- html += "
";
-
- return html += '
';
- }
-
- /**
- * refresh the HTML
- */
-
- }, {
- key: "draw",
- value: function draw(force) {
- if (!this.isOpen && !force) {
- return;
- }
- var opts = this.options,
- minYear = opts.minYear,
- maxYear = opts.maxYear,
- minMonth = opts.minMonth,
- maxMonth = opts.maxMonth,
- html = '',
- randId = void 0;
-
- if (this._y <= minYear) {
- this._y = minYear;
- if (!isNaN(minMonth) && this._m < minMonth) {
- this._m = minMonth;
- }
- }
- if (this._y >= maxYear) {
- this._y = maxYear;
- if (!isNaN(maxMonth) && this._m > maxMonth) {
- this._m = maxMonth;
- }
- }
-
- randId = 'datepicker-title-' + Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 2);
-
- for (var c = 0; c < 1; c++) {
- this._renderDateDisplay();
- html += this.renderTitle(this, c, this.calendars[c].year, this.calendars[c].month, this.calendars[0].year, randId) + this.render(this.calendars[c].year, this.calendars[c].month, randId);
- }
-
- this.destroySelects();
-
- this.calendarEl.innerHTML = html;
-
- // Init Materialize Select
- var yearSelect = this.calendarEl.querySelector('.orig-select-year');
- var monthSelect = this.calendarEl.querySelector('.orig-select-month');
- M.FormSelect.init(yearSelect, {
- classes: 'select-year',
- dropdownOptions: { container: document.body, constrainWidth: false }
- });
- M.FormSelect.init(monthSelect, {
- classes: 'select-month',
- dropdownOptions: { container: document.body, constrainWidth: false }
- });
-
- // Add change handlers for select
- yearSelect.addEventListener('change', this._handleYearChange.bind(this));
- monthSelect.addEventListener('change', this._handleMonthChange.bind(this));
-
- if (typeof this.options.onDraw === 'function') {
- this.options.onDraw(this);
- }
- }
-
- /**
- * Setup Event Handlers
- */
-
- }, {
- key: "_setupEventHandlers",
- value: function _setupEventHandlers() {
- this._handleInputKeydownBound = this._handleInputKeydown.bind(this);
- this._handleInputClickBound = this._handleInputClick.bind(this);
- this._handleInputChangeBound = this._handleInputChange.bind(this);
- this._handleCalendarClickBound = this._handleCalendarClick.bind(this);
- this._finishSelectionBound = this._finishSelection.bind(this);
- this._handleMonthChange = this._handleMonthChange.bind(this);
- this._closeBound = this.close.bind(this);
-
- this.el.addEventListener('click', this._handleInputClickBound);
- this.el.addEventListener('keydown', this._handleInputKeydownBound);
- this.el.addEventListener('change', this._handleInputChangeBound);
- this.calendarEl.addEventListener('click', this._handleCalendarClickBound);
- this.doneBtn.addEventListener('click', this._finishSelectionBound);
- this.cancelBtn.addEventListener('click', this._closeBound);
-
- if (this.options.showClearBtn) {
- this._handleClearClickBound = this._handleClearClick.bind(this);
- this.clearBtn.addEventListener('click', this._handleClearClickBound);
- }
- }
- }, {
- key: "_setupVariables",
- value: function _setupVariables() {
- var _this56 = this;
-
- this.$modalEl = $(Datepicker._template);
- this.modalEl = this.$modalEl[0];
-
- this.calendarEl = this.modalEl.querySelector('.datepicker-calendar');
-
- this.yearTextEl = this.modalEl.querySelector('.year-text');
- this.dateTextEl = this.modalEl.querySelector('.date-text');
- if (this.options.showClearBtn) {
- this.clearBtn = this.modalEl.querySelector('.datepicker-clear');
- }
- this.doneBtn = this.modalEl.querySelector('.datepicker-done');
- this.cancelBtn = this.modalEl.querySelector('.datepicker-cancel');
-
- this.formats = {
- d: function () {
- return _this56.date.getDate();
- },
- dd: function () {
- var d = _this56.date.getDate();
- return (d < 10 ? '0' : '') + d;
- },
- ddd: function () {
- return _this56.options.i18n.weekdaysShort[_this56.date.getDay()];
- },
- dddd: function () {
- return _this56.options.i18n.weekdays[_this56.date.getDay()];
- },
- m: function () {
- return _this56.date.getMonth() + 1;
- },
- mm: function () {
- var m = _this56.date.getMonth() + 1;
- return (m < 10 ? '0' : '') + m;
- },
- mmm: function () {
- return _this56.options.i18n.monthsShort[_this56.date.getMonth()];
- },
- mmmm: function () {
- return _this56.options.i18n.months[_this56.date.getMonth()];
- },
- yy: function () {
- return ('' + _this56.date.getFullYear()).slice(2);
- },
- yyyy: function () {
- return _this56.date.getFullYear();
- }
+ onClose: null
+};
+class TapTarget extends component_1.Component {
+ constructor(el, options) {
+ super(el, options, TapTarget);
+ this._handleThrottledResize = utils_1.Utils.throttle(function () { this._handleResize(); }, 200).bind(this);
+ this._handleTargetClick = () => {
+ this.open();
};
- }
-
- /**
- * Remove Event Handlers
- */
-
- }, {
- key: "_removeEventHandlers",
- value: function _removeEventHandlers() {
- this.el.removeEventListener('click', this._handleInputClickBound);
- this.el.removeEventListener('keydown', this._handleInputKeydownBound);
- this.el.removeEventListener('change', this._handleInputChangeBound);
- this.calendarEl.removeEventListener('click', this._handleCalendarClickBound);
- }
- }, {
- key: "_handleInputClick",
- value: function _handleInputClick() {
- this.open();
- }
- }, {
- key: "_handleInputKeydown",
- value: function _handleInputKeydown(e) {
- if (e.which === M.keys.ENTER) {
- e.preventDefault();
- this.open();
- }
- }
- }, {
- key: "_handleCalendarClick",
- value: function _handleCalendarClick(e) {
- if (!this.isOpen) {
- return;
- }
-
- var $target = $(e.target);
- if (!$target.hasClass('is-disabled')) {
- if ($target.hasClass('datepicker-day-button') && !$target.hasClass('is-empty') && !$target.parent().hasClass('is-disabled')) {
- this.setDate(new Date(e.target.getAttribute('data-year'), e.target.getAttribute('data-month'), e.target.getAttribute('data-day')));
- if (this.options.autoClose) {
- this._finishSelection();
+ this._handleOriginClick = () => {
+ this.close();
+ };
+ this._handleResize = () => {
+ this._calculatePositioning();
+ };
+ this._handleDocumentClick = (e) => {
+ if (!e.target.closest('.tap-target-wrapper')) {
+ this.close();
+ e.preventDefault();
+ e.stopPropagation();
}
- } else if ($target.closest('.month-prev').length) {
- this.prevMonth();
- } else if ($target.closest('.month-next').length) {
- this.nextMonth();
- }
- }
- }
- }, {
- key: "_handleClearClick",
- value: function _handleClearClick() {
- this.date = null;
- this.setInputValue();
- this.close();
- }
- }, {
- key: "_handleMonthChange",
- value: function _handleMonthChange(e) {
- this.gotoMonth(e.target.value);
- }
- }, {
- key: "_handleYearChange",
- value: function _handleYearChange(e) {
- this.gotoYear(e.target.value);
- }
-
- /**
- * change view to a specific month (zero-index, e.g. 0: January)
- */
-
- }, {
- key: "gotoMonth",
- value: function gotoMonth(month) {
- if (!isNaN(month)) {
- this.calendars[0].month = parseInt(month, 10);
- this.adjustCalendars();
- }
- }
-
- /**
- * change view to a specific full year (e.g. "2012")
- */
-
- }, {
- key: "gotoYear",
- value: function gotoYear(year) {
- if (!isNaN(year)) {
- this.calendars[0].year = parseInt(year, 10);
- this.adjustCalendars();
- }
- }
- }, {
- key: "_handleInputChange",
- value: function _handleInputChange(e) {
- var date = void 0;
-
- // Prevent change event from being fired when triggered by the plugin
- if (e.firedBy === this) {
- return;
- }
- if (this.options.parse) {
- date = this.options.parse(this.el.value, this.options.format);
- } else {
- date = new Date(Date.parse(this.el.value));
- }
-
- if (Datepicker._isDate(date)) {
- this.setDate(date);
- }
- }
- }, {
- key: "renderDayName",
- value: function renderDayName(opts, day, abbr) {
- day += opts.firstDay;
- while (day >= 7) {
- day -= 7;
- }
- return abbr ? opts.i18n.weekdaysAbbrev[day] : opts.i18n.weekdays[day];
- }
-
- /**
- * Set input value to the selected date and close Datepicker
- */
-
- }, {
- key: "_finishSelection",
- value: function _finishSelection() {
- this.setInputValue();
- this.close();
- }
-
- /**
- * Open Datepicker
- */
-
- }, {
- key: "open",
- value: function open() {
- if (this.isOpen) {
- return;
- }
-
- this.isOpen = true;
- if (typeof this.options.onOpen === 'function') {
- this.options.onOpen.call(this);
- }
- this.draw();
- this.modal.open();
- return this;
- }
-
- /**
- * Close Datepicker
- */
-
- }, {
- key: "close",
- value: function close() {
- if (!this.isOpen) {
- return;
- }
-
+ };
+ /**
+ * Open Tap Target.
+ */
+ this.open = () => {
+ if (this.isOpen)
+ return;
+ // onOpen callback
+ if (typeof this.options.onOpen === 'function') {
+ this.options.onOpen.call(this, this._origin);
+ }
+ this.isOpen = true;
+ this.wrapper.classList.add('open');
+ document.body.addEventListener('click', this._handleDocumentClick, true);
+ document.body.addEventListener('touchend', this._handleDocumentClick);
+ };
+ /**
+ * Close Tap Target.
+ */
+ this.close = () => {
+ if (!this.isOpen)
+ return;
+ // onClose callback
+ if (typeof this.options.onClose === 'function') {
+ this.options.onClose.call(this, this._origin);
+ }
+ this.isOpen = false;
+ this.wrapper.classList.remove('open');
+ document.body.removeEventListener('click', this._handleDocumentClick, true);
+ document.body.removeEventListener('touchend', this._handleDocumentClick);
+ };
+ this.el.M_TapTarget = this;
+ this.options = Object.assign(Object.assign({}, TapTarget.defaults), options);
this.isOpen = false;
- if (typeof this.options.onClose === 'function') {
- this.options.onClose.call(this);
- }
- this.modal.close();
- return this;
- }
- }], [{
- key: "init",
- value: function init(els, options) {
- return _get(Datepicker.__proto__ || Object.getPrototypeOf(Datepicker), "init", this).call(this, this, els, options);
- }
- }, {
- key: "_isDate",
- value: function _isDate(obj) {
- return (/Date/.test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime())
- );
- }
- }, {
- key: "_isWeekend",
- value: function _isWeekend(date) {
- var day = date.getDay();
- return day === 0 || day === 6;
- }
- }, {
- key: "_setToStartOfDay",
- value: function _setToStartOfDay(date) {
- if (Datepicker._isDate(date)) date.setHours(0, 0, 0, 0);
- }
- }, {
- key: "_getDaysInMonth",
- value: function _getDaysInMonth(year, month) {
- return [31, Datepicker._isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
- }
- }, {
- key: "_isLeapYear",
- value: function _isLeapYear(year) {
- // solution by Matti Virkkunen: http://stackoverflow.com/a/4881951
- return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
- }
- }, {
- key: "_compareDates",
- value: function _compareDates(a, b) {
- // weak date comparison (use setToStartOfDay(date) to ensure correct result)
- return a.getTime() === b.getTime();
- }
- }, {
- key: "_setToStartOfDay",
- value: function _setToStartOfDay(date) {
- if (Datepicker._isDate(date)) date.setHours(0, 0, 0, 0);
- }
-
- /**
- * Get Instance
- */
-
- }, {
- key: "getInstance",
- value: function getInstance(el) {
- var domElem = !!el.jquery ? el[0] : el;
- return domElem.M_Datepicker;
- }
- }, {
- key: "defaults",
- get: function () {
+ // setup
+ this._origin = document.querySelector(`#${el.dataset.target}`);
+ this._setup();
+ this._calculatePositioning();
+ this._setupEventHandlers();
+ }
+ static get defaults() {
return _defaults;
- }
- }]);
+ }
+ /**
+ * Initializes instances of TapTarget.
+ * @param els HTML elements.
+ * @param options Component options.
+ */
+ static init(els, options = {}) {
+ return super.init(els, options, TapTarget);
+ }
+ static getInstance(el) {
+ return el.M_TapTarget;
+ }
+ destroy() {
+ this._removeEventHandlers();
+ this.el.TapTarget = undefined;
+ }
+ _setupEventHandlers() {
+ this.el.addEventListener('click', this._handleTargetClick);
+ this.originEl.addEventListener('click', this._handleOriginClick);
+ // Resize
+ window.addEventListener('resize', this._handleThrottledResize);
+ }
+ _removeEventHandlers() {
+ this.el.removeEventListener('click', this._handleTargetClick);
+ this.originEl.removeEventListener('click', this._handleOriginClick);
+ window.removeEventListener('resize', this._handleThrottledResize);
+ }
+ _setup() {
+ // Creating tap target
+ this.wrapper = this.el.parentElement;
+ this.waveEl = this.wrapper.querySelector('.tap-target-wave');
+ this.originEl = this.wrapper.querySelector('.tap-target-origin');
+ this.contentEl = this.el.querySelector('.tap-target-content');
+ // Creating wrapper
+ if (!this.wrapper.classList.contains('.tap-target-wrapper')) {
+ this.wrapper = document.createElement('div');
+ this.wrapper.classList.add('tap-target-wrapper');
+ this.el.before(this.wrapper);
+ this.wrapper.append(this.el);
+ }
+ // Creating content
+ if (!this.contentEl) {
+ this.contentEl = document.createElement('div');
+ this.contentEl.classList.add('tap-target-content');
+ this.el.append(this.contentEl);
+ }
+ // Creating foreground wave
+ if (!this.waveEl) {
+ this.waveEl = document.createElement('div');
+ this.waveEl.classList.add('tap-target-wave');
+ // Creating origin
+ if (!this.originEl) {
+ this.originEl = this._origin.cloneNode(true); // .clone(true, true);
+ this.originEl.classList.add('tap-target-origin');
+ this.originEl.removeAttribute('id');
+ this.originEl.removeAttribute('style');
+ this.waveEl.append(this.originEl);
+ }
+ this.wrapper.append(this.waveEl);
+ }
+ }
+ _offset(el) {
+ const box = el.getBoundingClientRect();
+ const docElem = document.documentElement;
+ return {
+ top: box.top + window.pageYOffset - docElem.clientTop,
+ left: box.left + window.pageXOffset - docElem.clientLeft
+ };
+ }
+ _calculatePositioning() {
+ // Element or parent is fixed position?
+ let isFixed = getComputedStyle(this._origin).position === 'fixed';
+ if (!isFixed) {
+ let currentElem = this._origin;
+ const parents = [];
+ while ((currentElem = currentElem.parentNode) && currentElem !== document)
+ parents.push(currentElem);
+ for (let i = 0; i < parents.length; i++) {
+ isFixed = getComputedStyle(parents[i]).position === 'fixed';
+ if (isFixed)
+ break;
+ }
+ }
+ // Calculating origin
+ const originWidth = this._origin.offsetWidth;
+ const originHeight = this._origin.offsetHeight;
+ const originTop = isFixed ? this._offset(this._origin).top - utils_1.Utils.getDocumentScrollTop() : this._offset(this._origin).top;
+ const originLeft = isFixed ? this._offset(this._origin).left - utils_1.Utils.getDocumentScrollLeft() : this._offset(this._origin).left;
+ // Calculating screen
+ const windowWidth = window.innerWidth;
+ const windowHeight = window.innerHeight;
+ const scrollBarWidth = windowWidth - document.documentElement.clientWidth;
+ const centerX = windowWidth / 2;
+ const centerY = windowHeight / 2;
+ const isLeft = originLeft <= centerX;
+ const isRight = originLeft > centerX;
+ const isTop = originTop <= centerY;
+ const isBottom = originTop > centerY;
+ const isCenterX = originLeft >= windowWidth * 0.25 && originLeft <= windowWidth * 0.75;
+ // Calculating tap target
+ const tapTargetWidth = this.el.offsetWidth;
+ const tapTargetHeight = this.el.offsetHeight;
+ const tapTargetTop = originTop + originHeight / 2 - tapTargetHeight / 2;
+ const tapTargetLeft = originLeft + originWidth / 2 - tapTargetWidth / 2;
+ const tapTargetPosition = isFixed ? 'fixed' : 'absolute';
+ // Calculating content
+ const tapTargetTextWidth = isCenterX ? tapTargetWidth : tapTargetWidth / 2 + originWidth;
+ const tapTargetTextHeight = tapTargetHeight / 2;
+ const tapTargetTextTop = isTop ? tapTargetHeight / 2 : 0;
+ const tapTargetTextBottom = 0;
+ const tapTargetTextLeft = isLeft && !isCenterX ? tapTargetWidth / 2 - originWidth : 0;
+ const tapTargetTextRight = 0;
+ const tapTargetTextPadding = originWidth;
+ const tapTargetTextAlign = isBottom ? 'bottom' : 'top';
+ // Calculating wave
+ const tapTargetWaveWidth = originWidth > originHeight ? originWidth * 2 : originWidth * 2;
+ const tapTargetWaveHeight = tapTargetWaveWidth;
+ const tapTargetWaveTop = tapTargetHeight / 2 - tapTargetWaveHeight / 2;
+ const tapTargetWaveLeft = tapTargetWidth / 2 - tapTargetWaveWidth / 2;
+ // Setting tap target
+ this.wrapper.style.top = isTop ? tapTargetTop + 'px' : '';
+ this.wrapper.style.right = isRight ? windowWidth - tapTargetLeft - tapTargetWidth - scrollBarWidth + 'px' : '';
+ this.wrapper.style.bottom = isBottom ? windowHeight - tapTargetTop - tapTargetHeight + 'px' : '';
+ this.wrapper.style.left = isLeft ? tapTargetLeft + 'px' : '';
+ this.wrapper.style.position = tapTargetPosition;
+ // Setting content
+ this.contentEl.style.width = tapTargetTextWidth + 'px';
+ this.contentEl.style.height = tapTargetTextHeight + 'px';
+ this.contentEl.style.top = tapTargetTextTop + 'px';
+ this.contentEl.style.right = tapTargetTextRight + 'px';
+ this.contentEl.style.bottom = tapTargetTextBottom + 'px';
+ this.contentEl.style.left = tapTargetTextLeft + 'px';
+ this.contentEl.style.padding = tapTargetTextPadding + 'px';
+ this.contentEl.style.verticalAlign = tapTargetTextAlign;
+ // Setting wave
+ this.waveEl.style.top = tapTargetWaveTop + 'px';
+ this.waveEl.style.left = tapTargetWaveLeft + 'px';
+ this.waveEl.style.width = tapTargetWaveWidth + 'px';
+ this.waveEl.style.height = tapTargetWaveHeight + 'px';
+ }
+}
+exports.TapTarget = TapTarget;
- return Datepicker;
- }(Component);
- Datepicker._template = ['