, m_suggestedIndex(-1)
{
ScriptWrappable::init(this);
+ setHasCustomStyleCallbacks();
}
-PassRefPtr<HTMLSelectElement> HTMLSelectElement::create(Document& document)
+PassRefPtrWillBeRawPtr<HTMLSelectElement> HTMLSelectElement::create(Document& document)
{
- return adoptRef(new HTMLSelectElement(document, 0));
+ return adoptRefWillBeRefCountedGarbageCollected(new HTMLSelectElement(document, 0));
}
-PassRefPtr<HTMLSelectElement> HTMLSelectElement::create(Document& document, HTMLFormElement* form)
+PassRefPtrWillBeRawPtr<HTMLSelectElement> HTMLSelectElement::create(Document& document, HTMLFormElement* form)
{
- return adoptRef(new HTMLSelectElement(document, form));
+ return adoptRefWillBeRefCountedGarbageCollected(new HTMLSelectElement(document, form));
}
const AtomicString& HTMLSelectElement::formControlType() const
String HTMLSelectElement::value() const
{
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
for (unsigned i = 0; i < items.size(); i++) {
if (isHTMLOptionElement(items[i]) && toHTMLOptionElement(items[i])->selected())
return toHTMLOptionElement(items[i])->value();
void HTMLSelectElement::setValue(const String &value, bool sendEvents)
{
// We clear the previously selected option(s) when needed, to guarantee calling setSelectedIndex() only once.
- unsigned optionIndex = 0;
+ int optionIndex = 0;
if (value.isNull()) {
optionIndex = -1;
} else {
// Find the option with value() matching the given parameter and make it the current selection.
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
for (unsigned i = 0; i < items.size(); i++) {
if (isHTMLOptionElement(items[i])) {
if (toHTMLOptionElement(items[i])->value() == value)
optionIndex++;
}
}
- if (optionIndex >= items.size())
+ if (optionIndex >= static_cast<int>(items.size()))
optionIndex = -1;
}
+
+ int previousSelectedIndex = selectedIndex();
setSelectedIndex(optionIndex);
- if (sendEvents) {
+ if (sendEvents && previousSelectedIndex != selectedIndex()) {
if (usesMenuList())
dispatchInputAndChangeEventForMenuList(false);
else
String HTMLSelectElement::suggestedValue() const
{
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
for (unsigned i = 0; i < items.size(); ++i) {
if (isHTMLOptionElement(items[i]) && m_suggestedIndex >= 0) {
if (i == static_cast<unsigned>(m_suggestedIndex))
return;
}
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
unsigned optionIndex = 0;
for (unsigned i = 0; i < items.size(); ++i) {
if (isHTMLOptionElement(items[i])) {
break;
} while (++diff);
} else {
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
// Removing children fires mutation events, which might mutate the DOM further, so we first copy out a list
// of elements that we intend to remove then attempt to remove them one at a time.
int HTMLSelectElement::nextValidIndex(int listIndex, SkipDirection direction, int skip) const
{
ASSERT(direction == -1 || direction == 1);
- const Vector<HTMLElement*>& listItems = this->listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this->listItems();
int lastGoodIndex = listIndex;
int size = listItems.size();
for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex += direction) {
--skip;
- if (!listItems[listIndex]->isDisabledFormControl() && isHTMLOptionElement(*listItems[listIndex])) {
- lastGoodIndex = listIndex;
- if (skip <= 0)
- break;
- }
+ HTMLElement* element = listItems[listIndex];
+ if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDisabledFormControl() || toHTMLOptionElement(element)->isDisplayNone())
+ continue;
+ lastGoodIndex = listIndex;
+ if (skip <= 0)
+ break;
}
return lastGoodIndex;
}
int HTMLSelectElement::firstSelectableListIndex() const
{
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
int index = nextValidIndex(items.size(), SkipBackwards, INT_MAX);
if (static_cast<size_t>(index) == items.size())
return -1;
// Returns the index of the next valid item one page away from |startIndex| in direction |direction|.
int HTMLSelectElement::nextSelectableListIndexPageAway(int startIndex, SkipDirection direction) const
{
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
// Can't use m_size because renderer forces a minimum size.
int pageSize = 0;
if (renderer()->isListBox())
}
m_lastOnChangeSelection.clear();
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
for (unsigned i = 0; i < items.size(); ++i) {
HTMLElement* element = items[i];
m_lastOnChangeSelection.append(isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selected());
// selection pivots around this anchor index.
m_cachedStateForActiveSelection.clear();
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
for (unsigned i = 0; i < items.size(); ++i) {
HTMLElement* element = items[i];
m_cachedStateForActiveSelection.append(isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selected());
unsigned start = min(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex);
unsigned end = max(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex);
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
for (unsigned i = 0; i < items.size(); ++i) {
HTMLElement* element = items[i];
- if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDisabledFormControl())
+ if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDisabledFormControl() || toHTMLOptionElement(element)->isDisplayNone())
continue;
if (i >= start && i <= end)
{
ASSERT(!usesMenuList() || m_multiple);
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
// If the cached selection list is empty, or the size has changed, then fire
// dispatchFormControlChangeEvent, and return early.
}
if (fireOnChange) {
- RefPtr<HTMLSelectElement> protector(this);
+ RefPtrWillBeRawPtr<HTMLSelectElement> protector(this);
dispatchInputEvent();
dispatchFormControlChangeEvent();
}
if (m_lastOnChangeIndex != selected && (!requiresUserGesture || m_isProcessingUserDrivenChange)) {
m_lastOnChangeIndex = selected;
m_isProcessingUserDrivenChange = false;
- RefPtr<HTMLSelectElement> protector(this);
+ RefPtrWillBeRawPtr<HTMLSelectElement> protector(this);
dispatchInputEvent();
dispatchFormControlChangeEvent();
}
}
}
-const Vector<HTMLElement*>& HTMLSelectElement::listItems() const
+const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& HTMLSelectElement::listItems() const
{
if (m_shouldRecalcListItems)
recalcListItems();
else {
#if !ASSERT_DISABLED
- Vector<HTMLElement*> items = m_listItems;
+ WillBeHeapVector<RawPtrWillBeMember<HTMLElement> > items = m_listItems;
recalcListItems(false);
ASSERT(items == m_listItems);
#endif
unsigned index = 0;
// Return the number of the first option selected.
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
for (size_t i = 0; i < items.size(); ++i) {
HTMLElement* element = items[i];
if (isHTMLOptionElement(*element)) {
{
bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions);
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
int listIndex = optionToListIndex(optionIndex);
HTMLElement* element = 0;
scrollToSelection();
+ setNeedsValidityCheck();
+
if (usesMenuList()) {
m_isProcessingUserDrivenChange = flags & UserDriven;
if (flags & DispatchInputAndChangeEvent)
}
}
- setNeedsValidityCheck();
notifyFormStateChanged();
}
int HTMLSelectElement::optionToListIndex(int optionIndex) const
{
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
int listSize = static_cast<int>(items.size());
if (optionIndex < 0 || optionIndex >= listSize)
return -1;
int HTMLSelectElement::listToOptionIndex(int listIndex) const
{
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
if (listIndex < 0 || listIndex >= static_cast<int>(items.size()) || !isHTMLOptionElement(*items[listIndex]))
return -1;
void HTMLSelectElement::deselectItemsWithoutValidation(HTMLElement* excludeElement)
{
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
for (unsigned i = 0; i < items.size(); ++i) {
HTMLElement* element = items[i];
if (element != excludeElement && isHTMLOptionElement(*element))
FormControlState HTMLSelectElement::saveFormControlState() const
{
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
size_t length = items.size();
FormControlState state;
for (unsigned i = 0; i < length; ++i) {
size_t HTMLSelectElement::searchOptionsForValue(const String& value, size_t listIndexStart, size_t listIndexEnd) const
{
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
size_t loopEndIndex = std::min(items.size(), listIndexEnd);
for (size_t i = listIndexStart; i < loopEndIndex; ++i) {
if (!isHTMLOptionElement(items[i]))
{
recalcListItems();
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
size_t itemsSize = items.size();
if (!itemsSize)
return;
return false;
bool successful = false;
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
for (unsigned i = 0; i < items.size(); ++i) {
HTMLElement* element = items[i];
HTMLOptionElement* firstOption = 0;
HTMLOptionElement* selectedOption = 0;
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
for (unsigned i = 0; i < items.size(); ++i) {
HTMLElement* element = items[i];
if (!isHTMLOptionElement(*element))
const String& keyIdentifier = toKeyboardEvent(event)->keyIdentifier();
bool handled = true;
- const Vector<HTMLElement*>& listItems = this->listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this->listItems();
int listIndex = optionToListIndex(selectedIndex());
if (keyIdentifier == "Down" || keyIdentifier == "Right")
{
ASSERT(listIndex >= 0);
+ HTMLElement* clickedElement = listItems()[listIndex];
+ ASSERT(clickedElement);
+ if (isHTMLOptGroupElement(clickedElement))
+ return;
+
// Save the selection so it can be compared to the new selection when
// dispatching change events during mouseup, or after autoscroll finishes.
saveLastSelection();
bool shiftSelect = m_multiple && shift;
bool multiSelect = m_multiple && multi && !shift;
- HTMLElement* clickedElement = listItems()[listIndex];
- ASSERT(clickedElement);
if (isHTMLOptionElement(*clickedElement)) {
// Keep track of whether an active selection (like during drag
// selection), should select or deselect.
void HTMLSelectElement::listBoxDefaultEventHandler(Event* event)
{
- const Vector<HTMLElement*>& listItems = this->listItems();
- bool dragSelection = false;
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this->listItems();
if (event->type() == EventTypeNames::gesturetap && event->isGestureEvent()) {
focus();
// Calling focus() may cause us to lose our renderer or change the render type, in which case do not want to handle the event.
updateListBoxSelection(true);
}
}
- dragSelection = true;
}
} else if (event->type() == EventTypeNames::mouseup && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton && renderer() && !toRenderBox(renderer())->autoscrollInProgress()) {
// We didn't start this click/drag on any options.
if (m_lastOnChangeSelection.isEmpty())
return;
- // This makes sure we fire dispatchFormControlChangeEvent for a single
- // click. For drag selection, onChange will fire when the autoscroll
- // timer stops.
- if (!dragSelection) {
- listBoxOnChange();
- }
+ listBoxOnChange();
} else if (event->type() == EventTypeNames::keydown) {
if (!event->isKeyboardEvent())
return;
int HTMLSelectElement::lastSelectedListIndex() const
{
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
for (size_t i = items.size(); i;) {
HTMLElement* element = items[--i];
if (isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selected())
String HTMLSelectElement::optionAtIndex(int index) const
{
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
HTMLElement* element = items[index];
if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDisabledFormControl())
accessKeyAction(false);
// If this index is already selected, unselect. otherwise update the selected index.
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
int listIndex = optionToListIndex(index);
if (listIndex >= 0) {
HTMLElement* element = items[listIndex];
{
unsigned options = 0;
- const Vector<HTMLElement*>& items = listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems();
for (unsigned i = 0; i < items.size(); ++i) {
if (isHTMLOptionElement(*items[i]))
++options;
updateListItemSelectedStates();
}
-bool HTMLSelectElement::anonymousIndexedSetter(unsigned index, PassRefPtr<HTMLOptionElement> value, ExceptionState& exceptionState)
+bool HTMLSelectElement::anonymousIndexedSetter(unsigned index, PassRefPtrWillBeRawPtr<HTMLOptionElement> value, ExceptionState& exceptionState)
{
if (!value) { // undefined or null
remove(index);
return true;
}
+void HTMLSelectElement::updateListOnRenderer()
+{
+ setOptionsChangedOnRenderer();
+}
+
+void HTMLSelectElement::trace(Visitor* visitor)
+{
+#if ENABLE(OILPAN)
+ visitor->trace(m_listItems);
+#endif
+ HTMLFormControlElementWithState::trace(visitor);
+}
+
} // namespace