Source Code Cross Referenced for HTMLCollection.java in  » Testing » htmlunit » com » gargoylesoftware » htmlunit » javascript » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Testing » htmlunit » com.gargoylesoftware.htmlunit.javascript 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright (c) 2002-2008 Gargoyle Software Inc. All rights reserved.
003:         *
004:         * Redistribution and use in source and binary forms, with or without
005:         * modification, are permitted provided that the following conditions are met:
006:         *
007:         * 1. Redistributions of source code must retain the above copyright notice,
008:         *    this list of conditions and the following disclaimer.
009:         * 2. Redistributions in binary form must reproduce the above copyright notice,
010:         *    this list of conditions and the following disclaimer in the documentation
011:         *    and/or other materials provided with the distribution.
012:         * 3. The end-user documentation included with the redistribution, if any, must
013:         *    include the following acknowledgment:
014:         *
015:         *       "This product includes software developed by Gargoyle Software Inc.
016:         *        (http://www.GargoyleSoftware.com/)."
017:         *
018:         *    Alternately, this acknowledgment may appear in the software itself, if
019:         *    and wherever such third-party acknowledgments normally appear.
020:         * 4. The name "Gargoyle Software" must not be used to endorse or promote
021:         *    products derived from this software without prior written permission.
022:         *    For written permission, please contact info@GargoyleSoftware.com.
023:         * 5. Products derived from this software may not be called "HtmlUnit", nor may
024:         *    "HtmlUnit" appear in their name, without prior written permission of
025:         *    Gargoyle Software Inc.
026:         *
027:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
028:         * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
029:         * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
030:         * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
031:         * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
032:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
033:         * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
034:         * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
035:         * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
036:         * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037:         */
038:        package com.gargoylesoftware.htmlunit.javascript;
039:
040:        import java.util.ArrayList;
041:        import java.util.Iterator;
042:        import java.util.List;
043:        import java.util.Map;
044:        import java.util.Set;
045:
046:        import org.apache.commons.collections.CollectionUtils;
047:        import org.apache.commons.collections.Transformer;
048:        import org.apache.commons.collections.functors.NOPTransformer;
049:        import org.jaxen.JaxenException;
050:        import org.jaxen.XPath;
051:        import org.jaxen.saxpath.SAXPathException;
052:        import org.mozilla.javascript.Context;
053:        import org.mozilla.javascript.Function;
054:        import org.mozilla.javascript.JavaScriptException;
055:        import org.mozilla.javascript.Scriptable;
056:
057:        import com.gargoylesoftware.htmlunit.BrowserVersion;
058:        import com.gargoylesoftware.htmlunit.WebWindow;
059:        import com.gargoylesoftware.htmlunit.html.DomChangeEvent;
060:        import com.gargoylesoftware.htmlunit.html.DomChangeListener;
061:        import com.gargoylesoftware.htmlunit.html.DomNode;
062:        import com.gargoylesoftware.htmlunit.html.DomText;
063:        import com.gargoylesoftware.htmlunit.html.HtmlAttributeChangeEvent;
064:        import com.gargoylesoftware.htmlunit.html.HtmlAttributeChangeListener;
065:        import com.gargoylesoftware.htmlunit.html.HtmlElement;
066:        import com.gargoylesoftware.htmlunit.html.HtmlNoScript;
067:        import com.gargoylesoftware.htmlunit.javascript.configuration.JavaScriptConfiguration;
068:        import com.gargoylesoftware.htmlunit.xml.XmlAttr;
069:        import com.gargoylesoftware.htmlunit.xml.XmlElement;
070:        import com.gargoylesoftware.htmlunit.xml.XmlPage;
071:
072:        /**
073:         * An array of elements. Used for the element arrays returned by <tt>document.all</tt>,
074:         * <tt>document.all.tags('x')</tt>, <tt>document.forms</tt>, <tt>window.frames</tt>, etc.
075:         * Note that this class must not be used for collections that can be modified, for example
076:         * <tt>map.areas</tt> and <tt>select.options</tt>.
077:         * <br>
078:         * This class (like all classes in this package) is specific for the javascript engine.
079:         * Users of HtmlUnit shouldn't use it directly.
080:         *
081:         * @version $Revision: 2158 $
082:         * @author Daniel Gredler
083:         * @author Marc Guillemot
084:         * @author Chris Erskine
085:         * @author Ahmed Ashour
086:         */
087:        public class HTMLCollection extends SimpleScriptable implements 
088:                Function {
089:            private static final long serialVersionUID = 4049916048017011764L;
090:
091:            private XPath xpath_;
092:            private DomNode node_;
093:
094:            /**
095:             * The transformer used to get the element to return from the html element.
096:             * It returns the html element itself except for frames where it returns the nested window.
097:             */
098:            private Transformer transformer_;
099:
100:            private List cachedElements_;
101:
102:            /**
103:             * Create an instance. Javascript objects must have a default constructor.
104:             */
105:            public HTMLCollection() {
106:                // nothing
107:            }
108:
109:            /**
110:             * Create an instance
111:             * @param parentScope parent scope
112:             */
113:            public HTMLCollection(final SimpleScriptable parentScope) {
114:                setParentScope(parentScope);
115:                setPrototype(getPrototype(getClass()));
116:            }
117:
118:            /**
119:             * Init the content of this collection. The elements will be "calculated" at each
120:             * access using the xpath applied on the node.
121:             * @param node the node to serve as root for the xpath expression
122:             * @param xpath the xpath giving the elements of the collection
123:             */
124:            public void init(final DomNode node, final XPath xpath) {
125:                init(node, xpath, NOPTransformer.INSTANCE);
126:            }
127:
128:            /**
129:             * Init the content of this collection. The elements will be "calculated" at each
130:             * access using the xpath applied on the node and transformed using the transformer.
131:             * @param node the node to serve as root for the xpath expression
132:             * @param xpath the xpath giving the elements of the collection
133:             * @param transformer the transformer allowing to get the expected objects from the xpath
134:             * evaluation
135:             */
136:            public void init(final DomNode node, final XPath xpath,
137:                    final Transformer transformer) {
138:                if (node != null) {
139:                    node_ = node;
140:                    xpath_ = xpath;
141:                    try {
142:                        if (node instanceof  XmlPage) {
143:                            final XmlElement documentElement = ((XmlPage) node)
144:                                    .getDocumentXmlElement();
145:                            if (documentElement != null) {
146:                                addNamespace(documentElement);
147:                            }
148:                        } else if (node instanceof  XmlElement) {
149:                            addNamespace((XmlElement) node);
150:                        }
151:                    } catch (final JaxenException e) {
152:                        throw Context
153:                                .reportRuntimeError("Exception adding namespaces: "
154:                                        + e);
155:                    }
156:                    transformer_ = transformer;
157:                    final DomHtmlAttributeChangeListenerImpl listener = new DomHtmlAttributeChangeListenerImpl();
158:                    node_.addDomChangeListener(listener);
159:                    if (node_ instanceof  HtmlElement) {
160:                        ((HtmlElement) node_)
161:                                .addHtmlAttributeChangeListener(listener);
162:                        cachedElements_ = null;
163:                    }
164:                }
165:            }
166:
167:            /**
168:             * Adds all namespaces defined in the given element and its all descendants to the XPath.
169:             * @param element root element
170:             * @throws JaxenException if a <code>NamespaceContext</code>
171:             *         used by the XPath has been explicitly installed
172:             */
173:            private void addNamespace(final XmlElement element)
174:                    throws JaxenException {
175:                final Map attributes = element.getAttributes();
176:                for (final Iterator keys = attributes.keySet().iterator(); keys
177:                        .hasNext();) {
178:                    final String name = (String) keys.next();
179:                    final String value = (String) ((XmlAttr) attributes
180:                            .get(name)).getValue();
181:                    if (name.startsWith("xmlns:")) {
182:                        final String prefix = name.substring("xmlns:".length());
183:                        xpath_.addNamespace(prefix, value);
184:                    }
185:                }
186:                for (final Iterator children = element.getChildIterator(); children
187:                        .hasNext();) {
188:                    final DomNode child = (DomNode) children.next();
189:                    if (child instanceof  XmlElement) {
190:                        addNamespace((XmlElement) child);
191:                    }
192:                }
193:            }
194:
195:            /**
196:             * {@inheritDoc}
197:             */
198:            public final Object call(final Context context,
199:                    final Scriptable scope, final Scriptable this Obj,
200:                    final Object[] args) throws JavaScriptException {
201:                if (args.length == 0) {
202:                    throw Context
203:                            .reportRuntimeError("Zero arguments; need an index or a key.");
204:                }
205:                final Object response = get(args[0]);
206:                if (response == NOT_FOUND) {
207:                    return null;
208:                }
209:                return response;
210:            }
211:
212:            /**
213:             * {@inheritDoc}
214:             */
215:            public final Scriptable construct(final Context arg0,
216:                    final Scriptable arg1, final Object[] arg2)
217:                    throws JavaScriptException {
218:                return null;
219:            }
220:
221:            /**
222:             * Private helper that retrieves the item or items corresponding to the specified
223:             * index or key.
224:             * @param o The index or key corresponding to the element or elements to return.
225:             * @return The element or elements corresponding to the specified index or key.
226:             */
227:            private Object get(final Object o) {
228:                if (o instanceof  Number) {
229:                    final Number n = (Number) o;
230:                    final int i = n.intValue();
231:                    return get(i, this );
232:                } else {
233:                    final String key = String.valueOf(o);
234:                    return get(key, this );
235:                }
236:            }
237:
238:            /**
239:             * Returns the element at the specified index, or <tt>NOT_FOUND</tt> if the
240:             * index is invalid.
241:             * {@inheritDoc}
242:             */
243:            public final Object get(final int index, final Scriptable start) {
244:                final HTMLCollection array = (HTMLCollection) start;
245:                final List elements = array.getElements();
246:
247:                if (index >= 0 && index < elements.size()) {
248:                    return getScriptableFor(transformer_.transform(elements
249:                            .get(index)));
250:                } else {
251:                    return NOT_FOUND;
252:                }
253:            }
254:
255:            /**
256:             * Gets the html elements. Avoid calling it multiple times within a method because the evaluation
257:             * needs to be performed each time again
258:             * @return the list of {@link HtmlElement} contained in this collection
259:             */
260:            private List getElements() {
261:                if (cachedElements_ == null) {
262:                    try {
263:                        if (node_ != null) {
264:                            cachedElements_ = xpath_.selectNodes(node_);
265:                        } else {
266:                            cachedElements_ = new ArrayList();
267:                        }
268:                        boolean isXmlPage = false;
269:
270:                        //TODO: should be replaced by "getPage() instanceof XmlPage"
271:                        for (DomNode parent = node_; parent != null; parent = parent
272:                                .getParentDomNode()) {
273:                            if (parent instanceof  XmlPage) {
274:                                isXmlPage = true;
275:                            }
276:                        }
277:
278:                        final boolean isIE = getWindow().getWebWindow()
279:                                .getWebClient().getBrowserVersion().isIE();
280:
281:                        for (int i = 0; i < cachedElements_.size(); i++) {
282:                            final DomNode element = (DomNode) cachedElements_
283:                                    .get(i);
284:
285:                            //IE: XmlPage ignores all empty text nodes
286:                            if (isIE
287:                                    && isXmlPage
288:                                    && element instanceof  DomText
289:                                    && ((DomText) element).getNodeValue()
290:                                            .trim().length() == 0) {
291:
292:                                //and 'xml:space' is 'default'
293:                                final Boolean xmlSpaceDefault = isXMLSpaceDefault(element
294:                                        .getParentDomNode());
295:                                if (xmlSpaceDefault != Boolean.FALSE) {
296:                                    cachedElements_.remove(i--);
297:                                    continue;
298:                                }
299:                            }
300:                            for (DomNode parent = element.getParentDomNode(); parent != null; parent = parent
301:                                    .getParentDomNode()) {
302:                                if (parent instanceof  HtmlNoScript) {
303:                                    cachedElements_.remove(i--);
304:                                    break;
305:                                }
306:                            }
307:                        }
308:                    } catch (final JaxenException e) {
309:                        throw Context
310:                                .reportRuntimeError("Exeption getting elements: "
311:                                        + e.getMessage());
312:                    }
313:                }
314:                return cachedElements_;
315:            }
316:
317:            /**
318:             * Recursively checks whether "xml:space" attribute is set to "default".
319:             * @param node node to start checking from.
320:             * @return {@link Boolean#TRUE} if "default" is set, {@link Boolean#FALSE} for other value,
321:             *         or null if nothing is set.
322:             */
323:            private static Boolean isXMLSpaceDefault(DomNode node) {
324:                for (; node instanceof  XmlElement; node = node
325:                        .getParentDomNode()) {
326:                    final String value = ((XmlElement) node)
327:                            .getAttributeValue("xml:space");
328:                    if (value.length() != 0) {
329:                        if (value.equals("default")) {
330:                            return Boolean.TRUE;
331:                        } else {
332:                            return Boolean.FALSE;
333:                        }
334:                    }
335:                }
336:                return null;
337:            }
338:
339:            /**
340:             * Returns the element or elements that match the specified key. If it is the name
341:             * of a property, the property value is returned. If it is the id of an element in
342:             * the array, that element is returned. Finally, if it is the name of an element or
343:             * elements in the array, then all those elements are returned. Otherwise,
344:             * {@link #NOT_FOUND} is returned.
345:             * {@inheritDoc}
346:             */
347:            protected Object getWithPreemption(final String name) {
348:                // Test to see if we are trying to get the length of this collection?
349:                // If so return NOT_FOUND here to let the property be retrieved using the prototype
350:                if ("length".equals(name)) {
351:                    return NOT_FOUND;
352:                }
353:
354:                final List elements = getElements();
355:                CollectionUtils.transform(elements, transformer_);
356:
357:                // See if there is an element in the element array with the specified id.
358:                for (final Iterator iter = elements.iterator(); iter.hasNext();) {
359:                    final Object next = iter.next();
360:                    if (next instanceof  HtmlElement) {
361:                        final HtmlElement element = (HtmlElement) next;
362:                        final String id = element.getId();
363:                        if (id != null && id.equals(name)) {
364:                            getLog().debug(
365:                                    "Property \"" + name
366:                                            + "\" evaluated (by id) to "
367:                                            + element);
368:                            return getScriptableFor(element);
369:                        }
370:                    } else if (next instanceof  WebWindow) {
371:                        final WebWindow window = (WebWindow) next;
372:                        final String windowName = window.getName();
373:                        if (windowName != null && windowName.equals(name)) {
374:                            getLog().debug(
375:                                    "Property \"" + name
376:                                            + "\" evaluated (by name) to "
377:                                            + window);
378:                            return getScriptableFor(window);
379:                        }
380:                    } else {
381:                        getLog().debug(
382:                                "Unrecognized type in array: \""
383:                                        + next.getClass().getName() + "\"");
384:                    }
385:                }
386:
387:                // See if there are any elements in the element array with the specified name.
388:                final HTMLCollection array = new HTMLCollection(this );
389:                try {
390:                    final String newCondition = "@name = '" + name + "'";
391:                    final String currentXPathExpr = xpath_.toString();
392:                    final String xpathExpr;
393:                    if (currentXPathExpr.endsWith("]")) {
394:                        xpathExpr = currentXPathExpr.substring(0,
395:                                currentXPathExpr.length() - 1)
396:                                + " and " + newCondition + "]";
397:                    } else {
398:                        xpathExpr = currentXPathExpr + "[" + newCondition + "]";
399:                    }
400:                    final XPath xpathName = xpath_.getNavigator().parseXPath(
401:                            xpathExpr);
402:                    array.init(node_, xpathName);
403:                } catch (final SAXPathException e) {
404:                    throw Context
405:                            .reportRuntimeError("Failed getting sub elements by name"
406:                                    + e.getMessage());
407:                }
408:
409:                final List subElements = array.getElements();
410:                if (subElements.size() > 1) {
411:                    getLog().debug(
412:                            "Property \"" + name + "\" evaluated (by name) to "
413:                                    + array + " with " + subElements.size()
414:                                    + " elements");
415:                    return array;
416:                } else if (subElements.size() == 1) {
417:                    final SimpleScriptable singleResult = getScriptableFor(subElements
418:                            .get(0));
419:                    getLog().debug(
420:                            "Property \"" + name + "\" evaluated (by name) to "
421:                                    + singleResult);
422:                    return singleResult;
423:                }
424:
425:                // Nothing was found.
426:                return NOT_FOUND;
427:            }
428:
429:            /**
430:             * Returns the length of this element array.
431:             * @return The length of this element array.
432:             * @see <a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/length.asp">MSDN doc</a>
433:             */
434:            public final int jsxGet_length() {
435:                return getElements().size();
436:            }
437:
438:            /**
439:             * Retrieves the item or items corresponding to the specified index or key.
440:             * @param index The index or key corresponding to the element or elements to return.
441:             * @return The element or elements corresponding to the specified index or key.
442:             * @see <a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/item.asp">MSDN doc</a>
443:             */
444:            public final Object jsxFunction_item(final Object index) {
445:                return get(index);
446:            }
447:
448:            /**
449:             * Retrieves the item or items corresponding to the specified name (checks ids, and if
450:             * that does not work, then names).
451:             * @param name The name or id the element or elements to return.
452:             * @return The element or elements corresponding to the specified name or id.
453:             * @see <a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/nameditem.asp">MSDN doc</a>
454:             */
455:            public final Object jsxFunction_namedItem(final String name) {
456:                return get(name);
457:            }
458:
459:            /**
460:             * Returns all the elements in this element array that have the specified tag name.
461:             * This method returns an empty element array if there are no elements with the
462:             * specified tag name.
463:             * @param tagName The name of the tag of the elements to return.
464:             * @return All the elements in this element array that have the specified tag name.
465:             * @see <a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/tags.asp">MSDN doc</a>
466:             */
467:            public final Object jsxFunction_tags(final String tagName) {
468:                final HTMLCollection array = new HTMLCollection(this );
469:                try {
470:                    final String newXPathExpr = xpath_ + "[name() = '"
471:                            + tagName.toLowerCase() + "']";
472:                    array.init(node_, xpath_.getNavigator().parseXPath(
473:                            newXPathExpr));
474:                } catch (final SAXPathException e) {
475:                    // should never occur
476:                    throw Context.reportRuntimeError("Failed call tags: "
477:                            + e.getMessage());
478:                }
479:
480:                return array;
481:            }
482:
483:            /**
484:             * Just for debug purpose.
485:             * {@inheritDoc}
486:             */
487:            public String toString() {
488:                if (xpath_ != null) {
489:                    return super .toString() + '<' + xpath_ + '>';
490:                }
491:                return super .toString();
492:            }
493:
494:            /**
495:             * Called for the js "==".
496:             * {@inheritDoc}
497:             */
498:            protected Object equivalentValues(final Object other) {
499:                if (other == this ) {
500:                    return Boolean.TRUE;
501:                } else if (other instanceof  HTMLCollection) {
502:                    final HTMLCollection otherArray = (HTMLCollection) other;
503:                    if (node_ == otherArray.node_
504:                            && xpath_.toString().equals(
505:                                    otherArray.xpath_.toString())
506:                            && transformer_.equals(otherArray.transformer_)) {
507:                        return Boolean.TRUE;
508:                    } else {
509:                        return NOT_FOUND;
510:                    }
511:                }
512:
513:                return super .equivalentValues(other);
514:            }
515:
516:            /**
517:             * {@inheritDoc}
518:             */
519:            public boolean has(final String name, final Scriptable start) {
520:                if (!getWindow().getWebWindow().getWebClient()
521:                        .getBrowserVersion().isIE()) {
522:                    if (name.equals("0") || name.equals("length")) {
523:                        return true;
524:                    }
525:                    final JavaScriptConfiguration jsConfig = JavaScriptConfiguration
526:                            .getInstance(BrowserVersion.FIREFOX_2);
527:                    final Set functionKeys = jsConfig.getClassConfiguration(
528:                            getClassName()).functionKeys();
529:                    for (final Iterator functionIt = functionKeys.iterator(); functionIt
530:                            .hasNext();) {
531:                        if (name.equals(functionIt.next())) {
532:                            return true;
533:                        }
534:                    }
535:                    return false;
536:                } else {
537:                    return name.equals("length")
538:                            || getWithPreemption(name) != NOT_FOUND;
539:                }
540:            }
541:
542:            /**
543:             * Returns the element or elements that match the specified key. If it is the name
544:             * of a property, the property value is returned. If it is the id of an element in
545:             * the array, that element is returned. Finally, if it is the name of an element or
546:             * elements in the array, then all those elements are returned. Otherwise,
547:             * {@inheritDoc}.
548:             */
549:            public Object[] getIds() {
550:                final List idList = new ArrayList();
551:
552:                if (!getWindow().getWebWindow().getWebClient()
553:                        .getBrowserVersion().isIE()) {
554:                    idList.add("0");
555:                    idList.add("length");
556:                    final JavaScriptConfiguration jsConfig = JavaScriptConfiguration
557:                            .getInstance(BrowserVersion.FIREFOX_2);
558:                    final Set functionKeys = jsConfig.getClassConfiguration(
559:                            getClassName()).functionKeys();
560:                    for (final Iterator functionIt = functionKeys.iterator(); functionIt
561:                            .hasNext();) {
562:                        idList.add(functionIt.next());
563:                    }
564:                    //'document.all.tags' is different from 'document.forms.tags'
565:                    //See HTMLCollectionTest.testTags()
566:                    idList.remove("tags");
567:                } else {
568:                    idList.add("length");
569:
570:                    final List elements = getElements();
571:                    CollectionUtils.transform(elements, transformer_);
572:
573:                    // See if there is an element in the element array with the specified id.
574:                    for (final Iterator iter = elements.iterator(); iter
575:                            .hasNext();) {
576:                        final Object next = iter.next();
577:                        if (next instanceof  HtmlElement) {
578:                            final HtmlElement element = (HtmlElement) next;
579:                            final String id = element.getId();
580:                            if (id != HtmlElement.ATTRIBUTE_NOT_DEFINED) {
581:                                idList.add(id);
582:                            }
583:                        } else if (next instanceof  WebWindow) {
584:                            final WebWindow window = (WebWindow) next;
585:                            final String windowName = window.getName();
586:                            if (windowName != null) {
587:                                idList.add(windowName);
588:                            }
589:                        } else {
590:                            getLog().debug(
591:                                    "Unrecognized type in array: \""
592:                                            + next.getClass().getName() + "\"");
593:                        }
594:                    }
595:
596:                    if (xpath_ != null) {
597:                        // See if there are any elements in the element array with the specified name.
598:                        final HTMLCollection array = new HTMLCollection(this );
599:                        try {
600:                            final String newCondition = "@name";
601:                            final String currentXPathExpr = xpath_.toString();
602:                            final String xpathExpr;
603:                            if (currentXPathExpr.endsWith("]")) {
604:                                xpathExpr = currentXPathExpr.substring(0,
605:                                        currentXPathExpr.length() - 1)
606:                                        + " and " + newCondition + "]";
607:                            } else {
608:                                xpathExpr = currentXPathExpr + "["
609:                                        + newCondition + "]";
610:                            }
611:                            final XPath xpathName = xpath_.getNavigator()
612:                                    .parseXPath(xpathExpr);
613:                            array.init(node_, xpathName);
614:                        } catch (final SAXPathException e) {
615:                            throw Context
616:                                    .reportRuntimeError("Failed getting sub elements by name"
617:                                            + e.getMessage());
618:                        }
619:
620:                        final List subElements = array.getElements();
621:                        for (final Iterator it = subElements.iterator(); it
622:                                .hasNext();) {
623:                            final DomNode next = (DomNode) it.next();
624:                            if (next instanceof  HtmlElement) {
625:                                final HtmlElement element = (HtmlElement) next;
626:                                final String id = element.getAttribute("name");
627:                                if (id != null) {
628:                                    idList.add(id);
629:                                }
630:                            }
631:                        }
632:                    }
633:                }
634:                return idList.toArray();
635:            }
636:
637:            private class DomHtmlAttributeChangeListenerImpl implements 
638:                    DomChangeListener, HtmlAttributeChangeListener {
639:                /**
640:                 * {@inheritDoc}
641:                 */
642:                public void nodeAdded(final DomChangeEvent event) {
643:                    cachedElements_ = null;
644:                }
645:
646:                /**
647:                 * {@inheritDoc}
648:                 */
649:                public void nodeDeleted(final DomChangeEvent event) {
650:                    cachedElements_ = null;
651:                }
652:
653:                /**
654:                 * {@inheritDoc}
655:                 */
656:                public void attributeAdded(final HtmlAttributeChangeEvent event) {
657:                    cachedElements_ = null;
658:                }
659:
660:                /**
661:                 * {@inheritDoc}
662:                 */
663:                public void attributeRemoved(
664:                        final HtmlAttributeChangeEvent event) {
665:                    cachedElements_ = null;
666:                }
667:
668:                /**
669:                 * {@inheritDoc}
670:                 */
671:                public void attributeReplaced(
672:                        final HtmlAttributeChangeEvent event) {
673:                    cachedElements_ = null;
674:                }
675:            }
676:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.