OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 | |
6 #include "modules/accessibility/AXRadioInput.h" | |
7 | |
8 #include "core/dom/ElementTraversal.h" | |
9 #include "core/html/HTMLInputElement.h" | |
10 #include "modules/accessibility/AXObjectCacheImpl.h" | |
11 | |
12 namespace blink { | |
13 | |
14 namespace { | |
15 | |
16 HTMLElement* nextElement(const HTMLElement& element, HTMLFormElement* stayWithin , bool forward) | |
17 { | |
18 return forward ? Traversal<HTMLElement>::next(element, (Node* )stayWithin) : Traversal<HTMLElement>::previous(element, (Node* )stayWithin); | |
19 } | |
20 | |
21 } // namespace | |
22 | |
23 using namespace HTMLNames; | |
24 | |
25 AXRadioInput::AXRadioInput(LayoutObject* layoutObject, AXObjectCacheImpl& axObje ctCache) | |
26 : AXLayoutObject(layoutObject, axObjectCache) | |
27 { | |
28 // Updates posInSet and setSize for the current object and the next objects. | |
29 if (!calculatePosInSet()) | |
30 return; | |
31 // When a new object is inserted, it needs to update setSize for the previou s objects. | |
32 requestUpdateToNextNode(false); | |
33 } | |
34 | |
35 AXRadioInput* AXRadioInput::create(LayoutObject* layoutObject, AXObjectCacheImpl & axObjectCache) | |
36 { | |
37 return new AXRadioInput(layoutObject, axObjectCache); | |
38 } | |
39 | |
40 void AXRadioInput::updatePosAndSetSize(int position) | |
41 { | |
42 if (position) | |
43 m_posInSet = position; | |
44 m_setSize = sizeOfRadioGroup(); | |
45 } | |
46 | |
47 void AXRadioInput::requestUpdateToNextNode(bool forward) | |
48 { | |
49 HTMLInputElement* nextElement = findNextFocusableRadioButtonInGroup(element( ), forward); | |
50 AXObject* nextAXobject = axObjectCache().get(nextElement); | |
51 if (!nextAXobject || !nextAXobject->isAXRadioInput()) | |
52 return; | |
53 int position = 0; | |
54 if (forward) | |
55 position = posInSet() + 1; | |
56 // It moves to backward only when a new node inserted to AX tree which alrea dy exists. | |
57 // it just needs update for setSize and its position is not changed. | |
58 toAXRadioInput(nextAXobject)->updatePosAndSetSize(position); | |
59 axObjectCache().postNotification(nextAXobject, AXObjectCacheImpl::AXAriaAttr ibuteChanged); | |
60 toAXRadioInput(nextAXobject)->requestUpdateToNextNode(forward); | |
61 } | |
62 | |
63 HTMLInputElement* AXRadioInput::findFristFocusableRadioButtonInGroup(HTMLInputEl ement* current) const | |
keishi
2016/02/29 05:19:19
s/Frist/First/
je_julie(Not used)
2016/02/29 15:11:44
Done.
| |
64 { | |
65 while (HTMLInputElement* prevElement = findNextFocusableRadioButtonInGroup(c urrent, false)) | |
66 current = prevElement; | |
67 return current; | |
68 } | |
69 | |
70 int AXRadioInput::posInSet() const | |
71 { | |
72 if (hasAttribute(aria_posinsetAttr)) | |
73 return getAttribute(aria_posinsetAttr).toInt(); | |
74 return m_posInSet; | |
75 } | |
76 | |
77 int AXRadioInput::setSize() const | |
78 { | |
79 if (hasAttribute(aria_setsizeAttr)) | |
80 return getAttribute(aria_setsizeAttr).toInt(); | |
81 return m_setSize; | |
82 } | |
83 | |
84 bool AXRadioInput::calculatePosInSet() | |
85 { | |
86 // Calculate 'posInSet' attribute when AXRadioInputs need to be updated | |
87 // as a new AXRadioInput Object is added or one of objects from RadioGroup i s removed. | |
88 bool needToUpdatePrev = false; | |
89 int position = 1; | |
90 HTMLInputElement* prevElement = findNextFocusableRadioButtonInGroup(element( ), false); | |
91 if (prevElement) { | |
92 AXObject* object = axObjectCache().get(prevElement); | |
93 // If the previous element doesn't have AXObject yet, caculate position from the first element. | |
94 // Otherwise, get position from the previous AXObject. | |
95 if (!object || !object->isAXRadioInput()) { | |
96 position = countFromFirstElement(); | |
97 } else { | |
98 position = object->posInSet() + 1; | |
99 // It returns true if previous objects need to be updated. | |
100 // When AX tree exists already and a new node is inserted, | |
101 // as updating is started from the inserted node, | |
102 // we need to update setSize for previous nodes. | |
103 if (setSize() != object->setSize()) | |
104 needToUpdatePrev = true; | |
105 } | |
106 } | |
107 updatePosAndSetSize(position); | |
108 | |
109 // If it is not the last element, request update to the next node. | |
110 if (position != setSize()) | |
111 requestUpdateToNextNode(true); | |
112 return needToUpdatePrev; | |
113 } | |
114 | |
115 HTMLInputElement* AXRadioInput::findNextFocusableRadioButtonInGroup(HTMLInputEle ment* current, bool forward) const | |
keishi
2016/02/29 05:19:19
nit: This function isn't checking focusable.
je_julie(Not used)
2016/02/29 15:11:44
According to spec, there is no mention about focus
dmazzoni
2016/02/29 17:16:18
That's fine, but change the name of the function f
| |
116 { | |
117 for (HTMLElement* htmlElement = nextElement(*current, current->form(), forwa rd); htmlElement; htmlElement = nextElement(*htmlElement, current->form(), forwa rd)) { | |
118 if (!isHTMLInputElement(*htmlElement)) | |
119 continue; | |
120 HTMLInputElement* inputElement = toHTMLInputElement(htmlElement); | |
121 if (current->form() == inputElement->form() && inputElement->isRadioButt on() && inputElement->name() == current->name()) | |
122 return inputElement; | |
123 } | |
124 return nullptr; | |
125 } | |
126 | |
127 int AXRadioInput::countFromFirstElement() const | |
128 { | |
129 int count = 1; | |
130 HTMLInputElement* current = element(); | |
131 while (HTMLInputElement* prevElement = findNextFocusableRadioButtonInGroup(c urrent, false)) { | |
132 current = prevElement; | |
133 count++; | |
134 } | |
135 return count; | |
136 } | |
137 | |
138 HTMLInputElement* AXRadioInput::element() const | |
139 { | |
140 return toHTMLInputElement(m_layoutObject->node()); | |
141 } | |
142 | |
143 int AXRadioInput::sizeOfRadioGroup() const | |
144 { | |
145 int size = element()->sizeOfRadioGroup(); | |
146 // If it has no size in Group, it means that there is only itself. | |
147 if (!size) | |
148 return 1; | |
149 return size; | |
150 } | |
151 | |
152 } // namespace blink | |
OLD | NEW |