1/*
2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
3 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
4 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
5 *           (C) 2000 Dirk Mueller (mueller@kde.org)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved.
7 * Copyright (C) 2010 Google Inc. All rights reserved.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB.  If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 *
24 */
25
26#ifndef HTMLSelectElement_h
27#define HTMLSelectElement_h
28
29#include "core/events/Event.h"
30#include "core/html/HTMLFormControlElementWithState.h"
31#include "core/html/HTMLOptionsCollection.h"
32#include "core/html/forms/TypeAhead.h"
33#include "wtf/Vector.h"
34
35namespace WebCore {
36
37class ExceptionState;
38class HTMLOptionElement;
39
40class HTMLSelectElement FINAL : public HTMLFormControlElementWithState, public TypeAheadDataSource {
41public:
42    static PassRefPtr<HTMLSelectElement> create(Document&);
43    static PassRefPtr<HTMLSelectElement> create(Document&, HTMLFormElement*, bool createdByParser);
44
45    int selectedIndex() const;
46    void setSelectedIndex(int);
47
48    void optionSelectedByUser(int index, bool dispatchChangeEvent, bool allowMultipleSelection = false);
49
50    // For ValidityState
51    virtual String validationMessage() const OVERRIDE;
52    virtual bool valueMissing() const OVERRIDE;
53
54    virtual void resetImpl() OVERRIDE;
55
56    unsigned length() const;
57
58    int size() const { return m_size; }
59    bool multiple() const { return m_multiple; }
60
61    bool usesMenuList() const;
62
63    void add(HTMLElement*, HTMLElement* beforeElement, ExceptionState&);
64
65    using Node::remove;
66    void remove(int index);
67    void remove(HTMLOptionElement*);
68
69    String value() const;
70    void setValue(const String&);
71
72    PassRefPtr<HTMLOptionsCollection> options();
73    PassRefPtr<HTMLCollection> selectedOptions();
74
75    void optionElementChildrenChanged();
76
77    void setRecalcListItems();
78    void invalidateSelectedItems();
79    void updateListItemSelectedStates();
80
81    const Vector<HTMLElement*>& listItems() const;
82
83    virtual void accessKeyAction(bool sendMouseEvents);
84    void accessKeySetSelectedIndex(int);
85
86    void setMultiple(bool);
87
88    void setSize(int);
89
90    void setOption(unsigned index, HTMLOptionElement*, ExceptionState&);
91    void setLength(unsigned, ExceptionState&);
92
93    Node* namedItem(const AtomicString& name);
94    Node* item(unsigned index);
95
96    void scrollToSelection();
97
98    void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true);
99
100    bool canSelectAll() const;
101    void selectAll();
102    int listToOptionIndex(int listIndex) const;
103    void listBoxOnChange();
104    int optionToListIndex(int optionIndex) const;
105    int activeSelectionStartListIndex() const;
106    int activeSelectionEndListIndex() const;
107    void setActiveSelectionAnchorIndex(int);
108    void setActiveSelectionEndIndex(int);
109    void updateListBoxSelection(bool deselectOtherOptions);
110
111    // For use in the implementation of HTMLOptionElement.
112    void optionSelectionStateChanged(HTMLOptionElement*, bool optionIsSelected);
113    bool isParsingInProgress() const { return m_isParsingInProgress; }
114    bool anonymousIndexedSetter(unsigned, PassRefPtr<HTMLOptionElement>, ExceptionState&);
115    bool anonymousIndexedSetterRemove(unsigned, ExceptionState&);
116
117protected:
118    HTMLSelectElement(Document&, HTMLFormElement*, bool createdByParser);
119
120private:
121    virtual const AtomicString& formControlType() const;
122
123    virtual bool shouldShowFocusRingOnMouseFocus() const OVERRIDE;
124
125    virtual void dispatchFocusEvent(Element* oldFocusedElement, FocusDirection) OVERRIDE;
126    virtual void dispatchBlurEvent(Element* newFocusedElemnet) OVERRIDE;
127
128    virtual bool canStartSelection() const { return false; }
129
130    virtual bool isEnumeratable() const { return true; }
131    virtual bool isInteractiveContent() const OVERRIDE;
132    virtual bool supportLabels() const OVERRIDE { return true; }
133
134    virtual FormControlState saveFormControlState() const OVERRIDE;
135    virtual void restoreFormControlState(const FormControlState&) OVERRIDE;
136
137    virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
138    virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE;
139
140    virtual bool childShouldCreateRenderer(const Node& child) const OVERRIDE;
141    virtual RenderObject* createRenderer(RenderStyle *);
142    virtual bool appendFormData(FormDataList&, bool);
143
144    virtual void defaultEventHandler(Event*);
145
146    void dispatchChangeEventForMenuList();
147
148    void recalcListItems(bool updateSelectedStates = true) const;
149
150    void deselectItems(HTMLOptionElement* excludeElement = 0);
151    void typeAheadFind(KeyboardEvent*);
152    void saveLastSelection();
153
154    virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
155
156    virtual bool isOptionalFormControl() const { return !isRequiredFormControl(); }
157    virtual bool isRequiredFormControl() const;
158
159    bool hasPlaceholderLabelOption() const;
160
161    enum SelectOptionFlag {
162        DeselectOtherOptions = 1 << 0,
163        DispatchChangeEvent = 1 << 1,
164        UserDriven = 1 << 2,
165    };
166    typedef unsigned SelectOptionFlags;
167    void selectOption(int optionIndex, SelectOptionFlags = 0);
168    void deselectItemsWithoutValidation(HTMLElement* elementToExclude = 0);
169    void parseMultipleAttribute(const AtomicString&);
170    int lastSelectedListIndex() const;
171    void updateSelectedState(int listIndex, bool multi, bool shift);
172    void menuListDefaultEventHandler(Event*);
173    bool platformHandleKeydownEvent(KeyboardEvent*);
174    void listBoxDefaultEventHandler(Event*);
175    void setOptionsChangedOnRenderer();
176    size_t searchOptionsForValue(const String&, size_t listIndexStart, size_t listIndexEnd) const;
177
178    enum SkipDirection {
179        SkipBackwards = -1,
180        SkipForwards = 1
181    };
182    int nextValidIndex(int listIndex, SkipDirection, int skip) const;
183    int nextSelectableListIndex(int startIndex) const;
184    int previousSelectableListIndex(int startIndex) const;
185    int firstSelectableListIndex() const;
186    int lastSelectableListIndex() const;
187    int nextSelectableListIndexPageAway(int startIndex, SkipDirection) const;
188
189    virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
190    virtual bool areAuthorShadowsAllowed() const OVERRIDE { return false; }
191    virtual void finishParsingChildren() OVERRIDE;
192
193    // TypeAheadDataSource functions.
194    virtual int indexOfSelectedOption() const OVERRIDE;
195    virtual int optionCount() const OVERRIDE;
196    virtual String optionAtIndex(int index) const OVERRIDE;
197
198    // m_listItems contains HTMLOptionElement, HTMLOptGroupElement, and HTMLHRElement objects.
199    mutable Vector<HTMLElement*> m_listItems;
200    Vector<bool> m_lastOnChangeSelection;
201    Vector<bool> m_cachedStateForActiveSelection;
202    TypeAhead m_typeAhead;
203    int m_size;
204    int m_lastOnChangeIndex;
205    int m_activeSelectionAnchorIndex;
206    int m_activeSelectionEndIndex;
207    bool m_isProcessingUserDrivenChange;
208    bool m_multiple;
209    bool m_activeSelectionState;
210    mutable bool m_shouldRecalcListItems;
211    bool m_isParsingInProgress;
212};
213
214DEFINE_NODE_TYPE_CASTS(HTMLSelectElement, hasTagName(HTMLNames::selectTag));
215
216} // namespace
217
218#endif
219