import {Component, Directive, View, ElementRef, NgIf, ViewQuery, QueryList} from 'angular2/angular2'; import {Gesture} from 'ionic/gestures/gesture'; import {DragGesture} from 'ionic/gestures/drag-gesture'; import {Hammer} from 'ionic/gestures/hammer'; import * as util from 'ionic/util'; import {CSS, raf} from 'ionic/util/dom'; /** * @name ionItem * @description * Creates a list-item that can easily be swiped, * deleted, reordered, edited, and more. * * @usage * ```html * * * {{item.title}} *
* {{item.note}} *
* *
* ``` */ @Component({ selector: 'ion-item-sliding,[ion-item-sliding]', host: { 'class': 'item' }, properties: [ 'sliding' ] }) @View({ template: '' + '' + '' + ''+ '' + '' + '' + '', directives: [NgIf] }) export class ItemSliding { /** * TODO * @param {ElementRef} elementRef A reference to the component's DOM element. */ constructor(elementRef: ElementRef) { this._isOpen = false; this._isSlideActive = false; this._isTransitioning = false; this._transform = ''; this.ele = elementRef.nativeElement; this.swipeButtons = {}; this.optionButtons = {}; } onInit() { this._initSliding(); } _initSliding() { var itemSlidingContent = this.ele.querySelector('ion-item-sliding-content'); var itemOptionsContent = this.ele.querySelector('ion-item-options'); this.itemSlidingContent = itemSlidingContent; this.itemOptions = itemOptionsContent; this.itemWidth = itemSlidingContent.offsetWidth; this.itemOptionsWidth = itemOptionsContent && itemOptionsContent.offsetWidth || 0; this.openAmount = 0; this.gesture = new ItemSlideGesture(this, itemSlidingContent); } close() { this.openAmount = 0; // Enable it once, it'll get disabled on the next drag this.enableAnimation(); el.style[CSS.transform] = 'translateX(' + -amt + 'px)'; } open(amt) { let el = this.itemSlidingContent; this.openAmount = amt || 0; if(amt === '') { el.style[CSS.transform] = ''; } else { el.style[CSS.transform] = 'translateX(' + -amt + 'px)'; } } get isOpen() { return this.openAmount > 0; } getOpenAmt() { return this.openAmount; } getItemWidth() { return this.itemWidth; } disableAnimation() { this.itemSlidingContent.style[CSS.transition] = 'none'; } enableAnimation() { // Clear the explicit transition, allow for CSS one to take over this.itemSlidingContent.style[CSS.transition] = ''; } } class ItemSlideGesture extends DragGesture { constructor(item: ItemSliding, el: Element) { super(el, { direction: 'x', threshold: el.offsetWidth }); this.el = el; this.item = item; this.listen(); } onDragStart(ev) { this.slide = {}; this.slide.offsetX = this.item.getOpenAmt(); this.slide.startX = ev.center[this.direction]; this.slide.started = true; this.item.disableAnimation(); } onDrag(ev) { if (!this.slide || !this.slide.started) return; this.slide.x = ev.center[this.direction]; this.slide.delta = this.slide.x - this.slide.startX; let newX = Math.max(0, this.slide.offsetX - this.slide.delta); let buttonsWidth = this.item.itemOptionsWidth; if(newX > this.item.itemOptionsWidth) { // Calculate the new X position, capped at the top of the buttons newX = -Math.min(-buttonsWidth, -buttonsWidth + (((this.slide.delta + buttonsWidth) * 0.4))); } this.item.open(newX); } onDragEnd(ev) { if (!this.slide || !this.slide.started) return; let buttonsWidth = this.item.itemOptionsWidth; // If we are currently dragging, we want to snap back into place // The final resting point X will be the width of the exposed buttons var restingPoint = this.item.itemOptionsWidth; // Check if the drag didn't clear the buttons mid-point // and we aren't moving fast enough to swipe open if (this.item.openAmount < (buttonsWidth / 2)) { // If we are going left but too slow, or going right, go back to resting if (ev.direction & Hammer.DIRECTION_RIGHT) { // Left restingPoint = 0; } else if (Math.abs(ev.velocityX) < 0.3) { // Right restingPoint = 0; } } raf(() => { if (restingPoint === 0) { // Reset to zero this.item.open(''); var buttons = this.item.itemOptions; clearTimeout(this.hideButtonsTimeout); this.hideButtonsTimeout = setTimeout(() => { buttons && buttons.classList.add('invisible'); }, 250); } else { this.item.open(restingPoint); } this.item.enableAnimation(); this.slide = null; }); } }