1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.html;
16
17 import java.io.IOException;
18 import java.io.PrintWriter;
19 import java.util.Map;
20
21 import org.htmlunit.Page;
22 import org.htmlunit.SgmlPage;
23 import org.htmlunit.html.serializer.HtmlSerializerNormalizedText;
24 import org.htmlunit.javascript.host.event.Event;
25 import org.htmlunit.javascript.host.event.MouseEvent;
26 import org.w3c.dom.Node;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 public class HtmlOption extends HtmlElement implements DisabledElement {
42
43
44 public static final String TAG_NAME = "option";
45
46 private boolean selected_;
47
48
49
50
51
52
53
54
55 HtmlOption(final String qualifiedName, final SgmlPage page,
56 final Map<String, DomAttr> attributes) {
57 super(qualifiedName, page, attributes);
58 reset();
59 }
60
61
62
63
64
65 public boolean isSelected() {
66 return selected_;
67 }
68
69
70
71
72
73
74
75
76
77 public Page setSelected(final boolean selected) {
78 setSelected(selected, true, false, false, false);
79 return getPage();
80 }
81
82
83
84
85
86
87
88
89
90 public void setSelectedFromJavaScript(final boolean selected) {
91 setSelected(selected, false, false, true, false);
92 }
93
94
95
96
97
98
99
100
101
102
103
104 private void setSelected(final boolean selected, final boolean invokeOnFocus, final boolean isClick,
105 final boolean shiftKey, final boolean ctrlKey) {
106 if (selected == isSelected()) {
107 return;
108 }
109 final HtmlSelect select = getEnclosingSelect();
110 if (select != null) {
111 select.setSelectedAttribute(this, selected, invokeOnFocus, shiftKey, ctrlKey, isClick);
112 return;
113 }
114
115
116 setSelectedInternal(selected);
117 }
118
119
120
121
122 @Override
123 public void insertBefore(final DomNode newNode) {
124 super.insertBefore(newNode);
125 if (newNode instanceof HtmlOption) {
126 final HtmlOption option = (HtmlOption) newNode;
127 if (option.isSelected()) {
128 getEnclosingSelect().setSelectedAttribute(option, true);
129 }
130 }
131 }
132
133
134
135
136
137 public HtmlSelect getEnclosingSelect() {
138 return (HtmlSelect) getEnclosingElement(HtmlSelect.TAG_NAME);
139 }
140
141
142
143
144 public void reset() {
145 setSelectedInternal(hasAttribute("selected"));
146 }
147
148
149
150
151
152
153
154
155
156 public final String getSelectedAttribute() {
157 return getAttributeDirect("selected");
158 }
159
160
161
162
163
164
165
166
167 public final boolean isDefaultSelected() {
168 return hasAttribute("selected");
169 }
170
171
172
173
174 @Override
175 public final boolean isDisabled() {
176 if (hasAttribute(ATTRIBUTE_DISABLED)) {
177 return true;
178 }
179
180 Node node = getParentNode();
181 while (node != null) {
182 if (node instanceof DisabledElement
183 && ((DisabledElement) node).isDisabled()) {
184 return true;
185 }
186 node = node.getParentNode();
187 }
188
189 return false;
190 }
191
192
193
194
195 @Override
196 public final String getDisabledAttribute() {
197 return getAttributeDirect(ATTRIBUTE_DISABLED);
198 }
199
200
201
202
203
204
205
206
207 public final String getLabelAttribute() {
208 return getAttributeDirect("label");
209 }
210
211
212
213
214
215
216
217
218 public final void setLabelAttribute(final String newLabel) {
219 setAttribute("label", newLabel);
220 }
221
222
223
224
225
226
227
228
229
230 public final String getValueAttribute() {
231 String value = getAttributeDirect(VALUE_ATTRIBUTE);
232 if (ATTRIBUTE_NOT_DEFINED == value) {
233 value = getText();
234 }
235 return value;
236 }
237
238
239
240
241
242
243
244
245 public final void setValueAttribute(final String newValue) {
246 setAttribute(VALUE_ATTRIBUTE, newValue);
247 }
248
249
250
251
252
253 @Override
254 protected boolean doClickStateUpdate(final boolean shiftKey, final boolean ctrlKey) throws IOException {
255 boolean changed = false;
256 if (!isSelected()) {
257 setSelected(true, true, true, shiftKey, ctrlKey);
258 changed = true;
259 }
260 else if (getEnclosingSelect().isMultipleSelectEnabled()) {
261 if (ctrlKey) {
262 setSelected(false, true, true, shiftKey, ctrlKey);
263 changed = true;
264 }
265 else {
266 getEnclosingSelect().setOnlySelected(this, true);
267 }
268 }
269 super.doClickStateUpdate(shiftKey, ctrlKey);
270 return changed;
271 }
272
273
274
275
276 @Override
277 protected boolean isStateUpdateFirst() {
278 return true;
279 }
280
281
282
283
284 @Override
285 protected void printOpeningTagContentAsXml(final PrintWriter printWriter) {
286 super.printOpeningTagContentAsXml(printWriter);
287 if (selected_ && getAttributeDirect("selected") == ATTRIBUTE_NOT_DEFINED) {
288 printWriter.print(" selected=\"selected\"");
289 }
290 }
291
292
293
294
295
296
297 void setSelectedInternal(final boolean selected) {
298 selected_ = selected;
299 }
300
301
302
303
304
305 public void setText(final String text) {
306 if (text == null || text.isEmpty()) {
307 removeAllChildren();
308 }
309 else {
310 final DomNode child = getFirstChild();
311 if (child == null) {
312 appendChild(new DomText(getPage(), text));
313 }
314 else {
315 child.setNodeValue(text);
316 }
317 }
318 }
319
320
321
322
323
324 public String getText() {
325 final HtmlSerializerNormalizedText ser = new HtmlSerializerNormalizedText();
326 ser.setIgnoreMaskedElements(false);
327 return ser.asText(this);
328 }
329
330
331
332
333 @Override
334 public Page mouseOver(final boolean shiftKey, final boolean ctrlKey, final boolean altKey, final int button) {
335
336
337 getEnclosingSelect().mouseOver(shiftKey, ctrlKey, altKey, button);
338
339 return super.mouseOver(shiftKey, ctrlKey, altKey, button);
340 }
341
342
343
344
345 @Override
346 public DisplayStyle getDefaultStyleDisplay() {
347 return DisplayStyle.BLOCK;
348 }
349
350
351
352
353 @Override
354 public boolean handles(final Event event) {
355 if (MouseEvent.TYPE_MOUSE_OVER.equals(event.getType())) {
356 return true;
357 }
358 return super.handles(event);
359 }
360
361
362
363
364 @Override
365 protected void basicRemove() {
366 final DomNode parent = getParentNode();
367 super.basicRemove();
368
369 if (parent != null && isSelected()) {
370
371 parent.onAllChildrenAddedToPage(false);
372 }
373 }
374 }