| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578 |
- import { fromEvent } from 'rxjs';
- import { Directive, ElementRef, Renderer2, Input, Output, HostListener, EventEmitter, NgModule } from '@angular/core';
- /**
- * @fileoverview added by tsickle
- * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
- */
- class Position {
- /**
- * @param {?} x
- * @param {?} y
- */
- constructor(x, y) {
- this.x = x;
- this.y = y;
- }
- /**
- * @param {?} e
- * @param {?=} el
- * @return {?}
- */
- static fromEvent(e, el = null) {
- /**
- * Fix issue: Resize doesn't work on Windows10 IE11 (and on some windows 7 IE11)
- * https://github.com/xieziyu/angular2-draggable/issues/164
- * e instanceof MouseEvent check returns false on IE11
- */
- if (this.isMouseEvent(e)) {
- return new Position(e.clientX, e.clientY);
- }
- else {
- if (el === null || e.changedTouches.length === 1) {
- return new Position(e.changedTouches[0].clientX, e.changedTouches[0].clientY);
- }
- /**
- * Fix issue: Multiple phone draggables at the same time
- * https://github.com/xieziyu/angular2-draggable/issues/128
- */
- for (let i = 0; i < e.changedTouches.length; i++) {
- if (e.changedTouches[i].target === el) {
- return new Position(e.changedTouches[i].clientX, e.changedTouches[i].clientY);
- }
- }
- }
- }
- /**
- * @param {?} e
- * @return {?}
- */
- static isMouseEvent(e) {
- return Object.prototype.toString.apply(e).indexOf('MouseEvent') === 8;
- }
- /**
- * @param {?} obj
- * @return {?}
- */
- static isIPosition(obj) {
- return !!obj && ('x' in obj) && ('y' in obj);
- }
- /**
- * @param {?} el
- * @return {?}
- */
- static getCurrent(el) {
- /** @type {?} */
- let pos = new Position(0, 0);
- if (window) {
- /** @type {?} */
- const computed = window.getComputedStyle(el);
- if (computed) {
- /** @type {?} */
- let x = parseInt(computed.getPropertyValue('left'), 10);
- /** @type {?} */
- let y = parseInt(computed.getPropertyValue('top'), 10);
- pos.x = isNaN(x) ? 0 : x;
- pos.y = isNaN(y) ? 0 : y;
- }
- return pos;
- }
- else {
- console.error('Not Supported!');
- return null;
- }
- }
- /**
- * @param {?} p
- * @return {?}
- */
- static copy(p) {
- return new Position(0, 0).set(p);
- }
- /**
- * @return {?}
- */
- get value() {
- return { x: this.x, y: this.y };
- }
- /**
- * @template THIS
- * @this {THIS}
- * @param {?} p
- * @return {THIS}
- */
- add(p) {
- (/** @type {?} */ (this)).x += p.x;
- (/** @type {?} */ (this)).y += p.y;
- return (/** @type {?} */ (this));
- }
- /**
- * @template THIS
- * @this {THIS}
- * @param {?} p
- * @return {THIS}
- */
- subtract(p) {
- (/** @type {?} */ (this)).x -= p.x;
- (/** @type {?} */ (this)).y -= p.y;
- return (/** @type {?} */ (this));
- }
- /**
- * @param {?} n
- * @return {?}
- */
- multiply(n) {
- this.x *= n;
- this.y *= n;
- }
- /**
- * @param {?} n
- * @return {?}
- */
- divide(n) {
- this.x /= n;
- this.y /= n;
- }
- /**
- * @template THIS
- * @this {THIS}
- * @return {THIS}
- */
- reset() {
- (/** @type {?} */ (this)).x = 0;
- (/** @type {?} */ (this)).y = 0;
- return (/** @type {?} */ (this));
- }
- /**
- * @template THIS
- * @this {THIS}
- * @param {?} p
- * @return {THIS}
- */
- set(p) {
- (/** @type {?} */ (this)).x = p.x;
- (/** @type {?} */ (this)).y = p.y;
- return (/** @type {?} */ (this));
- }
- }
- /**
- * @fileoverview added by tsickle
- * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
- */
- class HelperBlock {
- /**
- * @param {?} parent
- * @param {?} renderer
- */
- constructor(parent, renderer) {
- this.parent = parent;
- this.renderer = renderer;
- this._added = false;
- // generate helper div
- /** @type {?} */
- let helper = renderer.createElement('div');
- renderer.setStyle(helper, 'position', 'absolute');
- renderer.setStyle(helper, 'width', '100%');
- renderer.setStyle(helper, 'height', '100%');
- renderer.setStyle(helper, 'background-color', 'transparent');
- renderer.setStyle(helper, 'top', '0');
- renderer.setStyle(helper, 'left', '0');
- // done
- this._helper = helper;
- }
- /**
- * @return {?}
- */
- add() {
- // append div to parent
- if (this.parent && !this._added) {
- this.parent.appendChild(this._helper);
- this._added = true;
- }
- }
- /**
- * @return {?}
- */
- remove() {
- if (this.parent && this._added) {
- this.parent.removeChild(this._helper);
- this._added = false;
- }
- }
- /**
- * @return {?}
- */
- dispose() {
- this._helper = null;
- this._added = false;
- }
- /**
- * @return {?}
- */
- get el() {
- return this._helper;
- }
- }
- /**
- * @fileoverview added by tsickle
- * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
- */
- class AngularDraggableDirective {
- /**
- * @param {?} el
- * @param {?} renderer
- */
- constructor(el, renderer) {
- this.el = el;
- this.renderer = renderer;
- this.allowDrag = true;
- this.moving = false;
- this.orignal = null;
- this.oldTrans = new Position(0, 0);
- this.tempTrans = new Position(0, 0);
- this.currTrans = new Position(0, 0);
- this.oldZIndex = '';
- this._zIndex = '';
- this.needTransform = false;
- this.draggingSub = null;
- /**
- * Bugfix: iFrames, and context unrelated elements block all events, and are unusable
- * https://github.com/xieziyu/angular2-draggable/issues/84
- */
- this._helperBlock = null;
- this.started = new EventEmitter();
- this.stopped = new EventEmitter();
- this.edge = new EventEmitter();
- /**
- * List of allowed out of bounds edges *
- */
- this.outOfBounds = {
- top: false,
- right: false,
- bottom: false,
- left: false
- };
- /**
- * Round the position to nearest grid
- */
- this.gridSize = 1;
- /**
- * Whether to limit the element stay in the bounds
- */
- this.inBounds = false;
- /**
- * Whether the element should use it's previous drag position on a new drag event.
- */
- this.trackPosition = true;
- /**
- * Input css scale transform of element so translations are correct
- */
- this.scale = 1;
- /**
- * Whether to prevent default event
- */
- this.preventDefaultEvent = false;
- /**
- * Set initial position by offsets
- */
- this.position = { x: 0, y: 0 };
- /**
- * Lock axis: 'x' or 'y'
- */
- this.lockAxis = null;
- /**
- * Emit position offsets when moving
- */
- this.movingOffset = new EventEmitter();
- /**
- * Emit position offsets when put back
- */
- this.endOffset = new EventEmitter();
- this._helperBlock = new HelperBlock(el.nativeElement, renderer);
- }
- /**
- * Set z-index when not dragging
- * @param {?} setting
- * @return {?}
- */
- set zIndex(setting) {
- this.renderer.setStyle(this.el.nativeElement, 'z-index', setting);
- this._zIndex = setting;
- }
- /**
- * @param {?} setting
- * @return {?}
- */
- set ngDraggable(setting) {
- if (setting !== undefined && setting !== null && setting !== '') {
- this.allowDrag = !!setting;
- /** @type {?} */
- let element = this.getDragEl();
- if (this.allowDrag) {
- this.renderer.addClass(element, 'ng-draggable');
- }
- else {
- this.putBack();
- this.renderer.removeClass(element, 'ng-draggable');
- }
- }
- }
- /**
- * @return {?}
- */
- ngOnInit() {
- if (this.allowDrag) {
- /** @type {?} */
- let element = this.getDragEl();
- this.renderer.addClass(element, 'ng-draggable');
- }
- this.resetPosition();
- }
- /**
- * @return {?}
- */
- ngOnDestroy() {
- this.bounds = null;
- this.handle = null;
- this.orignal = null;
- this.oldTrans = null;
- this.tempTrans = null;
- this.currTrans = null;
- this._helperBlock.dispose();
- this._helperBlock = null;
- if (this.draggingSub) {
- this.draggingSub.unsubscribe();
- }
- }
- /**
- * @param {?} changes
- * @return {?}
- */
- ngOnChanges(changes) {
- if (changes['position'] && !changes['position'].isFirstChange()) {
- /** @type {?} */
- let p = changes['position'].currentValue;
- if (!this.moving) {
- if (Position.isIPosition(p)) {
- this.oldTrans.set(p);
- }
- else {
- this.oldTrans.reset();
- }
- this.transform();
- }
- else {
- this.needTransform = true;
- }
- }
- }
- /**
- * @return {?}
- */
- ngAfterViewInit() {
- if (this.inBounds) {
- this.boundsCheck();
- this.oldTrans.add(this.tempTrans);
- this.tempTrans.reset();
- }
- }
- /**
- * @private
- * @return {?}
- */
- getDragEl() {
- return this.handle ? this.handle : this.el.nativeElement;
- }
- /**
- * @return {?}
- */
- resetPosition() {
- if (Position.isIPosition(this.position)) {
- this.oldTrans.set(this.position);
- }
- else {
- this.oldTrans.reset();
- }
- this.tempTrans.reset();
- this.transform();
- }
- /**
- * @private
- * @param {?} p
- * @return {?}
- */
- moveTo(p) {
- if (this.orignal) {
- p.subtract(this.orignal);
- this.tempTrans.set(p);
- this.tempTrans.divide(this.scale);
- this.transform();
- if (this.bounds) {
- this.edge.emit(this.boundsCheck());
- }
- this.movingOffset.emit(this.currTrans.value);
- }
- }
- /**
- * @private
- * @return {?}
- */
- transform() {
- /** @type {?} */
- let translateX = this.tempTrans.x + this.oldTrans.x;
- /** @type {?} */
- let translateY = this.tempTrans.y + this.oldTrans.y;
- if (this.lockAxis === 'x') {
- translateX = this.oldTrans.x;
- this.tempTrans.x = 0;
- }
- else if (this.lockAxis === 'y') {
- translateY = this.oldTrans.y;
- this.tempTrans.y = 0;
- }
- // Snap to grid: by grid size
- if (this.gridSize > 1) {
- translateX = Math.round(translateX / this.gridSize) * this.gridSize;
- translateY = Math.round(translateY / this.gridSize) * this.gridSize;
- }
- /** @type {?} */
- let value = `translate(${Math.round(translateX)}px, ${Math.round(translateY)}px)`;
- this.renderer.setStyle(this.el.nativeElement, 'transform', value);
- this.renderer.setStyle(this.el.nativeElement, '-webkit-transform', value);
- this.renderer.setStyle(this.el.nativeElement, '-ms-transform', value);
- this.renderer.setStyle(this.el.nativeElement, '-moz-transform', value);
- this.renderer.setStyle(this.el.nativeElement, '-o-transform', value);
- // save current position
- this.currTrans.x = translateX;
- this.currTrans.y = translateY;
- }
- /**
- * @private
- * @return {?}
- */
- pickUp() {
- // get old z-index:
- this.oldZIndex = this.el.nativeElement.style.zIndex ? this.el.nativeElement.style.zIndex : '';
- if (window) {
- this.oldZIndex = window.getComputedStyle(this.el.nativeElement, null).getPropertyValue('z-index');
- }
- if (this.zIndexMoving) {
- this.renderer.setStyle(this.el.nativeElement, 'z-index', this.zIndexMoving);
- }
- if (!this.moving) {
- this.started.emit(this.el.nativeElement);
- this.moving = true;
- /** @type {?} */
- const element = this.getDragEl();
- this.renderer.addClass(element, 'ng-dragging');
- /**
- * Fix performance issue:
- * https://github.com/xieziyu/angular2-draggable/issues/112
- */
- this.subscribeEvents();
- }
- }
- /**
- * @private
- * @return {?}
- */
- subscribeEvents() {
- this.draggingSub = fromEvent(document, 'mousemove', { passive: false }).subscribe(event => this.onMouseMove((/** @type {?} */ (event))));
- this.draggingSub.add(fromEvent(document, 'touchmove', { passive: false }).subscribe(event => this.onMouseMove((/** @type {?} */ (event)))));
- this.draggingSub.add(fromEvent(document, 'mouseup', { passive: false }).subscribe(() => this.putBack()));
- // checking if browser is IE or Edge - https://github.com/xieziyu/angular2-draggable/issues/153
- /** @type {?} */
- let isIEOrEdge = /msie\s|trident\//i.test(window.navigator.userAgent);
- if (!isIEOrEdge) {
- this.draggingSub.add(fromEvent(document, 'mouseleave', { passive: false }).subscribe(() => this.putBack()));
- }
- this.draggingSub.add(fromEvent(document, 'touchend', { passive: false }).subscribe(() => this.putBack()));
- this.draggingSub.add(fromEvent(document, 'touchcancel', { passive: false }).subscribe(() => this.putBack()));
- }
- /**
- * @private
- * @return {?}
- */
- unsubscribeEvents() {
- this.draggingSub.unsubscribe();
- this.draggingSub = null;
- }
- /**
- * @return {?}
- */
- boundsCheck() {
- if (this.bounds) {
- /** @type {?} */
- let boundary = this.bounds.getBoundingClientRect();
- /** @type {?} */
- let elem = this.el.nativeElement.getBoundingClientRect();
- /** @type {?} */
- let result = {
- 'top': this.outOfBounds.top ? true : boundary.top < elem.top,
- 'right': this.outOfBounds.right ? true : boundary.right > elem.right,
- 'bottom': this.outOfBounds.bottom ? true : boundary.bottom > elem.bottom,
- 'left': this.outOfBounds.left ? true : boundary.left < elem.left
- };
- if (this.inBounds) {
- if (!result.top) {
- this.tempTrans.y -= (elem.top - boundary.top) / this.scale;
- }
- if (!result.bottom) {
- this.tempTrans.y -= (elem.bottom - boundary.bottom) / this.scale;
- }
- if (!result.right) {
- this.tempTrans.x -= (elem.right - boundary.right) / this.scale;
- }
- if (!result.left) {
- this.tempTrans.x -= (elem.left - boundary.left) / this.scale;
- }
- this.transform();
- }
- return result;
- }
- }
- /**
- * Get current offset
- * @return {?}
- */
- getCurrentOffset() {
- return this.currTrans.value;
- }
- /**
- * @private
- * @return {?}
- */
- putBack() {
- if (this._zIndex) {
- this.renderer.setStyle(this.el.nativeElement, 'z-index', this._zIndex);
- }
- else if (this.zIndexMoving) {
- if (this.oldZIndex) {
- this.renderer.setStyle(this.el.nativeElement, 'z-index', this.oldZIndex);
- }
- else {
- this.el.nativeElement.style.removeProperty('z-index');
- }
- }
- if (this.moving) {
- this.stopped.emit(this.el.nativeElement);
- // Remove the helper div:
- this._helperBlock.remove();
- if (this.needTransform) {
- if (Position.isIPosition(this.position)) {
- this.oldTrans.set(this.position);
- }
- else {
- this.oldTrans.reset();
- }
- this.transform();
- this.needTransform = false;
- }
- if (this.bounds) {
- this.edge.emit(this.boundsCheck());
- }
- this.moving = false;
- this.endOffset.emit(this.currTrans.value);
- if (this.trackPosition) {
- this.oldTrans.add(this.tempTrans);
- }
- this.tempTrans.reset();
- if (!this.trackPosition) {
- this.transform();
- }
- /** @type {?} */
- const element = this.getDragEl();
- this.renderer.removeClass(element, 'ng-dragging');
- /**
- * Fix performance issue:
- * https://github.com/xieziyu/angular2-draggable/issues/112
- */
- this.unsubscribeEvents();
- }
- }
- /**
- * @param {?} target
- * @param {?} element
- * @return {?}
- */
- checkHandleTarget(target, element) {
- // Checks if the target is the element clicked, then checks each child element of element as well
- // Ignores button clicks
- // Ignore elements of type button
- if (element.tagName === 'BUTTON') {
- return false;
- }
- // If the target was found, return true (handle was found)
- if (element === target) {
- return true;
- }
- // Recursively iterate this elements children
- for (let child in element.children) {
- if (element.children.hasOwnProperty(child)) {
- if (this.checkHandleTarget(target, element.children[child])) {
- return true;
- }
- }
- }
- // Handle was not found in this lineage
- // Note: return false is ignore unless it is the parent element
- return false;
- }
- /**
- * @param {?} event
- * @return {?}
- */
- onMouseDown(event) {
- // 1. skip right click;
- if (event instanceof MouseEvent && event.button === 2) {
- return;
- }
- // 2. if handle is set, the element can only be moved by handle
- /** @type {?} */
- let target = event.target || event.srcElement;
- if (this.handle !== undefined && !this.checkHandleTarget(target, this.handle)) {
- return;
- }
- // 3. if allow drag is set to false, ignore the mousedown
- if (this.allowDrag === false) {
- return;
- }
- if (this.preventDefaultEvent) {
- event.stopPropagation();
- event.preventDefault();
- }
- this.orignal = Position.fromEvent(event, this.getDragEl());
- this.pickUp();
- }
- /**
- * @param {?} event
- * @return {?}
- */
- onMouseMove(event) {
- if (this.moving && this.allowDrag) {
- if (this.preventDefaultEvent) {
- event.stopPropagation();
- event.preventDefault();
- }
- // Add a transparent helper div:
- this._helperBlock.add();
- this.moveTo(Position.fromEvent(event, this.getDragEl()));
- }
- }
- }
- AngularDraggableDirective.decorators = [
- { type: Directive, args: [{
- selector: '[ngDraggable]',
- exportAs: 'ngDraggable'
- },] }
- ];
- /** @nocollapse */
- AngularDraggableDirective.ctorParameters = () => [
- { type: ElementRef },
- { type: Renderer2 }
- ];
- AngularDraggableDirective.propDecorators = {
- started: [{ type: Output }],
- stopped: [{ type: Output }],
- edge: [{ type: Output }],
- handle: [{ type: Input }],
- bounds: [{ type: Input }],
- outOfBounds: [{ type: Input }],
- gridSize: [{ type: Input }],
- zIndexMoving: [{ type: Input }],
- zIndex: [{ type: Input }],
- inBounds: [{ type: Input }],
- trackPosition: [{ type: Input }],
- scale: [{ type: Input }],
- preventDefaultEvent: [{ type: Input }],
- position: [{ type: Input }],
- lockAxis: [{ type: Input }],
- movingOffset: [{ type: Output }],
- endOffset: [{ type: Output }],
- ngDraggable: [{ type: Input }],
- onMouseDown: [{ type: HostListener, args: ['mousedown', ['$event'],] }, { type: HostListener, args: ['touchstart', ['$event'],] }]
- };
- /**
- * @fileoverview added by tsickle
- * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
- */
- class ResizeHandle {
- /**
- * @param {?} parent
- * @param {?} renderer
- * @param {?} type
- * @param {?} css
- * @param {?} onMouseDown
- */
- constructor(parent, renderer, type, css, onMouseDown) {
- this.parent = parent;
- this.renderer = renderer;
- this.type = type;
- this.css = css;
- this.onMouseDown = onMouseDown;
- // generate handle div
- /** @type {?} */
- let handle = renderer.createElement('div');
- renderer.addClass(handle, 'ng-resizable-handle');
- renderer.addClass(handle, css);
- // add default diagonal for se handle
- if (type === 'se') {
- renderer.addClass(handle, 'ng-resizable-diagonal');
- }
- // append div to parent
- if (this.parent) {
- parent.appendChild(handle);
- }
- // create and register event listener
- this._onResize = (event) => { onMouseDown(event, this); };
- handle.addEventListener('mousedown', this._onResize, { passive: false });
- handle.addEventListener('touchstart', this._onResize, { passive: false });
- // done
- this._handle = handle;
- }
- /**
- * @return {?}
- */
- dispose() {
- this._handle.removeEventListener('mousedown', this._onResize);
- this._handle.removeEventListener('touchstart', this._onResize);
- if (this.parent) {
- this.parent.removeChild(this._handle);
- }
- this._handle = null;
- this._onResize = null;
- }
- /**
- * @return {?}
- */
- get el() {
- return this._handle;
- }
- }
- /**
- * @fileoverview added by tsickle
- * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
- */
- class Size {
- /**
- * @param {?} width
- * @param {?} height
- */
- constructor(width, height) {
- this.width = width;
- this.height = height;
- }
- /**
- * @param {?} el
- * @return {?}
- */
- static getCurrent(el) {
- /** @type {?} */
- let size = new Size(0, 0);
- if (window) {
- /** @type {?} */
- const computed = window.getComputedStyle(el);
- if (computed) {
- size.width = parseInt(computed.getPropertyValue('width'), 10);
- size.height = parseInt(computed.getPropertyValue('height'), 10);
- }
- return size;
- }
- else {
- console.error('Not Supported!');
- return null;
- }
- }
- /**
- * @param {?} s
- * @return {?}
- */
- static copy(s) {
- return new Size(0, 0).set(s);
- }
- /**
- * @template THIS
- * @this {THIS}
- * @param {?} s
- * @return {THIS}
- */
- set(s) {
- (/** @type {?} */ (this)).width = s.width;
- (/** @type {?} */ (this)).height = s.height;
- return (/** @type {?} */ (this));
- }
- }
- /**
- * @fileoverview added by tsickle
- * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
- */
- class AngularResizableDirective {
- /**
- * @param {?} el
- * @param {?} renderer
- */
- constructor(el, renderer) {
- this.el = el;
- this.renderer = renderer;
- this._resizable = true;
- this._handles = {};
- this._handleType = [];
- this._handleResizing = null;
- this._direction = null;
- this._directionChanged = null;
- this._aspectRatio = 0;
- this._containment = null;
- this._origMousePos = null;
- /**
- * Original Size and Position
- */
- this._origSize = null;
- this._origPos = null;
- /**
- * Current Size and Position
- */
- this._currSize = null;
- this._currPos = null;
- /**
- * Initial Size and Position
- */
- this._initSize = null;
- this._initPos = null;
- /**
- * Snap to gird
- */
- this._gridSize = null;
- this._bounding = null;
- /**
- * Bugfix: iFrames, and context unrelated elements block all events, and are unusable
- * https://github.com/xieziyu/angular2-draggable/issues/84
- */
- this._helperBlock = null;
- this.draggingSub = null;
- this._adjusted = false;
- /**
- * Which handles can be used for resizing.
- * \@example
- * [rzHandles] = "'n,e,s,w,se,ne,sw,nw'"
- * equals to: [rzHandles] = "'all'"
- *
- *
- */
- this.rzHandles = 'e,s,se';
- /**
- * Whether the element should be constrained to a specific aspect ratio.
- * Multiple types supported:
- * boolean: When set to true, the element will maintain its original aspect ratio.
- * number: Force the element to maintain a specific aspect ratio during resizing.
- */
- this.rzAspectRatio = false;
- /**
- * Constrains resizing to within the bounds of the specified element or region.
- * Multiple types supported:
- * Selector: The resizable element will be contained to the bounding box of the first element found by the selector.
- * If no element is found, no containment will be set.
- * Element: The resizable element will be contained to the bounding box of this element.
- * String: Possible values: "parent".
- */
- this.rzContainment = null;
- /**
- * Snaps the resizing element to a grid, every x and y pixels.
- * A number for both width and height or an array values like [ x, y ]
- */
- this.rzGrid = null;
- /**
- * The minimum width the resizable should be allowed to resize to.
- */
- this.rzMinWidth = null;
- /**
- * The minimum height the resizable should be allowed to resize to.
- */
- this.rzMinHeight = null;
- /**
- * The maximum width the resizable should be allowed to resize to.
- */
- this.rzMaxWidth = null;
- /**
- * The maximum height the resizable should be allowed to resize to.
- */
- this.rzMaxHeight = null;
- /**
- * Whether to prevent default event
- */
- this.preventDefaultEvent = true;
- /**
- * emitted when start resizing
- */
- this.rzStart = new EventEmitter();
- /**
- * emitted when start resizing
- */
- this.rzResizing = new EventEmitter();
- /**
- * emitted when stop resizing
- */
- this.rzStop = new EventEmitter();
- this._helperBlock = new HelperBlock(el.nativeElement, renderer);
- }
- /**
- * Disables the resizable if set to false.
- * @param {?} v
- * @return {?}
- */
- set ngResizable(v) {
- if (v !== undefined && v !== null && v !== '') {
- this._resizable = !!v;
- this.updateResizable();
- }
- }
- /**
- * @param {?} changes
- * @return {?}
- */
- ngOnChanges(changes) {
- if (changes['rzHandles'] && !changes['rzHandles'].isFirstChange()) {
- this.updateResizable();
- }
- if (changes['rzAspectRatio'] && !changes['rzAspectRatio'].isFirstChange()) {
- this.updateAspectRatio();
- }
- if (changes['rzContainment'] && !changes['rzContainment'].isFirstChange()) {
- this.updateContainment();
- }
- }
- /**
- * @return {?}
- */
- ngOnInit() {
- this.updateResizable();
- }
- /**
- * @return {?}
- */
- ngOnDestroy() {
- this.removeHandles();
- this._containment = null;
- this._helperBlock.dispose();
- this._helperBlock = null;
- }
- /**
- * @return {?}
- */
- ngAfterViewInit() {
- /** @type {?} */
- const elm = this.el.nativeElement;
- this._initSize = Size.getCurrent(elm);
- this._initPos = Position.getCurrent(elm);
- this._currSize = Size.copy(this._initSize);
- this._currPos = Position.copy(this._initPos);
- this.updateAspectRatio();
- this.updateContainment();
- }
- /**
- * A method to reset size
- * @return {?}
- */
- resetSize() {
- this._currSize = Size.copy(this._initSize);
- this._currPos = Position.copy(this._initPos);
- this.doResize();
- }
- /**
- * A method to get current status
- * @return {?}
- */
- getStatus() {
- if (!this._currPos || !this._currSize) {
- return null;
- }
- return {
- size: {
- width: this._currSize.width,
- height: this._currSize.height
- },
- position: {
- top: this._currPos.y,
- left: this._currPos.x
- }
- };
- }
- /**
- * @private
- * @return {?}
- */
- updateResizable() {
- /** @type {?} */
- const element = this.el.nativeElement;
- // clear handles:
- this.renderer.removeClass(element, 'ng-resizable');
- this.removeHandles();
- // create new ones:
- if (this._resizable) {
- this.renderer.addClass(element, 'ng-resizable');
- this.createHandles();
- }
- }
- /**
- * Use it to update aspect
- * @private
- * @return {?}
- */
- updateAspectRatio() {
- if (typeof this.rzAspectRatio === 'boolean') {
- if (this.rzAspectRatio && this._currSize.height) {
- this._aspectRatio = (this._currSize.width / this._currSize.height);
- }
- else {
- this._aspectRatio = 0;
- }
- }
- else {
- /** @type {?} */
- let r = Number(this.rzAspectRatio);
- this._aspectRatio = isNaN(r) ? 0 : r;
- }
- }
- /**
- * Use it to update containment
- * @private
- * @return {?}
- */
- updateContainment() {
- if (!this.rzContainment) {
- this._containment = null;
- return;
- }
- if (typeof this.rzContainment === 'string') {
- if (this.rzContainment === 'parent') {
- this._containment = this.el.nativeElement.parentElement;
- }
- else {
- this._containment = document.querySelector(this.rzContainment);
- }
- }
- else {
- this._containment = this.rzContainment;
- }
- }
- /**
- * Use it to create handle divs
- * @private
- * @return {?}
- */
- createHandles() {
- if (!this.rzHandles) {
- return;
- }
- /** @type {?} */
- let tmpHandleTypes;
- if (typeof this.rzHandles === 'string') {
- if (this.rzHandles === 'all') {
- tmpHandleTypes = ['n', 'e', 's', 'w', 'ne', 'se', 'nw', 'sw'];
- }
- else {
- tmpHandleTypes = this.rzHandles.replace(/ /g, '').toLowerCase().split(',');
- }
- for (let type of tmpHandleTypes) {
- // default handle theme: ng-resizable-$type.
- /** @type {?} */
- let handle = this.createHandleByType(type, `ng-resizable-${type}`);
- if (handle) {
- this._handleType.push(type);
- this._handles[type] = handle;
- }
- }
- }
- else {
- tmpHandleTypes = Object.keys(this.rzHandles);
- for (let type of tmpHandleTypes) {
- // custom handle theme.
- /** @type {?} */
- let handle = this.createHandleByType(type, this.rzHandles[type]);
- if (handle) {
- this._handleType.push(type);
- this._handles[type] = handle;
- }
- }
- }
- }
- /**
- * Use it to create a handle
- * @private
- * @param {?} type
- * @param {?} css
- * @return {?}
- */
- createHandleByType(type, css) {
- /** @type {?} */
- const _el = this.el.nativeElement;
- if (!type.match(/^(se|sw|ne|nw|n|e|s|w)$/)) {
- console.error('Invalid handle type:', type);
- return null;
- }
- return new ResizeHandle(_el, this.renderer, type, css, this.onMouseDown.bind(this));
- }
- /**
- * @private
- * @return {?}
- */
- removeHandles() {
- for (let type of this._handleType) {
- this._handles[type].dispose();
- }
- this._handleType = [];
- this._handles = {};
- }
- /**
- * @param {?} event
- * @param {?} handle
- * @return {?}
- */
- onMouseDown(event, handle) {
- // skip right click;
- if (event instanceof MouseEvent && event.button === 2) {
- return;
- }
- if (this.preventDefaultEvent) {
- // prevent default events
- event.stopPropagation();
- event.preventDefault();
- }
- if (!this._handleResizing) {
- this._origMousePos = Position.fromEvent(event);
- this.startResize(handle);
- this.subscribeEvents();
- }
- }
- /**
- * @private
- * @return {?}
- */
- subscribeEvents() {
- this.draggingSub = fromEvent(document, 'mousemove', { passive: false }).subscribe(event => this.onMouseMove((/** @type {?} */ (event))));
- this.draggingSub.add(fromEvent(document, 'touchmove', { passive: false }).subscribe(event => this.onMouseMove((/** @type {?} */ (event)))));
- this.draggingSub.add(fromEvent(document, 'mouseup', { passive: false }).subscribe(() => this.onMouseLeave()));
- // fix for issue #164
- /** @type {?} */
- let isIEOrEdge = /msie\s|trident\//i.test(window.navigator.userAgent);
- if (!isIEOrEdge) {
- this.draggingSub.add(fromEvent(document, 'mouseleave', { passive: false }).subscribe(() => this.onMouseLeave()));
- }
- this.draggingSub.add(fromEvent(document, 'touchend', { passive: false }).subscribe(() => this.onMouseLeave()));
- this.draggingSub.add(fromEvent(document, 'touchcancel', { passive: false }).subscribe(() => this.onMouseLeave()));
- }
- /**
- * @private
- * @return {?}
- */
- unsubscribeEvents() {
- this.draggingSub.unsubscribe();
- this.draggingSub = null;
- }
- /**
- * @return {?}
- */
- onMouseLeave() {
- if (this._handleResizing) {
- this.stopResize();
- this._origMousePos = null;
- this.unsubscribeEvents();
- }
- }
- /**
- * @param {?} event
- * @return {?}
- */
- onMouseMove(event) {
- if (this._handleResizing && this._resizable && this._origMousePos && this._origPos && this._origSize) {
- this.resizeTo(Position.fromEvent(event));
- this.onResizing();
- }
- }
- /**
- * @private
- * @param {?} handle
- * @return {?}
- */
- startResize(handle) {
- /** @type {?} */
- const elm = this.el.nativeElement;
- this._origSize = Size.getCurrent(elm);
- this._origPos = Position.getCurrent(elm); // x: left, y: top
- this._currSize = Size.copy(this._origSize);
- this._currPos = Position.copy(this._origPos);
- if (this._containment) {
- this.getBounding();
- }
- this.getGridSize();
- // Add a transparent helper div:
- this._helperBlock.add();
- this._handleResizing = handle;
- this.updateDirection();
- this.rzStart.emit(this.getResizingEvent());
- }
- /**
- * @private
- * @return {?}
- */
- stopResize() {
- // Remove the helper div:
- this._helperBlock.remove();
- this.rzStop.emit(this.getResizingEvent());
- this._handleResizing = null;
- this._direction = null;
- this._origSize = null;
- this._origPos = null;
- if (this._containment) {
- this.resetBounding();
- }
- }
- /**
- * @private
- * @return {?}
- */
- onResizing() {
- this.rzResizing.emit(this.getResizingEvent());
- }
- /**
- * @private
- * @return {?}
- */
- getResizingEvent() {
- return {
- host: this.el.nativeElement,
- handle: this._handleResizing ? this._handleResizing.el : null,
- size: {
- width: this._currSize.width,
- height: this._currSize.height
- },
- position: {
- top: this._currPos.y,
- left: this._currPos.x
- },
- direction: Object.assign({}, this._directionChanged),
- };
- }
- /**
- * @private
- * @return {?}
- */
- updateDirection() {
- this._direction = {
- n: !!this._handleResizing.type.match(/n/),
- s: !!this._handleResizing.type.match(/s/),
- w: !!this._handleResizing.type.match(/w/),
- e: !!this._handleResizing.type.match(/e/)
- };
- this._directionChanged = Object.assign({}, this._direction);
- // if aspect ration should be preserved:
- if (this.rzAspectRatio) {
- // if north then west (unless ne)
- if (this._directionChanged.n && !this._directionChanged.e) {
- this._directionChanged.w = true;
- }
- // if south then east (unless sw)
- if (this._directionChanged.s && !this._directionChanged.w) {
- this._directionChanged.e = true;
- }
- // if east then south (unless ne)
- if (this._directionChanged.e && !this._directionChanged.n) {
- this._directionChanged.s = true;
- }
- // if west then south (unless nw)
- if (this._directionChanged.w && !this._directionChanged.n) {
- this._directionChanged.s = true;
- }
- }
- }
- /**
- * @private
- * @param {?} p
- * @return {?}
- */
- resizeTo(p) {
- p.subtract(this._origMousePos);
- /** @type {?} */
- const tmpX = Math.round(p.x / this._gridSize.x) * this._gridSize.x;
- /** @type {?} */
- const tmpY = Math.round(p.y / this._gridSize.y) * this._gridSize.y;
- if (this._direction.n) {
- // n, ne, nw
- this._currPos.y = this._origPos.y + tmpY;
- this._currSize.height = this._origSize.height - tmpY;
- }
- else if (this._direction.s) {
- // s, se, sw
- this._currSize.height = this._origSize.height + tmpY;
- }
- if (this._direction.e) {
- // e, ne, se
- this._currSize.width = this._origSize.width + tmpX;
- }
- else if (this._direction.w) {
- // w, nw, sw
- this._currSize.width = this._origSize.width - tmpX;
- this._currPos.x = this._origPos.x + tmpX;
- }
- this.checkBounds();
- this.checkSize();
- this.adjustByRatio();
- this.doResize();
- }
- /**
- * @private
- * @return {?}
- */
- doResize() {
- /** @type {?} */
- const container = this.el.nativeElement;
- if (!this._direction || this._direction.n || this._direction.s || this._aspectRatio) {
- this.renderer.setStyle(container, 'height', this._currSize.height + 'px');
- }
- if (!this._direction || this._direction.w || this._direction.e || this._aspectRatio) {
- this.renderer.setStyle(container, 'width', this._currSize.width + 'px');
- }
- this.renderer.setStyle(container, 'left', this._currPos.x + 'px');
- this.renderer.setStyle(container, 'top', this._currPos.y + 'px');
- }
- /**
- * @private
- * @return {?}
- */
- adjustByRatio() {
- if (this._aspectRatio && !this._adjusted) {
- if (this._direction.e || this._direction.w) {
- /** @type {?} */
- const newHeight = Math.floor(this._currSize.width / this._aspectRatio);
- if (this._direction.n) {
- this._currPos.y += this._currSize.height - newHeight;
- }
- this._currSize.height = newHeight;
- }
- else {
- /** @type {?} */
- const newWidth = Math.floor(this._aspectRatio * this._currSize.height);
- if (this._direction.n) {
- this._currPos.x += this._currSize.width - newWidth;
- }
- this._currSize.width = newWidth;
- }
- }
- }
- /**
- * @private
- * @return {?}
- */
- checkBounds() {
- if (this._containment) {
- /** @type {?} */
- const maxWidth = this._bounding.width - this._bounding.pr - this._bounding.deltaL - this._bounding.translateX - this._currPos.x;
- /** @type {?} */
- const maxHeight = this._bounding.height - this._bounding.pb - this._bounding.deltaT - this._bounding.translateY - this._currPos.y;
- if (this._direction.n && (this._currPos.y + this._bounding.translateY < 0)) {
- this._currPos.y = -this._bounding.translateY;
- this._currSize.height = this._origSize.height + this._origPos.y + this._bounding.translateY;
- }
- if (this._direction.w && (this._currPos.x + this._bounding.translateX) < 0) {
- this._currPos.x = -this._bounding.translateX;
- this._currSize.width = this._origSize.width + this._origPos.x + this._bounding.translateX;
- }
- if (this._currSize.width > maxWidth) {
- this._currSize.width = maxWidth;
- }
- if (this._currSize.height > maxHeight) {
- this._currSize.height = maxHeight;
- }
- /**
- * Fix Issue: Additional check for aspect ratio
- * https://github.com/xieziyu/angular2-draggable/issues/132
- */
- if (this._aspectRatio) {
- this._adjusted = false;
- if ((this._direction.w || this._direction.e) &&
- (this._currSize.width / this._aspectRatio) >= maxHeight) {
- /** @type {?} */
- const newWidth = Math.floor(maxHeight * this._aspectRatio);
- if (this._direction.w) {
- this._currPos.x += this._currSize.width - newWidth;
- }
- this._currSize.width = newWidth;
- this._currSize.height = maxHeight;
- this._adjusted = true;
- }
- if ((this._direction.n || this._direction.s) &&
- (this._currSize.height * this._aspectRatio) >= maxWidth) {
- /** @type {?} */
- const newHeight = Math.floor(maxWidth / this._aspectRatio);
- if (this._direction.n) {
- this._currPos.y += this._currSize.height - newHeight;
- }
- this._currSize.width = maxWidth;
- this._currSize.height = newHeight;
- this._adjusted = true;
- }
- }
- }
- }
- /**
- * @private
- * @return {?}
- */
- checkSize() {
- /** @type {?} */
- const minHeight = !this.rzMinHeight ? 1 : this.rzMinHeight;
- /** @type {?} */
- const minWidth = !this.rzMinWidth ? 1 : this.rzMinWidth;
- if (this._currSize.height < minHeight) {
- this._currSize.height = minHeight;
- if (this._direction.n) {
- this._currPos.y = this._origPos.y + (this._origSize.height - minHeight);
- }
- }
- if (this._currSize.width < minWidth) {
- this._currSize.width = minWidth;
- if (this._direction.w) {
- this._currPos.x = this._origPos.x + (this._origSize.width - minWidth);
- }
- }
- if (this.rzMaxHeight && this._currSize.height > this.rzMaxHeight) {
- this._currSize.height = this.rzMaxHeight;
- if (this._direction.n) {
- this._currPos.y = this._origPos.y + (this._origSize.height - this.rzMaxHeight);
- }
- }
- if (this.rzMaxWidth && this._currSize.width > this.rzMaxWidth) {
- this._currSize.width = this.rzMaxWidth;
- if (this._direction.w) {
- this._currPos.x = this._origPos.x + (this._origSize.width - this.rzMaxWidth);
- }
- }
- }
- /**
- * @private
- * @return {?}
- */
- getBounding() {
- /** @type {?} */
- const el = this._containment;
- /** @type {?} */
- const computed = window.getComputedStyle(el);
- if (computed) {
- /** @type {?} */
- let p = computed.getPropertyValue('position');
- /** @type {?} */
- const nativeEl = window.getComputedStyle(this.el.nativeElement);
- /** @type {?} */
- let transforms = nativeEl.getPropertyValue('transform').replace(/[^-\d,]/g, '').split(',');
- this._bounding = {};
- this._bounding.width = el.clientWidth;
- this._bounding.height = el.clientHeight;
- this._bounding.pr = parseInt(computed.getPropertyValue('padding-right'), 10);
- this._bounding.pb = parseInt(computed.getPropertyValue('padding-bottom'), 10);
- this._bounding.deltaL = this.el.nativeElement.offsetLeft - this._currPos.x;
- this._bounding.deltaT = this.el.nativeElement.offsetTop - this._currPos.y;
- if (transforms.length >= 6) {
- this._bounding.translateX = parseInt(transforms[4], 10);
- this._bounding.translateY = parseInt(transforms[5], 10);
- }
- else {
- this._bounding.translateX = 0;
- this._bounding.translateY = 0;
- }
- this._bounding.position = computed.getPropertyValue('position');
- if (p === 'static') {
- this.renderer.setStyle(el, 'position', 'relative');
- }
- }
- }
- /**
- * @private
- * @return {?}
- */
- resetBounding() {
- if (this._bounding && this._bounding.position === 'static') {
- this.renderer.setStyle(this._containment, 'position', 'relative');
- }
- this._bounding = null;
- }
- /**
- * @private
- * @return {?}
- */
- getGridSize() {
- // set default value:
- this._gridSize = { x: 1, y: 1 };
- if (this.rzGrid) {
- if (typeof this.rzGrid === 'number') {
- this._gridSize = { x: this.rzGrid, y: this.rzGrid };
- }
- else if (Array.isArray(this.rzGrid)) {
- this._gridSize = { x: this.rzGrid[0], y: this.rzGrid[1] };
- }
- }
- }
- }
- AngularResizableDirective.decorators = [
- { type: Directive, args: [{
- selector: '[ngResizable]',
- exportAs: 'ngResizable'
- },] }
- ];
- /** @nocollapse */
- AngularResizableDirective.ctorParameters = () => [
- { type: ElementRef },
- { type: Renderer2 }
- ];
- AngularResizableDirective.propDecorators = {
- ngResizable: [{ type: Input }],
- rzHandles: [{ type: Input }],
- rzAspectRatio: [{ type: Input }],
- rzContainment: [{ type: Input }],
- rzGrid: [{ type: Input }],
- rzMinWidth: [{ type: Input }],
- rzMinHeight: [{ type: Input }],
- rzMaxWidth: [{ type: Input }],
- rzMaxHeight: [{ type: Input }],
- preventDefaultEvent: [{ type: Input }],
- rzStart: [{ type: Output }],
- rzResizing: [{ type: Output }],
- rzStop: [{ type: Output }]
- };
- /**
- * @fileoverview added by tsickle
- * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
- */
- class AngularDraggableModule {
- }
- AngularDraggableModule.decorators = [
- { type: NgModule, args: [{
- imports: [],
- declarations: [
- AngularDraggableDirective,
- AngularResizableDirective
- ],
- exports: [
- AngularDraggableDirective,
- AngularResizableDirective
- ]
- },] }
- ];
- /**
- * @fileoverview added by tsickle
- * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
- */
- /**
- * @fileoverview added by tsickle
- * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
- */
- export { AngularDraggableDirective, AngularResizableDirective, AngularDraggableModule, Position };
- //# sourceMappingURL=angular2-draggable.js.map
|