| 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 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 return String(); | 182 return String(); |
| 183 return validationMessage(); | 183 return validationMessage(); |
| 184 } | 184 } |
| 185 | 185 |
| 186 void HTMLSelectElement::selectMultipleOptionsByPopup(const Vector<int>& listIndi
ces) | 186 void HTMLSelectElement::selectMultipleOptionsByPopup(const Vector<int>& listIndi
ces) |
| 187 { | 187 { |
| 188 DCHECK(usesMenuList()); | 188 DCHECK(usesMenuList()); |
| 189 DCHECK(!multiple()); | 189 DCHECK(!multiple()); |
| 190 for (size_t i = 0; i < listIndices.size(); ++i) { | 190 for (size_t i = 0; i < listIndices.size(); ++i) { |
| 191 bool addSelectionIfNotFirst = i > 0; | 191 bool addSelectionIfNotFirst = i > 0; |
| 192 HTMLElement* element = listItems()[listIndices[i]]; | 192 if (HTMLOptionElement* option = optionAtListIndex(listIndices[i])) |
| 193 if (isHTMLOptionElement(element)) | 193 updateSelectedState(option, addSelectionIfNotFirst, false); |
| 194 updateSelectedState(toHTMLOptionElement(element), addSelectionIfNotF
irst, false); | |
| 195 } | 194 } |
| 196 setNeedsValidityCheck(); | 195 setNeedsValidityCheck(); |
| 197 // TODO(tkent): Using listBoxOnChange() is very confusing. | 196 // TODO(tkent): Using listBoxOnChange() is very confusing. |
| 198 listBoxOnChange(); | 197 listBoxOnChange(); |
| 199 } | 198 } |
| 200 | 199 |
| 201 bool HTMLSelectElement::usesMenuList() const | 200 bool HTMLSelectElement::usesMenuList() const |
| 202 { | 201 { |
| 203 if (LayoutTheme::theme().delegatesMenuListRendering()) | 202 if (LayoutTheme::theme().delegatesMenuListRendering()) |
| 204 return true; | 203 return true; |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 } | 473 } |
| 475 } | 474 } |
| 476 setNeedsValidityCheck(); | 475 setNeedsValidityCheck(); |
| 477 } | 476 } |
| 478 | 477 |
| 479 bool HTMLSelectElement::isRequiredFormControl() const | 478 bool HTMLSelectElement::isRequiredFormControl() const |
| 480 { | 479 { |
| 481 return isRequired(); | 480 return isRequired(); |
| 482 } | 481 } |
| 483 | 482 |
| 483 HTMLOptionElement* HTMLSelectElement::optionAtListIndex(int listIndex) const |
| 484 { |
| 485 if (listIndex < 0) |
| 486 return nullptr; |
| 487 const ListItems& items = listItems(); |
| 488 if (static_cast<size_t>(listIndex) >= items.size() || !isHTMLOptionElement(i
tems[listIndex])) |
| 489 return nullptr; |
| 490 return toHTMLOptionElement(items[listIndex]); |
| 491 } |
| 492 |
| 484 // Returns the 1st valid OPTION |skip| items from |listIndex| in direction | 493 // Returns the 1st valid OPTION |skip| items from |listIndex| in direction |
| 485 // |direction| if there is one. | 494 // |direction| if there is one. |
| 486 // Otherwise, it returns the valid OPTION closest to that boundary which is past | 495 // Otherwise, it returns the valid OPTION closest to that boundary which is past |
| 487 // |listIndex| if there is one. | 496 // |listIndex| if there is one. |
| 488 // Otherwise, it returns nullptr. | 497 // Otherwise, it returns nullptr. |
| 489 // Valid means that it is enabled and visible. | 498 // Valid means that it is enabled and visible. |
| 490 HTMLOptionElement* HTMLSelectElement::nextValidOption(int listIndex, SkipDirecti
on direction, int skip) const | 499 HTMLOptionElement* HTMLSelectElement::nextValidOption(int listIndex, SkipDirecti
on direction, int skip) const |
| 491 { | 500 { |
| 492 ASSERT(direction == SkipBackwards || direction == SkipForwards); | 501 ASSERT(direction == SkipBackwards || direction == SkipForwards); |
| 493 const ListItems& listItems = this->listItems(); | 502 const ListItems& listItems = this->listItems(); |
| (...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1051 return listIndex; | 1060 return listIndex; |
| 1052 } | 1061 } |
| 1053 } | 1062 } |
| 1054 | 1063 |
| 1055 return -1; | 1064 return -1; |
| 1056 } | 1065 } |
| 1057 | 1066 |
| 1058 int HTMLSelectElement::listToOptionIndex(int listIndex) const | 1067 int HTMLSelectElement::listToOptionIndex(int listIndex) const |
| 1059 { | 1068 { |
| 1060 const ListItems& items = listItems(); | 1069 const ListItems& items = listItems(); |
| 1061 if (listIndex < 0 || listIndex >= static_cast<int>(items.size()) || !isHTMLO
ptionElement(*items[listIndex])) | 1070 if (!optionAtListIndex(listIndex)) |
| 1062 return -1; | 1071 return -1; |
| 1063 | 1072 |
| 1064 // Actual index of option not counting OPTGROUP entries that may be in list. | 1073 // Actual index of option not counting OPTGROUP entries that may be in list. |
| 1065 int optionIndex = 0; | 1074 int optionIndex = 0; |
| 1066 for (int i = 0; i < listIndex; ++i) { | 1075 for (int i = 0; i < listIndex; ++i) { |
| 1067 if (isHTMLOptionElement(*items[i])) | 1076 if (isHTMLOptionElement(*items[i])) |
| 1068 ++optionIndex; | 1077 ++optionIndex; |
| 1069 } | 1078 } |
| 1070 | 1079 |
| 1071 return optionIndex; | 1080 return optionIndex; |
| (...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1667 return; | 1676 return; |
| 1668 } | 1677 } |
| 1669 } | 1678 } |
| 1670 HTMLFormControlElementWithState::defaultEventHandler(event); | 1679 HTMLFormControlElementWithState::defaultEventHandler(event); |
| 1671 } | 1680 } |
| 1672 | 1681 |
| 1673 HTMLOptionElement* HTMLSelectElement::lastSelectedOption() const | 1682 HTMLOptionElement* HTMLSelectElement::lastSelectedOption() const |
| 1674 { | 1683 { |
| 1675 const ListItems& items = listItems(); | 1684 const ListItems& items = listItems(); |
| 1676 for (size_t i = items.size(); i;) { | 1685 for (size_t i = items.size(); i;) { |
| 1677 HTMLElement* element = items[--i]; | 1686 if (HTMLOptionElement* option = optionAtListIndex(--i)) { |
| 1678 if (isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selec
ted()) | 1687 if (option->selected()) |
| 1679 return toHTMLOptionElement(element); | 1688 return option; |
| 1689 } |
| 1680 } | 1690 } |
| 1681 return nullptr; | 1691 return nullptr; |
| 1682 } | 1692 } |
| 1683 | 1693 |
| 1684 int HTMLSelectElement::indexOfSelectedOption() const | 1694 int HTMLSelectElement::indexOfSelectedOption() const |
| 1685 { | 1695 { |
| 1686 return optionToListIndex(selectedIndex()); | 1696 return optionToListIndex(selectedIndex()); |
| 1687 } | 1697 } |
| 1688 | 1698 |
| 1689 int HTMLSelectElement::optionCount() const | 1699 int HTMLSelectElement::optionCount() const |
| 1690 { | 1700 { |
| 1691 return listItems().size(); | 1701 return listItems().size(); |
| 1692 } | 1702 } |
| 1693 | 1703 |
| 1694 String HTMLSelectElement::optionAtIndex(int index) const | 1704 String HTMLSelectElement::optionAtIndex(int index) const |
| 1695 { | 1705 { |
| 1696 const ListItems& items = listItems(); | 1706 if (HTMLOptionElement* option = optionAtListIndex(index)) { |
| 1697 HTMLElement* element = items[index]; | 1707 if (!option->isDisabledFormControl()) |
| 1698 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDisabl
edFormControl()) | 1708 return option->displayLabel(); |
| 1699 return String(); | 1709 } |
| 1700 return toHTMLOptionElement(element)->displayLabel(); | 1710 return String(); |
| 1701 } | 1711 } |
| 1702 | 1712 |
| 1703 void HTMLSelectElement::typeAheadFind(KeyboardEvent* event) | 1713 void HTMLSelectElement::typeAheadFind(KeyboardEvent* event) |
| 1704 { | 1714 { |
| 1705 int index = m_typeAhead.handleEvent(event, TypeAhead::MatchPrefix | TypeAhea
d::CycleFirstChar); | 1715 int index = m_typeAhead.handleEvent(event, TypeAhead::MatchPrefix | TypeAhea
d::CycleFirstChar); |
| 1706 if (index < 0) | 1716 if (index < 0) |
| 1707 return; | 1717 return; |
| 1708 HTMLOptionElement* option = nullptr; | 1718 selectOption(optionAtListIndex(index), DeselectOtherOptions | MakeOptionDirt
y | DispatchInputAndChangeEvent); |
| 1709 if (static_cast<size_t>(index) < listItems().size() && isHTMLOptionElement(l
istItems()[index])) | |
| 1710 option = toHTMLOptionElement(listItems()[index]); | |
| 1711 selectOption(option, DeselectOtherOptions | MakeOptionDirty | DispatchInputA
ndChangeEvent); | |
| 1712 if (!usesMenuList()) | 1719 if (!usesMenuList()) |
| 1713 listBoxOnChange(); | 1720 listBoxOnChange(); |
| 1714 } | 1721 } |
| 1715 | 1722 |
| 1716 void HTMLSelectElement::accessKeySetSelectedIndex(int index) | 1723 void HTMLSelectElement::accessKeySetSelectedIndex(int index) |
| 1717 { | 1724 { |
| 1718 // First bring into focus the list box. | 1725 // First bring into focus the list box. |
| 1719 if (!focused()) | 1726 if (!focused()) |
| 1720 accessKeyAction(false); | 1727 accessKeyAction(false); |
| 1721 | 1728 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1881 | 1888 |
| 1882 void HTMLSelectElement::setIndexToSelectOnCancel(int listIndex) | 1889 void HTMLSelectElement::setIndexToSelectOnCancel(int listIndex) |
| 1883 { | 1890 { |
| 1884 m_indexToSelectOnCancel = listIndex; | 1891 m_indexToSelectOnCancel = listIndex; |
| 1885 if (layoutObject()) | 1892 if (layoutObject()) |
| 1886 layoutObject()->updateFromElement(); | 1893 layoutObject()->updateFromElement(); |
| 1887 } | 1894 } |
| 1888 | 1895 |
| 1889 HTMLOptionElement* HTMLSelectElement::optionToBeShown() const | 1896 HTMLOptionElement* HTMLSelectElement::optionToBeShown() const |
| 1890 { | 1897 { |
| 1891 if (m_indexToSelectOnCancel >= 0 && static_cast<size_t>(m_indexToSelectOnCan
cel) < listItems().size() && isHTMLOptionElement(listItems()[m_indexToSelectOnCa
ncel])) | 1898 if (HTMLOptionElement* option = optionAtListIndex(m_indexToSelectOnCancel)) |
| 1892 return toHTMLOptionElement(listItems()[m_indexToSelectOnCancel]); | 1899 return option; |
| 1893 if (m_suggestedOption) | 1900 if (m_suggestedOption) |
| 1894 return m_suggestedOption; | 1901 return m_suggestedOption; |
| 1895 // TODO(tkent): We should not call optionToBeShown() in multiple() case. | 1902 // TODO(tkent): We should not call optionToBeShown() in multiple() case. |
| 1896 if (multiple()) | 1903 if (multiple()) |
| 1897 return selectedOption(); | 1904 return selectedOption(); |
| 1898 DCHECK_EQ(selectedOption(), m_lastOnChangeOption); | 1905 DCHECK_EQ(selectedOption(), m_lastOnChangeOption); |
| 1899 return m_lastOnChangeOption; | 1906 return m_lastOnChangeOption; |
| 1900 } | 1907 } |
| 1901 | 1908 |
| 1902 void HTMLSelectElement::selectOptionByPopup(int listIndex) | 1909 void HTMLSelectElement::selectOptionByPopup(int listIndex) |
| 1903 { | 1910 { |
| 1904 DCHECK(usesMenuList()); | 1911 DCHECK(usesMenuList()); |
| 1905 // Check to ensure a page navigation has not occurred while the popup was | 1912 // Check to ensure a page navigation has not occurred while the popup was |
| 1906 // up. | 1913 // up. |
| 1907 Document& doc = document(); | 1914 Document& doc = document(); |
| 1908 if (&doc != doc.frame()->document()) | 1915 if (&doc != doc.frame()->document()) |
| 1909 return; | 1916 return; |
| 1910 | 1917 |
| 1911 setIndexToSelectOnCancel(-1); | 1918 setIndexToSelectOnCancel(-1); |
| 1912 | 1919 |
| 1913 HTMLOptionElement* option = nullptr; | 1920 HTMLOptionElement* option = optionAtListIndex(listIndex); |
| 1914 if (listIndex >= 0 && isHTMLOptionElement(listItems()[listIndex])) | |
| 1915 option = toHTMLOptionElement(listItems()[listIndex]); | |
| 1916 // Bail out if this index is already the selected one, to avoid running | 1921 // Bail out if this index is already the selected one, to avoid running |
| 1917 // unnecessary JavaScript that can mess up autofill when there is no actual | 1922 // unnecessary JavaScript that can mess up autofill when there is no actual |
| 1918 // change (see https://bugs.webkit.org/show_bug.cgi?id=35256 and | 1923 // change (see https://bugs.webkit.org/show_bug.cgi?id=35256 and |
| 1919 // <rdar://7467917>). The selectOption function does not behave this way, | 1924 // <rdar://7467917>). The selectOption function does not behave this way, |
| 1920 // possibly because other callers need a change event even in cases where | 1925 // possibly because other callers need a change event even in cases where |
| 1921 // the selected option is not change. | 1926 // the selected option is not change. |
| 1922 if (option == selectedOption()) | 1927 if (option == selectedOption()) |
| 1923 return; | 1928 return; |
| 1924 selectOption(option, DeselectOtherOptions | MakeOptionDirty | DispatchInputA
ndChangeEvent); | 1929 selectOption(option, DeselectOtherOptions | MakeOptionDirty | DispatchInputA
ndChangeEvent); |
| 1925 } | 1930 } |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2058 } | 2063 } |
| 2059 | 2064 |
| 2060 void HTMLSelectElement::didMutateSubtree() | 2065 void HTMLSelectElement::didMutateSubtree() |
| 2061 { | 2066 { |
| 2062 DCHECK(popupIsVisible()); | 2067 DCHECK(popupIsVisible()); |
| 2063 DCHECK(m_popup); | 2068 DCHECK(m_popup); |
| 2064 m_popup->updateFromElement(PopupMenu::ByDOMChange); | 2069 m_popup->updateFromElement(PopupMenu::ByDOMChange); |
| 2065 } | 2070 } |
| 2066 | 2071 |
| 2067 } // namespace blink | 2072 } // namespace blink |
| OLD | NEW |