No Description

ons-switch.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. import _toConsumableArray from 'babel-runtime/helpers/toConsumableArray';
  2. import _Object$getPrototypeOf from 'babel-runtime/core-js/object/get-prototype-of';
  3. import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
  4. import _createClass from 'babel-runtime/helpers/createClass';
  5. import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
  6. import _get from 'babel-runtime/helpers/get';
  7. import _inherits from 'babel-runtime/helpers/inherits';
  8. /*
  9. Copyright 2013-2015 ASIAL CORPORATION
  10. Licensed under the Apache License, Version 2.0 (the "License");
  11. you may not use this file except in compliance with the License.
  12. You may obtain a copy of the License at
  13. http://www.apache.org/licenses/LICENSE-2.0
  14. Unless required by applicable law or agreed to in writing, software
  15. distributed under the License is distributed on an "AS IS" BASIS,
  16. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. See the License for the specific language governing permissions and
  18. limitations under the License.
  19. */
  20. import onsElements from '../ons/elements';
  21. import util from '../ons/util';
  22. import autoStyle from '../ons/autostyle';
  23. import ModifierUtil from '../ons/internal/modifier-util';
  24. import BaseCheckboxElement from './base/base-checkbox';
  25. import contentReady from '../ons/content-ready';
  26. import GestureDetector from '../ons/gesture-detector';
  27. var scheme = {
  28. '': 'switch--*',
  29. '.switch__input': 'switch--*__input',
  30. '.switch__handle': 'switch--*__handle',
  31. '.switch__toggle': 'switch--*__toggle'
  32. };
  33. var locations = {
  34. ios: [1, 21],
  35. material: [0, 16]
  36. };
  37. /**
  38. * @element ons-switch
  39. * @category form
  40. * @description
  41. * [en]
  42. * Switch component. The switch can be toggled both by dragging and tapping.
  43. *
  44. * Will automatically displays a Material Design switch on Android devices.
  45. * [/en]
  46. * [ja]スイッチを表示するコンポーネントです。[/ja]
  47. * @modifier material
  48. * [en]Material Design switch[/en]
  49. * [ja][/ja]
  50. * @codepen LpXZQQ
  51. * @tutorial vanilla/Reference/switch
  52. * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
  53. * @example
  54. * <ons-switch checked></ons-switch>
  55. * <ons-switch disabled></ons-switch>
  56. * <ons-switch modifier="material"></ons-switch>
  57. */
  58. var SwitchElement = function (_BaseCheckboxElement) {
  59. _inherits(SwitchElement, _BaseCheckboxElement);
  60. function SwitchElement() {
  61. _classCallCheck(this, SwitchElement);
  62. var _this = _possibleConstructorReturn(this, (SwitchElement.__proto__ || _Object$getPrototypeOf(SwitchElement)).call(this));
  63. contentReady(_this, function () {
  64. _this.attributeChangedCallback('modifier', null, _this.getAttribute('modifier'));
  65. });
  66. _this._onChange = _this._onChange.bind(_this);
  67. _this._onRelease = _this._onRelease.bind(_this);
  68. _this._lastTimeStamp = 0;
  69. return _this;
  70. }
  71. _createClass(SwitchElement, [{
  72. key: '_getPosition',
  73. /* Own props */
  74. value: function _getPosition(e) {
  75. var l = this._locations;
  76. return Math.min(l[1], Math.max(l[0], this._startX + e.gesture.deltaX));
  77. }
  78. }, {
  79. key: '_emitChangeEvent',
  80. value: function _emitChangeEvent() {
  81. util.triggerElementEvent(this, 'change', {
  82. value: this.checked,
  83. switch: this,
  84. isInteractive: true
  85. });
  86. }
  87. }, {
  88. key: '_onChange',
  89. value: function _onChange(event) {
  90. if (event && event.stopPropagation) {
  91. event.stopPropagation();
  92. }
  93. this._emitChangeEvent();
  94. }
  95. }, {
  96. key: '_onClick',
  97. value: function _onClick(ev) {
  98. if (ev.target.classList.contains(this.defaultElementClass + '__touch') || ev.timeStamp - this._lastTimeStamp < 50 // Prevent second click triggered by <label>
  99. ) {
  100. ev.preventDefault();
  101. }
  102. this._lastTimeStamp = ev.timeStamp;
  103. }
  104. }, {
  105. key: '_onHold',
  106. value: function _onHold(e) {
  107. if (!this.disabled) {
  108. ModifierUtil.addModifier(this, 'active');
  109. document.addEventListener('release', this._onRelease);
  110. }
  111. }
  112. }, {
  113. key: '_onDragStart',
  114. value: function _onDragStart(e) {
  115. if (this.disabled || ['left', 'right'].indexOf(e.gesture.direction) === -1) {
  116. ModifierUtil.removeModifier(this, 'active');
  117. return;
  118. }
  119. e.consumed = true;
  120. ModifierUtil.addModifier(this, 'active');
  121. this._startX = this._locations[this.checked ? 1 : 0]; // - e.gesture.deltaX;
  122. this.addEventListener('drag', this._onDrag);
  123. document.addEventListener('release', this._onRelease);
  124. }
  125. }, {
  126. key: '_onDrag',
  127. value: function _onDrag(e) {
  128. e.stopPropagation();
  129. this._handle.style.left = this._getPosition(e) + 'px';
  130. }
  131. }, {
  132. key: '_onRelease',
  133. value: function _onRelease(e) {
  134. var l = this._locations;
  135. var position = this._getPosition(e);
  136. var previousValue = this.checked;
  137. this.checked = position >= (l[0] + l[1]) / 2;
  138. if (this.checked !== previousValue) {
  139. this._emitChangeEvent();
  140. }
  141. this.removeEventListener('drag', this._onDrag);
  142. document.removeEventListener('release', this._onRelease);
  143. this._handle.style.left = '';
  144. ModifierUtil.removeModifier(this, 'active');
  145. }
  146. }, {
  147. key: 'click',
  148. value: function click() {
  149. var ev = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  150. if (!this.disabled) {
  151. this.checked = !this.checked;
  152. this._emitChangeEvent();
  153. this._lastTimeStamp = ev.timeStamp || 0;
  154. }
  155. }
  156. }, {
  157. key: 'connectedCallback',
  158. value: function connectedCallback() {
  159. var _this2 = this;
  160. contentReady(this, function () {
  161. _this2._input.addEventListener('change', _this2._onChange);
  162. });
  163. this.addEventListener('dragstart', this._onDragStart);
  164. this.addEventListener('hold', this._onHold);
  165. this.addEventListener('tap', this.click);
  166. this.addEventListener('click', this._onClick);
  167. this._gestureDetector = new GestureDetector(this, { dragMinDistance: 1, holdTimeout: 251, passive: true });
  168. }
  169. }, {
  170. key: 'disconnectedCallback',
  171. value: function disconnectedCallback() {
  172. var _this3 = this;
  173. contentReady(this, function () {
  174. _this3._input.removeEventListener('change', _this3._onChange);
  175. });
  176. this.removeEventListener('dragstart', this._onDragStart);
  177. this.removeEventListener('hold', this._onHold);
  178. this.removeEventListener('tap', this.click);
  179. this.removeEventListener('click', this._onClick);
  180. if (this._gestureDetector) {
  181. this._gestureDetector.dispose();
  182. }
  183. }
  184. }, {
  185. key: 'attributeChangedCallback',
  186. value: function attributeChangedCallback(name, last, current) {
  187. if (name === 'modifier') {
  188. var md = (current || '').indexOf('material') !== -1;
  189. this._locations = locations[md ? 'material' : 'ios'];
  190. }
  191. _get(SwitchElement.prototype.__proto__ || _Object$getPrototypeOf(SwitchElement.prototype), 'attributeChangedCallback', this).call(this, name, last, current);
  192. }
  193. /**
  194. * @event change
  195. * @description
  196. * [en]Fired when the switch is toggled.[/en]
  197. * [ja]ON/OFFが変わった時に発火します。[/ja]
  198. * @param {Object} event
  199. * [en]Event object.[/en]
  200. * [ja]イベントオブジェクト。[/ja]
  201. * @param {Object} event.switch
  202. * [en]Switch object.[/en]
  203. * [ja]イベントが発火したSwitchオブジェクトを返します。[/ja]
  204. * @param {Boolean} event.value
  205. * [en]Current value.[/en]
  206. * [ja]現在の値を返します。[/ja]
  207. * @param {Boolean} event.isInteractive
  208. * [en]True if the change was triggered by the user clicking on the switch.[/en]
  209. * [ja]タップやクリックなどのユーザの操作によって変わった場合にはtrueを返します。[/ja]
  210. */
  211. /**
  212. * @attribute modifier
  213. * @type {String}
  214. * @description
  215. * [en]The appearance of the switch.[/en]
  216. * [ja]スイッチの表現を指定します。[/ja]
  217. */
  218. /**
  219. * @attribute disabled
  220. * @description
  221. * [en]Whether the switch is be disabled.[/en]
  222. * [ja]スイッチを無効の状態にする場合に指定します。[/ja]
  223. */
  224. /**
  225. * @attribute checked
  226. * @description
  227. * [en]Whether the switch is checked.[/en]
  228. * [ja]スイッチがONの状態にするときに指定します。[/ja]
  229. */
  230. /**
  231. * @attribute input-id
  232. * @type {String}
  233. * @description
  234. * [en]Specify the `id` attribute of the inner `<input>` element. This is useful when using `<label for="...">` elements.[/en]
  235. * [ja][/ja]
  236. */
  237. /**
  238. * @property checked
  239. * @type {Boolean}
  240. * @description
  241. * [en]This value is `true` if the switch is checked.[/en]
  242. * [ja]スイッチがONの場合に`true`。[/ja]
  243. */
  244. /**
  245. * @property value
  246. * @type {String}
  247. * @description
  248. * [en]The current value of the input.[/en]
  249. * [ja][/ja]
  250. */
  251. /**
  252. * @property disabled
  253. * @type {Boolean}
  254. * @description
  255. * [en]Whether the element is disabled or not.[/en]
  256. * [ja]無効化されている場合に`true`。[/ja]
  257. */
  258. /**
  259. * @property checkbox
  260. * @readonly
  261. * @type {HTMLElement}
  262. * @description
  263. * [en]The underlying checkbox element.[/en]
  264. * [ja]コンポーネント内部のcheckbox要素になります。[/ja]
  265. */
  266. }, {
  267. key: '_scheme',
  268. get: function get() {
  269. return scheme;
  270. }
  271. }, {
  272. key: '_defaultClassName',
  273. get: function get() {
  274. return 'switch';
  275. }
  276. }, {
  277. key: '_template',
  278. get: function get() {
  279. return '\n <input type="' + this.type + '" class="' + this._defaultClassName + '__input">\n <div class="' + this._defaultClassName + '__toggle">\n <div class="' + this._defaultClassName + '__handle">\n <div class="' + this._defaultClassName + '__touch"></div>\n </div>\n </div>\n ';
  280. }
  281. }, {
  282. key: 'type',
  283. get: function get() {
  284. return 'checkbox';
  285. }
  286. }, {
  287. key: '_handle',
  288. get: function get() {
  289. return this.querySelector('.' + this._defaultClassName + '__handle');
  290. }
  291. }, {
  292. key: 'checkbox',
  293. get: function get() {
  294. return this._input;
  295. }
  296. }], [{
  297. key: 'observedAttributes',
  298. get: function get() {
  299. return [].concat(_toConsumableArray(_get(SwitchElement.__proto__ || _Object$getPrototypeOf(SwitchElement), 'observedAttributes', this)), ['modifier']);
  300. }
  301. }]);
  302. return SwitchElement;
  303. }(BaseCheckboxElement);
  304. export default SwitchElement;
  305. onsElements.Switch = SwitchElement;
  306. customElements.define('ons-switch', SwitchElement);