⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 htmlselectelement.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) *           (C) 1999 Antti Koivisto (koivisto@kde.org) *           (C) 2001 Dirk Mueller (mueller@kde.org) * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. *           (C) 2006 Alexey Proskuryakov (ap@nypop.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB.  If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "config.h"#include "HTMLSelectElement.h"#include "AXObjectCache.h"#include "CSSPropertyNames.h"#include "CSSStyleSelector.h"#include "CharacterNames.h"#include "ChromeClient.h"#include "Document.h"#include "Event.h"#include "EventHandler.h"#include "EventNames.h"#include "FormDataList.h"#include "Frame.h"#include "FrameLoader.h"#include "FrameLoaderClient.h"#include "HTMLFormElement.h"#include "HTMLNames.h"#include "HTMLOptionElement.h"#include "HTMLOptionsCollection.h"#include "KeyboardEvent.h"#include "MouseEvent.h"#include "Page.h"#include "RenderListBox.h"#include "RenderMenuList.h"#include <math.h>#include <wtf/StdLibExtras.h>#include <wtf/Vector.h>#if PLATFORM(MAC)#define ARROW_KEYS_POP_MENU 1#else#define ARROW_KEYS_POP_MENU 0#endifusing namespace std;using namespace WTF;using namespace Unicode;namespace WebCore {using namespace HTMLNames;static const DOMTimeStamp typeAheadTimeout = 1000;HTMLSelectElement::HTMLSelectElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)    : HTMLFormControlElementWithState(tagName, doc, f)    , m_minwidth(0)    , m_size(0)    , m_multiple(false)    , m_recalcListItems(false)    , m_lastOnChangeIndex(-1)    , m_activeSelectionAnchorIndex(-1)    , m_activeSelectionEndIndex(-1)    , m_activeSelectionState(false)    , m_repeatingChar(0)    , m_lastCharTime(0){    ASSERT(hasTagName(selectTag) || hasTagName(keygenTag));}bool HTMLSelectElement::checkDTD(const Node* newChild){    // Make sure to keep <optgroup> in sync with this.    return newChild->isTextNode() || newChild->hasTagName(optionTag) || newChild->hasTagName(optgroupTag) || newChild->hasTagName(hrTag) ||           newChild->hasTagName(scriptTag);}void HTMLSelectElement::recalcStyle( StyleChange ch ){    if (hasChangedChild() && renderer()) {        if (usesMenuList())            static_cast<RenderMenuList*>(renderer())->setOptionsChanged(true);        else            static_cast<RenderListBox*>(renderer())->setOptionsChanged(true);    } else if (m_recalcListItems)        recalcListItems();    HTMLFormControlElementWithState::recalcStyle(ch);}const AtomicString& HTMLSelectElement::type() const{    DEFINE_STATIC_LOCAL(const AtomicString, selectMultiple, ("select-multiple"));    DEFINE_STATIC_LOCAL(const AtomicString, selectOne, ("select-one"));    return m_multiple ? selectMultiple : selectOne;}int HTMLSelectElement::selectedIndex() const{    // return the number of the first option selected    unsigned index = 0;    const Vector<HTMLElement*>& items = listItems();    for (unsigned int i = 0; i < items.size(); i++) {        if (items[i]->hasLocalName(optionTag)) {            if (static_cast<HTMLOptionElement*>(items[i])->selected())                return index;            index++;        }    }    return -1;}int HTMLSelectElement::lastSelectedListIndex() const{    // return the number of the last option selected    unsigned index = 0;    bool found = false;    const Vector<HTMLElement*>& items = listItems();    for (unsigned int i = 0; i < items.size(); i++) {        if (items[i]->hasLocalName(optionTag)) {            if (static_cast<HTMLOptionElement*>(items[i])->selected()) {                index = i;                found = true;            }        }    }    return found ? (int) index : -1;}void HTMLSelectElement::deselectItems(HTMLOptionElement* excludeElement){    const Vector<HTMLElement*>& items = listItems();    unsigned i;    for (i = 0; i < items.size(); i++) {        if (items[i]->hasLocalName(optionTag) && (items[i] != excludeElement)) {            HTMLOptionElement* element = static_cast<HTMLOptionElement*>(items[i]);            element->setSelectedState(false);        }    }}void HTMLSelectElement::setSelectedIndex(int optionIndex, bool deselect, bool fireOnChange){    const Vector<HTMLElement*>& items = listItems();    int listIndex = optionToListIndex(optionIndex);    HTMLOptionElement* element = 0;    if (!multiple())        deselect = true;    if (listIndex >= 0) {        if (m_activeSelectionAnchorIndex < 0 || deselect)            setActiveSelectionAnchorIndex(listIndex);        if (m_activeSelectionEndIndex < 0 || deselect)            setActiveSelectionEndIndex(listIndex);        element = static_cast<HTMLOptionElement*>(items[listIndex]);        element->setSelectedState(true);    }    if (deselect)        deselectItems(element);    scrollToSelection();    // This only gets called with fireOnChange for menu lists.     if (fireOnChange && usesMenuList())        menuListOnChange();    Frame* frame = document()->frame();    if (frame)        frame->page()->chrome()->client()->formStateDidChange(this);}int HTMLSelectElement::activeSelectionStartListIndex() const{    if (m_activeSelectionAnchorIndex >= 0)        return m_activeSelectionAnchorIndex;    return optionToListIndex(selectedIndex());}int HTMLSelectElement::activeSelectionEndListIndex() const{    if (m_activeSelectionEndIndex >= 0)        return m_activeSelectionEndIndex;    return lastSelectedListIndex();}unsigned HTMLSelectElement::length() const{    unsigned len = 0;    const Vector<HTMLElement*>& items = listItems();    for (unsigned i = 0; i < items.size(); ++i) {        if (items[i]->hasLocalName(optionTag))            ++len;    }    return len;}void HTMLSelectElement::add(HTMLElement *element, HTMLElement *before, ExceptionCode& ec){    RefPtr<HTMLElement> protectNewChild(element); // make sure the element is ref'd and deref'd so we don't leak it    if (!element || !(element->hasLocalName(optionTag) || element->hasLocalName(hrTag)))        return;    ec = 0;    insertBefore(element, before, ec);    if (!ec)        setRecalcListItems();}void HTMLSelectElement::remove(int index){    ExceptionCode ec = 0;    int listIndex = optionToListIndex(index);    const Vector<HTMLElement*>& items = listItems();    if (listIndex < 0 || index >= int(items.size()))        return; // ### what should we do ? remove the last item?    Element *item = items[listIndex];    ASSERT(item->parentNode());    item->parentNode()->removeChild(item, ec);    if (!ec)        setRecalcListItems();}String HTMLSelectElement::value(){    unsigned i;    const Vector<HTMLElement*>& items = listItems();    for (i = 0; i < items.size(); i++) {        if (items[i]->hasLocalName(optionTag) && static_cast<HTMLOptionElement*>(items[i])->selected())            return static_cast<HTMLOptionElement*>(items[i])->value();    }    return String("");}void HTMLSelectElement::setValue(const String &value){    if (value.isNull())        return;    // find the option with value() matching the given parameter    // and make it the current selection.    const Vector<HTMLElement*>& items = listItems();    unsigned optionIndex = 0;    for (unsigned i = 0; i < items.size(); i++)        if (items[i]->hasLocalName(optionTag)) {            if (static_cast<HTMLOptionElement*>(items[i])->value() == value) {                setSelectedIndex(optionIndex, true);                return;            }            optionIndex++;        }}bool HTMLSelectElement::saveState(String& value) const{    const Vector<HTMLElement*>& items = listItems();    int l = items.size();    Vector<char, 1024> characters(l);    for (int i = 0; i < l; ++i) {        HTMLElement* e = items[i];        bool selected = e->hasLocalName(optionTag) && static_cast<HTMLOptionElement*>(e)->selected();        characters[i] = selected ? 'X' : '.';    }    value = String(characters.data(), l);    return true;}void HTMLSelectElement::restoreState(const String& state){    recalcListItems();        const Vector<HTMLElement*>& items = listItems();    int l = items.size();    for (int i = 0; i < l; i++)        if (items[i]->hasLocalName(optionTag))            static_cast<HTMLOptionElement*>(items[i])->setSelectedState(state[i] == 'X');                setChanged();}bool HTMLSelectElement::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach){    bool result = HTMLFormControlElementWithState::insertBefore(newChild, refChild, ec, shouldLazyAttach);    if (result)        setRecalcListItems();    return result;}bool HTMLSelectElement::replaceChild(PassRefPtr<Node> newChild, Node *oldChild, ExceptionCode& ec, bool shouldLazyAttach){    bool result = HTMLFormControlElementWithState::replaceChild(newChild, oldChild, ec, shouldLazyAttach);    if (result)        setRecalcListItems();    return result;}bool HTMLSelectElement::removeChild(Node* oldChild, ExceptionCode& ec){    bool result = HTMLFormControlElementWithState::removeChild(oldChild, ec);    if (result)        setRecalcListItems();    return result;}bool HTMLSelectElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach){    bool result = HTMLFormControlElementWithState::appendChild(newChild, ec, shouldLazyAttach);    if (result)        setRecalcListItems();    return result;}bool HTMLSelectElement::removeChildren(){    bool result = HTMLFormControlElementWithState::removeChildren();    if (result)        setRecalcListItems();    return result;}void HTMLSelectElement::parseMappedAttribute(MappedAttribute *attr){    bool oldUsesMenuList = usesMenuList();    if (attr->name() == sizeAttr) {        int oldSize = m_size;        // Set the attribute value to a number.        // This is important since the style rules for this attribute can determine the appearance property.        int size = attr->value().toInt();        String attrSize = String::number(size);        if (attrSize != attr->value())            attr->setValue(attrSize);        m_size = max(size, 1);        if ((oldUsesMenuList != usesMenuList() || !oldUsesMenuList && m_size != oldSize) && attached()) {            detach();            attach();            setRecalcListItems();        }    } else if (attr->name() == widthAttr) {        m_minwidth = max(attr->value().toInt(), 0);    } else if (attr->name() == multipleAttr) {        m_multiple = (!attr->isNull());        if (oldUsesMenuList != usesMenuList() && attached()) {            detach();            attach();        }    } else if (attr->name() == accesskeyAttr) {        // FIXME: ignore for the moment    } else if (attr->name() == alignAttr) {        // Don't map 'align' attribute.  This matches what Firefox, Opera and IE do.        // See http://bugs.webkit.org/show_bug.cgi?id=12072    } else if (attr->name() == onfocusAttr) {        setInlineEventListenerForTypeAndAttribute(eventNames().focusEvent, attr);    } else if (attr->name() == onblurAttr) {        setInlineEventListenerForTypeAndAttribute(eventNames().blurEvent, attr);    } else if (attr->name() == onchangeAttr) {        setInlineEventListenerForTypeAndAttribute(eventNames().changeEvent, attr);    } else        HTMLFormControlElementWithState::parseMappedAttribute(attr);}bool HTMLSelectElement::isKeyboardFocusable(KeyboardEvent* event) const

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -