OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). | 2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
3 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 3 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
4 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 4 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
5 * (C) 2001 Dirk Mueller (mueller@kde.org) | 5 * (C) 2001 Dirk Mueller (mueller@kde.org) |
6 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights
reserved. | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights
reserved. |
7 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 7 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
8 * Copyright (C) 2010 Google Inc. All rights reserved. | 8 * Copyright (C) 2010 Google Inc. All rights reserved. |
9 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) | 9 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) |
10 * | 10 * |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 | 273 |
274 String HTMLSelectElement::value() const | 274 String HTMLSelectElement::value() const |
275 { | 275 { |
276 if (HTMLOptionElement* option = selectedOption()) | 276 if (HTMLOptionElement* option = selectedOption()) |
277 return option->value(); | 277 return option->value(); |
278 return ""; | 278 return ""; |
279 } | 279 } |
280 | 280 |
281 void HTMLSelectElement::setValue(const String &value, bool sendEvents) | 281 void HTMLSelectElement::setValue(const String &value, bool sendEvents) |
282 { | 282 { |
283 // We clear the previously selected option(s) when needed, to guarantee | |
284 // calling setSelectedIndex() only once. | |
285 int optionIndex = 0; | |
286 HTMLOptionElement* option = nullptr; | 283 HTMLOptionElement* option = nullptr; |
287 if (value.isNull()) { | 284 // Find the option with value() matching the given parameter and make it the |
288 optionIndex = -1; | 285 // current selection. |
289 } else { | 286 for (const auto& item : optionList()) { |
290 // Find the option with value() matching the given parameter and make it | 287 if (item->value() == value) { |
291 // the current selection. | 288 option = item; |
292 for (auto& item : listItems()) { | 289 break; |
293 if (!isHTMLOptionElement(item)) | |
294 continue; | |
295 if (toHTMLOptionElement(item)->value() == value) { | |
296 option = toHTMLOptionElement(item); | |
297 break; | |
298 } | |
299 optionIndex++; | |
300 } | 290 } |
301 if (optionIndex >= static_cast<int>(listItems().size())) | |
302 optionIndex = -1; | |
303 } | 291 } |
304 | 292 |
305 int previousSelectedIndex = selectedIndex(); | 293 HTMLOptionElement* previousSelectedOption = selectedOption(); |
306 setSuggestedOption(nullptr); | 294 setSuggestedOption(nullptr); |
307 if (m_isAutofilledByPreview) | 295 if (m_isAutofilledByPreview) |
308 setAutofilled(false); | 296 setAutofilled(false); |
309 SelectOptionFlags flags = DeselectOtherOptions | MakeOptionDirty; | 297 SelectOptionFlags flags = DeselectOtherOptions | MakeOptionDirty; |
310 if (sendEvents) | 298 if (sendEvents) |
311 flags |= DispatchInputAndChangeEvent; | 299 flags |= DispatchInputAndChangeEvent; |
312 selectOption(option, flags); | 300 selectOption(option, flags); |
313 | 301 |
314 if (sendEvents && previousSelectedIndex != selectedIndex() && !usesMenuList(
)) | 302 if (sendEvents && previousSelectedOption != option && !usesMenuList()) |
315 listBoxOnChange(); | 303 listBoxOnChange(); |
316 } | 304 } |
317 | 305 |
318 String HTMLSelectElement::suggestedValue() const | 306 String HTMLSelectElement::suggestedValue() const |
319 { | 307 { |
320 return m_suggestedOption ? m_suggestedOption->value() : ""; | 308 return m_suggestedOption ? m_suggestedOption->value() : ""; |
321 } | 309 } |
322 | 310 |
323 void HTMLSelectElement::setSuggestedValue(const String& value) | 311 void HTMLSelectElement::setSuggestedValue(const String& value) |
324 { | 312 { |
325 if (value.isNull()) { | 313 if (value.isNull()) { |
326 setSuggestedOption(nullptr); | 314 setSuggestedOption(nullptr); |
327 return; | 315 return; |
328 } | 316 } |
329 | 317 |
330 for (auto& item : listItems()) { | 318 for (const auto& option : optionList()) { |
331 if (!isHTMLOptionElement(item)) | 319 if (option->value() == value) { |
332 continue; | 320 setSuggestedOption(option); |
333 if (toHTMLOptionElement(item)->value() == value) { | |
334 setSuggestedOption(toHTMLOptionElement(item)); | |
335 m_isAutofilledByPreview = true; | 321 m_isAutofilledByPreview = true; |
336 return; | 322 return; |
337 } | 323 } |
338 } | 324 } |
339 | 325 |
340 setSuggestedOption(nullptr); | 326 setSuggestedOption(nullptr); |
341 } | 327 } |
342 | 328 |
343 bool HTMLSelectElement::isPresentationAttribute(const QualifiedName& name) const | 329 bool HTMLSelectElement::isPresentationAttribute(const QualifiedName& name) const |
344 { | 330 { |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 if (diff < 0) { // Add dummy elements. | 476 if (diff < 0) { // Add dummy elements. |
491 do { | 477 do { |
492 appendChild(document().createElement(optionTag, CreatedByCreateEleme
nt), exceptionState); | 478 appendChild(document().createElement(optionTag, CreatedByCreateEleme
nt), exceptionState); |
493 if (exceptionState.hadException()) | 479 if (exceptionState.hadException()) |
494 break; | 480 break; |
495 } while (++diff); | 481 } while (++diff); |
496 } else { | 482 } else { |
497 // Removing children fires mutation events, which might mutate the DOM | 483 // Removing children fires mutation events, which might mutate the DOM |
498 // further, so we first copy out a list of elements that we intend to | 484 // further, so we first copy out a list of elements that we intend to |
499 // remove then attempt to remove them one at a time. | 485 // remove then attempt to remove them one at a time. |
500 HeapVector<Member<Element>> itemsToRemove; | 486 HeapVector<Member<HTMLOptionElement>> itemsToRemove; |
501 size_t optionIndex = 0; | 487 size_t optionIndex = 0; |
502 for (auto& item : listItems()) { | 488 for (const auto& option : optionList()) { |
503 if (isHTMLOptionElement(item) && optionIndex++ >= newLen) { | 489 if (optionIndex++ >= newLen) { |
504 ASSERT(item->parentNode()); | 490 DCHECK(option->parentNode()); |
505 itemsToRemove.append(item.get()); | 491 itemsToRemove.append(option); |
506 } | 492 } |
507 } | 493 } |
508 | 494 |
509 for (auto& item : itemsToRemove) { | 495 for (auto& item : itemsToRemove) { |
510 if (item->parentNode()) | 496 if (item->parentNode()) |
511 item->parentNode()->removeChild(item.get(), exceptionState); | 497 item->parentNode()->removeChild(item.get(), exceptionState); |
512 } | 498 } |
513 } | 499 } |
514 setNeedsValidityCheck(); | 500 setNeedsValidityCheck(); |
515 } | 501 } |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
881 return option; | 867 return option; |
882 } | 868 } |
883 return nullptr; | 869 return nullptr; |
884 } | 870 } |
885 | 871 |
886 int HTMLSelectElement::selectedIndex() const | 872 int HTMLSelectElement::selectedIndex() const |
887 { | 873 { |
888 unsigned index = 0; | 874 unsigned index = 0; |
889 | 875 |
890 // Return the number of the first option selected. | 876 // Return the number of the first option selected. |
891 for (auto& element : listItems()) { | 877 for (const auto& option : optionList()) { |
892 if (!isHTMLOptionElement(*element)) | 878 if (option->selected()) |
893 continue; | |
894 if (toHTMLOptionElement(*element).selected()) | |
895 return index; | 879 return index; |
896 ++index; | 880 ++index; |
897 } | 881 } |
898 | 882 |
899 return -1; | 883 return -1; |
900 } | 884 } |
901 | 885 |
902 void HTMLSelectElement::setSelectedIndex(int index) | 886 void HTMLSelectElement::setSelectedIndex(int index) |
903 { | 887 { |
904 selectOption(item(index), DeselectOtherOptions | MakeOptionDirty); | 888 selectOption(item(index), DeselectOtherOptions | MakeOptionDirty); |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1250 resetToDefaultSelection(); | 1234 resetToDefaultSelection(); |
1251 } | 1235 } |
1252 } | 1236 } |
1253 | 1237 |
1254 void HTMLSelectElement::appendToFormData(FormData& formData) | 1238 void HTMLSelectElement::appendToFormData(FormData& formData) |
1255 { | 1239 { |
1256 const AtomicString& name = this->name(); | 1240 const AtomicString& name = this->name(); |
1257 if (name.isEmpty()) | 1241 if (name.isEmpty()) |
1258 return; | 1242 return; |
1259 | 1243 |
1260 for (auto& element : listItems()) { | 1244 for (const auto& option : optionList()) { |
1261 if (isHTMLOptionElement(*element) && toHTMLOptionElement(*element).selec
ted() && !toHTMLOptionElement(*element).isDisabledFormControl()) | 1245 if (option->selected() && !option->isDisabledFormControl()) |
1262 formData.append(name, toHTMLOptionElement(*element).value()); | 1246 formData.append(name, option->value()); |
1263 } | 1247 } |
1264 } | 1248 } |
1265 | 1249 |
1266 void HTMLSelectElement::resetImpl() | 1250 void HTMLSelectElement::resetImpl() |
1267 { | 1251 { |
1268 for (auto& item : listItems()) { | 1252 for (const auto& option : optionList()) { |
1269 if (!isHTMLOptionElement(item)) | |
1270 continue; | |
1271 HTMLOptionElement* option = toHTMLOptionElement(item); | |
1272 option->setSelectedState(option->fastHasAttribute(selectedAttr)); | 1253 option->setSelectedState(option->fastHasAttribute(selectedAttr)); |
1273 option->setDirty(false); | 1254 option->setDirty(false); |
1274 } | 1255 } |
1275 resetToDefaultSelection(); | 1256 resetToDefaultSelection(); |
1276 setNeedsValidityCheck(); | 1257 setNeedsValidityCheck(); |
1277 } | 1258 } |
1278 | 1259 |
1279 void HTMLSelectElement::handlePopupOpenKeyboardEvent(Event* event) | 1260 void HTMLSelectElement::handlePopupOpenKeyboardEvent(Event* event) |
1280 { | 1261 { |
1281 focus(); | 1262 focus(); |
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1780 option->setDirty(true); | 1761 option->setDirty(true); |
1781 if (usesMenuList()) | 1762 if (usesMenuList()) |
1782 return; | 1763 return; |
1783 listBoxOnChange(); | 1764 listBoxOnChange(); |
1784 scrollToSelection(); | 1765 scrollToSelection(); |
1785 } | 1766 } |
1786 | 1767 |
1787 unsigned HTMLSelectElement::length() const | 1768 unsigned HTMLSelectElement::length() const |
1788 { | 1769 { |
1789 unsigned options = 0; | 1770 unsigned options = 0; |
1790 for (auto& item : listItems()) { | 1771 for (const auto& option : optionList()) { |
1791 if (isHTMLOptionElement(*item)) | 1772 ALLOW_UNUSED_LOCAL(option); |
1792 ++options; | 1773 ++options; |
1793 } | 1774 } |
1794 return options; | 1775 return options; |
1795 } | 1776 } |
1796 | 1777 |
1797 void HTMLSelectElement::finishParsingChildren() | 1778 void HTMLSelectElement::finishParsingChildren() |
1798 { | 1779 { |
1799 HTMLFormControlElementWithState::finishParsingChildren(); | 1780 HTMLFormControlElementWithState::finishParsingChildren(); |
1800 if (usesMenuList()) | 1781 if (usesMenuList()) |
1801 return; | 1782 return; |
1802 scrollToOption(selectedOption()); | 1783 scrollToOption(selectedOption()); |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2088 } | 2069 } |
2089 | 2070 |
2090 void HTMLSelectElement::didMutateSubtree() | 2071 void HTMLSelectElement::didMutateSubtree() |
2091 { | 2072 { |
2092 DCHECK(popupIsVisible()); | 2073 DCHECK(popupIsVisible()); |
2093 DCHECK(m_popup); | 2074 DCHECK(m_popup); |
2094 m_popup->updateFromElement(PopupMenu::ByDOMChange); | 2075 m_popup->updateFromElement(PopupMenu::ByDOMChange); |
2095 } | 2076 } |
2096 | 2077 |
2097 } // namespace blink | 2078 } // namespace blink |
OLD | NEW |