No Description

ons-segment.js 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. import _Promise from 'babel-runtime/core-js/promise';
  2. import _setImmediate from 'babel-runtime/core-js/set-immediate';
  3. import _Object$getPrototypeOf from 'babel-runtime/core-js/object/get-prototype-of';
  4. import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
  5. import _createClass from 'babel-runtime/helpers/createClass';
  6. import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
  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 BaseElement from './base/base-element';
  25. import contentReady from '../ons/content-ready';
  26. var defaultClassName = 'segment';
  27. var scheme = {
  28. '': 'segment--*',
  29. '.segment__item': 'segment--*__item',
  30. '.segment__input': 'segment--*__input',
  31. '.segment__button': 'segment--*__button'
  32. };
  33. var generateId = function () {
  34. var i = 0;
  35. return function () {
  36. return 'ons-segment-gen-' + i++;
  37. };
  38. }();
  39. /**
  40. * @element ons-segment
  41. * @category control
  42. * @modifier material
  43. * [en]Material Design segment[/en]
  44. * [ja][/ja]
  45. * @description
  46. * [en]
  47. * Segment component. Use this component to have a button bar with automatic styles that switch on click of another button.
  48. *
  49. * Will automatically display as a Material Design segment on Android.
  50. * [/en]
  51. * [ja][/ja]
  52. * @codepen hLayx
  53. * @tutorial vanilla/Reference/segment
  54. * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja]
  55. * @guide theming.html#cross-platform-styling-autostyling [en]Information about cross platform styling[/en][ja]Information about cross platform styling[/ja]
  56. * @example
  57. * <ons-segment>
  58. * <ons-button>Label 1</ons-button>
  59. * <ons-button>Label 2</ons-button>
  60. * <ons-button>Label 3</ons-button>
  61. * </ons-segment>
  62. */
  63. var SegmentElement = function (_BaseElement) {
  64. _inherits(SegmentElement, _BaseElement);
  65. /**
  66. * @event postchange
  67. * @description
  68. * [en]Fires after the active button is changed.[/en]
  69. * [ja][/ja]
  70. * @param {Object} event
  71. * [en]Event object.[/en]
  72. * [ja][/ja]
  73. * @param {Number} event.index
  74. * [en]Tapped button index.[/en]
  75. * [ja][/ja]
  76. * @param {Object} event.segmentItem
  77. * [en]Segment item object.[/en]
  78. * [ja][/ja]
  79. */
  80. /**
  81. * @attribute modifier
  82. * @type {String}
  83. * @description
  84. * [en]The appearance of the segment.[/en]
  85. * [ja][/ja]
  86. */
  87. /**
  88. * @attribute tabbar-id
  89. * @initonly
  90. * @type {String}
  91. * @description
  92. * [en]ID of the tabbar element to "connect" to the segment. Must be inside the same page.[/en]
  93. * [ja][/ja]
  94. */
  95. /**
  96. * @attribute active-index
  97. * @initonly
  98. * @default 0
  99. * @type {Number}
  100. * @description
  101. * [en]Index of the first active button, only works if there is no connected tabbar (in which case the active tab sets the active button).[/en]
  102. * [ja][/ja]
  103. */
  104. /**
  105. * @attribute disabled
  106. * @description
  107. * [en]Specify if segment should be disabled.[/en]
  108. * [ja]ボタンを無効化する場合は指定します。[/ja]
  109. */
  110. function SegmentElement() {
  111. _classCallCheck(this, SegmentElement);
  112. var _this = _possibleConstructorReturn(this, (SegmentElement.__proto__ || _Object$getPrototypeOf(SegmentElement)).call(this));
  113. _this._segmentId = generateId();
  114. _this._tabbar = null;
  115. _this._onChange = _this._onChange.bind(_this);
  116. _this._onTabbarPreChange = _this._onTabbarPreChange.bind(_this);
  117. contentReady(_this, function () {
  118. _this._compile();
  119. _setImmediate(function () {
  120. return _this._lastActiveIndex = _this._tabbar ? _this._tabbar.getActiveTabIndex() : _this.getActiveButtonIndex();
  121. });
  122. });
  123. return _this;
  124. }
  125. _createClass(SegmentElement, [{
  126. key: '_compile',
  127. value: function _compile() {
  128. autoStyle.prepare(this);
  129. this.classList.add(defaultClassName);
  130. for (var index = this.children.length - 1; index >= 0; index--) {
  131. var item = this.children[index];
  132. item.classList.add('segment__item');
  133. var input = util.findChild(item, '.segment__input') || util.create('input.segment__input');
  134. input.type = 'radio';
  135. input.value = index;
  136. input.name = input.name || this._segmentId;
  137. input.checked = !this.hasAttribute('tabbar-id') && index === (parseInt(this.getAttribute('active-index')) || 0);
  138. var button = util.findChild(item, '.segment__button') || util.create('.segment__button');
  139. if (button.parentElement !== item) {
  140. while (item.firstChild) {
  141. button.appendChild(item.firstChild);
  142. }
  143. }
  144. item.appendChild(input);
  145. item.appendChild(button);
  146. }
  147. ModifierUtil.initModifier(this, scheme);
  148. }
  149. }, {
  150. key: 'connectedCallback',
  151. value: function connectedCallback() {
  152. var _this2 = this;
  153. contentReady(this, function () {
  154. if (_this2.hasAttribute('tabbar-id')) {
  155. var page = util.findParent(_this2, 'ons-page');
  156. _this2._tabbar = page && page.querySelector('#' + _this2.getAttribute('tabbar-id'));
  157. if (!_this2._tabbar || _this2._tabbar.tagName !== 'ONS-TABBAR') {
  158. util.throw('No tabbar with id ' + _this2.getAttribute('tabbar-id') + ' was found.');
  159. }
  160. _this2._tabbar.setAttribute('hide-tabs', '');
  161. _setImmediate(function () {
  162. return _this2._setChecked(_this2._tabbar.getActiveTabIndex());
  163. });
  164. _this2._tabbar.addEventListener('prechange', _this2._onTabbarPreChange);
  165. }
  166. });
  167. this.addEventListener('change', this._onChange);
  168. }
  169. }, {
  170. key: 'disconnectedCallback',
  171. value: function disconnectedCallback() {
  172. var _this3 = this;
  173. contentReady(this, function () {
  174. if (_this3._tabbar) {
  175. _this3._tabbar.removeEventListener('prechange', _this3._onTabbarPreChange);
  176. _this3._tabbar = null;
  177. }
  178. });
  179. this.removeEventListener('change', this._onChange);
  180. }
  181. }, {
  182. key: '_setChecked',
  183. value: function _setChecked(index) {
  184. this.children[index].firstElementChild.checked = true;
  185. }
  186. /**
  187. * @method setActiveButton
  188. * @signature setActiveButton(index, [options])
  189. * @param {Number} index
  190. * [en]Button index.[/en]
  191. * [ja][/ja]
  192. * @param {Object} [options]
  193. * [en]Parameter object, works only if there is a connected tabbar. Supports the same options as `ons-tabbar`'s `setActiveTab` method.[/en]
  194. * [ja][/ja]
  195. * @description
  196. * [en]Make button with the specified index active. If there is a connected tabbar it shows the corresponding tab page. In this case animations and their options can be specified by the second parameter.[/en]
  197. * [ja][/ja]
  198. * @return {Promise}
  199. * [en]Resolves to the selected index or to the new page element if there is a connected tabbar.[/en]
  200. * [ja][/ja]
  201. */
  202. }, {
  203. key: 'setActiveButton',
  204. value: function setActiveButton(index, options) {
  205. if (this._tabbar) {
  206. return this._tabbar.setActiveTab(index, options);
  207. }
  208. this._setChecked(index);
  209. this._postChange(index);
  210. return _Promise.resolve(index);
  211. }
  212. /**
  213. * @method getActiveButtonIndex
  214. * @signature getActiveButtonIndex()
  215. * @return {Number}
  216. * [en]The index of the currently active button.[/en]
  217. * [ja][/ja]
  218. * @description
  219. * [en]Returns button index of current active button. If active button is not found, returns -1.[/en]
  220. * [ja][/ja]
  221. */
  222. }, {
  223. key: 'getActiveButtonIndex',
  224. value: function getActiveButtonIndex() {
  225. for (var i = this.children.length - 1; i >= 0; i--) {
  226. // Array.findIndex
  227. if (this.children[i].firstElementChild.checked) {
  228. return i;
  229. }
  230. }
  231. return -1;
  232. }
  233. }, {
  234. key: '_onChange',
  235. value: function _onChange(event) {
  236. event.stopPropagation();
  237. this._tabbar ? this._tabbar.setActiveTab(this.getActiveButtonIndex(), { reject: false }) : this._postChange(this.getActiveButtonIndex());
  238. }
  239. }, {
  240. key: '_onTabbarPreChange',
  241. value: function _onTabbarPreChange(event) {
  242. var _this4 = this;
  243. _setImmediate(function () {
  244. if (!event.detail.canceled) {
  245. _this4._setChecked(event.index);
  246. _this4._postChange(event.index);
  247. }
  248. });
  249. }
  250. }, {
  251. key: '_postChange',
  252. value: function _postChange(index) {
  253. util.triggerElementEvent(this, 'postchange', {
  254. index: index,
  255. activeIndex: index,
  256. lastActiveIndex: this._lastActiveIndex,
  257. segmentItem: this.children[index]
  258. });
  259. this._lastActiveIndex = index;
  260. }
  261. /**
  262. * @property disabled
  263. * @type {Boolean}
  264. * @description
  265. * [en]Whether the segment is disabled or not.[/en]
  266. * [ja]無効化されている場合に`true`。[/ja]
  267. */
  268. }, {
  269. key: 'attributeChangedCallback',
  270. value: function attributeChangedCallback(name, last, current) {
  271. switch (name) {
  272. case 'class':
  273. util.restoreClass(this, defaultClassName, scheme);
  274. break;
  275. case 'modifier':
  276. ModifierUtil.onModifierChanged(last, current, this, scheme);
  277. break;
  278. }
  279. }
  280. }, {
  281. key: 'disabled',
  282. set: function set(value) {
  283. return util.toggleAttribute(this, 'disabled', value);
  284. },
  285. get: function get() {
  286. return this.hasAttribute('disabled');
  287. }
  288. }], [{
  289. key: 'observedAttributes',
  290. get: function get() {
  291. return ['class', 'modifier'];
  292. }
  293. }, {
  294. key: 'events',
  295. get: function get() {
  296. return ['postchange'];
  297. }
  298. }]);
  299. return SegmentElement;
  300. }(BaseElement);
  301. export default SegmentElement;
  302. onsElements.Segment = SegmentElement;
  303. customElements.define('ons-segment', SegmentElement);