1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.css;
16
17 import java.io.IOException;
18 import java.io.StringReader;
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.htmlunit.corejs.javascript.Scriptable;
25 import org.htmlunit.css.CssStyleSheet;
26 import org.htmlunit.cssparser.dom.AbstractCSSRuleImpl;
27 import org.htmlunit.cssparser.dom.CSSCharsetRuleImpl;
28 import org.htmlunit.cssparser.dom.CSSRuleListImpl;
29 import org.htmlunit.cssparser.parser.InputSource;
30 import org.htmlunit.javascript.JavaScriptEngine;
31 import org.htmlunit.javascript.configuration.JsxClass;
32 import org.htmlunit.javascript.configuration.JsxConstructor;
33 import org.htmlunit.javascript.configuration.JsxFunction;
34 import org.htmlunit.javascript.configuration.JsxGetter;
35 import org.htmlunit.javascript.host.Window;
36 import org.htmlunit.javascript.host.html.HTMLElement;
37 import org.w3c.dom.DOMException;
38
39
40
41
42
43
44
45
46
47
48
49
50
51 @JsxClass
52 public class CSSStyleSheet extends StyleSheet {
53
54 private static final Log LOG = LogFactory.getLog(CSSStyleSheet.class);
55
56
57 private CssStyleSheet styleSheet_;
58
59
60 private CSSRuleList cssRules_;
61 private List<Integer> cssRulesIndexFix_;
62
63
64
65
66 public CSSStyleSheet() {
67 super(null);
68 styleSheet_ = new CssStyleSheet(null, (InputSource) null, null);
69 }
70
71
72
73
74 @Override
75 @JsxConstructor
76 public void jsConstructor() {
77 super.jsConstructor();
78 styleSheet_ = new CssStyleSheet(null, (InputSource) null, null);
79 }
80
81
82
83
84
85
86
87 public CSSStyleSheet(final HTMLElement element, final InputSource source, final String uri) {
88 super(element);
89
90 setParentScope(element.getWindow());
91 setPrototype(getPrototype(CSSStyleSheet.class));
92
93 styleSheet_ = new CssStyleSheet(element.getDomNodeOrDie(), source, uri);
94 }
95
96
97
98
99
100
101
102 public CSSStyleSheet(final HTMLElement element, final String styleSheet, final String uri) {
103 super(element);
104
105 final Window win = element.getWindow();
106
107 CssStyleSheet css = null;
108 try (InputSource source = new InputSource(new StringReader(styleSheet))) {
109 css = new CssStyleSheet(element.getDomNodeOrDie(), source, uri);
110 }
111 catch (final IOException e) {
112 LOG.error(e.getMessage(), e);
113 }
114
115 setParentScope(win);
116 setPrototype(getPrototype(CSSStyleSheet.class));
117
118 styleSheet_ = css;
119 }
120
121
122
123
124
125
126
127 public CSSStyleSheet(final HTMLElement element, final Scriptable parentScope,
128 final CssStyleSheet cssStyleSheet) {
129 super(element);
130
131 setParentScope(parentScope);
132 setPrototype(getPrototype(CSSStyleSheet.class));
133 styleSheet_ = cssStyleSheet;
134 }
135
136
137
138
139
140 public CssStyleSheet getCssStyleSheet() {
141 return styleSheet_;
142 }
143
144
145
146
147
148 @JsxGetter
149 public CSSRuleList getRules() {
150 return getCssRules();
151 }
152
153
154
155
156
157 @JsxGetter
158 public CSSRuleList getCssRules() {
159 initCssRules();
160 return cssRules_;
161 }
162
163
164
165
166
167
168
169
170 @JsxFunction
171 public int insertRule(final String rule, final int position) {
172 try {
173 initCssRules();
174 getCssStyleSheet().getWrappedSheet().insertRule(rule, fixIndex(position));
175 refreshCssRules();
176 return position;
177 }
178 catch (final DOMException e) {
179
180 final int pos = rule.indexOf('{');
181 if (pos > -1) {
182 final String newRule = rule.substring(0, pos) + "{}";
183 try {
184 getCssStyleSheet().getWrappedSheet().insertRule(newRule, fixIndex(position));
185 refreshCssRules();
186 return position;
187 }
188 catch (final DOMException ex) {
189 throw JavaScriptEngine.asJavaScriptException(getWindow(), ex.getMessage(), ex.code);
190 }
191 }
192 throw JavaScriptEngine.asJavaScriptException(getWindow(), e.getMessage(), e.code);
193 }
194 }
195
196 private void refreshCssRules() {
197 if (cssRules_ == null) {
198 return;
199 }
200
201 cssRules_.clearRules();
202 cssRulesIndexFix_.clear();
203
204 final CSSRuleListImpl ruleList = getCssStyleSheet().getWrappedSheet().getCssRules();
205 final List<AbstractCSSRuleImpl> rules = ruleList.getRules();
206 int pos = 0;
207 for (final AbstractCSSRuleImpl rule : rules) {
208 if (rule instanceof CSSCharsetRuleImpl) {
209 cssRulesIndexFix_.add(pos);
210 continue;
211 }
212
213 final CSSRule cssRule = CSSRule.create(this, rule);
214 if (null == cssRule) {
215 cssRulesIndexFix_.add(pos);
216 }
217 else {
218 cssRules_.addRule(cssRule);
219 }
220 pos++;
221 }
222
223
224 getCssStyleSheet().getWrappedSheet().resetRuleIndex();
225 }
226
227 private int fixIndex(int index) {
228 for (final int fix : cssRulesIndexFix_) {
229 if (fix > index) {
230 return index;
231 }
232 index++;
233 }
234 return index;
235 }
236
237
238
239
240
241
242 @JsxFunction
243 public void deleteRule(final int position) {
244 try {
245 initCssRules();
246 getCssStyleSheet().getWrappedSheet().deleteRule(fixIndex(position));
247 refreshCssRules();
248 }
249 catch (final DOMException e) {
250 throw JavaScriptEngine.asJavaScriptException(getWindow(), e.getMessage(), e.code);
251 }
252 }
253
254
255
256
257
258
259
260
261 @JsxFunction
262 public int addRule(final String selector, final String rule) {
263 String completeRule = selector + " {" + rule + "}";
264 try {
265 initCssRules();
266 getCssStyleSheet().getWrappedSheet().insertRule(completeRule,
267 getCssStyleSheet().getWrappedSheet().getCssRules().getLength());
268 refreshCssRules();
269 }
270 catch (final DOMException e) {
271
272 completeRule = selector + " {}";
273 try {
274 getCssStyleSheet().getWrappedSheet().insertRule(completeRule,
275 getCssStyleSheet().getWrappedSheet().getCssRules().getLength());
276 refreshCssRules();
277 }
278 catch (final DOMException ex) {
279 throw JavaScriptEngine.asJavaScriptException(getWindow(), ex.getMessage(), ex.code);
280 }
281 }
282 return -1;
283 }
284
285
286
287
288
289
290 @JsxFunction
291 public void removeRule(final int position) {
292 try {
293 initCssRules();
294 getCssStyleSheet().getWrappedSheet().deleteRule(fixIndex(position));
295 refreshCssRules();
296 }
297 catch (final DOMException e) {
298 throw JavaScriptEngine.throwAsScriptRuntimeEx(e);
299 }
300 }
301
302
303
304
305
306
307 @Override
308 public String getUri() {
309 return getCssStyleSheet().getUri();
310 }
311
312 private void initCssRules() {
313 if (cssRules_ == null) {
314 cssRules_ = new CSSRuleList(this);
315 cssRulesIndexFix_ = new ArrayList<>();
316 refreshCssRules();
317 }
318 }
319 }