Provide some tests and make sure it works on all officially supported  
browsers even if the implementation is suboptimal. There are many js  
libs out there so it's not hard to find the best way to do it fir the  
various browsers...

On 18/04/2009, at 12:39 PM, Vitali Lovich <[email protected]> wrote:

> Just my first attempt at adding some initial support for
> getElementsByClassName.  This is by no means tested or
>
> Newer browsers support getElementsByClassName.  This is my attempt  
> at a patch.
>
> Caveats:
> There's a "bug" in that quirks mode doesn't behave properly (I don't
> know how to detect it in the deferred binding) for IE & Firefox2 &
> earlier.  According to the HTML5 spec, it's supposed to be case
> insensitive in quirks mode.  However, this "bug" behaves the exact
> same way as all the javascript wrappers do (since I based the XPath &
> RegExp code paths roughly around the implementations floating out
> there).
>
> I'm also not sure if I added the support correctly for Firefox.
> getElementsByClassName only came in with FF3 & requires the xpath
> workaround for FF2 & earlier (I believe I read xpath was introduced
> with FF 1.5).  I placed the xpath code in DOMImplMozillaOld for now
> (not sure whether or not gecko1_8 represents FF2).
>
> There's also no mention of the versions of Safari & Opera that are
> supported by GWT, so they're defaulting to using the native version
> (which will not work if they don't provide it).
>
> Safari in particular got it with version 3.1.  if earlier versions are
> supported, it's not too much work.  Simply grab the expression built
> in the FF xpath  & pass it to document._getElementsByXPath(query,
> parent) for Safari versions that have xpath (not sure which those
> are).  Not sure how to distinguish Safari pre3.1 & post3.1 in deferred
> binding.
>
> Opera got it with 9.5.  Not sure when xPath support got into Opera
> (should be a straightfoward copy of the mozilla code).  Not sure how
> to distinguish the two in the deferred binding.
>
> Feedback would be appreciated.
>
> Should this go as an enhancement request in the issue tracker?
>
> >
> diff --git a/user/src/com/google/gwt/dom/client/DOMImpl.java b/user/ 
> src/com/google/gwt/dom/client/DOMImpl.java index 1d7e39b..581764b  
> 100644 --- a/user/src/com/google/gwt/dom/client/DOMImpl.java +++ b/ 
> user/src/com/google/gwt/dom/client/DOMImpl.java @@ -176,6 +176,8 @@  
> abstract class DOMImpl { return 0; }-*/; + public abstract NodeList  
> getElementsByClassName(Element parent, String className); + public  
> native Element getFirstChildElement(Element elem) /*-{ var child =  
> elem.firstChild; while (child && child.nodeType != 1) diff --git a/ 
> user/src/com/google/gwt/dom/client/DOMImplIE6.java b/user/src/com/ 
> google/gwt/dom/client/DOMImplIE6.java index 04c205a..8c24a6c 100644  
> --- a/user/src/com/google/gwt/dom/client/DOMImplIE6.java +++ b/user/ 
> src/com/google/gwt/dom/client/DOMImplIE6.java @@ -15,6 +15,8 @@ */  
> package com.google.gwt.dom.client; +import  
> com.google.gwt.core.client.JsArray; +  /** * Internet Explorer 6  
> implementation of * {...@link com.google.gwt.user.client.impl.DOMImpl}.  
> @@ -184,6 +186,31 @@ class DOMImplIE6 extends DOMImpl { } @Override  
> + public NodeList getElementsByClassName(Element parent, String  
> className) { + // TODO: detect quirks mode so that the regexps do a  
> case insensitive match as per the + // spec. when quirks mode  
> detected, pass "i" as the flags parameter + return  
> getElementsByClassName(parent, className.split(" "), "").cast(); + }  
> + +  private native JsArray getElementsByClassName(Element parent,  
> String [] classes, String flags) /*-{ + var i, j, e, c, elements =  
> parent.all || parent.getElementsByTagName("*"); + var regexps = [],  
> result = []; + for (i = classes.length - 1; i >= 0; i--) { + c =  
> classes[i].replace(/^\s+|\s+$/g, ""); + if (c.length) +  
> regexps.push(new RegExp(new Array("(?:^|\\s)", c, "(?:\\s| 
> $)").join(""), flags); + } + if (regexps.length) { + for (i = 0, c =  
> elements.length; i < c; i++) { + e = elements[i]; + for (j =  
> regexps.length - 1; j >= 0 && regexps[j].test(e); j--) {} + j == -1  
> && result.push(e); + } + } + return result; + }-*/; + + @Override  
> public native String getInnerText(Element elem) /*-{ return  
> elem.innerText; }-*/; diff --git a/user/src/com/google/gwt/dom/ 
> client/DOMImplMozillaOld.java b/user/src/com/google/gwt/dom/client/ 
> DOMImplMozillaOld.java index ecf52fb..5fd7312 100644 --- a/user/src/ 
> com/google/gwt/dom/client/DOMImplMozillaOld.java +++ b/user/src/com/ 
> google/gwt/dom/client/DOMImplMozillaOld.java @@ -15,6 +15,8 @@ */  
> package com.google.gwt.dom.client; +import  
> com.google.gwt.core.client.JsArray; +  /** * DOM implementation  
> differences for older version of Mozilla (mostly the * hosted mode  
> browser on linux). The main difference is due to changes in @@  
> -114,4 +116,23 @@ package com.google.gwt.dom.client; return top +  
> viewport.scrollTop; }-*/; + + @Override + public NodeList  
> getElementsByClassName(Element parent, String className) { + // the  
> cast should be safe since both it & JsArray access the underlying  
> object the same way + // and NodeList is immutable (constraints  
> added, not removed) + return getElementsByClassName(parent,  
> className.split(" ")).cast(); + } + + private native JsArray  
> getElementsByClassName(Element parent, String [] classes) /*-{ + var  
> result, i, xpathResult, classExpr = ".//*"; + for (i =  
> classes.length - 1; i >= 0; i--) { + classExpr +=  
> "[contains(concat(' ', @class, ' '), ' " + classes[i] + " ')]"; + }  
> + xpathResult = document.evaluate(classExpr, parent, null, 0, null);  
> + while ((i = xpathResult.iterateNext())) { + result.push(i); + } +  
> return result; + }-*/; } diff --git a/user/src/com/google/gwt/dom/ 
> client/DOMImplStandard.java b/user/src/com/google/gwt/dom/client/ 
> DOMImplStandard.java index 90d2e89..be29fe1 100644 --- a/user/src/ 
> com/google/gwt/dom/client/DOMImplStandard.java +++ b/user/src/com/ 
> google/gwt/dom/client/DOMImplStandard.java @@ -114,6 +114,11 @@  
> abstract class DOMImplStandard extends DOMImpl { }-*/; @Override +  
> public native NodeList getElementsByClassName(Element parent, String  
> className) /*-{ + return parent.getElementsByClassName(className);  
> + }-*/; + + @Override public native boolean isOrHasChild(Element  
> parent, Element child) /*-{ return parent.contains(child); }-*/;  
> diff --git a/user/src/com/google/gwt/dom/client/Document.java b/user/ 
> src/com/google/gwt/dom/client/Document.java index 209b1b9..23d6daf  
> 100644 --- a/user/src/com/google/gwt/dom/client/Document.java +++ b/ 
> user/src/com/google/gwt/dom/client/Document.java @@ -1125,6 +1125,18  
> @@ public class Document extends Node { }-*/; /** + * Returns a  
> {...@link NodeList} of all the {...@link Element Elements} with a given +  
> * class name in the order in which they are encountered in a  
> preorder traversal + * of the document tree. + * + * @param  
> className the space-separated name of the classes to match on + *  
> @return a list containing all the matched elements. + */ + public  
> final NodeList getElementsByClassName(String className) { + return  
> DOMImpl.impl.getElementsByClassName(this.cast(), className); + } +  
> + /** * Returns the {...@link Element} whose id is given by elementId.  
> If no such * element exists, returns null. Behavior is not defined  
> if more than one * element has this id. diff --git a/user/src/com/ 
> google/gwt/dom/client/Element.java b/user/src/com/google/gwt/dom/ 
> client/Element.java index a0bf9f2..d64b83e 100644 --- a/user/src/com/ 
> google/gwt/dom/client/Element.java +++ b/user/src/com/google/gwt/dom/ 
> client/Element.java @@ -149,6 +149,18 @@ public class Element  
> extends Node { }-*/; /** + * Returns a {...@link NodeList} of all the  
> {...@link Element Elements} with a given + * class name in the order in  
> which they are encountered in a preorder traversal + * of this  
> elements children. + * + * @param className the space-separated  
> names of the classes to match on + * @return a list containing all  
> the matched elements. + */ + public final NodeList  
> getElementsByClassName(String className) { + return  
> DOMImpl.impl.getElementsByClassName(this, className); + } + + /** *  
> Returns a NodeList of all descendant Elements with a given tag name,  
> in the * order in which they are encountered in a preorder traversal  
> of this Element * tree.

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to