Beispiel #1
0
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;
}
Beispiel #3
0
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);
}
Beispiel #5
0
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);
    }
}
Beispiel #6
0
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);
    }
}
Beispiel #7
0
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();
}
Beispiel #8
0
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());
}
Beispiel #10
0
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());
}
Beispiel #11
0
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;
        }
    }
}