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 "Event.h"
30#include "HTMLFormControlElementWithState.h"
31#include "TypeAhead.h"
32#include <wtf/Vector.h>
33
34namespace WebCore {
35
36class HTMLOptionElement;
37class HTMLOptionsCollection;
38
39class HTMLSelectElement : public HTMLFormControlElementWithState, public TypeAheadDataSource {
40public:
41    static PassRefPtr<HTMLSelectElement> create(const QualifiedName&, Document&, HTMLFormElement*);
42
43    int selectedIndex() const;
44    void setSelectedIndex(int);
45
46    void optionSelectedByUser(int index, bool dispatchChangeEvent, bool allowMultipleSelection = false);
47
48    // For ValidityState
49    virtual String validationMessage() const override;
50    virtual bool valueMissing() const override;
51
52    unsigned length() const;
53
54    int size() const { return m_size; }
55    bool multiple() const { return m_multiple; }
56
57    bool usesMenuList() const;
58
59    void add(HTMLElement*, HTMLElement* beforeElement, ExceptionCode&);
60
61    using Node::remove;
62    // Should be remove(int) but it conflicts with Node::remove(ExceptionCode&).
63    void removeByIndex(int);
64    void remove(HTMLOptionElement*);
65
66    String value() const;
67    void setValue(const String&);
68
69    PassRefPtr<HTMLOptionsCollection> options();
70    PassRefPtr<HTMLCollection> selectedOptions();
71
72    void optionElementChildrenChanged();
73
74    void setRecalcListItems();
75    void invalidateSelectedItems();
76    void updateListItemSelectedStates();
77
78    const Vector<HTMLElement*>& listItems() const;
79
80    virtual void accessKeyAction(bool sendMouseEvents) override;
81    void accessKeySetSelectedIndex(int);
82
83    void setMultiple(bool);
84
85    void setSize(int);
86
87    void setOption(unsigned index, HTMLOptionElement*, ExceptionCode&);
88    void setLength(unsigned, ExceptionCode&);
89
90    Node* namedItem(const AtomicString& name);
91    Node* item(unsigned index);
92
93    void scrollToSelection();
94
95    void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true);
96
97#if PLATFORM(IOS)
98    virtual bool willRespondToMouseClickEvents() override;
99#endif
100
101    bool canSelectAll() const;
102    void selectAll();
103    int listToOptionIndex(int listIndex) const;
104    void listBoxOnChange();
105    int optionToListIndex(int optionIndex) const;
106    int activeSelectionStartListIndex() const;
107    int activeSelectionEndListIndex() const;
108    void setActiveSelectionAnchorIndex(int);
109    void setActiveSelectionEndIndex(int);
110    void updateListBoxSelection(bool deselectOtherOptions);
111
112    // For use in the implementation of HTMLOptionElement.
113    void optionSelectionStateChanged(HTMLOptionElement*, bool optionIsSelected);
114    bool allowsNonContiguousSelection() const { return m_allowsNonContiguousSelection; };
115
116protected:
117    HTMLSelectElement(const QualifiedName&, Document&, HTMLFormElement*);
118
119private:
120    virtual const AtomicString& formControlType() const override;
121
122    virtual bool isKeyboardFocusable(KeyboardEvent*) const override;
123    virtual bool isMouseFocusable() const override;
124
125    virtual void dispatchFocusEvent(PassRefPtr<Element> oldFocusedElement, FocusDirection) override final;
126    virtual void dispatchBlurEvent(PassRefPtr<Element> newFocusedElement) override final;
127
128    virtual bool canStartSelection() const override { return false; }
129
130    virtual bool isEnumeratable() const override { return true; }
131    virtual bool supportLabels() const override { return true; }
132
133    virtual FormControlState saveFormControlState() const override;
134    virtual void restoreFormControlState(const FormControlState&) override;
135
136    virtual void parseAttribute(const QualifiedName&, const AtomicString&) override;
137    virtual bool isPresentationAttribute(const QualifiedName&) const override;
138
139    virtual bool childShouldCreateRenderer(const Node&) const override;
140    virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override;
141    virtual bool appendFormData(FormDataList&, bool) override;
142
143    virtual void reset() override;
144
145    virtual void defaultEventHandler(Event*) override;
146
147    void dispatchChangeEventForMenuList();
148
149    virtual void didRecalcStyle(Style::Change) override final;
150
151    void recalcListItems(bool updateSelectedStates = true) const;
152
153    void deselectItems(HTMLOptionElement* excludeElement = 0);
154    void typeAheadFind(KeyboardEvent*);
155    void saveLastSelection();
156
157    virtual InsertionNotificationRequest insertedInto(ContainerNode&) override;
158
159    virtual bool isOptionalFormControl() const override { return !isRequiredFormControl(); }
160    virtual bool isRequiredFormControl() const override;
161
162    bool hasPlaceholderLabelOption() const;
163
164    enum SelectOptionFlag {
165        DeselectOtherOptions = 1 << 0,
166        DispatchChangeEvent = 1 << 1,
167        UserDriven = 1 << 2,
168    };
169    typedef unsigned SelectOptionFlags;
170    void selectOption(int optionIndex, SelectOptionFlags = 0);
171    void deselectItemsWithoutValidation(HTMLElement* elementToExclude = 0);
172    void parseMultipleAttribute(const AtomicString&);
173    int lastSelectedListIndex() const;
174    void updateSelectedState(int listIndex, bool multi, bool shift);
175    void menuListDefaultEventHandler(Event*);
176    bool platformHandleKeydownEvent(KeyboardEvent*);
177    void listBoxDefaultEventHandler(Event*);
178    void setOptionsChangedOnRenderer();
179    size_t searchOptionsForValue(const String&, size_t listIndexStart, size_t listIndexEnd) const;
180
181    enum SkipDirection {
182        SkipBackwards = -1,
183        SkipForwards = 1
184    };
185    int nextValidIndex(int listIndex, SkipDirection, int skip) const;
186    int nextSelectableListIndex(int startIndex) const;
187    int previousSelectableListIndex(int startIndex) const;
188    int firstSelectableListIndex() const;
189    int lastSelectableListIndex() const;
190    int nextSelectableListIndexPageAway(int startIndex, SkipDirection) const;
191
192    virtual void childrenChanged(const ChildChange&) override;
193
194    // TypeAheadDataSource functions.
195    virtual int indexOfSelectedOption() const override;
196    virtual int optionCount() const override;
197    virtual String optionAtIndex(int index) const override;
198
199    // m_listItems contains HTMLOptionElement, HTMLOptGroupElement, and HTMLHRElement objects.
200    mutable Vector<HTMLElement*> m_listItems;
201    Vector<bool> m_lastOnChangeSelection;
202    Vector<bool> m_cachedStateForActiveSelection;
203    TypeAhead m_typeAhead;
204    int m_size;
205    int m_lastOnChangeIndex;
206    int m_activeSelectionAnchorIndex;
207    int m_activeSelectionEndIndex;
208    bool m_isProcessingUserDrivenChange;
209    bool m_multiple;
210    bool m_activeSelectionState;
211    bool m_allowsNonContiguousSelection;
212    mutable bool m_shouldRecalcListItems;
213};
214
215NODE_TYPE_CASTS(HTMLSelectElement)
216
217} // namespace
218
219#endif
220