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; }
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(); } }