Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 35c9f0d

Browse files
matskoatscott
authored andcommitted
fix(animations): process shorthand margin and padding styles correctly (#35701)
Prior to this patch, the `margin` and `padding` properties were not detected properly by Firefox due to them being shorthand properties. This patch ensures that both `margin` and `padding` are converted read as `top right bottom left` in the event that the shorthand property detection fails for auto-styling in Angular animations. Fix #35463 (FW-1886) PR Close #35701
1 parent d7efc45 commit 35c9f0d

File tree

9 files changed

+100
-16
lines changed

9 files changed

+100
-16
lines changed

‎aio/scripts/_payload-limits.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"master": {
1313
"uncompressed": {
1414
"runtime-es2015": 2987,
15-
"main-es2015": 451469,
15+
"main-es2015": 451552,
1616
"polyfills-es2015": 52195
1717
}
1818
}
@@ -21,7 +21,7 @@
2121
"master": {
2222
"uncompressed": {
2323
"runtime-es2015": 3097,
24-
"main-es2015": 429230,
24+
"main-es2015": 429313,
2525
"polyfills-es2015": 52195
2626
}
2727
}

‎packages/animations/browser/src/render/css_keyframes/css_keyframes_driver.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
*/
88
import {AnimationPlayer, ɵStyleData} from '@angular/animations';
99

10-
import {allowPreviousPlayerStylesMerge, balancePreviousStylesIntoKeyframes, computeStyle} from '../../util';
10+
import {allowPreviousPlayerStylesMerge, balancePreviousStylesIntoKeyframes} from '../../util';
1111
import {AnimationDriver} from '../animation_driver';
12-
import {containsElement, hypenatePropsObject, invokeQuery, matchesElement, validateStyleProperty} from '../shared';
12+
import {computeStyle, containsElement, hypenatePropsObject, invokeQuery, matchesElement, validateStyleProperty} from '../shared';
1313
import {packageNonAnimatableStyles} from '../special_cased_styles';
1414

1515
import {CssKeyframesPlayer} from './css_keyframes_player';
@@ -36,7 +36,7 @@ export class CssKeyframesDriver implements AnimationDriver {
3636
}
3737

3838
computeStyle(element: any, prop: string, defaultValue?: string): string {
39-
return (window.getComputedStyle(element) as any)[prop] as string;
39+
return computeStyle(element, prop);
4040
}
4141

4242
buildKeyframeElement(element: any, name: string, keyframes: {[key: string]: any}[]): any {

‎packages/animations/browser/src/render/css_keyframes/css_keyframes_player.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88
import {AnimationPlayer} from '@angular/animations';
99

10-
import {computeStyle} from '../../util';
10+
import {computeStyle} from '../shared';
1111
import {SpecialCasedStyles} from '../special_cased_styles';
1212
import {ElementAnimationStyleHandler} from './element_animation_style_handler';
1313

‎packages/animations/browser/src/render/shared.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,37 @@ export function hypenatePropsObject(object: {[key: string]: any}): {[key: string
237237
});
238238
return newObj;
239239
}
240+
241+
242+
/**
243+
* Returns the computed style for the provided property on the provided element.
244+
*
245+
* This function uses `window.getComputedStyle` internally to determine the
246+
* style value for the element. Firefox doesn't support reading the shorthand
247+
* forms of margin/padding and for this reason this function needs to account
248+
* for that.
249+
*/
250+
export function computeStyle(element: HTMLElement, prop: string): string {
251+
const gcs = window.getComputedStyle(element);
252+
253+
// this is casted to any because the `CSSStyleDeclaration` type is a fixed
254+
// set of properties and `prop` is a dynamic reference to a property within
255+
// the `CSSStyleDeclaration` list.
256+
let value = gcs[prop as any];
257+
258+
// Firefox returns empty string values for `margin` and `padding` properties
259+
// when extracted using getComputedStyle (see similar issue here:
260+
// https://github.com/jquery/jquery/issues/3383). In this situation
261+
// we want to emulate the value that is returned by creating the top,
262+
// right, bottom and left properties as individual style lookups.
263+
if (value.length === 0 && (prop === 'margin' || prop === 'padding')) {
264+
// reconstruct the padding/margin value as `top right bottom left`
265+
const propTop = (prop + 'Top') as 'marginTop' | 'paddingTop';
266+
const propRight = (prop + 'Right') as 'marginRight' | 'paddingRight';
267+
const propBottom = (prop + 'Bottom') as 'marginBottom' | 'paddingBottom';
268+
const propLeft = (prop + 'Left') as 'marginLeft' | 'paddingLeft';
269+
value = `${gcs[propTop]} ${gcs[propRight]} ${gcs[propBottom]} ${gcs[propLeft]}`;
270+
}
271+
272+
return value;
273+
}

‎packages/animations/browser/src/render/web_animations/web_animations_driver.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {AnimationPlayer, ɵStyleData} from '@angular/animations';
1010
import {allowPreviousPlayerStylesMerge, balancePreviousStylesIntoKeyframes, copyStyles} from '../../util';
1111
import {AnimationDriver} from '../animation_driver';
1212
import {CssKeyframesDriver} from '../css_keyframes/css_keyframes_driver';
13-
import {containsElement, invokeQuery, isBrowser, matchesElement, validateStyleProperty} from '../shared';
13+
import {computeStyle, containsElement, invokeQuery, isBrowser, matchesElement, validateStyleProperty} from '../shared';
1414
import {packageNonAnimatableStyles} from '../special_cased_styles';
1515

1616
import {WebAnimationsPlayer} from './web_animations_player';
@@ -32,7 +32,7 @@ export class WebAnimationsDriver implements AnimationDriver {
3232
}
3333

3434
computeStyle(element: any, prop: string, defaultValue?: string): string {
35-
return (window.getComputedStyle(element) as any)[prop] as string;
35+
return computeStyle(element, prop);
3636
}
3737

3838
overrideWebAnimationsSupport(supported: boolean) { this._isNativeImpl = supported; }

‎packages/animations/browser/src/render/web_animations/web_animations_player.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88
import {AnimationPlayer} from '@angular/animations';
99

10-
import {computeStyle} from '../../util';
10+
import {computeStyle} from '../shared';
1111
import {SpecialCasedStyles} from '../special_cased_styles';
1212

1313
import {DOMAnimation} from './dom_animation';

‎packages/animations/browser/src/util.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88
import {AnimateTimings, AnimationMetadata, AnimationMetadataType, AnimationOptions, sequence, ɵStyleData} from '@angular/animations';
9+
910
import {Ast as AnimationAst, AstVisitor as AnimationAstVisitor} from './dsl/animation_ast';
1011
import {AnimationDslVisitor} from './dsl/animation_dsl_visitor';
11-
import {isNode} from './render/shared';
12+
import {computeStyle, isNode} from './render/shared';
1213

1314
export const ONE_SECOND = 1000;
1415

@@ -340,7 +341,3 @@ export function visitDslNode(visitor: any, node: any, context: any): any {
340341
throw new Error(`Unable to resolve animation metadata node #${node.type}`);
341342
}
342343
}
343-
344-
export function computeStyle(element: any, prop: string): string {
345-
return (<any>window.getComputedStyle(element))[prop];
346-
}

