com.google.gwt.query.client.GQuery Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2011, The gwtquery team.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.query.client;
import static com.google.gwt.query.client.plugins.QueuePlugin.Queue;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayMixed;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.core.client.ScriptInjector;
import com.google.gwt.dom.client.BodyElement;
import com.google.gwt.dom.client.ButtonElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.InputElement;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.OptionElement;
import com.google.gwt.dom.client.SelectElement;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.TextAreaElement;
import com.google.gwt.query.client.builders.JsonBuilder;
import com.google.gwt.query.client.css.HasCssValue;
import com.google.gwt.query.client.css.TakesCssValue;
import com.google.gwt.query.client.css.TakesCssValue.CssSetter;
import com.google.gwt.query.client.impl.AttributeImpl;
import com.google.gwt.query.client.impl.DocumentStyleImpl;
import com.google.gwt.query.client.impl.SelectorEngine;
import com.google.gwt.query.client.js.JsCache;
import com.google.gwt.query.client.js.JsMap;
import com.google.gwt.query.client.js.JsNamedArray;
import com.google.gwt.query.client.js.JsNodeArray;
import com.google.gwt.query.client.js.JsObjectArray;
import com.google.gwt.query.client.js.JsUtils;
import com.google.gwt.query.client.plugins.Effects;
import com.google.gwt.query.client.plugins.Events;
import com.google.gwt.query.client.plugins.Plugin;
import com.google.gwt.query.client.plugins.Widgets;
import com.google.gwt.query.client.plugins.ajax.Ajax;
import com.google.gwt.query.client.plugins.ajax.Ajax.Settings;
import com.google.gwt.query.client.plugins.deferred.Deferred;
import com.google.gwt.query.client.plugins.deferred.PromiseFunction;
import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing;
import com.google.gwt.query.client.plugins.events.EventsListener;
import com.google.gwt.query.client.plugins.widgets.WidgetsUtils;
import com.google.gwt.regexp.shared.MatchResult;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* GwtQuery is a GWT clone of the popular jQuery library.
*/
public class GQuery implements Lazy {
private enum DomMan {
AFTER, APPEND, BEFORE, PREPEND;
}
/**
* A POJO used to store the top/left CSS positioning values of an element.
*/
public static class Offset {
public int left;
public int top;
public Offset(int left, int top) {
this.left = left;
this.top = top;
}
public Offset add(int left, int top) {
return new Offset(this.left + left, this.top + top);
}
public String toString() {
return top + "+" + left;
}
}
/**
* Class used internally to create DOM element from html snippet.
*/
private static class TagWrapper {
public static final TagWrapper DEFAULT = new TagWrapper(0, "", "");
private String postWrap;
private String preWrap;
private int wrapDepth;
public TagWrapper(int wrapDepth, String preWrap, String postWrap) {
this.wrapDepth = wrapDepth;
this.postWrap = postWrap;
this.preWrap = preWrap;
}
}
/**
* Implementation class to modify attributes.
*/
protected static AttributeImpl attributeImpl;
/**
* The body element in the current page.
*/
public static final BodyElement body = GWT.isClient() ? Document.get().getBody() : null;
/**
* A Browser object with a set of browser-specific flags.
*/
public static final Browser browser = GWT.isClient() ? GWT.create(Browser.class) : null;
/**
* An object with the same methods than window.console.
*/
public static final Console console = GWT.isClient() ? GWT.create(Console.class) : null;
/**
* Object to store element data (public so as we can access to it from tests).
*/
public static JsCache dataCache = null;
/**
* The document element in the current page.
*/
public static final Document document = GWT.isClient() ? Document.get() : null;
/**
* Static reference Effects plugin.
*/
public static Class Effects = com.google.gwt.query.client.plugins.Effects.Effects;
/**
* Implementation engine used for CSS selectors.
*/
protected static SelectorEngine engine;
/**
* Static reference Events plugin.
*/
public static Class Events = com.google.gwt.query.client.plugins.Events.Events;
/**
* A static reference to the GQuery class.
*/
public static Class GQUERY = GQuery.class;
private static final String OLD_DATA_PREFIX = "old-";
private static final String OLD_DISPLAY = OLD_DATA_PREFIX + "display";
private static JsMap, Plugin extends GQuery>> plugins;
// Sizzle POS regex : usefull in some methods
// TODO: Share this static with SelectorEngineSizzle
private static RegExp posRegex = RegExp
.compile("^:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)$");
/**
* Implementation class used for style manipulations.
*/
private static DocumentStyleImpl styleImpl;
private static RegExp tagNameRegex = RegExp.compile("<([\\w:-]+)");
/**
* Static reference to the Widgets plugin.
*/
public static Class Widgets = com.google.gwt.query.client.plugins.Widgets.Widgets;
/**
* The window object.
*/
public static final Element window = GWT.isClient() ? ScriptInjector.TOP_WINDOW. cast()
: null;
private static Element windowData = null;
private static JsNamedArray wrapperMap;
/**
* Create an empty GQuery object.
*/
public static GQuery $() {
return new GQuery(JsNodeArray.create());
}
/**
* Wrap a GQuery around any object, supported objects are:
* String, GQuery, Function, Widget, JavaScriptObject.
*
* In the case of string, we accept a CSS selector which is then used to match a set of
* elements, or a raw HTML to create a GQuery element containing those elements. Xpath
* selector is supported in browsers with native xpath engine.
*
* In the case of a JavaScriptObject we handle:
* Element, Event, Node, Nodelist, Function, and native functions or arrays.
*
* If the case of a native function, we execute it and return empty.
*/
public static GQuery $(Object o) {
if (o != null) {
if (o instanceof String) {
return $((String) o);
}
if (o instanceof SafeHtml) {
return $(((SafeHtml) o).asString());
}
if (o instanceof GQuery) {
return (GQuery) o;
}
if (o instanceof Function) {
return new GQuery(((Function) o).getElement());
}
if (JsUtils.isElement(o)) {
return new GQuery(JsUtils. cast(o));
}
if (o instanceof JsonBuilder) {
return new GQuery(((JsonBuilder) o).getDataImpl());
}
if (o instanceof IsWidget) {
return $(Arrays.asList(o));
}
if (o instanceof JavaScriptObject) {
JavaScriptObject jso = (JavaScriptObject) o;
// Execute a native javascript function like jquery does
if (JsUtils.isFunction(jso)) {
new JsUtils.JsFunction(jso).fe();
return $();
}
// Wraps a native array like jquery does
if (!JsUtils.isWindow(jso) && !JsUtils.isElement(jso) && JsUtils.isArray(jso)) {
JsArrayMixed c = jso.cast();
JsNodeArray elms = JsNodeArray.create();
for (int i = 0; i < c.length(); i++) {
Object obj = c.getObject(i);
if (obj instanceof Node) {
elms.addNode((Node) obj);
}
}
return new GQuery(elms);
}
// Wraps a native NodeList
if (JsUtils.isNodeList(jso)) {
return new GQuery(jso.> cast());
}
// Wraps an event
if (JsUtils.isEvent(jso)) {
jso = jso.cast().getCurrentEventTarget();
}
// Otherwise we wrap it as an element
return new GQuery(jso. cast());
}
throw new RuntimeException("Error: GQuery.$(Object o) could not wrap the type : " + o.getClass().getName() + " " + o);
}
return $();
}
/**
* Create a new GQuery given a list of {@link com.google.gwt.dom.client.Node} or
* {@link com.google.gwt.user.client.ui.IsWidget}.
*/
public static GQuery $(List> nodesOrWidgets) {
JsNodeArray elms = JsNodeArray.create();
if (nodesOrWidgets != null) {
for (Object o : nodesOrWidgets) {
if (o instanceof Node) {
elms.addNode((Node) o);
} else if (o instanceof IsWidget) {
elms.addNode(((IsWidget) o).asWidget().getElement());
}
}
}
return new GQuery(elms);
}
/**
* This function accepts a string containing a CSS selector which is then used to match a set of
* elements, or it accepts raw HTML creating a GQuery element containing those elements. Xpath
* selector is supported in browsers with native xpath engine.
*/
public static GQuery $(String selectorOrHtml) {
return $(selectorOrHtml, document);
}
/**
* This function accepts a string containing a CSS selector which is then used to match a set of
* elements, or it accepts raw HTML creating a GQuery element containing those elements. The
* second parameter is is a class reference to a plugin to be used.
*
* Xpath selector is supported in browsers with native xpath engine.
*/
public static T $(String selector, Class plugin) {
return $(selector, document, plugin);
}
/**
* This function accepts a string containing a CSS selector which is then used to match a set of
* elements, or it accepts raw HTML creating a GQuery element containing those elements. The
* second parameter is the context to use for the selector, or the document where the new elements
* will be created.
*
* Xpath selector is supported in browsers with native xpath engine.
*/
public static GQuery $(String selectorOrHtml, Node ctx) {
String selector = null;
if (selectorOrHtml == null || (selector = selectorOrHtml.trim()).length() == 0) {
return $();
}
if (selector.startsWith("<")) {
return innerHtml(selectorOrHtml, JsUtils.getOwnerDocument(ctx));
}
return new GQuery().select(selectorOrHtml, ctx);
}
/**
* This function accepts a string containing a CSS selector which is then used to match a set of
* elements, or it accepts raw HTML creating a GQuery element containing those elements. The
* second parameter is the context to use for the selector. The third parameter is the class
* plugin to use.
*
* Xpath selector is supported in browsers with native xpath engine.
*/
@SuppressWarnings("unchecked")
public static T $(String selector, Node context, Class plugin) {
try {
if (plugins != null) {
T gquery = (T) plugins.get(plugin).init(new GQuery().select(selector, context));
return gquery;
}
throw new RuntimeException("No plugin for class " + plugin);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* This function accepts a string containing a CSS selector which is then used to match a set of
* elements, or it accepts raw HTML creating a GQuery element containing those elements. The
* second parameter is the context to use for the selector, or the document where the new elements
* will be created.
*
* Xpath selector is supported in browsers with native xpath engine.
*/
public static GQuery $(String selectorOrHtml, Widget context) {
return $(selectorOrHtml, context.getElement());
}
/**
* This function accepts a string containing a CSS selector which is then used to match a set of
* elements, or it accepts raw HTML creating a GQuery element containing those elements. The
* second parameter is the context to use for the selector. The third parameter is the class
* plugin to use.
*
* Xpath selector is supported in browsers with native xpath engine.
*/
public static T $(String selector, Widget context, Class plugin) {
return $(selector, context.getElement(), plugin);
}
/**
* Wrap a GQuery around one widget or an array of existing ones.
*/
public static GQuery $(Widget... widgets) {
return $(Arrays.asList(widgets));
}
/**
* Wrap a GQuery around one node or an array of existing ones.
*/
public static GQuery $(Node... nodes) {
return $(Arrays.asList(nodes));
}
/**
* Create an empty JSON object.
*/
public static Properties $$() {
return $$(null);
}
/**
* Wrap a JSON object.
*/
public static Properties $$(String properties) {
return Properties.create(properties);
}
/**
* Perform an ajax request to the server.
*/
public static Promise ajax(Properties p) {
return Ajax.ajax(p);
}
/**
* Perform an ajax request to the server.
*/
public static Promise ajax(Settings settings) {
return Ajax.ajax(settings);
}
/**
* Perform an ajax request to the server.
*/
public static Promise ajax(String url, Settings settings) {
return Ajax.ajax(url, settings);
}
protected static GQuery cleanHtmlString(String elem, Document doc) {
MatchResult mResult = tagNameRegex.exec(elem);
if (mResult == null) {
return $(doc.createTextNode(elem));
}
String tag = mResult.getGroup(1);
if (wrapperMap == null) {
initWrapperMap();
}
TagWrapper wrapper = wrapperMap.get(tag.toLowerCase());
if (wrapper == null) {
wrapper = TagWrapper.DEFAULT;
}
// TODO: fix IE link tag serialization
// TODO: fix IE