From cd2ebd22fd4c9fa4c557b7a132ebbbac900a7a6e Mon Sep 17 00:00:00 2001 From: Adam Plumer Date: Thu, 1 Mar 2018 10:25:34 -0500 Subject: [PATCH] fix(platform-server): add styles to elements correctly (#22527) * Partially reverts #22263 due to lack of total spec compliance on the server * Maintains the camel-case styles fix PR Close #22527 --- packages/core/test/dom/dom_adapter_spec.ts | 9 +++++ .../platform-server/src/domino_adapter.ts | 40 +++++++++++++++++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/packages/core/test/dom/dom_adapter_spec.ts b/packages/core/test/dom/dom_adapter_spec.ts index c2b06accc8..194b192d03 100644 --- a/packages/core/test/dom/dom_adapter_spec.ts +++ b/packages/core/test/dom/dom_adapter_spec.ts @@ -74,6 +74,15 @@ import {el, stringifyElement} from '@angular/platform-browser/testing/src/browse expect(getDOM().getStyle(d, 'background-url')).toBe('url(http://test.com/bg.jpg)'); }); + // Test for regression caused by angular/angular#22536 + it('should parse styles correctly following the spec', () => { + const d = getDOM().createElement('div'); + getDOM().setStyle(d, 'background-image', 'url("paper.gif")'); + expect(d.style.backgroundImage).toBe('url("paper.gif")'); + expect(d.style.getPropertyValue('background-image')).toBe('url("paper.gif")'); + expect(getDOM().getStyle(d, 'background-image')).toBe('url("paper.gif")'); + }); + it('should parse camel-case styles correctly', () => { const d = getDOM().createElement('div'); getDOM().setStyle(d, 'marginRight', '10px'); diff --git a/packages/platform-server/src/domino_adapter.ts b/packages/platform-server/src/domino_adapter.ts index 15d0484b28..737ca6f50b 100644 --- a/packages/platform-server/src/domino_adapter.ts +++ b/packages/platform-server/src/domino_adapter.ts @@ -135,17 +135,51 @@ export class DominoAdapter extends BrowserDomAdapter { return href; } + /** @internal */ + _readStyleAttribute(element: any): {[name: string]: string} { + const styleMap: {[name: string]: string} = {}; + const styleAttribute = element.getAttribute('style'); + if (styleAttribute) { + const styleList = styleAttribute.split(/;+/g); + for (let i = 0; i < styleList.length; i++) { + const style = styleList[i].trim(); + if (style.length > 0) { + const colonIndex = style.indexOf(':'); + if (colonIndex === -1) { + throw new Error(`Invalid CSS style: ${style}`); + } + const name = style.substr(0, colonIndex).trim(); + styleMap[name] = style.substr(colonIndex + 1).trim(); + } + } + } + return styleMap; + } + /** @internal */ + _writeStyleAttribute(element: any, styleMap: {[name: string]: string}) { + let styleAttrValue = ''; + for (const key in styleMap) { + const newValue = styleMap[key]; + if (newValue) { + styleAttrValue += key + ':' + styleMap[key] + ';'; + } + } + element.setAttribute('style', styleAttrValue); + } setStyle(element: any, styleName: string, styleValue?: string|null) { styleName = styleName.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); - element.style[styleName] = styleValue; + const styleMap = this._readStyleAttribute(element); + styleMap[styleName] = styleValue || ''; + this._writeStyleAttribute(element, styleMap); } removeStyle(element: any, styleName: string) { // IE requires '' instead of null // see https://github.com/angular/angular/issues/7916 - element.style[styleName] = ''; + this.setStyle(element, styleName, ''); } getStyle(element: any, styleName: string): string { - return element.style[styleName] || element.style.getPropertyValue(styleName); + const styleMap = this._readStyleAttribute(element); + return styleMap[styleName] || ''; } hasStyle(element: any, styleName: string, styleValue?: string): boolean { const value = this.getStyle(element, styleName);