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 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 { | 222 { |
223 int listIndex = optionToListIndex(optionIndex); | 223 int listIndex = optionToListIndex(optionIndex); |
224 if (listIndex < 0) | 224 if (listIndex < 0) |
225 return; | 225 return; |
226 | 226 |
227 listItems()[listIndex]->remove(IGNORE_EXCEPTION); | 227 listItems()[listIndex]->remove(IGNORE_EXCEPTION); |
228 } | 228 } |
229 | 229 |
230 String HTMLSelectElement::value() const | 230 String HTMLSelectElement::value() const |
231 { | 231 { |
232 const Vector<HTMLElement*>& items = listItems(); | 232 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
233 for (unsigned i = 0; i < items.size(); i++) { | 233 for (unsigned i = 0; i < items.size(); i++) { |
234 if (isHTMLOptionElement(items[i]) && toHTMLOptionElement(items[i])->sele
cted()) | 234 if (isHTMLOptionElement(items[i]) && toHTMLOptionElement(items[i])->sele
cted()) |
235 return toHTMLOptionElement(items[i])->value(); | 235 return toHTMLOptionElement(items[i])->value(); |
236 } | 236 } |
237 return ""; | 237 return ""; |
238 } | 238 } |
239 | 239 |
240 void HTMLSelectElement::setValue(const String &value, bool sendEvents) | 240 void HTMLSelectElement::setValue(const String &value, bool sendEvents) |
241 { | 241 { |
242 // We clear the previously selected option(s) when needed, to guarantee call
ing setSelectedIndex() only once. | 242 // We clear the previously selected option(s) when needed, to guarantee call
ing setSelectedIndex() only once. |
243 int optionIndex = 0; | 243 int optionIndex = 0; |
244 if (value.isNull()) { | 244 if (value.isNull()) { |
245 optionIndex = -1; | 245 optionIndex = -1; |
246 } else { | 246 } else { |
247 // Find the option with value() matching the given parameter and make it
the current selection. | 247 // Find the option with value() matching the given parameter and make it
the current selection. |
248 const Vector<HTMLElement*>& items = listItems(); | 248 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listIt
ems(); |
249 for (unsigned i = 0; i < items.size(); i++) { | 249 for (unsigned i = 0; i < items.size(); i++) { |
250 if (isHTMLOptionElement(items[i])) { | 250 if (isHTMLOptionElement(items[i])) { |
251 if (toHTMLOptionElement(items[i])->value() == value) | 251 if (toHTMLOptionElement(items[i])->value() == value) |
252 break; | 252 break; |
253 optionIndex++; | 253 optionIndex++; |
254 } | 254 } |
255 } | 255 } |
256 if (optionIndex >= static_cast<int>(items.size())) | 256 if (optionIndex >= static_cast<int>(items.size())) |
257 optionIndex = -1; | 257 optionIndex = -1; |
258 } | 258 } |
259 | 259 |
260 int previousSelectedIndex = selectedIndex(); | 260 int previousSelectedIndex = selectedIndex(); |
261 setSelectedIndex(optionIndex); | 261 setSelectedIndex(optionIndex); |
262 | 262 |
263 if (sendEvents && previousSelectedIndex != selectedIndex()) { | 263 if (sendEvents && previousSelectedIndex != selectedIndex()) { |
264 if (usesMenuList()) | 264 if (usesMenuList()) |
265 dispatchInputAndChangeEventForMenuList(false); | 265 dispatchInputAndChangeEventForMenuList(false); |
266 else | 266 else |
267 listBoxOnChange(); | 267 listBoxOnChange(); |
268 } | 268 } |
269 } | 269 } |
270 | 270 |
271 String HTMLSelectElement::suggestedValue() const | 271 String HTMLSelectElement::suggestedValue() const |
272 { | 272 { |
273 const Vector<HTMLElement*>& items = listItems(); | 273 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
274 for (unsigned i = 0; i < items.size(); ++i) { | 274 for (unsigned i = 0; i < items.size(); ++i) { |
275 if (isHTMLOptionElement(items[i]) && m_suggestedIndex >= 0) { | 275 if (isHTMLOptionElement(items[i]) && m_suggestedIndex >= 0) { |
276 if (i == static_cast<unsigned>(m_suggestedIndex)) | 276 if (i == static_cast<unsigned>(m_suggestedIndex)) |
277 return toHTMLOptionElement(items[i])->value(); | 277 return toHTMLOptionElement(items[i])->value(); |
278 } | 278 } |
279 } | 279 } |
280 return ""; | 280 return ""; |
281 } | 281 } |
282 | 282 |
283 void HTMLSelectElement::setSuggestedValue(const String& value) | 283 void HTMLSelectElement::setSuggestedValue(const String& value) |
284 { | 284 { |
285 if (value.isNull()) { | 285 if (value.isNull()) { |
286 setSuggestedIndex(-1); | 286 setSuggestedIndex(-1); |
287 return; | 287 return; |
288 } | 288 } |
289 | 289 |
290 const Vector<HTMLElement*>& items = listItems(); | 290 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
291 unsigned optionIndex = 0; | 291 unsigned optionIndex = 0; |
292 for (unsigned i = 0; i < items.size(); ++i) { | 292 for (unsigned i = 0; i < items.size(); ++i) { |
293 if (isHTMLOptionElement(items[i])) { | 293 if (isHTMLOptionElement(items[i])) { |
294 if (toHTMLOptionElement(items[i])->value() == value) { | 294 if (toHTMLOptionElement(items[i])->value() == value) { |
295 setSuggestedIndex(optionIndex); | 295 setSuggestedIndex(optionIndex); |
296 return; | 296 return; |
297 } | 297 } |
298 optionIndex++; | 298 optionIndex++; |
299 } | 299 } |
300 } | 300 } |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 | 475 |
476 if (diff < 0) { // Add dummy elements. | 476 if (diff < 0) { // Add dummy elements. |
477 do { | 477 do { |
478 RefPtr<Element> option = document().createElement(optionTag, false); | 478 RefPtr<Element> option = document().createElement(optionTag, false); |
479 ASSERT(option); | 479 ASSERT(option); |
480 add(toHTMLElement(option), 0, exceptionState); | 480 add(toHTMLElement(option), 0, exceptionState); |
481 if (exceptionState.hadException()) | 481 if (exceptionState.hadException()) |
482 break; | 482 break; |
483 } while (++diff); | 483 } while (++diff); |
484 } else { | 484 } else { |
485 const Vector<HTMLElement*>& items = listItems(); | 485 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listIt
ems(); |
486 | 486 |
487 // Removing children fires mutation events, which might mutate the DOM f
urther, so we first copy out a list | 487 // Removing children fires mutation events, which might mutate the DOM f
urther, so we first copy out a list |
488 // of elements that we intend to remove then attempt to remove them one
at a time. | 488 // of elements that we intend to remove then attempt to remove them one
at a time. |
489 Vector<RefPtr<Element> > itemsToRemove; | 489 Vector<RefPtr<Element> > itemsToRemove; |
490 size_t optionIndex = 0; | 490 size_t optionIndex = 0; |
491 for (size_t i = 0; i < items.size(); ++i) { | 491 for (size_t i = 0; i < items.size(); ++i) { |
492 Element* item = items[i]; | 492 Element* item = items[i]; |
493 if (isHTMLOptionElement(items[i]) && optionIndex++ >= newLen) { | 493 if (isHTMLOptionElement(items[i]) && optionIndex++ >= newLen) { |
494 ASSERT(item->parentNode()); | 494 ASSERT(item->parentNode()); |
495 itemsToRemove.append(item); | 495 itemsToRemove.append(item); |
(...skipping 14 matching lines...) Expand all Loading... |
510 return isRequired(); | 510 return isRequired(); |
511 } | 511 } |
512 | 512 |
513 // Returns the 1st valid item |skip| items from |listIndex| in direction |direct
ion| if there is one. | 513 // Returns the 1st valid item |skip| items from |listIndex| in direction |direct
ion| if there is one. |
514 // Otherwise, it returns the valid item closest to that boundary which is past |
listIndex| if there is one. | 514 // Otherwise, it returns the valid item closest to that boundary which is past |
listIndex| if there is one. |
515 // Otherwise, it returns |listIndex|. | 515 // Otherwise, it returns |listIndex|. |
516 // Valid means that it is enabled and an option element. | 516 // Valid means that it is enabled and an option element. |
517 int HTMLSelectElement::nextValidIndex(int listIndex, SkipDirection direction, in
t skip) const | 517 int HTMLSelectElement::nextValidIndex(int listIndex, SkipDirection direction, in
t skip) const |
518 { | 518 { |
519 ASSERT(direction == -1 || direction == 1); | 519 ASSERT(direction == -1 || direction == 1); |
520 const Vector<HTMLElement*>& listItems = this->listItems(); | 520 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this->
listItems(); |
521 int lastGoodIndex = listIndex; | 521 int lastGoodIndex = listIndex; |
522 int size = listItems.size(); | 522 int size = listItems.size(); |
523 for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex +
= direction) { | 523 for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex +
= direction) { |
524 --skip; | 524 --skip; |
525 HTMLElement* element = listItems[listIndex]; | 525 HTMLElement* element = listItems[listIndex]; |
526 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDi
sabledFormControl() || toHTMLOptionElement(element)->isDisplayNone()) | 526 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDi
sabledFormControl() || toHTMLOptionElement(element)->isDisplayNone()) |
527 continue; | 527 continue; |
528 lastGoodIndex = listIndex; | 528 lastGoodIndex = listIndex; |
529 if (skip <= 0) | 529 if (skip <= 0) |
530 break; | 530 break; |
531 } | 531 } |
532 return lastGoodIndex; | 532 return lastGoodIndex; |
533 } | 533 } |
534 | 534 |
535 int HTMLSelectElement::nextSelectableListIndex(int startIndex) const | 535 int HTMLSelectElement::nextSelectableListIndex(int startIndex) const |
536 { | 536 { |
537 return nextValidIndex(startIndex, SkipForwards, 1); | 537 return nextValidIndex(startIndex, SkipForwards, 1); |
538 } | 538 } |
539 | 539 |
540 int HTMLSelectElement::previousSelectableListIndex(int startIndex) const | 540 int HTMLSelectElement::previousSelectableListIndex(int startIndex) const |
541 { | 541 { |
542 if (startIndex == -1) | 542 if (startIndex == -1) |
543 startIndex = listItems().size(); | 543 startIndex = listItems().size(); |
544 return nextValidIndex(startIndex, SkipBackwards, 1); | 544 return nextValidIndex(startIndex, SkipBackwards, 1); |
545 } | 545 } |
546 | 546 |
547 int HTMLSelectElement::firstSelectableListIndex() const | 547 int HTMLSelectElement::firstSelectableListIndex() const |
548 { | 548 { |
549 const Vector<HTMLElement*>& items = listItems(); | 549 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
550 int index = nextValidIndex(items.size(), SkipBackwards, INT_MAX); | 550 int index = nextValidIndex(items.size(), SkipBackwards, INT_MAX); |
551 if (static_cast<size_t>(index) == items.size()) | 551 if (static_cast<size_t>(index) == items.size()) |
552 return -1; | 552 return -1; |
553 return index; | 553 return index; |
554 } | 554 } |
555 | 555 |
556 int HTMLSelectElement::lastSelectableListIndex() const | 556 int HTMLSelectElement::lastSelectableListIndex() const |
557 { | 557 { |
558 return nextValidIndex(-1, SkipForwards, INT_MAX); | 558 return nextValidIndex(-1, SkipForwards, INT_MAX); |
559 } | 559 } |
560 | 560 |
561 // Returns the index of the next valid item one page away from |startIndex| in d
irection |direction|. | 561 // Returns the index of the next valid item one page away from |startIndex| in d
irection |direction|. |
562 int HTMLSelectElement::nextSelectableListIndexPageAway(int startIndex, SkipDirec
tion direction) const | 562 int HTMLSelectElement::nextSelectableListIndexPageAway(int startIndex, SkipDirec
tion direction) const |
563 { | 563 { |
564 const Vector<HTMLElement*>& items = listItems(); | 564 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
565 // Can't use m_size because renderer forces a minimum size. | 565 // Can't use m_size because renderer forces a minimum size. |
566 int pageSize = 0; | 566 int pageSize = 0; |
567 if (renderer()->isListBox()) | 567 if (renderer()->isListBox()) |
568 pageSize = toRenderListBox(renderer())->size() - 1; // -1 so we still sh
ow context. | 568 pageSize = toRenderListBox(renderer())->size() - 1; // -1 so we still sh
ow context. |
569 | 569 |
570 // One page away, but not outside valid bounds. | 570 // One page away, but not outside valid bounds. |
571 // If there is a valid option item one page away, the index is chosen. | 571 // If there is a valid option item one page away, the index is chosen. |
572 // If there is no exact one page away valid option, returns startIndex or th
e most far index. | 572 // If there is no exact one page away valid option, returns startIndex or th
e most far index. |
573 int edgeIndex = (direction == SkipForwards) ? 0 : (items.size() - 1); | 573 int edgeIndex = (direction == SkipForwards) ? 0 : (items.size() - 1); |
574 int skipAmount = pageSize + ((direction == SkipForwards) ? startIndex : (edg
eIndex - startIndex)); | 574 int skipAmount = pageSize + ((direction == SkipForwards) ? startIndex : (edg
eIndex - startIndex)); |
(...skipping 20 matching lines...) Expand all Loading... |
595 } | 595 } |
596 | 596 |
597 void HTMLSelectElement::saveLastSelection() | 597 void HTMLSelectElement::saveLastSelection() |
598 { | 598 { |
599 if (usesMenuList()) { | 599 if (usesMenuList()) { |
600 m_lastOnChangeIndex = selectedIndex(); | 600 m_lastOnChangeIndex = selectedIndex(); |
601 return; | 601 return; |
602 } | 602 } |
603 | 603 |
604 m_lastOnChangeSelection.clear(); | 604 m_lastOnChangeSelection.clear(); |
605 const Vector<HTMLElement*>& items = listItems(); | 605 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
606 for (unsigned i = 0; i < items.size(); ++i) { | 606 for (unsigned i = 0; i < items.size(); ++i) { |
607 HTMLElement* element = items[i]; | 607 HTMLElement* element = items[i]; |
608 m_lastOnChangeSelection.append(isHTMLOptionElement(*element) && toHTMLOp
tionElement(element)->selected()); | 608 m_lastOnChangeSelection.append(isHTMLOptionElement(*element) && toHTMLOp
tionElement(element)->selected()); |
609 } | 609 } |
610 } | 610 } |
611 | 611 |
612 void HTMLSelectElement::setActiveSelectionAnchorIndex(int index) | 612 void HTMLSelectElement::setActiveSelectionAnchorIndex(int index) |
613 { | 613 { |
614 m_activeSelectionAnchorIndex = index; | 614 m_activeSelectionAnchorIndex = index; |
615 | 615 |
616 // Cache the selection state so we can restore the old selection as the new | 616 // Cache the selection state so we can restore the old selection as the new |
617 // selection pivots around this anchor index. | 617 // selection pivots around this anchor index. |
618 m_cachedStateForActiveSelection.clear(); | 618 m_cachedStateForActiveSelection.clear(); |
619 | 619 |
620 const Vector<HTMLElement*>& items = listItems(); | 620 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
621 for (unsigned i = 0; i < items.size(); ++i) { | 621 for (unsigned i = 0; i < items.size(); ++i) { |
622 HTMLElement* element = items[i]; | 622 HTMLElement* element = items[i]; |
623 m_cachedStateForActiveSelection.append(isHTMLOptionElement(*element) &&
toHTMLOptionElement(element)->selected()); | 623 m_cachedStateForActiveSelection.append(isHTMLOptionElement(*element) &&
toHTMLOptionElement(element)->selected()); |
624 } | 624 } |
625 } | 625 } |
626 | 626 |
627 void HTMLSelectElement::setActiveSelectionEndIndex(int index) | 627 void HTMLSelectElement::setActiveSelectionEndIndex(int index) |
628 { | 628 { |
629 m_activeSelectionEndIndex = index; | 629 m_activeSelectionEndIndex = index; |
630 } | 630 } |
631 | 631 |
632 void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions) | 632 void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions) |
633 { | 633 { |
634 ASSERT(renderer() && (renderer()->isListBox() || m_multiple)); | 634 ASSERT(renderer() && (renderer()->isListBox() || m_multiple)); |
635 ASSERT(!listItems().size() || m_activeSelectionAnchorIndex >= 0); | 635 ASSERT(!listItems().size() || m_activeSelectionAnchorIndex >= 0); |
636 | 636 |
637 unsigned start = min(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex
); | 637 unsigned start = min(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex
); |
638 unsigned end = max(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex); | 638 unsigned end = max(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex); |
639 | 639 |
640 const Vector<HTMLElement*>& items = listItems(); | 640 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
641 for (unsigned i = 0; i < items.size(); ++i) { | 641 for (unsigned i = 0; i < items.size(); ++i) { |
642 HTMLElement* element = items[i]; | 642 HTMLElement* element = items[i]; |
643 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDi
sabledFormControl() || toHTMLOptionElement(element)->isDisplayNone()) | 643 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDi
sabledFormControl() || toHTMLOptionElement(element)->isDisplayNone()) |
644 continue; | 644 continue; |
645 | 645 |
646 if (i >= start && i <= end) | 646 if (i >= start && i <= end) |
647 toHTMLOptionElement(element)->setSelectedState(m_activeSelectionStat
e); | 647 toHTMLOptionElement(element)->setSelectedState(m_activeSelectionStat
e); |
648 else if (deselectOtherOptions || i >= m_cachedStateForActiveSelection.si
ze()) | 648 else if (deselectOtherOptions || i >= m_cachedStateForActiveSelection.si
ze()) |
649 toHTMLOptionElement(element)->setSelectedState(false); | 649 toHTMLOptionElement(element)->setSelectedState(false); |
650 else | 650 else |
651 toHTMLOptionElement(element)->setSelectedState(m_cachedStateForActiv
eSelection[i]); | 651 toHTMLOptionElement(element)->setSelectedState(m_cachedStateForActiv
eSelection[i]); |
652 } | 652 } |
653 | 653 |
654 scrollToSelection(); | 654 scrollToSelection(); |
655 setNeedsValidityCheck(); | 655 setNeedsValidityCheck(); |
656 notifyFormStateChanged(); | 656 notifyFormStateChanged(); |
657 } | 657 } |
658 | 658 |
659 void HTMLSelectElement::listBoxOnChange() | 659 void HTMLSelectElement::listBoxOnChange() |
660 { | 660 { |
661 ASSERT(!usesMenuList() || m_multiple); | 661 ASSERT(!usesMenuList() || m_multiple); |
662 | 662 |
663 const Vector<HTMLElement*>& items = listItems(); | 663 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
664 | 664 |
665 // If the cached selection list is empty, or the size has changed, then fire | 665 // If the cached selection list is empty, or the size has changed, then fire |
666 // dispatchFormControlChangeEvent, and return early. | 666 // dispatchFormControlChangeEvent, and return early. |
667 // FIXME: Why? This looks unreasonable. | 667 // FIXME: Why? This looks unreasonable. |
668 if (m_lastOnChangeSelection.isEmpty() || m_lastOnChangeSelection.size() != i
tems.size()) { | 668 if (m_lastOnChangeSelection.isEmpty() || m_lastOnChangeSelection.size() != i
tems.size()) { |
669 dispatchFormControlChangeEvent(); | 669 dispatchFormControlChangeEvent(); |
670 return; | 670 return; |
671 } | 671 } |
672 | 672 |
673 // Update m_lastOnChangeSelection and fire dispatchFormControlChangeEvent. | 673 // Update m_lastOnChangeSelection and fire dispatchFormControlChangeEvent. |
674 bool fireOnChange = false; | 674 bool fireOnChange = false; |
675 for (unsigned i = 0; i < items.size(); ++i) { | 675 for (unsigned i = 0; i < items.size(); ++i) { |
676 HTMLElement* element = items[i]; | 676 HTMLElement* element = items[i]; |
677 bool selected = isHTMLOptionElement(*element) && toHTMLOptionElement(ele
ment)->selected(); | 677 bool selected = isHTMLOptionElement(*element) && toHTMLOptionElement(ele
ment)->selected(); |
678 if (selected != m_lastOnChangeSelection[i]) | 678 if (selected != m_lastOnChangeSelection[i]) |
679 fireOnChange = true; | 679 fireOnChange = true; |
680 m_lastOnChangeSelection[i] = selected; | 680 m_lastOnChangeSelection[i] = selected; |
681 } | 681 } |
682 | 682 |
683 if (fireOnChange) { | 683 if (fireOnChange) { |
684 RefPtr<HTMLSelectElement> protector(this); | 684 RefPtrWillBeRawPtr<HTMLSelectElement> protector(this); |
685 dispatchInputEvent(); | 685 dispatchInputEvent(); |
686 dispatchFormControlChangeEvent(); | 686 dispatchFormControlChangeEvent(); |
687 } | 687 } |
688 } | 688 } |
689 | 689 |
690 void HTMLSelectElement::dispatchInputAndChangeEventForMenuList(bool requiresUser
Gesture) | 690 void HTMLSelectElement::dispatchInputAndChangeEventForMenuList(bool requiresUser
Gesture) |
691 { | 691 { |
692 ASSERT(usesMenuList()); | 692 ASSERT(usesMenuList()); |
693 | 693 |
694 int selected = selectedIndex(); | 694 int selected = selectedIndex(); |
695 if (m_lastOnChangeIndex != selected && (!requiresUserGesture || m_isProcessi
ngUserDrivenChange)) { | 695 if (m_lastOnChangeIndex != selected && (!requiresUserGesture || m_isProcessi
ngUserDrivenChange)) { |
696 m_lastOnChangeIndex = selected; | 696 m_lastOnChangeIndex = selected; |
697 m_isProcessingUserDrivenChange = false; | 697 m_isProcessingUserDrivenChange = false; |
698 RefPtr<HTMLSelectElement> protector(this); | 698 RefPtrWillBeRawPtr<HTMLSelectElement> protector(this); |
699 dispatchInputEvent(); | 699 dispatchInputEvent(); |
700 dispatchFormControlChangeEvent(); | 700 dispatchFormControlChangeEvent(); |
701 } | 701 } |
702 } | 702 } |
703 | 703 |
704 void HTMLSelectElement::scrollToSelection() | 704 void HTMLSelectElement::scrollToSelection() |
705 { | 705 { |
706 if (usesMenuList()) | 706 if (usesMenuList()) |
707 return; | 707 return; |
708 | 708 |
709 if (RenderObject* renderer = this->renderer()) | 709 if (RenderObject* renderer = this->renderer()) |
710 toRenderListBox(renderer)->selectionChanged(); | 710 toRenderListBox(renderer)->selectionChanged(); |
711 } | 711 } |
712 | 712 |
713 void HTMLSelectElement::setOptionsChangedOnRenderer() | 713 void HTMLSelectElement::setOptionsChangedOnRenderer() |
714 { | 714 { |
715 if (RenderObject* renderer = this->renderer()) { | 715 if (RenderObject* renderer = this->renderer()) { |
716 if (usesMenuList()) | 716 if (usesMenuList()) |
717 toRenderMenuList(renderer)->setOptionsChanged(true); | 717 toRenderMenuList(renderer)->setOptionsChanged(true); |
718 else | 718 else |
719 toRenderListBox(renderer)->setOptionsChanged(true); | 719 toRenderListBox(renderer)->setOptionsChanged(true); |
720 } | 720 } |
721 } | 721 } |
722 | 722 |
723 const Vector<HTMLElement*>& HTMLSelectElement::listItems() const | 723 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& HTMLSelectElement::lis
tItems() const |
724 { | 724 { |
725 if (m_shouldRecalcListItems) | 725 if (m_shouldRecalcListItems) |
726 recalcListItems(); | 726 recalcListItems(); |
727 else { | 727 else { |
728 #if !ASSERT_DISABLED | 728 #if !ASSERT_DISABLED |
729 Vector<HTMLElement*> items = m_listItems; | 729 WillBeHeapVector<RawPtrWillBeMember<HTMLElement> > items = m_listItems; |
730 recalcListItems(false); | 730 recalcListItems(false); |
731 ASSERT(items == m_listItems); | 731 ASSERT(items == m_listItems); |
732 #endif | 732 #endif |
733 } | 733 } |
734 | 734 |
735 return m_listItems; | 735 return m_listItems; |
736 } | 736 } |
737 | 737 |
738 void HTMLSelectElement::invalidateSelectedItems() | 738 void HTMLSelectElement::invalidateSelectedItems() |
739 { | 739 { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
822 | 822 |
823 if (!foundSelected && m_size <= 1 && firstOption && !firstOption->selected()
) | 823 if (!foundSelected && m_size <= 1 && firstOption && !firstOption->selected()
) |
824 firstOption->setSelectedState(true); | 824 firstOption->setSelectedState(true); |
825 } | 825 } |
826 | 826 |
827 int HTMLSelectElement::selectedIndex() const | 827 int HTMLSelectElement::selectedIndex() const |
828 { | 828 { |
829 unsigned index = 0; | 829 unsigned index = 0; |
830 | 830 |
831 // Return the number of the first option selected. | 831 // Return the number of the first option selected. |
832 const Vector<HTMLElement*>& items = listItems(); | 832 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
833 for (size_t i = 0; i < items.size(); ++i) { | 833 for (size_t i = 0; i < items.size(); ++i) { |
834 HTMLElement* element = items[i]; | 834 HTMLElement* element = items[i]; |
835 if (isHTMLOptionElement(*element)) { | 835 if (isHTMLOptionElement(*element)) { |
836 if (toHTMLOptionElement(*element).selected()) | 836 if (toHTMLOptionElement(*element).selected()) |
837 return index; | 837 return index; |
838 ++index; | 838 ++index; |
839 } | 839 } |
840 } | 840 } |
841 | 841 |
842 return -1; | 842 return -1; |
(...skipping 28 matching lines...) Expand all Loading... |
871 else if (!usesMenuList() || multiple()) | 871 else if (!usesMenuList() || multiple()) |
872 selectOption(-1); | 872 selectOption(-1); |
873 else | 873 else |
874 selectOption(nextSelectableListIndex(-1)); | 874 selectOption(nextSelectableListIndex(-1)); |
875 } | 875 } |
876 | 876 |
877 void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags) | 877 void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags) |
878 { | 878 { |
879 bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions); | 879 bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions); |
880 | 880 |
881 const Vector<HTMLElement*>& items = listItems(); | 881 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
882 int listIndex = optionToListIndex(optionIndex); | 882 int listIndex = optionToListIndex(optionIndex); |
883 | 883 |
884 HTMLElement* element = 0; | 884 HTMLElement* element = 0; |
885 if (listIndex >= 0) { | 885 if (listIndex >= 0) { |
886 element = items[listIndex]; | 886 element = items[listIndex]; |
887 if (isHTMLOptionElement(*element)) { | 887 if (isHTMLOptionElement(*element)) { |
888 if (m_activeSelectionAnchorIndex < 0 || shouldDeselect) | 888 if (m_activeSelectionAnchorIndex < 0 || shouldDeselect) |
889 setActiveSelectionAnchorIndex(listIndex); | 889 setActiveSelectionAnchorIndex(listIndex); |
890 if (m_activeSelectionEndIndex < 0 || shouldDeselect) | 890 if (m_activeSelectionEndIndex < 0 || shouldDeselect) |
891 setActiveSelectionEndIndex(listIndex); | 891 setActiveSelectionEndIndex(listIndex); |
(...skipping 22 matching lines...) Expand all Loading... |
914 else if (renderer->isListBox()) | 914 else if (renderer->isListBox()) |
915 toRenderListBox(renderer)->selectionChanged(); | 915 toRenderListBox(renderer)->selectionChanged(); |
916 } | 916 } |
917 } | 917 } |
918 | 918 |
919 notifyFormStateChanged(); | 919 notifyFormStateChanged(); |
920 } | 920 } |
921 | 921 |
922 int HTMLSelectElement::optionToListIndex(int optionIndex) const | 922 int HTMLSelectElement::optionToListIndex(int optionIndex) const |
923 { | 923 { |
924 const Vector<HTMLElement*>& items = listItems(); | 924 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
925 int listSize = static_cast<int>(items.size()); | 925 int listSize = static_cast<int>(items.size()); |
926 if (optionIndex < 0 || optionIndex >= listSize) | 926 if (optionIndex < 0 || optionIndex >= listSize) |
927 return -1; | 927 return -1; |
928 | 928 |
929 int optionIndex2 = -1; | 929 int optionIndex2 = -1; |
930 for (int listIndex = 0; listIndex < listSize; ++listIndex) { | 930 for (int listIndex = 0; listIndex < listSize; ++listIndex) { |
931 if (isHTMLOptionElement(*items[listIndex])) { | 931 if (isHTMLOptionElement(*items[listIndex])) { |
932 ++optionIndex2; | 932 ++optionIndex2; |
933 if (optionIndex2 == optionIndex) | 933 if (optionIndex2 == optionIndex) |
934 return listIndex; | 934 return listIndex; |
935 } | 935 } |
936 } | 936 } |
937 | 937 |
938 return -1; | 938 return -1; |
939 } | 939 } |
940 | 940 |
941 int HTMLSelectElement::listToOptionIndex(int listIndex) const | 941 int HTMLSelectElement::listToOptionIndex(int listIndex) const |
942 { | 942 { |
943 const Vector<HTMLElement*>& items = listItems(); | 943 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
944 if (listIndex < 0 || listIndex >= static_cast<int>(items.size()) || !isHTMLO
ptionElement(*items[listIndex])) | 944 if (listIndex < 0 || listIndex >= static_cast<int>(items.size()) || !isHTMLO
ptionElement(*items[listIndex])) |
945 return -1; | 945 return -1; |
946 | 946 |
947 // Actual index of option not counting OPTGROUP entries that may be in list. | 947 // Actual index of option not counting OPTGROUP entries that may be in list. |
948 int optionIndex = 0; | 948 int optionIndex = 0; |
949 for (int i = 0; i < listIndex; ++i) { | 949 for (int i = 0; i < listIndex; ++i) { |
950 if (isHTMLOptionElement(*items[i])) | 950 if (isHTMLOptionElement(*items[i])) |
951 ++optionIndex; | 951 ++optionIndex; |
952 } | 952 } |
953 | 953 |
(...skipping 14 matching lines...) Expand all Loading... |
968 // We only need to fire change events here for menu lists, because we fire | 968 // We only need to fire change events here for menu lists, because we fire |
969 // change events for list boxes whenever the selection change is actually ma
de. | 969 // change events for list boxes whenever the selection change is actually ma
de. |
970 // This matches other browsers' behavior. | 970 // This matches other browsers' behavior. |
971 if (usesMenuList()) | 971 if (usesMenuList()) |
972 dispatchInputAndChangeEventForMenuList(); | 972 dispatchInputAndChangeEventForMenuList(); |
973 HTMLFormControlElementWithState::dispatchBlurEvent(newFocusedElement); | 973 HTMLFormControlElementWithState::dispatchBlurEvent(newFocusedElement); |
974 } | 974 } |
975 | 975 |
976 void HTMLSelectElement::deselectItemsWithoutValidation(HTMLElement* excludeEleme
nt) | 976 void HTMLSelectElement::deselectItemsWithoutValidation(HTMLElement* excludeEleme
nt) |
977 { | 977 { |
978 const Vector<HTMLElement*>& items = listItems(); | 978 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
979 for (unsigned i = 0; i < items.size(); ++i) { | 979 for (unsigned i = 0; i < items.size(); ++i) { |
980 HTMLElement* element = items[i]; | 980 HTMLElement* element = items[i]; |
981 if (element != excludeElement && isHTMLOptionElement(*element)) | 981 if (element != excludeElement && isHTMLOptionElement(*element)) |
982 toHTMLOptionElement(element)->setSelectedState(false); | 982 toHTMLOptionElement(element)->setSelectedState(false); |
983 } | 983 } |
984 } | 984 } |
985 | 985 |
986 FormControlState HTMLSelectElement::saveFormControlState() const | 986 FormControlState HTMLSelectElement::saveFormControlState() const |
987 { | 987 { |
988 const Vector<HTMLElement*>& items = listItems(); | 988 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
989 size_t length = items.size(); | 989 size_t length = items.size(); |
990 FormControlState state; | 990 FormControlState state; |
991 for (unsigned i = 0; i < length; ++i) { | 991 for (unsigned i = 0; i < length; ++i) { |
992 if (!isHTMLOptionElement(*items[i])) | 992 if (!isHTMLOptionElement(*items[i])) |
993 continue; | 993 continue; |
994 HTMLOptionElement* option = toHTMLOptionElement(items[i]); | 994 HTMLOptionElement* option = toHTMLOptionElement(items[i]); |
995 if (!option->selected()) | 995 if (!option->selected()) |
996 continue; | 996 continue; |
997 state.append(option->value()); | 997 state.append(option->value()); |
998 if (!multiple()) | 998 if (!multiple()) |
999 break; | 999 break; |
1000 } | 1000 } |
1001 return state; | 1001 return state; |
1002 } | 1002 } |
1003 | 1003 |
1004 size_t HTMLSelectElement::searchOptionsForValue(const String& value, size_t list
IndexStart, size_t listIndexEnd) const | 1004 size_t HTMLSelectElement::searchOptionsForValue(const String& value, size_t list
IndexStart, size_t listIndexEnd) const |
1005 { | 1005 { |
1006 const Vector<HTMLElement*>& items = listItems(); | 1006 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
1007 size_t loopEndIndex = std::min(items.size(), listIndexEnd); | 1007 size_t loopEndIndex = std::min(items.size(), listIndexEnd); |
1008 for (size_t i = listIndexStart; i < loopEndIndex; ++i) { | 1008 for (size_t i = listIndexStart; i < loopEndIndex; ++i) { |
1009 if (!isHTMLOptionElement(items[i])) | 1009 if (!isHTMLOptionElement(items[i])) |
1010 continue; | 1010 continue; |
1011 if (toHTMLOptionElement(items[i])->value() == value) | 1011 if (toHTMLOptionElement(items[i])->value() == value) |
1012 return i; | 1012 return i; |
1013 } | 1013 } |
1014 return kNotFound; | 1014 return kNotFound; |
1015 } | 1015 } |
1016 | 1016 |
1017 void HTMLSelectElement::restoreFormControlState(const FormControlState& state) | 1017 void HTMLSelectElement::restoreFormControlState(const FormControlState& state) |
1018 { | 1018 { |
1019 recalcListItems(); | 1019 recalcListItems(); |
1020 | 1020 |
1021 const Vector<HTMLElement*>& items = listItems(); | 1021 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
1022 size_t itemsSize = items.size(); | 1022 size_t itemsSize = items.size(); |
1023 if (!itemsSize) | 1023 if (!itemsSize) |
1024 return; | 1024 return; |
1025 | 1025 |
1026 for (size_t i = 0; i < itemsSize; ++i) { | 1026 for (size_t i = 0; i < itemsSize; ++i) { |
1027 if (!isHTMLOptionElement(items[i])) | 1027 if (!isHTMLOptionElement(items[i])) |
1028 continue; | 1028 continue; |
1029 toHTMLOptionElement(items[i])->setSelectedState(false); | 1029 toHTMLOptionElement(items[i])->setSelectedState(false); |
1030 } | 1030 } |
1031 | 1031 |
(...skipping 28 matching lines...) Expand all Loading... |
1060 lazyReattachIfAttached(); | 1060 lazyReattachIfAttached(); |
1061 } | 1061 } |
1062 | 1062 |
1063 bool HTMLSelectElement::appendFormData(FormDataList& list, bool) | 1063 bool HTMLSelectElement::appendFormData(FormDataList& list, bool) |
1064 { | 1064 { |
1065 const AtomicString& name = this->name(); | 1065 const AtomicString& name = this->name(); |
1066 if (name.isEmpty()) | 1066 if (name.isEmpty()) |
1067 return false; | 1067 return false; |
1068 | 1068 |
1069 bool successful = false; | 1069 bool successful = false; |
1070 const Vector<HTMLElement*>& items = listItems(); | 1070 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
1071 | 1071 |
1072 for (unsigned i = 0; i < items.size(); ++i) { | 1072 for (unsigned i = 0; i < items.size(); ++i) { |
1073 HTMLElement* element = items[i]; | 1073 HTMLElement* element = items[i]; |
1074 if (isHTMLOptionElement(*element) && toHTMLOptionElement(*element).selec
ted() && !toHTMLOptionElement(*element).isDisabledFormControl()) { | 1074 if (isHTMLOptionElement(*element) && toHTMLOptionElement(*element).selec
ted() && !toHTMLOptionElement(*element).isDisabledFormControl()) { |
1075 list.appendData(name, toHTMLOptionElement(*element).value()); | 1075 list.appendData(name, toHTMLOptionElement(*element).value()); |
1076 successful = true; | 1076 successful = true; |
1077 } | 1077 } |
1078 } | 1078 } |
1079 | 1079 |
1080 // It's possible that this is a menulist with multiple options and nothing | 1080 // It's possible that this is a menulist with multiple options and nothing |
1081 // will be submitted (!successful). We won't send a unselected non-disabled | 1081 // will be submitted (!successful). We won't send a unselected non-disabled |
1082 // option as fallback. This behavior matches to other browsers. | 1082 // option as fallback. This behavior matches to other browsers. |
1083 return successful; | 1083 return successful; |
1084 } | 1084 } |
1085 | 1085 |
1086 void HTMLSelectElement::resetImpl() | 1086 void HTMLSelectElement::resetImpl() |
1087 { | 1087 { |
1088 HTMLOptionElement* firstOption = 0; | 1088 HTMLOptionElement* firstOption = 0; |
1089 HTMLOptionElement* selectedOption = 0; | 1089 HTMLOptionElement* selectedOption = 0; |
1090 | 1090 |
1091 const Vector<HTMLElement*>& items = listItems(); | 1091 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
1092 for (unsigned i = 0; i < items.size(); ++i) { | 1092 for (unsigned i = 0; i < items.size(); ++i) { |
1093 HTMLElement* element = items[i]; | 1093 HTMLElement* element = items[i]; |
1094 if (!isHTMLOptionElement(*element)) | 1094 if (!isHTMLOptionElement(*element)) |
1095 continue; | 1095 continue; |
1096 | 1096 |
1097 if (items[i]->fastHasAttribute(selectedAttr)) { | 1097 if (items[i]->fastHasAttribute(selectedAttr)) { |
1098 if (selectedOption && !m_multiple) | 1098 if (selectedOption && !m_multiple) |
1099 selectedOption->setSelectedState(false); | 1099 selectedOption->setSelectedState(false); |
1100 toHTMLOptionElement(element)->setSelectedState(true); | 1100 toHTMLOptionElement(element)->setSelectedState(true); |
1101 selectedOption = toHTMLOptionElement(element); | 1101 selectedOption = toHTMLOptionElement(element); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1159 // When using spatial navigation, we want to be able to navigate away | 1159 // When using spatial navigation, we want to be able to navigate away |
1160 // from the select element when the user hits any of the arrow keys, | 1160 // from the select element when the user hits any of the arrow keys, |
1161 // instead of changing the selection. | 1161 // instead of changing the selection. |
1162 if (isSpatialNavigationEnabled(document().frame())) { | 1162 if (isSpatialNavigationEnabled(document().frame())) { |
1163 if (!m_activeSelectionState) | 1163 if (!m_activeSelectionState) |
1164 return; | 1164 return; |
1165 } | 1165 } |
1166 | 1166 |
1167 const String& keyIdentifier = toKeyboardEvent(event)->keyIdentifier(); | 1167 const String& keyIdentifier = toKeyboardEvent(event)->keyIdentifier(); |
1168 bool handled = true; | 1168 bool handled = true; |
1169 const Vector<HTMLElement*>& listItems = this->listItems(); | 1169 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = th
is->listItems(); |
1170 int listIndex = optionToListIndex(selectedIndex()); | 1170 int listIndex = optionToListIndex(selectedIndex()); |
1171 | 1171 |
1172 if (keyIdentifier == "Down" || keyIdentifier == "Right") | 1172 if (keyIdentifier == "Down" || keyIdentifier == "Right") |
1173 listIndex = nextValidIndex(listIndex, SkipForwards, 1); | 1173 listIndex = nextValidIndex(listIndex, SkipForwards, 1); |
1174 else if (keyIdentifier == "Up" || keyIdentifier == "Left") | 1174 else if (keyIdentifier == "Up" || keyIdentifier == "Left") |
1175 listIndex = nextValidIndex(listIndex, SkipBackwards, 1); | 1175 listIndex = nextValidIndex(listIndex, SkipBackwards, 1); |
1176 else if (keyIdentifier == "PageDown") | 1176 else if (keyIdentifier == "PageDown") |
1177 listIndex = nextValidIndex(listIndex, SkipForwards, 3); | 1177 listIndex = nextValidIndex(listIndex, SkipForwards, 3); |
1178 else if (keyIdentifier == "PageUp") | 1178 else if (keyIdentifier == "PageUp") |
1179 listIndex = nextValidIndex(listIndex, SkipBackwards, 3); | 1179 listIndex = nextValidIndex(listIndex, SkipBackwards, 3); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1330 // clicked. | 1330 // clicked. |
1331 if (m_activeSelectionAnchorIndex < 0 || !shiftSelect) | 1331 if (m_activeSelectionAnchorIndex < 0 || !shiftSelect) |
1332 setActiveSelectionAnchorIndex(listIndex); | 1332 setActiveSelectionAnchorIndex(listIndex); |
1333 | 1333 |
1334 setActiveSelectionEndIndex(listIndex); | 1334 setActiveSelectionEndIndex(listIndex); |
1335 updateListBoxSelection(!multiSelect); | 1335 updateListBoxSelection(!multiSelect); |
1336 } | 1336 } |
1337 | 1337 |
1338 void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) | 1338 void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) |
1339 { | 1339 { |
1340 const Vector<HTMLElement*>& listItems = this->listItems(); | 1340 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this->
listItems(); |
1341 if (event->type() == EventTypeNames::gesturetap && event->isGestureEvent())
{ | 1341 if (event->type() == EventTypeNames::gesturetap && event->isGestureEvent())
{ |
1342 focus(); | 1342 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. | 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. |
1344 if (!renderer() || !renderer()->isListBox()) | 1344 if (!renderer() || !renderer()->isListBox()) |
1345 return; | 1345 return; |
1346 | 1346 |
1347 // Convert to coords relative to the list box if needed. | 1347 // Convert to coords relative to the list box if needed. |
1348 GestureEvent& gestureEvent = toGestureEvent(*event); | 1348 GestureEvent& gestureEvent = toGestureEvent(*event); |
1349 IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(gestu
reEvent.absoluteLocation(), UseTransforms)); | 1349 IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(gestu
reEvent.absoluteLocation(), UseTransforms)); |
1350 int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize
(localOffset)); | 1350 int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize
(localOffset)); |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1529 typeAheadFind(keyboardEvent); | 1529 typeAheadFind(keyboardEvent); |
1530 event->setDefaultHandled(); | 1530 event->setDefaultHandled(); |
1531 return; | 1531 return; |
1532 } | 1532 } |
1533 } | 1533 } |
1534 HTMLFormControlElementWithState::defaultEventHandler(event); | 1534 HTMLFormControlElementWithState::defaultEventHandler(event); |
1535 } | 1535 } |
1536 | 1536 |
1537 int HTMLSelectElement::lastSelectedListIndex() const | 1537 int HTMLSelectElement::lastSelectedListIndex() const |
1538 { | 1538 { |
1539 const Vector<HTMLElement*>& items = listItems(); | 1539 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
1540 for (size_t i = items.size(); i;) { | 1540 for (size_t i = items.size(); i;) { |
1541 HTMLElement* element = items[--i]; | 1541 HTMLElement* element = items[--i]; |
1542 if (isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selec
ted()) | 1542 if (isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selec
ted()) |
1543 return i; | 1543 return i; |
1544 } | 1544 } |
1545 return -1; | 1545 return -1; |
1546 } | 1546 } |
1547 | 1547 |
1548 int HTMLSelectElement::indexOfSelectedOption() const | 1548 int HTMLSelectElement::indexOfSelectedOption() const |
1549 { | 1549 { |
1550 return optionToListIndex(selectedIndex()); | 1550 return optionToListIndex(selectedIndex()); |
1551 } | 1551 } |
1552 | 1552 |
1553 int HTMLSelectElement::optionCount() const | 1553 int HTMLSelectElement::optionCount() const |
1554 { | 1554 { |
1555 return listItems().size(); | 1555 return listItems().size(); |
1556 } | 1556 } |
1557 | 1557 |
1558 String HTMLSelectElement::optionAtIndex(int index) const | 1558 String HTMLSelectElement::optionAtIndex(int index) const |
1559 { | 1559 { |
1560 const Vector<HTMLElement*>& items = listItems(); | 1560 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
1561 | 1561 |
1562 HTMLElement* element = items[index]; | 1562 HTMLElement* element = items[index]; |
1563 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDisabl
edFormControl()) | 1563 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDisabl
edFormControl()) |
1564 return String(); | 1564 return String(); |
1565 return toHTMLOptionElement(element)->textIndentedToRespectGroupLabel(); | 1565 return toHTMLOptionElement(element)->textIndentedToRespectGroupLabel(); |
1566 } | 1566 } |
1567 | 1567 |
1568 void HTMLSelectElement::typeAheadFind(KeyboardEvent* event) | 1568 void HTMLSelectElement::typeAheadFind(KeyboardEvent* event) |
1569 { | 1569 { |
1570 int index = m_typeAhead.handleEvent(event, TypeAhead::MatchPrefix | TypeAhea
d::CycleFirstChar); | 1570 int index = m_typeAhead.handleEvent(event, TypeAhead::MatchPrefix | TypeAhea
d::CycleFirstChar); |
(...skipping 14 matching lines...) Expand all Loading... |
1585 return InsertionDone; | 1585 return InsertionDone; |
1586 } | 1586 } |
1587 | 1587 |
1588 void HTMLSelectElement::accessKeySetSelectedIndex(int index) | 1588 void HTMLSelectElement::accessKeySetSelectedIndex(int index) |
1589 { | 1589 { |
1590 // First bring into focus the list box. | 1590 // First bring into focus the list box. |
1591 if (!focused()) | 1591 if (!focused()) |
1592 accessKeyAction(false); | 1592 accessKeyAction(false); |
1593 | 1593 |
1594 // If this index is already selected, unselect. otherwise update the selecte
d index. | 1594 // If this index is already selected, unselect. otherwise update the selecte
d index. |
1595 const Vector<HTMLElement*>& items = listItems(); | 1595 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
1596 int listIndex = optionToListIndex(index); | 1596 int listIndex = optionToListIndex(index); |
1597 if (listIndex >= 0) { | 1597 if (listIndex >= 0) { |
1598 HTMLElement* element = items[listIndex]; | 1598 HTMLElement* element = items[listIndex]; |
1599 if (isHTMLOptionElement(*element)) { | 1599 if (isHTMLOptionElement(*element)) { |
1600 if (toHTMLOptionElement(*element).selected()) | 1600 if (toHTMLOptionElement(*element).selected()) |
1601 toHTMLOptionElement(*element).setSelectedState(false); | 1601 toHTMLOptionElement(*element).setSelectedState(false); |
1602 else | 1602 else |
1603 selectOption(index, DispatchInputAndChangeEvent | UserDriven); | 1603 selectOption(index, DispatchInputAndChangeEvent | UserDriven); |
1604 } | 1604 } |
1605 } | 1605 } |
1606 | 1606 |
1607 if (usesMenuList()) | 1607 if (usesMenuList()) |
1608 dispatchInputAndChangeEventForMenuList(); | 1608 dispatchInputAndChangeEventForMenuList(); |
1609 else | 1609 else |
1610 listBoxOnChange(); | 1610 listBoxOnChange(); |
1611 | 1611 |
1612 scrollToSelection(); | 1612 scrollToSelection(); |
1613 } | 1613 } |
1614 | 1614 |
1615 unsigned HTMLSelectElement::length() const | 1615 unsigned HTMLSelectElement::length() const |
1616 { | 1616 { |
1617 unsigned options = 0; | 1617 unsigned options = 0; |
1618 | 1618 |
1619 const Vector<HTMLElement*>& items = listItems(); | 1619 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(
); |
1620 for (unsigned i = 0; i < items.size(); ++i) { | 1620 for (unsigned i = 0; i < items.size(); ++i) { |
1621 if (isHTMLOptionElement(*items[i])) | 1621 if (isHTMLOptionElement(*items[i])) |
1622 ++options; | 1622 ++options; |
1623 } | 1623 } |
1624 | 1624 |
1625 return options; | 1625 return options; |
1626 } | 1626 } |
1627 | 1627 |
1628 void HTMLSelectElement::finishParsingChildren() | 1628 void HTMLSelectElement::finishParsingChildren() |
1629 { | 1629 { |
1630 HTMLFormControlElementWithState::finishParsingChildren(); | 1630 HTMLFormControlElementWithState::finishParsingChildren(); |
1631 updateListItemSelectedStates(); | 1631 updateListItemSelectedStates(); |
1632 } | 1632 } |
1633 | 1633 |
1634 bool HTMLSelectElement::anonymousIndexedSetter(unsigned index, PassRefPtr<HTMLOp
tionElement> value, ExceptionState& exceptionState) | 1634 bool HTMLSelectElement::anonymousIndexedSetter(unsigned index, PassRefPtrWillBeR
awPtr<HTMLOptionElement> value, ExceptionState& exceptionState) |
1635 { | 1635 { |
1636 if (!value) { // undefined or null | 1636 if (!value) { // undefined or null |
1637 remove(index); | 1637 remove(index); |
1638 return true; | 1638 return true; |
1639 } | 1639 } |
1640 setOption(index, value.get(), exceptionState); | 1640 setOption(index, value.get(), exceptionState); |
1641 return true; | 1641 return true; |
1642 } | 1642 } |
1643 | 1643 |
1644 bool HTMLSelectElement::isInteractiveContent() const | 1644 bool HTMLSelectElement::isInteractiveContent() const |
1645 { | 1645 { |
1646 return true; | 1646 return true; |
1647 } | 1647 } |
1648 | 1648 |
1649 bool HTMLSelectElement::supportsAutofocus() const | 1649 bool HTMLSelectElement::supportsAutofocus() const |
1650 { | 1650 { |
1651 return true; | 1651 return true; |
1652 } | 1652 } |
1653 | 1653 |
1654 void HTMLSelectElement::updateListOnRenderer() | 1654 void HTMLSelectElement::updateListOnRenderer() |
1655 { | 1655 { |
1656 setOptionsChangedOnRenderer(); | 1656 setOptionsChangedOnRenderer(); |
1657 } | 1657 } |
1658 | 1658 |
| 1659 void HTMLSelectElement::trace(Visitor* visitor) |
| 1660 { |
| 1661 visitor->trace(m_listItems); |
| 1662 HTMLFormControlElementWithState::trace(visitor); |
| 1663 } |
| 1664 |
1659 } // namespace | 1665 } // namespace |
OLD | NEW |