‎packages/animations/browser/test/render/css_keyframes/element_animation_style_handler_spec.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88
import {ElementAnimationStyleHandler} from '../../../src/render/css_keyframes/element_animation_style_handler';
9-
import {computeStyle} from '../../../src/util';
10-
119
import {assertStyle, createElement, makeAnimationEvent, supportsAnimationEventCreation} from './shared';
1210

1311
const EMPTY_FN = () => {};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
import {computeStyle} from '../../src/render/shared';
9+
10+
describe('shared animations code', () => {
11+
if (isNode) return;
12+
13+
describe('computeStyle', () => {
14+
it('should compute the margin style into the form top,right,bottom,left', () => {
15+
const div = buildActualElement();
16+
17+
div.style.setProperty('margin', '1px 2px 3px 4px');
18+
expect(computeStyle(div, 'margin')).toEqual('1px 2px 3px 4px');
19+
20+
div.style.setProperty('margin', '0px');
21+
div.style.setProperty('margin-top', '10px');
22+
div.style.setProperty('margin-right', '20px');
23+
div.style.setProperty('margin-bottom', '30px');
24+
div.style.setProperty('margin-left', '40px');
25+
expect(computeStyle(div, 'margin')).toEqual('10px 20px 30px 40px');
26+
});
27+
28+
it('should compute the padding style into the form top,right,bottom,left', () => {
29+
const div = buildActualElement();
30+
31+
div.style.setProperty('padding', '1px 2px 3px 4px');
32+
expect(computeStyle(div, 'padding')).toEqual('1px 2px 3px 4px');
33+
34+
div.style.setProperty('padding', '0px');
35+
div.style.setProperty('padding-top', '10px');
36+
div.style.setProperty('padding-right', '20px');
37+
div.style.setProperty('padding-bottom', '30px');
38+
div.style.setProperty('padding-left', '40px');
39+
expect(computeStyle(div, 'padding')).toEqual('10px 20px 30px 40px');
40+
});
41+
});
42+
});
43+
44+
/**
45+
* Returns a div element that's attached to the body.
46+
*
47+
* The reason why this function exists is because in order to
48+
* compute style values on an element is must be attached within
49+
* the body of a webpage.
50+
*/
51+
function buildActualElement() {
52+
const div = document.createElement('div');
53+
document.body.appendChild(div);
54+
return div;
55+
}

0 commit comments

Comments
 (0)