Skip to content

Commit 77eaabf

Browse files
author
Oliver Eivak
committed
apply patch ebondu#universal-support (edcarroll/pull/270)
1 parent 348d2e5 commit 77eaabf

File tree

24 files changed

+101
-59
lines changed

24 files changed

+101
-59
lines changed

demo/src/app/components/sidebar/sidebar.component.ts

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import { Component, HostBinding, Output, EventEmitter, HostListener, isDevMode } from "@angular/core";
2-
// Polyfill for IE
3-
import "element-closest";
42

53
interface IAugmentedElement extends Element {
64
closest(selector:string):IAugmentedElement;

package-lock.json

-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
"dependencies": {
5252
"bowser": "^1.7.2",
5353
"date-fns": "2.0.0-alpha.1",
54-
"element-closest": "^2.0.2",
5554
"extend": "^3.0.1",
5655
"is-ua-webview": "^1.0.0",
5756
"popper.js": "^1.14.0",

src/misc/util/helpers/closest.ts

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// element-closest | CC0-1.0 | github.com/jonathantneal/closest
2+
3+
/** @this {Foo} */
4+
if (typeof Element !== "undefined") {
5+
if (typeof Element.prototype.matches !== "function") {
6+
Element.prototype.matches = Element.prototype.msMatchesSelector ||
7+
(Element as any).prototype["mozMatchesSelector"] ||
8+
Element.prototype.webkitMatchesSelector ||
9+
function matches(selector:any):boolean {
10+
const element = this;
11+
const elements = (element.document || element.ownerDocument).querySelectorAll(selector);
12+
let index = 0;
13+
14+
while (elements[index] && elements[index] !== element) {
15+
++index;
16+
}
17+
18+
return Boolean(elements[index]);
19+
};
20+
}
21+
22+
if (typeof Element.prototype["closest"] !== "function") {
23+
Element.prototype["closest"] = function closest(selector:any):any {
24+
let element = this;
25+
26+
while (element && element.nodeType === 1) {
27+
if (element.matches(selector)) {
28+
return element;
29+
}
30+
31+
element = element.parentNode;
32+
}
33+
34+
return undefined;
35+
};
36+
}
37+
}

src/modules/checkbox/components/checkbox.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export class SuiCheckbox implements ICustomValueAccessorHost<boolean> {
6767
}
6868

6969
@HostListener("mousedown", ["$event"])
70-
public onMouseDown(e:MouseEvent):void {
70+
public onMouseDown(e:any):void {
7171
e.preventDefault();
7272
}
7373

src/modules/checkbox/components/radio.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export class SuiRadio<T> implements ICustomValueAccessorHost<T> {
7777
}
7878

7979
@HostListener("mousedown", ["$event"])
80-
public onMouseDown(e:MouseEvent):void {
80+
public onMouseDown(e:any):void {
8181
e.preventDefault();
8282
}
8383

src/modules/datepicker/components/datepicker.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export class SuiDatepicker {
4545
}
4646

4747
@HostListener("mousedown", ["$event"])
48-
public onMouseDown(e:MouseEvent):void {
48+
public onMouseDown(e:any):void {
4949
e.preventDefault();
5050
}
5151
}

src/modules/datepicker/directives/datepicker.directive.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ export class SuiDatepickerDirective
189189
}
190190

191191
@HostListener("keydown", ["$event"])
192-
public onKeyDown(e:KeyboardEvent):void {
192+
public onKeyDown(e:any):void {
193193
if (e.keyCode === KeyCode.Escape) {
194194
this.close();
195195
}

src/modules/datepicker/views/calendar-view.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export abstract class CalendarView implements AfterViewInit, OnDestroy {
5454
this._type = viewType;
5555
this.ranges = ranges;
5656

57-
this._documentKeyDownListener = renderer.listen("document", "keydown", (e:KeyboardEvent) => this.onDocumentKeyDown(e));
57+
this._documentKeyDownListener = renderer.listen("document", "keydown", (e:any) => this.onDocumentKeyDown(e));
5858
}
5959

6060
// Template Methods
@@ -111,7 +111,7 @@ export abstract class CalendarView implements AfterViewInit, OnDestroy {
111111
}
112112
}
113113

114-
private onDocumentKeyDown(e:KeyboardEvent):void {
114+
private onDocumentKeyDown(e:any):void {
115115
if (this._highlightedItem && e.keyCode === KeyCode.Enter) {
116116
this.setDate(this._highlightedItem);
117117
return;

src/modules/dropdown/directives/dropdown-menu.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { Transition, SuiTransition, TransitionController, TransitionDirection }
66
import { HandledEvent, IAugmentedElement, KeyCode } from "../../../misc/util/index";
77
import { DropdownService, DropdownAutoCloseType } from "../services/dropdown.service";
88
// Polyfill for IE
9-
import "element-closest";
9+
import "../../../misc/util/helpers/closest";
1010

1111
@Directive({
1212
// We must attach to every '.item' as Angular doesn't support > selectors.
@@ -144,11 +144,11 @@ export class SuiDropdownMenu extends SuiTransition implements AfterContentInit,
144144
this.menuAutoSelectFirst = false;
145145
this.menuSelectedItemClass = "selected";
146146

147-
this._documentKeyDownListener = renderer.listen("document", "keydown", (e:KeyboardEvent) => this.onDocumentKeyDown(e));
147+
this._documentKeyDownListener = renderer.listen("document", "keydown", (e:any) => this.onDocumentKeyDown(e));
148148
}
149149

150150
@HostListener("click", ["$event"])
151-
public onClick(e:HandledEvent & MouseEvent):void {
151+
public onClick(e:HandledEvent & any):void {
152152
if (!e.eventHandled) {
153153
e.eventHandled = true;
154154

@@ -162,7 +162,7 @@ export class SuiDropdownMenu extends SuiTransition implements AfterContentInit,
162162
}
163163
}
164164

165-
public onDocumentKeyDown(e:KeyboardEvent):void {
165+
public onDocumentKeyDown(e:any):void {
166166
// Only the root dropdown (i.e. not nested dropdowns) is responsible for keeping track of the currently selected item.
167167
if (this._service.isOpen && !this._service.isNested) {
168168
// Stop document events like scrolling while open.

src/modules/dropdown/directives/dropdown.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ export class SuiDropdown implements AfterContentInit {
124124
}
125125

126126
@HostListener("keypress", ["$event"])
127-
public onKeypress(e:HandledEvent & KeyboardEvent):void {
127+
public onKeypress(e:HandledEvent & any):void {
128128
// Block the keyboard event from being fired on parent dropdowns.
129129
if (!e.eventHandled) {
130130

src/modules/modal/components/modal.ts

+15-13
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import { ModalConfig, ModalSize } from "../classes/modal-config";
3232
#modal>
3333
3434
<!-- Configurable close icon -->
35-
<i class="close icon" *ngIf="isClosable" (click)="close()"></i>
35+
<i class="close icon" [hidden]="!isClosable" (click)="close()"></i>
3636
<!-- <ng-content> so that <sui-modal> can be used as a normal component. -->
3737
<ng-content></ng-content>
3838
<!-- @ViewChild reference so we can insert elements beside this div. -->
@@ -270,27 +270,29 @@ export class SuiModal<T, U> implements OnInit, AfterViewInit {
270270

271271
// Decides whether the modal needs to reposition to allow scrolling.
272272
private updateScroll():void {
273-
// Semantic UI modal margin is 3.5rem, which is relative to the global font size, so for compatibility:
274-
const fontSize = parseFloat(window.getComputedStyle(document.documentElement).getPropertyValue("font-size"));
275-
const margin = fontSize * 3.5;
276-
277-
// _mustAlwaysScroll works by stopping _mustScroll from being automatically updated, so it stays `true`.
278-
if (!this._mustAlwaysScroll && this._modalElement) {
279-
const element = this._modalElement.nativeElement as Element;
280-
281-
// The modal must scroll if the window height is smaller than the modal height + both margins.
282-
this._mustScroll = window.innerHeight < element.clientHeight + margin * 2;
273+
if (window) {
274+
// Semantic UI modal margin is 3.5rem, which is relative to the global font size, so for compatibility:
275+
const fontSize = parseFloat(window.getComputedStyle(document.documentElement).getPropertyValue("font-size"));
276+
const margin = fontSize * 3.5;
277+
278+
// _mustAlwaysScroll works by stopping _mustScroll from being automatically updated, so it stays `true`.
279+
if (!this._mustAlwaysScroll && this._modalElement) {
280+
const element = this._modalElement.nativeElement as Element;
281+
282+
// The modal must scroll if the window height is smaller than the modal height + both margins.
283+
this._mustScroll = window.innerHeight < element.clientHeight + margin * 2;
284+
}
283285
}
284286
}
285287

286-
public onClick(e:MouseEvent):void {
288+
public onClick(e:any):void {
287289
// Makes sense here, as the modal shouldn't be attached to any DOM element.
288290
e.stopPropagation();
289291
}
290292

291293
// Document listener is fine here because nobody will enough modals open.
292294
@HostListener("document:keyup", ["$event"])
293-
public onDocumentKeyUp(e:KeyboardEvent):void {
295+
public onDocumentKeyup(e:any):void {
294296
if (e.keyCode === KeyCode.Escape) {
295297
// Close automatically covers case of `!isClosable`, so check not needed.
296298
this.close();

src/modules/popup/classes/popup-controller.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export abstract class SuiPopupController implements IPopup, OnDestroy {
4040
// When the popup is closed (onClose fires on animation complete),
4141
this.popup.onClose.subscribe(() => this.cleanup());
4242

43-
this._documentListener = renderer.listen("document", "click", (e:MouseEvent) => this.onDocumentClick(e));
43+
this._documentListener = renderer.listen("document", "click", (e:any) => this.onDocumentClick(e));
4444
}
4545

4646
public configure(config?:IPopupConfig):void {
@@ -53,8 +53,10 @@ export abstract class SuiPopupController implements IPopup, OnDestroy {
5353
// Cancel the opening timer.
5454
clearTimeout(this._openingTimeout);
5555

56-
// Start the popup opening after the specified delay interval.
57-
this._openingTimeout = window.setTimeout(() => this.open(), this.popup.config.delay);
56+
if (window) {
57+
// Start the popup opening after the specified delay interval.
58+
this._openingTimeout = window.setTimeout(() => this.open(), this.popup.config.delay);
59+
}
5860
}
5961

6062
public open():void {
@@ -141,7 +143,7 @@ export abstract class SuiPopupController implements IPopup, OnDestroy {
141143
}
142144
}
143145

144-
public onDocumentClick(e:MouseEvent):void {
146+
public onDocumentClick(e:any):void {
145147
// If the popup trigger is outside click,
146148
if (this._componentRef && this.popup.config.trigger === PopupTrigger.OutsideClick) {
147149
const target = e.target as Element;

src/modules/popup/components/popup.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ export class SuiPopup implements IPopup {
176176

177177
public close():void {
178178
// Only attempt to close if currently open.
179-
if (this.isOpen) {
179+
if (this.isOpen && window) {
180180
// Cancel all other transitions, and initiate the closing transition.
181181
this.transitionController.stopAll();
182182
this.transitionController.animate(
@@ -193,7 +193,7 @@ export class SuiPopup implements IPopup {
193193
}
194194

195195
@HostListener("click", ["$event"])
196-
public onClick(event:MouseEvent):void {
196+
public onClick(event:any):void {
197197
// Makes sense here, as the popup shouldn't be attached to any DOM element.
198198
event.stopPropagation();
199199
}

src/modules/search/components/search.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ export class SuiSearch<T> implements AfterViewInit, OnDestroy {
202202
this.transition = "scale";
203203
this.transitionDuration = 200;
204204

205-
this._documentClickListener = renderer.listen("document", "click", (e:MouseEvent) => this.onDocumentClick(e));
205+
this._documentClickListener = renderer.listen("document", "click", (e:any) => this.onDocumentClick(e));
206206
}
207207

208208
public ngAfterViewInit():void {
@@ -226,7 +226,7 @@ export class SuiSearch<T> implements AfterViewInit, OnDestroy {
226226
}
227227
}
228228

229-
public onClick(e:MouseEvent):void {
229+
public onClick(e:any):void {
230230
this.open();
231231
}
232232

@@ -251,7 +251,7 @@ export class SuiSearch<T> implements AfterViewInit, OnDestroy {
251251
}
252252
}
253253

254-
public onDocumentClick(e:MouseEvent):void {
254+
public onDocumentClick(e:any):void {
255255
if (!this._element.nativeElement.contains(e.target)) {
256256
this.dropdownService.setOpenState(false);
257257
}

src/modules/search/services/search.service.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,14 @@ export class SearchService<T, U> {
108108
this._query = query;
109109

110110
clearTimeout(this._searchDelayTimeout);
111-
this._searchDelayTimeout = window.setTimeout(
112-
() => {
113-
this.updateQuery(query, callback);
114-
},
115-
this.searchDelay
116-
);
111+
if (window) {
112+
this._searchDelayTimeout = window.setTimeout(
113+
() => {
114+
this.updateQuery(query, callback);
115+
},
116+
this.searchDelay
117+
);
118+
}
117119
}
118120

119121
// Updates the current search query.

src/modules/select/classes/select-base.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ export abstract class SuiSelectBase<T, U> implements AfterContentInit, OnDestroy
243243
this.transitionDuration = 200;
244244

245245
this.onTouched = new EventEmitter<void>();
246-
this._documentKeyDownListener = renderer.listen("document", "keydown", (e:KeyboardEvent) => this.onDocumentKeyDown(e));
246+
this._documentKeyDownListener = renderer.listen("document", "keydown", (e:any) => this.onDocumentKeyDown(e));
247247

248248
this._selectClasses = true;
249249
}
@@ -378,15 +378,15 @@ export abstract class SuiSelectBase<T, U> implements AfterContentInit, OnDestroy
378378
}
379379

380380
@HostListener("keypress", ["$event"])
381-
public onKeyPress(e:KeyboardEvent):void {
381+
public onKeyPress(e:any):void {
382382
if (e.keyCode === KeyCode.Enter) {
383383
// Enables support for focussing and opening with the keyboard alone.
384384
// Using directly because Renderer2 doesn't have invokeElementMethod method anymore.
385385
this._element.nativeElement.click();
386386
}
387387
}
388388

389-
public onDocumentKeyDown(e:KeyboardEvent):void {
389+
public onDocumentKeyDown(e:any):void {
390390
if (this._element.nativeElement.contains(e.target) &&
391391
!this.dropdownService.isOpen &&
392392
e.keyCode === KeyCode.Down) {
@@ -399,7 +399,7 @@ export abstract class SuiSelectBase<T, U> implements AfterContentInit, OnDestroy
399399
}
400400
}
401401

402-
public onQueryInputKeydown(event:KeyboardEvent):void {}
402+
public onQueryInputKeydown(event:any):void {}
403403

404404
protected focus():void {
405405
if (this.isSearchable && this.searchInput) {

src/modules/select/components/multi-select.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ export class SuiMultiSelect<T, U> extends SuiSelectBase<T, U> implements ICustom
229229
}
230230
}
231231

232-
public onQueryInputKeydown(event:KeyboardEvent):void {
232+
public onQueryInputKeydown(event:any):void {
233233
if (event.keyCode === KeyCode.Backspace && this.query === "" && this.selectedOptions.length > 0) {
234234
// Deselect the rightmost option when the user presses backspace in the search input.
235235
this.deselectOption(this.selectedOptions[this.selectedOptions.length - 1]);

src/modules/select/directives/select-search.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ export class SuiSelectSearch {
1515
}
1616

1717
public onQueryUpdated:EventEmitter<string>;
18-
public onQueryKeyDown:EventEmitter<KeyboardEvent>;
18+
public onQueryKeyDown:EventEmitter<any>;
1919

2020
constructor(private _renderer:Renderer2, private _element:ElementRef) {
2121
this.onQueryUpdated = new EventEmitter<string>();
22-
this.onQueryKeyDown = new EventEmitter<KeyboardEvent>();
22+
this.onQueryKeyDown = new EventEmitter<any>();
2323

2424
this._searchClass = true;
2525
this._autoComplete = "off";
@@ -31,7 +31,7 @@ export class SuiSelectSearch {
3131
}
3232

3333
@HostListener("keydown", ["$event"])
34-
private onKeyDown(e:KeyboardEvent):void {
34+
private onKeyDown(e:any):void {
3535
this.onQueryKeyDown.emit(e);
3636
}
3737

src/modules/sidebar/components/sidebar-sibling.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export class SuiSidebarSibling {
6767
}
6868

6969
@HostListener("click", ["$event"])
70-
public onClick(event:MouseEvent):void {
70+
public onClick(event:any):void {
7171
if (this.service.isVisible && !this.service.wasJustOpened) {
7272
this.service.setVisibleState(false);
7373
}

src/modules/sidebar/services/sidebar.service.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ export class SidebarService {
9393

9494
setTimeout(() => this.wasJustOpened = false);
9595
clearTimeout(this._isAnimatingTimeout);
96-
this._isAnimatingTimeout = window.setTimeout(() => this.isAnimating = false, 500);
96+
if (window) {
97+
this._isAnimatingTimeout = window.setTimeout(() => this.isAnimating = false, 500);
98+
}
9799
}
98100
}
99101

0 commit comments

Comments
 (0)