diff --git a/dlls/mshtml/htmldoc3.c b/dlls/mshtml/htmldoc3.c index a00fa95b21b..b930d882344 100644 --- a/dlls/mshtml/htmldoc3.c +++ b/dlls/mshtml/htmldoc3.c @@ -431,6 +431,8 @@ static HRESULT WINAPI HTMLDocument3_getElementById(IHTMLDocument3 *iface, BSTR v HTMLDocument *This = HTMLDOC3_THIS(iface); nsIDOMElement *nselem; HTMLDOMNode *node; + nsIDOMNode *nsnode, *nsnode_by_id, *nsnode_by_name; + nsIDOMNodeList *nsnode_list; nsAString id_str; nsresult nsres; @@ -442,16 +444,64 @@ static HRESULT WINAPI HTMLDocument3_getElementById(IHTMLDocument3 *iface, BSTR v } nsAString_Init(&id_str, v); + /* get element by id attribute */ nsres = nsIDOMHTMLDocument_GetElementById(This->doc_node->nsdoc, &id_str, &nselem); - nsAString_Finish(&id_str); if(FAILED(nsres)) { ERR("GetElementById failed: %08x\n", nsres); + nsAString_Finish(&id_str); return E_FAIL; } + nsnode_by_id = (nsIDOMNode*)nselem; - if(nselem) { - node = get_node(This->doc_node, (nsIDOMNode*)nselem, TRUE); - nsIDOMElement_Release(nselem); + /* get first element by name attribute */ + nsres = nsIDOMHTMLDocument_GetElementsByName(This->doc_node->nsdoc, &id_str, &nsnode_list); + if(FAILED(nsres)) { + ERR("getElementsByName failed: %08x\n", nsres); + nsAString_Finish(&id_str); + if(nsnode_by_id) + nsIDOMNode_Release(nsnode_by_id); + return E_FAIL; + } + nsIDOMNodeList_Item(nsnode_list, 0, &nsnode_by_name); + nsIDOMNodeList_Release(nsnode_list); + + nsAString_Finish(&id_str); + + if(nsnode_by_name && nsnode_by_id) { + nsIDOM3Node *node3; + PRUint16 pos; + + nsres = nsIDOMNode_QueryInterface(nsnode_by_name, &IID_nsIDOM3Node, (void**)&node3); + if(NS_FAILED(nsres)) { + FIXME("failed to get nsIDOM3Node interface: 0x%08x\n", nsres); + nsIDOMNode_Release(nsnode_by_name); + nsIDOMNode_Release(nsnode_by_id); + return E_FAIL; + } + + nsres = nsIDOM3Node_CompareDocumentPosition(node3, nsnode_by_id, &pos); + nsIDOM3Node_Release(node3); + if(NS_FAILED(nsres)) { + FIXME("nsIDOM3Node_CompareDocumentPosition failed: 0x%08x\n", nsres); + nsIDOMNode_Release(nsnode_by_name); + nsIDOMNode_Release(nsnode_by_id); + return E_FAIL; + } + + TRACE("CompareDocumentPosition gave: 0x%x\n", pos); + if(pos & PRECEDING || pos & CONTAINS) { + nsnode = nsnode_by_id; + nsIDOMNode_Release(nsnode_by_name); + }else { + nsnode = nsnode_by_name; + nsIDOMNode_Release(nsnode_by_id); + } + }else + nsnode = nsnode_by_name ? nsnode_by_name : nsnode_by_id; + + if(nsnode) { + node = get_node(This->doc_node, nsnode, TRUE); + nsIDOMNode_Release(nsnode); IHTMLDOMNode_QueryInterface(HTMLDOMNODE(node), &IID_IHTMLElement, (void**)pel); }else { diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl index 19f29b0b663..9d0bb309dbd 100644 --- a/dlls/mshtml/nsiface.idl +++ b/dlls/mshtml/nsiface.idl @@ -140,6 +140,8 @@ typedef nsISupports nsIContent; typedef nsISupports nsINode; typedef nsISupports nsIStyleSheet; typedef nsISupports nsIStyleRule; +typedef nsISupports nsIVariant; +typedef nsISupports nsIDOMUserDataHandler; [ object, @@ -601,6 +603,37 @@ interface nsIDOMNodeList : nsISupports nsresult GetLength(PRUint32 *aLength); } +[ + object, + uuid(29fb2a18-1dd2-11b2-8dd9-a6fd5d5ad12f), + local + /* NOT_FROZEN */ +] +interface nsIDOM3Node : nsISupports +{ + enum NSDOCPOSITION { + DISCONNECTED = 1, + PRECEDING = 2, + FOLLOWING = 4, + CONTAINS = 8, + CONTAINED_BY = 16, + IMPLEMENTATION_SPECIFIC = 32 + }; + + nsresult GetBaseURI(nsAString *aBaseURI); + nsresult CompareDocumentPosition(nsIDOMNode *other, PRUint16 *_retval); + nsresult GetTextContent(nsAString *aTextContent); + nsresult SetTextContent(const nsAString *aTextContent); + nsresult IsSameNode(nsIDOMNode *other, PRBool *_retval); + nsresult LookupPrefix(const nsAString *namespaceURI, PRBool *_retval); + nsresult IsDefaultNamespace(const nsAString *namespaceURI, PRBool *_retval); + nsresult LookupNamespaceURI(const nsAString *prefix, nsAString _retval); + nsresult IsEqualNode(nsIDOMNode *arg, PRBool *_retval); + nsresult GetFeature(const nsAString *feature, const nsAString *version, nsISupports **_retval); + nsresult SetUserData(const nsAString *key, nsIVariant *data, nsIDOMUserDataHandler *handler, nsIVariant **_retval); + nsresult GetUserData(const nsAString *key, nsIVariant **_retval); +} + [ object, uuid(a6cf907c-15b3-11d2-932e-00805f8add32), diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 868116427fc..bd55c9f5fba 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -65,7 +65,7 @@ static const char cond_comment_str[] = ""; static const char frameset_str[] = "frameset test" - "" + "" ""; static WCHAR characterW[] = {'c','h','a','r','a','c','t','e','r',0}; @@ -5396,6 +5396,7 @@ static void test_elems(IHTMLDocument2 *doc) ok(!node, "node = %p\n", node); elem2 = get_doc_elem_by_id(doc, "x"); + test_elem_tag((IUnknown*)elem2, "A"); node = node_get_next((IUnknown*)elem2); IHTMLDOMNode_Release(node); IHTMLElement_Release(elem2); @@ -5682,6 +5683,7 @@ static void test_frameset(IHTMLDocument2 *doc) { IHTMLWindow2 *window; IHTMLFramesCollection2 *frames; + IHTMLElement *elem; LONG length; VARIANT index_var, result_var; HRESULT hres; @@ -5805,6 +5807,11 @@ static void test_frameset(IHTMLDocument2 *doc) ok(hres == E_INVALIDARG, "IHTMLWindow2_item should have" "failed with E_INVALIDARG, instead: 0x%08x\n", hres); VariantClear(&result_var); + + /* getElementById with node name attributes */ + elem = get_doc_elem_by_id(doc, "nm1"); + test_elem_id((IUnknown*)elem, "fr1"); + IHTMLElement_Release(elem); } static IHTMLDocument2 *notif_doc;