/* globals define */ (function(define){'use strict';define(['require','exports','module','gaia-component','drag'],function(require,exports,module){ /** * Dependencies */ var component = require('gaia-component'); var Drag = require('drag'); /** * Simple logger * @type {Function} */ var debug = 0 ? console.log.bind(console) : function() {}; /** * Exports */ module.exports = component.register('gaia-switch', { extends: HTMLInputElement.prototype, rtl: true, created: function() { this.setupShadowRoot(); this.els = { inner: this.shadowRoot.querySelector('.inner'), track: this.shadowRoot.querySelector('.track'), handle: this.shadowRoot.querySelector('.handle') }; // Bind context this.updateDir = this.updateDir.bind(this); this.toggle = this.toggle.bind(this); // Events on(this, 'click', e => this.onClick(e)); // Configure this.setupDrag(); this.disabled = this.getAttribute('disabled'); this.checked = this.getAttribute('checked'); // process everything that doesn't affect user interaction // after the component is created setTimeout(() => { // enable transitions after creation this.activateTransitions(); this.makeAccessible(); }); }, /** * Accessibility enhancements. * Read gaia-switch as switch. * make it tabable * read its checked and disabled state */ makeAccessible: function() { this.setAttribute('role', 'switch'); // Make tabable this.tabIndex = 0; this.setAttribute('aria-checked', this.checked); if (this.disabled) { this.setAttr('aria-disabled', true); } }, attached: function() { debug('attached'); on(document, 'dirchanged', this.updateDir); }, detached: function() { debug('detached'); off(document, 'dirchanged', this.updateDir); }, setupDrag: function() { debug('setup drag'); this.drag = new Drag({ container: { el: this.els.track, width: 50, height: 32 }, handle: { el: this.els.handle, width: 32, height: 32, x: 0, y: 0 }, }); this.drag.on('ended', () => this.drag.snap()); this.drag.on('snapped', (e) => this.onSnapped(e)); }, activateTransitions: function() { debug('activate transitions'); this.els.inner.classList.add('transitions-on'); }, onClick: function(e) { debug('click', e); e.stopPropagation(); if (this.drag.dragging) { return; } if (this.disabled) { return; } this.toggle(); }, updateDir: function() { debug('update dir', dir()); this.updatePosition(); }, onSnapped: function(e) { debug('snapped', e, convert.toChecked(e.detail.x)); this.checked = convert.toChecked(e.detail.x); }, toggle: function(value) { debug('toggle', value); this.checked = !this.checked; }, updatePosition: function() { var edge = convert.toEdge(this.checked); this.drag.transition(edge, 0); debug('updated position', edge); }, attrs: { checked: { get: function() { return this._checked; }, set: function(value) { debug('set checked', value); value = !!(value || value === ''); if (this._checked === value) { return; } var changed = this._checked !== undefined; this._checked = value; this.els.handle.style.transform = ''; this.els.handle.style.transition = ''; if (value) { this.setAttr('checked', ''); this.setAttribute('aria-checked', true); } else { this.removeAttr('checked'); this.setAttribute('aria-checked', false); } this.updatePosition(); if (changed) { this.dispatchEvent(new CustomEvent('change')); } } }, disabled: { get: function() { return this._disabled; }, set: function(value) { value = !!(value || value === ''); if (this._disabled === value) { return; } debug('set disabled', value); this._disabled = value; if (value) { this.setAttr('disabled', ''); this.setAttr('aria-disabled', true); } else { this.removeAttr('disabled'); this.removeAttr('aria-disabled'); } } } }, template: `