diff --git a/dlls/mshtml/htmldoc3.c b/dlls/mshtml/htmldoc3.c index de5cdab9dbf..9637e993181 100644 --- a/dlls/mshtml/htmldoc3.c +++ b/dlls/mshtml/htmldoc3.c @@ -536,8 +536,43 @@ static HRESULT WINAPI HTMLDocument3_getElementsByName(IHTMLDocument3 *iface, BST IHTMLElementCollection **ppelColl) { HTMLDocument *This = impl_from_IHTMLDocument3(iface); - FIXME("(%p)->(%s %p)\n", This, debugstr_w(v), ppelColl); - return E_NOTIMPL; + nsIDOMNodeList *node_list; + nsAString selector_str; + WCHAR *selector; + nsresult nsres; + + static const WCHAR formatW[] = {'*','[','i','d','=','%','s',']',',','*','[','n','a','m','e','=','%','s',']',0}; + + TRACE("(%p)->(%s %p)\n", This, debugstr_w(v), ppelColl); + + if(!This->doc_node || !This->doc_node->nsdoc) { + /* We should probably return an empty collection. */ + FIXME("No nsdoc\n"); + return E_NOTIMPL; + } + + selector = heap_alloc(2*SysStringLen(v)*sizeof(WCHAR) + sizeof(formatW)); + if(!selector) + return E_OUTOFMEMORY; + sprintfW(selector, formatW, v, v); + + /* + * NOTE: IE getElementsByName implementation differs from Gecko. It searches both name and id attributes. + * That's why we use CSS selector instead. We should also use name only when it applies to given element + * types and search should be case insensitive. Those are currently not supported properly. + */ + nsAString_InitDepend(&selector_str, selector); + nsres = nsIDOMNodeSelector_QuerySelectorAll(This->doc_node->nsnode_selector, &selector_str, &node_list); + nsAString_Finish(&selector_str); + heap_free(selector); + if(NS_FAILED(nsres)) { + ERR("QuerySelectorAll failed: %08x\n", nsres); + return E_FAIL; + } + + *ppelColl = create_collection_from_nodelist(This->doc_node, node_list); + nsIDOMNodeList_Release(node_list); + return S_OK; } diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index cf72873b8f3..6e6b01a8b7c 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -759,6 +759,18 @@ static IHTMLElement4 *_get_elem4_iface(unsigned line, IUnknown *unk) return elem; } +#define get_doc3_iface(u) _get_doc3_iface(__LINE__,u) +static IHTMLDocument3 *_get_doc3_iface(unsigned line, IHTMLDocument2 *doc) +{ + IHTMLDocument3 *doc3; + HRESULT hres; + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3); + ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLDocument3 interface: %08x\n", hres); + + return doc3; +} + #define get_node_iface(u) _get_node_iface(__LINE__,u) static IHTMLDOMNode *_get_node_iface(unsigned line, IUnknown *unk) { @@ -6737,6 +6749,54 @@ static void test_blocked(IHTMLDocument2 *doc, IHTMLElement *outer_elem) } } +#define doc_get_elems_by_name(a,b) _doc_get_elems_by_name(__LINE__,a,b) +static IHTMLElementCollection *_doc_get_elems_by_name(unsigned line, IHTMLDocument2 *doc, const char *name) +{ + IHTMLDocument3 *doc3 = _get_doc3_iface(line, doc); + IHTMLElementCollection *col; + BSTR str = a2bstr(name); + HRESULT hres; + + hres = IHTMLDocument3_getElementsByName(doc3, str, &col); + ok_(__FILE__,line)(hres == S_OK, "getElementsByName failed: %08x\n", hres); + ok_(__FILE__,line)(col != NULL, "col = NULL\n"); + + IHTMLDocument3_Release(doc3); + SysFreeString(str); + return col; +} + +static void test_elem_names(IHTMLDocument2 *doc) +{ + IHTMLElementCollection *col; + IHTMLElement *body; + LONG len; + HRESULT hres; + + static const elem_type_t test1_types[] = {ET_INPUT, ET_A, ET_DIV}; + + body = doc_get_body(doc); + + test_elem_set_innerhtml((IUnknown*)body, + "
"); + col = doc_get_elems_by_name(doc, "test"); + test_elem_collection((IUnknown*)col, test1_types, sizeof(test1_types)/sizeof(*test1_types)); + IHTMLElementCollection_Release(col); + + col = doc_get_elems_by_name(doc, "yyy"); + test_elem_collection((IUnknown*)col, NULL, 0); + IHTMLElementCollection_Release(col); + + /* case insensivity test */ + col = doc_get_elems_by_name(doc, "Xxx"); + hres = IHTMLElementCollection_get_length(col, &len); + ok(hres == S_OK, "get_length failed: %08x\n", hres); + todo_wine ok(len == 1, "len = %d\n", len); + IHTMLElementCollection_Release(col); + + IHTMLElement_Release(body); +} + static void test_elems2(IHTMLDocument2 *doc) { IHTMLElement *elem, *elem2, *div; @@ -6825,6 +6885,7 @@ static void test_elems2(IHTMLDocument2 *doc) test_attr(div); test_blocked(doc, div); + test_elem_names(doc); IHTMLElement_Release(div); }