import {Component, Template, Inject, Parent, NgElement} from 'angular2/angular2'; import {Ion} from '../ion'; import {IonConfig} from '../../config'; import {SlideEdgeGesture} from '../../core/gestures/slide-edge-gesture'; import * as util from '../../util'; export var asideConfig = new IonConfig('aside'); // TODO defaults or bindings? asideConfig.set({ side: 'left', dragThreshold: 50 }) @Component({ selector: 'ion-aside', bind: { side: 'side', dragThreshold: 'dragThreshold' } }) @Template({ inline: `` }) export class Aside { constructor( @Parent() asideParent: AsideParent, @NgElement() element: NgElement ) { this.domElement = element.domElement; this._drag = {}; this.domElement.addEventListener('transitionend', ev => { this.setChanging(false); }) let gestureConstructor = { left: LeftAsideSlideGesture, top: TopAsideSlideGesture, bottom: BottomAsideSlideGesture, right: RightAsideSlideGesture }; // TODO: remove this. setTimeout has to be done so the bindings can be applied setTimeout(() => { // asideConfig.invoke(this); this.domElement.classList.add(this.side); this.gesture = new gestureConstructor[this.side](this, asideParent.domElement); this.gesture.listen(); }); } setSliding(isSliding) { this.domElement.classList[isSliding ? 'add' : 'remove']('sliding'); } setChanging(isChanging) { if (isChanging !== this.isChanging) { this.isChanging = isChanging; this.domElement.classList[isChanging ? 'add' : 'remove']('changing'); } } setOpen(isOpen) { if (isOpen !== this.isOpen) { this.isOpen = isOpen; this.setChanging(true); requestAnimationFrame(() => { this.domElement.classList[isOpen ? 'add' : 'remove']('open'); }) } } } @Component({ selector: 'ion-aside-parent' }) @Template({ inline: '' }) export class AsideParent { constructor(@NgElement() element: NgElement) { this.domElement = element.domElement; super(); } } class AsideSlideGesture extends SlideEdgeGesture { constructor(aside: Aside, slideElement: Element) { this.aside = aside; super(slideElement, { direction: (aside.side === 'left' || aside.side === 'right') ? 'x' : 'y', edge: aside.side || 'left', threshold: aside.dragThreshold || 100 }); } canStart(ev) { // Only restrict edges if the aside is closed return this.aside.isOpen ? true : super.canStart(ev); } onSlideBeforeStart(slide, ev) { this.aside.setSliding(true); this.aside.setChanging(true); return new Promise(resolve => { requestAnimationFrame(resolve); }); } onSlide(slide, ev) { this.aside.domElement.style.transform = 'translate3d(' + slide.distance + 'px,0,0)'; } onSlideEnd(slide, ev) { this.aside.domElement.style.transform = ''; this.aside.setSliding(false); if (Math.abs(ev.velocityX) > 0.2 || Math.abs(slide.delta) > Math.abs(slide.max) * 0.5) { this.aside.setOpen(!this.aside.isOpen); } } getElementStartPos(slide, ev) { return this.aside.isOpen ? slide.max : slide.min; } getSlideBoundaries() { return { min: 0, max: this.aside.domElement.offsetWidth }; } } class LeftAsideSlideGesture extends AsideSlideGesture {} class RightAsideSlideGesture extends LeftAsideSlideGesture { getElementStartPos(slide, ev) { return this.aside.isOpen ? slide.min : slide.max; } getSlideBoundaries() { return { min: -this.aside.domElement.offsetWidth, max: 0 }; } } import Hammer from 'hammer'; class TopAsideSlideGesture extends AsideSlideGesture { onSlide(slide, ev) { this.aside.domElement.style.transform = 'translate3d(0,' + slide.distance + 'px,0)'; } getSlideBoundaries() { return { min: 0, max: this.aside.domElement.offsetHeight }; } } class BottomAsideSlideGesture extends TopAsideSlideGesture { getElementStartPos(slide, ev) { return this.aside.isOpen ? slide.min : slide.max; } getSlideBoundaries() { return { min: -this.aside.domElement.offsetHeight, max: 0 }; } }