| 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 |