Title: [150637] trunk/Source/WebKit/blackberry
Revision
150637
Author
mifen...@rim.com
Date
2013-05-24 05:47:18 -0700 (Fri, 24 May 2013)

Log Message

[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):

Modified Paths

Diff

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.");
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to