TEST_F(HTMLSelectElementTest, SaveRestoreSelectSingleFormControlState) { document().documentElement()->setInnerHTML( String("<!DOCTYPE HTML><select id='sel'>" "<option value='111' id='0'>111</option>" "<option value='222'>222</option>" "<option value='111' selected id='2'>!666</option>" "<option value='999'>999</option></select>"), ASSERT_NO_EXCEPTION); document().view()->updateAllLifecyclePhases(); Element* element = document().getElementById("sel"); HTMLFormControlElementWithState* select = toHTMLSelectElement(element); HTMLOptionElement* opt0 = toHTMLOptionElement(document().getElementById("0")); HTMLOptionElement* opt2 = toHTMLOptionElement(document().getElementById("2")); // Save the select element state, and then restore again. // Test passes if the restored state is not changed. EXPECT_EQ(2, toHTMLSelectElement(element)->selectedIndex()); EXPECT_FALSE(opt0->selected()); EXPECT_TRUE(opt2->selected()); FormControlState selectState = select->saveFormControlState(); EXPECT_EQ(2U, selectState.valueSize()); // Clear the selected state, to be restored by restoreFormControlState. toHTMLSelectElement(select)->setSelectedIndex(-1); ASSERT_FALSE(opt2->selected()); // Restore select->restoreFormControlState(selectState); EXPECT_EQ(2, toHTMLSelectElement(element)->selectedIndex()); EXPECT_FALSE(opt0->selected()); EXPECT_TRUE(opt2->selected()); }
TEST_F(HTMLSelectElementTest, PreviousSelectableOption) { { document().documentElement()->setInnerHTML("<select></select>", ASSERT_NO_EXCEPTION); document().view()->updateAllLifecyclePhases(); HTMLSelectElement* select = toHTMLSelectElement(document().body()->firstChild()); EXPECT_EQ(nullptr, select->previousSelectableOption(nullptr)); } { document().documentElement()->setInnerHTML("<select><option id=o1></option><option id=o2></option></select>", ASSERT_NO_EXCEPTION); document().view()->updateAllLifecyclePhases(); HTMLSelectElement* select = toHTMLSelectElement(document().body()->firstChild()); EXPECT_EQ("o2", select->previousSelectableOption(nullptr)->fastGetAttribute(HTMLNames::idAttr)); } { document().documentElement()->setInnerHTML("<select><option id=o1></option><option id=o2 disabled></option></select>", ASSERT_NO_EXCEPTION); document().view()->updateAllLifecyclePhases(); HTMLSelectElement* select = toHTMLSelectElement(document().body()->firstChild()); EXPECT_EQ("o1", select->previousSelectableOption(nullptr)->fastGetAttribute(HTMLNames::idAttr)); } { document().documentElement()->setInnerHTML("<select><option id=o1></option><option id=o2 style='display:none'></option></select>", ASSERT_NO_EXCEPTION); document().view()->updateAllLifecyclePhases(); HTMLSelectElement* select = toHTMLSelectElement(document().body()->firstChild()); EXPECT_EQ("o1", select->previousSelectableOption(nullptr)->fastGetAttribute(HTMLNames::idAttr)); } { document().documentElement()->setInnerHTML("<select><optgroup><option id=o1></option><option id=o2></option></optgroup></select>", ASSERT_NO_EXCEPTION); document().view()->updateAllLifecyclePhases(); HTMLSelectElement* select = toHTMLSelectElement(document().body()->firstChild()); EXPECT_EQ("o2", select->previousSelectableOption(nullptr)->fastGetAttribute(HTMLNames::idAttr)); } { document().documentElement()->setInnerHTML("<select><option id=o1></option><option id=o2></option></select>", ASSERT_NO_EXCEPTION); document().view()->updateAllLifecyclePhases(); HTMLSelectElement* select = toHTMLSelectElement(document().body()->firstChild()); HTMLOptionElement* option = toHTMLOptionElement(document().getElementById("o2")); EXPECT_EQ("o1", select->previousSelectableOption(option)->fastGetAttribute(HTMLNames::idAttr)); EXPECT_EQ(nullptr, select->previousSelectableOption(toHTMLOptionElement(document().getElementById("o1")))); } { document().documentElement()->setInnerHTML("<select><option id=o1></option><optgroup><option id=o2></option></optgroup></select>", ASSERT_NO_EXCEPTION); document().view()->updateAllLifecyclePhases(); HTMLSelectElement* select = toHTMLSelectElement(document().body()->firstChild()); HTMLOptionElement* option = toHTMLOptionElement(document().getElementById("o2")); EXPECT_EQ("o1", select->previousSelectableOption(option)->fastGetAttribute(HTMLNames::idAttr)); } }
void OptionListIterator::advance(HTMLOptionElement* previous) { // This function returns only // - An OPTION child of m_select, or // - An OPTION child of an OPTGROUP child of m_select. Element* current; if (previous) { DCHECK_EQ(previous->ownerSelectElement(), m_select); current = ElementTraversal::nextSkippingChildren(*previous, m_select); } else { current = ElementTraversal::firstChild(*m_select); } while (current) { if (isHTMLOptionElement(current)) { m_current = toHTMLOptionElement(current); return; } if (isHTMLOptGroupElement(current) && current->parentNode() == m_select.get()) { if ((m_current = Traversal<HTMLOptionElement>::firstChild(*current))) return; } current = ElementTraversal::nextSkippingChildren(*current, m_select); } m_current = nullptr; }
void PopupMenuImpl::update() { if (!m_popup || !m_ownerElement) return; ownerElement().document().updateLayoutTreeIfNeeded(); // disconnectClient() might have been called. if (!m_ownerElement) return; m_needsUpdate = false; RefPtr<SharedBuffer> data = SharedBuffer::create(); PagePopupClient::addString("window.updateData = {\n", data.get()); PagePopupClient::addString("type: \"update\",\n", data.get()); ItemIterationContext context(*m_ownerElement->computedStyle(), data.get()); context.serializeBaseStyle(); PagePopupClient::addString("children: [", data.get()); const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = m_ownerElement->listItems(); for (; context.m_listIndex < items.size(); ++context.m_listIndex) { Element& child = *items[context.m_listIndex]; if (!isHTMLOptGroupElement(child.parentNode())) context.finishGroupIfNecessary(); if (isHTMLOptionElement(child)) addOption(context, toHTMLOptionElement(child)); else if (isHTMLOptGroupElement(child)) addOptGroup(context, toHTMLOptGroupElement(child)); else if (isHTMLHRElement(child)) addSeparator(context, toHTMLHRElement(child)); } context.finishGroupIfNecessary(); PagePopupClient::addString("],\n", data.get()); PagePopupClient::addString("}\n", data.get()); m_popup->postMessage(String::fromUTF8(data->data(), data->size())); }
void PopupMenuImpl::update() { if (!m_popup || !m_client) return; ownerElement().document().updateLayoutTreeIfNeeded(); if (!m_client) return; m_needsUpdate = false; RefPtr<SharedBuffer> data = SharedBuffer::create(); PagePopupClient::addString("window.updateData = {\n", data.get()); PagePopupClient::addString("type: \"update\",\n", data.get()); PagePopupClient::addString("children: [", data.get()); bool enableExtraStyling = !hasTooManyItemsForStyling(); for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())) { if (isHTMLOptionElement(child)) addOption(toHTMLOptionElement(child), enableExtraStyling, data.get()); if (isHTMLOptGroupElement(child)) addOptGroup(toHTMLOptGroupElement(child), enableExtraStyling, data.get()); if (isHTMLHRElement(child)) addSeparator(toHTMLHRElement(child), enableExtraStyling, data.get()); } PagePopupClient::addString("],\n", data.get()); PagePopupClient::addString("}\n", data.get()); m_popup->postMessage(String::fromUTF8(data->data(), data->size())); }
TEST_F(HTMLSelectElementTest, RestoreUnmatchedFormControlState) { // We had a bug that selectedOption() and m_lastOnChangeOption were // mismatched in optionToBeShown(). It happened when // restoreFormControlState() couldn't find matched OPTIONs. // crbug.com/627833. document().documentElement()->setInnerHTML( "<select id='sel'>" "<option selected>Default</option>" "<option id='2'>222</option>" "</select>", ASSERT_NO_EXCEPTION); document().view()->updateAllLifecyclePhases(); Element* element = document().getElementById("sel"); HTMLFormControlElementWithState* select = toHTMLSelectElement(element); HTMLOptionElement* opt2 = toHTMLOptionElement(document().getElementById("2")); toHTMLSelectElement(element)->setSelectedIndex(1); // Save the current state. FormControlState selectState = select->saveFormControlState(); EXPECT_EQ(2U, selectState.valueSize()); // Reset the status. select->reset(); ASSERT_FALSE(opt2->selected()); element->removeChild(opt2); // Restore select->restoreFormControlState(selectState); EXPECT_EQ(-1, toHTMLSelectElement(element)->selectedIndex()); EXPECT_EQ(nullptr, toHTMLSelectElement(element)->optionToBeShown()); }
void PopupMenuImpl::update() { if (!m_popup || !m_client) return; ownerElement().document().updateLayoutTreeIfNeeded(); if (!m_client) return; m_needsUpdate = false; RefPtr<SharedBuffer> data = SharedBuffer::create(); PagePopupClient::addString("window.updateData = {\n", data.get()); PagePopupClient::addString("type: \"update\",\n", data.get()); ItemIterationContext context(*ownerElement().computedStyle(), data.get()); context.serializeBaseStyle(); PagePopupClient::addString("children: [", data.get()); for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())) { if (isHTMLOptionElement(child)) addOption(context, toHTMLOptionElement(child)); if (isHTMLOptGroupElement(child)) addOptGroup(context, toHTMLOptGroupElement(child)); if (isHTMLHRElement(child)) addSeparator(context, toHTMLHRElement(child)); } PagePopupClient::addString("],\n", data.get()); PagePopupClient::addString("}\n", data.get()); m_popup->postMessage(String::fromUTF8(data->data(), data->size())); }
void PopupMenuImpl::writeDocument(SharedBuffer* data) { IntRect anchorRectInScreen = m_chromeClient->viewportToScreen(m_client->elementRectRelativeToViewport()); PagePopupClient::addString("<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", data); data->append(Platform::current()->loadResource("pickerCommon.css")); data->append(Platform::current()->loadResource("listPicker.css")); PagePopupClient::addString("</style></head><body><div id=main>Loading...</div><script>\n" "window.dialogArguments = {\n", data); addProperty("selectedIndex", m_client->selectedIndex(), data); const ComputedStyle* ownerStyle = ownerElement().computedStyle(); ItemIterationContext context(*ownerStyle, data); context.serializeBaseStyle(); PagePopupClient::addString("children: [\n", data); for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())) { if (isHTMLOptionElement(child)) addOption(context, toHTMLOptionElement(child)); if (isHTMLOptGroupElement(child)) addOptGroup(context, toHTMLOptGroupElement(child)); if (isHTMLHRElement(child)) addSeparator(context, toHTMLHRElement(child)); } PagePopupClient::addString("],\n", data); addProperty("anchorRectInScreen", anchorRectInScreen, data); bool isRTL = !ownerStyle->isLeftToRightDirection(); addProperty("isRTL", isRTL, data); addProperty("paddingStart", isRTL ? m_client->clientPaddingRight().toDouble() : m_client->clientPaddingLeft().toDouble(), data); PagePopupClient::addString("};\n", data); data->append(Platform::current()->loadResource("pickerCommon.js")); data->append(Platform::current()->loadResource("listPicker.js")); PagePopupClient::addString("</script></body>\n", data); }
TEST_F(HTMLSelectElementTest, ActiveSelectionEndAfterOptionRemoval) { document().documentElement()->setInnerHTML("<select><optgroup><option selected>o1</option></optgroup></select>", ASSERT_NO_EXCEPTION); document().view()->updateAllLifecyclePhases(); HTMLSelectElement* select = toHTMLSelectElement(document().body()->firstChild()); HTMLOptionElement* option = toHTMLOptionElement(select->firstChild()->firstChild()); EXPECT_EQ(1, select->activeSelectionEndListIndex()); select->firstChild()->removeChild(option, ASSERT_NO_EXCEPTION); EXPECT_EQ(-1, select->activeSelectionEndListIndex()); select->appendChild(option, ASSERT_NO_EXCEPTION); EXPECT_EQ(1, select->activeSelectionEndListIndex()); }
void PopupMenuImpl::writeDocument(SharedBuffer* data) { HTMLSelectElement& ownerElement = *m_ownerElement; IntRect anchorRectInScreen = m_chromeClient->viewportToScreen( ownerElement.visibleBoundsInVisualViewport(), ownerElement.document().view()); PagePopupClient::addString( "<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", data); data->append(Platform::current()->loadResource("pickerCommon.css")); data->append(Platform::current()->loadResource("listPicker.css")); PagePopupClient::addString( "</style></head><body><div id=main>Loading...</div><script>\n" "window.dialogArguments = {\n", data); addProperty("selectedIndex", ownerElement.selectedListIndex(), data); const ComputedStyle* ownerStyle = ownerElement.computedStyle(); ItemIterationContext context(*ownerStyle, data); context.serializeBaseStyle(); PagePopupClient::addString("children: [\n", data); const HeapVector<Member<HTMLElement>>& items = ownerElement.listItems(); for (; context.m_listIndex < items.size(); ++context.m_listIndex) { Element& child = *items[context.m_listIndex]; if (!isHTMLOptGroupElement(child.parentNode())) context.finishGroupIfNecessary(); if (isHTMLOptionElement(child)) addOption(context, toHTMLOptionElement(child)); else if (isHTMLOptGroupElement(child)) addOptGroup(context, toHTMLOptGroupElement(child)); else if (isHTMLHRElement(child)) addSeparator(context, toHTMLHRElement(child)); } context.finishGroupIfNecessary(); PagePopupClient::addString("],\n", data); addProperty("anchorRectInScreen", anchorRectInScreen, data); float zoom = zoomFactor(); float scaleFactor = m_chromeClient->windowToViewportScalar(1.f); addProperty("zoomFactor", zoom / scaleFactor, data); bool isRTL = !ownerStyle->isLeftToRightDirection(); addProperty("isRTL", isRTL, data); addProperty("paddingStart", isRTL ? ownerElement.clientPaddingRight().toDouble() / zoom : ownerElement.clientPaddingLeft().toDouble() / zoom, data); PagePopupClient::addString("};\n", data); data->append(Platform::current()->loadResource("pickerCommon.js")); data->append(Platform::current()->loadResource("listPicker.js")); PagePopupClient::addString("</script></body>\n", data); }
JSValue JSHTMLOptionsCollection::add(ExecState* exec) { HTMLOptionsCollection* imp = static_cast<HTMLOptionsCollection*>(impl()); HTMLOptionElement* option = toHTMLOptionElement(exec->argument(0)); ExceptionCode ec = 0; if (exec->argumentCount() < 2) imp->add(option, ec); else { int index = exec->argument(1).toInt32(exec); if (exec->hadException()) return jsUndefined(); imp->add(option, index, ec); } setDOMException(exec, ec); return jsUndefined(); }
void PopupMenuImpl::update() { if (!m_popup || !m_ownerElement) return; ownerElement().document().updateStyleAndLayoutTree(); // disconnectClient() might have been called. if (!m_ownerElement) return; m_needsUpdate = false; if (!ownerElement() .document() .frame() ->view() ->visibleContentRect() .intersects(ownerElement().pixelSnappedBoundingBox())) { hide(); return; } RefPtr<SharedBuffer> data = SharedBuffer::create(); PagePopupClient::addString("window.updateData = {\n", data.get()); PagePopupClient::addString("type: \"update\",\n", data.get()); ItemIterationContext context(*m_ownerElement->computedStyle(), data.get()); context.serializeBaseStyle(); PagePopupClient::addString("children: [", data.get()); const HeapVector<Member<HTMLElement>>& items = m_ownerElement->listItems(); for (; context.m_listIndex < items.size(); ++context.m_listIndex) { Element& child = *items[context.m_listIndex]; if (!isHTMLOptGroupElement(child.parentNode())) context.finishGroupIfNecessary(); if (isHTMLOptionElement(child)) addOption(context, toHTMLOptionElement(child)); else if (isHTMLOptGroupElement(child)) addOptGroup(context, toHTMLOptGroupElement(child)); else if (isHTMLHRElement(child)) addSeparator(context, toHTMLHRElement(child)); } context.finishGroupIfNecessary(); PagePopupClient::addString("],\n", data.get()); IntRect anchorRectInScreen = m_chromeClient->viewportToScreen( m_ownerElement->visibleBoundsInVisualViewport(), ownerElement().document().view()); addProperty("anchorRectInScreen", anchorRectInScreen, data.get()); PagePopupClient::addString("}\n", data.get()); m_popup->postMessage(String::fromUTF8(data->data(), data->size())); }
void BaseMultipleFieldsDateAndTimeInputType::updatePickerIndicatorVisibility() { if (m_pickerIndicatorIsAlwaysVisible) { showPickerIndicator(); return; } #if ENABLE(DATALIST_ELEMENT) if (HTMLDataListElement* dataList = element()->dataList()) { RefPtr<HTMLCollection> options = dataList->options(); for (unsigned i = 0; HTMLOptionElement* option = toHTMLOptionElement(options->item(i)); ++i) { if (element()->isValidValue(option->value())) { showPickerIndicator(); return; } } } hidePickerIndicator(); #endif }
JSValue JSHTMLOptionsCollection::add(ExecState* exec) { HTMLOptionsCollection* imp = static_cast<HTMLOptionsCollection*>(impl()); HTMLOptionElement* option = toHTMLOptionElement(exec->argument(0)); ExceptionCode ec = 0; if (exec->argumentCount() < 2) imp->add(option, ec); else { bool ok; int index = finiteInt32Value(exec->argument(1), exec, ok); if (exec->hadException()) return jsUndefined(); if (!ok) ec = TYPE_MISMATCH_ERR; else imp->add(option, index, ec); } setDOMException(exec, ec); return jsUndefined(); }
JSValue JSHTMLOptionsCollection::add(ExecState* exec, const ArgList& args) { HTMLOptionsCollection* imp = static_cast<HTMLOptionsCollection*>(impl()); HTMLOptionElement* option = toHTMLOptionElement(args.at(0)); ExceptionCode ec = 0; if (args.size() < 2) imp->add(option, ec); else { bool ok; int index = args.at(1).toInt32(exec, ok); if (exec->hadException()) return jsUndefined(); if (!ok) ec = TYPE_MISMATCH_ERR; else imp->add(option, index, ec); } setDOMException(exec, ec); return jsUndefined(); }
void PopupMenuImpl::writeDocument(SharedBuffer* data) { IntRect anchorRectInScreen = m_chromeClient->viewportToScreen(m_client->elementRectRelativeToViewport()); PagePopupClient::addString("<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", data); data->append(Platform::current()->loadResource("pickerCommon.css")); data->append(Platform::current()->loadResource("listPicker.css")); PagePopupClient::addString("</style></head><body><div id=main>Loading...</div><script>\n" "window.dialogArguments = {\n", data); addProperty("selectedIndex", m_client->selectedIndex(), data); PagePopupClient::addString("children: [\n", data); bool enableExtraStyling = !hasTooManyItemsForStyling(); for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())) { if (isHTMLOptionElement(child)) addOption(toHTMLOptionElement(child), enableExtraStyling, data); if (isHTMLOptGroupElement(child)) addOptGroup(toHTMLOptGroupElement(child), enableExtraStyling, data); if (isHTMLHRElement(child)) addSeparator(toHTMLHRElement(child), enableExtraStyling, data); } PagePopupClient::addString("],\n", data); addProperty("anchorRectInScreen", anchorRectInScreen, data); const ComputedStyle* ownerStyle = ownerElement().computedStyle(); Color backgroundColor = ownerStyle->visitedDependentColor(CSSPropertyBackgroundColor); #if OS(LINUX) // On other platforms, the <option> background color is the same as the // <select> background color. On Linux, that makes the <option> // background color very dark, so by default, try to use a lighter // background color for <option>s. if (LayoutTheme::theme().systemColor(CSSValueButtonface) == backgroundColor) backgroundColor = LayoutTheme::theme().systemColor(CSSValueMenu); #endif addProperty("backgroundColor", backgroundColor.serialized(), data); bool isRTL = !ownerStyle->isLeftToRightDirection(); addProperty("isRTL", isRTL, data); addProperty("paddingStart", isRTL ? m_client->clientPaddingRight().toDouble() : m_client->clientPaddingLeft().toDouble(), data); PagePopupClient::addString("};\n", data); data->append(Platform::current()->loadResource("pickerCommon.js")); data->append(Platform::current()->loadResource("listPicker.js")); PagePopupClient::addString("</script></body>\n", data); }
void PopupMenuImpl::addOptGroup(HTMLOptGroupElement& element, bool enableExtraStyling, SharedBuffer* data) { PagePopupClient::addString("{\n", data); PagePopupClient::addString("type: \"optgroup\",\n", data); addProperty("label", element.groupLabelText(), data); addProperty("title", element.title(), data); addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr), data); addProperty("disabled", element.isDisabledFormControl(), data); addElementStyle(element, enableExtraStyling, data); PagePopupClient::addString("children: [", data); for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(element)) { if (isHTMLOptionElement(child)) addOption(toHTMLOptionElement(child), enableExtraStyling, data); if (isHTMLOptGroupElement(child)) addOptGroup(toHTMLOptGroupElement(child), enableExtraStyling, data); if (isHTMLHRElement(child)) addSeparator(toHTMLHRElement(child), enableExtraStyling, data); } PagePopupClient::addString("],\n", data); PagePopupClient::addString("},\n", data); }
void ExternalPopupMenu::getPopupMenuInfo(WebPopupMenuInfo& info, HTMLSelectElement& ownerElement) { const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = ownerElement.listItems(); size_t itemCount = listItems.size(); size_t count = 0; Vector<WebMenuItemInfo> items(itemCount); for (size_t i = 0; i < itemCount; ++i) { if (ownerElement.itemIsDisplayNone(*listItems[i])) continue; Element& itemElement = *listItems[i]; WebMenuItemInfo& popupItem = items[count++]; popupItem.label = ownerElement.itemText(itemElement); popupItem.toolTip = itemElement.title(); popupItem.checked = false; if (isHTMLHRElement(itemElement)) { popupItem.type = WebMenuItemInfo::Separator; } else if (isHTMLOptGroupElement(itemElement)) { popupItem.type = WebMenuItemInfo::Group; } else { popupItem.type = WebMenuItemInfo::Option; popupItem.checked = toHTMLOptionElement(itemElement).selected(); } popupItem.enabled = !itemElement.isDisabledFormControl(); const ComputedStyle& style = *ownerElement.itemComputedStyle(itemElement); popupItem.textDirection = toWebTextDirection(style.direction()); popupItem.hasTextDirectionOverride = isOverride(style.unicodeBidi()); } const ComputedStyle& menuStyle = ownerElement.computedStyle() ? *ownerElement.computedStyle() : *ownerElement.ensureComputedStyle(); info.itemHeight = menuStyle.font().fontMetrics().height(); info.itemFontSize = static_cast<int>(menuStyle.font().fontDescription().computedSize()); info.selectedIndex = toExternalPopupMenuItemIndex(ownerElement.optionToListIndex(ownerElement.selectedIndex()), ownerElement); info.rightAligned = menuStyle.direction() == RTL; info.allowMultipleSelection = ownerElement.multiple(); if (count < itemCount) items.shrink(count); info.items = items; }
void RangeInputType::updateTickMarkValues() { if (!m_tickMarkValuesDirty) return; m_tickMarkValues.clear(); m_tickMarkValuesDirty = false; HTMLDataListElement* dataList = element().dataList(); if (!dataList) return; RefPtr<HTMLCollection> options = dataList->options(); m_tickMarkValues.reserveCapacity(options->length()); for (unsigned i = 0; i < options->length(); ++i) { Element* element = options->item(i); HTMLOptionElement* optionElement = toHTMLOptionElement(element); String optionValue = optionElement->value(); if (!this->element().isValidValue(optionValue)) continue; m_tickMarkValues.append(parseToNumber(optionValue, Decimal::nan())); } m_tickMarkValues.shrinkToFit(); nonCopyingSort(m_tickMarkValues.begin(), m_tickMarkValues.end(), decimalCompare); }
void HTMLOptionsCollection::add(PassRefPtr<HTMLOptionElement> element, int index, ExceptionState& exceptionState) { HTMLOptionElement* newOption = element.get(); if (!newOption) { exceptionState.throwTypeError("The element provided was not an HTMLOptionElement."); return; } if (index < -1) { exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is less than -1."); return; } HTMLSelectElement* select = toHTMLSelectElement(ownerNode()); if (index == -1 || unsigned(index) >= length()) select->add(newOption, 0, exceptionState); else select->add(newOption, toHTMLOptionElement(item(index)), exceptionState); ASSERT(!exceptionState.hadException()); }
void HTMLOptionsCollection::add(PassRefPtr<HTMLOptionElement> element, int index, ExceptionCode& ec) { HTMLOptionElement* newOption = element.get(); if (!newOption) { ec = TYPE_MISMATCH_ERR; return; } if (index < -1) { ec = INDEX_SIZE_ERR; return; } ec = 0; HTMLSelectElement* select = toHTMLSelectElement(ownerNode()); if (index == -1 || unsigned(index) >= length()) select->add(newOption, 0, ec); else select->add(newOption, toHTMLOptionElement(item(index)), ec); ASSERT(!ec); }
void PopupMenuImpl::addOptGroup(ItemIterationContext& context, HTMLOptGroupElement& element) { SharedBuffer* data = context.m_buffer; ++context.m_listIndex; PagePopupClient::addString("{\n", data); PagePopupClient::addString("type: \"optgroup\",\n", data); addProperty("label", element.groupLabelText(), data); addProperty("title", element.title(), data); addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr), data); addProperty("disabled", element.isDisabledFormControl(), data); addElementStyle(context, element); PagePopupClient::addString("children: [", data); for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(element)) { if (isHTMLOptionElement(child)) addOption(context, toHTMLOptionElement(child)); // TODO(tkent): Ignore nested OPTGROUP. crbug.com/502101. if (isHTMLOptGroupElement(child)) addOptGroup(context, toHTMLOptGroupElement(child)); if (isHTMLHRElement(child)) addSeparator(context, toHTMLHRElement(child)); } PagePopupClient::addString("],\n", data); PagePopupClient::addString("},\n", data); }
void RenderTheme::paintSliderTicks(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect) { Node* node = o->node(); if (!node) return; HTMLInputElement* input = node->toInputElement(); if (!input) return; HTMLDataListElement* dataList = static_cast<HTMLDataListElement*>(input->list()); if (!dataList) return; double min = input->minimum(); double max = input->maximum(); ControlPart part = o->style()->appearance(); // We don't support ticks on alternate sliders like MediaVolumeSliders. if (part != SliderHorizontalPart && part != SliderVerticalPart) return; bool isHorizontal = part == SliderHorizontalPart; IntSize thumbSize; RenderObject* thumbRenderer = input->sliderThumbElement()->renderer(); if (thumbRenderer) { RenderStyle* thumbStyle = thumbRenderer->style(); int thumbWidth = thumbStyle->width().intValue(); int thumbHeight = thumbStyle->height().intValue(); thumbSize.setWidth(isHorizontal ? thumbWidth : thumbHeight); thumbSize.setHeight(isHorizontal ? thumbHeight : thumbWidth); } IntSize tickSize = sliderTickSize(); float zoomFactor = o->style()->effectiveZoom(); FloatRect tickRect; int tickRegionSideMargin = 0; int tickRegionWidth = 0; IntRect trackBounds; RenderObject* trackRenderer = input->sliderTrackElement()->renderer(); // We can ignoring transforms because transform is handled by the graphics context. if (trackRenderer) trackBounds = trackRenderer->absoluteBoundingBoxRectIgnoringTransforms(); IntRect sliderBounds = o->absoluteBoundingBoxRectIgnoringTransforms(); // Make position relative to the transformed ancestor element. trackBounds.setX(trackBounds.x() - sliderBounds.x() + rect.x()); trackBounds.setY(trackBounds.y() - sliderBounds.y() + rect.y()); if (isHorizontal) { tickRect.setWidth(floor(tickSize.width() * zoomFactor)); tickRect.setHeight(floor(tickSize.height() * zoomFactor)); tickRect.setY(floor(rect.y() + rect.height() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor)); tickRegionSideMargin = trackBounds.x() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0; tickRegionWidth = trackBounds.width() - thumbSize.width(); } else { tickRect.setWidth(floor(tickSize.height() * zoomFactor)); tickRect.setHeight(floor(tickSize.width() * zoomFactor)); tickRect.setX(floor(rect.x() + rect.width() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor)); tickRegionSideMargin = trackBounds.y() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0; tickRegionWidth = trackBounds.height() - thumbSize.width(); } RefPtr<HTMLCollection> options = dataList->options(); GraphicsContextStateSaver stateSaver(*paintInfo.context); paintInfo.context->setFillColor(o->style()->visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB); for (unsigned i = 0; Node* node = options->item(i); i++) { ASSERT(node->hasTagName(optionTag)); HTMLOptionElement* optionElement = toHTMLOptionElement(node); String value = optionElement->value(); if (!input->isValidValue(value)) continue; double parsedValue = parseToDoubleForNumberType(input->sanitizeValue(value)); double tickFraction = (parsedValue - min) / (max - min); double tickRatio = isHorizontal && o->style()->isLeftToRightDirection() ? tickFraction : 1.0 - tickFraction; double tickPosition = round(tickRegionSideMargin + tickRegionWidth * tickRatio); if (isHorizontal) tickRect.setX(tickPosition); else tickRect.setY(tickPosition); paintInfo.context->fillRect(tickRect); } }
WebOptionElement::operator PassRefPtr<HTMLOptionElement>() const { return toHTMLOptionElement(m_private.get()); }