1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.html;
16
17 import java.util.ArrayList;
18 import java.util.List;
19
20 import org.htmlunit.corejs.javascript.Context;
21 import org.htmlunit.corejs.javascript.Scriptable;
22 import org.htmlunit.html.DomElement;
23 import org.htmlunit.html.DomNode;
24 import org.htmlunit.javascript.JavaScriptEngine;
25 import org.htmlunit.javascript.configuration.JsxClass;
26 import org.htmlunit.javascript.configuration.JsxConstructor;
27
28
29
30
31
32
33
34 @JsxClass
35 public class HTMLAllCollection extends HTMLCollection {
36
37
38
39
40 public HTMLAllCollection() {
41 super();
42 }
43
44
45
46
47 @Override
48 @JsxConstructor
49 public void jsConstructor() {
50 super.jsConstructor();
51 }
52
53
54
55
56
57 public HTMLAllCollection(final DomNode parentScope) {
58 super(parentScope, false);
59 }
60
61
62
63
64
65
66
67 @Override
68 public Object item(final Object index) {
69 final double numb;
70
71 if (index instanceof String) {
72 final String name = (String) index;
73 final Object result = namedItem(name);
74 if (null != result && !JavaScriptEngine.isUndefined(result)) {
75 return result;
76 }
77 numb = JavaScriptEngine.toNumber(index);
78 if (Double.isNaN(numb)) {
79 return null;
80 }
81 }
82 else {
83 numb = JavaScriptEngine.toNumber(index);
84 }
85
86 if (numb < 0) {
87 return null;
88 }
89
90 if (Double.isInfinite(numb) || numb != Math.floor(numb)) {
91 return null;
92 }
93
94 final Object object = get((int) numb, this);
95 if (object == NOT_FOUND) {
96 return null;
97 }
98 return object;
99 }
100
101
102
103
104 @Override
105 public final Scriptable namedItem(final String name) {
106 final List<DomNode> elements = getElements();
107
108
109 final List<DomElement> matching = new ArrayList<>();
110
111 for (final DomNode next : elements) {
112 if (next instanceof DomElement) {
113 final DomElement elem = (DomElement) next;
114 if (name.equals(elem.getAttributeDirect(DomElement.NAME_ATTRIBUTE))
115 || name.equals(elem.getId())) {
116 matching.add(elem);
117 }
118 }
119 }
120
121 if (matching.size() == 1) {
122 return getScriptableForElement(matching.get(0));
123 }
124 if (matching.isEmpty()) {
125 return null;
126 }
127
128
129 final DomNode domNode = getDomNodeOrNull();
130 final List<DomNode> nodes = new ArrayList<>(matching);
131 final HTMLCollection collection = new HTMLCollection(domNode, nodes);
132 collection.setAvoidObjectDetection(true);
133 return collection;
134 }
135
136
137
138
139 @Override
140 public Object call(final Context cx, final Scriptable scope, final Scriptable thisObj, final Object[] args) {
141 boolean nullIfNotFound = false;
142 if (args[0] instanceof Number) {
143 final double val = ((Number) args[0]).doubleValue();
144 if (val != (int) val) {
145 return null;
146 }
147 if (val >= 0) {
148 nullIfNotFound = true;
149 }
150 }
151 else {
152 final String val = JavaScriptEngine.toString(args[0]);
153 try {
154 args[0] = Integer.parseInt(val);
155 }
156 catch (final NumberFormatException ignored) {
157
158 }
159 }
160
161 final Object value = super.call(cx, scope, thisObj, args);
162 if (nullIfNotFound && JavaScriptEngine.isUndefined(value)) {
163 return null;
164 }
165 return value;
166 }
167
168
169
170
171 @Override
172 protected boolean supportsParentheses() {
173 return true;
174 }
175
176
177
178
179 @Override
180 protected Object equivalentValues(final Object value) {
181 if (value == null || JavaScriptEngine.isUndefined(value)) {
182 return Boolean.TRUE;
183 }
184
185 return super.equivalentValues(value);
186 }
187 }