Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(368)

Side by Side Diff: Source/core/html/HTMLSelectElement.cpp

Issue 347773002: Implement select listbox using shadow DOM (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/html/HTMLSelectElement.h ('k') | Source/core/html/shadow/ShadowElementNames.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 21 matching lines...) Expand all
32 #include "bindings/core/v8/ExceptionState.h" 32 #include "bindings/core/v8/ExceptionState.h"
33 #include "bindings/core/v8/ExceptionStatePlaceholder.h" 33 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
34 #include "core/HTMLNames.h" 34 #include "core/HTMLNames.h"
35 #include "core/accessibility/AXObjectCache.h" 35 #include "core/accessibility/AXObjectCache.h"
36 #include "core/dom/Attribute.h" 36 #include "core/dom/Attribute.h"
37 #include "core/dom/ElementTraversal.h" 37 #include "core/dom/ElementTraversal.h"
38 #include "core/dom/NodeTraversal.h" 38 #include "core/dom/NodeTraversal.h"
39 #include "core/events/GestureEvent.h" 39 #include "core/events/GestureEvent.h"
40 #include "core/events/KeyboardEvent.h" 40 #include "core/events/KeyboardEvent.h"
41 #include "core/events/MouseEvent.h" 41 #include "core/events/MouseEvent.h"
42 #include "core/frame/FrameView.h"
42 #include "core/frame/LocalFrame.h" 43 #include "core/frame/LocalFrame.h"
43 #include "core/html/FormDataList.h" 44 #include "core/html/FormDataList.h"
44 #include "core/html/HTMLFormElement.h" 45 #include "core/html/HTMLFormElement.h"
46 #include "core/html/HTMLOptGroupElement.h"
45 #include "core/html/HTMLOptionElement.h" 47 #include "core/html/HTMLOptionElement.h"
46 #include "core/html/forms/FormController.h" 48 #include "core/html/forms/FormController.h"
49 #include "core/page/AutoscrollController.h"
47 #include "core/page/EventHandler.h" 50 #include "core/page/EventHandler.h"
51 #include "core/page/Page.h"
48 #include "core/page/SpatialNavigation.h" 52 #include "core/page/SpatialNavigation.h"
53 #include "core/rendering/HitTestRequest.h"
54 #include "core/rendering/HitTestResult.h"
49 #include "core/rendering/RenderListBox.h" 55 #include "core/rendering/RenderListBox.h"
50 #include "core/rendering/RenderMenuList.h" 56 #include "core/rendering/RenderMenuList.h"
51 #include "core/rendering/RenderTheme.h" 57 #include "core/rendering/RenderTheme.h"
58 #include "core/rendering/RenderView.h"
52 #include "platform/PlatformMouseEvent.h" 59 #include "platform/PlatformMouseEvent.h"
53 #include "platform/text/PlatformLocale.h" 60 #include "platform/text/PlatformLocale.h"
54 61
55 using namespace WTF::Unicode; 62 using namespace WTF::Unicode;
56 63
57 namespace WebCore { 64 namespace WebCore {
58 65
59 using namespace HTMLNames; 66 using namespace HTMLNames;
60 67
61 // Upper limit agreed upon with representatives of Opera and Mozilla. 68 // Upper limit agreed upon with representatives of Opera and Mozilla.
(...skipping 11 matching lines...) Expand all
73 , m_activeSelectionState(false) 80 , m_activeSelectionState(false)
74 , m_shouldRecalcListItems(false) 81 , m_shouldRecalcListItems(false)
75 , m_suggestedIndex(-1) 82 , m_suggestedIndex(-1)
76 { 83 {
77 ScriptWrappable::init(this); 84 ScriptWrappable::init(this);
78 setHasCustomStyleCallbacks(); 85 setHasCustomStyleCallbacks();
79 } 86 }
80 87
81 PassRefPtrWillBeRawPtr<HTMLSelectElement> HTMLSelectElement::create(Document& do cument) 88 PassRefPtrWillBeRawPtr<HTMLSelectElement> HTMLSelectElement::create(Document& do cument)
82 { 89 {
83 return adoptRefWillBeNoop(new HTMLSelectElement(document, 0)); 90 RefPtrWillBeRawPtr<HTMLSelectElement> select = adoptRefWillBeNoop(new HTMLSe lectElement(document, 0));
91 select->ensureUserAgentShadowRoot();
92 return select.release();
84 } 93 }
85 94
86 PassRefPtrWillBeRawPtr<HTMLSelectElement> HTMLSelectElement::create(Document& do cument, HTMLFormElement* form) 95 PassRefPtrWillBeRawPtr<HTMLSelectElement> HTMLSelectElement::create(Document& do cument, HTMLFormElement* form)
87 { 96 {
88 return adoptRefWillBeNoop(new HTMLSelectElement(document, form)); 97 RefPtrWillBeRawPtr<HTMLSelectElement> select = adoptRefWillBeNoop(new HTMLSe lectElement(document, form));
98 select->ensureUserAgentShadowRoot();
99 return select.release();
89 } 100 }
90 101
91 const AtomicString& HTMLSelectElement::formControlType() const 102 const AtomicString& HTMLSelectElement::formControlType() const
92 { 103 {
93 DEFINE_STATIC_LOCAL(const AtomicString, selectMultiple, ("select-multiple", AtomicString::ConstructFromLiteral)); 104 DEFINE_STATIC_LOCAL(const AtomicString, selectMultiple, ("select-multiple", AtomicString::ConstructFromLiteral));
94 DEFINE_STATIC_LOCAL(const AtomicString, selectOne, ("select-one", AtomicStri ng::ConstructFromLiteral)); 105 DEFINE_STATIC_LOCAL(const AtomicString, selectOne, ("select-one", AtomicStri ng::ConstructFromLiteral));
95 return m_multiple ? selectMultiple : selectOne; 106 return m_multiple ? selectMultiple : selectOne;
96 } 107 }
97 108
98 void HTMLSelectElement::optionSelectedByUser(int optionIndex, bool fireOnChangeN ow, bool allowMultipleSelection) 109 void HTMLSelectElement::optionSelectedByUser(int optionIndex, bool fireOnChangeN ow, bool allowMultipleSelection)
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 // Valid means that it is enabled and an option element. 527 // Valid means that it is enabled and an option element.
517 int HTMLSelectElement::nextValidIndex(int listIndex, SkipDirection direction, in t skip) const 528 int HTMLSelectElement::nextValidIndex(int listIndex, SkipDirection direction, in t skip) const
518 { 529 {
519 ASSERT(direction == -1 || direction == 1); 530 ASSERT(direction == -1 || direction == 1);
520 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this-> listItems(); 531 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this-> listItems();
521 int lastGoodIndex = listIndex; 532 int lastGoodIndex = listIndex;
522 int size = listItems.size(); 533 int size = listItems.size();
523 for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex + = direction) { 534 for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex + = direction) {
524 --skip; 535 --skip;
525 HTMLElement* element = listItems[listIndex]; 536 HTMLElement* element = listItems[listIndex];
526 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDi sabledFormControl() || toHTMLOptionElement(element)->isDisplayNone()) 537 if (!isHTMLOptionElement(*element))
538 continue;
539 if (element->isDisabledFormControl())
540 continue;
541 if (!usesMenuList() && !element->renderer())
527 continue; 542 continue;
528 lastGoodIndex = listIndex; 543 lastGoodIndex = listIndex;
529 if (skip <= 0) 544 if (skip <= 0)
530 break; 545 break;
531 } 546 }
532 return lastGoodIndex; 547 return lastGoodIndex;
533 } 548 }
534 549
535 int HTMLSelectElement::nextSelectableListIndex(int startIndex) const 550 int HTMLSelectElement::nextSelectableListIndex(int startIndex) const
536 { 551 {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 634
620 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); 635 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( );
621 for (unsigned i = 0; i < items.size(); ++i) { 636 for (unsigned i = 0; i < items.size(); ++i) {
622 HTMLElement* element = items[i]; 637 HTMLElement* element = items[i];
623 m_cachedStateForActiveSelection.append(isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selected()); 638 m_cachedStateForActiveSelection.append(isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selected());
624 } 639 }
625 } 640 }
626 641
627 void HTMLSelectElement::setActiveSelectionEndIndex(int index) 642 void HTMLSelectElement::setActiveSelectionEndIndex(int index)
628 { 643 {
644 if (index == m_activeSelectionEndIndex)
645 return;
629 m_activeSelectionEndIndex = index; 646 m_activeSelectionEndIndex = index;
647 setNeedsStyleRecalc(SubtreeStyleChange);
630 } 648 }
631 649
632 void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions) 650 void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions)
633 { 651 {
634 ASSERT(renderer() && (renderer()->isListBox() || m_multiple)); 652 ASSERT(renderer() && (renderer()->isListBox() || m_multiple));
635 ASSERT(!listItems().size() || m_activeSelectionAnchorIndex >= 0); 653 ASSERT(!listItems().size() || m_activeSelectionAnchorIndex >= 0);
636 654
637 unsigned start = std::min(m_activeSelectionAnchorIndex, m_activeSelectionEnd Index); 655 unsigned start = std::min(m_activeSelectionAnchorIndex, m_activeSelectionEnd Index);
638 unsigned end = std::max(m_activeSelectionAnchorIndex, m_activeSelectionEndIn dex); 656 unsigned end = std::max(m_activeSelectionAnchorIndex, m_activeSelectionEndIn dex);
639 657
640 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); 658 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( );
641 for (unsigned i = 0; i < items.size(); ++i) { 659 for (unsigned i = 0; i < items.size(); ++i) {
642 HTMLElement* element = items[i]; 660 HTMLElement* element = items[i];
643 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDi sabledFormControl() || toHTMLOptionElement(element)->isDisplayNone()) 661 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDi sabledFormControl() || !toHTMLOptionElement(element)->renderer())
644 continue; 662 continue;
645 663
646 if (i >= start && i <= end) 664 if (i >= start && i <= end)
647 toHTMLOptionElement(element)->setSelectedState(m_activeSelectionStat e); 665 toHTMLOptionElement(element)->setSelectedState(m_activeSelectionStat e);
648 else if (deselectOtherOptions || i >= m_cachedStateForActiveSelection.si ze()) 666 else if (deselectOtherOptions || i >= m_cachedStateForActiveSelection.si ze())
649 toHTMLOptionElement(element)->setSelectedState(false); 667 toHTMLOptionElement(element)->setSelectedState(false);
650 else 668 else
651 toHTMLOptionElement(element)->setSelectedState(m_cachedStateForActiv eSelection[i]); 669 toHTMLOptionElement(element)->setSelectedState(m_cachedStateForActiv eSelection[i]);
652 } 670 }
653 671
672 setNeedsValidityCheck();
654 scrollToSelection(); 673 scrollToSelection();
655 setNeedsValidityCheck();
656 notifyFormStateChanged(); 674 notifyFormStateChanged();
657 } 675 }
658 676
659 void HTMLSelectElement::listBoxOnChange() 677 void HTMLSelectElement::listBoxOnChange()
660 { 678 {
661 ASSERT(!usesMenuList() || m_multiple); 679 ASSERT(!usesMenuList() || m_multiple);
662 680
663 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); 681 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( );
664 682
665 // If the cached selection list is empty, or the size has changed, then fire 683 // If the cached selection list is empty, or the size has changed, then fire
(...skipping 30 matching lines...) Expand all
696 m_lastOnChangeIndex = selected; 714 m_lastOnChangeIndex = selected;
697 m_isProcessingUserDrivenChange = false; 715 m_isProcessingUserDrivenChange = false;
698 RefPtrWillBeRawPtr<HTMLSelectElement> protector(this); 716 RefPtrWillBeRawPtr<HTMLSelectElement> protector(this);
699 dispatchInputEvent(); 717 dispatchInputEvent();
700 dispatchFormControlChangeEvent(); 718 dispatchFormControlChangeEvent();
701 } 719 }
702 } 720 }
703 721
704 void HTMLSelectElement::scrollToSelection() 722 void HTMLSelectElement::scrollToSelection()
705 { 723 {
724 if (!isFinishedParsingChildren())
725 return;
706 if (usesMenuList()) 726 if (usesMenuList())
707 return; 727 return;
708 728 scrollTo(activeSelectionEndListIndex());
709 if (RenderObject* renderer = this->renderer()) 729 if (AXObjectCache* cache = document().existingAXObjectCache())
710 toRenderListBox(renderer)->selectionChanged(); 730 cache->selectedChildrenChanged(this);
711 } 731 }
712 732
713 void HTMLSelectElement::setOptionsChangedOnRenderer() 733 void HTMLSelectElement::setOptionsChangedOnRenderer()
714 { 734 {
715 if (RenderObject* renderer = this->renderer()) { 735 if (RenderObject* renderer = this->renderer()) {
716 if (usesMenuList()) 736 if (usesMenuList())
717 toRenderMenuList(renderer)->setOptionsChanged(true); 737 toRenderMenuList(renderer)->setOptionsChanged(true);
718 else
719 toRenderListBox(renderer)->setOptionsChanged(true);
720 } 738 }
721 } 739 }
722 740
723 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& HTMLSelectElement::lis tItems() const 741 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& HTMLSelectElement::lis tItems() const
724 { 742 {
725 if (m_shouldRecalcListItems) 743 if (m_shouldRecalcListItems)
726 recalcListItems(); 744 recalcListItems();
727 else { 745 else {
728 #if ENABLE(ASSERT) 746 #if ENABLE(ASSERT)
729 WillBeHeapVector<RawPtrWillBeMember<HTMLElement> > items = m_listItems; 747 WillBeHeapVector<RawPtrWillBeMember<HTMLElement> > items = m_listItems;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 { 869 {
852 return m_suggestedIndex; 870 return m_suggestedIndex;
853 } 871 }
854 872
855 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex) 873 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex)
856 { 874 {
857 m_suggestedIndex = suggestedIndex; 875 m_suggestedIndex = suggestedIndex;
858 876
859 if (RenderObject* renderer = this->renderer()) { 877 if (RenderObject* renderer = this->renderer()) {
860 renderer->updateFromElement(); 878 renderer->updateFromElement();
861 if (renderer->isListBox()) 879 scrollTo(suggestedIndex);
862 toRenderListBox(renderer)->scrollToRevealElementAtListIndex(suggeste dIndex);
863 } 880 }
864 } 881 }
865 882
883 void HTMLSelectElement::scrollTo(int listIndex)
884 {
885 if (listIndex < 0)
886 return;
887 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( );
888 int listSize = static_cast<int>(items.size());
889 if (listIndex >= listSize)
890 return;
891 items[listIndex]->scrollIntoViewIfNeeded(false);
892 }
893
866 void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, b ool optionIsSelected) 894 void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, b ool optionIsSelected)
867 { 895 {
868 ASSERT(option->ownerSelectElement() == this); 896 ASSERT(option->ownerSelectElement() == this);
869 if (optionIsSelected) 897 if (optionIsSelected)
870 selectOption(option->index()); 898 selectOption(option->index());
871 else if (!usesMenuList() || multiple()) 899 else if (!usesMenuList() || multiple())
872 selectOption(-1); 900 selectOption(-1);
873 else 901 else
874 selectOption(nextSelectableListIndex(-1)); 902 selectOption(nextSelectableListIndex(-1));
875 } 903 }
876 904
905 void HTMLSelectElement::optionRemoved(const HTMLOptionElement& option)
906 {
907 if (m_activeSelectionAnchorIndex < 0 && m_activeSelectionEndIndex < 0)
908 return;
909 int listIndex = optionToListIndex(option.index());
910 if (listIndex <= m_activeSelectionAnchorIndex)
911 m_activeSelectionAnchorIndex--;
912 if (listIndex <= m_activeSelectionEndIndex)
913 m_activeSelectionEndIndex--;
914 }
915
877 void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags) 916 void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags)
878 { 917 {
879 bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions); 918 bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions);
880 919
881 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); 920 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( );
882 int listIndex = optionToListIndex(optionIndex); 921 int listIndex = optionToListIndex(optionIndex);
883 922
884 HTMLElement* element = 0; 923 HTMLElement* element = 0;
885 if (listIndex >= 0) { 924 if (listIndex >= 0) {
886 element = items[listIndex]; 925 element = items[listIndex];
(...skipping 15 matching lines...) Expand all
902 941
903 scrollToSelection(); 942 scrollToSelection();
904 943
905 setNeedsValidityCheck(); 944 setNeedsValidityCheck();
906 945
907 if (usesMenuList()) { 946 if (usesMenuList()) {
908 m_isProcessingUserDrivenChange = flags & UserDriven; 947 m_isProcessingUserDrivenChange = flags & UserDriven;
909 if (flags & DispatchInputAndChangeEvent) 948 if (flags & DispatchInputAndChangeEvent)
910 dispatchInputAndChangeEventForMenuList(); 949 dispatchInputAndChangeEventForMenuList();
911 if (RenderObject* renderer = this->renderer()) { 950 if (RenderObject* renderer = this->renderer()) {
912 if (usesMenuList()) 951 if (usesMenuList()) {
913 toRenderMenuList(renderer)->didSetSelectedIndex(listIndex); 952 toRenderMenuList(renderer)->didSetSelectedIndex(listIndex);
914 else if (renderer->isListBox()) 953 } else if (renderer->isListBox()) {
915 toRenderListBox(renderer)->selectionChanged(); 954 if (AXObjectCache* cache = document().existingAXObjectCache())
955 cache->selectedChildrenChanged(this);
956 }
916 } 957 }
917 } 958 }
918 959
919 notifyFormStateChanged(); 960 notifyFormStateChanged();
920 } 961 }
921 962
922 int HTMLSelectElement::optionToListIndex(int optionIndex) const 963 int HTMLSelectElement::optionToListIndex(int optionIndex) const
923 { 964 {
924 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); 965 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( );
925 int listSize = static_cast<int>(items.size()); 966 int listSize = static_cast<int>(items.size());
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1046 startIndex = foundIndex + 1; 1087 startIndex = foundIndex + 1;
1047 } 1088 }
1048 } 1089 }
1049 1090
1050 setOptionsChangedOnRenderer(); 1091 setOptionsChangedOnRenderer();
1051 setNeedsValidityCheck(); 1092 setNeedsValidityCheck();
1052 } 1093 }
1053 1094
1054 void HTMLSelectElement::parseMultipleAttribute(const AtomicString& value) 1095 void HTMLSelectElement::parseMultipleAttribute(const AtomicString& value)
1055 { 1096 {
1056 bool oldUsesMenuList = usesMenuList();
1057 m_multiple = !value.isNull(); 1097 m_multiple = !value.isNull();
1058 setNeedsValidityCheck(); 1098 setNeedsValidityCheck();
1059 if (oldUsesMenuList != usesMenuList()) 1099
1060 lazyReattachIfAttached(); 1100 lazyReattachIfAttached();
1061 } 1101 }
1062 1102
1063 bool HTMLSelectElement::appendFormData(FormDataList& list, bool) 1103 bool HTMLSelectElement::appendFormData(FormDataList& list, bool)
1064 { 1104 {
1065 const AtomicString& name = this->name(); 1105 const AtomicString& name = this->name();
1066 if (name.isEmpty()) 1106 if (name.isEmpty())
1067 return false; 1107 return false;
1068 1108
1069 bool successful = false; 1109 bool successful = false;
1070 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); 1110 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( );
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
1310 // we're doing a single selection, or a multiple selection (using cmd or 1350 // we're doing a single selection, or a multiple selection (using cmd or
1311 // ctrl), then initialize the anchor index to the listIndex that just got 1351 // ctrl), then initialize the anchor index to the listIndex that just got
1312 // clicked. 1352 // clicked.
1313 if (m_activeSelectionAnchorIndex < 0 || !shiftSelect) 1353 if (m_activeSelectionAnchorIndex < 0 || !shiftSelect)
1314 setActiveSelectionAnchorIndex(listIndex); 1354 setActiveSelectionAnchorIndex(listIndex);
1315 1355
1316 setActiveSelectionEndIndex(listIndex); 1356 setActiveSelectionEndIndex(listIndex);
1317 updateListBoxSelection(!multiSelect); 1357 updateListBoxSelection(!multiSelect);
1318 } 1358 }
1319 1359
1360 int HTMLSelectElement::listIndexForEventTargetOption(const Event& event)
1361 {
1362 Node* targetNode = event.target()->toNode();
1363 if (!targetNode || !isHTMLOptionElement(*targetNode))
1364 return -1;
1365 return listIndexForOption(toHTMLOptionElement(*targetNode));
1366 }
1367
1368 int HTMLSelectElement::listIndexForOption(const HTMLOptionElement& option)
1369 {
1370 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = this->list Items();
1371 size_t length = items.size();
1372 for (size_t i = 0; i < length; ++i) {
1373 if (items[i].get() == &option)
1374 return i;
1375 }
1376 return -1;
1377 }
1378
1379 AutoscrollController* HTMLSelectElement::autoscrollController() const
1380 {
1381 if (Page* page = document().page())
1382 return &page->autoscrollController();
1383 return 0;
1384 }
1385
1386 void HTMLSelectElement::handleMouseRelease()
1387 {
1388 // We didn't start this click/drag on any options.
1389 if (m_lastOnChangeSelection.isEmpty())
1390 return;
1391 listBoxOnChange();
1392 }
1393
1320 void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) 1394 void HTMLSelectElement::listBoxDefaultEventHandler(Event* event)
1321 { 1395 {
1322 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this-> listItems(); 1396 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this-> listItems();
1323 if (event->type() == EventTypeNames::gesturetap && event->isGestureEvent()) { 1397 if (event->type() == EventTypeNames::gesturetap && event->isGestureEvent()) {
1324 focus(); 1398 focus();
1325 // 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. 1399 // 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.
1326 if (!renderer() || !renderer()->isListBox()) 1400 if (!renderer() || !renderer()->isListBox())
1327 return; 1401 return;
1328 1402
1329 // Convert to coords relative to the list box if needed. 1403 // Convert to coords relative to the list box if needed.
1330 GestureEvent& gestureEvent = toGestureEvent(*event); 1404 GestureEvent& gestureEvent = toGestureEvent(*event);
1331 IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(gestu reEvent.absoluteLocation(), UseTransforms)); 1405 int listIndex = listIndexForEventTargetOption(gestureEvent);
1332 int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize (localOffset));
1333 if (listIndex >= 0) { 1406 if (listIndex >= 0) {
1334 if (!isDisabledFormControl()) 1407 if (!isDisabledFormControl())
1335 updateSelectedState(listIndex, true, gestureEvent.shiftKey()); 1408 updateSelectedState(listIndex, true, gestureEvent.shiftKey());
1336 event->setDefaultHandled(); 1409 event->setDefaultHandled();
1337 } 1410 }
1338 } else if (event->type() == EventTypeNames::mousedown && event->isMouseEvent () && toMouseEvent(event)->button() == LeftButton) { 1411 } else if (event->type() == EventTypeNames::mousedown && event->isMouseEvent () && toMouseEvent(event)->button() == LeftButton) {
1339 focus(); 1412 focus();
1340 // Calling focus() may cause us to lose our renderer, in which case do n ot want to handle the event. 1413 // Calling focus() may cause us to lose our renderer, in which case do n ot want to handle the event.
1341 if (!renderer() || !renderer()->isListBox() || isDisabledFormControl()) 1414 if (!renderer() || !renderer()->isListBox() || isDisabledFormControl())
1342 return; 1415 return;
1343 1416
1344 // Convert to coords relative to the list box if needed. 1417 // Convert to coords relative to the list box if needed.
1345 MouseEvent* mouseEvent = toMouseEvent(event); 1418 MouseEvent* mouseEvent = toMouseEvent(event);
1346 IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(mouse Event->absoluteLocation(), UseTransforms)); 1419 int listIndex = listIndexForEventTargetOption(*mouseEvent);
1347 int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize (localOffset));
1348 if (listIndex >= 0) { 1420 if (listIndex >= 0) {
1349 if (!isDisabledFormControl()) { 1421 if (!isDisabledFormControl()) {
1350 #if OS(MACOSX) 1422 #if OS(MACOSX)
1351 updateSelectedState(listIndex, mouseEvent->metaKey(), mouseEvent ->shiftKey()); 1423 updateSelectedState(listIndex, mouseEvent->metaKey(), mouseEvent ->shiftKey());
1352 #else 1424 #else
1353 updateSelectedState(listIndex, mouseEvent->ctrlKey(), mouseEvent ->shiftKey()); 1425 updateSelectedState(listIndex, mouseEvent->ctrlKey(), mouseEvent ->shiftKey());
1354 #endif 1426 #endif
1355 } 1427 }
1356 if (LocalFrame* frame = document().frame()) 1428 if (LocalFrame* frame = document().frame())
1357 frame->eventHandler().setMouseDownMayStartAutoscroll(); 1429 frame->eventHandler().setMouseDownMayStartAutoscroll();
1358 1430
1359 event->setDefaultHandled(); 1431 event->setDefaultHandled();
1360 } 1432 }
1361 } else if (event->type() == EventTypeNames::mousemove && event->isMouseEvent () && !toRenderBox(renderer())->canBeScrolledAndHasScrollableArea()) { 1433 } else if (event->type() == EventTypeNames::mousemove && event->isMouseEvent ()) {
1362 MouseEvent* mouseEvent = toMouseEvent(event); 1434 MouseEvent* mouseEvent = toMouseEvent(event);
1363 if (mouseEvent->button() != LeftButton || !mouseEvent->buttonDown()) 1435 if (mouseEvent->button() != LeftButton || !mouseEvent->buttonDown())
1364 return; 1436 return;
1365 1437
1366 IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(mouse Event->absoluteLocation(), UseTransforms)); 1438 if (Page* page = document().page())
1367 int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize (localOffset)); 1439 page->autoscrollController().startAutoscrollForSelection(renderer()) ;
1440
1441 int listIndex = listIndexForEventTargetOption(*mouseEvent);
1368 if (listIndex >= 0) { 1442 if (listIndex >= 0) {
1369 if (!isDisabledFormControl()) { 1443 if (!isDisabledFormControl()) {
1370 if (m_multiple) { 1444 if (m_multiple) {
1371 // Only extend selection if there is something selected. 1445 // Only extend selection if there is something selected.
1372 if (m_activeSelectionAnchorIndex < 0) 1446 if (m_activeSelectionAnchorIndex < 0)
1373 return; 1447 return;
1374 1448
1375 setActiveSelectionEndIndex(listIndex); 1449 setActiveSelectionEndIndex(listIndex);
1376 updateListBoxSelection(false); 1450 updateListBoxSelection(false);
1377 } else { 1451 } else {
1378 setActiveSelectionAnchorIndex(listIndex); 1452 setActiveSelectionAnchorIndex(listIndex);
1379 setActiveSelectionEndIndex(listIndex); 1453 setActiveSelectionEndIndex(listIndex);
1380 updateListBoxSelection(true); 1454 updateListBoxSelection(true);
1381 } 1455 }
1382 } 1456 }
1383 } 1457 }
1384 } else if (event->type() == EventTypeNames::mouseup && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton && renderer() && !toRenderBox(re nderer())->autoscrollInProgress()) { 1458 } else if (event->type() == EventTypeNames::mouseup && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton && renderer()) {
1385 // We didn't start this click/drag on any options. 1459 if (document().page() && document().page()->autoscrollController().autos crollInProgress(toRenderBox(renderer())))
1386 if (m_lastOnChangeSelection.isEmpty()) 1460 document().page()->autoscrollController().stopAutoscroll();
1387 return; 1461 else
1388 listBoxOnChange(); 1462 handleMouseRelease();
1389 } else if (event->type() == EventTypeNames::keydown) { 1463 } else if (event->type() == EventTypeNames::keydown) {
1390 if (!event->isKeyboardEvent()) 1464 if (!event->isKeyboardEvent())
1391 return; 1465 return;
1392 const String& keyIdentifier = toKeyboardEvent(event)->keyIdentifier(); 1466 const String& keyIdentifier = toKeyboardEvent(event)->keyIdentifier();
1393 1467
1394 bool handled = false; 1468 bool handled = false;
1395 int endIndex = 0; 1469 int endIndex = 0;
1396 if (m_activeSelectionEndIndex < 0) { 1470 if (m_activeSelectionEndIndex < 0) {
1397 // Initialize the end index 1471 // Initialize the end index
1398 if (keyIdentifier == "Down" || keyIdentifier == "PageDown") { 1472 if (keyIdentifier == "Down" || keyIdentifier == "PageDown") {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1453 m_activeSelectionState = true; 1527 m_activeSelectionState = true;
1454 // If the anchor is unitialized, or if we're going to deselect all 1528 // If the anchor is unitialized, or if we're going to deselect all
1455 // other options, then set the anchor index equal to the end index. 1529 // other options, then set the anchor index equal to the end index.
1456 bool deselectOthers = !m_multiple || (!toKeyboardEvent(event)->shift Key() && selectNewItem); 1530 bool deselectOthers = !m_multiple || (!toKeyboardEvent(event)->shift Key() && selectNewItem);
1457 if (m_activeSelectionAnchorIndex < 0 || deselectOthers) { 1531 if (m_activeSelectionAnchorIndex < 0 || deselectOthers) {
1458 if (deselectOthers) 1532 if (deselectOthers)
1459 deselectItemsWithoutValidation(); 1533 deselectItemsWithoutValidation();
1460 setActiveSelectionAnchorIndex(m_activeSelectionEndIndex); 1534 setActiveSelectionAnchorIndex(m_activeSelectionEndIndex);
1461 } 1535 }
1462 1536
1463 toRenderListBox(renderer())->scrollToRevealElementAtListIndex(endInd ex); 1537 scrollTo(endIndex);
1464 if (selectNewItem) { 1538 if (selectNewItem) {
1465 updateListBoxSelection(deselectOthers); 1539 updateListBoxSelection(deselectOthers);
1466 listBoxOnChange(); 1540 listBoxOnChange();
1467 } else 1541 } else
1468 scrollToSelection(); 1542 scrollToSelection();
1469 1543
1470 event->setDefaultHandled(); 1544 event->setDefaultHandled();
1471 } 1545 }
1472 } else if (event->type() == EventTypeNames::keypress) { 1546 } else if (event->type() == EventTypeNames::keypress) {
1473 if (!event->isKeyboardEvent()) 1547 if (!event->isKeyboardEvent())
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1604 ++options; 1678 ++options;
1605 } 1679 }
1606 1680
1607 return options; 1681 return options;
1608 } 1682 }
1609 1683
1610 void HTMLSelectElement::finishParsingChildren() 1684 void HTMLSelectElement::finishParsingChildren()
1611 { 1685 {
1612 HTMLFormControlElementWithState::finishParsingChildren(); 1686 HTMLFormControlElementWithState::finishParsingChildren();
1613 updateListItemSelectedStates(); 1687 updateListItemSelectedStates();
1688 scrollToSelection();
1614 } 1689 }
1615 1690
1616 bool HTMLSelectElement::anonymousIndexedSetter(unsigned index, PassRefPtrWillBeR awPtr<HTMLOptionElement> value, ExceptionState& exceptionState) 1691 bool HTMLSelectElement::anonymousIndexedSetter(unsigned index, PassRefPtrWillBeR awPtr<HTMLOptionElement> value, ExceptionState& exceptionState)
1617 { 1692 {
1618 if (!value) { // undefined or null 1693 if (!value) { // undefined or null
1619 remove(index); 1694 remove(index);
1620 return true; 1695 return true;
1621 } 1696 }
1622 setOption(index, value.get(), exceptionState); 1697 setOption(index, value.get(), exceptionState);
1623 return true; 1698 return true;
(...skipping 15 matching lines...) Expand all
1639 } 1714 }
1640 1715
1641 void HTMLSelectElement::trace(Visitor* visitor) 1716 void HTMLSelectElement::trace(Visitor* visitor)
1642 { 1717 {
1643 #if ENABLE(OILPAN) 1718 #if ENABLE(OILPAN)
1644 visitor->trace(m_listItems); 1719 visitor->trace(m_listItems);
1645 #endif 1720 #endif
1646 HTMLFormControlElementWithState::trace(visitor); 1721 HTMLFormControlElementWithState::trace(visitor);
1647 } 1722 }
1648 1723
1724 void HTMLSelectElement::didAddUserAgentShadowRoot(ShadowRoot& root)
1725 {
1726 RefPtrWillBeRawPtr<HTMLContentElement> content = HTMLContentElement::create( document());
1727 content->setAttribute(selectAttr, "option,optgroup");
1728 root.appendChild(content);
1729 }
1730
1731 HTMLOptionElement* HTMLSelectElement::spatialNavigationFocusedOption()
1732 {
1733 if (!isSpatialNavigationEnabled(document().frame()))
1734 return nullptr;
1735 int focusedIndex = activeSelectionEndListIndex();
1736 if (focusedIndex < 0)
1737 focusedIndex = firstSelectableListIndex();
1738 if (focusedIndex < 0)
1739 return nullptr;
1740 HTMLElement* focused = listItems()[focusedIndex];
1741 return isHTMLOptionElement(focused) ? toHTMLOptionElement(focused) : nullptr ;
1742 }
1743
1649 } // namespace 1744 } // namespace
OLDNEW
« no previous file with comments | « Source/core/html/HTMLSelectElement.h ('k') | Source/core/html/shadow/ShadowElementNames.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698