mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor(layout): use single style tag for dynamically-created media queries (#10946)
This commit is contained in:
committed by
Joey Perrott
parent
22524e3896
commit
7d2c31efaa
@@ -28,16 +28,24 @@ describe('MediaMatcher', () => {
|
||||
expect(mediaMatcher.matchMedia('(max-width: 1px)').matches).toBeFalsy();
|
||||
});
|
||||
|
||||
it('adds css rules for provided queries when the platform is webkit, otherwise adds nothing.',
|
||||
it('should add CSS rules for provided queries when the platform is webkit',
|
||||
inject([Platform], (platform: Platform) => {
|
||||
let randomWidth = Math.random();
|
||||
expect(document.head.textContent).not.toContain(randomWidth);
|
||||
const randomWidth = `${Math.random()}px`;
|
||||
|
||||
expect(getStyleTagByString(randomWidth)).toBeFalsy();
|
||||
mediaMatcher.matchMedia(`(width: ${randomWidth})`);
|
||||
|
||||
if (platform.WEBKIT) {
|
||||
expect(document.head.textContent).toContain(randomWidth);
|
||||
expect(getStyleTagByString(randomWidth)).toBeTruthy();
|
||||
} else {
|
||||
expect(document.head.textContent).not.toContain(randomWidth);
|
||||
expect(getStyleTagByString(randomWidth)).toBeFalsy();
|
||||
}
|
||||
|
||||
function getStyleTagByString(str: string): HTMLStyleElement | undefined {
|
||||
return Array.from(document.head.querySelectorAll('style')).find(tag => {
|
||||
const rules = tag.sheet ? Array.from((tag.sheet as CSSStyleSheet).cssRules) : [];
|
||||
return !!rules.find(rule => rule.cssText.includes(str));
|
||||
});
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -8,10 +8,11 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {Platform} from '@angular/cdk/platform';
|
||||
|
||||
/**
|
||||
* Global registry for all dynamically-created, injected style tags.
|
||||
*/
|
||||
const styleElementForWebkitCompatibility: Map<string, HTMLStyleElement> = new Map();
|
||||
/** Global registry for all dynamically-created, injected media queries. */
|
||||
const mediaQueriesForWebkitCompatibility: Set<string> = new Set<string>();
|
||||
|
||||
/** Style tag that holds all of the dynamically-created media queries. */
|
||||
let mediaQueryStyleNode: HTMLStyleElement | undefined;
|
||||
|
||||
/** A utility for calling matchMedia queries. */
|
||||
@Injectable({providedIn: 'root'})
|
||||
@@ -42,27 +43,28 @@ export class MediaMatcher {
|
||||
}
|
||||
|
||||
/**
|
||||
* For Webkit engines that only trigger the MediaQueryListListener when there is at least one CSS
|
||||
* selector for the respective media query.
|
||||
* For Webkit engines that only trigger the MediaQueryListListener when
|
||||
* there is at least one CSS selector for the respective media query.
|
||||
*/
|
||||
function createEmptyStyleRule(query: string) {
|
||||
if (!styleElementForWebkitCompatibility.has(query)) {
|
||||
try {
|
||||
const style = document.createElement('style');
|
||||
if (mediaQueriesForWebkitCompatibility.has(query)) {
|
||||
return;
|
||||
}
|
||||
|
||||
style.setAttribute('type', 'text/css');
|
||||
if (!style.sheet) {
|
||||
const cssText = `@media ${query} {.fx-query-test{ }}`;
|
||||
style.appendChild(document.createTextNode(cssText));
|
||||
}
|
||||
|
||||
document.getElementsByTagName('head')[0].appendChild(style);
|
||||
|
||||
// Store in private global registry
|
||||
styleElementForWebkitCompatibility.set(query, style);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
try {
|
||||
if (!mediaQueryStyleNode) {
|
||||
mediaQueryStyleNode = document.createElement('style');
|
||||
mediaQueryStyleNode.setAttribute('type', 'text/css');
|
||||
document.head.appendChild(mediaQueryStyleNode);
|
||||
}
|
||||
|
||||
if (mediaQueryStyleNode.sheet) {
|
||||
(mediaQueryStyleNode.sheet as CSSStyleSheet)
|
||||
.insertRule(`@media ${query} {.fx-query-test{ }}`, 0);
|
||||
mediaQueriesForWebkitCompatibility.add(query);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user