diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c
index 91705dd..efd5a96 100644
--- a/dlls/mshtml/navigate.c
+++ b/dlls/mshtml/navigate.c
@@ -19,6 +19,7 @@
#include "config.h"
#include
+#include
#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 = (void*)0xdeadbeef;
+ 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);
+ nsres = nsIDOMNodeSelector_QuerySelector(node_selector, &selector_str, &nselem);
+ ERR("nselem %p %08x\n", nselem, nsres);
+ 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
]