diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/WebCore/html/HTMLSelectElement.cpp | |
parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/WebCore/html/HTMLSelectElement.cpp')
-rw-r--r-- | Source/WebCore/html/HTMLSelectElement.cpp | 495 |
1 files changed, 253 insertions, 242 deletions
diff --git a/Source/WebCore/html/HTMLSelectElement.cpp b/Source/WebCore/html/HTMLSelectElement.cpp index aeded1236..2c2eb89a8 100644 --- a/Source/WebCore/html/HTMLSelectElement.cpp +++ b/Source/WebCore/html/HTMLSelectElement.cpp @@ -29,6 +29,7 @@ #include "HTMLSelectElement.h" #include "AXObjectCache.h" +#include "Attribute.h" #include "Chrome.h" #include "ChromeClient.h" #include "ElementTraversal.h" @@ -38,7 +39,6 @@ #include "FormController.h" #include "FormDataList.h" #include "Frame.h" -#include "GenericCachedHTMLCollection.h" #include "HTMLFormElement.h" #include "HTMLNames.h" #include "HTMLOptGroupElement.h" @@ -47,7 +47,6 @@ #include "KeyboardEvent.h" #include "LocalizedStrings.h" #include "MouseEvent.h" -#include "NodeRareData.h" #include "Page.h" #include "PlatformMouseEvent.h" #include "RenderListBox.h" @@ -81,10 +80,10 @@ HTMLSelectElement::HTMLSelectElement(const QualifiedName& tagName, Document& doc ASSERT(hasTagName(selectTag)); } -Ref<HTMLSelectElement> HTMLSelectElement::create(const QualifiedName& tagName, Document& document, HTMLFormElement* form) +PassRefPtr<HTMLSelectElement> HTMLSelectElement::create(const QualifiedName& tagName, Document& document, HTMLFormElement* form) { ASSERT(tagName.matches(selectTag)); - return adoptRef(*new HTMLSelectElement(tagName, document, form)); + return adoptRef(new HTMLSelectElement(tagName, document, form)); } void HTMLSelectElement::didRecalcStyle(Style::Change styleChange) @@ -97,15 +96,15 @@ void HTMLSelectElement::didRecalcStyle(Style::Change styleChange) const AtomicString& HTMLSelectElement::formControlType() const { - static NeverDestroyed<const AtomicString> selectMultiple("select-multiple", AtomicString::ConstructFromLiteral); - static NeverDestroyed<const AtomicString> selectOne("select-one", AtomicString::ConstructFromLiteral); + DEFINE_STATIC_LOCAL(const AtomicString, selectMultiple, ("select-multiple", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(const AtomicString, selectOne, ("select-one", AtomicString::ConstructFromLiteral)); return m_multiple ? selectMultiple : selectOne; } void HTMLSelectElement::deselectItems(HTMLOptionElement* excludeElement) { deselectItemsWithoutValidation(excludeElement); - updateValidity(); + setNeedsValidityCheck(); } void HTMLSelectElement::optionSelectedByUser(int optionIndex, bool fireOnChangeNow, bool allowMultipleSelection) @@ -114,7 +113,7 @@ void HTMLSelectElement::optionSelectedByUser(int optionIndex, bool fireOnChangeN // This produces that same behavior for changes triggered by other code running on behalf of the user. if (!usesMenuList()) { updateSelectedState(optionToListIndex(optionIndex), allowMultipleSelection, false); - updateValidity(); + setNeedsValidityCheck(); if (fireOnChangeNow) listBoxOnChange(); return; @@ -150,8 +149,8 @@ bool HTMLSelectElement::hasPlaceholderLabelOption() const ASSERT(listIndex >= 0); if (listIndex < 0) return false; - HTMLOptionElement& option = downcast<HTMLOptionElement>(*listItems()[listIndex]); - return !listIndex && option.value().isEmpty(); + HTMLOptionElement* option = toHTMLOptionElement(listItems()[listIndex]); + return !listIndex && option->value().isEmpty(); } String HTMLSelectElement::validationMessage() const @@ -185,7 +184,7 @@ void HTMLSelectElement::listBoxSelectItem(int listIndex, bool allowMultiplySelec optionSelectedByUser(listToOptionIndex(listIndex), fireOnChangeNow, false); else { updateSelectedState(listIndex, allowMultiplySelections, shift); - updateValidity(); + setNeedsValidityCheck(); if (fireOnChangeNow) listBoxOnChange(); } @@ -219,21 +218,16 @@ int HTMLSelectElement::activeSelectionEndListIndex() const return lastSelectedListIndex(); } -void HTMLSelectElement::add(HTMLElement* element, HTMLElement* beforeElement, ExceptionCode& ec) +void HTMLSelectElement::add(HTMLElement* element, HTMLElement* before, ExceptionCode& ec) { - if (!element || !(is<HTMLOptionElement>(*element) || element->hasTagName(hrTag) || is<HTMLOptGroupElement>(*element))) + if (!element || !(element->hasLocalName(optionTag) || element->hasLocalName(hrTag))) return; // Make sure the element is ref'd and deref'd so we don't leak it. Ref<HTMLElement> protectNewChild(*element); - insertBefore(*element, beforeElement, ec); - updateValidity(); -} - -void HTMLSelectElement::add(HTMLElement* element, int beforeIndex, ExceptionCode& ec) -{ - add(element, item(beforeIndex), ec); + insertBefore(element, before, ec); + setNeedsValidityCheck(); } void HTMLSelectElement::removeByIndex(int optionIndex) @@ -255,14 +249,15 @@ void HTMLSelectElement::remove(HTMLOptionElement* option) String HTMLSelectElement::value() const { - for (auto* item : listItems()) { - if (is<HTMLOptionElement>(*item)) { - HTMLOptionElement& option = downcast<HTMLOptionElement>(*item); - if (option.selected()) - return option.value(); + const Vector<HTMLElement*>& items = listItems(); + for (unsigned i = 0; i < items.size(); i++) { + if (items[i]->hasLocalName(optionTag)) { + HTMLOptionElement* option = toHTMLOptionElement(items[i]); + if (option->selected()) + return option->value(); } } - return emptyString(); + return ""; } void HTMLSelectElement::setValue(const String &value) @@ -274,14 +269,15 @@ void HTMLSelectElement::setValue(const String &value) } // Find the option with value() matching the given parameter and make it the current selection. + const Vector<HTMLElement*>& items = listItems(); unsigned optionIndex = 0; - for (auto* item : listItems()) { - if (is<HTMLOptionElement>(*item)) { - if (downcast<HTMLOptionElement>(*item).value() == value) { + for (unsigned i = 0; i < items.size(); i++) { + if (items[i]->hasLocalName(optionTag)) { + if (toHTMLOptionElement(items[i])->value() == value) { setSelectedIndex(optionIndex); return; } - ++optionIndex; + optionIndex++; } } @@ -312,14 +308,14 @@ void HTMLSelectElement::parseAttribute(const QualifiedName& name, const AtomicSt if (Attribute* sizeAttribute = ensureUniqueElementData().findAttributeByName(sizeAttr)) sizeAttribute->setValue(attrSize); } - size = std::max(size, 0); + size = std::max(size, 1); // Ensure that we've determined selectedness of the items at least once prior to changing the size. if (oldSize != size) updateListItemSelectedStates(); m_size = size; - updateValidity(); + setNeedsValidityCheck(); if (m_size != oldSize) { setNeedsStyleRecalc(ReconstructRenderTree); setRecalcListItems(); @@ -352,14 +348,14 @@ bool HTMLSelectElement::canSelectAll() const return !usesMenuList(); } -RenderPtr<RenderElement> HTMLSelectElement::createElementRenderer(Ref<RenderStyle>&& style, const RenderTreePosition&) +RenderPtr<RenderElement> HTMLSelectElement::createElementRenderer(PassRef<RenderStyle> style) { #if !PLATFORM(IOS) if (usesMenuList()) - return createRenderer<RenderMenuList>(*this, WTFMove(style)); - return createRenderer<RenderListBox>(*this, WTFMove(style)); + return createRenderer<RenderMenuList>(*this, std::move(style)); + return createRenderer<RenderListBox>(*this, std::move(style)); #else - return createRenderer<RenderMenuList>(*this, WTFMove(style)); + return createRenderer<RenderMenuList>(*this, std::move(style)); #endif } @@ -369,19 +365,19 @@ bool HTMLSelectElement::childShouldCreateRenderer(const Node& child) const return false; #if !PLATFORM(IOS) if (!usesMenuList()) - return is<HTMLOptionElement>(child) || is<HTMLOptGroupElement>(child) || validationMessageShadowTreeContains(child); + return isHTMLOptionElement(child) || isHTMLOptGroupElement(child) || validationMessageShadowTreeContains(child); #endif return validationMessageShadowTreeContains(child); } -Ref<HTMLCollection> HTMLSelectElement::selectedOptions() +PassRefPtr<HTMLCollection> HTMLSelectElement::selectedOptions() { - return ensureRareData().ensureNodeLists().addCachedCollection<GenericCachedHTMLCollection<CollectionTypeTraits<SelectedOptions>::traversalType>>(*this, SelectedOptions); + return ensureCachedHTMLCollection(SelectedOptions); } -Ref<HTMLOptionsCollection> HTMLSelectElement::options() +PassRefPtr<HTMLOptionsCollection> HTMLSelectElement::options() { - return ensureRareData().ensureNodeLists().addCachedCollection<HTMLOptionsCollection>(*this, SelectOptions); + return static_cast<HTMLOptionsCollection*>(ensureCachedHTMLCollection(SelectOptions).get()); } void HTMLSelectElement::updateListItemSelectedStates() @@ -393,7 +389,7 @@ void HTMLSelectElement::updateListItemSelectedStates() void HTMLSelectElement::childrenChanged(const ChildChange& change) { setRecalcListItems(); - updateValidity(); + setNeedsValidityCheck(); m_lastOnChangeSelection.clear(); HTMLFormControlElementWithState::childrenChanged(change); @@ -402,7 +398,7 @@ void HTMLSelectElement::childrenChanged(const ChildChange& change) void HTMLSelectElement::optionElementChildrenChanged() { setRecalcListItems(); - updateValidity(); + setNeedsValidityCheck(); if (renderer()) { if (AXObjectCache* cache = renderer()->document().existingAXObjectCache()) @@ -433,12 +429,12 @@ void HTMLSelectElement::setSize(int size) setIntegralAttribute(sizeAttr, size); } -HTMLOptionElement* HTMLSelectElement::namedItem(const AtomicString& name) +Node* HTMLSelectElement::namedItem(const AtomicString& name) { return options()->namedItem(name); } -HTMLOptionElement* HTMLSelectElement::item(unsigned index) +Node* HTMLSelectElement::item(unsigned index) { return options()->item(index); } @@ -449,13 +445,13 @@ void HTMLSelectElement::setOption(unsigned index, HTMLOptionElement* option, Exc if (index > maxSelectItems - 1) index = maxSelectItems - 1; int diff = index - length(); - RefPtr<HTMLOptionElement> before; + RefPtr<HTMLElement> before = 0; // Out of array bounds? First insert empty dummies. if (diff > 0) { setLength(index, ec); // Replace an existing entry? } else if (diff < 0) { - before = item(index + 1); + before = toHTMLElement(options()->item(index+1)); removeByIndex(index); } // Finally add the new element. @@ -477,7 +473,7 @@ void HTMLSelectElement::setLength(unsigned newLen, ExceptionCode& ec) do { RefPtr<Element> option = document().createElement(optionTag, false); ASSERT(option); - add(downcast<HTMLElement>(option.get()), nullptr, ec); + add(toHTMLElement(option.get()), 0, ec); if (ec) break; } while (++diff); @@ -486,21 +482,23 @@ void HTMLSelectElement::setLength(unsigned newLen, ExceptionCode& ec) // Removing children fires mutation events, which might mutate the DOM further, so we first copy out a list // of elements that we intend to remove then attempt to remove them one at a time. - Vector<Ref<Element>> itemsToRemove; + Vector<RefPtr<Element>> itemsToRemove; size_t optionIndex = 0; - for (auto& item : items) { - if (is<HTMLOptionElement>(*item) && optionIndex++ >= newLen) { + for (size_t i = 0; i < items.size(); ++i) { + Element* item = items[i]; + if (item->hasLocalName(optionTag) && optionIndex++ >= newLen) { ASSERT(item->parentNode()); - itemsToRemove.append(*item); + itemsToRemove.append(item); } } - for (auto& item : itemsToRemove) { + for (size_t i = 0; i < itemsToRemove.size(); ++i) { + Element* item = itemsToRemove[i].get(); if (item->parentNode()) - item->parentNode()->removeChild(item.get(), ec); + item->parentNode()->removeChild(item, ec); } } - updateValidity(); + setNeedsValidityCheck(); } bool HTMLSelectElement::isRequiredFormControl() const @@ -527,7 +525,7 @@ int HTMLSelectElement::nextValidIndex(int listIndex, SkipDirection direction, in int size = listItems.size(); for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex += direction) { --skip; - if (!listItems[listIndex]->isDisabledFormControl() && is<HTMLOptionElement>(*listItems[listIndex])) { + if (!listItems[listIndex]->isDisabledFormControl() && isHTMLOptionElement(listItems[listIndex])) { lastGoodIndex = listIndex; if (skip <= 0) break; @@ -568,14 +566,14 @@ int HTMLSelectElement::nextSelectableListIndexPageAway(int startIndex, SkipDirec const Vector<HTMLElement*>& items = listItems(); // Can't use m_size because renderer forces a minimum size. int pageSize = 0; - if (is<RenderListBox>(*renderer())) - pageSize = downcast<RenderListBox>(*renderer()).size() - 1; // -1 so we still show context. + if (renderer()->isListBox()) + pageSize = toRenderListBox(renderer())->size() - 1; // -1 so we still show context. // One page away, but not outside valid bounds. // If there is a valid option item one page away, the index is chosen. // If there is no exact one page away valid option, returns startIndex or the most far index. - int edgeIndex = direction == SkipForwards ? 0 : items.size() - 1; - int skipAmount = pageSize + (direction == SkipForwards ? startIndex : edgeIndex - startIndex); + int edgeIndex = (direction == SkipForwards) ? 0 : (items.size() - 1); + int skipAmount = pageSize + ((direction == SkipForwards) ? startIndex : (edgeIndex - startIndex)); return nextValidIndex(edgeIndex, direction, skipAmount); } @@ -597,7 +595,7 @@ void HTMLSelectElement::selectAll() updateListBoxSelection(false); listBoxOnChange(); - updateValidity(); + setNeedsValidityCheck(); } void HTMLSelectElement::saveLastSelection() @@ -608,8 +606,11 @@ void HTMLSelectElement::saveLastSelection() } m_lastOnChangeSelection.clear(); - for (auto& element : listItems()) - m_lastOnChangeSelection.append(is<HTMLOptionElement>(*element) && downcast<HTMLOptionElement>(*element).selected()); + const Vector<HTMLElement*>& items = listItems(); + for (unsigned i = 0; i < items.size(); ++i) { + HTMLElement* element = items[i]; + m_lastOnChangeSelection.append(isHTMLOptionElement(element) && toHTMLOptionElement(element)->selected()); + } } void HTMLSelectElement::setActiveSelectionAnchorIndex(int index) @@ -620,8 +621,11 @@ void HTMLSelectElement::setActiveSelectionAnchorIndex(int index) // selection pivots around this anchor index. m_cachedStateForActiveSelection.clear(); - for (auto& element : listItems()) - m_cachedStateForActiveSelection.append(is<HTMLOptionElement>(*element) && downcast<HTMLOptionElement>(*element).selected()); + const Vector<HTMLElement*>& items = listItems(); + for (unsigned i = 0; i < items.size(); ++i) { + HTMLElement* element = items[i]; + m_cachedStateForActiveSelection.append(isHTMLOptionElement(element) && toHTMLOptionElement(element)->selected()); + } } void HTMLSelectElement::setActiveSelectionEndIndex(int index) @@ -644,19 +648,20 @@ void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions) const Vector<HTMLElement*>& items = listItems(); for (unsigned i = 0; i < items.size(); ++i) { HTMLElement* element = items[i]; - if (!is<HTMLOptionElement>(*element) || downcast<HTMLOptionElement>(*element).isDisabledFormControl()) + if (!isHTMLOptionElement(element) || toHTMLOptionElement(element)->isDisabledFormControl()) continue; if (i >= start && i <= end) - downcast<HTMLOptionElement>(*element).setSelectedState(m_activeSelectionState); + toHTMLOptionElement(element)->setSelectedState(m_activeSelectionState); else if (deselectOtherOptions || i >= m_cachedStateForActiveSelection.size()) - downcast<HTMLOptionElement>(*element).setSelectedState(false); + toHTMLOptionElement(element)->setSelectedState(false); else - downcast<HTMLOptionElement>(*element).setSelectedState(m_cachedStateForActiveSelection[i]); + toHTMLOptionElement(element)->setSelectedState(m_cachedStateForActiveSelection[i]); } scrollToSelection(); - updateValidity(); + setNeedsValidityCheck(); + notifyFormStateChanged(); } void HTMLSelectElement::listBoxOnChange() @@ -676,16 +681,14 @@ void HTMLSelectElement::listBoxOnChange() bool fireOnChange = false; for (unsigned i = 0; i < items.size(); ++i) { HTMLElement* element = items[i]; - bool selected = is<HTMLOptionElement>(*element) && downcast<HTMLOptionElement>(*element).selected(); + bool selected = isHTMLOptionElement(element) && toHTMLOptionElement(element)->selected(); if (selected != m_lastOnChangeSelection[i]) fireOnChange = true; m_lastOnChangeSelection[i] = selected; } - if (fireOnChange) { - dispatchInputEvent(); + if (fireOnChange) dispatchFormControlChangeEvent(); - } } void HTMLSelectElement::dispatchChangeEventForMenuList() @@ -696,7 +699,6 @@ void HTMLSelectElement::dispatchChangeEventForMenuList() if (m_lastOnChangeIndex != selected && m_isProcessingUserDrivenChange) { m_lastOnChangeIndex = selected; m_isProcessingUserDrivenChange = false; - dispatchInputEvent(); dispatchFormControlChangeEvent(); } } @@ -707,26 +709,26 @@ void HTMLSelectElement::scrollToSelection() if (usesMenuList()) return; - auto* renderer = this->renderer(); - if (!is<RenderListBox>(renderer)) + auto renderer = this->renderer(); + if (!renderer || !renderer->isListBox()) return; - downcast<RenderListBox>(*renderer).selectionChanged(); + toRenderListBox(renderer)->selectionChanged(); #else - if (auto* renderer = this->renderer()) + if (auto renderer = this->renderer()) renderer->repaint(); #endif } void HTMLSelectElement::setOptionsChangedOnRenderer() { - if (auto* renderer = this->renderer()) { + if (auto renderer = this->renderer()) { #if !PLATFORM(IOS) - if (is<RenderMenuList>(*renderer)) - downcast<RenderMenuList>(*renderer).setOptionsChanged(true); + if (renderer->isMenuList()) + toRenderMenuList(renderer)->setOptionsChanged(true); else - downcast<RenderListBox>(*renderer).setOptionsChanged(true); + toRenderListBox(renderer)->setOptionsChanged(true); #else - downcast<RenderMenuList>(*renderer).setOptionsChanged(true); + toRenderMenuList(renderer)->setOptionsChanged(true); #endif } } @@ -749,7 +751,7 @@ const Vector<HTMLElement*>& HTMLSelectElement::listItems() const void HTMLSelectElement::invalidateSelectedItems() { if (HTMLCollection* collection = cachedHTMLCollection(SelectedOptions)) - collection->invalidateCache(document()); + collection->invalidateCache(); } void HTMLSelectElement::setRecalcListItems() @@ -761,7 +763,7 @@ void HTMLSelectElement::setRecalcListItems() setNeedsStyleRecalc(); if (!inDocument()) { if (HTMLCollection* collection = cachedHTMLCollection(SelectOptions)) - collection->invalidateCache(document()); + collection->invalidateCache(); } if (!inDocument()) invalidateSelectedItems(); @@ -780,44 +782,44 @@ void HTMLSelectElement::recalcListItems(bool updateSelectedStates) const HTMLOptionElement* foundSelected = 0; HTMLOptionElement* firstOption = 0; - for (Element* currentElement = ElementTraversal::firstWithin(*this); currentElement; ) { - if (!is<HTMLElement>(*currentElement)) { - currentElement = ElementTraversal::nextSkippingChildren(*currentElement, this); + for (Element* currentElement = ElementTraversal::firstWithin(this); currentElement; ) { + if (!currentElement->isHTMLElement()) { + currentElement = ElementTraversal::nextSkippingChildren(currentElement, this); continue; } - HTMLElement& current = downcast<HTMLElement>(*currentElement); + HTMLElement* current = toHTMLElement(currentElement); // optgroup tags may not nest. However, both FireFox and IE will // flatten the tree automatically, so we follow suit. // (http://www.w3.org/TR/html401/interact/forms.html#h-17.6) - if (is<HTMLOptGroupElement>(current)) { - m_listItems.append(¤t); + if (isHTMLOptGroupElement(current)) { + m_listItems.append(current); if (Element* nextElement = ElementTraversal::firstWithin(current)) { currentElement = nextElement; continue; } } - if (is<HTMLOptionElement>(current)) { - m_listItems.append(¤t); + if (isHTMLOptionElement(current)) { + m_listItems.append(current); if (updateSelectedStates && !m_multiple) { - HTMLOptionElement& option = downcast<HTMLOptionElement>(current); + HTMLOptionElement* option = toHTMLOptionElement(current); if (!firstOption) - firstOption = &option; - if (option.selected()) { + firstOption = option; + if (option->selected()) { if (foundSelected) foundSelected->setSelectedState(false); - foundSelected = &option; - } else if (m_size <= 1 && !foundSelected && !option.isDisabledFormControl()) { - foundSelected = &option; + foundSelected = option; + } else if (m_size <= 1 && !foundSelected && !option->isDisabledFormControl()) { + foundSelected = option; foundSelected->setSelectedState(true); } } } - if (current.hasTagName(hrTag)) - m_listItems.append(¤t); + if (current->hasTagName(hrTag)) + m_listItems.append(current); // In conforming HTML code, only <optgroup> and <option> will be found // within a <select>. We call NodeTraversal::nextSkippingChildren so that we only step @@ -825,7 +827,7 @@ void HTMLSelectElement::recalcListItems(bool updateSelectedStates) const // with the case where odd tags like a <div> have been added but we // handle this because such tags have already been removed from the // <select>'s subtree at this point. - currentElement = ElementTraversal::nextSkippingChildren(*currentElement, this); + currentElement = ElementTraversal::nextSkippingChildren(currentElement, this); } if (!foundSelected && m_size <= 1 && firstOption && !firstOption->selected()) @@ -837,9 +839,11 @@ int HTMLSelectElement::selectedIndex() const unsigned index = 0; // Return the number of the first option selected. - for (auto& element : listItems()) { - if (is<HTMLOptionElement>(*element)) { - if (downcast<HTMLOptionElement>(*element).selected()) + const Vector<HTMLElement*>& items = listItems(); + for (size_t i = 0; i < items.size(); ++i) { + HTMLElement* element = items[i]; + if (isHTMLOptionElement(element)) { + if (toHTMLOptionElement(element)->selected()) return index; ++index; } @@ -871,26 +875,23 @@ void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags) const Vector<HTMLElement*>& items = listItems(); int listIndex = optionToListIndex(optionIndex); - HTMLElement* element = nullptr; + HTMLElement* element = 0; if (listIndex >= 0) { element = items[listIndex]; + if (isHTMLOptionElement(element)) { + if (m_activeSelectionAnchorIndex < 0 || shouldDeselect) + setActiveSelectionAnchorIndex(listIndex); + if (m_activeSelectionEndIndex < 0 || shouldDeselect) + setActiveSelectionEndIndex(listIndex); + toHTMLOptionElement(element)->setSelectedState(true); + } } if (shouldDeselect) deselectItemsWithoutValidation(element); - if (is<HTMLOptionElement>(element)) { - if (m_activeSelectionAnchorIndex < 0 || shouldDeselect) - setActiveSelectionAnchorIndex(listIndex); - if (m_activeSelectionEndIndex < 0 || shouldDeselect) - setActiveSelectionEndIndex(listIndex); - downcast<HTMLOptionElement>(*element).setSelectedState(true); - } - - updateValidity(); - // For the menu list case, this is what makes the selected element appear. - if (auto* renderer = this->renderer()) + if (auto renderer = this->renderer()) renderer->updateFromElement(); scrollToSelection(); @@ -899,13 +900,16 @@ void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags) m_isProcessingUserDrivenChange = flags & UserDriven; if (flags & DispatchChangeEvent) dispatchChangeEventForMenuList(); - if (auto* renderer = this->renderer()) { - if (is<RenderMenuList>(*renderer)) - downcast<RenderMenuList>(*renderer).didSetSelectedIndex(listIndex); + if (auto renderer = this->renderer()) { + if (renderer->isMenuList()) + toRenderMenuList(renderer)->didSetSelectedIndex(listIndex); else - downcast<RenderListBox>(*renderer).selectionChanged(); + toRenderListBox(renderer)->selectionChanged(); } } + + setNeedsValidityCheck(); + notifyFormStateChanged(); } int HTMLSelectElement::optionToListIndex(int optionIndex) const @@ -917,7 +921,7 @@ int HTMLSelectElement::optionToListIndex(int optionIndex) const int optionIndex2 = -1; for (int listIndex = 0; listIndex < listSize; ++listIndex) { - if (is<HTMLOptionElement>(*items[listIndex])) { + if (isHTMLOptionElement(items[listIndex])) { ++optionIndex2; if (optionIndex2 == optionIndex) return listIndex; @@ -930,56 +934,60 @@ int HTMLSelectElement::optionToListIndex(int optionIndex) const int HTMLSelectElement::listToOptionIndex(int listIndex) const { const Vector<HTMLElement*>& items = listItems(); - if (listIndex < 0 || listIndex >= static_cast<int>(items.size()) || !is<HTMLOptionElement>(*items[listIndex])) + if (listIndex < 0 || listIndex >= static_cast<int>(items.size()) || !isHTMLOptionElement(items[listIndex])) return -1; // Actual index of option not counting OPTGROUP entries that may be in list. int optionIndex = 0; for (int i = 0; i < listIndex; ++i) { - if (is<HTMLOptionElement>(*items[i])) + if (isHTMLOptionElement(items[i])) ++optionIndex; } return optionIndex; } -void HTMLSelectElement::dispatchFocusEvent(RefPtr<Element>&& oldFocusedElement, FocusDirection direction) +void HTMLSelectElement::dispatchFocusEvent(PassRefPtr<Element> oldFocusedElement, FocusDirection direction) { // Save the selection so it can be compared to the new selection when // dispatching change events during blur event dispatch. if (usesMenuList()) saveLastSelection(); - HTMLFormControlElementWithState::dispatchFocusEvent(WTFMove(oldFocusedElement), direction); + HTMLFormControlElementWithState::dispatchFocusEvent(oldFocusedElement, direction); } -void HTMLSelectElement::dispatchBlurEvent(RefPtr<Element>&& newFocusedElement) +void HTMLSelectElement::dispatchBlurEvent(PassRefPtr<Element> newFocusedElement) { // We only need to fire change events here for menu lists, because we fire // change events for list boxes whenever the selection change is actually made. // This matches other browsers' behavior. if (usesMenuList()) dispatchChangeEventForMenuList(); - HTMLFormControlElementWithState::dispatchBlurEvent(WTFMove(newFocusedElement)); + HTMLFormControlElementWithState::dispatchBlurEvent(newFocusedElement); } void HTMLSelectElement::deselectItemsWithoutValidation(HTMLElement* excludeElement) { - for (auto& element : listItems()) { - if (element != excludeElement && is<HTMLOptionElement>(*element)) - downcast<HTMLOptionElement>(*element).setSelectedState(false); + const Vector<HTMLElement*>& items = listItems(); + for (unsigned i = 0; i < items.size(); ++i) { + HTMLElement* element = items[i]; + if (element != excludeElement && isHTMLOptionElement(element)) + toHTMLOptionElement(element)->setSelectedState(false); } } FormControlState HTMLSelectElement::saveFormControlState() const { + const Vector<HTMLElement*>& items = listItems(); + size_t length = items.size(); FormControlState state; - for (auto& element : listItems()) { - if (!is<HTMLOptionElement>(*element)) + for (unsigned i = 0; i < length; ++i) { + if (!isHTMLOptionElement(items[i])) continue; - HTMLOptionElement& option = downcast<HTMLOptionElement>(*element); - if (!option.selected()) + HTMLOptionElement* option = toHTMLOptionElement(items[i]); + if (!option->selected()) continue; - state.append(option.value()); + state.append(option->value()); if (!multiple()) break; } @@ -991,9 +999,9 @@ size_t HTMLSelectElement::searchOptionsForValue(const String& value, size_t list const Vector<HTMLElement*>& items = listItems(); size_t loopEndIndex = std::min(items.size(), listIndexEnd); for (size_t i = listIndexStart; i < loopEndIndex; ++i) { - if (!is<HTMLOptionElement>(*items[i])) + if (!items[i]->hasLocalName(optionTag)) continue; - if (downcast<HTMLOptionElement>(*items[i]).value() == value) + if (toHTMLOptionElement(items[i])->value() == value) return i; } return notFound; @@ -1008,16 +1016,16 @@ void HTMLSelectElement::restoreFormControlState(const FormControlState& state) if (!itemsSize) return; - for (auto& element : items) { - if (!is<HTMLOptionElement>(*element)) + for (size_t i = 0; i < itemsSize; ++i) { + if (!items[i]->hasLocalName(optionTag)) continue; - downcast<HTMLOptionElement>(*element).setSelectedState(false); + toHTMLOptionElement(items[i])->setSelectedState(false); } if (!multiple()) { size_t foundIndex = searchOptionsForValue(state[0], 0, itemsSize); if (foundIndex != notFound) - downcast<HTMLOptionElement>(*items[foundIndex]).setSelectedState(true); + toHTMLOptionElement(items[foundIndex])->setSelectedState(true); } else { size_t startIndex = 0; for (size_t i = 0; i < state.valueSize(); ++i) { @@ -1027,20 +1035,20 @@ void HTMLSelectElement::restoreFormControlState(const FormControlState& state) foundIndex = searchOptionsForValue(value, 0, startIndex); if (foundIndex == notFound) continue; - downcast<HTMLOptionElement>(*items[foundIndex]).setSelectedState(true); + toHTMLOptionElement(items[foundIndex])->setSelectedState(true); startIndex = foundIndex + 1; } } setOptionsChangedOnRenderer(); - updateValidity(); + setNeedsValidityCheck(); } void HTMLSelectElement::parseMultipleAttribute(const AtomicString& value) { bool oldUsesMenuList = usesMenuList(); m_multiple = !value.isNull(); - updateValidity(); + setNeedsValidityCheck(); if (oldUsesMenuList != usesMenuList()) setNeedsStyleRecalc(ReconstructRenderTree); } @@ -1052,9 +1060,12 @@ bool HTMLSelectElement::appendFormData(FormDataList& list, bool) return false; bool successful = false; - for (auto& element : listItems()) { - if (is<HTMLOptionElement>(*element) && downcast<HTMLOptionElement>(*element).selected() && !downcast<HTMLOptionElement>(*element).isDisabledFormControl()) { - list.appendData(name, downcast<HTMLOptionElement>(*element).value()); + const Vector<HTMLElement*>& items = listItems(); + + for (unsigned i = 0; i < items.size(); ++i) { + HTMLElement* element = items[i]; + if (isHTMLOptionElement(element) && toHTMLOptionElement(element)->selected() && !toHTMLOptionElement(element)->isDisabledFormControl()) { + list.appendData(name, toHTMLOptionElement(element)->value()); successful = true; } } @@ -1067,24 +1078,25 @@ bool HTMLSelectElement::appendFormData(FormDataList& list, bool) void HTMLSelectElement::reset() { - HTMLOptionElement* firstOption = nullptr; - HTMLOptionElement* selectedOption = nullptr; + HTMLOptionElement* firstOption = 0; + HTMLOptionElement* selectedOption = 0; - for (auto& element : listItems()) { - if (!is<HTMLOptionElement>(*element)) + const Vector<HTMLElement*>& items = listItems(); + for (unsigned i = 0; i < items.size(); ++i) { + HTMLElement* element = items[i]; + if (!isHTMLOptionElement(element)) continue; - HTMLOptionElement& option = downcast<HTMLOptionElement>(*element); - if (option.fastHasAttribute(selectedAttr)) { + if (items[i]->fastHasAttribute(selectedAttr)) { if (selectedOption && !m_multiple) selectedOption->setSelectedState(false); - option.setSelectedState(true); - selectedOption = &option; + toHTMLOptionElement(element)->setSelectedState(true); + selectedOption = toHTMLOptionElement(element); } else - option.setSelectedState(false); + toHTMLOptionElement(element)->setSelectedState(false); if (!firstOption) - firstOption = &option; + firstOption = toHTMLOptionElement(element); } if (!selectedOption && firstOption && !m_multiple && m_size <= 1) @@ -1092,7 +1104,7 @@ void HTMLSelectElement::reset() setOptionsChangedOnRenderer(); setNeedsStyleRecalc(); - updateValidity(); + setNeedsValidityCheck(); } #if !PLATFORM(WIN) @@ -1110,7 +1122,7 @@ bool HTMLSelectElement::platformHandleKeydownEvent(KeyboardEvent* event) // Calling focus() may cause us to lose our renderer. Return true so // that our caller doesn't process the event further, but don't set // the event as handled. - if (!is<RenderMenuList>(renderer())) + if (!renderer() || !renderer()->isMenuList()) return true; // Save the selection so it can be compared to the new selection @@ -1118,7 +1130,7 @@ bool HTMLSelectElement::platformHandleKeydownEvent(KeyboardEvent* event) // gets called from RenderMenuList::valueChanged, which gets called // after the user makes a selection from the menu. saveLastSelection(); - downcast<RenderMenuList>(*renderer()).showPopup(); + toRenderMenuList(renderer())->showPopup(); event->setDefaultHandled(); } return true; @@ -1136,11 +1148,10 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) RefPtr<RenderTheme> renderTheme = page ? &page->theme() : RenderTheme::defaultTheme(); if (event->type() == eventNames().keydownEvent) { - if (!is<KeyboardEvent>(*event)) + if (!event->isKeyboardEvent()) return; - KeyboardEvent& keyboardEvent = downcast<KeyboardEvent>(*event); - if (platformHandleKeydownEvent(&keyboardEvent)) + if (platformHandleKeydownEvent(static_cast<KeyboardEvent*>(event))) return; // When using spatial navigation, we want to be able to navigate away @@ -1151,7 +1162,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) return; } - const String& keyIdentifier = keyboardEvent.keyIdentifier(); + const String& keyIdentifier = static_cast<KeyboardEvent*>(event)->keyIdentifier(); bool handled = true; const Vector<HTMLElement*>& listItems = this->listItems(); int listIndex = optionToListIndex(selectedIndex()); @@ -1183,23 +1194,22 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) selectOption(listToOptionIndex(listIndex), DeselectOtherOptions | DispatchChangeEvent | UserDriven); if (handled) - keyboardEvent.setDefaultHandled(); + event->setDefaultHandled(); } // Use key press event here since sending simulated mouse events // on key down blocks the proper sending of the key press event. if (event->type() == eventNames().keypressEvent) { - if (!is<KeyboardEvent>(*event)) + if (!event->isKeyboardEvent()) return; - KeyboardEvent& keyboardEvent = downcast<KeyboardEvent>(*event); - int keyCode = keyboardEvent.keyCode(); + int keyCode = static_cast<KeyboardEvent*>(event)->keyCode(); bool handled = false; if (keyCode == ' ' && isSpatialNavigationEnabled(document().frame())) { // Use space to toggle arrow key handling for selection change or spatial navigation. m_activeSelectionState = !m_activeSelectionState; - keyboardEvent.setDefaultHandled(); + event->setDefaultHandled(); return; } @@ -1209,7 +1219,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) // Calling focus() may remove the renderer or change the // renderer type. - if (!is<RenderMenuList>(renderer())) + if (!renderer() || !renderer()->isMenuList()) return; // Save the selection so it can be compared to the new selection @@ -1217,7 +1227,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) // gets called from RenderMenuList::valueChanged, which gets called // after the user makes a selection from the menu. saveLastSelection(); - downcast<RenderMenuList>(*renderer()).showPopup(); + toRenderMenuList(renderer())->showPopup(); handled = true; } } else if (renderTheme->popsMenuByArrowKeys()) { @@ -1226,7 +1236,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) // Calling focus() may remove the renderer or change the // renderer type. - if (!is<RenderMenuList>(renderer())) + if (!renderer() || !renderer()->isMenuList()) return; // Save the selection so it can be compared to the new selection @@ -1234,33 +1244,36 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) // gets called from RenderMenuList::valueChanged, which gets called // after the user makes a selection from the menu. saveLastSelection(); - downcast<RenderMenuList>(*renderer()).showPopup(); + toRenderMenuList(renderer())->showPopup(); handled = true; } else if (keyCode == '\r') { if (form()) - form()->submitImplicitly(&keyboardEvent, false); + form()->submitImplicitly(event, false); dispatchChangeEventForMenuList(); handled = true; } } if (handled) - keyboardEvent.setDefaultHandled(); + event->setDefaultHandled(); } - if (event->type() == eventNames().mousedownEvent && is<MouseEvent>(*event) && downcast<MouseEvent>(*event).button() == LeftButton) { + if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) { focus(); #if !PLATFORM(IOS) - if (is<RenderMenuList>(renderer())) { - auto& menuList = downcast<RenderMenuList>(*renderer()); - ASSERT(!menuList.popupIsVisible()); - // Save the selection so it can be compared to the new - // selection when we call onChange during selectOption, - // which gets called from RenderMenuList::valueChanged, - // which gets called after the user makes a selection from - // the menu. - saveLastSelection(); - menuList.showPopup(); + if (renderer() && renderer()->isMenuList()) { + auto& menuList = toRenderMenuList(*renderer()); + if (menuList.popupIsVisible()) + menuList.hidePopup(); + else { + // Save the selection so it can be compared to the new + // selection when we call onChange during selectOption, + // which gets called from RenderMenuList::valueChanged, + // which gets called after the user makes a selection from + // the menu. + saveLastSelection(); + menuList.showPopup(); + } } #endif event->setDefaultHandled(); @@ -1268,7 +1281,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) #if !PLATFORM(IOS) if (event->type() == eventNames().blurEvent && !focused()) { - auto& menuList = downcast<RenderMenuList>(*renderer()); + auto& menuList = toRenderMenuList(*renderer()); if (menuList.popupIsVisible()) menuList.hidePopup(); } @@ -1289,13 +1302,13 @@ void HTMLSelectElement::updateSelectedState(int listIndex, bool multi, bool shif bool multiSelect = m_multiple && multi && !shift; HTMLElement* clickedElement = listItems()[listIndex]; - if (is<HTMLOptionElement>(*clickedElement)) { + if (isHTMLOptionElement(clickedElement)) { // Keep track of whether an active selection (like during drag // selection), should select or deselect. - if (downcast<HTMLOptionElement>(*clickedElement).selected() && multiSelect) + if (toHTMLOptionElement(clickedElement)->selected() && multiSelect) m_activeSelectionState = false; if (!m_activeSelectionState) - downcast<HTMLOptionElement>(*clickedElement).setSelectedState(false); + toHTMLOptionElement(clickedElement)->setSelectedState(false); } // If we're not in any special multiple selection mode, then deselect all @@ -1310,8 +1323,8 @@ void HTMLSelectElement::updateSelectedState(int listIndex, bool multi, bool shif setActiveSelectionAnchorIndex(selectedIndex()); // Set the selection state of the clicked option. - if (is<HTMLOptionElement>(*clickedElement) && !downcast<HTMLOptionElement>(*clickedElement).isDisabledFormControl()) - downcast<HTMLOptionElement>(*clickedElement).setSelectedState(true); + if (isHTMLOptionElement(clickedElement) && !toHTMLOptionElement(clickedElement)->isDisabledFormControl()) + toHTMLOptionElement(clickedElement)->setSelectedState(true); // If there was no selectedIndex() for the previous initialization, or If // we're doing a single selection, or a multiple selection (using cmd or @@ -1328,36 +1341,36 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) { const Vector<HTMLElement*>& listItems = this->listItems(); - if (event->type() == eventNames().mousedownEvent && is<MouseEvent>(*event) && downcast<MouseEvent>(*event).button() == LeftButton) { + if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) { focus(); // Calling focus() may remove or change our renderer, in which case we don't want to handle the event further. - if (!is<RenderListBox>(renderer())) + if (!renderer() || !renderer()->isListBox()) return; // Convert to coords relative to the list box if needed. - MouseEvent& mouseEvent = downcast<MouseEvent>(*event); - IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(mouseEvent.absoluteLocation(), UseTransforms)); - int listIndex = downcast<RenderListBox>(*renderer()).listIndexAtOffset(toIntSize(localOffset)); + MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); + IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(mouseEvent->absoluteLocation(), UseTransforms)); + int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize(localOffset)); if (listIndex >= 0) { if (!isDisabledFormControl()) { -#if PLATFORM(COCOA) - updateSelectedState(listIndex, mouseEvent.metaKey(), mouseEvent.shiftKey()); +#if PLATFORM(MAC) + updateSelectedState(listIndex, mouseEvent->metaKey(), mouseEvent->shiftKey()); #else - updateSelectedState(listIndex, mouseEvent.ctrlKey(), mouseEvent.shiftKey()); + updateSelectedState(listIndex, mouseEvent->ctrlKey(), mouseEvent->shiftKey()); #endif } if (Frame* frame = document().frame()) frame->eventHandler().setMouseDownMayStartAutoscroll(); - mouseEvent.setDefaultHandled(); + event->setDefaultHandled(); } - } else if (event->type() == eventNames().mousemoveEvent && is<MouseEvent>(*event) && !downcast<RenderBox>(*renderer()).canBeScrolledAndHasScrollableArea()) { - MouseEvent& mouseEvent = downcast<MouseEvent>(*event); - if (mouseEvent.button() != LeftButton || !mouseEvent.buttonDown()) + } else if (event->type() == eventNames().mousemoveEvent && event->isMouseEvent() && !toRenderBox(renderer())->canBeScrolledAndHasScrollableArea()) { + MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); + if (mouseEvent->button() != LeftButton || !mouseEvent->buttonDown()) return; - IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(mouseEvent.absoluteLocation(), UseTransforms)); - int listIndex = downcast<RenderListBox>(*renderer()).listIndexAtOffset(toIntSize(localOffset)); + IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(mouseEvent->absoluteLocation(), UseTransforms)); + int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize(localOffset)); if (listIndex >= 0) { if (!isDisabledFormControl()) { if (m_multiple) { @@ -1373,9 +1386,9 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) updateListBoxSelection(true); } } - mouseEvent.setDefaultHandled(); + event->setDefaultHandled(); } - } else if (event->type() == eventNames().mouseupEvent && is<MouseEvent>(*event) && downcast<MouseEvent>(*event).button() == LeftButton && document().frame()->eventHandler().autoscrollRenderer() != renderer()) { + } else if (event->type() == eventNames().mouseupEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton && document().frame()->eventHandler().autoscrollRenderer() != renderer()) { // This click or drag event was not over any of the options. if (m_lastOnChangeSelection.isEmpty()) return; @@ -1384,11 +1397,9 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) // timer stops. listBoxOnChange(); } else if (event->type() == eventNames().keydownEvent) { - if (!is<KeyboardEvent>(*event)) + if (!event->isKeyboardEvent()) return; - - KeyboardEvent& keyboardEvent = downcast<KeyboardEvent>(*event); - const String& keyIdentifier = keyboardEvent.keyIdentifier(); + const String& keyIdentifier = static_cast<KeyboardEvent*>(event)->keyIdentifier(); bool handled = false; int endIndex = 0; @@ -1447,52 +1458,51 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) ASSERT_UNUSED(listItems, !listItems.size() || static_cast<size_t>(endIndex) < listItems.size()); setActiveSelectionEndIndex(endIndex); -#if PLATFORM(COCOA) +#if PLATFORM(MAC) m_allowsNonContiguousSelection = m_multiple && isSpatialNavigationEnabled(document().frame()); #else - m_allowsNonContiguousSelection = m_multiple && (isSpatialNavigationEnabled(document().frame()) || keyboardEvent.ctrlKey()); + m_allowsNonContiguousSelection = m_multiple && (isSpatialNavigationEnabled(document().frame()) || static_cast<KeyboardEvent*>(event)->ctrlKey()); #endif - bool selectNewItem = keyboardEvent.shiftKey() || !m_allowsNonContiguousSelection; + bool selectNewItem = static_cast<KeyboardEvent*>(event)->shiftKey() || !m_allowsNonContiguousSelection; if (selectNewItem) m_activeSelectionState = true; // If the anchor is unitialized, or if we're going to deselect all // other options, then set the anchor index equal to the end index. - bool deselectOthers = !m_multiple || (!keyboardEvent.shiftKey() && selectNewItem); + bool deselectOthers = !m_multiple || (!static_cast<KeyboardEvent*>(event)->shiftKey() && selectNewItem); if (m_activeSelectionAnchorIndex < 0 || deselectOthers) { if (deselectOthers) deselectItemsWithoutValidation(); setActiveSelectionAnchorIndex(m_activeSelectionEndIndex); } - downcast<RenderListBox>(*renderer()).scrollToRevealElementAtListIndex(endIndex); + toRenderListBox(renderer())->scrollToRevealElementAtListIndex(endIndex); if (selectNewItem) { updateListBoxSelection(deselectOthers); listBoxOnChange(); } else scrollToSelection(); - keyboardEvent.setDefaultHandled(); + event->setDefaultHandled(); } } else if (event->type() == eventNames().keypressEvent) { - if (!is<KeyboardEvent>(*event)) + if (!event->isKeyboardEvent()) return; - KeyboardEvent& keyboardEvent = downcast<KeyboardEvent>(*event); - int keyCode = keyboardEvent.keyCode(); + int keyCode = static_cast<KeyboardEvent*>(event)->keyCode(); if (keyCode == '\r') { if (form()) - form()->submitImplicitly(&keyboardEvent, false); - keyboardEvent.setDefaultHandled(); + form()->submitImplicitly(event, false); + event->setDefaultHandled(); } else if (m_multiple && keyCode == ' ' && m_allowsNonContiguousSelection) { // Use space to toggle selection change. m_activeSelectionState = !m_activeSelectionState; - ASSERT(m_activeSelectionEndIndex >= 0); - ASSERT(m_activeSelectionEndIndex < static_cast<int>(listItems.size())); - ASSERT(is<HTMLOptionElement>(*listItems[m_activeSelectionEndIndex])); + ASSERT(m_activeSelectionEndIndex >= 0 + && m_activeSelectionEndIndex < static_cast<int>(listItems.size()) + && listItems[m_activeSelectionEndIndex]->hasTagName(optionTag)); updateSelectedState(m_activeSelectionEndIndex, true /*multi*/, false /*shift*/); listBoxOnChange(); - keyboardEvent.setDefaultHandled(); + event->setDefaultHandled(); } } } @@ -1518,9 +1528,9 @@ void HTMLSelectElement::defaultEventHandler(Event* event) if (event->defaultHandled()) return; - if (event->type() == eventNames().keypressEvent && is<KeyboardEvent>(*event)) { - KeyboardEvent& keyboardEvent = downcast<KeyboardEvent>(*event); - if (!keyboardEvent.ctrlKey() && !keyboardEvent.altKey() && !keyboardEvent.metaKey() && u_isprint(keyboardEvent.charCode())) { + if (event->type() == eventNames().keypressEvent && event->isKeyboardEvent()) { + KeyboardEvent* keyboardEvent = static_cast<KeyboardEvent*>(event); + if (!keyboardEvent->ctrlKey() && !keyboardEvent->altKey() && !keyboardEvent->metaKey() && u_isprint(keyboardEvent->charCode())) { typeAheadFind(keyboardEvent); event->setDefaultHandled(); return; @@ -1534,7 +1544,7 @@ int HTMLSelectElement::lastSelectedListIndex() const const Vector<HTMLElement*>& items = listItems(); for (size_t i = items.size(); i;) { HTMLElement* element = items[--i]; - if (is<HTMLOptionElement>(*element) && downcast<HTMLOptionElement>(*element).selected()) + if (isHTMLOptionElement(element) && toHTMLOptionElement(element)->selected()) return i; } return -1; @@ -1555,14 +1565,14 @@ String HTMLSelectElement::optionAtIndex(int index) const const Vector<HTMLElement*>& items = listItems(); HTMLElement* element = items[index]; - if (!is<HTMLOptionElement>(*element) || downcast<HTMLOptionElement>(*element).isDisabledFormControl()) + if (!isHTMLOptionElement(element) || toHTMLOptionElement(element)->isDisabledFormControl()) return String(); - return downcast<HTMLOptionElement>(*element).textIndentedToRespectGroupLabel(); + return toHTMLOptionElement(element)->textIndentedToRespectGroupLabel(); } -void HTMLSelectElement::typeAheadFind(KeyboardEvent& event) +void HTMLSelectElement::typeAheadFind(KeyboardEvent* event) { - int index = m_typeAhead.handleEvent(&event, TypeAhead::MatchPrefix | TypeAhead::CycleFirstChar); + int index = m_typeAhead.handleEvent(event, TypeAhead::MatchPrefix | TypeAhead::CycleFirstChar); if (index < 0) return; selectOption(listToOptionIndex(index), DeselectOtherOptions | DispatchChangeEvent | UserDriven); @@ -1576,7 +1586,8 @@ Node::InsertionNotificationRequest HTMLSelectElement::insertedInto(ContainerNode // items yet - but for innerHTML and related methods, this method is called // after the whole subtree is constructed. recalcListItems(); - return HTMLFormControlElementWithState::insertedInto(insertionPoint); + HTMLFormControlElementWithState::insertedInto(insertionPoint); + return InsertionDone; } void HTMLSelectElement::accessKeySetSelectedIndex(int index) @@ -1590,9 +1601,9 @@ void HTMLSelectElement::accessKeySetSelectedIndex(int index) int listIndex = optionToListIndex(index); if (listIndex >= 0) { HTMLElement* element = items[listIndex]; - if (is<HTMLOptionElement>(*element)) { - if (downcast<HTMLOptionElement>(*element).selected()) - downcast<HTMLOptionElement>(*element).setSelectedState(false); + if (isHTMLOptionElement(element)) { + if (toHTMLOptionElement(element)->selected()) + toHTMLOptionElement(element)->setSelectedState(false); else selectOption(index, DispatchChangeEvent | UserDriven); } @@ -1612,7 +1623,7 @@ unsigned HTMLSelectElement::length() const const Vector<HTMLElement*>& items = listItems(); for (unsigned i = 0; i < items.size(); ++i) { - if (is<HTMLOptionElement>(*items[i])) + if (isHTMLOptionElement(items[i])) ++options; } |