Skip to content

Commit

Permalink
feat(resizeHandles): add support for nesting resize handles inside th…
Browse files Browse the repository at this point in the history
…e element

Closes #10
  • Loading branch information
Matt Lewis committed Jun 26, 2016
1 parent aa3f75f commit 1af705a
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 63 deletions.
16 changes: 13 additions & 3 deletions demo/demo.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {Component} from '@angular/core';
import {NgStyle} from '@angular/common';
import {Resizable, ResizeEvent} from './../angular2-resizable';
import {Resizable, ResizeEvent, ResizeHandle} from './../angular2-resizable';

@Component({
selector: 'demo-app',
directives: [Resizable, NgStyle],
directives: [Resizable, ResizeHandle, NgStyle],
styles: [`
.rectangle {
position: relative;
Expand All @@ -19,6 +19,12 @@ import {Resizable, ResizeEvent} from './../angular2-resizable';
color: #121621;
margin: auto;
}
.resize-handle {
position: absolute;
bottom: 10px;
right: 10px;
-webkit-user-drag: none;
}
`],
template: `
<div class="text-center">
Expand All @@ -27,9 +33,13 @@ import {Resizable, ResizeEvent} from './../angular2-resizable';
class="rectangle"
[ngStyle]="style"
mwl-resizable
[resizeEdges]="{left: true, right: true, top: true, bottom: true}"
[validateResize]="validate"
(onResizeEnd)="onResizeEnd($event)">
<img
src="http://i.imgur.com/eqzz2dl.gif"
class="resize-handle"
mwl-resize-handle
[resizeEdges]="{bottom: true, right: true}">
</div>
</div>
`
Expand Down
107 changes: 72 additions & 35 deletions src/resizable.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import {
Renderer,
ElementRef,
OnInit,
AfterViewInit,
Output,
Input,
EventEmitter
EventEmitter,
ContentChildren,
QueryList
} from '@angular/core';
import {Subject} from 'rxjs/Subject';
import {Observable} from 'rxjs/Observable';
Expand Down Expand Up @@ -106,20 +109,47 @@ const getResizeCursor: Function = (edges: Edges): string => {
}
};

@Directive({
selector: '[mwl-resize-handle]'
})
export class ResizeHandle {

@Input() resizeEdges: Edges = {};

public resizable: Resizable; // set by the parent mwl-resizable directive

@HostListener('mouseup', ['$event.clientX', '$event.clientY'])
private onMouseup(mouseX: number, mouseY: number): void {
this.resizable.mouseup.next({mouseX, mouseY, edges: this.resizeEdges});
}

@HostListener('mousedown', ['$event.clientX', '$event.clientY'])
private onMousedown(mouseX: number, mouseY: number): void {
this.resizable.mousedown.next({mouseX, mouseY, edges: this.resizeEdges});
}

@HostListener('mousemove', ['$event.clientX', '$event.clientY'])
private onMousemove(mouseX: number, mouseY: number): void {
this.resizable.mousemove.next({mouseX, mouseY, edges: this.resizeEdges});
}

}

@Directive({
selector: '[mwl-resizable]'
})
export class Resizable implements OnInit {
export class Resizable implements OnInit, AfterViewInit {

@Input() validateResize: Function;
@Input() resizeEdges: Edges = {};
@Output() onResizeStart: EventEmitter<Object> = new EventEmitter(false);
@Output() onResize: EventEmitter<Object> = new EventEmitter(false);
@Output() onResizeEnd: EventEmitter<Object> = new EventEmitter(false);
@ContentChildren(ResizeHandle) resizeHandles: QueryList<ResizeHandle>;

private mouseup: Subject<any> = new Subject();
private mousedown: Subject<any> = new Subject();
private mousemove: Subject<any> = new Subject();
public mouseup: Subject<any> = new Subject();
public mousedown: Subject<any> = new Subject();
public mousemove: Subject<any> = new Subject();

constructor(private renderer: Renderer, private elm: ElementRef) {}

Expand Down Expand Up @@ -191,37 +221,38 @@ export class Resizable implements OnInit {

});

this.mousedown.subscribe(({mouseX, mouseY}) => {
const edges: Edges = getResizeEdges({mouseX, mouseY, elm: this.elm, allowedEdges: this.resizeEdges});
if (Object.keys(edges).length > 0) {
if (currentResize) {
resetElementStyles();
}
const startingRect: BoundingRectangle = this.elm.nativeElement.getBoundingClientRect();
currentResize = {
edges,
startingRect,
currentRect: startingRect,
originalStyles: {
position: this.elm.nativeElement.style.position,
left: this.elm.nativeElement.style.left,
top: this.elm.nativeElement.style.top,
width: `${startingRect.width}px`,
height: `${startingRect.height}px`,
'user-drag': this.elm.nativeElement.style['user-drag'],
'-webkit-user-drag': this.elm.nativeElement.style['-webkit-user-drag']
}
};
this.renderer.setElementStyle(this.elm.nativeElement, 'position', 'fixed');
this.renderer.setElementStyle(this.elm.nativeElement, 'left', `${currentResize.startingRect.left}px`);
this.renderer.setElementStyle(this.elm.nativeElement, 'top', `${currentResize.startingRect.top}px`);
this.renderer.setElementStyle(this.elm.nativeElement, 'user-drag', 'none');
this.renderer.setElementStyle(this.elm.nativeElement, '-webkit-user-drag', 'none');
this.onResizeStart.emit({
edges,
rectangle: getNewBoundingRectangle(startingRect, {}, 0, 0)
});
this.mousedown.map(({mouseX, mouseY, edges}) => {
return edges || getResizeEdges({mouseX, mouseY, elm: this.elm, allowedEdges: this.resizeEdges});
}).filter((edges: Edges) => {
return Object.keys(edges).length > 0;
}).subscribe((edges: Edges) => {
if (currentResize) {
resetElementStyles();
}
const startingRect: BoundingRectangle = this.elm.nativeElement.getBoundingClientRect();
currentResize = {
edges,
startingRect,
currentRect: startingRect,
originalStyles: {
position: this.elm.nativeElement.style.position,
left: this.elm.nativeElement.style.left,
top: this.elm.nativeElement.style.top,
width: `${startingRect.width}px`,
height: `${startingRect.height}px`,
'user-drag': this.elm.nativeElement.style['user-drag'],
'-webkit-user-drag': this.elm.nativeElement.style['-webkit-user-drag']
}
};
this.renderer.setElementStyle(this.elm.nativeElement, 'position', 'fixed');
this.renderer.setElementStyle(this.elm.nativeElement, 'left', `${currentResize.startingRect.left}px`);
this.renderer.setElementStyle(this.elm.nativeElement, 'top', `${currentResize.startingRect.top}px`);
this.renderer.setElementStyle(this.elm.nativeElement, 'user-drag', 'none');
this.renderer.setElementStyle(this.elm.nativeElement, '-webkit-user-drag', 'none');
this.onResizeStart.emit({
edges,
rectangle: getNewBoundingRectangle(startingRect, {}, 0, 0)
});
});

this.mouseup.subscribe(() => {
Expand All @@ -237,6 +268,12 @@ export class Resizable implements OnInit {

}

ngAfterViewInit(): void {
this.resizeHandles.forEach((handle: ResizeHandle) => {
handle.resizable = this;
});
}

@HostListener('document:mouseup', ['$event.clientX', '$event.clientY'])
private onMouseup(mouseX: number, mouseY: number): void {
this.mouseup.next({mouseX, mouseY});
Expand Down
Loading

0 comments on commit 1af705a

Please sign in to comment.