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 ]