| 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 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 466 // Otherwise, it returns |listIndex|. | 466 // Otherwise, it returns |listIndex|. |
| 467 // Valid means that it is enabled and an option element. | 467 // Valid means that it is enabled and an option element. |
| 468 int HTMLSelectElement::nextValidIndex(int listIndex, SkipDirection direction, in
t skip) const | 468 int HTMLSelectElement::nextValidIndex(int listIndex, SkipDirection direction, in
t skip) const |
| 469 { | 469 { |
| 470 ASSERT(direction == -1 || direction == 1); | 470 ASSERT(direction == -1 || direction == 1); |
| 471 const Vector<HTMLElement*>& listItems = this->listItems(); | 471 const Vector<HTMLElement*>& listItems = this->listItems(); |
| 472 int lastGoodIndex = listIndex; | 472 int lastGoodIndex = listIndex; |
| 473 int size = listItems.size(); | 473 int size = listItems.size(); |
| 474 for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex +
= direction) { | 474 for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex +
= direction) { |
| 475 --skip; | 475 --skip; |
| 476 if (!listItems[listIndex]->isDisabledFormControl() && listItems[listInde
x]->hasTagName(optionTag)) { | 476 if (!listItems[listIndex]->isDisabledFormControl() && isHTMLOptionElemen
t(*listItems[listIndex])) { |
| 477 lastGoodIndex = listIndex; | 477 lastGoodIndex = listIndex; |
| 478 if (skip <= 0) | 478 if (skip <= 0) |
| 479 break; | 479 break; |
| 480 } | 480 } |
| 481 } | 481 } |
| 482 return lastGoodIndex; | 482 return lastGoodIndex; |
| 483 } | 483 } |
| 484 | 484 |
| 485 int HTMLSelectElement::nextSelectableListIndex(int startIndex) const | 485 int HTMLSelectElement::nextSelectableListIndex(int startIndex) const |
| 486 { | 486 { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 548 { | 548 { |
| 549 if (usesMenuList()) { | 549 if (usesMenuList()) { |
| 550 m_lastOnChangeIndex = selectedIndex(); | 550 m_lastOnChangeIndex = selectedIndex(); |
| 551 return; | 551 return; |
| 552 } | 552 } |
| 553 | 553 |
| 554 m_lastOnChangeSelection.clear(); | 554 m_lastOnChangeSelection.clear(); |
| 555 const Vector<HTMLElement*>& items = listItems(); | 555 const Vector<HTMLElement*>& items = listItems(); |
| 556 for (unsigned i = 0; i < items.size(); ++i) { | 556 for (unsigned i = 0; i < items.size(); ++i) { |
| 557 HTMLElement* element = items[i]; | 557 HTMLElement* element = items[i]; |
| 558 m_lastOnChangeSelection.append(element->hasTagName(optionTag) && toHTMLO
ptionElement(element)->selected()); | 558 m_lastOnChangeSelection.append(isHTMLOptionElement(*element) && toHTMLOp
tionElement(element)->selected()); |
| 559 } | 559 } |
| 560 } | 560 } |
| 561 | 561 |
| 562 void HTMLSelectElement::setActiveSelectionAnchorIndex(int index) | 562 void HTMLSelectElement::setActiveSelectionAnchorIndex(int index) |
| 563 { | 563 { |
| 564 m_activeSelectionAnchorIndex = index; | 564 m_activeSelectionAnchorIndex = index; |
| 565 | 565 |
| 566 // Cache the selection state so we can restore the old selection as the new | 566 // Cache the selection state so we can restore the old selection as the new |
| 567 // selection pivots around this anchor index. | 567 // selection pivots around this anchor index. |
| 568 m_cachedStateForActiveSelection.clear(); | 568 m_cachedStateForActiveSelection.clear(); |
| 569 | 569 |
| 570 const Vector<HTMLElement*>& items = listItems(); | 570 const Vector<HTMLElement*>& items = listItems(); |
| 571 for (unsigned i = 0; i < items.size(); ++i) { | 571 for (unsigned i = 0; i < items.size(); ++i) { |
| 572 HTMLElement* element = items[i]; | 572 HTMLElement* element = items[i]; |
| 573 m_cachedStateForActiveSelection.append(element->hasTagName(optionTag) &&
toHTMLOptionElement(element)->selected()); | 573 m_cachedStateForActiveSelection.append(isHTMLOptionElement(*element) &&
toHTMLOptionElement(element)->selected()); |
| 574 } | 574 } |
| 575 } | 575 } |
| 576 | 576 |
| 577 void HTMLSelectElement::setActiveSelectionEndIndex(int index) | 577 void HTMLSelectElement::setActiveSelectionEndIndex(int index) |
| 578 { | 578 { |
| 579 m_activeSelectionEndIndex = index; | 579 m_activeSelectionEndIndex = index; |
| 580 } | 580 } |
| 581 | 581 |
| 582 void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions) | 582 void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions) |
| 583 { | 583 { |
| 584 ASSERT(renderer() && (renderer()->isListBox() || m_multiple)); | 584 ASSERT(renderer() && (renderer()->isListBox() || m_multiple)); |
| 585 ASSERT(!listItems().size() || m_activeSelectionAnchorIndex >= 0); | 585 ASSERT(!listItems().size() || m_activeSelectionAnchorIndex >= 0); |
| 586 | 586 |
| 587 unsigned start = min(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex
); | 587 unsigned start = min(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex
); |
| 588 unsigned end = max(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex); | 588 unsigned end = max(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex); |
| 589 | 589 |
| 590 const Vector<HTMLElement*>& items = listItems(); | 590 const Vector<HTMLElement*>& items = listItems(); |
| 591 for (unsigned i = 0; i < items.size(); ++i) { | 591 for (unsigned i = 0; i < items.size(); ++i) { |
| 592 HTMLElement* element = items[i]; | 592 HTMLElement* element = items[i]; |
| 593 if (!element->hasTagName(optionTag) || toHTMLOptionElement(element)->isD
isabledFormControl()) | 593 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDi
sabledFormControl()) |
| 594 continue; | 594 continue; |
| 595 | 595 |
| 596 if (i >= start && i <= end) | 596 if (i >= start && i <= end) |
| 597 toHTMLOptionElement(element)->setSelectedState(m_activeSelectionStat
e); | 597 toHTMLOptionElement(element)->setSelectedState(m_activeSelectionStat
e); |
| 598 else if (deselectOtherOptions || i >= m_cachedStateForActiveSelection.si
ze()) | 598 else if (deselectOtherOptions || i >= m_cachedStateForActiveSelection.si
ze()) |
| 599 toHTMLOptionElement(element)->setSelectedState(false); | 599 toHTMLOptionElement(element)->setSelectedState(false); |
| 600 else | 600 else |
| 601 toHTMLOptionElement(element)->setSelectedState(m_cachedStateForActiv
eSelection[i]); | 601 toHTMLOptionElement(element)->setSelectedState(m_cachedStateForActiv
eSelection[i]); |
| 602 } | 602 } |
| 603 | 603 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 617 // FIXME: Why? This looks unreasonable. | 617 // FIXME: Why? This looks unreasonable. |
| 618 if (m_lastOnChangeSelection.isEmpty() || m_lastOnChangeSelection.size() != i
tems.size()) { | 618 if (m_lastOnChangeSelection.isEmpty() || m_lastOnChangeSelection.size() != i
tems.size()) { |
| 619 dispatchFormControlChangeEvent(); | 619 dispatchFormControlChangeEvent(); |
| 620 return; | 620 return; |
| 621 } | 621 } |
| 622 | 622 |
| 623 // Update m_lastOnChangeSelection and fire dispatchFormControlChangeEvent. | 623 // Update m_lastOnChangeSelection and fire dispatchFormControlChangeEvent. |
| 624 bool fireOnChange = false; | 624 bool fireOnChange = false; |
| 625 for (unsigned i = 0; i < items.size(); ++i) { | 625 for (unsigned i = 0; i < items.size(); ++i) { |
| 626 HTMLElement* element = items[i]; | 626 HTMLElement* element = items[i]; |
| 627 bool selected = element->hasTagName(optionTag) && toHTMLOptionElement(el
ement)->selected(); | 627 bool selected = isHTMLOptionElement(*element) && toHTMLOptionElement(ele
ment)->selected(); |
| 628 if (selected != m_lastOnChangeSelection[i]) | 628 if (selected != m_lastOnChangeSelection[i]) |
| 629 fireOnChange = true; | 629 fireOnChange = true; |
| 630 m_lastOnChangeSelection[i] = selected; | 630 m_lastOnChangeSelection[i] = selected; |
| 631 } | 631 } |
| 632 | 632 |
| 633 if (fireOnChange) { | 633 if (fireOnChange) { |
| 634 RefPtr<HTMLSelectElement> protector(this); | 634 RefPtr<HTMLSelectElement> protector(this); |
| 635 dispatchInputEvent(); | 635 dispatchInputEvent(); |
| 636 dispatchFormControlChangeEvent(); | 636 dispatchFormControlChangeEvent(); |
| 637 } | 637 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 for (Element* currentElement = ElementTraversal::firstWithin(*this); current
Element; ) { | 725 for (Element* currentElement = ElementTraversal::firstWithin(*this); current
Element; ) { |
| 726 if (!currentElement->isHTMLElement()) { | 726 if (!currentElement->isHTMLElement()) { |
| 727 currentElement = ElementTraversal::nextSkippingChildren(*currentElem
ent, this); | 727 currentElement = ElementTraversal::nextSkippingChildren(*currentElem
ent, this); |
| 728 continue; | 728 continue; |
| 729 } | 729 } |
| 730 HTMLElement& current = toHTMLElement(*currentElement); | 730 HTMLElement& current = toHTMLElement(*currentElement); |
| 731 | 731 |
| 732 // optgroup tags may not nest. However, both FireFox and IE will | 732 // optgroup tags may not nest. However, both FireFox and IE will |
| 733 // flatten the tree automatically, so we follow suit. | 733 // flatten the tree automatically, so we follow suit. |
| 734 // (http://www.w3.org/TR/html401/interact/forms.html#h-17.6) | 734 // (http://www.w3.org/TR/html401/interact/forms.html#h-17.6) |
| 735 if (current.hasTagName(optgroupTag)) { | 735 if (isHTMLOptGroupElement(current)) { |
| 736 m_listItems.append(¤t); | 736 m_listItems.append(¤t); |
| 737 if (Element* nextElement = ElementTraversal::firstWithin(current)) { | 737 if (Element* nextElement = ElementTraversal::firstWithin(current)) { |
| 738 currentElement = nextElement; | 738 currentElement = nextElement; |
| 739 continue; | 739 continue; |
| 740 } | 740 } |
| 741 } | 741 } |
| 742 | 742 |
| 743 if (current.hasTagName(optionTag)) { | 743 if (isHTMLOptionElement(current)) { |
| 744 m_listItems.append(¤t); | 744 m_listItems.append(¤t); |
| 745 | 745 |
| 746 if (updateSelectedStates && !m_multiple) { | 746 if (updateSelectedStates && !m_multiple) { |
| 747 HTMLOptionElement& option = toHTMLOptionElement(current); | 747 HTMLOptionElement& option = toHTMLOptionElement(current); |
| 748 if (!firstOption) | 748 if (!firstOption) |
| 749 firstOption = &option; | 749 firstOption = &option; |
| 750 if (option.selected()) { | 750 if (option.selected()) { |
| 751 if (foundSelected) | 751 if (foundSelected) |
| 752 foundSelected->setSelectedState(false); | 752 foundSelected->setSelectedState(false); |
| 753 foundSelected = &option; | 753 foundSelected = &option; |
| 754 } else if (m_size <= 1 && !foundSelected && !option.isDisabledFo
rmControl()) { | 754 } else if (m_size <= 1 && !foundSelected && !option.isDisabledFo
rmControl()) { |
| 755 foundSelected = &option; | 755 foundSelected = &option; |
| 756 foundSelected->setSelectedState(true); | 756 foundSelected->setSelectedState(true); |
| 757 } | 757 } |
| 758 } | 758 } |
| 759 } | 759 } |
| 760 | 760 |
| 761 if (current.hasTagName(hrTag)) | 761 if (isHTMLHRElement(current)) |
| 762 m_listItems.append(¤t); | 762 m_listItems.append(¤t); |
| 763 | 763 |
| 764 // In conforming HTML code, only <optgroup> and <option> will be found | 764 // In conforming HTML code, only <optgroup> and <option> will be found |
| 765 // within a <select>. We call NodeTraversal::nextSkippingChildren so tha
t we only step | 765 // within a <select>. We call NodeTraversal::nextSkippingChildren so tha
t we only step |
| 766 // into those tags that we choose to. For web-compat, we should cope | 766 // into those tags that we choose to. For web-compat, we should cope |
| 767 // with the case where odd tags like a <div> have been added but we | 767 // with the case where odd tags like a <div> have been added but we |
| 768 // handle this because such tags have already been removed from the | 768 // handle this because such tags have already been removed from the |
| 769 // <select>'s subtree at this point. | 769 // <select>'s subtree at this point. |
| 770 currentElement = ElementTraversal::nextSkippingChildren(*currentElement,
this); | 770 currentElement = ElementTraversal::nextSkippingChildren(*currentElement,
this); |
| 771 } | 771 } |
| 772 | 772 |
| 773 if (!foundSelected && m_size <= 1 && firstOption && !firstOption->selected()
) | 773 if (!foundSelected && m_size <= 1 && firstOption && !firstOption->selected()
) |
| 774 firstOption->setSelectedState(true); | 774 firstOption->setSelectedState(true); |
| 775 } | 775 } |
| 776 | 776 |
| 777 int HTMLSelectElement::selectedIndex() const | 777 int HTMLSelectElement::selectedIndex() const |
| 778 { | 778 { |
| 779 unsigned index = 0; | 779 unsigned index = 0; |
| 780 | 780 |
| 781 // Return the number of the first option selected. | 781 // Return the number of the first option selected. |
| 782 const Vector<HTMLElement*>& items = listItems(); | 782 const Vector<HTMLElement*>& items = listItems(); |
| 783 for (size_t i = 0; i < items.size(); ++i) { | 783 for (size_t i = 0; i < items.size(); ++i) { |
| 784 HTMLElement* element = items[i]; | 784 HTMLElement* element = items[i]; |
| 785 if (element->hasTagName(optionTag)) { | 785 if (isHTMLOptionElement(*element)) { |
| 786 if (toHTMLOptionElement(element)->selected()) | 786 if (toHTMLOptionElement(*element).selected()) |
| 787 return index; | 787 return index; |
| 788 ++index; | 788 ++index; |
| 789 } | 789 } |
| 790 } | 790 } |
| 791 | 791 |
| 792 return -1; | 792 return -1; |
| 793 } | 793 } |
| 794 | 794 |
| 795 void HTMLSelectElement::setSelectedIndex(int index) | 795 void HTMLSelectElement::setSelectedIndex(int index) |
| 796 { | 796 { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 811 void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags) | 811 void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags) |
| 812 { | 812 { |
| 813 bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions); | 813 bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions); |
| 814 | 814 |
| 815 const Vector<HTMLElement*>& items = listItems(); | 815 const Vector<HTMLElement*>& items = listItems(); |
| 816 int listIndex = optionToListIndex(optionIndex); | 816 int listIndex = optionToListIndex(optionIndex); |
| 817 | 817 |
| 818 HTMLElement* element = 0; | 818 HTMLElement* element = 0; |
| 819 if (listIndex >= 0) { | 819 if (listIndex >= 0) { |
| 820 element = items[listIndex]; | 820 element = items[listIndex]; |
| 821 if (element->hasTagName(optionTag)) { | 821 if (isHTMLOptionElement(*element)) { |
| 822 if (m_activeSelectionAnchorIndex < 0 || shouldDeselect) | 822 if (m_activeSelectionAnchorIndex < 0 || shouldDeselect) |
| 823 setActiveSelectionAnchorIndex(listIndex); | 823 setActiveSelectionAnchorIndex(listIndex); |
| 824 if (m_activeSelectionEndIndex < 0 || shouldDeselect) | 824 if (m_activeSelectionEndIndex < 0 || shouldDeselect) |
| 825 setActiveSelectionEndIndex(listIndex); | 825 setActiveSelectionEndIndex(listIndex); |
| 826 toHTMLOptionElement(element)->setSelectedState(true); | 826 toHTMLOptionElement(*element).setSelectedState(true); |
| 827 } | 827 } |
| 828 } | 828 } |
| 829 | 829 |
| 830 if (shouldDeselect) | 830 if (shouldDeselect) |
| 831 deselectItemsWithoutValidation(element); | 831 deselectItemsWithoutValidation(element); |
| 832 | 832 |
| 833 // For the menu list case, this is what makes the selected element appear. | 833 // For the menu list case, this is what makes the selected element appear. |
| 834 if (RenderObject* renderer = this->renderer()) | 834 if (RenderObject* renderer = this->renderer()) |
| 835 renderer->updateFromElement(); | 835 renderer->updateFromElement(); |
| 836 | 836 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 854 | 854 |
| 855 int HTMLSelectElement::optionToListIndex(int optionIndex) const | 855 int HTMLSelectElement::optionToListIndex(int optionIndex) const |
| 856 { | 856 { |
| 857 const Vector<HTMLElement*>& items = listItems(); | 857 const Vector<HTMLElement*>& items = listItems(); |
| 858 int listSize = static_cast<int>(items.size()); | 858 int listSize = static_cast<int>(items.size()); |
| 859 if (optionIndex < 0 || optionIndex >= listSize) | 859 if (optionIndex < 0 || optionIndex >= listSize) |
| 860 return -1; | 860 return -1; |
| 861 | 861 |
| 862 int optionIndex2 = -1; | 862 int optionIndex2 = -1; |
| 863 for (int listIndex = 0; listIndex < listSize; ++listIndex) { | 863 for (int listIndex = 0; listIndex < listSize; ++listIndex) { |
| 864 if (items[listIndex]->hasTagName(optionTag)) { | 864 if (isHTMLOptionElement(*items[listIndex])) { |
| 865 ++optionIndex2; | 865 ++optionIndex2; |
| 866 if (optionIndex2 == optionIndex) | 866 if (optionIndex2 == optionIndex) |
| 867 return listIndex; | 867 return listIndex; |
| 868 } | 868 } |
| 869 } | 869 } |
| 870 | 870 |
| 871 return -1; | 871 return -1; |
| 872 } | 872 } |
| 873 | 873 |
| 874 int HTMLSelectElement::listToOptionIndex(int listIndex) const | 874 int HTMLSelectElement::listToOptionIndex(int listIndex) const |
| 875 { | 875 { |
| 876 const Vector<HTMLElement*>& items = listItems(); | 876 const Vector<HTMLElement*>& items = listItems(); |
| 877 if (listIndex < 0 || listIndex >= static_cast<int>(items.size()) || !items[l
istIndex]->hasTagName(optionTag)) | 877 if (listIndex < 0 || listIndex >= static_cast<int>(items.size()) || !isHTMLO
ptionElement(*items[listIndex])) |
| 878 return -1; | 878 return -1; |
| 879 | 879 |
| 880 // Actual index of option not counting OPTGROUP entries that may be in list. | 880 // Actual index of option not counting OPTGROUP entries that may be in list. |
| 881 int optionIndex = 0; | 881 int optionIndex = 0; |
| 882 for (int i = 0; i < listIndex; ++i) { | 882 for (int i = 0; i < listIndex; ++i) { |
| 883 if (items[i]->hasTagName(optionTag)) | 883 if (isHTMLOptionElement(*items[i])) |
| 884 ++optionIndex; | 884 ++optionIndex; |
| 885 } | 885 } |
| 886 | 886 |
| 887 return optionIndex; | 887 return optionIndex; |
| 888 } | 888 } |
| 889 | 889 |
| 890 void HTMLSelectElement::dispatchFocusEvent(Element* oldFocusedElement, FocusType
type) | 890 void HTMLSelectElement::dispatchFocusEvent(Element* oldFocusedElement, FocusType
type) |
| 891 { | 891 { |
| 892 // Save the selection so it can be compared to the new selection when | 892 // Save the selection so it can be compared to the new selection when |
| 893 // dispatching change events during blur event dispatch. | 893 // dispatching change events during blur event dispatch. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 904 if (usesMenuList()) | 904 if (usesMenuList()) |
| 905 dispatchInputAndChangeEventForMenuList(); | 905 dispatchInputAndChangeEventForMenuList(); |
| 906 HTMLFormControlElementWithState::dispatchBlurEvent(newFocusedElement); | 906 HTMLFormControlElementWithState::dispatchBlurEvent(newFocusedElement); |
| 907 } | 907 } |
| 908 | 908 |
| 909 void HTMLSelectElement::deselectItemsWithoutValidation(HTMLElement* excludeEleme
nt) | 909 void HTMLSelectElement::deselectItemsWithoutValidation(HTMLElement* excludeEleme
nt) |
| 910 { | 910 { |
| 911 const Vector<HTMLElement*>& items = listItems(); | 911 const Vector<HTMLElement*>& items = listItems(); |
| 912 for (unsigned i = 0; i < items.size(); ++i) { | 912 for (unsigned i = 0; i < items.size(); ++i) { |
| 913 HTMLElement* element = items[i]; | 913 HTMLElement* element = items[i]; |
| 914 if (element != excludeElement && element->hasTagName(optionTag)) | 914 if (element != excludeElement && isHTMLOptionElement(*element)) |
| 915 toHTMLOptionElement(element)->setSelectedState(false); | 915 toHTMLOptionElement(element)->setSelectedState(false); |
| 916 } | 916 } |
| 917 } | 917 } |
| 918 | 918 |
| 919 FormControlState HTMLSelectElement::saveFormControlState() const | 919 FormControlState HTMLSelectElement::saveFormControlState() const |
| 920 { | 920 { |
| 921 const Vector<HTMLElement*>& items = listItems(); | 921 const Vector<HTMLElement*>& items = listItems(); |
| 922 size_t length = items.size(); | 922 size_t length = items.size(); |
| 923 FormControlState state; | 923 FormControlState state; |
| 924 for (unsigned i = 0; i < length; ++i) { | 924 for (unsigned i = 0; i < length; ++i) { |
| 925 if (!items[i]->hasTagName(optionTag)) | 925 if (!isHTMLOptionElement(*items[i])) |
| 926 continue; | 926 continue; |
| 927 HTMLOptionElement* option = toHTMLOptionElement(items[i]); | 927 HTMLOptionElement* option = toHTMLOptionElement(items[i]); |
| 928 if (!option->selected()) | 928 if (!option->selected()) |
| 929 continue; | 929 continue; |
| 930 state.append(option->value()); | 930 state.append(option->value()); |
| 931 if (!multiple()) | 931 if (!multiple()) |
| 932 break; | 932 break; |
| 933 } | 933 } |
| 934 return state; | 934 return state; |
| 935 } | 935 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 997 { | 997 { |
| 998 const AtomicString& name = this->name(); | 998 const AtomicString& name = this->name(); |
| 999 if (name.isEmpty()) | 999 if (name.isEmpty()) |
| 1000 return false; | 1000 return false; |
| 1001 | 1001 |
| 1002 bool successful = false; | 1002 bool successful = false; |
| 1003 const Vector<HTMLElement*>& items = listItems(); | 1003 const Vector<HTMLElement*>& items = listItems(); |
| 1004 | 1004 |
| 1005 for (unsigned i = 0; i < items.size(); ++i) { | 1005 for (unsigned i = 0; i < items.size(); ++i) { |
| 1006 HTMLElement* element = items[i]; | 1006 HTMLElement* element = items[i]; |
| 1007 if (element->hasTagName(optionTag) && toHTMLOptionElement(element)->sele
cted() && !toHTMLOptionElement(element)->isDisabledFormControl()) { | 1007 if (isHTMLOptionElement(*element) && toHTMLOptionElement(*element).selec
ted() && !toHTMLOptionElement(*element).isDisabledFormControl()) { |
| 1008 list.appendData(name, toHTMLOptionElement(element)->value()); | 1008 list.appendData(name, toHTMLOptionElement(*element).value()); |
| 1009 successful = true; | 1009 successful = true; |
| 1010 } | 1010 } |
| 1011 } | 1011 } |
| 1012 | 1012 |
| 1013 // It's possible that this is a menulist with multiple options and nothing | 1013 // It's possible that this is a menulist with multiple options and nothing |
| 1014 // will be submitted (!successful). We won't send a unselected non-disabled | 1014 // will be submitted (!successful). We won't send a unselected non-disabled |
| 1015 // option as fallback. This behavior matches to other browsers. | 1015 // option as fallback. This behavior matches to other browsers. |
| 1016 return successful; | 1016 return successful; |
| 1017 } | 1017 } |
| 1018 | 1018 |
| 1019 void HTMLSelectElement::resetImpl() | 1019 void HTMLSelectElement::resetImpl() |
| 1020 { | 1020 { |
| 1021 HTMLOptionElement* firstOption = 0; | 1021 HTMLOptionElement* firstOption = 0; |
| 1022 HTMLOptionElement* selectedOption = 0; | 1022 HTMLOptionElement* selectedOption = 0; |
| 1023 | 1023 |
| 1024 const Vector<HTMLElement*>& items = listItems(); | 1024 const Vector<HTMLElement*>& items = listItems(); |
| 1025 for (unsigned i = 0; i < items.size(); ++i) { | 1025 for (unsigned i = 0; i < items.size(); ++i) { |
| 1026 HTMLElement* element = items[i]; | 1026 HTMLElement* element = items[i]; |
| 1027 if (!element->hasTagName(optionTag)) | 1027 if (!isHTMLOptionElement(*element)) |
| 1028 continue; | 1028 continue; |
| 1029 | 1029 |
| 1030 if (items[i]->fastHasAttribute(selectedAttr)) { | 1030 if (items[i]->fastHasAttribute(selectedAttr)) { |
| 1031 if (selectedOption && !m_multiple) | 1031 if (selectedOption && !m_multiple) |
| 1032 selectedOption->setSelectedState(false); | 1032 selectedOption->setSelectedState(false); |
| 1033 toHTMLOptionElement(element)->setSelectedState(true); | 1033 toHTMLOptionElement(element)->setSelectedState(true); |
| 1034 selectedOption = toHTMLOptionElement(element); | 1034 selectedOption = toHTMLOptionElement(element); |
| 1035 } else | 1035 } else |
| 1036 toHTMLOptionElement(element)->setSelectedState(false); | 1036 toHTMLOptionElement(element)->setSelectedState(false); |
| 1037 | 1037 |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1222 // Save the selection so it can be compared to the new selection when | 1222 // Save the selection so it can be compared to the new selection when |
| 1223 // dispatching change events during mouseup, or after autoscroll finishes. | 1223 // dispatching change events during mouseup, or after autoscroll finishes. |
| 1224 saveLastSelection(); | 1224 saveLastSelection(); |
| 1225 | 1225 |
| 1226 m_activeSelectionState = true; | 1226 m_activeSelectionState = true; |
| 1227 | 1227 |
| 1228 bool shiftSelect = m_multiple && shift; | 1228 bool shiftSelect = m_multiple && shift; |
| 1229 bool multiSelect = m_multiple && multi && !shift; | 1229 bool multiSelect = m_multiple && multi && !shift; |
| 1230 | 1230 |
| 1231 HTMLElement* clickedElement = listItems()[listIndex]; | 1231 HTMLElement* clickedElement = listItems()[listIndex]; |
| 1232 if (clickedElement->hasTagName(optionTag)) { | 1232 ASSERT(clickedElement); |
| 1233 if (isHTMLOptionElement(*clickedElement)) { |
| 1233 // Keep track of whether an active selection (like during drag | 1234 // Keep track of whether an active selection (like during drag |
| 1234 // selection), should select or deselect. | 1235 // selection), should select or deselect. |
| 1235 if (toHTMLOptionElement(clickedElement)->selected() && multiSelect) | 1236 if (toHTMLOptionElement(*clickedElement).selected() && multiSelect) |
| 1236 m_activeSelectionState = false; | 1237 m_activeSelectionState = false; |
| 1237 if (!m_activeSelectionState) | 1238 if (!m_activeSelectionState) |
| 1238 toHTMLOptionElement(clickedElement)->setSelectedState(false); | 1239 toHTMLOptionElement(*clickedElement).setSelectedState(false); |
| 1239 } | 1240 } |
| 1240 | 1241 |
| 1241 // If we're not in any special multiple selection mode, then deselect all | 1242 // If we're not in any special multiple selection mode, then deselect all |
| 1242 // other items, excluding the clicked option. If no option was clicked, then | 1243 // other items, excluding the clicked option. If no option was clicked, then |
| 1243 // this will deselect all items in the list. | 1244 // this will deselect all items in the list. |
| 1244 if (!shiftSelect && !multiSelect) | 1245 if (!shiftSelect && !multiSelect) |
| 1245 deselectItemsWithoutValidation(clickedElement); | 1246 deselectItemsWithoutValidation(clickedElement); |
| 1246 | 1247 |
| 1247 // If the anchor hasn't been set, and we're doing a single selection or a | 1248 // If the anchor hasn't been set, and we're doing a single selection or a |
| 1248 // shift selection, then initialize the anchor to the first selected index. | 1249 // shift selection, then initialize the anchor to the first selected index. |
| 1249 if (m_activeSelectionAnchorIndex < 0 && !multiSelect) | 1250 if (m_activeSelectionAnchorIndex < 0 && !multiSelect) |
| 1250 setActiveSelectionAnchorIndex(selectedIndex()); | 1251 setActiveSelectionAnchorIndex(selectedIndex()); |
| 1251 | 1252 |
| 1252 // Set the selection state of the clicked option. | 1253 // Set the selection state of the clicked option. |
| 1253 if (clickedElement->hasTagName(optionTag) && !toHTMLOptionElement(clickedEle
ment)->isDisabledFormControl()) | 1254 if (isHTMLOptionElement(*clickedElement) && !toHTMLOptionElement(*clickedEle
ment).isDisabledFormControl()) |
| 1254 toHTMLOptionElement(clickedElement)->setSelectedState(true); | 1255 toHTMLOptionElement(*clickedElement).setSelectedState(true); |
| 1255 | 1256 |
| 1256 // If there was no selectedIndex() for the previous initialization, or If | 1257 // If there was no selectedIndex() for the previous initialization, or If |
| 1257 // we're doing a single selection, or a multiple selection (using cmd or | 1258 // we're doing a single selection, or a multiple selection (using cmd or |
| 1258 // ctrl), then initialize the anchor index to the listIndex that just got | 1259 // ctrl), then initialize the anchor index to the listIndex that just got |
| 1259 // clicked. | 1260 // clicked. |
| 1260 if (m_activeSelectionAnchorIndex < 0 || !shiftSelect) | 1261 if (m_activeSelectionAnchorIndex < 0 || !shiftSelect) |
| 1261 setActiveSelectionAnchorIndex(listIndex); | 1262 setActiveSelectionAnchorIndex(listIndex); |
| 1262 | 1263 |
| 1263 setActiveSelectionEndIndex(listIndex); | 1264 setActiveSelectionEndIndex(listIndex); |
| 1264 updateListBoxSelection(!multiSelect); | 1265 updateListBoxSelection(!multiSelect); |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1453 } | 1454 } |
| 1454 } | 1455 } |
| 1455 HTMLFormControlElementWithState::defaultEventHandler(event); | 1456 HTMLFormControlElementWithState::defaultEventHandler(event); |
| 1456 } | 1457 } |
| 1457 | 1458 |
| 1458 int HTMLSelectElement::lastSelectedListIndex() const | 1459 int HTMLSelectElement::lastSelectedListIndex() const |
| 1459 { | 1460 { |
| 1460 const Vector<HTMLElement*>& items = listItems(); | 1461 const Vector<HTMLElement*>& items = listItems(); |
| 1461 for (size_t i = items.size(); i;) { | 1462 for (size_t i = items.size(); i;) { |
| 1462 HTMLElement* element = items[--i]; | 1463 HTMLElement* element = items[--i]; |
| 1463 if (element->hasTagName(optionTag) && toHTMLOptionElement(element)->sele
cted()) | 1464 if (isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selec
ted()) |
| 1464 return i; | 1465 return i; |
| 1465 } | 1466 } |
| 1466 return -1; | 1467 return -1; |
| 1467 } | 1468 } |
| 1468 | 1469 |
| 1469 int HTMLSelectElement::indexOfSelectedOption() const | 1470 int HTMLSelectElement::indexOfSelectedOption() const |
| 1470 { | 1471 { |
| 1471 return optionToListIndex(selectedIndex()); | 1472 return optionToListIndex(selectedIndex()); |
| 1472 } | 1473 } |
| 1473 | 1474 |
| 1474 int HTMLSelectElement::optionCount() const | 1475 int HTMLSelectElement::optionCount() const |
| 1475 { | 1476 { |
| 1476 return listItems().size(); | 1477 return listItems().size(); |
| 1477 } | 1478 } |
| 1478 | 1479 |
| 1479 String HTMLSelectElement::optionAtIndex(int index) const | 1480 String HTMLSelectElement::optionAtIndex(int index) const |
| 1480 { | 1481 { |
| 1481 const Vector<HTMLElement*>& items = listItems(); | 1482 const Vector<HTMLElement*>& items = listItems(); |
| 1482 | 1483 |
| 1483 HTMLElement* element = items[index]; | 1484 HTMLElement* element = items[index]; |
| 1484 if (!element->hasTagName(optionTag) || toHTMLOptionElement(element)->isDisab
ledFormControl()) | 1485 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDisabl
edFormControl()) |
| 1485 return String(); | 1486 return String(); |
| 1486 return toHTMLOptionElement(element)->textIndentedToRespectGroupLabel(); | 1487 return toHTMLOptionElement(element)->textIndentedToRespectGroupLabel(); |
| 1487 } | 1488 } |
| 1488 | 1489 |
| 1489 void HTMLSelectElement::typeAheadFind(KeyboardEvent* event) | 1490 void HTMLSelectElement::typeAheadFind(KeyboardEvent* event) |
| 1490 { | 1491 { |
| 1491 int index = m_typeAhead.handleEvent(event, TypeAhead::MatchPrefix | TypeAhea
d::CycleFirstChar); | 1492 int index = m_typeAhead.handleEvent(event, TypeAhead::MatchPrefix | TypeAhea
d::CycleFirstChar); |
| 1492 if (index < 0) | 1493 if (index < 0) |
| 1493 return; | 1494 return; |
| 1494 selectOption(listToOptionIndex(index), DeselectOtherOptions | DispatchInputA
ndChangeEvent | UserDriven); | 1495 selectOption(listToOptionIndex(index), DeselectOtherOptions | DispatchInputA
ndChangeEvent | UserDriven); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1510 { | 1511 { |
| 1511 // First bring into focus the list box. | 1512 // First bring into focus the list box. |
| 1512 if (!focused()) | 1513 if (!focused()) |
| 1513 accessKeyAction(false); | 1514 accessKeyAction(false); |
| 1514 | 1515 |
| 1515 // If this index is already selected, unselect. otherwise update the selecte
d index. | 1516 // If this index is already selected, unselect. otherwise update the selecte
d index. |
| 1516 const Vector<HTMLElement*>& items = listItems(); | 1517 const Vector<HTMLElement*>& items = listItems(); |
| 1517 int listIndex = optionToListIndex(index); | 1518 int listIndex = optionToListIndex(index); |
| 1518 if (listIndex >= 0) { | 1519 if (listIndex >= 0) { |
| 1519 HTMLElement* element = items[listIndex]; | 1520 HTMLElement* element = items[listIndex]; |
| 1520 if (element->hasTagName(optionTag)) { | 1521 if (isHTMLOptionElement(*element)) { |
| 1521 if (toHTMLOptionElement(element)->selected()) | 1522 if (toHTMLOptionElement(*element).selected()) |
| 1522 toHTMLOptionElement(element)->setSelectedState(false); | 1523 toHTMLOptionElement(*element).setSelectedState(false); |
| 1523 else | 1524 else |
| 1524 selectOption(index, DispatchInputAndChangeEvent | UserDriven); | 1525 selectOption(index, DispatchInputAndChangeEvent | UserDriven); |
| 1525 } | 1526 } |
| 1526 } | 1527 } |
| 1527 | 1528 |
| 1528 if (usesMenuList()) | 1529 if (usesMenuList()) |
| 1529 dispatchInputAndChangeEventForMenuList(); | 1530 dispatchInputAndChangeEventForMenuList(); |
| 1530 else | 1531 else |
| 1531 listBoxOnChange(); | 1532 listBoxOnChange(); |
| 1532 | 1533 |
| 1533 scrollToSelection(); | 1534 scrollToSelection(); |
| 1534 } | 1535 } |
| 1535 | 1536 |
| 1536 unsigned HTMLSelectElement::length() const | 1537 unsigned HTMLSelectElement::length() const |
| 1537 { | 1538 { |
| 1538 unsigned options = 0; | 1539 unsigned options = 0; |
| 1539 | 1540 |
| 1540 const Vector<HTMLElement*>& items = listItems(); | 1541 const Vector<HTMLElement*>& items = listItems(); |
| 1541 for (unsigned i = 0; i < items.size(); ++i) { | 1542 for (unsigned i = 0; i < items.size(); ++i) { |
| 1542 if (items[i]->hasTagName(optionTag)) | 1543 if (isHTMLOptionElement(*items[i])) |
| 1543 ++options; | 1544 ++options; |
| 1544 } | 1545 } |
| 1545 | 1546 |
| 1546 return options; | 1547 return options; |
| 1547 } | 1548 } |
| 1548 | 1549 |
| 1549 void HTMLSelectElement::finishParsingChildren() | 1550 void HTMLSelectElement::finishParsingChildren() |
| 1550 { | 1551 { |
| 1551 HTMLFormControlElementWithState::finishParsingChildren(); | 1552 HTMLFormControlElementWithState::finishParsingChildren(); |
| 1552 updateListItemSelectedStates(); | 1553 updateListItemSelectedStates(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1566 { | 1567 { |
| 1567 return true; | 1568 return true; |
| 1568 } | 1569 } |
| 1569 | 1570 |
| 1570 bool HTMLSelectElement::supportsAutofocus() const | 1571 bool HTMLSelectElement::supportsAutofocus() const |
| 1571 { | 1572 { |
| 1572 return true; | 1573 return true; |
| 1573 } | 1574 } |
| 1574 | 1575 |
| 1575 } // namespace | 1576 } // namespace |
| OLD | NEW |