Source Code Cross Referenced for HTMLElement.java in  » Testing » htmlunit » com » gargoylesoftware » htmlunit » javascript » host » 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.host 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 2002-2008 Gargoyle Software Inc. All rights reserved.
0003:         *
0004:         * Redistribution and use in source and binary forms, with or without
0005:         * modification, are permitted provided that the following conditions are met:
0006:         *
0007:         * 1. Redistributions of source code must retain the above copyright notice,
0008:         *    this list of conditions and the following disclaimer.
0009:         * 2. Redistributions in binary form must reproduce the above copyright notice,
0010:         *    this list of conditions and the following disclaimer in the documentation
0011:         *    and/or other materials provided with the distribution.
0012:         * 3. The end-user documentation included with the redistribution, if any, must
0013:         *    include the following acknowledgment:
0014:         *
0015:         *       "This product includes software developed by Gargoyle Software Inc.
0016:         *        (http://www.GargoyleSoftware.com/)."
0017:         *
0018:         *    Alternately, this acknowledgment may appear in the software itself, if
0019:         *    and wherever such third-party acknowledgments normally appear.
0020:         * 4. The name "Gargoyle Software" must not be used to endorse or promote
0021:         *    products derived from this software without prior written permission.
0022:         *    For written permission, please contact info@GargoyleSoftware.com.
0023:         * 5. Products derived from this software may not be called "HtmlUnit", nor may
0024:         *    "HtmlUnit" appear in their name, without prior written permission of
0025:         *    Gargoyle Software Inc.
0026:         *
0027:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
0028:         * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
0029:         * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
0030:         * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
0031:         * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0032:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
0033:         * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0034:         * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0035:         * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
0036:         * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0037:         */
0038:        package com.gargoylesoftware.htmlunit.javascript.host;
0039:
0040:        import java.io.IOException;
0041:        import java.lang.reflect.InvocationTargetException;
0042:        import java.lang.reflect.Method;
0043:        import java.net.MalformedURLException;
0044:        import java.net.URL;
0045:        import java.util.Arrays;
0046:        import java.util.HashSet;
0047:        import java.util.Iterator;
0048:        import java.util.List;
0049:        import java.util.Set;
0050:
0051:        import org.apache.commons.lang.StringUtils;
0052:        import org.jaxen.JaxenException;
0053:        import org.jaxen.XPath;
0054:        import org.mozilla.javascript.BaseFunction;
0055:        import org.mozilla.javascript.Context;
0056:        import org.mozilla.javascript.ContextAction;
0057:        import org.mozilla.javascript.Function;
0058:        import org.mozilla.javascript.NativeArray;
0059:        import org.mozilla.javascript.Scriptable;
0060:        import org.xml.sax.SAXException;
0061:        import org.xml.sax.helpers.AttributesImpl;
0062:
0063:        import com.gargoylesoftware.htmlunit.BrowserVersion;
0064:        import com.gargoylesoftware.htmlunit.ScriptResult;
0065:        import com.gargoylesoftware.htmlunit.WebClient;
0066:        import com.gargoylesoftware.htmlunit.WebRequestSettings;
0067:        import com.gargoylesoftware.htmlunit.WebResponse;
0068:        import com.gargoylesoftware.htmlunit.html.ClickableElement;
0069:        import com.gargoylesoftware.htmlunit.html.DomCharacterData;
0070:        import com.gargoylesoftware.htmlunit.html.DomComment;
0071:        import com.gargoylesoftware.htmlunit.html.DomDocumentFragment;
0072:        import com.gargoylesoftware.htmlunit.html.DomNode;
0073:        import com.gargoylesoftware.htmlunit.html.DomText;
0074:        import com.gargoylesoftware.htmlunit.html.HTMLParser;
0075:        import com.gargoylesoftware.htmlunit.html.HtmlAttr;
0076:        import com.gargoylesoftware.htmlunit.html.HtmlBody;
0077:        import com.gargoylesoftware.htmlunit.html.HtmlDivision;
0078:        import com.gargoylesoftware.htmlunit.html.HtmlElement;
0079:        import com.gargoylesoftware.htmlunit.html.HtmlFrameSet;
0080:        import com.gargoylesoftware.htmlunit.html.HtmlPage;
0081:        import com.gargoylesoftware.htmlunit.html.HtmlTable;
0082:        import com.gargoylesoftware.htmlunit.html.HtmlTableDataCell;
0083:        import com.gargoylesoftware.htmlunit.html.xpath.HtmlUnitXPath;
0084:        import com.gargoylesoftware.htmlunit.javascript.HTMLCollection;
0085:        import com.gargoylesoftware.htmlunit.javascript.NamedNodeMap;
0086:        import com.gargoylesoftware.htmlunit.javascript.ScriptableWithFallbackGetter;
0087:
0088:        /**
0089:         * The javascript object "HTMLElement" which is the base class for all HTML
0090:         * objects. This will typically wrap an instance of {@link HtmlElement}.
0091:         *
0092:         * @version $Revision: 2155 $
0093:         * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
0094:         * @author David K. Taylor
0095:         * @author Barnaby Court
0096:         * @author <a href="mailto:cse@dynabean.de">Christian Sell</a>
0097:         * @author Chris Erskine
0098:         * @author David D. Kilzer
0099:         * @author Daniel Gredler
0100:         * @author Marc Guillemot
0101:         * @author Hans Donner
0102:         * @author Bruce Faulkner
0103:         * @author Ahmed Ashour
0104:         */
0105:        public class HTMLElement extends Element implements 
0106:                ScriptableWithFallbackGetter {
0107:
0108:            private static final long serialVersionUID = -6864034414262085851L;
0109:            private static final int BEHAVIOR_ID_UNKNOWN = -1;
0110:            private static final int BEHAVIOR_ID_CLIENT_CAPS = 0;
0111:            private static final int BEHAVIOR_ID_HOMEPAGE = 1;
0112:            private static final int BEHAVIOR_ID_DOWNLOAD = 2;
0113:            private static final String BEHAVIOR_CLIENT_CAPS = "#default#clientCaps";
0114:            private static final String BEHAVIOR_HOMEPAGE = "#default#homePage";
0115:            private static final String BEHAVIOR_DOWNLOAD = "#default#download";
0116:            static final String POSITION_BEFORE_BEGIN = "beforeBegin";
0117:            static final String POSITION_AFTER_BEGIN = "afterBegin";
0118:            static final String POSITION_BEFORE_END = "beforeEnd";
0119:            static final String POSITION_AFTER_END = "afterEnd";
0120:
0121:            /**
0122:             * Static counter for {@link #uniqueID_}.
0123:             */
0124:            private static int UniqueID_Counter_ = 1;
0125:
0126:            private final Set behaviors_ = new HashSet();
0127:            private BoxObject boxObject_; // lazy init
0128:            private HTMLCollection all_; // has to be a member to have equality (==) working
0129:            private int scrollLeft_;
0130:            private int scrollTop_;
0131:            private String uniqueID_;
0132:
0133:            /**
0134:             * The tag names of the objects for which outerHTML is readonly
0135:             */
0136:            private static final List OUTER_HTML_READONLY = Arrays
0137:                    .asList(new String[] { "caption", "col", "colgroup",
0138:                            "frameset", "html", "tbody", "td", "tfoot", "th",
0139:                            "thead", "tr" });
0140:
0141:            private Style style_;
0142:
0143:            /**
0144:             * Create an instance.
0145:             */
0146:            public HTMLElement() {
0147:                // Empty.
0148:            }
0149:
0150:            /**
0151:             * Return the value of the "all" property.
0152:             * @return The value of the "all" property
0153:             */
0154:            public HTMLCollection jsxGet_all() {
0155:                if (all_ == null) {
0156:                    all_ = new HTMLCollection(this );
0157:                    try {
0158:                        all_.init(getDomNodeOrDie(), new HtmlUnitXPath(".//*"));
0159:                    } catch (final JaxenException e) {
0160:                        throw Context
0161:                                .reportRuntimeError("Failed to initialize collection all: "
0162:                                        + e.getMessage());
0163:                    }
0164:                }
0165:                return all_;
0166:            }
0167:
0168:            /**
0169:             * Return the style object for this element.
0170:             *
0171:             * @return The style object
0172:             */
0173:            public Object jsxGet_style() {
0174:                return style_;
0175:            }
0176:
0177:            /**
0178:             * Returns the current style object for this element.
0179:             * @return The current style object
0180:             */
0181:            public Object jsxGet_currentStyle() {
0182:                return style_;
0183:            }
0184:
0185:            /**
0186:             * Returns the runtime style object for this element.
0187:             * @return The runtime style object
0188:             */
0189:            public Object jsxGet_runtimeStyle() {
0190:                return style_;
0191:            }
0192:
0193:            /**
0194:             * Set the DOM node that corresponds to this javascript object
0195:             * @param domNode The DOM node
0196:             */
0197:            public void setDomNode(final DomNode domNode) {
0198:                super .setDomNode(domNode);
0199:
0200:                style_ = new Style(this );
0201:
0202:                /**
0203:                 * Convert javascript snippets defined in the attribute map to executable event handlers.
0204:                 * Should be called only on construction.
0205:                 */
0206:                final HtmlElement htmlElt = (HtmlElement) domNode;
0207:                for (final Iterator iter = htmlElt
0208:                        .getAttributeEntriesIterator(); iter.hasNext();) {
0209:                    final HtmlAttr entry = (HtmlAttr) iter.next();
0210:                    final String eventName = entry.getName();
0211:                    if (eventName.startsWith("on")) {
0212:                        // TODO: check that it is an "allowed" event for the browser, and take care to the case
0213:                        final BaseFunction eventHandler = new EventHandler(
0214:                                htmlElt, eventName, (String) entry
0215:                                        .getHtmlValue());
0216:                        setEventHandler(eventName, eventHandler);
0217:                        // forward onload, onclick, ondblclick, ... to window
0218:                        if ((domNode instanceof  HtmlBody || domNode instanceof  HtmlFrameSet)) {
0219:                            getWindow().getEventListenersContainer()
0220:                                    .setEventHandlerProp(
0221:                                            eventName.substring(2),
0222:                                            eventHandler);
0223:                        }
0224:                    }
0225:                }
0226:            }
0227:
0228:            /**
0229:             * Return the element ID.
0230:             * @return The ID of this element.
0231:             */
0232:            public String jsxGet_id() {
0233:                return getHtmlElementOrDie().getId();
0234:            }
0235:
0236:            /**
0237:             * Set the identifier this element.
0238:             * @param newId The new identifier of this element.
0239:             */
0240:            public void jsxSet_id(final String newId) {
0241:                getHtmlElementOrDie().setId(newId);
0242:            }
0243:
0244:            /**
0245:             * Return the element title.
0246:             * @return The ID of this element.
0247:             */
0248:            public String jsxGet_title() {
0249:                return getHtmlElementOrDie().getAttributeValue("title");
0250:            }
0251:
0252:            /**
0253:             * Set the title of this element.
0254:             * @param newTitle The new identifier of this element.
0255:             */
0256:            public void jsxSet_title(final String newTitle) {
0257:                getHtmlElementOrDie().setAttributeValue("title", newTitle);
0258:            }
0259:
0260:            /**
0261:             * Return true if this element is disabled.
0262:             * @return True if this element is disabled.
0263:             */
0264:            public boolean jsxGet_disabled() {
0265:                return getHtmlElementOrDie().isAttributeDefined("disabled");
0266:            }
0267:
0268:            /**
0269:             * Set whether or not to disable this element
0270:             * @param disabled True if this is to be disabled.
0271:             */
0272:            public void jsxSet_disabled(final boolean disabled) {
0273:                final HtmlElement element = getHtmlElementOrDie();
0274:                if (disabled) {
0275:                    element.setAttributeValue("disabled", "disabled");
0276:                } else {
0277:                    element.removeAttribute("disabled");
0278:                }
0279:            }
0280:
0281:            /**
0282:             * Return the tag name of this element.
0283:             * @return The tag name in uppercase.
0284:             */
0285:            public String jsxGet_tagName() {
0286:                String tagName = getHtmlElementOrDie().getTagName();
0287:                if (jsxGet_namespaceURI() == null) {
0288:                    tagName = tagName.toUpperCase();
0289:                }
0290:                return tagName;
0291:            }
0292:
0293:            /**
0294:             * Returns The URI that identifies an XML namespace.
0295:             * @return The URI that identifies an XML namespace.
0296:             */
0297:            public String jsxGet_namespaceURI() {
0298:                return getHtmlElementOrDie().getNamespaceURI();
0299:            }
0300:
0301:            /**
0302:             * Returns The local name (without prefix).
0303:             * @return The local name (without prefix).
0304:             */
0305:            public String jsxGet_localName() {
0306:                String localName = getHtmlElementOrDie().getLocalName();
0307:                if (jsxGet_namespaceURI() == null) {
0308:                    localName = localName.toUpperCase();
0309:                }
0310:                return localName;
0311:            }
0312:
0313:            /**
0314:             * Returns The Namespace prefix
0315:             * @return The Namespace prefix.
0316:             */
0317:            public String jsxGet_prefix() {
0318:                return getHtmlElementOrDie().getPrefix();
0319:            }
0320:
0321:            /**
0322:             * Return the owner document
0323:             * @return the document
0324:             */
0325:            public Object jsxGet_ownerDocument() {
0326:                return getWindow().jsxGet_document();
0327:            }
0328:
0329:            /**
0330:             * Looks at attributes with the given name
0331:             * {@inheritDoc}
0332:             */
0333:            public Object getWithFallback(final String name) {
0334:                final HtmlElement htmlElement = getHtmlElementOrNull();
0335:                // can name be an attribute of current element?
0336:                // first approximation: attribute are all lowercase
0337:                // this should be improved because it's wrong. For instance: tabIndex, hideFocus, acceptCharset
0338:                if (htmlElement != null && name.toLowerCase().equals(name)) {
0339:                    final String value = htmlElement.getAttributeValue(name);
0340:                    if (HtmlElement.ATTRIBUTE_NOT_DEFINED != value) {
0341:                        getLog().debug(
0342:                                "Found attribute for evaluation of property \""
0343:                                        + name + "\" for of " + this );
0344:                        return value;
0345:                    }
0346:                }
0347:
0348:                return NOT_FOUND;
0349:            }
0350:
0351:            /**
0352:             * Returns a collection of the attributes of this element.
0353:             * @return a collection of the attributes of this element
0354:             * @see <a href="http://developer.mozilla.org/en/docs/DOM:element.attributes">Gecko DOM Reference</a>
0355:             */
0356:            public NamedNodeMap jsxGet_attributes() {
0357:                return new NamedNodeMap(getHtmlElementOrDie());
0358:            }
0359:
0360:            /**
0361:             * Gets the specified attribute.
0362:             * @param attributeName attribute name.
0363:             * @return The value of the specified attribute, <code>null</code> if the attribute is not defined
0364:             */
0365:            public String jsxFunction_getAttribute(final String attributeName) {
0366:                final String value = getHtmlElementOrDie().getAttributeValue(
0367:                        attributeName);
0368:                if (value == HtmlElement.ATTRIBUTE_NOT_DEFINED) {
0369:                    return null;
0370:                } else {
0371:                    return value;
0372:                }
0373:            }
0374:
0375:            /**
0376:             * Gets the specified attribute.
0377:             * @param namespaceURI the namespace URI
0378:             * @param localName the local name of the attribute to look for
0379:             * @return The value of the specified attribute, <code>null</code> if the attribute is not defined
0380:             */
0381:            public String jsxFunction_getAttributeNS(final String namespaceURI,
0382:                    final String localName) {
0383:                return getHtmlElementOrDie().getAttributeNS(namespaceURI,
0384:                        localName);
0385:            }
0386:
0387:            /**
0388:             * Test for attribute.
0389:             * See also <a href="http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-ElHasAttr">
0390:             * the DOM reference</a>
0391:             *
0392:             * @param name Name of the attribute to test
0393:             * @return <code>true</code> if the node has this attribute
0394:             */
0395:            public boolean jsxFunction_hasAttribute(final String name) {
0396:                return getHtmlElementOrDie().getAttribute(name) != HtmlElement.ATTRIBUTE_NOT_DEFINED;
0397:            }
0398:
0399:            /**
0400:             * Test for attribute.
0401:             * See also <a href="http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-ElHasAttrNS">
0402:             * the DOM reference</a>
0403:             *
0404:             * @param namespaceURI the namespace URI
0405:             * @param localName the local name of the attribute to look for
0406:             * @return <code>true</code> if the node has this attribute
0407:             */
0408:            public boolean jsxFunction_hasAttributeNS(
0409:                    final String namespaceURI, final String localName) {
0410:                return getHtmlElementOrDie().getAttributeNS(namespaceURI,
0411:                        localName) != HtmlElement.ATTRIBUTE_NOT_DEFINED;
0412:            }
0413:
0414:            /**
0415:             * Set an attribute.
0416:             * See also <a href="http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-F68F082">
0417:             * the DOM reference</a>
0418:             *
0419:             * @param name Name of the attribute to set
0420:             * @param value Value to set the attribute to
0421:             */
0422:            public void jsxFunction_setAttribute(final String name,
0423:                    final String value) {
0424:                getHtmlElementOrDie().setAttributeValue(name, value);
0425:
0426:                //FF: call corresponding event handler jsxSet_onxxx if found
0427:                if (getWindow().getWebWindow().getWebClient()
0428:                        .getBrowserVersion().isNetscape()) {
0429:                    try {
0430:                        final Method method = getClass().getMethod(
0431:                                "jsxSet_" + name, new Class[] { Object.class });
0432:                        final String source = "function(){" + value + "}";
0433:                        method.invoke(this , new Object[] { Context
0434:                                .getCurrentContext().compileFunction(
0435:                                        getWindow(), source, "", 0, null) });
0436:                    } catch (final NoSuchMethodException e) {
0437:                        //silently ignore
0438:                    } catch (final IllegalAccessException e) {
0439:                        //silently ignore
0440:                    } catch (final InvocationTargetException e) {
0441:                        throw new RuntimeException(e.getCause());
0442:                    }
0443:                }
0444:            }
0445:
0446:            /**
0447:             * Sets the specified attribute.
0448:             * @param namespaceURI the namespace URI
0449:             * @param qualifiedName the local name of the attribute to look for
0450:             * @param value the new attribute value
0451:             */
0452:            public void jsxFunction_setAttributeNS(final String namespaceURI,
0453:                    final String qualifiedName, final String value) {
0454:                getHtmlElementOrDie().setAttributeValue(namespaceURI,
0455:                        qualifiedName, value);
0456:            }
0457:
0458:            /**
0459:             * Remove an attribute.
0460:             *
0461:             * @param name Name of the attribute to remove
0462:             */
0463:            public void jsxFunction_removeAttribute(final String name) {
0464:                getHtmlElementOrDie().removeAttribute(name);
0465:            }
0466:
0467:            /**
0468:             * Gets the attribute node for the specified attribute.
0469:             * @param attributeName the name of the attribute to retrieve
0470:             * @return the attribute node for the specified attribute.
0471:             */
0472:            public Object jsxFunction_getAttributeNode(
0473:                    final String attributeName) {
0474:                final Attribute att = new Attribute();
0475:                att.setPrototype(getPrototype(Attribute.class));
0476:                att.setParentScope(getWindow());
0477:                att.init(attributeName, getHtmlElementOrDie());
0478:                return att;
0479:            }
0480:
0481:            /**
0482:             * Sets the attribute node for the specified attribute.
0483:             * @param newAtt the attribute to set.
0484:             * @return the replaced attribute node, if any.
0485:             */
0486:            public Attribute jsxFunction_setAttributeNode(final Attribute newAtt) {
0487:                final String name = newAtt.jsxGet_name();
0488:                final String value = newAtt.jsxGet_value();
0489:                final Attribute replacedAtt = (Attribute) jsxFunction_getAttributeNode(name);
0490:                replacedAtt.detachFromParent();
0491:                getHtmlElementOrDie().setAttributeValue(name, value);
0492:                return replacedAtt;
0493:            }
0494:
0495:            /**
0496:             * Returns all the descendant elements with the specified tag name.
0497:             * @param tagName the name to search for
0498:             * @return all the descendant elements with the specified tag name
0499:             */
0500:            public Object jsxFunction_getElementsByTagName(final String tagName) {
0501:                final DomNode node = getDomNodeOrDie();
0502:                final HTMLCollection collection = new HTMLCollection(this );
0503:                try {
0504:                    final String xpath;
0505:                    if ("*".equals(tagName)) {
0506:                        xpath = "//*";
0507:                    } else {
0508:                        xpath = "//node()[name() = '" + tagName.toLowerCase()
0509:                                + "']";
0510:                    }
0511:                    collection.init(node, new HtmlUnitXPath(xpath,
0512:                            HtmlUnitXPath.buildSubtreeNavigator(node)));
0513:                } catch (final JaxenException e) {
0514:                    final String msg = "Error initializing collection getElementsByTagName("
0515:                            + tagName + "): ";
0516:                    throw Context.reportRuntimeError(msg + e.getMessage());
0517:                }
0518:                return collection;
0519:            }
0520:
0521:            /**
0522:             * Return the class defined for this element
0523:             * @return the class name
0524:             */
0525:            public Object jsxGet_className() {
0526:                return getHtmlElementOrDie().getAttributeValue("class");
0527:            }
0528:
0529:            /**
0530:             * Set the class attribute for this element.
0531:             * @param className - the new class name
0532:             */
0533:            public void jsxSet_className(final String className) {
0534:                getHtmlElementOrDie().setAttributeValue("class", className);
0535:            }
0536:
0537:            /**
0538:             * Get the innerHTML attribute
0539:             * @return the contents of this node as html
0540:             */
0541:            public String jsxGet_innerHTML() {
0542:                final StringBuffer buf = new StringBuffer();
0543:                // we can't rely on DomNode.asXml because it adds indentation and new lines
0544:                printChildren(buf, getDomNodeOrDie(), !"SCRIPT"
0545:                        .equals(jsxGet_tagName()));
0546:                return buf.toString();
0547:            }
0548:
0549:            /**
0550:             * Get the innerText attribute
0551:             * @return the contents of this node as text
0552:             */
0553:            public String jsxGet_innerText() {
0554:                final StringBuffer buf = new StringBuffer();
0555:                // we can't rely on DomNode.asXml because it adds indentation and new lines
0556:                printChildren(buf, getDomNodeOrDie(), false);
0557:                return buf.toString();
0558:            }
0559:
0560:            /**
0561:             * Gets the outerHTML of the node.
0562:             * @see <a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/outerhtml.asp">
0563:             * MSDN documentation</a>
0564:             * @return the contents of this node as HTML
0565:             */
0566:            public String jsxGet_outerHTML() {
0567:                final StringBuffer buf = new StringBuffer();
0568:                // we can't rely on DomNode.asXml because it adds indentation and new lines
0569:                printNode(buf, getDomNodeOrDie(), true);
0570:                return buf.toString();
0571:            }
0572:
0573:            private void printChildren(final StringBuffer buffer,
0574:                    final DomNode node, final boolean html) {
0575:                for (final Iterator iter = node.getChildIterator(); iter
0576:                        .hasNext();) {
0577:                    printNode(buffer, (DomNode) iter.next(), html);
0578:                }
0579:            }
0580:
0581:            private void printNode(final StringBuffer buffer,
0582:                    final DomNode node, final boolean html) {
0583:                if (node instanceof  DomComment) {
0584:                    // Remove whitespace sequences.
0585:                    final String s = node.getNodeValue().replaceAll("  ", " ");
0586:                    buffer.append("<!--").append(s).append("-->");
0587:                } else if (node instanceof  DomCharacterData) {
0588:                    // Remove whitespace sequences, possibly escape XML characters.
0589:                    String s = node.getNodeValue().replaceAll("  ", " ");
0590:                    if (html) {
0591:                        s = com.gargoylesoftware.htmlunit.util.StringUtils
0592:                                .escapeXmlChars(s);
0593:                    }
0594:                    buffer.append(s);
0595:                } else if (html) {
0596:                    // Start the tag name. IE does it in uppercase, FF in lowercase.
0597:                    final HtmlElement element = (HtmlElement) node;
0598:                    final boolean ie = getWindow().getWebWindow()
0599:                            .getWebClient().getBrowserVersion().isIE();
0600:                    String tag = element.getTagName();
0601:                    if (ie) {
0602:                        tag = tag.toUpperCase();
0603:                    }
0604:                    buffer.append("<").append(tag);
0605:                    // Add the attributes. IE does not use quotes, FF does.
0606:                    for (final Iterator iterator = element
0607:                            .getAttributeEntriesIterator(); iterator.hasNext();) {
0608:                        final HtmlAttr entry = (HtmlAttr) iterator.next();
0609:                        final String name = entry.getName();
0610:                        final String value = (String) entry.getHtmlValue();
0611:                        final boolean quote = !ie
0612:                                || com.gargoylesoftware.htmlunit.util.StringUtils
0613:                                        .containsWhitespace(value);
0614:                        buffer.append(' ').append(name).append("=");
0615:                        if (quote) {
0616:                            buffer.append("\"");
0617:                        }
0618:                        buffer.append(value);
0619:                        if (quote) {
0620:                            buffer.append("\"");
0621:                        }
0622:                    }
0623:                    buffer.append(">");
0624:                    // Add the children.
0625:                    printChildren(buffer, node, html);
0626:                    // Close the tag. IE does it in uppercase, FF in lowercase.
0627:                    buffer.append("</").append(tag).append(">");
0628:                } else {
0629:                    final HtmlElement element = (HtmlElement) node;
0630:                    if (element.getTagName().equals("p")) {
0631:                        buffer.append("\r\n"); // \r\n because it's to implement something IE specific
0632:                    }
0633:                    if (!element.getTagName().equals("script")) {
0634:                        printChildren(buffer, node, html);
0635:                    }
0636:                }
0637:            }
0638:
0639:            /**
0640:             * Replace all children elements of this element with the supplied value.
0641:             * @param value - the new value for the contents of this node
0642:             */
0643:            public void jsxSet_innerHTML(final Object value) {
0644:                final DomNode domNode = getDomNodeOrDie();
0645:                domNode.removeAllChildren();
0646:
0647:                final BrowserVersion browserVersion = getWindow()
0648:                        .getWebWindow().getWebClient().getBrowserVersion();
0649:
0650:                // null && IE     -> add child
0651:                // null && non-IE -> Don't add
0652:                // ''             -> Don't add
0653:                if ((value == null && browserVersion.isIE())
0654:                        || (value != null && !"".equals(value))) {
0655:
0656:                    final String valueAsString = Context.toString(value);
0657:                    parseHtmlSnippet(domNode, true, valueAsString);
0658:
0659:                    //if the parentNode has null parentNode in IE,
0660:                    //create a DocumentFragment to be the parentNode's parentNode.
0661:                    if (domNode.getParentDomNode() == null
0662:                            && getWindow().getWebWindow().getWebClient()
0663:                                    .getBrowserVersion().isIE()) {
0664:                        final DomDocumentFragment fragment = domNode.getPage()
0665:                                .createDomDocumentFragment();
0666:                        fragment.appendDomChild(domNode);
0667:                    }
0668:                }
0669:            }
0670:
0671:            /**
0672:             * Replace all children elements of this element with the supplied value.
0673:             * @param value - the new value for the contents of this node
0674:             */
0675:            public void jsxSet_innerText(final String value) {
0676:                final DomNode domNode = getDomNodeOrDie();
0677:                domNode.removeAllChildren();
0678:
0679:                final DomNode node = new DomText(getDomNodeOrDie().getPage(),
0680:                        value);
0681:                domNode.appendDomChild(node);
0682:
0683:                //if the parentNode has null parentNode in IE,
0684:                //create a DocumentFragment to be the parentNode's parentNode.
0685:                if (domNode.getParentDomNode() == null
0686:                        && getWindow().getWebWindow().getWebClient()
0687:                                .getBrowserVersion().isIE()) {
0688:                    final DomDocumentFragment fragment = domNode.getPage()
0689:                            .createDomDocumentFragment();
0690:                    fragment.appendDomChild(domNode);
0691:                }
0692:            }
0693:
0694:            /**
0695:             * Replace all children elements of this element with the supplied value.
0696:             * Sets the outerHTML of the node.
0697:             * @see <a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/outerhtml.asp">
0698:             * MSDN documentation</a>
0699:             * @param value - the new value for replacing this node
0700:             */
0701:            public void jsxSet_outerHTML(final String value) {
0702:                final DomNode domNode = getDomNodeOrDie();
0703:
0704:                if (OUTER_HTML_READONLY.contains(domNode.getNodeName())) {
0705:                    throw Context
0706:                            .reportRuntimeError("outerHTML is read-only for tag "
0707:                                    + domNode.getNodeName());
0708:                }
0709:
0710:                parseHtmlSnippet(domNode, false, value);
0711:                domNode.remove();
0712:            }
0713:
0714:            /**
0715:             * Parses the html code
0716:             * @param htmlSnippet the html code extract to parse
0717:             */
0718:            private void parseHtmlSnippet(final DomNode target,
0719:                    final boolean append, final String source) {
0720:
0721:                final DomNode proxyNode = new HtmlDivision(null,
0722:                        HtmlDivision.TAG_NAME, target.getPage(), null) {
0723:                    private static final long serialVersionUID = 2108037256628269797L;
0724:
0725:                    public DomNode appendDomChild(final DomNode node) {
0726:                        if (append) {
0727:                            return target.appendDomChild(node);
0728:                        } else {
0729:                            target.insertBefore(node);
0730:                            return node;
0731:                        }
0732:                    }
0733:                };
0734:
0735:                try {
0736:                    HTMLParser.parseFragment(proxyNode, source);
0737:                } catch (final IOException e) {
0738:                    getLog()
0739:                            .error(
0740:                                    "Unexpected exception occurred while parsing html snippet",
0741:                                    e);
0742:                    throw Context
0743:                            .reportRuntimeError("Unexpected exception occurred while parsing html snippet: "
0744:                                    + e.getMessage());
0745:                } catch (final SAXException e) {
0746:                    getLog()
0747:                            .error(
0748:                                    "Unexpected exception occurred while parsing html snippet",
0749:                                    e);
0750:                    throw Context
0751:                            .reportRuntimeError("Unexpected exception occurred while parsing html snippet: "
0752:                                    + e.getMessage());
0753:                }
0754:            }
0755:
0756:            /**
0757:             * Gets the attributes of the element in the form of a {@link org.xml.sax.Attributes}
0758:             * @param element the element to read the attributes from
0759:             * @return the attributes
0760:             */
0761:            protected AttributesImpl readAttributes(final HtmlElement element) {
0762:                final AttributesImpl attributes = new AttributesImpl();
0763:                for (final Iterator iter = element
0764:                        .getAttributeEntriesIterator(); iter.hasNext();) {
0765:                    final HtmlAttr entry = (HtmlAttr) iter.next();
0766:                    final String name = entry.getName();
0767:                    final String value = (String) entry.getHtmlValue();
0768:                    attributes.addAttribute(null, name, name, null, value);
0769:                }
0770:
0771:                return attributes;
0772:            }
0773:
0774:            /**
0775:             * Inserts the given HTML text into the element at the location.
0776:             * @see <a href="http://msdn2.microsoft.com/en-us/library/ms536452.aspx">
0777:             * MSDN documentation</a>
0778:             * @param where specifies where to insert the HTML text, using one of the following value:
0779:             *        beforeBegin, afterBegin, beforeEnd, afterEnd
0780:             * @param text the HTML text to insert
0781:             */
0782:            public void jsxFunction_insertAdjacentHTML(final String where,
0783:                    final String text) {
0784:                final Object[] values = getInsertAdjacentLocation(where);
0785:                final DomNode node = (DomNode) values[0];
0786:                final boolean append = ((Boolean) values[1]).booleanValue();
0787:
0788:                // add the new nodes
0789:                parseHtmlSnippet(node, append, text);
0790:            }
0791:
0792:            /**
0793:             * Inserts the given element into the element at the location.
0794:             * @see <a href="http://msdn2.microsoft.com/en-us/library/ms536451.aspx">
0795:             * MSDN documentation</a>
0796:             * @param where specifies where to insert the element, using one of the following value:
0797:             *        beforeBegin, afterBegin, beforeEnd, afterEnd
0798:             * @param object the element to insert
0799:             * @return an element object
0800:             */
0801:            public Object jsxFunction_insertAdjacentElement(final String where,
0802:                    final Object object) {
0803:                if (object instanceof  Node) {
0804:                    final DomNode childNode = ((Node) object).getDomNodeOrDie();
0805:                    final Object[] values = getInsertAdjacentLocation(where);
0806:                    final DomNode node = (DomNode) values[0];
0807:                    final boolean append = ((Boolean) values[1]).booleanValue();
0808:
0809:                    if (append) {
0810:                        node.appendDomChild(childNode);
0811:                    } else {
0812:                        node.insertBefore(childNode);
0813:                    }
0814:                    return object;
0815:                } else {
0816:                    throw Context
0817:                            .reportRuntimeError("Passed object is not an element: "
0818:                                    + object);
0819:                }
0820:            }
0821:
0822:            /**
0823:             * Returns where and how to add the new node.
0824:             * Used by {@link #jsxFunction_insertAdjacentHTML(String, String)} and
0825:             * {@link #jsxFunction_insertAdjacentElement(String, Object)}.
0826:             *
0827:             * @param where specifies where to insert the element, using one of the following value:
0828:             *        beforeBegin, afterBegin, beforeEnd, afterEnd
0829:             *
0830:             * @return an array of 1-DomNode:parentNode and 2-Boolean:append
0831:             */
0832:            private Object[] getInsertAdjacentLocation(final String where) {
0833:                final DomNode currentNode = getDomNodeOrDie();
0834:                final DomNode node;
0835:                final boolean append;
0836:
0837:                // compute the where and how the new nodes should be added
0838:                if (POSITION_AFTER_BEGIN.equalsIgnoreCase(where)) {
0839:                    if (currentNode.getFirstDomChild() == null) {
0840:                        // new nodes should appended to the children of current node
0841:                        node = currentNode;
0842:                        append = true;
0843:                    } else {
0844:                        // new nodes should be inserted before first child
0845:                        node = currentNode.getFirstDomChild();
0846:                        append = false;
0847:                    }
0848:                } else if (POSITION_BEFORE_BEGIN.equalsIgnoreCase(where)) {
0849:                    // new nodes should be inserted before current node
0850:                    node = currentNode;
0851:                    append = false;
0852:                } else if (POSITION_BEFORE_END.equalsIgnoreCase(where)) {
0853:                    // new nodes should appended to the children of current node
0854:                    node = currentNode;
0855:                    append = true;
0856:                } else if (POSITION_AFTER_END.equalsIgnoreCase(where)) {
0857:                    if (currentNode.getNextDomSibling() == null) {
0858:                        // new nodes should appended to the children of parent node
0859:                        node = currentNode.getParentDomNode();
0860:                        append = true;
0861:                    } else {
0862:                        // new nodes should be inserted before current node's next sibling
0863:                        node = currentNode.getNextDomSibling();
0864:                        append = false;
0865:                    }
0866:                } else {
0867:                    throw Context
0868:                            .reportRuntimeError("Illegal position value: \""
0869:                                    + where + "\"");
0870:                }
0871:
0872:                if (append) {
0873:                    return new Object[] { node, Boolean.TRUE };
0874:                } else {
0875:                    return new Object[] { node, Boolean.FALSE };
0876:                }
0877:            }
0878:
0879:            /**
0880:             * Adds the specified behavior to this HTML element. Currently only supports
0881:             * the following default IE behaviors:
0882:             * <ul>
0883:             *   <li>#default#clientCaps</li>
0884:             *   <li>#default#homePage</li>
0885:             *   <li>#default#download</li>
0886:             * </ul>
0887:             * @param behavior the URL of the behavior to add, or a default behavior name
0888:             * @return an identifier that can be user later to detach the behavior from the element
0889:             */
0890:            public int jsxFunction_addBehavior(final String behavior) {
0891:                // if behavior already defined, then nothing to do
0892:                if (behaviors_.contains(behavior)) {
0893:                    return 0;
0894:                }
0895:
0896:                if (BEHAVIOR_CLIENT_CAPS.equalsIgnoreCase(behavior)) {
0897:                    final Class c = getClass();
0898:                    defineProperty("availHeight", c, 0);
0899:                    defineProperty("availWidth", c, 0);
0900:                    defineProperty("bufferDepth", c, 0);
0901:                    defineProperty("colorDepth", c, 0);
0902:                    defineProperty("connectionType", c, 0);
0903:                    defineProperty("cookieEnabled", c, 0);
0904:                    defineProperty("cpuClass", c, 0);
0905:                    defineProperty("height", c, 0);
0906:                    defineProperty("javaEnabled", c, 0);
0907:                    defineProperty("platform", c, 0);
0908:                    defineProperty("systemLanguage", c, 0);
0909:                    defineProperty("userLanguage", c, 0);
0910:                    defineProperty("width", c, 0);
0911:                    defineFunctionProperties(
0912:                            new String[] { "addComponentRequest" }, c, 0);
0913:                    defineFunctionProperties(
0914:                            new String[] { "clearComponentRequest" }, c, 0);
0915:                    defineFunctionProperties(
0916:                            new String[] { "compareVersions" }, c, 0);
0917:                    defineFunctionProperties(
0918:                            new String[] { "doComponentRequest" }, c, 0);
0919:                    defineFunctionProperties(
0920:                            new String[] { "getComponentVersion" }, c, 0);
0921:                    defineFunctionProperties(
0922:                            new String[] { "isComponentInstalled" }, c, 0);
0923:                    behaviors_.add(BEHAVIOR_CLIENT_CAPS);
0924:                    return BEHAVIOR_ID_CLIENT_CAPS;
0925:                } else if (BEHAVIOR_HOMEPAGE.equalsIgnoreCase(behavior)) {
0926:                    final Class c = getClass();
0927:                    defineFunctionProperties(new String[] { "isHomePage" }, c,
0928:                            0);
0929:                    defineFunctionProperties(new String[] { "setHomePage" }, c,
0930:                            0);
0931:                    defineFunctionProperties(
0932:                            new String[] { "navigateHomePage" }, c, 0);
0933:                    behaviors_.add(BEHAVIOR_CLIENT_CAPS);
0934:                    return BEHAVIOR_ID_HOMEPAGE;
0935:                } else if (BEHAVIOR_DOWNLOAD.equalsIgnoreCase(behavior)) {
0936:                    final Class c = getClass();
0937:                    defineFunctionProperties(new String[] { "startDownload" },
0938:                            c, 0);
0939:                    behaviors_.add(BEHAVIOR_DOWNLOAD);
0940:                    return BEHAVIOR_ID_DOWNLOAD;
0941:                } else {
0942:                    getLog().warn("Unimplemented behavior: " + behavior);
0943:                    return BEHAVIOR_ID_UNKNOWN;
0944:                }
0945:            }
0946:
0947:            /**
0948:             * Removes the behavior corresponding to the specified identifier from this element.
0949:             * @param id the identifier for the behavior to remove
0950:             */
0951:            public void jsxFunction_removeBehavior(final int id) {
0952:                switch (id) {
0953:                case BEHAVIOR_ID_CLIENT_CAPS:
0954:                    delete("availHeight");
0955:                    delete("availWidth");
0956:                    delete("bufferDepth");
0957:                    delete("colorDepth");
0958:                    delete("connectionType");
0959:                    delete("cookieEnabled");
0960:                    delete("cpuClass");
0961:                    delete("height");
0962:                    delete("javaEnabled");
0963:                    delete("platform");
0964:                    delete("systemLanguage");
0965:                    delete("userLanguage");
0966:                    delete("width");
0967:                    delete("addComponentRequest");
0968:                    delete("clearComponentRequest");
0969:                    delete("compareVersions");
0970:                    delete("doComponentRequest");
0971:                    delete("getComponentVersion");
0972:                    delete("isComponentInstalled");
0973:                    behaviors_.remove(BEHAVIOR_CLIENT_CAPS);
0974:                    break;
0975:                case BEHAVIOR_ID_HOMEPAGE:
0976:                    delete("isHomePage");
0977:                    delete("setHomePage");
0978:                    delete("navigateHomePage");
0979:                    behaviors_.remove(BEHAVIOR_HOMEPAGE);
0980:                    break;
0981:                case BEHAVIOR_ID_DOWNLOAD:
0982:                    delete("startDownload");
0983:                    behaviors_.remove(BEHAVIOR_DOWNLOAD);
0984:                    break;
0985:                default:
0986:                    getLog().warn(
0987:                            "Unexpected behavior id: " + id + ". Ignoring.");
0988:                }
0989:            }
0990:
0991:            //----------------------- START #default#clientCaps BEHAVIOR -----------------------
0992:
0993:            /**
0994:             * Returns the screen's available height. Part of the <tt>#default#clientCaps</tt>
0995:             * default IE behavior implementation.
0996:             * @return the screen's available height.
0997:             */
0998:            public int getAvailHeight() {
0999:                return getWindow().jsxGet_screen().jsxGet_availHeight();
1000:            }
1001:
1002:            /**
1003:             * Returns the screen's available width. Part of the <tt>#default#clientCaps</tt>
1004:             * default IE behavior implementation.
1005:             * @return the screen's available width.
1006:             */
1007:            public int getAvailWidth() {
1008:                return getWindow().jsxGet_screen().jsxGet_availWidth();
1009:            }
1010:
1011:            /**
1012:             * Returns the screen's buffer depth. Part of the <tt>#default#clientCaps</tt>
1013:             * default IE behavior implementation.
1014:             * @return the screen's buffer depth.
1015:             */
1016:            public int getBufferDepth() {
1017:                return getWindow().jsxGet_screen().jsxGet_bufferDepth();
1018:            }
1019:
1020:            /**
1021:             * Returns BoxObject for this element.
1022:             * @return BoxObject for this element.
1023:             */
1024:            public BoxObject getBoxObject() {
1025:                if (boxObject_ == null) {
1026:                    boxObject_ = new BoxObject();
1027:                    boxObject_.setParentScope(getWindow());
1028:                    boxObject_
1029:                            .setPrototype(getPrototype(boxObject_.getClass()));
1030:                }
1031:                return boxObject_;
1032:            }
1033:
1034:            /**
1035:             * Returns the screen's color depth. Part of the <tt>#default#clientCaps</tt>
1036:             * default IE behavior implementation.
1037:             * @return the screen's color depth.
1038:             */
1039:            public int getColorDepth() {
1040:                return getWindow().jsxGet_screen().jsxGet_colorDepth();
1041:            }
1042:
1043:            /**
1044:             * Returns the connection type being used. Part of the <tt>#default#clientCaps</tt>
1045:             * default IE behavior implementation.
1046:             * @return the connection type being used.
1047:             * Current implementation always return "modem"
1048:             */
1049:            public String getConnectionType() {
1050:                return "modem";
1051:            }
1052:
1053:            /**
1054:             * Returns <tt>true</tt> if cookies are enabled. Part of the <tt>#default#clientCaps</tt>
1055:             * default IE behavior implementation.
1056:             * @return whether or not cookies are enabled.
1057:             */
1058:            public boolean getCookieEnabled() {
1059:                return getWindow().jsxGet_navigator().jsxGet_cookieEnabled();
1060:            }
1061:
1062:            /**
1063:             * Returns the type of CPU used. Part of the <tt>#default#clientCaps</tt>
1064:             * default IE behavior implementation.
1065:             * @return the type of CPU used.
1066:             */
1067:            public String getCpuClass() {
1068:                return getWindow().jsxGet_navigator().jsxGet_cpuClass();
1069:            }
1070:
1071:            /**
1072:             * Returns the screen's height. Part of the <tt>#default#clientCaps</tt>
1073:             * default IE behavior implementation.
1074:             * @return the screen's height.
1075:             */
1076:            public int getHeight() {
1077:                return getWindow().jsxGet_screen().jsxGet_height();
1078:            }
1079:
1080:            /**
1081:             * Returns <tt>true</tt> if Java is enabled. Part of the <tt>#default#clientCaps</tt>
1082:             * default IE behavior implementation.
1083:             * @return whether or not Java is enabled.
1084:             */
1085:            public boolean getJavaEnabled() {
1086:                return getWindow().jsxGet_navigator().jsxFunction_javaEnabled();
1087:            }
1088:
1089:            /**
1090:             * Returns the platform used. Part of the <tt>#default#clientCaps</tt>
1091:             * default IE behavior implementation.
1092:             * @return the platform used.
1093:             */
1094:            public String getPlatform() {
1095:                return getWindow().jsxGet_navigator().jsxGet_platform();
1096:            }
1097:
1098:            /**
1099:             * Returns the system language. Part of the <tt>#default#clientCaps</tt>
1100:             * default IE behavior implementation.
1101:             * @return the system language.
1102:             */
1103:            public String getSystemLanguage() {
1104:                return getWindow().jsxGet_navigator().jsxGet_systemLanguage();
1105:            }
1106:
1107:            /**
1108:             * Returns the user language. Part of the <tt>#default#clientCaps</tt>
1109:             * default IE behavior implementation.
1110:             * @return the user language.
1111:             */
1112:            public String getUserLanguage() {
1113:                return getWindow().jsxGet_navigator().jsxGet_userLanguage();
1114:            }
1115:
1116:            /**
1117:             * Returns the screen's width. Part of the <tt>#default#clientCaps</tt>
1118:             * default IE behavior implementation.
1119:             * @return the screen's width.
1120:             */
1121:            public int getWidth() {
1122:                return getWindow().jsxGet_screen().jsxGet_width();
1123:            }
1124:
1125:            /**
1126:             * Adds the specified component to the queue of components to be installed. Note
1127:             * that no components ever get installed, and this call is always ignored. Part of
1128:             * the <tt>#default#clientCaps</tt> default IE behavior implementation.
1129:             * @param id the identifier for the component to install
1130:             * @param idType the type of identifier specified
1131:             * @param minVersion the minimum version of the component to install
1132:             */
1133:            public void addComponentRequest(final String id,
1134:                    final String idType, final String minVersion) {
1135:                getLog().debug(
1136:                        "Call to addComponentRequest(" + id + ", " + idType
1137:                                + ", " + minVersion + ") ignored.");
1138:            }
1139:
1140:            /**
1141:             * Clears the component install queue of all component requests. Note that no components
1142:             * ever get installed, and this call is always ignored. Part of the <tt>#default#clientCaps</tt>
1143:             * default IE behavior implementation.
1144:             */
1145:            public void clearComponentRequest() {
1146:                getLog().debug("Call to clearComponentRequest() ignored.");
1147:            }
1148:
1149:            /**
1150:             * Compares the two specified version numbers. Part of the <tt>#default#clientCaps</tt>
1151:             * default IE behavior implementation.
1152:             * @param v1 the first of the two version numbers to compare
1153:             * @param v2 the second of the two version numbers to compare
1154:             * @return -1 if v1 < v2, 0 if v1 = v2, and 1 if v1 > v2
1155:             */
1156:            public int compareVersions(final String v1, final String v2) {
1157:                final int i = v1.compareTo(v2);
1158:                if (i == 0) {
1159:                    return 0;
1160:                } else if (i < 0) {
1161:                    return -1;
1162:                } else {
1163:                    return 1;
1164:                }
1165:            }
1166:
1167:            /**
1168:             * Downloads all the components queued via {@link #addComponentRequest(String, String, String)}.
1169:             * @return <tt>true</tt> if the components are downloaded successfully.
1170:             * Current implementation always return <code>false</code>
1171:             */
1172:            public boolean doComponentRequest() {
1173:                return false;
1174:            }
1175:
1176:            /**
1177:             * Returns the version of the specified component.
1178:             * @param id the identifier for the component whose version is to be returned
1179:             * @param idType the type of identifier specified
1180:             * @return the version of the specified component.
1181:             * Current implementation always return "1.0"
1182:             */
1183:            public String getComponentVersion(final String id,
1184:                    final String idType) {
1185:                return "1.0";
1186:            }
1187:
1188:            /**
1189:             * Returns <tt>true</tt> if the specified component is installed.
1190:             * @param id the identifier for the component to check for
1191:             * @param idType the type of id specified
1192:             * @param minVersion the minimum version to check for
1193:             * @return <tt>true</tt> if the specified component is installed.
1194:             */
1195:            public boolean isComponentInstalled(final String id,
1196:                    final String idType, final String minVersion) {
1197:                return false;
1198:            }
1199:
1200:            //----------------------- START #default#download BEHAVIOR -----------------------
1201:            /**
1202:             * Implementation of the IE behavior #default#download
1203:             * @param uri The URI of the download source
1204:             * @param callback the method which should be called when the download is finished
1205:             * @see <a href="http://msdn.microsoft.com/workshop/author/behaviors/reference/methods/startdownload.asp">
1206:             * MSDN documentation</a>
1207:             * @throws MalformedURLException If the url cannot be created
1208:             */
1209:            public void startDownload(final String uri, final Function callback)
1210:                    throws MalformedURLException {
1211:                final HtmlPage page = (HtmlPage) getWindow().getWebWindow()
1212:                        .getEnclosedPage();
1213:                final URL url = page.getFullyQualifiedUrl(uri);
1214:                if (!page.getWebResponse().getUrl().getHost().equals(
1215:                        url.getHost())) {
1216:                    throw Context.reportRuntimeError("Not authorized url: "
1217:                            + url);
1218:                }
1219:                final Thread t = new DownloadBehaviorDownloader(url, callback);
1220:                getLog().debug("Starting download thread for " + url);
1221:                t.start();
1222:            }
1223:
1224:            /**
1225:             * A helper class for the IE behavior #default#download
1226:             * This represents a download action. The download is handled
1227:             * asynchronously, when the download is finished, the method specified
1228:             * by callback is called with one argument - the content of the response as string.
1229:             * @see #startDownload(String, Function)
1230:             * @author <a href="mailto:stefan@anzinger.net">Stefan Anzinger</a>
1231:             */
1232:            private class DownloadBehaviorDownloader extends Thread {
1233:                private final URL url_;
1234:                private final Function callback_;
1235:
1236:                /**
1237:                 * @param url The URL to download
1238:                 * @param callback The function to callback
1239:                 */
1240:                public DownloadBehaviorDownloader(final URL url,
1241:                        final Function callback) {
1242:                    super ("Downloader for behavior #default#download '" + url
1243:                            + "'");
1244:                    url_ = url;
1245:                    callback_ = callback;
1246:                }
1247:
1248:                /**
1249:                 * Does the download and calls the callback method
1250:                 */
1251:                public void run() {
1252:                    final WebClient wc = getWindow().getWebWindow()
1253:                            .getWebClient();
1254:                    final Scriptable scope = callback_.getParentScope();
1255:                    final WebRequestSettings settings = new WebRequestSettings(
1256:                            url_);
1257:
1258:                    try {
1259:                        final WebResponse webResponse = wc
1260:                                .loadWebResponse(settings);
1261:                        final String content = webResponse.getContentAsString();
1262:                        getLog().debug(
1263:                                "Downloaded content: "
1264:                                        + StringUtils.abbreviate(content, 512));
1265:                        final Object[] args = new Object[] { content };
1266:                        final ContextAction action = new ContextAction() {
1267:                            public Object run(final Context cx) {
1268:                                callback_.call(cx, scope, scope, args);
1269:                                return null;
1270:                            }
1271:                        };
1272:                        Context.call(action);
1273:                    } catch (final Exception e) {
1274:                        getLog().error(
1275:                                "Behavior #default#download: Cannot download "
1276:                                        + url_, e);
1277:                    }
1278:                }
1279:            }
1280:
1281:            //----------------------- END #default#download BEHAVIOR -----------------------
1282:
1283:            //----------------------- START #default#homePage BEHAVIOR -----------------------
1284:
1285:            /**
1286:             * Returns <tt>true</tt> if the specified URL is the web client's current
1287:             * homepage and the document calling the method is on the same domain as the
1288:             * user's homepage. Part of the <tt>#default#homePage</tt> default IE behavior
1289:             * implementation.
1290:             * @param url the URL to check
1291:             * @return <tt>true</tt> if the specified URL is the current homepage
1292:             */
1293:            public boolean isHomePage(final String url) {
1294:                try {
1295:                    final URL newUrl = new URL(url);
1296:                    final URL currentUrl = getDomNodeOrDie().getPage()
1297:                            .getWebResponse().getUrl();
1298:                    final String home = getDomNodeOrDie().getPage()
1299:                            .getWebClient().getHomePage();
1300:                    final boolean sameDomains = newUrl.getHost()
1301:                            .equalsIgnoreCase(currentUrl.getHost());
1302:                    final boolean isHomePage = (home != null && home
1303:                            .equals(url));
1304:                    return (sameDomains && isHomePage);
1305:                } catch (final MalformedURLException e) {
1306:                    return false;
1307:                }
1308:            }
1309:
1310:            /**
1311:             * Sets the web client's current homepage. Part of the <tt>#default#homePage</tt>
1312:             * default IE behavior implementation.
1313:             * @param url the new homepage URL
1314:             */
1315:            public void setHomePage(final String url) {
1316:                getDomNodeOrDie().getPage().getWebClient().setHomePage(url);
1317:            }
1318:
1319:            /**
1320:             * Causes the web client to navigate to the current home page. Part of the
1321:             * <tt>#default#homePage</tt> default IE behavior implementation.
1322:             * @throws IOException if loading home page fails
1323:             */
1324:            public void navigateHomePage() throws IOException {
1325:                final WebClient webClient = getDomNodeOrDie().getPage()
1326:                        .getWebClient();
1327:                webClient.getPage(webClient.getHomePage());
1328:            }
1329:
1330:            //----------------------- END #default#homePage BEHAVIOR -----------------------
1331:
1332:            /**
1333:             * Get the children of the current node.
1334:             * @see <a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/collections/children.asp">
1335:             * MSDN documentation</a>
1336:             * @return the child at the given position
1337:             */
1338:            public Object jsxGet_children() {
1339:                final DomNode element = getDomNodeOrDie();
1340:                final HTMLCollection children = new HTMLCollection(this );
1341:
1342:                try {
1343:                    final XPath xpath = new HtmlUnitXPath("./*", HtmlUnitXPath
1344:                            .buildSubtreeNavigator(element));
1345:                    children.init(element, xpath);
1346:                } catch (final JaxenException e) {
1347:                    // should never occur
1348:                    throw Context
1349:                            .reportRuntimeError("Failed initializing children: "
1350:                                    + e.getMessage());
1351:                }
1352:                return children;
1353:            }
1354:
1355:            /**
1356:             * Set the onclick event handler for this element.
1357:             * @param handler the new handler
1358:             */
1359:            public void jsxSet_onclick(final Object handler) {
1360:                setEventHandlerProp("onclick", handler);
1361:            }
1362:
1363:            /**
1364:             * Get the onclick event handler for this element.
1365:             * @return <code>org.mozilla.javascript.Function</code>
1366:             */
1367:            public Object jsxGet_onclick() {
1368:                return getEventHandlerProp("onclick");
1369:            }
1370:
1371:            /**
1372:             * Set the ondblclick event handler for this element.
1373:             * @param handler the new handler
1374:             **/
1375:            public void jsxSet_ondblclick(final Object handler) {
1376:                setEventHandlerProp("ondblclick", handler);
1377:            }
1378:
1379:            /**
1380:             * Get the ondblclick event handler for this element.
1381:             * @return <code>org.mozilla.javascript.Function</code>
1382:             */
1383:            public Object jsxGet_ondblclick() {
1384:                return getEventHandlerProp("ondblclick");
1385:            }
1386:
1387:            /**
1388:             * Set the onblur event handler for this element.
1389:             * @param handler the new handler
1390:             */
1391:            public void jsxSet_onblur(final Object handler) {
1392:                setEventHandlerProp("onblur", handler);
1393:            }
1394:
1395:            /**
1396:             * Get the onblur event handler for this element.
1397:             * @return <code>org.mozilla.javascript.Function</code>
1398:             */
1399:            public Object jsxGet_onblur() {
1400:                return getEventHandlerProp("onblur");
1401:            }
1402:
1403:            /**
1404:             * Set the onfocus event handler for this element.
1405:             * @param handler the new handler
1406:             */
1407:            public void jsxSet_onfocus(final Object handler) {
1408:                setEventHandlerProp("onfocus", handler);
1409:            }
1410:
1411:            /**
1412:             * Get the onfocus event handler for this element.
1413:             * @return <code>org.mozilla.javascript.Function</code>
1414:             */
1415:            public Object jsxGet_onfocus() {
1416:                return getEventHandlerProp("onfocus");
1417:            }
1418:
1419:            /**
1420:             * Set the onkeydown event handler for this element.
1421:             * @param handler the new handler
1422:             */
1423:            public void jsxSet_onkeydown(final Object handler) {
1424:                setEventHandlerProp("onkeydown", handler);
1425:            }
1426:
1427:            /**
1428:             * Get the onkeydown event handler for this element.
1429:             * @return <code>org.mozilla.javascript.Function</code>
1430:             */
1431:            public Object jsxGet_onkeydown() {
1432:                return getEventHandlerProp("onkeydown");
1433:            }
1434:
1435:            /**
1436:             * Set the onkeypress event handler for this element.
1437:             * @param handler the new handler
1438:             */
1439:            public void jsxSet_onkeypress(final Object handler) {
1440:                setEventHandlerProp("onkeypress", handler);
1441:            }
1442:
1443:            /**
1444:             * Get the onkeypress event handler for this element.
1445:             * @return <code>org.mozilla.javascript.Function</code>
1446:             */
1447:            public Object jsxGet_onkeypress() {
1448:                return getEventHandlerProp("onkeypress");
1449:            }
1450:
1451:            /**
1452:             * Set the onkeyup event handler for this element.
1453:             * @param handler the new handler
1454:             */
1455:            public void jsxSet_onkeyup(final Object handler) {
1456:                setEventHandlerProp("onkeyup", handler);
1457:            }
1458:
1459:            /**
1460:             * Get the onkeyup event handler for this element.
1461:             * @return <code>org.mozilla.javascript.Function</code>
1462:             */
1463:            public Object jsxGet_onkeyup() {
1464:                return getEventHandlerProp("onkeyup");
1465:            }
1466:
1467:            /**
1468:             * Set the onmousedown event handler for this element.
1469:             * @param handler the new handler
1470:             */
1471:            public void jsxSet_onmousedown(final Object handler) {
1472:                setEventHandlerProp("onmousedown", handler);
1473:            }
1474:
1475:            /**
1476:             * Get the onmousedown event handler for this element.
1477:             * @return <code>org.mozilla.javascript.Function</code>
1478:             */
1479:            public Object jsxGet_onmousedown() {
1480:                return getEventHandlerProp("onmousedown");
1481:            }
1482:
1483:            /**
1484:             * Set the onmousemove event handler for this element.
1485:             * @param handler the new handler
1486:             */
1487:            public void jsxSet_onmousemove(final Object handler) {
1488:                setEventHandlerProp("onmousemove", handler);
1489:            }
1490:
1491:            /**
1492:             * Get the onmousemove event handler for this element.
1493:             * @return <code>org.mozilla.javascript.Function</code>
1494:             */
1495:            public Object jsxGet_onmousemove() {
1496:                return getEventHandlerProp("onmousemove");
1497:            }
1498:
1499:            /**
1500:             * Set the onmouseout event handler for this element.
1501:             * @param handler the new handler
1502:             */
1503:            public void jsxSet_onmouseout(final Object handler) {
1504:                setEventHandlerProp("onmouseout", handler);
1505:            }
1506:
1507:            /**
1508:             * Get the onmouseout event handler for this element.
1509:             * @return <code>org.mozilla.javascript.Function</code>
1510:             */
1511:            public Object jsxGet_onmouseout() {
1512:                return getEventHandlerProp("onmouseout");
1513:            }
1514:
1515:            /**
1516:             * Set the onmouseover event handler for this element.
1517:             * @param handler the new handler
1518:             */
1519:            public void jsxSet_onmouseover(final Object handler) {
1520:                setEventHandlerProp("onmouseover", handler);
1521:            }
1522:
1523:            /**
1524:             * Get the onmouseover event handler for this element.
1525:             * @return <code>org.mozilla.javascript.Function</code>
1526:             */
1527:            public Object jsxGet_onmouseover() {
1528:                return getEventHandlerProp("onmouseover");
1529:            }
1530:
1531:            /**
1532:             * Set the onmouseup event handler for this element.
1533:             * @param handler the new handler
1534:             */
1535:            public void jsxSet_onmouseup(final Object handler) {
1536:                setEventHandlerProp("onmouseup", handler);
1537:            }
1538:
1539:            /**
1540:             * Get the onmouseup event handler for this element.
1541:             * @return <code>org.mozilla.javascript.Function</code>
1542:             */
1543:            public Object jsxGet_onmouseup() {
1544:                return getEventHandlerProp("onmouseup");
1545:            }
1546:
1547:            /**
1548:             * Set the oncontextmenu event handler for this element.
1549:             * @param handler the new handler
1550:             */
1551:            public void jsxSet_oncontextmenu(final Object handler) {
1552:                setEventHandlerProp("oncontextmenu", handler);
1553:            }
1554:
1555:            /**
1556:             * Get the oncontextmenu event handler for this element.
1557:             * @return <code>org.mozilla.javascript.Function</code>
1558:             */
1559:            public Object jsxGet_oncontextmenu() {
1560:                return getEventHandlerProp("oncontextmenu");
1561:            }
1562:
1563:            /**
1564:             * Set the onresize event handler for this element.
1565:             * @param handler the new handler
1566:             */
1567:            public void jsxSet_onresize(final Object handler) {
1568:                setEventHandlerProp("onresize", handler);
1569:            }
1570:
1571:            /**
1572:             * Get the onresize event handler for this element.
1573:             * @return <code>org.mozilla.javascript.Function</code>
1574:             */
1575:            public Object jsxGet_onresize() {
1576:                return getEventHandlerProp("onresize");
1577:            }
1578:
1579:            /**
1580:             * Returns this element's <tt>offsetHeight</tt>, which is the element height plus the element's padding
1581:             * plus the element's border. This method returns a dummy value compatible with mouse event coordinates
1582:             * during mouse events.
1583:             * @return this element's <tt>offsetHeight</tt>
1584:             * @see <a href="http://msdn2.microsoft.com/en-us/library/ms534199.aspx">MSDN Documentation</a>
1585:             * @see <a href="http://www.quirksmode.org/js/elementdimensions.html">Element Dimensions</a>
1586:             */
1587:            public int jsxGet_offsetHeight() {
1588:                final MouseEvent event = MouseEvent.getCurrentMouseEvent();
1589:                if (isAncestorOfEventTarget(event)) {
1590:                    // compute appropriate offsetHeight to make as if mouse event produced within this element
1591:                    return event.jsxGet_clientY() - getPosY() + 50;
1592:                } else {
1593:                    return 1;
1594:                }
1595:            }
1596:
1597:            /**
1598:             * Returns this element's <tt>offsetWidth</tt>, which is the element width plus the element's padding
1599:             * plus the element's border. This method returns a dummy value compatible with mouse event coordinates
1600:             * during mouse events.
1601:             * @return this element's <tt>offsetWidth</tt>
1602:             * @see <a href="http://msdn2.microsoft.com/en-us/library/ms534304.aspx">MSDN Documentation</a>
1603:             * @see <a href="http://www.quirksmode.org/js/elementdimensions.html">Element Dimensions</a>
1604:             */
1605:            public int jsxGet_offsetWidth() {
1606:                final MouseEvent event = MouseEvent.getCurrentMouseEvent();
1607:                if (isAncestorOfEventTarget(event)) {
1608:                    // compute appropriate offsetwidth to make as if mouse event produced within this element
1609:                    return event.jsxGet_clientX() - getPosX() + 50;
1610:                } else {
1611:                    return 1;
1612:                }
1613:            }
1614:
1615:            /**
1616:             * Returns <tt>true</tt> if this element's node is an ancestor of the specified event's target node.
1617:             * @param event the event whose target node is to be checked
1618:             * @return <tt>true</tt> if this element's node is an ancestor of the specified event's target node
1619:             */
1620:            private boolean isAncestorOfEventTarget(final MouseEvent event) {
1621:                if (event == null) {
1622:                    return false;
1623:                }
1624:                final HTMLElement target = (HTMLElement) event.jsxGet_target();
1625:                return getHtmlElementOrDie().isAncestorOf(
1626:                        target.getHtmlElementOrDie());
1627:            }
1628:
1629:            /**
1630:             * Gets the x position of the element. The value returned doesn't need to be "correct" as it
1631:             * just needs to be compatible with mouse event coordinates.
1632:             *
1633:             * @return the x position
1634:             */
1635:            int getPosX() {
1636:                int cumulativeOffset = 0;
1637:                HTMLElement element = this ;
1638:                while (element != null) {
1639:                    cumulativeOffset += element.jsxGet_offsetLeft();
1640:                    element = (HTMLElement) element.jsxGet_offsetParent();
1641:                }
1642:                return cumulativeOffset;
1643:            }
1644:
1645:            /**
1646:             * Gets the y position of the element. The value returned doesn't need to be "correct" as it
1647:             * just needs to be compatible with mouse event coordinates.
1648:             * @return the y position
1649:             */
1650:            int getPosY() {
1651:                int cumulativeOffset = 0;
1652:                HTMLElement element = this ;
1653:                while (element != null) {
1654:                    cumulativeOffset += element.jsxGet_offsetTop();
1655:                    element = (HTMLElement) element.jsxGet_offsetParent();
1656:                }
1657:                return cumulativeOffset;
1658:            }
1659:
1660:            /**
1661:             * Returns this element's <tt>offsetLeft</tt>, which is the calculated left position of this
1662:             * element relative to the <tt>offsetParent</tt>.
1663:             * @return this element's <tt>offsetLeft</tt>
1664:             * @see <a href="http://msdn2.microsoft.com/en-us/library/ms534200.aspx">MSDN Documentation</a>
1665:             * @see <a href="http://www.quirksmode.org/js/elementdimensions.html">Element Dimensions</a>
1666:             */
1667:            public int jsxGet_offsetLeft() {
1668:                return 1;
1669:            }
1670:
1671:            /**
1672:             * Returns this element's <tt>offsetTop</tt>, which is the calculated top position of this
1673:             * element relative to the <tt>offsetParent</tt>.
1674:             * @return this element's <tt>offsetTop</tt>
1675:             * @see <a href="http://msdn2.microsoft.com/en-us/library/ms534303.aspx">MSDN Documentation</a>
1676:             * @see <a href="http://www.quirksmode.org/js/elementdimensions.html">Element Dimensions</a>
1677:             */
1678:            public int jsxGet_offsetTop() {
1679:                return 1;
1680:            }
1681:
1682:            /**
1683:             * Returns this element's <tt>offsetParent</tt>. The <tt>offsetLeft</tt> and <tt>offsetTop</tt>
1684:             * attributes are relative to the <tt>offsetParent</tt>.
1685:             * @return this element's <tt>offsetParent</tt>
1686:             * @see <a href="http://msdn2.microsoft.com/en-us/library/ms534302.aspx">MSDN Documentation</a>
1687:             * @see <a href="http://www.mozilla.org/docs/dom/domref/dom_el_ref20.html">Gecko DOM Reference</a>
1688:             * @see <a href="http://www.quirksmode.org/js/elementdimensions.html">Element Dimensions</a>
1689:             * @see <a href="http://www.w3.org/TR/REC-CSS2/box.html">Box Model</a>
1690:             */
1691:            public Object jsxGet_offsetParent() {
1692:                DomNode currentElement = getHtmlElementOrDie();
1693:                Object offsetParent = null;
1694:                while (currentElement != null) {
1695:                    final DomNode parentNode = currentElement
1696:                            .getParentDomNode();
1697:                    // According to the Microsoft and Mozilla documentation, and from experimentation
1698:                    // in the IE and Firefox browsers, the offsetParent is the container
1699:                    // (<td>, <table>, <body>) nearest to the node
1700:                    if ((parentNode instanceof  HtmlTableDataCell)
1701:                            || (parentNode instanceof  HtmlTable)
1702:                            || (parentNode instanceof  HtmlBody)) {
1703:                        offsetParent = parentNode.getScriptObject();
1704:                        break;
1705:                    }
1706:                    currentElement = currentElement.getParentDomNode();
1707:                }
1708:                return offsetParent;
1709:            }
1710:
1711:            /**
1712:             * Just for debug purposes.
1713:             * {@inheritDoc}
1714:             */
1715:            public String toString() {
1716:                return "HTMLElement for " + getHtmlElementOrNull();
1717:            }
1718:
1719:            /**
1720:             * Get the scrollTop for this element.
1721:             * @return a dummy value (default is 0)
1722:             * @see <a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/scrollTop.asp">
1723:             * MSDN documentation</a>
1724:             */
1725:            public int jsxGet_scrollTop() {
1726:                return scrollTop_;
1727:            }
1728:
1729:            /**
1730:             * Set the scrollTop for this element.
1731:             * @param scroll the new value
1732:             */
1733:            public void jsxSet_scrollTop(final int scroll) {
1734:                scrollTop_ = scroll;
1735:            }
1736:
1737:            /**
1738:             * Get the scrollLeft for this element.
1739:             * @return a dummy value (default is 0)
1740:             * @see <a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/scrollLeft.asp">
1741:             * MSDN documentation</a>
1742:             */
1743:            public int jsxGet_scrollLeft() {
1744:                return scrollLeft_;
1745:            }
1746:
1747:            /**
1748:             * Set the scrollLeft for this element.
1749:             * @param scroll the new value
1750:             */
1751:            public void jsxSet_scrollLeft(final int scroll) {
1752:                scrollLeft_ = scroll;
1753:            }
1754:
1755:            /**
1756:             * Get the scrollHeight for this element.
1757:             * @return a dummy value of 10
1758:             * @see <a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/scrollHeight.asp">
1759:             * MSDN documentation</a>
1760:             */
1761:            public int jsxGet_scrollHeight() {
1762:                return 10;
1763:            }
1764:
1765:            /**
1766:             * Get the scrollWidth for this element.
1767:             * @return a dummy value of 10
1768:             * @see <a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/scrollWidth.asp">
1769:             * MSDN documentation</a>
1770:             */
1771:            public int jsxGet_scrollWidth() {
1772:                return 10;
1773:            }
1774:
1775:            /**
1776:             * Get the JavaScript property "parentElement".
1777:             * <p>It is identical to {@link #jsxGet_parentNode()}
1778:             * with the exception of <tt>HTML</tt>, which has a <tt>null</tt> parent element.
1779:             * @return The parent element
1780:             * @see #jsxGet_parentNode()
1781:             */
1782:            public Object jsxGet_parentElement() {
1783:                if ("html".equalsIgnoreCase(getDomNodeOrDie().getNodeName())) {
1784:                    return null;
1785:                } else {
1786:                    return jsxGet_parentNode();
1787:                }
1788:            }
1789:
1790:            /**
1791:             * Implement the scrollIntoView() javascript function but don't actually do
1792:             * anything. The requirement
1793:             * is just to prevent scripts that call that method from failing
1794:             */
1795:            public void jsxFunction_scrollIntoView() {
1796:            }
1797:
1798:            /**
1799:             * Retrieves an object that specifies the bounds of a collection of TextRectangle objects.
1800:             * @return an object that specifies the bounds of a collection of TextRectangle objects.
1801:             */
1802:            public TextRectangle jsxFunction_getBoundingClientRect() {
1803:                final TextRectangle textRectangle = new TextRectangle();
1804:                textRectangle.setParentScope(getWindow());
1805:                textRectangle.setPrototype(getPrototype(textRectangle
1806:                        .getClass()));
1807:                return textRectangle;
1808:            }
1809:
1810:            /**
1811:             * Retrieves a collection of rectangles that describes the layout of the contents of an object
1812:             * or range within the client. Each rectangle describes a single line.
1813:             * @return a collection of rectangles that describes the layout of the contents.
1814:             */
1815:            public Object jsxFunction_getClientRects() {
1816:                return new NativeArray(0);
1817:            }
1818:
1819:            /**
1820:             * Sets an expression for the specified HTMLElement.
1821:             *
1822:             * @param propertyName Specifies the name of the property to which expression is added.
1823:             * @param expression specifies any valid script statement without quotations or semicolons.
1824:             *        This string can include references to other properties on the current page.
1825:             *        Array references are not allowed on object properties included in this script.
1826:             * @param language specified the language used.
1827:             */
1828:            public void jsxFunction_setExpression(final String propertyName,
1829:                    final String expression, final String language) {
1830:                //empty implementation
1831:            }
1832:
1833:            /**
1834:             * Removes the expression from the specified property.
1835:             *
1836:             * @param propertyName Specifies the name of the property from which to remove an expression.
1837:             * @return true if the expression was successfully removed.
1838:             */
1839:            public boolean jsxFunction_removeExpression(
1840:                    final String propertyName) {
1841:                return true;
1842:            }
1843:
1844:            /**
1845:             * Retrieves an auto-generated, unique identifier for the object.
1846:             * <b>Note</b> The unique ID generated is not guaranteed to be the same every time the page is loaded.
1847:             * @return an auto-generated, unique identifier for the object.
1848:             */
1849:            public String jsxGet_uniqueID() {
1850:                if (uniqueID_ == null) {
1851:                    uniqueID_ = "ms__id" + UniqueID_Counter_++;
1852:                }
1853:                return uniqueID_;
1854:            }
1855:
1856:            /**
1857:             * Dispatches an event into the event system (standards-conformant browsers only). See
1858:             * <a href="http://developer.mozilla.org/en/docs/DOM:element.dispatchEvent">the Gecko
1859:             * DOM reference</a> for more information.
1860:             *
1861:             * @param event the event to be dispatched
1862:             * @return <tt>false</tt> if at least one of the event handlers which handled the event
1863:             *         called <tt>preventDefault</tt>; <tt>true</tt> otherwise
1864:             */
1865:            public boolean jsxFunction_dispatchEvent(final Event event) {
1866:                final HtmlElement element = getHtmlElementOrDie();
1867:                if (event instanceof  MouseEvent
1868:                        && element instanceof  ClickableElement) {
1869:                    if (event.jsxGet_type().equals(MouseEvent.TYPE_CLICK)) {
1870:                        try {
1871:                            ((ClickableElement) element).click(event);
1872:                        } catch (final IOException e) {
1873:                            throw Context
1874:                                    .reportRuntimeError("Error calling click(): "
1875:                                            + e.getMessage());
1876:                        }
1877:                    } else if (event.jsxGet_type().equals(
1878:                            MouseEvent.TYPE_DBL_CLICK)) {
1879:                        try {
1880:                            ((ClickableElement) element).dblClick(event
1881:                                    .jsxGet_shiftKey(), event.jsxGet_ctrlKey(),
1882:                                    event.jsxGet_altKey());
1883:                        } catch (final IOException e) {
1884:                            throw Context
1885:                                    .reportRuntimeError("Error calling dblClick(): "
1886:                                            + e.getMessage());
1887:                        }
1888:                    } else {
1889:                        fireEvent(event);
1890:                    }
1891:                } else {
1892:                    fireEvent(event);
1893:                }
1894:                return !event.isPreventDefault();
1895:            }
1896:
1897:            /**
1898:             * Fires a specified event on this element (IE only). See the
1899:             * <a href="http://msdn2.microsoft.com/en-us/library/ms536423.aspx">MSDN documentation</a>
1900:             * for more information.
1901:             * @param cx the JavaScript context
1902:             * @param thisObj the element instance on which this method was invoked
1903:             * @param args contains the event type as a string, and an optional event template
1904:             * @param f the function being invoked
1905:             * @return <tt>true</tt> if the event fired successfully, <tt>false</tt> if it was cancelled
1906:             */
1907:            public static ScriptResult jsxFunction_fireEvent(final Context cx,
1908:                    final Scriptable this Obj, final Object[] args,
1909:                    final Function f) {
1910:
1911:                final HTMLElement me = (HTMLElement) this Obj;
1912:
1913:                // Extract the function arguments.
1914:                final String type = (String) args[0];
1915:                final Event template;
1916:                if (args.length > 1) {
1917:                    template = (Event) args[1];
1918:                } else {
1919:                    template = null;
1920:                }
1921:
1922:                // Create the event, whose class will depend on the type specified.
1923:                final Event event;
1924:                final String cleanedType = StringUtils.removeStart(type
1925:                        .toLowerCase(), "on");
1926:                if (MouseEvent.isMouseEvent(cleanedType)) {
1927:                    event = new MouseEvent();
1928:                    event.setPrototype(me.getPrototype(MouseEvent.class));
1929:                } else {
1930:                    event = new Event();
1931:                    event.setPrototype(me.getPrototype(Event.class));
1932:                }
1933:                event.setParentScope(me.getWindow());
1934:
1935:                // Initialize the event using the template, if provided.
1936:                if (template != null) {
1937:                    event.copyPropertiesFrom(template);
1938:                }
1939:
1940:                // These four properties have predefined values, independent of the template.
1941:                event.jsxSet_cancelBubble(false);
1942:                event.jsxSet_returnValue(Boolean.TRUE);
1943:                event.jsxSet_srcElement(me);
1944:                event.setEventType(cleanedType);
1945:
1946:                return me.fireEvent(event);
1947:            }
1948:
1949:            /**
1950:             * Return the html element that corresponds to this javascript object or throw an exception
1951:             * if one cannot be found.
1952:             * @return The html element
1953:             * @exception IllegalStateException If the html element could not be found.
1954:             */
1955:            public final HtmlElement getHtmlElementOrDie()
1956:                    throws IllegalStateException {
1957:                return (HtmlElement) getDomNodeOrDie();
1958:            }
1959:
1960:            /**
1961:             * Return the html element that corresponds to this javascript object
1962:             * or null if an element hasn't been set.
1963:             * @return The html element or null
1964:             */
1965:            public final HtmlElement getHtmlElementOrNull() {
1966:                return (HtmlElement) getDomNodeOrNull();
1967:            }
1968:
1969:            /**
1970:             * Remove focus from this element.
1971:             */
1972:            public void jsxFunction_blur() {
1973:                final HtmlElement element = (HtmlElement) getDomNodeOrDie();
1974:                element.blur();
1975:            }
1976:
1977:            /**
1978:             * Set the focus to this element.
1979:             */
1980:            public void jsxFunction_focus() {
1981:                final HtmlElement element = (HtmlElement) getDomNodeOrDie();
1982:                element.focus();
1983:            }
1984:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.