bool HTMLSelectElement::appendFormData(FormDataList& list, bool) { bool successful = false; const Vector<HTMLElement*>& items = listItems(); unsigned i; for (i = 0; i < items.size(); i++) { if (items[i]->hasLocalName(optionTag)) { HTMLOptionElement *option = static_cast<HTMLOptionElement*>(items[i]); if (option->selected()) { list.appendData(name(), option->value()); successful = true; } } } // ### this case should not happen. make sure that we select the first option // in any case. otherwise we have no consistency with the DOM interface. FIXME! // we return the first one if it was a combobox select if (!successful && !m_multiple && m_size <= 1 && items.size() && (items[0]->hasLocalName(optionTag))) { HTMLOptionElement *option = static_cast<HTMLOptionElement*>(items[0]); if (option->value().isNull()) list.appendData(name(), option->text().stripWhiteSpace()); else list.appendData(name(), option->value()); successful = true; } return successful; }
JSValue jsHTMLOptionElementSelected(ExecState* exec, JSValue slotBase, const Identifier&) { JSHTMLOptionElement* castedThis = static_cast<JSHTMLOptionElement*>(asObject(slotBase)); UNUSED_PARAM(exec); HTMLOptionElement* imp = static_cast<HTMLOptionElement*>(castedThis->impl()); JSValue result = jsBoolean(imp->selected()); return result; }
inline bool HTMLCollection::isAcceptableElement(Element* element) const { switch (m_type) { case DocImages: return element->hasLocalName(imgTag); case DocScripts: return element->hasLocalName(scriptTag); case DocForms: return element->hasLocalName(formTag); case TableTBodies: return element->hasLocalName(tbodyTag); case TRCells: return element->hasLocalName(tdTag) || element->hasLocalName(thTag); case TSectionRows: return element->hasLocalName(trTag); case SelectOptions: return element->hasLocalName(optionTag); case SelectedOptions: if (element->hasLocalName(optionTag)) { HTMLOptionElement* option = static_cast<HTMLOptionElement*>(element); if (option->selected()) return true; } return false; case DataListOptions: if (element->hasLocalName(optionTag)) { HTMLOptionElement* option = static_cast<HTMLOptionElement*>(element); if (!option->disabled() && !option->value().isEmpty()) return true; } return false; case MapAreas: return element->hasLocalName(areaTag); case DocApplets: return element->hasLocalName(appletTag) || (element->hasLocalName(objectTag) && static_cast<HTMLObjectElement*>(element)->containsJavaApplet()); case DocEmbeds: return element->hasLocalName(embedTag); case DocObjects: return element->hasLocalName(objectTag); case DocLinks: return (element->hasLocalName(aTag) || element->hasLocalName(areaTag)) && element->fastHasAttribute(hrefAttr); case DocAnchors: return element->hasLocalName(aTag) && element->fastHasAttribute(nameAttr); case DocAll: case NodeChildren: return true; #if ENABLE(MICRODATA) case ItemProperties: return element->isHTMLElement() && element->fastHasAttribute(itempropAttr); #endif case DocumentNamedItems: case OtherCollection: case WindowNamedItems: ASSERT_NOT_REACHED(); } return false; }
void LayoutMenuList::setTextFromOption(int optionIndex) { HTMLSelectElement* select = selectElement(); const HeapVector<Member<HTMLElement>>& listItems = select->listItems(); const int size = listItems.size(); String text = emptyString(); m_optionStyle.clear(); if (selectElement()->multiple()) { unsigned selectedCount = 0; int firstSelectedIndex = -1; for (int i = 0; i < size; ++i) { Element* element = listItems[i]; if (!isHTMLOptionElement(*element)) continue; if (toHTMLOptionElement(element)->selected()) { if (++selectedCount == 1) firstSelectedIndex = i; } } if (selectedCount == 1) { ASSERT(0 <= firstSelectedIndex); ASSERT(firstSelectedIndex < size); HTMLOptionElement* selectedOptionElement = toHTMLOptionElement(listItems[firstSelectedIndex]); ASSERT(selectedOptionElement->selected()); text = selectedOptionElement->textIndentedToRespectGroupLabel(); m_optionStyle = selectedOptionElement->mutableComputedStyle(); } else { Locale& locale = select->locale(); String localizedNumberString = locale.convertToLocalizedNumber(String::number(selectedCount)); text = locale.queryString(WebLocalizedString::SelectMenuListText, localizedNumberString); ASSERT(!m_optionStyle); } } else { const int i = select->optionToListIndex(optionIndex); if (i >= 0 && i < size) { Element* element = listItems[i]; if (isHTMLOptionElement(*element)) { text = toHTMLOptionElement(element)->textIndentedToRespectGroupLabel(); m_optionStyle = element->mutableComputedStyle(); } } } setText(text.stripWhiteSpace()); didUpdateActiveOption(optionIndex); }
void HTMLSelectElement::setActiveSelectionAnchorIndex(int index) { m_activeSelectionAnchorIndex = index; // Cache the selection state so we can restore the old selection as the new selection pivots around this anchor index const Vector<HTMLElement*>& items = listItems(); m_cachedStateForActiveSelection.clear(); for (unsigned i = 0; i < items.size(); i++) { if (items[i]->hasLocalName(optionTag)) { HTMLOptionElement* option = static_cast<HTMLOptionElement*>(items[i]); m_cachedStateForActiveSelection.append(option->selected()); } else m_cachedStateForActiveSelection.append(false); } }
void HTMLSelectElement::saveLastSelection() { const Vector<HTMLElement*>& items = listItems(); if (usesMenuList()) { m_lastOnChangeIndex = selectedIndex(); return; } m_lastOnChangeSelection.clear(); for (unsigned i = 0; i < items.size(); i++) { if (items[i]->hasLocalName(optionTag)) { HTMLOptionElement* option = static_cast<HTMLOptionElement*>(items[i]); m_lastOnChangeSelection.append(option->selected()); } else m_lastOnChangeSelection.append(false); } }
void HTMLSelectElement::accessKeySetSelectedIndex(int index) { // first bring into focus the list box if (!focused()) accessKeyAction(false); // if this index is already selected, unselect. otherwise update the selected index Node* listNode = item(index); if (listNode && listNode->hasTagName(optionTag)) { HTMLOptionElement* listElement = static_cast<HTMLOptionElement*>(listNode); if (listElement->selected()) listElement->setSelectedState(false); else setSelectedIndex(index, false, true); } listBoxOnChange(); scrollToSelection(); }
void LayoutMenuList::updateFromElement() { HTMLSelectElement* select = selectElement(); HTMLOptionElement* option = select->optionToBeShown(); String text = emptyString(); m_optionStyle.clear(); if (select->isMultiple()) { unsigned selectedCount = 0; HTMLOptionElement* selectedOptionElement = nullptr; for (const auto& option : select->optionList()) { if (option->selected()) { if (++selectedCount == 1) selectedOptionElement = option; } } if (selectedCount == 1) { text = selectedOptionElement->textIndentedToRespectGroupLabel(); m_optionStyle = selectedOptionElement->mutableComputedStyle(); } else { Locale& locale = select->locale(); String localizedNumberString = locale.convertToLocalizedNumber(String::number(selectedCount)); text = locale.queryString(WebLocalizedString::SelectMenuListText, localizedNumberString); ASSERT(!m_optionStyle); } } else { if (option) { text = option->textIndentedToRespectGroupLabel(); m_optionStyle = option->mutableComputedStyle(); } } setText(text.stripWhiteSpace()); didUpdateActiveOption(option); }
static v8::Handle<v8::Value> selectedAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { HTMLOptionElement* imp = V8HTMLOptionElement::toNative(info.Holder()); return v8Boolean(imp->selected(), info.GetIsolate()); }
static v8::Handle<v8::Value> selectedAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLOptionElement.selected._get"); HTMLOptionElement* imp = V8HTMLOptionElement::toNative(info.Holder()); return v8Boolean(imp->selected()); }
void HTMLSelectElement::listBoxDefaultEventHandler(Event* evt) { if (evt->type() == eventNames().mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) { focus(); MouseEvent* mEvt = static_cast<MouseEvent*>(evt); int listIndex = static_cast<RenderListBox*>(renderer())->listIndexAtOffset(mEvt->offsetX(), mEvt->offsetY()); if (listIndex >= 0) { // Save the selection so it can be compared to the new selection when we call onChange during mouseup, or after autoscroll finishes. saveLastSelection(); m_activeSelectionState = true; bool multiSelectKeyPressed = false; #if PLATFORM(MAC) multiSelectKeyPressed = mEvt->metaKey(); #else multiSelectKeyPressed = mEvt->ctrlKey(); #endif bool shiftSelect = multiple() && mEvt->shiftKey(); bool multiSelect = multiple() && multiSelectKeyPressed && !mEvt->shiftKey(); HTMLElement* clickedElement = listItems()[listIndex]; HTMLOptionElement* option = 0; if (clickedElement->hasLocalName(optionTag)) { option = static_cast<HTMLOptionElement*>(clickedElement); // Keep track of whether an active selection (like during drag selection), should select or deselect if (option->selected() && multiSelectKeyPressed) m_activeSelectionState = false; if (!m_activeSelectionState) option->setSelectedState(false); } // If we're not in any special multiple selection mode, then deselect all other items, excluding the clicked option. // If no option was clicked, then this will deselect all items in the list. if (!shiftSelect && !multiSelect) deselectItems(option); // If the anchor hasn't been set, and we're doing a single selection or a shift selection, then initialize the anchor to the first selected index. if (m_activeSelectionAnchorIndex < 0 && !multiSelect) setActiveSelectionAnchorIndex(selectedIndex()); // Set the selection state of the clicked option if (option && !option->disabled()) option->setSelectedState(true); // If there was no selectedIndex() for the previous initialization, or // If we're doing a single selection, or a multiple selection (using cmd or ctrl), then initialize the anchor index to the listIndex that just got clicked. if (listIndex >= 0 && (m_activeSelectionAnchorIndex < 0 || !shiftSelect)) setActiveSelectionAnchorIndex(listIndex); setActiveSelectionEndIndex(listIndex); updateListBoxSelection(!multiSelect); if (Frame* frame = document()->frame()) frame->eventHandler()->setMouseDownMayStartAutoscroll(); evt->setDefaultHandled(); } } else if (evt->type() == eventNames().mouseupEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton && document()->frame()->eventHandler()->autoscrollRenderer() != renderer()) // This makes sure we fire onChange for a single click. For drag selection, onChange will fire when the autoscroll timer stops. listBoxOnChange(); else if (evt->type() == eventNames().keydownEvent) { if (!evt->isKeyboardEvent()) return; String keyIdentifier = static_cast<KeyboardEvent*>(evt)->keyIdentifier(); int endIndex = 0; if (m_activeSelectionEndIndex < 0) { // Initialize the end index if (keyIdentifier == "Down") endIndex = nextSelectableListIndex(lastSelectedListIndex()); else if (keyIdentifier == "Up") endIndex = previousSelectableListIndex(optionToListIndex(selectedIndex())); } else { // Set the end index based on the current end index if (keyIdentifier == "Down") endIndex = nextSelectableListIndex(m_activeSelectionEndIndex); else if (keyIdentifier == "Up") endIndex = previousSelectableListIndex(m_activeSelectionEndIndex); } if (keyIdentifier == "Down" || keyIdentifier == "Up") { // Save the selection so it can be compared to the new selection when we call onChange immediately after making the new selection. saveLastSelection(); ASSERT(endIndex >= 0 && (unsigned)endIndex < listItems().size()); setActiveSelectionEndIndex(endIndex); // If the anchor is unitialized, or if we're going to deselect all other options, then set the anchor index equal to the end index. bool deselectOthers = !multiple() || !static_cast<KeyboardEvent*>(evt)->shiftKey(); if (m_activeSelectionAnchorIndex < 0 || deselectOthers) { m_activeSelectionState = true; if (deselectOthers) deselectItems(); setActiveSelectionAnchorIndex(m_activeSelectionEndIndex); } static_cast<RenderListBox*>(renderer())->scrollToRevealElementAtListIndex(endIndex); updateListBoxSelection(deselectOthers); listBoxOnChange(); evt->setDefaultHandled(); } } else if (evt->type() == eventNames().keypressEvent) { if (!evt->isKeyboardEvent()) return; int keyCode = static_cast<KeyboardEvent*>(evt)->keyCode(); if (keyCode == '\r') { if (form()) form()->submitClick(evt); evt->setDefaultHandled(); return; } } }