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 21 matching lines...) Expand all Loading... | |
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 Loading... | |
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 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
327 sizeAttribute->setValue(attrSize); | 338 sizeAttribute->setValue(attrSize); |
328 } | 339 } |
329 size = std::max(size, 1); | 340 size = std::max(size, 1); |
330 | 341 |
331 // Ensure that we've determined selectedness of the items at least once prior to changing the size. | 342 // Ensure that we've determined selectedness of the items at least once prior to changing the size. |
332 if (oldSize != size) | 343 if (oldSize != size) |
333 updateListItemSelectedStates(); | 344 updateListItemSelectedStates(); |
334 | 345 |
335 m_size = size; | 346 m_size = size; |
336 setNeedsValidityCheck(); | 347 setNeedsValidityCheck(); |
337 if (m_size != oldSize && inActiveDocument()) { | 348 if (m_size != oldSize && document().isActive() && inDocument()) { |
tkent
2014/07/08 04:43:46
This change looks unnecessary.
keishi
2014/07/10 09:48:03
Done.
| |
338 lazyReattachIfAttached(); | 349 lazyReattachIfAttached(); |
339 setRecalcListItems(); | 350 setRecalcListItems(); |
340 } | 351 } |
341 } else if (name == multipleAttr) | 352 } else if (name == multipleAttr) |
342 parseMultipleAttribute(value); | 353 parseMultipleAttribute(value); |
343 else if (name == accesskeyAttr) { | 354 else if (name == accesskeyAttr) { |
344 // FIXME: ignore for the moment. | 355 // FIXME: ignore for the moment. |
345 // | 356 // |
346 } else if (name == disabledAttr) { | 357 } else if (name == disabledAttr) { |
347 HTMLFormControlElementWithState::parseAttribute(name, value); | 358 HTMLFormControlElementWithState::parseAttribute(name, value); |
(...skipping 11 matching lines...) Expand all Loading... | |
359 bool HTMLSelectElement::shouldShowFocusRingOnMouseFocus() const | 370 bool HTMLSelectElement::shouldShowFocusRingOnMouseFocus() const |
360 { | 371 { |
361 return true; | 372 return true; |
362 } | 373 } |
363 | 374 |
364 bool HTMLSelectElement::canSelectAll() const | 375 bool HTMLSelectElement::canSelectAll() const |
365 { | 376 { |
366 return !usesMenuList(); | 377 return !usesMenuList(); |
367 } | 378 } |
368 | 379 |
369 RenderObject* HTMLSelectElement::createRenderer(RenderStyle*) | 380 RenderObject* HTMLSelectElement::createRenderer(RenderStyle* style) |
tkent
2014/07/08 02:20:59
This change looks unnecessary.
keishi
2014/07/10 09:48:03
Done.
| |
370 { | 381 { |
371 if (usesMenuList()) | 382 if (usesMenuList()) |
372 return new RenderMenuList(this); | 383 return new RenderMenuList(this); |
373 return new RenderListBox(this); | 384 return new RenderListBox(this); |
374 } | 385 } |
375 | 386 |
376 PassRefPtrWillBeRawPtr<HTMLCollection> HTMLSelectElement::selectedOptions() | 387 PassRefPtrWillBeRawPtr<HTMLCollection> HTMLSelectElement::selectedOptions() |
377 { | 388 { |
378 updateListItemSelectedStates(); | 389 updateListItemSelectedStates(); |
379 return ensureCachedHTMLCollection(SelectedOptions); | 390 return ensureCachedHTMLCollection(SelectedOptions); |
380 } | 391 } |
381 | 392 |
382 PassRefPtrWillBeRawPtr<HTMLOptionsCollection> HTMLSelectElement::options() | 393 PassRefPtrWillBeRawPtr<HTMLOptionsCollection> HTMLSelectElement::options() |
383 { | 394 { |
384 return toHTMLOptionsCollection(ensureCachedHTMLCollection(SelectOptions).get ()); | 395 return toHTMLOptionsCollection(ensureCachedHTMLCollection(SelectOptions).get ()); |
385 } | 396 } |
386 | 397 |
387 void HTMLSelectElement::updateListItemSelectedStates() | 398 void HTMLSelectElement::updateListItemSelectedStates() |
388 { | 399 { |
389 if (!m_shouldRecalcListItems) | 400 if (!m_shouldRecalcListItems) |
390 return; | 401 return; |
391 recalcListItems(); | 402 recalcListItems(); |
392 setNeedsValidityCheck(); | 403 setNeedsValidityCheck(); |
393 } | 404 } |
394 | 405 |
395 void HTMLSelectElement::childrenChanged(const ChildrenChange& change) | 406 void HTMLSelectElement::childrenChanged(const ChildrenChange& change) |
396 { | 407 { |
397 setRecalcListItems(); | 408 setRecalcListItems(); |
398 setNeedsValidityCheck(); | 409 setNeedsValidityCheck(); |
399 m_lastOnChangeSelection.clear(); | |
tkent
2014/07/08 04:43:46
Why do you remove this?
keishi
2014/07/10 09:48:03
Reverted. See comment for HTMLSelectElement::listB
| |
400 | 410 |
401 HTMLFormControlElementWithState::childrenChanged(change); | 411 HTMLFormControlElementWithState::childrenChanged(change); |
402 } | 412 } |
403 | 413 |
404 void HTMLSelectElement::optionElementChildrenChanged() | 414 void HTMLSelectElement::optionElementChildrenChanged() |
405 { | 415 { |
406 setRecalcListItems(); | 416 setRecalcListItems(); |
407 setNeedsValidityCheck(); | 417 setNeedsValidityCheck(); |
408 | 418 |
409 if (renderer()) { | 419 if (renderer()) { |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
516 // Valid means that it is enabled and an option element. | 526 // Valid means that it is enabled and an option element. |
517 int HTMLSelectElement::nextValidIndex(int listIndex, SkipDirection direction, in t skip) const | 527 int HTMLSelectElement::nextValidIndex(int listIndex, SkipDirection direction, in t skip) const |
518 { | 528 { |
519 ASSERT(direction == -1 || direction == 1); | 529 ASSERT(direction == -1 || direction == 1); |
520 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this-> listItems(); | 530 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this-> listItems(); |
521 int lastGoodIndex = listIndex; | 531 int lastGoodIndex = listIndex; |
522 int size = listItems.size(); | 532 int size = listItems.size(); |
523 for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex + = direction) { | 533 for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex + = direction) { |
524 --skip; | 534 --skip; |
525 HTMLElement* element = listItems[listIndex]; | 535 HTMLElement* element = listItems[listIndex]; |
526 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDi sabledFormControl() || toHTMLOptionElement(element)->isDisplayNone()) | 536 if (isHTMLOptionElement(*element)) { |
537 const HTMLOptionElement& option = toHTMLOptionElement(*element); | |
tkent
2014/07/08 04:43:46
This cast is unnecessary. isDisabledFormControl an
keishi
2014/07/10 09:48:03
Done.
| |
538 if (option.isDisabledFormControl()) | |
539 continue; | |
540 if (!usesMenuList() && !option.renderer()) | |
541 continue; | |
542 } else { | |
527 continue; | 543 continue; |
tkent
2014/07/08 04:43:46
We prefer early continue.
if (!isHTMLOptionElemen
keishi
2014/07/10 09:48:03
Done.
| |
544 } | |
528 lastGoodIndex = listIndex; | 545 lastGoodIndex = listIndex; |
529 if (skip <= 0) | 546 if (skip <= 0) |
530 break; | 547 break; |
531 } | 548 } |
532 return lastGoodIndex; | 549 return lastGoodIndex; |
533 } | 550 } |
534 | 551 |
535 int HTMLSelectElement::nextSelectableListIndex(int startIndex) const | 552 int HTMLSelectElement::nextSelectableListIndex(int startIndex) const |
536 { | 553 { |
537 return nextValidIndex(startIndex, SkipForwards, 1); | 554 return nextValidIndex(startIndex, SkipForwards, 1); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
619 | 636 |
620 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); | 637 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); |
621 for (unsigned i = 0; i < items.size(); ++i) { | 638 for (unsigned i = 0; i < items.size(); ++i) { |
622 HTMLElement* element = items[i]; | 639 HTMLElement* element = items[i]; |
623 m_cachedStateForActiveSelection.append(isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selected()); | 640 m_cachedStateForActiveSelection.append(isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selected()); |
624 } | 641 } |
625 } | 642 } |
626 | 643 |
627 void HTMLSelectElement::setActiveSelectionEndIndex(int index) | 644 void HTMLSelectElement::setActiveSelectionEndIndex(int index) |
628 { | 645 { |
646 if (index == m_activeSelectionEndIndex) | |
647 return; | |
629 m_activeSelectionEndIndex = index; | 648 m_activeSelectionEndIndex = index; |
649 setNeedsStyleRecalc(SubtreeStyleChange); | |
630 } | 650 } |
631 | 651 |
632 void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions) | 652 void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions) |
633 { | 653 { |
634 ASSERT(renderer() && (renderer()->isListBox() || m_multiple)); | 654 ASSERT(renderer() && (renderer()->isListBox() || m_multiple)); |
635 ASSERT(!listItems().size() || m_activeSelectionAnchorIndex >= 0); | 655 ASSERT(!listItems().size() || m_activeSelectionAnchorIndex >= 0); |
636 | 656 |
637 unsigned start = std::min(m_activeSelectionAnchorIndex, m_activeSelectionEnd Index); | 657 unsigned start = std::min(m_activeSelectionAnchorIndex, m_activeSelectionEnd Index); |
638 unsigned end = std::max(m_activeSelectionAnchorIndex, m_activeSelectionEndIn dex); | 658 unsigned end = std::max(m_activeSelectionAnchorIndex, m_activeSelectionEndIn dex); |
639 | 659 |
640 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); | 660 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); |
641 for (unsigned i = 0; i < items.size(); ++i) { | 661 for (unsigned i = 0; i < items.size(); ++i) { |
642 HTMLElement* element = items[i]; | 662 HTMLElement* element = items[i]; |
643 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDi sabledFormControl() || toHTMLOptionElement(element)->isDisplayNone()) | 663 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDi sabledFormControl() || !toHTMLOptionElement(element)->renderer()) |
644 continue; | 664 continue; |
645 | 665 |
646 if (i >= start && i <= end) | 666 if (i >= start && i <= end) |
647 toHTMLOptionElement(element)->setSelectedState(m_activeSelectionStat e); | 667 toHTMLOptionElement(element)->setSelectedState(m_activeSelectionStat e); |
648 else if (deselectOtherOptions || i >= m_cachedStateForActiveSelection.si ze()) | 668 else if (deselectOtherOptions || i >= m_cachedStateForActiveSelection.si ze()) |
649 toHTMLOptionElement(element)->setSelectedState(false); | 669 toHTMLOptionElement(element)->setSelectedState(false); |
650 else | 670 else |
651 toHTMLOptionElement(element)->setSelectedState(m_cachedStateForActiv eSelection[i]); | 671 toHTMLOptionElement(element)->setSelectedState(m_cachedStateForActiv eSelection[i]); |
652 } | 672 } |
653 | 673 |
674 setNeedsValidityCheck(); | |
654 scrollToSelection(); | 675 scrollToSelection(); |
655 setNeedsValidityCheck(); | |
656 notifyFormStateChanged(); | 676 notifyFormStateChanged(); |
657 } | 677 } |
658 | 678 |
659 void HTMLSelectElement::listBoxOnChange() | 679 void HTMLSelectElement::listBoxOnChange() |
tkent
2014/07/08 04:43:46
Is the change in this function necessary now?
keishi
2014/07/10 09:48:03
Because we animate scrolling now, RenderListBox::s
| |
660 { | 680 { |
661 ASSERT(!usesMenuList() || m_multiple); | 681 ASSERT(!usesMenuList() || m_multiple); |
662 | 682 |
663 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); | 683 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); |
664 | 684 |
665 // If the cached selection list is empty, or the size has changed, then fire | |
666 // dispatchFormControlChangeEvent, and return early. | |
667 // FIXME: Why? This looks unreasonable. | |
668 if (m_lastOnChangeSelection.isEmpty() || m_lastOnChangeSelection.size() != i tems.size()) { | |
669 dispatchFormControlChangeEvent(); | |
670 return; | |
671 } | |
672 | |
673 // Update m_lastOnChangeSelection and fire dispatchFormControlChangeEvent. | 685 // Update m_lastOnChangeSelection and fire dispatchFormControlChangeEvent. |
674 bool fireOnChange = false; | 686 bool fireOnChange = false; |
675 for (unsigned i = 0; i < items.size(); ++i) { | 687 for (unsigned i = 0; i < items.size(); ++i) { |
676 HTMLElement* element = items[i]; | 688 HTMLElement* element = items[i]; |
677 bool selected = isHTMLOptionElement(*element) && toHTMLOptionElement(ele ment)->selected(); | 689 bool selected = isHTMLOptionElement(*element) && toHTMLOptionElement(ele ment)->selected(); |
678 if (selected != m_lastOnChangeSelection[i]) | 690 if (i < m_lastOnChangeSelection.size()) { |
691 if (selected != m_lastOnChangeSelection[i]) { | |
692 fireOnChange = true; | |
693 break; | |
694 } | |
695 } else if (selected) { | |
679 fireOnChange = true; | 696 fireOnChange = true; |
680 m_lastOnChangeSelection[i] = selected; | 697 break; |
698 } | |
681 } | 699 } |
682 | 700 |
683 if (fireOnChange) { | 701 if (fireOnChange) { |
702 saveLastSelection(); | |
684 RefPtrWillBeRawPtr<HTMLSelectElement> protector(this); | 703 RefPtrWillBeRawPtr<HTMLSelectElement> protector(this); |
685 dispatchInputEvent(); | 704 dispatchInputEvent(); |
686 dispatchFormControlChangeEvent(); | 705 dispatchFormControlChangeEvent(); |
687 } | 706 } |
688 } | 707 } |
689 | 708 |
690 void HTMLSelectElement::dispatchInputAndChangeEventForMenuList(bool requiresUser Gesture) | 709 void HTMLSelectElement::dispatchInputAndChangeEventForMenuList(bool requiresUser Gesture) |
691 { | 710 { |
692 ASSERT(usesMenuList()); | 711 ASSERT(usesMenuList()); |
693 | 712 |
694 int selected = selectedIndex(); | 713 int selected = selectedIndex(); |
695 if (m_lastOnChangeIndex != selected && (!requiresUserGesture || m_isProcessi ngUserDrivenChange)) { | 714 if (m_lastOnChangeIndex != selected && (!requiresUserGesture || m_isProcessi ngUserDrivenChange)) { |
696 m_lastOnChangeIndex = selected; | 715 m_lastOnChangeIndex = selected; |
697 m_isProcessingUserDrivenChange = false; | 716 m_isProcessingUserDrivenChange = false; |
698 RefPtrWillBeRawPtr<HTMLSelectElement> protector(this); | 717 RefPtrWillBeRawPtr<HTMLSelectElement> protector(this); |
699 dispatchInputEvent(); | 718 dispatchInputEvent(); |
700 dispatchFormControlChangeEvent(); | 719 dispatchFormControlChangeEvent(); |
701 } | 720 } |
702 } | 721 } |
703 | 722 |
704 void HTMLSelectElement::scrollToSelection() | 723 void HTMLSelectElement::scrollToSelection() |
705 { | 724 { |
725 if (!isFinishedParsingChildren()) | |
726 return; | |
706 if (usesMenuList()) | 727 if (usesMenuList()) |
707 return; | 728 return; |
708 | 729 scrollTo(activeSelectionEndListIndex()); |
709 if (RenderObject* renderer = this->renderer()) | 730 if (AXObjectCache* cache = document().existingAXObjectCache()) |
710 toRenderListBox(renderer)->selectionChanged(); | 731 cache->selectedChildrenChanged(this); |
711 } | 732 } |
712 | 733 |
713 void HTMLSelectElement::setOptionsChangedOnRenderer() | 734 void HTMLSelectElement::setOptionsChangedOnRenderer() |
714 { | 735 { |
715 if (RenderObject* renderer = this->renderer()) { | 736 if (RenderObject* renderer = this->renderer()) { |
716 if (usesMenuList()) | 737 if (usesMenuList()) |
717 toRenderMenuList(renderer)->setOptionsChanged(true); | 738 toRenderMenuList(renderer)->setOptionsChanged(true); |
718 else | |
719 toRenderListBox(renderer)->setOptionsChanged(true); | |
720 } | 739 } |
721 } | 740 } |
722 | 741 |
723 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& HTMLSelectElement::lis tItems() const | 742 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& HTMLSelectElement::lis tItems() const |
724 { | 743 { |
725 if (m_shouldRecalcListItems) | 744 if (m_shouldRecalcListItems) |
726 recalcListItems(); | 745 recalcListItems(); |
727 else { | 746 else { |
728 #if ASSERT_ENABLED | 747 #if ASSERT_ENABLED |
729 WillBeHeapVector<RawPtrWillBeMember<HTMLElement> > items = m_listItems; | 748 WillBeHeapVector<RawPtrWillBeMember<HTMLElement> > items = m_listItems; |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
851 { | 870 { |
852 return m_suggestedIndex; | 871 return m_suggestedIndex; |
853 } | 872 } |
854 | 873 |
855 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex) | 874 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex) |
856 { | 875 { |
857 m_suggestedIndex = suggestedIndex; | 876 m_suggestedIndex = suggestedIndex; |
858 | 877 |
859 if (RenderObject* renderer = this->renderer()) { | 878 if (RenderObject* renderer = this->renderer()) { |
860 renderer->updateFromElement(); | 879 renderer->updateFromElement(); |
861 if (renderer->isListBox()) | 880 scrollTo(suggestedIndex); |
862 toRenderListBox(renderer)->scrollToRevealElementAtListIndex(suggeste dIndex); | |
863 } | 881 } |
864 } | 882 } |
865 | 883 |
884 void HTMLSelectElement::scrollTo(int listIndex) | |
885 { | |
886 if (listIndex < 0) | |
887 return; | |
888 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); | |
889 int listSize = static_cast<int>(items.size()); | |
890 if (listIndex >= listSize) | |
891 return; | |
892 items[listIndex]->scrollIntoViewIfNeeded(false); | |
893 } | |
894 | |
866 void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, b ool optionIsSelected) | 895 void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, b ool optionIsSelected) |
867 { | 896 { |
868 ASSERT(option->ownerSelectElement() == this); | 897 ASSERT(option->ownerSelectElement() == this); |
869 if (optionIsSelected) | 898 if (optionIsSelected) |
870 selectOption(option->index()); | 899 selectOption(option->index()); |
871 else if (!usesMenuList() || multiple()) | 900 else if (!usesMenuList() || multiple()) |
872 selectOption(-1); | 901 selectOption(-1); |
873 else | 902 else |
874 selectOption(nextSelectableListIndex(-1)); | 903 selectOption(nextSelectableListIndex(-1)); |
875 } | 904 } |
876 | 905 |
906 void HTMLSelectElement::optionRemoved(HTMLOptionElement* option) | |
tkent
2014/07/08 04:43:46
probably the argument type should be |const HTMLOp
keishi
2014/07/10 09:48:03
Done.
keishi
2014/07/10 09:48:03
Done.
| |
907 { | |
908 if (m_activeSelectionAnchorIndex < 0 && m_activeSelectionEndIndex < 0) | |
909 return; | |
910 int listIndex = optionToListIndex(option->index()); | |
911 if (listIndex <= m_activeSelectionAnchorIndex) | |
912 m_activeSelectionAnchorIndex--; | |
913 if (listIndex <= m_activeSelectionEndIndex) | |
914 m_activeSelectionEndIndex--; | |
915 } | |
916 | |
877 void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags) | 917 void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags) |
878 { | 918 { |
879 bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions); | 919 bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions); |
880 | 920 |
881 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); | 921 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); |
882 int listIndex = optionToListIndex(optionIndex); | 922 int listIndex = optionToListIndex(optionIndex); |
883 | 923 |
884 HTMLElement* element = 0; | 924 HTMLElement* element = 0; |
885 if (listIndex >= 0) { | 925 if (listIndex >= 0) { |
886 element = items[listIndex]; | 926 element = items[listIndex]; |
(...skipping 15 matching lines...) Expand all Loading... | |
902 | 942 |
903 scrollToSelection(); | 943 scrollToSelection(); |
904 | 944 |
905 setNeedsValidityCheck(); | 945 setNeedsValidityCheck(); |
906 | 946 |
907 if (usesMenuList()) { | 947 if (usesMenuList()) { |
908 m_isProcessingUserDrivenChange = flags & UserDriven; | 948 m_isProcessingUserDrivenChange = flags & UserDriven; |
909 if (flags & DispatchInputAndChangeEvent) | 949 if (flags & DispatchInputAndChangeEvent) |
910 dispatchInputAndChangeEventForMenuList(); | 950 dispatchInputAndChangeEventForMenuList(); |
911 if (RenderObject* renderer = this->renderer()) { | 951 if (RenderObject* renderer = this->renderer()) { |
912 if (usesMenuList()) | 952 if (usesMenuList()) { |
913 toRenderMenuList(renderer)->didSetSelectedIndex(listIndex); | 953 toRenderMenuList(renderer)->didSetSelectedIndex(listIndex); |
914 else if (renderer->isListBox()) | 954 } else if (renderer->isListBox()) { |
915 toRenderListBox(renderer)->selectionChanged(); | 955 if (AXObjectCache* cache = document().existingAXObjectCache()) |
956 cache->selectedChildrenChanged(this); | |
957 } | |
916 } | 958 } |
917 } | 959 } |
918 | 960 |
919 notifyFormStateChanged(); | 961 notifyFormStateChanged(); |
920 } | 962 } |
921 | 963 |
922 int HTMLSelectElement::optionToListIndex(int optionIndex) const | 964 int HTMLSelectElement::optionToListIndex(int optionIndex) const |
923 { | 965 { |
924 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); | 966 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); |
925 int listSize = static_cast<int>(items.size()); | 967 int listSize = static_cast<int>(items.size()); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1046 startIndex = foundIndex + 1; | 1088 startIndex = foundIndex + 1; |
1047 } | 1089 } |
1048 } | 1090 } |
1049 | 1091 |
1050 setOptionsChangedOnRenderer(); | 1092 setOptionsChangedOnRenderer(); |
1051 setNeedsValidityCheck(); | 1093 setNeedsValidityCheck(); |
1052 } | 1094 } |
1053 | 1095 |
1054 void HTMLSelectElement::parseMultipleAttribute(const AtomicString& value) | 1096 void HTMLSelectElement::parseMultipleAttribute(const AtomicString& value) |
1055 { | 1097 { |
1056 bool oldUsesMenuList = usesMenuList(); | |
1057 m_multiple = !value.isNull(); | 1098 m_multiple = !value.isNull(); |
1058 setNeedsValidityCheck(); | 1099 setNeedsValidityCheck(); |
1059 if (oldUsesMenuList != usesMenuList()) | 1100 |
1060 lazyReattachIfAttached(); | 1101 lazyReattachIfAttached(); |
1061 } | 1102 } |
1062 | 1103 |
1063 bool HTMLSelectElement::appendFormData(FormDataList& list, bool) | 1104 bool HTMLSelectElement::appendFormData(FormDataList& list, bool) |
1064 { | 1105 { |
1065 const AtomicString& name = this->name(); | 1106 const AtomicString& name = this->name(); |
1066 if (name.isEmpty()) | 1107 if (name.isEmpty()) |
1067 return false; | 1108 return false; |
1068 | 1109 |
1069 bool successful = false; | 1110 bool successful = false; |
1070 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); | 1111 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1328 // we're doing a single selection, or a multiple selection (using cmd or | 1369 // we're doing a single selection, or a multiple selection (using cmd or |
1329 // ctrl), then initialize the anchor index to the listIndex that just got | 1370 // ctrl), then initialize the anchor index to the listIndex that just got |
1330 // clicked. | 1371 // clicked. |
1331 if (m_activeSelectionAnchorIndex < 0 || !shiftSelect) | 1372 if (m_activeSelectionAnchorIndex < 0 || !shiftSelect) |
1332 setActiveSelectionAnchorIndex(listIndex); | 1373 setActiveSelectionAnchorIndex(listIndex); |
1333 | 1374 |
1334 setActiveSelectionEndIndex(listIndex); | 1375 setActiveSelectionEndIndex(listIndex); |
1335 updateListBoxSelection(!multiSelect); | 1376 updateListBoxSelection(!multiSelect); |
1336 } | 1377 } |
1337 | 1378 |
1379 int HTMLSelectElement::listIndexForEventTargetOption(const Event& event) | |
1380 { | |
1381 Node* targetNode = event.target()->toNode(); | |
1382 if (!targetNode || !isHTMLOptionElement(*targetNode)) | |
1383 return -1; | |
1384 return listIndexForOption(toHTMLOptionElement(*targetNode)); | |
1385 } | |
1386 | |
1387 int HTMLSelectElement::listIndexForOption(const HTMLOptionElement& option) | |
1388 { | |
1389 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = this->list Items(); | |
1390 size_t length = items.size(); | |
1391 for (size_t i = 0; i < length; ++i) { | |
1392 if (items[i] == &option) | |
1393 return i; | |
1394 } | |
1395 return -1; | |
1396 } | |
1397 | |
1398 AutoscrollController* HTMLSelectElement::autoscrollController() const | |
1399 { | |
1400 if (Page* page = document().page()) | |
1401 return &page->autoscrollController(); | |
1402 return 0; | |
1403 } | |
1404 | |
1338 void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) | 1405 void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) |
1339 { | 1406 { |
1340 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this-> listItems(); | 1407 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this-> listItems(); |
1341 if (event->type() == EventTypeNames::gesturetap && event->isGestureEvent()) { | 1408 if (event->type() == EventTypeNames::gesturetap && event->isGestureEvent()) { |
1342 focus(); | 1409 focus(); |
1343 // 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. | 1410 // 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. |
1344 if (!renderer() || !renderer()->isListBox()) | 1411 if (!renderer() || !renderer()->isListBox()) |
1345 return; | 1412 return; |
1346 | 1413 |
1347 // Convert to coords relative to the list box if needed. | 1414 // Convert to coords relative to the list box if needed. |
1348 GestureEvent& gestureEvent = toGestureEvent(*event); | 1415 GestureEvent& gestureEvent = toGestureEvent(*event); |
1349 IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(gestu reEvent.absoluteLocation(), UseTransforms)); | 1416 int listIndex = listIndexForEventTargetOption(gestureEvent); |
1350 int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize (localOffset)); | |
1351 if (listIndex >= 0) { | 1417 if (listIndex >= 0) { |
1352 if (!isDisabledFormControl()) | 1418 if (!isDisabledFormControl()) |
1353 updateSelectedState(listIndex, true, gestureEvent.shiftKey()); | 1419 updateSelectedState(listIndex, true, gestureEvent.shiftKey()); |
1354 event->setDefaultHandled(); | 1420 event->setDefaultHandled(); |
1355 } | 1421 } |
1356 } else if (event->type() == EventTypeNames::mousedown && event->isMouseEvent () && toMouseEvent(event)->button() == LeftButton) { | 1422 } else if (event->type() == EventTypeNames::mousedown && event->isMouseEvent () && toMouseEvent(event)->button() == LeftButton) { |
1357 focus(); | 1423 focus(); |
1358 // Calling focus() may cause us to lose our renderer, in which case do n ot want to handle the event. | 1424 // Calling focus() may cause us to lose our renderer, in which case do n ot want to handle the event. |
1359 if (!renderer() || !renderer()->isListBox() || isDisabledFormControl()) | 1425 if (!renderer() || !renderer()->isListBox() || isDisabledFormControl()) |
1360 return; | 1426 return; |
1361 | 1427 |
1428 if (Page* page = document().page()) | |
1429 page->autoscrollController().startAutoscrollForSelection(renderer()) ; | |
1430 | |
1362 // Convert to coords relative to the list box if needed. | 1431 // Convert to coords relative to the list box if needed. |
1363 MouseEvent* mouseEvent = toMouseEvent(event); | 1432 MouseEvent* mouseEvent = toMouseEvent(event); |
1364 IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(mouse Event->absoluteLocation(), UseTransforms)); | 1433 int listIndex = listIndexForEventTargetOption(*mouseEvent); |
1365 int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize (localOffset)); | |
1366 if (listIndex >= 0) { | 1434 if (listIndex >= 0) { |
1367 if (!isDisabledFormControl()) { | 1435 if (!isDisabledFormControl()) { |
1368 #if OS(MACOSX) | 1436 #if OS(MACOSX) |
1369 updateSelectedState(listIndex, mouseEvent->metaKey(), mouseEvent ->shiftKey()); | 1437 updateSelectedState(listIndex, mouseEvent->metaKey(), mouseEvent ->shiftKey()); |
1370 #else | 1438 #else |
1371 updateSelectedState(listIndex, mouseEvent->ctrlKey(), mouseEvent ->shiftKey()); | 1439 updateSelectedState(listIndex, mouseEvent->ctrlKey(), mouseEvent ->shiftKey()); |
1372 #endif | 1440 #endif |
1373 } | 1441 } |
1374 if (LocalFrame* frame = document().frame()) | 1442 if (LocalFrame* frame = document().frame()) |
1375 frame->eventHandler().setMouseDownMayStartAutoscroll(); | 1443 frame->eventHandler().setMouseDownMayStartAutoscroll(); |
1376 | 1444 |
1377 event->setDefaultHandled(); | 1445 event->setDefaultHandled(); |
1378 } | 1446 } |
1379 } else if (event->type() == EventTypeNames::mousemove && event->isMouseEvent () && !toRenderBox(renderer())->canBeScrolledAndHasScrollableArea()) { | 1447 } else if (event->type() == EventTypeNames::mousemove && event->isMouseEvent ()) { |
1380 MouseEvent* mouseEvent = toMouseEvent(event); | 1448 MouseEvent* mouseEvent = toMouseEvent(event); |
1381 if (mouseEvent->button() != LeftButton || !mouseEvent->buttonDown()) | 1449 if (mouseEvent->button() != LeftButton || !mouseEvent->buttonDown()) |
1382 return; | 1450 return; |
1383 | 1451 int listIndex = listIndexForEventTargetOption(*mouseEvent); |
1384 IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(mouse Event->absoluteLocation(), UseTransforms)); | |
1385 int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize (localOffset)); | |
1386 if (listIndex >= 0) { | 1452 if (listIndex >= 0) { |
1387 if (!isDisabledFormControl()) { | 1453 if (!isDisabledFormControl()) { |
1388 if (m_multiple) { | 1454 if (m_multiple) { |
1389 // Only extend selection if there is something selected. | 1455 // Only extend selection if there is something selected. |
1390 if (m_activeSelectionAnchorIndex < 0) | 1456 if (m_activeSelectionAnchorIndex < 0) |
1391 return; | 1457 return; |
1392 | 1458 |
1393 setActiveSelectionEndIndex(listIndex); | 1459 setActiveSelectionEndIndex(listIndex); |
1394 updateListBoxSelection(false); | 1460 updateListBoxSelection(false); |
1395 } else { | 1461 } else { |
1396 setActiveSelectionAnchorIndex(listIndex); | 1462 setActiveSelectionAnchorIndex(listIndex); |
1397 setActiveSelectionEndIndex(listIndex); | 1463 setActiveSelectionEndIndex(listIndex); |
1398 updateListBoxSelection(true); | 1464 updateListBoxSelection(true); |
1399 } | 1465 } |
1400 } | 1466 } |
1401 } | 1467 } |
1402 } else if (event->type() == EventTypeNames::mouseup && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton && renderer() && !toRenderBox(re nderer())->autoscrollInProgress()) { | 1468 } else if (event->type() == EventTypeNames::mouseup && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton && renderer()) { |
tkent
2014/07/08 04:43:46
Is it safe to remove autoscrollInProgress check?
keishi
2014/07/10 09:48:03
I added back this check and added a call to stopAu
| |
1403 // We didn't start this click/drag on any options. | 1469 // We didn't start this click/drag on any options. |
1404 if (m_lastOnChangeSelection.isEmpty()) | 1470 if (m_lastOnChangeSelection.isEmpty()) |
1405 return; | 1471 return; |
1406 listBoxOnChange(); | 1472 listBoxOnChange(); |
1407 } else if (event->type() == EventTypeNames::keydown) { | 1473 } else if (event->type() == EventTypeNames::keydown) { |
1408 if (!event->isKeyboardEvent()) | 1474 if (!event->isKeyboardEvent()) |
1409 return; | 1475 return; |
1410 const String& keyIdentifier = toKeyboardEvent(event)->keyIdentifier(); | 1476 const String& keyIdentifier = toKeyboardEvent(event)->keyIdentifier(); |
1411 | 1477 |
1412 bool handled = false; | 1478 bool handled = false; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1471 m_activeSelectionState = true; | 1537 m_activeSelectionState = true; |
1472 // If the anchor is unitialized, or if we're going to deselect all | 1538 // If the anchor is unitialized, or if we're going to deselect all |
1473 // other options, then set the anchor index equal to the end index. | 1539 // other options, then set the anchor index equal to the end index. |
1474 bool deselectOthers = !m_multiple || (!toKeyboardEvent(event)->shift Key() && selectNewItem); | 1540 bool deselectOthers = !m_multiple || (!toKeyboardEvent(event)->shift Key() && selectNewItem); |
1475 if (m_activeSelectionAnchorIndex < 0 || deselectOthers) { | 1541 if (m_activeSelectionAnchorIndex < 0 || deselectOthers) { |
1476 if (deselectOthers) | 1542 if (deselectOthers) |
1477 deselectItemsWithoutValidation(); | 1543 deselectItemsWithoutValidation(); |
1478 setActiveSelectionAnchorIndex(m_activeSelectionEndIndex); | 1544 setActiveSelectionAnchorIndex(m_activeSelectionEndIndex); |
1479 } | 1545 } |
1480 | 1546 |
1481 toRenderListBox(renderer())->scrollToRevealElementAtListIndex(endInd ex); | 1547 scrollTo(endIndex); |
1482 if (selectNewItem) { | 1548 if (selectNewItem) { |
1483 updateListBoxSelection(deselectOthers); | 1549 updateListBoxSelection(deselectOthers); |
1484 listBoxOnChange(); | 1550 listBoxOnChange(); |
1485 } else | 1551 } else |
1486 scrollToSelection(); | 1552 scrollToSelection(); |
1487 | 1553 |
1488 event->setDefaultHandled(); | 1554 event->setDefaultHandled(); |
1489 } | 1555 } |
1490 } else if (event->type() == EventTypeNames::keypress) { | 1556 } else if (event->type() == EventTypeNames::keypress) { |
1491 if (!event->isKeyboardEvent()) | 1557 if (!event->isKeyboardEvent()) |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1622 ++options; | 1688 ++options; |
1623 } | 1689 } |
1624 | 1690 |
1625 return options; | 1691 return options; |
1626 } | 1692 } |
1627 | 1693 |
1628 void HTMLSelectElement::finishParsingChildren() | 1694 void HTMLSelectElement::finishParsingChildren() |
1629 { | 1695 { |
1630 HTMLFormControlElementWithState::finishParsingChildren(); | 1696 HTMLFormControlElementWithState::finishParsingChildren(); |
1631 updateListItemSelectedStates(); | 1697 updateListItemSelectedStates(); |
1698 scrollToSelection(); | |
1632 } | 1699 } |
1633 | 1700 |
1634 bool HTMLSelectElement::anonymousIndexedSetter(unsigned index, PassRefPtrWillBeR awPtr<HTMLOptionElement> value, ExceptionState& exceptionState) | 1701 bool HTMLSelectElement::anonymousIndexedSetter(unsigned index, PassRefPtrWillBeR awPtr<HTMLOptionElement> value, ExceptionState& exceptionState) |
1635 { | 1702 { |
1636 if (!value) { // undefined or null | 1703 if (!value) { // undefined or null |
1637 remove(index); | 1704 remove(index); |
1638 return true; | 1705 return true; |
1639 } | 1706 } |
1640 setOption(index, value.get(), exceptionState); | 1707 setOption(index, value.get(), exceptionState); |
1641 return true; | 1708 return true; |
(...skipping 15 matching lines...) Expand all Loading... | |
1657 } | 1724 } |
1658 | 1725 |
1659 void HTMLSelectElement::trace(Visitor* visitor) | 1726 void HTMLSelectElement::trace(Visitor* visitor) |
1660 { | 1727 { |
1661 #if ENABLE(OILPAN) | 1728 #if ENABLE(OILPAN) |
1662 visitor->trace(m_listItems); | 1729 visitor->trace(m_listItems); |
1663 #endif | 1730 #endif |
1664 HTMLFormControlElementWithState::trace(visitor); | 1731 HTMLFormControlElementWithState::trace(visitor); |
1665 } | 1732 } |
1666 | 1733 |
1734 void HTMLSelectElement::didAddUserAgentShadowRoot(ShadowRoot& root) | |
1735 { | |
1736 RefPtrWillBeRawPtr<HTMLContentElement> content = HTMLContentElement::create( document()); | |
1737 content->setAttribute(selectAttr, "option,optgroup"); | |
1738 root.appendChild(content); | |
1739 } | |
1740 | |
1741 HTMLOptionElement* HTMLSelectElement::spatialNavigationFocusedOption() | |
1742 { | |
1743 if (!isSpatialNavigationEnabled(document().frame())) | |
1744 return nullptr; | |
1745 int focusedIndex = activeSelectionEndListIndex(); | |
1746 if (focusedIndex < 0) | |
1747 focusedIndex = firstSelectableListIndex(); | |
1748 if (focusedIndex < 0) | |
1749 return nullptr; | |
1750 HTMLElement* focused = listItems()[focusedIndex]; | |
1751 return isHTMLOptionElement(focused) ? toHTMLOptionElement(focused) : nullptr ; | |
1752 } | |
1753 | |
1667 } // namespace | 1754 } // namespace |
OLD | NEW |