UI for Zipcoin Blue

item-sliding.js 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. import { ChangeDetectionStrategy, Component, ContentChild, ContentChildren, ElementRef, EventEmitter, NgZone, Optional, Output, Renderer, ViewEncapsulation, forwardRef } from '@angular/core';
  2. import { swipeShouldReset } from '../../util/util';
  3. import { Item } from './item';
  4. import { List } from '../list/list';
  5. import { Platform } from '../../platform/platform';
  6. import { ItemOptions } from './item-options';
  7. var SWIPE_MARGIN = 30;
  8. var ELASTIC_FACTOR = 0.55;
  9. var ITEM_SIDE_FLAG_NONE = 0;
  10. var ITEM_SIDE_FLAG_LEFT = 1 << 0;
  11. var ITEM_SIDE_FLAG_RIGHT = 1 << 1;
  12. var ITEM_SIDE_FLAG_BOTH = ITEM_SIDE_FLAG_LEFT | ITEM_SIDE_FLAG_RIGHT;
  13. /**
  14. * @name ItemSliding
  15. * @description
  16. * A sliding item is a list item that can be swiped to reveal buttons. It requires
  17. * an [Item](../Item) component as a child and a [List](../../list/List) component as
  18. * a parent. All buttons to reveal can be placed in the `<ion-item-options>` element.
  19. *
  20. * @usage
  21. * ```html
  22. * <ion-list>
  23. * <ion-item-sliding #item>
  24. * <ion-item>
  25. * Item
  26. * </ion-item>
  27. * <ion-item-options side="left">
  28. * <button ion-button (click)="favorite(item)">Favorite</button>
  29. * <button ion-button color="danger" (click)="share(item)">Share</button>
  30. * </ion-item-options>
  31. *
  32. * <ion-item-options side="right">
  33. * <button ion-button (click)="unread(item)">Unread</button>
  34. * </ion-item-options>
  35. * </ion-item-sliding>
  36. * </ion-list>
  37. * ```
  38. *
  39. * ### Swipe Direction
  40. * By default, the buttons are revealed when the sliding item is swiped from right to left,
  41. * so the buttons are placed in the right side. But it's also possible to reveal them
  42. * in the right side (sliding from left to right) by setting the `side` attribute
  43. * on the `ion-item-options` element. Up to 2 `ion-item-options` can used at the same time
  44. * in order to reveal two different sets of buttons depending the swipping direction.
  45. *
  46. * ```html
  47. * <ion-item-options side="right">
  48. * <button ion-button (click)="archive(item)">
  49. * <ion-icon name="archive"></ion-icon>
  50. * Archive
  51. * </button>
  52. * </ion-item-options>
  53. *
  54. * <ion-item-options side="left">
  55. * <button ion-button (click)="archive(item)">
  56. * <ion-icon name="archive"></ion-icon>
  57. * Archive
  58. * </button>
  59. * </ion-item-options>
  60. * ```
  61. *
  62. * ### Listening for events (ionDrag) and (ionSwipe)
  63. * It's possible to know the current relative position of the sliding item by subscribing
  64. * to the (ionDrag)` event.
  65. *
  66. * ```html
  67. * <ion-item-sliding (ionDrag)="logDrag($event)">
  68. * <ion-item>Item</ion-item>
  69. * <ion-item-options>
  70. * <button ion-button>Favorite</button>
  71. * </ion-item-options>
  72. * </ion-item-sliding>
  73. * ```
  74. *
  75. * ### Button Layout
  76. * If an icon is placed with text in the option button, by default it will
  77. * display the icon on top of the text. This can be changed to display the icon
  78. * to the left of the text by setting `icon-start` as an attribute on the
  79. * `<ion-item-options>` element.
  80. *
  81. * ```html
  82. * <ion-item-options icon-start>
  83. * <button ion-button (click)="archive(item)">
  84. * <ion-icon name="archive"></ion-icon>
  85. * Archive
  86. * </button>
  87. * </ion-item-options>
  88. *
  89. * ```
  90. *
  91. * ### Expandable Options
  92. *
  93. * Options can be expanded to take up the full width of the item if you swipe past
  94. * a certain point. This can be combined with the `ionSwipe` event to call methods
  95. * on the class.
  96. *
  97. * ```html
  98. *
  99. * <ion-item-sliding (ionSwipe)="delete(item)">
  100. * <ion-item>Item</ion-item>
  101. * <ion-item-options>
  102. * <button ion-button expandable (click)="delete(item)">Delete</button>
  103. * </ion-item-options>
  104. * </ion-item-sliding>
  105. * ```
  106. *
  107. * We can call `delete` by either clicking the button, or by doing a full swipe on the item.
  108. *
  109. * @demo /docs/demos/src/item-sliding/
  110. * @see {@link /docs/components#lists List Component Docs}
  111. * @see {@link ../Item Item API Docs}
  112. * @see {@link ../../list/List List API Docs}
  113. */
  114. var ItemSliding = (function () {
  115. function ItemSliding(list, _plt, _renderer, _elementRef, _zone) {
  116. this._plt = _plt;
  117. this._renderer = _renderer;
  118. this._elementRef = _elementRef;
  119. this._zone = _zone;
  120. this._openAmount = 0;
  121. this._startX = 0;
  122. this._optsWidthRightSide = 0;
  123. this._optsWidthLeftSide = 0;
  124. this._tmr = null;
  125. this._optsDirty = true;
  126. this._state = 2 /* Disabled */;
  127. /**
  128. * @output {event} Emitted when the sliding position changes.
  129. * It reports the relative position.
  130. *
  131. * ```ts
  132. * ondrag(item) {
  133. * let percent = item.getSlidingPercent();
  134. * if (percent > 0) {
  135. * // positive
  136. * console.log('right side');
  137. * } else {
  138. * // negative
  139. * console.log('left side');
  140. * }
  141. * if (Math.abs(percent) > 1) {
  142. * console.log('overscroll');
  143. * }
  144. * }
  145. * ```
  146. *
  147. */
  148. this.ionDrag = new EventEmitter();
  149. list && list.containsSlidingItem(true);
  150. _elementRef.nativeElement.$ionComponent = this;
  151. this.setElementClass('item-wrapper', true);
  152. }
  153. Object.defineProperty(ItemSliding.prototype, "_itemOptions", {
  154. set: function (itemOptions) {
  155. var sides = 0;
  156. // Reset left and right options in case they were removed
  157. this._leftOptions = this._rightOptions = null;
  158. for (var _i = 0, _a = itemOptions.toArray(); _i < _a.length; _i++) {
  159. var item = _a[_i];
  160. if (item.isRightSide()) {
  161. this._rightOptions = item;
  162. sides |= ITEM_SIDE_FLAG_RIGHT;
  163. }
  164. else {
  165. this._leftOptions = item;
  166. sides |= ITEM_SIDE_FLAG_LEFT;
  167. }
  168. }
  169. this._optsDirty = true;
  170. this._sides = sides;
  171. },
  172. enumerable: true,
  173. configurable: true
  174. });
  175. /**
  176. * @hidden
  177. */
  178. ItemSliding.prototype.getOpenAmount = function () {
  179. return this._openAmount;
  180. };
  181. /**
  182. * @hidden
  183. */
  184. ItemSliding.prototype.getSlidingPercent = function () {
  185. var openAmount = this._openAmount;
  186. if (openAmount > 0) {
  187. return openAmount / this._optsWidthRightSide;
  188. }
  189. else if (openAmount < 0) {
  190. return openAmount / this._optsWidthLeftSide;
  191. }
  192. else {
  193. return 0;
  194. }
  195. };
  196. /**
  197. * @hidden
  198. */
  199. ItemSliding.prototype.startSliding = function (startX) {
  200. if (this._tmr) {
  201. this._plt.cancelTimeout(this._tmr);
  202. this._tmr = null;
  203. }
  204. if (this._openAmount === 0) {
  205. this._optsDirty = true;
  206. this._setState(4 /* Enabled */);
  207. }
  208. this._startX = startX + this._openAmount;
  209. this.item.setElementStyle(this._plt.Css.transition, 'none');
  210. };
  211. /**
  212. * @hidden
  213. */
  214. ItemSliding.prototype.moveSliding = function (x) {
  215. if (this._optsDirty) {
  216. this.calculateOptsWidth();
  217. return;
  218. }
  219. var openAmount = (this._startX - x);
  220. switch (this._sides) {
  221. case ITEM_SIDE_FLAG_RIGHT:
  222. openAmount = Math.max(0, openAmount);
  223. break;
  224. case ITEM_SIDE_FLAG_LEFT:
  225. openAmount = Math.min(0, openAmount);
  226. break;
  227. case ITEM_SIDE_FLAG_BOTH: break;
  228. case ITEM_SIDE_FLAG_NONE: return;
  229. default:
  230. (void 0) /* assert */;
  231. break;
  232. }
  233. if (openAmount > this._optsWidthRightSide) {
  234. var optsWidth = this._optsWidthRightSide;
  235. openAmount = optsWidth + (openAmount - optsWidth) * ELASTIC_FACTOR;
  236. }
  237. else if (openAmount < -this._optsWidthLeftSide) {
  238. var optsWidth = -this._optsWidthLeftSide;
  239. openAmount = optsWidth + (openAmount - optsWidth) * ELASTIC_FACTOR;
  240. }
  241. this._setOpenAmount(openAmount, false);
  242. return openAmount;
  243. };
  244. /**
  245. * @hidden
  246. */
  247. ItemSliding.prototype.endSliding = function (velocity) {
  248. var restingPoint = (this._openAmount > 0)
  249. ? this._optsWidthRightSide
  250. : -this._optsWidthLeftSide;
  251. // Check if the drag didn't clear the buttons mid-point
  252. // and we aren't moving fast enough to swipe open
  253. var isResetDirection = (this._openAmount > 0) === !(velocity < 0);
  254. var isMovingFast = Math.abs(velocity) > 0.3;
  255. var isOnCloseZone = Math.abs(this._openAmount) < Math.abs(restingPoint / 2);
  256. if (swipeShouldReset(isResetDirection, isMovingFast, isOnCloseZone)) {
  257. restingPoint = 0;
  258. }
  259. this.fireSwipeEvent();
  260. this._setOpenAmount(restingPoint, true);
  261. return restingPoint;
  262. };
  263. /**
  264. * @hidden
  265. */
  266. ItemSliding.prototype.fireSwipeEvent = function () {
  267. var _this = this;
  268. if (this._state & 32 /* SwipeRight */) {
  269. this._zone.run(function () { return _this._rightOptions.ionSwipe.emit(_this); });
  270. }
  271. else if (this._state & 64 /* SwipeLeft */) {
  272. this._zone.run(function () { return _this._leftOptions.ionSwipe.emit(_this); });
  273. }
  274. };
  275. /**
  276. * @hidden
  277. */
  278. ItemSliding.prototype.calculateOptsWidth = function () {
  279. if (!this._optsDirty) {
  280. return;
  281. }
  282. this._optsWidthRightSide = 0;
  283. if (this._rightOptions) {
  284. this._optsWidthRightSide = this._rightOptions.width();
  285. (void 0) /* assert */;
  286. }
  287. this._optsWidthLeftSide = 0;
  288. if (this._leftOptions) {
  289. this._optsWidthLeftSide = this._leftOptions.width();
  290. (void 0) /* assert */;
  291. }
  292. this._optsDirty = false;
  293. };
  294. ItemSliding.prototype._setOpenAmount = function (openAmount, isFinal) {
  295. var _this = this;
  296. var platform = this._plt;
  297. if (this._tmr) {
  298. platform.cancelTimeout(this._tmr);
  299. this._tmr = null;
  300. }
  301. this._openAmount = openAmount;
  302. if (isFinal) {
  303. this.item.setElementStyle(platform.Css.transition, '');
  304. }
  305. if (openAmount > 0) {
  306. var state = (openAmount >= (this._optsWidthRightSide + SWIPE_MARGIN))
  307. ? 8 /* Right */ | 32 /* SwipeRight */
  308. : 8 /* Right */;
  309. this._setState(state);
  310. }
  311. else if (openAmount < 0) {
  312. var state_1 = (openAmount <= (-this._optsWidthLeftSide - SWIPE_MARGIN))
  313. ? 16 /* Left */ | 64 /* SwipeLeft */
  314. : 16 /* Left */;
  315. this._setState(state_1);
  316. }
  317. else {
  318. (void 0) /* assert */;
  319. this._tmr = platform.timeout(function () {
  320. _this._setState(2 /* Disabled */);
  321. _this._tmr = null;
  322. }, 600);
  323. this.item.setElementStyle(platform.Css.transform, '');
  324. return;
  325. }
  326. this.item.setElementStyle(platform.Css.transform, "translate3d(" + -openAmount + "px,0,0)");
  327. var ionDrag = this.ionDrag;
  328. if (ionDrag.observers.length > 0) {
  329. ionDrag.emit(this);
  330. }
  331. };
  332. ItemSliding.prototype._setState = function (state) {
  333. if (state === this._state) {
  334. return;
  335. }
  336. this.setElementClass('active-slide', (state !== 2 /* Disabled */));
  337. this.setElementClass('active-options-right', !!(state & 8 /* Right */));
  338. this.setElementClass('active-options-left', !!(state & 16 /* Left */));
  339. this.setElementClass('active-swipe-right', !!(state & 32 /* SwipeRight */));
  340. this.setElementClass('active-swipe-left', !!(state & 64 /* SwipeLeft */));
  341. this._state = state;
  342. };
  343. /**
  344. * Close the sliding item. Items can also be closed from the [List](../../list/List).
  345. *
  346. * The sliding item can be closed by grabbing a reference to `ItemSliding`. In the
  347. * below example, the template reference variable `slidingItem` is placed on the element
  348. * and passed to the `share` method.
  349. *
  350. * ```html
  351. * <ion-list>
  352. * <ion-item-sliding #slidingItem>
  353. * <ion-item>
  354. * Item
  355. * </ion-item>
  356. * <ion-item-options>
  357. * <button ion-button (click)="share(slidingItem)">Share</button>
  358. * </ion-item-options>
  359. * </ion-item-sliding>
  360. * </ion-list>
  361. * ```
  362. *
  363. * ```ts
  364. * import { Component } from '@angular/core';
  365. * import { ItemSliding } from 'ionic-angular';
  366. *
  367. * @Component({...})
  368. * export class MyClass {
  369. * constructor() { }
  370. *
  371. * share(slidingItem: ItemSliding) {
  372. * slidingItem.close();
  373. * }
  374. * }
  375. * ```
  376. */
  377. ItemSliding.prototype.close = function () {
  378. this._setOpenAmount(0, true);
  379. };
  380. /**
  381. * @hidden
  382. */
  383. ItemSliding.prototype.setElementClass = function (cssClass, shouldAdd) {
  384. this._renderer.setElementClass(this._elementRef.nativeElement, cssClass, shouldAdd);
  385. };
  386. ItemSliding.decorators = [
  387. { type: Component, args: [{
  388. selector: 'ion-item-sliding',
  389. template: "\n <ng-content select=\"ion-item,[ion-item]\"></ng-content>\n <ng-content select=\"ion-item-options\"></ng-content>\n ",
  390. changeDetection: ChangeDetectionStrategy.OnPush,
  391. encapsulation: ViewEncapsulation.None
  392. },] },
  393. ];
  394. /** @nocollapse */
  395. ItemSliding.ctorParameters = function () { return [
  396. { type: List, decorators: [{ type: Optional },] },
  397. { type: Platform, },
  398. { type: Renderer, },
  399. { type: ElementRef, },
  400. { type: NgZone, },
  401. ]; };
  402. ItemSliding.propDecorators = {
  403. 'item': [{ type: ContentChild, args: [Item,] },],
  404. 'ionDrag': [{ type: Output },],
  405. '_itemOptions': [{ type: ContentChildren, args: [forwardRef(function () { return ItemOptions; }),] },],
  406. };
  407. return ItemSliding;
  408. }());
  409. export { ItemSliding };
  410. //# sourceMappingURL=item-sliding.js.map