Skip to content

Commit

Permalink
feat(ghostElementPositioning): allow ghost element positioning to be …
Browse files Browse the repository at this point in the history
…configured

* feat(elementAbsolutePosition): using offsetPosition when true

* feat(elementAbsolutePosition): using offsetPosition when true

* feat(elementAbsolutePosition): using offsetPosition when true

* feat(elementAbsolutePosition): add unit-test
  • Loading branch information
Badra00 authored and mattlewis92 committed Mar 16, 2017
1 parent 6f30ab2 commit b77c9fc
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 5 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
.DS_Store
node_modules
coverage

*.iml
28 changes: 26 additions & 2 deletions src/resizable.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,25 @@ function getNewBoundingRectangle(startingRect: BoundingRectangle, edges: Edges,

}

function getElementRect(element: ElementRef, ghostElementPositioning: string): BoundingRectangle {
if (ghostElementPositioning === 'absolute') {
return {
top: element.nativeElement.offsetTop,
bottom: element.nativeElement.offsetHeight + element.nativeElement.offsetTop,
left: element.nativeElement.offsetLeft,
right: element.nativeElement.offsetWidth + element.nativeElement.offsetLeft
};
} else {
const boundingRect: BoundingRectangle = element.nativeElement.getBoundingClientRect();
return {
top: boundingRect.top,
bottom: boundingRect.bottom,
left: boundingRect.left,
right: boundingRect.right
};
}
}

