Skip to content

Commit bd3d826

Browse files
authored
Merge pull request #304 from swiety85/298-element_style-is-undefined-error
Fix: prevent error while dragging widget outside browser window
2 parents 9ecd6ce + 7855b99 commit bd3d826

File tree

2 files changed

+72
-38
lines changed

2 files changed

+72
-38
lines changed

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
{
2-
}
2+
"prettier.printWidth": 100
3+
}

projects/angular2gridster/src/lib/utils/draggable.ts

Lines changed: 70 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export class Draggable {
1616
private cancelAnimationFrame: Function;
1717
private mousemove: Observable<{} | Event> = merge(
1818
fromEvent(document, 'mousemove'),
19-
fromEvent(document, 'touchmove', {passive: false})
19+
fromEvent(document, 'touchmove', { passive: false })
2020
).pipe(share());
2121
private mouseup: Observable<{} | Event> = merge(
2222
fromEvent(document, 'mouseup'),
@@ -48,7 +48,8 @@ export class Draggable {
4848

4949
this.fixProblemWithDnDForIE(element);
5050

51-
this.requestAnimationFrame = window.requestAnimationFrame || (callback => setTimeout(callback, 1000 / 60));
51+
this.requestAnimationFrame =
52+
window.requestAnimationFrame || (callback => setTimeout(callback, 1000 / 60));
5253
this.cancelAnimationFrame = window.cancelAnimationFrame || (cafID => clearTimeout(cafID));
5354
}
5455

@@ -78,16 +79,18 @@ export class Draggable {
7879
);
7980
}
8081

81-
private createDragMoveObservable(dragStart: Observable<DraggableEvent>): Observable<DraggableEvent> {
82+
private createDragMoveObservable(
83+
dragStart: Observable<DraggableEvent>
84+
): Observable<DraggableEvent> {
8285
return dragStart.pipe(
83-
tap((event) => {
86+
tap(event => {
8487
this.addTouchActionNone(event.target);
8588
}),
86-
switchMap((startEvent) => {
89+
switchMap(startEvent => {
8790
return this.mousemove.pipe(
8891
skip(1),
8992
map(mm => new DraggableEvent(mm)),
90-
tap((event) => {
93+
tap(event => {
9194
event.pauseEvent();
9295
startEvent.pauseEvent();
9396
}),
@@ -109,8 +112,10 @@ export class Draggable {
109112
return this.mouseup.pipe(take(1));
110113
}),
111114
map(e => new DraggableEvent(e)),
112-
tap((e) => {
113-
this.removeTouchActionNone(e.target);
115+
tap(e => {
116+
if (e.target) {
117+
this.removeTouchActionNone(e.target);
118+
}
114119
this.autoScrollingInterval.forEach(raf => this.cancelAnimationFrame(raf));
115120
})
116121
);
@@ -128,7 +133,6 @@ export class Draggable {
128133
}
129134

130135
private startScrollForContainer(event: DraggableEvent, scrollContainer: HTMLElement): void {
131-
132136
if (!this.config.scrollDirection || this.config.scrollDirection === 'vertical') {
133137
this.startScrollVerticallyForContainer(event, scrollContainer);
134138
}
@@ -138,28 +142,39 @@ export class Draggable {
138142
}
139143
}
140144

141-
private startScrollVerticallyForContainer(event: DraggableEvent, scrollContainer: HTMLElement): void {
145+
private startScrollVerticallyForContainer(
146+
event: DraggableEvent,
147+
scrollContainer: HTMLElement
148+
): void {
142149
if (event.pageY - this.getOffset(scrollContainer).top < this.config.scrollEdge) {
143150
this.startAutoScrolling(scrollContainer, -Draggable.SCROLL_SPEED, 'scrollTop');
144-
} else if ((this.getOffset(scrollContainer).top + scrollContainer.getBoundingClientRect().height) -
145-
event.pageY < this.config.scrollEdge) {
146-
151+
} else if (
152+
this.getOffset(scrollContainer).top +
153+
scrollContainer.getBoundingClientRect().height -
154+
event.pageY <
155+
this.config.scrollEdge
156+
) {
147157
this.startAutoScrolling(scrollContainer, Draggable.SCROLL_SPEED, 'scrollTop');
148158
}
149159
}
150160

151-
private startScrollHorizontallyForContainer(event: DraggableEvent, scrollContainer: HTMLElement): void {
161+
private startScrollHorizontallyForContainer(
162+
event: DraggableEvent,
163+
scrollContainer: HTMLElement
164+
): void {
152165
if (event.pageX - scrollContainer.getBoundingClientRect().left < this.config.scrollEdge) {
153166
this.startAutoScrolling(scrollContainer, -Draggable.SCROLL_SPEED, 'scrollLeft');
154-
} else if ((this.getOffset(scrollContainer).left + scrollContainer.getBoundingClientRect().width) -
155-
event.pageX < this.config.scrollEdge) {
156-
167+
} else if (
168+
this.getOffset(scrollContainer).left +
169+
scrollContainer.getBoundingClientRect().width -
170+
event.pageX <
171+
this.config.scrollEdge
172+
) {
157173
this.startAutoScrolling(scrollContainer, Draggable.SCROLL_SPEED, 'scrollLeft');
158174
}
159175
}
160176

161177
private startScrollForWindow(event) {
162-
163178
if (!this.config.scrollDirection || this.config.scrollDirection === 'vertical') {
164179
this.startScrollVerticallyForWindow(event);
165180
}
@@ -170,23 +185,31 @@ export class Draggable {
170185
}
171186

172187
private startScrollVerticallyForWindow(event: DraggableEvent): void {
173-
const scrollingElement = document.scrollingElement || document.documentElement || document.body;
188+
const scrollingElement =
189+
document.scrollingElement || document.documentElement || document.body;
174190

175191
// NOTE: Using `window.pageYOffset` here because IE doesn't have `window.scrollY`.
176-
if ((event.pageY - window.pageYOffset) < this.config.scrollEdge) {
192+
if (event.pageY - window.pageYOffset < this.config.scrollEdge) {
177193
this.startAutoScrolling(scrollingElement, -Draggable.SCROLL_SPEED, 'scrollTop');
178-
} else if ((window.innerHeight - (event.pageY - window.pageYOffset)) < this.config.scrollEdge) {
194+
} else if (
195+
window.innerHeight - (event.pageY - window.pageYOffset) <
196+
this.config.scrollEdge
197+
) {
179198
this.startAutoScrolling(scrollingElement, Draggable.SCROLL_SPEED, 'scrollTop');
180199
}
181200
}
182201

183202
private startScrollHorizontallyForWindow(event: DraggableEvent): void {
184-
const scrollingElement = document.scrollingElement || document.documentElement || document.body;
203+
const scrollingElement =
204+
document.scrollingElement || document.documentElement || document.body;
185205

186206
// NOTE: Using `window.pageXOffset` here because IE doesn't have `window.scrollX`.
187-
if ((event.pageX - window.pageXOffset) < this.config.scrollEdge) {
207+
if (event.pageX - window.pageXOffset < this.config.scrollEdge) {
188208
this.startAutoScrolling(scrollingElement, -Draggable.SCROLL_SPEED, 'scrollLeft');
189-
} else if ((window.innerWidth - (event.pageX - window.pageXOffset)) < this.config.scrollEdge) {
209+
} else if (
210+
window.innerWidth - (event.pageX - window.pageXOffset) <
211+
this.config.scrollEdge
212+
) {
190213
this.startAutoScrolling(scrollingElement, Draggable.SCROLL_SPEED, 'scrollLeft');
191214
}
192215
}
@@ -198,30 +221,34 @@ export class Draggable {
198221
return node;
199222
}
200223

201-
if (!(new RegExp('(body|html)', 'i')).test(node.parentNode.tagName)) {
224+
if (!new RegExp('(body|html)', 'i').test(node.parentNode.tagName)) {
202225
return this.getScrollContainer(node.parentNode);
203226
}
204227

205228
return null;
206229
}
207230

208231
private startAutoScrolling(node, amount, direction) {
209-
this.autoScrollingInterval.push(this.requestAnimationFrame(function() {
210-
this.startAutoScrolling(node, amount, direction);
211-
}.bind(this)));
232+
this.autoScrollingInterval.push(
233+
this.requestAnimationFrame(
234+
function() {
235+
this.startAutoScrolling(node, amount, direction);
236+
}.bind(this)
237+
)
238+
);
212239

213-
return node[direction] += (amount * 0.25);
240+
return (node[direction] += amount * 0.25);
214241
}
215242

216-
private getOffset (el) {
243+
private getOffset(el) {
217244
const rect = el.getBoundingClientRect();
218245
return {
219246
left: rect.left + this.getScroll('scrollLeft', 'pageXOffset'),
220247
top: rect.top + this.getScroll('scrollTop', 'pageYOffset')
221248
};
222249
}
223250

224-
private getScroll (scrollProp, offsetProp) {
251+
private getScroll(scrollProp, offsetProp) {
225252
if (typeof window[offsetProp] !== 'undefined') {
226253
return window[offsetProp];
227254
}
@@ -236,17 +263,22 @@ export class Draggable {
236263
return false;
237264
}
238265

239-
return !this.config.handlerClass ||
240-
(this.config.handlerClass && this.hasElementWithClass(this.config.handlerClass, event.target));
266+
return (
267+
!this.config.handlerClass ||
268+
(this.config.handlerClass &&
269+
this.hasElementWithClass(this.config.handlerClass, event.target))
270+
);
241271
}
242272

243273
private isValidDragHandler(targetEl: any): boolean {
244274
return ['input', 'textarea'].indexOf(targetEl.tagName.toLowerCase()) === -1;
245275
}
246276

247277
private inRange(startEvent: DraggableEvent, moveEvent: DraggableEvent, range: number): boolean {
248-
return Math.abs(moveEvent.clientX - startEvent.clientX) > range ||
249-
Math.abs(moveEvent.clientY - startEvent.clientY) > range;
278+
return (
279+
Math.abs(moveEvent.clientX - startEvent.clientX) > range ||
280+
Math.abs(moveEvent.clientY - startEvent.clientY) > range
281+
);
250282
}
251283

252284
private hasElementWithClass(className: string, target: any): boolean {
@@ -285,8 +317,9 @@ export class Draggable {
285317
}
286318

287319
private isTouchDevice() {
288-
return 'ontouchstart' in window // works on most browsers
289-
|| navigator.maxTouchPoints; // works on IE10/11 and Surface
320+
return (
321+
'ontouchstart' in window || navigator.maxTouchPoints // works on most browsers
322+
); // works on IE10/11 and Surface
290323
}
291324

292325
private isIEorEdge() {

0 commit comments

Comments
 (0)