
org.vectomatic.dom.svg.utils.DOMHelper Maven / Gradle / Ivy
/**********************************************
* Copyright (C) 2010 Lukas Laag
* This file is part of lib-gwt-svg.
*
* libgwtsvg is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libgwtsvg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libgwtsvg. If not, see http://www.gnu.org/licenses/
**********************************************/
/*
* Copyright (c) 2004 World Wide Web Consortium,
*
* (Massachusetts Institute of Technology, European Research Consortium for
* Informatics and Mathematics, Keio University). All Rights Reserved. This
* work is distributed under the W3C(r) Software License [1] in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
*/
package org.vectomatic.dom.svg.utils;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.vectomatic.dom.svg.OMElement;
import org.vectomatic.dom.svg.OMNode;
import org.vectomatic.dom.svg.OMSVGElement;
import org.vectomatic.dom.svg.impl.Attr;
import org.vectomatic.dom.svg.impl.DOMHelperImpl;
import org.vectomatic.dom.svg.impl.NamedNodeMap;
import org.w3c.dom.DOMException;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.Text;
import com.google.gwt.event.dom.client.LoseCaptureHandler;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* Class to group miscellaneous DOM level 2 methods. These
* methods are missing from the GWT DOM overlay types (such as
* {@link com.google.gwt.dom.client.Element} or {@link com.google.gwt.dom.client.Node})
* but exist in almost all browsers and are sometimes required
* to develop an SVG application.
* @author laaglu
*/
public class DOMHelper {
private static final DOMHelperImpl impl = GWT.create(DOMHelperImpl.class);
/**
* Creates an element of the given qualified name and namespace URI.
*
Per [XML Namespaces]
* , applications must use the value null
as the
* namespaceURI parameter for methods if they wish to have no namespace.
* @param document The document in which the element is to be created.
* @param namespaceURI The namespace URI of the element to create.
* @param qualifiedName The qualified name of the element type to
* instantiate.
* @return A new Element
object with the following
* attributes:
*
*
* Attribute
* Value
*
*
* Node.nodeName
*
* qualifiedName
*
*
* Node.namespaceURI
*
* namespaceURI
*
*
* Node.prefix
* prefix, extracted
* from qualifiedName
, or null
if there is
* no prefix
*
*
* Node.localName
* local name, extracted from
* qualifiedName
*
*
* Element.tagName
*
* qualifiedName
*
*
* @exception DOMException
* INVALID_CHARACTER_ERR: Raised if the specified
* qualifiedName
is not an XML name according to the XML
* version in use specified in the Document.xmlVersion
* attribute.
*
NAMESPACE_ERR: Raised if the qualifiedName
is a
* malformed qualified name, if the qualifiedName
has a
* prefix and the namespaceURI
is null
, or
* if the qualifiedName
has a prefix that is "xml" and
* the namespaceURI
is different from "
* http://www.w3.org/XML/1998/namespace" [XML Namespaces]
* , or if the qualifiedName
or its prefix is "xmlns" and
* the namespaceURI
is different from "http://www.w3.org/2000/xmlns/", or if the namespaceURI
is "http://www.w3.org/2000/xmlns/" and neither the qualifiedName
nor its prefix is "xmlns".
*
NOT_SUPPORTED_ERR: Always thrown if the current document does not
* support the "XML"
feature, since namespaces were
* defined by XML.
*/
public static final native Element createElementNS(Document document, String namespaceURI, String qualifiedName) throws JavaScriptException /*-{
return document.createElementNS(namespaceURI, qualifiedName);
}-*/;
/**
* Creates a new empty SVG document
* @return
* a new empty SVG document
*/
public static final native Document createDocument(String uri, String qname) /*-{
return $doc.implementation.createDocument(uri, qname, null);
}-*/;
/**
* Imports a node from another document to this document, without altering
* or removing the source node from the original document; this method
* creates a new copy of the source node. The returned node has no
* parent; (parentNode
is null
).
*
For all nodes, importing a node creates a node object owned by the
* importing document, with attribute values identical to the source
* node's nodeName
and nodeType
, plus the
* attributes related to namespaces (prefix
,
* localName
, and namespaceURI
). As in the
* cloneNode
operation, the source node is not altered.
* User data associated to the imported node is not carried over.
* However, if any UserDataHandlers
has been specified
* along with the associated data these handlers will be called with the
* appropriate parameters before this method returns.
*
Additional information is copied as appropriate to the
* nodeType
, attempting to mirror the behavior expected if
* a fragment of XML or HTML source was copied from one document to
* another, recognizing that the two documents may have different DTDs
* in the XML case. The following list describes the specifics for each
* type of node.
*
* - ATTRIBUTE_NODE
* - The
ownerElement
attribute
* is set to null
and the specified
flag is
* set to true
on the generated Attr
. The
* descendants of the source Attr
are recursively imported
* and the resulting nodes reassembled to form the corresponding subtree.
* Note that the deep
parameter has no effect on
* Attr
nodes; they always carry their children with them
* when imported.
* - DOCUMENT_FRAGMENT_NODE
* - If the
deep
option
* was set to true
, the descendants of the source
* DocumentFragment
are recursively imported and the
* resulting nodes reassembled under the imported
* DocumentFragment
to form the corresponding subtree.
* Otherwise, this simply generates an empty
* DocumentFragment
.
* - DOCUMENT_NODE
* Document
* nodes cannot be imported.
* - DOCUMENT_TYPE_NODE
* DocumentType
* nodes cannot be imported.
* - ELEMENT_NODE
* - Specified attribute nodes of the source element are imported, and the generated
*
Attr
nodes are attached to the generated
* Element
. Default attributes are not copied, though if the document being imported into defines default
* attributes for this element name, those are assigned. If the
* importNode
deep
parameter was set to
* true
, the descendants of the source element are
* recursively imported and the resulting nodes reassembled to form the
* corresponding subtree.
* - ENTITY_NODE
* Entity
nodes can be
* imported, however in the current release of the DOM the
* DocumentType
is readonly. Ability to add these imported
* nodes to a DocumentType
will be considered for addition
* to a future release of the DOM.On import, the publicId
,
* systemId
, and notationName
attributes are
* copied. If a deep
import is requested, the descendants
* of the the source Entity
are recursively imported and
* the resulting nodes reassembled to form the corresponding subtree.
* -
* ENTITY_REFERENCE_NODE
* - Only the
EntityReference
itself is
* copied, even if a deep
import is requested, since the
* source and destination documents might have defined the entity
* differently. If the document being imported into provides a
* definition for this entity name, its value is assigned.
* - NOTATION_NODE
* -
*
Notation
nodes can be imported, however in the current
* release of the DOM the DocumentType
is readonly. Ability
* to add these imported nodes to a DocumentType
will be
* considered for addition to a future release of the DOM.On import, the
* publicId
and systemId
attributes are copied.
* Note that the deep
parameter has no effect on this type
* of nodes since they cannot have any children.
* -
* PROCESSING_INSTRUCTION_NODE
* - The imported node copies its
*
target
and data
values from those of the
* source node.Note that the deep
parameter has no effect
* on this type of nodes since they cannot have any children.
* - TEXT_NODE,
* CDATA_SECTION_NODE, COMMENT_NODE
* - These three types of nodes inheriting
* from
CharacterData
copy their data
and
* length
attributes from those of the source node.Note
* that the deep
parameter has no effect on these types of
* nodes since they cannot have any children.
*
* @param document The document in which to import the node.
* @param importedNode The node to import.
* @param deep If true
, recursively import the subtree under
* the specified node; if false
, import only the node
* itself, as explained above. This has no effect on nodes that cannot
* have any children, and on Attr
, and
* EntityReference
nodes.
* @return The imported node that belongs to this Document
.
* @exception DOMException
* NOT_SUPPORTED_ERR: Raised if the type of node being imported is not
* supported.
*
INVALID_CHARACTER_ERR: Raised if one of the imported names is not
* an XML name according to the XML version in use specified in the
* Document.xmlVersion
attribute. This may happen when
* importing an XML 1.1 [XML 1.1] element
* into an XML 1.0 document, for instance.
*/
public static final native Node importNode(Document document, Node importedNode, boolean deep) /*-{
return document.importNode(importedNode, deep);
}-*/;
/**
* Puts all Text
nodes in the full depth of the sub-tree
* underneath this Node
, including attribute nodes, into a
* "normal" form where only structure (e.g., elements, comments,
* processing instructions, CDATA sections, and entity references)
* separates Text
nodes, i.e., there are neither adjacent
* Text
nodes nor empty Text
nodes. This can
* be used to ensure that the DOM view of a document is the same as if
* it were saved and re-loaded, and is useful when operations (such as
* XPointer [XPointer]
* lookups) that depend on a particular document tree structure are to
* be used. If the parameter "normalize-characters" of the
* DOMConfiguration
object attached to the
* Node.ownerDocument
is true
, this method
* will also fully normalize the characters of the Text
* nodes.
* Note: In cases where the document contains
* CDATASections
, the normalize operation alone may not be
* sufficient, since XPointers do not differentiate between
* Text
nodes and CDATASection
nodes.
* @param node the node to normalize
*/
public static final native void normalize(Node node) /*-{
return node.normalize();
}-*/;
/**
* Extracts a range of data from the node.
* @param text the text node
* @param offset Start offset of substring to extract.
* @param count The number of 16-bit units to extract.
* @return The specified substring. If the sum of offset
and
* count
exceeds the length
, then all 16-bit
* units to the end of the data are returned.
* @exception DOMException
* INDEX_SIZE_ERR: Raised if the specified offset
is
* negative or greater than the number of 16-bit units in
* data
, or if the specified count
is
* negative.
*
DOMSTRING_SIZE_ERR: Raised if the specified range of text does
* not fit into a String
.
*/
public static final native String substringData(Text text, int offset, int count) throws JavaScriptException /*-{
return text.substringData(offset, count);
}-*/;
/**
* Append the string to the end of the character data of the node. Upon
* success, data
provides access to the concatenation of
* data
and the String
specified.
* @param text the text node
* @param arg The String
to append.
* @exception DOMException
* NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
*/
public static final native void appendData(Text text, String arg) throws JavaScriptException /*-{
text.appendData(offset, arg);
}-*/;
/**
* Retrieves an attribute value by local name and namespace URI on
* the specified element.
*
Per [XML Namespaces]
* , applications must use the value null
as the
* namespaceURI
parameter for methods if they wish to have
* no namespace.
* @param elem the element
* @param namespaceURI The namespace URI of the attribute to retrieve.
* @param localName The local name of the attribute to retrieve.
* @return The Attr
value as a string, or the empty string
* if that attribute does not have a specified or default value.
* @exception DOMException
* NOT_SUPPORTED_ERR: May be raised if the implementation does not
* support the feature "XML"
and the language exposed
* through the Document does not support XML Namespaces (such as [HTML 4.01]).
* @since DOM Level 2
*/
public static final native String getAttributeNS(Element elem, String namespaceURI, String localName) throws JavaScriptException /*-{
return elem.getAttributeNS(namespaceURI, localName);
}-*/;
/**
* Returns a NodeList
of all the descendant
* Elements
of the specified element
* with a given local name and namespace URI in
* document order.
* @param elem The element
* @param namespaceURI The namespace URI of the elements to match on. The
* special value "*" matches all namespaces.
* @param localName The local name of the elements to match on. The
* special value "*" matches all local names.
* @return A new NodeList
object containing all the matched
* Elements
.
* @exception DOMException
* NOT_SUPPORTED_ERR: May be raised if the implementation does not
* support the feature "XML"
and the language exposed
* through the Document does not support XML Namespaces (such as [HTML 4.01]).
* @since DOM Level 2
*/
public static final native NodeList extends Node> getElementsByTagNameNS(Element elem, String namespaceURI, String localName) throws JavaScriptException /*-{
return elem.getElementsByTagNameNS(namespaceURI, localName);
}-*/;
/**
* Returns a NodeList
of all the Elements
* in the specified document with a
* given local name and namespace URI in document order.
* @param doc The document
* @param namespaceURI The namespace URI of the elements to match on. The
* special value "*"
matches all namespaces.
* @param localName The local name of the elements to match on. The
* special value "*" matches all local names.
* @return A new NodeList
object containing all the matched
* Elements
.
* @since DOM Level 2
*/
public static final native NodeList extends Node> getElementsByTagNameNS(Document doc, String namespaceURI, String localName) throws JavaScriptException /*-{
return doc.getElementsByTagNameNS(namespaceURI, localName);
}-*/;
/**
* Returns the current document
* @return the current document
*/
public static final native Document getCurrentDocument() /*-{
return $doc;
}-*/;
/**
* Returns a NamedNodeMap
containing the attributes of the
* specified element.
* @param elem The element
* @return a NamedNodeMap
containing the attributes of the
* specified element
*/
public static final native NamedNodeMap getAttributes(Element elem) /*-{
return elem.attributes;
}-*/;
/**
* Retrieves an attribute node by name on the specified element.
*
To retrieve an attribute node by qualified name and namespace URI,
* use the getAttributeNodeNS
method.
* @param elt The element
* @param attrName The name (nodeName
) of the attribute to
* retrieve.
* @return The Attr
node with the specified name (
* nodeName
) or null
if there is no such
* attribute.
*/
public static final native Attr getAttributeNode(Element elt, String attrName) /*-{
return elt.getAttributeNode(attrName);
}-*/;
/**
* Adds a new attribute node to the specified element. If an attribute with that name (
* nodeName
) is already present in the element, it is
* replaced by the new one. Replacing an attribute node by itself has no
* effect.
*
To add a new attribute node with a qualified name and namespace
* URI, use the setAttributeNodeNS
method.
* @param elt The element
* @param attr The Attr
node to add to the attribute list.
* @return If the attr
attribute replaces an existing
* attribute, the replaced Attr
node is returned,
* otherwise null
is returned.
* @exception DOMException
* WRONG_DOCUMENT_ERR: Raised if attr
was created from a
* different document than the one that created the element.
*
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
*
INUSE_ATTRIBUTE_ERR: Raised if attr
is already an
* attribute of another Element
object. The DOM user must
* explicitly clone Attr
nodes to re-use them in other
* elements.
*/
public static final native Attr setAttributeNode(Element elt, Attr attr) throws JavaScriptException /*-{
return elt.setAttributeNode(attr);
}-*/;
/**
* Returns true
when an attribute with a given local name and
* namespace URI is specified on the specified element or has a default value,
* false
otherwise.
*
Per [XML Namespaces]
* , applications must use the value null
as the
* namespaceURI
parameter for methods if they wish to have
* no namespace.
* @param elem The element
* @param namespaceURI The namespace URI of the attribute to look for.
* @param localName The local name of the attribute to look for.
* @return true
if an attribute with the given local name
* and namespace URI is specified or has a default value on this
* element, false
otherwise.
* @exception DOMException
* NOT_SUPPORTED_ERR: May be raised if the implementation does not
* support the feature "XML"
and the language exposed
* through the Document does not support XML Namespaces (such as [HTML 4.01]).
*/
public static final native boolean hasAttributeNS(Element elem, String namespaceURI, String localName) throws JavaScriptException /*-{
return elem.hasAttributeNS(namespaceURI, localName);
}-*/;
/**
* Adds a new attribute to the specified element. If an attribute with the same local name and
* namespace URI is already present on the element, its prefix is
* changed to be the prefix part of the qualifiedName
, and
* its value is changed to be the value
parameter. This
* value is a simple string; it is not parsed as it is being set. So any
* markup (such as syntax to be recognized as an entity reference) is
* treated as literal text, and needs to be appropriately escaped by the
* implementation when it is written out. In order to assign an
* attribute value that contains entity references, the user must create
* an Attr
node plus any Text
and
* EntityReference
nodes, build the appropriate subtree,
* and use setAttributeNodeNS
or
* setAttributeNode
to assign it as the value of an
* attribute.
*
Per [XML Namespaces]
* , applications must use the value null
as the
* namespaceURI
parameter for methods if they wish to have
* no namespace.
* @param elem The element
* @param namespaceURI The namespace URI of the attribute to create or
* alter.
* @param localName The local name of the attribute to create or
* alter.
* @param value The value to set in string form.
* @exception DOMException
* INVALID_CHARACTER_ERR: Raised if the specified qualified name is not
* an XML name according to the XML version in use specified in the
* Document.xmlVersion
attribute.
*
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
*
NAMESPACE_ERR: Raised if the qualifiedName
is
* malformed per the Namespaces in XML specification, if the
* qualifiedName
has a prefix and the
* namespaceURI
is null
, if the
* qualifiedName
has a prefix that is "xml" and the
* namespaceURI
is different from "
* http://www.w3.org/XML/1998/namespace", if the qualifiedName
or its prefix is "xmlns" and the
* namespaceURI
is different from "http://www.w3.org/2000/xmlns/", or if the namespaceURI
is "http://www.w3.org/2000/xmlns/" and neither the qualifiedName
nor its prefix is "xmlns".
*
NOT_SUPPORTED_ERR: May be raised if the implementation does not
* support the feature "XML"
and the language exposed
* through the Document does not support XML Namespaces (such as [HTML 4.01]).
*/
public static final native void setAttributeNS(Element elem, String namespaceURI, String localName, String value) throws JavaScriptException /*-{
elem.setAttributeNS(namespaceURI, localName, value);
}-*/;
/**
* The namespace URI of the specified node, or null
if it is
* unspecified (see ).
*
This is not a computed value that is the result of a namespace
* lookup based on an examination of the namespace declarations in
* scope. It is merely the namespace URI given at creation time.
*
For nodes of any type other than ELEMENT_NODE
and
* ATTRIBUTE_NODE
and nodes created with a DOM Level 1
* method, such as Document.createElement()
, this is always
* null
.
* Note: Per the Namespaces in XML Specification [XML Namespaces]
* an attribute does not inherit its namespace from the element it is
* attached to. If an attribute is not explicitly given a namespace, it
* simply has no namespace.
* @param node a DOM node
* @return The namespace URI of this node
*/
public static native String getNamespaceURI(Node node) /*-{
return node.namespaceURI;
}-*/;
/**
* Returns the local part of the qualified name of this node.
*
For nodes of any type other than ELEMENT_NODE
and
* ATTRIBUTE_NODE
and nodes created with a DOM Level 1
* method, such as Document.createElement()
, this is always
* null
.
* @param node a DOM node
* @return The local part of the qualified name of this node
*/
public static native String getLocalName(Node node) /*-{
return node.localName;
}-*/;
/**
* Makes a node sink the events emitted by the specified element
* @param elem The element emitting the events
* @param eventName The event name
*/
public static void bindEventListener(Element elem, String eventName) {
impl.bindEventListener(elem, eventName);
}
/**
* Stops making a node sink the events emitted by the specified element
* @param elem The element emitting the events
* @param eventName The event name
*/
public static void unbindEventListener(Element elem, String eventName) {
impl.unbindEventListener(elem, eventName);
}
/**
* Returns the element which currently captures all the
* events after a call to {@link org.vectomatic.dom.svg.utils.DOMHelper#setCaptureElement(OMSVGElement, LoseCaptureHandler)}
* or null if element is set to capture events
* @return The event capturing element
*/
public static OMSVGElement getCaptureElement() {
return impl.getCaptureElement();
}
/**
* Makes the specified element capture all the events, until
* a call to {@link org.vectomatic.dom.svg.utils.DOMHelper#releaseCaptureElement()}
* terminates the capture
* @param element The capturing element
* @param loseCaptureHandler A handler which will be invoked
* if the element loses capture
* @return {@link HandlerRegistration} used to remove this handler
*/
public static HandlerRegistration setCaptureElement(OMSVGElement element, LoseCaptureHandler loseCaptureHandler) {
return impl.setCaptureElement(element, loseCaptureHandler);
}
/**
* Stops the forwarding of all events to the capturing element
* specified by {@link org.vectomatic.dom.svg.utils.DOMHelper#setCaptureElement(OMSVGElement, LoseCaptureHandler)}
*/
public static void releaseCaptureElement() {
impl.releaseCaptureElement();
}
/**
* Returns the JavaScript type of an object.
* The function getType is borrowed from:
* JavaScript: The Definitive Guide, 5th Edition
* By David Flanagan
*/
public static final native String getType(JavaScriptObject x) /*-{
// If x is null, return "null"
if (x == null) {
return "null";
}
// Next try the typeof operator
var t = typeof x;
// If the result is not vague, return it
if (t != "object") {
return t;
}
// Hack from Chrome48+
if ('__IsSVGPathSegList__' in x) {
return 'SVGPathSegList';
}
// Otherwise, x is an object. Use the default toString( ) method to
// get the class value of the object.
var c = Object.prototype.toString.apply(x); // Returns "[object class]"
c = c.substring(8, c.length-1); // Strip off "[object" and "]"
// If the class is not a vague one, return it.
if (c != "Object") {
return c;
}
// If we get here, c is "Object". Check to see if
// the value x is really just a generic object.
if (x.constructor == Object) {
return c; // Okay the type really is "Object"
}
// For user-defined classes, look for a string-valued property named
// classname, that is inherited from the object's prototype
if ("classname" in x.constructor.prototype && // inherits classname
typeof x.constructor.prototype.classname == "string") // its a string
return x.constructor.prototype.classname;
// If we really can't figure it out, say so.
return "";
}-*/;
/**
* Creates a value of the formed expected by SVG
* href attribtues.
* @param s the identifier of the data pointed by the href.
* @return a value of the formed expected by SVG
* href attribtues.
*/
public static final String toUrl(String s) {
return "url(#" + s + ")";
}
/**
* Tests if the underlying DOM implementation supports the specified feature
* @param featureName
* The name of the feature to test
* @return
* true if the feature is supported, false otherwise
*/
public static boolean hasFeature(String featureName) {
if (SVGConstants.SVG_FEATURE_TOUCH_EVENTS.equals(featureName)) {
return supportsSvgTouchEvents();
} if (SVGConstants.SVG_FEATURE_DND_EVENTS.equals(featureName)) {
return supportsSvgDndEvents();
} else {
return hasFeature_(featureName);
}
}
private static native boolean hasFeature_(String featureName) /*-{
return $doc.implementation.hasFeature(featureName, 1.1);
}-*/;
/**
* Evaluates the specified XPath expression and returns
* a iterator for the selected {@link org.vectomatic.dom.svg.OMNode} node list.
* The expression must evaluate to a node list.
* @param root
* The element the expression is rooted at
* @param expr
* The XPath expression
* @param resolver
* A prefix resolver if the expression has prefix
* @return
* A node iterator for the selected nodes.
*/
public static Iterator evaluateXPath(OMElement root, String expr, XPathPrefixResolver resolver) {
final JavaScriptObject result = impl.evaluateNodeListXPath_(root.getElement(), expr, resolver);
return new Iterator() {
boolean fetched;
Node next;
@Override
public boolean hasNext() {
if (!fetched) {
next = iterateNext(result);
fetched = true;
}
return next != null;
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
fetched = false;
return OMNode.convert(next);
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
private native Node iterateNext(JavaScriptObject result) /*-{
return result.iterateNext();
}-*/;
};
}
/**
* Evaluates the specified XPath expression and returns
* a iterator for the selected {@link com.google.gwt.dom.client.Node} node list.
* The expression must evaluate to a node list.
* @param root
* The element the expression is rooted at
* @param expr
* The XPath expression
* @param resolver
* A prefix resolver if the expression has prefix
* @return
* A node iterator for the selected nodes.
*/
public static Iterator evaluateNodeListXPath(Element root, String expr, XPathPrefixResolver resolver) {
final JavaScriptObject result = impl.evaluateNodeListXPath_(root, expr, resolver);
return new Iterator() {
boolean fetched;
T next;
@Override
public boolean hasNext() {
if (!fetched) {
next = iterateNext(result);
fetched = true;
}
return next != null;
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
fetched = false;
return next;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
private native T iterateNext(JavaScriptObject result) /*-{
return result.iterateNext();
}-*/;
};
}
/**
* Evaluates the specified XPath expression and returns
* the matching {@link com.google.gwt.dom.client.Node} node.
* The expression must evaluate to a single node.
* @param root
* The element the expression is rooted at
* @param expr
* The XPath expression
* @param resolver
* A prefix resolver if the expression has prefix
* @return
* The selected node, or null if no such node exists.
*/
public static T evaluateNodeXPath(Element root, String expr, XPathPrefixResolver resolver) {
return (T)(impl.evaluateNodeXPath_(root, expr, resolver));
}
/**
* Evaluates the specified XPath expression and returns
* the matching {@link java.lang.String}.
* The expression must evaluate to a string.
* @param root
* The element the expression is rooted at
* @param expr
* The XPath expression
* @param resolver
* A prefix resolver if the expression has prefix
* @return
* The matching string, or null if no such string exists.
*/
public static String evaluateStringXPath(Element root, String expr, XPathPrefixResolver resolver) {
return impl.evaluateStringXPath_(root, expr, resolver);
}
/**
* Evaluates the specified XPath expression and returns
* the matching float.
* The expression must evaluate to a number.
* @param root
* The element the expression is rooted at
* @param expr
* The XPath expression
* @param resolver
* A prefix resolver if the expression has prefix
* @return
* The matching float, or NaN if no such number exists.
*/
public static float evaluateNumberXPath(Element root, String expr, XPathPrefixResolver resolver) {
return impl.evaluateNumberXPath_(root, expr, resolver);
}
/**
* Evaluates the specified XPath expression and returns
* the matching boolean.
* The expression must evaluate to a boolean.
* @param root
* The element the expression is rooted at
* @param expr
* The XPath expression
* @param resolver
* A prefix resolver if the expression has prefix
* @return
* The matching boolean.
*/
public static boolean evaluateBooleanXPath(Element root, String expr, XPathPrefixResolver resolver) {
return impl.evaluateBooleanXPath_(root, expr, resolver);
}
/**
* Returns an XPath expression which enables reaching the specified node
* from the root node
* @param node
* The node to reach
* @param root
* The root node, or null to specify the document root
* @return
* An XPath expression which enables reaching the specified node
* from the root node
*/
public static String getXPath(Node node, Node root) {
StringBuilder builder = new StringBuilder();
Node parentNode;
while ((node != root) && (parentNode = node.getParentNode()) != null) {
NodeList siblings = parentNode.getChildNodes();
int index = 0;
for (int i = 0, length = siblings.getLength(); i < length; i++) {
Node sibling = siblings.getItem(i);
if (sibling.getNodeType() == Node.ELEMENT_NODE) {
index++;
if (node == sibling) {
builder.insert(0, "/*[" + index + "]");
break;
}
}
}
node = parentNode;
}
return builder.toString();
}
/**
* Returns whether touch events on SVG elements are supported
* on the current platform.
* @return true if touch events on SVG elements are supported
* on the current platform, false otherwise
* @deprecated
* Use the {@link #hasFeature(String)} method with the
* {@link SVGConstants#SVG_FEATURE_TOUCH_EVENTS} parameter instead.
*/
public static native boolean supportsSvgTouchEvents() /*-{
var elem = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
elem.setAttribute('ontouchstart', 'return;');
return (typeof elem.ontouchstart) == "function";
}-*/;
/***
* Returns whether drag and drop events on SVG elements are supported
* on the current platform.
* @return true if drag and drop events on SVG elements are supported
* on the current platform, false otherwise
*/
private static native boolean supportsSvgDndEvents() /*-{
var elem = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
return 'ondragstart' in elem;
}-*/;
/**
* Returns a base64 encoding of the specified binary string
* @param str
* A binary string (obtained for instance by the FileReader API)
* @return a base64 encoded string.
*/
public static native String base64encode(String str) /*-{
return $wnd.btoa(str);
}-*/;
}