1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.html;
16
17 import static org.htmlunit.BrowserVersionFeatures.JS_SELECT_REMOVE_IGNORE_IF_INDEX_OUTSIDE;
18
19 import java.util.List;
20
21 import org.htmlunit.corejs.javascript.Context;
22 import org.htmlunit.corejs.javascript.Function;
23 import org.htmlunit.corejs.javascript.Scriptable;
24 import org.htmlunit.corejs.javascript.VarScope;
25 import org.htmlunit.html.HtmlOption;
26 import org.htmlunit.html.HtmlSelect;
27 import org.htmlunit.javascript.JavaScriptEngine;
28 import org.htmlunit.javascript.configuration.JsxClass;
29 import org.htmlunit.javascript.configuration.JsxConstructor;
30 import org.htmlunit.javascript.configuration.JsxFunction;
31 import org.htmlunit.javascript.configuration.JsxGetter;
32 import org.htmlunit.javascript.configuration.JsxSetter;
33 import org.htmlunit.javascript.configuration.JsxSymbol;
34 import org.htmlunit.javascript.host.dom.Node;
35 import org.htmlunit.javascript.host.dom.NodeList;
36
37
38
39
40
41
42
43
44
45
46
47
48 @JsxClass(domClass = HtmlSelect.class)
49 public class HTMLSelectElement extends HTMLElement {
50
51 private HTMLOptionsCollection optionsArray_;
52
53
54 private NodeList labels_;
55
56
57
58
59 @Override
60 @JsxConstructor
61 public void jsConstructor() {
62 super.jsConstructor();
63 }
64
65
66
67
68
69 public void initialize() {
70 final HtmlSelect htmlSelect = getDomNodeOrDie();
71 htmlSelect.setScriptableObject(this);
72 if (optionsArray_ == null) {
73 optionsArray_ = new HTMLOptionsCollection(getParentScope());
74 optionsArray_.initialize(htmlSelect);
75 }
76 }
77
78
79
80
81 @Override
82 public HtmlSelect getDomNodeOrDie() {
83 return (HtmlSelect) super.getDomNodeOrDie();
84 }
85
86
87
88
89
90
91
92
93
94 @JsxFunction
95 public static void remove(final Context context, final VarScope scope,
96 final Scriptable thisObj, final Object[] args, final Function function) {
97 if (!(thisObj instanceof HTMLSelectElement htmlSelect)) {
98 throw JavaScriptEngine.reportRuntimeError(
99 "HTMLSelectElement.replace() failed - this is not a HTMLSelectElement");
100 }
101
102 if (args.length == 0) {
103 htmlSelect.remove();
104 return;
105 }
106
107 final int index = JavaScriptEngine.toInt32(args[0]);
108 if (index < 0
109 && htmlSelect.getBrowserVersion().hasFeature(JS_SELECT_REMOVE_IGNORE_IF_INDEX_OUTSIDE)) {
110 return;
111 }
112
113 final HTMLOptionsCollection options = htmlSelect.getOptions();
114 if (index >= options.getLength()
115 && htmlSelect.getBrowserVersion().hasFeature(JS_SELECT_REMOVE_IGNORE_IF_INDEX_OUTSIDE)) {
116 return;
117 }
118
119 htmlSelect.getOptions().remove(index);
120 }
121
122
123
124
125
126
127 @JsxFunction
128 public void add(final HTMLOptionElement newOptionObject, final Object beforeOptionObject) {
129 getOptions().add(newOptionObject, beforeOptionObject);
130 }
131
132
133
134
135 @Override
136 public Node appendChild(final Object childObject) {
137 final Node node = super.appendChild(childObject);
138 getDomNodeOrDie().ensureSelectedIndex();
139 return node;
140 }
141
142
143
144
145 @Override
146 public Node insertBeforeImpl(final Object[] args) {
147 final Node node = super.insertBeforeImpl(args);
148 getDomNodeOrDie().ensureSelectedIndex();
149 return node;
150 }
151
152
153
154
155
156
157 @JsxFunction
158 public Object item(final int index) {
159 final Object option = getOptions().item(index);
160 if (JavaScriptEngine.isUndefined(option)) {
161 return null;
162 }
163 return option;
164 }
165
166
167
168
169
170 @JsxGetter
171 public String getType() {
172 final String type;
173 if (getDomNodeOrDie().isMultipleSelectEnabled()) {
174 type = "select-multiple";
175 }
176 else {
177 type = "select-one";
178 }
179 return type;
180 }
181
182
183
184
185
186 @JsxGetter
187 public HTMLOptionsCollection getOptions() {
188 if (optionsArray_ == null) {
189 initialize();
190 }
191 return optionsArray_;
192 }
193
194
195
196
197
198 @JsxGetter
199 public int getSelectedIndex() {
200 return getDomNodeOrDie().getSelectedIndex();
201 }
202
203
204
205
206
207 @JsxSetter
208 public void setSelectedIndex(final int index) {
209 getDomNodeOrDie().setSelectedIndex(index);
210 }
211
212
213
214
215
216 @Override
217 @JsxGetter
218 public String getValue() {
219 final List<HtmlOption> selectedOptions = getDomNodeOrDie().getSelectedOptions();
220 if (selectedOptions.isEmpty()) {
221 return "";
222 }
223 return ((HTMLOptionElement) selectedOptions.get(0).getScriptableObject()).getValue();
224 }
225
226
227
228
229
230 @JsxGetter
231 public int getLength() {
232 return getOptions().getLength();
233 }
234
235
236
237
238
239 @JsxSetter
240 public void setLength(final int newLength) {
241 getOptions().setLength(newLength);
242 }
243
244
245
246
247
248
249
250 @Override
251 public Object get(final int index, final Scriptable start) {
252 if (getDomNodeOrNull() == null) {
253 return NOT_FOUND;
254 }
255 return getOptions().get(index, start);
256 }
257
258
259
260
261
262
263
264 @Override
265 public void put(final int index, final Scriptable start, final Object newValue) {
266 getOptions().put(index, start, newValue);
267 }
268
269
270
271
272
273 @Override
274 @JsxSetter
275 public void setValue(final Object newValue) {
276 final String val = JavaScriptEngine.toString(newValue);
277 getDomNodeOrDie().setSelectedAttribute(val, true, false);
278 }
279
280
281
282
283
284 @JsxGetter
285 public int getSize() {
286 return getDomNodeOrDie().getSize();
287 }
288
289
290
291
292
293 @JsxSetter
294 public void setSize(final String size) {
295 getDomNodeOrDie().setAttribute("size", size);
296 }
297
298
299
300
301
302 @JsxGetter
303 public boolean isMultiple() {
304 return getDomNodeOrDie().hasAttribute("multiple");
305 }
306
307
308
309
310
311 @JsxSetter
312 public void setMultiple(final boolean multiple) {
313 if (multiple) {
314 getDomNodeOrDie().setAttribute("multiple", "multiple");
315 }
316 else {
317 getDomNodeOrDie().removeAttribute("multiple");
318 }
319 }
320
321
322
323
324
325 @JsxGetter
326 public NodeList getLabels() {
327 if (labels_ == null) {
328 labels_ = new LabelsNodeList(getDomNodeOrDie());
329 }
330 return labels_;
331 }
332
333
334
335
336
337 @JsxGetter
338 public boolean isRequired() {
339 return getDomNodeOrDie().isRequired();
340 }
341
342
343
344
345
346 @JsxSetter
347 public void setRequired(final boolean required) {
348 getDomNodeOrDie().setRequired(required);
349 }
350
351
352
353
354 @JsxGetter
355 @Override
356 public String getName() {
357 return super.getName();
358 }
359
360
361
362
363 @JsxSetter
364 @Override
365 public void setName(final String newName) {
366 super.setName(newName);
367 }
368
369
370
371
372 @Override
373 @JsxGetter
374 public boolean isDisabled() {
375 return super.isDisabled();
376 }
377
378
379
380
381 @Override
382 @JsxSetter
383 public void setDisabled(final boolean disabled) {
384 super.setDisabled(disabled);
385 }
386
387
388
389
390 @JsxGetter
391 @Override
392 public HTMLFormElement getForm() {
393 return super.getForm();
394 }
395
396
397
398
399
400 @JsxFunction
401 public boolean checkValidity() {
402 return getDomNodeOrDie().isValid();
403 }
404
405
406
407
408 @JsxGetter
409 public ValidityState getValidity() {
410 final ValidityState validityState = new ValidityState();
411 validityState.setPrototype(getPrototype(validityState.getClass()));
412 validityState.setParentScope(getParentScope());
413 validityState.setDomNode(getDomNodeOrDie());
414 return validityState;
415 }
416
417
418
419
420 @JsxGetter
421 public boolean isWillValidate() {
422 return getDomNodeOrDie().willValidate();
423 }
424
425
426
427
428
429 @JsxFunction
430 public void setCustomValidity(final String message) {
431 getDomNodeOrDie().setCustomValidity(message);
432 }
433
434
435
436
437 @JsxSymbol
438 public Scriptable iterator() {
439 return getOptions().iterator();
440 }
441 }