function isWithinBoundingY({mouseY, rect}: {mouseY: number, rect: ClientRect}): boolean {
return mouseY >= rect.top && mouseY <= rect.bottom;
}
Expand Down Expand Up @@ -212,6 +231,11 @@ export class Resizable implements OnInit, OnDestroy, AfterViewInit {
*/
@Input() resizeCursorPrecision: number = 3;

/**
* Define the positioning of the ghost element (can be fixed or absolute)
*/
@Input() ghostElementPositioning: 'fixed' | 'absolute' = 'fixed';

/**
* Called when the mouse is pressed and a resize event is about to begin. `$event` is a `ResizeEvent` object.
*/
Expand Down Expand Up @@ -408,7 +432,7 @@ export class Resizable implements OnInit, OnDestroy, AfterViewInit {
if (currentResize) {
removeGhostElement();
}
const startingRect: BoundingRectangle = this.elm.nativeElement.getBoundingClientRect();
const startingRect: BoundingRectangle = getElementRect(this.elm, this.ghostElementPositioning);
currentResize = {
edges,
startingRect,
Expand All @@ -419,7 +443,7 @@ export class Resizable implements OnInit, OnDestroy, AfterViewInit {
const resizeCursors: ResizeCursors = Object.assign({}, DEFAULT_RESIZE_CURSORS, this.resizeCursors);
this.elm.nativeElement.parentElement.appendChild(currentResize.clonedNode);
this.renderer.setElementStyle(this.elm.nativeElement, 'visibility', 'hidden');
this.renderer.setElementStyle(currentResize.clonedNode, 'position', 'fixed');
this.renderer.setElementStyle(currentResize.clonedNode, 'position', this.ghostElementPositioning);
this.renderer.setElementStyle(currentResize.clonedNode, 'left', `${currentResize.startingRect.left}px`);
this.renderer.setElementStyle(currentResize.clonedNode, 'top', `${currentResize.startingRect.top}px`);
this.renderer.setElementStyle(currentResize.clonedNode, 'height', `${currentResize.startingRect.height}px`);
Expand Down
159 changes: 156 additions & 3 deletions test/resizable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ describe('resizable directive', () => {
[resizeSnapGrid]="resizeSnapGrid"
[resizeCursors]="resizeCursors"
[resizeCursorPrecision]="resizeCursorPrecision"
[ghostElementPositioning]="ghostElementPositioning"
(resizeStart)="resizeStart($event)"
(resizing)="resizing($event)"
(resizeEnd)="resizeEnd($event)">
Expand All @@ -48,7 +49,7 @@ describe('resizable directive', () => {
public resizeSnapGrid: Object = {};
public resizeCursors: Object = {};
public resizeCursorPrecision: number;

public ghostElementPositioning: 'fixed' | 'absolute' = 'fixed';
}

const triggerDomEvent: Function = (eventType: string, target: HTMLElement | Element, eventData: Object = {}) => {
Expand All @@ -65,9 +66,12 @@ describe('resizable directive', () => {
let component: ComponentFixture<TestCmp>, createComponent: Function;
beforeEach(() => {
document.body.style.margin = '0px';
createComponent = (template?: string) => {
createComponent = (template?: string, styles?: Array<string>) => {
if (template) {
TestBed.overrideComponent(TestCmp, {set: {template}});
TestBed.overrideComponent(TestCmp, {set: {template: template}});
}
if (styles) {
TestBed.overrideComponent(TestCmp, {set: {styles: styles}});
}
const fixture: ComponentFixture<TestCmp> = TestBed.createComponent(TestCmp);
fixture.detectChanges();
Expand Down Expand Up @@ -1077,4 +1081,153 @@ describe('resizable directive', () => {

});

describe('absolute positioning', () => {
let domEvents: Array<any>;
beforeEach(() => {
domEvents = [];
});

it('should have the same top/left/height when resize from the right', () => {
domEvents.push({
name: 'mousedown',
data: {
clientX: 600,
clientY: 405
}
});
domEvents.push({
name: 'mousemove',
data: {
clientX: 620,
clientY: 405
},
style: {
top: '200px',
left: '100px',
height: '150px'
}
});
});

it('should have the same top/height when resize from the left', () => {
domEvents.push({
name: 'mousedown',
data: {
clientX: 300,
clientY: 405
}
});
domEvents.push({
name: 'mousemove',
data: {
clientX: 280,
clientY: 405
},
style: {
top: '200px',
height: '150px'
}
});
});

it('should have the same left/width when resize from the top', () => {
domEvents.push({
name: 'mousedown',
data: {
clientX: 400,
clientY: 400
}
});
domEvents.push({
name: 'mousemove',
data: {
clientX: 400,
clientY: 280
},
style: {
left: '100px',
width: '300px'
}
});
});

it('should have the same top/left/width when resize from the bottom', () => {
domEvents.push({
name: 'mousedown',
data: {
clientX: 400,
clientY: 550
}
});
domEvents.push({
name: 'mousemove',
data: {
clientX: 400,
clientY: 570
},
style: {
top: '200px',
left: '100px',
width: '300px',
}
});
});

afterEach(() => {
const template: string = `
<div class="container">
<div
class="rectangle"
[ngStyle]="style"
mwlResizable
[validateResize]="validate"
[resizeEdges]="resizeEdges"
[enableGhostResize]="enableGhostResize"
[resizeSnapGrid]="resizeSnapGrid"
[resizeCursors]="resizeCursors"
[resizeCursorPrecision]="resizeCursorPrecision"
[ghostElementPositioning]="ghostElementPositioning"
(resizeStart)="resizeStart($event)"
(resizing)="resizing($event)"
(resizeEnd)="resizeEnd($event)">
</div>
</div>
`;
const styles: Array<string> = [`
.container {
-webkit-transform: scale3d(1, 1, 1);
position: relative;
top: 200px;
left: 200px;
}
.rectangle {
position: absolute;
top: 200px;
left: 100px;
width: 300px;
height: 150px;
}
`];

const fixture: ComponentFixture<TestCmp> = createComponent(template, styles);
fixture.componentInstance.ghostElementPositioning = 'absolute';
fixture.detectChanges();

const elm: HTMLElement = fixture.componentInstance.resizable.elm.nativeElement;
domEvents.forEach(event => {
triggerDomEvent(event.name, elm, event.data);

const clonedNode: Element = elm.parentElement.children[1];
if (event.name !== 'mouseup') {
expect(clonedNode['style'].position).to.equal('absolute');
}
if (event.style) {
Object.keys(event.style).forEach(styleKey => {
expect(clonedNode['style'][styleKey]).to.equal(event.style[styleKey]);
});
}
});
});
});

});

0 comments on commit b77c9fc

Please sign in to comment.