From 1a7c79746ddcfbdac16b14211d834bce61becfd0 Mon Sep 17 00:00:00 2001 From: Kara Erickson Date: Fri, 30 Aug 2019 11:31:24 -0700 Subject: [PATCH] refactor(core): move misc methods that only have one version from DomAdapter (#32408) PR Close #32408 --- packages/common/src/dom_adapter.ts | 8 -- .../animation/animation_integration_spec.ts | 2 +- packages/core/test/debug/debug_node_spec.ts | 2 +- .../src/browser/browser_adapter.ts | 80 ------------------- .../src/browser/server-transition.ts | 2 +- .../src/browser/testability.ts | 4 +- .../platform-browser/src/browser/title.ts | 4 +- packages/platform-browser/src/dom/debug/by.ts | 12 ++- .../src/dom/events/key_events.ts | 70 +++++++++++++++- .../test/browser/title_spec.ts | 8 +- .../platform-server/src/server_renderer.ts | 2 +- .../src/web_workers/worker/worker_adapter.ts | 6 -- 12 files changed, 92 insertions(+), 108 deletions(-) diff --git a/packages/common/src/dom_adapter.ts b/packages/common/src/dom_adapter.ts index e362b5dc68..8dc07e158f 100644 --- a/packages/common/src/dom_adapter.ts +++ b/packages/common/src/dom_adapter.ts @@ -50,22 +50,14 @@ export abstract class DomAdapter { abstract createHtmlDocument(): HTMLDocument; abstract getDefaultDocument(): Document; - // Used by Title - abstract getTitle(doc: Document): string; - abstract setTitle(doc: Document, newTitle: string): any; - // Used by By.css - abstract elementMatches(n: any, selector: string): boolean; abstract isElementNode(node: any): boolean; // Used by Testability - abstract parentElement(el: any): Node|null; abstract isShadowRoot(node: any): boolean; - abstract getHost(el: any): any; // Used by KeyEventsPlugin abstract onAndCancel(el: any, evt: any, listener: any): Function; - abstract getEventKey(event: any): string; abstract supportsDOMEvents(): boolean; // Used by PlatformLocation and ServerEventManagerPlugin diff --git a/packages/core/test/animation/animation_integration_spec.ts b/packages/core/test/animation/animation_integration_spec.ts index b4bbb3670e..cea2674953 100644 --- a/packages/core/test/animation/animation_integration_spec.ts +++ b/packages/core/test/animation/animation_integration_spec.ts @@ -3743,7 +3743,7 @@ const DEFAULT_COMPONENT_ID = '1'; })(); function assertHasParent(element: any, yes: boolean) { - const parent = getDOM().parentElement(element); + const parent = element.parentNode; if (yes) { expect(parent).toBeTruthy(); } else { diff --git a/packages/core/test/debug/debug_node_spec.ts b/packages/core/test/debug/debug_node_spec.ts index da2f9187d5..78cec8b42d 100644 --- a/packages/core/test/debug/debug_node_spec.ts +++ b/packages/core/test/debug/debug_node_spec.ts @@ -878,7 +878,7 @@ class TestCmptWithPropBindings { fixture = TestBed.createComponent(SimpleContentComp); fixture.detectChanges(); - const parent = getDOM().parentElement(fixture.nativeElement) !; + const parent = fixture.nativeElement.parentElement; const content = fixture.componentInstance.content.nativeElement; // Move the content element outside the component diff --git a/packages/platform-browser/src/browser/browser_adapter.ts b/packages/platform-browser/src/browser/browser_adapter.ts index 00f44b1a2b..54a31a4609 100644 --- a/packages/platform-browser/src/browser/browser_adapter.ts +++ b/packages/platform-browser/src/browser/browser_adapter.ts @@ -11,50 +11,6 @@ import {ɵglobal as global} from '@angular/core'; import {GenericBrowserDomAdapter} from './generic_browser_adapter'; - -const DOM_KEY_LOCATION_NUMPAD = 3; - -// Map to convert some key or keyIdentifier values to what will be returned by getEventKey -const _keyMap: {[k: string]: string} = { - // The following values are here for cross-browser compatibility and to match the W3C standard - // cf http://www.w3.org/TR/DOM-Level-3-Events-key/ - '\b': 'Backspace', - '\t': 'Tab', - '\x7F': 'Delete', - '\x1B': 'Escape', - 'Del': 'Delete', - 'Esc': 'Escape', - 'Left': 'ArrowLeft', - 'Right': 'ArrowRight', - 'Up': 'ArrowUp', - 'Down': 'ArrowDown', - 'Menu': 'ContextMenu', - 'Scroll': 'ScrollLock', - 'Win': 'OS' -}; - -// There is a bug in Chrome for numeric keypad keys: -// https://code.google.com/p/chromium/issues/detail?id=155654 -// 1, 2, 3 ... are reported as A, B, C ... -const _chromeNumKeyPadMap = { - 'A': '1', - 'B': '2', - 'C': '3', - 'D': '4', - 'E': '5', - 'F': '6', - 'G': '7', - 'H': '8', - 'I': '9', - 'J': '*', - 'K': '+', - 'M': '-', - 'N': '.', - 'O': '/', - '\x60': '0', - '\x90': 'NumLock' -}; - const nodeContains: (this: Node, other: Node) => boolean = (() => { if (global['Node']) { return global['Node'].prototype.contains || function(this: Node, node: any) { @@ -102,7 +58,6 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter { return () => { el.removeEventListener(evt, listener, false); }; } dispatchEvent(el: Node, evt: any) { el.dispatchEvent(evt); } - parentElement(el: Node): Node|null { return el.parentNode; } appendChild(el: Node, node: Node) { el.appendChild(node); } remove(node: Node): Node { if (node.parentNode) { @@ -115,7 +70,6 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter { doc = doc || this.getDefaultDocument(); return doc.createElement(tagName); } - getHost(el: HTMLElement): HTMLElement { return (el).host; } getElementsByTagName(element: any, name: string): HTMLElement[] { return element.getElementsByTagName(name); } @@ -129,45 +83,11 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter { return document.implementation.createHTMLDocument('fakeTitle'); } getDefaultDocument(): Document { return document; } - getTitle(doc: Document): string { return doc.title; } - setTitle(doc: Document, newTitle: string) { doc.title = newTitle || ''; } - elementMatches(n: any, selector: string): boolean { - if (this.isElementNode(n)) { - return n.matches && n.matches(selector) || - n.msMatchesSelector && n.msMatchesSelector(selector) || - n.webkitMatchesSelector && n.webkitMatchesSelector(selector); - } - - return false; - } isElementNode(node: Node): boolean { return node.nodeType === Node.ELEMENT_NODE; } isShadowRoot(node: any): boolean { return node instanceof DocumentFragment; } - getEventKey(event: any): string { - let key = event.key; - if (key == null) { - key = event.keyIdentifier; - // keyIdentifier is defined in the old draft of DOM Level 3 Events implemented by Chrome and - // Safari cf - // http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-20071221/events.html#Events-KeyboardEvents-Interfaces - if (key == null) { - return 'Unidentified'; - } - if (key.startsWith('U+')) { - key = String.fromCharCode(parseInt(key.substring(2), 16)); - if (event.location === DOM_KEY_LOCATION_NUMPAD && _chromeNumKeyPadMap.hasOwnProperty(key)) { - // There is a bug in Chrome for numeric keypad keys: - // https://code.google.com/p/chromium/issues/detail?id=155654 - // 1, 2, 3 ... are reported as A, B, C ... - key = (_chromeNumKeyPadMap as any)[key]; - } - } - } - - return _keyMap[key] || key; - } getGlobalEventTarget(doc: Document, target: string): EventTarget|null { if (target === 'window') { return window; diff --git a/packages/platform-browser/src/browser/server-transition.ts b/packages/platform-browser/src/browser/server-transition.ts index 32a94f8102..1277df68fe 100644 --- a/packages/platform-browser/src/browser/server-transition.ts +++ b/packages/platform-browser/src/browser/server-transition.ts @@ -22,7 +22,7 @@ export function appInitializerFactory(transitionId: string, document: any, injec injector.get(ApplicationInitStatus).donePromise.then(() => { const dom = getDOM(); const styles: any[] = - Array.prototype.slice.apply(dom.querySelectorAll(document, `style[ng-transition]`)); + Array.prototype.slice.apply(document.querySelectorAll(`style[ng-transition]`)); styles.filter(el => dom.getAttribute(el, 'ng-transition') === transitionId) .forEach(el => dom.remove(el)); }); diff --git a/packages/platform-browser/src/browser/testability.ts b/packages/platform-browser/src/browser/testability.ts index fcde1bed70..bddcc9700d 100644 --- a/packages/platform-browser/src/browser/testability.ts +++ b/packages/platform-browser/src/browser/testability.ts @@ -59,8 +59,8 @@ export class BrowserGetTestability implements GetTestability { return null; } if (getDOM().isShadowRoot(elem)) { - return this.findTestabilityInTree(registry, getDOM().getHost(elem), true); + return this.findTestabilityInTree(registry, (elem).host, true); } - return this.findTestabilityInTree(registry, getDOM().parentElement(elem), true); + return this.findTestabilityInTree(registry, elem.parentElement, true); } } diff --git a/packages/platform-browser/src/browser/title.ts b/packages/platform-browser/src/browser/title.ts index c78d0339e6..81ec5f2974 100644 --- a/packages/platform-browser/src/browser/title.ts +++ b/packages/platform-browser/src/browser/title.ts @@ -33,11 +33,11 @@ export class Title { /** * Get the title of the current HTML document. */ - getTitle(): string { return getDOM().getTitle(this._doc); } + getTitle(): string { return this._doc.title; } /** * Set the title of the current HTML document. * @param newTitle */ - setTitle(newTitle: string) { getDOM().setTitle(this._doc, newTitle); } + setTitle(newTitle: string) { this._doc.title = newTitle || ''; } } diff --git a/packages/platform-browser/src/dom/debug/by.ts b/packages/platform-browser/src/dom/debug/by.ts index 1c328b90c7..d35e4055f6 100644 --- a/packages/platform-browser/src/dom/debug/by.ts +++ b/packages/platform-browser/src/dom/debug/by.ts @@ -38,7 +38,7 @@ export class By { static css(selector: string): Predicate { return (debugElement) => { return debugElement.nativeElement != null ? - getDOM().elementMatches(debugElement.nativeElement, selector) : + elementMatches(debugElement.nativeElement, selector) : false; }; } @@ -55,3 +55,13 @@ export class By { return (debugNode) => debugNode.providerTokens !.indexOf(type) !== -1; } } + +function elementMatches(n: any, selector: string): boolean { + if (getDOM().isElementNode(n)) { + return n.matches && n.matches(selector) || + n.msMatchesSelector && n.msMatchesSelector(selector) || + n.webkitMatchesSelector && n.webkitMatchesSelector(selector); + } + + return false; +} diff --git a/packages/platform-browser/src/dom/events/key_events.ts b/packages/platform-browser/src/dom/events/key_events.ts index df90c01095..e7516ae591 100644 --- a/packages/platform-browser/src/dom/events/key_events.ts +++ b/packages/platform-browser/src/dom/events/key_events.ts @@ -15,6 +15,50 @@ import {EventManagerPlugin} from './event_manager'; */ const MODIFIER_KEYS = ['alt', 'control', 'meta', 'shift']; +const DOM_KEY_LOCATION_NUMPAD = 3; + +// Map to convert some key or keyIdentifier values to what will be returned by getEventKey +const _keyMap: {[k: string]: string} = { + // The following values are here for cross-browser compatibility and to match the W3C standard + // cf http://www.w3.org/TR/DOM-Level-3-Events-key/ + '\b': 'Backspace', + '\t': 'Tab', + '\x7F': 'Delete', + '\x1B': 'Escape', + 'Del': 'Delete', + 'Esc': 'Escape', + 'Left': 'ArrowLeft', + 'Right': 'ArrowRight', + 'Up': 'ArrowUp', + 'Down': 'ArrowDown', + 'Menu': 'ContextMenu', + 'Scroll': 'ScrollLock', + 'Win': 'OS' +}; + +// There is a bug in Chrome for numeric keypad keys: +// https://code.google.com/p/chromium/issues/detail?id=155654 +// 1, 2, 3 ... are reported as A, B, C ... +const _chromeNumKeyPadMap = { + 'A': '1', + 'B': '2', + 'C': '3', + 'D': '4', + 'E': '5', + 'F': '6', + 'G': '7', + 'H': '8', + 'I': '9', + 'J': '*', + 'K': '+', + 'M': '-', + 'N': '.', + 'O': '/', + '\x60': '0', + '\x90': 'NumLock' +}; + + /** * Retrieves modifiers from key-event objects. */ @@ -96,7 +140,7 @@ export class KeyEventsPlugin extends EventManagerPlugin { static getEventFullKey(event: KeyboardEvent): string { let fullKey = ''; - let key = getDOM().getEventKey(event); + let key = getEventKey(event); key = key.toLowerCase(); if (key === ' ') { key = 'space'; // for readability @@ -141,3 +185,27 @@ export class KeyEventsPlugin extends EventManagerPlugin { } } } + +function getEventKey(event: any): string { + let key = event.key; + if (key == null) { + key = event.keyIdentifier; + // keyIdentifier is defined in the old draft of DOM Level 3 Events implemented by Chrome and + // Safari cf + // http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-20071221/events.html#Events-KeyboardEvents-Interfaces + if (key == null) { + return 'Unidentified'; + } + if (key.startsWith('U+')) { + key = String.fromCharCode(parseInt(key.substring(2), 16)); + if (event.location === DOM_KEY_LOCATION_NUMPAD && _chromeNumKeyPadMap.hasOwnProperty(key)) { + // There is a bug in Chrome for numeric keypad keys: + // https://code.google.com/p/chromium/issues/detail?id=155654 + // 1, 2, 3 ... are reported as A, B, C ... + key = (_chromeNumKeyPadMap as any)[key]; + } + } + } + + return _keyMap[key] || key; +} diff --git a/packages/platform-browser/test/browser/title_spec.ts b/packages/platform-browser/test/browser/title_spec.ts index 617018a2bd..2acd56ac37 100644 --- a/packages/platform-browser/test/browser/title_spec.ts +++ b/packages/platform-browser/test/browser/title_spec.ts @@ -20,24 +20,24 @@ import {expect} from '@angular/platform-browser/testing/src/matchers'; beforeEach(() => { doc = getDOM().createHtmlDocument(); - initialTitle = getDOM().getTitle(doc); + initialTitle = doc.title; titleService = new Title(doc); }); - afterEach(() => { getDOM().setTitle(doc, initialTitle); }); + afterEach(() => { doc.title = initialTitle; }); it('should allow reading initial title', () => { expect(titleService.getTitle()).toEqual(initialTitle); }); it('should set a title on the injected document', () => { titleService.setTitle('test title'); - expect(getDOM().getTitle(doc)).toEqual('test title'); + expect(doc.title).toEqual('test title'); expect(titleService.getTitle()).toEqual('test title'); }); it('should reset title to empty string if title not provided', () => { titleService.setTitle(null !); - expect(getDOM().getTitle(doc)).toEqual(''); + expect(doc.title).toEqual(''); }); }); diff --git a/packages/platform-server/src/server_renderer.ts b/packages/platform-server/src/server_renderer.ts index a9d8147bf3..e097642871 100644 --- a/packages/platform-server/src/server_renderer.ts +++ b/packages/platform-server/src/server_renderer.ts @@ -118,7 +118,7 @@ class DefaultServerRenderer2 implements Renderer2 { return el; } - parentNode(node: any): any { return getDOM().parentElement(node); } + parentNode(node: any): any { return node.parentNode; } nextSibling(node: any): any { return node.nextSibling; } diff --git a/packages/platform-webworker/src/web_workers/worker/worker_adapter.ts b/packages/platform-webworker/src/web_workers/worker/worker_adapter.ts index 4a7bffae8c..db2ea7b9b7 100644 --- a/packages/platform-webworker/src/web_workers/worker/worker_adapter.ts +++ b/packages/platform-webworker/src/web_workers/worker/worker_adapter.ts @@ -47,22 +47,16 @@ export class WorkerDomAdapter extends DomAdapter { querySelectorAll(el: any, selector: string): any[] { throw 'not implemented'; } onAndCancel(el: any, evt: any, listener: any): Function { throw 'not implemented'; } dispatchEvent(el: any, evt: any) { throw 'not implemented'; } - parentElement(el: any): Node { throw 'not implemented'; } appendChild(el: any, node: any) { throw 'not implemented'; } remove(el: any): Node { throw 'not implemented'; } createElement(tagName: any, doc?: any): HTMLElement { throw 'not implemented'; } - getHost(el: any): any { throw 'not implemented'; } getElementsByTagName(element: any, name: string): HTMLElement[] { throw 'not implemented'; } getAttribute(element: any, attribute: string): string { throw 'not implemented'; } setAttribute(element: any, name: string, value: string) { throw 'not implemented'; } createHtmlDocument(): HTMLDocument { throw 'not implemented'; } getDefaultDocument(): Document { throw 'not implemented'; } - getTitle(doc: Document): string { throw 'not implemented'; } - setTitle(doc: Document, newTitle: string) { throw 'not implemented'; } - elementMatches(n: any, selector: string): boolean { throw 'not implemented'; } isElementNode(node: any): boolean { throw 'not implemented'; } isShadowRoot(node: any): boolean { throw 'not implemented'; } - getEventKey(event: any): string { throw 'not implemented'; } supportsDOMEvents(): boolean { throw 'not implemented'; } getGlobalEventTarget(doc: Document, target: string): any { throw 'not implemented'; } getHistory(): History { throw 'not implemented'; }