示例#1
0
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));
    }
}
示例#3
0
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;
}
示例#4
0
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()));
}
示例#5
0
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()));
}
示例#6
0
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());
}
示例#10
0
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();
}
示例#12
0
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()));
}
示例#13
0
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();
}
示例#16
0
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);
}
示例#17
0
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;

}
示例#19
0
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);
}
示例#20
0
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());
}
示例#21
0
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);
}
示例#23
0
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);
    }
}
示例#24
0
WebOptionElement::operator PassRefPtr<HTMLOptionElement>() const
{
    return toHTMLOptionElement(m_private.get());
}