| 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 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 | 573 |
| 574 int HTMLSelectElement::lastSelectableListIndex() const | 574 int HTMLSelectElement::lastSelectableListIndex() const |
| 575 { | 575 { |
| 576 return nextValidIndex(-1, SkipForwards, INT_MAX); | 576 return nextValidIndex(-1, SkipForwards, INT_MAX); |
| 577 } | 577 } |
| 578 | 578 |
| 579 // Returns the index of the next valid item one page away from |startIndex| in d
irection |direction|. | 579 // Returns the index of the next valid item one page away from |startIndex| in d
irection |direction|. |
| 580 int HTMLSelectElement::nextSelectableListIndexPageAway(int startIndex, SkipDirec
tion direction) const | 580 int HTMLSelectElement::nextSelectableListIndexPageAway(int startIndex, SkipDirec
tion direction) const |
| 581 { | 581 { |
| 582 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems()
; | 582 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems()
; |
| 583 // Can't use m_size because renderer forces a minimum size. | 583 // Can't use m_size because layoutObject forces a minimum size. |
| 584 int pageSize = 0; | 584 int pageSize = 0; |
| 585 if (layoutObject()->isListBox()) | 585 if (layoutObject()->isListBox()) |
| 586 pageSize = toLayoutListBox(layoutObject())->size() - 1; // -1 so we stil
l show context. | 586 pageSize = toLayoutListBox(layoutObject())->size() - 1; // -1 so we stil
l show context. |
| 587 | 587 |
| 588 // One page away, but not outside valid bounds. | 588 // One page away, but not outside valid bounds. |
| 589 // If there is a valid option item one page away, the index is chosen. | 589 // If there is a valid option item one page away, the index is chosen. |
| 590 // If there is no exact one page away valid option, returns startIndex or th
e most far index. | 590 // If there is no exact one page away valid option, returns startIndex or th
e most far index. |
| 591 int edgeIndex = (direction == SkipForwards) ? 0 : (items.size() - 1); | 591 int edgeIndex = (direction == SkipForwards) ? 0 : (items.size() - 1); |
| 592 int skipAmount = pageSize + ((direction == SkipForwards) ? startIndex : (edg
eIndex - startIndex)); | 592 int skipAmount = pageSize + ((direction == SkipForwards) ? startIndex : (edg
eIndex - startIndex)); |
| 593 return nextValidIndex(edgeIndex, direction, skipAmount); | 593 return nextValidIndex(edgeIndex, direction, skipAmount); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 { | 726 { |
| 727 if (!isFinishedParsingChildren()) | 727 if (!isFinishedParsingChildren()) |
| 728 return; | 728 return; |
| 729 if (usesMenuList()) | 729 if (usesMenuList()) |
| 730 return; | 730 return; |
| 731 scrollToIndex(activeSelectionEndListIndex()); | 731 scrollToIndex(activeSelectionEndListIndex()); |
| 732 if (AXObjectCache* cache = document().existingAXObjectCache()) | 732 if (AXObjectCache* cache = document().existingAXObjectCache()) |
| 733 cache->listboxActiveIndexChanged(this); | 733 cache->listboxActiveIndexChanged(this); |
| 734 } | 734 } |
| 735 | 735 |
| 736 void HTMLSelectElement::setOptionsChangedOnRenderer() | 736 void HTMLSelectElement::setOptionsChangedOnLayoutObject() |
| 737 { | 737 { |
| 738 if (LayoutObject* renderer = this->layoutObject()) { | 738 if (LayoutObject* layoutObject = this->layoutObject()) { |
| 739 if (usesMenuList()) | 739 if (usesMenuList()) |
| 740 toLayoutMenuList(renderer)->setOptionsChanged(true); | 740 toLayoutMenuList(layoutObject)->setOptionsChanged(true); |
| 741 } | 741 } |
| 742 } | 742 } |
| 743 | 743 |
| 744 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& HTMLSelectElement::list
Items() const | 744 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& HTMLSelectElement::list
Items() const |
| 745 { | 745 { |
| 746 if (m_shouldRecalcListItems) | 746 if (m_shouldRecalcListItems) |
| 747 recalcListItems(); | 747 recalcListItems(); |
| 748 else { | 748 else { |
| 749 #if ENABLE(ASSERT) | 749 #if ENABLE(ASSERT) |
| 750 WillBeHeapVector<RawPtrWillBeMember<HTMLElement>> items = m_listItems; | 750 WillBeHeapVector<RawPtrWillBeMember<HTMLElement>> items = m_listItems; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 763 } | 763 } |
| 764 | 764 |
| 765 void HTMLSelectElement::setRecalcListItems() | 765 void HTMLSelectElement::setRecalcListItems() |
| 766 { | 766 { |
| 767 // FIXME: This function does a bunch of confusing things depending on if it | 767 // FIXME: This function does a bunch of confusing things depending on if it |
| 768 // is in the document or not. | 768 // is in the document or not. |
| 769 | 769 |
| 770 m_shouldRecalcListItems = true; | 770 m_shouldRecalcListItems = true; |
| 771 // Manual selection anchor is reset when manipulating the select programmati
cally. | 771 // Manual selection anchor is reset when manipulating the select programmati
cally. |
| 772 m_activeSelectionAnchorIndex = -1; | 772 m_activeSelectionAnchorIndex = -1; |
| 773 setOptionsChangedOnRenderer(); | 773 setOptionsChangedOnLayoutObject(); |
| 774 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(
StyleChangeReason::ControlValue)); | 774 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(
StyleChangeReason::ControlValue)); |
| 775 if (!inDocument()) { | 775 if (!inDocument()) { |
| 776 if (HTMLOptionsCollection* collection = cachedCollection<HTMLOptionsColl
ection>(SelectOptions)) | 776 if (HTMLOptionsCollection* collection = cachedCollection<HTMLOptionsColl
ection>(SelectOptions)) |
| 777 collection->invalidateCache(); | 777 collection->invalidateCache(); |
| 778 } | 778 } |
| 779 if (!inDocument()) | 779 if (!inDocument()) |
| 780 invalidateSelectedItems(); | 780 invalidateSelectedItems(); |
| 781 | 781 |
| 782 if (layoutObject()) { | 782 if (layoutObject()) { |
| 783 if (AXObjectCache* cache = layoutObject()->document().existingAXObjectCa
che()) | 783 if (AXObjectCache* cache = layoutObject()->document().existingAXObjectCa
che()) |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 | 870 |
| 871 int HTMLSelectElement::suggestedIndex() const | 871 int HTMLSelectElement::suggestedIndex() const |
| 872 { | 872 { |
| 873 return m_suggestedIndex; | 873 return m_suggestedIndex; |
| 874 } | 874 } |
| 875 | 875 |
| 876 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex) | 876 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex) |
| 877 { | 877 { |
| 878 m_suggestedIndex = suggestedIndex; | 878 m_suggestedIndex = suggestedIndex; |
| 879 | 879 |
| 880 if (LayoutObject* renderer = this->layoutObject()) { | 880 if (LayoutObject* layoutObject = this->layoutObject()) { |
| 881 renderer->updateFromElement(); | 881 layoutObject->updateFromElement(); |
| 882 scrollToIndex(suggestedIndex); | 882 scrollToIndex(suggestedIndex); |
| 883 } | 883 } |
| 884 } | 884 } |
| 885 | 885 |
| 886 void HTMLSelectElement::scrollToIndex(int listIndex) | 886 void HTMLSelectElement::scrollToIndex(int listIndex) |
| 887 { | 887 { |
| 888 if (listIndex < 0) | 888 if (listIndex < 0) |
| 889 return; | 889 return; |
| 890 if (usesMenuList()) | 890 if (usesMenuList()) |
| 891 return; | 891 return; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 950 if (m_activeSelectionEndIndex < 0 || shouldDeselect) | 950 if (m_activeSelectionEndIndex < 0 || shouldDeselect) |
| 951 setActiveSelectionEndIndex(listIndex); | 951 setActiveSelectionEndIndex(listIndex); |
| 952 toHTMLOptionElement(*element).setSelectedState(true); | 952 toHTMLOptionElement(*element).setSelectedState(true); |
| 953 } | 953 } |
| 954 } | 954 } |
| 955 | 955 |
| 956 if (shouldDeselect) | 956 if (shouldDeselect) |
| 957 deselectItemsWithoutValidation(element); | 957 deselectItemsWithoutValidation(element); |
| 958 | 958 |
| 959 // For the menu list case, this is what makes the selected element appear. | 959 // For the menu list case, this is what makes the selected element appear. |
| 960 if (LayoutObject* renderer = this->layoutObject()) | 960 if (LayoutObject* layoutObject = this->layoutObject()) |
| 961 renderer->updateFromElement(); | 961 layoutObject->updateFromElement(); |
| 962 | 962 |
| 963 scrollToSelection(); | 963 scrollToSelection(); |
| 964 setNeedsValidityCheck(); | 964 setNeedsValidityCheck(); |
| 965 | 965 |
| 966 if (usesMenuList()) { | 966 if (usesMenuList()) { |
| 967 m_isProcessingUserDrivenChange = flags & UserDriven; | 967 m_isProcessingUserDrivenChange = flags & UserDriven; |
| 968 if (flags & DispatchInputAndChangeEvent) | 968 if (flags & DispatchInputAndChangeEvent) |
| 969 dispatchInputAndChangeEventForMenuList(); | 969 dispatchInputAndChangeEventForMenuList(); |
| 970 if (LayoutObject* renderer = this->layoutObject()) { | 970 if (LayoutObject* layoutObject = this->layoutObject()) { |
| 971 if (usesMenuList()) { | 971 if (usesMenuList()) { |
| 972 toLayoutMenuList(renderer)->didSetSelectedIndex(listIndex); | 972 toLayoutMenuList(layoutObject)->didSetSelectedIndex(listIndex); |
| 973 } | 973 } |
| 974 } | 974 } |
| 975 } | 975 } |
| 976 | 976 |
| 977 notifyFormStateChanged(); | 977 notifyFormStateChanged(); |
| 978 } | 978 } |
| 979 | 979 |
| 980 int HTMLSelectElement::optionToListIndex(int optionIndex) const | 980 int HTMLSelectElement::optionToListIndex(int optionIndex) const |
| 981 { | 981 { |
| 982 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems()
; | 982 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems()
; |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 if (foundIndex == kNotFound) | 1112 if (foundIndex == kNotFound) |
| 1113 foundIndex = searchOptionsForValue(value, 0, startIndex); | 1113 foundIndex = searchOptionsForValue(value, 0, startIndex); |
| 1114 if (foundIndex == kNotFound) | 1114 if (foundIndex == kNotFound) |
| 1115 continue; | 1115 continue; |
| 1116 toHTMLOptionElement(items[foundIndex])->setSelectedState(true); | 1116 toHTMLOptionElement(items[foundIndex])->setSelectedState(true); |
| 1117 startIndex = foundIndex + 1; | 1117 startIndex = foundIndex + 1; |
| 1118 } | 1118 } |
| 1119 } | 1119 } |
| 1120 } | 1120 } |
| 1121 | 1121 |
| 1122 setOptionsChangedOnRenderer(); | 1122 setOptionsChangedOnLayoutObject(); |
| 1123 setNeedsValidityCheck(); | 1123 setNeedsValidityCheck(); |
| 1124 } | 1124 } |
| 1125 | 1125 |
| 1126 void HTMLSelectElement::parseMultipleAttribute(const AtomicString& value) | 1126 void HTMLSelectElement::parseMultipleAttribute(const AtomicString& value) |
| 1127 { | 1127 { |
| 1128 m_multiple = !value.isNull(); | 1128 m_multiple = !value.isNull(); |
| 1129 setNeedsValidityCheck(); | 1129 setNeedsValidityCheck(); |
| 1130 | 1130 |
| 1131 lazyReattachIfAttached(); | 1131 lazyReattachIfAttached(); |
| 1132 } | 1132 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1173 } else | 1173 } else |
| 1174 toHTMLOptionElement(element)->setSelectedState(false); | 1174 toHTMLOptionElement(element)->setSelectedState(false); |
| 1175 | 1175 |
| 1176 if (!firstOption) | 1176 if (!firstOption) |
| 1177 firstOption = toHTMLOptionElement(element); | 1177 firstOption = toHTMLOptionElement(element); |
| 1178 } | 1178 } |
| 1179 | 1179 |
| 1180 if (!selectedOption && firstOption && !m_multiple && m_size <= 1) | 1180 if (!selectedOption && firstOption && !m_multiple && m_size <= 1) |
| 1181 firstOption->setSelectedState(true); | 1181 firstOption->setSelectedState(true); |
| 1182 | 1182 |
| 1183 setOptionsChangedOnRenderer(); | 1183 setOptionsChangedOnLayoutObject(); |
| 1184 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(
StyleChangeReason::ControlValue)); | 1184 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(
StyleChangeReason::ControlValue)); |
| 1185 setNeedsValidityCheck(); | 1185 setNeedsValidityCheck(); |
| 1186 } | 1186 } |
| 1187 | 1187 |
| 1188 void HTMLSelectElement::handlePopupOpenKeyboardEvent(Event* event) | 1188 void HTMLSelectElement::handlePopupOpenKeyboardEvent(Event* event) |
| 1189 { | 1189 { |
| 1190 focus(); | 1190 focus(); |
| 1191 // Calling focus() may cause us to lose our renderer. Return true so | 1191 // Calling focus() may cause us to lose our layoutObject. Return true so |
| 1192 // that our caller doesn't process the event further, but don't set | 1192 // that our caller doesn't process the event further, but don't set |
| 1193 // the event as handled. | 1193 // the event as handled. |
| 1194 if (!layoutObject() || !layoutObject()->isMenuList() || isDisabledFormContro
l()) | 1194 if (!layoutObject() || !layoutObject()->isMenuList() || isDisabledFormContro
l()) |
| 1195 return; | 1195 return; |
| 1196 // Save the selection so it can be compared to the new selection | 1196 // Save the selection so it can be compared to the new selection |
| 1197 // when dispatching change events during selectOption, which | 1197 // when dispatching change events during selectOption, which |
| 1198 // gets called from LayoutMenuList::valueChanged, which gets called | 1198 // gets called from LayoutMenuList::valueChanged, which gets called |
| 1199 // after the user makes a selection from the menu. | 1199 // after the user makes a selection from the menu. |
| 1200 saveLastSelection(); | 1200 saveLastSelection(); |
| 1201 if (LayoutMenuList* menuList = toLayoutMenuList(layoutObject())) | 1201 if (LayoutMenuList* menuList = toLayoutMenuList(layoutObject())) |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1416 if (m_lastOnChangeSelection.isEmpty()) | 1416 if (m_lastOnChangeSelection.isEmpty()) |
| 1417 return; | 1417 return; |
| 1418 listBoxOnChange(); | 1418 listBoxOnChange(); |
| 1419 } | 1419 } |
| 1420 | 1420 |
| 1421 void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) | 1421 void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) |
| 1422 { | 1422 { |
| 1423 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = this->l
istItems(); | 1423 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = this->l
istItems(); |
| 1424 if (event->type() == EventTypeNames::gesturetap && event->isGestureEvent())
{ | 1424 if (event->type() == EventTypeNames::gesturetap && event->isGestureEvent())
{ |
| 1425 focus(); | 1425 focus(); |
| 1426 // Calling focus() may cause us to lose our renderer or change the rende
r type, in which case do not want to handle the event. | 1426 // Calling focus() may cause us to lose our layoutObject or change the l
ayoutObject type, in which case do not want to handle the event. |
| 1427 if (!layoutObject() || !layoutObject()->isListBox()) | 1427 if (!layoutObject() || !layoutObject()->isListBox()) |
| 1428 return; | 1428 return; |
| 1429 | 1429 |
| 1430 // Convert to coords relative to the list box if needed. | 1430 // Convert to coords relative to the list box if needed. |
| 1431 GestureEvent& gestureEvent = toGestureEvent(*event); | 1431 GestureEvent& gestureEvent = toGestureEvent(*event); |
| 1432 int listIndex = listIndexForEventTargetOption(gestureEvent); | 1432 int listIndex = listIndexForEventTargetOption(gestureEvent); |
| 1433 if (listIndex >= 0) { | 1433 if (listIndex >= 0) { |
| 1434 if (!isDisabledFormControl()) { | 1434 if (!isDisabledFormControl()) { |
| 1435 updateSelectedState(listIndex, true, gestureEvent.shiftKey()); | 1435 updateSelectedState(listIndex, true, gestureEvent.shiftKey()); |
| 1436 listBoxOnChange(); | 1436 listBoxOnChange(); |
| 1437 } | 1437 } |
| 1438 event->setDefaultHandled(); | 1438 event->setDefaultHandled(); |
| 1439 } | 1439 } |
| 1440 } else if (event->type() == EventTypeNames::mousedown && event->isMouseEvent
() && toMouseEvent(event)->button() == LeftButton) { | 1440 } else if (event->type() == EventTypeNames::mousedown && event->isMouseEvent
() && toMouseEvent(event)->button() == LeftButton) { |
| 1441 focus(); | 1441 focus(); |
| 1442 // Calling focus() may cause us to lose our renderer, in which case do n
ot want to handle the event. | 1442 // Calling focus() may cause us to lose our layoutObject, in which case
do not want to handle the event. |
| 1443 if (!layoutObject() || !layoutObject()->isListBox() || isDisabledFormCon
trol()) | 1443 if (!layoutObject() || !layoutObject()->isListBox() || isDisabledFormCon
trol()) |
| 1444 return; | 1444 return; |
| 1445 | 1445 |
| 1446 // Convert to coords relative to the list box if needed. | 1446 // Convert to coords relative to the list box if needed. |
| 1447 MouseEvent* mouseEvent = toMouseEvent(event); | 1447 MouseEvent* mouseEvent = toMouseEvent(event); |
| 1448 int listIndex = listIndexForEventTargetOption(*mouseEvent); | 1448 int listIndex = listIndexForEventTargetOption(*mouseEvent); |
| 1449 if (listIndex >= 0) { | 1449 if (listIndex >= 0) { |
| 1450 if (!isDisabledFormControl()) { | 1450 if (!isDisabledFormControl()) { |
| 1451 #if OS(MACOSX) | 1451 #if OS(MACOSX) |
| 1452 updateSelectedState(listIndex, mouseEvent->metaKey(), mouseEvent
->shiftKey()); | 1452 updateSelectedState(listIndex, mouseEvent->metaKey(), mouseEvent
->shiftKey()); |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1731 bool HTMLSelectElement::isInteractiveContent() const | 1731 bool HTMLSelectElement::isInteractiveContent() const |
| 1732 { | 1732 { |
| 1733 return true; | 1733 return true; |
| 1734 } | 1734 } |
| 1735 | 1735 |
| 1736 bool HTMLSelectElement::supportsAutofocus() const | 1736 bool HTMLSelectElement::supportsAutofocus() const |
| 1737 { | 1737 { |
| 1738 return true; | 1738 return true; |
| 1739 } | 1739 } |
| 1740 | 1740 |
| 1741 void HTMLSelectElement::updateListOnRenderer() | 1741 void HTMLSelectElement::updateListOnLayoutObject() |
| 1742 { | 1742 { |
| 1743 setOptionsChangedOnRenderer(); | 1743 setOptionsChangedOnLayoutObject(); |
| 1744 } | 1744 } |
| 1745 | 1745 |
| 1746 DEFINE_TRACE(HTMLSelectElement) | 1746 DEFINE_TRACE(HTMLSelectElement) |
| 1747 { | 1747 { |
| 1748 #if ENABLE(OILPAN) | 1748 #if ENABLE(OILPAN) |
| 1749 visitor->trace(m_listItems); | 1749 visitor->trace(m_listItems); |
| 1750 #endif | 1750 #endif |
| 1751 HTMLFormControlElementWithState::trace(visitor); | 1751 HTMLFormControlElementWithState::trace(visitor); |
| 1752 } | 1752 } |
| 1753 | 1753 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1765 int focusedIndex = activeSelectionEndListIndex(); | 1765 int focusedIndex = activeSelectionEndListIndex(); |
| 1766 if (focusedIndex < 0) | 1766 if (focusedIndex < 0) |
| 1767 focusedIndex = firstSelectableListIndex(); | 1767 focusedIndex = firstSelectableListIndex(); |
| 1768 if (focusedIndex < 0) | 1768 if (focusedIndex < 0) |
| 1769 return nullptr; | 1769 return nullptr; |
| 1770 HTMLElement* focused = listItems()[focusedIndex]; | 1770 HTMLElement* focused = listItems()[focusedIndex]; |
| 1771 return isHTMLOptionElement(focused) ? toHTMLOptionElement(focused) : nullptr
; | 1771 return isHTMLOptionElement(focused) ? toHTMLOptionElement(focused) : nullptr
; |
| 1772 } | 1772 } |
| 1773 | 1773 |
| 1774 } // namespace | 1774 } // namespace |
| OLD | NEW |