Jacek Caban : mshtml: Added support for navigating to anchors with IDs containing '#'.

Alexandre Julliard julliard at winehq.org
Mon Sep 10 15:22:12 CDT 2012


Module: wine
Branch: master
Commit: 3f2365d5decc3150db8dd797ba5527b561e24d5b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3f2365d5decc3150db8dd797ba5527b561e24d5b

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Mon Sep 10 14:42:39 2012 +0200

mshtml: Added support for navigating to anchors with IDs containing '#'.

---

 dlls/mshtml/navigate.c  |   43 ++++++++++++++++++++++++++++++++++++++++---
 dlls/mshtml/nsiface.idl |   11 +++++++++++
 2 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c
index 91705dd..1046356 100644
--- a/dlls/mshtml/navigate.c
+++ b/dlls/mshtml/navigate.c
@@ -19,6 +19,7 @@
 #include "config.h"
 
 #include <stdarg.h>
+#include <assert.h>
 
 #define COBJMACROS
 #define NONAMELESSUNION
@@ -1925,10 +1926,13 @@ static HRESULT navigate_fragment(HTMLOuterWindow *window, IUri *uri)
 {
     nsIDOMLocation *nslocation;
     nsAString nsfrag_str;
+    WCHAR *selector;
     BSTR frag;
     nsresult nsres;
     HRESULT hres;
 
+    const WCHAR selector_formatW[] = {'a','[','i','d','=','"','%','s','"',']',0};
+
     set_current_uri(window, uri);
 
     nsres = nsIDOMWindow_GetLocation(window->nswindow, &nslocation);
@@ -1945,12 +1949,45 @@ static HRESULT navigate_fragment(HTMLOuterWindow *window, IUri *uri)
     nsres = nsIDOMLocation_SetHash(nslocation, &nsfrag_str);
     nsAString_Finish(&nsfrag_str);
     nsIDOMLocation_Release(nslocation);
-    SysFreeString(frag);
-    if(NS_FAILED(nsres)) {
+    if(NS_FAILED(nsres))
         ERR("SetHash failed: %08x\n", nsres);
-        return E_FAIL;
+
+    /*
+     * IE supports scrolling to anchor elements with "#hash" ids (note that '#' is part of the id),
+     * while Gecko scrolls only to elements with "hash" ids. We scroll the page ourselves if
+     * a[id="#hash"] element can be found.
+     */
+    selector = heap_alloc(sizeof(selector_formatW)+SysStringLen(frag)*sizeof(WCHAR));
+    if(selector) {
+        nsIDOMNodeSelector *node_selector;
+        nsIDOMElement *nselem = NULL;
+        nsAString selector_str;
+
+        nsres = nsIDOMHTMLDocument_QueryInterface(window->base.inner_window->doc->nsdoc, &IID_nsIDOMNodeSelector,
+                (void**)&node_selector);
+        assert(nsres == NS_OK);
+
+        sprintfW(selector, selector_formatW, frag);
+        nsAString_InitDepend(&selector_str, selector);
+        /* NOTE: Gecko doesn't set result to NULL if there is no match, so nselem must be initialized */
+        nsres = nsIDOMNodeSelector_QuerySelector(node_selector, &selector_str, &nselem);
+        nsIDOMNodeSelector_Release(node_selector);
+        nsAString_Finish(&selector_str);
+        heap_free(selector);
+        if(NS_SUCCEEDED(nsres) && nselem) {
+            nsIDOMHTMLElement *html_elem;
+
+            nsres = nsIDOMElement_QueryInterface(nselem, &IID_nsIDOMHTMLElement, (void**)&html_elem);
+            nsIDOMElement_Release(nselem);
+            if(NS_SUCCEEDED(nsres)) {
+                nsIDOMHTMLElement_ScrollIntoView(html_elem, TRUE, 1);
+                nsIDOMHTMLElement_Release(html_elem);
+            }
+        }
     }
 
+    SysFreeString(frag);
+
     if(window->doc_obj->doc_object_service) {
         IDocObjectService_FireNavigateComplete2(window->doc_obj->doc_object_service, &window->base.IHTMLWindow2_iface, 0x10);
         IDocObjectService_FireDocumentComplete(window->doc_obj->doc_object_service, &window->base.IHTMLWindow2_iface, 0);
diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl
index d19d5df..a4202f0 100644
--- a/dlls/mshtml/nsiface.idl
+++ b/dlls/mshtml/nsiface.idl
@@ -2073,6 +2073,17 @@ interface nsIDOMHTMLStyleElement : nsIDOMHTMLElement
 
 [
     object,
+    uuid(7cebc153-168a-416c-ba5a-56a8c2ddb2ec),
+    local
+]
+interface nsIDOMNodeSelector : nsISupports
+{
+    nsresult QuerySelector(const nsAString *selectors, nsIDOMElement **_retval);
+    nsresult QuerySelectorAll(const nsAString *selectors, nsIDOMNodeList **_retval);
+}
+
+[
+    object,
     uuid(94928ab3-8b63-11d3-989d-001083010e9b),
     local
 ]




More information about the wine-cvs mailing list