Modified: trunk/Source/WebKit/blackberry/ChangeLog (150636 => 150637)
--- trunk/Source/WebKit/blackberry/ChangeLog 2013-05-24 08:41:00 UTC (rev 150636)
+++ trunk/Source/WebKit/blackberry/ChangeLog 2013-05-24 12:47:18 UTC (rev 150637)
@@ -1,3 +1,24 @@
+2013-05-24 Mike Fenton <mifen...@rim.com>
+
+ [BlackBerry] Respect tabindex when using form controls.
+ https://bugs.webkit.org/show_bug.cgi?id=116676
+
+ Reviewed by Xan Lopez.
+
+ PR 337419.
+
+ Update form control navigation tracking to take tabindex
+ order into account when calculating next and previous nodes.
+
+ The order to follow is tab index 1 - N, followed by all items
+ without a tab index or tab index 0 in rendering order to match
+ with standard desktop behavior.
+
+ Internally Reviewed by Genevieve Mak and Nima Ghanavatian.
+
+ * WebKitSupport/InputHandler.cpp:
+ (BlackBerry::WebKit::InputHandler::updateFormState):
+
2013-05-24 Jeff Rogers <jrog...@rim.com>
[BlackBerry] Remove SKIA leftovers from WebPage.cpp
Modified: trunk/Source/WebKit/blackberry/WebKitSupport/InputHandler.cpp (150636 => 150637)
--- trunk/Source/WebKit/blackberry/WebKitSupport/InputHandler.cpp 2013-05-24 08:41:00 UTC (rev 150636)
+++ trunk/Source/WebKit/blackberry/WebKitSupport/InputHandler.cpp 2013-05-24 12:47:18 UTC (rev 150637)
@@ -947,35 +947,104 @@
if (formElementCount < 2)
return;
- InputLog(Platform::LogLevelInfo, "InputHandler::updateFormState form has %d fields", formElementCount);
+ m_hasSubmitButton = true;
- m_hasSubmitButton = true;
+ // Walk all elements in the form to determine next/prev elements.
+ // For each element in the form we need to do the following:
+ // If it's the focus node, use render order to try to find the next/prev directly.
+ // For all other nodes:
+ // 1) If the focused node has a specific tab index, compare the elements tab
+ // index with the current prev/next looking for the best match.
+ // 2) If the focused node does not have a tab index, update the maximum
+ // tab index value, required for prev navigation.
+ int focusTabIndex = static_cast<Node*>(m_currentFocusElement.get())->tabIndex();
+ int prevTabIndex = -1;
+ int nextTabIndex = std::numeric_limits<short>::max() + 1;
+ InputLog(Platform::LogLevelInfo, "InputHandler::updateFormState form has %d fields and tabIndex %d", formElementCount, focusTabIndex);
+
+ Element* firstInFieldWithoutTabIndex = 0;
+ Element* highestTabIndexElement = 0;
for (int focusElementId = 0; focusElementId < formElementCount; focusElementId++) {
- if (toHTMLElement(formElementList[focusElementId]) != m_currentFocusElement)
- continue;
+ // Check for the focused element, and if we don't have any target nodes, use the form order next
+ // and previous as placeholders. In a form without provided tab indices, this will determine the
+ // control fields.
+ Element* element = const_cast<HTMLElement*>(toHTMLElement(formElementList[focusElementId]));
+ if (element == m_currentFocusElement) {
+ InputLog(Platform::LogLevelInfo, "InputHandler::updateFormState found focused element.");
- // Found the focused element, get the next and previous elements if they exist.
+ // If the focus tab index is set for the node, don't use the logical ordering.
+ // Jump from last tab index to un-ordered is done separately.
+ if (focusTabIndex)
+ continue;
- // Previous
- for (int previousElementId = focusElementId - 1; previousElementId >= 0; previousElementId--) {
- Element* element = const_cast<HTMLElement*>(toHTMLElement(formElementList[previousElementId]));
- if (DOMSupport::isTextBasedContentEditableElement(element) && !DOMSupport::isElementReadOnly(element)) {
- m_previousFocusableTextElement = element;
- InputLog(Platform::LogLevelInfo, "InputHandler::updateFormState found previous element");
- break;
+ // Get the next/prev element if we don't already have a tab index based item.
+ // Previous
+ if (!m_previousFocusableTextElement) {
+ for (int previousElementId = focusElementId - 1; previousElementId >= 0; previousElementId--) {
+ Element* prevElement = const_cast<HTMLElement*>(toHTMLElement(formElementList[previousElementId]));
+ if (DOMSupport::isTextBasedContentEditableElement(prevElement) && !DOMSupport::isElementReadOnly(prevElement) && !static_cast<Node*>(prevElement)->tabIndex()) {
+ m_previousFocusableTextElement = prevElement;
+ InputLog(Platform::LogLevelInfo, "InputHandler::updateFormState found previous element");
+ break;
+ }
+ }
}
- }
- // Next
- for (int nextElementId = focusElementId + 1; nextElementId < formElementCount; nextElementId++) {
- Element* element = const_cast<HTMLElement*>(toHTMLElement(formElementList[nextElementId]));
+
+ // Next
+ if (!m_nextFocusableTextElement) {
+ for (int nextElementId = focusElementId + 1; nextElementId < formElementCount; nextElementId++) {
+ Element* nextElement = const_cast<HTMLElement*>(toHTMLElement(formElementList[nextElementId]));
+ if (DOMSupport::isTextBasedContentEditableElement(nextElement) && !DOMSupport::isElementReadOnly(nextElement) && !static_cast<Node*>(nextElement)->tabIndex()) {
+ m_nextFocusableTextElement = nextElement;
+ InputLog(Platform::LogLevelInfo, "InputHandler::updateFormState found next element");
+ break;
+ }
+ }
+ }
+ } else if (focusTabIndex) {
+ InputLog(Platform::LogLevelInfo, "InputHandler::updateFormState processing element");
if (DOMSupport::isTextBasedContentEditableElement(element) && !DOMSupport::isElementReadOnly(element)) {
- m_nextFocusableTextElement = element;
- InputLog(Platform::LogLevelInfo, "InputHandler::updateFormState found next element");
- break;
+ InputLog(Platform::LogLevelInfo, "InputHandler::updateFormState processing element valid");
+ if (int tabIndex = static_cast<Node*>(element)->tabIndex()) {
+ InputLog(Platform::LogLevelInfo, "InputHandler::updateFormState processing element with tab index %d", tabIndex);
+ // Compare for the before and after form positions based on the tab index, and/or form position
+ // if tab indexes are equal form position should be used.
+ if (tabIndex && tabIndex < focusTabIndex && tabIndex > prevTabIndex) {
+ m_previousFocusableTextElement = element;
+ prevTabIndex = tabIndex;
+ InputLog(Platform::LogLevelInfo, "InputHandler::updateFormState found previous element with tabIndex %d", tabIndex);
+ } else if (tabIndex > focusTabIndex && tabIndex < nextTabIndex) {
+ m_nextFocusableTextElement = element;
+ nextTabIndex = tabIndex;
+ InputLog(Platform::LogLevelInfo, "InputHandler::updateFormState found next element with tabIndex %d", tabIndex);
+ }
+ } else if (!firstInFieldWithoutTabIndex) {
+ // Store the first field in the form without a tab index if we have a form with some tab indexes the "next" one from
+ // the highest tab index is the first field without a tab index.
+ firstInFieldWithoutTabIndex = element;
+ }
}
+ } else {
+ // The field has no tab index, if it's the first node we'll need the highest tab index field
+ // when navigating backwards.
+ if (int tabIndex = static_cast<Node*>(element)->tabIndex()) {
+ if (!highestTabIndexElement || (tabIndex > static_cast<Node*>(highestTabIndexElement)->tabIndex()))
+ highestTabIndexElement = element;
+ }
}
}
+ if (!m_nextFocusableTextElement && firstInFieldWithoutTabIndex) {
+ // No next focusable field was found, but a first one without a tabindex was found, use it as the next field.
+ m_nextFocusableTextElement = firstInFieldWithoutTabIndex;
+ }
+
+ if (!m_previousFocusableTextElement && highestTabIndexElement) {
+ // No prev focusable field was found, use the highest tab index as previous since this field must not have
+ // a tabindex, otheriwse highestTabIndexElement would be null.
+ m_previousFocusableTextElement = highestTabIndexElement;
+ }
+
if (!m_nextFocusableTextElement && !m_previousFocusableTextElement) {
m_hasSubmitButton = false;
InputLog(Platform::LogLevelInfo, "InputHandler::updateFormState no valid elements found, clearing state.");