1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.css;
16
17 import static org.htmlunit.BrowserVersionFeatures.CSS_BACKGROUND_INITIAL;
18 import static org.htmlunit.BrowserVersionFeatures.JS_STYLE_LETTER_SPACING_ACCEPTS_PERCENT;
19 import static org.htmlunit.BrowserVersionFeatures.JS_STYLE_WORD_SPACING_ACCEPTS_PERCENT;
20 import static org.htmlunit.css.CssStyleSheet.ABSOLUTE;
21 import static org.htmlunit.css.CssStyleSheet.AUTO;
22 import static org.htmlunit.css.CssStyleSheet.FIXED;
23 import static org.htmlunit.css.CssStyleSheet.INHERIT;
24 import static org.htmlunit.css.CssStyleSheet.INITIAL;
25 import static org.htmlunit.css.CssStyleSheet.RELATIVE;
26 import static org.htmlunit.css.CssStyleSheet.STATIC;
27 import static org.htmlunit.javascript.configuration.SupportedBrowser.CHROME;
28 import static org.htmlunit.javascript.configuration.SupportedBrowser.EDGE;
29
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.Collections;
33 import java.util.HashSet;
34 import java.util.LinkedHashMap;
35 import java.util.List;
36 import java.util.Locale;
37 import java.util.Map;
38 import java.util.Set;
39
40 import org.apache.commons.lang3.ArrayUtils;
41 import org.apache.commons.lang3.StringUtils;
42 import org.htmlunit.BrowserVersion;
43 import org.htmlunit.corejs.javascript.Scriptable;
44 import org.htmlunit.corejs.javascript.ScriptableObject;
45 import org.htmlunit.css.AbstractCssStyleDeclaration;
46 import org.htmlunit.css.StyleAttributes;
47 import org.htmlunit.css.StyleAttributes.Definition;
48 import org.htmlunit.css.StyleElement;
49 import org.htmlunit.css.WrappedCssStyleDeclaration;
50 import org.htmlunit.cssparser.dom.AbstractCSSRuleImpl;
51 import org.htmlunit.cssparser.dom.DOMExceptionImpl;
52 import org.htmlunit.javascript.HtmlUnitScriptable;
53 import org.htmlunit.javascript.JavaScriptEngine;
54 import org.htmlunit.javascript.configuration.JsxClass;
55 import org.htmlunit.javascript.configuration.JsxConstructor;
56 import org.htmlunit.javascript.configuration.JsxFunction;
57 import org.htmlunit.javascript.configuration.JsxGetter;
58 import org.htmlunit.javascript.configuration.JsxSetter;
59 import org.htmlunit.javascript.configuration.JsxSymbol;
60 import org.htmlunit.javascript.host.Element;
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 @JsxClass
78 public class CSSStyleDeclaration extends HtmlUnitScriptable {
79
80 private static final Set<String> LENGTH_PROPERTIES_FFFF = new HashSet<>(Arrays.asList(
81 Definition.BORDER_TOP_WIDTH.getAttributeName(),
82 Definition.BORDER_LEFT_WIDTH.getAttributeName(),
83 Definition.BORDER_BOTTOM_WIDTH.getAttributeName(),
84 Definition.BORDER_RIGHT_WIDTH.getAttributeName()));
85
86 private static final Set<String> LENGTH_PROPERTIES_TTFF = new HashSet<>(Arrays.asList(
87 Definition.HEIGHT.getAttributeName(),
88 Definition.WIDTH.getAttributeName(),
89 Definition.TOP.getAttributeName(),
90 Definition.LEFT.getAttributeName(),
91 Definition.BOTTOM.getAttributeName(),
92 Definition.RIGHT.getAttributeName(),
93 Definition.MARGIN_TOP.getAttributeName(),
94 Definition.MARGIN_LEFT.getAttributeName(),
95 Definition.MARGIN_BOTTOM.getAttributeName(),
96 Definition.MARGIN_RIGHT.getAttributeName(),
97 Definition.MIN_HEIGHT.getAttributeName(),
98 Definition.MIN_WIDTH.getAttributeName()
99 ));
100
101 private static final Set<String> LENGTH_PROPERTIES_FTFF = new HashSet<>(Arrays.asList(
102 Definition.FONT_SIZE.getAttributeName(),
103 Definition.TEXT_INDENT.getAttributeName(),
104 Definition.PADDING_TOP.getAttributeName(),
105 Definition.PADDING_LEFT.getAttributeName(),
106 Definition.PADDING_BOTTOM.getAttributeName(),
107 Definition.PADDING_RIGHT.getAttributeName(),
108 Definition.MAX_HEIGHT.getAttributeName(),
109 Definition.MAX_WIDTH.getAttributeName()
110 ));
111
112 private static final String[] THIN_MED_THICK = {"thin", "medium", "thick"};
113 private static final String[] ALIGN_KEYWORDS =
114 {"baseline", "sub", "super", "text-top", "text-bottom", "middle", "top", "bottom",
115 "inherit", "initial", "revert", "unset"};
116 private static final String[] FONT_SIZES =
117 {"xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "xxx-large",
118 "smaller", "larger"};
119
120
121
122
123 private AbstractCssStyleDeclaration styleDeclaration_;
124
125
126
127
128 public CSSStyleDeclaration() {
129 super();
130 }
131
132
133
134
135
136
137
138 @JsxConstructor
139 public void jsConstructor(final String type, final ScriptableObject details) {
140 throw JavaScriptEngine.typeError("CSSStyleDeclaration ctor is not available");
141 }
142
143
144
145
146
147
148 public CSSStyleDeclaration(final Element element, final AbstractCssStyleDeclaration styleDeclaration) {
149 super();
150 setParentScope(element.getParentScope());
151 setPrototype(getPrototype(getClass()));
152
153 setDomNode(element.getDomNodeOrNull(), false);
154
155 if (styleDeclaration == null) {
156 throw new IllegalStateException("styleDeclaration can't be null");
157 }
158 styleDeclaration_ = styleDeclaration;
159 }
160
161
162
163
164
165
166 CSSStyleDeclaration(final CSSStyleSheet parentStyleSheet, final WrappedCssStyleDeclaration styleDeclaration) {
167 super();
168 setParentScope(parentStyleSheet);
169 setPrototype(getPrototype(getClass()));
170
171 if (styleDeclaration == null) {
172 throw new IllegalStateException("styleDeclaration can't be null");
173 }
174 styleDeclaration_ = styleDeclaration;
175 }
176
177 protected AbstractCssStyleDeclaration getCssStyleDeclaration() {
178 return styleDeclaration_;
179 }
180
181
182
183
184
185
186
187 protected String getStylePriority(final String name) {
188 return styleDeclaration_.getStylePriority(name);
189 }
190
191
192
193
194
195
196 protected void setStyleAttribute(final String name, final String newValue) {
197 setStyleAttribute(name, newValue, "");
198 }
199
200
201
202
203
204
205
206 protected void setStyleAttribute(final String name, String newValue, final String important) {
207 if (null == newValue || "null".equals(newValue)) {
208 newValue = "";
209 }
210
211 styleDeclaration_.setStyleAttribute(name, newValue, important);
212 }
213
214
215
216
217
218 private String removeStyleAttribute(final String name) {
219 if (styleDeclaration_ == null) {
220 return null;
221 }
222 return styleDeclaration_.removeStyleAttribute(name);
223 }
224
225
226
227
228
229
230
231 private Map<String, StyleElement> getStyleMap() {
232 if (styleDeclaration_ == null) {
233 return Collections.emptyMap();
234 }
235 return styleDeclaration_.getStyleMap();
236 }
237
238
239
240
241
242 @JsxGetter
243 public String getBackgroundAttachment() {
244 if (styleDeclaration_ == null) {
245 return null;
246 }
247 return styleDeclaration_.getBackgroundAttachment();
248 }
249
250
251
252
253
254 @JsxSetter
255 public void setBackgroundAttachment(final String backgroundAttachment) {
256 setStyleAttribute(Definition.BACKGROUND_ATTACHMENT.getAttributeName(), backgroundAttachment);
257 }
258
259
260
261
262
263 @JsxGetter
264 public String getBackgroundColor() {
265 if (styleDeclaration_ == null) {
266 return null;
267 }
268 return styleDeclaration_.getBackgroundColor();
269 }
270
271
272
273
274
275 @JsxSetter
276 public void setBackgroundColor(final String backgroundColor) {
277 setStyleAttribute(Definition.BACKGROUND_COLOR.getAttributeName(), backgroundColor);
278 }
279
280
281
282
283
284 @JsxGetter
285 public String getBackgroundImage() {
286 if (styleDeclaration_ == null) {
287 return null;
288 }
289 return styleDeclaration_.getBackgroundImage();
290 }
291
292
293
294
295
296 @JsxSetter
297 public void setBackgroundImage(final String backgroundImage) {
298 setStyleAttribute(Definition.BACKGROUND_IMAGE.getAttributeName(), backgroundImage);
299 }
300
301
302
303
304
305 @JsxGetter
306 public String getBackgroundPosition() {
307 if (styleDeclaration_ == null) {
308 return null;
309 }
310 return styleDeclaration_.getBackgroundPosition();
311 }
312
313
314
315
316
317 @JsxSetter
318 public void setBackgroundPosition(final String backgroundPosition) {
319 setStyleAttribute(Definition.BACKGROUND_POSITION.getAttributeName(), backgroundPosition);
320 }
321
322
323
324
325
326 @JsxGetter
327 public String getBackgroundRepeat() {
328 if (styleDeclaration_ == null) {
329 return null;
330 }
331 return styleDeclaration_.getBackgroundRepeat();
332 }
333
334
335
336
337
338 @JsxSetter
339 public void setBackgroundRepeat(final String backgroundRepeat) {
340 setStyleAttribute(Definition.BACKGROUND_REPEAT.getAttributeName(), backgroundRepeat);
341 }
342
343
344
345
346
347 @JsxGetter
348 public String getBlockSize() {
349 if (styleDeclaration_ == null) {
350 return null;
351 }
352 return styleDeclaration_.getBlockSize();
353 }
354
355
356
357
358
359 @JsxSetter
360 public void setBlockSize(final String blockSize) {
361 setStyleAttribute(Definition.BLOCK_SIZE.getAttributeName(), blockSize);
362 }
363
364
365
366
367
368 @JsxGetter
369 public String getBorderBottomColor() {
370 if (styleDeclaration_ == null) {
371 return null;
372 }
373 return styleDeclaration_.getBorderBottomColor();
374 }
375
376
377
378
379
380 @JsxSetter
381 public void setBorderBottomColor(final String borderBottomColor) {
382 setStyleAttribute(Definition.BORDER_BOTTOM_COLOR.getAttributeName(), borderBottomColor);
383 }
384
385
386
387
388
389 @JsxGetter
390 public String getBorderBottomStyle() {
391 if (styleDeclaration_ == null) {
392 return null;
393 }
394 return styleDeclaration_.getBorderBottomStyle();
395 }
396
397
398
399
400
401 @JsxSetter
402 public void setBorderBottomStyle(final String borderBottomStyle) {
403 setStyleAttribute(Definition.BORDER_BOTTOM_STYLE.getAttributeName(), borderBottomStyle);
404 }
405
406
407
408
409
410 @JsxGetter
411 public String getBorderBottomWidth() {
412 if (styleDeclaration_ == null) {
413 return null;
414 }
415 return styleDeclaration_.getBorderBottomWidth();
416 }
417
418
419
420
421
422 @JsxSetter
423 public void setBorderBottomWidth(final Object borderBottomWidth) {
424 setStyleLengthAttribute(Definition.BORDER_BOTTOM_WIDTH.getAttributeName(), borderBottomWidth, "",
425 false, false, null);
426 }
427
428
429
430
431
432 @JsxGetter
433 public String getBorderLeftColor() {
434 if (styleDeclaration_ == null) {
435 return null;
436 }
437 return styleDeclaration_.getBorderLeftColor();
438 }
439
440
441
442
443
444 @JsxSetter
445 public void setBorderLeftColor(final String borderLeftColor) {
446 setStyleAttribute(Definition.BORDER_LEFT_COLOR.getAttributeName(), borderLeftColor);
447 }
448
449
450
451
452
453 @JsxGetter
454 public String getBorderLeftStyle() {
455 if (styleDeclaration_ == null) {
456 return null;
457 }
458 return styleDeclaration_.getBorderLeftStyle();
459 }
460
461
462
463
464
465 @JsxSetter
466 public void setBorderLeftStyle(final String borderLeftStyle) {
467 setStyleAttribute(Definition.BORDER_LEFT_STYLE.getAttributeName(), borderLeftStyle);
468 }
469
470
471
472
473
474 @JsxGetter
475 public String getBorderLeftWidth() {
476 if (styleDeclaration_ == null) {
477 return null;
478 }
479 return styleDeclaration_.getBorderLeftWidth();
480 }
481
482
483
484
485
486 @JsxSetter
487 public void setBorderLeftWidth(final Object borderLeftWidth) {
488 setStyleLengthAttribute(Definition.BORDER_LEFT_WIDTH.getAttributeName(), borderLeftWidth, "",
489 false, false, null);
490 }
491
492
493
494
495
496 @JsxGetter
497 public String getBorderRightColor() {
498 if (styleDeclaration_ == null) {
499 return null;
500 }
501 return styleDeclaration_.getBorderRightColor();
502 }
503
504
505
506
507
508 @JsxSetter
509 public void setBorderRightColor(final String borderRightColor) {
510 setStyleAttribute(Definition.BORDER_RIGHT_COLOR.getAttributeName(), borderRightColor);
511 }
512
513
514
515
516
517 @JsxGetter
518 public String getBorderRightStyle() {
519 if (styleDeclaration_ == null) {
520 return null;
521 }
522 return styleDeclaration_.getBorderRightStyle();
523 }
524
525
526
527
528
529 @JsxSetter
530 public void setBorderRightStyle(final String borderRightStyle) {
531 setStyleAttribute(Definition.BORDER_RIGHT_STYLE.getAttributeName(), borderRightStyle);
532 }
533
534
535
536
537
538 @JsxGetter
539 public String getBorderRightWidth() {
540 if (styleDeclaration_ == null) {
541 return null;
542 }
543 return styleDeclaration_.getBorderRightWidth();
544 }
545
546
547
548
549
550 @JsxSetter
551 public void setBorderRightWidth(final Object borderRightWidth) {
552 setStyleLengthAttribute(Definition.BORDER_RIGHT_WIDTH.getAttributeName(), borderRightWidth, "",
553 false, false, null);
554 }
555
556
557
558
559
560 @JsxGetter
561 public String getBorderTop() {
562 if (styleDeclaration_ == null) {
563 return null;
564 }
565 return styleDeclaration_.getBorderTop();
566 }
567
568
569
570
571
572 @JsxSetter
573 public void setBorderTop(final String borderTop) {
574 setStyleAttribute(Definition.BORDER_TOP.getAttributeName(), borderTop);
575 }
576
577
578
579
580
581 @JsxGetter
582 public String getBorderTopColor() {
583 if (styleDeclaration_ == null) {
584 return null;
585 }
586 return styleDeclaration_.getBorderTopColor();
587 }
588
589
590
591
592
593 @JsxSetter
594 public void setBorderTopColor(final String borderTopColor) {
595 setStyleAttribute(Definition.BORDER_TOP_COLOR.getAttributeName(), borderTopColor);
596 }
597
598
599
600
601
602 @JsxGetter
603 public String getBorderTopStyle() {
604 if (styleDeclaration_ == null) {
605 return null;
606 }
607 return styleDeclaration_.getBorderTopStyle();
608 }
609
610
611
612
613
614 @JsxSetter
615 public void setBorderTopStyle(final String borderTopStyle) {
616 setStyleAttribute(Definition.BORDER_TOP_STYLE.getAttributeName(), borderTopStyle);
617 }
618
619
620
621
622
623 @JsxGetter
624 public String getBorderTopWidth() {
625 if (styleDeclaration_ == null) {
626 return null;
627 }
628 return styleDeclaration_.getBorderTopWidth();
629 }
630
631
632
633
634
635 @JsxSetter
636 public void setBorderTopWidth(final Object borderTopWidth) {
637 setStyleLengthAttribute(Definition.BORDER_TOP_WIDTH.getAttributeName(), borderTopWidth, "",
638 false, false, null);
639 }
640
641
642
643
644
645 @JsxGetter
646 public String getBottom() {
647 if (styleDeclaration_ == null) {
648 return null;
649 }
650 return styleDeclaration_.getBottom();
651 }
652
653
654
655
656
657 @JsxSetter
658 public void setBottom(final Object bottom) {
659 setStyleLengthAttribute(Definition.BOTTOM.getAttributeName(), bottom, "", true, true, null);
660 }
661
662
663
664
665
666 @JsxGetter
667 public String getColor() {
668 if (styleDeclaration_ == null) {
669 return null;
670 }
671 return styleDeclaration_.getColor();
672 }
673
674
675
676
677
678 @JsxSetter
679 public void setColor(final String color) {
680 setStyleAttribute(Definition.COLOR.getAttributeName(), color);
681 }
682
683
684
685
686
687 @JsxGetter
688 public String getCssFloat() {
689 if (styleDeclaration_ == null) {
690 return null;
691 }
692 return styleDeclaration_.getCssFloat();
693 }
694
695
696
697
698
699 @JsxSetter
700 public void setCssFloat(final String value) {
701 setStyleAttribute(Definition.FLOAT.getAttributeName(), value);
702 }
703
704
705
706
707
708 @JsxGetter
709 public String getCssText() {
710 if (styleDeclaration_ == null) {
711 return null;
712 }
713 return styleDeclaration_.getCssText();
714 }
715
716
717
718
719
720 @JsxSetter
721 public void setCssText(final String value) {
722 String fixedValue = value;
723 if (fixedValue == null || "null".equals(fixedValue)) {
724 fixedValue = "";
725 }
726
727 try {
728 styleDeclaration_.setCssText(fixedValue);
729 }
730 catch (final DOMExceptionImpl e) {
731
732 styleDeclaration_.setCssText("");
733 }
734 }
735
736
737
738
739
740 @JsxGetter
741 public String getDisplay() {
742 if (styleDeclaration_ == null) {
743 return null;
744 }
745 return styleDeclaration_.getDisplay();
746 }
747
748
749
750
751
752 @JsxSetter
753 public void setDisplay(final String display) {
754 setStyleAttribute(Definition.DISPLAY.getAttributeName(), display);
755 }
756
757
758
759
760
761 @JsxGetter
762 public String getFontSize() {
763 if (styleDeclaration_ == null) {
764 return null;
765 }
766 return styleDeclaration_.getFontSize();
767 }
768
769
770
771
772
773 @JsxSetter
774 public void setFontSize(final Object fontSize) {
775 setStyleLengthAttribute(Definition.FONT_SIZE.getAttributeName(), fontSize, "", false, true, FONT_SIZES);
776 updateFont(getFont(), false);
777 }
778
779
780
781
782
783 @JsxGetter
784 public String getLineHeight() {
785 if (styleDeclaration_ == null) {
786 return null;
787 }
788 return styleDeclaration_.getLineHeight();
789 }
790
791
792
793
794
795 @JsxSetter
796 public void setLineHeight(final String lineHeight) {
797 setStyleAttribute(Definition.LINE_HEIGHT.getAttributeName(), lineHeight);
798 updateFont(getFont(), false);
799 }
800
801
802
803
804
805 @JsxGetter
806 public String getFontFamily() {
807 if (styleDeclaration_ == null) {
808 return null;
809 }
810 return styleDeclaration_.getFontFamily();
811 }
812
813
814
815
816
817 @JsxSetter
818 public void setFontFamily(final String fontFamily) {
819 setStyleAttribute(Definition.FONT_FAMILY.getAttributeName(), fontFamily);
820 updateFont(getFont(), false);
821 }
822
823 private void updateFont(final String font, final boolean force) {
824 final BrowserVersion browserVersion = getBrowserVersion();
825 final String[] details = ComputedFont.getDetails(font);
826 if (details != null || force) {
827 final StringBuilder newFont = new StringBuilder();
828 newFont.append(getFontSize());
829 String lineHeight = getLineHeight();
830 final String defaultLineHeight = Definition.LINE_HEIGHT.getDefaultComputedValue(browserVersion);
831 if (lineHeight.isEmpty()) {
832 lineHeight = defaultLineHeight;
833 }
834
835 if (!lineHeight.equals(defaultLineHeight)) {
836 newFont.append('/');
837 if (lineHeight.equals(defaultLineHeight)) {
838 newFont.append(Definition.LINE_HEIGHT.getDefaultComputedValue(browserVersion));
839 }
840 else {
841 newFont.append(lineHeight);
842 }
843 }
844
845 newFont.append(' ').append(getFontFamily());
846 setStyleAttribute(Definition.FONT.getAttributeName(), newFont.toString());
847 }
848 }
849
850
851
852
853
854 @JsxGetter
855 public String getFont() {
856 if (styleDeclaration_ == null) {
857 return null;
858 }
859 return styleDeclaration_.getFont();
860 }
861
862
863
864
865
866 @JsxSetter
867 public void setFont(final String font) {
868 final String[] details = ComputedFont.getDetails(font);
869 if (details != null) {
870 setStyleAttribute(Definition.FONT_FAMILY.getAttributeName(), details[ComputedFont.FONT_FAMILY_INDEX]);
871 final String fontSize = details[ComputedFont.FONT_SIZE_INDEX];
872 if (details[ComputedFont.LINE_HEIGHT_INDEX] != null) {
873 setStyleAttribute(Definition.LINE_HEIGHT.getAttributeName(), details[ComputedFont.LINE_HEIGHT_INDEX]);
874 }
875 setStyleAttribute(Definition.FONT_SIZE.getAttributeName(), fontSize);
876 updateFont(font, true);
877 }
878 }
879
880
881
882
883
884 @JsxGetter
885 public String getHeight() {
886 if (styleDeclaration_ == null) {
887 return null;
888 }
889 return styleDeclaration_.getHeight();
890 }
891
892
893
894
895
896 @JsxSetter
897 public void setHeight(final Object height) {
898 setStyleLengthAttribute(Definition.HEIGHT.getAttributeName(), height, "", true, true, null);
899 }
900
901
902
903
904
905 @JsxGetter
906 public String getLeft() {
907 if (styleDeclaration_ == null) {
908 return null;
909 }
910 return styleDeclaration_.getLeft();
911 }
912
913
914
915
916
917 @JsxSetter
918 public void setLeft(final Object left) {
919 setStyleLengthAttribute(Definition.LEFT.getAttributeName(), left, "", true, true, null);
920 }
921
922
923
924
925
926 @JsxGetter
927 public int getLength() {
928 if (styleDeclaration_ == null) {
929 return 0;
930 }
931 return styleDeclaration_.getLength();
932 }
933
934
935
936
937
938 @JsxFunction
939 public String item(final int index) {
940 if (styleDeclaration_ == null) {
941 return null;
942 }
943
944 return styleDeclaration_.item(index);
945 }
946
947
948
949
950
951 @JsxSymbol(symbolName = "iterator")
952 public Scriptable values() {
953 return JavaScriptEngine.newArrayIteratorTypeValues(getParentScope(), this);
954 }
955
956
957
958
959
960 @JsxGetter
961 public String getLetterSpacing() {
962 if (styleDeclaration_ == null) {
963 return null;
964 }
965 return styleDeclaration_.getLetterSpacing();
966 }
967
968
969
970
971
972 @JsxSetter
973 public void setLetterSpacing(final Object letterSpacing) {
974 setStyleLengthAttribute(Definition.LETTER_SPACING.getAttributeName(), letterSpacing, "",
975 false, getBrowserVersion().hasFeature(JS_STYLE_LETTER_SPACING_ACCEPTS_PERCENT), null);
976 }
977
978
979
980
981
982 @JsxGetter
983 public String getMargin() {
984 if (styleDeclaration_ == null) {
985 return null;
986 }
987 return styleDeclaration_.getMargin();
988 }
989
990
991
992
993
994 @JsxSetter
995 public void setMargin(final String margin) {
996 setStyleAttribute(Definition.MARGIN.getAttributeName(), margin);
997 }
998
999
1000
1001
1002
1003 @JsxGetter
1004 public String getMarginBottom() {
1005 if (styleDeclaration_ == null) {
1006 return null;
1007 }
1008 return styleDeclaration_.getMarginBottom();
1009 }
1010
1011
1012
1013
1014
1015 @JsxSetter
1016 public void setMarginBottom(final Object marginBottom) {
1017 setStyleLengthAttribute(Definition.MARGIN_BOTTOM.getAttributeName(), marginBottom, "", true, true, null);
1018 }
1019
1020
1021
1022
1023
1024 @JsxGetter
1025 public String getMarginLeft() {
1026 if (styleDeclaration_ == null) {
1027 return null;
1028 }
1029 return styleDeclaration_.getMarginLeft();
1030 }
1031
1032
1033
1034
1035
1036 @JsxSetter
1037 public void setMarginLeft(final Object marginLeft) {
1038 setStyleLengthAttribute(Definition.MARGIN_LEFT.getAttributeName(), marginLeft, "", true, true, null);
1039 }
1040
1041
1042
1043
1044
1045 @JsxGetter
1046 public String getMarginRight() {
1047 if (styleDeclaration_ == null) {
1048 return null;
1049 }
1050 return styleDeclaration_.getMarginRight();
1051 }
1052
1053
1054
1055
1056
1057 @JsxSetter
1058 public void setMarginRight(final Object marginRight) {
1059 setStyleLengthAttribute(Definition.MARGIN_RIGHT.getAttributeName(), marginRight, "", true, true, null);
1060 }
1061
1062
1063
1064
1065
1066 @JsxGetter
1067 public String getMarginTop() {
1068 if (styleDeclaration_ == null) {
1069 return null;
1070 }
1071 return styleDeclaration_.getMarginTop();
1072 }
1073
1074
1075
1076
1077
1078 @JsxSetter
1079 public void setMarginTop(final Object marginTop) {
1080 setStyleLengthAttribute(Definition.MARGIN_TOP.getAttributeName(), marginTop, "", true, true, null);
1081 }
1082
1083
1084
1085
1086
1087 @JsxGetter
1088 public String getMaxHeight() {
1089 if (styleDeclaration_ == null) {
1090 return null;
1091 }
1092 return styleDeclaration_.getMaxHeight();
1093 }
1094
1095
1096
1097
1098
1099 @JsxSetter
1100 public void setMaxHeight(final Object maxHeight) {
1101 setStyleLengthAttribute(Definition.MAX_HEIGHT.getAttributeName(), maxHeight, "", false, true, null);
1102 }
1103
1104
1105
1106
1107
1108 @JsxGetter
1109 public String getMaxWidth() {
1110 if (styleDeclaration_ == null) {
1111 return null;
1112 }
1113 return styleDeclaration_.getMaxWidth();
1114 }
1115
1116
1117
1118
1119
1120 @JsxSetter
1121 public void setMaxWidth(final Object maxWidth) {
1122 setStyleLengthAttribute(Definition.MAX_WIDTH.getAttributeName(), maxWidth, "", false, true, null);
1123 }
1124
1125
1126
1127
1128
1129 @JsxGetter
1130 public String getMinHeight() {
1131 if (styleDeclaration_ == null) {
1132 return null;
1133 }
1134 return styleDeclaration_.getMinHeight();
1135 }
1136
1137
1138
1139
1140
1141 @JsxSetter
1142 public void setMinHeight(final Object minHeight) {
1143 setStyleLengthAttribute(Definition.MIN_HEIGHT.getAttributeName(), minHeight, "", true, true, null);
1144 }
1145
1146
1147
1148
1149
1150 @JsxGetter
1151 public String getMinWidth() {
1152 if (styleDeclaration_ == null) {
1153 return null;
1154 }
1155 return styleDeclaration_.getMinWidth();
1156 }
1157
1158
1159
1160
1161
1162 @JsxSetter
1163 public void setMinWidth(final Object minWidth) {
1164 setStyleLengthAttribute(Definition.MIN_WIDTH.getAttributeName(), minWidth, "", true, true, null);
1165 }
1166
1167
1168
1169
1170 @Override
1171 public Object get(final String name, final Scriptable start) {
1172 if (this != start) {
1173 return super.get(name, start);
1174 }
1175
1176 Scriptable prototype = getPrototype();
1177 while (prototype != null) {
1178 Object value = prototype.get(name, start);
1179 if (value != Scriptable.NOT_FOUND) {
1180 return value;
1181 }
1182
1183 final String camel = org.htmlunit.util.StringUtils.cssCamelize(name);
1184 if (!name.equals(camel)) {
1185 value = prototype.get(camel, start);
1186 if (value != Scriptable.NOT_FOUND) {
1187 return value;
1188 }
1189 }
1190 prototype = prototype.getPrototype();
1191 }
1192
1193 final Definition style = StyleAttributes.getDefinition(name, getBrowserVersion());
1194 if (style != null) {
1195 return getStyleAttribute(style);
1196 }
1197
1198 return super.get(name, start);
1199 }
1200
1201 @Override
1202 public Object get(final int index, final Scriptable start) {
1203 if (index < 0) {
1204 return JavaScriptEngine.UNDEFINED;
1205 }
1206
1207 final Map<String, StyleElement> style = getStyleMap();
1208 final int size = style.size();
1209 if (index >= size) {
1210 return JavaScriptEngine.UNDEFINED;
1211 }
1212 return style.keySet().toArray(new String[0])[index];
1213 }
1214
1215
1216
1217
1218
1219
1220 public final String getStyleAttribute(final Definition definition) {
1221 return getStyleAttribute(definition, true);
1222 }
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232 public String getStyleAttribute(final Definition definition, final boolean getDefaultValueIfEmpty) {
1233 if (styleDeclaration_ == null) {
1234 return "";
1235 }
1236 return styleDeclaration_.getStyleAttribute(definition, getDefaultValueIfEmpty);
1237 }
1238
1239 @Override
1240 public void put(final String name, final Scriptable start, final Object value) {
1241 if (this != start) {
1242 super.put(name, start, value);
1243 return;
1244 }
1245
1246 final Scriptable prototype = getPrototype();
1247 if (prototype != null && !"constructor".equals(name)) {
1248 if (prototype.get(name, start) != Scriptable.NOT_FOUND) {
1249 prototype.put(name, start, value);
1250 return;
1251 }
1252 final String camel = org.htmlunit.util.StringUtils.cssCamelize(name);
1253 if (!name.equals(camel) && prototype.get(camel, start) != Scriptable.NOT_FOUND) {
1254 prototype.put(camel, start, value);
1255 return;
1256 }
1257 }
1258
1259 if (getDomNodeOrNull() != null) {
1260 final Definition style = StyleAttributes.getDefinition(name, getBrowserVersion());
1261 if (style != null) {
1262 final String stringValue = JavaScriptEngine.toString(value);
1263 setStyleAttribute(style.getAttributeName(), stringValue);
1264 return;
1265 }
1266 }
1267
1268 super.put(name, start, value);
1269 }
1270
1271 @Override
1272 public boolean has(final String name, final Scriptable start) {
1273 if (this != start) {
1274 return super.has(name, start);
1275 }
1276
1277 final BrowserVersion browserVersion = getBrowserVersion();
1278 if (browserVersion != null) {
1279 final Definition style = StyleAttributes.getDefinition(name, getBrowserVersion());
1280 if (style != null) {
1281 return true;
1282 }
1283 }
1284
1285 return super.has(name, start);
1286 }
1287
1288 @Override
1289 public Object[] getIds() {
1290 final List<Object> ids = new ArrayList<>();
1291 for (final Definition styleAttribute : StyleAttributes.getDefinitions(getBrowserVersion())) {
1292 ids.add(styleAttribute.getPropertyName());
1293 }
1294 final Object[] normalIds = super.getIds();
1295 for (final Object o : normalIds) {
1296 if (!ids.contains(o)) {
1297 ids.add(o);
1298 }
1299 }
1300 return ids.toArray();
1301 }
1302
1303
1304
1305
1306
1307 @JsxGetter
1308 public String getOpacity() {
1309 if (styleDeclaration_ == null) {
1310 return null;
1311 }
1312 return styleDeclaration_.getOpacity();
1313 }
1314
1315
1316
1317
1318
1319 @JsxSetter
1320 public void setOpacity(final Object opacity) {
1321 if (JavaScriptEngine.isNaN(opacity)) {
1322 return;
1323 }
1324
1325 final double doubleValue;
1326 if (opacity instanceof Number) {
1327 doubleValue = ((Number) opacity).doubleValue();
1328 }
1329 else {
1330 String valueString = JavaScriptEngine.toString(opacity);
1331
1332 if (valueString.isEmpty()) {
1333 setStyleAttribute(Definition.OPACITY.getAttributeName(), valueString);
1334 return;
1335 }
1336
1337 valueString = valueString.trim();
1338 try {
1339 doubleValue = Double.parseDouble(valueString);
1340 }
1341 catch (final NumberFormatException e) {
1342
1343 return;
1344 }
1345 }
1346
1347 if (Double.isNaN(doubleValue) || Double.isInfinite(doubleValue)) {
1348 return;
1349 }
1350 setStyleAttribute(Definition.OPACITY.getAttributeName(), Double.toString(doubleValue));
1351 }
1352
1353
1354
1355
1356
1357 @JsxGetter
1358 public String getOutline() {
1359 if (styleDeclaration_ == null) {
1360 return null;
1361 }
1362 return styleDeclaration_.getOutline();
1363 }
1364
1365
1366
1367
1368
1369 @JsxSetter
1370 public void setOutline(final String outline) {
1371 setStyleAttribute(Definition.OUTLINE.getAttributeName(), outline);
1372 }
1373
1374
1375
1376
1377
1378 @JsxGetter
1379 public String getOutlineWidth() {
1380 if (styleDeclaration_ == null) {
1381 return null;
1382 }
1383 return styleDeclaration_.getOutlineWidth();
1384 }
1385
1386
1387
1388
1389
1390 @JsxSetter
1391 public void setOutlineWidth(final Object outlineWidth) {
1392 setStyleLengthAttribute(Definition.OUTLINE_WIDTH.getAttributeName(), outlineWidth, "",
1393 false, false, THIN_MED_THICK);
1394 }
1395
1396
1397
1398
1399
1400 @JsxGetter
1401 public String getPadding() {
1402 if (styleDeclaration_ == null) {
1403 return null;
1404 }
1405 return styleDeclaration_.getPadding();
1406 }
1407
1408
1409
1410
1411
1412 @JsxSetter
1413 public void setPadding(final String padding) {
1414 setStyleAttribute(Definition.PADDING.getAttributeName(), padding);
1415 }
1416
1417
1418
1419
1420
1421 @JsxGetter
1422 public String getPaddingBottom() {
1423 if (styleDeclaration_ == null) {
1424 return null;
1425 }
1426 return styleDeclaration_.getPaddingBottom();
1427 }
1428
1429
1430
1431
1432
1433 @JsxSetter
1434 public void setPaddingBottom(final Object paddingBottom) {
1435 setStyleLengthAttribute(Definition.PADDING_BOTTOM.getAttributeName(),
1436 paddingBottom, "", false, true, null);
1437 }
1438
1439
1440
1441
1442
1443 @JsxGetter
1444 public String getPaddingLeft() {
1445 if (styleDeclaration_ == null) {
1446 return null;
1447 }
1448 return styleDeclaration_.getPaddingLeft();
1449 }
1450
1451
1452
1453
1454
1455 @JsxSetter
1456 public void setPaddingLeft(final Object paddingLeft) {
1457 setStyleLengthAttribute(Definition.PADDING_LEFT.getAttributeName(), paddingLeft, "", false, true, null);
1458 }
1459
1460
1461
1462
1463
1464 @JsxGetter
1465 public String getPaddingRight() {
1466 if (styleDeclaration_ == null) {
1467 return null;
1468 }
1469 return styleDeclaration_.getPaddingRight();
1470 }
1471
1472
1473
1474
1475
1476 @JsxSetter
1477 public void setPaddingRight(final Object paddingRight) {
1478 setStyleLengthAttribute(Definition.PADDING_RIGHT.getAttributeName(),
1479 paddingRight, "", false, true, null);
1480 }
1481
1482
1483
1484
1485
1486 @JsxGetter
1487 public String getPaddingTop() {
1488 if (styleDeclaration_ == null) {
1489 return null;
1490 }
1491 return styleDeclaration_.getPaddingTop();
1492 }
1493
1494
1495
1496
1497
1498 @JsxSetter
1499 public void setPaddingTop(final Object paddingTop) {
1500 setStyleLengthAttribute(Definition.PADDING_TOP.getAttributeName(), paddingTop, "", false, true, null);
1501 }
1502
1503
1504
1505
1506
1507
1508
1509 @JsxGetter
1510 public CSSRule getParentRule() {
1511 final AbstractCSSRuleImpl parentRule = styleDeclaration_.getParentRule();
1512 if (parentRule != null) {
1513 return CSSRule.create((CSSStyleSheet) getParentScope(), parentRule);
1514 }
1515 return null;
1516 }
1517
1518
1519
1520
1521
1522 @JsxSetter
1523 public void setParentRule(final CSSRule parentRule) {
1524
1525 }
1526
1527
1528
1529
1530
1531 @JsxGetter
1532 public String getRight() {
1533 if (styleDeclaration_ == null) {
1534 return null;
1535 }
1536 return styleDeclaration_.getRight();
1537 }
1538
1539
1540
1541
1542
1543 @JsxSetter
1544 public void setRight(final Object right) {
1545 setStyleLengthAttribute(Definition.RIGHT.getAttributeName(), right, "", true, true, null);
1546 }
1547
1548
1549
1550
1551
1552 @JsxGetter
1553 public String getRubyAlign() {
1554 if (styleDeclaration_ == null) {
1555 return null;
1556 }
1557 return styleDeclaration_.getRubyAlign();
1558 }
1559
1560
1561
1562
1563
1564 @JsxSetter
1565 public void setRubyAlign(final String rubyAlign) {
1566 setStyleAttribute(Definition.RUBY_ALIGN.getAttributeName(), rubyAlign);
1567 }
1568
1569
1570
1571
1572
1573 @JsxGetter({CHROME, EDGE})
1574 public String getSize() {
1575 if (styleDeclaration_ == null) {
1576 return null;
1577 }
1578 return styleDeclaration_.getSize();
1579 }
1580
1581
1582
1583
1584
1585 @JsxSetter({CHROME, EDGE})
1586 public void setSize(final String size) {
1587 setStyleAttribute(Definition.SIZE.getAttributeName(), size);
1588 }
1589
1590
1591
1592
1593
1594 @JsxGetter
1595 public String getTextIndent() {
1596 if (styleDeclaration_ == null) {
1597 return null;
1598 }
1599 return styleDeclaration_.getTextIndent();
1600 }
1601
1602
1603
1604
1605
1606 @JsxSetter
1607 public void setTextIndent(final Object textIndent) {
1608 setStyleLengthAttribute(Definition.TEXT_INDENT.getAttributeName(), textIndent, "", false, true, null);
1609 }
1610
1611
1612
1613
1614
1615 @JsxGetter
1616 public String getTop() {
1617 if (styleDeclaration_ == null) {
1618 return null;
1619 }
1620 return styleDeclaration_.getTop();
1621 }
1622
1623
1624
1625
1626
1627 @JsxSetter
1628 public void setTop(final Object top) {
1629 setStyleLengthAttribute(Definition.TOP.getAttributeName(), top, "", true, true, null);
1630 }
1631
1632
1633
1634
1635
1636 @JsxGetter
1637 public String getVerticalAlign() {
1638 if (styleDeclaration_ == null) {
1639 return null;
1640 }
1641 return styleDeclaration_.getVerticalAlign();
1642 }
1643
1644
1645
1646
1647
1648 @JsxSetter
1649 public void setVerticalAlign(final Object verticalAlign) {
1650 setStyleLengthAttribute(Definition.VERTICAL_ALIGN.getAttributeName(),
1651 verticalAlign, "", false, true, ALIGN_KEYWORDS);
1652 }
1653
1654
1655
1656
1657
1658 @JsxGetter
1659 public String getWidth() {
1660 if (styleDeclaration_ == null) {
1661 return null;
1662 }
1663 return styleDeclaration_.getWidth();
1664 }
1665
1666
1667
1668
1669
1670 @JsxSetter
1671 public void setWidth(final Object width) {
1672 setStyleLengthAttribute(Definition.WIDTH.getAttributeName(), width, "", true, true, null);
1673 }
1674
1675
1676
1677
1678
1679 @JsxGetter({CHROME, EDGE})
1680 public String getWidows() {
1681 if (styleDeclaration_ == null) {
1682 return null;
1683 }
1684 return styleDeclaration_.getWidows();
1685 }
1686
1687
1688
1689
1690
1691 @JsxSetter({CHROME, EDGE})
1692 public void setWidows(final String widows) {
1693 if (getBrowserVersion().hasFeature(CSS_BACKGROUND_INITIAL)) {
1694 try {
1695 if (Integer.parseInt(widows) <= 0) {
1696 return;
1697 }
1698 }
1699 catch (final NumberFormatException e) {
1700 return;
1701 }
1702 }
1703 setStyleAttribute(Definition.WIDOWS.getAttributeName(), widows);
1704 }
1705
1706
1707
1708
1709
1710 @JsxGetter({CHROME, EDGE})
1711 public String getOrphans() {
1712 if (styleDeclaration_ == null) {
1713 return null;
1714 }
1715 return styleDeclaration_.getOrphans();
1716 }
1717
1718
1719
1720
1721
1722 @JsxSetter({CHROME, EDGE})
1723 public void setOrphans(final String orphans) {
1724 if (getBrowserVersion().hasFeature(CSS_BACKGROUND_INITIAL)) {
1725 try {
1726 if (Integer.parseInt(orphans) <= 0) {
1727 return;
1728 }
1729 }
1730 catch (final NumberFormatException e) {
1731 return;
1732 }
1733 }
1734 setStyleAttribute(Definition.ORPHANS.getAttributeName(), orphans);
1735 }
1736
1737
1738
1739
1740
1741 @JsxGetter
1742 public String getPosition() {
1743 if (styleDeclaration_ == null) {
1744 return null;
1745 }
1746 return styleDeclaration_.getPosition();
1747 }
1748
1749
1750
1751
1752
1753 @JsxSetter
1754 public void setPosition(final String position) {
1755 if (position.isEmpty() || STATIC.equalsIgnoreCase(position) || ABSOLUTE.equalsIgnoreCase(position)
1756 || FIXED.equalsIgnoreCase(position) || RELATIVE.equalsIgnoreCase(position)
1757 || INITIAL.equalsIgnoreCase(position) || INHERIT.equalsIgnoreCase(position)) {
1758 setStyleAttribute(Definition.POSITION.getAttributeName(), position.toLowerCase(Locale.ROOT));
1759 }
1760 }
1761
1762
1763
1764
1765
1766 @JsxGetter
1767 public String getWordSpacing() {
1768 if (styleDeclaration_ == null) {
1769 return null;
1770 }
1771 return styleDeclaration_.getWordSpacing();
1772 }
1773
1774
1775
1776
1777
1778 @JsxSetter
1779 public void setWordSpacing(final Object wordSpacing) {
1780 setStyleLengthAttribute(Definition.WORD_SPACING.getAttributeName(), wordSpacing, "",
1781 false, getBrowserVersion().hasFeature(JS_STYLE_WORD_SPACING_ACCEPTS_PERCENT), null);
1782 }
1783
1784
1785
1786
1787
1788 @JsxGetter
1789 public String getZIndex() {
1790 if (styleDeclaration_ == null) {
1791 return null;
1792 }
1793 return styleDeclaration_.getZIndex();
1794 }
1795
1796
1797
1798
1799
1800 @JsxSetter
1801 public void setZIndex(final Object zIndex) {
1802
1803 if (zIndex == null || StringUtils.isEmpty(zIndex.toString())) {
1804 setStyleAttribute(Definition.Z_INDEX_.getAttributeName(), "");
1805 return;
1806 }
1807
1808 if (JavaScriptEngine.isUndefined(zIndex)) {
1809 return;
1810 }
1811
1812
1813 if (zIndex instanceof Number) {
1814 final Number number = (Number) zIndex;
1815 if (number.doubleValue() % 1 == 0) {
1816 setStyleAttribute(Definition.Z_INDEX_.getAttributeName(), Integer.toString(number.intValue()));
1817 }
1818 return;
1819 }
1820 try {
1821 final int i = Integer.parseInt(zIndex.toString());
1822 setStyleAttribute(Definition.Z_INDEX_.getAttributeName(), Integer.toString(i));
1823 }
1824 catch (final NumberFormatException ignored) {
1825
1826 }
1827 }
1828
1829
1830
1831
1832
1833
1834 @JsxFunction
1835 public String getPropertyValue(final String name) {
1836 if (name != null && name.contains("-")) {
1837 final Object value = getProperty(this, org.htmlunit.util.StringUtils.cssCamelize(name));
1838 if (value instanceof String) {
1839 return (String) value;
1840 }
1841 }
1842
1843 return styleDeclaration_.getStyleAttribute(name);
1844 }
1845
1846
1847
1848
1849
1850
1851 @JsxFunction
1852 public String getPropertyPriority(final String name) {
1853 return getStylePriority(name);
1854 }
1855
1856
1857
1858
1859
1860
1861
1862
1863 @JsxFunction
1864 public void setProperty(final String name, final Object value, final String important) {
1865 String imp = "";
1866 if (!StringUtils.isEmpty(important) && !"null".equals(important)) {
1867 if (!StyleElement.PRIORITY_IMPORTANT.equalsIgnoreCase(important)) {
1868 return;
1869 }
1870 imp = StyleElement.PRIORITY_IMPORTANT;
1871 }
1872
1873 if (LENGTH_PROPERTIES_FFFF.contains(name)) {
1874 setStyleLengthAttribute(name, value, imp, false, false, null);
1875 }
1876 else if (LENGTH_PROPERTIES_TTFF.contains(name)) {
1877 setStyleLengthAttribute(name, value, imp, true, true, null);
1878 }
1879 else if (LENGTH_PROPERTIES_FTFF.contains(name)) {
1880 setStyleLengthAttribute(name, value, imp, false, true, null);
1881 }
1882 else if (Definition.OUTLINE_WIDTH.getAttributeName().equals(name)) {
1883 setStyleLengthAttribute(Definition.OUTLINE_WIDTH.getAttributeName(),
1884 value, imp, false, false, THIN_MED_THICK);
1885 }
1886 else if (Definition.LETTER_SPACING.getAttributeName().equals(name)) {
1887 setStyleLengthAttribute(Definition.LETTER_SPACING.getAttributeName(), value, imp,
1888 false, getBrowserVersion().hasFeature(JS_STYLE_LETTER_SPACING_ACCEPTS_PERCENT), null);
1889 }
1890 else if (Definition.WORD_SPACING.getAttributeName().equals(name)) {
1891 setStyleLengthAttribute(Definition.WORD_SPACING.getAttributeName(), value, imp,
1892 false, getBrowserVersion().hasFeature(JS_STYLE_WORD_SPACING_ACCEPTS_PERCENT), null);
1893 }
1894 else if (Definition.VERTICAL_ALIGN.getAttributeName().equals(name)) {
1895 setStyleLengthAttribute(Definition.VERTICAL_ALIGN.getAttributeName(), value, imp, false, true, null);
1896 }
1897 else {
1898 setStyleAttribute(name, JavaScriptEngine.toString(value), imp);
1899 }
1900 }
1901
1902
1903
1904
1905
1906
1907 @JsxFunction
1908 public String removeProperty(final Object name) {
1909 return removeStyleAttribute(JavaScriptEngine.toString(name));
1910 }
1911
1912
1913
1914
1915
1916
1917 static boolean isLength(String token) {
1918 if (token.endsWith("em") || token.endsWith("ex") || token.endsWith("px") || token.endsWith("in")
1919 || token.endsWith("cm") || token.endsWith("mm") || token.endsWith("pt") || token.endsWith("pc")
1920 || token.endsWith("%")) {
1921
1922 if (token.endsWith("%")) {
1923 token = token.substring(0, token.length() - 1);
1924 }
1925 else {
1926 token = token.substring(0, token.length() - 2);
1927 }
1928 try {
1929 Double.parseDouble(token);
1930 return true;
1931 }
1932 catch (final NumberFormatException ignored) {
1933
1934 }
1935 }
1936 return false;
1937 }
1938
1939
1940
1941
1942 @Override
1943 public String toString() {
1944 if (styleDeclaration_ == null) {
1945 return "CSSStyleDeclaration for 'null'";
1946 }
1947
1948 return "CSSStyleDeclaration for '" + styleDeclaration_ + "'";
1949 }
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961 private void setStyleLengthAttribute(final String name, final Object value, final String important,
1962 final boolean auto, final boolean percent, final String[] validValues) {
1963 if (JavaScriptEngine.isNaN(value)) {
1964 return;
1965 }
1966
1967 if (value instanceof Number) {
1968 return;
1969 }
1970
1971 String valueString = JavaScriptEngine.toString(value);
1972 if (null == value) {
1973 valueString = "";
1974 }
1975
1976 if (StringUtils.isEmpty(valueString)) {
1977 setStyleAttribute(name, valueString, important);
1978 return;
1979 }
1980
1981 if ((auto && AUTO.equals(valueString))
1982 || INITIAL.equals(valueString)
1983 || INHERIT.equals(valueString)) {
1984 setStyleAttribute(name, valueString, important);
1985 return;
1986 }
1987
1988 if (validValues != null && ArrayUtils.contains(validValues, valueString)) {
1989 setStyleAttribute(name, valueString, important);
1990 return;
1991 }
1992
1993 String unit = "px";
1994 if (percent && valueString.endsWith("%")) {
1995 unit = valueString.substring(valueString.length() - 1);
1996 valueString = valueString.substring(0, valueString.length() - 1);
1997 }
1998 else if (valueString.endsWith("px")
1999 || valueString.endsWith("em")
2000 || valueString.endsWith("ex")
2001 || valueString.endsWith("pt")
2002 || valueString.endsWith("cm")
2003 || valueString.endsWith("mm")
2004 || valueString.endsWith("in")
2005 || valueString.endsWith("pc")
2006 || valueString.endsWith("ch")
2007 || valueString.endsWith("vh")
2008 || valueString.endsWith("vw")) {
2009 unit = valueString.substring(valueString.length() - 2);
2010 valueString = valueString.substring(0, valueString.length() - 2);
2011 }
2012 else if (valueString.endsWith("rem")
2013 || valueString.endsWith("vmin")
2014 || valueString.endsWith("vmax")) {
2015 unit = valueString.substring(valueString.length() - 3);
2016 valueString = valueString.substring(0, valueString.length() - 3);
2017 }
2018 else {
2019 return;
2020 }
2021
2022 if (!valueString.equals(valueString.trim())) {
2023
2024 return;
2025 }
2026 final double doubleValue = JavaScriptEngine.toNumber(valueString);
2027
2028 try {
2029 if (Double.isNaN(doubleValue) || Double.isInfinite(doubleValue)) {
2030 return;
2031 }
2032
2033 final String valueStr;
2034 if (doubleValue % 1 == 0) {
2035 valueStr = (int) doubleValue + unit;
2036 }
2037 else {
2038 valueStr = doubleValue + unit;
2039 }
2040
2041 setStyleAttribute(name, valueStr, important);
2042 }
2043 catch (final Exception ignored) {
2044
2045 }
2046 }
2047 }