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