import { Directive, ElementRef, EventEmitter, Input, NgZone, Optional, Output, Renderer } from '@angular/core'; import { Content } from '../content/content'; import { DomController } from '../../platform/dom-controller'; import { isTrueProperty, reorderArray } from '../../util/util'; import { ItemReorderGesture } from './item-reorder-gesture'; import { Platform } from '../../platform/platform'; var ReorderIndexes = (function () { function ReorderIndexes(from, to) { this.from = from; this.to = to; } ReorderIndexes.prototype.applyTo = function (array) { reorderArray(array, this); }; return ReorderIndexes; }()); export { ReorderIndexes }; /** * @name ItemReorder * @description * Item reorder adds the ability to change an item's order in a group. * It can be used within an `ion-list` or `ion-item-group` to provide a * visual drag and drop interface. * * ## Grouping Items * * All reorderable items must be grouped in the same element. If an item * should not be reordered, it shouldn't be included in this group. For * example, the following code works because the items are grouped in the * ``: * * ```html * * {% raw %}{{ item }}{% endraw %} * * ``` * * However, the below list includes a header that shouldn't be reordered: * * ```html * * Header * {% raw %}{{ item }}{% endraw %} * * ``` * * In order to mix different sets of items, `ion-item-group` should be used to * group the reorderable items: * * ```html * * Header * * {% raw %}{{ item }}{% endraw %} * * * ``` * * It's important to note that in this example, the `[reorder]` directive is applied to * the `` instead of the ``. This way makes it possible to * mix items that should and shouldn't be reordered. * * * ## Implementing the Reorder Function * * When the item is dragged and dropped into the new position, the `(ionItemReorder)` event is * emitted. This event provides the initial index (from) and the new index (to) of the reordered * item. For example, if the first item is dragged to the fifth position, the event will emit * `{from: 0, to: 4}`. Note that the index starts at zero. * * A function should be called when the event is emitted that handles the reordering of the items. * See [usage](#usage) below for some examples. * * * @usage * * ```html * * Header * * {% raw %}{{ item }}{% endraw %} * * * ``` * * ```ts * class MyComponent { * items = []; * * constructor() { * for (let x = 0; x < 5; x++) { * this.items.push(x); * } * } * * reorderItems(indexes) { * let element = this.items[indexes.from]; * this.items.splice(indexes.from, 1); * this.items.splice(indexes.to, 0, element); * } * } * ``` * * Ionic also provides a helper function called `reorderArray` to * reorder the array of items. This can be used instead: * * ```ts * import { reorderArray } from 'ionic-angular'; * * class MyComponent { * items = []; * * constructor() { * for (let x = 0; x < 5; x++) { * this.items.push(x); * } * } * * reorderItems(indexes) { * this.items = reorderArray(this.items, indexes); * } * } * ``` * Alternatevely you can execute helper function inside template: * * ```html * * Header * * {% raw %}{{ item }}{% endraw %} * * * ``` * * @demo /docs/demos/src/item-reorder/ * @see {@link /docs/components#lists List Component Docs} * @see {@link ../../list/List List API Docs} * @see {@link ../Item Item API Docs} */ var ItemReorder = (function () { function ItemReorder(_plt, _dom, elementRef, _rendered, _zone, _content) { this._plt = _plt; this._dom = _dom; this._rendered = _rendered; this._zone = _zone; this._content = _content; this._enableReorder = false; this._visibleReorder = false; this._isStart = false; this._lastToIndex = -1; /** * @output {object} Emitted when the item is reordered. Emits an object * with `from` and `to` properties. */ this.ionItemReorder = new EventEmitter(); this._element = elementRef.nativeElement; } Object.defineProperty(ItemReorder.prototype, "side", { /** * @input {string} Which side of the view the ion-reorder should be placed. Default `"end"`. */ set: function (side) { this._isStart = side === 'start'; }, enumerable: true, configurable: true }); /** * @hidden */ ItemReorder.prototype.ngOnDestroy = function () { this._element = null; this._reorderGesture && this._reorderGesture.destroy(); }; Object.defineProperty(ItemReorder.prototype, "reorder", { /** * @hidden */ get: function () { return this._enableReorder; }, set: function (val) { var _this = this; var enabled = isTrueProperty(val); if (!enabled && this._reorderGesture) { this._reorderGesture.destroy(); this._reorderGesture = null; this._visibleReorder = false; setTimeout(function () { return _this._enableReorder = false; }, 400); } else if (enabled && !this._reorderGesture) { (void 0) /* console.debug */; this._reorderGesture = new ItemReorderGesture(this._plt, this); this._enableReorder = true; this._dom.write(function () { _this._zone.run(function () { _this._visibleReorder = true; }); }, 16); } }, enumerable: true, configurable: true }); ItemReorder.prototype._reorderPrepare = function () { var ele = this._element; var children = ele.children; for (var i = 0, ilen = children.length; i < ilen; i++) { var child = children[i]; child.$ionIndex = i; child.$ionReorderList = ele; } }; ItemReorder.prototype._reorderStart = function () { this.setElementClass('reorder-list-active', true); }; ItemReorder.prototype._reorderEmit = function (fromIndex, toIndex) { var _this = this; this._reorderReset(); if (fromIndex !== toIndex) { this._zone.run(function () { var indexes = new ReorderIndexes(fromIndex, toIndex); _this.ionItemReorder.emit(indexes); }); } }; ItemReorder.prototype._scrollContent = function (scroll) { var scrollTop = this._content.scrollTop + scroll; if (scroll !== 0) { this._content.scrollTo(0, scrollTop, 0); } return scrollTop; }; ItemReorder.prototype._reorderReset = function () { var children = this._element.children; var len = children.length; this.setElementClass('reorder-list-active', false); var transform = this._plt.Css.transform; for (var i = 0; i < len; i++) { children[i].style[transform] = ''; } this._lastToIndex = -1; }; ItemReorder.prototype._reorderMove = function (fromIndex, toIndex, itemHeight) { if (this._lastToIndex === -1) { this._lastToIndex = fromIndex; } var lastToIndex = this._lastToIndex; this._lastToIndex = toIndex; // TODO: I think both loops can be merged into a single one // but I had no luck last time I tried /********* DOM READ ********** */ var children = this._element.children; /********* DOM WRITE ********* */ var transform = this._plt.Css.transform; if (toIndex >= lastToIndex) { for (var i = lastToIndex; i <= toIndex; i++) { if (i !== fromIndex) { children[i].style[transform] = (i > fromIndex) ? "translateY(" + -itemHeight + "px)" : ''; } } } if (toIndex <= lastToIndex) { for (var i = toIndex; i <= lastToIndex; i++) { if (i !== fromIndex) { children[i].style[transform] = (i < fromIndex) ? "translateY(" + itemHeight + "px)" : ''; } } } }; /** * @hidden */ ItemReorder.prototype.setElementClass = function (classname, add) { this._rendered.setElementClass(this._element, classname, add); }; /** * @hidden */ ItemReorder.prototype.getNativeElement = function () { return this._element; }; ItemReorder.decorators = [ { type: Directive, args: [{ selector: 'ion-list[reorder],ion-item-group[reorder]', host: { '[class.reorder-enabled]': '_enableReorder', '[class.reorder-visible]': '_visibleReorder', '[class.reorder-side-start]': '_isStart' } },] }, ]; /** @nocollapse */ ItemReorder.ctorParameters = function () { return [ { type: Platform, }, { type: DomController, }, { type: ElementRef, }, { type: Renderer, }, { type: NgZone, }, { type: Content, decorators: [{ type: Optional },] }, ]; }; ItemReorder.propDecorators = { 'ionItemReorder': [{ type: Output },], 'side': [{ type: Input, args: ['side',] },], 'reorder': [{ type: Input },], }; return ItemReorder; }()); export { ItemReorder }; //# sourceMappingURL=item-reorder.js.map