-
Notifications
You must be signed in to change notification settings - Fork 82
/
Copy pathcss-cascade.ts
194 lines (151 loc) · 5.59 KB
/
css-cascade.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/// <reference path="../requirements.ts" />
/// <reference path="css-syntax.ts" />
interface ModuleHub { (file: 'core:css-cascade'): CSSCascade.CSSCascadeModule; }
module CSSCascade {
/**
* Provide helpers to interact with or simulate the css cascading engine.
* This module is almost a necessary requirement for any css polyfill.
*/
export interface CSSCascadeModule extends Object {
/**
* Computes the priority of a CSS Selector given as a string.
*
* @param selector The CSS Selector to analyze; this cannot include multiple selectors separated by a comma.
* @return A positive integer whose value becomes higher with the priority.
*/
computeSelectorPriorityOf(
selector: string
)
: number;
/**
* Finds all rules which match a specific element.
*
* Please note you will rarely need this function as most of this work is done by the library.
* @param element The HTML element the rules will be matched against. We assume it is part of the DOM.
* @return A list of CSS Style Rule which did match the provided element.
*/
findAllMatchingRules(
element: HTMLElement
)
: CSSSyntax.SpecializedTokenList<CSSSyntax.StyleRule>;
/**
* Returns the specified style of a property on the provided element.
*
* The last two parameters will enable optimizations:
* - matchedRules: allow you to mutualize the findAllMatchingRules call
* --- PLEASE NOTE THIS IS OFTEN NOT NECESSARY IF YOU MONITOR THIS PROPERTY
* - stringOnly: allow you to skip tokenization (a fake TokenList will be returned)
* --- THIS WILL RETURN YOU A BUGGY TOKENLIST, BE WISE
*
* @param element The HTML element the rules will be matched against. We assume it is part of the DOM.
* @param cssPropertyName The CSS property whose value will be returned.
* @return A CSS TokenList containing the property value.
*/
getSpecifiedStyle(
element: HTMLElement,
cssPropertyName: string,
matchedRules?: CSSSyntax.SpecializedTokenList<CSSSyntax.StyleRule>,
stringOnly?: boolean
)
: CSSSyntax.TokenList
/**
* Sets up a listener for property changes on an element
*
* NOTE: the event may fire even if the property didn't really change, plan optimizations such as:
* - DETECT NOOP CHANGES (when the final value didn't change as a result)
* - DEBOUNCING UPDATES (you may get many events for an element during on single frame)
*
* @param properties An array of string containing the css properties to monitor
* @param handler An object whose "onupdate" method will be called
*/
startMonitoringProperties(
properties: Array<string>,
handler: OnElementRuleMatchChanged
)
: void
/**
* Polyfills element.myStyle.propertyName and start monitoring a css property
*
* NOTE: it is recommended you use "cssStyle.styleOf(element)" instead of the "element.myStyle" property
* @param cssPropertyName The property to emulate
*
*/
polyfillStyleInterface(
cssPropertyName: string
)
: void
/**
* Load a polyfilled stylesheet via its css text
*
* @param cssText The content of the stylesheet
* @param i The position of the stylesheet in the document (you should leave this undefined)
*/
loadStyleSheet(
cssText: string,
i?: number
)
: void
/**
* Load a polyfilled stylesheet via its html element
*
* @param cssText The content of the stylesheet
* @param i The position of the stylesheet in the document (you should leave this undefined)
*/
loadStyleSheetTag(
element: HTMLElement,
i?: number
)
: void
}
export interface OnElementRuleMatchChanged {
onupdate(element: HTMLElement, rule: CSSSyntax.StyleRule) : void
}
}
interface HTMLElement {
myStyle: CSSStyleDeclaration
}
/////////////////////////////////////////////////////////////////////////
//// EXAMPLES ///////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
/** How do you start monitoring a css property? */
function monitor_some_property() {
var cssCascade = require('core:css-cascade');
cssCascade.startMonitoringProperties(
["-css-grid", "-css-grid-row", "css-grid-col"],
{
onupdate: function(element, rule) {
// TODO: update the layout of "element"
}
}
);
}
/** How do you find out the specified style for a property? */
function obtain_specified_style() {
var cssCascade = require('core:css-cascade');
return cssCascade.getSpecifiedStyle(document.body, 'poly-grid')
}
/** How do you find out the specified style for multiple properties? */
function obtain_specified_styles() {
var cssCascade = require('core:css-cascade');
var rules = cssCascade.findAllMatchingRules(document.body);
var row = cssCascade.getSpecifiedStyle(document.body, 'poly-grid-row', rules);
var col = cssCascade.getSpecifiedStyle(document.body, 'poly-grid-col', rules);
return [row, col];
}
/** How do you polyfill a property style getter/setter? */
function polyfill_property_getters() {
var cssCascade = require('core:css-cascade');
cssCascade.polyfillStyleInterface('poly-grid');
var cssStyle = require('core:css-style').valueOf();
var style = cssStyle.usedStyleOf(document.body);
return style.polyGrid;
}
/** How do you manually choose which stylesheets to polyfill? */
function manually_load_stylesheets() {
// BEFORE LOADING THE POLYFILL:
window['no_auto_stylesheet_detection'] = true;
// AFTER LOADING THE POLYFILL:
var cssCascade = require('core:css-cascade');
cssCascade.loadStyleSheet("* { color: red; }");
cssCascade.loadStyleSheetTag(document.querySelector('style.polyfill').valueOf());
}