int SelectElement::listToOptionIndex(const SelectElementData& data, const Element* element, int listIndex)
{
    const Vector<Element*>& items = data.listItems(element);
    if (listIndex < 0 || listIndex >= int(items.size()) ||
        !isOptionElement(items[listIndex]))
        return -1;

    int optionIndex = 0; // actual index of option not counting OPTGROUP entries that may be in list
    for (int i = 0; i < listIndex; ++i)
        if (isOptionElement(items[i]))
            ++optionIndex;

    return optionIndex;
}
Vector<unsigned> WMLSelectElement::valueStringToOptionIndices(const String& value) const
{
    Vector<unsigned> indices;
    if (value.isEmpty())
        return indices;

    const Vector<Element*>& items = m_data.listItems(this);
    if (items.isEmpty())
        return indices;

    Vector<String> indexStrings;
    value.split(';', indexStrings);

    unsigned optionIndex = 0;

    Vector<String>::const_iterator end = indexStrings.end();
    for (Vector<String>::const_iterator it = indexStrings.begin(); it != end; ++it) {
        String value = *it;

        for (unsigned i = 0; i < items.size(); ++i) {
            if (!isOptionElement(items[i]))
                continue;

            ++optionIndex;
            if (OptionElement* optionElement = toOptionElement(items[i])) {
                if (optionElement->value() == value) {
                    indices.append(optionIndex);
                    break;
                }
            }
        }
    }

    return indices;
}
int SelectElement::nextSelectableListIndex(SelectElementData& data, Element* element, int startIndex)
{
    const Vector<Element*>& items = data.listItems(element);
    int index = startIndex + 1;
    while (index >= 0 && (unsigned) index < items.size() && (!isOptionElement(items[index]) || items[index]->disabled()))
        ++index;
    if ((unsigned) index == items.size())
        return startIndex;
    return index;
}
unsigned SelectElement::optionCount(const SelectElementData& data, const Element* element)
{
    unsigned options = 0;

    const Vector<Element*>& items = data.listItems(element);
    for (unsigned i = 0; i < items.size(); ++i) {
        if (isOptionElement(items[i]))
            ++options;
    }

    return options;
}
int SelectElement::optionToListIndex(const SelectElementData& data, const Element* element, int optionIndex)
{
    const Vector<Element*>& items = data.listItems(element);
    int listSize = (int) items.size();
    if (optionIndex < 0 || optionIndex >= listSize)
        return -1;

    int optionIndex2 = -1;
    for (int listIndex = 0; listIndex < listSize; ++listIndex) {
        if (isOptionElement(items[listIndex])) {
            ++optionIndex2;
            if (optionIndex2 == optionIndex)
                return listIndex;
        }
    }

    return -1;
}
Beispiel #6
0
int OptionElement::optionIndex(SelectElement* selectElement, const Element* element)
{
    if (!selectElement)
        return 0;

    // Let's do this dynamically. Might be a bit slow, but we're sure
    // we won't forget to update a member variable in some cases...
    const Vector<Element*>& items = selectElement->listItems();
    int length = items.size();
    int optionIndex = 0;
    for (int i = 0; i < length; ++i) {
        if (!isOptionElement(items[i]))
            continue;
        if (items[i] == element)
            return optionIndex;
        ++optionIndex;
    }

    return 0;
}
void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element* element, Event* event, HTMLFormElement* htmlForm)
{
#if !ARROW_KEYS_POP_MENU
    UNUSED_PARAM(htmlForm);
#endif

    if (event->type() == eventNames().keydownEvent) {
        if (!element->renderer() || !event->isKeyboardEvent())
            return;

        String keyIdentifier = static_cast<KeyboardEvent*>(event)->keyIdentifier();
        bool handled = false;

#if ARROW_KEYS_POP_MENU
        if (keyIdentifier == "Down" || keyIdentifier == "Up") {
            element->focus();
            // Save the selection so it can be compared to the new selection when dispatching change events during setSelectedIndex,
            // which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu.
            saveLastSelection(data, element);
            if (RenderMenuList* menuList = static_cast<RenderMenuList*>(element->renderer()))
                menuList->showPopup();
            handled = true;
        }
#else
        const Vector<Element*>& listItems = data.listItems(element);
        int size = listItems.size();

        int listIndex = optionToListIndex(data, element, selectedIndex(data, element));
        if (keyIdentifier == "Down" || keyIdentifier == "Right") {
            for (listIndex += 1;
                 listIndex >= 0 && listIndex < size && (listItems[listIndex]->disabled() || !isOptionElement(listItems[listIndex]));
                 ++listIndex) { }
            if (listIndex >= 0 && listIndex < size)
                setSelectedIndex(data, element, listToOptionIndex(data, element, listIndex));
            handled = true;
        } else if (keyIdentifier == "Up" || keyIdentifier == "Left") {
            for (listIndex -= 1;
                 listIndex >= 0 && listIndex < size && (listItems[listIndex]->disabled() || !isOptionElement(listItems[listIndex]));
                 --listIndex) { }
            if (listIndex >= 0 && listIndex < size)
                setSelectedIndex(data, element, listToOptionIndex(data, element, listIndex));
            handled = true;
        }
#endif
        if (handled)
            event->setDefaultHandled();
    }

    // Use key press event here since sending simulated mouse events
    // on key down blocks the proper sending of the key press event.
    if (event->type() == eventNames().keypressEvent) {
        if (!element->renderer() || !event->isKeyboardEvent())
            return;

        int keyCode = static_cast<KeyboardEvent*>(event)->keyCode();
        bool handled = false;

#if SPACE_OR_RETURN_POP_MENU
        if (keyCode == ' ' || keyCode == '\r') {
            element->focus();
            // Save the selection so it can be compared to the new selection when dispatching change events during setSelectedIndex,
            // which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu.
            saveLastSelection(data, element);
            if (RenderMenuList* menuList = static_cast<RenderMenuList*>(element->renderer()))
                menuList->showPopup();
            handled = true;
        }
#elif ARROW_KEYS_POP_MENU
        if (keyCode == ' ') {
            element->focus();
            // Save the selection so it can be compared to the new selection when dispatching change events during setSelectedIndex,
            // which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu.
            saveLastSelection(data, element);
            if (RenderMenuList* menuList = static_cast<RenderMenuList*>(element->renderer()))
                menuList->showPopup();
            handled = true;
        } else if (keyCode == '\r') {
            menuListOnChange(data, element);
            if (htmlForm)
                htmlForm->submitClick(event);
            handled = true;
        }
#else
        int listIndex = optionToListIndex(data, element, selectedIndex(data, element));
        if (keyCode == '\r') {
            // listIndex should already be selected, but this will fire the onchange handler.
            setSelectedIndex(data, element, listToOptionIndex(data, element, listIndex), true, true);
            handled = true;
        }
#endif
        if (handled)
            event->setDefaultHandled();
    }

    if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) {
        element->focus();
        if (RenderMenuList* menuList = static_cast<RenderMenuList*>(element->renderer())) {
            if (menuList->popupIsVisible())
                menuList->hidePopup();
            else {
                // Save the selection so it can be compared to the new selection when we call onChange during setSelectedIndex,
                // which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu.
                saveLastSelection(data, element);
                menuList->showPopup();
            }
        }
        event->setDefaultHandled();
    }
}