123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- import _Array$from from 'babel-runtime/core-js/array/from';
- import _Object$getPrototypeOf from 'babel-runtime/core-js/object/get-prototype-of';
- import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
- import _createClass from 'babel-runtime/helpers/createClass';
- import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
- import _inherits from 'babel-runtime/helpers/inherits';
- /*
- Copyright 2013-2015 ASIAL CORPORATION
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- */
-
- import onsElements from '../../ons/elements';
- import animit from '../../ons/animit';
- import util from '../../ons/util';
- import styler from '../../ons/styler';
- import autoStyle from '../../ons/autostyle';
- import ModifierUtil from '../../ons/internal/modifier-util';
- import AnimatorFactory from '../../ons/internal/animator-factory';
- import { ListItemAnimator, SlideListItemAnimator } from './animator';
- import BaseElement from '../base/base-element';
- import contentReady from '../../ons/content-ready';
-
- var defaultClassName = 'list-item';
- var scheme = {
- '.list-item': 'list-item--*',
- '.list-item__left': 'list-item--*__left',
- '.list-item__center': 'list-item--*__center',
- '.list-item__right': 'list-item--*__right',
- '.list-item__label': 'list-item--*__label',
- '.list-item__title': 'list-item--*__title',
- '.list-item__subtitle': 'list-item--*__subtitle',
- '.list-item__thumbnail': 'list-item--*__thumbnail',
- '.list-item__icon': 'list-item--*__icon'
- };
-
- var _animatorDict = {
- 'default': SlideListItemAnimator,
- 'none': ListItemAnimator
- };
-
- /**
- * @element ons-list-item
- * @category list
- * @modifier tappable
- * [en]Make the list item change appearance when it's tapped. On iOS it is better to use the "tappable" and "tap-background-color" attribute for better behavior when scrolling.[/en]
- * [ja]タップやクリックした時に効果が表示されるようになります。[/ja]
- * @modifier chevron
- * [en]Display a chevron at the right end of the list item and make it change appearance when tapped.[/en]
- * [ja][/ja]
- * @modifier longdivider
- * [en]Displays a long horizontal divider between items.[/en]
- * [ja][/ja]
- * @modifier nodivider
- * [en]Removes the divider between list items.[/en]
- * [ja][/ja]
- * @modifier material
- * [en]Display a Material Design list item.[/en]
- * [ja][/ja]
- * @description
- * [en]
- * Component that represents each item in a list. The list item is composed of four parts that are represented with the `left`, `center`, `right` and `expandable-content` classes. These classes can be used to ensure that the content of the list items is properly aligned.
- *
- * ```
- * <ons-list-item>
- * <div class="left">Left</div>
- * <div class="center">Center</div>
- * <div class="right">Right</div>
- * <div class="expandable-content">Expandable content</div>
- * </ons-list-item>
- * ```
- *
- * There are also a number of classes (prefixed with `list-item__*`) that help when putting things like icons and thumbnails into the list items.
- * [/en]
- * [ja][/ja]
- * @seealso ons-list
- * [en]ons-list component[/en]
- * [ja]ons-listコンポーネント[/ja]
- * @seealso ons-list-header
- * [en]ons-list-header component[/en]
- * [ja]ons-list-headerコンポーネント[/ja]
- * @codepen yxcCt
- * @tutorial vanilla/Reference/list
- * @example
- * <ons-list-item>
- * <div class="left">
- * <ons-icon icon="md-face" class="list-item__icon"></ons-icon>
- * </div>
- * <div class="center">
- * <div class="list-item__title">Title</div>
- * <div class="list-item__subtitle">Subtitle</div>
- * </div>
- * <div class="right">
- * <ons-switch></ons-switch>
- * </div>
- * </ons-list-item>
- */
-
- var ListItemElement = function (_BaseElement) {
- _inherits(ListItemElement, _BaseElement);
-
- /**
- * @attribute modifier
- * @type {String}
- * @description
- * [en]The appearance of the list item.[/en]
- * [ja]各要素の表現を指定します。[/ja]
- */
-
- /**
- * @attribute lock-on-drag
- * @type {String}
- * @description
- * [en]Prevent vertical scrolling when the user drags horizontally.[/en]
- * [ja]この属性があると、ユーザーがこの要素を横方向にドラッグしている時に、縦方向のスクロールが起きないようになります。[/ja]
- */
-
- /**
- * @attribute tappable
- * @type {Boolean}
- * @description
- * [en]Makes the element react to taps. `prevent-tap` attribute can be added to child elements like buttons or inputs to prevent this effect. `ons-*` elements are ignored by default.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute tap-background-color
- * @type {Color}
- * @description
- * [en] Changes the background color when tapped. For this to work, the attribute "tappable" needs to be set. The default color is "#d9d9d9". It will display as a ripple effect on Android.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute expandable
- * @type {Boolean}
- * @description
- * [en]Makes the element able to be expanded to reveal extra content. For this to work, the expandable content must be defined in `div.expandable-content`.[/en]
- * [ja][/ja]
- */
-
- /**
- * @attribute animation
- * @type {String}
- * @default default
- * @description
- * [en]The animation used when showing and hiding the expandable content. Can be either `"default"` or `"none"`.[/en]
- * [ja][/ja]
- */
-
- function ListItemElement() {
- _classCallCheck(this, ListItemElement);
-
- var _this = _possibleConstructorReturn(this, (ListItemElement.__proto__ || _Object$getPrototypeOf(ListItemElement)).call(this));
-
- _this._animatorFactory = _this._updateAnimatorFactory();
- _this.toggleExpansion = _this.toggleExpansion.bind(_this);
-
- // Elements ignored when tapping
- var re = /^ons-(?!col$|row$|if$)/i;
- _this._shouldIgnoreTap = function (e) {
- return e.hasAttribute('prevent-tap') || re.test(e.tagName);
- };
-
- // show and hide functions for Vue hidable mixin
- _this.show = _this.showExpansion;
- _this.hide = _this.hideExpansion;
-
- contentReady(_this, function () {
- _this._compile();
- });
- return _this;
- }
-
- /**
- * Compiles the list item.
- *
- * Various elements are allowed in the body of a list item:
- *
- * - div.left, div.right, and div.center are allowed as direct children
- * - if div.center is not defined, anything that isn't div.left, div.right or div.expandable-content will be put in a div.center
- * - if div.center is defined, anything that isn't div.left, div.right or div.expandable-content will be ignored
- * - if list item has expandable attribute:
- * - div.expandable-content is allowed as a direct child
- * - div.top is allowed as direct child
- * - if div.top is defined, anything that isn't div.expandable-content should be inside div.top - anything else will be ignored
- * - if div.right is not defined, a div.right will be created with a drop-down chevron
- *
- * See the tests for examples.
- */
-
-
- _createClass(ListItemElement, [{
- key: '_compile',
- value: function _compile() {
- autoStyle.prepare(this);
- this.classList.add(defaultClassName);
-
- var top = void 0,
- expandableContent = void 0;
- var topContent = [];
- _Array$from(this.childNodes).forEach(function (node) {
- if (node.nodeType !== Node.ELEMENT_NODE) {
- topContent.push(node);
- } else if (node.classList.contains('top')) {
- top = node;
- } else if (node.classList.contains('expandable-content')) {
- expandableContent = node;
- } else {
- topContent.push(node);
- }
-
- if (node.nodeName !== 'ONS-RIPPLE') {
- node.remove();
- }
- });
- topContent = top ? _Array$from(top.childNodes) : topContent;
-
- var left = void 0,
- right = void 0,
- center = void 0;
- var centerContent = [];
- topContent.forEach(function (node) {
- if (node.nodeType !== Node.ELEMENT_NODE) {
- centerContent.push(node);
- } else if (node.classList.contains('left')) {
- left = node;
- } else if (node.classList.contains('right')) {
- right = node;
- } else if (node.classList.contains('center')) {
- center = node;
- } else {
- centerContent.push(node);
- }
- });
-
- if (this.hasAttribute('expandable')) {
- this.classList.add('list-item--expandable');
-
- if (!top) {
- top = document.createElement('div');
- top.classList.add('top');
- }
- top.classList.add('list-item__top');
- this.appendChild(top);
- this._top = top;
-
- if (expandableContent) {
- expandableContent.classList.add('list-item__expandable-content');
- this.appendChild(expandableContent);
- }
-
- if (!right) {
- right = document.createElement('div');
- right.classList.add('list-item__right', 'right');
-
- // We cannot use a pseudo-element for this chevron, as we cannot animate it using
- // JS. So, we make a chevron span instead.
- var chevron = document.createElement('span');
- chevron.classList.add('list-item__expand-chevron');
- right.appendChild(chevron);
- }
- } else {
- top = this;
- }
-
- if (!center) {
- center = document.createElement('div');
- center.classList.add('center');
- centerContent.forEach(function (node) {
- return center.appendChild(node);
- });
- }
- center.classList.add('list-item__center');
- top.appendChild(center);
-
- if (left) {
- left.classList.add('list-item__left');
- top.appendChild(left);
- }
- if (right) {
- right.classList.add('list-item__right');
- top.appendChild(right);
- }
-
- util.updateRipple(this);
- ModifierUtil.initModifier(this, scheme);
- }
-
- /**
- * @method showExpansion
- * @signature showExpansion()
- * @description
- * [en]Show the expandable content if the element is expandable.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'showExpansion',
- value: function showExpansion() {
- var _this2 = this;
-
- if (this.hasAttribute('expandable') && !this._expanding) {
- this.expanded = true;
- this._expanding = true;
-
- var animator = this._animatorFactory.newAnimator();
- animator.showExpansion(this, function () {
- _this2.classList.add('expanded');
- _this2._expanding = false;
- });
- }
- }
-
- /**
- * @method hideExpansion
- * @signature hideExpansion()
- * @description
- * [en]Hide the expandable content if the element expandable.[/en]
- * [ja][/ja]
- */
-
- }, {
- key: 'hideExpansion',
- value: function hideExpansion() {
- var _this3 = this;
-
- if (this.hasAttribute('expandable') && !this._expanding) {
- this.expanded = false;
- this._expanding = true;
-
- var animator = this._animatorFactory.newAnimator();
- animator.hideExpansion(this, function () {
- _this3.classList.remove('expanded');
- _this3._expanding = false;
- });
- }
- }
- }, {
- key: 'toggleExpansion',
- value: function toggleExpansion() {
- this.classList.contains('expanded') ? this.hideExpansion() : this.showExpansion();
- this.dispatchEvent(new Event('expansion'));
- }
- }, {
- key: '_updateAnimatorFactory',
- value: function _updateAnimatorFactory() {
- return new AnimatorFactory({
- animators: _animatorDict,
- baseClass: ListItemAnimator,
- baseClassName: 'ListItemAnimator',
- defaultAnimation: this.getAttribute('animation') || 'default'
- });
- }
- }, {
- key: 'attributeChangedCallback',
- value: function attributeChangedCallback(name, last, current) {
- switch (name) {
- case 'class':
- util.restoreClass(this, defaultClassName, scheme);
- break;
- case 'modifier':
- ModifierUtil.onModifierChanged(last, current, this, scheme);
- break;
- case 'ripple':
- util.updateRipple(this);
- break;
- case 'animation':
- this._animatorFactory = this._updateAnimatorFactory();
- break;
- }
- }
- }, {
- key: 'connectedCallback',
- value: function connectedCallback() {
- var _this4 = this;
-
- contentReady(this, function () {
- _this4._setupListeners(true);
- _this4._originalBackgroundColor = _this4.style.backgroundColor;
- _this4.tapped = false;
- });
- }
- }, {
- key: 'disconnectedCallback',
- value: function disconnectedCallback() {
- this._setupListeners(false);
- }
- }, {
- key: '_setupListeners',
- value: function _setupListeners(add) {
- var action = (add ? 'add' : 'remove') + 'EventListener';
- util[action](this, 'touchstart', this._onTouch, { passive: true });
- util[action](this, 'touchmove', this._onRelease, { passive: true });
- this[action]('touchcancel', this._onRelease);
- this[action]('touchend', this._onRelease);
- this[action]('touchleave', this._onRelease);
- this[action]('drag', this._onDrag);
- this[action]('mousedown', this._onTouch);
- this[action]('mouseup', this._onRelease);
- this[action]('mouseout', this._onRelease);
-
- if (this._top) {
- this._top[action]('click', this.toggleExpansion);
- }
- }
- }, {
- key: '_onDrag',
- value: function _onDrag(event) {
- var gesture = event.gesture;
- // Prevent vertical scrolling if the users pans left or right.
- if (this.hasAttribute('lock-on-drag') && ['left', 'right'].indexOf(gesture.direction) > -1) {
- gesture.preventDefault();
- }
- }
- }, {
- key: '_onTouch',
- value: function _onTouch(e) {
- var _this5 = this;
-
- if (this.tapped || this !== e.target && (this._shouldIgnoreTap(e.target) || util.findParent(e.target, this._shouldIgnoreTap, function (p) {
- return p === _this5;
- }))) {
- return; // Ignore tap
- }
-
- this.tapped = true;
- var touchStyle = { transition: 'background-color 0.0s linear 0.02s, box-shadow 0.0s linear 0.02s' };
-
- if (this.hasAttribute('tappable')) {
- if (this.style.backgroundColor) {
- this._originalBackgroundColor = this.style.backgroundColor;
- }
-
- touchStyle.backgroundColor = this.getAttribute('tap-background-color') || '#d9d9d9';
- touchStyle.boxShadow = '0px -1px 0px 0px ' + touchStyle.backgroundColor;
- }
-
- styler(this, touchStyle);
- }
- }, {
- key: '_onRelease',
- value: function _onRelease() {
- this.tapped = false;
- this.style.backgroundColor = this._originalBackgroundColor || '';
- styler.clear(this, 'transition boxShadow');
- }
- }, {
- key: 'expandableContent',
- get: function get() {
- return this.querySelector('.list-item__expandable-content');
- }
- }, {
- key: 'expandChevron',
- get: function get() {
- return this.querySelector('.list-item__expand-chevron');
- }
- }], [{
- key: 'observedAttributes',
- get: function get() {
- return ['modifier', 'class', 'ripple', 'animation'];
- }
- }]);
-
- return ListItemElement;
- }(BaseElement);
-
- export default ListItemElement;
-
-
- onsElements.ListItem = ListItemElement;
- customElements.define('ons-list-item', ListItemElement);
|