diff options
author | Manuel Carrasco Moñino <manuel.carrasco.m@gmail.com> | 2012-11-26 16:20:48 +0100 |
---|---|---|
committer | Manuel Carrasco Moñino <manuel.carrasco.m@gmail.com> | 2012-11-26 16:20:48 +0100 |
commit | 1313f0c0286cc31edf9874cedeb44f8689e7d0d0 (patch) | |
tree | 2b8f76e39102d96fa813fab5b7dec78765d6bcde | |
parent | 305fd24cf14d4592ce0db0409193195ebc686678 (diff) | |
download | gwtquery-1313f0c0286cc31edf9874cedeb44f8689e7d0d0.tar.gz gwtquery-1313f0c0286cc31edf9874cedeb44f8689e7d0d0.zip |
End lines with LF instead of CRLF
213 files changed, 18053 insertions, 18053 deletions
diff --git a/archetype/src/main/resources/archetype-resources/pom.xml b/archetype/src/main/resources/archetype-resources/pom.xml index d0de9573..dc350f81 100644 --- a/archetype/src/main/resources/archetype-resources/pom.xml +++ b/archetype/src/main/resources/archetype-resources/pom.xml @@ -1,197 +1,197 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<project>
- <modelVersion>4.0.0</modelVersion>
-
- <name>${projectName} gwtquery project</name>
- <groupId>${groupId}</groupId>
- <artifactId>${artifactId}</artifactId>
- <packaging>war</packaging>
- <version>${version}</version>
-
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <maven.compiler.source>1.6</maven.compiler.source>
- <maven.compiler.target>1.6</maven.compiler.target>
- <gQueryVersion>1.1.0</gQueryVersion>
- <gwtversion>2.5.0-rc1</gwtversion>
- <gwtmaven>2.4.0</gwtmaven>
- </properties>
-
- <repositories>
- <repository>
- <id>central</id>
- <url>http://repo1.maven.org/maven2</url>
- </repository>
- <repository>
- <id>gwtquery-plugins</id>
- <url>http://gwtquery-plugins.googlecode.com/svn/mavenrepo</url>
- </repository>
- <repository>
- <id>sonatype</id>
- <url>http://oss.sonatype.org/content/repositories/snapshots</url>
- <snapshots><enabled>true</enabled></snapshots>
- <releases><enabled>false</enabled></releases>
- </repository>
- <repository>
- <id>m.g.o</id>
- <url>http://maven.glassfish.org/content/groups/public/</url>
- </repository>
- </repositories>
-
- <scm>
- </scm>
-
- <issueManagement>
- </issueManagement>
-
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>3.8.1</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>com.google.gwt</groupId>
- <artifactId>gwt-user</artifactId>
- <version>${gwtversion}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>com.google.gwt</groupId>
- <artifactId>gwt-dev</artifactId>
- <version>${gwtversion}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>com.google.gwt</groupId>
- <artifactId>gwt-servlet</artifactId>
- <version>${gwtversion}</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>com.googlecode.gwtquery</groupId>
- <artifactId>gwtquery</artifactId>
- <version>${gQueryVersion}</version>
- <scope>provided</scope>
- </dependency>
- <!-- GWT 2.3.0 depends on these -->
- <dependency>
- <groupId>javax.validation</groupId>
- <artifactId>validation-api</artifactId>
- <version>1.0.0.GA</version>
- </dependency>
- <dependency>
- <groupId>javax.validation</groupId>
- <artifactId>validation-api</artifactId>
- <version>1.0.0.GA</version>
- <classifier>sources</classifier>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>2.1</version>
- <configuration>
- <source>1.6</source>
- <target>1.6</target>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>gwt-maven-plugin</artifactId>
- <version>${gwtmaven}</version>
- <configuration>
- <logLevel>${gwt.loglevel}</logLevel>
- <style>${gwt.outputstyle}</style>
- <gwtVersion>${gwtversion}</gwtVersion>
- <compileReport>true</compileReport>
- <runTarget>${projectName}/${projectName}.html</runTarget>
- <hostedWebApp>${project.build.directory}/${project.build.finalName}</hostedWebApp>
- </configuration>
- <executions>
- <execution>
- <phase>prepare-package</phase>
- <goals>
- <goal>compile</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>2.8.1</version>
- <configuration>
- <additionalClasspathElements>
- <additionalClasspathElement>\${project.build.sourceDirectory}</additionalClasspathElement>
- <additionalClasspathElement>\${project.build.testSourceDirectory}</additionalClasspathElement>
- </additionalClasspathElements>
- <useManifestOnlyJar>false</useManifestOnlyJar>
- <forkMode>always</forkMode>
- <systemProperties>
- <property>
- <name>gwt.args</name>
- <value>-out target/gwt-tests</value>
- </property>
- <property>
- <!-- Setting this to true (default) causes a exception first time test are run Gwt issue_6443 -->
- <name>gwt.persistentunitcache</name>
- <value>false</value>
- </property>
- </systemProperties>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-eclipse-plugin</artifactId>
- <version>2.7</version>
- <configuration>
- <downloadSources>true</downloadSources>
- <downloadJavadocs>false</downloadJavadocs>
- <additionalBuildcommands>
- <buildcommand>com.google.gwt.eclipse.core.gwtProjectValidator</buildcommand>
- <buildcommand>org.eclipse.wst.common.modulecore.ComponentStructuralBuilder</buildcommand>
- <buildcommand>org.eclipse.jdt.core.javabuilder</buildcommand>
- <buildcommand>org.eclipse.wst.common.modulecore.ComponentStructuralBuilderDependencyResolver</buildcommand>
- </additionalBuildcommands>
- <additionalProjectnatures>
- <projectnature>com.google.gwt.eclipse.core.gwtNature</projectnature>
- <projectnature>org.eclipse.jdt.core.javanature</projectnature>
- <projectnature>org.eclipse.wst.common.modulecore.ModuleCoreNature</projectnature>
- </additionalProjectnatures>
- <classpathContainers>
- <classpathContainer>com.google.gwt.eclipse.core.GWT_CONTAINER</classpathContainer>
- <classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer>
- <classpathContainer>org.eclipse.jdt.junit.JUNIT_CONTAINER/3</classpathContainer>
- </classpathContainers>
- </configuration>
- </plugin>
- <!-- GWT plugin does not copy the webapp folder in hosted mode -->
- <plugin>
- <artifactId>maven-resources-plugin</artifactId>
- <version>2.5</version>
- <executions>
- <execution>
- <id>copy-resources</id>
- <phase>generate-sources</phase>
- <goals>
- <goal>copy-resources</goal>
- </goals>
- <configuration>
- <outputDirectory>${project.build.directory}/${project.build.finalName}</outputDirectory>
- <resources>
- <resource>
- <directory>src/main/webapp</directory>
- <filtering>true</filtering>
- </resource>
- </resources>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- <outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory>
- </build>
-</project>
+<?xml version="1.0" encoding="UTF-8"?> +<project> + <modelVersion>4.0.0</modelVersion> + + <name>${projectName} gwtquery project</name> + <groupId>${groupId}</groupId> + <artifactId>${artifactId}</artifactId> + <packaging>war</packaging> + <version>${version}</version> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <maven.compiler.source>1.6</maven.compiler.source> + <maven.compiler.target>1.6</maven.compiler.target> + <gQueryVersion>1.1.0</gQueryVersion> + <gwtversion>2.5.0-rc1</gwtversion> + <gwtmaven>2.4.0</gwtmaven> + </properties> + + <repositories> + <repository> + <id>central</id> + <url>http://repo1.maven.org/maven2</url> + </repository> + <repository> + <id>gwtquery-plugins</id> + <url>http://gwtquery-plugins.googlecode.com/svn/mavenrepo</url> + </repository> + <repository> + <id>sonatype</id> + <url>http://oss.sonatype.org/content/repositories/snapshots</url> + <snapshots><enabled>true</enabled></snapshots> + <releases><enabled>false</enabled></releases> + </repository> + <repository> + <id>m.g.o</id> + <url>http://maven.glassfish.org/content/groups/public/</url> + </repository> + </repositories> + + <scm> + </scm> + + <issueManagement> + </issueManagement> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>3.8.1</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.google.gwt</groupId> + <artifactId>gwt-user</artifactId> + <version>${gwtversion}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.google.gwt</groupId> + <artifactId>gwt-dev</artifactId> + <version>${gwtversion}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.google.gwt</groupId> + <artifactId>gwt-servlet</artifactId> + <version>${gwtversion}</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>com.googlecode.gwtquery</groupId> + <artifactId>gwtquery</artifactId> + <version>${gQueryVersion}</version> + <scope>provided</scope> + </dependency> + <!-- GWT 2.3.0 depends on these --> + <dependency> + <groupId>javax.validation</groupId> + <artifactId>validation-api</artifactId> + <version>1.0.0.GA</version> + </dependency> + <dependency> + <groupId>javax.validation</groupId> + <artifactId>validation-api</artifactId> + <version>1.0.0.GA</version> + <classifier>sources</classifier> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>2.1</version> + <configuration> + <source>1.6</source> + <target>1.6</target> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>gwt-maven-plugin</artifactId> + <version>${gwtmaven}</version> + <configuration> + <logLevel>${gwt.loglevel}</logLevel> + <style>${gwt.outputstyle}</style> + <gwtVersion>${gwtversion}</gwtVersion> + <compileReport>true</compileReport> + <runTarget>${projectName}/${projectName}.html</runTarget> + <hostedWebApp>${project.build.directory}/${project.build.finalName}</hostedWebApp> + </configuration> + <executions> + <execution> + <phase>prepare-package</phase> + <goals> + <goal>compile</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.8.1</version> + <configuration> + <additionalClasspathElements> + <additionalClasspathElement>\${project.build.sourceDirectory}</additionalClasspathElement> + <additionalClasspathElement>\${project.build.testSourceDirectory}</additionalClasspathElement> + </additionalClasspathElements> + <useManifestOnlyJar>false</useManifestOnlyJar> + <forkMode>always</forkMode> + <systemProperties> + <property> + <name>gwt.args</name> + <value>-out target/gwt-tests</value> + </property> + <property> + <!-- Setting this to true (default) causes a exception first time test are run Gwt issue_6443 --> + <name>gwt.persistentunitcache</name> + <value>false</value> + </property> + </systemProperties> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-eclipse-plugin</artifactId> + <version>2.7</version> + <configuration> + <downloadSources>true</downloadSources> + <downloadJavadocs>false</downloadJavadocs> + <additionalBuildcommands> + <buildcommand>com.google.gwt.eclipse.core.gwtProjectValidator</buildcommand> + <buildcommand>org.eclipse.wst.common.modulecore.ComponentStructuralBuilder</buildcommand> + <buildcommand>org.eclipse.jdt.core.javabuilder</buildcommand> + <buildcommand>org.eclipse.wst.common.modulecore.ComponentStructuralBuilderDependencyResolver</buildcommand> + </additionalBuildcommands> + <additionalProjectnatures> + <projectnature>com.google.gwt.eclipse.core.gwtNature</projectnature> + <projectnature>org.eclipse.jdt.core.javanature</projectnature> + <projectnature>org.eclipse.wst.common.modulecore.ModuleCoreNature</projectnature> + </additionalProjectnatures> + <classpathContainers> + <classpathContainer>com.google.gwt.eclipse.core.GWT_CONTAINER</classpathContainer> + <classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer> + <classpathContainer>org.eclipse.jdt.junit.JUNIT_CONTAINER/3</classpathContainer> + </classpathContainers> + </configuration> + </plugin> + <!-- GWT plugin does not copy the webapp folder in hosted mode --> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>2.5</version> + <executions> + <execution> + <id>copy-resources</id> + <phase>generate-sources</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>${project.build.directory}/${project.build.finalName}</outputDirectory> + <resources> + <resource> + <directory>src/main/webapp</directory> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + <outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory> + </build> +</project> diff --git a/archetype/src/main/resources/archetype-resources/src/main/java/__artifactId__/__projectName__.gwt.xml b/archetype/src/main/resources/archetype-resources/src/main/java/__artifactId__/__projectName__.gwt.xml index 5476f939..13e1d579 100644 --- a/archetype/src/main/resources/archetype-resources/src/main/java/__artifactId__/__projectName__.gwt.xml +++ b/archetype/src/main/resources/archetype-resources/src/main/java/__artifactId__/__projectName__.gwt.xml @@ -5,4 +5,4 @@ <inherits name='com.google.gwt.query.Query'/> <entry-point class='${package}.${artifactId}.client.${projectName}'/> </module> - + diff --git a/archetype/src/main/resources/archetype-resources/src/main/java/__artifactId__/client/__projectName__.java b/archetype/src/main/resources/archetype-resources/src/main/java/__artifactId__/client/__projectName__.java index 891f5d3e..d5c178e8 100644 --- a/archetype/src/main/resources/archetype-resources/src/main/java/__artifactId__/client/__projectName__.java +++ b/archetype/src/main/resources/archetype-resources/src/main/java/__artifactId__/client/__projectName__.java @@ -1,31 +1,31 @@ #set( $symbol_pound = '#' ) #set( $symbol_dollar = '$' ) #set( $symbol_escape = '\' ) -package ${package}.${artifactId}.client;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.query.client.Function;
-import static com.google.gwt.query.client.GQuery.*;
-
-
-import com.google.gwt.core.client.EntryPoint;
-
-/**
- * Example code for a GwtQuery application
- */
-public class ${projectName} implements EntryPoint {
-
- public void onModuleLoad() {
-
- ${symbol_dollar}("div")
- .hover(new Function() {
- public void f(Element e) {
- ${symbol_dollar}(e).css("color", "blue").stop(true, true).animate("fontSize: '+=10px'");
- }
- }, new Function() {
- public void f(Element e) {
- ${symbol_dollar}(e).css("color", "").stop(true, true).animate("fontSize: '-=10px'");
- }
- });
- }
-
-}
+package ${package}.${artifactId}.client; +import com.google.gwt.dom.client.Element; +import com.google.gwt.query.client.Function; +import static com.google.gwt.query.client.GQuery.*; + + +import com.google.gwt.core.client.EntryPoint; + +/** + * Example code for a GwtQuery application + */ +public class ${projectName} implements EntryPoint { + + public void onModuleLoad() { + + ${symbol_dollar}("div") + .hover(new Function() { + public void f(Element e) { + ${symbol_dollar}(e).css("color", "blue").stop(true, true).animate("fontSize: '+=10px'"); + } + }, new Function() { + public void f(Element e) { + ${symbol_dollar}(e).css("color", "").stop(true, true).animate("fontSize: '-=10px'"); + } + }); + } + +} diff --git a/archetype/src/main/resources/archetype-resources/src/test/java/__artifactId__/client/__projectName__Test.java b/archetype/src/main/resources/archetype-resources/src/test/java/__artifactId__/client/__projectName__Test.java index aef7cf9e..e007a0a6 100644 --- a/archetype/src/main/resources/archetype-resources/src/test/java/__artifactId__/client/__projectName__Test.java +++ b/archetype/src/main/resources/archetype-resources/src/test/java/__artifactId__/client/__projectName__Test.java @@ -23,7 +23,7 @@ public class ${projectName}Test extends GWTTestCase { } public void testOnModuleLoad() { - + // Create a container in the document final GQuery g = $("<div></div>").appendTo(document); @@ -41,7 +41,7 @@ public class ${projectName}Test extends GWTTestCase { public void run() { // assert that the font size increases assertTrue(fontSize(g) > size1); - + // trigger mouse out event final double size2 = fontSize(g); g.trigger(Event.ONMOUSEOUT); @@ -50,7 +50,7 @@ public class ${projectName}Test extends GWTTestCase { // assert that the font size decreases assertTrue(fontSize(g) < size2); g.remove(); - + // finish the test finishTest(); } diff --git a/devtest/src/main/java/com/google/gwt/query/DevTestRunner.gwt.xml b/devtest/src/main/java/com/google/gwt/query/DevTestRunner.gwt.xml index 537f0c47..401fde05 100644 --- a/devtest/src/main/java/com/google/gwt/query/DevTestRunner.gwt.xml +++ b/devtest/src/main/java/com/google/gwt/query/DevTestRunner.gwt.xml @@ -2,4 +2,4 @@ <inherits name='com.google.gwt.query.Query'/> <entry-point class='com.google.gwt.query.client.DevTestRunner'/> </module> - + diff --git a/devtest/src/main/java/com/google/gwt/query/client/DevTestRunner.java b/devtest/src/main/java/com/google/gwt/query/client/DevTestRunner.java index 26b5faea..53ef8e18 100644 --- a/devtest/src/main/java/com/google/gwt/query/client/DevTestRunner.java +++ b/devtest/src/main/java/com/google/gwt/query/client/DevTestRunner.java @@ -1,2022 +1,2022 @@ -/*
- * 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.GQuery.$;
-import static com.google.gwt.query.client.GQuery.window;
-
-import com.google.gwt.core.client.EntryPoint;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.RepeatingCommand;
-import com.google.gwt.query.client.js.JsUtils;
-
-/**
- * This module is thought to emulate a test environment similar to
- * GWTTestCase, but running it in development mode.
- *
- * The main goal of it is to execute tests in a faster way, because you just
- * push reload in your browser after changing any code.
- *
- * @author manolo
- *
- */
-public class DevTestRunner extends MyTestCase implements EntryPoint {
-
- public void onModuleLoad() {
- try {
- gwtSetUp();
- // Replace this with the method to run
- testSomething();
- } catch (Exception ex) {
- ex.printStackTrace();
- $(e).html("").after("<div>ERROR: " + ex.getMessage() + "</div>");
- }
- }
-
- public void testSomething() {
- // Copy and paste any test from the gquery suite
- }
-
- /**
- * Runs jquery code via jsni.
- *
- * Example:
- * System.out.println(evalJQuery("$('div').size()"));
- */
- private native <T> T evalJQuery(String command) /*-{
- command = command.replace(/\$/g, "$wnd.$");
- try {
- return "" + eval(command);
- } catch(e) {
- $wnd.alert(command + " " + e);
- return "";
- }
- }-*/;
-
- /**
- * Loads jquery and schedule the execution of the method testCompare()
- * which should have code to test something in both in jquery and gquery.
- *
- * Put this method in onModuleLoad, and replace below the method to execute
- * after jquery is available
- */
- public void runTestJQuery() {
- JsUtils.loadScript("jquery-1.6.2.js", "jq");
- Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
- private int cont = 0;
- private native boolean loaded(String func) /*-{
- return eval("$wnd." + func) ? true : false;
- }-*/;
- public boolean execute() {
- if (cont++ > 10 || JsUtils.hasProperty(window, "$")) {
-
- // Replace with the method to run
- testJQueryCompare();
- return false;
- }
- return true;
- }
- }, 100);
- }
-
- public void testJQueryCompare() {
- $(e).html("<div id='parent' style='background-color: yellow; width: 100px; height: 200px; top:130px; position: absolute; left: 130px'><p id='child' style='background-color: pink; width: 100px; height: 100px; position: absolute; padding: 5px'>Content 1</p></div>");
- GQuery g = $("#child");
- Properties prop1;
-
- prop1 = GQuery.$$("marginTop: '0', marginLeft: '0', top: '0%', left: '0%', width: '100px', height: '100px', padding: '5px'");
- g.css(prop1);
- validateCurCSSBoth("#child", prop1.keys());
- }
-
- public void validateSizesBoth(String html) {
- $(e).html(html);
- String gqw = "" + $(".outer").width();
- String jqw = evalJQuery("$('.outer').width()");
- String gqh = "" + $(".outer").height();
- String jqh = evalJQuery("$('.outer').height()");
-
- System.out.println(".outer size: GQuery: " + gqw + "x" + gqh + " jQuery: " + jqw + "x" + jqh);
- assertEquals(gqw, jqw);
- assertEquals(gqh, jqh);
- }
-
- public void validateCssBoth(String selector, boolean force, String... props) {
- for (String prop: props) {
- String gs = $(selector).css(prop, force);
- String js = evalJQuery("$.css($('" + selector + "').get(0), '" + prop + "', " + force + ")");
- System.out.println(selector + " prop:" + prop + " force:" + force + " gQuery:" + gs + " jQuery:" + js);
- assertEquals(gs.replaceAll("px", ""), js.replaceAll("px", ""));
- }
- }
-
- public void validateCurCSSBoth(String selector, String... props) {
- for (String prop: props) {
- String gs = Double.toString($(selector).cur(prop, true)).replaceFirst("\\.\\d+$", "");
- String js = evalJQuery("$.curCSS($('" + selector + "').get(0), '" + prop + "', true)");
- gs = gs.replaceAll("px$", "");
- js = js.replaceAll("px$", "");
- System.out.println(selector + " prop:" + prop + " gQuery:" + gs + " jQuery:" + js);
- assertEquals(gs, js);
- }
- }
-
- // This method is used to initialize a huge html String, because
- // java 1.5 has a limitation in the size of static strings.
- private String getTestContent() {
- String ret = "";
- ret += "<div>";
- ret += " <div class='head dialog'>";
- ret += " <p><a href='http://www.w3.org/'><img alt='W3C' src='' height='48' width='72'></a></p>";
- ret += " <h1 id='title'>Selectors</h1>";
- ret += " <em><span>.</span></em>";
- ret += " <h2>W3C Working Draft 15 December 2005</h2>";
- ret += " <dl>";
- ret += " <dt>This version:</dt>";
- ret += " <dd><a href='http://www.w3.org/TR/2005/WD-css3-selectors-20051215'>";
- ret += " http://www.w3.org/TR/2005/WD-css3-selectors-20051215</a></dd>";
- ret += " <dt>Latest version:";
- ret += " </dt><dd><a href='http://www.w3.org/TR/css3-selectors'>";
- ret += " http://www.w3.org/TR/css3-selectors</a>";
- ret += " </dd><dt>Previous version:";
- ret += " </dt><dd><a href='http://www.w3.org/TR/2001/CR-css3-selectors-20011113'>";
- ret += " http://www.w3.org/TR/2001/CR-css3-selectors-20011113</a>";
- ret += " </dd><dt><a name='editors-list'></a>Editors:";
- ret += " </dt><dd class='vcard'><span class='fn'>Daniel Glazman</span> (Invited";
- ret += " </dd>";
- ret += " <dd class='vcard'><a class='url fn' href='http://www.tantek.com/' lang='tr'>Tantek Çelik</a>";
- ret += " </dd><dd class='vcard'><a href='mailto:ian@hixie.ch' class='url fn'>Ian";
- ret += " Hickson</a> (<span class='company'><a href='http://www.google.com/'>Google</a></span>)";
- ret += " </dd><dd class='vcard'><span class='fn'>Peter Linss</span> (former";
- ret += " editor, <span class='company'><a href='http://www.netscape.com/'>Netscape/AOL</a></span>)";
- ret += " </dd><dd class='vcard'><span class='fn'>John Williams</span> (former editor, <span class='company'><a href='http://www.quark.com/'>Quark, Inc.</a></span>)";
- ret += " </dd></dl>";
- ret += " <p class='copyright'><a href='http://www.w3.org/Consortium/Legal/ipr-notice#Copyright'>";
- ret += " Copyright</a> © 2005 <a href='http://www.w3.org/'><abbr title='World Wide Web Consortium'>W3C</abbr></a><sup>®</sup>";
- ret += " (<a href='http://www.csail.mit.edu/'><abbr title='Massachusetts";
- ret += " Institute of Technology'>MIT</abbr></a>, <a href='http://www.ercim.org/'><acronym title='European Research";
- ret += " Consortium for Informatics and Mathematics'>ERCIM</acronym></a>, <a href='http://www.keio.ac.jp/'>Keio</a>), All Rights Reserved.";
- ret += " <a href='http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer'>liability</a>,";
- ret += " <a href='http://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks'>trademark</a>,";
- ret += " <a href='http://www.w3.org/Consortium/Legal/copyright-documents'>document";
- ret += " use</a> rules apply.";
- ret += " </p><hr title='Separator for header'>";
- ret += " </div>";
- ret += " <h2><a name='abstract'></a>Abstract</h2>";
- ret += " <p><em>Selectors</em> are patterns that match against elements in a";
- ret += " tree. Selectors have been optimized for use with HTML and XML, and";
- ret += " are designed to be usable in performance-critical code.</p>";
- ret += " <p><acronym title='Cascading Style Sheets'>CSS</acronym> (Cascading";
- ret += " Style Sheets) is a language for describing the rendering of <acronym title='Hypertext Markup Language'>HTML</acronym> and <acronym title='Extensible Markup Language'>XML</acronym> documents on";
- ret += " screen, on paper, in speech, etc. CSS uses Selectors for binding";
- ret += " describes extensions to the selectors defined in CSS level 2. These";
- ret += " extended selectors will be used by CSS level 3.";
- ret += " </p><p>Selectors define the following function:</p>";
- ret += " <pre>expression ∗ element → boolean</pre>";
- ret += " <p>That is, given an element and a selector, this specification";
- ret += " defines whether that element matches the selector.</p>";
- ret += " <p>These expressions can also be used, for instance, to select a set";
- ret += " subtree. <acronym title='Simple Tree Transformation";
- ret += " Sheets'>STTS</acronym> (Simple Tree Transformation Sheets), a";
- ret += " language for transforming XML trees, uses this mechanism. <a href='#refsSTTS'>[STTS]</a></p>";
- ret += " <h2><a name='status'></a>Status of this document</h2>";
- ret += " <p><em>This section describes the status of this document at the";
- ret += " of this technical report can be found in the <a href='http://www.w3.org/TR/'>W3C technical reports index at";
- ret += " http://www.w3.org/TR/.</a></em></p>";
- ret += " <p>This document describes the selectors that already exist in <a href='#refsCSS1'><abbr title='CSS level 1'>CSS1</abbr></a> and <a href='#refsCSS21'><abbr title='CSS level 2'>CSS2</abbr></a>, and";
- ret += " also proposes new selectors for <abbr title='CSS level";
- ret += " 3'>CSS3</abbr> and other languages that may need them.</p>";
- ret += " <p>The CSS Working Group doesn't expect that all implementations of";
- ret += " CSS3 will have to implement all selectors. Instead, there will";
- ret += " will include all of the selectors.</p>";
- ret += " <p>This specification is a last call working draft for the the <a href='http://www.w3.org/Style/CSS/members'>CSS Working Group</a>";
- ret += " (<a href='/Style/'>Style Activity</a>). This";
- ret += " document is a revision of the <a href='http://www.w3.org/TR/2001/CR-css3-selectors-20011113/'>Candidate";
- ret += " Recommendation dated 2001 November 13</a>, and has incorporated";
- ret += " be demonstrable.</p>";
- ret += " <p>All persons are encouraged to review and implement this";
- ret += " specification and return comments to the (<a href='http://lists.w3.org/Archives/Public/www-style/'>archived</a>)";
- ret += " public mailing list <a href='http://www.w3.org/Mail/Lists.html#www-style'>www-style</a>";
- ret += " (see <a href='http://www.w3.org/Mail/Request'>instructions</a>). W3C";
- ret += " The deadline for comments is 14 January 2006.</p>";
- ret += " <p>This is still a draft document and may be updated, replaced, or";
- ret += " </p><p>This document may be available in <a href='http://www.w3.org/Style/css3-selectors-updates/translations'>translation</a>.";
- ret += " </p><div class='subtoc'>";
- ret += " <h2><a name='contents'>Table of contents</a></h2>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline2'><a href='#context'>1. Introduction</a>";
- ret += " <ul>";
- ret += " <li><a href='#dependencies'>1.1. Dependencies</a></li>";
- ret += " <li><a href='#terminology'>1.2. Terminology</a></li>";
- ret += " <li><a href='#changesFromCSS2'>1.3. Changes from CSS2</a></li>";
- ret += " </ul>";
- ret += " </li><li class='tocline2'><a href='#selectors'>2. Selectors</a>";
- ret += " </li><li class='tocline2'><a href='#casesens'>3. Case sensitivity</a>";
- ret += " </li><li class='tocline2'><a href='#selector-syntax'>4. Selector syntax</a>";
- ret += " </li><li class='tocline2'><a href='#grouping'>5. Groups of selectors</a>";
- ret += " </li><li class='tocline2'><a href='#simple-selectors'>6. Simple selectors</a>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline3'><a href='#type-selectors'>6.1. Type";
- ret += " selectors</a>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline4'><a href='#typenmsp'>6.1.1. Type";
- ret += " selectors and namespaces</a></li>";
- ret += " </ul>";
- ret += " </li><li class='tocline3'><a href='#universal-selector'>6.2.";
- ret += " Universal selector</a>";
- ret += " <ul>";
- ret += " <li><a href='#univnmsp'>6.2.1. Universal selector and";
- ret += " namespaces</a></li>";
- ret += " </ul>";
- ret += " </li><li class='tocline3'><a href='#attribute-selectors'>6.3.";
- ret += " Attribute selectors</a>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline4'><a href='#attribute-representation'>6.3.1.";
- ret += " values</a>";
- ret += " </li><li><a href='#attribute-substrings'>6.3.2. Substring";
- ret += " matching attribute selectors</a>";
- ret += " </li><li class='tocline4'><a href='#attrnmsp'>6.3.3.";
- ret += " Attribute selectors and namespaces</a>";
- ret += " </li><li class='tocline4'><a href='#def-values'>6.3.4.";
- ret += " Default attribute values in DTDs</a></li>";
- ret += " </ul>";
- ret += " </li><li class='tocline3'><a href='#class-html'>6.4. Class";
- ret += " selectors</a>";
- ret += " </li><li class='tocline3'><a href='#id-selectors'>6.5. ID";
- ret += " selectors</a>";
- ret += " </li><li class='tocline3'><a href='#pseudo-classes'>6.6.";
- ret += " Pseudo-classes</a>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline4'><a href='#dynamic-pseudos'>6.6.1.";
- ret += " Dynamic pseudo-classes</a>";
- ret += " </li><li class='tocline4'><a href='#target-pseudo'>6.6.2. The";
- ret += " :target pseudo-class</a>";
- ret += " </li><li class='tocline4'><a href='#lang-pseudo'>6.6.3. The";
- ret += " :lang() pseudo-class</a>";
- ret += " </li><li class='tocline4'><a href='#UIstates'>6.6.4. UI";
- ret += " element states pseudo-classes</a>";
- ret += " </li><li class='tocline4'><a href='#structural-pseudos'>6.6.5.";
- ret += " Structural pseudo-classes</a>";
- ret += " <ul>";
- ret += " <li><a href='#root-pseudo'>:root";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#nth-child-pseudo'>:nth-child()";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#nth-last-child-pseudo'>:nth-last-child()</a>";
- ret += " </li><li><a href='#nth-of-type-pseudo'>:nth-of-type()";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#nth-last-of-type-pseudo'>:nth-last-of-type()</a>";
- ret += " </li><li><a href='#first-child-pseudo'>:first-child";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#last-child-pseudo'>:last-child";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#first-of-type-pseudo'>:first-of-type";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#last-of-type-pseudo'>:last-of-type";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#only-child-pseudo'>:only-child";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#only-of-type-pseudo'>:only-of-type";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#empty-pseudo'>:empty";
- ret += " pseudo-class</a></li>";
- ret += " </ul>";
- ret += " </li><li class='tocline4'><a href='#negation'>6.6.7. The";
- ret += " negation pseudo-class</a></li>";
- ret += " </ul>";
- ret += " </li>";
- ret += " </ul>";
- ret += " </li><li><a href='#pseudo-elements'>7. Pseudo-elements</a>";
- ret += " <ul>";
- ret += " <li><a href='#first-line'>7.1. The ::first-line";
- ret += " pseudo-element</a>";
- ret += " </li><li><a href='#first-letter'>7.2. The ::first-letter";
- ret += " pseudo-element</a>";
- ret += " </li><li><a href='#UIfragments'>7.3. The ::selection";
- ret += " pseudo-element</a>";
- ret += " </li><li><a href='#gen-content'>7.4. The ::before and ::after";
- ret += " pseudo-elements</a></li>";
- ret += " </ul>";
- ret += " </li><li class='tocline2'><a href='#combinators'>8. Combinators</a>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline3'><a href='#descendant-combinators'>8.1.";
- ret += " Descendant combinators</a>";
- ret += " </li><li class='tocline3'><a href='#child-combinators'>8.2. Child";
- ret += " combinators</a>";
- ret += " </li><li class='tocline3'><a href='#sibling-combinators'>8.3. Sibling";
- ret += " combinators</a>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline4'><a href='#adjacent-sibling-combinators'>8.3.1.";
- ret += " Adjacent sibling combinator</a>";
- ret += " </li><li class='tocline4'><a href='#general-sibling-combinators'>8.3.2.";
- ret += " General sibling combinator</a></li>";
- ret += " </ul>";
- ret += " </li>";
- ret += " </ul>";
- ret += " </li><li class='tocline2'><a href='#specificity'>9. Calculating a selector's";
- ret += " specificity</a>";
- ret += " </li><li class='tocline2'><a href='#w3cselgrammar'>10. The grammar of";
- ret += " Selectors</a>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline3'><a href='#grammar'>10.1. Grammar</a>";
- ret += " </li><li class='tocline3'><a href='#lex'>10.2. Lexical scanner</a>";
- ret += " </li>";
- ret += " </ul>";
- ret += " </li><li class='tocline2'><a href='#downlevel'>11. Namespaces and down-level";
- ret += " clients</a>";
- ret += " </li><li class='tocline2'><a href='#profiling'>12. Profiles</a>";
- ret += " </li><li><a href='#Conformance'>13. Conformance and requirements</a>";
- ret += " </li><li><a href='#Tests'>14. Tests</a>";
- ret += " </li><li><a href='#ACKS'>15. Acknowledgements</a>";
- ret += " </li><li class='tocline2'><a href='#references'>16. References</a>";
- ret += " </li></ul>";
- ret += " </div>";
- ret += " <h2><a name='context'>1. Introduction</a></h2>";
- ret += " <h3><a name='dependencies'></a>1.1. Dependencies</h3>";
- ret += " <p>Some features of this specification are specific to CSS, or have";
- ret += " specification, these have been described in terms of CSS2.1. <a href='#refsCSS21'>[CSS21]</a></p>";
- ret += " <h3><a name='terminology'></a>1.2. Terminology</h3>";
- ret += " <p>All of the text of this specification is normative except";
- ret += " non-normative.</p>";
- ret += " <h3><a name='changesFromCSS2'></a>1.3. Changes from CSS2</h3>";
- ret += " <p><em>This section is non-normative.</em></p>";
- ret += " <p>The main differences between the selectors in CSS2 and those in";
- ret += " Selectors are:";
- ret += " </p><ul>";
- ret += " <li>the list of basic definitions (selector, group of selectors,";
- ret += " of simple selectors, and the term 'simple selector' is now used for";
- ret += " </li>";
- ret += " <li>an optional namespace component is now allowed in type element";
- ret += " selectors, the universal selector and attribute selectors";
- ret += " </li>";
- ret += " <li>a <a href='#general-sibling-combinators'>new combinator</a> has been";
- ret += " </li>";
- ret += " <li>new simple selectors including substring matching attribute";
- ret += " selectors, and new pseudo-classes";
- ret += " </li>";
- ret += " <li>new pseudo-elements, and introduction of the '::' convention";
- ret += " </li>";
- ret += " <li>the grammar has been rewritten</li>";
- ret += " <li>profiles to be added to specifications integrating Selectors";
- ret += " and defining the set of selectors which is actually supported by";
- ret += " </li>";
- ret += " <li>Selectors are now a CSS3 Module and an independent";
- ret += " </li>";
- ret += " <li>the specification now has its own test suite</li>";
- ret += " </ul>";
- ret += " <h2><a name='selectors'></a>2. Selectors</h2>";
- ret += " <p><em>This section is non-normative, as it merely summarizes the";
- ret += " following sections.</em></p>";
- ret += " <p>A Selector represents a structure. This structure can be used as a";
- ret += " HTML or XML fragment corresponding to that structure.</p>";
- ret += " <p>Selectors may range from simple element names to rich contextual";
- ret += " representations.</p>";
- ret += " <p>The following table summarizes the Selector syntax:</p>";
- ret += " <table class='selectorsReview'>";
- ret += " <thead>";
- ret += " <tr>";
- ret += " <th class='pattern'>Pattern</th>";
- ret += " <th class='meaning'>Meaning</th>";
- ret += " <th class='described'>Described in section</th>";
- ret += " <th class='origin'>First defined in CSS level</th>";
- ret += " </tr>";
- ret += " </thead><tbody>";
- ret += " <tr>";
- ret += " <td class='pattern'>*</td>";
- ret += " <td class='meaning'>any element</td>";
- ret += " <td class='described'><a href='#universal-selector'>Universal";
- ret += " selector</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E</td>";
- ret += " <td class='meaning'>an element of type E</td>";
- ret += " <td class='described'><a href='#type-selectors'>Type selector</a></td>";
- ret += " <td class='origin'>1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E[foo]</td>";
- ret += " <td class='meaning'>an E element with a 'foo' attribute</td>";
- ret += " <td class='described'><a href='#attribute-selectors'>Attribute";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E[foo='bar']</td>";
- ret += " <td class='meaning'>an E element whose 'foo' attribute value is exactly";
- ret += " </td>";
- ret += " <td class='described'><a href='#attribute-selectors'>Attribute";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E[foo~='bar']</td>";
- ret += " <td class='meaning'>an E element whose 'foo' attribute value is a list of";
- ret += " </td>";
- ret += " <td class='described'><a href='#attribute-selectors'>Attribute";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E[foo^='bar']</td>";
- ret += " <td class='meaning'>an E element whose 'foo' attribute value begins exactly";
- ret += " </td>";
- ret += " <td class='described'><a href='#attribute-selectors'>Attribute";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E[foo$='bar']</td>";
- ret += " <td class='meaning'>an E element whose 'foo' attribute value ends exactly";
- ret += " </td>";
- ret += " <td class='described'><a href='#attribute-selectors'>Attribute";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E[foo*='bar']</td>";
- ret += " <td class='meaning'>an E element whose 'foo' attribute value contains the";
- ret += " </td>";
- ret += " <td class='described'><a href='#attribute-selectors'>Attribute";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E[hreflang|='en']</td>";
- ret += " <td class='meaning'>an E element whose 'hreflang' attribute has a";
- ret += " </td>";
- ret += " <td class='described'><a href='#attribute-selectors'>Attribute";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:root</td>";
- ret += " <td class='meaning'>an E element, root of the document</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:nth-child(n)</td>";
- ret += " <td class='meaning'>an E element, the n-th child of its parent</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:nth-last-child(n)</td>";
- ret += " <td class='meaning'>an E element, the n-th child of its parent, counting";
- ret += " </td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:nth-of-type(n)</td>";
- ret += " <td class='meaning'>an E element, the n-th sibling of its type</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:nth-last-of-type(n)</td>";
- ret += " <td class='meaning'>an E element, the n-th sibling of its type, counting";
- ret += " </td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:first-child</td>";
- ret += " <td class='meaning'>an E element, first child of its parent</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:last-child</td>";
- ret += " <td class='meaning'>an E element, last child of its parent</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:first-of-type</td>";
- ret += " <td class='meaning'>an E element, first sibling of its type</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:last-of-type</td>";
- ret += " <td class='meaning'>an E element, last sibling of its type</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:only-child</td>";
- ret += " <td class='meaning'>an E element, only child of its parent</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:only-of-type</td>";
- ret += " <td class='meaning'>an E element, only sibling of its type</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:empty</td>";
- ret += " <td class='meaning'>an E element that has no children (including text";
- ret += " </td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:link<br>E:visited</td>";
- ret += " <td class='meaning'>an E element being the source anchor of a hyperlink of";
- ret += " </td>";
- ret += " <td class='described'><a href='#link'>The link";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:active<br>E:hover<br>E:focus</td>";
- ret += " <td class='meaning'>an E element during certain user actions</td>";
- ret += " <td class='described'><a href='#useraction-pseudos'>The user";
- ret += " action pseudo-classes</a></td>";
- ret += " <td class='origin'>1 and 2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:target</td>";
- ret += " <td class='meaning'>an E element being the target of the referring URI</td>";
- ret += " <td class='described'><a href='#target-pseudo'>The target";
- ret += " pseudo-class</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:lang(fr)</td>";
- ret += " <td class='meaning'>an element of type E in language 'fr' (the document";
- ret += " </td>";
- ret += " <td class='described'><a href='#lang-pseudo'>The :lang()";
- ret += " pseudo-class</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:enabled<br>E:disabled</td>";
- ret += " <td class='meaning'>a user interface element E which is enabled or";
- ret += " </td>";
- ret += " <td class='described'><a href='#UIstates'>The UI element states";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:checked<!--<br>E:indeterminate--></td>";
- ret += " <td class='meaning'>a user interface element E which is checked<!-- or in an";
- ret += " indeterminate state--> (for instance a radio-button or checkbox)";
- ret += " </td>";
- ret += " <td class='described'><a href='#UIstates'>The UI element states";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E::first-line</td>";
- ret += " <td class='meaning'>the first formatted line of an E element</td>";
- ret += " <td class='described'><a href='#first-line'>The ::first-line";
- ret += " pseudo-element</a></td>";
- ret += " <td class='origin'>1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E::first-letter</td>";
- ret += " <td class='meaning'>the first formatted letter of an E element</td>";
- ret += " <td class='described'><a href='#first-letter'>The ::first-letter";
- ret += " pseudo-element</a></td>";
- ret += " <td class='origin'>1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E::selection</td>";
- ret += " <td class='meaning'>the portion of an E element that is currently";
- ret += " </td>";
- ret += " <td class='described'><a href='#UIfragments'>The UI element";
- ret += " fragments pseudo-elements</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E::before</td>";
- ret += " <td class='meaning'>generated content before an E element</td>";
- ret += " <td class='described'><a href='#gen-content'>The ::before";
- ret += " pseudo-element</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E::after</td>";
- ret += " <td class='meaning'>generated content after an E element</td>";
- ret += " <td class='described'><a href='#gen-content'>The ::after";
- ret += " pseudo-element</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E.warning</td>";
- ret += " <td class='meaning'>an E element whose class is";
- ret += " </td>";
- ret += " <td class='described'><a href='#class-html'>Class";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E#myid</td>";
- ret += " <td class='meaning'>an E element with ID equal to 'myid'.</td>";
- ret += " <td class='described'><a href='#id-selectors'>ID";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:not(s)</td>";
- ret += " <td class='meaning'>an E element that does not match simple selector s</td>";
- ret += " <td class='described'><a href='#negation'>Negation";
- ret += " pseudo-class</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E F</td>";
- ret += " <td class='meaning'>an F element descendant of an E element</td>";
- ret += " <td class='described'><a href='#descendant-combinators'>Descendant";
- ret += " combinator</a></td>";
- ret += " <td class='origin'>1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E > F</td>";
- ret += " <td class='meaning'>an F element child of an E element</td>";
- ret += " <td class='described'><a href='#child-combinators'>Child";
- ret += " combinator</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E + F</td>";
- ret += " <td class='meaning'>an F element immediately preceded by an E element</td>";
- ret += " <td class='described'><a href='#adjacent-sibling-combinators'>Adjacent sibling combinator</a>";
- ret += " </td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E ~ F</td>";
- ret += " <td class='meaning'>an F element preceded by an E element</td>";
- ret += " <td class='described'><a href='#general-sibling-combinators'>General sibling combinator</a>";
- ret += " </td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " </tbody>";
- ret += " </table>";
- ret += " <p>The meaning of each selector is derived from the table above by";
- ret += " column.</p>";
- ret += " <h2><a name='casesens'>3. Case sensitivity</a></h2>";
- ret += " <p>The case sensitivity of document language element names, attribute";
- ret += " names, and attribute values in selectors depends on the document";
- ret += " but in XML, they are case-sensitive.</p>";
- ret += " <h2><a name='selector-syntax'>4. Selector syntax</a></h2>";
- ret += " <p>A <dfn><a name='selector'>selector</a></dfn> is a chain of one";
- ret += " or more <a href='#sequence'>sequences of simple selectors</a>";
- ret += " separated by <a href='#combinators'>combinators</a>.</p>";
- ret += " <p>A <dfn><a name='sequence'>sequence of simple selectors</a></dfn>";
- ret += " is a chain of <a href='#simple-selectors-dfn'>simple selectors</a>";
- ret += " that are not separated by a <a href='#combinators'>combinator</a>. It";
- ret += " always begins with a <a href='#type-selectors'>type selector</a> or a";
- ret += " <a href='#universal-selector'>universal selector</a>. No other type";
- ret += " selector or universal selector is allowed in the sequence.</p>";
- ret += " <p>A <dfn><a name='simple-selectors-dfn'></a><a href='#simple-selectors'>simple selector</a></dfn> is either a <a href='#type-selectors'>type selector</a>, <a href='#universal-selector'>universal selector</a>, <a href='#attribute-selectors'>attribute selector</a>, <a href='#class-html'>class selector</a>, <a href='#id-selectors'>ID selector</a>, <a href='#content-selectors'>content selector</a>, or <a href='#pseudo-classes'>pseudo-class</a>. One <a href='#pseudo-elements'>pseudo-element</a> may be appended to the last";
- ret += " sequence of simple selectors.</p>";
- ret += " <p><dfn>Combinators</dfn> are: white space, 'greater-than";
- ret += " sign' (U+003E, <code>></code>), 'plus sign' (U+002B,";
- ret += " <code>+</code>) and 'tilde' (U+007E, <code>~</code>). White";
- ret += " space may appear between a combinator and the simple selectors around";
- ret += " it. <a name='whitespace'></a>Only the characters 'space' (U+0020), 'tab'";
- ret += " never part of white space.</p>";
- ret += " <p>The elements of a document tree that are represented by a selector";
- ret += " are the <dfn><a name='subject'></a>subjects of the selector</dfn>. A";
- ret += " selector consisting of a single sequence of simple selectors";
- ret += " sequence of simple selectors and a combinator to a sequence imposes";
- ret += " simple selectors.</p>";
- ret += " <p>An empty selector, containing no sequence of simple selectors and";
- ret += " no pseudo-element, is an <a href='#Conformance'>invalid";
- ret += " selector</a>.</p>";
- ret += " <h2><a name='grouping'>5. Groups of selectors</a></h2>";
- ret += " <p>When several selectors share the same declarations, they may be";
- ret += " grouped into a comma-separated list. (A comma is U+002C.)</p>";
- ret += " <div class='example'>";
- ret += " <p>CSS examples:</p>";
- ret += " <p>In this example, we condense three rules with identical";
- ret += " declarations into one. Thus,</p>";
- ret += " <pre>h1 { font-family: sans-serif }";
- ret += " h3 { font-family: sans-serif }</pre>";
- ret += " <p>is equivalent to:</p>";
- ret += " <pre>h1, h2, h3 { font-family: sans-serif }</pre>";
- ret += " </div>";
- ret += " <p><strong>Warning</strong>: the equivalence is true in this example";
- ret += " because all the selectors are valid selectors. If just one of these";
- ret += " selectors were invalid, the entire group of selectors would be";
- ret += " heading rules would be invalidated.</p>";
- ret += " <h2><a name='simple-selectors'>6. Simple selectors</a></h2>";
- ret += " <h3><a name='type-selectors'>6.1. Type selector</a></h3>";
- ret += " <p>A <dfn>type selector</dfn> is the name of a document language";
- ret += " type in the document tree.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>The following selector represents an <code>h1</code> element in the";
- ret += " document tree:</p>";
- ret += " <pre>h1</pre>";
- ret += " </div>";
- ret += " <h4><a name='typenmsp'>6.1.1. Type selectors and namespaces</a></h4>";
- ret += " <p>Type selectors allow an optional namespace (<a href='#refsXMLNAMES'>[XMLNAMES]</a>) component. A namespace prefix";
- ret += " (U+007C, <code>|</code>).</p>";
- ret += " <p>The namespace component may be left empty to indicate that the";
- ret += " selector is only to represent elements with no declared namespace.</p>";
- ret += " <p>An asterisk may be used for the namespace prefix, indicating that";
- ret += " with no namespace).</p>";
- ret += " <p>Element type selectors that have no namespace component (no";
- ret += " element's namespace (equivalent to '<code>*|</code>') unless a default";
- ret += " namespace.</p>";
- ret += " <p>A type selector containing a namespace prefix that has not been";
- ret += " previously declared is an <a href='#Conformance'>invalid</a> selector.";
- ret += " language implementing Selectors. In CSS, such a mechanism is defined";
- ret += " in the General Syntax module.</p>";
- ret += " <p>In a namespace-aware client, element type selectors will only match";
- ret += " against the <a href='http://www.w3.org/TR/REC-xml-names/#NT-LocalPart'>local";
- ret += " part</a>";
- ret += " of the element's <a href='http://www.w3.org/TR/REC-xml-names/#ns-qualnames'>qualified";
- ret += " name</a>. See <a href='#downlevel'>below</a> for notes about matching";
- ret += " behaviors in down-level clients.</p>";
- ret += " <p>In summary:</p>";
- ret += " <dl>";
- ret += " <dt><code>ns|E</code></dt>";
- ret += " <dd>elements with name E in namespace ns</dd>";
- ret += " <dt><code>*|E</code></dt>";
- ret += " <dd>elements with name E in any namespace, including those without any";
- ret += " </dd>";
- ret += " <dt><code>|E</code></dt>";
- ret += " <dd>elements with name E without any declared namespace</dd>";
- ret += " <dt><code>E</code></dt>";
- ret += " <dd>if no default namespace has been specified, this is equivalent to *|E.";
- ret += " </dd>";
- ret += " </dl>";
- ret += " <div class='example'>";
- ret += " <p>CSS examples:</p>";
- ret += " <pre>@namespace foo url(http://www.example.com);";
- ret += " h1 { color: green }</pre>";
- ret += " <p>The first rule will match only <code>h1</code> elements in the";
- ret += " 'http://www.example.com' namespace.</p>";
- ret += " <p>The second rule will match all elements in the";
- ret += " 'http://www.example.com' namespace.</p>";
- ret += " <p>The third rule will match only <code>h1</code> elements without";
- ret += " any declared namespace.</p>";
- ret += " <p>The fourth rule will match <code>h1</code> elements in any";
- ret += " namespace (including those without any declared namespace).</p>";
- ret += " <p>The last rule is equivalent to the fourth rule because no default";
- ret += " namespace has been defined.</p>";
- ret += " </div>";
- ret += " <h3><a name='universal-selector'>6.2. Universal selector</a></h3>";
- ret += " <p>The <dfn>universal selector</dfn>, written 'asterisk'";
- ret += " (<code>*</code>), represents the qualified name of any element";
- ret += " specified, see <a href='#univnmsp'>Universal selector and";
- ret += " Namespaces</a> below.</p>";
- ret += " <p>If the universal selector is not the only component of a sequence";
- ret += " of simple selectors, the <code>*</code> may be omitted.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <ul>";
- ret += " <li><code>*[hreflang|=en]</code> and <code>[hreflang|=en]</code> are";
- ret += " </li>";
- ret += " <li><code>*.warning</code> and <code>.warning</code> are equivalent,";
- ret += " </li>";
- ret += " <li><code>*#myid</code> and <code>#myid</code> are equivalent.</li>";
- ret += " </ul>";
- ret += " </div>";
- ret += " <p class='note'><strong>Note:</strong> it is recommended that the";
- ret += " <code>*</code>, representing the universal selector, not be";
- ret += " omitted.</p>";
- ret += " <h4><a name='univnmsp'>6.2.1. Universal selector and namespaces</a></h4>";
- ret += " <p>The universal selector allows an optional namespace component. It";
- ret += " is used as follows:</p>";
- ret += " <dl>";
- ret += " <dt><code>ns|*</code></dt>";
- ret += " <dd>all elements in namespace ns</dd>";
- ret += " <dt><code>*|*</code></dt>";
- ret += " <dd>all elements</dd>";
- ret += " <dt><code>|*</code></dt>";
- ret += " <dd>all elements without any declared namespace</dd>";
- ret += " <dt><code>*</code></dt>";
- ret += " <dd>if no default namespace has been specified, this is equivalent to *|*.";
- ret += " </dd>";
- ret += " </dl>";
- ret += " <p>A universal selector containing a namespace prefix that has not";
- ret += " been previously declared is an <a href='#Conformance'>invalid</a>";
- ret += " to the language implementing Selectors. In CSS, such a mechanism is";
- ret += " defined in the General Syntax module.</p>";
- ret += " <h3><a name='attribute-selectors'>6.3. Attribute selectors</a></h3>";
- ret += " <p>Selectors allow the representation of an element's attributes. When";
- ret += " attribute selectors must be considered to match an element if that";
- ret += " attribute selector.</p>";
- ret += " <h4><a name='attribute-representation'>6.3.1. Attribute presence and values";
- ret += " selectors</a></h4>";
- ret += " <p>CSS2 introduced four attribute selectors:</p>";
- ret += " <dl>";
- ret += " <dt><code>[att]</code>";
- ret += " </dt><dd>Represents an element with the <code>att</code> attribute, whatever the";
- ret += " </dd>";
- ret += " <dt><code>[att=val]</code></dt>";
- ret += " <dd>Represents an element with the <code>att</code> attribute whose value is";
- ret += " </dd>";
- ret += " <dt><code>[att~=val]</code></dt>";
- ret += " <dd>Represents an element with the <code>att</code> attribute whose value is";
- ret += " a <a href='#whitespace'>whitespace</a>-separated list of words, one";
- ret += " represent anything (since the words are <em>separated</em> by";
- ret += " </dd>";
- ret += " <dt><code>[att|=val]</code>";
- ret += " </dt><dd>Represents an element with the <code>att</code> attribute, its value";
- ret += " matches (e.g., the <code>hreflang</code> attribute on the";
- ret += " <code>link</code> element in HTML) as described in RFC 3066 (<a href='#refsRFC3066'>[RFC3066]</a>). For <code>lang</code> (or";
- ret += " <code>xml:lang</code>) language subcode matching, please see <a href='#lang-pseudo'>the <code>:lang</code> pseudo-class</a>.";
- ret += " </dd>";
- ret += " </dl>";
- ret += " <p>Attribute values must be identifiers or strings. The";
- ret += " case-sensitivity of attribute names and values in selectors depends on";
- ret += " the document language.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following attribute selector represents an <code>h1</code>";
- ret += " element that carries the <code>title</code> attribute, whatever its";
- ret += " value:</p>";
- ret += " <pre>h1[title]</pre>";
- ret += " <p>In the following example, the selector represents a";
- ret += " <code>span</code> element whose <code>class</code> attribute has";
- ret += " exactly the value 'example':</p>";
- ret += " <pre>span[class='example']</pre>";
- ret += " <p>Multiple attribute selectors can be used to represent several";
- ret += " attribute. Here, the selector represents a <code>span</code> element";
- ret += " whose <code>hello</code> attribute has exactly the value 'Cleveland'";
- ret += " and whose <code>goodbye</code> attribute has exactly the value";
- ret += " 'Columbus':</p>";
- ret += " <pre>span[hello='Cleveland'][goodbye='Columbus']</pre>";
- ret += " <p>The following selectors illustrate the differences between '='";
- ret += " 'copyright copyleft copyeditor' on a <code>rel</code> attribute. The";
- ret += " second selector will only represent an <code>a</code> element with";
- ret += " an <code>href</code> attribute having the exact value";
- ret += " 'http://www.w3.org/'.</p>";
- ret += " <pre>a[rel~='copyright']";
- ret += " a[href='http://www.w3.org/']</pre>";
- ret += " <p>The following selector represents a <code>link</code> element";
- ret += " whose <code>hreflang</code> attribute is exactly 'fr'.</p>";
- ret += " <pre>link[hreflang=fr]</pre>";
- ret += " <p>The following selector represents a <code>link</code> element for";
- ret += " which the values of the <code>hreflang</code> attribute begins with";
- ret += " 'en', including 'en', 'en-US', and 'en-cockney':</p>";
- ret += " <pre>link[hreflang|='en']</pre>";
- ret += " <p>Similarly, the following selectors represents a";
- ret += " <code>DIALOGUE</code> element whenever it has one of two different";
- ret += " values for an attribute <code>character</code>:</p>";
- ret += " <pre>DIALOGUE[character=romeo]";
- ret += " DIALOGUE[character=juliet]</pre>";
- ret += " </div>";
- ret += " <h4><a name='attribute-substrings'></a>6.3.2. Substring matching attribute";
- ret += " selectors</h4>";
- ret += " <p>Three additional attribute selectors are provided for matching";
- ret += " substrings in the value of an attribute:</p>";
- ret += " <dl>";
- ret += " <dt><code>[att^=val]</code></dt>";
- ret += " <dd>Represents an element with the <code>att</code> attribute whose value";
- ret += " </dd>";
- ret += " <dt><code>[att$=val]</code>";
- ret += " </dt><dd>Represents an element with the <code>att</code> attribute whose value";
- ret += " </dd>";
- ret += " <dt><code>[att*=val]</code>";
- ret += " </dt><dd>Represents an element with the <code>att</code> attribute whose value";
- ret += " </dd>";
- ret += " </dl>";
- ret += " <p>Attribute values must be identifiers or strings. The";
- ret += " case-sensitivity of attribute names in selectors depends on the";
- ret += " document language.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following selector represents an HTML <code>object</code>,";
- ret += " image:</p>";
- ret += " <pre>object[type^='image/']</pre>";
- ret += " <p>The following selector represents an HTML anchor <code>a</code> with an";
- ret += " <code>href</code> attribute whose value ends with '.html'.</p>";
- ret += " <pre>a[href$='.html']</pre>";
- ret += " <p>The following selector represents an HTML paragraph with a";
- ret += " <code>title</code>";
- ret += " attribute whose value contains the substring 'hello'</p>";
- ret += " <pre>p[title*='hello']</pre>";
- ret += " </div>";
- ret += " <h4><a name='attrnmsp'>6.3.3. Attribute selectors and namespaces</a></h4>";
- ret += " <p>Attribute selectors allow an optional namespace component to the";
- ret += " separator 'vertical bar' (<code>|</code>). In keeping with";
- ret += " apply to attributes, therefore attribute selectors without a namespace";
- ret += " (equivalent to '<code>|attr</code>'). An asterisk may be used for the";
- ret += " </p><p>An attribute selector with an attribute name containing a namespace";
- ret += " prefix that has not been previously declared is an <a href='#Conformance'>invalid</a> selector. The mechanism for";
- ret += " a namespace prefix is left up to the language implementing Selectors.";
- ret += " </p><div class='example'>";
- ret += " <p>CSS examples:</p>";
- ret += " <pre>@namespace foo 'http://www.example.com';";
- ret += " [att] { color: green }</pre>";
- ret += " <p>The first rule will match only elements with the attribute";
- ret += " <code>att</code> in the 'http://www.example.com' namespace with the";
- ret += " value 'val'.</p>";
- ret += " <p>The second rule will match only elements with the attribute";
- ret += " <code>att</code> regardless of the namespace of the attribute";
- ret += " (including no declared namespace).</p>";
- ret += " <p>The last two rules are equivalent and will match only elements";
- ret += " with the attribute <code>att</code> where the attribute is not";
- ret += " declared to be in a namespace.</p>";
- ret += " </div>";
- ret += " <h4><a name='def-values'>6.3.4. Default attribute values in DTDs</a></h4>";
- ret += " <p>Attribute selectors represent explicitly set attribute values in";
- ret += " selectors. Selectors should be designed so that they work even if the";
- ret += " default values are not included in the document tree.</p>";
- ret += " <p>More precisely, a UA is <em>not</em> required to read an 'external";
- ret += " subset' of the DTD but <em>is</em> required to look for default";
- ret += " attribute values in the document's 'internal subset.' (See <a href='#refsXML10'>[XML10]</a> for definitions of these subsets.)</p>";
- ret += " <p>A UA that recognizes an XML namespace <a href='#refsXMLNAMES'>[XMLNAMES]</a> is not required to use its";
- ret += " required to use its built-in knowledge of the XHTML DTD.)</p>";
- ret += " <p class='note'><strong>Note:</strong> Typically, implementations";
- ret += " choose to ignore external subsets.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>Consider an element EXAMPLE with an attribute 'notation' that has a";
- ret += " default value of 'decimal'. The DTD fragment might be</p>";
- ret += " <pre class='dtd-example'><!ATTLIST EXAMPLE notation (decimal,octal) 'decimal'></pre>";
- ret += " <p>If the style sheet contains the rules</p>";
- ret += " <pre>EXAMPLE[notation=decimal] { /*... default property settings ...*/ }";
- ret += " EXAMPLE[notation=octal] { /*... other settings...*/ }</pre>";
- ret += " <p>the first rule will not match elements whose 'notation' attribute";
- ret += " attribute selector for the default value must be dropped:</p>";
- ret += " <pre>EXAMPLE { /*... default property settings ...*/ }";
- ret += " EXAMPLE[notation=octal] { /*... other settings...*/ }</pre>";
- ret += " <p>Here, because the selector <code>EXAMPLE[notation=octal]</code> is";
- ret += " cases' style rules.</p>";
- ret += " </div>";
- ret += " <h3><a name='class-html'>6.4. Class selectors</a></h3>";
- ret += " <p>Working with HTML, authors may use the period (U+002E,";
- ret += " <code>.</code>) notation as an alternative to the <code>~=</code>";
- ret += " notation when representing the <code>class</code> attribute. Thus, for";
- ret += " HTML, <code>div.value</code> and <code>div[class~=value]</code> have";
- ret += " 'period' (<code>.</code>).</p>";
- ret += " <p>UAs may apply selectors using the period (.) notation in XML";
- ret += " 1.0 <a href='#refsSVG'>[SVG]</a> describes the <a href='http://www.w3.org/TR/2001/PR-SVG-20010719/styling.html#ClassAttribute'>SVG";
- ret += " 'class' attribute</a> and how a UA should interpret it, and";
- ret += " similarly MathML 1.01 <a href='#refsMATH'>[MATH]</a> describes the <a href='http://www.w3.org/1999/07/REC-MathML-19990707/chapter2.html#sec2.3.4'>MathML";
- ret += " 'class' attribute</a>.)</p>";
- ret += " <div class='example'>";
- ret += " <p>CSS examples:</p>";
- ret += " <p>We can assign style information to all elements with";
- ret += " <code>class~='pastoral'</code> as follows:</p>";
- ret += " <pre>*.pastoral { color: green } /* all elements with class~=pastoral */</pre>";
- ret += " <p>or just</p>";
- ret += " <pre>.pastoral { color: green } /* all elements with class~=pastoral */</pre>";
- ret += " <p>The following assigns style only to H1 elements with";
- ret += " <code>class~='pastoral'</code>:</p>";
- ret += " <pre>H1.pastoral { color: green } /* H1 elements with class~=pastoral */</pre>";
- ret += " <p>Given these rules, the first H1 instance below would not have";
- ret += " green text, while the second would:</p>";
- ret += " <pre><H1>Not green</H1>";
- ret += " <H1 class='pastoral'>Very green</H1></pre>";
- ret += " </div>";
- ret += " <p>To represent a subset of 'class' values, each value must be preceded";
- ret += " by a '.', in any order.</p>";
- ret += " <div class='example'>";
- ret += " <p>CSS example:</p>";
- ret += " <p>The following rule matches any P element whose 'class' attribute";
- ret += " has been assigned a list of <a href='#whitespace'>whitespace</a>-separated values that includes";
- ret += " 'pastoral' and 'marine':</p>";
- ret += " <pre>p.pastoral.marine { color: green }</pre>";
- ret += " <p>This rule matches when <code>class='pastoral blue aqua";
- ret += " marine'</code> but does not match for <code>class='pastoral";
- ret += " blue'</code>.</p>";
- ret += " </div>";
- ret += " <p class='note'><strong>Note:</strong> Because CSS gives considerable";
- ret += " not.</p>";
- ret += " <p class='note'><strong>Note:</strong> If an element has multiple";
- ret += " this specification.</p>";
- ret += " <h3><a name='id-selectors'>6.5. ID selectors</a></h3>";
- ret += " <p>Document languages may contain attributes that are declared to be";
- ret += " applies.</p>";
- ret += " <p>An ID-typed attribute of a document language allows authors to";
- ret += " ID selectors represent an element instance based on its identifier. An";
- ret += " <code>#</code>) immediately followed by the ID value, which must be an";
- ret += " identifier.</p>";
- ret += " <p>Selectors does not specify how a UA knows the ID-typed attribute of";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following ID selector represents an <code>h1</code> element";
- ret += " whose ID-typed attribute has the value 'chapter1':</p>";
- ret += " <pre>h1#chapter1</pre>";
- ret += " <p>The following ID selector represents any element whose ID-typed";
- ret += " attribute has the value 'chapter1':</p>";
- ret += " <pre>#chapter1</pre>";
- ret += " <p>The following selector represents any element whose ID-typed";
- ret += " attribute has the value 'z98y'.</p>";
- ret += " <pre>*#z98y</pre>";
- ret += " </div>";
- ret += " <p class='note'><strong>Note.</strong> In XML 1.0 <a href='#refsXML10'>[XML10]</a>, the information about which attribute";
- ret += " should use normal attribute selectors instead:";
- ret += " <code>[name=p371]</code> instead of <code>#p371</code>. Elements in";
- ret += " XML 1.0 documents without a DTD do not have IDs at all.</p>";
- ret += " <p>If an element has multiple ID attributes, all of them must be";
- ret += " DOM3 Core, XML DTDs, and namespace-specific knowledge.</p>";
- ret += " <h3><a name='pseudo-classes'>6.6. Pseudo-classes</a></h3>";
- ret += " <p>The pseudo-class concept is introduced to permit selection based on";
- ret += " expressed using the other simple selectors.</p>";
- ret += " <p>A pseudo-class always consists of a 'colon'";
- ret += " (<code>:</code>) followed by the name of the pseudo-class and";
- ret += " optionally by a value between parentheses.</p>";
- ret += " <p>Pseudo-classes are allowed in all sequences of simple selectors";
- ret += " sequences of simple selectors, after the leading type selector or";
- ret += " document.</p>";
- ret += " <h4><a name='dynamic-pseudos'>6.6.1. Dynamic pseudo-classes</a></h4>";
- ret += " <p>Dynamic pseudo-classes classify elements on characteristics other";
- ret += " that cannot be deduced from the document tree.</p>";
- ret += " <p>Dynamic pseudo-classes do not appear in the document source or";
- ret += " document tree.</p>";
- ret += " <h5>The <a name='link'>link pseudo-classes: :link and :visited</a></h5>";
- ret += " <p>User agents commonly display unvisited links differently from";
- ret += " previously visited ones. Selectors";
- ret += " provides the pseudo-classes <code>:link</code> and";
- ret += " <code>:visited</code> to distinguish them:</p>";
- ret += " <ul>";
- ret += " <li>The <code>:link</code> pseudo-class applies to links that have";
- ret += " </li>";
- ret += " <li>The <code>:visited</code> pseudo-class applies once the link has";
- ret += " </li>";
- ret += " </ul>";
- ret += " <p>After some amount of time, user agents may choose to return a";
- ret += " visited link to the (unvisited) ':link' state.</p>";
- ret += " <p>The two states are mutually exclusive.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>The following selector represents links carrying class";
- ret += " <code>external</code> and already visited:</p>";
- ret += " <pre>a.external:visited</pre>";
- ret += " </div>";
- ret += " <p class='note'><strong>Note:</strong> It is possible for style sheet";
- ret += " </p><p>UAs may therefore treat all links as unvisited links, or implement";
- ret += " and unvisited links differently.</p>";
- ret += " <h5>The <a name='useraction-pseudos'>user action pseudo-classes";
- ret += " :hover, :active, and :focus</a></h5>";
- ret += " <p>Interactive user agents sometimes change the rendering in response";
- ret += " to user actions. Selectors provides";
- ret += " acting on.</p>";
- ret += " <ul>";
- ret += " <li>The <code>:hover</code> pseudo-class applies while the user";
- ret += " element. User agents not that do not support <a href='http://www.w3.org/TR/REC-CSS2/media.html#interactive-media-group'>interactive";
- ret += " media</a> do not have to support this pseudo-class. Some conforming";
- ret += " user agents that support <a href='http://www.w3.org/TR/REC-CSS2/media.html#interactive-media-group'>interactive";
- ret += " media</a> may not be able to support this pseudo-class (e.g., a pen";
- ret += " </li>";
- ret += " <li>The <code>:active</code> pseudo-class applies while an element";
- ret += " </li>";
- ret += " <li>The <code>:focus</code> pseudo-class applies while an element";
- ret += " </li>";
- ret += " </ul>";
- ret += " <p>There may be document language or implementation specific limits on";
- ret += " which elements can become <code>:active</code> or acquire";
- ret += " <code>:focus</code>.</p>";
- ret += " <p>These pseudo-classes are not mutually exclusive. An element may";
- ret += " match several pseudo-classes at the same time.</p>";
- ret += " <p>Selectors doesn't define if the parent of an element that is";
- ret += " ':active' or ':hover' is also in that state.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <pre>a:link /* unvisited links */";
- ret += " a:active /* active links */</pre>";
- ret += " <p>An example of combining dynamic pseudo-classes:</p>";
- ret += " <pre>a:focus";
- ret += " a:focus:hover</pre>";
- ret += " <p>The last selector matches <code>a</code> elements that are in";
- ret += " the pseudo-class :focus and in the pseudo-class :hover.</p>";
- ret += " </div>";
- ret += " <p class='note'><strong>Note:</strong> An element can be both ':visited'";
- ret += " and ':active' (or ':link' and ':active').</p>";
- ret += " <h4><a name='target-pseudo'>6.6.2. The target pseudo-class :target</a></h4>";
- ret += " <p>Some URIs refer to a location within a resource. This kind of URI";
- ret += " identifier (called the fragment identifier).</p>";
- ret += " <p>URIs with fragment identifiers link to a certain element within the";
- ret += " pointing to an anchor named <code>section_2</code> in an HTML";
- ret += " document:</p>";
- ret += " <pre>http://example.com/html/top.html#section_2</pre>";
- ret += " <p>A target element can be represented by the <code>:target</code>";
- ret += " the document has no target element.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <pre>p.note:target</pre>";
- ret += " <p>This selector represents a <code>p</code> element of class";
- ret += " <code>note</code> that is the target element of the referring";
- ret += " URI.</p>";
- ret += " </div>";
- ret += " <div class='example'>";
- ret += " <p>CSS example:</p>";
- ret += " <p>Here, the <code>:target</code> pseudo-class is used to make the";
- ret += " target element red and place an image before it, if there is one:</p>";
- ret += " <pre>*:target { color : red }";
- ret += " *:target::before { content : url(target.png) }</pre>";
- ret += " </div>";
- ret += " <h4><a name='lang-pseudo'>6.6.3. The language pseudo-class :lang</a></h4>";
- ret += " <p>If the document language specifies how the human language of an";
- ret += " element is determined, it is possible to write selectors that";
- ret += " represent an element based on its language. For example, in HTML <a href='#refsHTML4'>[HTML4]</a>, the language is determined by a";
- ret += " combination of the <code>lang</code> attribute, the <code>meta</code>";
- ret += " headers). XML uses an attribute called <code>xml:lang</code>, and";
- ret += " the language.</p>";
- ret += " <p>The pseudo-class <code>:lang(C)</code> represents an element that";
- ret += " <code>:lang()</code> selector is based solely on the identifier C";
- ret += " element's language value, in the same way as if performed by the <a href='#attribute-representation'>'|='</a> operator in attribute";
- ret += " selectors. The identifier C does not have to be a valid language";
- ret += " name.</p>";
- ret += " <p>C must not be empty. (If it is, the selector is invalid.)</p>";
- ret += " <p class='note'><strong>Note:</strong> It is recommended that";
- ret += " documents and protocols indicate language using codes from RFC 3066 <a href='#refsRFC3066'>[RFC3066]</a> or its successor, and by means of";
- ret += " 'xml:lang' attributes in the case of XML-based documents <a href='#refsXML10'>[XML10]</a>. See <a href='http://www.w3.org/International/questions/qa-lang-2or3.html'>";
- ret += " 'FAQ: Two-letter or three-letter language codes.'</a></p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The two following selectors represent an HTML document that is in";
- ret += " Belgian, French, or German. The two next selectors represent";
- ret += " <code>q</code> quotations in an arbitrary element in Belgian, French,";
- ret += " or German.</p>";
- ret += " <pre>html:lang(fr-be)";
- ret += " :lang(de) > q</pre>";
- ret += " </div>";
- ret += " <h4><a name='UIstates'>6.6.4. The UI element states pseudo-classes</a></h4>";
- ret += " <h5><a name='enableddisabled'>The :enabled and :disabled pseudo-classes</a></h5>";
- ret += " <p>The <code>:enabled</code> pseudo-class allows authors to customize";
- ret += " an enabled <code>input</code> element without also specifying what it";
- ret += " would look like when it was disabled.</p>";
- ret += " <p>Similar to <code>:enabled</code>, <code>:disabled</code> allows the";
- ret += " element should look.</p>";
- ret += " <p>Most elements will be neither enabled nor disabled. An element is";
- ret += " presently activate it or transfer focus to it.</p>";
- ret += " <h5><a name='checked'>The :checked pseudo-class</a></h5>";
- ret += " <p>Radio and checkbox elements can be toggled by the user. Some menu";
- ret += " toggled 'on' the <code>:checked</code> pseudo-class applies. The";
- ret += " <code>:checked</code> pseudo-class initially applies to such elements";
- ret += " that have the HTML4 <code>selected</code> and <code>checked</code>";
- ret += " attributes as described in <a href='http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.2.1'>Section";
- ret += " 17.2.1 of HTML4</a>, but of course the user can toggle 'off' such";
- ret += " elements in which case the <code>:checked</code> pseudo-class would no";
- ret += " longer apply. While the <code>:checked</code> pseudo-class is dynamic";
- ret += " on the presence of the semantic HTML4 <code>selected</code> and";
- ret += " <code>checked</code> attributes, it applies to all media.";
- ret += " </p><h5><a name='indeterminate'>The :indeterminate pseudo-class</a></h5>";
- ret += " <div class='note'>";
- ret += " <p>Radio and checkbox elements can be toggled by the user, but are";
- ret += " This can be due to an element attribute, or DOM manipulation.</p>";
- ret += " <p>A future version of this specification may introduce an";
- ret += " <code>:indeterminate</code> pseudo-class that applies to such elements.";
- ret += " <!--While the <code>:indeterminate</code> pseudo-class is dynamic in";
- ret += " the presence of an element attribute, it applies to all media.</p>";
- ret += " <p>Components of a radio-group initialized with no pre-selected choice";
- ret += " are an example of :indeterminate state.--></p>";
- ret += " </div>";
- ret += " <h4><a name='structural-pseudos'>6.6.5. Structural pseudo-classes</a></h4>";
- ret += " <p>Selectors introduces the concept of <dfn>structural";
- ret += " pseudo-classes</dfn> to permit selection based on extra information that";
- ret += " the document tree but cannot be represented by other simple selectors or";
- ret += " </p><p>Note that standalone pieces of PCDATA (text nodes in the DOM) are";
- ret += " </p><h5><a name='root-pseudo'>:root pseudo-class</a></h5>";
- ret += " <p>The <code>:root</code> pseudo-class represents an element that is";
- ret += " <code>HTML</code> element.";
- ret += " </p><h5><a name='nth-child-pseudo'>:nth-child() pseudo-class</a></h5>";
- ret += " <p>The";
- ret += " <code>:nth-child(<var>a</var><code>n</code>+<var>b</var>)</code>";
- ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings";
- ret += " <strong>before</strong> it in the document tree, for a given positive";
- ret += " integer or zero value of <code>n</code>, and has a parent element. In";
- ret += " other words, this matches the <var>b</var>th child of an element after";
- ret += " all the children have been split into groups of <var>a</var> elements";
- ret += " each. For example, this allows the selectors to address every other";
- ret += " of paragraph text in a cycle of four. The <var>a</var> and";
- ret += " <var>b</var> values must be zero, negative integers or positive";
- ret += " </p><p>In addition to this, <code>:nth-child()</code> can take";
- ret += " '<code>odd</code>' and '<code>even</code>' as arguments instead.";
- ret += " '<code>odd</code>' has the same signification as <code>2n+1</code>,";
- ret += " and '<code>even</code>' has the same signification as <code>2n</code>.";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <pre>tr:nth-child(2n+1) /* represents every odd row of an HTML table */";
- ret += " p:nth-child(4n+4) { color: purple; }</pre>";
- ret += " </div>";
- ret += " <p>When <var>a</var>=0, no repeating is used, so for example";
- ret += " <code>:nth-child(0n+5)</code> matches only the fifth child. When";
- ret += " <var>a</var>=0, the <var>a</var><code>n</code> part need not be";
- ret += " <code>:nth-child(<var>b</var>)</code> and the last example simplifies";
- ret += " to <code>:nth-child(5)</code>.";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <pre>foo:nth-child(0n+1) /* represents an element foo, first child of its parent element */";
- ret += " foo:nth-child(1) /* same */</pre>";
- ret += " </div>";
- ret += " <p>When <var>a</var>=1, the number may be omitted from the rule.";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following selectors are therefore equivalent:</p>";
- ret += " <pre>bar:nth-child(1n+0) /* represents all bar elements, specificity (0,1,1) */";
- ret += " bar /* same but lower specificity (0,0,1) */</pre>";
- ret += " </div>";
- ret += " <p>If <var>b</var>=0, then every <var>a</var>th element is picked. In";
- ret += " such a case, the <var>b</var> part may be omitted.";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <pre>tr:nth-child(2n+0) /* represents every even row of an HTML table */";
- ret += " tr:nth-child(2n) /* same */</pre>";
- ret += " </div>";
- ret += " <p>If both <var>a</var> and <var>b</var> are equal to zero, the";
- ret += " pseudo-class represents no element in the document tree.</p>";
- ret += " <p>The value <var>a</var> can be negative, but only the positive";
- ret += " values of <var>a</var><code>n</code>+<var>b</var>, for";
- ret += " <code>n</code>≥0, may represent an element in the document";
- ret += " tree.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <pre>html|tr:nth-child(-n+6) /* represents the 6 first rows of XHTML tables */</pre>";
- ret += " </div>";
- ret += " <p>When the value <var>b</var> is negative, the '+' character in the";
- ret += " character indicating the negative value of <var>b</var>).</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <pre>:nth-child(10n-1) /* represents the 9th, 19th, 29th, etc, element */";
- ret += " :nth-child(10n+-1) /* Syntactically invalid, and would be ignored */</pre>";
- ret += " </div>";
- ret += " <h5><a name='nth-last-child-pseudo'>:nth-last-child() pseudo-class</a></h5>";
- ret += " <p>The <code>:nth-last-child(<var>a</var>n+<var>b</var>)</code>";
- ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings";
- ret += " <strong>after</strong> it in the document tree, for a given positive";
- ret += " integer or zero value of <code>n</code>, and has a parent element. See";
- ret += " <code>:nth-child()</code> pseudo-class for the syntax of its argument.";
- ret += " It also accepts the '<code>even</code>' and '<code>odd</code>' values";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <pre>tr:nth-last-child(-n+2) /* represents the two last rows of an HTML table */";
- ret += " counting from the last one */</pre>";
- ret += " </div>";
- ret += " <h5><a name='nth-of-type-pseudo'>:nth-of-type() pseudo-class</a></h5>";
- ret += " <p>The <code>:nth-of-type(<var>a</var>n+<var>b</var>)</code>";
- ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings with the same";
- ret += " element name <strong>before</strong> it in the document tree, for a";
- ret += " given zero or positive integer value of <code>n</code>, and has a";
- ret += " parent element. In other words, this matches the <var>b</var>th child";
- ret += " groups of a elements each. See <code>:nth-child()</code> pseudo-class";
- ret += " '<code>even</code>' and '<code>odd</code>' values.";
- ret += " </p><div class='example'>";
- ret += " <p>CSS example:</p>";
- ret += " <p>This allows an author to alternate the position of floated images:</p>";
- ret += " <pre>img:nth-of-type(2n+1) { float: right; }";
- ret += " img:nth-of-type(2n) { float: left; }</pre>";
- ret += " </div>";
- ret += " <h5><a name='nth-last-of-type-pseudo'>:nth-last-of-type() pseudo-class</a></h5>";
- ret += " <p>The <code>:nth-last-of-type(<var>a</var>n+<var>b</var>)</code>";
- ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings with the same";
- ret += " element name <strong>after</strong> it in the document tree, for a";
- ret += " given zero or positive integer value of <code>n</code>, and has a";
- ret += " parent element. See <code>:nth-child()</code> pseudo-class for the";
- ret += " syntax of its argument. It also accepts the '<code>even</code>' and '<code>odd</code>'";
- ret += " </p><div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>To represent all <code>h2</code> children of an XHTML";
- ret += " <code>body</code> except the first and last, one could use the";
- ret += " following selector:</p>";
- ret += " <pre>body > h2:nth-of-type(n+2):nth-last-of-type(n+2)</pre>";
- ret += " <p>In this case, one could also use <code>:not()</code>, although the";
- ret += " selector ends up being just as long:</p>";
- ret += " <pre>body > h2:not(:first-of-type):not(:last-of-type)</pre>";
- ret += " </div>";
- ret += " <h5><a name='first-child-pseudo'>:first-child pseudo-class</a></h5>";
- ret += " <p>Same as <code>:nth-child(1)</code>. The <code>:first-child</code>";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following selector represents a <code>p</code> element that is";
- ret += " the first child of a <code>div</code> element:</p>";
- ret += " <pre>div > p:first-child</pre>";
- ret += " <p>This selector can represent the <code>p</code> inside the";
- ret += " <code>div</code> of the following fragment:</p>";
- ret += " <pre><p> The last P before the note.</p>";
- ret += " </div></pre>";
- ret += " but cannot represent the second <code>p</code> in the following";
- ret += " <pre><p> The last P before the note.</p>";
- ret += " </div></pre>";
- ret += " <p>The following two selectors are usually equivalent:</p>";
- ret += " <pre>* > a:first-child /* a is first child of any element */";
- ret += " a:first-child /* Same (assuming a is not the root element) */</pre>";
- ret += " </div>";
- ret += " <h5><a name='last-child-pseudo'>:last-child pseudo-class</a></h5>";
- ret += " <p>Same as <code>:nth-last-child(1)</code>. The <code>:last-child</code>";
- ret += " </p><div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>The following selector represents a list item <code>li</code> that";
- ret += " is the last child of an ordered list <code>ol</code>.";
- ret += " </p><pre>ol > li:last-child</pre>";
- ret += " </div>";
- ret += " <h5><a name='first-of-type-pseudo'>:first-of-type pseudo-class</a></h5>";
- ret += " <p>Same as <code>:nth-of-type(1)</code>. The <code>:first-of-type</code>";
- ret += " </p><div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>The following selector represents a definition title";
- ret += " <code>dt</code> inside a definition list <code>dl</code>, this";
- ret += " <code>dt</code> being the first of its type in the list of children of";
- ret += " its parent element.</p>";
- ret += " <pre>dl dt:first-of-type</pre>";
- ret += " <p>It is a valid description for the first two <code>dt</code>";
- ret += " elements in the following example but not for the third one:</p>";
- ret += " <pre><dl>";
- ret += " </dl></pre>";
- ret += " </div>";
- ret += " <h5><a name='last-of-type-pseudo'>:last-of-type pseudo-class</a></h5>";
- ret += " <p>Same as <code>:nth-last-of-type(1)</code>. The";
- ret += " <code>:last-of-type</code> pseudo-class represents an element that is";
- ret += " element.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>The following selector represents the last data cell";
- ret += " <code>td</code> of a table row.</p>";
- ret += " <pre>tr > td:last-of-type</pre>";
- ret += " </div>";
- ret += " <h5><a name='only-child-pseudo'>:only-child pseudo-class</a></h5>";
- ret += " <p>Represents an element that has a parent element and whose parent";
- ret += " <code>:first-child:last-child</code> or";
- ret += " <code>:nth-child(1):nth-last-child(1)</code>, but with a lower";
- ret += " specificity.</p>";
- ret += " <h5><a name='only-of-type-pseudo'>:only-of-type pseudo-class</a></h5>";
- ret += " <p>Represents an element that has a parent element and whose parent";
- ret += " as <code>:first-of-type:last-of-type</code> or";
- ret += " <code>:nth-of-type(1):nth-last-of-type(1)</code>, but with a lower";
- ret += " specificity.</p>";
- ret += " <h5><a name='empty-pseudo'></a>:empty pseudo-class</h5>";
- ret += " <p>The <code>:empty</code> pseudo-class represents an element that has";
- ret += " empty or not.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p><code>p:empty</code> is a valid representation of the following fragment:";
- ret += " </p>";
- ret += " <pre><p></p></pre>";
- ret += " <p><code>foo:empty</code> is not a valid representation for the";
- ret += " following fragments:</p>";
- ret += " <pre><foo>bar</foo></pre>";
- ret += " <pre><foo><bar>bla</bar></foo></pre>";
- ret += " <pre><foo>this is not <bar>:empty</bar></foo></pre>";
- ret += " </div>";
- ret += " <h4><a name='content-selectors'>6.6.6. Blank</a></h4>";
- ret += " <!-- It's the Return of Appendix H!!! Run away! -->";
- ret += " <p>This section intentionally left blank.</p>";
- ret += " <!-- (used to be :contains()) -->";
- ret += " <h4><a name='negation'></a>6.6.7. The negation pseudo-class</h4>";
- ret += " <p>The negation pseudo-class, <code>:not(<var>X</var>)</code>, is a";
- ret += " functional notation taking a <a href='#simple-selectors-dfn'>simple";
- ret += " selector</a> (excluding the negation pseudo-class itself and";
- ret += " <!-- pseudo-elements are not simple selectors, so the above paragraph";
- ret += " may be a bit confusing -->";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following CSS selector matches all <code>button</code>";
- ret += " elements in an HTML document that are not disabled.</p>";
- ret += " <pre>button:not([DISABLED])</pre>";
- ret += " <p>The following selector represents all but <code>FOO</code>";
- ret += " elements.</p>";
- ret += " <pre>*:not(FOO)</pre>";
- ret += " <p>The following group of selectors represents all HTML elements";
- ret += " except links.</p>";
- ret += " <pre>html|*:not(:link):not(:visited)</pre>";
- ret += " </div>";
- ret += " <p>Default namespace declarations do not affect the argument of the";
- ret += " type selector.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>Assuming that the default namespace is bound to";
- ret += " elements that are not in that namespace:</p>";
- ret += " <pre>*|*:not(*)</pre>";
- ret += " <p>The following CSS selector matches any element being hovered,";
- ret += " rule when they <em>are</em> being hovered.</p>";
- ret += " <pre>*|*:not(:hover)</pre>";
- ret += " </div>";
- ret += " <p class='note'><strong>Note</strong>: the :not() pseudo allows";
- ret += " useless selectors to be written. For instance <code>:not(*|*)</code>,";
- ret += " which represents no element at all, or <code>foo:not(bar)</code>,";
- ret += " which is equivalent to <code>foo</code> but with a higher";
- ret += " specificity.</p>";
- ret += " <h3><a name='pseudo-elements'>7. Pseudo-elements</a></h3>";
- ret += " <p>Pseudo-elements create abstractions about the document tree beyond";
- ret += " source document (e.g., the <code>::before</code> and";
- ret += " <code>::after</code> pseudo-elements give access to generated";
- ret += " content).</p>";
- ret += " <p>A pseudo-element is made of two colons (<code>::</code>) followed";
- ret += " by the name of the pseudo-element.</p>";
- ret += " <p>This <code>::</code> notation is introduced by the current document";
- ret += " <code>:first-line</code>, <code>:first-letter</code>,";
- ret += " <code>:before</code> and <code>:after</code>). This compatibility is";
- ret += " not allowed for the new pseudo-elements introduced in CSS level 3.</p>";
- ret += " <p>Only one pseudo-element may appear per selector, and if present it";
- ret += " must appear after the sequence of simple selectors that represents the";
- ret += " <a href='#subject'>subjects</a> of the selector. <span class='note'>A";
- ret += " pesudo-elements per selector.</span></p>";
- ret += " <h4><a name='first-line'>7.1. The ::first-line pseudo-element</a></h4>";
- ret += " <p>The <code>::first-line</code> pseudo-element describes the contents";
- ret += " </p><div class='example'>";
- ret += " <p>CSS example:</p>";
- ret += " <pre>p::first-line { text-transform: uppercase }</pre>";
- ret += " <p>The above rule means 'change the letters of the first line of every";
- ret += " paragraph to uppercase'.</p>";
- ret += " </div>";
- ret += " <p>The selector <code>p::first-line</code> does not match any real";
- ret += " agents will insert at the beginning of every paragraph.</p>";
- ret += " <p>Note that the length of the first line depends on a number of";
- ret += " an ordinary HTML paragraph such as:</p>";
- ret += " <pre> <P>This is a somewhat long HTML ";
- ret += " </pre>";
- ret += " <p>the lines of which happen to be broken as follows:";
- ret += " </p><pre> THIS IS A SOMEWHAT LONG HTML PARAGRAPH THAT";
- ret += " </pre>";
- ret += " <p>This paragraph might be 'rewritten' by user agents to include the";
- ret += " <em>fictional tag sequence</em> for <code>::first-line</code>. This";
- ret += " fictional tag sequence helps to show how properties are inherited.</p>";
- ret += " <pre> <P><b><P::first-line></b> This is a somewhat long HTML ";
- ret += " paragraph that <b></P::first-line></b> will be broken into several";
- ret += " </pre>";
- ret += " <p>If a pseudo-element breaks up a real element, the desired effect";
- ret += " with a <code>span</code> element:</p>";
- ret += " <pre> <P><b><SPAN class='test'></b> This is a somewhat long HTML";
- ret += " lines.<b></SPAN></b> The first line will be identified";
- ret += " </pre>";
- ret += " <p>the user agent could simulate start and end tags for";
- ret += " <code>span</code> when inserting the fictional tag sequence for";
- ret += " <code>::first-line</code>.";
- ret += " </p><pre> <P><P::first-line><b><SPAN class='test'></b> This is a";
- ret += " paragraph that will <b></SPAN></b></P::first-line><b><SPAN";
- ret += " class='test'></b> be";
- ret += " lines.<b></SPAN></b> The first line will be identified";
- ret += " </pre>";
- ret += " <p>In CSS, the <code>::first-line</code> pseudo-element can only be";
- ret += " or a table-cell.</p>";
- ret += " <p><a name='first-formatted-line'></a>The 'first formatted line' of an";
- ret += " line of the <code>div</code> in <code><DIV><P>This";
- ret += " line...</P></DIV></code> is the first line of the <code>p</code>";
- ret += " that both <code>p</code> and <code>div</code> are block-level).";
- ret += " </p><p>The first line of a table-cell or inline-block cannot be the first";
- ret += " formatted line of an ancestor element. Thus, in <code><DIV><P";
- ret += " etcetera</DIV></code> the first formatted line of the";
- ret += " <code>div</code> is not the line 'Hello'.";
- ret += " </p><p class='note'>Note that the first line of the <code>p</code> in this";
- ret += " fragment: <code><p><br>First...</code> doesn't contain any";
- ret += " letters (assuming the default style for <code>br</code> in HTML";
- ret += " </p><p>A UA should act as if the fictional start tags of the";
- ret += " <code>::first-line</code> pseudo-elements were nested just inside the";
- ret += " is an example. The fictional tag sequence for</p>";
- ret += " <pre> <DIV>";
- ret += " </pre>";
- ret += " <p>is</p>";
- ret += " <pre> <DIV>";
- ret += " </pre>";
- ret += " <p>The <code>::first-line</code> pseudo-element is similar to an";
- ret += " following properties apply to a <code>::first-line</code>";
- ret += " properties as well.</p>";
- ret += " <h4><a name='first-letter'>7.2. The ::first-letter pseudo-element</a></h4>";
- ret += " <p>The <code>::first-letter</code> pseudo-element represents the first";
- ret += " is 'none'; otherwise, it is similar to a floated element.</p>";
- ret += " <p>In CSS, these are the properties that apply to <code>::first-letter</code>";
- ret += " of the letter, unlike for normal elements.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>This example shows a possible rendering of an initial cap. Note";
- ret += " <code>::first-letter</code>";
- ret += " fictional start tag of the first letter is inside the <span>span</span>,";
- ret += " the font weight of the first letter is normal, not bold as the <span>span</span>:";
- ret += " </p><pre> p { line-height: 1.1 }";
- ret += " </pre>";
- ret += " <div class='figure'>";
- ret += " <p><img src='' alt='Image illustrating the ::first-letter pseudo-element'>";
- ret += " </p></div>";
- ret += " </div>";
- ret += " <div class='example'>";
- ret += " <p>The following CSS will make a drop cap initial letter span about two";
- ret += " lines:</p>";
- ret += " <pre> <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN'>";
- ret += " </pre>";
- ret += " <p>This example might be formatted as follows:</p>";
- ret += " <div class='figure'>";
- ret += " <p><img src='' alt='Image illustrating the combined effect of the ::first-letter and ::first-line pseudo-elements'>";
- ret += " </p>";
- ret += " </div>";
- ret += " <p>The <span class='index-inst' title='fictional tag";
- ret += " sequence'>fictional tag sequence</span> is:</p>";
- ret += " <pre> <P>";
- ret += " </pre>";
- ret += " <p>Note that the <code>::first-letter</code> pseudo-element tags abut";
- ret += " block element.</p></div>";
- ret += " <p>In order to achieve traditional drop caps formatting, user agents";
- ret += " glyph outline may be taken into account when formatting.</p>";
- ret += " <p>Punctuation (i.e, characters defined in Unicode in the 'open' (Ps),";
- ret += " be included. <a href='#refsUNICODE'>[UNICODE]</a></p>";
- ret += " <div class='figure'>";
- ret += " <p><img src='' alt='Quotes that precede the";
- ret += " first letter should be included.'></p>";
- ret += " </div>";
- ret += " <p>The <code>::first-letter</code> also applies if the first letter is";
- ret += " money.'</p>";
- ret += " <p>In CSS, the <code>::first-letter</code> pseudo-element applies to";
- ret += " elements. <span class='note'>A future version of this specification";
- ret += " types.</span></p>";
- ret += " <p>The <code>::first-letter</code> pseudo-element can be used with all";
- ret += " the element, even if that first text is in a descendant.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>The fictional tag sequence for this HTMLfragment:";
- ret += " </p><pre><div>";
- ret += " <p>The first text.</pre>";
- ret += " <p>is:";
- ret += " </p><pre><div>";
- ret += " <p><div::first-letter><p::first-letter>T</...></...>he first text.</pre>";
- ret += " </div>";
- ret += " <p>The first letter of a table-cell or inline-block cannot be the";
- ret += " first letter of an ancestor element. Thus, in <code><DIV><P";
- ret += " etcetera</DIV></code> the first letter of the <code>div</code> is";
- ret += " letter 'H'. In fact, the <code>div</code> doesn't have a first letter.";
- ret += " </p><p>The first letter must occur on the <a href='#first-formatted-line'>first formatted line.</a> For example, in";
- ret += " this fragment: <code><p><br>First...</code> the first line";
- ret += " doesn't contain any letters and <code>::first-letter</code> doesn't";
- ret += " match anything (assuming the default style for <code>br</code> in HTML";
- ret += " </p><p>In CSS, if an element is a list item ('display: list-item'), the";
- ret += " <code>::first-letter</code> applies to the first letter in the";
- ret += " <code>::first-letter</code> on list items with 'list-style-position:";
- ret += " inside'. If an element has <code>::before</code> or";
- ret += " <code>::after</code> content, the <code>::first-letter</code> applies";
- ret += " to the first letter of the element <em>including</em> that content.";
- ret += " </p><div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>After the rule 'p::before {content: 'Note: '}', the selector";
- ret += " 'p::first-letter' matches the 'N' of 'Note'.</p>";
- ret += " </div>";
- ret += " <p>Some languages may have specific rules about how to treat certain";
- ret += " considered within the <code>::first-letter</code> pseudo-element.";
- ret += " </p><p>If the letters that would form the ::first-letter are not in the";
- ret += " same element, such as ''T' in <code><p>'<em>T...</code>, the UA";
- ret += " both elements, or simply not create a pseudo-element.</p>";
- ret += " <p>Similarly, if the first letter(s) of the block are not at the start";
- ret += " </p><div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p><a name='overlapping-example'>The following example</a> illustrates";
- ret += " paragraph will be 'red'.</p>";
- ret += " <pre>p { color: red; font-size: 12pt }";
- ret += " <P>Some text that ends up on two lines</P></pre>";
- ret += " <p>Assuming that a line break will occur before the word 'ends', the";
- ret += " <span class='index-inst' title='fictional tag sequence'>fictional tag";
- ret += " sequence</span> for this fragment might be:</p>";
- ret += " <pre><P>";
- ret += " </P></pre>";
- ret += " <p>Note that the <code>::first-letter</code> element is inside the <code>::first-line</code>";
- ret += " element. Properties set on <code>::first-line</code> are inherited by";
- ret += " <code>::first-letter</code>, but are overridden if the same property is";
- ret += " <code>::first-letter</code>.</p>";
- ret += " </div>";
- ret += " <h4><a name='UIfragments'>7.3.</a> <a name='selection'>The ::selection";
- ret += " pseudo-element</a></h4>";
- ret += " <p>The <code>::selection</code> pseudo-element applies to the portion";
- ret += " field. This pseudo-element should not be confused with the <code><a href='#checked'>:checked</a></code> pseudo-class (which used to be";
- ret += " named <code>:selected</code>)";
- ret += " </p><p>Although the <code>::selection</code> pseudo-element is dynamic in";
- ret += " <a href='#refsCSS21'>[CSS21]</a>) which was originally rendered to a";
- ret += " <code>::selection</code> state to that other medium, and have all the";
- ret += " required — UAs may omit the <code>::selection</code>";
- ret += " </p><p>These are the CSS properties that apply to <code>::selection</code>";
- ret += " <code>::selection</code> may be ignored.";
- ret += " </p><h4><a name='gen-content'>7.4. The ::before and ::after pseudo-elements</a></h4>";
- ret += " <p>The <code>::before</code> and <code>::after</code> pseudo-elements";
- ret += " content. They are explained in CSS 2.1 <a href='#refsCSS21'>[CSS21]</a>.</p>";
- ret += " <p>When the <code>::first-letter</code> and <code>::first-line</code>";
- ret += " pseudo-elements are combined with <code>::before</code> and";
- ret += " <code>::after</code>, they apply to the first letter or line of the";
- ret += " element including the inserted text.</p>";
- ret += " <h2><a name='combinators'>8. Combinators</a></h2>";
- ret += " <h3><a name='descendant-combinators'>8.1. Descendant combinator</a></h3>";
- ret += " <p>At times, authors may want selectors to describe an element that is";
- ret += " <code>EM</code> element that is contained within an <code>H1</code>";
- ret += " descendant combinator is <a href='#whitespace'>white space</a> that";
- ret += " separates two sequences of simple selectors. A selector of the form";
- ret += " '<code>A B</code>' represents an element <code>B</code> that is an";
- ret += " arbitrary descendant of some ancestor element <code>A</code>.";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>For example, consider the following selector:</p>";
- ret += " <pre>h1 em</pre>";
- ret += " <p>It represents an <code>em</code> element being the descendant of";
- ret += " an <code>h1</code> element. It is a correct and valid, but partial,";
- ret += " description of the following fragment:</p>";
- ret += " <pre><h1>This <span class='myclass'>headline";
- ret += " is <em>very</em> important</span></h1></pre>";
- ret += " <p>The following selector:</p>";
- ret += " <pre>div * p</pre>";
- ret += " <p>represents a <code>p</code> element that is a grandchild or later";
- ret += " descendant of a <code>div</code> element. Note the whitespace on";
- ret += " of the P.</p>";
- ret += " <p>The following selector, which combines descendant combinators and";
- ret += " <a href='#attribute-selectors'>attribute selectors</a>, represents an";
- ret += " element that (1) has the <code>href</code> attribute set and (2) is";
- ret += " inside a <code>p</code> that is itself inside a <code>div</code>:</p>";
- ret += " <pre>div p *[href]</pre>";
- ret += " </div>";
- ret += " <h3><a name='child-combinators'>8.2. Child combinators</a></h3>";
- ret += " <p>A <dfn>child combinator</dfn> describes a childhood relationship";
- ret += " 'greater-than sign' (<code>></code>) character and";
- ret += " separates two sequences of simple selectors.";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following selector represents a <code>p</code> element that is";
- ret += " child of <code>body</code>:</p>";
- ret += " <pre>body > p</pre>";
- ret += " <p>The following example combines descendant combinators and child";
- ret += " combinators.</p>";
- ret += " <pre>div ol>li p</pre>";
- ret += " <!-- LEAVE THOSE SPACES OUT! see below -->";
- ret += " <p>It represents a <code>p</code> element that is a descendant of an";
- ret += " <code>li</code> element; the <code>li</code> element must be the";
- ret += " child of an <code>ol</code> element; the <code>ol</code> element must";
- ret += " be a descendant of a <code>div</code>. Notice that the optional white";
- ret += " space around the '>' combinator has been left out.</p>";
- ret += " </div>";
- ret += " <p>For information on selecting the first child of an element, please";
- ret += " see the section on the <code><a href='#structural-pseudos'>:first-child</a></code> pseudo-class";
- ret += " above.</p>";
- ret += " <h3><a name='sibling-combinators'>8.3. Sibling combinators</a></h3>";
- ret += " <p>There are two different sibling combinators: the adjacent sibling";
- ret += " considering adjacency of elements.</p>";
- ret += " <h4><a name='adjacent-sibling-combinators'>8.3.1. Adjacent sibling combinator</a>";
- ret += " </h4>";
- ret += " <p>The adjacent sibling combinator is made of the 'plus";
- ret += " sign' (U+002B, <code>+</code>) character that separates two";
- ret += " sequences of simple selectors. The elements represented by the two";
- ret += " represented by the second one.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following selector represents a <code>p</code> element";
- ret += " immediately following a <code>math</code> element:</p>";
- ret += " <pre>math + p</pre>";
- ret += " <p>The following selector is conceptually similar to the one in the";
- ret += " adds a constraint to the <code>h1</code> element, that it must have";
- ret += " <code>class='opener'</code>:</p>";
- ret += " <pre>h1.opener + h2</pre>";
- ret += " </div>";
- ret += " <h4><a name='general-sibling-combinators'>8.3.2. General sibling combinator</a>";
- ret += " </h4>";
- ret += " <p>The general sibling combinator is made of the 'tilde'";
- ret += " (U+007E, <code>~</code>) character that separates two sequences of";
- ret += " simple selectors. The elements represented by the two sequences share";
- ret += " represented by the second one.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <pre>h1 ~ pre</pre>";
- ret += " <p>represents a <code>pre</code> element following an <code>h1</code>. It";
- ret += " is a correct and valid, but partial, description of:</p>";
- ret += " <pre><h1>Definition of the function a</h1>";
- ret += " <pre>function a(x) = 12x/13.5</pre></pre>";
- ret += " </div>";
- ret += " <h2><a name='specificity'>9. Calculating a selector's specificity</a></h2>";
- ret += " <p>A selector's specificity is calculated as follows:</p>";
- ret += " <ul>";
- ret += " <li>count the number of ID selectors in the selector (= a)</li>";
- ret += " <li>count the number of class selectors, attributes selectors, and";
- ret += " </li>";
- ret += " <li>count the number of element names in the selector (= c)</li>";
- ret += " <li>ignore pseudo-elements</li>";
- ret += " </ul>";
- ret += " <p>Selectors inside <a href='#negation'>the negation pseudo-class</a>";
- ret += " a pseudo-class.</p>";
- ret += " <p>Concatenating the three numbers a-b-c (in a number system with a";
- ret += " large base) gives the specificity.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <pre>* /* a=0 b=0 c=0 -> specificity = 0 */";
- ret += " </pre>";
- ret += " </div>";
- ret += " <p class='note'><strong>Note:</strong> the specificity of the styles";
- ret += " specified in an HTML <code>style</code> attribute is described in CSS";
- ret += " 2.1. <a href='#refsCSS21'>[CSS21]</a>.</p>";
- ret += " <h2><a name='w3cselgrammar'>10. The grammar of Selectors</a></h2>";
- ret += " <h3><a name='grammar'>10.1. Grammar</a></h3>";
- ret += " <p>The grammar below defines the syntax of Selectors. It is globally";
- ret += " shorthand notations beyond Yacc (see <a href='#refsYACC'>[YACC]</a>)";
- ret += " are used:</p>";
- ret += " <ul>";
- ret += " <li><b>*</b>: 0 or more";
- ret += " </li><li><b>+</b>: 1 or more";
- ret += " </li><li><b>?</b>: 0 or 1";
- ret += " </li><li><b>|</b>: separates alternatives";
- ret += " </li><li><b>[ ]</b>: grouping</li>";
- ret += " </ul>";
- ret += " <p>The productions are:</p>";
- ret += " <pre>selectors_group";
- ret += " ;</pre>";
- ret += " <h3><a name='lex'>10.2. Lexical scanner</a></h3>";
- ret += " <p>The following is the <a name='x3'>tokenizer</a>, written in Flex (see";
- ret += " <a href='#refsFLEX'>[FLEX]</a>) notation. The tokenizer is";
- ret += " case-insensitive.</p>";
- ret += " <p>The two occurrences of '\377' represent the highest character";
- ret += " possible code point in Unicode/ISO-10646. <a href='#refsUNICODE'>[UNICODE]</a></p>";
- ret += " <pre>%option case-insensitive";
- ret += " . return *yytext;</pre>";
- ret += " <h2><a name='downlevel'>11. Namespaces and down-level clients</a></h2>";
- ret += " <p>An important issue is the interaction of CSS selectors with XML";
- ret += " to construct a CSS style sheet which will properly match selectors in";
- ret += " is possible to construct a style sheet in which selectors would match";
- ret += " elements and attributes correctly.</p>";
- ret += " <p>It should be noted that a down-level CSS client will (if it";
- ret += " <code>@namespace</code> at-rules, as well as all style rules that make";
- ret += " use of namespace qualified element type or attribute selectors. The";
- ret += " than possibly match them incorrectly.</p>";
- ret += " <p>The use of default namespaces in CSS makes it possible to write";
- ret += " element type selectors that will function in both namespace aware CSS";
- ret += " down-level clients may incorrectly match selectors against XML";
- ret += " elements in other namespaces.</p>";
- ret += " <p>The following are scenarios and examples in which it is possible to";
- ret += " that do not implement this proposal.</p>";
- ret += " <ol>";
- ret += " <li>";
- ret += " <p>The XML document does not use namespaces.</p>";
- ret += " <ul>";
- ret += " <li>In this case, it is obviously not necessary to declare or use";
- ret += " attribute selectors will function adequately in a down-level";
- ret += " </li>";
- ret += " <li>In a CSS namespace aware client, the default behavior of";
- ret += " element selectors matching without regard to namespace will";
- ret += " present. However, the use of specific element type selectors";
- ret += " match only elements that have no namespace ('<code>|name</code>')";
- ret += " will guarantee that selectors will match only XML elements that";
- ret += " </li>";
- ret += " </ul>";
- ret += " </li>";
- ret += " <li>";
- ret += " <p>The XML document defines a single, default namespace used";
- ret += " names.</p>";
- ret += " <ul>";
- ret += " <li>In this case, a down-level client will function as if";
- ret += " element type and attribute selectors will match against all";
- ret += " </li>";
- ret += " </ul>";
- ret += " </li>";
- ret += " <li>";
- ret += " <p>The XML document does <b>not</b> use a default namespace, all";
- ret += " to the same URI).</p>";
- ret += " <ul>";
- ret += " <li>In this case, the down-level client will view and match";
- ret += " element type and attribute selectors based on their fully";
- ret += " qualified name, not the local part as outlined in the <a href='#typenmsp'>Type selectors and Namespaces</a>";
- ret += " selectors may be declared using an escaped colon";
- ret += " '<code>\\:</code>'";
- ret += " '<code>html\\:h1</code>' will match";
- ret += " <code><html:h1></code>. Selectors using the qualified name";
- ret += " </li>";
- ret += " <li>Note that selectors declared in this fashion will";
- ret += " <em>only</em> match in down-level clients. A CSS namespace aware";
- ret += " client will match element type and attribute selectors based on";
- ret += " the name's local part. Selectors declared with the fully";
- ret += " </li>";
- ret += " </ul>";
- ret += " </li>";
- ret += " </ol>";
- ret += " <p>In other scenarios: when the namespace prefixes used in the XML are";
- ret += " <em>different</em> namespace URIs within the same document, or in";
- ret += " a CSS and XML namespace aware client.</p>";
- ret += " <h2><a name='profiling'>12. Profiles</a></h2>";
- ret += " <p>Each specification using Selectors must define the subset of W3C";
- ret += " Selectors it allows and excludes, and describe the local meaning of";
- ret += " all the components of that subset.</p>";
- ret += " <p>Non normative examples:";
- ret += " </p><div class='profile'>";
- ret += " <table class='tprofile'>";
- ret += " <tbody>";
- ret += " <tr>";
- ret += " <th class='title' colspan='2'>Selectors profile</th>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Specification</th>";
- ret += " <td>CSS level 1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Accepts</th>";
- ret += " <td>type selectors<br>class selectors<br>ID selectors<br>:link,";
- ret += " :visited and :active pseudo-classes<br>descendant combinator";
- ret += " <br>::first-line and ::first-letter pseudo-elements";
- ret += " </td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Excludes</th>";
- ret += " <td>";
- ret += " <p>universal selector<br>attribute selectors<br>:hover and";
- ret += " pseudo-classes<br>:target pseudo-class<br>:lang()";
- ret += " pseudo-class<br>all UI";
- ret += " element states pseudo-classes<br>all structural";
- ret += " pseudo-classes<br>negation pseudo-class<br>all";
- ret += " UI element fragments pseudo-elements<br>::before and ::after";
- ret += " pseudo-elements<br>child combinators<br>sibling combinators";
- ret += " </p><p>namespaces</p></td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Extra constraints</th>";
- ret += " <td>only one class selector allowed per sequence of simple";
- ret += " selectors";
- ret += " </td>";
- ret += " </tr>";
- ret += " </tbody>";
- ret += " </table>";
- ret += " <br><br>";
- ret += " <table class='tprofile'>";
- ret += " <tbody>";
- ret += " <tr>";
- ret += " <th class='title' colspan='2'>Selectors profile</th>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Specification</th>";
- ret += " <td>CSS level 2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Accepts</th>";
- ret += " <td>type selectors<br>universal selector<br>attribute presence and";
- ret += " values selectors<br>class selectors<br>ID selectors<br>:link,";
- ret += " <br>descendant combinator<br>child combinator<br>adjacent";
- ret += " combinator<br>::first-line and ::first-letter";
- ret += " pseudo-elements<br>::before";
- ret += " </td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Excludes</th>";
- ret += " <td>";
- ret += " <p>content selectors<br>substring matching attribute";
- ret += " selectors<br>:target pseudo-classes<br>all UI element";
- ret += " states pseudo-classes<br>all structural pseudo-classes other";
- ret += " than :first-child<br>negation pseudo-class<br>all UI element";
- ret += " fragments pseudo-elements<br>general sibling combinators";
- ret += " </p><p>namespaces</p></td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Extra constraints</th>";
- ret += " <td>more than one class selector per sequence of simple selectors";
- ret += " </td>";
- ret += " </tr>";
- ret += " </tbody>";
- ret += " </table>";
- ret += " <p>In CSS, selectors express pattern matching rules that determine which";
- ret += " </p><p>The following selector (CSS level 2) will <b>match</b> all anchors <code>a</code>";
- ret += " with attribute <code>name</code> set inside a section 1 header";
- ret += " <code>h1</code>:";
- ret += " </p><pre>h1 a[name]</pre>";
- ret += " <p>All CSS declarations attached to such a selector are applied to elements";
- ret += " matching it.</p></div>";
- ret += " <div class='profile'>";
- ret += " <table class='tprofile'>";
- ret += " <tbody>";
- ret += " <tr>";
- ret += " <th class='title' colspan='2'>Selectors profile</th>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Specification</th>";
- ret += " <td>STTS 3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Accepts</th>";
- ret += " <td>";
- ret += " <p>type selectors<br>universal selectors<br>attribute";
- ret += " selectors<br>class";
- ret += " selectors<br>ID selectors<br>all structural";
- ret += " pseudo-classes<br>";
- ret += " </p><p>namespaces</p></td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Excludes</th>";
- ret += " <td>non-accepted pseudo-classes<br>pseudo-elements<br></td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Extra constraints</th>";
- ret += " <td>some selectors and combinators are not allowed in fragment";
- ret += " </td>";
- ret += " </tr>";
- ret += " </tbody>";
- ret += " </table>";
- ret += " <p>Selectors can be used in STTS 3 in two different";
- ret += " </p><ol>";
- ret += " <li>a selection mechanism equivalent to CSS selection mechanism:";
- ret += " </li><li>fragment descriptions that appear on the right side of declarations.";
- ret += " </li>";
- ret += " </ol>";
- ret += " </div>";
- ret += " <h2><a name='Conformance'></a>13. Conformance and requirements</h2>";
- ret += " <p>This section defines conformance with the present specification only.";
- ret += " </p><p>The inability of a user agent to implement part of this specification due to";
- ret += " </p><p>All specifications reusing Selectors must contain a <a href='#profiling'>Profile</a> listing the";
- ret += " subset of Selectors it accepts or excludes, and describing the constraints";
- ret += " </p><p>Invalidity is caused by a parsing error, e.g. an unrecognized token or a";
- ret += " </p><p>User agents must observe the rules for handling parsing errors:";
- ret += " </p><ul>";
- ret += " <li>a simple selector containing an undeclared namespace prefix is invalid";
- ret += " </li>";
- ret += " <li>a selector containing an invalid simple selector, an invalid combinator";
- ret += " </li>";
- ret += " <li>a group of selectors containing an invalid selector is invalid.</li>";
- ret += " </ul>";
- ret += " <p>Specifications reusing Selectors must define how to handle parsing";
- ret += " used is dropped.)</p>";
- ret += " <!-- Apparently all these references are out of date:";
- ret += " <p>Implementations of this specification must behave as";
- ret += " 'recipients of text data' as defined by <a href='#refsCWWW'>[CWWW]</a>";
- ret += " when parsing selectors and attempting matches. (In particular,";
- ret += " <a href='#refsCWWW'>[CWWW]</a> and <a";
- ret += " href='#refsUNICODE'>[UNICODE]</a> and apply to implementations of this";
- ret += " specification.</p>-->";
- ret += " <h2><a name='Tests'></a>14. Tests</h2>";
- ret += " <p>This specification has <a href='http://www.w3.org/Style/CSS/Test/CSS3/Selectors/current/'>a test";
- ret += " suite</a> allowing user agents to verify their basic conformance to";
- ret += " and does not cover all possible combined cases of Selectors.</p>";
- ret += " <h2><a name='ACKS'></a>15. Acknowledgements</h2>";
- ret += " <p>The CSS working group would like to thank everyone who has sent";
- ret += " comments on this specification over the years.</p>";
- ret += " <p>The working group would like to extend special thanks to Donna";
- ret += " the final editorial review.</p>";
- ret += " <h2><a name='references'>16. References</a></h2>";
- ret += " <dl class='refs'>";
- ret += " <dt>[CSS1]";
- ret += " </dt><dd><a name='refsCSS1'></a> Bert Bos, Håkon Wium Lie; '<cite>Cascading";
- ret += " Style Sheets, level 1</cite>', W3C Recommendation, 17 Dec 1996, revised";
- ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/REC-CSS1'>http://www.w3.org/TR/REC-CSS1</a></code>)";
- ret += " </dd><dt>[CSS21]";
- ret += " </dt><dd><a name='refsCSS21'></a> Bert Bos, Tantek Çelik, Ian Hickson, Håkon";
- ret += " Wium Lie, editors; '<cite>Cascading Style Sheets, level 2 revision";
- ret += " 1</cite>', W3C Working Draft, 13 June 2005";
- ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/CSS21'>http://www.w3.org/TR/CSS21</a></code>)";
- ret += " </dd><dt>[CWWW]";
- ret += " </dt><dd><a name='refsCWWW'></a> Martin J. Dürst, François Yergeau,";
- ret += " Misha Wolf, Asmus Freytag, Tex Texin, editors; '<cite>Character Model";
- ret += " for the World Wide Web</cite>', W3C Recommendation, 15 February 2005";
- ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/charmod/'>http://www.w3.org/TR/charmod/</a></code>)";
- ret += " </dd><dt>[FLEX]";
- ret += " </dt><dd><a name='refsFLEX'></a> '<cite>Flex: The Lexical Scanner";
- ret += " Generator</cite>', Version 2.3.7, ISBN 1882114213";
- ret += " </dd><dt>[HTML4]";
- ret += " </dt><dd><a name='refsHTML4'></a> Dave Ragget, Arnaud Le Hors, Ian Jacobs,";
- ret += " editors; '<cite>HTML 4.01 Specification</cite>', W3C Recommendation, 24";
- ret += " </dd><dd>";
- ret += " (<a href='http://www.w3.org/TR/html4/'><code>http://www.w3.org/TR/html4/</code></a>)";
- ret += " </dd><dt>[MATH]";
- ret += " </dt><dd><a name='refsMATH'></a> Patrick Ion, Robert Miner, editors; '<cite>Mathematical";
- ret += " Markup Language (MathML) 1.01</cite>', W3C Recommendation, revision of 7";
- ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/REC-MathML/'>http://www.w3.org/TR/REC-MathML/</a></code>)";
- ret += " </dd><dt>[RFC3066]";
- ret += " </dt><dd><a name='refsRFC3066'></a> H. Alvestrand; '<cite>Tags for the";
- ret += " Identification of Languages</cite>', Request for Comments 3066, January";
- ret += " </dd><dd>(<a href='http://www.ietf.org/rfc/rfc3066.txt'><code>http://www.ietf.org/rfc/rfc3066.txt</code></a>)";
- ret += " </dd><dt>[STTS]";
- ret += " </dt><dd><a name='refsSTTS'></a> Daniel Glazman; '<cite>Simple Tree Transformation";
- ret += " Sheets 3</cite>', Electricité de France, submission to the W3C,";
- ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/NOTE-STTS3'>http://www.w3.org/TR/NOTE-STTS3</a></code>)";
- ret += " </dd><dt>[SVG]";
- ret += " </dt><dd><a name='refsSVG'></a> Jon Ferraiolo, 藤沢 淳, Dean";
- ret += " Jackson, editors; '<cite>Scalable Vector Graphics (SVG) 1.1";
- ret += " Specification</cite>', W3C Recommendation, 14 January 2003";
- ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/SVG/'>http://www.w3.org/TR/SVG/</a></code>)";
- ret += " </dd><dt>[UNICODE]</dt>";
- ret += " <dd><a name='refsUNICODE'></a> <cite><a href='http://www.unicode.org/versions/Unicode4.1.0/'>The Unicode";
- ret += " Standard, Version 4.1</a></cite>, The Unicode Consortium. Boston, MA,";
- ret += " Addison-Wesley, March 2005. ISBN 0-321-18578-1, as amended by <a href='http://www.unicode.org/versions/Unicode4.0.1/'>Unicode";
- ret += " 4.0.1</a> and <a href='http://www.unicode.org/versions/Unicode4.1.0/'>Unicode";
- ret += " 4.1.0</a>.";
- ret += " </dd><dd>(<code><a href='http://www.unicode.org/versions/'>http://www.unicode.org/versions/</a></code>)";
- ret += " </dd>";
- ret += " <dt>[XML10]";
- ret += " </dt><dd><a name='refsXML10'></a> Tim Bray, Jean Paoli, C. M. Sperberg-McQueen,";
- ret += " Eve Maler, François Yergeau, editors; '<cite>Extensible Markup";
- ret += " Language (XML) 1.0 (Third Edition)</cite>', W3C Recommendation, 4";
- ret += " </dd><dd>(<a href='http://www.w3.org/TR/REC-xml/'><code>http://www.w3.org/TR/REC-xml/</code></a>)";
- ret += " </dd><dt>[XMLNAMES]";
- ret += " </dt><dd><a name='refsXMLNAMES'></a> Tim Bray, Dave Hollander, Andrew Layman,";
- ret += " editors; '<cite>Namespaces in XML</cite>', W3C Recommendation, 14";
- ret += " </dd><dd>(<a href='http://www.w3.org/TR/REC-xml-names/'><code>http://www.w3.org/TR/REC-xml-names/</code></a>)";
- ret += " </dd><dt>[YACC]";
- ret += " </dt><dd><a name='refsYACC'></a> S. C. Johnson; '<cite>YACC — Yet another";
- ret += " compiler compiler</cite>', Technical Report, Murray Hill, 1975";
- ret += " </dd></dl>'; </div>";
- ret += " <input name='n' value='v1' type='radio'>1";
- ret += " <input name='n' value='v2' checked='checked' type='radio'>2";
- ret += "";
- return ret;
- }
-
-}
+/* + * 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.GQuery.$; +import static com.google.gwt.query.client.GQuery.window; + +import com.google.gwt.core.client.EntryPoint; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.core.client.Scheduler.RepeatingCommand; +import com.google.gwt.query.client.js.JsUtils; + +/** + * This module is thought to emulate a test environment similar to + * GWTTestCase, but running it in development mode. + * + * The main goal of it is to execute tests in a faster way, because you just + * push reload in your browser after changing any code. + * + * @author manolo + * + */ +public class DevTestRunner extends MyTestCase implements EntryPoint { + + public void onModuleLoad() { + try { + gwtSetUp(); + // Replace this with the method to run + testSomething(); + } catch (Exception ex) { + ex.printStackTrace(); + $(e).html("").after("<div>ERROR: " + ex.getMessage() + "</div>"); + } + } + + public void testSomething() { + // Copy and paste any test from the gquery suite + } + + /** + * Runs jquery code via jsni. + * + * Example: + * System.out.println(evalJQuery("$('div').size()")); + */ + private native <T> T evalJQuery(String command) /*-{ + command = command.replace(/\$/g, "$wnd.$"); + try { + return "" + eval(command); + } catch(e) { + $wnd.alert(command + " " + e); + return ""; + } + }-*/; + + /** + * Loads jquery and schedule the execution of the method testCompare() + * which should have code to test something in both in jquery and gquery. + * + * Put this method in onModuleLoad, and replace below the method to execute + * after jquery is available + */ + public void runTestJQuery() { + JsUtils.loadScript("jquery-1.6.2.js", "jq"); + Scheduler.get().scheduleFixedDelay(new RepeatingCommand() { + private int cont = 0; + private native boolean loaded(String func) /*-{ + return eval("$wnd." + func) ? true : false; + }-*/; + public boolean execute() { + if (cont++ > 10 || JsUtils.hasProperty(window, "$")) { + + // Replace with the method to run + testJQueryCompare(); + return false; + } + return true; + } + }, 100); + } + + public void testJQueryCompare() { + $(e).html("<div id='parent' style='background-color: yellow; width: 100px; height: 200px; top:130px; position: absolute; left: 130px'><p id='child' style='background-color: pink; width: 100px; height: 100px; position: absolute; padding: 5px'>Content 1</p></div>"); + GQuery g = $("#child"); + Properties prop1; + + prop1 = GQuery.$$("marginTop: '0', marginLeft: '0', top: '0%', left: '0%', width: '100px', height: '100px', padding: '5px'"); + g.css(prop1); + validateCurCSSBoth("#child", prop1.keys()); + } + + public void validateSizesBoth(String html) { + $(e).html(html); + String gqw = "" + $(".outer").width(); + String jqw = evalJQuery("$('.outer').width()"); + String gqh = "" + $(".outer").height(); + String jqh = evalJQuery("$('.outer').height()"); + + System.out.println(".outer size: GQuery: " + gqw + "x" + gqh + " jQuery: " + jqw + "x" + jqh); + assertEquals(gqw, jqw); + assertEquals(gqh, jqh); + } + + public void validateCssBoth(String selector, boolean force, String... props) { + for (String prop: props) { + String gs = $(selector).css(prop, force); + String js = evalJQuery("$.css($('" + selector + "').get(0), '" + prop + "', " + force + ")"); + System.out.println(selector + " prop:" + prop + " force:" + force + " gQuery:" + gs + " jQuery:" + js); + assertEquals(gs.replaceAll("px", ""), js.replaceAll("px", "")); + } + } + + public void validateCurCSSBoth(String selector, String... props) { + for (String prop: props) { + String gs = Double.toString($(selector).cur(prop, true)).replaceFirst("\\.\\d+$", ""); + String js = evalJQuery("$.curCSS($('" + selector + "').get(0), '" + prop + "', true)"); + gs = gs.replaceAll("px$", ""); + js = js.replaceAll("px$", ""); + System.out.println(selector + " prop:" + prop + " gQuery:" + gs + " jQuery:" + js); + assertEquals(gs, js); + } + } + + // This method is used to initialize a huge html String, because + // java 1.5 has a limitation in the size of static strings. + private String getTestContent() { + String ret = ""; + ret += "<div>"; + ret += " <div class='head dialog'>"; + ret += " <p><a href='http://www.w3.org/'><img alt='W3C' src='' height='48' width='72'></a></p>"; + ret += " <h1 id='title'>Selectors</h1>"; + ret += " <em><span>.</span></em>"; + ret += " <h2>W3C Working Draft 15 December 2005</h2>"; + ret += " <dl>"; + ret += " <dt>This version:</dt>"; + ret += " <dd><a href='http://www.w3.org/TR/2005/WD-css3-selectors-20051215'>"; + ret += " http://www.w3.org/TR/2005/WD-css3-selectors-20051215</a></dd>"; + ret += " <dt>Latest version:"; + ret += " </dt><dd><a href='http://www.w3.org/TR/css3-selectors'>"; + ret += " http://www.w3.org/TR/css3-selectors</a>"; + ret += " </dd><dt>Previous version:"; + ret += " </dt><dd><a href='http://www.w3.org/TR/2001/CR-css3-selectors-20011113'>"; + ret += " http://www.w3.org/TR/2001/CR-css3-selectors-20011113</a>"; + ret += " </dd><dt><a name='editors-list'></a>Editors:"; + ret += " </dt><dd class='vcard'><span class='fn'>Daniel Glazman</span> (Invited"; + ret += " </dd>"; + ret += " <dd class='vcard'><a class='url fn' href='http://www.tantek.com/' lang='tr'>Tantek Çelik</a>"; + ret += " </dd><dd class='vcard'><a href='mailto:ian@hixie.ch' class='url fn'>Ian"; + ret += " Hickson</a> (<span class='company'><a href='http://www.google.com/'>Google</a></span>)"; + ret += " </dd><dd class='vcard'><span class='fn'>Peter Linss</span> (former"; + ret += " editor, <span class='company'><a href='http://www.netscape.com/'>Netscape/AOL</a></span>)"; + ret += " </dd><dd class='vcard'><span class='fn'>John Williams</span> (former editor, <span class='company'><a href='http://www.quark.com/'>Quark, Inc.</a></span>)"; + ret += " </dd></dl>"; + ret += " <p class='copyright'><a href='http://www.w3.org/Consortium/Legal/ipr-notice#Copyright'>"; + ret += " Copyright</a> © 2005 <a href='http://www.w3.org/'><abbr title='World Wide Web Consortium'>W3C</abbr></a><sup>®</sup>"; + ret += " (<a href='http://www.csail.mit.edu/'><abbr title='Massachusetts"; + ret += " Institute of Technology'>MIT</abbr></a>, <a href='http://www.ercim.org/'><acronym title='European Research"; + ret += " Consortium for Informatics and Mathematics'>ERCIM</acronym></a>, <a href='http://www.keio.ac.jp/'>Keio</a>), All Rights Reserved."; + ret += " <a href='http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer'>liability</a>,"; + ret += " <a href='http://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks'>trademark</a>,"; + ret += " <a href='http://www.w3.org/Consortium/Legal/copyright-documents'>document"; + ret += " use</a> rules apply."; + ret += " </p><hr title='Separator for header'>"; + ret += " </div>"; + ret += " <h2><a name='abstract'></a>Abstract</h2>"; + ret += " <p><em>Selectors</em> are patterns that match against elements in a"; + ret += " tree. Selectors have been optimized for use with HTML and XML, and"; + ret += " are designed to be usable in performance-critical code.</p>"; + ret += " <p><acronym title='Cascading Style Sheets'>CSS</acronym> (Cascading"; + ret += " Style Sheets) is a language for describing the rendering of <acronym title='Hypertext Markup Language'>HTML</acronym> and <acronym title='Extensible Markup Language'>XML</acronym> documents on"; + ret += " screen, on paper, in speech, etc. CSS uses Selectors for binding"; + ret += " describes extensions to the selectors defined in CSS level 2. These"; + ret += " extended selectors will be used by CSS level 3."; + ret += " </p><p>Selectors define the following function:</p>"; + ret += " <pre>expression ∗ element → boolean</pre>"; + ret += " <p>That is, given an element and a selector, this specification"; + ret += " defines whether that element matches the selector.</p>"; + ret += " <p>These expressions can also be used, for instance, to select a set"; + ret += " subtree. <acronym title='Simple Tree Transformation"; + ret += " Sheets'>STTS</acronym> (Simple Tree Transformation Sheets), a"; + ret += " language for transforming XML trees, uses this mechanism. <a href='#refsSTTS'>[STTS]</a></p>"; + ret += " <h2><a name='status'></a>Status of this document</h2>"; + ret += " <p><em>This section describes the status of this document at the"; + ret += " of this technical report can be found in the <a href='http://www.w3.org/TR/'>W3C technical reports index at"; + ret += " http://www.w3.org/TR/.</a></em></p>"; + ret += " <p>This document describes the selectors that already exist in <a href='#refsCSS1'><abbr title='CSS level 1'>CSS1</abbr></a> and <a href='#refsCSS21'><abbr title='CSS level 2'>CSS2</abbr></a>, and"; + ret += " also proposes new selectors for <abbr title='CSS level"; + ret += " 3'>CSS3</abbr> and other languages that may need them.</p>"; + ret += " <p>The CSS Working Group doesn't expect that all implementations of"; + ret += " CSS3 will have to implement all selectors. Instead, there will"; + ret += " will include all of the selectors.</p>"; + ret += " <p>This specification is a last call working draft for the the <a href='http://www.w3.org/Style/CSS/members'>CSS Working Group</a>"; + ret += " (<a href='/Style/'>Style Activity</a>). This"; + ret += " document is a revision of the <a href='http://www.w3.org/TR/2001/CR-css3-selectors-20011113/'>Candidate"; + ret += " Recommendation dated 2001 November 13</a>, and has incorporated"; + ret += " be demonstrable.</p>"; + ret += " <p>All persons are encouraged to review and implement this"; + ret += " specification and return comments to the (<a href='http://lists.w3.org/Archives/Public/www-style/'>archived</a>)"; + ret += " public mailing list <a href='http://www.w3.org/Mail/Lists.html#www-style'>www-style</a>"; + ret += " (see <a href='http://www.w3.org/Mail/Request'>instructions</a>). W3C"; + ret += " The deadline for comments is 14 January 2006.</p>"; + ret += " <p>This is still a draft document and may be updated, replaced, or"; + ret += " </p><p>This document may be available in <a href='http://www.w3.org/Style/css3-selectors-updates/translations'>translation</a>."; + ret += " </p><div class='subtoc'>"; + ret += " <h2><a name='contents'>Table of contents</a></h2>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline2'><a href='#context'>1. Introduction</a>"; + ret += " <ul>"; + ret += " <li><a href='#dependencies'>1.1. Dependencies</a></li>"; + ret += " <li><a href='#terminology'>1.2. Terminology</a></li>"; + ret += " <li><a href='#changesFromCSS2'>1.3. Changes from CSS2</a></li>"; + ret += " </ul>"; + ret += " </li><li class='tocline2'><a href='#selectors'>2. Selectors</a>"; + ret += " </li><li class='tocline2'><a href='#casesens'>3. Case sensitivity</a>"; + ret += " </li><li class='tocline2'><a href='#selector-syntax'>4. Selector syntax</a>"; + ret += " </li><li class='tocline2'><a href='#grouping'>5. Groups of selectors</a>"; + ret += " </li><li class='tocline2'><a href='#simple-selectors'>6. Simple selectors</a>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline3'><a href='#type-selectors'>6.1. Type"; + ret += " selectors</a>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline4'><a href='#typenmsp'>6.1.1. Type"; + ret += " selectors and namespaces</a></li>"; + ret += " </ul>"; + ret += " </li><li class='tocline3'><a href='#universal-selector'>6.2."; + ret += " Universal selector</a>"; + ret += " <ul>"; + ret += " <li><a href='#univnmsp'>6.2.1. Universal selector and"; + ret += " namespaces</a></li>"; + ret += " </ul>"; + ret += " </li><li class='tocline3'><a href='#attribute-selectors'>6.3."; + ret += " Attribute selectors</a>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline4'><a href='#attribute-representation'>6.3.1."; + ret += " values</a>"; + ret += " </li><li><a href='#attribute-substrings'>6.3.2. Substring"; + ret += " matching attribute selectors</a>"; + ret += " </li><li class='tocline4'><a href='#attrnmsp'>6.3.3."; + ret += " Attribute selectors and namespaces</a>"; + ret += " </li><li class='tocline4'><a href='#def-values'>6.3.4."; + ret += " Default attribute values in DTDs</a></li>"; + ret += " </ul>"; + ret += " </li><li class='tocline3'><a href='#class-html'>6.4. Class"; + ret += " selectors</a>"; + ret += " </li><li class='tocline3'><a href='#id-selectors'>6.5. ID"; + ret += " selectors</a>"; + ret += " </li><li class='tocline3'><a href='#pseudo-classes'>6.6."; + ret += " Pseudo-classes</a>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline4'><a href='#dynamic-pseudos'>6.6.1."; + ret += " Dynamic pseudo-classes</a>"; + ret += " </li><li class='tocline4'><a href='#target-pseudo'>6.6.2. The"; + ret += " :target pseudo-class</a>"; + ret += " </li><li class='tocline4'><a href='#lang-pseudo'>6.6.3. The"; + ret += " :lang() pseudo-class</a>"; + ret += " </li><li class='tocline4'><a href='#UIstates'>6.6.4. UI"; + ret += " element states pseudo-classes</a>"; + ret += " </li><li class='tocline4'><a href='#structural-pseudos'>6.6.5."; + ret += " Structural pseudo-classes</a>"; + ret += " <ul>"; + ret += " <li><a href='#root-pseudo'>:root"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#nth-child-pseudo'>:nth-child()"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#nth-last-child-pseudo'>:nth-last-child()</a>"; + ret += " </li><li><a href='#nth-of-type-pseudo'>:nth-of-type()"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#nth-last-of-type-pseudo'>:nth-last-of-type()</a>"; + ret += " </li><li><a href='#first-child-pseudo'>:first-child"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#last-child-pseudo'>:last-child"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#first-of-type-pseudo'>:first-of-type"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#last-of-type-pseudo'>:last-of-type"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#only-child-pseudo'>:only-child"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#only-of-type-pseudo'>:only-of-type"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#empty-pseudo'>:empty"; + ret += " pseudo-class</a></li>"; + ret += " </ul>"; + ret += " </li><li class='tocline4'><a href='#negation'>6.6.7. The"; + ret += " negation pseudo-class</a></li>"; + ret += " </ul>"; + ret += " </li>"; + ret += " </ul>"; + ret += " </li><li><a href='#pseudo-elements'>7. Pseudo-elements</a>"; + ret += " <ul>"; + ret += " <li><a href='#first-line'>7.1. The ::first-line"; + ret += " pseudo-element</a>"; + ret += " </li><li><a href='#first-letter'>7.2. The ::first-letter"; + ret += " pseudo-element</a>"; + ret += " </li><li><a href='#UIfragments'>7.3. The ::selection"; + ret += " pseudo-element</a>"; + ret += " </li><li><a href='#gen-content'>7.4. The ::before and ::after"; + ret += " pseudo-elements</a></li>"; + ret += " </ul>"; + ret += " </li><li class='tocline2'><a href='#combinators'>8. Combinators</a>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline3'><a href='#descendant-combinators'>8.1."; + ret += " Descendant combinators</a>"; + ret += " </li><li class='tocline3'><a href='#child-combinators'>8.2. Child"; + ret += " combinators</a>"; + ret += " </li><li class='tocline3'><a href='#sibling-combinators'>8.3. Sibling"; + ret += " combinators</a>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline4'><a href='#adjacent-sibling-combinators'>8.3.1."; + ret += " Adjacent sibling combinator</a>"; + ret += " </li><li class='tocline4'><a href='#general-sibling-combinators'>8.3.2."; + ret += " General sibling combinator</a></li>"; + ret += " </ul>"; + ret += " </li>"; + ret += " </ul>"; + ret += " </li><li class='tocline2'><a href='#specificity'>9. Calculating a selector's"; + ret += " specificity</a>"; + ret += " </li><li class='tocline2'><a href='#w3cselgrammar'>10. The grammar of"; + ret += " Selectors</a>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline3'><a href='#grammar'>10.1. Grammar</a>"; + ret += " </li><li class='tocline3'><a href='#lex'>10.2. Lexical scanner</a>"; + ret += " </li>"; + ret += " </ul>"; + ret += " </li><li class='tocline2'><a href='#downlevel'>11. Namespaces and down-level"; + ret += " clients</a>"; + ret += " </li><li class='tocline2'><a href='#profiling'>12. Profiles</a>"; + ret += " </li><li><a href='#Conformance'>13. Conformance and requirements</a>"; + ret += " </li><li><a href='#Tests'>14. Tests</a>"; + ret += " </li><li><a href='#ACKS'>15. Acknowledgements</a>"; + ret += " </li><li class='tocline2'><a href='#references'>16. References</a>"; + ret += " </li></ul>"; + ret += " </div>"; + ret += " <h2><a name='context'>1. Introduction</a></h2>"; + ret += " <h3><a name='dependencies'></a>1.1. Dependencies</h3>"; + ret += " <p>Some features of this specification are specific to CSS, or have"; + ret += " specification, these have been described in terms of CSS2.1. <a href='#refsCSS21'>[CSS21]</a></p>"; + ret += " <h3><a name='terminology'></a>1.2. Terminology</h3>"; + ret += " <p>All of the text of this specification is normative except"; + ret += " non-normative.</p>"; + ret += " <h3><a name='changesFromCSS2'></a>1.3. Changes from CSS2</h3>"; + ret += " <p><em>This section is non-normative.</em></p>"; + ret += " <p>The main differences between the selectors in CSS2 and those in"; + ret += " Selectors are:"; + ret += " </p><ul>"; + ret += " <li>the list of basic definitions (selector, group of selectors,"; + ret += " of simple selectors, and the term 'simple selector' is now used for"; + ret += " </li>"; + ret += " <li>an optional namespace component is now allowed in type element"; + ret += " selectors, the universal selector and attribute selectors"; + ret += " </li>"; + ret += " <li>a <a href='#general-sibling-combinators'>new combinator</a> has been"; + ret += " </li>"; + ret += " <li>new simple selectors including substring matching attribute"; + ret += " selectors, and new pseudo-classes"; + ret += " </li>"; + ret += " <li>new pseudo-elements, and introduction of the '::' convention"; + ret += " </li>"; + ret += " <li>the grammar has been rewritten</li>"; + ret += " <li>profiles to be added to specifications integrating Selectors"; + ret += " and defining the set of selectors which is actually supported by"; + ret += " </li>"; + ret += " <li>Selectors are now a CSS3 Module and an independent"; + ret += " </li>"; + ret += " <li>the specification now has its own test suite</li>"; + ret += " </ul>"; + ret += " <h2><a name='selectors'></a>2. Selectors</h2>"; + ret += " <p><em>This section is non-normative, as it merely summarizes the"; + ret += " following sections.</em></p>"; + ret += " <p>A Selector represents a structure. This structure can be used as a"; + ret += " HTML or XML fragment corresponding to that structure.</p>"; + ret += " <p>Selectors may range from simple element names to rich contextual"; + ret += " representations.</p>"; + ret += " <p>The following table summarizes the Selector syntax:</p>"; + ret += " <table class='selectorsReview'>"; + ret += " <thead>"; + ret += " <tr>"; + ret += " <th class='pattern'>Pattern</th>"; + ret += " <th class='meaning'>Meaning</th>"; + ret += " <th class='described'>Described in section</th>"; + ret += " <th class='origin'>First defined in CSS level</th>"; + ret += " </tr>"; + ret += " </thead><tbody>"; + ret += " <tr>"; + ret += " <td class='pattern'>*</td>"; + ret += " <td class='meaning'>any element</td>"; + ret += " <td class='described'><a href='#universal-selector'>Universal"; + ret += " selector</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E</td>"; + ret += " <td class='meaning'>an element of type E</td>"; + ret += " <td class='described'><a href='#type-selectors'>Type selector</a></td>"; + ret += " <td class='origin'>1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E[foo]</td>"; + ret += " <td class='meaning'>an E element with a 'foo' attribute</td>"; + ret += " <td class='described'><a href='#attribute-selectors'>Attribute"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E[foo='bar']</td>"; + ret += " <td class='meaning'>an E element whose 'foo' attribute value is exactly"; + ret += " </td>"; + ret += " <td class='described'><a href='#attribute-selectors'>Attribute"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E[foo~='bar']</td>"; + ret += " <td class='meaning'>an E element whose 'foo' attribute value is a list of"; + ret += " </td>"; + ret += " <td class='described'><a href='#attribute-selectors'>Attribute"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E[foo^='bar']</td>"; + ret += " <td class='meaning'>an E element whose 'foo' attribute value begins exactly"; + ret += " </td>"; + ret += " <td class='described'><a href='#attribute-selectors'>Attribute"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E[foo$='bar']</td>"; + ret += " <td class='meaning'>an E element whose 'foo' attribute value ends exactly"; + ret += " </td>"; + ret += " <td class='described'><a href='#attribute-selectors'>Attribute"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E[foo*='bar']</td>"; + ret += " <td class='meaning'>an E element whose 'foo' attribute value contains the"; + ret += " </td>"; + ret += " <td class='described'><a href='#attribute-selectors'>Attribute"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E[hreflang|='en']</td>"; + ret += " <td class='meaning'>an E element whose 'hreflang' attribute has a"; + ret += " </td>"; + ret += " <td class='described'><a href='#attribute-selectors'>Attribute"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:root</td>"; + ret += " <td class='meaning'>an E element, root of the document</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:nth-child(n)</td>"; + ret += " <td class='meaning'>an E element, the n-th child of its parent</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:nth-last-child(n)</td>"; + ret += " <td class='meaning'>an E element, the n-th child of its parent, counting"; + ret += " </td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:nth-of-type(n)</td>"; + ret += " <td class='meaning'>an E element, the n-th sibling of its type</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:nth-last-of-type(n)</td>"; + ret += " <td class='meaning'>an E element, the n-th sibling of its type, counting"; + ret += " </td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:first-child</td>"; + ret += " <td class='meaning'>an E element, first child of its parent</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:last-child</td>"; + ret += " <td class='meaning'>an E element, last child of its parent</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:first-of-type</td>"; + ret += " <td class='meaning'>an E element, first sibling of its type</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:last-of-type</td>"; + ret += " <td class='meaning'>an E element, last sibling of its type</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:only-child</td>"; + ret += " <td class='meaning'>an E element, only child of its parent</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:only-of-type</td>"; + ret += " <td class='meaning'>an E element, only sibling of its type</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:empty</td>"; + ret += " <td class='meaning'>an E element that has no children (including text"; + ret += " </td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:link<br>E:visited</td>"; + ret += " <td class='meaning'>an E element being the source anchor of a hyperlink of"; + ret += " </td>"; + ret += " <td class='described'><a href='#link'>The link"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:active<br>E:hover<br>E:focus</td>"; + ret += " <td class='meaning'>an E element during certain user actions</td>"; + ret += " <td class='described'><a href='#useraction-pseudos'>The user"; + ret += " action pseudo-classes</a></td>"; + ret += " <td class='origin'>1 and 2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:target</td>"; + ret += " <td class='meaning'>an E element being the target of the referring URI</td>"; + ret += " <td class='described'><a href='#target-pseudo'>The target"; + ret += " pseudo-class</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:lang(fr)</td>"; + ret += " <td class='meaning'>an element of type E in language 'fr' (the document"; + ret += " </td>"; + ret += " <td class='described'><a href='#lang-pseudo'>The :lang()"; + ret += " pseudo-class</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:enabled<br>E:disabled</td>"; + ret += " <td class='meaning'>a user interface element E which is enabled or"; + ret += " </td>"; + ret += " <td class='described'><a href='#UIstates'>The UI element states"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:checked<!--<br>E:indeterminate--></td>"; + ret += " <td class='meaning'>a user interface element E which is checked<!-- or in an"; + ret += " indeterminate state--> (for instance a radio-button or checkbox)"; + ret += " </td>"; + ret += " <td class='described'><a href='#UIstates'>The UI element states"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E::first-line</td>"; + ret += " <td class='meaning'>the first formatted line of an E element</td>"; + ret += " <td class='described'><a href='#first-line'>The ::first-line"; + ret += " pseudo-element</a></td>"; + ret += " <td class='origin'>1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E::first-letter</td>"; + ret += " <td class='meaning'>the first formatted letter of an E element</td>"; + ret += " <td class='described'><a href='#first-letter'>The ::first-letter"; + ret += " pseudo-element</a></td>"; + ret += " <td class='origin'>1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E::selection</td>"; + ret += " <td class='meaning'>the portion of an E element that is currently"; + ret += " </td>"; + ret += " <td class='described'><a href='#UIfragments'>The UI element"; + ret += " fragments pseudo-elements</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E::before</td>"; + ret += " <td class='meaning'>generated content before an E element</td>"; + ret += " <td class='described'><a href='#gen-content'>The ::before"; + ret += " pseudo-element</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E::after</td>"; + ret += " <td class='meaning'>generated content after an E element</td>"; + ret += " <td class='described'><a href='#gen-content'>The ::after"; + ret += " pseudo-element</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E.warning</td>"; + ret += " <td class='meaning'>an E element whose class is"; + ret += " </td>"; + ret += " <td class='described'><a href='#class-html'>Class"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E#myid</td>"; + ret += " <td class='meaning'>an E element with ID equal to 'myid'.</td>"; + ret += " <td class='described'><a href='#id-selectors'>ID"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:not(s)</td>"; + ret += " <td class='meaning'>an E element that does not match simple selector s</td>"; + ret += " <td class='described'><a href='#negation'>Negation"; + ret += " pseudo-class</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E F</td>"; + ret += " <td class='meaning'>an F element descendant of an E element</td>"; + ret += " <td class='described'><a href='#descendant-combinators'>Descendant"; + ret += " combinator</a></td>"; + ret += " <td class='origin'>1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E > F</td>"; + ret += " <td class='meaning'>an F element child of an E element</td>"; + ret += " <td class='described'><a href='#child-combinators'>Child"; + ret += " combinator</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E + F</td>"; + ret += " <td class='meaning'>an F element immediately preceded by an E element</td>"; + ret += " <td class='described'><a href='#adjacent-sibling-combinators'>Adjacent sibling combinator</a>"; + ret += " </td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E ~ F</td>"; + ret += " <td class='meaning'>an F element preceded by an E element</td>"; + ret += " <td class='described'><a href='#general-sibling-combinators'>General sibling combinator</a>"; + ret += " </td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " </tbody>"; + ret += " </table>"; + ret += " <p>The meaning of each selector is derived from the table above by"; + ret += " column.</p>"; + ret += " <h2><a name='casesens'>3. Case sensitivity</a></h2>"; + ret += " <p>The case sensitivity of document language element names, attribute"; + ret += " names, and attribute values in selectors depends on the document"; + ret += " but in XML, they are case-sensitive.</p>"; + ret += " <h2><a name='selector-syntax'>4. Selector syntax</a></h2>"; + ret += " <p>A <dfn><a name='selector'>selector</a></dfn> is a chain of one"; + ret += " or more <a href='#sequence'>sequences of simple selectors</a>"; + ret += " separated by <a href='#combinators'>combinators</a>.</p>"; + ret += " <p>A <dfn><a name='sequence'>sequence of simple selectors</a></dfn>"; + ret += " is a chain of <a href='#simple-selectors-dfn'>simple selectors</a>"; + ret += " that are not separated by a <a href='#combinators'>combinator</a>. It"; + ret += " always begins with a <a href='#type-selectors'>type selector</a> or a"; + ret += " <a href='#universal-selector'>universal selector</a>. No other type"; + ret += " selector or universal selector is allowed in the sequence.</p>"; + ret += " <p>A <dfn><a name='simple-selectors-dfn'></a><a href='#simple-selectors'>simple selector</a></dfn> is either a <a href='#type-selectors'>type selector</a>, <a href='#universal-selector'>universal selector</a>, <a href='#attribute-selectors'>attribute selector</a>, <a href='#class-html'>class selector</a>, <a href='#id-selectors'>ID selector</a>, <a href='#content-selectors'>content selector</a>, or <a href='#pseudo-classes'>pseudo-class</a>. One <a href='#pseudo-elements'>pseudo-element</a> may be appended to the last"; + ret += " sequence of simple selectors.</p>"; + ret += " <p><dfn>Combinators</dfn> are: white space, 'greater-than"; + ret += " sign' (U+003E, <code>></code>), 'plus sign' (U+002B,"; + ret += " <code>+</code>) and 'tilde' (U+007E, <code>~</code>). White"; + ret += " space may appear between a combinator and the simple selectors around"; + ret += " it. <a name='whitespace'></a>Only the characters 'space' (U+0020), 'tab'"; + ret += " never part of white space.</p>"; + ret += " <p>The elements of a document tree that are represented by a selector"; + ret += " are the <dfn><a name='subject'></a>subjects of the selector</dfn>. A"; + ret += " selector consisting of a single sequence of simple selectors"; + ret += " sequence of simple selectors and a combinator to a sequence imposes"; + ret += " simple selectors.</p>"; + ret += " <p>An empty selector, containing no sequence of simple selectors and"; + ret += " no pseudo-element, is an <a href='#Conformance'>invalid"; + ret += " selector</a>.</p>"; + ret += " <h2><a name='grouping'>5. Groups of selectors</a></h2>"; + ret += " <p>When several selectors share the same declarations, they may be"; + ret += " grouped into a comma-separated list. (A comma is U+002C.)</p>"; + ret += " <div class='example'>"; + ret += " <p>CSS examples:</p>"; + ret += " <p>In this example, we condense three rules with identical"; + ret += " declarations into one. Thus,</p>"; + ret += " <pre>h1 { font-family: sans-serif }"; + ret += " h3 { font-family: sans-serif }</pre>"; + ret += " <p>is equivalent to:</p>"; + ret += " <pre>h1, h2, h3 { font-family: sans-serif }</pre>"; + ret += " </div>"; + ret += " <p><strong>Warning</strong>: the equivalence is true in this example"; + ret += " because all the selectors are valid selectors. If just one of these"; + ret += " selectors were invalid, the entire group of selectors would be"; + ret += " heading rules would be invalidated.</p>"; + ret += " <h2><a name='simple-selectors'>6. Simple selectors</a></h2>"; + ret += " <h3><a name='type-selectors'>6.1. Type selector</a></h3>"; + ret += " <p>A <dfn>type selector</dfn> is the name of a document language"; + ret += " type in the document tree.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>The following selector represents an <code>h1</code> element in the"; + ret += " document tree:</p>"; + ret += " <pre>h1</pre>"; + ret += " </div>"; + ret += " <h4><a name='typenmsp'>6.1.1. Type selectors and namespaces</a></h4>"; + ret += " <p>Type selectors allow an optional namespace (<a href='#refsXMLNAMES'>[XMLNAMES]</a>) component. A namespace prefix"; + ret += " (U+007C, <code>|</code>).</p>"; + ret += " <p>The namespace component may be left empty to indicate that the"; + ret += " selector is only to represent elements with no declared namespace.</p>"; + ret += " <p>An asterisk may be used for the namespace prefix, indicating that"; + ret += " with no namespace).</p>"; + ret += " <p>Element type selectors that have no namespace component (no"; + ret += " element's namespace (equivalent to '<code>*|</code>') unless a default"; + ret += " namespace.</p>"; + ret += " <p>A type selector containing a namespace prefix that has not been"; + ret += " previously declared is an <a href='#Conformance'>invalid</a> selector."; + ret += " language implementing Selectors. In CSS, such a mechanism is defined"; + ret += " in the General Syntax module.</p>"; + ret += " <p>In a namespace-aware client, element type selectors will only match"; + ret += " against the <a href='http://www.w3.org/TR/REC-xml-names/#NT-LocalPart'>local"; + ret += " part</a>"; + ret += " of the element's <a href='http://www.w3.org/TR/REC-xml-names/#ns-qualnames'>qualified"; + ret += " name</a>. See <a href='#downlevel'>below</a> for notes about matching"; + ret += " behaviors in down-level clients.</p>"; + ret += " <p>In summary:</p>"; + ret += " <dl>"; + ret += " <dt><code>ns|E</code></dt>"; + ret += " <dd>elements with name E in namespace ns</dd>"; + ret += " <dt><code>*|E</code></dt>"; + ret += " <dd>elements with name E in any namespace, including those without any"; + ret += " </dd>"; + ret += " <dt><code>|E</code></dt>"; + ret += " <dd>elements with name E without any declared namespace</dd>"; + ret += " <dt><code>E</code></dt>"; + ret += " <dd>if no default namespace has been specified, this is equivalent to *|E."; + ret += " </dd>"; + ret += " </dl>"; + ret += " <div class='example'>"; + ret += " <p>CSS examples:</p>"; + ret += " <pre>@namespace foo url(http://www.example.com);"; + ret += " h1 { color: green }</pre>"; + ret += " <p>The first rule will match only <code>h1</code> elements in the"; + ret += " 'http://www.example.com' namespace.</p>"; + ret += " <p>The second rule will match all elements in the"; + ret += " 'http://www.example.com' namespace.</p>"; + ret += " <p>The third rule will match only <code>h1</code> elements without"; + ret += " any declared namespace.</p>"; + ret += " <p>The fourth rule will match <code>h1</code> elements in any"; + ret += " namespace (including those without any declared namespace).</p>"; + ret += " <p>The last rule is equivalent to the fourth rule because no default"; + ret += " namespace has been defined.</p>"; + ret += " </div>"; + ret += " <h3><a name='universal-selector'>6.2. Universal selector</a></h3>"; + ret += " <p>The <dfn>universal selector</dfn>, written 'asterisk'"; + ret += " (<code>*</code>), represents the qualified name of any element"; + ret += " specified, see <a href='#univnmsp'>Universal selector and"; + ret += " Namespaces</a> below.</p>"; + ret += " <p>If the universal selector is not the only component of a sequence"; + ret += " of simple selectors, the <code>*</code> may be omitted.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <ul>"; + ret += " <li><code>*[hreflang|=en]</code> and <code>[hreflang|=en]</code> are"; + ret += " </li>"; + ret += " <li><code>*.warning</code> and <code>.warning</code> are equivalent,"; + ret += " </li>"; + ret += " <li><code>*#myid</code> and <code>#myid</code> are equivalent.</li>"; + ret += " </ul>"; + ret += " </div>"; + ret += " <p class='note'><strong>Note:</strong> it is recommended that the"; + ret += " <code>*</code>, representing the universal selector, not be"; + ret += " omitted.</p>"; + ret += " <h4><a name='univnmsp'>6.2.1. Universal selector and namespaces</a></h4>"; + ret += " <p>The universal selector allows an optional namespace component. It"; + ret += " is used as follows:</p>"; + ret += " <dl>"; + ret += " <dt><code>ns|*</code></dt>"; + ret += " <dd>all elements in namespace ns</dd>"; + ret += " <dt><code>*|*</code></dt>"; + ret += " <dd>all elements</dd>"; + ret += " <dt><code>|*</code></dt>"; + ret += " <dd>all elements without any declared namespace</dd>"; + ret += " <dt><code>*</code></dt>"; + ret += " <dd>if no default namespace has been specified, this is equivalent to *|*."; + ret += " </dd>"; + ret += " </dl>"; + ret += " <p>A universal selector containing a namespace prefix that has not"; + ret += " been previously declared is an <a href='#Conformance'>invalid</a>"; + ret += " to the language implementing Selectors. In CSS, such a mechanism is"; + ret += " defined in the General Syntax module.</p>"; + ret += " <h3><a name='attribute-selectors'>6.3. Attribute selectors</a></h3>"; + ret += " <p>Selectors allow the representation of an element's attributes. When"; + ret += " attribute selectors must be considered to match an element if that"; + ret += " attribute selector.</p>"; + ret += " <h4><a name='attribute-representation'>6.3.1. Attribute presence and values"; + ret += " selectors</a></h4>"; + ret += " <p>CSS2 introduced four attribute selectors:</p>"; + ret += " <dl>"; + ret += " <dt><code>[att]</code>"; + ret += " </dt><dd>Represents an element with the <code>att</code> attribute, whatever the"; + ret += " </dd>"; + ret += " <dt><code>[att=val]</code></dt>"; + ret += " <dd>Represents an element with the <code>att</code> attribute whose value is"; + ret += " </dd>"; + ret += " <dt><code>[att~=val]</code></dt>"; + ret += " <dd>Represents an element with the <code>att</code> attribute whose value is"; + ret += " a <a href='#whitespace'>whitespace</a>-separated list of words, one"; + ret += " represent anything (since the words are <em>separated</em> by"; + ret += " </dd>"; + ret += " <dt><code>[att|=val]</code>"; + ret += " </dt><dd>Represents an element with the <code>att</code> attribute, its value"; + ret += " matches (e.g., the <code>hreflang</code> attribute on the"; + ret += " <code>link</code> element in HTML) as described in RFC 3066 (<a href='#refsRFC3066'>[RFC3066]</a>). For <code>lang</code> (or"; + ret += " <code>xml:lang</code>) language subcode matching, please see <a href='#lang-pseudo'>the <code>:lang</code> pseudo-class</a>."; + ret += " </dd>"; + ret += " </dl>"; + ret += " <p>Attribute values must be identifiers or strings. The"; + ret += " case-sensitivity of attribute names and values in selectors depends on"; + ret += " the document language.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following attribute selector represents an <code>h1</code>"; + ret += " element that carries the <code>title</code> attribute, whatever its"; + ret += " value:</p>"; + ret += " <pre>h1[title]</pre>"; + ret += " <p>In the following example, the selector represents a"; + ret += " <code>span</code> element whose <code>class</code> attribute has"; + ret += " exactly the value 'example':</p>"; + ret += " <pre>span[class='example']</pre>"; + ret += " <p>Multiple attribute selectors can be used to represent several"; + ret += " attribute. Here, the selector represents a <code>span</code> element"; + ret += " whose <code>hello</code> attribute has exactly the value 'Cleveland'"; + ret += " and whose <code>goodbye</code> attribute has exactly the value"; + ret += " 'Columbus':</p>"; + ret += " <pre>span[hello='Cleveland'][goodbye='Columbus']</pre>"; + ret += " <p>The following selectors illustrate the differences between '='"; + ret += " 'copyright copyleft copyeditor' on a <code>rel</code> attribute. The"; + ret += " second selector will only represent an <code>a</code> element with"; + ret += " an <code>href</code> attribute having the exact value"; + ret += " 'http://www.w3.org/'.</p>"; + ret += " <pre>a[rel~='copyright']"; + ret += " a[href='http://www.w3.org/']</pre>"; + ret += " <p>The following selector represents a <code>link</code> element"; + ret += " whose <code>hreflang</code> attribute is exactly 'fr'.</p>"; + ret += " <pre>link[hreflang=fr]</pre>"; + ret += " <p>The following selector represents a <code>link</code> element for"; + ret += " which the values of the <code>hreflang</code> attribute begins with"; + ret += " 'en', including 'en', 'en-US', and 'en-cockney':</p>"; + ret += " <pre>link[hreflang|='en']</pre>"; + ret += " <p>Similarly, the following selectors represents a"; + ret += " <code>DIALOGUE</code> element whenever it has one of two different"; + ret += " values for an attribute <code>character</code>:</p>"; + ret += " <pre>DIALOGUE[character=romeo]"; + ret += " DIALOGUE[character=juliet]</pre>"; + ret += " </div>"; + ret += " <h4><a name='attribute-substrings'></a>6.3.2. Substring matching attribute"; + ret += " selectors</h4>"; + ret += " <p>Three additional attribute selectors are provided for matching"; + ret += " substrings in the value of an attribute:</p>"; + ret += " <dl>"; + ret += " <dt><code>[att^=val]</code></dt>"; + ret += " <dd>Represents an element with the <code>att</code> attribute whose value"; + ret += " </dd>"; + ret += " <dt><code>[att$=val]</code>"; + ret += " </dt><dd>Represents an element with the <code>att</code> attribute whose value"; + ret += " </dd>"; + ret += " <dt><code>[att*=val]</code>"; + ret += " </dt><dd>Represents an element with the <code>att</code> attribute whose value"; + ret += " </dd>"; + ret += " </dl>"; + ret += " <p>Attribute values must be identifiers or strings. The"; + ret += " case-sensitivity of attribute names in selectors depends on the"; + ret += " document language.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following selector represents an HTML <code>object</code>,"; + ret += " image:</p>"; + ret += " <pre>object[type^='image/']</pre>"; + ret += " <p>The following selector represents an HTML anchor <code>a</code> with an"; + ret += " <code>href</code> attribute whose value ends with '.html'.</p>"; + ret += " <pre>a[href$='.html']</pre>"; + ret += " <p>The following selector represents an HTML paragraph with a"; + ret += " <code>title</code>"; + ret += " attribute whose value contains the substring 'hello'</p>"; + ret += " <pre>p[title*='hello']</pre>"; + ret += " </div>"; + ret += " <h4><a name='attrnmsp'>6.3.3. Attribute selectors and namespaces</a></h4>"; + ret += " <p>Attribute selectors allow an optional namespace component to the"; + ret += " separator 'vertical bar' (<code>|</code>). In keeping with"; + ret += " apply to attributes, therefore attribute selectors without a namespace"; + ret += " (equivalent to '<code>|attr</code>'). An asterisk may be used for the"; + ret += " </p><p>An attribute selector with an attribute name containing a namespace"; + ret += " prefix that has not been previously declared is an <a href='#Conformance'>invalid</a> selector. The mechanism for"; + ret += " a namespace prefix is left up to the language implementing Selectors."; + ret += " </p><div class='example'>"; + ret += " <p>CSS examples:</p>"; + ret += " <pre>@namespace foo 'http://www.example.com';"; + ret += " [att] { color: green }</pre>"; + ret += " <p>The first rule will match only elements with the attribute"; + ret += " <code>att</code> in the 'http://www.example.com' namespace with the"; + ret += " value 'val'.</p>"; + ret += " <p>The second rule will match only elements with the attribute"; + ret += " <code>att</code> regardless of the namespace of the attribute"; + ret += " (including no declared namespace).</p>"; + ret += " <p>The last two rules are equivalent and will match only elements"; + ret += " with the attribute <code>att</code> where the attribute is not"; + ret += " declared to be in a namespace.</p>"; + ret += " </div>"; + ret += " <h4><a name='def-values'>6.3.4. Default attribute values in DTDs</a></h4>"; + ret += " <p>Attribute selectors represent explicitly set attribute values in"; + ret += " selectors. Selectors should be designed so that they work even if the"; + ret += " default values are not included in the document tree.</p>"; + ret += " <p>More precisely, a UA is <em>not</em> required to read an 'external"; + ret += " subset' of the DTD but <em>is</em> required to look for default"; + ret += " attribute values in the document's 'internal subset.' (See <a href='#refsXML10'>[XML10]</a> for definitions of these subsets.)</p>"; + ret += " <p>A UA that recognizes an XML namespace <a href='#refsXMLNAMES'>[XMLNAMES]</a> is not required to use its"; + ret += " required to use its built-in knowledge of the XHTML DTD.)</p>"; + ret += " <p class='note'><strong>Note:</strong> Typically, implementations"; + ret += " choose to ignore external subsets.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>Consider an element EXAMPLE with an attribute 'notation' that has a"; + ret += " default value of 'decimal'. The DTD fragment might be</p>"; + ret += " <pre class='dtd-example'><!ATTLIST EXAMPLE notation (decimal,octal) 'decimal'></pre>"; + ret += " <p>If the style sheet contains the rules</p>"; + ret += " <pre>EXAMPLE[notation=decimal] { /*... default property settings ...*/ }"; + ret += " EXAMPLE[notation=octal] { /*... other settings...*/ }</pre>"; + ret += " <p>the first rule will not match elements whose 'notation' attribute"; + ret += " attribute selector for the default value must be dropped:</p>"; + ret += " <pre>EXAMPLE { /*... default property settings ...*/ }"; + ret += " EXAMPLE[notation=octal] { /*... other settings...*/ }</pre>"; + ret += " <p>Here, because the selector <code>EXAMPLE[notation=octal]</code> is"; + ret += " cases' style rules.</p>"; + ret += " </div>"; + ret += " <h3><a name='class-html'>6.4. Class selectors</a></h3>"; + ret += " <p>Working with HTML, authors may use the period (U+002E,"; + ret += " <code>.</code>) notation as an alternative to the <code>~=</code>"; + ret += " notation when representing the <code>class</code> attribute. Thus, for"; + ret += " HTML, <code>div.value</code> and <code>div[class~=value]</code> have"; + ret += " 'period' (<code>.</code>).</p>"; + ret += " <p>UAs may apply selectors using the period (.) notation in XML"; + ret += " 1.0 <a href='#refsSVG'>[SVG]</a> describes the <a href='http://www.w3.org/TR/2001/PR-SVG-20010719/styling.html#ClassAttribute'>SVG"; + ret += " 'class' attribute</a> and how a UA should interpret it, and"; + ret += " similarly MathML 1.01 <a href='#refsMATH'>[MATH]</a> describes the <a href='http://www.w3.org/1999/07/REC-MathML-19990707/chapter2.html#sec2.3.4'>MathML"; + ret += " 'class' attribute</a>.)</p>"; + ret += " <div class='example'>"; + ret += " <p>CSS examples:</p>"; + ret += " <p>We can assign style information to all elements with"; + ret += " <code>class~='pastoral'</code> as follows:</p>"; + ret += " <pre>*.pastoral { color: green } /* all elements with class~=pastoral */</pre>"; + ret += " <p>or just</p>"; + ret += " <pre>.pastoral { color: green } /* all elements with class~=pastoral */</pre>"; + ret += " <p>The following assigns style only to H1 elements with"; + ret += " <code>class~='pastoral'</code>:</p>"; + ret += " <pre>H1.pastoral { color: green } /* H1 elements with class~=pastoral */</pre>"; + ret += " <p>Given these rules, the first H1 instance below would not have"; + ret += " green text, while the second would:</p>"; + ret += " <pre><H1>Not green</H1>"; + ret += " <H1 class='pastoral'>Very green</H1></pre>"; + ret += " </div>"; + ret += " <p>To represent a subset of 'class' values, each value must be preceded"; + ret += " by a '.', in any order.</p>"; + ret += " <div class='example'>"; + ret += " <p>CSS example:</p>"; + ret += " <p>The following rule matches any P element whose 'class' attribute"; + ret += " has been assigned a list of <a href='#whitespace'>whitespace</a>-separated values that includes"; + ret += " 'pastoral' and 'marine':</p>"; + ret += " <pre>p.pastoral.marine { color: green }</pre>"; + ret += " <p>This rule matches when <code>class='pastoral blue aqua"; + ret += " marine'</code> but does not match for <code>class='pastoral"; + ret += " blue'</code>.</p>"; + ret += " </div>"; + ret += " <p class='note'><strong>Note:</strong> Because CSS gives considerable"; + ret += " not.</p>"; + ret += " <p class='note'><strong>Note:</strong> If an element has multiple"; + ret += " this specification.</p>"; + ret += " <h3><a name='id-selectors'>6.5. ID selectors</a></h3>"; + ret += " <p>Document languages may contain attributes that are declared to be"; + ret += " applies.</p>"; + ret += " <p>An ID-typed attribute of a document language allows authors to"; + ret += " ID selectors represent an element instance based on its identifier. An"; + ret += " <code>#</code>) immediately followed by the ID value, which must be an"; + ret += " identifier.</p>"; + ret += " <p>Selectors does not specify how a UA knows the ID-typed attribute of"; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following ID selector represents an <code>h1</code> element"; + ret += " whose ID-typed attribute has the value 'chapter1':</p>"; + ret += " <pre>h1#chapter1</pre>"; + ret += " <p>The following ID selector represents any element whose ID-typed"; + ret += " attribute has the value 'chapter1':</p>"; + ret += " <pre>#chapter1</pre>"; + ret += " <p>The following selector represents any element whose ID-typed"; + ret += " attribute has the value 'z98y'.</p>"; + ret += " <pre>*#z98y</pre>"; + ret += " </div>"; + ret += " <p class='note'><strong>Note.</strong> In XML 1.0 <a href='#refsXML10'>[XML10]</a>, the information about which attribute"; + ret += " should use normal attribute selectors instead:"; + ret += " <code>[name=p371]</code> instead of <code>#p371</code>. Elements in"; + ret += " XML 1.0 documents without a DTD do not have IDs at all.</p>"; + ret += " <p>If an element has multiple ID attributes, all of them must be"; + ret += " DOM3 Core, XML DTDs, and namespace-specific knowledge.</p>"; + ret += " <h3><a name='pseudo-classes'>6.6. Pseudo-classes</a></h3>"; + ret += " <p>The pseudo-class concept is introduced to permit selection based on"; + ret += " expressed using the other simple selectors.</p>"; + ret += " <p>A pseudo-class always consists of a 'colon'"; + ret += " (<code>:</code>) followed by the name of the pseudo-class and"; + ret += " optionally by a value between parentheses.</p>"; + ret += " <p>Pseudo-classes are allowed in all sequences of simple selectors"; + ret += " sequences of simple selectors, after the leading type selector or"; + ret += " document.</p>"; + ret += " <h4><a name='dynamic-pseudos'>6.6.1. Dynamic pseudo-classes</a></h4>"; + ret += " <p>Dynamic pseudo-classes classify elements on characteristics other"; + ret += " that cannot be deduced from the document tree.</p>"; + ret += " <p>Dynamic pseudo-classes do not appear in the document source or"; + ret += " document tree.</p>"; + ret += " <h5>The <a name='link'>link pseudo-classes: :link and :visited</a></h5>"; + ret += " <p>User agents commonly display unvisited links differently from"; + ret += " previously visited ones. Selectors"; + ret += " provides the pseudo-classes <code>:link</code> and"; + ret += " <code>:visited</code> to distinguish them:</p>"; + ret += " <ul>"; + ret += " <li>The <code>:link</code> pseudo-class applies to links that have"; + ret += " </li>"; + ret += " <li>The <code>:visited</code> pseudo-class applies once the link has"; + ret += " </li>"; + ret += " </ul>"; + ret += " <p>After some amount of time, user agents may choose to return a"; + ret += " visited link to the (unvisited) ':link' state.</p>"; + ret += " <p>The two states are mutually exclusive.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>The following selector represents links carrying class"; + ret += " <code>external</code> and already visited:</p>"; + ret += " <pre>a.external:visited</pre>"; + ret += " </div>"; + ret += " <p class='note'><strong>Note:</strong> It is possible for style sheet"; + ret += " </p><p>UAs may therefore treat all links as unvisited links, or implement"; + ret += " and unvisited links differently.</p>"; + ret += " <h5>The <a name='useraction-pseudos'>user action pseudo-classes"; + ret += " :hover, :active, and :focus</a></h5>"; + ret += " <p>Interactive user agents sometimes change the rendering in response"; + ret += " to user actions. Selectors provides"; + ret += " acting on.</p>"; + ret += " <ul>"; + ret += " <li>The <code>:hover</code> pseudo-class applies while the user"; + ret += " element. User agents not that do not support <a href='http://www.w3.org/TR/REC-CSS2/media.html#interactive-media-group'>interactive"; + ret += " media</a> do not have to support this pseudo-class. Some conforming"; + ret += " user agents that support <a href='http://www.w3.org/TR/REC-CSS2/media.html#interactive-media-group'>interactive"; + ret += " media</a> may not be able to support this pseudo-class (e.g., a pen"; + ret += " </li>"; + ret += " <li>The <code>:active</code> pseudo-class applies while an element"; + ret += " </li>"; + ret += " <li>The <code>:focus</code> pseudo-class applies while an element"; + ret += " </li>"; + ret += " </ul>"; + ret += " <p>There may be document language or implementation specific limits on"; + ret += " which elements can become <code>:active</code> or acquire"; + ret += " <code>:focus</code>.</p>"; + ret += " <p>These pseudo-classes are not mutually exclusive. An element may"; + ret += " match several pseudo-classes at the same time.</p>"; + ret += " <p>Selectors doesn't define if the parent of an element that is"; + ret += " ':active' or ':hover' is also in that state.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <pre>a:link /* unvisited links */"; + ret += " a:active /* active links */</pre>"; + ret += " <p>An example of combining dynamic pseudo-classes:</p>"; + ret += " <pre>a:focus"; + ret += " a:focus:hover</pre>"; + ret += " <p>The last selector matches <code>a</code> elements that are in"; + ret += " the pseudo-class :focus and in the pseudo-class :hover.</p>"; + ret += " </div>"; + ret += " <p class='note'><strong>Note:</strong> An element can be both ':visited'"; + ret += " and ':active' (or ':link' and ':active').</p>"; + ret += " <h4><a name='target-pseudo'>6.6.2. The target pseudo-class :target</a></h4>"; + ret += " <p>Some URIs refer to a location within a resource. This kind of URI"; + ret += " identifier (called the fragment identifier).</p>"; + ret += " <p>URIs with fragment identifiers link to a certain element within the"; + ret += " pointing to an anchor named <code>section_2</code> in an HTML"; + ret += " document:</p>"; + ret += " <pre>http://example.com/html/top.html#section_2</pre>"; + ret += " <p>A target element can be represented by the <code>:target</code>"; + ret += " the document has no target element.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <pre>p.note:target</pre>"; + ret += " <p>This selector represents a <code>p</code> element of class"; + ret += " <code>note</code> that is the target element of the referring"; + ret += " URI.</p>"; + ret += " </div>"; + ret += " <div class='example'>"; + ret += " <p>CSS example:</p>"; + ret += " <p>Here, the <code>:target</code> pseudo-class is used to make the"; + ret += " target element red and place an image before it, if there is one:</p>"; + ret += " <pre>*:target { color : red }"; + ret += " *:target::before { content : url(target.png) }</pre>"; + ret += " </div>"; + ret += " <h4><a name='lang-pseudo'>6.6.3. The language pseudo-class :lang</a></h4>"; + ret += " <p>If the document language specifies how the human language of an"; + ret += " element is determined, it is possible to write selectors that"; + ret += " represent an element based on its language. For example, in HTML <a href='#refsHTML4'>[HTML4]</a>, the language is determined by a"; + ret += " combination of the <code>lang</code> attribute, the <code>meta</code>"; + ret += " headers). XML uses an attribute called <code>xml:lang</code>, and"; + ret += " the language.</p>"; + ret += " <p>The pseudo-class <code>:lang(C)</code> represents an element that"; + ret += " <code>:lang()</code> selector is based solely on the identifier C"; + ret += " element's language value, in the same way as if performed by the <a href='#attribute-representation'>'|='</a> operator in attribute"; + ret += " selectors. The identifier C does not have to be a valid language"; + ret += " name.</p>"; + ret += " <p>C must not be empty. (If it is, the selector is invalid.)</p>"; + ret += " <p class='note'><strong>Note:</strong> It is recommended that"; + ret += " documents and protocols indicate language using codes from RFC 3066 <a href='#refsRFC3066'>[RFC3066]</a> or its successor, and by means of"; + ret += " 'xml:lang' attributes in the case of XML-based documents <a href='#refsXML10'>[XML10]</a>. See <a href='http://www.w3.org/International/questions/qa-lang-2or3.html'>"; + ret += " 'FAQ: Two-letter or three-letter language codes.'</a></p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The two following selectors represent an HTML document that is in"; + ret += " Belgian, French, or German. The two next selectors represent"; + ret += " <code>q</code> quotations in an arbitrary element in Belgian, French,"; + ret += " or German.</p>"; + ret += " <pre>html:lang(fr-be)"; + ret += " :lang(de) > q</pre>"; + ret += " </div>"; + ret += " <h4><a name='UIstates'>6.6.4. The UI element states pseudo-classes</a></h4>"; + ret += " <h5><a name='enableddisabled'>The :enabled and :disabled pseudo-classes</a></h5>"; + ret += " <p>The <code>:enabled</code> pseudo-class allows authors to customize"; + ret += " an enabled <code>input</code> element without also specifying what it"; + ret += " would look like when it was disabled.</p>"; + ret += " <p>Similar to <code>:enabled</code>, <code>:disabled</code> allows the"; + ret += " element should look.</p>"; + ret += " <p>Most elements will be neither enabled nor disabled. An element is"; + ret += " presently activate it or transfer focus to it.</p>"; + ret += " <h5><a name='checked'>The :checked pseudo-class</a></h5>"; + ret += " <p>Radio and checkbox elements can be toggled by the user. Some menu"; + ret += " toggled 'on' the <code>:checked</code> pseudo-class applies. The"; + ret += " <code>:checked</code> pseudo-class initially applies to such elements"; + ret += " that have the HTML4 <code>selected</code> and <code>checked</code>"; + ret += " attributes as described in <a href='http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.2.1'>Section"; + ret += " 17.2.1 of HTML4</a>, but of course the user can toggle 'off' such"; + ret += " elements in which case the <code>:checked</code> pseudo-class would no"; + ret += " longer apply. While the <code>:checked</code> pseudo-class is dynamic"; + ret += " on the presence of the semantic HTML4 <code>selected</code> and"; + ret += " <code>checked</code> attributes, it applies to all media."; + ret += " </p><h5><a name='indeterminate'>The :indeterminate pseudo-class</a></h5>"; + ret += " <div class='note'>"; + ret += " <p>Radio and checkbox elements can be toggled by the user, but are"; + ret += " This can be due to an element attribute, or DOM manipulation.</p>"; + ret += " <p>A future version of this specification may introduce an"; + ret += " <code>:indeterminate</code> pseudo-class that applies to such elements."; + ret += " <!--While the <code>:indeterminate</code> pseudo-class is dynamic in"; + ret += " the presence of an element attribute, it applies to all media.</p>"; + ret += " <p>Components of a radio-group initialized with no pre-selected choice"; + ret += " are an example of :indeterminate state.--></p>"; + ret += " </div>"; + ret += " <h4><a name='structural-pseudos'>6.6.5. Structural pseudo-classes</a></h4>"; + ret += " <p>Selectors introduces the concept of <dfn>structural"; + ret += " pseudo-classes</dfn> to permit selection based on extra information that"; + ret += " the document tree but cannot be represented by other simple selectors or"; + ret += " </p><p>Note that standalone pieces of PCDATA (text nodes in the DOM) are"; + ret += " </p><h5><a name='root-pseudo'>:root pseudo-class</a></h5>"; + ret += " <p>The <code>:root</code> pseudo-class represents an element that is"; + ret += " <code>HTML</code> element."; + ret += " </p><h5><a name='nth-child-pseudo'>:nth-child() pseudo-class</a></h5>"; + ret += " <p>The"; + ret += " <code>:nth-child(<var>a</var><code>n</code>+<var>b</var>)</code>"; + ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings"; + ret += " <strong>before</strong> it in the document tree, for a given positive"; + ret += " integer or zero value of <code>n</code>, and has a parent element. In"; + ret += " other words, this matches the <var>b</var>th child of an element after"; + ret += " all the children have been split into groups of <var>a</var> elements"; + ret += " each. For example, this allows the selectors to address every other"; + ret += " of paragraph text in a cycle of four. The <var>a</var> and"; + ret += " <var>b</var> values must be zero, negative integers or positive"; + ret += " </p><p>In addition to this, <code>:nth-child()</code> can take"; + ret += " '<code>odd</code>' and '<code>even</code>' as arguments instead."; + ret += " '<code>odd</code>' has the same signification as <code>2n+1</code>,"; + ret += " and '<code>even</code>' has the same signification as <code>2n</code>."; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <pre>tr:nth-child(2n+1) /* represents every odd row of an HTML table */"; + ret += " p:nth-child(4n+4) { color: purple; }</pre>"; + ret += " </div>"; + ret += " <p>When <var>a</var>=0, no repeating is used, so for example"; + ret += " <code>:nth-child(0n+5)</code> matches only the fifth child. When"; + ret += " <var>a</var>=0, the <var>a</var><code>n</code> part need not be"; + ret += " <code>:nth-child(<var>b</var>)</code> and the last example simplifies"; + ret += " to <code>:nth-child(5)</code>."; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <pre>foo:nth-child(0n+1) /* represents an element foo, first child of its parent element */"; + ret += " foo:nth-child(1) /* same */</pre>"; + ret += " </div>"; + ret += " <p>When <var>a</var>=1, the number may be omitted from the rule."; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following selectors are therefore equivalent:</p>"; + ret += " <pre>bar:nth-child(1n+0) /* represents all bar elements, specificity (0,1,1) */"; + ret += " bar /* same but lower specificity (0,0,1) */</pre>"; + ret += " </div>"; + ret += " <p>If <var>b</var>=0, then every <var>a</var>th element is picked. In"; + ret += " such a case, the <var>b</var> part may be omitted."; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <pre>tr:nth-child(2n+0) /* represents every even row of an HTML table */"; + ret += " tr:nth-child(2n) /* same */</pre>"; + ret += " </div>"; + ret += " <p>If both <var>a</var> and <var>b</var> are equal to zero, the"; + ret += " pseudo-class represents no element in the document tree.</p>"; + ret += " <p>The value <var>a</var> can be negative, but only the positive"; + ret += " values of <var>a</var><code>n</code>+<var>b</var>, for"; + ret += " <code>n</code>≥0, may represent an element in the document"; + ret += " tree.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <pre>html|tr:nth-child(-n+6) /* represents the 6 first rows of XHTML tables */</pre>"; + ret += " </div>"; + ret += " <p>When the value <var>b</var> is negative, the '+' character in the"; + ret += " character indicating the negative value of <var>b</var>).</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <pre>:nth-child(10n-1) /* represents the 9th, 19th, 29th, etc, element */"; + ret += " :nth-child(10n+-1) /* Syntactically invalid, and would be ignored */</pre>"; + ret += " </div>"; + ret += " <h5><a name='nth-last-child-pseudo'>:nth-last-child() pseudo-class</a></h5>"; + ret += " <p>The <code>:nth-last-child(<var>a</var>n+<var>b</var>)</code>"; + ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings"; + ret += " <strong>after</strong> it in the document tree, for a given positive"; + ret += " integer or zero value of <code>n</code>, and has a parent element. See"; + ret += " <code>:nth-child()</code> pseudo-class for the syntax of its argument."; + ret += " It also accepts the '<code>even</code>' and '<code>odd</code>' values"; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <pre>tr:nth-last-child(-n+2) /* represents the two last rows of an HTML table */"; + ret += " counting from the last one */</pre>"; + ret += " </div>"; + ret += " <h5><a name='nth-of-type-pseudo'>:nth-of-type() pseudo-class</a></h5>"; + ret += " <p>The <code>:nth-of-type(<var>a</var>n+<var>b</var>)</code>"; + ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings with the same"; + ret += " element name <strong>before</strong> it in the document tree, for a"; + ret += " given zero or positive integer value of <code>n</code>, and has a"; + ret += " parent element. In other words, this matches the <var>b</var>th child"; + ret += " groups of a elements each. See <code>:nth-child()</code> pseudo-class"; + ret += " '<code>even</code>' and '<code>odd</code>' values."; + ret += " </p><div class='example'>"; + ret += " <p>CSS example:</p>"; + ret += " <p>This allows an author to alternate the position of floated images:</p>"; + ret += " <pre>img:nth-of-type(2n+1) { float: right; }"; + ret += " img:nth-of-type(2n) { float: left; }</pre>"; + ret += " </div>"; + ret += " <h5><a name='nth-last-of-type-pseudo'>:nth-last-of-type() pseudo-class</a></h5>"; + ret += " <p>The <code>:nth-last-of-type(<var>a</var>n+<var>b</var>)</code>"; + ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings with the same"; + ret += " element name <strong>after</strong> it in the document tree, for a"; + ret += " given zero or positive integer value of <code>n</code>, and has a"; + ret += " parent element. See <code>:nth-child()</code> pseudo-class for the"; + ret += " syntax of its argument. It also accepts the '<code>even</code>' and '<code>odd</code>'"; + ret += " </p><div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>To represent all <code>h2</code> children of an XHTML"; + ret += " <code>body</code> except the first and last, one could use the"; + ret += " following selector:</p>"; + ret += " <pre>body > h2:nth-of-type(n+2):nth-last-of-type(n+2)</pre>"; + ret += " <p>In this case, one could also use <code>:not()</code>, although the"; + ret += " selector ends up being just as long:</p>"; + ret += " <pre>body > h2:not(:first-of-type):not(:last-of-type)</pre>"; + ret += " </div>"; + ret += " <h5><a name='first-child-pseudo'>:first-child pseudo-class</a></h5>"; + ret += " <p>Same as <code>:nth-child(1)</code>. The <code>:first-child</code>"; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following selector represents a <code>p</code> element that is"; + ret += " the first child of a <code>div</code> element:</p>"; + ret += " <pre>div > p:first-child</pre>"; + ret += " <p>This selector can represent the <code>p</code> inside the"; + ret += " <code>div</code> of the following fragment:</p>"; + ret += " <pre><p> The last P before the note.</p>"; + ret += " </div></pre>"; + ret += " but cannot represent the second <code>p</code> in the following"; + ret += " <pre><p> The last P before the note.</p>"; + ret += " </div></pre>"; + ret += " <p>The following two selectors are usually equivalent:</p>"; + ret += " <pre>* > a:first-child /* a is first child of any element */"; + ret += " a:first-child /* Same (assuming a is not the root element) */</pre>"; + ret += " </div>"; + ret += " <h5><a name='last-child-pseudo'>:last-child pseudo-class</a></h5>"; + ret += " <p>Same as <code>:nth-last-child(1)</code>. The <code>:last-child</code>"; + ret += " </p><div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>The following selector represents a list item <code>li</code> that"; + ret += " is the last child of an ordered list <code>ol</code>."; + ret += " </p><pre>ol > li:last-child</pre>"; + ret += " </div>"; + ret += " <h5><a name='first-of-type-pseudo'>:first-of-type pseudo-class</a></h5>"; + ret += " <p>Same as <code>:nth-of-type(1)</code>. The <code>:first-of-type</code>"; + ret += " </p><div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>The following selector represents a definition title"; + ret += " <code>dt</code> inside a definition list <code>dl</code>, this"; + ret += " <code>dt</code> being the first of its type in the list of children of"; + ret += " its parent element.</p>"; + ret += " <pre>dl dt:first-of-type</pre>"; + ret += " <p>It is a valid description for the first two <code>dt</code>"; + ret += " elements in the following example but not for the third one:</p>"; + ret += " <pre><dl>"; + ret += " </dl></pre>"; + ret += " </div>"; + ret += " <h5><a name='last-of-type-pseudo'>:last-of-type pseudo-class</a></h5>"; + ret += " <p>Same as <code>:nth-last-of-type(1)</code>. The"; + ret += " <code>:last-of-type</code> pseudo-class represents an element that is"; + ret += " element.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>The following selector represents the last data cell"; + ret += " <code>td</code> of a table row.</p>"; + ret += " <pre>tr > td:last-of-type</pre>"; + ret += " </div>"; + ret += " <h5><a name='only-child-pseudo'>:only-child pseudo-class</a></h5>"; + ret += " <p>Represents an element that has a parent element and whose parent"; + ret += " <code>:first-child:last-child</code> or"; + ret += " <code>:nth-child(1):nth-last-child(1)</code>, but with a lower"; + ret += " specificity.</p>"; + ret += " <h5><a name='only-of-type-pseudo'>:only-of-type pseudo-class</a></h5>"; + ret += " <p>Represents an element that has a parent element and whose parent"; + ret += " as <code>:first-of-type:last-of-type</code> or"; + ret += " <code>:nth-of-type(1):nth-last-of-type(1)</code>, but with a lower"; + ret += " specificity.</p>"; + ret += " <h5><a name='empty-pseudo'></a>:empty pseudo-class</h5>"; + ret += " <p>The <code>:empty</code> pseudo-class represents an element that has"; + ret += " empty or not.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p><code>p:empty</code> is a valid representation of the following fragment:"; + ret += " </p>"; + ret += " <pre><p></p></pre>"; + ret += " <p><code>foo:empty</code> is not a valid representation for the"; + ret += " following fragments:</p>"; + ret += " <pre><foo>bar</foo></pre>"; + ret += " <pre><foo><bar>bla</bar></foo></pre>"; + ret += " <pre><foo>this is not <bar>:empty</bar></foo></pre>"; + ret += " </div>"; + ret += " <h4><a name='content-selectors'>6.6.6. Blank</a></h4>"; + ret += " <!-- It's the Return of Appendix H!!! Run away! -->"; + ret += " <p>This section intentionally left blank.</p>"; + ret += " <!-- (used to be :contains()) -->"; + ret += " <h4><a name='negation'></a>6.6.7. The negation pseudo-class</h4>"; + ret += " <p>The negation pseudo-class, <code>:not(<var>X</var>)</code>, is a"; + ret += " functional notation taking a <a href='#simple-selectors-dfn'>simple"; + ret += " selector</a> (excluding the negation pseudo-class itself and"; + ret += " <!-- pseudo-elements are not simple selectors, so the above paragraph"; + ret += " may be a bit confusing -->"; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following CSS selector matches all <code>button</code>"; + ret += " elements in an HTML document that are not disabled.</p>"; + ret += " <pre>button:not([DISABLED])</pre>"; + ret += " <p>The following selector represents all but <code>FOO</code>"; + ret += " elements.</p>"; + ret += " <pre>*:not(FOO)</pre>"; + ret += " <p>The following group of selectors represents all HTML elements"; + ret += " except links.</p>"; + ret += " <pre>html|*:not(:link):not(:visited)</pre>"; + ret += " </div>"; + ret += " <p>Default namespace declarations do not affect the argument of the"; + ret += " type selector.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>Assuming that the default namespace is bound to"; + ret += " elements that are not in that namespace:</p>"; + ret += " <pre>*|*:not(*)</pre>"; + ret += " <p>The following CSS selector matches any element being hovered,"; + ret += " rule when they <em>are</em> being hovered.</p>"; + ret += " <pre>*|*:not(:hover)</pre>"; + ret += " </div>"; + ret += " <p class='note'><strong>Note</strong>: the :not() pseudo allows"; + ret += " useless selectors to be written. For instance <code>:not(*|*)</code>,"; + ret += " which represents no element at all, or <code>foo:not(bar)</code>,"; + ret += " which is equivalent to <code>foo</code> but with a higher"; + ret += " specificity.</p>"; + ret += " <h3><a name='pseudo-elements'>7. Pseudo-elements</a></h3>"; + ret += " <p>Pseudo-elements create abstractions about the document tree beyond"; + ret += " source document (e.g., the <code>::before</code> and"; + ret += " <code>::after</code> pseudo-elements give access to generated"; + ret += " content).</p>"; + ret += " <p>A pseudo-element is made of two colons (<code>::</code>) followed"; + ret += " by the name of the pseudo-element.</p>"; + ret += " <p>This <code>::</code> notation is introduced by the current document"; + ret += " <code>:first-line</code>, <code>:first-letter</code>,"; + ret += " <code>:before</code> and <code>:after</code>). This compatibility is"; + ret += " not allowed for the new pseudo-elements introduced in CSS level 3.</p>"; + ret += " <p>Only one pseudo-element may appear per selector, and if present it"; + ret += " must appear after the sequence of simple selectors that represents the"; + ret += " <a href='#subject'>subjects</a> of the selector. <span class='note'>A"; + ret += " pesudo-elements per selector.</span></p>"; + ret += " <h4><a name='first-line'>7.1. The ::first-line pseudo-element</a></h4>"; + ret += " <p>The <code>::first-line</code> pseudo-element describes the contents"; + ret += " </p><div class='example'>"; + ret += " <p>CSS example:</p>"; + ret += " <pre>p::first-line { text-transform: uppercase }</pre>"; + ret += " <p>The above rule means 'change the letters of the first line of every"; + ret += " paragraph to uppercase'.</p>"; + ret += " </div>"; + ret += " <p>The selector <code>p::first-line</code> does not match any real"; + ret += " agents will insert at the beginning of every paragraph.</p>"; + ret += " <p>Note that the length of the first line depends on a number of"; + ret += " an ordinary HTML paragraph such as:</p>"; + ret += " <pre> <P>This is a somewhat long HTML "; + ret += " </pre>"; + ret += " <p>the lines of which happen to be broken as follows:"; + ret += " </p><pre> THIS IS A SOMEWHAT LONG HTML PARAGRAPH THAT"; + ret += " </pre>"; + ret += " <p>This paragraph might be 'rewritten' by user agents to include the"; + ret += " <em>fictional tag sequence</em> for <code>::first-line</code>. This"; + ret += " fictional tag sequence helps to show how properties are inherited.</p>"; + ret += " <pre> <P><b><P::first-line></b> This is a somewhat long HTML "; + ret += " paragraph that <b></P::first-line></b> will be broken into several"; + ret += " </pre>"; + ret += " <p>If a pseudo-element breaks up a real element, the desired effect"; + ret += " with a <code>span</code> element:</p>"; + ret += " <pre> <P><b><SPAN class='test'></b> This is a somewhat long HTML"; + ret += " lines.<b></SPAN></b> The first line will be identified"; + ret += " </pre>"; + ret += " <p>the user agent could simulate start and end tags for"; + ret += " <code>span</code> when inserting the fictional tag sequence for"; + ret += " <code>::first-line</code>."; + ret += " </p><pre> <P><P::first-line><b><SPAN class='test'></b> This is a"; + ret += " paragraph that will <b></SPAN></b></P::first-line><b><SPAN"; + ret += " class='test'></b> be"; + ret += " lines.<b></SPAN></b> The first line will be identified"; + ret += " </pre>"; + ret += " <p>In CSS, the <code>::first-line</code> pseudo-element can only be"; + ret += " or a table-cell.</p>"; + ret += " <p><a name='first-formatted-line'></a>The 'first formatted line' of an"; + ret += " line of the <code>div</code> in <code><DIV><P>This"; + ret += " line...</P></DIV></code> is the first line of the <code>p</code>"; + ret += " that both <code>p</code> and <code>div</code> are block-level)."; + ret += " </p><p>The first line of a table-cell or inline-block cannot be the first"; + ret += " formatted line of an ancestor element. Thus, in <code><DIV><P"; + ret += " etcetera</DIV></code> the first formatted line of the"; + ret += " <code>div</code> is not the line 'Hello'."; + ret += " </p><p class='note'>Note that the first line of the <code>p</code> in this"; + ret += " fragment: <code><p><br>First...</code> doesn't contain any"; + ret += " letters (assuming the default style for <code>br</code> in HTML"; + ret += " </p><p>A UA should act as if the fictional start tags of the"; + ret += " <code>::first-line</code> pseudo-elements were nested just inside the"; + ret += " is an example. The fictional tag sequence for</p>"; + ret += " <pre> <DIV>"; + ret += " </pre>"; + ret += " <p>is</p>"; + ret += " <pre> <DIV>"; + ret += " </pre>"; + ret += " <p>The <code>::first-line</code> pseudo-element is similar to an"; + ret += " following properties apply to a <code>::first-line</code>"; + ret += " properties as well.</p>"; + ret += " <h4><a name='first-letter'>7.2. The ::first-letter pseudo-element</a></h4>"; + ret += " <p>The <code>::first-letter</code> pseudo-element represents the first"; + ret += " is 'none'; otherwise, it is similar to a floated element.</p>"; + ret += " <p>In CSS, these are the properties that apply to <code>::first-letter</code>"; + ret += " of the letter, unlike for normal elements.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>This example shows a possible rendering of an initial cap. Note"; + ret += " <code>::first-letter</code>"; + ret += " fictional start tag of the first letter is inside the <span>span</span>,"; + ret += " the font weight of the first letter is normal, not bold as the <span>span</span>:"; + ret += " </p><pre> p { line-height: 1.1 }"; + ret += " </pre>"; + ret += " <div class='figure'>"; + ret += " <p><img src='' alt='Image illustrating the ::first-letter pseudo-element'>"; + ret += " </p></div>"; + ret += " </div>"; + ret += " <div class='example'>"; + ret += " <p>The following CSS will make a drop cap initial letter span about two"; + ret += " lines:</p>"; + ret += " <pre> <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN'>"; + ret += " </pre>"; + ret += " <p>This example might be formatted as follows:</p>"; + ret += " <div class='figure'>"; + ret += " <p><img src='' alt='Image illustrating the combined effect of the ::first-letter and ::first-line pseudo-elements'>"; + ret += " </p>"; + ret += " </div>"; + ret += " <p>The <span class='index-inst' title='fictional tag"; + ret += " sequence'>fictional tag sequence</span> is:</p>"; + ret += " <pre> <P>"; + ret += " </pre>"; + ret += " <p>Note that the <code>::first-letter</code> pseudo-element tags abut"; + ret += " block element.</p></div>"; + ret += " <p>In order to achieve traditional drop caps formatting, user agents"; + ret += " glyph outline may be taken into account when formatting.</p>"; + ret += " <p>Punctuation (i.e, characters defined in Unicode in the 'open' (Ps),"; + ret += " be included. <a href='#refsUNICODE'>[UNICODE]</a></p>"; + ret += " <div class='figure'>"; + ret += " <p><img src='' alt='Quotes that precede the"; + ret += " first letter should be included.'></p>"; + ret += " </div>"; + ret += " <p>The <code>::first-letter</code> also applies if the first letter is"; + ret += " money.'</p>"; + ret += " <p>In CSS, the <code>::first-letter</code> pseudo-element applies to"; + ret += " elements. <span class='note'>A future version of this specification"; + ret += " types.</span></p>"; + ret += " <p>The <code>::first-letter</code> pseudo-element can be used with all"; + ret += " the element, even if that first text is in a descendant.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>The fictional tag sequence for this HTMLfragment:"; + ret += " </p><pre><div>"; + ret += " <p>The first text.</pre>"; + ret += " <p>is:"; + ret += " </p><pre><div>"; + ret += " <p><div::first-letter><p::first-letter>T</...></...>he first text.</pre>"; + ret += " </div>"; + ret += " <p>The first letter of a table-cell or inline-block cannot be the"; + ret += " first letter of an ancestor element. Thus, in <code><DIV><P"; + ret += " etcetera</DIV></code> the first letter of the <code>div</code> is"; + ret += " letter 'H'. In fact, the <code>div</code> doesn't have a first letter."; + ret += " </p><p>The first letter must occur on the <a href='#first-formatted-line'>first formatted line.</a> For example, in"; + ret += " this fragment: <code><p><br>First...</code> the first line"; + ret += " doesn't contain any letters and <code>::first-letter</code> doesn't"; + ret += " match anything (assuming the default style for <code>br</code> in HTML"; + ret += " </p><p>In CSS, if an element is a list item ('display: list-item'), the"; + ret += " <code>::first-letter</code> applies to the first letter in the"; + ret += " <code>::first-letter</code> on list items with 'list-style-position:"; + ret += " inside'. If an element has <code>::before</code> or"; + ret += " <code>::after</code> content, the <code>::first-letter</code> applies"; + ret += " to the first letter of the element <em>including</em> that content."; + ret += " </p><div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>After the rule 'p::before {content: 'Note: '}', the selector"; + ret += " 'p::first-letter' matches the 'N' of 'Note'.</p>"; + ret += " </div>"; + ret += " <p>Some languages may have specific rules about how to treat certain"; + ret += " considered within the <code>::first-letter</code> pseudo-element."; + ret += " </p><p>If the letters that would form the ::first-letter are not in the"; + ret += " same element, such as ''T' in <code><p>'<em>T...</code>, the UA"; + ret += " both elements, or simply not create a pseudo-element.</p>"; + ret += " <p>Similarly, if the first letter(s) of the block are not at the start"; + ret += " </p><div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p><a name='overlapping-example'>The following example</a> illustrates"; + ret += " paragraph will be 'red'.</p>"; + ret += " <pre>p { color: red; font-size: 12pt }"; + ret += " <P>Some text that ends up on two lines</P></pre>"; + ret += " <p>Assuming that a line break will occur before the word 'ends', the"; + ret += " <span class='index-inst' title='fictional tag sequence'>fictional tag"; + ret += " sequence</span> for this fragment might be:</p>"; + ret += " <pre><P>"; + ret += " </P></pre>"; + ret += " <p>Note that the <code>::first-letter</code> element is inside the <code>::first-line</code>"; + ret += " element. Properties set on <code>::first-line</code> are inherited by"; + ret += " <code>::first-letter</code>, but are overridden if the same property is"; + ret += " <code>::first-letter</code>.</p>"; + ret += " </div>"; + ret += " <h4><a name='UIfragments'>7.3.</a> <a name='selection'>The ::selection"; + ret += " pseudo-element</a></h4>"; + ret += " <p>The <code>::selection</code> pseudo-element applies to the portion"; + ret += " field. This pseudo-element should not be confused with the <code><a href='#checked'>:checked</a></code> pseudo-class (which used to be"; + ret += " named <code>:selected</code>)"; + ret += " </p><p>Although the <code>::selection</code> pseudo-element is dynamic in"; + ret += " <a href='#refsCSS21'>[CSS21]</a>) which was originally rendered to a"; + ret += " <code>::selection</code> state to that other medium, and have all the"; + ret += " required — UAs may omit the <code>::selection</code>"; + ret += " </p><p>These are the CSS properties that apply to <code>::selection</code>"; + ret += " <code>::selection</code> may be ignored."; + ret += " </p><h4><a name='gen-content'>7.4. The ::before and ::after pseudo-elements</a></h4>"; + ret += " <p>The <code>::before</code> and <code>::after</code> pseudo-elements"; + ret += " content. They are explained in CSS 2.1 <a href='#refsCSS21'>[CSS21]</a>.</p>"; + ret += " <p>When the <code>::first-letter</code> and <code>::first-line</code>"; + ret += " pseudo-elements are combined with <code>::before</code> and"; + ret += " <code>::after</code>, they apply to the first letter or line of the"; + ret += " element including the inserted text.</p>"; + ret += " <h2><a name='combinators'>8. Combinators</a></h2>"; + ret += " <h3><a name='descendant-combinators'>8.1. Descendant combinator</a></h3>"; + ret += " <p>At times, authors may want selectors to describe an element that is"; + ret += " <code>EM</code> element that is contained within an <code>H1</code>"; + ret += " descendant combinator is <a href='#whitespace'>white space</a> that"; + ret += " separates two sequences of simple selectors. A selector of the form"; + ret += " '<code>A B</code>' represents an element <code>B</code> that is an"; + ret += " arbitrary descendant of some ancestor element <code>A</code>."; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>For example, consider the following selector:</p>"; + ret += " <pre>h1 em</pre>"; + ret += " <p>It represents an <code>em</code> element being the descendant of"; + ret += " an <code>h1</code> element. It is a correct and valid, but partial,"; + ret += " description of the following fragment:</p>"; + ret += " <pre><h1>This <span class='myclass'>headline"; + ret += " is <em>very</em> important</span></h1></pre>"; + ret += " <p>The following selector:</p>"; + ret += " <pre>div * p</pre>"; + ret += " <p>represents a <code>p</code> element that is a grandchild or later"; + ret += " descendant of a <code>div</code> element. Note the whitespace on"; + ret += " of the P.</p>"; + ret += " <p>The following selector, which combines descendant combinators and"; + ret += " <a href='#attribute-selectors'>attribute selectors</a>, represents an"; + ret += " element that (1) has the <code>href</code> attribute set and (2) is"; + ret += " inside a <code>p</code> that is itself inside a <code>div</code>:</p>"; + ret += " <pre>div p *[href]</pre>"; + ret += " </div>"; + ret += " <h3><a name='child-combinators'>8.2. Child combinators</a></h3>"; + ret += " <p>A <dfn>child combinator</dfn> describes a childhood relationship"; + ret += " 'greater-than sign' (<code>></code>) character and"; + ret += " separates two sequences of simple selectors."; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following selector represents a <code>p</code> element that is"; + ret += " child of <code>body</code>:</p>"; + ret += " <pre>body > p</pre>"; + ret += " <p>The following example combines descendant combinators and child"; + ret += " combinators.</p>"; + ret += " <pre>div ol>li p</pre>"; + ret += " <!-- LEAVE THOSE SPACES OUT! see below -->"; + ret += " <p>It represents a <code>p</code> element that is a descendant of an"; + ret += " <code>li</code> element; the <code>li</code> element must be the"; + ret += " child of an <code>ol</code> element; the <code>ol</code> element must"; + ret += " be a descendant of a <code>div</code>. Notice that the optional white"; + ret += " space around the '>' combinator has been left out.</p>"; + ret += " </div>"; + ret += " <p>For information on selecting the first child of an element, please"; + ret += " see the section on the <code><a href='#structural-pseudos'>:first-child</a></code> pseudo-class"; + ret += " above.</p>"; + ret += " <h3><a name='sibling-combinators'>8.3. Sibling combinators</a></h3>"; + ret += " <p>There are two different sibling combinators: the adjacent sibling"; + ret += " considering adjacency of elements.</p>"; + ret += " <h4><a name='adjacent-sibling-combinators'>8.3.1. Adjacent sibling combinator</a>"; + ret += " </h4>"; + ret += " <p>The adjacent sibling combinator is made of the 'plus"; + ret += " sign' (U+002B, <code>+</code>) character that separates two"; + ret += " sequences of simple selectors. The elements represented by the two"; + ret += " represented by the second one.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following selector represents a <code>p</code> element"; + ret += " immediately following a <code>math</code> element:</p>"; + ret += " <pre>math + p</pre>"; + ret += " <p>The following selector is conceptually similar to the one in the"; + ret += " adds a constraint to the <code>h1</code> element, that it must have"; + ret += " <code>class='opener'</code>:</p>"; + ret += " <pre>h1.opener + h2</pre>"; + ret += " </div>"; + ret += " <h4><a name='general-sibling-combinators'>8.3.2. General sibling combinator</a>"; + ret += " </h4>"; + ret += " <p>The general sibling combinator is made of the 'tilde'"; + ret += " (U+007E, <code>~</code>) character that separates two sequences of"; + ret += " simple selectors. The elements represented by the two sequences share"; + ret += " represented by the second one.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <pre>h1 ~ pre</pre>"; + ret += " <p>represents a <code>pre</code> element following an <code>h1</code>. It"; + ret += " is a correct and valid, but partial, description of:</p>"; + ret += " <pre><h1>Definition of the function a</h1>"; + ret += " <pre>function a(x) = 12x/13.5</pre></pre>"; + ret += " </div>"; + ret += " <h2><a name='specificity'>9. Calculating a selector's specificity</a></h2>"; + ret += " <p>A selector's specificity is calculated as follows:</p>"; + ret += " <ul>"; + ret += " <li>count the number of ID selectors in the selector (= a)</li>"; + ret += " <li>count the number of class selectors, attributes selectors, and"; + ret += " </li>"; + ret += " <li>count the number of element names in the selector (= c)</li>"; + ret += " <li>ignore pseudo-elements</li>"; + ret += " </ul>"; + ret += " <p>Selectors inside <a href='#negation'>the negation pseudo-class</a>"; + ret += " a pseudo-class.</p>"; + ret += " <p>Concatenating the three numbers a-b-c (in a number system with a"; + ret += " large base) gives the specificity.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <pre>* /* a=0 b=0 c=0 -> specificity = 0 */"; + ret += " </pre>"; + ret += " </div>"; + ret += " <p class='note'><strong>Note:</strong> the specificity of the styles"; + ret += " specified in an HTML <code>style</code> attribute is described in CSS"; + ret += " 2.1. <a href='#refsCSS21'>[CSS21]</a>.</p>"; + ret += " <h2><a name='w3cselgrammar'>10. The grammar of Selectors</a></h2>"; + ret += " <h3><a name='grammar'>10.1. Grammar</a></h3>"; + ret += " <p>The grammar below defines the syntax of Selectors. It is globally"; + ret += " shorthand notations beyond Yacc (see <a href='#refsYACC'>[YACC]</a>)"; + ret += " are used:</p>"; + ret += " <ul>"; + ret += " <li><b>*</b>: 0 or more"; + ret += " </li><li><b>+</b>: 1 or more"; + ret += " </li><li><b>?</b>: 0 or 1"; + ret += " </li><li><b>|</b>: separates alternatives"; + ret += " </li><li><b>[ ]</b>: grouping</li>"; + ret += " </ul>"; + ret += " <p>The productions are:</p>"; + ret += " <pre>selectors_group"; + ret += " ;</pre>"; + ret += " <h3><a name='lex'>10.2. Lexical scanner</a></h3>"; + ret += " <p>The following is the <a name='x3'>tokenizer</a>, written in Flex (see"; + ret += " <a href='#refsFLEX'>[FLEX]</a>) notation. The tokenizer is"; + ret += " case-insensitive.</p>"; + ret += " <p>The two occurrences of '\377' represent the highest character"; + ret += " possible code point in Unicode/ISO-10646. <a href='#refsUNICODE'>[UNICODE]</a></p>"; + ret += " <pre>%option case-insensitive"; + ret += " . return *yytext;</pre>"; + ret += " <h2><a name='downlevel'>11. Namespaces and down-level clients</a></h2>"; + ret += " <p>An important issue is the interaction of CSS selectors with XML"; + ret += " to construct a CSS style sheet which will properly match selectors in"; + ret += " is possible to construct a style sheet in which selectors would match"; + ret += " elements and attributes correctly.</p>"; + ret += " <p>It should be noted that a down-level CSS client will (if it"; + ret += " <code>@namespace</code> at-rules, as well as all style rules that make"; + ret += " use of namespace qualified element type or attribute selectors. The"; + ret += " than possibly match them incorrectly.</p>"; + ret += " <p>The use of default namespaces in CSS makes it possible to write"; + ret += " element type selectors that will function in both namespace aware CSS"; + ret += " down-level clients may incorrectly match selectors against XML"; + ret += " elements in other namespaces.</p>"; + ret += " <p>The following are scenarios and examples in which it is possible to"; + ret += " that do not implement this proposal.</p>"; + ret += " <ol>"; + ret += " <li>"; + ret += " <p>The XML document does not use namespaces.</p>"; + ret += " <ul>"; + ret += " <li>In this case, it is obviously not necessary to declare or use"; + ret += " attribute selectors will function adequately in a down-level"; + ret += " </li>"; + ret += " <li>In a CSS namespace aware client, the default behavior of"; + ret += " element selectors matching without regard to namespace will"; + ret += " present. However, the use of specific element type selectors"; + ret += " match only elements that have no namespace ('<code>|name</code>')"; + ret += " will guarantee that selectors will match only XML elements that"; + ret += " </li>"; + ret += " </ul>"; + ret += " </li>"; + ret += " <li>"; + ret += " <p>The XML document defines a single, default namespace used"; + ret += " names.</p>"; + ret += " <ul>"; + ret += " <li>In this case, a down-level client will function as if"; + ret += " element type and attribute selectors will match against all"; + ret += " </li>"; + ret += " </ul>"; + ret += " </li>"; + ret += " <li>"; + ret += " <p>The XML document does <b>not</b> use a default namespace, all"; + ret += " to the same URI).</p>"; + ret += " <ul>"; + ret += " <li>In this case, the down-level client will view and match"; + ret += " element type and attribute selectors based on their fully"; + ret += " qualified name, not the local part as outlined in the <a href='#typenmsp'>Type selectors and Namespaces</a>"; + ret += " selectors may be declared using an escaped colon"; + ret += " '<code>\\:</code>'"; + ret += " '<code>html\\:h1</code>' will match"; + ret += " <code><html:h1></code>. Selectors using the qualified name"; + ret += " </li>"; + ret += " <li>Note that selectors declared in this fashion will"; + ret += " <em>only</em> match in down-level clients. A CSS namespace aware"; + ret += " client will match element type and attribute selectors based on"; + ret += " the name's local part. Selectors declared with the fully"; + ret += " </li>"; + ret += " </ul>"; + ret += " </li>"; + ret += " </ol>"; + ret += " <p>In other scenarios: when the namespace prefixes used in the XML are"; + ret += " <em>different</em> namespace URIs within the same document, or in"; + ret += " a CSS and XML namespace aware client.</p>"; + ret += " <h2><a name='profiling'>12. Profiles</a></h2>"; + ret += " <p>Each specification using Selectors must define the subset of W3C"; + ret += " Selectors it allows and excludes, and describe the local meaning of"; + ret += " all the components of that subset.</p>"; + ret += " <p>Non normative examples:"; + ret += " </p><div class='profile'>"; + ret += " <table class='tprofile'>"; + ret += " <tbody>"; + ret += " <tr>"; + ret += " <th class='title' colspan='2'>Selectors profile</th>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Specification</th>"; + ret += " <td>CSS level 1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Accepts</th>"; + ret += " <td>type selectors<br>class selectors<br>ID selectors<br>:link,"; + ret += " :visited and :active pseudo-classes<br>descendant combinator"; + ret += " <br>::first-line and ::first-letter pseudo-elements"; + ret += " </td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Excludes</th>"; + ret += " <td>"; + ret += " <p>universal selector<br>attribute selectors<br>:hover and"; + ret += " pseudo-classes<br>:target pseudo-class<br>:lang()"; + ret += " pseudo-class<br>all UI"; + ret += " element states pseudo-classes<br>all structural"; + ret += " pseudo-classes<br>negation pseudo-class<br>all"; + ret += " UI element fragments pseudo-elements<br>::before and ::after"; + ret += " pseudo-elements<br>child combinators<br>sibling combinators"; + ret += " </p><p>namespaces</p></td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Extra constraints</th>"; + ret += " <td>only one class selector allowed per sequence of simple"; + ret += " selectors"; + ret += " </td>"; + ret += " </tr>"; + ret += " </tbody>"; + ret += " </table>"; + ret += " <br><br>"; + ret += " <table class='tprofile'>"; + ret += " <tbody>"; + ret += " <tr>"; + ret += " <th class='title' colspan='2'>Selectors profile</th>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Specification</th>"; + ret += " <td>CSS level 2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Accepts</th>"; + ret += " <td>type selectors<br>universal selector<br>attribute presence and"; + ret += " values selectors<br>class selectors<br>ID selectors<br>:link,"; + ret += " <br>descendant combinator<br>child combinator<br>adjacent"; + ret += " combinator<br>::first-line and ::first-letter"; + ret += " pseudo-elements<br>::before"; + ret += " </td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Excludes</th>"; + ret += " <td>"; + ret += " <p>content selectors<br>substring matching attribute"; + ret += " selectors<br>:target pseudo-classes<br>all UI element"; + ret += " states pseudo-classes<br>all structural pseudo-classes other"; + ret += " than :first-child<br>negation pseudo-class<br>all UI element"; + ret += " fragments pseudo-elements<br>general sibling combinators"; + ret += " </p><p>namespaces</p></td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Extra constraints</th>"; + ret += " <td>more than one class selector per sequence of simple selectors"; + ret += " </td>"; + ret += " </tr>"; + ret += " </tbody>"; + ret += " </table>"; + ret += " <p>In CSS, selectors express pattern matching rules that determine which"; + ret += " </p><p>The following selector (CSS level 2) will <b>match</b> all anchors <code>a</code>"; + ret += " with attribute <code>name</code> set inside a section 1 header"; + ret += " <code>h1</code>:"; + ret += " </p><pre>h1 a[name]</pre>"; + ret += " <p>All CSS declarations attached to such a selector are applied to elements"; + ret += " matching it.</p></div>"; + ret += " <div class='profile'>"; + ret += " <table class='tprofile'>"; + ret += " <tbody>"; + ret += " <tr>"; + ret += " <th class='title' colspan='2'>Selectors profile</th>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Specification</th>"; + ret += " <td>STTS 3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Accepts</th>"; + ret += " <td>"; + ret += " <p>type selectors<br>universal selectors<br>attribute"; + ret += " selectors<br>class"; + ret += " selectors<br>ID selectors<br>all structural"; + ret += " pseudo-classes<br>"; + ret += " </p><p>namespaces</p></td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Excludes</th>"; + ret += " <td>non-accepted pseudo-classes<br>pseudo-elements<br></td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Extra constraints</th>"; + ret += " <td>some selectors and combinators are not allowed in fragment"; + ret += " </td>"; + ret += " </tr>"; + ret += " </tbody>"; + ret += " </table>"; + ret += " <p>Selectors can be used in STTS 3 in two different"; + ret += " </p><ol>"; + ret += " <li>a selection mechanism equivalent to CSS selection mechanism:"; + ret += " </li><li>fragment descriptions that appear on the right side of declarations."; + ret += " </li>"; + ret += " </ol>"; + ret += " </div>"; + ret += " <h2><a name='Conformance'></a>13. Conformance and requirements</h2>"; + ret += " <p>This section defines conformance with the present specification only."; + ret += " </p><p>The inability of a user agent to implement part of this specification due to"; + ret += " </p><p>All specifications reusing Selectors must contain a <a href='#profiling'>Profile</a> listing the"; + ret += " subset of Selectors it accepts or excludes, and describing the constraints"; + ret += " </p><p>Invalidity is caused by a parsing error, e.g. an unrecognized token or a"; + ret += " </p><p>User agents must observe the rules for handling parsing errors:"; + ret += " </p><ul>"; + ret += " <li>a simple selector containing an undeclared namespace prefix is invalid"; + ret += " </li>"; + ret += " <li>a selector containing an invalid simple selector, an invalid combinator"; + ret += " </li>"; + ret += " <li>a group of selectors containing an invalid selector is invalid.</li>"; + ret += " </ul>"; + ret += " <p>Specifications reusing Selectors must define how to handle parsing"; + ret += " used is dropped.)</p>"; + ret += " <!-- Apparently all these references are out of date:"; + ret += " <p>Implementations of this specification must behave as"; + ret += " 'recipients of text data' as defined by <a href='#refsCWWW'>[CWWW]</a>"; + ret += " when parsing selectors and attempting matches. (In particular,"; + ret += " <a href='#refsCWWW'>[CWWW]</a> and <a"; + ret += " href='#refsUNICODE'>[UNICODE]</a> and apply to implementations of this"; + ret += " specification.</p>-->"; + ret += " <h2><a name='Tests'></a>14. Tests</h2>"; + ret += " <p>This specification has <a href='http://www.w3.org/Style/CSS/Test/CSS3/Selectors/current/'>a test"; + ret += " suite</a> allowing user agents to verify their basic conformance to"; + ret += " and does not cover all possible combined cases of Selectors.</p>"; + ret += " <h2><a name='ACKS'></a>15. Acknowledgements</h2>"; + ret += " <p>The CSS working group would like to thank everyone who has sent"; + ret += " comments on this specification over the years.</p>"; + ret += " <p>The working group would like to extend special thanks to Donna"; + ret += " the final editorial review.</p>"; + ret += " <h2><a name='references'>16. References</a></h2>"; + ret += " <dl class='refs'>"; + ret += " <dt>[CSS1]"; + ret += " </dt><dd><a name='refsCSS1'></a> Bert Bos, Håkon Wium Lie; '<cite>Cascading"; + ret += " Style Sheets, level 1</cite>', W3C Recommendation, 17 Dec 1996, revised"; + ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/REC-CSS1'>http://www.w3.org/TR/REC-CSS1</a></code>)"; + ret += " </dd><dt>[CSS21]"; + ret += " </dt><dd><a name='refsCSS21'></a> Bert Bos, Tantek Çelik, Ian Hickson, Håkon"; + ret += " Wium Lie, editors; '<cite>Cascading Style Sheets, level 2 revision"; + ret += " 1</cite>', W3C Working Draft, 13 June 2005"; + ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/CSS21'>http://www.w3.org/TR/CSS21</a></code>)"; + ret += " </dd><dt>[CWWW]"; + ret += " </dt><dd><a name='refsCWWW'></a> Martin J. Dürst, François Yergeau,"; + ret += " Misha Wolf, Asmus Freytag, Tex Texin, editors; '<cite>Character Model"; + ret += " for the World Wide Web</cite>', W3C Recommendation, 15 February 2005"; + ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/charmod/'>http://www.w3.org/TR/charmod/</a></code>)"; + ret += " </dd><dt>[FLEX]"; + ret += " </dt><dd><a name='refsFLEX'></a> '<cite>Flex: The Lexical Scanner"; + ret += " Generator</cite>', Version 2.3.7, ISBN 1882114213"; + ret += " </dd><dt>[HTML4]"; + ret += " </dt><dd><a name='refsHTML4'></a> Dave Ragget, Arnaud Le Hors, Ian Jacobs,"; + ret += " editors; '<cite>HTML 4.01 Specification</cite>', W3C Recommendation, 24"; + ret += " </dd><dd>"; + ret += " (<a href='http://www.w3.org/TR/html4/'><code>http://www.w3.org/TR/html4/</code></a>)"; + ret += " </dd><dt>[MATH]"; + ret += " </dt><dd><a name='refsMATH'></a> Patrick Ion, Robert Miner, editors; '<cite>Mathematical"; + ret += " Markup Language (MathML) 1.01</cite>', W3C Recommendation, revision of 7"; + ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/REC-MathML/'>http://www.w3.org/TR/REC-MathML/</a></code>)"; + ret += " </dd><dt>[RFC3066]"; + ret += " </dt><dd><a name='refsRFC3066'></a> H. Alvestrand; '<cite>Tags for the"; + ret += " Identification of Languages</cite>', Request for Comments 3066, January"; + ret += " </dd><dd>(<a href='http://www.ietf.org/rfc/rfc3066.txt'><code>http://www.ietf.org/rfc/rfc3066.txt</code></a>)"; + ret += " </dd><dt>[STTS]"; + ret += " </dt><dd><a name='refsSTTS'></a> Daniel Glazman; '<cite>Simple Tree Transformation"; + ret += " Sheets 3</cite>', Electricité de France, submission to the W3C,"; + ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/NOTE-STTS3'>http://www.w3.org/TR/NOTE-STTS3</a></code>)"; + ret += " </dd><dt>[SVG]"; + ret += " </dt><dd><a name='refsSVG'></a> Jon Ferraiolo, 藤沢 淳, Dean"; + ret += " Jackson, editors; '<cite>Scalable Vector Graphics (SVG) 1.1"; + ret += " Specification</cite>', W3C Recommendation, 14 January 2003"; + ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/SVG/'>http://www.w3.org/TR/SVG/</a></code>)"; + ret += " </dd><dt>[UNICODE]</dt>"; + ret += " <dd><a name='refsUNICODE'></a> <cite><a href='http://www.unicode.org/versions/Unicode4.1.0/'>The Unicode"; + ret += " Standard, Version 4.1</a></cite>, The Unicode Consortium. Boston, MA,"; + ret += " Addison-Wesley, March 2005. ISBN 0-321-18578-1, as amended by <a href='http://www.unicode.org/versions/Unicode4.0.1/'>Unicode"; + ret += " 4.0.1</a> and <a href='http://www.unicode.org/versions/Unicode4.1.0/'>Unicode"; + ret += " 4.1.0</a>."; + ret += " </dd><dd>(<code><a href='http://www.unicode.org/versions/'>http://www.unicode.org/versions/</a></code>)"; + ret += " </dd>"; + ret += " <dt>[XML10]"; + ret += " </dt><dd><a name='refsXML10'></a> Tim Bray, Jean Paoli, C. M. Sperberg-McQueen,"; + ret += " Eve Maler, François Yergeau, editors; '<cite>Extensible Markup"; + ret += " Language (XML) 1.0 (Third Edition)</cite>', W3C Recommendation, 4"; + ret += " </dd><dd>(<a href='http://www.w3.org/TR/REC-xml/'><code>http://www.w3.org/TR/REC-xml/</code></a>)"; + ret += " </dd><dt>[XMLNAMES]"; + ret += " </dt><dd><a name='refsXMLNAMES'></a> Tim Bray, Dave Hollander, Andrew Layman,"; + ret += " editors; '<cite>Namespaces in XML</cite>', W3C Recommendation, 14"; + ret += " </dd><dd>(<a href='http://www.w3.org/TR/REC-xml-names/'><code>http://www.w3.org/TR/REC-xml-names/</code></a>)"; + ret += " </dd><dt>[YACC]"; + ret += " </dt><dd><a name='refsYACC'></a> S. C. Johnson; '<cite>YACC — Yet another"; + ret += " compiler compiler</cite>', Technical Report, Murray Hill, 1975"; + ret += " </dd></dl>'; </div>"; + ret += " <input name='n' value='v1' type='radio'>1"; + ret += " <input name='n' value='v2' checked='checked' type='radio'>2"; + ret += ""; + return ret; + } + +} diff --git a/devtest/src/main/java/com/google/gwt/query/client/MyTestCase.java b/devtest/src/main/java/com/google/gwt/query/client/MyTestCase.java index 8ea94ea1..3c335039 100644 --- a/devtest/src/main/java/com/google/gwt/query/client/MyTestCase.java +++ b/devtest/src/main/java/com/google/gwt/query/client/MyTestCase.java @@ -1,148 +1,148 @@ -/*
- * 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 com.google.gwt.dom.client.Element;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.RootPanel;
-import static com.google.gwt.query.client.GQuery.*;
-
-/**
- * Just a simple class to emulate JUnit TestCase.
- */
-public class MyTestCase {
-
- static Element e = null;
- static HTML testPanel = null;
-
- public static void assertEquals(Object a, Object b) {
- check(a.equals(b), "assertEquals: expected=" + a + " actual=" + b);
- }
-
- public static void assertFalse(boolean b) {
- check(!b, "assertTrue: actual should be false but is true");
- }
-
- public static void assertFalse(String msg, boolean b) {
- check(!b, msg);
- }
-
- public static void assertNotNull(Object a) {
- check(a != null, "assertNotNull: actual object is null");
- }
-
- public static void assertNull(Object a) {
- check(a == null, "assertNull: actual object is not null");
- }
-
- public static void assertTrue(boolean b) {
- check(b, "assertTrue: actual should be true but is false");
- }
-
- public static void assertTrue(String msg, boolean b) {
- check(b, msg);
- }
-
- public static void check(boolean condition, String message) {
- if (!condition) {
- RuntimeException ex = new RuntimeException(message);
- ex.printStackTrace();
- throw ex;
- }
- }
-
- protected static void assertHtmlEquals(Object expected, Object actual) {
- assertEquals(iExplorerFixHtml(expected), iExplorerFixHtml(actual));
- }
-
- protected static String iExplorerFixHtml(Object s) {
- return s.toString().trim().toLowerCase().replaceAll(
- "[\r\n]", "").replaceAll(
- " ([\\w]+)=[\"']([^\"']+)[\"']", " $1=$2").replaceAll(
- "\\s+\\$h=\"[^\"]+\"", "").replaceAll(
- " added=[^ >]+", "");
- }
-
- public void gwtSetUp() {
- if (e == null) {
- testPanel = new HTML();
- RootPanel.get().add(testPanel);
- e = testPanel.getElement();
- e.setId("core-tst");
- } else {
- e.setInnerHTML("");
- }
- }
-
- protected static void assertArrayContains(Object result, Object... array) {
- assertArrayContains("", result, array);
- }
-
- protected static void assertArrayContains(String message, Object result, Object... array) {
- String values = "";
- boolean done = false;
- for (Object o : array) {
- values += o.toString() + " ";
- if (result.equals(o)) {
- done = true;
- }
- }
- message = message + ", value (" + result + ") not found in: " + values;
- assertTrue(message, done);
- }
-
- private boolean testRunning = false;
-
- protected void delayTestFinish(int millis) {
- testRunning = true;
- new Timer(){
- public void run() {
- assertFalse(testRunning);
- }
- }.schedule(millis);
- }
-
- protected void finishTest() {
- testRunning = false;
- }
-
- protected void fail() {
- check(false, "Test failure");
- }
-
- protected void fail(String msg) {
- check(false, msg);
- }
-
- protected void assertPosition(GQuery g, Offset min, Offset max) {
- int a = Math.min(min.top, max.top);
- int b = Math.max(min.top, max.top);
- int v = g.offset().top;
- boolean c = a <= v && v <= b;
- String msg = "Top has the value " + v + ", but should be in the range: "
- + a + " - " + b;
- assertTrue(msg, c);
-
- a = Math.min(min.left, max.left);
- b = Math.max(min.left, max.left);
- v = g.offset().left;
- c = a <= v && v <= b;
- msg = "Left has the value " + v + ", but should be in the range: " + a
- + " - " + b;
- assertTrue(msg, c);
- }
-}
+/* + * 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 com.google.gwt.dom.client.Element; +import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.RootPanel; +import static com.google.gwt.query.client.GQuery.*; + +/** + * Just a simple class to emulate JUnit TestCase. + */ +public class MyTestCase { + + static Element e = null; + static HTML testPanel = null; + + public static void assertEquals(Object a, Object b) { + check(a.equals(b), "assertEquals: expected=" + a + " actual=" + b); + } + + public static void assertFalse(boolean b) { + check(!b, "assertTrue: actual should be false but is true"); + } + + public static void assertFalse(String msg, boolean b) { + check(!b, msg); + } + + public static void assertNotNull(Object a) { + check(a != null, "assertNotNull: actual object is null"); + } + + public static void assertNull(Object a) { + check(a == null, "assertNull: actual object is not null"); + } + + public static void assertTrue(boolean b) { + check(b, "assertTrue: actual should be true but is false"); + } + + public static void assertTrue(String msg, boolean b) { + check(b, msg); + } + + public static void check(boolean condition, String message) { + if (!condition) { + RuntimeException ex = new RuntimeException(message); + ex.printStackTrace(); + throw ex; + } + } + + protected static void assertHtmlEquals(Object expected, Object actual) { + assertEquals(iExplorerFixHtml(expected), iExplorerFixHtml(actual)); + } + + protected static String iExplorerFixHtml(Object s) { + return s.toString().trim().toLowerCase().replaceAll( + "[\r\n]", "").replaceAll( + " ([\\w]+)=[\"']([^\"']+)[\"']", " $1=$2").replaceAll( + "\\s+\\$h=\"[^\"]+\"", "").replaceAll( + " added=[^ >]+", ""); + } + + public void gwtSetUp() { + if (e == null) { + testPanel = new HTML(); + RootPanel.get().add(testPanel); + e = testPanel.getElement(); + e.setId("core-tst"); + } else { + e.setInnerHTML(""); + } + } + + protected static void assertArrayContains(Object result, Object... array) { + assertArrayContains("", result, array); + } + + protected static void assertArrayContains(String message, Object result, Object... array) { + String values = ""; + boolean done = false; + for (Object o : array) { + values += o.toString() + " "; + if (result.equals(o)) { + done = true; + } + } + message = message + ", value (" + result + ") not found in: " + values; + assertTrue(message, done); + } + + private boolean testRunning = false; + + protected void delayTestFinish(int millis) { + testRunning = true; + new Timer(){ + public void run() { + assertFalse(testRunning); + } + }.schedule(millis); + } + + protected void finishTest() { + testRunning = false; + } + + protected void fail() { + check(false, "Test failure"); + } + + protected void fail(String msg) { + check(false, msg); + } + + protected void assertPosition(GQuery g, Offset min, Offset max) { + int a = Math.min(min.top, max.top); + int b = Math.max(min.top, max.top); + int v = g.offset().top; + boolean c = a <= v && v <= b; + String msg = "Top has the value " + v + ", but should be in the range: " + + a + " - " + b; + assertTrue(msg, c); + + a = Math.min(min.left, max.left); + b = Math.max(min.left, max.left); + v = g.offset().left; + c = a <= v && v <= b; + msg = "Left has the value " + v + ", but should be in the range: " + a + + " - " + b; + assertTrue(msg, c); + } +} diff --git a/devtest/src/main/java/com/google/gwt/query/public/test.html b/devtest/src/main/java/com/google/gwt/query/public/test.html index 42830523..1dff4d7e 100644 --- a/devtest/src/main/java/com/google/gwt/query/public/test.html +++ b/devtest/src/main/java/com/google/gwt/query/public/test.html @@ -1,9 +1,9 @@ -<!doctype html>
-<html>
- <head>
- </head>
- <body>
- <script src="test.nocache.js"></script>
- </body>
-</html>
-
+<!doctype html> +<html> + <head> + </head> + <body> + <script src="test.nocache.js"></script> + </body> +</html> + diff --git a/gwtquery-core-2.0.1/src/main/java/com/google/gwt/core/client/JsArrayMixed.java b/gwtquery-core-2.0.1/src/main/java/com/google/gwt/core/client/JsArrayMixed.java index dae68b3a..0639f8d9 100644 --- a/gwtquery-core-2.0.1/src/main/java/com/google/gwt/core/client/JsArrayMixed.java +++ b/gwtquery-core-2.0.1/src/main/java/com/google/gwt/core/client/JsArrayMixed.java @@ -1,12 +1,12 @@ /* * Copyright 2010 Google Inc. - * + * * 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 @@ -17,10 +17,10 @@ package com.google.gwt.core.client; /** * A simple wrapper around an heterogeneous native array of values. - * + * * This class may not be directly instantiated, and can only be returned from a * native method. For example, - * + * * <code> * native JsArrayMixed getNativeArray() /*-{ * return [ @@ -38,7 +38,7 @@ public class JsArrayMixed extends JavaScriptObject { /** * Gets the boolean at a given index. - * + * * @param index the index to be retrieved * @return the object at the given index, or <code>null</code> if none exists */ @@ -48,7 +48,7 @@ public class JsArrayMixed extends JavaScriptObject { /** * Gets the double at a given index. - * + * * @param index the index to be retrieved * @return the object at the given index, or <code>null</code> if none exists */ @@ -58,7 +58,7 @@ public class JsArrayMixed extends JavaScriptObject { /** * Gets the {@link JavaScriptObject} at a given index. - * + * * @param index the index to be retrieved * @return the {@code JavaScriptObject} at the given index, or * <code>null</code> if none exists @@ -69,7 +69,7 @@ public class JsArrayMixed extends JavaScriptObject { /** * Gets the String at a given index. - * + * * @param index the index to be retrieved * @return the object at the given index, or <code>null</code> if none exists */ @@ -98,7 +98,7 @@ public class JsArrayMixed extends JavaScriptObject { /** * Gets the length of the array. - * + * * @return the array length */ public final native int length() /*-{ @@ -135,10 +135,10 @@ public class JsArrayMixed extends JavaScriptObject { /** * Sets the boolean value at a given index. - * + * * If the index is out of bounds, the value will still be set. The array's * length will be updated to encompass the bounds implied by the added value. - * + * * @param index the index to be set * @param value the boolean to be stored */ @@ -148,10 +148,10 @@ public class JsArrayMixed extends JavaScriptObject { /** * Sets the double value at a given index. - * + * * If the index is out of bounds, the value will still be set. The array's * length will be updated to encompass the bounds implied by the added value. - * + * * @param index the index to be set * @param value the double to be stored */ @@ -161,10 +161,10 @@ public class JsArrayMixed extends JavaScriptObject { /** * Sets the object value at a given index. - * + * * If the index is out of bounds, the value will still be set. The array's * length will be updated to encompass the bounds implied by the added object. - * + * * @param index the index to be set * @param value the {@link JavaScriptObject} to be stored */ @@ -174,10 +174,10 @@ public class JsArrayMixed extends JavaScriptObject { /** * Sets the String value at a given index. - * + * * If the index is out of bounds, the value will still be set. The array's * length will be updated to encompass the bounds implied by the added String. - * + * * @param index the index to be set * @param value the String to be stored */ @@ -187,7 +187,7 @@ public class JsArrayMixed extends JavaScriptObject { /** * Reset the length of the array. - * + * * @param newLength the new length of the array */ public final native void setLength(int newLength) /*-{ @@ -196,7 +196,7 @@ public class JsArrayMixed extends JavaScriptObject { /** * Shifts the first value off the array. - * + * * @return the shifted boolean */ public final native boolean shiftBoolean() /*-{ @@ -205,7 +205,7 @@ public class JsArrayMixed extends JavaScriptObject { /** * Shifts the first value off the array. - * + * * @return the shifted double */ public final native double shiftNumber() /*-{ @@ -214,7 +214,7 @@ public class JsArrayMixed extends JavaScriptObject { /** * Shifts the first value off the array. - * + * * @return the shifted {@link JavaScriptObject} */ public final native <T extends JavaScriptObject> T shiftObject() /*-{ @@ -223,7 +223,7 @@ public class JsArrayMixed extends JavaScriptObject { /** * Shifts the first value off the array. - * + * * @return the shifted String */ public final native String shiftString() /*-{ @@ -232,7 +232,7 @@ public class JsArrayMixed extends JavaScriptObject { /** * Shifts a boolean onto the beginning of the array. - * + * * @param value the value to the stored */ public final native void unshift(boolean value) /*-{ @@ -241,7 +241,7 @@ public class JsArrayMixed extends JavaScriptObject { /** * Shifts a double onto the beginning of the array. - * + * * @param value the value to store */ public final native void unshift(double value) /*-{ @@ -250,7 +250,7 @@ public class JsArrayMixed extends JavaScriptObject { /** * Shifts a {@link JavaScriptObject} onto the beginning of the array. - * + * * @param value the value to store */ public final native void unshift(JavaScriptObject value) /*-{ @@ -259,7 +259,7 @@ public class JsArrayMixed extends JavaScriptObject { /** * Shifts a String onto the beginning of the array. - * + * * @param value the value to store */ public final native void unshift(String value) /*-{ diff --git a/gwtquery-core-2.0.1/src/main/java/com/google/gwt/query/linker/IFrameWithDocTypeLinker.java b/gwtquery-core-2.0.1/src/main/java/com/google/gwt/query/linker/IFrameWithDocTypeLinker.java index fca45d43..a1bbf53f 100644 --- a/gwtquery-core-2.0.1/src/main/java/com/google/gwt/query/linker/IFrameWithDocTypeLinker.java +++ b/gwtquery-core-2.0.1/src/main/java/com/google/gwt/query/linker/IFrameWithDocTypeLinker.java @@ -1,12 +1,12 @@ /* * Copyright 2009 Google Inc. - * + * * 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 diff --git a/gwtquery-core-2.0.1/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorCssToXPath.java b/gwtquery-core-2.0.1/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorCssToXPath.java index 04028ef0..688a6042 100644 --- a/gwtquery-core-2.0.1/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorCssToXPath.java +++ b/gwtquery-core-2.0.1/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorCssToXPath.java @@ -1,112 +1,112 @@ -/*
- * 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.rebind;
-
-import java.util.ArrayList;
-import java.util.regex.MatchResult;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathFactory;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.typeinfo.JMethod;
-import com.google.gwt.query.client.Selector;
-import com.google.gwt.query.client.impl.SelectorEngineCssToXPath;
-import com.google.gwt.query.client.impl.SelectorEngineCssToXPath.ReplaceCallback;
-import com.google.gwt.query.client.impl.SelectorEngineCssToXPath.Replacer;
-import com.google.gwt.user.rebind.SourceWriter;
-
-/**
- * Compile time selector generator which translates selector into XPath at
- * compile time. It Uses the SelectorEngineCssToXpath to produce the xpath
- * selectors
- */
-public class SelectorGeneratorCssToXPath extends SelectorGeneratorBase {
-
- /**
- * The replacer implementation for the JVM.
- */
- public static final Replacer replacerJvm = new Replacer() {
- public String replaceAll(String s, String r, Object o) {
- Pattern p = Pattern.compile(r);
- if (o instanceof ReplaceCallback) {
- final Matcher matcher = p.matcher(s);
- ReplaceCallback callback = (ReplaceCallback) o;
- while (matcher.find()) {
- final MatchResult matchResult = matcher.toMatchResult();
- ArrayList<String> argss = new ArrayList<String>();
- for (int i = 0; i < matchResult.groupCount() + 1; i++) {
- argss.add(matchResult.group(i));
- }
- final String replacement = callback.foundMatch(argss);
- s = s.substring(0, matchResult.start()) + replacement
- + s.substring(matchResult.end());
- matcher.reset(s);
- }
- return s;
- } else {
- return p.matcher(s).replaceAll(o.toString());
- }
- }
- };
-
- public static final Replacer replacer = replacerJvm;
-
- private SelectorEngineCssToXPath engine = new SelectorEngineCssToXPath(
- replacer);
-
- protected String css2Xpath(String s) {
- return engine.css2Xpath(s);
- }
-
- private XPathFactory factory = XPathFactory.newInstance();
- private XPath xpath = factory.newXPath();
-
- protected void generateMethodBody(SourceWriter sw, JMethod method,
- TreeLogger treeLogger, boolean hasContext)
- throws UnableToCompleteException {
-
- String selector = method.getAnnotation(Selector.class).value();
- String xselector = css2Xpath(selector);
-
- // Validate the generated xpath selector.
- try {
- validateXpath(xselector);
- } catch (XPathExpressionException e1) {
- System.err.println("Invalid XPath generated selector, please revise it: " + xselector);
- if (!selector.equals(xselector)) {
- System.err.println("If your css2 selector syntax is correct, open an issue in the gwtquery project. cssselector:"
- + selector + " xpath:" + xselector);
- }
- throw new UnableToCompleteException();
- }
-
- sw.println("return "
- + wrap(method, "xpathEvaluate(\"" + xselector + "\", root)") + ";");
- }
-
- public void validateXpath(String xselector) throws XPathExpressionException {
- xpath.compile(xselector);
- }
-
- protected String getImplSuffix() {
- return "CssToXPath" + super.getImplSuffix();
- }
-}
+/* + * 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.rebind; + +import java.util.ArrayList; +import java.util.regex.MatchResult; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.query.client.Selector; +import com.google.gwt.query.client.impl.SelectorEngineCssToXPath; +import com.google.gwt.query.client.impl.SelectorEngineCssToXPath.ReplaceCallback; +import com.google.gwt.query.client.impl.SelectorEngineCssToXPath.Replacer; +import com.google.gwt.user.rebind.SourceWriter; + +/** + * Compile time selector generator which translates selector into XPath at + * compile time. It Uses the SelectorEngineCssToXpath to produce the xpath + * selectors + */ +public class SelectorGeneratorCssToXPath extends SelectorGeneratorBase { + + /** + * The replacer implementation for the JVM. + */ + public static final Replacer replacerJvm = new Replacer() { + public String replaceAll(String s, String r, Object o) { + Pattern p = Pattern.compile(r); + if (o instanceof ReplaceCallback) { + final Matcher matcher = p.matcher(s); + ReplaceCallback callback = (ReplaceCallback) o; + while (matcher.find()) { + final MatchResult matchResult = matcher.toMatchResult(); + ArrayList<String> argss = new ArrayList<String>(); + for (int i = 0; i < matchResult.groupCount() + 1; i++) { + argss.add(matchResult.group(i)); + } + final String replacement = callback.foundMatch(argss); + s = s.substring(0, matchResult.start()) + replacement + + s.substring(matchResult.end()); + matcher.reset(s); + } + return s; + } else { + return p.matcher(s).replaceAll(o.toString()); + } + } + }; + + public static final Replacer replacer = replacerJvm; + + private SelectorEngineCssToXPath engine = new SelectorEngineCssToXPath( + replacer); + + protected String css2Xpath(String s) { + return engine.css2Xpath(s); + } + + private XPathFactory factory = XPathFactory.newInstance(); + private XPath xpath = factory.newXPath(); + + protected void generateMethodBody(SourceWriter sw, JMethod method, + TreeLogger treeLogger, boolean hasContext) + throws UnableToCompleteException { + + String selector = method.getAnnotation(Selector.class).value(); + String xselector = css2Xpath(selector); + + // Validate the generated xpath selector. + try { + validateXpath(xselector); + } catch (XPathExpressionException e1) { + System.err.println("Invalid XPath generated selector, please revise it: " + xselector); + if (!selector.equals(xselector)) { + System.err.println("If your css2 selector syntax is correct, open an issue in the gwtquery project. cssselector:" + + selector + " xpath:" + xselector); + } + throw new UnableToCompleteException(); + } + + sw.println("return " + + wrap(method, "xpathEvaluate(\"" + xselector + "\", root)") + ";"); + } + + public void validateXpath(String xselector) throws XPathExpressionException { + xpath.compile(xselector); + } + + protected String getImplSuffix() { + return "CssToXPath" + super.getImplSuffix(); + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/Query.gwt.xml b/gwtquery-core/src/main/java/com/google/gwt/query/Query.gwt.xml index 61cdd0df..c71a4361 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/Query.gwt.xml +++ b/gwtquery-core/src/main/java/com/google/gwt/query/Query.gwt.xml @@ -1,142 +1,142 @@ -<!--
- 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.
--->
-
-<module>
- <inherits name='com.google.gwt.user.User'/>
-
- <!-- Json and Xml builders -->
- <generate-with class="com.google.gwt.query.rebind.JsonBuilderGenerator">
- <when-type-assignable class="com.google.gwt.query.client.builders.JsonBuilder"/>
- </generate-with>
- <generate-with class="com.google.gwt.query.rebind.XmlBuilderGenerator">
- <when-type-assignable class="com.google.gwt.query.client.builders.XmlBuilder"/>
- </generate-with>
-
- <!-- Lazy Generator -->
- <generate-with class="com.google.gwt.query.rebind.LazyGenerator">
- <when-type-assignable class="com.google.gwt.query.client.Lazy"/>
- </generate-with>
-
- <!-- Selector Generators -->
- <generate-with class="com.google.gwt.query.rebind.SelectorGeneratorJS">
- <when-type-assignable class="com.google.gwt.query.client.Selectors"/>
- </generate-with>
- <generate-with class="com.google.gwt.query.rebind.SelectorGeneratorNative">
- <when-type-assignable class="com.google.gwt.query.client.Selectors"/>
- <any>
- <when-property-is name="user.agent" value="gecko1_8"/>
- <when-property-is name="user.agent" value="opera"/>
- <when-property-is name="user.agent" value="safari"/>
- </any>
- </generate-with>
- <generate-with class="com.google.gwt.query.rebind.SelectorGeneratorNativeIE8">
- <when-type-assignable class="com.google.gwt.query.client.Selectors"/>
- <when-property-is name="user.agent" value="ie8"/>
+<!-- + 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. +--> + +<module> + <inherits name='com.google.gwt.user.User'/> + + <!-- Json and Xml builders --> + <generate-with class="com.google.gwt.query.rebind.JsonBuilderGenerator"> + <when-type-assignable class="com.google.gwt.query.client.builders.JsonBuilder"/> </generate-with> - <generate-with class="com.google.gwt.query.rebind.SelectorGeneratorNativeIE9">
- <when-type-assignable class="com.google.gwt.query.client.Selectors"/>
- <when-property-is name="user.agent" value="ie9"/>
- </generate-with>
-
- <!-- Document Style -->
- <replace-with class="com.google.gwt.query.client.impl.DocumentStyleImpl">
- <when-type-assignable class="com.google.gwt.query.client.impl.DocumentStyleImpl"/>
- </replace-with>
- <replace-with class="com.google.gwt.query.client.impl.DocumentStyleImplIE">
- <when-type-assignable class="com.google.gwt.query.client.impl.DocumentStyleImpl"/>
- <any>
- <when-property-is name="user.agent" value="ie6"/>
- <when-property-is name="user.agent" value="ie8"/>
- <when-property-is name="user.agent" value="ie9"/>
- </any>
- </replace-with>
-
- <!-- Fall-back Engine for unsupported cases when using SelectorEngineImpl -->
- <replace-with class="com.google.gwt.query.client.impl.SelectorEngineCssToXPath">
- <when-type-assignable class="com.google.gwt.query.client.impl.HasSelector"/>
- </replace-with>
- <replace-with class="com.google.gwt.query.client.impl.SelectorEngineSizzleIE">
- <when-type-assignable class="com.google.gwt.query.client.impl.HasSelector"/>
- <any>
- <when-property-is name="user.agent" value="ie6"/>
- <when-property-is name="user.agent" value="ie8"/>
- <when-property-is name="user.agent" value="ie9"/>
- </any>
- </replace-with>
-
- <!-- Selector Engines -->
- <replace-with class="com.google.gwt.query.client.impl.SelectorEngineSizzle">
- <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/>
- </replace-with>
- <replace-with class="com.google.gwt.query.client.impl.SelectorEngineSizzleIE">
- <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/>
- <any>
- <when-property-is name="user.agent" value="ie6"/>
- </any>
- </replace-with>
- <replace-with class="com.google.gwt.query.client.impl.SelectorEngineNative">
- <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/>
- <any>
- <when-property-is name="user.agent" value="gecko1_8"/>
- <when-property-is name="user.agent" value="opera"/>
- <when-property-is name="user.agent" value="safari"/>
- <when-property-is name="user.agent" value="ie9"/>
- </any>
- </replace-with>
- <replace-with class="com.google.gwt.query.client.impl.SelectorEngineNativeIE8">
- <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/>
- <any>
- <when-property-is name="user.agent" value="ie8"/>
- </any>
- </replace-with>
-
- <!-- UI implementations -->
- <replace-with class="com.google.gwt.query.client.plugins.UiPlugin.GQueryUiImpl">
- <when-type-is class="com.google.gwt.query.client.plugins.UiPlugin.GQueryUiImpl" />
- </replace-with>
- <replace-with class="com.google.gwt.query.client.plugins.UiPlugin.GQueryUiImplTrident">
- <when-type-is class="com.google.gwt.query.client.plugins.UiPlugin.GQueryUiImpl" />
- <any>
- <when-property-is name="user.agent" value="ie6" />
- <when-property-is name="user.agent" value="ie8" />
- <when-property-is name="user.agent" value="ie9" />
- </any>
- </replace-with>
-
- <!-- Attribute setter implementations -->
- <replace-with class="com.google.gwt.query.client.impl.AttributeImpl">
- <when-type-is class="com.google.gwt.query.client.impl.AttributeImpl" />
- </replace-with>
- <replace-with class="com.google.gwt.query.client.impl.AttributeTridentImpl">
- <when-type-is class="com.google.gwt.query.client.impl.AttributeImpl" />
- <when-property-is name="user.agent" value="ie6" />
- </replace-with>
-
- <!-- JsUtils implementations -->
- <replace-with class="com.google.gwt.query.client.js.JsUtils.JsUtilsImpl">
- <when-type-is class="com.google.gwt.query.client.js.JsUtils.JsUtilsImpl" />
- </replace-with>
- <replace-with class="com.google.gwt.query.client.js.JsUtils.JsUtilsImplIE6">
- <when-type-is class="com.google.gwt.query.client.js.JsUtils.JsUtilsImpl" />
- <when-property-is name="user.agent" value="ie6" />
- </replace-with>
-
- <!-- IE8 needs the iframe where the js of app is loaded set to standard in order
- to use the queryAll native selector -->
- <define-linker name="stddoctype" class="com.google.gwt.query.linker.IFrameWithDocTypeLinker"/>
- <add-linker name="stddoctype"/>
-
-</module>
+ <generate-with class="com.google.gwt.query.rebind.XmlBuilderGenerator"> + <when-type-assignable class="com.google.gwt.query.client.builders.XmlBuilder"/> + </generate-with> + + <!-- Lazy Generator --> + <generate-with class="com.google.gwt.query.rebind.LazyGenerator"> + <when-type-assignable class="com.google.gwt.query.client.Lazy"/> + </generate-with> + + <!-- Selector Generators --> + <generate-with class="com.google.gwt.query.rebind.SelectorGeneratorJS"> + <when-type-assignable class="com.google.gwt.query.client.Selectors"/> + </generate-with> + <generate-with class="com.google.gwt.query.rebind.SelectorGeneratorNative"> + <when-type-assignable class="com.google.gwt.query.client.Selectors"/> + <any> + <when-property-is name="user.agent" value="gecko1_8"/> + <when-property-is name="user.agent" value="opera"/> + <when-property-is name="user.agent" value="safari"/> + </any> + </generate-with> + <generate-with class="com.google.gwt.query.rebind.SelectorGeneratorNativeIE8"> + <when-type-assignable class="com.google.gwt.query.client.Selectors"/> + <when-property-is name="user.agent" value="ie8"/> + </generate-with> + <generate-with class="com.google.gwt.query.rebind.SelectorGeneratorNativeIE9"> + <when-type-assignable class="com.google.gwt.query.client.Selectors"/> + <when-property-is name="user.agent" value="ie9"/> + </generate-with> + + <!-- Document Style --> + <replace-with class="com.google.gwt.query.client.impl.DocumentStyleImpl"> + <when-type-assignable class="com.google.gwt.query.client.impl.DocumentStyleImpl"/> + </replace-with> + <replace-with class="com.google.gwt.query.client.impl.DocumentStyleImplIE"> + <when-type-assignable class="com.google.gwt.query.client.impl.DocumentStyleImpl"/> + <any> + <when-property-is name="user.agent" value="ie6"/> + <when-property-is name="user.agent" value="ie8"/> + <when-property-is name="user.agent" value="ie9"/> + </any> + </replace-with> + + <!-- Fall-back Engine for unsupported cases when using SelectorEngineImpl --> + <replace-with class="com.google.gwt.query.client.impl.SelectorEngineCssToXPath"> + <when-type-assignable class="com.google.gwt.query.client.impl.HasSelector"/> + </replace-with> + <replace-with class="com.google.gwt.query.client.impl.SelectorEngineSizzleIE"> + <when-type-assignable class="com.google.gwt.query.client.impl.HasSelector"/> + <any> + <when-property-is name="user.agent" value="ie6"/> + <when-property-is name="user.agent" value="ie8"/> + <when-property-is name="user.agent" value="ie9"/> + </any> + </replace-with> + + <!-- Selector Engines --> + <replace-with class="com.google.gwt.query.client.impl.SelectorEngineSizzle"> + <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/> + </replace-with> + <replace-with class="com.google.gwt.query.client.impl.SelectorEngineSizzleIE"> + <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/> + <any> + <when-property-is name="user.agent" value="ie6"/> + </any> + </replace-with> + <replace-with class="com.google.gwt.query.client.impl.SelectorEngineNative"> + <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/> + <any> + <when-property-is name="user.agent" value="gecko1_8"/> + <when-property-is name="user.agent" value="opera"/> + <when-property-is name="user.agent" value="safari"/> + <when-property-is name="user.agent" value="ie9"/> + </any> + </replace-with> + <replace-with class="com.google.gwt.query.client.impl.SelectorEngineNativeIE8"> + <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/> + <any> + <when-property-is name="user.agent" value="ie8"/> + </any> + </replace-with> + + <!-- UI implementations --> + <replace-with class="com.google.gwt.query.client.plugins.UiPlugin.GQueryUiImpl"> + <when-type-is class="com.google.gwt.query.client.plugins.UiPlugin.GQueryUiImpl" /> + </replace-with> + <replace-with class="com.google.gwt.query.client.plugins.UiPlugin.GQueryUiImplTrident"> + <when-type-is class="com.google.gwt.query.client.plugins.UiPlugin.GQueryUiImpl" /> + <any> + <when-property-is name="user.agent" value="ie6" /> + <when-property-is name="user.agent" value="ie8" /> + <when-property-is name="user.agent" value="ie9" /> + </any> + </replace-with> + + <!-- Attribute setter implementations --> + <replace-with class="com.google.gwt.query.client.impl.AttributeImpl"> + <when-type-is class="com.google.gwt.query.client.impl.AttributeImpl" /> + </replace-with> + <replace-with class="com.google.gwt.query.client.impl.AttributeTridentImpl"> + <when-type-is class="com.google.gwt.query.client.impl.AttributeImpl" /> + <when-property-is name="user.agent" value="ie6" /> + </replace-with> + + <!-- JsUtils implementations --> + <replace-with class="com.google.gwt.query.client.js.JsUtils.JsUtilsImpl"> + <when-type-is class="com.google.gwt.query.client.js.JsUtils.JsUtilsImpl" /> + </replace-with> + <replace-with class="com.google.gwt.query.client.js.JsUtils.JsUtilsImplIE6"> + <when-type-is class="com.google.gwt.query.client.js.JsUtils.JsUtilsImpl" /> + <when-property-is name="user.agent" value="ie6" /> + </replace-with> + + <!-- IE8 needs the iframe where the js of app is loaded set to standard in order + to use the queryAll native selector --> + <define-linker name="stddoctype" class="com.google.gwt.query.linker.IFrameWithDocTypeLinker"/> + <add-linker name="stddoctype"/> + +</module> diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/QueryMin.gwt.xml b/gwtquery-core/src/main/java/com/google/gwt/query/QueryMin.gwt.xml index 9678a7ee..4a9b0fd0 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/QueryMin.gwt.xml +++ b/gwtquery-core/src/main/java/com/google/gwt/query/QueryMin.gwt.xml @@ -1,72 +1,72 @@ -<!--
- 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.
--->
-
-<!-- Include com.google.gwt.query.QueryMin instead of com.google.gwt.query.Query-->
-<!-- if you want small javascript code and you are not using any of the selectors: -->
-<!-- ".*(:contains|!=|:checked|:not|:nth-|:last-|:only-).*"-->
-<!-- Note: that this will increase the number of total permutations. -->
-<module>
-
- <!-- Inherit GQuery module -->
- <inherits name='com.google.gwt.query.Query'/>
-
- <!-- Detect whether querySelectorAll is available -->
- <define-property name="selectorCapability" values="native,js"/>
- <property-provider name="selectorCapability">
- <![CDATA[
- return !/_force_no_native/.test(document.location.search) &&
- document.querySelectorAll &&
- /native/.test(String(document.querySelectorAll)) ? "native" : "js";
- ]]>
- </property-provider>
-
- <set-property name="selectorCapability" value="js" >
- <when-property-is name="user.agent" value="ie6" />
- </set-property>
- <set-property name="selectorCapability" value="native" >
- <any>
- <when-property-is name="user.agent" value="safari" />
- </any>
- </set-property>
-
- <!-- Selector Engines -->
- <replace-with class="com.google.gwt.query.client.impl.SelectorEngineNativeMin">
- <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/>
- <any>
- <when-property-is name="user.agent" value="gecko1_8"/>
- <when-property-is name="user.agent" value="opera"/>
- <when-property-is name="user.agent" value="safari"/>
- </any>
- <when-property-is name="selectorCapability" value="native"/>
- </replace-with>
- <replace-with class="com.google.gwt.query.client.impl.SelectorEngineCssToXPath">
- <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/>
- <any>
- <when-property-is name="user.agent" value="gecko1_8"/>
- <when-property-is name="user.agent" value="opera"/>
- <when-property-is name="user.agent" value="safari"/>
- </any>
- <when-property-is name="selectorCapability" value="js"/>
- </replace-with>
- <replace-with class="com.google.gwt.query.client.impl.SelectorEngineNativeMinIE8">
- <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/>
- <any>
- <when-property-is name="user.agent" value="ie8"/>
- <when-property-is name="user.agent" value="ie9"/>
- </any>
- <when-property-is name="selectorCapability" value="native"/>
- </replace-with>
-</module>
+<!-- + 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. +--> + +<!-- Include com.google.gwt.query.QueryMin instead of com.google.gwt.query.Query--> +<!-- if you want small javascript code and you are not using any of the selectors: --> +<!-- ".*(:contains|!=|:checked|:not|:nth-|:last-|:only-).*"--> +<!-- Note: that this will increase the number of total permutations. --> +<module> + + <!-- Inherit GQuery module --> + <inherits name='com.google.gwt.query.Query'/> + + <!-- Detect whether querySelectorAll is available --> + <define-property name="selectorCapability" values="native,js"/> + <property-provider name="selectorCapability"> + <![CDATA[ + return !/_force_no_native/.test(document.location.search) && + document.querySelectorAll && + /native/.test(String(document.querySelectorAll)) ? "native" : "js"; + ]]> + </property-provider> + + <set-property name="selectorCapability" value="js" > + <when-property-is name="user.agent" value="ie6" /> + </set-property> + <set-property name="selectorCapability" value="native" > + <any> + <when-property-is name="user.agent" value="safari" /> + </any> + </set-property> + + <!-- Selector Engines --> + <replace-with class="com.google.gwt.query.client.impl.SelectorEngineNativeMin"> + <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/> + <any> + <when-property-is name="user.agent" value="gecko1_8"/> + <when-property-is name="user.agent" value="opera"/> + <when-property-is name="user.agent" value="safari"/> + </any> + <when-property-is name="selectorCapability" value="native"/> + </replace-with> + <replace-with class="com.google.gwt.query.client.impl.SelectorEngineCssToXPath"> + <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/> + <any> + <when-property-is name="user.agent" value="gecko1_8"/> + <when-property-is name="user.agent" value="opera"/> + <when-property-is name="user.agent" value="safari"/> + </any> + <when-property-is name="selectorCapability" value="js"/> + </replace-with> + <replace-with class="com.google.gwt.query.client.impl.SelectorEngineNativeMinIE8"> + <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/> + <any> + <when-property-is name="user.agent" value="ie8"/> + <when-property-is name="user.agent" value="ie9"/> + </any> + <when-property-is name="selectorCapability" value="native"/> + </replace-with> +</module> diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Function.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Function.java index f6a7b82c..361eea1f 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Function.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Function.java @@ -1,12 +1,12 @@ /* * 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 @@ -25,33 +25,33 @@ import com.google.gwt.user.client.ui.Widget; * Extend this class to implement functions callbacks. */ public abstract class Function { - + private com.google.gwt.dom.client.Element element = null; private Event event = null; private int index = -1; private Object[] data = new Object[0]; - + public <T extends com.google.gwt.dom.client.Element> T getElement() { return element.<T>cast(); } - + public <T extends com.google.gwt.dom.client.Element> void setElement(T e) { element = e; } - + public void setEvent(Event e) { event = e; element = e != null ? e.getCurrentEventTarget().<com.google.gwt.dom.client.Element>cast() : null; } - + public Event getEvent() { return event; } - + public void setIndex(int i) { index = i; } - + public Object[] getData() { return data; } @@ -59,7 +59,7 @@ public abstract class Function { public void setData(Object...data) { this.data = data; } - + public Object getDataObject() { return getDataObject(0); } @@ -67,11 +67,11 @@ public abstract class Function { public Object getDataObject(int idx) { return data != null && data.length > idx ? data[idx] : null; } - + public Properties getDataProperties() { return getDataProperties(0); } - + public Properties getDataProperties(int idx) { Object o = getDataObject(idx); if (o != null && o instanceof JavaScriptObject) { @@ -87,20 +87,20 @@ public abstract class Function { public void setData(double b) { setData(Double.valueOf(b)); } - + public void setDataObject(Object data) { setData(data); } - + public int getIndex() { return index; } - + /** * Override this for methods which invoke a cancel action. - * + * * @param e takes a com.google.gwt.dom.client.Element. - * + * */ public void cancel(com.google.gwt.dom.client.Element e) { setElement(e); @@ -110,9 +110,9 @@ public abstract class Function { /** * Override this for methods which invoke a cancel action. - * + * * @param e takes a com.google.gwt.user.client.Element. - * + * */ public void cancel(com.google.gwt.user.client.Element e) { setElement(e); @@ -129,23 +129,23 @@ public abstract class Function { /** * Override this for GQuery methods which loop over matched elements and * invoke a callback on each element. - * + * * @param e takes a com.google.gwt.dom.client.Element. - * + * */ public Object f(com.google.gwt.dom.client.Element e, int i) { setElement(e); setIndex(i); // This has to be the order of calls - return f(e.<com.google.gwt.user.client.Element>cast(), i); + return f(e.<com.google.gwt.user.client.Element>cast(), i); } /** * Override this for GQuery methods which loop over matched elements and * invoke a callback on each element. - * + * * @param e takes a com.google.gwt.user.client.Element. - * + * */ public Object f(com.google.gwt.user.client.Element e, int i) { setElement(e); @@ -162,10 +162,10 @@ public abstract class Function { /** * Override this for GQuery methods which loop over matched widgets and * invoke a callback on each widget. - * - * NOTE: If your query has non-widget elements you might need to override + * + * NOTE: If your query has non-widget elements you might need to override * 'public void f()' or 'public void f(Element e)' to handle these elements and - * avoid a runtime exception. + * avoid a runtime exception. */ public Object f(Widget w, int i) { setElement(w.getElement()); @@ -173,21 +173,21 @@ public abstract class Function { f(w); return null; } - + /** * Override this method for bound callbacks */ public void f(Object... data) { fe(data); } - + /** * Override this method for bound callbacks */ public void f(int i, Object data) { f(i, new Object[]{data}); } - + /** * Override this method for bound callbacks */ @@ -206,7 +206,7 @@ public abstract class Function { } } } - + /** * Override this method for bound event handlers if you wish to deal with * per-handler user data. @@ -219,19 +219,19 @@ public abstract class Function { /** * Override this method for bound event handlers. - * - * @return boolean: false means stop propagation and prevent default + * + * @return boolean: false means stop propagation and prevent default */ public boolean f(Event e) { setEvent(e); f(element); return true; } - + /** * Override this for GQuery methods which take a callback and do not expect a * return value. - * + * * @param e takes a com.google.gwt.dom.client.Element */ public void f(com.google.gwt.dom.client.Element e) { @@ -239,11 +239,11 @@ public abstract class Function { // This has to be the order of calls f(e.<com.google.gwt.user.client.Element>cast()); } - + /** * Override this for GQuery methods which take a callback and do not expect a * return value. - * + * * @param e takes a com.google.gwt.user.client.Element */ private boolean loop = false; @@ -257,14 +257,14 @@ public abstract class Function { f(); } } - + /** * Override this for GQuery methods which take a callback, but do not expect a * return value, apply to a single widget. - * - * NOTE: If your query has non-widget elements you might need to override + * + * NOTE: If your query has non-widget elements you might need to override * 'public void f()' or 'public void f(Element e)' to handle these elements and - * avoid a runtime exception. + * avoid a runtime exception. */ public void f(Widget w){ setElement(w.getElement()); @@ -279,7 +279,7 @@ public abstract class Function { /** * Methods fe(...) should be used from asynchronous contexts so as we can * catch the exception and send it to the GWT UncaughtExceptionHandler. - * They are intentionally final to avoid override them + * They are intentionally final to avoid override them */ public final void fe() { fe(data); @@ -288,16 +288,16 @@ public abstract class Function { /** * Methods fe(...) should be used from asynchronous contexts so as we can * catch the exception and send it to the GWT UncaughtExceptionHandler - * They are intentionally final to avoid override them + * They are intentionally final to avoid override them */ public final void fe(Object data) { fe(new Object[]{data}); } - + /** * Methods fe(...) should be used from asynchronous contexts so as we can * catch the exception and send it to the GWT UncaughtExceptionHandler - * They are intentionally final to avoid override them + * They are intentionally final to avoid override them */ public final void fe(Object... data) { setData(data); @@ -315,7 +315,7 @@ public abstract class Function { /** * Methods fe(...) should be used from asynchronous contexts so as we can * catch the exception and send it to the GWT UncaughtExceptionHandler - * They are intentionally final to avoid override them + * They are intentionally final to avoid override them */ public final boolean fe(Event ev, Object data) { if (GWT.getUncaughtExceptionHandler() != null) { @@ -328,11 +328,11 @@ public abstract class Function { } return f(ev, data); } - + /** * Methods fe(...) should be used from asynchronous contexts so as we can * catch the exception and send it to the GWT UncaughtExceptionHandler - * They are intentionally final to avoid override them + * They are intentionally final to avoid override them */ public final void fe(com.google.gwt.dom.client.Element elem) { if (GWT.getUncaughtExceptionHandler() != null) { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java index f6912470..caf188f1 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java @@ -1,4656 +1,4656 @@ -/*
- * 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 java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-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.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.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.Style.HasCssName;
-import com.google.gwt.dom.client.TextAreaElement;
-import com.google.gwt.query.client.css.CSS;
-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.JsRegexp;
-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.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.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;
-
-/**
- * GwtQuery is a GWT clone of the popular jQuery library.
- */
-public class GQuery implements Lazy<GQuery, LazyGQuery> {
-
- 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 = Document.get().getBody();
-
- /**
- * 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 = Document.get();
-
- /**
- * Static reference Effects plugin
- */
- public static Class<Effects> 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> Events = com.google.gwt.query.client.plugins.Events.Events;
-
- /**
- * A static reference to the GQuery class.
- */
- public static Class<GQuery> GQUERY = GQuery.class;
-
- private static final String OLD_DATA_PREFIX = "old-";
-
- private static final String OLD_DISPLAY = OLD_DATA_PREFIX + "display";
-
- private static JsMap<Class<? extends GQuery>, Plugin<? extends GQuery>> plugins;
-
- // Sizzle POS regex : usefull in some methods
- // TODO: Share this static with SelectorEngineSizzle
- private static final String POS_REGEX =
- ":(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)";
-
- /**
- * Implementation class used for style manipulations.
- */
- private static DocumentStyleImpl styleImpl;
-
- private static JsRegexp tagNameRegex = new JsRegexp("<([\\w:]+)");
-
- /**
- * Static reference to the Widgets plugin
- */
- public static Class<Widgets> Widgets = com.google.gwt.query.client.plugins.Widgets.Widgets;
-
- /**
- * The window object.
- */
- public static final Element window = window();
-
- private static Element windowData = null;
-
- private static JsNamedArray<TagWrapper> wrapperMap;
-
- /**
- * Create an empty GQuery object.
- */
- public static GQuery $() {
- return new GQuery(JsNodeArray.create());
- }
-
- /**
- * Wrap a GQuery around an existing element.
- */
- public static GQuery $(Element element) {
- return new GQuery(element);
- }
-
- /**
- * Wrap a GQuery around an event's target element.
- */
- public static GQuery $(Event event) {
- return event == null ? $() : $((Element) event.getCurrentEventTarget().cast());
- }
-
- /**
- * Wrap a GQuery around the element of a Function callback.
- */
- public static GQuery $(Function f) {
- return $(f.getElement());
- }
-
- /**
- * Wrap a GQuery around an existing javascript element, event, node, nodelist, function or array.
- */
- public static GQuery $(JavaScriptObject jso) {
- if (jso == null) {
- return $();
- }
- // 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 $((NodeList<Element>)elms);
- }
-
- return JsUtils.isWindow(jso) ? $(jso.<Element> cast()) :
- JsUtils.isElement(jso) ? $(jso.<Element> cast()) :
- JsUtils.isEvent(jso) ? $(jso.<Event> cast()) :
- JsUtils.isNodeList(jso) ? $(jso.<NodeList<Element>> cast()) : $();
- }
-
- /**
- * 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 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 GQuery) {
- return (GQuery)o;
- }
- if (o instanceof Function) {
- return $((Function)o);
- }
- if (o instanceof JavaScriptObject) {
- return $((JavaScriptObject)o);
- }
- if (o instanceof IsWidget) {
- return $(Arrays.asList(o));
- }
- System.err.println("GQuery.$(Object o) could not wrap the type : " + o.getClass());
- }
- return $();
- }
-
- /**
- * Create a new GQuery given a list of nodes, elements or widgets
- */
- 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);
- }
-
- /**
- * Wrap a GQuery around an existing node.
- */
- public static GQuery $(Node n) {
- return $((Element) n);
- }
-
- /**
- * Wrap a GQuery around existing Elements.
- */
- public static GQuery $(NodeList<Element> elms) {
- 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 extends GQuery> T $(String selector, Class<T> 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 extends GQuery> T $(String selector, Node context, Class<T> 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 extends GQuery> T $(String selector, Widget context, Class<T> 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 JSON object.
- */
- public static Properties $$(String properties) {
- return Properties.create(properties);
- }
-
- /**
- * Perform an ajax request to the server.
- */
- public static void ajax(Properties p) {
- ajax(p);
- }
-
- /**
- * Perform an ajax request to the server.
- */
- public static void ajax(Settings settings) {
- Ajax.ajax(settings);
- }
-
- /**
- * Perform an ajax request to the server.
- */
- public static void ajax(String url, Settings settings) {
- Ajax.ajax(url, settings);
- }
-
- @SuppressWarnings("unchecked")
- protected static GQuery cleanHtmlString(String elem, Document doc) {
-
- String tag = tagNameRegex.exec(elem).get(1);
-
- if (tag == null) {
- throw new RuntimeException("HTML snippet doesn't contain any tag");
- }
-
- 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 <script> tag
- // TODO: add fixes for IE TBODY issue
-
- // We use a temporary element to wrap the elements
- Element div = doc.createDivElement();
- div.setInnerHTML(wrapper.preWrap + elem.trim() + wrapper.postWrap);
- Node n = div;
- int depth = wrapper.wrapDepth;
- while (depth-- != 0) {
- n = n.getLastChild();
- }
-
- return
- // return all nodes added to the wrapper
- $(n.getChildNodes())
- // detach nodes from their temporary parent
- .remove(null, false);
- }
-
- /**
- * Return true if the element b is contained in a.
- */
- public static boolean contains(Element a, Element b) {
- return engine.contains(a, b);
- }
-
- /**
- * Get the element data matching the key.
- */
- public static Object data(Element e, String key) {
- return GQuery.data(e, key, null);
- }
-
- /**
- * We store data in js object which has this structure:
- *
- * datacache [element_hash] [key] = value
- *
- * @return the value stored in the element with the given name
- */
- protected static <S> Object data(Element element, String key, S value) {
- if (dataCache == null) {
- windowData = JavaScriptObject.createObject().cast();
- dataCache = JavaScriptObject.createObject().cast();
- }
- element = element == window || element.getNodeName() == null ? windowData : element;
- if (element != null && key != null) {
- int id = element.hashCode();
-
- if (value == null) {
- return dataCache.exists(id) ? dataCache.getCache(id).get(key) : null;
- }
-
- if (!dataCache.exists(id)) {
- dataCache.put(id, JsCache.createObject().cast());
- }
- dataCache.getCache(id).put(key, value);
- }
- return value;
- }
-
- /**
- * Execute a function around each object
- */
- public static void each(JsArrayMixed objects, Function f) {
- for (int i = 0, l = objects.length(); i < l; i++) {
- f.f(i, objects.getObject(i));
- }
- }
-
- /**
- * Execute a function around each object
- */
- public static <T> void each(List<T> objects, Function f) {
- for (int i = 0, l = objects.size(); i < l; i++) {
- f.f(i, objects.get(i));
- }
- }
-
- /**
- * Execute a function around each object
- */
- public static <T> void each(T[] objects, Function f) {
- for (int i = 0, l = objects.length; i < l; i++) {
- f.f(i, objects[i]);
- }
- }
-
- /**
- * Perform an ajax request to the server using GET.
- */
- public static void get(String url, Properties data, final Function onSuccess) {
- Ajax.get(url, data, onSuccess);
- }
-
- /**
- * We will use the fact as GWT use the widget itself as EventListener ! If no Widget associated
- * with the element, this method returns null.
- */
- protected static Widget getAssociatedWidget(Element e) {
- try {
- EventListener listener = DOM.getEventListener((com.google.gwt.user.client.Element) e);
- // No listener attached to the element, so no widget exist for this element
- if (listener == null) {
- return null;
- }
- if (listener instanceof Widget) {
- // GWT uses the widget as event listener
- return (Widget) listener;
- } else if (listener instanceof EventsListener) {
- // GQuery replaces the gwt event listener and save it
- EventsListener gQueryListener = (EventsListener) listener;
- if (gQueryListener.getOriginalEventListener() != null
- && gQueryListener.getOriginalEventListener() instanceof Widget) {
- return (Widget) gQueryListener.getOriginalEventListener();
- }
- }
- } catch (Exception e2) {
- // Some times this code could raise an exception.
- // We do not want GQuery to fail, but in dev-mode we log the error.
- e2.printStackTrace();
- }
- return null;
- }
-
- private static AttributeImpl getAttributeImpl() {
- if (attributeImpl == null) {
- attributeImpl = GWT.create(AttributeImpl.class);
- }
- return attributeImpl;
- }
-
- /**
- * Perform an ajax request to the server using POST and parsing the json response.
- */
- public static void getJSON(String url, Properties data, final Function onSuccess) {
- Ajax.getJSON(url, data, onSuccess);
- }
-
- /**
- * Perform an ajax request to the server using scripts tags and parsing the json response. The
- * request is not subject to the same origin policy restrictions.
- *
- * Server side should accept a parameter to specify the callback funcion name, and it must return
- * a valid json object wrapped this callback function.
- *
- * Example:
- *
- * <pre>
- Client code:
- getJSONP("http://server.exampe.com/getData.php",$$("myCallback:'?', otherParameter='whatever'"),
- new Function(){ public void f() {
- Properties p = getDataProperties();
- alert(p.getStr("k1");
- }});
-
- Server response:
- myCallback({"k1":"v1", "k2":"v2"});
- </pre>
- *
- */
- public static void getJSONP(String url, Properties data, final Function onSuccess) {
- Ajax.getJSONP(url, data, onSuccess);
- }
-
- protected static DocumentStyleImpl getStyleImpl() {
- if (styleImpl == null) {
- styleImpl = GWT.create(DocumentStyleImpl.class);
- }
- return styleImpl;
- }
-
- /**
- * Return only the set of objects with match the predicate.
- */
- @SuppressWarnings("unchecked")
- public static <T> T[] grep(T[] objects, Predicate f) {
- ArrayList<Object> ret = new ArrayList<Object>();
- for (int i = 0, l = objects.length; i < l; i++) {
- if (f.f(objects[i], i)) {
- ret.add(objects[i]);
- }
- }
- return (T[]) ret.toArray(new Object[0]);
- }
-
- private static boolean hasClass(Element e, String clz) {
- return e.getClassName().matches("(^|.*\\s)" + clz + "(\\s.*|$)");
- }
-
- private static void initWrapperMap() {
-
- TagWrapper tableWrapper = new TagWrapper(1, "<table>", "</table>");
- TagWrapper selectWrapper = new TagWrapper(1, "<select multiple=\"multiple\">", "</select>");
- TagWrapper trWrapper = new TagWrapper(3, "<table><tbody><tr>", "</tr></tbody></table>");
-
- wrapperMap = JsNamedArray.create();
- wrapperMap.put("option", selectWrapper);
- wrapperMap.put("optgroup", selectWrapper);
- wrapperMap.put("legend", new TagWrapper(1, "<fieldset>", "</fieldset>"));
- wrapperMap.put("thead", tableWrapper);
- wrapperMap.put("tbody", tableWrapper);
- wrapperMap.put("tfoot", tableWrapper);
- wrapperMap.put("colgroup", tableWrapper);
- wrapperMap.put("caption", tableWrapper);
- wrapperMap.put("tr", new TagWrapper(2, "<table><tbody>", "</tbody></table>"));
- wrapperMap.put("td", trWrapper);
- wrapperMap.put("th", trWrapper);
- wrapperMap.put("col", new TagWrapper(2, "<table><tbody></tbody><colgroup>",
- "</colgroup></table>"));
- wrapperMap.put("area", new TagWrapper(1, "<map>", "</map>"));
-
- }
-
- private static GQuery innerHtml(String html, Document doc) {
- return cleanHtmlString(html, doc);
- }
-
- protected static String[] jsArrayToString(JsArrayString array) {
- if (GWT.isScript()) {
- return jsArrayToString0(array);
- } else {
- String result[] = new String[array.length()];
- for (int i = 0, l = result.length; i < l; i++) {
- result[i] = array.get(i);
- }
- return result;
- }
- }
-
- private static native String[] jsArrayToString0(JsArrayString array) /*-{
- return array;
- }-*/;
-
- /**
- * Return a lazy version of the GQuery interface. Lazy function calls are simply queued up and not
- * executed immediately.
- */
- public static LazyGQuery<?> lazy() {
- return $().createLazy();
- }
-
- /**
- * Perform an ajax request to the server using POST.
- */
- public static void post(String url, Properties data, final Function onSuccess) {
- Ajax.post(url, data, onSuccess);
- }
-
- public static <T extends GQuery> Class<T> registerPlugin(Class<T> plugin, Plugin<T> pluginFactory) {
- if (plugins == null) {
- plugins = JsMap.createObject().cast();
- }
-
- plugins.put(plugin, pluginFactory);
- return plugin;
- }
-
- private static native void scrollIntoViewImpl(Node n) /*-{
- if (n)
- n.scrollIntoView()
- }-*/;
-
- private static native void setElementValue(Element e, String value) /*-{
- e.value = value;
- }-*/;
-
- private static native Element window() /*-{
- return $wnd;
- }-*/;
-
- protected Node currentContext;
-
- protected String currentSelector;
- /**
- * Immutable array of matched elements, modify this using setArray
- */
- private Element[] elements = new Element[0];
-
- /**
- * The nodeList of matched elements, modify this using setArray
- */
- // TODO: remove this and use elements, change return type of get()
- private NodeList<Element> nodeList = JavaScriptObject.createArray().cast();
-
- private GQuery previousObject;
-
- private GQuery() {
- }
-
- private GQuery(Element element) {
- this(JsNodeArray.create(element));
- }
-
- protected GQuery(GQuery gq) {
- this(gq == null ? null : gq.get());
- currentSelector = gq.getSelector();
- currentContext = gq.getContext();
- }
-
- private GQuery(JsNodeArray nodes) {
- this(nodes.<NodeList<Element>> cast());
- }
-
- private GQuery(NodeList<Element> list) {
- setArray(list);
- }
-
- /**
- * Add elements to the set of matched elements if they are not included yet.
- *
- * It construct a new GQuery object and does not modify the original ones.
- *
- * It also update the selector appending the new one.
- */
- public GQuery add(GQuery elementsToAdd) {
- return pushStack(JsUtils.copyNodeList(nodeList, elementsToAdd.nodeList, true)
- .<JsNodeArray> cast(), "add", getSelector() + "," + elementsToAdd.getSelector());
- }
-
- /**
- * Add elements to the set of matched elements if they are not included yet.
- */
- public GQuery add(String selector) {
- return add($(selector));
- }
-
- /**
- * Adds the specified classes to each matched element.
- */
- public GQuery addClass(String... classes) {
- for (Element e : elements) {
- // issue 81 : ensure that the element is an Element node.
- if (Element.is(e)) {
- for (String clz : classes) {
- e.addClassName(clz);
- }
- }
- }
- return this;
- }
-
- /**
- * Insert content after each of the matched elements. The elements must already be inserted into
- * the document (you can't insert an element after another if it's not in the page).
- */
- public GQuery after(GQuery query) {
- return domManip(query, DomMan.AFTER);
- }
-
- /**
- * Insert content after each of the matched elements. The elements must already be inserted into
- * the document (you can't insert an element after another if it's not in the page).
- */
- public GQuery after(Node n) {
- return domManip($(n), DomMan.AFTER);
- }
-
- /**
- * Insert content after each of the matched elements. The elements must already be inserted into
- * the document (you can't insert an element after another if it's not in the page).
- */
- public GQuery after(String html) {
- return domManip(html, DomMan.AFTER);
- }
-
- private void allNextSiblingElements(Element firstChildElement, JsNodeArray result, Element elem,
- GQuery until, String filterSelector) {
-
- while (firstChildElement != null) {
-
- if (until != null && until.index(firstChildElement) != -1) {
- return;
- }
-
- if (firstChildElement != elem
- && (filterSelector == null || $(firstChildElement).is(filterSelector))) {
- result.addNode(firstChildElement);
- }
- firstChildElement = firstChildElement.getNextSiblingElement();
- }
- }
-
- private void allPreviousSiblingElements(Element firstChildElement, JsNodeArray result,
- GQuery until, String filterSelector) {
- while (firstChildElement != null) {
- if (until != null && until.index(firstChildElement) != -1) {
- return;
- }
-
- if (filterSelector == null || $(firstChildElement).is(filterSelector)) {
- result.addNode(firstChildElement);
- }
-
- firstChildElement = getPreviousSiblingElement(firstChildElement);
- }
- }
-
- /**
- * Add the previous selection to the current selection. Useful for traversing elements, and then
- * adding something that was matched before the last traversal.
- */
- public GQuery andSelf() {
- return add(previousObject);
- }
-
- /**
- *
- * The animate() method allows you to create animation effects on any numeric Attribute, CSS
- * property, or color CSS property.
- *
- * Concerning to numeric properties, values are treated as a number of pixels unless otherwise
- * specified. The units em and % can be specified where applicable.
- *
- * By default animate considers css properties, if you wanted to animate element attributes you
- * should to prepend the symbol dollar to the attribute name.
- *
- * Example:
- *
- * <pre class="code">
- * //move the element from its original position to left:500px for 500ms
- * $("#foo").animate("left:'500'");
- * // Change the width attribute of a table
- * $("table").animate("$width:'500'"), 400, Easing.LINEAR);
- * </pre>
- *
- * In addition to numeric values, each property can take the strings 'show', 'hide', and 'toggle'.
- * These shortcuts allow for custom hiding and showing animations that take into account the
- * display type of the element. Animated properties can also be relative. If a value is supplied
- * with a leading += or -= sequence of characters, then the target value is computed by adding or
- * subtracting the given number from the current value of the property.
- *
- * Example:
- *
- * <pre class="code">
- * //move the element from its original position to 500px to the left for 500ms and
- * // change the background color of the element at the end of the animation
- * $("#foo").animate("left:'+=500'", new Function(){
- *
- * public void f(Element e){
- * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED);
- * }
- *
- * });
- * </pre>
- *
- * The duration of the animation is 500ms.
- *
- * For color css properties, values can be specified via hexadecimal or rgb or literal values.
- *
- * Example:
- *
- * <pre class="code">
- * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'");
- * </pre>
- *
- * @param prop the property to animate : "cssName:'value'"
- * @param funcs an array of {@link Function} called once the animation is complete
- */
- public GQuery animate(Object stringOrProperties, Function... funcs) {
- return as(Effects).animate(stringOrProperties, funcs);
- }
-
- /**
- * The animate() method allows you to create animation effects on any numeric Attribute, CSS
- * property, or color CSS property.
- *
- * Concerning to numeric properties, values are treated as a number of pixels unless otherwise
- * specified. The units em and % can be specified where applicable.
- *
- * By default animate considers css properties, if you wanted to animate element attributes you
- * should to prepend the symbol dollar to the attribute name.
- *
- * Example:
- *
- * <pre class="code">
- * //move the element from its original position to the position top:500px and left:500px for 400ms.
- * //use a swing easing function for the transition
- * $("#foo").animate(Properties.create("{top:'500px',left:'500px'}"), 400, Easing.SWING);
- * // Change the width and border attributes of a table
- * $("table").animate(Properties.create("{$width: '500', $border: '10'}"), 400, Easing.LINEAR);
- * </pre>
- *
- * In addition to numeric values, each property can take the strings 'show', 'hide', and 'toggle'.
- * These shortcuts allow for custom hiding and showing animations that take into account the
- * display type of the element. Animated properties can also be relative. If a value is supplied
- * with a leading += or -= sequence of characters, then the target value is computed by adding or
- * subtracting the given number from the current value of the property.
- *
- * Example:
- *
- * <pre class="code">
- * //move the element from its original position to 500px to the left and 5OOpx down for 400ms.
- * //use a swing easing function for the transition
- * $("#foo").animate(Properties.create("{top:'+=500px',left:'+=500px'}"), 400, Easing.SWING);
- * </pre>
- *
- * For color css properties, values can be specified via hexadecimal or rgb or literal values.
- *
- * Example:
- *
- * <pre class="code">
- * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'"), 400, Easing.SWING);
- * </pre>
- *
- * @param stringOrProperties a String or a {@link Properties} object containing css properties to
- * animate.
- * @param funcs an array of {@link Function} called once the animation is complete
- * @param duration the duration in milliseconds of the animation
- * @param easing the easing function to use for the transition
- */
- public GQuery animate(Object stringOrProperties, int duration, Easing easing, Function... funcs) {
- return as(Effects).animate(stringOrProperties, duration, easing, funcs);
- }
-
- /**
- * The animate() method allows you to create animation effects on any numeric Attribute, CSS
- * properties, or color CSS property.
- *
- * Concerning to numeric property, values are treated as a number of pixels unless otherwise
- * specified. The units em and % can be specified where applicable.
- *
- * By default animate considers css properties, if you wanted to animate element attributes you
- * should to prepend the symbol dollar to the attribute name.
- *
- * Example:
- *
- * <pre class="code">
- * //move the element from its original position to left:500px for 2s
- * $("#foo").animate("left:'500px'", 2000);
- * // Change the width attribute of a table
- * $("table").animate("$width:'500'"), 400);
- * </pre>
- *
- * In addition to numeric values, each property can take the strings 'show', 'hide', and 'toggle'.
- * These shortcuts allow for custom hiding and showing animations that take into account the
- * display type of the element. Animated properties can also be relative. If a value is supplied
- * with a leading += or -= sequence of characters, then the target value is computed by adding or
- * subtracting the given number from the current value of the property.
- *
- * Example:
- *
- * <pre class="code">
- * //move the element from its original position to 500px to the left for 1000ms and
- * // change the background color of the element at the end of the animation
- * $("#foo").animate("left:'+=500'", 1000, new Function(){
- * public void f(Element e){
- * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED);
- * }
- * });
- * </pre>
- *
- *
- * For color css properties, values can be specified via hexadecimal or rgb or literal values.
- *
- * Example:
- *
- * <pre class="code">
- * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)', 1000");
- * </pre>
- *
- *
- * @param prop the property to animate : "cssName:'value'"
- * @param funcs an array of {@link Function} called once the animation is complete
- * @param duration the duration in milliseconds of the animation
- */
- public GQuery animate(Object stringOrProperties, int duration, Function... funcs) {
- return as(Effects).animate(stringOrProperties, duration, funcs);
- }
-
- /**
- * Append content to the inside of every matched element. This operation is similar to doing an
- * appendChild to all the specified elements, adding them into the document.
- */
- public GQuery append(GQuery query) {
- return domManip(query, DomMan.APPEND);
- }
-
- /**
- * Append content to the inside of every matched element. This operation is similar to doing an
- * appendChild to all the specified elements, adding them into the document.
- */
- public GQuery append(Node n) {
- return domManip($(n), DomMan.APPEND);
- }
-
- /**
- * Append content to the inside of every matched element. This operation is similar to doing an
- * appendChild to all the specified elements, adding them into the document.
- */
- public GQuery append(String html) {
- return domManip(html, DomMan.APPEND);
- }
-
- /**
- * All of the matched set of elements will be inserted at the end of the element(s) specified by
- * the parameter other.
- *
- * The operation $(A).appendTo(B) is, essentially, the reverse of doing a regular $(A).append(B),
- * instead of appending B to A, you're appending A to B.
- */
- public GQuery appendTo(GQuery other) {
- other.append(this);
- return this;
- }
-
- /**
- * All of the matched set of elements will be inserted at the end of the element(s) specified by
- * the parameter other.
- *
- * The operation $(A).appendTo(B) is, essentially, the reverse of doing a regular $(A).append(B),
- * instead of appending B to A, you're appending A to B.
- */
- public GQuery appendTo(Node n) {
- GQuery a = $(n);
- GQuery b = this;
- a.append(b);
- return this;
- }
-
- /**
- * All of the matched set of elements will be inserted at the end of the element(s) specified by
- * the parameter other.
- *
- * The operation $(A).appendTo(B) is, essentially, the reverse of doing a regular $(A).append(B),
- * instead of appending B to A, you're appending A to B.
- */
- public GQuery appendTo(String html) {
- $(html).append(this);
- return this;
- }
-
- /**
- * Convert to Plugin interface provided by Class literal.
- */
- @SuppressWarnings("unchecked")
- public <T extends GQuery> T as(Class<T> plugin) {
- // GQuery is not a plugin for itself
- if (plugin == GQUERY) {
- return (T)this;
- } else if (plugins != null) {
- Plugin<?> p = plugins.get(plugin);
- if (p != null) {
- return (T)p.init(this);
- }
- }
- throw new RuntimeException("No plugin registered for class " + plugin.getName());
- }
-
- /**
- * Set a key/value object as properties to all matched elements.
- *
- * Example: $("img").attr(new Properties("src: 'test.jpg', alt: 'Test Image'"))
- */
- public GQuery attr(Properties properties) {
- for (String name : properties.keys()) {
- attr(name, properties.getStr(name));
- }
- return this;
- }
-
- /**
- * Access a property on the first matched element. This method makes it easy to retrieve a
- * property value from the first matched element. If the element does not have an attribute with
- * such a name, empty string is returned. Attributes include title, alt, src, href, width, style,
- * etc.
- */
- public String attr(String name) {
- return isEmpty() ? "" : get(0).getAttribute(name);
- }
-
- /**
- * Set a single property to a computed value, on all matched elements.
- */
- public GQuery attr(String key, Function closure) {
- int i = 0;
- for (Element e : elements) {
- Object val = closure.f(e.<com.google.gwt.dom.client.Element> cast(), i++);
- $(e).attr(key, val);
- }
- return this;
- }
-
- /**
- * Set a single property to a value, on all matched elements.
- */
- public GQuery attr(String key, Object value) {
- assert key != null : "key cannot be null";
- assert !"$H".equalsIgnoreCase(key) : "$H is a GWT reserved attribute. Changing its value will break your application.";
-
- getAttributeImpl().setAttribute(this, key, value);
-
- return this;
- }
-
- /**
- * Insert content before each of the matched elements. The elements must already be inserted into
- * the document (you can't insert an element before another if it's not in the page).
- */
- public GQuery before(GQuery query) {
- return domManip(query, DomMan.BEFORE);
- }
-
- /**
- * Insert content before each of the matched elements. The elements must already be inserted into
- * the document (you can't insert an element before another if it's not in the page).
- */
- public GQuery before(Node n) {
- return domManip($(n), DomMan.BEFORE);
- }
-
- /**
- * Insert content before each of the matched elements. The elements must already be inserted into
- * the document (you can't insert an element before another if it's not in the page).
- */
- public GQuery before(String html) {
- return domManip(html, DomMan.BEFORE);
- }
-
- /**
- * Binds a set of handlers to a particular Event for each matched element.
- *
- * The event handlers are passed as Functions that you can use to prevent default behavior. To
- * stop both default action and event bubbling, the function event handler has to return false.
- *
- * You can pass an additional Object data to your Function as the second parameter
- *
- */
- public GQuery bind(int eventbits, final Object data, final Function... funcs) {
- return as(Events).bind(eventbits, data, funcs);
- }
-
- /**
- * Binds a set of handlers to a particular Event for each matched element.
- *
- * The event handlers are passed as Functions that you can use to prevent default behavior. To
- * stop both default action and event bubbling, the function event handler has to return false.
- *
- *
- */
- public GQuery bind(int eventbits, final Function... funcs) {
- return as(Events).bind(eventbits, null, funcs);
- }
-
- /**
- * Binds a set of handlers to a particular Event for each matched element.
- *
- * The event handlers are passed as Functions that you can use to prevent default behavior. To
- * stop both default action and event bubbling, the function event handler has to return false.
- *
- * You can pass an additional Object data to your Function as the second parameter
- *
- */
- public GQuery bind(String eventType, final Object data, final Function... funcs) {
- return as(Events).bind(eventType, data, funcs);
- }
-
- /**
- * Binds a set of handlers to a particular Event for each matched element.
- *
- * The event handlers are passed as Functions that you can use to prevent default behavior. To
- * stop both default action and event bubbling, the function event handler has to return false.
- *
- *
- */
- public GQuery bind(String eventType, final Function... funcs) {
- return as(Events).bind(eventType, null, funcs);
- }
-
- /**
- * Bind Handlers or fire Events for each matched element.
- */
- private GQuery bindOrFire(int eventbits, final Object data, final Function... funcs) {
- if (funcs.length == 0) {
- return trigger(eventbits);
- } else {
- return bind(eventbits, data, funcs);
- }
- }
-
- /**
- * Bind a set of functions to the blur event of each matched element. Or trigger the blur event if
- * no functions are provided.
- */
- public GQuery blur(Function... f) {
- bindOrFire(Event.ONBLUR, null, f);
- if (!isEmpty() && f.length == 0) {
- get(0).blur();
- }
- return this;
- }
-
- /**
- * Bind a set of functions to the change event of each matched element. Or trigger the event if no
- * functions are provided.
- */
- public GQuery change(Function... f) {
- return bindOrFire(Event.ONCHANGE, null, f);
- }
-
- /**
- * Get a set of elements containing all of the unique immediate children of each of the matched
- * set of elements. Also note: while parents() will look at all ancestors, children() will only
- * consider immediate child elements.
- */
- public GQuery children() {
- JsNodeArray result = JsNodeArray.create();
- for (Element e : elements) {
- allNextSiblingElements(e.getFirstChildElement(), result, null, null, null);
- }
- return new GQuery(unique(result));
- }
-
- /**
- * Get a set of elements containing all of the unique children of each of the matched set of
- * elements. This set is filtered with the expressions that will cause only elements matching any
- * of the selectors to be collected.
- */
- public GQuery children(String... filters) {
- return children().filter(filters);
- }
-
- private void cleanGQData(Element... elements) {
- for (Element el : elements) {
- try {
- EventsListener.clean(el);
- removeData(el, null);
- } catch (Exception e) {
- // If for some reason event/data removal fails, do not break the app,
- // just log the error in dev-mode
- // e.g.: this happens when removing iframes which are no fully loaded.
- e.printStackTrace();
- }
- }
- }
-
- /**
- * Remove from the Effects queue all {@link Function} that have not yet been run.
- */
- public GQuery clearQueue() {
- return as(Queue).clearQueue();
- }
-
- /**
- * Remove from the queue all {@link Function} that have not yet been run.
- */
- public GQuery clearQueue(String queueName) {
- return as(Queue).clearQueue(queueName);
- }
-
- /**
- * Bind a set of functions to the click event of each matched element. Or trigger the event if no
- * functions are provided.
- */
- public GQuery click(Function... f) {
- return bindOrFire(Event.ONCLICK, null, f);
- }
-
- /**
- * Clone matched DOM Elements and select the clones. This is useful for moving copies of the
- * elements to another location in the DOM.
- */
- public GQuery clone() {
- JsNodeArray result = JsNodeArray.create();
- for (Element e : elements) {
- result.addNode(e.cloneNode(true));
- }
- GQuery ret = new GQuery(result);
- ret.currentContext = currentContext;
- ret.currentSelector = currentSelector;
- return ret;
- }
-
- /**
- * Get the first ancestor element that matches the selector (for each matched element), beginning
- * at the current element and progressing up through the DOM tree.
- *
- * @param selector
- * @return
- */
- public GQuery closest(String selector) {
- return closest(selector, null);
- }
-
- /**
- * Get the first ancestor element that matches the selector (for each matched element), beginning
- * at the current element and progressing up through the DOM tree until reach the
- * <code>context</code> node.
- *
- * If no context is passed in then the context of the gQuery object will be used instead.
- *
- */
- public GQuery closest(String selector, Node context) {
- assert selector != null;
-
- if (context == null) {
- context = currentContext;
- }
-
- GQuery pos = selector.matches(POS_REGEX) ? $(selector, context) : null;
- JsNodeArray result = JsNodeArray.create();
-
- for (Element e : elements) {
- Element current = e;
- while (current != null && current.getOwnerDocument() != null && current != context) {
- boolean match = pos != null ? pos.index(current) > -1 : $(current).is(selector);
- if (match) {
- result.addNode(current);
- break;
- } else {
- current = current.getParentElement();
- }
- }
- }
-
- return $(unique(result));
-
- }
-
- /**
- * Returns a {@link Map} object as key a selector and as value the list of ancestor elements
- * matching this selectors, beginning at the first matched element and progressing up through the
- * DOM. This method allows retrieving the list of ancestors matching many selectors by traversing
- * the DOM only one time.
- *
- * @param selector
- * @return
- */
- public JsNamedArray<NodeList<Element>> closest(String[] selectors) {
- return closest(selectors, null);
- }
-
- /**
- * Returns a {@link Map} object as key a selector and as value the list of ancestor elements
- * matching this selectors, beginning at the first matched element and progressing up through the
- * DOM until reach the <code>context</code> node.. This method allows retrieving the list of
- * ancestors matching many selectors by traversing the DOM only one time.
- *
- * @param selector
- * @return
- */
- public JsNamedArray<NodeList<Element>> closest(String[] selectors, Node context) {
- JsNamedArray<NodeList<Element>> results = JsNamedArray.create();
-
- if (context == null) {
- context = currentContext;
- }
-
- Element first = get(0);
- if (first != null && selectors != null && selectors.length > 0) {
- JsNamedArray<GQuery> matches = JsNamedArray.create();
- for (String selector : selectors) {
- if (!matches.exists(selector)) {
- matches.put(selector, selector.matches(POS_REGEX) ? $(selector, context) : null);
- }
- }
-
- Element current = first;
- while (current != null && current.getOwnerDocument() != null && current != context) {
- // for each selector, check if the current element match it.
- for (String selector : matches.keys()) {
-
- GQuery pos = matches.get(selector);
- boolean match = pos != null ? pos.index(current) > -1 : $(current).is(selector);
-
- if (match) {
- JsNodeArray elementsMatchingSelector = results.get(selector).cast();
- if (elementsMatchingSelector == null) {
- elementsMatchingSelector = JsNodeArray.create();
- results.put(selector, elementsMatchingSelector);
- }
- elementsMatchingSelector.addNode(current);
- }
- }
-
- current = current.getParentElement();
- }
- }
- return results;
- }
-
- /**
- * Filter the set of elements to those that contain the specified text.
- */
- public GQuery contains(String text) {
- JsNodeArray array = JsNodeArray.create();
- for (Element e : elements) {
- if ($(e).text().contains(text)) {
- array.addNode(e);
- }
- }
- return $(array);
- }
-
- /**
- * Find all the child nodes inside the matched elements (including text nodes), or the content
- * document, if the element is an iframe.
- */
- public GQuery contents() {
- JsNodeArray result = JsNodeArray.create();
- for (Element e : elements) {
- if (JsUtils.isWindow(e) || "iframe".equalsIgnoreCase(e.getTagName())) {
- result.addNode(getStyleImpl().getContentDocument(e));
- } else {
- NodeList<Node> children = e.getChildNodes();
- for (int i = 0, l = children.getLength(); i < l; i++) {
- result.addNode(children.getItem(i));
- }
- }
- }
- return new GQuery(unique(result));
- }
-
- public LazyGQuery<?> createLazy() {
- return GWT.create(GQuery.class);
- }
-
- /**
- * Set CSS a single style property on every matched element using type-safe enumerations.
- *
- * The best way to use this method (i.e. to generate a CssSetter) is to take the desired css
- * property defined in {@link CSS} class and call the {@link TakesCssValue#with(HasCssName)}
- * method on it.
- *
- *
- * ex :
- *
- * <pre class="code">
- * $("#myDiv").css(CSS.TOP.with(Length.cm(15)));
- * $("#myDiv").css(CSS.BACKGROUND.with(RGBColor.SILVER, ImageValue.url(""),
- * BackgroundRepeat.NO_REPEAT, BackgroundAttachment.FIXED,
- * BackgroundPosition.CENTER));
- * $("#myDiv").css(CSS.BACKGROUND_ATTACHMENT.with(BackgroundAttachment.FIXED));
- *
- * </pre>
- *
- */
- public GQuery css(CssSetter... cssSetter) {
- for (Element e : elements) {
- for (CssSetter s : cssSetter) {
- s.applyCss(e);
- }
- }
- return this;
- }
-
- /**
- * Return a style property on the first matched element using type-safe enumerations.
- *
- * Ex : $("#myId").css(CSS.BACKGROUND_COLOR);
- */
- public String css(HasCssValue property) {
- return css(property, true);
- }
-
- /**
- * Return a style property on the first matched element using type-safe enumerations.
- *
- * The parameter force has a special meaning here: - When force is false, returns the value of the
- * css property defined in the style attribute of the element. - Otherwise it returns the real
- * computed value.
- *
- * For instance if you define 'display=none' not in the element style but in the css stylesheet,
- * it returns an empty string unless you pass the parameter force=true.
- *
- * Ex : $("#myId").css(CSS.WIDTH, true);
- */
- public String css(HasCssValue property, boolean force) {
- return css(property.getCssName(), force);
- }
-
- /**
- * Set a key/value object as style properties to all matched elements. This serves as the best way
- * to set a large number of style properties on all matched elements. You can use either js maps
- * or pure css syntax.
- *
- * Example:
- *
- * <pre class="code">
- * $(".item").css(Properties.create("color: 'red', background:'blue'"))
- * $(".item").css(Properties.create("color: red; background: blue;"))
- * </pre>
- */
- public GQuery css(Properties properties) {
- for (String property : properties.keys()) {
- css(property, properties.getStr(property));
- }
- return this;
- }
-
- /**
- * Return a style property on the first matched element.
- */
- public String css(String name) {
- return css(name, true);
- }
-
- /**
- * Return a style property on the first matched element.
- *
- * The parameter force has a special meaning here:
- * <ul>
- * <li>When force is false, returns the value of the css property defined in the style attribute
- * of the element.
- * <li>Otherwise it returns the real computed value.
- * </ul>
- *
- * For instance if you don't define 'display=none'in the element style but in the css stylesheet,
- * it returns an empty string unless you pass the parameter force=true.
- */
- public String css(String name, boolean force) {
- return isEmpty() ? "" : getStyleImpl().curCSS(get(0), name, force);
- }
-
- /**
- * Set a single style property to a value, on all matched elements.
- *
- */
- public GQuery css(String prop, String val) {
- for (Element e : elements) {
- getStyleImpl().setStyleProperty(e, prop, val);
- }
- return this;
- }
-
- /**
- * Set CSS a single style property on every matched element using type-safe enumerations. This
- * method allows you to set manually the value or set <i>inherit</i> value
- *
- * ex :
- *
- * <pre class="code">
- * $(#myId).css(CSS.TEXT_DECORATION, CSS.INHERIT);
- * </pre>
- */
- public GQuery css(TakesCssValue<?> cssProperty, String value) {
- return css(cssProperty.getCssName(), value);
- }
-
- /**
- * Returns the numeric value of a css property.
- */
- public double cur(String prop) {
- return cur(prop, false);
- }
-
- /**
- * Returns the numeric value of a css property.
- *
- * The parameter force has a special meaning: - When force is false, returns the value of the css
- * property defined in the set of style attributes. - When true returns the real computed value.
- */
- public double cur(String prop, boolean force) {
- return isEmpty() ? 0 : getStyleImpl().cur(get(0), prop, force);
- }
-
- /**
- * Returns value at named data store for the element, as set by data(name, value).
- */
- public Object data(String name) {
- return isEmpty() ? null : data(get(0), name, null);
- }
-
- /**
- * Returns value at named data store for the element, as set by data(name, value) with desired
- * return type.
- *
- * @param clz return type class literal
- */
- @SuppressWarnings("unchecked")
- public <T> T data(String name, Class<T> clz) {
- return isEmpty() ? null : (T) data(get(0), name, null);
- }
-
- /**
- * Stores the value in the named spot with desired return type.
- */
- public GQuery data(String name, Object value) {
- for (Element e : elements()) {
- data(e, name, value);
- }
- return this;
- }
-
- /**
- * Bind a set of functions to the dblclick event of each matched element. Or trigger the event if
- * no functions are provided.
- */
- public GQuery dblclick(Function... f) {
- return bindOrFire(Event.ONDBLCLICK, null, f);
- }
-
- /**
- * Insert a delay (in ms) in the GQuery queue, and optionally execute one o more functions if
- * provided when the delay finishes. It uses the effects queue namespace, so you can stack any of
- * the methods in the effects plugin.
- *
- * Example:
- *
- * <pre class="code">
- * $("#foo").slideUp(300)
- * .delay(800)
- * .fadeIn(400);
- * </pre>
- *
- * When this statement is executed, the element slides up for 300 milliseconds and then pauses for
- * 800 milliseconds before fading in for 400 milliseconds. Aditionally after those 800
- * milliseconds the element color is set to red.
- *
- * NOTE that this methods affects only methods which uses the queue like effects. So the following
- * example is wrong:
- *
- * <pre>
- * $("#foo").css(CSS.COLOR.with(RGBColor.RED)).delay(800).css(CSS.COLOR.with(RGBColor.BLACK));
- * </pre>
- *
- * The code above will not insert a delay of 800 ms between the css() calls ! For this kind of
- * behavior, you should execute these methods puting them in inline functions passed as argument
- * to the delay() method, or adding them to the queue.
- *
- * <pre>
- * $("#foo").css(CSS.COLOR.with(RGBColor.RED)).delay(800, lazy().css(CSS.COLOR.with(RGBColor.BLACK)).done());
- * $("#foo").css(CSS.COLOR.with(RGBColor.RED)).delay(800).queue(lazy().css(CSS.COLOR.with(RGBColor.BLACK)).dequeue().done());
- * </pre>
- */
- public GQuery delay(int milliseconds, Function... f) {
- return as(Queue).delay(milliseconds, f);
- }
-
- /**
- * Insert a delay (in ms) in the queue identified by the <code>queueName</code> parameter, and
- * optionally execute one o more functions if provided when the delay finishes.
- *
- * If <code>queueName</code> is null or equats to 'fx', the delay will be inserted to the Effects
- * queue.
- *
- * Example :
- *
- * <pre class="code">
- * $("#foo").queue("colorQueue", lazy().css(CSS.COLOR.with(RGBColor.RED)).dequeue("colorQueue").done())
- * .delay(800, "colorQueue")
- * .queue("colorQueue", lazy().css(CSS.COLOR.with(RGBColor.BLACK)).dequeue("colorQueue").done());
- * </pre>
- *
- * When this statement is executed, the text color of the element changes to red and then wait for
- * 800 milliseconds before changes the text color to black.
- *
- */
- public GQuery delay(int milliseconds, String queueName, Function... f) {
- return as(Queue).delay(milliseconds, queueName, f);
- }
-
- /**
- * Attach <code>handlers</code> to one or more events for all elements that match the
- * <code>selector</code>, now or in the future, based on a specific set of root elements.
- *
- * Example:
- *
- * <pre>
- * $("table").delegate("td", Event.ONCLICK, new Function(){
- * public void f(Element e){
- * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED));
- * }
- * });
- * </pre>
- *
- * This code above add an handler on click event on all cell (the existing oneand the future cell)
- * of all table. This code is equivalent to :
- *
- * <pre>
- * $("table").each(new Function(){
- * public void f(Element table){
- * $("td", table).live(Event.ONCLICK, new Function(){
- * public void f(Element e){
- * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED));
- * }
- * }
- * });
- *
- * </pre>
- *
- * You can attach the handlers to many events by using the '|' operator ex:
- *
- * <pre>
- * $("div.main").delegate(".subMain", Event.ONCLICK | Event.ONDBLCLICK, new Function(){...});
- * </pre>
- */
- public GQuery delegate(String selector, int eventbits, Function... handlers) {
- return delegate(selector, eventbits, null, handlers);
- }
-
- /**
- * Attach <code>handlers</code> to one or more events for all elements that match the
- * <code>selector</code>, now or in the future, based on a specific set of root elements. The
- * <code>data</code> parameter allows us to pass data to the handler.
- *
- * Example:
- *
- * <pre>
- * $("table").delegate("td", "click", new Function(){
- * public void f(Element e){
- * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED));
- * }
- * });
- * </pre>
- *
- * This code above add an handler on click event on all cell (the existing oneand the future cell)
- * of all table. This code is equivalent to :
- *
- * <pre>
- * $("table").each(new Function(){
- * public void f(Element table){
- * $("td", table).live("click", new Function(){
- * public void f(Element e){
- * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED));
- * }
- * }
- * });
- *
- * </pre>
- *
- * You can pass attach the handlers to many events by using the '|' operator ex:
- *
- * <pre>
- * $("div.main").delegate(".subMain", Event.ONCLICK | Event.ONDBLCLICK, new Function(){...});
- * </pre>
- */
- public GQuery delegate(String selector, int eventbits, Object data, Function... handlers) {
-
- for (Element e : elements) {
- $(selector, e).live(eventbits, data, handlers);
- }
-
- return this;
- }
-
- /**
- * Attach <code>handlers</code> to one or more events for all elements that match the
- * <code>selector</code>, now or in the future, based on a specific set of root elements.
- *
- * Example:
- *
- * <pre>
- * $("table").delegate("td", "click", new Function(){
- * public void f(Element e){
- * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED));
- * }
- * });
- * </pre>
- *
- * This code above add an handler on click event on all cell (the existing oneand the future cell)
- * of all table. This code is equivalent to :
- *
- * <pre>
- * $("table").each(new Function(){
- * public void f(Element table){
- * $("td", table).live("click", new Function(){
- * public void f(Element e){
- * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED));
- * }
- * }
- * });
- *
- * </pre>
- *
- * You can pass attach the handlers to many events by specifying a String with espaced event type.
- * ex:
- *
- * <pre>
- * $("div.main").delegate(".subMain", "click dblclick", new Function(){...});
- * </pre>
- *
- * </pre>
- */
- public GQuery delegate(String selector, String eventType, Function... handlers) {
- return delegate(selector, eventType, null, handlers);
- }
-
- /**
- * Attach <code>handlers</code> to one or more events for all elements that match the
- * <code>selector</code>, now or in the future, based on a specific set of root elements.
- *
- * Example:
- *
- * <pre>
- * $("table").delegate("td", "click", new Function(){
- * public void f(Element e){
- * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED));
- * }
- * });
- * </pre>
- *
- * This code above add an handler on click event on all cell (the existing oneand the future cell)
- * of all table. This code is equivalent to :
- *
- * <pre>
- * $("table").each(new Function(){
- * public void f(Element table){
- * $("td", table).live("click", new Function(){
- * public void f(Element e){
- * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED));
- * }
- * }
- * });
- *
- * You can pass attach the handlers to many events by specifying a String with espaced event type.
- * ex:
- *
- * <pre>
- * $("div.main").delegate(".subMain", "click dblclick", new Function(){...});
- * </pre>
- *
- * </pre>
- */
- public GQuery delegate(String selector, String eventType, Object data, Function... handlers) {
- for (Element e : elements) {
- $(selector, e).live(eventType, data, handlers);
- }
-
- return this;
- }
-
- /**
- * Execute the next function on the Effects queue for the matched elements. This method is usefull
- * to tell when a function you add in the Effects queue is ended and so the next function in the
- * queue can start.
- *
- * Note: you should be sure to call dequeue() in all functions of a queue chain, otherwise the
- * queue execution will be stopped.
- */
- public GQuery dequeue() {
- return as(Queue).dequeue();
- }
-
- /**
- * Execute the next function on the queue named as queueName for the matched elements. This method
- * is usefull to tell when a function you add in the Effects queue is ended and so the next
- * function in the queue can start.
- */
- public GQuery dequeue(String queueName) {
- return as(Queue).dequeue(queueName);
- }
-
- /**
- * Detach all matched elements from the DOM. This method is the same than {@link #remove()} method
- * except all data and event handlers are not remove from the element. This method is useful when
- * removed elements are to be reinserted into the DOM at a later time.
- */
- public GQuery detach() {
- return remove(null, false);
- }
-
- /**
- * Detach from the DOM all matched elements filtered by the <code>filter</code>.. This method is
- * the same than {@link #remove(String)} method except all data and event handlers are not remove
- * from the element. This method is useful when removed elements are to be reinserted into the DOM
- * at a later time.
- */
- public GQuery detach(String filter) {
- return remove(filter, false);
- }
-
- /**
- * Remove all event handlers previously attached using {@link #live(String, Function)}. In order
- * for this method to function correctly, the selector used with it must match exactly the
- * selector initially used with {@link #live(String, Function)}
- */
- public GQuery die() {
- return die(0);
- }
-
- /**
- * Remove an event handlers previously attached using {@link #live(int, Function)} In order for
- * this method to function correctly, the selector used with it must match exactly the selector
- * initially used with {@link #live(int, Function)}
- */
- public GQuery die(int eventbits) {
- return as(Events).die(eventbits);
- }
-
- /**
- * Remove an event handlers previously attached using {@link #live(String, Function)} In order for
- * this method to function correctly, the selector used with it must match exactly the selector
- * initially used with {@link #live(String, Function)}
- */
- public GQuery die(String eventName) {
- return as(Events).die(eventName);
- }
-
- private GQuery domManip(GQuery g, DomMan type, Element... elms) {
- JsNodeArray newNodes = JsNodeArray.create();
- if (elms.length == 0) {
- elms = elements;
- }
- for (int i = 0, l = elms.length; i < l; i++) {
- Element e = elms[i];
- if (e.getNodeType() == Node.DOCUMENT_NODE) {
- e = e.<Document> cast().getBody();
- }
- for (int j = 0, size = g.size(); j < size; j++) {
- // Widget w = getAssociatedWidget(g.get(j));
- // GqUi.detachWidget(w);
-
- Node n = g.get(j);
- // If an element selected is inserted elsewhere, it will be moved into the target (not
- // cloned).
- // If there is more than one target element, however, cloned copies of the inserted element
- // will be created for each target after the first
- if (i > 0) {
- n = n.cloneNode(true);
- }
- switch (type) {
- case PREPEND:
- newNodes.addNode(e.insertBefore(n, e.getFirstChild()));
- break;
- case APPEND:
- newNodes.addNode(e.appendChild(n));
- break;
- case AFTER:
- newNodes.addNode(e.getParentNode().insertBefore(n, e.getNextSibling()));
- break;
- case BEFORE:
- newNodes.addNode(e.getParentNode().insertBefore(n, e));
- break;
- }
- EventsListener.rebind(n.<Element> cast());
- // GqUi.attachWidget(w);
- }
- }
- // TODO: newNodes.size() > g.size() makes testRebind fail
- if (newNodes.size() >= g.size()) {
- g.setArray(newNodes);
- }
- return this;
- }
-
- // TODO: this should be handled by the other domManip method
- private GQuery domManip(String htmlString, DomMan type) {
- JsMap<Document, GQuery> cache = JsMap.createObject().cast();
- for (Element e : elements) {
- Document d = JsUtils.getOwnerDocument(e);
- GQuery g = cache.get(d);
- if (g == null) {
- g = cleanHtmlString(htmlString, d);
- cache.put(d, g);
- }
- domManip(g.clone(), type, e);
- }
- return this;
- }
-
- /**
- * Run one or more Functions over each element of the GQuery. You have to override one of these
- * funcions: public void f(Element e) public String f(Element e, int i)
- */
- public GQuery each(Function... f) {
- if (f != null) {
- for (Function f1 : f) {
- int i = 0;
- for (Element e : elements) {
- f1.f(e.<com.google.gwt.dom.client.Element> cast(), i++);
- }
- }
- }
- return this;
- }
-
- /**
- * Returns the working set of nodes as a Java array. <b>Do NOT</b> attempt to modify this array,
- * e.g. assign to its elements, or call Arrays.sort()
- */
- public Element[] elements() {
- return elements;
- }
-
- /**
- * Remove all child nodes from the set of matched elements. In the case of a document element, it
- * removes all the content You should call this method whenever you create a new iframe and you
- * want to add dynamic content to it.
- */
- public GQuery empty() {
- for (Element e : elements) {
- if (e.getNodeType() == Element.DOCUMENT_NODE) {
- getStyleImpl().emptyDocument(e.<Document> cast());
- } else {
- Node c = e.getFirstChild();
- while (c != null) {
- removeData(c.<Element> cast(), null);
- WidgetsUtils.detachWidget(getAssociatedWidget(e));
- EventsListener.clean(c.<Element> cast());
- e.removeChild(c);
- c = e.getFirstChild();
- }
- }
- }
- return this;
- }
-
- /**
- * Revert the most recent 'destructive' operation, changing the set of matched elements to its
- * previous state (right before the destructive operation).
- */
- public GQuery end() {
- return previousObject != null ? previousObject : new GQuery();
- }
-
- /**
- * Reduce GQuery to element in the specified position. This method accept negative index. A
- * negative index is counted from the end of the matched set:
- *
- * Example:
- *
- * <pre>
- * $("div").eq(0) will reduce the matched set to the first matched div
- * $("div").eq(1) will reduce the matched set to the second matched div
- *
- * $("div").eq(-1) will reduce the matched set to the last matched div
- * $("div").eq(-2) will reduce the matched set to the second-to-last matched div
- * ...
- * </pre>
- */
- public GQuery eq(int pos) {
- return $(get(pos));
- }
-
- /**
- * Bind a set of functions to the error event of each matched element. Or trigger the event if no
- * functions are provided.
- */
- public GQuery error(Function... f) {
- return bindOrFire(Event.ONERROR, null, f);
- }
-
- /**
- * Fade in all matched elements by adjusting their opacity. The effect will take 1000 milliseconds
- * to complete
- */
- public GQuery fadeIn(Function... f) {
- return as(Effects).fadeIn(f);
- }
-
- /**
- * Fade in all matched elements by adjusting their opacity.
- */
- public GQuery fadeIn(int millisecs, Function... f) {
- return as(Effects).fadeIn(millisecs, f);
- }
-
- /**
- * Fade out all matched elements by adjusting their opacity. The effect will take 1000
- * milliseconds to complete
- */
- public GQuery fadeOut(Function... f) {
- return as(Effects).fadeOut(f);
- }
-
- /**
- * Fade out all matched elements by adjusting their opacity.
- */
- public GQuery fadeOut(int millisecs, Function... f) {
- return as(Effects).fadeOut(millisecs, f);
- }
-
- /**
- * Toggle the visibility of all matched elements by adjusting their opacity and firing an optional
- * callback after completion. Only the opacity is adjusted for this animation, meaning that all of
- * the matched elements should already have some form of height and width associated with them.
- */
- public Effects fadeToggle(int millisecs, Function... f) {
- return as(Effects).fadeToggle(millisecs, f);
- }
-
- /**
- * Removes all elements from the set of matched elements that do not match the specified function.
- * The function is called with a context equal to the current element. If the function returns
- * false, then the element is removed - anything else and the element is kept.
- */
- public GQuery filter(Predicate filterFn) {
- JsNodeArray result = JsNodeArray.create();
- int i = 0;
- for (Element e : elements) {
- if (filterFn.f(e, i++)) {
- result.addNode(e);
- }
- }
- return pushStack(result, "filter", currentSelector);
- }
-
- /**
- * Removes all elements from the set of matched elements that do not pass the specified css
- * expression. This method is used to narrow down the results of a search.
- */
- // TODO performance bad...
- public GQuery filter(String... filters) {
- JsNodeArray array = JsNodeArray.create();
- /*
- * StringBuilder filterBuilder = new StringBuilder(); for (int i = 0; i < filters.length ; i++){
- * filterBuilder.append(filters[i]); if (i < filters.length - 1){ filterBuilder.append(","); } }
- *
- * String filter = filterBuilder.toString();
- */
-
- for (String f : filters) {
- for (Element e : elements) {
- boolean ghostParent = false;
-
- if (e.getParentNode() == null) {
- DOM.createDiv().appendChild(e);
- ghostParent = true;
- }
-
- for (Element c : $(f, e.getParentNode()).elements) {
- if (c == e) {
- array.addNode(c);
- break;
- }
- }
-
- if (ghostParent) {
- e.removeFromParent();
- }
- }
- }
-
- return pushStack(unique(array), "filter", filters[0]);
- }
-
- /**
- * Searches for all elements that match the specified css expression. This method is a good way to
- * find additional descendant elements with which to process.
- *
- * Provide a comma-separated list of expressions to apply multiple filters at once.
- */
- public GQuery find(String... filters) {
- JsNodeArray array = JsNodeArray.create();
- for (String selector : filters) {
- for (Element e : elements) {
- for (Element c : $(selector, e).elements) {
- array.addNode(c);
- }
- }
- }
- return pushStack(unique(array), "find", filters[0]);
- }
-
- /**
- * Reduce the set of matched elements to the first in the set.
- */
- public GQuery first() {
- return eq(0);
- }
-
- /**
- * Bind a set of functions to the focus event of each matched element. Or trigger the event and
- * move the input focus to the first element if no functions are provided.
- */
- public GQuery focus(Function... f) {
- bindOrFire(Event.ONFOCUS, null, f);
- if (!isEmpty() && f.length == 0) {
- get(0).focus();
- }
- return this;
- }
-
- /**
- * Return all elements matched in the GQuery as a NodeList. @see #elements() for a method which
- * returns them as an immutable Java array.
- */
- public NodeList<Element> get() {
- return nodeList;
- }
-
- /**
- * Return the ith element matched. This method accept negative index. A negative index is counted
- * from the end of the matched set.
- *
- * Example:
- *
- * <pre>
- * $("div").get(0) will return the first matched div
- * $("div").get(1) will return the second matched div
- *
- * $("div").get(-1) will return the last matched div
- * $("div").get(-2) will return the secont-to-last matched div
- * ...
- * </pre>
- */
- public Element get(int i) {
- int l = elements.length;
- if (i >= 0 && i < l) {
- return elements[i];
- }
- if (i < 0 && l + i >= 0) {
- return elements[l + i];
- }
- return null;
- }
-
- public Node getContext() {
- return currentContext;
- }
-
- /**
- * Return the previous set of matched elements prior to the last destructive operation (e.g.
- * query)
- */
- public GQuery getPreviousObject() {
- return previousObject;
- }
-
- private native Element getPreviousSiblingElement(Element elem) /*-{
- var sib = elem.previousSibling;
- while (sib && sib.nodeType != 1)
- sib = sib.previousSibling;
- return sib;
- }-*/;
-
- /**
- * Return the selector representing the current set of matched elements.
- */
- public String getSelector() {
- return currentSelector;
- }
-
- /**
- * Returns true any of the specified classes are present on any of the matched Reduce the set of
- * matched elements to all elements after a given position. The position of the element in the set
- * of matched elements starts at 0 and goes to length - 1.
- */
- public GQuery gt(int pos) {
- return slice(pos + 1, -1);
- }
-
- /**
- * Reduce the set of matched elements to those that have a descendant that matches the Element.
- */
- public GQuery has(final Element elem) {
- return filter(new Predicate() {
- public boolean f(Element e, int index) {
- return engine.contains(e, elem);
- }
- });
- }
-
- /**
- * Reduce the set of matched elements to those that have a descendant that matches the selector.
- */
- public GQuery has(final String selector) {
- return filter(new Predicate() {
- public boolean f(Element e, int index) {
- return !$(selector, e).isEmpty();
- }
- });
- }
-
- /**
- * Returns true any of the specified classes are present on any of the matched elements.
- */
- public boolean hasClass(String... classes) {
- for (Element e : elements) {
- for (String clz : classes) {
- if (hasClass(e, clz)) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Get the current computed, pixel, height of the first matched element. It does not include
- * margin, padding nor border.
- */
- public int height() {
- return (int) cur("height", true);
- }
-
- /**
- * Set the height of every element in the matched set.
- */
- public GQuery height(int height) {
- for (Element e : elements) {
- e.getStyle().setPropertyPx("height", height);
- }
- return this;
- }
-
- /**
- * Set the height style property of every matched element. It's useful for using 'percent' or 'em'
- * units Example: $(".a").width("100%")
- */
- public GQuery height(String height) {
- return css("height", height);
- }
-
- /**
- * Make invisible all matched elements.
- */
- public GQuery hide() {
- for (Element e : elements) {
- String currentDisplay = getStyleImpl().curCSS(e, "display", false);
- Object old = data(e, OLD_DISPLAY, null);
- if (old == null && currentDisplay.length() != 0 && !"none".equals(currentDisplay)) {
- data(e, OLD_DISPLAY, currentDisplay);
- }
- }
-
- // Set the display value in a separate for loop to avoid constant reflow
- // Reflows is very bad in performance point of view
- for (Element e : elements) {
- e.getStyle().setDisplay(Display.NONE);
- }
-
- return this;
- }
-
- /**
- * Bind a function to the mouseover event of each matched element. A method for simulating
- * hovering (moving the mouse on, and off, an object). This is a custom method which provides an
- * 'in' to a frequent task. Whenever the mouse cursor is moved over a matched element, the first
- * specified function is fired. Whenever the mouse moves off of the element, the second specified
- * function fires.
- */
- public GQuery hover(Function fover, Function fout) {
- return bind(Event.ONMOUSEOVER, null, fover).bind(Event.ONMOUSEOUT, null, fout);
- }
-
- /**
- * Get the innerHTML of the first matched element.
- */
- public String html() {
- return isEmpty() ? "" : get(0).getInnerHTML();
- }
-
- /**
- * Set the innerHTML of every matched element.
- */
- public GQuery html(String html) {
- for (Element e : elements) {
- if (e.getNodeType() == Node.DOCUMENT_NODE) {
- e = e.<Document> cast().getBody();
- }
- e.setInnerHTML(html);
- }
- return this;
- }
-
- /**
- * Get the id of the first matched element.
- */
- public String id() {
- return attr("id");
- }
-
- /**
- * Set the id of the first matched element.
- */
- public GQuery id(String id) {
- return eq(0).attr("id", id);
- }
-
- /**
- * Find the index of the specified Element.
- */
- public int index(Element element) {
- int i = 0;
- for (Element e : elements) {
- if (e == element) {
- return i;
- }
- i++;
- }
- return -1;
- }
-
- /**
- * Returns the inner height of the first matched element, including padding but not the vertical
- * scrollbar height, border, or margin.
- */
- public int innerHeight() {
- return (int) cur("clientHeight", true);
- }
-
- /**
- * Returns the inner width of the first matched element, including padding but not the vertical
- * scrollbar width, border, or margin.
- */
- public int innerWidth() {
- return (int) cur("clientWidth", true);
- }
-
- /**
- * Insert all of the matched elements after another, specified, set of elements.
- */
- public GQuery insertAfter(Element elem) {
- return insertAfter($(elem));
- }
-
- /**
- * Insert all of the matched elements after another, specified, set of elements.
- */
- public GQuery insertAfter(GQuery query) {
- for (Element e : elements) {
- query.after(e);
- }
- return this;
- }
-
- /**
- * Insert all of the matched elements after another, specified, set of elements.
- */
- public GQuery insertAfter(String selector) {
- return insertAfter($(selector));
- }
-
- /**
- * Insert all of the matched elements before another, specified, set of elements.
- *
- * The elements must already be inserted into the document (you can't insert an element after
- * another if it's not in the page).
- */
- public GQuery insertBefore(Element item) {
- return insertBefore($(item));
- }
-
- /**
- * Insert all of the matched elements before another, specified, set of elements.
- *
- * The elements must already be inserted into the document (you can't insert an element after
- * another if it's not in the page).
- */
- public GQuery insertBefore(GQuery query) {
- for (Element e : elements) {
- query.before(e);
- }
- return this;
- }
-
- /**
- * Insert all of the matched elements before another, specified, set of elements.
- *
- * The elements must already be inserted into the document (you can't insert an element after
- * another if it's not in the page).
- */
- public GQuery insertBefore(String selector) {
- return insertBefore($(selector));
- }
-
- /**
- * Checks the current selection against an expression and returns true, if at least one element of
- * the selection fits the given expression. Does return false, if no element fits or the
- * expression is not valid.
- */
- public boolean is(String... filters) {
- return !filter(filters).isEmpty();
- }
-
- /**
- * Returns true if the number of matched elements is 0.
- */
- public boolean isEmpty() {
- return size() == 0;
- }
-
- /**
- * Return true if the first element is visible.isVisible
- */
- public boolean isVisible() {
- return isEmpty() ? false : getStyleImpl().isVisible(get(0));
- }
-
- /**
- * Bind a set of functions to the keydown event of each matched element. Or trigger the event if
- * no functions are provided.
- */
- public GQuery keydown(Function... f) {
- return bindOrFire(Event.ONKEYDOWN, null, f);
- }
-
- /**
- * Trigger a keydown event passing the key pushed.
- */
- public GQuery keydown(int key) {
- return trigger(Event.ONKEYDOWN, key);
- }
-
- /**
- * Bind a set of functions to the keypress event of each matched element. Or trigger the event if
- * no functions are provided.
- */
- public GQuery keypress(Function... f) {
- return bindOrFire(Event.ONKEYPRESS, null, f);
- }
-
- /**
- * Trigger a keypress event passing the key pushed.
- */
- public GQuery keypress(int key) {
- return trigger(Event.ONKEYPRESS, key);
- }
-
- /**
- * Bind a set of functions to the keyup event of each matched element. Or trigger the event if no
- * functions are provided.
- */
- public GQuery keyup(Function... f) {
- return bindOrFire(Event.ONKEYUP, null, f);
- }
-
- /**
- * Trigger a keyup event passing the key pushed.
- */
- public GQuery keyup(int key) {
- return trigger(Event.ONKEYUP, key);
- }
-
- /**
- * Reduce the set of matched elements to the final one in the set.
- */
- public GQuery last() {
- return eq(size() - 1);
- }
-
- /**
- * Returns the computed left position of the first element matched.
- */
- public int left() {
- return (int) cur("left", true);
- }
-
- /**
- * Returns the number of elements currently matched. The size function will return the same value.
- */
- public int length() {
- return size();
- }
-
- /**
- * Attach a handler for this event to all elements which match the current selector, now and in
- * the future.
- */
- public GQuery live(int eventbits, Function... funcs) {
- return as(Events).live(eventbits, null, funcs);
- }
-
- /**
- * Attach a handler for this event to all elements which match the current selector, now and in
- * the future.
- */
- public GQuery live(int eventbits, Object data, Function... funcs) {
- return as(Events).live(eventbits, data, funcs);
- }
-
- /**
- * <p>
- * Attach a handler for this event to all elements which match the current selector, now and in
- * the future.
- * <p>
- * <p>
- * Ex :
- *
- * <pre>
- * $(".clickable").live("click", new Function(){
- * public void f(Element e){
- * $(e).css(CSS.COLOR.with(RGBColor.RED));
- * }
- * });
- * </pre>
- *
- * With this code, all elements with class "clickable" present in the DOM or added to the DOM in
- * the future will be clickable. The text color will be changed to red when they will be clicked.
- * So if after in the code, you add another element :
- *
- * <pre>
- * $("body").append("<div class='clickable'>Click me and I will be red</div>");
- * </pre>
- *
- * The click on this new element will also trigger the handler.
- * </p>
- * <p>
- * In the same way, if you add "clickable" class on some existing element, these elements will be
- * clickable also.
- * </p>
- * <p>
- * <h3>important remarks</h3>
- * <ul>
- * <li>
- * The live method should be always called after a selector</li>
- * <li>
- * Live events are bound to the context of the {@link GQuery} object :
- *
- * <pre>
- * $(".clickable", myElement).live("click", new Function(){
- * public void f(Element e){
- * $(e).css(CSS.COLOR.with(RGBColor.RED));
- * }
- * });
- * </pre>
- * The {@link Function} will be called only on elements having the class "clickable" and being
- * descendant of myElement.</li>
- * </ul>
- * </p>
- */
- public GQuery live(String eventName, Function... funcs) {
- return as(Events).live(eventName, null, funcs);
- }
-
- /**
- * <p>
- * Attach a handler for this event to all elements which match the current selector, now and in
- * the future. The <code>data</code> parameter allows us to pass data to the handler.
- * <p>
- * <p>
- * Ex :
- *
- * <pre>
- * $(".clickable").live("click", new Function(){
- * public void f(Element e){
- * $(e).css(CSS.COLOR.with(RGBColor.RED));
- * }
- * });
- * </pre>
- *
- * With this code, all elements with class "clickable" present in the DOM or added to the DOM in
- * the future will be clickable. The text color will be changed to red when they will be clicked.
- * So if after in the code, you add another element :
- *
- * <pre>
- * $("body").append("<div class='clickable'>Click me and I will be red</div>");
- * </pre>
- *
- * The click on this new element will also trigger the handler.
- * </p>
- * <p>
- * In the same way, if you add "clickable" class on some existing element, these elements will be
- * clickable also.
- * </p>
- * <p>
- * <h3>important remarks</h3>
- * <ul>
- * <li>
- * The live method should be always called after a selector</li>
- * <li>
- * Live events are bound to the context of the {@link GQuery} object :
- *
- * <pre>
- * $(".clickable", myElement).live("click", new Function(){
- * public void f(Element e){
- * $(e).css(CSS.COLOR.with(RGBColor.RED));
- * }
- * });
- * </pre>
- * The {@link Function} will be called only on elements having the class "clickable" and being
- * descendant of myElement.</li>
- * </ul>
- * </p>
- */
- public GQuery live(String eventName, Object data, Function... funcs) {
- return as(Events).live(eventName, data, funcs);
- }
-
- /**
- * Bind a function to the load event of each matched element.
- */
- @Deprecated
- public GQuery load(Function f) {
- return bind(Event.ONLOAD, null, f);
- }
-
- /**
- * Load data from the server and place the returned HTML into the matched element.
- *
- * The url allows us to specify a portion of the remote document to be inserted. This is achieved
- * with a special syntax for the url parameter. If one or more space characters are included in
- * the string, the portion of the string following the first space is assumed to be a GQuery
- * selector that determines the content to be loaded.
- *
- */
- public GQuery load(String url) {
- return load(url, null, null);
- }
-
- /**
- * Load data from the server and place the returned HTML into the matched element.
- *
- * The url allows us to specify a portion of the remote document to be inserted. This is achieved
- * with a special syntax for the url parameter. If one or more space characters are included in
- * the string, the portion of the string following the first space is assumed to be a GQuery
- * selector that determines the content to be loaded.
- *
- */
- public GQuery load(String url, Properties data, final Function onSuccess) {
- return as(Ajax.Ajax).load(url, data, onSuccess);
- }
-
- /**
- * Reduce the set of matched elements to all elements before a given position. The position of the
- * element in the set of matched elements starts at 0 and goes to length - 1.
- */
- public GQuery lt(int pos) {
- return slice(0, pos);
- }
-
- /**
- * Pass each element in the current matched set through a function, producing a new array
- * containing the return values. When the call to the function returns a null it is not added to
- * the array.
- */
- public <W> List<W> map(Function f) {
- ArrayList<W> ret = new ArrayList<W>();
- int i = 0;
- for (Element e : elements) {
- @SuppressWarnings("unchecked")
- W o = (W) f.f(e.<com.google.gwt.dom.client.Element> cast(), i++);
- if (o != null) {
- ret.add(o);
- }
- }
- return ret;
- }
-
- /**
- * Bind a set of functions to the mousedown event of each matched element. Or trigger the event if
- * no functions are provided.
- */
- public GQuery mousedown(Function... f) {
- return bindOrFire(Event.ONMOUSEDOWN, null, f);
- }
-
- /**
- * Bind an event handler to be fired when the mouse enter an element, or trigger that handler on
- * an element if no functions are provided.
- *
- * The mouseenter event differs from mouseover in the way it handles event bubbling. When
- * mouseover is used on an element having inner element(s), then when the mouse pointer moves hover
- * of the Inner element, the handler would be triggered. This is usually undesirable behavior. The
- * mouseenter event, on the other hand, only triggers its handler when the mouse enters the
- * element it is bound to, not a descendant.
- */
- public GQuery mouseenter(Function... f) {
- return as(Events).mouseenter(f);
- }
-
- /**
- * Bind an event handler to be fired when the mouse leaves an element, or trigger that handler on
- * an element if no functions are provided.
- *
- * The mouseleave event differs from mouseout in the way it handles event bubbling. When
- * mouseout is used on an element having inner element(s), then when the mouse pointer moves out
- * of the Inner element, the handler would be triggered. This is usually undesirable behavior. The
- * mouseleave event, on the other hand, only triggers its handler when the mouse leaves the
- * element it is bound to, not a descendant.
- */
- public GQuery mouseleave(Function... f) {
- return as(Events).mouseleave(f);
- }
-
- /**
- * Bind a set of functions to the mousemove event of each matched element. Or trigger the event if
- * no functions are provided.
- */
- public GQuery mousemove(Function... f) {
- return bindOrFire(Event.ONMOUSEMOVE, null, f);
- }
-
- /**
- * Bind a set of functions to the mouseout event of each matched element. Or trigger the event if
- * no functions are provided.
- */
- public GQuery mouseout(Function... f) {
- return bindOrFire(Event.ONMOUSEOUT, null, f);
- }
-
- /**
- * Bind a set of functions to the mouseover event of each matched element. Or trigger the event if
- * no functions are provided.
- */
- public GQuery mouseover(Function... f) {
- return bindOrFire(Event.ONMOUSEOVER, null, f);
- }
-
- /**
- * Bind a set of functions to the mouseup event of each matched element. Or trigger the event if
- * no functions are provided.
- */
- public GQuery mouseup(Function... f) {
- return bindOrFire(Event.ONMOUSEUP, null, f);
- }
-
- /**
- * Get a set of elements containing the unique next siblings of each of the given set of elements.
- * next only returns the very next sibling for each element, not all next siblings see {#nextAll}.
- */
- public GQuery next() {
- JsNodeArray result = JsNodeArray.create();
- for (Element e : elements) {
- Element next = e.getNextSiblingElement();
- if (next != null) {
- result.addNode(next);
- }
- }
- return pushStack(unique(result), "next", getSelector());
- }
-
- /**
- * Get a set of elements containing the unique next siblings of each of the given set of elements
- * filtered by 1 or more selectors. next only returns the very next sibling for each element, not
- * all next siblings see {#nextAll}.
- */
- public GQuery next(String... selectors) {
- JsNodeArray result = JsNodeArray.create();
- for (Element e : elements) {
- Element next = e.getNextSiblingElement();
- if (next != null) {
- result.addNode(next);
- }
- }
- return pushStack(result, "next", selectors[0]).filter(selectors);
- }
-
- /**
- * Get all following siblings of each element in the set of matched elements.
- */
- public GQuery nextAll() {
- return nextAll(null);
- }
-
- /**
- * Get all following siblings of each element in the set of matched elements, filtered by a
- * selector.
- */
- public GQuery nextAll(String filter) {
- JsNodeArray result = JsNodeArray.create();
- for (Element e : elements) {
- allNextSiblingElements(e.getNextSiblingElement(), result, null, null, filter);
- }
-
- return pushStack(unique(result), "nextAll", getSelector());
- }
-
- /**
- * Get all following siblings of each element up to but not including the element matched by the
- * selector.
- *
- * @param selector
- * @return
- */
- public GQuery nextUntil(String selector) {
- return nextUntil($(selector), null);
- }
-
- /**
- * Get all following siblings of each element up to but not including the element matched by the
- * selector, filtered by a selector.
- *
- * @param selector
- * @return
- */
- public GQuery nextUntil(String selector, String filter) {
- return nextUntil($(selector), filter);
- }
-
- /**
- * Get all following siblings of each element up to but not including the element matched by the
- * DOM node.
- *
- * @param selector
- * @return
- */
- public GQuery nextUntil(Element until) {
- return nextUntil($(until), null);
- }
-
- /**
- * Get all following siblings of each element up to but not including the element matched by the
- * DOM node, filtered by a selector.
- *
- * @param selector
- * @return
- */
- public GQuery nextUntil(Element until, String filter) {
- return nextUntil($(until), filter);
- }
-
- /**
- * Get all following siblings of each element up to but not including the element matched by the
- * GQuery object.
- *
- * @param selector
- * @return
- */
- public GQuery nextUntil(GQuery until) {
- return nextUntil(until, null);
- }
-
- /**
- * Get all following siblings of each element up to but not including the element matched by the
- * GQuery object, filtered by a selector
- *
- * @param selector
- * @return
- */
- public GQuery nextUntil(GQuery until, String filter) {
- JsNodeArray result = JsNodeArray.create();
- for (Element e : elements) {
- allNextSiblingElements(e.getNextSiblingElement(), result, null, until, filter);
- }
- return pushStack(unique(result), "nextUntil", getSelector());
- }
-
- /**
- * Removes the specified Element from the set of matched elements. This method is used to remove a
- * single Element from a jQuery object.
- */
- public GQuery not(Element elem) {
- JsNodeArray array = JsNodeArray.create();
- for (Element e : elements) {
- if (e != elem) {
- array.addNode(e);
- }
- }
- return $(array);
- }
-
- /**
- * Removes any elements inside the passed set of elements from the set of matched elements.
- */
- public GQuery not(GQuery gq) {
- GQuery ret = this;
- for (Element e : gq.elements) {
- ret = ret.not(e);
- }
- return ret;
- }
-
- /**
- * Removes elements matching the specified expression from the set of matched elements.
- */
- public GQuery not(String... filters) {
- GQuery ret = this;
- for (String f : filters) {
- ret = ret.not($(f));
- }
- return ret;
- }
-
- /**
- * Get the current offset of the first matched element, in pixels, relative to the document. The
- * returned object contains two integer properties, top and left. The method works only with
- * visible elements.
- */
- public com.google.gwt.query.client.GQuery.Offset offset() {
- Element e = get(0);
- return e == null ? new Offset(0, 0) : new Offset(e.getAbsoluteLeft(), e.getAbsoluteTop());
- }
-
- /**
- * Returns a GQuery collection with the positioned parent of the first matched element. This is
- * the first parent of the element that has position (as in relative or absolute). This method
- * only works with visible elements.
- */
- public GQuery offsetParent() {
- if (isEmpty()) {
- return $();
- }
- Element offParent = JsUtils.or(get(0).getOffsetParent(), body);
- while (offParent != null && !"body".equalsIgnoreCase(offParent.getTagName())
- && !"html".equalsIgnoreCase(offParent.getTagName())
- && "static".equals(getStyleImpl().curCSS(offParent, "position", true))) {
- offParent = offParent.getOffsetParent();
- }
- return new GQuery(offParent);
- }
-
- /**
- * Binds a handler to a particular Event (like Event.ONCLICK) for each matched element. The
- * handler is executed only once for each element.
- *
- * The event handler is passed as a Function that you can use to prevent default behavior. To stop
- * both default action and event bubbling, the function event handler has to return false.
- *
- * You can pass an additional Object data to your Function as the second parameter
- */
- public GQuery one(int eventbits, final Object data, final Function f) {
- return as(Events).one(eventbits, data, f);
- }
-
- /**
- * Get the current computed height for the first element in the set of matched elements, including
- * padding, border, but not the margin.
- */
- public int outerHeight() {
- return outerHeight(false);
- }
-
- /**
- * Get the current computed height for the first element in the set of matched elements, including
- * padding, border, and optionally margin.
- */
- public int outerHeight(boolean includeMargin) {
- if (isEmpty()) {
- return 0;
- }
- // height including padding and border
- int outerHeight = (int)cur("offsetHeight", true);
- if (includeMargin) {
- outerHeight += cur("marginTop", true) + cur("marginBottom", true);
- }
- return outerHeight;
- }
-
- /**
- * Get the current computed width for the first element in the set of matched elements, including
- * padding, border, but not the margin.
- */
- public int outerWidth() {
- return outerWidth(false);
- }
-
- /**
- * Get the current computed width for the first element in the set of matched elements, including
- * padding and border and optionally margin.
- */
- public int outerWidth(boolean includeMargin) {
- if (isEmpty()) {
- return 0;
- }
- // width including padding and border
- int outerWidth = (int)cur("offsetWidth", true);
- if (includeMargin) {
- outerWidth += cur("marginRight", true) + cur("marginLeft", true);
- }
- return outerWidth;
- }
-
- /**
- * Get a set of elements containing the unique parents of the matched set of elements.
- */
- public GQuery parent() {
- JsNodeArray result = JsNodeArray.create();
- for (Element e : elements) {
- Element p = e.getParentElement();
- if (p != null) {
- result.addNode(p);
- }
- }
- return new GQuery(unique(result));
- }
-
- /**
- * Get a set of elements containing the unique parents of the matched set of elements. You may use
- * an optional expressions to filter the set of parent elements that will match one of them.
- */
- public GQuery parent(String... filters) {
- return parent().filter(filters);
- }
-
- /**
- * Get a set of elements containing the unique ancestors of the matched set of elements (except
- * for the root element).
- */
- public GQuery parents() {
- return parentsUntil(null);
- }
-
- /**
- * Get a set of elements containing the unique ancestors of the matched set of elements (except
- * for the root element). The matched elements are filtered, returning those that match any of the
- * filters.
- */
- public GQuery parents(String... filters) {
- return parents().filter(filters);
- }
-
- /**
- * Get the ancestors of each element in the current set of matched elements, up to but not
- * including the element matched by the selector.
- *
- */
- public GQuery parentsUntil(String selector) {
- JsNodeArray result = JsNodeArray.create();
- for (Element e : elements) {
- Node par = e.getParentNode();
- while (par != null && par != document) {
- if (selector != null && $(par).is(selector)) {
- break;
- }
- result.addNode(par);
- par = par.getParentNode();
- }
- }
- return new GQuery(unique(result));
- }
-
- /**
- * Gets the top and left position of an element relative to its offset parent. The returned object
- * contains two Integer properties, top and left. For accurate calculations make sure to use pixel
- * values for margins, borders and padding. This method only works with visible elements.
- */
- public com.google.gwt.query.client.GQuery.Offset position() {
- if (isEmpty()) {
- return new Offset(0, 0);
- }
- Element element = get(0);
- // Get *real* offsetParent
- Element offsetParent = get(0).getOffsetParent();
- // Get correct offsets
- Offset offset = offset();
- Offset parentOffset = null;
- if (offsetParent == body || offsetParent == (Node) document) {
- parentOffset = new Offset(0, 0);
- } else {
- parentOffset = $(offsetParent).offset();
- }
-
- // Subtract element margins
- int topMargin = (int) getStyleImpl().cur(element, "marginTop", true);
- // TODO: move this check to getStyleImpl()
- // When margin-left = auto, Safari and chrome return a value while IE and
- // Firefox return 0
- // force the margin-left to 0 if margin-left = auto.
- int leftMargin = 0;
- if (!"auto".equals(element.getStyle().getMarginLeft())) {
- leftMargin = (int) getStyleImpl().cur(element, "marginLeft", true);
- }
-
- offset = offset.add(-leftMargin, -topMargin);
-
- // Add offsetParent borders
- int parentOffsetBorderTop = (int) getStyleImpl().cur(offsetParent, "borderTopWidth", true);
- int parentOffsetBorderLeft = (int) getStyleImpl().cur(offsetParent, "borderLeftWidth", true);
- parentOffset = parentOffset.add(parentOffsetBorderLeft, parentOffsetBorderTop);
-
- // Subtract the two offsets
- return offset.add(-parentOffset.left, -parentOffset.top);
- }
-
- /**
- * Prepend content to the inside of every matched element. This operation is the best way to
- * insert elements inside, at the beginning, of all matched elements.
- */
- public GQuery prepend(GQuery query) {
- return domManip(query, DomMan.PREPEND);
- }
-
- /**
- * Prepend content to the inside of every matched element. This operation is the best way to
- * insert elements inside, at the beginning, of all matched elements.
- */
- public GQuery prepend(Node n) {
- return domManip($(n), DomMan.PREPEND);
- }
-
- /**
- * Prepend content to the inside of every matched element. This operation is the best way to
- * insert elements inside, at the beginning, of all matched elements.
- */
- public GQuery prepend(String html) {
- return domManip(html, DomMan.PREPEND);
- }
-
- /**
- * All of the matched set of elements will be inserted at the beginning of the element(s)
- * specified by the parameter other.
- *
- * The operation $(A).prependTo(B) is, essentially, the reverse of doing a regular
- * $(A).prepend(B), instead of prepending B to A, you're prepending A to B.
- */
- public GQuery prependTo(GQuery other) {
- other.prepend(this);
- return this;
- }
-
- /**
- * All of the matched set of elements will be inserted at the beginning of the element(s)
- * specified by the parameter other.
- *
- * The operation $(A).prependTo(B) is, essentially, the reverse of doing a regular
- * $(A).prepend(B), instead of prepending B to A, you're prepending A to B.
- */
- public GQuery prependTo(Node n) {
- $(n).prepend(this);
- return this;
- }
-
- /**
- * All of the matched set of elements will be inserted at the beginning of the element(s)
- * specified by the parameter other.
- *
- * The operation $(A).prependTo(B) is, essentially, the reverse of doing a regular
- * $(A).prepend(B), instead of prepending B to A, you're prepending A to B.
- */
- public GQuery prependTo(String html) {
- $(html).prepend(this);
- return this;
- }
-
- /**
- * Get a set of elements containing the unique previous siblings of each of the matched set of
- * elements. Only the immediately previous sibling is returned, not all previous siblings.
- */
- public GQuery prev() {
- JsNodeArray result = JsNodeArray.create();
- for (Element e : elements) {
- Element next = getPreviousSiblingElement(e);
- if (next != null) {
- result.addNode(next);
- }
- }
- return new GQuery(unique(result));
- }
-
- /**
- * Get a set of elements containing the unique previous siblings of each of the matched set of
- * elements filtered by selector. Only the immediately previous sibling is returned, not all
- * previous siblings.
- */
- public GQuery prev(String... selectors) {
- JsNodeArray result = JsNodeArray.create();
- for (Element e : elements) {
- Element next = getPreviousSiblingElement(e);
- if (next != null) {
- result.addNode(next);
- }
- }
- return new GQuery(unique(result)).filter(selectors);
- }
-
- /**
- * Get all preceding siblings of each element in the set of matched elements.
- */
- public GQuery prevAll() {
- return prevAll(null);
- }
-
- /**
- * Get all preceding siblings of each element in the set of matched elements filtered by a
- * selector.
- */
- public GQuery prevAll(String selector) {
- JsNodeArray result = JsNodeArray.create();
- for (Element e : elements) {
- allPreviousSiblingElements(getPreviousSiblingElement(e), result, null, selector);
- }
- return pushStack(unique(result), "prevAll", getSelector());
- }
-
- /**
- * Get all preceding siblings of each element up to but not including the element matched by the
- * <code>selector</code>.
- *
- * The elements are returned in order from the closest sibling to the farthest.
- */
- public GQuery prevUntil(String selector) {
- return prevUntil($(selector), null);
- }
-
- /**
- * Get all preceding siblings of each element up to but not including the <code>until</code>
- * element.
- *
- * The elements are returned in order from the closest sibling to the farthest.
- */
- public GQuery prevUntil(Element until) {
- return prevUntil($(until), null);
- }
-
- /**
- * Get all preceding siblings of each element up to but not including the <code>until</code>
- * element.
- *
- * The elements are returned in order from the closest sibling to the farthest.
- */
- public GQuery prevUntil(GQuery until) {
- return prevUntil(until, null);
- }
-
- /**
- * Get all preceding siblings of each element matching the <code>filter</code> up to but not
- * including the element matched by the <code>selector</code>.
- *
- * The elements are returned in order from the closest sibling to the farthest.
- */
- public GQuery prevUntil(String selector, String filter) {
- return prevUntil($(selector), filter);
- }
-
- /**
- * Get all preceding siblings of each element matching the <code>filter</code> up to but not
- * including the <code>until</code> element.
- *
- */
- public GQuery prevUntil(Element until, String filter) {
- return prevUntil($(until), filter);
- }
-
- /**
- * Get all preceding siblings of each element matching the <code>filter</code> up to but not
- * including the element matched by the <code>until</code> element.
- *
- */
- public GQuery prevUntil(GQuery until, String filter) {
- JsNodeArray result = JsNodeArray.create();
- for (Element e : elements) {
- allPreviousSiblingElements(getPreviousSiblingElement(e), result, until, filter);
- }
- return pushStack(unique(result), "prevUntil", getSelector());
- }
-
- /**
- * Accesses a boolean property on the first matched element.
- *
- * @param key the name of the boolean property to be accessed
- *
- * @return <code>true</code> if at least one element is matched and the specified boolean property
- * is set to <code>true</code> on the first matched element; <code>false</code> otherwise
- *
- */
- public boolean prop(String key) {
- assert key != null : "Key is null";
-
- return !isEmpty() && get(0).getPropertyBoolean(key);
- }
-
- /**
- * Sets a boolean property to a value on all matched elements.
- *
- * @param key the name of the boolean property to be set
- * @param value the value the specified boolean property should be set to
- *
- * @return this <code>GQuery</code> object
- *
- */
- public GQuery prop(String key, boolean value) {
- assert key != null : "Key is null";
-
- for (final Element element : elements) {
- element.setPropertyBoolean(key, value);
- }
-
- return this;
- }
-
- /**
- * Sets a boolean property to a computed value on all matched elements.
- *
- * @param key the name of the boolean property to be set
- * @param closure the closure to be used to compute the value the specified boolean property
- * should be set to; the <code>closure</code> is
- * {@linkplain Function#f(com.google.gwt.dom.client.Element, int) passed} the target
- * element and its index as arguments and is expected to return either a
- * <code>Boolean</code> value or an object whose textual representation is converted to a
- * <code>Boolean</code> value; <code>null</code> return values are ignored
- *
- * @return this <code>GQuery</code> object
- *
- */
- public GQuery prop(String key, Function closure) {
- assert key != null : "Key is null";
- assert closure != null : "Closure is null";
-
- int i = 0;
- for (Element e : elements) {
- Object value = closure.f(e, i++);
- if (value != null) {
- e.setPropertyBoolean(key, value instanceof Boolean ? (Boolean) value : Boolean
- .valueOf(value.toString()));
- }
- }
-
- return this;
- }
-
- protected GQuery pushStack(JsNodeArray elts, String name, String selector) {
- GQuery g = new GQuery(elts);
- g.setPreviousObject(this);
- g.setSelector(selector);
- g.currentContext = currentContext;
- return g;
- }
-
- /**
- * Show the number of functions in the efects queue to be executed on the first matched element.
- */
- public int queue() {
- return as(Queue).queue();
- }
-
- /**
- * Put a set of {@link Function} at the end of the Effects queue.
- *
- * Example:
- *
- * <pre class="code">
- * $("#foo").animate("left:'+=500'", 400)
- * .queue(new Function(){
- * public void f(Element e){
- * $(e).css(CSS.BACKGROUNG_COLOR.with(RGBColor.RED));
- * $(e).dequeue();
- * }
- * })
- * .animate("left:'-=500'", 400)
- * .queue(lazy().css("color", "yellow");
- *
- * </pre>
- *
- * When this statement is executed, the element move to 500 px to left for 400 ms, then its
- * background color is changed to red and then move to 500px to right for 400ms, and finally its
- * color is set to yellow.
- *
- * Please note that {@link #dequeue()} function is needed at the end of your function to start the
- * next function in the queue. In lazy() methods you should call dequeue() just before the done()
- * call. {@see #dequeue()}
- */
- public GQuery queue(Function... f) {
- return as(Queue).queue(f);
- }
-
- /**
- * Show the number of functions in the queued named as queueName to be executed on the first
- * matched element.
- */
- public int queue(String queueName) {
- return as(Queue).queue();
- }
-
- /**
- * Put a set of {@link Function} at the end of a queue.
- *
- * Example:
- *
- * <pre class="code">
- * $("#foo").queue("myQueue", new Function(){
- * public void f(Element e){
- * $(e).css(CSS.BACKGROUNG_COLOR.with(RGBColor.RED));
- * dequeue("myQueue");
- * }
- * })
- * .delay(500, "myQueue")
- * .queue("myQueue", lazy().css(CSS.COLOR.with(RGBColor.YELLOW)).dequeue("myQueue").done());
- * </pre>
- *
- * When this statement is executed, the background color of the element is set to red, then wait
- * 500ms before to set the text color of the element to yellow. right for 400ms.
- *
- * Please note that {@link #dequeue()} function is needed at the end of your function to start the
- * next function in the queue. In lazy() methods you should call dequeue() just before the done()
- * call. {@see #dequeue()}
- */
- public GQuery queue(String queueName, Function... f) {
- return as(Queue).queue(queueName, f);
- }
-
- /**
- * Removes all matched elements from the DOM.
- */
- public GQuery remove() {
- return remove(null, true);
- }
-
- /**
- * Removes from the DOM all matched elements filtered by the <code>filter</code>.
- */
- public GQuery remove(String filter) {
- return remove(filter, true);
- }
-
- /**
- * Removes all matched elements from the DOM and cleans their data and bound events if the value
- * of <code>clean</code> parameter is set to true. The <code> filter</code> parameter allows to
- * filter the matched set to remove.
- */
- protected GQuery remove(String filter, boolean clean) {
- for (Element e : elements) {
- if (filter == null || $(e).filter(filter).length() == 1) {
- if (clean) {
- // clean data linked to the children
- // TODO: "*" fails in queryselectorall (webkit mobile)
- cleanGQData($("*", e).elements());
- // clean data linked to the element itself
- cleanGQData(e);
- }
- Widget w = getAssociatedWidget(e);
- if (w != null) {
- w.removeFromParent();
- } else {
- e.removeFromParent();
- }
- }
- }
- return this;
- }
-
- /**
- * Remove the named attribute from every element in the matched set.
- */
- public GQuery removeAttr(String key) {
- getAttributeImpl().removeAttribute(this, key);
- return this;
- }
-
- /**
- * Removes the specified classes to each matched element.
- *
- * If no arguments are provided, it removes all classes like jquery does.
- */
- public GQuery removeClass(String... classes) {
- for (Element e : elements) {
- if (Element.is(e)) {
- if (classes.length == 0) {
- e.setClassName(null);
- } else {
- for (String clz : classes) {
- e.removeClassName(clz);
- }
- }
- }
- }
- return this;
- }
-
- protected void removeData(Element item, String name) {
- if (dataCache == null) {
- windowData = JavaScriptObject.createObject().cast();
- dataCache = JavaScriptObject.createObject().cast();
- }
- item = item == window || item.getNodeName() == null ? windowData : item;
- int id = item.hashCode();
- if (name != null) {
- if (dataCache.exists(id)) {
- dataCache.getCache(id).delete(name);
- }
- if (dataCache.getCache(id).isEmpty()) {
- removeData(item, null);
- }
- } else {
- // when the element cache is empty we remove its entry to save memory (issue 132)
- dataCache.delete(id);
- }
- }
-
- /**
- * Removes named data store from an element.
- */
- public GQuery removeData(String name) {
- for (Element e : elements) {
- removeData(e, name);
- }
- return this;
- }
-
- /**
- * Replaces the element <code>elem</code> by the specified selector with the matched elements.
- * This function is the complement to replaceWith() which does the same task with the parameters
- * reversed.
- *
- * @return a {@link GQuery} object containing the new elements.
- */
- public GQuery replaceAll(Element elem) {
- return replaceAll($(elem));
- }
-
- /**
- * Replaces the elements matched by the target with the selected elements. This function is the
- * complement to replaceWith() which does the same task with the parameters reversed.
- *
- * @return a {@link GQuery} object containing the new elements.
- */
- public GQuery replaceAll(GQuery target) {
- // if there is only one element and it is not attached to the dom, we have
- // to clone it to be reused on each element of target (if target contains
- // more than one element)
- boolean mustBeCloned = length() == 1 && parents().filter("body").length() == 0;
-
- List<Element> newElements = new ArrayList<Element>();
- for (int i = 0, l = target.size(); i < l; i++) {
- GQuery _this = (i > 0 && mustBeCloned) ? this.clone() : this;
- $(target.get(i)).replaceWith(_this);
- newElements.addAll(Arrays.asList(_this.elements));
- }
- return $(newElements);
- }
-
- /**
- * Replaces the elements matched by the specified selector with the matched elements. This
- * function is the complement to replaceWith() which does the same task with the parameters
- * reversed.
- *
- * @return a {@link GQuery} object containing the new elements.
- */
- public GQuery replaceAll(String selector) {
- return replaceAll($(selector));
- }
-
- /**
- * Replaces all matched elements with the specified element.
- *
- * @return the GQuery element that was just replaced, which has been removed from the DOM and not
- * the new element that has replaced it.
- */
- public GQuery replaceWith(Element elem) {
- return replaceWith($(elem));
- }
-
- /**
- * Replaces all matched elements with elements selected by <code>target</code> .
- *
- * @return the GQuery element that was just replaced, which has been removed from the DOM and not
- * the new element that has replaced it.
- */
- public GQuery replaceWith(GQuery target) {
- for (Element el : elements) {
- Element nextSibling = el.getNextSiblingElement();
-
- if (nextSibling != null) {
- $(nextSibling).before(target);
- } else {
- Element parent = el.getParentElement();
- $(parent).append(target);
- }
- $(el).remove();
- }
- return this;
-
- }
-
- /**
- * Replaces all matched elements with the specified HTML.
- *
- * @return the GQuery element that was just replaced, which has been removed from the DOM and not
- * the new element that has replaced it.
- */
- public GQuery replaceWith(String html) {
- for (Element el : elements) {
- Element nextSibling = el.getNextSiblingElement();
-
- if (nextSibling != null) {
- $(nextSibling).before(html);
- } else {
- Element parent = el.getParentElement();
- $(parent).append(html);
- }
- $(el).remove();
- }
- return this;
- }
-
- /**
- * Bind a set of functions to the resize event of each matched element, or tigger the resize event
- * if no functions are provided.
- *
- * Note that although all elements can be configured to handle resize events, by default only
- * window will trigger it when it is resized, for an arbitrary element you have to trigger the
- * event after resizing the object.
- *
- */
- public GQuery resize(Function... f) {
- return bindOrFire(EventsListener.ONRESIZE, null, f);
- }
-
- /**
- * Bind an event handler to the "resize" JavaScript event, or trigger that event on an element.
- */
- public GQuery resize(final Function f) {
- return bindOrFire(EventsListener.ONRESIZE, null, f);
- }
-
- /**
- * Save a set of Css properties of every matched element.
- */
- public void restoreCssAttrs(String... cssProps) {
- for (Element e : elements) {
- for (String a : cssProps) {
- String datakey = OLD_DATA_PREFIX + a;
- getStyleImpl().setStyleProperty(e, a, (String) data(e, datakey, null));
- removeData(e, datakey);
- }
- }
- }
-
- /**
- * Restore a set of previously saved Css properties in every matched element.
- */
- public void saveCssAttrs(String... cssProps) {
- for (Element e : elements) {
- for (String a : cssProps) {
- data(OLD_DATA_PREFIX + a, getStyleImpl().curCSS(e, a, false));
- }
- }
- }
-
- /**
- * Bind a set of functions to the scroll event of each matched element. Or trigger the event if no
- * functions are provided.
- */
- public GQuery scroll(Function... f) {
- return bindOrFire(Event.ONSCROLL, null, f);
- }
-
- /**
- * Scrolls the first matched element into view.
- */
- public GQuery scrollIntoView() {
- if (!isEmpty())
- scrollIntoViewImpl(get(0));
- return this;
- }
-
- /**
- * Scrolls the first matched element into view.
- *
- * If ensure == true, it crawls up the DOM hierarchy, adjusting the scrollLeft and scrollTop
- * properties of each scroll-able element to ensure that the specified element is completely in
- * view. It adjusts each scroll position by the minimum amount necessary.
- */
- public GQuery scrollIntoView(boolean ensure) {
- if (!isEmpty() && ensure) {
- DOM.scrollIntoView((com.google.gwt.user.client.Element) get(0));
- } else {
- scrollIntoView();
- }
- return this;
- }
-
- /**
- * Gets the scroll left offset of the first matched element. This method works for both visible
- * and hidden elements.
- */
- public int scrollLeft() {
- Element e = get(0);
- if (e == null) {
- return 0;
- }
- if (e == window || e.getNodeName() == null) {
- return Window.getScrollLeft();
- } else if (e == (Node) document) {
- return document.getScrollLeft();
- } else {
- return e.getScrollLeft();
- }
- }
-
- /**
- * The scroll left offset is set to the passed value on all matched elements. This method works
- * for both visible and hidden elements.
- */
- public GQuery scrollLeft(int left) {
- for (Element e : elements) {
- if (e == window || e.getNodeName() == null || e == (Node) document) {
- Window.scrollTo(left, $(e).scrollTop());
- } else {
- e.setPropertyInt("scrollLeft", left);
- }
- }
- return this;
- }
-
- /**
- *
- * Scrolls the contents of all matched elements to the specified co-ordinate becoming the top left
- * corner of the viewable area.
- *
- * This method is only useful where there are areas of the document not viewable within the
- * current viewable area of the window and the visible property of the window's scrollbar must be
- * set to true.
- *
- */
- public GQuery scrollTo(int left, int top) {
- scrollLeft(left).scrollTop(top);
- return this;
- }
-
- /**
- * Gets the scroll top offset of the first matched element. This method works for both visible and
- * hidden elements.
- */
- public int scrollTop() {
- Element e = get(0);
- if (e == null) {
- return 0;
- }
- if (e == window || e.getNodeName() == null) {
- return Window.getScrollTop();
- } else if (e == (Node) document) {
- return document.getScrollTop();
- } else {
- return e.getScrollTop();
- }
- }
-
- /**
- * The scroll top offset is set to the passed value on all matched elements. This method works for
- * both visible and hidden elements.
- */
- public GQuery scrollTop(int top) {
- for (Element e : elements) {
- if (e == window || e.getNodeName() == null || e == (Node) document) {
- Window.scrollTo($(e).scrollLeft(), top);
- } else {
- e.setPropertyInt("scrollTop", top);
- }
- }
- return this;
- }
-
- public GQuery select() {
- return as(Events).triggerHtmlEvent("select");
- }
-
- private GQuery select(String selector, Node context) {
- if (engine == null) {
- engine = new SelectorEngine();
- }
-
- NodeList<Element> n = engine.select(selector, context == null ? document : context);
- currentSelector = selector;
- currentContext = context != null ? context : document;
- return setArray(n);
- }
-
- /**
- * Force the current matched set of elements to become the specified array of elements.
- */
- public GQuery setArray(NodeList<Element> list) {
- if (list != null) {
- nodeList.<JsCache> cast().clear();
- int l = list.getLength();
- elements = new Element[l];
- for (int i = 0; i < l; i++) {
- elements[i] = list.getItem(i);
- nodeList.<JsObjectArray<Element>> cast().add(list.getItem(i));
- }
- }
- return this;
- }
-
- public void setPreviousObject(GQuery previousObject) {
- this.previousObject = previousObject;
- }
-
- public GQuery setSelector(String selector) {
- this.currentSelector = selector;
- return this;
- }
-
- /**
- * Make all matched elements visible
- */
- public GQuery show() {
- for (Element e : elements) {
- String currentDisplay = e.getStyle().getDisplay();
- String oldDisplay = (String) data(e, OLD_DISPLAY, null);
-
- // reset the display
- if (oldDisplay == null && "none".equals(currentDisplay)) {
- getStyleImpl().setStyleProperty(e, "display", "");
- currentDisplay = "";
- }
-
- // check if the stylesheet impose display: none. If it is the case, determine
- // the default display for the tag and store it at the element level
- if ("".equals(currentDisplay) && !getStyleImpl().isVisible(e)) {
- data(e, OLD_DISPLAY, getStyleImpl().defaultDisplay(e.getNodeName()));
- }
- }
-
- // set the display value in a separate for loop to avoid constant reflow
- // because broswer reflow is triggered each time we gonna set and after get (in
- // isVisibleProperty() method)
- // the diplay property. Reflows is very bad in performance point of view
- for (Element e : elements) {
- String currentDisplay = e.getStyle().getDisplay();
- if ("".equals(currentDisplay) || "none".equals(currentDisplay)) {
- getStyleImpl().setStyleProperty(e, "display",
- JsUtils.or((String) data(e, OLD_DISPLAY, null), ""));
- }
- }
- removeData(OLD_DISPLAY);
- return this;
- }
-
- /**
- * Get a set of elements containing all of the unique siblings of each of the matched set of
- * elements.
- */
- public GQuery siblings() {
- JsNodeArray result = JsNodeArray.create();
- for (Element e : elements) {
- allNextSiblingElements(e.getParentElement().getFirstChildElement(), result, e, null, null);
- }
- return new GQuery(unique(result));
- }
-
- /**
- * Get a set of elements containing all of the unique siblings of each of the matched set of
- * elements filtered by the provided set of selectors.
- */
- public GQuery siblings(String... selectors) {
- return siblings().filter(selectors);
- }
-
- /**
- * Return the number of elements in the matched set.
- */
- public int size() {
- return elements.length;
- }
-
- /**
- * Selects a subset of the matched elements.
- */
- public GQuery slice(int start, int end) {
- JsNodeArray slice = JsNodeArray.create();
- int l = size();
- if (end == -1 || end > l) {
- end = l;
- }
- for (int i = start; i < end; i++) {
- slice.addNode(get(i));
- }
- return new GQuery(slice);
- }
-
- /**
- * Reveal all matched elements by adjusting their height and firing an optional callback after
- * completion.
- */
- public Effects slideDown(Function... f) {
- return as(Effects).slideDown(f);
- }
-
- /**
- * Reveal all matched elements by adjusting their height and firing an optional callback after
- * completion.
- */
- public Effects slideDown(int millisecs, Function... f) {
- return as(Effects).slideDown(millisecs, f);
- }
-
- /**
- * Toggle the visibility of all matched elements by adjusting their height and firing an optional
- * callback after completion. Only the height is adjusted for this animation, causing all matched
- * elements to be hidden or shown in a "sliding" manner
- */
- public Effects slideToggle(int millisecs, Function... f) {
- return as(Effects).slideToggle(millisecs, f);
- }
-
- /**
- * Hide all matched elements by adjusting their height and firing an optional callback after
- * completion.
- */
- public Effects slideUp(Function... f) {
- return as(Effects).slideUp(f);
- }
-
- /**
- * Hide all matched elements by adjusting their height and firing an optional callback after
- * completion.
- */
- public Effects slideUp(int millisecs, Function... f) {
- return as(Effects).slideUp(millisecs, f);
- }
-
- /**
- * When .stop() is called on an element, the currently-running animation (if any) is immediately
- * stopped. If, for instance, an element is being hidden with .slideUp() when .stop() is called,
- * the element will now still be displayed, but will be a fraction of its previous height.
- * Callback functions are not called but the next animation in the queue begins immediately.
- */
- public GQuery stop() {
- return stop(false);
- }
-
- /**
- * When .stop() is called on an element, the currently-running animation (if any) is immediately
- * stopped. If, for instance, an element is being hidden with .slideUp() when .stop() is called,
- * the element will now still be displayed, but will be a fraction of its previous height.
- * Callback functions are not called but the next animation in the queue begins immediately.
- *
- * If the clearQueue parameter is provided with a value of true, then the rest of the animations
- * in the queue are removed and never run.
- */
- public GQuery stop(boolean clearQueue) {
- return stop(clearQueue, false);
- }
-
- /**
- * When .stop() is called on an element, the currently-running animation (if any) is immediately
- * stopped. If, for instance, an element is being hidden with .slideUp() when .stop() is called,
- * the element will now still be displayed, but will be a fraction of its previous height.
- * Callback functions are not called but the next animation in the queue begins immediately.
- *
- * If the clearQueue parameter is provided with a value of true, then the rest of the animations
- * in the queue are removed and never run.
- *
- * If the jumpToEnd property is provided with a value of true, the current animation stops, but
- * the element is immediately given its target values for each CSS property. The callback
- * functions are then immediately called, if provided.
- */
- public GQuery stop(boolean clearQueue, boolean jumpToEnd) {
- return as(Queue).stop(clearQueue, jumpToEnd);
- }
-
- /**
- * Bind a set of functions to the submit event of each matched element. Or submit a form if no
- * functions are provided.
- */
- public GQuery submit(Function... funcs) {
- return bindOrFire(EventsListener.ONSUBMIT, null, funcs);
- }
-
- /**
- * Return the concatened text contained in the matched elements.
- */
- public String text() {
- String result = "";
- for (Element e : elements) {
- result += JsUtils.text(e);
- }
- return result;
- }
-
- /**
- * Set the innerText of every matched element.
- */
- public GQuery text(String txt) {
- for (Element e : elements) {
- e.setInnerText(txt);
- }
- return this;
- }
-
- /**
- * Toggle visibility of elements.
- */
- public GQuery toggle() {
- for (Element e : elements) {
- if (getStyleImpl().isVisible(e)) {
- $(e).hide();
- } else {
- $(e).show();
- e.getStyle().setDisplay(Display.BLOCK);
- }
- }
- return this;
- }
-
- /**
- * Toggle among two or more function calls every other click.
- */
- public GQuery toggle(final Function... fn) {
- for (Element e : elements) {
- $(e).click(new Function() {
- int click = 0;
-
- public boolean f(Event e) {
- int n = fn.length == 1 ? 0 : (click++ % fn.length);
- return fn[n].f(e);
- }
- });
- }
- return this;
- }
-
- /**
- * Adds or removes the specified classes to each matched element depending on the class's
- * presence.
- */
- public GQuery toggleClass(String... classes) {
- for (Element e : elements) {
- for (String clz : classes) {
- if (hasClass(e, clz)) {
- e.removeClassName(clz);
- } else {
- e.addClassName(clz);
- }
- }
- }
- return this;
- }
-
- /**
- * Adds or removes the specified classes to each matched element depending on the value of the
- * switch argument.
- *
- * if addOrRemove is true, the class is added and in the case of false it is removed.
- */
- public GQuery toggleClass(String clz, boolean addOrRemove) {
- if (addOrRemove) {
- addClass(clz);
- } else {
- removeClass(clz);
- }
- return this;
- }
-
- /**
- * Returns the computed top position of the first element matched.
- */
- public int top() {
- return (int) cur("top", true);
- }
-
- /**
- * Produces a string representation of the matched elements.
- */
- public String toString() {
- return toString(false);
- }
-
- /**
- * Produces a string representation of the matched elements.
- */
- public String toString(boolean pretty) {
- String r = "";
- for (Element e : elements) {
- if (window.equals(e)) {
- continue;
- }
- String elStr;
- try {
- elStr = JsUtils.isXML(e) ? JsUtils.XML2String(e) : e.getString();
- } catch (Exception e2) {
- elStr =
- "< " + (e == null ? "null" : e.getNodeName())
- + "(gquery, error getting the element string representation: " + e2.getMessage()
- + ")/>";
- }
- r += (pretty && r.length() > 0 ? "\n " : "") + elStr;
- }
- return r;
- }
-
- /**
- * Trigger a set of events on each matched element.
- *
- * For keyboard events you can pass a second parameter which represents the key-code of the pushed
- * key.
- *
- * Example: fire(Event.ONCLICK | Event.ONFOCUS) Example: fire(Event.ONKEYDOWN. 'a');
- */
- public GQuery trigger(int eventbits, int... keys) {
- return as(Events).trigger(eventbits, keys);
- }
-
- /**
- * Removes all events that match the eventbits.
- */
- public GQuery unbind(int eventbits) {
- return as(Events).unbind(eventbits);
- }
-
- /**
- * Removes the function passed from the set of events which match the eventbits.
- */
- public GQuery unbind(int eventbits, Function f) {
- return as(Events).unbind(eventbits, null, f);
- }
-
- /**
- * Removes all events that match the eventList.
- */
- public GQuery unbind(String eventList) {
- return unbind(eventList, null);
- }
-
- /**
- * Removes all events that match the eventList.
- */
- public GQuery unbind(String eventList, Function f) {
- return as(Events).unbind(eventList, f);
- }
-
- /**
- * Remove all event delegation that have been bound using
- * {@link #delegate(String, int, Function...)} {@link #live(int, Function...)} methods
- */
- public GQuery undelegate() {
- return as(Events).undelegate();
- }
-
- /**
- * Undelegate is a way of removing event handlers that have been bound using
- * {@link #delegate(String, int, Function...)} method
- */
- public GQuery undelegate(String selector) {
- for (Element e : elements) {
- $(selector, e).die();
- }
-
- return this;
- }
-
- /**
- * Undelegate is a way of removing event handlers that have been bound using
- * {@link #delegate(String, int, Function...)} method
- */
- public GQuery undelegate(String selector, int eventBit) {
- for (Element e : elements) {
- $(selector, e).die(eventBit);
- }
-
- return this;
- }
-
- /**
- * Undelegate is a way of removing event handlers that have been bound using
- * {@link #delegate(String, int, Function...)} method
- */
- public GQuery undelegate(String selector, String eventName) {
- for (Element e : elements) {
- $(selector, e).die(eventName);
- }
-
- return this;
- }
-
- /**
- * Remove all duplicate elements from an array of elements. Note that this only works on arrays of
- * DOM elements, not strings or numbers.
- */
- public JsNodeArray unique(NodeList<Element> result) {
- return JsUtils.unique(result.<JsArray<Element>> cast()).cast();
- }
-
- /**
- * This method removes the element's parent. The matched elements replaces their parents within
- * the DOM structure. It is the inverse of {@link GQuery#wrap(GQuery)} method
- *
- * @return
- */
- public GQuery unwrap() {
-
- for (Element parent : parent().elements) {
- if (!"body".equalsIgnoreCase(parent.getTagName())) {
- GQuery $parent = $(parent);
- $parent.replaceWith($parent.children());
- }
- }
- return this;
- }
-
- /**
- * Gets the content of the value attribute of the first matched element, returns only the first
- * value even if it is a multivalued element. To get an array of all values in multivalues
- * elements use vals()
- *
- * When the first element is a radio-button and is not checked, then it looks for the first
- * checked radio-button that has the same name in the list of matched elements.
- *
- * When there are not matched elements it returns null.
- */
- public String val() {
- if (isEmpty()) {
- return null;
- }
- String[] v = vals();
- return v == null ? null : v.length > 0 ? v[0] : "";
- }
-
- /**
- * Sets the value attribute of every matched element based in the return value of the function
- * evaluated for this element.
- *
- * NOTE: in jquery the function receives the arguments in different way, first index and them the
- * actual value, but we use the normal way in gquery Function, first the element and second the
- * index.
- */
- public GQuery val(Function f) {
- for (int i = 0; i < size(); i++) {
- eq(i).val(f.f(get(i), i).toString());
- }
- return this;
- }
-
- /**
- * Sets the 'value' attribute of every matched element, but does not set the checked flag to
- * checkboxes or radiobuttons.
- *
- * If you wanted to set values in collections of checkboxes o radiobuttons use val(String[])
- * instead
- */
- public GQuery val(String value) {
- for (Element e : elements) {
- setElementValue(e, value);
- }
- return this;
- }
-
- /**
- * Sets the value of every matched element.
- *
- * There is a different behaviour depending on the element type:
- * <ul>
- * <li>select multiple: options whose value match any of the passed values will be set.
- * <li>select single: the last option whose value matches any of the passed values will be set.
- * <li>input radio: the last input whose value matches any of the passed values will be set.
- * <li>input checkbox: inputs whose value match any of the passed values will be set.
- * <li>textarea, button, and other input: value will set to a string result of joining with coma,
- * all passed values
- * </ul>
- *
- * NOTE: if you wanted call this function with just one parameter, you have to pass an array
- * signature to avoid call the overloaded val(String) method:
- *
- * $(...).val(new String[]{"value"});
- */
- public GQuery val(String... values) {
- String value = values.length > 0 ? values[0] : "";
- for (int i = 1; i < values.length; i++) {
- value += "," + values[i];
- }
- for (Element e : elements) {
- String name = e.getNodeName();
- if ("select".equalsIgnoreCase(name)) {
- SelectElement s = SelectElement.as(e);
- s.setSelectedIndex(-1);
- for (String v : values) {
- if (s.isMultiple()) {
- for (int i = 0, l = s.getOptions().getLength(); i < l; i++) {
- if (v.equals(s.getOptions().getItem(i).getValue())) {
- s.getOptions().getItem(i).setSelected(true);
- }
- }
- } else {
- s.setValue(v);
- }
- }
- } else if ("input".equalsIgnoreCase(name)) {
- InputElement ie = InputElement.as(e);
- String type = ie.getType();
- if ("radio".equalsIgnoreCase((type)) || "checkbox".equalsIgnoreCase(type)) {
- ie.setChecked(false);
- for (String v : values) {
- if (ie.getValue().equals(v)) {
- ie.setChecked(true);
- break;
- }
- }
- } else {
- ie.setValue(value);
- }
- } else {
- setElementValue(e, value);
- }
- }
- return this;
- }
-
- /**
- * Gets the content of the value attribute of the first matched element, returns more than one
- * value if it is a multiple select.
- *
- * When the first element is a radio-button and is not checked, then it looks for a the first
- * checked radio-button that has the same name in the list of matched elements.
- *
- * This method always returns an array. If no valid value can be determined the array will be
- * empty, otherwise it will contain one or more values.
- */
- public String[] vals() {
- if (!isEmpty()) {
- Element e = get(0);
- if (e.getNodeName().equalsIgnoreCase("select")) {
- SelectElement se = SelectElement.as(e);
- if (se.isMultiple()) {
- JsArrayString result = JsArrayString.createArray().cast();
- for (int i = 0, l = se.getOptions().getLength(); i < l; i++) {
- OptionElement oe = se.getOptions().getItem(i);
- if (oe.isSelected()) {
- result.set(result.length(), oe.getValue());
- }
- }
- return result.length() > 0 ? jsArrayToString(result) : null;
- } else if (se.getSelectedIndex() >= 0) {
- return new String[] {se.getOptions().getItem(se.getSelectedIndex()).getValue()};
- }
- } else if (e.getNodeName().equalsIgnoreCase("input")) {
- InputElement ie = InputElement.as(e);
- return new String[] {ie.getValue()};
- } else if (e.getNodeName().equalsIgnoreCase("textarea")) {
- return new String[] {TextAreaElement.as(e).getValue()};
- } else if (e.getNodeName().equalsIgnoreCase("button")) {
- return new String[] {ButtonElement.as(e).getValue()};
- }
- }
- return new String[0];
- }
-
- @Deprecated
- public boolean visible() {
- return isVisible();
- }
-
- /**
- * Return the first non null attached widget from the matched elements or null if there isn't any.
- */
- @SuppressWarnings("unchecked")
- public <W extends Widget> W widget() {
- return (W) widget(0);
- }
-
- /**
- * Return the nth non null attached widget from the matched elements or null if there isn't any.
- */
- public <W extends Widget> W widget(int n) {
- for (Element e : elements) {
- @SuppressWarnings("unchecked")
- W w = (W) getAssociatedWidget(e);
- if (w != null) {
- if (n == 0) {
- return w;
- }
- n--;
- }
- }
- return null;
- }
-
- /**
- * return the list of attached widgets matching the query
- */
- public List<Widget> widgets() {
- List<Widget> widgets = new ArrayList<Widget>();
- for (Element e : elements) {
- Widget w = getAssociatedWidget(e);
- if (w != null) {
- widgets.add(w);
- }
- }
- return widgets;
- }
-
- /**
- * Return the list of attached widgets instance of the provided class matching the query.
- *
- * This method is very useful for decoupled views, so as we can access widgets from other views
- * without maintaining methods which export them.
- *
- */
- @SuppressWarnings("unchecked")
- public <W extends Widget> List<W> widgets(Class<W> clazz) {
- List<W> ret = new ArrayList<W>();
- for (Widget w : widgets()) {
- // isAssignableFrom does not work in gwt.
- Class<?> c = w.getClass();
- do {
- if (c.equals(clazz)) {
- ret.add((W) w);
- break;
- }
- c = c.getSuperclass();
- } while (c != null);
- }
- return ret;
- }
-
- /**
- * Get the current computed, pixel, width of the first matched element. It does not include
- * margin, padding nor border.
- */
- public int width() {
- return (int) cur("width", true);
- }
-
- /**
- * Set the width of every matched element.
- */
- public GQuery width(int width) {
- for (Element e : elements) {
- e.getStyle().setPropertyPx("width", width);
- }
- return this;
- }
-
- /**
- * Wrap each matched element with the specified HTML content. This wrapping process is most useful
- * for injecting additional structure into a document, without ruining the original semantic
- * qualities of a document. This works by going through the first element provided (which is
- * generated, on the fly, from the provided HTML) and finds the deepest descendant element within
- * its structure -- it is that element that will enwrap everything else.
- */
- public GQuery wrap(Element elem) {
- return wrap($(elem));
- }
-
- /**
- * Wrap each matched element with the specified HTML content. This wrapping process is most useful
- * for injecting additional structure into a document, without ruining the original semantic
- * qualities of a document. This works by going through the first element provided (which is
- * generated, on the fly, from the provided HTML) and finds the deepest descendant element within
- * its structure -- it is that element that will enwrap everything else.
- */
- public GQuery wrap(GQuery query) {
- for (Element e : elements) {
- $(e).wrapAll(query);
- }
- return this;
- }
-
- /**
- * Wrap each matched element with the specified HTML content. This wrapping process is most useful
- * for injecting additional structure into a document, without ruining the original semantic
- * qualities of a document. This works by going through the first element provided (which is
- * generated, on the fly, from the provided HTML) and finds the deepest descendant element within
- * its structure -- it is that element that will enwrap everything else.
- */
- public GQuery wrap(String html) {
- return wrap($(html));
- }
-
- /**
- * Wrap all the elements in the matched set into a single wrapper element. This is different from
- * .wrap() where each element in the matched set would get wrapped with an element. This wrapping
- * process is most useful for injecting additional structure into a document, without ruining the
- * original semantic qualities of a document.
- *
- * This works by going through the first element provided (which is generated, on the fly, from
- * the provided HTML) and finds the deepest descendant element within its structure -- it is that
- * element that will enwrap everything else.
- */
- public GQuery wrapAll(Element elem) {
- return wrapAll($(elem));
- }
-
- /**
- * Wrap all the elements in the matched set into a single wrapper element. This is different from
- * .wrap() where each element in the matched set would get wrapped with an element. This wrapping
- * process is most useful for injecting additional structure into a document, without ruining the
- * original semantic qualities of a document.
- *
- * This works by going through the first element provided (which is generated, on the fly, from
- * the provided HTML) and finds the deepest descendant element within its structure -- it is that
- * element that will enwrap everything else.
- */
- public GQuery wrapAll(GQuery query) {
- if (!isEmpty()) {
- GQuery wrap = query.clone();
- if (get(0).getParentNode() != null) {
- wrap.insertBefore(get(0));
- }
- for (Element e : wrap.elements) {
- Node n = e;
- while (n.getFirstChild() != null && n.getFirstChild().getNodeType() == Node.ELEMENT_NODE) {
- n = n.getFirstChild();
- }
- $((Element) n).append(this);
- }
- }
- return this;
- }
-
- /**
- * Wrap all the elements in the matched set into a single wrapper element. This is different from
- * .wrap() where each element in the matched set would get wrapped with an element. This wrapping
- * process is most useful for injecting additional structure into a document, without ruining the
- * original semantic qualities of a document.
- *
- * This works by going through the first element provided (which is generated, on the fly, from
- * the provided HTML) and finds the deepest descendant element within its structure -- it is that
- * element that will enwrap everything else.
- */
- public GQuery wrapAll(String html) {
- return wrapAll($(html));
- }
-
- /**
- * Wrap the inner child contents of each matched element (including text nodes) with an HTML
- * structure. This wrapping process is most useful for injecting additional structure into a
- * document, without ruining the original semantic qualities of a document. This works by going
- * through the first element provided (which is generated, on the fly, from the provided HTML) and
- * finds the deepest ancestor element within its structure -- it is that element that will enwrap
- * everything else.
- */
- public GQuery wrapInner(Element elem) {
- return wrapInner($(elem));
- }
-
- /**
- * Wrap the inner child contents of each matched element (including text nodes) with an HTML
- * structure. This wrapping process is most useful for injecting additional structure into a
- * document, without ruining the original semantic qualities of a document. This works by going
- * through the first element provided (which is generated, on the fly, from the provided HTML) and
- * finds the deepest ancestor element within its structure -- it is that element that will enwrap
- * everything else.
- */
- public GQuery wrapInner(GQuery query) {
- for (Element e : elements) {
- $(e).contents().wrapAll(query);
- }
- return this;
- }
-
- /**
- * Wrap the inner child contents of each matched element (including text nodes) with an HTML
- * structure. This wrapping process is most useful for injecting additional structure into a
- * document, without ruining the original semantic qualities of a document. This works by going
- * through the first element provided (which is generated, on the fly, from the provided HTML) and
- * finds the deepest ancestor element within its structure -- it is that element that will enwrap
- * everything else.
- */
- public GQuery wrapInner(String html) {
- return wrapInner($(html));
- }
-}
+/* + * 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 java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +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.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.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.Style.HasCssName; +import com.google.gwt.dom.client.TextAreaElement; +import com.google.gwt.query.client.css.CSS; +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.JsRegexp; +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.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.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; + +/** + * GwtQuery is a GWT clone of the popular jQuery library. + */ +public class GQuery implements Lazy<GQuery, LazyGQuery> { + + 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 = Document.get().getBody(); + + /** + * 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 = Document.get(); + + /** + * Static reference Effects plugin + */ + public static Class<Effects> 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> Events = com.google.gwt.query.client.plugins.Events.Events; + + /** + * A static reference to the GQuery class. + */ + public static Class<GQuery> GQUERY = GQuery.class; + + private static final String OLD_DATA_PREFIX = "old-"; + + private static final String OLD_DISPLAY = OLD_DATA_PREFIX + "display"; + + private static JsMap<Class<? extends GQuery>, Plugin<? extends GQuery>> plugins; + + // Sizzle POS regex : usefull in some methods + // TODO: Share this static with SelectorEngineSizzle + private static final String POS_REGEX = + ":(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)"; + + /** + * Implementation class used for style manipulations. + */ + private static DocumentStyleImpl styleImpl; + + private static JsRegexp tagNameRegex = new JsRegexp("<([\\w:]+)"); + + /** + * Static reference to the Widgets plugin + */ + public static Class<Widgets> Widgets = com.google.gwt.query.client.plugins.Widgets.Widgets; + + /** + * The window object. + */ + public static final Element window = window(); + + private static Element windowData = null; + + private static JsNamedArray<TagWrapper> wrapperMap; + + /** + * Create an empty GQuery object. + */ + public static GQuery $() { + return new GQuery(JsNodeArray.create()); + } + + /** + * Wrap a GQuery around an existing element. + */ + public static GQuery $(Element element) { + return new GQuery(element); + } + + /** + * Wrap a GQuery around an event's target element. + */ + public static GQuery $(Event event) { + return event == null ? $() : $((Element) event.getCurrentEventTarget().cast()); + } + + /** + * Wrap a GQuery around the element of a Function callback. + */ + public static GQuery $(Function f) { + return $(f.getElement()); + } + + /** + * Wrap a GQuery around an existing javascript element, event, node, nodelist, function or array. + */ + public static GQuery $(JavaScriptObject jso) { + if (jso == null) { + return $(); + } + // 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 $((NodeList<Element>)elms); + } + + return JsUtils.isWindow(jso) ? $(jso.<Element> cast()) : + JsUtils.isElement(jso) ? $(jso.<Element> cast()) : + JsUtils.isEvent(jso) ? $(jso.<Event> cast()) : + JsUtils.isNodeList(jso) ? $(jso.<NodeList<Element>> cast()) : $(); + } + + /** + * 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 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 GQuery) { + return (GQuery)o; + } + if (o instanceof Function) { + return $((Function)o); + } + if (o instanceof JavaScriptObject) { + return $((JavaScriptObject)o); + } + if (o instanceof IsWidget) { + return $(Arrays.asList(o)); + } + System.err.println("GQuery.$(Object o) could not wrap the type : " + o.getClass()); + } + return $(); + } + + /** + * Create a new GQuery given a list of nodes, elements or widgets + */ + 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); + } + + /** + * Wrap a GQuery around an existing node. + */ + public static GQuery $(Node n) { + return $((Element) n); + } + + /** + * Wrap a GQuery around existing Elements. + */ + public static GQuery $(NodeList<Element> elms) { + 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 extends GQuery> T $(String selector, Class<T> 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 extends GQuery> T $(String selector, Node context, Class<T> 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 extends GQuery> T $(String selector, Widget context, Class<T> 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 JSON object. + */ + public static Properties $$(String properties) { + return Properties.create(properties); + } + + /** + * Perform an ajax request to the server. + */ + public static void ajax(Properties p) { + ajax(p); + } + + /** + * Perform an ajax request to the server. + */ + public static void ajax(Settings settings) { + Ajax.ajax(settings); + } + + /** + * Perform an ajax request to the server. + */ + public static void ajax(String url, Settings settings) { + Ajax.ajax(url, settings); + } + + @SuppressWarnings("unchecked") + protected static GQuery cleanHtmlString(String elem, Document doc) { + + String tag = tagNameRegex.exec(elem).get(1); + + if (tag == null) { + throw new RuntimeException("HTML snippet doesn't contain any tag"); + } + + 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 <script> tag + // TODO: add fixes for IE TBODY issue + + // We use a temporary element to wrap the elements + Element div = doc.createDivElement(); + div.setInnerHTML(wrapper.preWrap + elem.trim() + wrapper.postWrap); + Node n = div; + int depth = wrapper.wrapDepth; + while (depth-- != 0) { + n = n.getLastChild(); + } + + return + // return all nodes added to the wrapper + $(n.getChildNodes()) + // detach nodes from their temporary parent + .remove(null, false); + } + + /** + * Return true if the element b is contained in a. + */ + public static boolean contains(Element a, Element b) { + return engine.contains(a, b); + } + + /** + * Get the element data matching the key. + */ + public static Object data(Element e, String key) { + return GQuery.data(e, key, null); + } + + /** + * We store data in js object which has this structure: + * + * datacache [element_hash] [key] = value + * + * @return the value stored in the element with the given name + */ + protected static <S> Object data(Element element, String key, S value) { + if (dataCache == null) { + windowData = JavaScriptObject.createObject().cast(); + dataCache = JavaScriptObject.createObject().cast(); + } + element = element == window || element.getNodeName() == null ? windowData : element; + if (element != null && key != null) { + int id = element.hashCode(); + + if (value == null) { + return dataCache.exists(id) ? dataCache.getCache(id).get(key) : null; + } + + if (!dataCache.exists(id)) { + dataCache.put(id, JsCache.createObject().cast()); + } + dataCache.getCache(id).put(key, value); + } + return value; + } + + /** + * Execute a function around each object + */ + public static void each(JsArrayMixed objects, Function f) { + for (int i = 0, l = objects.length(); i < l; i++) { + f.f(i, objects.getObject(i)); + } + } + + /** + * Execute a function around each object + */ + public static <T> void each(List<T> objects, Function f) { + for (int i = 0, l = objects.size(); i < l; i++) { + f.f(i, objects.get(i)); + } + } + + /** + * Execute a function around each object + */ + public static <T> void each(T[] objects, Function f) { + for (int i = 0, l = objects.length; i < l; i++) { + f.f(i, objects[i]); + } + } + + /** + * Perform an ajax request to the server using GET. + */ + public static void get(String url, Properties data, final Function onSuccess) { + Ajax.get(url, data, onSuccess); + } + + /** + * We will use the fact as GWT use the widget itself as EventListener ! If no Widget associated + * with the element, this method returns null. + */ + protected static Widget getAssociatedWidget(Element e) { + try { + EventListener listener = DOM.getEventListener((com.google.gwt.user.client.Element) e); + // No listener attached to the element, so no widget exist for this element + if (listener == null) { + return null; + } + if (listener instanceof Widget) { + // GWT uses the widget as event listener + return (Widget) listener; + } else if (listener instanceof EventsListener) { + // GQuery replaces the gwt event listener and save it + EventsListener gQueryListener = (EventsListener) listener; + if (gQueryListener.getOriginalEventListener() != null + && gQueryListener.getOriginalEventListener() instanceof Widget) { + return (Widget) gQueryListener.getOriginalEventListener(); + } + } + } catch (Exception e2) { + // Some times this code could raise an exception. + // We do not want GQuery to fail, but in dev-mode we log the error. + e2.printStackTrace(); + } + return null; + } + + private static AttributeImpl getAttributeImpl() { + if (attributeImpl == null) { + attributeImpl = GWT.create(AttributeImpl.class); + } + return attributeImpl; + } + + /** + * Perform an ajax request to the server using POST and parsing the json response. + */ + public static void getJSON(String url, Properties data, final Function onSuccess) { + Ajax.getJSON(url, data, onSuccess); + } + + /** + * Perform an ajax request to the server using scripts tags and parsing the json response. The + * request is not subject to the same origin policy restrictions. + * + * Server side should accept a parameter to specify the callback funcion name, and it must return + * a valid json object wrapped this callback function. + * + * Example: + * + * <pre> + Client code: + getJSONP("http://server.exampe.com/getData.php",$$("myCallback:'?', otherParameter='whatever'"), + new Function(){ public void f() { + Properties p = getDataProperties(); + alert(p.getStr("k1"); + }}); + + Server response: + myCallback({"k1":"v1", "k2":"v2"}); + </pre> + * + */ + public static void getJSONP(String url, Properties data, final Function onSuccess) { + Ajax.getJSONP(url, data, onSuccess); + } + + protected static DocumentStyleImpl getStyleImpl() { + if (styleImpl == null) { + styleImpl = GWT.create(DocumentStyleImpl.class); + } + return styleImpl; + } + + /** + * Return only the set of objects with match the predicate. + */ + @SuppressWarnings("unchecked") + public static <T> T[] grep(T[] objects, Predicate f) { + ArrayList<Object> ret = new ArrayList<Object>(); + for (int i = 0, l = objects.length; i < l; i++) { + if (f.f(objects[i], i)) { + ret.add(objects[i]); + } + } + return (T[]) ret.toArray(new Object[0]); + } + + private static boolean hasClass(Element e, String clz) { + return e.getClassName().matches("(^|.*\\s)" + clz + "(\\s.*|$)"); + } + + private static void initWrapperMap() { + + TagWrapper tableWrapper = new TagWrapper(1, "<table>", "</table>"); + TagWrapper selectWrapper = new TagWrapper(1, "<select multiple=\"multiple\">", "</select>"); + TagWrapper trWrapper = new TagWrapper(3, "<table><tbody><tr>", "</tr></tbody></table>"); + + wrapperMap = JsNamedArray.create(); + wrapperMap.put("option", selectWrapper); + wrapperMap.put("optgroup", selectWrapper); + wrapperMap.put("legend", new TagWrapper(1, "<fieldset>", "</fieldset>")); + wrapperMap.put("thead", tableWrapper); + wrapperMap.put("tbody", tableWrapper); + wrapperMap.put("tfoot", tableWrapper); + wrapperMap.put("colgroup", tableWrapper); + wrapperMap.put("caption", tableWrapper); + wrapperMap.put("tr", new TagWrapper(2, "<table><tbody>", "</tbody></table>")); + wrapperMap.put("td", trWrapper); + wrapperMap.put("th", trWrapper); + wrapperMap.put("col", new TagWrapper(2, "<table><tbody></tbody><colgroup>", + "</colgroup></table>")); + wrapperMap.put("area", new TagWrapper(1, "<map>", "</map>")); + + } + + private static GQuery innerHtml(String html, Document doc) { + return cleanHtmlString(html, doc); + } + + protected static String[] jsArrayToString(JsArrayString array) { + if (GWT.isScript()) { + return jsArrayToString0(array); + } else { + String result[] = new String[array.length()]; + for (int i = 0, l = result.length; i < l; i++) { + result[i] = array.get(i); + } + return result; + } + } + + private static native String[] jsArrayToString0(JsArrayString array) /*-{ + return array; + }-*/; + + /** + * Return a lazy version of the GQuery interface. Lazy function calls are simply queued up and not + * executed immediately. + */ + public static LazyGQuery<?> lazy() { + return $().createLazy(); + } + + /** + * Perform an ajax request to the server using POST. + */ + public static void post(String url, Properties data, final Function onSuccess) { + Ajax.post(url, data, onSuccess); + } + + public static <T extends GQuery> Class<T> registerPlugin(Class<T> plugin, Plugin<T> pluginFactory) { + if (plugins == null) { + plugins = JsMap.createObject().cast(); + } + + plugins.put(plugin, pluginFactory); + return plugin; + } + + private static native void scrollIntoViewImpl(Node n) /*-{ + if (n) + n.scrollIntoView() + }-*/; + + private static native void setElementValue(Element e, String value) /*-{ + e.value = value; + }-*/; + + private static native Element window() /*-{ + return $wnd; + }-*/; + + protected Node currentContext; + + protected String currentSelector; + /** + * Immutable array of matched elements, modify this using setArray + */ + private Element[] elements = new Element[0]; + + /** + * The nodeList of matched elements, modify this using setArray + */ + // TODO: remove this and use elements, change return type of get() + private NodeList<Element> nodeList = JavaScriptObject.createArray().cast(); + + private GQuery previousObject; + + private GQuery() { + } + + private GQuery(Element element) { + this(JsNodeArray.create(element)); + } + + protected GQuery(GQuery gq) { + this(gq == null ? null : gq.get()); + currentSelector = gq.getSelector(); + currentContext = gq.getContext(); + } + + private GQuery(JsNodeArray nodes) { + this(nodes.<NodeList<Element>> cast()); + } + + private GQuery(NodeList<Element> list) { + setArray(list); + } + + /** + * Add elements to the set of matched elements if they are not included yet. + * + * It construct a new GQuery object and does not modify the original ones. + * + * It also update the selector appending the new one. + */ + public GQuery add(GQuery elementsToAdd) { + return pushStack(JsUtils.copyNodeList(nodeList, elementsToAdd.nodeList, true) + .<JsNodeArray> cast(), "add", getSelector() + "," + elementsToAdd.getSelector()); + } + + /** + * Add elements to the set of matched elements if they are not included yet. + */ + public GQuery add(String selector) { + return add($(selector)); + } + + /** + * Adds the specified classes to each matched element. + */ + public GQuery addClass(String... classes) { + for (Element e : elements) { + // issue 81 : ensure that the element is an Element node. + if (Element.is(e)) { + for (String clz : classes) { + e.addClassName(clz); + } + } + } + return this; + } + + /** + * Insert content after each of the matched elements. The elements must already be inserted into + * the document (you can't insert an element after another if it's not in the page). + */ + public GQuery after(GQuery query) { + return domManip(query, DomMan.AFTER); + } + + /** + * Insert content after each of the matched elements. The elements must already be inserted into + * the document (you can't insert an element after another if it's not in the page). + */ + public GQuery after(Node n) { + return domManip($(n), DomMan.AFTER); + } + + /** + * Insert content after each of the matched elements. The elements must already be inserted into + * the document (you can't insert an element after another if it's not in the page). + */ + public GQuery after(String html) { + return domManip(html, DomMan.AFTER); + } + + private void allNextSiblingElements(Element firstChildElement, JsNodeArray result, Element elem, + GQuery until, String filterSelector) { + + while (firstChildElement != null) { + + if (until != null && until.index(firstChildElement) != -1) { + return; + } + + if (firstChildElement != elem + && (filterSelector == null || $(firstChildElement).is(filterSelector))) { + result.addNode(firstChildElement); + } + firstChildElement = firstChildElement.getNextSiblingElement(); + } + } + + private void allPreviousSiblingElements(Element firstChildElement, JsNodeArray result, + GQuery until, String filterSelector) { + while (firstChildElement != null) { + if (until != null && until.index(firstChildElement) != -1) { + return; + } + + if (filterSelector == null || $(firstChildElement).is(filterSelector)) { + result.addNode(firstChildElement); + } + + firstChildElement = getPreviousSiblingElement(firstChildElement); + } + } + + /** + * Add the previous selection to the current selection. Useful for traversing elements, and then + * adding something that was matched before the last traversal. + */ + public GQuery andSelf() { + return add(previousObject); + } + + /** + * + * The animate() method allows you to create animation effects on any numeric Attribute, CSS + * property, or color CSS property. + * + * Concerning to numeric properties, values are treated as a number of pixels unless otherwise + * specified. The units em and % can be specified where applicable. + * + * By default animate considers css properties, if you wanted to animate element attributes you + * should to prepend the symbol dollar to the attribute name. + * + * Example: + * + * <pre class="code"> + * //move the element from its original position to left:500px for 500ms + * $("#foo").animate("left:'500'"); + * // Change the width attribute of a table + * $("table").animate("$width:'500'"), 400, Easing.LINEAR); + * </pre> + * + * In addition to numeric values, each property can take the strings 'show', 'hide', and 'toggle'. + * These shortcuts allow for custom hiding and showing animations that take into account the + * display type of the element. Animated properties can also be relative. If a value is supplied + * with a leading += or -= sequence of characters, then the target value is computed by adding or + * subtracting the given number from the current value of the property. + * + * Example: + * + * <pre class="code"> + * //move the element from its original position to 500px to the left for 500ms and + * // change the background color of the element at the end of the animation + * $("#foo").animate("left:'+=500'", new Function(){ + * + * public void f(Element e){ + * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED); + * } + * + * }); + * </pre> + * + * The duration of the animation is 500ms. + * + * For color css properties, values can be specified via hexadecimal or rgb or literal values. + * + * Example: + * + * <pre class="code"> + * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'"); + * </pre> + * + * @param prop the property to animate : "cssName:'value'" + * @param funcs an array of {@link Function} called once the animation is complete + */ + public GQuery animate(Object stringOrProperties, Function... funcs) { + return as(Effects).animate(stringOrProperties, funcs); + } + + /** + * The animate() method allows you to create animation effects on any numeric Attribute, CSS + * property, or color CSS property. + * + * Concerning to numeric properties, values are treated as a number of pixels unless otherwise + * specified. The units em and % can be specified where applicable. + * + * By default animate considers css properties, if you wanted to animate element attributes you + * should to prepend the symbol dollar to the attribute name. + * + * Example: + * + * <pre class="code"> + * //move the element from its original position to the position top:500px and left:500px for 400ms. + * //use a swing easing function for the transition + * $("#foo").animate(Properties.create("{top:'500px',left:'500px'}"), 400, Easing.SWING); + * // Change the width and border attributes of a table + * $("table").animate(Properties.create("{$width: '500', $border: '10'}"), 400, Easing.LINEAR); + * </pre> + * + * In addition to numeric values, each property can take the strings 'show', 'hide', and 'toggle'. + * These shortcuts allow for custom hiding and showing animations that take into account the + * display type of the element. Animated properties can also be relative. If a value is supplied + * with a leading += or -= sequence of characters, then the target value is computed by adding or + * subtracting the given number from the current value of the property. + * + * Example: + * + * <pre class="code"> + * //move the element from its original position to 500px to the left and 5OOpx down for 400ms. + * //use a swing easing function for the transition + * $("#foo").animate(Properties.create("{top:'+=500px',left:'+=500px'}"), 400, Easing.SWING); + * </pre> + * + * For color css properties, values can be specified via hexadecimal or rgb or literal values. + * + * Example: + * + * <pre class="code"> + * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'"), 400, Easing.SWING); + * </pre> + * + * @param stringOrProperties a String or a {@link Properties} object containing css properties to + * animate. + * @param funcs an array of {@link Function} called once the animation is complete + * @param duration the duration in milliseconds of the animation + * @param easing the easing function to use for the transition + */ + public GQuery animate(Object stringOrProperties, int duration, Easing easing, Function... funcs) { + return as(Effects).animate(stringOrProperties, duration, easing, funcs); + } + + /** + * The animate() method allows you to create animation effects on any numeric Attribute, CSS + * properties, or color CSS property. + * + * Concerning to numeric property, values are treated as a number of pixels unless otherwise + * specified. The units em and % can be specified where applicable. + * + * By default animate considers css properties, if you wanted to animate element attributes you + * should to prepend the symbol dollar to the attribute name. + * + * Example: + * + * <pre class="code"> + * //move the element from its original position to left:500px for 2s + * $("#foo").animate("left:'500px'", 2000); + * // Change the width attribute of a table + * $("table").animate("$width:'500'"), 400); + * </pre> + * + * In addition to numeric values, each property can take the strings 'show', 'hide', and 'toggle'. + * These shortcuts allow for custom hiding and showing animations that take into account the + * display type of the element. Animated properties can also be relative. If a value is supplied + * with a leading += or -= sequence of characters, then the target value is computed by adding or + * subtracting the given number from the current value of the property. + * + * Example: + * + * <pre class="code"> + * //move the element from its original position to 500px to the left for 1000ms and + * // change the background color of the element at the end of the animation + * $("#foo").animate("left:'+=500'", 1000, new Function(){ + * public void f(Element e){ + * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED); + * } + * }); + * </pre> + * + * + * For color css properties, values can be specified via hexadecimal or rgb or literal values. + * + * Example: + * + * <pre class="code"> + * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)', 1000"); + * </pre> + * + * + * @param prop the property to animate : "cssName:'value'" + * @param funcs an array of {@link Function} called once the animation is complete + * @param duration the duration in milliseconds of the animation + */ + public GQuery animate(Object stringOrProperties, int duration, Function... funcs) { + return as(Effects).animate(stringOrProperties, duration, funcs); + } + + /** + * Append content to the inside of every matched element. This operation is similar to doing an + * appendChild to all the specified elements, adding them into the document. + */ + public GQuery append(GQuery query) { + return domManip(query, DomMan.APPEND); + } + + /** + * Append content to the inside of every matched element. This operation is similar to doing an + * appendChild to all the specified elements, adding them into the document. + */ + public GQuery append(Node n) { + return domManip($(n), DomMan.APPEND); + } + + /** + * Append content to the inside of every matched element. This operation is similar to doing an + * appendChild to all the specified elements, adding them into the document. + */ + public GQuery append(String html) { + return domManip(html, DomMan.APPEND); + } + + /** + * All of the matched set of elements will be inserted at the end of the element(s) specified by + * the parameter other. + * + * The operation $(A).appendTo(B) is, essentially, the reverse of doing a regular $(A).append(B), + * instead of appending B to A, you're appending A to B. + */ + public GQuery appendTo(GQuery other) { + other.append(this); + return this; + } + + /** + * All of the matched set of elements will be inserted at the end of the element(s) specified by + * the parameter other. + * + * The operation $(A).appendTo(B) is, essentially, the reverse of doing a regular $(A).append(B), + * instead of appending B to A, you're appending A to B. + */ + public GQuery appendTo(Node n) { + GQuery a = $(n); + GQuery b = this; + a.append(b); + return this; + } + + /** + * All of the matched set of elements will be inserted at the end of the element(s) specified by + * the parameter other. + * + * The operation $(A).appendTo(B) is, essentially, the reverse of doing a regular $(A).append(B), + * instead of appending B to A, you're appending A to B. + */ + public GQuery appendTo(String html) { + $(html).append(this); + return this; + } + + /** + * Convert to Plugin interface provided by Class literal. + */ + @SuppressWarnings("unchecked") + public <T extends GQuery> T as(Class<T> plugin) { + // GQuery is not a plugin for itself + if (plugin == GQUERY) { + return (T)this; + } else if (plugins != null) { + Plugin<?> p = plugins.get(plugin); + if (p != null) { + return (T)p.init(this); + } + } + throw new RuntimeException("No plugin registered for class " + plugin.getName()); + } + + /** + * Set a key/value object as properties to all matched elements. + * + * Example: $("img").attr(new Properties("src: 'test.jpg', alt: 'Test Image'")) + */ + public GQuery attr(Properties properties) { + for (String name : properties.keys()) { + attr(name, properties.getStr(name)); + } + return this; + } + + /** + * Access a property on the first matched element. This method makes it easy to retrieve a + * property value from the first matched element. If the element does not have an attribute with + * such a name, empty string is returned. Attributes include title, alt, src, href, width, style, + * etc. + */ + public String attr(String name) { + return isEmpty() ? "" : get(0).getAttribute(name); + } + + /** + * Set a single property to a computed value, on all matched elements. + */ + public GQuery attr(String key, Function closure) { + int i = 0; + for (Element e : elements) { + Object val = closure.f(e.<com.google.gwt.dom.client.Element> cast(), i++); + $(e).attr(key, val); + } + return this; + } + + /** + * Set a single property to a value, on all matched elements. + */ + public GQuery attr(String key, Object value) { + assert key != null : "key cannot be null"; + assert !"$H".equalsIgnoreCase(key) : "$H is a GWT reserved attribute. Changing its value will break your application."; + + getAttributeImpl().setAttribute(this, key, value); + + return this; + } + + /** + * Insert content before each of the matched elements. The elements must already be inserted into + * the document (you can't insert an element before another if it's not in the page). + */ + public GQuery before(GQuery query) { + return domManip(query, DomMan.BEFORE); + } + + /** + * Insert content before each of the matched elements. The elements must already be inserted into + * the document (you can't insert an element before another if it's not in the page). + */ + public GQuery before(Node n) { + return domManip($(n), DomMan.BEFORE); + } + + /** + * Insert content before each of the matched elements. The elements must already be inserted into + * the document (you can't insert an element before another if it's not in the page). + */ + public GQuery before(String html) { + return domManip(html, DomMan.BEFORE); + } + + /** + * Binds a set of handlers to a particular Event for each matched element. + * + * The event handlers are passed as Functions that you can use to prevent default behavior. To + * stop both default action and event bubbling, the function event handler has to return false. + * + * You can pass an additional Object data to your Function as the second parameter + * + */ + public GQuery bind(int eventbits, final Object data, final Function... funcs) { + return as(Events).bind(eventbits, data, funcs); + } + + /** + * Binds a set of handlers to a particular Event for each matched element. + * + * The event handlers are passed as Functions that you can use to prevent default behavior. To + * stop both default action and event bubbling, the function event handler has to return false. + * + * + */ + public GQuery bind(int eventbits, final Function... funcs) { + return as(Events).bind(eventbits, null, funcs); + } + + /** + * Binds a set of handlers to a particular Event for each matched element. + * + * The event handlers are passed as Functions that you can use to prevent default behavior. To + * stop both default action and event bubbling, the function event handler has to return false. + * + * You can pass an additional Object data to your Function as the second parameter + * + */ + public GQuery bind(String eventType, final Object data, final Function... funcs) { + return as(Events).bind(eventType, data, funcs); + } + + /** + * Binds a set of handlers to a particular Event for each matched element. + * + * The event handlers are passed as Functions that you can use to prevent default behavior. To + * stop both default action and event bubbling, the function event handler has to return false. + * + * + */ + public GQuery bind(String eventType, final Function... funcs) { + return as(Events).bind(eventType, null, funcs); + } + + /** + * Bind Handlers or fire Events for each matched element. + */ + private GQuery bindOrFire(int eventbits, final Object data, final Function... funcs) { + if (funcs.length == 0) { + return trigger(eventbits); + } else { + return bind(eventbits, data, funcs); + } + } + + /** + * Bind a set of functions to the blur event of each matched element. Or trigger the blur event if + * no functions are provided. + */ + public GQuery blur(Function... f) { + bindOrFire(Event.ONBLUR, null, f); + if (!isEmpty() && f.length == 0) { + get(0).blur(); + } + return this; + } + + /** + * Bind a set of functions to the change event of each matched element. Or trigger the event if no + * functions are provided. + */ + public GQuery change(Function... f) { + return bindOrFire(Event.ONCHANGE, null, f); + } + + /** + * Get a set of elements containing all of the unique immediate children of each of the matched + * set of elements. Also note: while parents() will look at all ancestors, children() will only + * consider immediate child elements. + */ + public GQuery children() { + JsNodeArray result = JsNodeArray.create(); + for (Element e : elements) { + allNextSiblingElements(e.getFirstChildElement(), result, null, null, null); + } + return new GQuery(unique(result)); + } + + /** + * Get a set of elements containing all of the unique children of each of the matched set of + * elements. This set is filtered with the expressions that will cause only elements matching any + * of the selectors to be collected. + */ + public GQuery children(String... filters) { + return children().filter(filters); + } + + private void cleanGQData(Element... elements) { + for (Element el : elements) { + try { + EventsListener.clean(el); + removeData(el, null); + } catch (Exception e) { + // If for some reason event/data removal fails, do not break the app, + // just log the error in dev-mode + // e.g.: this happens when removing iframes which are no fully loaded. + e.printStackTrace(); + } + } + } + + /** + * Remove from the Effects queue all {@link Function} that have not yet been run. + */ + public GQuery clearQueue() { + return as(Queue).clearQueue(); + } + + /** + * Remove from the queue all {@link Function} that have not yet been run. + */ + public GQuery clearQueue(String queueName) { + return as(Queue).clearQueue(queueName); + } + + /** + * Bind a set of functions to the click event of each matched element. Or trigger the event if no + * functions are provided. + */ + public GQuery click(Function... f) { + return bindOrFire(Event.ONCLICK, null, f); + } + + /** + * Clone matched DOM Elements and select the clones. This is useful for moving copies of the + * elements to another location in the DOM. + */ + public GQuery clone() { + JsNodeArray result = JsNodeArray.create(); + for (Element e : elements) { + result.addNode(e.cloneNode(true)); + } + GQuery ret = new GQuery(result); + ret.currentContext = currentContext; + ret.currentSelector = currentSelector; + return ret; + } + + /** + * Get the first ancestor element that matches the selector (for each matched element), beginning + * at the current element and progressing up through the DOM tree. + * + * @param selector + * @return + */ + public GQuery closest(String selector) { + return closest(selector, null); + } + + /** + * Get the first ancestor element that matches the selector (for each matched element), beginning + * at the current element and progressing up through the DOM tree until reach the + * <code>context</code> node. + * + * If no context is passed in then the context of the gQuery object will be used instead. + * + */ + public GQuery closest(String selector, Node context) { + assert selector != null; + + if (context == null) { + context = currentContext; + } + + GQuery pos = selector.matches(POS_REGEX) ? $(selector, context) : null; + JsNodeArray result = JsNodeArray.create(); + + for (Element e : elements) { + Element current = e; + while (current != null && current.getOwnerDocument() != null && current != context) { + boolean match = pos != null ? pos.index(current) > -1 : $(current).is(selector); + if (match) { + result.addNode(current); + break; + } else { + current = current.getParentElement(); + } + } + } + + return $(unique(result)); + + } + + /** + * Returns a {@link Map} object as key a selector and as value the list of ancestor elements + * matching this selectors, beginning at the first matched element and progressing up through the + * DOM. This method allows retrieving the list of ancestors matching many selectors by traversing + * the DOM only one time. + * + * @param selector + * @return + */ + public JsNamedArray<NodeList<Element>> closest(String[] selectors) { + return closest(selectors, null); + } + + /** + * Returns a {@link Map} object as key a selector and as value the list of ancestor elements + * matching this selectors, beginning at the first matched element and progressing up through the + * DOM until reach the <code>context</code> node.. This method allows retrieving the list of + * ancestors matching many selectors by traversing the DOM only one time. + * + * @param selector + * @return + */ + public JsNamedArray<NodeList<Element>> closest(String[] selectors, Node context) { + JsNamedArray<NodeList<Element>> results = JsNamedArray.create(); + + if (context == null) { + context = currentContext; + } + + Element first = get(0); + if (first != null && selectors != null && selectors.length > 0) { + JsNamedArray<GQuery> matches = JsNamedArray.create(); + for (String selector : selectors) { + if (!matches.exists(selector)) { + matches.put(selector, selector.matches(POS_REGEX) ? $(selector, context) : null); + } + } + + Element current = first; + while (current != null && current.getOwnerDocument() != null && current != context) { + // for each selector, check if the current element match it. + for (String selector : matches.keys()) { + + GQuery pos = matches.get(selector); + boolean match = pos != null ? pos.index(current) > -1 : $(current).is(selector); + + if (match) { + JsNodeArray elementsMatchingSelector = results.get(selector).cast(); + if (elementsMatchingSelector == null) { + elementsMatchingSelector = JsNodeArray.create(); + results.put(selector, elementsMatchingSelector); + } + elementsMatchingSelector.addNode(current); + } + } + + current = current.getParentElement(); + } + } + return results; + } + + /** + * Filter the set of elements to those that contain the specified text. + */ + public GQuery contains(String text) { + JsNodeArray array = JsNodeArray.create(); + for (Element e : elements) { + if ($(e).text().contains(text)) { + array.addNode(e); + } + } + return $(array); + } + + /** + * Find all the child nodes inside the matched elements (including text nodes), or the content + * document, if the element is an iframe. + */ + public GQuery contents() { + JsNodeArray result = JsNodeArray.create(); + for (Element e : elements) { + if (JsUtils.isWindow(e) || "iframe".equalsIgnoreCase(e.getTagName())) { + result.addNode(getStyleImpl().getContentDocument(e)); + } else { + NodeList<Node> children = e.getChildNodes(); + for (int i = 0, l = children.getLength(); i < l; i++) { + result.addNode(children.getItem(i)); + } + } + } + return new GQuery(unique(result)); + } + + public LazyGQuery<?> createLazy() { + return GWT.create(GQuery.class); + } + + /** + * Set CSS a single style property on every matched element using type-safe enumerations. + * + * The best way to use this method (i.e. to generate a CssSetter) is to take the desired css + * property defined in {@link CSS} class and call the {@link TakesCssValue#with(HasCssName)} + * method on it. + * + * + * ex : + * + * <pre class="code"> + * $("#myDiv").css(CSS.TOP.with(Length.cm(15))); + * $("#myDiv").css(CSS.BACKGROUND.with(RGBColor.SILVER, ImageValue.url(""), + * BackgroundRepeat.NO_REPEAT, BackgroundAttachment.FIXED, + * BackgroundPosition.CENTER)); + * $("#myDiv").css(CSS.BACKGROUND_ATTACHMENT.with(BackgroundAttachment.FIXED)); + * + * </pre> + * + */ + public GQuery css(CssSetter... cssSetter) { + for (Element e : elements) { + for (CssSetter s : cssSetter) { + s.applyCss(e); + } + } + return this; + } + + /** + * Return a style property on the first matched element using type-safe enumerations. + * + * Ex : $("#myId").css(CSS.BACKGROUND_COLOR); + */ + public String css(HasCssValue property) { + return css(property, true); + } + + /** + * Return a style property on the first matched element using type-safe enumerations. + * + * The parameter force has a special meaning here: - When force is false, returns the value of the + * css property defined in the style attribute of the element. - Otherwise it returns the real + * computed value. + * + * For instance if you define 'display=none' not in the element style but in the css stylesheet, + * it returns an empty string unless you pass the parameter force=true. + * + * Ex : $("#myId").css(CSS.WIDTH, true); + */ + public String css(HasCssValue property, boolean force) { + return css(property.getCssName(), force); + } + + /** + * Set a key/value object as style properties to all matched elements. This serves as the best way + * to set a large number of style properties on all matched elements. You can use either js maps + * or pure css syntax. + * + * Example: + * + * <pre class="code"> + * $(".item").css(Properties.create("color: 'red', background:'blue'")) + * $(".item").css(Properties.create("color: red; background: blue;")) + * </pre> + */ + public GQuery css(Properties properties) { + for (String property : properties.keys()) { + css(property, properties.getStr(property)); + } + return this; + } + + /** + * Return a style property on the first matched element. + */ + public String css(String name) { + return css(name, true); + } + + /** + * Return a style property on the first matched element. + * + * The parameter force has a special meaning here: + * <ul> + * <li>When force is false, returns the value of the css property defined in the style attribute + * of the element. + * <li>Otherwise it returns the real computed value. + * </ul> + * + * For instance if you don't define 'display=none'in the element style but in the css stylesheet, + * it returns an empty string unless you pass the parameter force=true. + */ + public String css(String name, boolean force) { + return isEmpty() ? "" : getStyleImpl().curCSS(get(0), name, force); + } + + /** + * Set a single style property to a value, on all matched elements. + * + */ + public GQuery css(String prop, String val) { + for (Element e : elements) { + getStyleImpl().setStyleProperty(e, prop, val); + } + return this; + } + + /** + * Set CSS a single style property on every matched element using type-safe enumerations. This + * method allows you to set manually the value or set <i>inherit</i> value + * + * ex : + * + * <pre class="code"> + * $(#myId).css(CSS.TEXT_DECORATION, CSS.INHERIT); + * </pre> + */ + public GQuery css(TakesCssValue<?> cssProperty, String value) { + return css(cssProperty.getCssName(), value); + } + + /** + * Returns the numeric value of a css property. + */ + public double cur(String prop) { + return cur(prop, false); + } + + /** + * Returns the numeric value of a css property. + * + * The parameter force has a special meaning: - When force is false, returns the value of the css + * property defined in the set of style attributes. - When true returns the real computed value. + */ + public double cur(String prop, boolean force) { + return isEmpty() ? 0 : getStyleImpl().cur(get(0), prop, force); + } + + /** + * Returns value at named data store for the element, as set by data(name, value). + */ + public Object data(String name) { + return isEmpty() ? null : data(get(0), name, null); + } + + /** + * Returns value at named data store for the element, as set by data(name, value) with desired + * return type. + * + * @param clz return type class literal + */ + @SuppressWarnings("unchecked") + public <T> T data(String name, Class<T> clz) { + return isEmpty() ? null : (T) data(get(0), name, null); + } + + /** + * Stores the value in the named spot with desired return type. + */ + public GQuery data(String name, Object value) { + for (Element e : elements()) { + data(e, name, value); + } + return this; + } + + /** + * Bind a set of functions to the dblclick event of each matched element. Or trigger the event if + * no functions are provided. + */ + public GQuery dblclick(Function... f) { + return bindOrFire(Event.ONDBLCLICK, null, f); + } + + /** + * Insert a delay (in ms) in the GQuery queue, and optionally execute one o more functions if + * provided when the delay finishes. It uses the effects queue namespace, so you can stack any of + * the methods in the effects plugin. + * + * Example: + * + * <pre class="code"> + * $("#foo").slideUp(300) + * .delay(800) + * .fadeIn(400); + * </pre> + * + * When this statement is executed, the element slides up for 300 milliseconds and then pauses for + * 800 milliseconds before fading in for 400 milliseconds. Aditionally after those 800 + * milliseconds the element color is set to red. + * + * NOTE that this methods affects only methods which uses the queue like effects. So the following + * example is wrong: + * + * <pre> + * $("#foo").css(CSS.COLOR.with(RGBColor.RED)).delay(800).css(CSS.COLOR.with(RGBColor.BLACK)); + * </pre> + * + * The code above will not insert a delay of 800 ms between the css() calls ! For this kind of + * behavior, you should execute these methods puting them in inline functions passed as argument + * to the delay() method, or adding them to the queue. + * + * <pre> + * $("#foo").css(CSS.COLOR.with(RGBColor.RED)).delay(800, lazy().css(CSS.COLOR.with(RGBColor.BLACK)).done()); + * $("#foo").css(CSS.COLOR.with(RGBColor.RED)).delay(800).queue(lazy().css(CSS.COLOR.with(RGBColor.BLACK)).dequeue().done()); + * </pre> + */ + public GQuery delay(int milliseconds, Function... f) { + return as(Queue).delay(milliseconds, f); + } + + /** + * Insert a delay (in ms) in the queue identified by the <code>queueName</code> parameter, and + * optionally execute one o more functions if provided when the delay finishes. + * + * If <code>queueName</code> is null or equats to 'fx', the delay will be inserted to the Effects + * queue. + * + * Example : + * + * <pre class="code"> + * $("#foo").queue("colorQueue", lazy().css(CSS.COLOR.with(RGBColor.RED)).dequeue("colorQueue").done()) + * .delay(800, "colorQueue") + * .queue("colorQueue", lazy().css(CSS.COLOR.with(RGBColor.BLACK)).dequeue("colorQueue").done()); + * </pre> + * + * When this statement is executed, the text color of the element changes to red and then wait for + * 800 milliseconds before changes the text color to black. + * + */ + public GQuery delay(int milliseconds, String queueName, Function... f) { + return as(Queue).delay(milliseconds, queueName, f); + } + + /** + * Attach <code>handlers</code> to one or more events for all elements that match the + * <code>selector</code>, now or in the future, based on a specific set of root elements. + * + * Example: + * + * <pre> + * $("table").delegate("td", Event.ONCLICK, new Function(){ + * public void f(Element e){ + * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED)); + * } + * }); + * </pre> + * + * This code above add an handler on click event on all cell (the existing oneand the future cell) + * of all table. This code is equivalent to : + * + * <pre> + * $("table").each(new Function(){ + * public void f(Element table){ + * $("td", table).live(Event.ONCLICK, new Function(){ + * public void f(Element e){ + * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED)); + * } + * } + * }); + * + * </pre> + * + * You can attach the handlers to many events by using the '|' operator ex: + * + * <pre> + * $("div.main").delegate(".subMain", Event.ONCLICK | Event.ONDBLCLICK, new Function(){...}); + * </pre> + */ + public GQuery delegate(String selector, int eventbits, Function... handlers) { + return delegate(selector, eventbits, null, handlers); + } + + /** + * Attach <code>handlers</code> to one or more events for all elements that match the + * <code>selector</code>, now or in the future, based on a specific set of root elements. The + * <code>data</code> parameter allows us to pass data to the handler. + * + * Example: + * + * <pre> + * $("table").delegate("td", "click", new Function(){ + * public void f(Element e){ + * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED)); + * } + * }); + * </pre> + * + * This code above add an handler on click event on all cell (the existing oneand the future cell) + * of all table. This code is equivalent to : + * + * <pre> + * $("table").each(new Function(){ + * public void f(Element table){ + * $("td", table).live("click", new Function(){ + * public void f(Element e){ + * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED)); + * } + * } + * }); + * + * </pre> + * + * You can pass attach the handlers to many events by using the '|' operator ex: + * + * <pre> + * $("div.main").delegate(".subMain", Event.ONCLICK | Event.ONDBLCLICK, new Function(){...}); + * </pre> + */ + public GQuery delegate(String selector, int eventbits, Object data, Function... handlers) { + + for (Element e : elements) { + $(selector, e).live(eventbits, data, handlers); + } + + return this; + } + + /** + * Attach <code>handlers</code> to one or more events for all elements that match the + * <code>selector</code>, now or in the future, based on a specific set of root elements. + * + * Example: + * + * <pre> + * $("table").delegate("td", "click", new Function(){ + * public void f(Element e){ + * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED)); + * } + * }); + * </pre> + * + * This code above add an handler on click event on all cell (the existing oneand the future cell) + * of all table. This code is equivalent to : + * + * <pre> + * $("table").each(new Function(){ + * public void f(Element table){ + * $("td", table).live("click", new Function(){ + * public void f(Element e){ + * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED)); + * } + * } + * }); + * + * </pre> + * + * You can pass attach the handlers to many events by specifying a String with espaced event type. + * ex: + * + * <pre> + * $("div.main").delegate(".subMain", "click dblclick", new Function(){...}); + * </pre> + * + * </pre> + */ + public GQuery delegate(String selector, String eventType, Function... handlers) { + return delegate(selector, eventType, null, handlers); + } + + /** + * Attach <code>handlers</code> to one or more events for all elements that match the + * <code>selector</code>, now or in the future, based on a specific set of root elements. + * + * Example: + * + * <pre> + * $("table").delegate("td", "click", new Function(){ + * public void f(Element e){ + * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED)); + * } + * }); + * </pre> + * + * This code above add an handler on click event on all cell (the existing oneand the future cell) + * of all table. This code is equivalent to : + * + * <pre> + * $("table").each(new Function(){ + * public void f(Element table){ + * $("td", table).live("click", new Function(){ + * public void f(Element e){ + * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED)); + * } + * } + * }); + * + * You can pass attach the handlers to many events by specifying a String with espaced event type. + * ex: + * + * <pre> + * $("div.main").delegate(".subMain", "click dblclick", new Function(){...}); + * </pre> + * + * </pre> + */ + public GQuery delegate(String selector, String eventType, Object data, Function... handlers) { + for (Element e : elements) { + $(selector, e).live(eventType, data, handlers); + } + + return this; + } + + /** + * Execute the next function on the Effects queue for the matched elements. This method is usefull + * to tell when a function you add in the Effects queue is ended and so the next function in the + * queue can start. + * + * Note: you should be sure to call dequeue() in all functions of a queue chain, otherwise the + * queue execution will be stopped. + */ + public GQuery dequeue() { + return as(Queue).dequeue(); + } + + /** + * Execute the next function on the queue named as queueName for the matched elements. This method + * is usefull to tell when a function you add in the Effects queue is ended and so the next + * function in the queue can start. + */ + public GQuery dequeue(String queueName) { + return as(Queue).dequeue(queueName); + } + + /** + * Detach all matched elements from the DOM. This method is the same than {@link #remove()} method + * except all data and event handlers are not remove from the element. This method is useful when + * removed elements are to be reinserted into the DOM at a later time. + */ + public GQuery detach() { + return remove(null, false); + } + + /** + * Detach from the DOM all matched elements filtered by the <code>filter</code>.. This method is + * the same than {@link #remove(String)} method except all data and event handlers are not remove + * from the element. This method is useful when removed elements are to be reinserted into the DOM + * at a later time. + */ + public GQuery detach(String filter) { + return remove(filter, false); + } + + /** + * Remove all event handlers previously attached using {@link #live(String, Function)}. In order + * for this method to function correctly, the selector used with it must match exactly the + * selector initially used with {@link #live(String, Function)} + */ + public GQuery die() { + return die(0); + } + + /** + * Remove an event handlers previously attached using {@link #live(int, Function)} In order for + * this method to function correctly, the selector used with it must match exactly the selector + * initially used with {@link #live(int, Function)} + */ + public GQuery die(int eventbits) { + return as(Events).die(eventbits); + } + + /** + * Remove an event handlers previously attached using {@link #live(String, Function)} In order for + * this method to function correctly, the selector used with it must match exactly the selector + * initially used with {@link #live(String, Function)} + */ + public GQuery die(String eventName) { + return as(Events).die(eventName); + } + + private GQuery domManip(GQuery g, DomMan type, Element... elms) { + JsNodeArray newNodes = JsNodeArray.create(); + if (elms.length == 0) { + elms = elements; + } + for (int i = 0, l = elms.length; i < l; i++) { + Element e = elms[i]; + if (e.getNodeType() == Node.DOCUMENT_NODE) { + e = e.<Document> cast().getBody(); + } + for (int j = 0, size = g.size(); j < size; j++) { + // Widget w = getAssociatedWidget(g.get(j)); + // GqUi.detachWidget(w); + + Node n = g.get(j); + // If an element selected is inserted elsewhere, it will be moved into the target (not + // cloned). + // If there is more than one target element, however, cloned copies of the inserted element + // will be created for each target after the first + if (i > 0) { + n = n.cloneNode(true); + } + switch (type) { + case PREPEND: + newNodes.addNode(e.insertBefore(n, e.getFirstChild())); + break; + case APPEND: + newNodes.addNode(e.appendChild(n)); + break; + case AFTER: + newNodes.addNode(e.getParentNode().insertBefore(n, e.getNextSibling())); + break; + case BEFORE: + newNodes.addNode(e.getParentNode().insertBefore(n, e)); + break; + } + EventsListener.rebind(n.<Element> cast()); + // GqUi.attachWidget(w); + } + } + // TODO: newNodes.size() > g.size() makes testRebind fail + if (newNodes.size() >= g.size()) { + g.setArray(newNodes); + } + return this; + } + + // TODO: this should be handled by the other domManip method + private GQuery domManip(String htmlString, DomMan type) { + JsMap<Document, GQuery> cache = JsMap.createObject().cast(); + for (Element e : elements) { + Document d = JsUtils.getOwnerDocument(e); + GQuery g = cache.get(d); + if (g == null) { + g = cleanHtmlString(htmlString, d); + cache.put(d, g); + } + domManip(g.clone(), type, e); + } + return this; + } + + /** + * Run one or more Functions over each element of the GQuery. You have to override one of these + * funcions: public void f(Element e) public String f(Element e, int i) + */ + public GQuery each(Function... f) { + if (f != null) { + for (Function f1 : f) { + int i = 0; + for (Element e : elements) { + f1.f(e.<com.google.gwt.dom.client.Element> cast(), i++); + } + } + } + return this; + } + + /** + * Returns the working set of nodes as a Java array. <b>Do NOT</b> attempt to modify this array, + * e.g. assign to its elements, or call Arrays.sort() + */ + public Element[] elements() { + return elements; + } + + /** + * Remove all child nodes from the set of matched elements. In the case of a document element, it + * removes all the content You should call this method whenever you create a new iframe and you + * want to add dynamic content to it. + */ + public GQuery empty() { + for (Element e : elements) { + if (e.getNodeType() == Element.DOCUMENT_NODE) { + getStyleImpl().emptyDocument(e.<Document> cast()); + } else { + Node c = e.getFirstChild(); + while (c != null) { + removeData(c.<Element> cast(), null); + WidgetsUtils.detachWidget(getAssociatedWidget(e)); + EventsListener.clean(c.<Element> cast()); + e.removeChild(c); + c = e.getFirstChild(); + } + } + } + return this; + } + + /** + * Revert the most recent 'destructive' operation, changing the set of matched elements to its + * previous state (right before the destructive operation). + */ + public GQuery end() { + return previousObject != null ? previousObject : new GQuery(); + } + + /** + * Reduce GQuery to element in the specified position. This method accept negative index. A + * negative index is counted from the end of the matched set: + * + * Example: + * + * <pre> + * $("div").eq(0) will reduce the matched set to the first matched div + * $("div").eq(1) will reduce the matched set to the second matched div + * + * $("div").eq(-1) will reduce the matched set to the last matched div + * $("div").eq(-2) will reduce the matched set to the second-to-last matched div + * ... + * </pre> + */ + public GQuery eq(int pos) { + return $(get(pos)); + } + + /** + * Bind a set of functions to the error event of each matched element. Or trigger the event if no + * functions are provided. + */ + public GQuery error(Function... f) { + return bindOrFire(Event.ONERROR, null, f); + } + + /** + * Fade in all matched elements by adjusting their opacity. The effect will take 1000 milliseconds + * to complete + */ + public GQuery fadeIn(Function... f) { + return as(Effects).fadeIn(f); + } + + /** + * Fade in all matched elements by adjusting their opacity. + */ + public GQuery fadeIn(int millisecs, Function... f) { + return as(Effects).fadeIn(millisecs, f); + } + + /** + * Fade out all matched elements by adjusting their opacity. The effect will take 1000 + * milliseconds to complete + */ + public GQuery fadeOut(Function... f) { + return as(Effects).fadeOut(f); + } + + /** + * Fade out all matched elements by adjusting their opacity. + */ + public GQuery fadeOut(int millisecs, Function... f) { + return as(Effects).fadeOut(millisecs, f); + } + + /** + * Toggle the visibility of all matched elements by adjusting their opacity and firing an optional + * callback after completion. Only the opacity is adjusted for this animation, meaning that all of + * the matched elements should already have some form of height and width associated with them. + */ + public Effects fadeToggle(int millisecs, Function... f) { + return as(Effects).fadeToggle(millisecs, f); + } + + /** + * Removes all elements from the set of matched elements that do not match the specified function. + * The function is called with a context equal to the current element. If the function returns + * false, then the element is removed - anything else and the element is kept. + */ + public GQuery filter(Predicate filterFn) { + JsNodeArray result = JsNodeArray.create(); + int i = 0; + for (Element e : elements) { + if (filterFn.f(e, i++)) { + result.addNode(e); + } + } + return pushStack(result, "filter", currentSelector); + } + + /** + * Removes all elements from the set of matched elements that do not pass the specified css + * expression. This method is used to narrow down the results of a search. + */ + // TODO performance bad... + public GQuery filter(String... filters) { + JsNodeArray array = JsNodeArray.create(); + /* + * StringBuilder filterBuilder = new StringBuilder(); for (int i = 0; i < filters.length ; i++){ + * filterBuilder.append(filters[i]); if (i < filters.length - 1){ filterBuilder.append(","); } } + * + * String filter = filterBuilder.toString(); + */ + + for (String f : filters) { + for (Element e : elements) { + boolean ghostParent = false; + + if (e.getParentNode() == null) { + DOM.createDiv().appendChild(e); + ghostParent = true; + } + + for (Element c : $(f, e.getParentNode()).elements) { + if (c == e) { + array.addNode(c); + break; + } + } + + if (ghostParent) { + e.removeFromParent(); + } + } + } + + return pushStack(unique(array), "filter", filters[0]); + } + + /** + * Searches for all elements that match the specified css expression. This method is a good way to + * find additional descendant elements with which to process. + * + * Provide a comma-separated list of expressions to apply multiple filters at once. + */ + public GQuery find(String... filters) { + JsNodeArray array = JsNodeArray.create(); + for (String selector : filters) { + for (Element e : elements) { + for (Element c : $(selector, e).elements) { + array.addNode(c); + } + } + } + return pushStack(unique(array), "find", filters[0]); + } + + /** + * Reduce the set of matched elements to the first in the set. + */ + public GQuery first() { + return eq(0); + } + + /** + * Bind a set of functions to the focus event of each matched element. Or trigger the event and + * move the input focus to the first element if no functions are provided. + */ + public GQuery focus(Function... f) { + bindOrFire(Event.ONFOCUS, null, f); + if (!isEmpty() && f.length == 0) { + get(0).focus(); + } + return this; + } + + /** + * Return all elements matched in the GQuery as a NodeList. @see #elements() for a method which + * returns them as an immutable Java array. + */ + public NodeList<Element> get() { + return nodeList; + } + + /** + * Return the ith element matched. This method accept negative index. A negative index is counted + * from the end of the matched set. + * + * Example: + * + * <pre> + * $("div").get(0) will return the first matched div + * $("div").get(1) will return the second matched div + * + * $("div").get(-1) will return the last matched div + * $("div").get(-2) will return the secont-to-last matched div + * ... + * </pre> + */ + public Element get(int i) { + int l = elements.length; + if (i >= 0 && i < l) { + return elements[i]; + } + if (i < 0 && l + i >= 0) { + return elements[l + i]; + } + return null; + } + + public Node getContext() { + return currentContext; + } + + /** + * Return the previous set of matched elements prior to the last destructive operation (e.g. + * query) + */ + public GQuery getPreviousObject() { + return previousObject; + } + + private native Element getPreviousSiblingElement(Element elem) /*-{ + var sib = elem.previousSibling; + while (sib && sib.nodeType != 1) + sib = sib.previousSibling; + return sib; + }-*/; + + /** + * Return the selector representing the current set of matched elements. + */ + public String getSelector() { + return currentSelector; + } + + /** + * Returns true any of the specified classes are present on any of the matched Reduce the set of + * matched elements to all elements after a given position. The position of the element in the set + * of matched elements starts at 0 and goes to length - 1. + */ + public GQuery gt(int pos) { + return slice(pos + 1, -1); + } + + /** + * Reduce the set of matched elements to those that have a descendant that matches the Element. + */ + public GQuery has(final Element elem) { + return filter(new Predicate() { + public boolean f(Element e, int index) { + return engine.contains(e, elem); + } + }); + } + + /** + * Reduce the set of matched elements to those that have a descendant that matches the selector. + */ + public GQuery has(final String selector) { + return filter(new Predicate() { + public boolean f(Element e, int index) { + return !$(selector, e).isEmpty(); + } + }); + } + + /** + * Returns true any of the specified classes are present on any of the matched elements. + */ + public boolean hasClass(String... classes) { + for (Element e : elements) { + for (String clz : classes) { + if (hasClass(e, clz)) { + return true; + } + } + } + return false; + } + + /** + * Get the current computed, pixel, height of the first matched element. It does not include + * margin, padding nor border. + */ + public int height() { + return (int) cur("height", true); + } + + /** + * Set the height of every element in the matched set. + */ + public GQuery height(int height) { + for (Element e : elements) { + e.getStyle().setPropertyPx("height", height); + } + return this; + } + + /** + * Set the height style property of every matched element. It's useful for using 'percent' or 'em' + * units Example: $(".a").width("100%") + */ + public GQuery height(String height) { + return css("height", height); + } + + /** + * Make invisible all matched elements. + */ + public GQuery hide() { + for (Element e : elements) { + String currentDisplay = getStyleImpl().curCSS(e, "display", false); + Object old = data(e, OLD_DISPLAY, null); + if (old == null && currentDisplay.length() != 0 && !"none".equals(currentDisplay)) { + data(e, OLD_DISPLAY, currentDisplay); + } + } + + // Set the display value in a separate for loop to avoid constant reflow + // Reflows is very bad in performance point of view + for (Element e : elements) { + e.getStyle().setDisplay(Display.NONE); + } + + return this; + } + + /** + * Bind a function to the mouseover event of each matched element. A method for simulating + * hovering (moving the mouse on, and off, an object). This is a custom method which provides an + * 'in' to a frequent task. Whenever the mouse cursor is moved over a matched element, the first + * specified function is fired. Whenever the mouse moves off of the element, the second specified + * function fires. + */ + public GQuery hover(Function fover, Function fout) { + return bind(Event.ONMOUSEOVER, null, fover).bind(Event.ONMOUSEOUT, null, fout); + } + + /** + * Get the innerHTML of the first matched element. + */ + public String html() { + return isEmpty() ? "" : get(0).getInnerHTML(); + } + + /** + * Set the innerHTML of every matched element. + */ + public GQuery html(String html) { + for (Element e : elements) { + if (e.getNodeType() == Node.DOCUMENT_NODE) { + e = e.<Document> cast().getBody(); + } + e.setInnerHTML(html); + } + return this; + } + + /** + * Get the id of the first matched element. + */ + public String id() { + return attr("id"); + } + + /** + * Set the id of the first matched element. + */ + public GQuery id(String id) { + return eq(0).attr("id", id); + } + + /** + * Find the index of the specified Element. + */ + public int index(Element element) { + int i = 0; + for (Element e : elements) { + if (e == element) { + return i; + } + i++; + } + return -1; + } + + /** + * Returns the inner height of the first matched element, including padding but not the vertical + * scrollbar height, border, or margin. + */ + public int innerHeight() { + return (int) cur("clientHeight", true); + } + + /** + * Returns the inner width of the first matched element, including padding but not the vertical + * scrollbar width, border, or margin. + */ + public int innerWidth() { + return (int) cur("clientWidth", true); + } + + /** + * Insert all of the matched elements after another, specified, set of elements. + */ + public GQuery insertAfter(Element elem) { + return insertAfter($(elem)); + } + + /** + * Insert all of the matched elements after another, specified, set of elements. + */ + public GQuery insertAfter(GQuery query) { + for (Element e : elements) { + query.after(e); + } + return this; + } + + /** + * Insert all of the matched elements after another, specified, set of elements. + */ + public GQuery insertAfter(String selector) { + return insertAfter($(selector)); + } + + /** + * Insert all of the matched elements before another, specified, set of elements. + * + * The elements must already be inserted into the document (you can't insert an element after + * another if it's not in the page). + */ + public GQuery insertBefore(Element item) { + return insertBefore($(item)); + } + + /** + * Insert all of the matched elements before another, specified, set of elements. + * + * The elements must already be inserted into the document (you can't insert an element after + * another if it's not in the page). + */ + public GQuery insertBefore(GQuery query) { + for (Element e : elements) { + query.before(e); + } + return this; + } + + /** + * Insert all of the matched elements before another, specified, set of elements. + * + * The elements must already be inserted into the document (you can't insert an element after + * another if it's not in the page). + */ + public GQuery insertBefore(String selector) { + return insertBefore($(selector)); + } + + /** + * Checks the current selection against an expression and returns true, if at least one element of + * the selection fits the given expression. Does return false, if no element fits or the + * expression is not valid. + */ + public boolean is(String... filters) { + return !filter(filters).isEmpty(); + } + + /** + * Returns true if the number of matched elements is 0. + */ + public boolean isEmpty() { + return size() == 0; + } + + /** + * Return true if the first element is visible.isVisible + */ + public boolean isVisible() { + return isEmpty() ? false : getStyleImpl().isVisible(get(0)); + } + + /** + * Bind a set of functions to the keydown event of each matched element. Or trigger the event if + * no functions are provided. + */ + public GQuery keydown(Function... f) { + return bindOrFire(Event.ONKEYDOWN, null, f); + } + + /** + * Trigger a keydown event passing the key pushed. + */ + public GQuery keydown(int key) { + return trigger(Event.ONKEYDOWN, key); + } + + /** + * Bind a set of functions to the keypress event of each matched element. Or trigger the event if + * no functions are provided. + */ + public GQuery keypress(Function... f) { + return bindOrFire(Event.ONKEYPRESS, null, f); + } + + /** + * Trigger a keypress event passing the key pushed. + */ + public GQuery keypress(int key) { + return trigger(Event.ONKEYPRESS, key); + } + + /** + * Bind a set of functions to the keyup event of each matched element. Or trigger the event if no + * functions are provided. + */ + public GQuery keyup(Function... f) { + return bindOrFire(Event.ONKEYUP, null, f); + } + + /** + * Trigger a keyup event passing the key pushed. + */ + public GQuery keyup(int key) { + return trigger(Event.ONKEYUP, key); + } + + /** + * Reduce the set of matched elements to the final one in the set. + */ + public GQuery last() { + return eq(size() - 1); + } + + /** + * Returns the computed left position of the first element matched. + */ + public int left() { + return (int) cur("left", true); + } + + /** + * Returns the number of elements currently matched. The size function will return the same value. + */ + public int length() { + return size(); + } + + /** + * Attach a handler for this event to all elements which match the current selector, now and in + * the future. + */ + public GQuery live(int eventbits, Function... funcs) { + return as(Events).live(eventbits, null, funcs); + } + + /** + * Attach a handler for this event to all elements which match the current selector, now and in + * the future. + */ + public GQuery live(int eventbits, Object data, Function... funcs) { + return as(Events).live(eventbits, data, funcs); + } + + /** + * <p> + * Attach a handler for this event to all elements which match the current selector, now and in + * the future. + * <p> + * <p> + * Ex : + * + * <pre> + * $(".clickable").live("click", new Function(){ + * public void f(Element e){ + * $(e).css(CSS.COLOR.with(RGBColor.RED)); + * } + * }); + * </pre> + * + * With this code, all elements with class "clickable" present in the DOM or added to the DOM in + * the future will be clickable. The text color will be changed to red when they will be clicked. + * So if after in the code, you add another element : + * + * <pre> + * $("body").append("<div class='clickable'>Click me and I will be red</div>"); + * </pre> + * + * The click on this new element will also trigger the handler. + * </p> + * <p> + * In the same way, if you add "clickable" class on some existing element, these elements will be + * clickable also. + * </p> + * <p> + * <h3>important remarks</h3> + * <ul> + * <li> + * The live method should be always called after a selector</li> + * <li> + * Live events are bound to the context of the {@link GQuery} object : + * + * <pre> + * $(".clickable", myElement).live("click", new Function(){ + * public void f(Element e){ + * $(e).css(CSS.COLOR.with(RGBColor.RED)); + * } + * }); + * </pre> + * The {@link Function} will be called only on elements having the class "clickable" and being + * descendant of myElement.</li> + * </ul> + * </p> + */ + public GQuery live(String eventName, Function... funcs) { + return as(Events).live(eventName, null, funcs); + } + + /** + * <p> + * Attach a handler for this event to all elements which match the current selector, now and in + * the future. The <code>data</code> parameter allows us to pass data to the handler. + * <p> + * <p> + * Ex : + * + * <pre> + * $(".clickable").live("click", new Function(){ + * public void f(Element e){ + * $(e).css(CSS.COLOR.with(RGBColor.RED)); + * } + * }); + * </pre> + * + * With this code, all elements with class "clickable" present in the DOM or added to the DOM in + * the future will be clickable. The text color will be changed to red when they will be clicked. + * So if after in the code, you add another element : + * + * <pre> + * $("body").append("<div class='clickable'>Click me and I will be red</div>"); + * </pre> + * + * The click on this new element will also trigger the handler. + * </p> + * <p> + * In the same way, if you add "clickable" class on some existing element, these elements will be + * clickable also. + * </p> + * <p> + * <h3>important remarks</h3> + * <ul> + * <li> + * The live method should be always called after a selector</li> + * <li> + * Live events are bound to the context of the {@link GQuery} object : + * + * <pre> + * $(".clickable", myElement).live("click", new Function(){ + * public void f(Element e){ + * $(e).css(CSS.COLOR.with(RGBColor.RED)); + * } + * }); + * </pre> + * The {@link Function} will be called only on elements having the class "clickable" and being + * descendant of myElement.</li> + * </ul> + * </p> + */ + public GQuery live(String eventName, Object data, Function... funcs) { + return as(Events).live(eventName, data, funcs); + } + + /** + * Bind a function to the load event of each matched element. + */ + @Deprecated + public GQuery load(Function f) { + return bind(Event.ONLOAD, null, f); + } + + /** + * Load data from the server and place the returned HTML into the matched element. + * + * The url allows us to specify a portion of the remote document to be inserted. This is achieved + * with a special syntax for the url parameter. If one or more space characters are included in + * the string, the portion of the string following the first space is assumed to be a GQuery + * selector that determines the content to be loaded. + * + */ + public GQuery load(String url) { + return load(url, null, null); + } + + /** + * Load data from the server and place the returned HTML into the matched element. + * + * The url allows us to specify a portion of the remote document to be inserted. This is achieved + * with a special syntax for the url parameter. If one or more space characters are included in + * the string, the portion of the string following the first space is assumed to be a GQuery + * selector that determines the content to be loaded. + * + */ + public GQuery load(String url, Properties data, final Function onSuccess) { + return as(Ajax.Ajax).load(url, data, onSuccess); + } + + /** + * Reduce the set of matched elements to all elements before a given position. The position of the + * element in the set of matched elements starts at 0 and goes to length - 1. + */ + public GQuery lt(int pos) { + return slice(0, pos); + } + + /** + * Pass each element in the current matched set through a function, producing a new array + * containing the return values. When the call to the function returns a null it is not added to + * the array. + */ + public <W> List<W> map(Function f) { + ArrayList<W> ret = new ArrayList<W>(); + int i = 0; + for (Element e : elements) { + @SuppressWarnings("unchecked") + W o = (W) f.f(e.<com.google.gwt.dom.client.Element> cast(), i++); + if (o != null) { + ret.add(o); + } + } + return ret; + } + + /** + * Bind a set of functions to the mousedown event of each matched element. Or trigger the event if + * no functions are provided. + */ + public GQuery mousedown(Function... f) { + return bindOrFire(Event.ONMOUSEDOWN, null, f); + } + + /** + * Bind an event handler to be fired when the mouse enter an element, or trigger that handler on + * an element if no functions are provided. + * + * The mouseenter event differs from mouseover in the way it handles event bubbling. When + * mouseover is used on an element having inner element(s), then when the mouse pointer moves hover + * of the Inner element, the handler would be triggered. This is usually undesirable behavior. The + * mouseenter event, on the other hand, only triggers its handler when the mouse enters the + * element it is bound to, not a descendant. + */ + public GQuery mouseenter(Function... f) { + return as(Events).mouseenter(f); + } + + /** + * Bind an event handler to be fired when the mouse leaves an element, or trigger that handler on + * an element if no functions are provided. + * + * The mouseleave event differs from mouseout in the way it handles event bubbling. When + * mouseout is used on an element having inner element(s), then when the mouse pointer moves out + * of the Inner element, the handler would be triggered. This is usually undesirable behavior. The + * mouseleave event, on the other hand, only triggers its handler when the mouse leaves the + * element it is bound to, not a descendant. + */ + public GQuery mouseleave(Function... f) { + return as(Events).mouseleave(f); + } + + /** + * Bind a set of functions to the mousemove event of each matched element. Or trigger the event if + * no functions are provided. + */ + public GQuery mousemove(Function... f) { + return bindOrFire(Event.ONMOUSEMOVE, null, f); + } + + /** + * Bind a set of functions to the mouseout event of each matched element. Or trigger the event if + * no functions are provided. + */ + public GQuery mouseout(Function... f) { + return bindOrFire(Event.ONMOUSEOUT, null, f); + } + + /** + * Bind a set of functions to the mouseover event of each matched element. Or trigger the event if + * no functions are provided. + */ + public GQuery mouseover(Function... f) { + return bindOrFire(Event.ONMOUSEOVER, null, f); + } + + /** + * Bind a set of functions to the mouseup event of each matched element. Or trigger the event if + * no functions are provided. + */ + public GQuery mouseup(Function... f) { + return bindOrFire(Event.ONMOUSEUP, null, f); + } + + /** + * Get a set of elements containing the unique next siblings of each of the given set of elements. + * next only returns the very next sibling for each element, not all next siblings see {#nextAll}. + */ + public GQuery next() { + JsNodeArray result = JsNodeArray.create(); + for (Element e : elements) { + Element next = e.getNextSiblingElement(); + if (next != null) { + result.addNode(next); + } + } + return pushStack(unique(result), "next", getSelector()); + } + + /** + * Get a set of elements containing the unique next siblings of each of the given set of elements + * filtered by 1 or more selectors. next only returns the very next sibling for each element, not + * all next siblings see {#nextAll}. + */ + public GQuery next(String... selectors) { + JsNodeArray result = JsNodeArray.create(); + for (Element e : elements) { + Element next = e.getNextSiblingElement(); + if (next != null) { + result.addNode(next); + } + } + return pushStack(result, "next", selectors[0]).filter(selectors); + } + + /** + * Get all following siblings of each element in the set of matched elements. + */ + public GQuery nextAll() { + return nextAll(null); + } + + /** + * Get all following siblings of each element in the set of matched elements, filtered by a + * selector. + */ + public GQuery nextAll(String filter) { + JsNodeArray result = JsNodeArray.create(); + for (Element e : elements) { + allNextSiblingElements(e.getNextSiblingElement(), result, null, null, filter); + } + + return pushStack(unique(result), "nextAll", getSelector()); + } + + /** + * Get all following siblings of each element up to but not including the element matched by the + * selector. + * + * @param selector + * @return + */ + public GQuery nextUntil(String selector) { + return nextUntil($(selector), null); + } + + /** + * Get all following siblings of each element up to but not including the element matched by the + * selector, filtered by a selector. + * + * @param selector + * @return + */ + public GQuery nextUntil(String selector, String filter) { + return nextUntil($(selector), filter); + } + + /** + * Get all following siblings of each element up to but not including the element matched by the + * DOM node. + * + * @param selector + * @return + */ + public GQuery nextUntil(Element until) { + return nextUntil($(until), null); + } + + /** + * Get all following siblings of each element up to but not including the element matched by the + * DOM node, filtered by a selector. + * + * @param selector + * @return + */ + public GQuery nextUntil(Element until, String filter) { + return nextUntil($(until), filter); + } + + /** + * Get all following siblings of each element up to but not including the element matched by the + * GQuery object. + * + * @param selector + * @return + */ + public GQuery nextUntil(GQuery until) { + return nextUntil(until, null); + } + + /** + * Get all following siblings of each element up to but not including the element matched by the + * GQuery object, filtered by a selector + * + * @param selector + * @return + */ + public GQuery nextUntil(GQuery until, String filter) { + JsNodeArray result = JsNodeArray.create(); + for (Element e : elements) { + allNextSiblingElements(e.getNextSiblingElement(), result, null, until, filter); + } + return pushStack(unique(result), "nextUntil", getSelector()); + } + + /** + * Removes the specified Element from the set of matched elements. This method is used to remove a + * single Element from a jQuery object. + */ + public GQuery not(Element elem) { + JsNodeArray array = JsNodeArray.create(); + for (Element e : elements) { + if (e != elem) { + array.addNode(e); + } + } + return $(array); + } + + /** + * Removes any elements inside the passed set of elements from the set of matched elements. + */ + public GQuery not(GQuery gq) { + GQuery ret = this; + for (Element e : gq.elements) { + ret = ret.not(e); + } + return ret; + } + + /** + * Removes elements matching the specified expression from the set of matched elements. + */ + public GQuery not(String... filters) { + GQuery ret = this; + for (String f : filters) { + ret = ret.not($(f)); + } + return ret; + } + + /** + * Get the current offset of the first matched element, in pixels, relative to the document. The + * returned object contains two integer properties, top and left. The method works only with + * visible elements. + */ + public com.google.gwt.query.client.GQuery.Offset offset() { + Element e = get(0); + return e == null ? new Offset(0, 0) : new Offset(e.getAbsoluteLeft(), e.getAbsoluteTop()); + } + + /** + * Returns a GQuery collection with the positioned parent of the first matched element. This is + * the first parent of the element that has position (as in relative or absolute). This method + * only works with visible elements. + */ + public GQuery offsetParent() { + if (isEmpty()) { + return $(); + } + Element offParent = JsUtils.or(get(0).getOffsetParent(), body); + while (offParent != null && !"body".equalsIgnoreCase(offParent.getTagName()) + && !"html".equalsIgnoreCase(offParent.getTagName()) + && "static".equals(getStyleImpl().curCSS(offParent, "position", true))) { + offParent = offParent.getOffsetParent(); + } + return new GQuery(offParent); + } + + /** + * Binds a handler to a particular Event (like Event.ONCLICK) for each matched element. The + * handler is executed only once for each element. + * + * The event handler is passed as a Function that you can use to prevent default behavior. To stop + * both default action and event bubbling, the function event handler has to return false. + * + * You can pass an additional Object data to your Function as the second parameter + */ + public GQuery one(int eventbits, final Object data, final Function f) { + return as(Events).one(eventbits, data, f); + } + + /** + * Get the current computed height for the first element in the set of matched elements, including + * padding, border, but not the margin. + */ + public int outerHeight() { + return outerHeight(false); + } + + /** + * Get the current computed height for the first element in the set of matched elements, including + * padding, border, and optionally margin. + */ + public int outerHeight(boolean includeMargin) { + if (isEmpty()) { + return 0; + } + // height including padding and border + int outerHeight = (int)cur("offsetHeight", true); + if (includeMargin) { + outerHeight += cur("marginTop", true) + cur("marginBottom", true); + } + return outerHeight; + } + + /** + * Get the current computed width for the first element in the set of matched elements, including + * padding, border, but not the margin. + */ + public int outerWidth() { + return outerWidth(false); + } + + /** + * Get the current computed width for the first element in the set of matched elements, including + * padding and border and optionally margin. + */ + public int outerWidth(boolean includeMargin) { + if (isEmpty()) { + return 0; + } + // width including padding and border + int outerWidth = (int)cur("offsetWidth", true); + if (includeMargin) { + outerWidth += cur("marginRight", true) + cur("marginLeft", true); + } + return outerWidth; + } + + /** + * Get a set of elements containing the unique parents of the matched set of elements. + */ + public GQuery parent() { + JsNodeArray result = JsNodeArray.create(); + for (Element e : elements) { + Element p = e.getParentElement(); + if (p != null) { + result.addNode(p); + } + } + return new GQuery(unique(result)); + } + + /** + * Get a set of elements containing the unique parents of the matched set of elements. You may use + * an optional expressions to filter the set of parent elements that will match one of them. + */ + public GQuery parent(String... filters) { + return parent().filter(filters); + } + + /** + * Get a set of elements containing the unique ancestors of the matched set of elements (except + * for the root element). + */ + public GQuery parents() { + return parentsUntil(null); + } + + /** + * Get a set of elements containing the unique ancestors of the matched set of elements (except + * for the root element). The matched elements are filtered, returning those that match any of the + * filters. + */ + public GQuery parents(String... filters) { + return parents().filter(filters); + } + + /** + * Get the ancestors of each element in the current set of matched elements, up to but not + * including the element matched by the selector. + * + */ + public GQuery parentsUntil(String selector) { + JsNodeArray result = JsNodeArray.create(); + for (Element e : elements) { + Node par = e.getParentNode(); + while (par != null && par != document) { + if (selector != null && $(par).is(selector)) { + break; + } + result.addNode(par); + par = par.getParentNode(); + } + } + return new GQuery(unique(result)); + } + + /** + * Gets the top and left position of an element relative to its offset parent. The returned object + * contains two Integer properties, top and left. For accurate calculations make sure to use pixel + * values for margins, borders and padding. This method only works with visible elements. + */ + public com.google.gwt.query.client.GQuery.Offset position() { + if (isEmpty()) { + return new Offset(0, 0); + } + Element element = get(0); + // Get *real* offsetParent + Element offsetParent = get(0).getOffsetParent(); + // Get correct offsets + Offset offset = offset(); + Offset parentOffset = null; + if (offsetParent == body || offsetParent == (Node) document) { + parentOffset = new Offset(0, 0); + } else { + parentOffset = $(offsetParent).offset(); + } + + // Subtract element margins + int topMargin = (int) getStyleImpl().cur(element, "marginTop", true); + // TODO: move this check to getStyleImpl() + // When margin-left = auto, Safari and chrome return a value while IE and + // Firefox return 0 + // force the margin-left to 0 if margin-left = auto. + int leftMargin = 0; + if (!"auto".equals(element.getStyle().getMarginLeft())) { + leftMargin = (int) getStyleImpl().cur(element, "marginLeft", true); + } + + offset = offset.add(-leftMargin, -topMargin); + + // Add offsetParent borders + int parentOffsetBorderTop = (int) getStyleImpl().cur(offsetParent, "borderTopWidth", true); + int parentOffsetBorderLeft = (int) getStyleImpl().cur(offsetParent, "borderLeftWidth", true); + parentOffset = parentOffset.add(parentOffsetBorderLeft, parentOffsetBorderTop); + + // Subtract the two offsets + return offset.add(-parentOffset.left, -parentOffset.top); + } + + /** + * Prepend content to the inside of every matched element. This operation is the best way to + * insert elements inside, at the beginning, of all matched elements. + */ + public GQuery prepend(GQuery query) { + return domManip(query, DomMan.PREPEND); + } + + /** + * Prepend content to the inside of every matched element. This operation is the best way to + * insert elements inside, at the beginning, of all matched elements. + */ + public GQuery prepend(Node n) { + return domManip($(n), DomMan.PREPEND); + } + + /** + * Prepend content to the inside of every matched element. This operation is the best way to + * insert elements inside, at the beginning, of all matched elements. + */ + public GQuery prepend(String html) { + return domManip(html, DomMan.PREPEND); + } + + /** + * All of the matched set of elements will be inserted at the beginning of the element(s) + * specified by the parameter other. + * + * The operation $(A).prependTo(B) is, essentially, the reverse of doing a regular + * $(A).prepend(B), instead of prepending B to A, you're prepending A to B. + */ + public GQuery prependTo(GQuery other) { + other.prepend(this); + return this; + } + + /** + * All of the matched set of elements will be inserted at the beginning of the element(s) + * specified by the parameter other. + * + * The operation $(A).prependTo(B) is, essentially, the reverse of doing a regular + * $(A).prepend(B), instead of prepending B to A, you're prepending A to B. + */ + public GQuery prependTo(Node n) { + $(n).prepend(this); + return this; + } + + /** + * All of the matched set of elements will be inserted at the beginning of the element(s) + * specified by the parameter other. + * + * The operation $(A).prependTo(B) is, essentially, the reverse of doing a regular + * $(A).prepend(B), instead of prepending B to A, you're prepending A to B. + */ + public GQuery prependTo(String html) { + $(html).prepend(this); + return this; + } + + /** + * Get a set of elements containing the unique previous siblings of each of the matched set of + * elements. Only the immediately previous sibling is returned, not all previous siblings. + */ + public GQuery prev() { + JsNodeArray result = JsNodeArray.create(); + for (Element e : elements) { + Element next = getPreviousSiblingElement(e); + if (next != null) { + result.addNode(next); + } + } + return new GQuery(unique(result)); + } + + /** + * Get a set of elements containing the unique previous siblings of each of the matched set of + * elements filtered by selector. Only the immediately previous sibling is returned, not all + * previous siblings. + */ + public GQuery prev(String... selectors) { + JsNodeArray result = JsNodeArray.create(); + for (Element e : elements) { + Element next = getPreviousSiblingElement(e); + if (next != null) { + result.addNode(next); + } + } + return new GQuery(unique(result)).filter(selectors); + } + + /** + * Get all preceding siblings of each element in the set of matched elements. + */ + public GQuery prevAll() { + return prevAll(null); + } + + /** + * Get all preceding siblings of each element in the set of matched elements filtered by a + * selector. + */ + public GQuery prevAll(String selector) { + JsNodeArray result = JsNodeArray.create(); + for (Element e : elements) { + allPreviousSiblingElements(getPreviousSiblingElement(e), result, null, selector); + } + return pushStack(unique(result), "prevAll", getSelector()); + } + + /** + * Get all preceding siblings of each element up to but not including the element matched by the + * <code>selector</code>. + * + * The elements are returned in order from the closest sibling to the farthest. + */ + public GQuery prevUntil(String selector) { + return prevUntil($(selector), null); + } + + /** + * Get all preceding siblings of each element up to but not including the <code>until</code> + * element. + * + * The elements are returned in order from the closest sibling to the farthest. + */ + public GQuery prevUntil(Element until) { + return prevUntil($(until), null); + } + + /** + * Get all preceding siblings of each element up to but not including the <code>until</code> + * element. + * + * The elements are returned in order from the closest sibling to the farthest. + */ + public GQuery prevUntil(GQuery until) { + return prevUntil(until, null); + } + + /** + * Get all preceding siblings of each element matching the <code>filter</code> up to but not + * including the element matched by the <code>selector</code>. + * + * The elements are returned in order from the closest sibling to the farthest. + */ + public GQuery prevUntil(String selector, String filter) { + return prevUntil($(selector), filter); + } + + /** + * Get all preceding siblings of each element matching the <code>filter</code> up to but not + * including the <code>until</code> element. + * + */ + public GQuery prevUntil(Element until, String filter) { + return prevUntil($(until), filter); + } + + /** + * Get all preceding siblings of each element matching the <code>filter</code> up to but not + * including the element matched by the <code>until</code> element. + * + */ + public GQuery prevUntil(GQuery until, String filter) { + JsNodeArray result = JsNodeArray.create(); + for (Element e : elements) { + allPreviousSiblingElements(getPreviousSiblingElement(e), result, until, filter); + } + return pushStack(unique(result), "prevUntil", getSelector()); + } + + /** + * Accesses a boolean property on the first matched element. + * + * @param key the name of the boolean property to be accessed + * + * @return <code>true</code> if at least one element is matched and the specified boolean property + * is set to <code>true</code> on the first matched element; <code>false</code> otherwise + * + */ + public boolean prop(String key) { + assert key != null : "Key is null"; + + return !isEmpty() && get(0).getPropertyBoolean(key); + } + + /** + * Sets a boolean property to a value on all matched elements. + * + * @param key the name of the boolean property to be set + * @param value the value the specified boolean property should be set to + * + * @return this <code>GQuery</code> object + * + */ + public GQuery prop(String key, boolean value) { + assert key != null : "Key is null"; + + for (final Element element : elements) { + element.setPropertyBoolean(key, value); + } + + return this; + } + + /** + * Sets a boolean property to a computed value on all matched elements. + * + * @param key the name of the boolean property to be set + * @param closure the closure to be used to compute the value the specified boolean property + * should be set to; the <code>closure</code> is + * {@linkplain Function#f(com.google.gwt.dom.client.Element, int) passed} the target + * element and its index as arguments and is expected to return either a + * <code>Boolean</code> value or an object whose textual representation is converted to a + * <code>Boolean</code> value; <code>null</code> return values are ignored + * + * @return this <code>GQuery</code> object + * + */ + public GQuery prop(String key, Function closure) { + assert key != null : "Key is null"; + assert closure != null : "Closure is null"; + + int i = 0; + for (Element e : elements) { + Object value = closure.f(e, i++); + if (value != null) { + e.setPropertyBoolean(key, value instanceof Boolean ? (Boolean) value : Boolean + .valueOf(value.toString())); + } + } + + return this; + } + + protected GQuery pushStack(JsNodeArray elts, String name, String selector) { + GQuery g = new GQuery(elts); + g.setPreviousObject(this); + g.setSelector(selector); + g.currentContext = currentContext; + return g; + } + + /** + * Show the number of functions in the efects queue to be executed on the first matched element. + */ + public int queue() { + return as(Queue).queue(); + } + + /** + * Put a set of {@link Function} at the end of the Effects queue. + * + * Example: + * + * <pre class="code"> + * $("#foo").animate("left:'+=500'", 400) + * .queue(new Function(){ + * public void f(Element e){ + * $(e).css(CSS.BACKGROUNG_COLOR.with(RGBColor.RED)); + * $(e).dequeue(); + * } + * }) + * .animate("left:'-=500'", 400) + * .queue(lazy().css("color", "yellow"); + * + * </pre> + * + * When this statement is executed, the element move to 500 px to left for 400 ms, then its + * background color is changed to red and then move to 500px to right for 400ms, and finally its + * color is set to yellow. + * + * Please note that {@link #dequeue()} function is needed at the end of your function to start the + * next function in the queue. In lazy() methods you should call dequeue() just before the done() + * call. {@see #dequeue()} + */ + public GQuery queue(Function... f) { + return as(Queue).queue(f); + } + + /** + * Show the number of functions in the queued named as queueName to be executed on the first + * matched element. + */ + public int queue(String queueName) { + return as(Queue).queue(); + } + + /** + * Put a set of {@link Function} at the end of a queue. + * + * Example: + * + * <pre class="code"> + * $("#foo").queue("myQueue", new Function(){ + * public void f(Element e){ + * $(e).css(CSS.BACKGROUNG_COLOR.with(RGBColor.RED)); + * dequeue("myQueue"); + * } + * }) + * .delay(500, "myQueue") + * .queue("myQueue", lazy().css(CSS.COLOR.with(RGBColor.YELLOW)).dequeue("myQueue").done()); + * </pre> + * + * When this statement is executed, the background color of the element is set to red, then wait + * 500ms before to set the text color of the element to yellow. right for 400ms. + * + * Please note that {@link #dequeue()} function is needed at the end of your function to start the + * next function in the queue. In lazy() methods you should call dequeue() just before the done() + * call. {@see #dequeue()} + */ + public GQuery queue(String queueName, Function... f) { + return as(Queue).queue(queueName, f); + } + + /** + * Removes all matched elements from the DOM. + */ + public GQuery remove() { + return remove(null, true); + } + + /** + * Removes from the DOM all matched elements filtered by the <code>filter</code>. + */ + public GQuery remove(String filter) { + return remove(filter, true); + } + + /** + * Removes all matched elements from the DOM and cleans their data and bound events if the value + * of <code>clean</code> parameter is set to true. The <code> filter</code> parameter allows to + * filter the matched set to remove. + */ + protected GQuery remove(String filter, boolean clean) { + for (Element e : elements) { + if (filter == null || $(e).filter(filter).length() == 1) { + if (clean) { + // clean data linked to the children + // TODO: "*" fails in queryselectorall (webkit mobile) + cleanGQData($("*", e).elements()); + // clean data linked to the element itself + cleanGQData(e); + } + Widget w = getAssociatedWidget(e); + if (w != null) { + w.removeFromParent(); + } else { + e.removeFromParent(); + } + } + } + return this; + } + + /** + * Remove the named attribute from every element in the matched set. + */ + public GQuery removeAttr(String key) { + getAttributeImpl().removeAttribute(this, key); + return this; + } + + /** + * Removes the specified classes to each matched element. + * + * If no arguments are provided, it removes all classes like jquery does. + */ + public GQuery removeClass(String... classes) { + for (Element e : elements) { + if (Element.is(e)) { + if (classes.length == 0) { + e.setClassName(null); + } else { + for (String clz : classes) { + e.removeClassName(clz); + } + } + } + } + return this; + } + + protected void removeData(Element item, String name) { + if (dataCache == null) { + windowData = JavaScriptObject.createObject().cast(); + dataCache = JavaScriptObject.createObject().cast(); + } + item = item == window || item.getNodeName() == null ? windowData : item; + int id = item.hashCode(); + if (name != null) { + if (dataCache.exists(id)) { + dataCache.getCache(id).delete(name); + } + if (dataCache.getCache(id).isEmpty()) { + removeData(item, null); + } + } else { + // when the element cache is empty we remove its entry to save memory (issue 132) + dataCache.delete(id); + } + } + + /** + * Removes named data store from an element. + */ + public GQuery removeData(String name) { + for (Element e : elements) { + removeData(e, name); + } + return this; + } + + /** + * Replaces the element <code>elem</code> by the specified selector with the matched elements. + * This function is the complement to replaceWith() which does the same task with the parameters + * reversed. + * + * @return a {@link GQuery} object containing the new elements. + */ + public GQuery replaceAll(Element elem) { + return replaceAll($(elem)); + } + + /** + * Replaces the elements matched by the target with the selected elements. This function is the + * complement to replaceWith() which does the same task with the parameters reversed. + * + * @return a {@link GQuery} object containing the new elements. + */ + public GQuery replaceAll(GQuery target) { + // if there is only one element and it is not attached to the dom, we have + // to clone it to be reused on each element of target (if target contains + // more than one element) + boolean mustBeCloned = length() == 1 && parents().filter("body").length() == 0; + + List<Element> newElements = new ArrayList<Element>(); + for (int i = 0, l = target.size(); i < l; i++) { + GQuery _this = (i > 0 && mustBeCloned) ? this.clone() : this; + $(target.get(i)).replaceWith(_this); + newElements.addAll(Arrays.asList(_this.elements)); + } + return $(newElements); + } + + /** + * Replaces the elements matched by the specified selector with the matched elements. This + * function is the complement to replaceWith() which does the same task with the parameters + * reversed. + * + * @return a {@link GQuery} object containing the new elements. + */ + public GQuery replaceAll(String selector) { + return replaceAll($(selector)); + } + + /** + * Replaces all matched elements with the specified element. + * + * @return the GQuery element that was just replaced, which has been removed from the DOM and not + * the new element that has replaced it. + */ + public GQuery replaceWith(Element elem) { + return replaceWith($(elem)); + } + + /** + * Replaces all matched elements with elements selected by <code>target</code> . + * + * @return the GQuery element that was just replaced, which has been removed from the DOM and not + * the new element that has replaced it. + */ + public GQuery replaceWith(GQuery target) { + for (Element el : elements) { + Element nextSibling = el.getNextSiblingElement(); + + if (nextSibling != null) { + $(nextSibling).before(target); + } else { + Element parent = el.getParentElement(); + $(parent).append(target); + } + $(el).remove(); + } + return this; + + } + + /** + * Replaces all matched elements with the specified HTML. + * + * @return the GQuery element that was just replaced, which has been removed from the DOM and not + * the new element that has replaced it. + */ + public GQuery replaceWith(String html) { + for (Element el : elements) { + Element nextSibling = el.getNextSiblingElement(); + + if (nextSibling != null) { + $(nextSibling).before(html); + } else { + Element parent = el.getParentElement(); + $(parent).append(html); + } + $(el).remove(); + } + return this; + } + + /** + * Bind a set of functions to the resize event of each matched element, or tigger the resize event + * if no functions are provided. + * + * Note that although all elements can be configured to handle resize events, by default only + * window will trigger it when it is resized, for an arbitrary element you have to trigger the + * event after resizing the object. + * + */ + public GQuery resize(Function... f) { + return bindOrFire(EventsListener.ONRESIZE, null, f); + } + + /** + * Bind an event handler to the "resize" JavaScript event, or trigger that event on an element. + */ + public GQuery resize(final Function f) { + return bindOrFire(EventsListener.ONRESIZE, null, f); + } + + /** + * Save a set of Css properties of every matched element. + */ + public void restoreCssAttrs(String... cssProps) { + for (Element e : elements) { + for (String a : cssProps) { + String datakey = OLD_DATA_PREFIX + a; + getStyleImpl().setStyleProperty(e, a, (String) data(e, datakey, null)); + removeData(e, datakey); + } + } + } + + /** + * Restore a set of previously saved Css properties in every matched element. + */ + public void saveCssAttrs(String... cssProps) { + for (Element e : elements) { + for (String a : cssProps) { + data(OLD_DATA_PREFIX + a, getStyleImpl().curCSS(e, a, false)); + } + } + } + + /** + * Bind a set of functions to the scroll event of each matched element. Or trigger the event if no + * functions are provided. + */ + public GQuery scroll(Function... f) { + return bindOrFire(Event.ONSCROLL, null, f); + } + + /** + * Scrolls the first matched element into view. + */ + public GQuery scrollIntoView() { + if (!isEmpty()) + scrollIntoViewImpl(get(0)); + return this; + } + + /** + * Scrolls the first matched element into view. + * + * If ensure == true, it crawls up the DOM hierarchy, adjusting the scrollLeft and scrollTop + * properties of each scroll-able element to ensure that the specified element is completely in + * view. It adjusts each scroll position by the minimum amount necessary. + */ + public GQuery scrollIntoView(boolean ensure) { + if (!isEmpty() && ensure) { + DOM.scrollIntoView((com.google.gwt.user.client.Element) get(0)); + } else { + scrollIntoView(); + } + return this; + } + + /** + * Gets the scroll left offset of the first matched element. This method works for both visible + * and hidden elements. + */ + public int scrollLeft() { + Element e = get(0); + if (e == null) { + return 0; + } + if (e == window || e.getNodeName() == null) { + return Window.getScrollLeft(); + } else if (e == (Node) document) { + return document.getScrollLeft(); + } else { + return e.getScrollLeft(); + } + } + + /** + * The scroll left offset is set to the passed value on all matched elements. This method works + * for both visible and hidden elements. + */ + public GQuery scrollLeft(int left) { + for (Element e : elements) { + if (e == window || e.getNodeName() == null || e == (Node) document) { + Window.scrollTo(left, $(e).scrollTop()); + } else { + e.setPropertyInt("scrollLeft", left); + } + } + return this; + } + + /** + * + * Scrolls the contents of all matched elements to the specified co-ordinate becoming the top left + * corner of the viewable area. + * + * This method is only useful where there are areas of the document not viewable within the + * current viewable area of the window and the visible property of the window's scrollbar must be + * set to true. + * + */ + public GQuery scrollTo(int left, int top) { + scrollLeft(left).scrollTop(top); + return this; + } + + /** + * Gets the scroll top offset of the first matched element. This method works for both visible and + * hidden elements. + */ + public int scrollTop() { + Element e = get(0); + if (e == null) { + return 0; + } + if (e == window || e.getNodeName() == null) { + return Window.getScrollTop(); + } else if (e == (Node) document) { + return document.getScrollTop(); + } else { + return e.getScrollTop(); + } + } + + /** + * The scroll top offset is set to the passed value on all matched elements. This method works for + * both visible and hidden elements. + */ + public GQuery scrollTop(int top) { + for (Element e : elements) { + if (e == window || e.getNodeName() == null || e == (Node) document) { + Window.scrollTo($(e).scrollLeft(), top); + } else { + e.setPropertyInt("scrollTop", top); + } + } + return this; + } + + public GQuery select() { + return as(Events).triggerHtmlEvent("select"); + } + + private GQuery select(String selector, Node context) { + if (engine == null) { + engine = new SelectorEngine(); + } + + NodeList<Element> n = engine.select(selector, context == null ? document : context); + currentSelector = selector; + currentContext = context != null ? context : document; + return setArray(n); + } + + /** + * Force the current matched set of elements to become the specified array of elements. + */ + public GQuery setArray(NodeList<Element> list) { + if (list != null) { + nodeList.<JsCache> cast().clear(); + int l = list.getLength(); + elements = new Element[l]; + for (int i = 0; i < l; i++) { + elements[i] = list.getItem(i); + nodeList.<JsObjectArray<Element>> cast().add(list.getItem(i)); + } + } + return this; + } + + public void setPreviousObject(GQuery previousObject) { + this.previousObject = previousObject; + } + + public GQuery setSelector(String selector) { + this.currentSelector = selector; + return this; + } + + /** + * Make all matched elements visible + */ + public GQuery show() { + for (Element e : elements) { + String currentDisplay = e.getStyle().getDisplay(); + String oldDisplay = (String) data(e, OLD_DISPLAY, null); + + // reset the display + if (oldDisplay == null && "none".equals(currentDisplay)) { + getStyleImpl().setStyleProperty(e, "display", ""); + currentDisplay = ""; + } + + // check if the stylesheet impose display: none. If it is the case, determine + // the default display for the tag and store it at the element level + if ("".equals(currentDisplay) && !getStyleImpl().isVisible(e)) { + data(e, OLD_DISPLAY, getStyleImpl().defaultDisplay(e.getNodeName())); + } + } + + // set the display value in a separate for loop to avoid constant reflow + // because broswer reflow is triggered each time we gonna set and after get (in + // isVisibleProperty() method) + // the diplay property. Reflows is very bad in performance point of view + for (Element e : elements) { + String currentDisplay = e.getStyle().getDisplay(); + if ("".equals(currentDisplay) || "none".equals(currentDisplay)) { + getStyleImpl().setStyleProperty(e, "display", + JsUtils.or((String) data(e, OLD_DISPLAY, null), "")); + } + } + removeData(OLD_DISPLAY); + return this; + } + + /** + * Get a set of elements containing all of the unique siblings of each of the matched set of + * elements. + */ + public GQuery siblings() { + JsNodeArray result = JsNodeArray.create(); + for (Element e : elements) { + allNextSiblingElements(e.getParentElement().getFirstChildElement(), result, e, null, null); + } + return new GQuery(unique(result)); + } + + /** + * Get a set of elements containing all of the unique siblings of each of the matched set of + * elements filtered by the provided set of selectors. + */ + public GQuery siblings(String... selectors) { + return siblings().filter(selectors); + } + + /** + * Return the number of elements in the matched set. + */ + public int size() { + return elements.length; + } + + /** + * Selects a subset of the matched elements. + */ + public GQuery slice(int start, int end) { + JsNodeArray slice = JsNodeArray.create(); + int l = size(); + if (end == -1 || end > l) { + end = l; + } + for (int i = start; i < end; i++) { + slice.addNode(get(i)); + } + return new GQuery(slice); + } + + /** + * Reveal all matched elements by adjusting their height and firing an optional callback after + * completion. + */ + public Effects slideDown(Function... f) { + return as(Effects).slideDown(f); + } + + /** + * Reveal all matched elements by adjusting their height and firing an optional callback after + * completion. + */ + public Effects slideDown(int millisecs, Function... f) { + return as(Effects).slideDown(millisecs, f); + } + + /** + * Toggle the visibility of all matched elements by adjusting their height and firing an optional + * callback after completion. Only the height is adjusted for this animation, causing all matched + * elements to be hidden or shown in a "sliding" manner + */ + public Effects slideToggle(int millisecs, Function... f) { + return as(Effects).slideToggle(millisecs, f); + } + + /** + * Hide all matched elements by adjusting their height and firing an optional callback after + * completion. + */ + public Effects slideUp(Function... f) { + return as(Effects).slideUp(f); + } + + /** + * Hide all matched elements by adjusting their height and firing an optional callback after + * completion. + */ + public Effects slideUp(int millisecs, Function... f) { + return as(Effects).slideUp(millisecs, f); + } + + /** + * When .stop() is called on an element, the currently-running animation (if any) is immediately + * stopped. If, for instance, an element is being hidden with .slideUp() when .stop() is called, + * the element will now still be displayed, but will be a fraction of its previous height. + * Callback functions are not called but the next animation in the queue begins immediately. + */ + public GQuery stop() { + return stop(false); + } + + /** + * When .stop() is called on an element, the currently-running animation (if any) is immediately + * stopped. If, for instance, an element is being hidden with .slideUp() when .stop() is called, + * the element will now still be displayed, but will be a fraction of its previous height. + * Callback functions are not called but the next animation in the queue begins immediately. + * + * If the clearQueue parameter is provided with a value of true, then the rest of the animations + * in the queue are removed and never run. + */ + public GQuery stop(boolean clearQueue) { + return stop(clearQueue, false); + } + + /** + * When .stop() is called on an element, the currently-running animation (if any) is immediately + * stopped. If, for instance, an element is being hidden with .slideUp() when .stop() is called, + * the element will now still be displayed, but will be a fraction of its previous height. + * Callback functions are not called but the next animation in the queue begins immediately. + * + * If the clearQueue parameter is provided with a value of true, then the rest of the animations + * in the queue are removed and never run. + * + * If the jumpToEnd property is provided with a value of true, the current animation stops, but + * the element is immediately given its target values for each CSS property. The callback + * functions are then immediately called, if provided. + */ + public GQuery stop(boolean clearQueue, boolean jumpToEnd) { + return as(Queue).stop(clearQueue, jumpToEnd); + } + + /** + * Bind a set of functions to the submit event of each matched element. Or submit a form if no + * functions are provided. + */ + public GQuery submit(Function... funcs) { + return bindOrFire(EventsListener.ONSUBMIT, null, funcs); + } + + /** + * Return the concatened text contained in the matched elements. + */ + public String text() { + String result = ""; + for (Element e : elements) { + result += JsUtils.text(e); + } + return result; + } + + /** + * Set the innerText of every matched element. + */ + public GQuery text(String txt) { + for (Element e : elements) { + e.setInnerText(txt); + } + return this; + } + + /** + * Toggle visibility of elements. + */ + public GQuery toggle() { + for (Element e : elements) { + if (getStyleImpl().isVisible(e)) { + $(e).hide(); + } else { + $(e).show(); + e.getStyle().setDisplay(Display.BLOCK); + } + } + return this; + } + + /** + * Toggle among two or more function calls every other click. + */ + public GQuery toggle(final Function... fn) { + for (Element e : elements) { + $(e).click(new Function() { + int click = 0; + + public boolean f(Event e) { + int n = fn.length == 1 ? 0 : (click++ % fn.length); + return fn[n].f(e); + } + }); + } + return this; + } + + /** + * Adds or removes the specified classes to each matched element depending on the class's + * presence. + */ + public GQuery toggleClass(String... classes) { + for (Element e : elements) { + for (String clz : classes) { + if (hasClass(e, clz)) { + e.removeClassName(clz); + } else { + e.addClassName(clz); + } + } + } + return this; + } + + /** + * Adds or removes the specified classes to each matched element depending on the value of the + * switch argument. + * + * if addOrRemove is true, the class is added and in the case of false it is removed. + */ + public GQuery toggleClass(String clz, boolean addOrRemove) { + if (addOrRemove) { + addClass(clz); + } else { + removeClass(clz); + } + return this; + } + + /** + * Returns the computed top position of the first element matched. + */ + public int top() { + return (int) cur("top", true); + } + + /** + * Produces a string representation of the matched elements. + */ + public String toString() { + return toString(false); + } + + /** + * Produces a string representation of the matched elements. + */ + public String toString(boolean pretty) { + String r = ""; + for (Element e : elements) { + if (window.equals(e)) { + continue; + } + String elStr; + try { + elStr = JsUtils.isXML(e) ? JsUtils.XML2String(e) : e.getString(); + } catch (Exception e2) { + elStr = + "< " + (e == null ? "null" : e.getNodeName()) + + "(gquery, error getting the element string representation: " + e2.getMessage() + + ")/>"; + } + r += (pretty && r.length() > 0 ? "\n " : "") + elStr; + } + return r; + } + + /** + * Trigger a set of events on each matched element. + * + * For keyboard events you can pass a second parameter which represents the key-code of the pushed + * key. + * + * Example: fire(Event.ONCLICK | Event.ONFOCUS) Example: fire(Event.ONKEYDOWN. 'a'); + */ + public GQuery trigger(int eventbits, int... keys) { + return as(Events).trigger(eventbits, keys); + } + + /** + * Removes all events that match the eventbits. + */ + public GQuery unbind(int eventbits) { + return as(Events).unbind(eventbits); + } + + /** + * Removes the function passed from the set of events which match the eventbits. + */ + public GQuery unbind(int eventbits, Function f) { + return as(Events).unbind(eventbits, null, f); + } + + /** + * Removes all events that match the eventList. + */ + public GQuery unbind(String eventList) { + return unbind(eventList, null); + } + + /** + * Removes all events that match the eventList. + */ + public GQuery unbind(String eventList, Function f) { + return as(Events).unbind(eventList, f); + } + + /** + * Remove all event delegation that have been bound using + * {@link #delegate(String, int, Function...)} {@link #live(int, Function...)} methods + */ + public GQuery undelegate() { + return as(Events).undelegate(); + } + + /** + * Undelegate is a way of removing event handlers that have been bound using + * {@link #delegate(String, int, Function...)} method + */ + public GQuery undelegate(String selector) { + for (Element e : elements) { + $(selector, e).die(); + } + + return this; + } + + /** + * Undelegate is a way of removing event handlers that have been bound using + * {@link #delegate(String, int, Function...)} method + */ + public GQuery undelegate(String selector, int eventBit) { + for (Element e : elements) { + $(selector, e).die(eventBit); + } + + return this; + } + + /** + * Undelegate is a way of removing event handlers that have been bound using + * {@link #delegate(String, int, Function...)} method + */ + public GQuery undelegate(String selector, String eventName) { + for (Element e : elements) { + $(selector, e).die(eventName); + } + + return this; + } + + /** + * Remove all duplicate elements from an array of elements. Note that this only works on arrays of + * DOM elements, not strings or numbers. + */ + public JsNodeArray unique(NodeList<Element> result) { + return JsUtils.unique(result.<JsArray<Element>> cast()).cast(); + } + + /** + * This method removes the element's parent. The matched elements replaces their parents within + * the DOM structure. It is the inverse of {@link GQuery#wrap(GQuery)} method + * + * @return + */ + public GQuery unwrap() { + + for (Element parent : parent().elements) { + if (!"body".equalsIgnoreCase(parent.getTagName())) { + GQuery $parent = $(parent); + $parent.replaceWith($parent.children()); + } + } + return this; + } + + /** + * Gets the content of the value attribute of the first matched element, returns only the first + * value even if it is a multivalued element. To get an array of all values in multivalues + * elements use vals() + * + * When the first element is a radio-button and is not checked, then it looks for the first + * checked radio-button that has the same name in the list of matched elements. + * + * When there are not matched elements it returns null. + */ + public String val() { + if (isEmpty()) { + return null; + } + String[] v = vals(); + return v == null ? null : v.length > 0 ? v[0] : ""; + } + + /** + * Sets the value attribute of every matched element based in the return value of the function + * evaluated for this element. + * + * NOTE: in jquery the function receives the arguments in different way, first index and them the + * actual value, but we use the normal way in gquery Function, first the element and second the + * index. + */ + public GQuery val(Function f) { + for (int i = 0; i < size(); i++) { + eq(i).val(f.f(get(i), i).toString()); + } + return this; + } + + /** + * Sets the 'value' attribute of every matched element, but does not set the checked flag to + * checkboxes or radiobuttons. + * + * If you wanted to set values in collections of checkboxes o radiobuttons use val(String[]) + * instead + */ + public GQuery val(String value) { + for (Element e : elements) { + setElementValue(e, value); + } + return this; + } + + /** + * Sets the value of every matched element. + * + * There is a different behaviour depending on the element type: + * <ul> + * <li>select multiple: options whose value match any of the passed values will be set. + * <li>select single: the last option whose value matches any of the passed values will be set. + * <li>input radio: the last input whose value matches any of the passed values will be set. + * <li>input checkbox: inputs whose value match any of the passed values will be set. + * <li>textarea, button, and other input: value will set to a string result of joining with coma, + * all passed values + * </ul> + * + * NOTE: if you wanted call this function with just one parameter, you have to pass an array + * signature to avoid call the overloaded val(String) method: + * + * $(...).val(new String[]{"value"}); + */ + public GQuery val(String... values) { + String value = values.length > 0 ? values[0] : ""; + for (int i = 1; i < values.length; i++) { + value += "," + values[i]; + } + for (Element e : elements) { + String name = e.getNodeName(); + if ("select".equalsIgnoreCase(name)) { + SelectElement s = SelectElement.as(e); + s.setSelectedIndex(-1); + for (String v : values) { + if (s.isMultiple()) { + for (int i = 0, l = s.getOptions().getLength(); i < l; i++) { + if (v.equals(s.getOptions().getItem(i).getValue())) { + s.getOptions().getItem(i).setSelected(true); + } + } + } else { + s.setValue(v); + } + } + } else if ("input".equalsIgnoreCase(name)) { + InputElement ie = InputElement.as(e); + String type = ie.getType(); + if ("radio".equalsIgnoreCase((type)) || "checkbox".equalsIgnoreCase(type)) { + ie.setChecked(false); + for (String v : values) { + if (ie.getValue().equals(v)) { + ie.setChecked(true); + break; + } + } + } else { + ie.setValue(value); + } + } else { + setElementValue(e, value); + } + } + return this; + } + + /** + * Gets the content of the value attribute of the first matched element, returns more than one + * value if it is a multiple select. + * + * When the first element is a radio-button and is not checked, then it looks for a the first + * checked radio-button that has the same name in the list of matched elements. + * + * This method always returns an array. If no valid value can be determined the array will be + * empty, otherwise it will contain one or more values. + */ + public String[] vals() { + if (!isEmpty()) { + Element e = get(0); + if (e.getNodeName().equalsIgnoreCase("select")) { + SelectElement se = SelectElement.as(e); + if (se.isMultiple()) { + JsArrayString result = JsArrayString.createArray().cast(); + for (int i = 0, l = se.getOptions().getLength(); i < l; i++) { + OptionElement oe = se.getOptions().getItem(i); + if (oe.isSelected()) { + result.set(result.length(), oe.getValue()); + } + } + return result.length() > 0 ? jsArrayToString(result) : null; + } else if (se.getSelectedIndex() >= 0) { + return new String[] {se.getOptions().getItem(se.getSelectedIndex()).getValue()}; + } + } else if (e.getNodeName().equalsIgnoreCase("input")) { + InputElement ie = InputElement.as(e); + return new String[] {ie.getValue()}; + } else if (e.getNodeName().equalsIgnoreCase("textarea")) { + return new String[] {TextAreaElement.as(e).getValue()}; + } else if (e.getNodeName().equalsIgnoreCase("button")) { + return new String[] {ButtonElement.as(e).getValue()}; + } + } + return new String[0]; + } + + @Deprecated + public boolean visible() { + return isVisible(); + } + + /** + * Return the first non null attached widget from the matched elements or null if there isn't any. + */ + @SuppressWarnings("unchecked") + public <W extends Widget> W widget() { + return (W) widget(0); + } + + /** + * Return the nth non null attached widget from the matched elements or null if there isn't any. + */ + public <W extends Widget> W widget(int n) { + for (Element e : elements) { + @SuppressWarnings("unchecked") + W w = (W) getAssociatedWidget(e); + if (w != null) { + if (n == 0) { + return w; + } + n--; + } + } + return null; + } + + /** + * return the list of attached widgets matching the query + */ + public List<Widget> widgets() { + List<Widget> widgets = new ArrayList<Widget>(); + for (Element e : elements) { + Widget w = getAssociatedWidget(e); + if (w != null) { + widgets.add(w); + } + } + return widgets; + } + + /** + * Return the list of attached widgets instance of the provided class matching the query. + * + * This method is very useful for decoupled views, so as we can access widgets from other views + * without maintaining methods which export them. + * + */ + @SuppressWarnings("unchecked") + public <W extends Widget> List<W> widgets(Class<W> clazz) { + List<W> ret = new ArrayList<W>(); + for (Widget w : widgets()) { + // isAssignableFrom does not work in gwt. + Class<?> c = w.getClass(); + do { + if (c.equals(clazz)) { + ret.add((W) w); + break; + } + c = c.getSuperclass(); + } while (c != null); + } + return ret; + } + + /** + * Get the current computed, pixel, width of the first matched element. It does not include + * margin, padding nor border. + */ + public int width() { + return (int) cur("width", true); + } + + /** + * Set the width of every matched element. + */ + public GQuery width(int width) { + for (Element e : elements) { + e.getStyle().setPropertyPx("width", width); + } + return this; + } + + /** + * Wrap each matched element with the specified HTML content. This wrapping process is most useful + * for injecting additional structure into a document, without ruining the original semantic + * qualities of a document. This works by going through the first element provided (which is + * generated, on the fly, from the provided HTML) and finds the deepest descendant element within + * its structure -- it is that element that will enwrap everything else. + */ + public GQuery wrap(Element elem) { + return wrap($(elem)); + } + + /** + * Wrap each matched element with the specified HTML content. This wrapping process is most useful + * for injecting additional structure into a document, without ruining the original semantic + * qualities of a document. This works by going through the first element provided (which is + * generated, on the fly, from the provided HTML) and finds the deepest descendant element within + * its structure -- it is that element that will enwrap everything else. + */ + public GQuery wrap(GQuery query) { + for (Element e : elements) { + $(e).wrapAll(query); + } + return this; + } + + /** + * Wrap each matched element with the specified HTML content. This wrapping process is most useful + * for injecting additional structure into a document, without ruining the original semantic + * qualities of a document. This works by going through the first element provided (which is + * generated, on the fly, from the provided HTML) and finds the deepest descendant element within + * its structure -- it is that element that will enwrap everything else. + */ + public GQuery wrap(String html) { + return wrap($(html)); + } + + /** + * Wrap all the elements in the matched set into a single wrapper element. This is different from + * .wrap() where each element in the matched set would get wrapped with an element. This wrapping + * process is most useful for injecting additional structure into a document, without ruining the + * original semantic qualities of a document. + * + * This works by going through the first element provided (which is generated, on the fly, from + * the provided HTML) and finds the deepest descendant element within its structure -- it is that + * element that will enwrap everything else. + */ + public GQuery wrapAll(Element elem) { + return wrapAll($(elem)); + } + + /** + * Wrap all the elements in the matched set into a single wrapper element. This is different from + * .wrap() where each element in the matched set would get wrapped with an element. This wrapping + * process is most useful for injecting additional structure into a document, without ruining the + * original semantic qualities of a document. + * + * This works by going through the first element provided (which is generated, on the fly, from + * the provided HTML) and finds the deepest descendant element within its structure -- it is that + * element that will enwrap everything else. + */ + public GQuery wrapAll(GQuery query) { + if (!isEmpty()) { + GQuery wrap = query.clone(); + if (get(0).getParentNode() != null) { + wrap.insertBefore(get(0)); + } + for (Element e : wrap.elements) { + Node n = e; + while (n.getFirstChild() != null && n.getFirstChild().getNodeType() == Node.ELEMENT_NODE) { + n = n.getFirstChild(); + } + $((Element) n).append(this); + } + } + return this; + } + + /** + * Wrap all the elements in the matched set into a single wrapper element. This is different from + * .wrap() where each element in the matched set would get wrapped with an element. This wrapping + * process is most useful for injecting additional structure into a document, without ruining the + * original semantic qualities of a document. + * + * This works by going through the first element provided (which is generated, on the fly, from + * the provided HTML) and finds the deepest descendant element within its structure -- it is that + * element that will enwrap everything else. + */ + public GQuery wrapAll(String html) { + return wrapAll($(html)); + } + + /** + * Wrap the inner child contents of each matched element (including text nodes) with an HTML + * structure. This wrapping process is most useful for injecting additional structure into a + * document, without ruining the original semantic qualities of a document. This works by going + * through the first element provided (which is generated, on the fly, from the provided HTML) and + * finds the deepest ancestor element within its structure -- it is that element that will enwrap + * everything else. + */ + public GQuery wrapInner(Element elem) { + return wrapInner($(elem)); + } + + /** + * Wrap the inner child contents of each matched element (including text nodes) with an HTML + * structure. This wrapping process is most useful for injecting additional structure into a + * document, without ruining the original semantic qualities of a document. This works by going + * through the first element provided (which is generated, on the fly, from the provided HTML) and + * finds the deepest ancestor element within its structure -- it is that element that will enwrap + * everything else. + */ + public GQuery wrapInner(GQuery query) { + for (Element e : elements) { + $(e).contents().wrapAll(query); + } + return this; + } + + /** + * Wrap the inner child contents of each matched element (including text nodes) with an HTML + * structure. This wrapping process is most useful for injecting additional structure into a + * document, without ruining the original semantic qualities of a document. This works by going + * through the first element provided (which is generated, on the fly, from the provided HTML) and + * finds the deepest ancestor element within its structure -- it is that element that will enwrap + * everything else. + */ + public GQuery wrapInner(String html) { + return wrapInner($(html)); + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Lazy.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Lazy.java index 212bc7a5..452688b1 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Lazy.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Lazy.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyBase.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyBase.java index c26dbe59..c5294aaa 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyBase.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyBase.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java index 9986d6eb..2b7c996f 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java @@ -1,11 +1,11 @@ /* * 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 @@ -67,9 +67,9 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Add elements to the set of matched elements if they are not included yet. - * + * * It construct a new GQuery object and does not modify the original ones. - * + * * It also update the selector appending the new one. */ LazyGQuery<T> add(GQuery elementsToAdd); @@ -109,55 +109,55 @@ public interface LazyGQuery<T> extends LazyBase<T>{ LazyGQuery<T> andSelf(); /** - * + * * The animate() method allows you to create animation effects on any numeric Attribute, CSS * property, or color CSS property. - * + * * Concerning to numeric properties, values are treated as a number of pixels unless otherwise * specified. The units em and % can be specified where applicable. - * + * * By default animate considers css properties, if you wanted to animate element attributes you * should to prepend the symbol dollar to the attribute name. - * + * * Example: - * + * * <pre class="code"> * //move the element from its original position to left:500px for 500ms * $("#foo").animate("left:'500'"); * // Change the width attribute of a table * $("table").animate("$width:'500'"), 400, Easing.LINEAR); * </pre> - * + * * In addition to numeric values, each property can take the strings 'show', 'hide', and 'toggle'. * These shortcuts allow for custom hiding and showing animations that take into account the * display type of the element. Animated properties can also be relative. If a value is supplied * with a leading += or -= sequence of characters, then the target value is computed by adding or * subtracting the given number from the current value of the property. - * + * * Example: - * + * * <pre class="code"> * //move the element from its original position to 500px to the left for 500ms and * // change the background color of the element at the end of the animation * $("#foo").animate("left:'+=500'", new Function(){ - * + * * public void f(Element e){ * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED); * } - * + * * }); * </pre> - * + * * The duration of the animation is 500ms. - * + * * For color css properties, values can be specified via hexadecimal or rgb or literal values. - * + * * Example: - * + * * <pre class="code"> * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'"); * </pre> - * + * * @param prop the property to animate : "cssName:'value'" * @param funcs an array of {@link Function} called once the animation is complete */ @@ -166,15 +166,15 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * The animate() method allows you to create animation effects on any numeric Attribute, CSS * property, or color CSS property. - * + * * Concerning to numeric properties, values are treated as a number of pixels unless otherwise * specified. The units em and % can be specified where applicable. - * + * * By default animate considers css properties, if you wanted to animate element attributes you * should to prepend the symbol dollar to the attribute name. - * + * * Example: - * + * * <pre class="code"> * //move the element from its original position to the position top:500px and left:500px for 400ms. * //use a swing easing function for the transition @@ -182,29 +182,29 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * // Change the width and border attributes of a table * $("table").animate(Properties.create("{$width: '500', $border: '10'}"), 400, Easing.LINEAR); * </pre> - * + * * In addition to numeric values, each property can take the strings 'show', 'hide', and 'toggle'. * These shortcuts allow for custom hiding and showing animations that take into account the * display type of the element. Animated properties can also be relative. If a value is supplied * with a leading += or -= sequence of characters, then the target value is computed by adding or * subtracting the given number from the current value of the property. - * + * * Example: - * + * * <pre class="code"> * //move the element from its original position to 500px to the left and 5OOpx down for 400ms. * //use a swing easing function for the transition * $("#foo").animate(Properties.create("{top:'+=500px',left:'+=500px'}"), 400, Easing.SWING); * </pre> - * + * * For color css properties, values can be specified via hexadecimal or rgb or literal values. - * + * * Example: - * + * * <pre class="code"> * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'"), 400, Easing.SWING); * </pre> - * + * * @param stringOrProperties a String or a {@link Properties} object containing css properties to * animate. * @param funcs an array of {@link Function} called once the animation is complete @@ -216,30 +216,30 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * The animate() method allows you to create animation effects on any numeric Attribute, CSS * properties, or color CSS property. - * + * * Concerning to numeric property, values are treated as a number of pixels unless otherwise * specified. The units em and % can be specified where applicable. - * + * * By default animate considers css properties, if you wanted to animate element attributes you * should to prepend the symbol dollar to the attribute name. - * + * * Example: - * + * * <pre class="code"> * //move the element from its original position to left:500px for 2s * $("#foo").animate("left:'500px'", 2000); * // Change the width attribute of a table * $("table").animate("$width:'500'"), 400); * </pre> - * + * * In addition to numeric values, each property can take the strings 'show', 'hide', and 'toggle'. * These shortcuts allow for custom hiding and showing animations that take into account the * display type of the element. Animated properties can also be relative. If a value is supplied * with a leading += or -= sequence of characters, then the target value is computed by adding or * subtracting the given number from the current value of the property. - * + * * Example: - * + * * <pre class="code"> * //move the element from its original position to 500px to the left for 1000ms and * // change the background color of the element at the end of the animation @@ -249,17 +249,17 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * } * }); * </pre> - * - * + * + * * For color css properties, values can be specified via hexadecimal or rgb or literal values. - * + * * Example: - * + * * <pre class="code"> * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)', 1000"); * </pre> - * - * + * + * * @param prop the property to animate : "cssName:'value'" * @param funcs an array of {@link Function} called once the animation is complete * @param duration the duration in milliseconds of the animation @@ -287,7 +287,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * All of the matched set of elements will be inserted at the end of the element(s) specified by * the parameter other. - * + * * The operation $(A).appendTo(B) is, essentially, the reverse of doing a regular $(A).append(B), * instead of appending B to A, you're appending A to B. */ @@ -296,7 +296,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * All of the matched set of elements will be inserted at the end of the element(s) specified by * the parameter other. - * + * * The operation $(A).appendTo(B) is, essentially, the reverse of doing a regular $(A).append(B), * instead of appending B to A, you're appending A to B. */ @@ -305,7 +305,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * All of the matched set of elements will be inserted at the end of the element(s) specified by * the parameter other. - * + * * The operation $(A).appendTo(B) is, essentially, the reverse of doing a regular $(A).append(B), * instead of appending B to A, you're appending A to B. */ @@ -318,7 +318,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Set a key/value object as properties to all matched elements. - * + * * Example: $("img").attr(new Properties("src: 'test.jpg', alt: 'Test Image'")) */ LazyGQuery<T> attr(Properties properties); @@ -361,43 +361,43 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Binds a set of handlers to a particular Event for each matched element. - * + * * The event handlers are passed as Functions that you can use to prevent default behavior. To * stop both default action and event bubbling, the function event handler has to return false. - * + * * You can pass an additional Object data to your Function as the second parameter - * + * */ LazyGQuery<T> bind(int eventbits, Object data, Function... funcs); /** * Binds a set of handlers to a particular Event for each matched element. - * + * * The event handlers are passed as Functions that you can use to prevent default behavior. To * stop both default action and event bubbling, the function event handler has to return false. - * - * + * + * */ LazyGQuery<T> bind(int eventbits, Function... funcs); /** * Binds a set of handlers to a particular Event for each matched element. - * + * * The event handlers are passed as Functions that you can use to prevent default behavior. To * stop both default action and event bubbling, the function event handler has to return false. - * + * * You can pass an additional Object data to your Function as the second parameter - * + * */ LazyGQuery<T> bind(String eventType, Object data, Function... funcs); /** * Binds a set of handlers to a particular Event for each matched element. - * + * * The event handlers are passed as Functions that you can use to prevent default behavior. To * stop both default action and event bubbling, the function event handler has to return false. - * - * + * + * */ LazyGQuery<T> bind(String eventType, Function... funcs); @@ -452,7 +452,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Get the first ancestor element that matches the selector (for each matched element), beginning * at the current element and progressing up through the DOM tree. - * + * * @param selector * @return */ @@ -462,9 +462,9 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * Get the first ancestor element that matches the selector (for each matched element), beginning * at the current element and progressing up through the DOM tree until reach the * <code>context</code> node. - * + * * If no context is passed in then the context of the gQuery object will be used instead. - * + * */ LazyGQuery<T> closest(String selector, Node context); @@ -473,7 +473,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * matching this selectors, beginning at the first matched element and progressing up through the * DOM. This method allows retrieving the list of ancestors matching many selectors by traversing * the DOM only one time. - * + * * @param selector * @return */ @@ -484,7 +484,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * matching this selectors, beginning at the first matched element and progressing up through the * DOM until reach the <code>context</code> node.. This method allows retrieving the list of * ancestors matching many selectors by traversing the DOM only one time. - * + * * @param selector * @return */ @@ -503,43 +503,43 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Set CSS a single style property on every matched element using type-safe enumerations. - * + * * The best way to use this method (i.e. to generate a CssSetter) is to take the desired css * property defined in {@link CSS} class and call the {@link TakesCssValue#with(HasCssName)} * method on it. - * - * + * + * * ex : - * + * * <pre class="code"> * $("#myDiv").css(CSS.TOP.with(Length.cm(15))); * $("#myDiv").css(CSS.BACKGROUND.with(RGBColor.SILVER, ImageValue.url(""), * BackgroundRepeat.NO_REPEAT, BackgroundAttachment.FIXED, * BackgroundPosition.CENTER)); * $("#myDiv").css(CSS.BACKGROUND_ATTACHMENT.with(BackgroundAttachment.FIXED)); - * + * * </pre> - * + * */ LazyGQuery<T> css(CssSetter... cssSetter); /** * Return a style property on the first matched element using type-safe enumerations. - * + * * Ex : $("#myId").css(CSS.BACKGROUND_COLOR); */ String css(HasCssValue property); /** * Return a style property on the first matched element using type-safe enumerations. - * + * * The parameter force has a special meaning here: - When force is false, returns the value of the * css property defined in the style attribute of the element. - Otherwise it returns the real * computed value. - * + * * For instance if you define 'display=none' not in the element style but in the css stylesheet, * it returns an empty string unless you pass the parameter force=true. - * + * * Ex : $("#myId").css(CSS.WIDTH, true); */ String css(HasCssValue property, boolean force); @@ -548,9 +548,9 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * Set a key/value object as style properties to all matched elements. This serves as the best way * to set a large number of style properties on all matched elements. You can use either js maps * or pure css syntax. - * + * * Example: - * + * * <pre class="code"> * $(".item").css(Properties.create("color: 'red', background:'blue'")) * $(".item").css(Properties.create("color: red; background: blue;")) @@ -565,14 +565,14 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Return a style property on the first matched element. - * + * * The parameter force has a special meaning here: * <ul> * <li>When force is false, returns the value of the css property defined in the style attribute * of the element. * <li>Otherwise it returns the real computed value. * </ul> - * + * * For instance if you don't define 'display=none'in the element style but in the css stylesheet, * it returns an empty string unless you pass the parameter force=true. */ @@ -580,16 +580,16 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Set a single style property to a value, on all matched elements. - * + * */ LazyGQuery<T> css(String prop, String val); /** * Set CSS a single style property on every matched element using type-safe enumerations. This * method allows you to set manually the value or set <i>inherit</i> value - * + * * ex : - * + * * <pre class="code"> * $(#myId).css(CSS.TEXT_DECORATION, CSS.INHERIT); * </pre> @@ -603,7 +603,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Returns the numeric value of a css property. - * + * * The parameter force has a special meaning: - When force is false, returns the value of the css * property defined in the set of style attributes. - When true returns the real computed value. */ @@ -617,7 +617,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Returns value at named data store for the element, as set by data(name, value) with desired * return type. - * + * * @param clz return type class literal */ <T> T data(String name, Class<T> clz); @@ -637,33 +637,33 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * Insert a delay (in ms) in the GQuery queue, and optionally execute one o more functions if * provided when the delay finishes. It uses the effects queue namespace, so you can stack any of * the methods in the effects plugin. - * + * * Example: - * + * * <pre class="code"> * $("#foo").slideUp(300) * .delay(800) - * .fadeIn(400); + * .fadeIn(400); * </pre> - * + * * When this statement is executed, the element slides up for 300 milliseconds and then pauses for * 800 milliseconds before fading in for 400 milliseconds. Aditionally after those 800 * milliseconds the element color is set to red. - * + * * NOTE that this methods affects only methods which uses the queue like effects. So the following * example is wrong: - * + * * <pre> - * $("#foo").css(CSS.COLOR.with(RGBColor.RED)).delay(800).css(CSS.COLOR.with(RGBColor.BLACK)); + * $("#foo").css(CSS.COLOR.with(RGBColor.RED)).delay(800).css(CSS.COLOR.with(RGBColor.BLACK)); * </pre> - * + * * The code above will not insert a delay of 800 ms between the css() calls ! For this kind of * behavior, you should execute these methods puting them in inline functions passed as argument * to the delay() method, or adding them to the queue. - * + * * <pre> - * $("#foo").css(CSS.COLOR.with(RGBColor.RED)).delay(800, lazy().css(CSS.COLOR.with(RGBColor.BLACK)).done()); - * $("#foo").css(CSS.COLOR.with(RGBColor.RED)).delay(800).queue(lazy().css(CSS.COLOR.with(RGBColor.BLACK)).dequeue().done()); + * $("#foo").css(CSS.COLOR.with(RGBColor.RED)).delay(800, lazy().css(CSS.COLOR.with(RGBColor.BLACK)).done()); + * $("#foo").css(CSS.COLOR.with(RGBColor.RED)).delay(800).queue(lazy().css(CSS.COLOR.with(RGBColor.BLACK)).dequeue().done()); * </pre> */ LazyGQuery<T> delay(int milliseconds, Function... f); @@ -671,30 +671,30 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Insert a delay (in ms) in the queue identified by the <code>queueName</code> parameter, and * optionally execute one o more functions if provided when the delay finishes. - * + * * If <code>queueName</code> is null or equats to 'fx', the delay will be inserted to the Effects * queue. - * + * * Example : - * + * * <pre class="code"> * $("#foo").queue("colorQueue", lazy().css(CSS.COLOR.with(RGBColor.RED)).dequeue("colorQueue").done()) * .delay(800, "colorQueue") - * .queue("colorQueue", lazy().css(CSS.COLOR.with(RGBColor.BLACK)).dequeue("colorQueue").done()); + * .queue("colorQueue", lazy().css(CSS.COLOR.with(RGBColor.BLACK)).dequeue("colorQueue").done()); * </pre> - * + * * When this statement is executed, the text color of the element changes to red and then wait for * 800 milliseconds before changes the text color to black. - * + * */ LazyGQuery<T> delay(int milliseconds, String queueName, Function... f); /** * Attach <code>handlers</code> to one or more events for all elements that match the * <code>selector</code>, now or in the future, based on a specific set of root elements. - * + * * Example: - * + * * <pre> * $("table").delegate("td", Event.ONCLICK, new Function(){ * public void f(Element e){ @@ -702,10 +702,10 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * } * }); * </pre> - * + * * This code above add an handler on click event on all cell (the existing oneand the future cell) * of all table. This code is equivalent to : - * + * * <pre> * $("table").each(new Function(){ * public void f(Element table){ @@ -717,9 +717,9 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * }); * * </pre> - * + * * You can attach the handlers to many events by using the '|' operator ex: - * + * * <pre> * $("div.main").delegate(".subMain", Event.ONCLICK | Event.ONDBLCLICK, new Function(){...}); * </pre> @@ -730,9 +730,9 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * Attach <code>handlers</code> to one or more events for all elements that match the * <code>selector</code>, now or in the future, based on a specific set of root elements. The * <code>data</code> parameter allows us to pass data to the handler. - * + * * Example: - * + * * <pre> * $("table").delegate("td", "click", new Function(){ * public void f(Element e){ @@ -740,10 +740,10 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * } * }); * </pre> - * + * * This code above add an handler on click event on all cell (the existing oneand the future cell) * of all table. This code is equivalent to : - * + * * <pre> * $("table").each(new Function(){ * public void f(Element table){ @@ -755,9 +755,9 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * }); * * </pre> - * + * * You can pass attach the handlers to many events by using the '|' operator ex: - * + * * <pre> * $("div.main").delegate(".subMain", Event.ONCLICK | Event.ONDBLCLICK, new Function(){...}); * </pre> @@ -767,9 +767,9 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Attach <code>handlers</code> to one or more events for all elements that match the * <code>selector</code>, now or in the future, based on a specific set of root elements. - * + * * Example: - * + * * <pre> * $("table").delegate("td", "click", new Function(){ * public void f(Element e){ @@ -777,10 +777,10 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * } * }); * </pre> - * + * * This code above add an handler on click event on all cell (the existing oneand the future cell) * of all table. This code is equivalent to : - * + * * <pre> * $("table").each(new Function(){ * public void f(Element table){ @@ -792,14 +792,14 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * }); * * </pre> - * + * * You can pass attach the handlers to many events by specifying a String with espaced event type. * ex: - * + * * <pre> * $("div.main").delegate(".subMain", "click dblclick", new Function(){...}); * </pre> - * + * * </pre> */ LazyGQuery<T> delegate(String selector, String eventType, Function... handlers); @@ -807,9 +807,9 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Attach <code>handlers</code> to one or more events for all elements that match the * <code>selector</code>, now or in the future, based on a specific set of root elements. - * + * * Example: - * + * * <pre> * $("table").delegate("td", "click", new Function(){ * public void f(Element e){ @@ -817,10 +817,10 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * } * }); * </pre> - * + * * This code above add an handler on click event on all cell (the existing oneand the future cell) * of all table. This code is equivalent to : - * + * * <pre> * $("table").each(new Function(){ * public void f(Element table){ @@ -833,11 +833,11 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * * You can pass attach the handlers to many events by specifying a String with espaced event type. * ex: - * + * * <pre> * $("div.main").delegate(".subMain", "click dblclick", new Function(){...}); * </pre> - * + * * </pre> */ LazyGQuery<T> delegate(String selector, String eventType, Object data, Function... handlers); @@ -846,7 +846,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * Execute the next function on the Effects queue for the matched elements. This method is usefull * to tell when a function you add in the Effects queue is ended and so the next function in the * queue can start. - * + * * Note: you should be sure to call dequeue() in all functions of a queue chain, otherwise the * queue execution will be stopped. */ @@ -923,13 +923,13 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Reduce GQuery to element in the specified position. This method accept negative index. A * negative index is counted from the end of the matched set: - * + * * Example: - * + * * <pre> * $("div").eq(0) will reduce the matched set to the first matched div * $("div").eq(1) will reduce the matched set to the second matched div - * + * * $("div").eq(-1) will reduce the matched set to the last matched div * $("div").eq(-2) will reduce the matched set to the second-to-last matched div * ... @@ -988,7 +988,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Searches for all elements that match the specified css expression. This method is a good way to * find additional descendant elements with which to process. - * + * * Provide a comma-separated list of expressions to apply multiple filters at once. */ LazyGQuery<T> find(String... filters); @@ -1013,13 +1013,13 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Return the ith element matched. This method accept negative index. A negative index is counted * from the end of the matched set. - * + * * Example: - * + * * <pre> * $("div").get(0) will return the first matched div * $("div").get(1) will return the second matched div - * + * * $("div").get(-1) will return the last matched div * $("div").get(-2) will return the secont-to-last matched div * ... @@ -1147,7 +1147,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Insert all of the matched elements before another, specified, set of elements. - * + * * The elements must already be inserted into the document (you can't insert an element after * another if it's not in the page). */ @@ -1155,7 +1155,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Insert all of the matched elements before another, specified, set of elements. - * + * * The elements must already be inserted into the document (you can't insert an element after * another if it's not in the page). */ @@ -1163,7 +1163,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Insert all of the matched elements before another, specified, set of elements. - * + * * The elements must already be inserted into the document (you can't insert an element after * another if it's not in the page). */ @@ -1253,7 +1253,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * <p> * <p> * Ex : - * + * * <pre> * $(".clickable").live("click", new Function(){ * public void f(Element e){ @@ -1261,15 +1261,15 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * } * }); * </pre> - * + * * With this code, all elements with class "clickable" present in the DOM or added to the DOM in * the future will be clickable. The text color will be changed to red when they will be clicked. * So if after in the code, you add another element : - * + * * <pre> * $("body").append("<div class='clickable'>Click me and I will be red</div>"); * </pre> - * + * * The click on this new element will also trigger the handler. * </p> * <p> @@ -1283,7 +1283,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * The live method should be always called after a selector</li> * <li> * Live events are bound to the context of the {@link GQuery} object : - * + * * <pre> * $(".clickable", myElement).live("click", new Function(){ * public void f(Element e){ @@ -1305,7 +1305,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * <p> * <p> * Ex : - * + * * <pre> * $(".clickable").live("click", new Function(){ * public void f(Element e){ @@ -1313,15 +1313,15 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * } * }); * </pre> - * + * * With this code, all elements with class "clickable" present in the DOM or added to the DOM in * the future will be clickable. The text color will be changed to red when they will be clicked. * So if after in the code, you add another element : - * + * * <pre> * $("body").append("<div class='clickable'>Click me and I will be red</div>"); * </pre> - * + * * The click on this new element will also trigger the handler. * </p> * <p> @@ -1335,7 +1335,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * The live method should be always called after a selector</li> * <li> * Live events are bound to the context of the {@link GQuery} object : - * + * * <pre> * $(".clickable", myElement).live("click", new Function(){ * public void f(Element e){ @@ -1352,23 +1352,23 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Load data from the server and place the returned HTML into the matched element. - * + * * The url allows us to specify a portion of the remote document to be inserted. This is achieved * with a special syntax for the url parameter. If one or more space characters are included in * the string, the portion of the string following the first space is assumed to be a GQuery * selector that determines the content to be loaded. - * + * */ LazyGQuery<T> load(String url); /** * Load data from the server and place the returned HTML into the matched element. - * + * * The url allows us to specify a portion of the remote document to be inserted. This is achieved * with a special syntax for the url parameter. If one or more space characters are included in * the string, the portion of the string following the first space is assumed to be a GQuery * selector that determines the content to be loaded. - * + * */ LazyGQuery<T> load(String url, Properties data, Function onSuccess); @@ -1394,7 +1394,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Bind an event handler to be fired when the mouse enter an element, or trigger that handler on * an element if no functions are provided. - * + * * The mouseenter event differs from mouseover in the way it handles event bubbling. When * mouseover is used on an element having inner element(s), then when the mouse pointer moves hover * of the Inner element, the handler would be triggered. This is usually undesirable behavior. The @@ -1406,7 +1406,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Bind an event handler to be fired when the mouse leaves an element, or trigger that handler on * an element if no functions are provided. - * + * * The mouseleave event differs from mouseout in the way it handles event bubbling. When * mouseout is used on an element having inner element(s), then when the mouse pointer moves out * of the Inner element, the handler would be triggered. This is usually undesirable behavior. The @@ -1466,7 +1466,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Get all following siblings of each element up to but not including the element matched by the * selector. - * + * * @param selector * @return */ @@ -1475,7 +1475,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Get all following siblings of each element up to but not including the element matched by the * selector, filtered by a selector. - * + * * @param selector * @return */ @@ -1484,7 +1484,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Get all following siblings of each element up to but not including the element matched by the * DOM node. - * + * * @param selector * @return */ @@ -1493,7 +1493,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Get all following siblings of each element up to but not including the element matched by the * DOM node, filtered by a selector. - * + * * @param selector * @return */ @@ -1502,7 +1502,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Get all following siblings of each element up to but not including the element matched by the * GQuery object. - * + * * @param selector * @return */ @@ -1511,7 +1511,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Get all following siblings of each element up to but not including the element matched by the * GQuery object, filtered by a selector - * + * * @param selector * @return */ @@ -1550,10 +1550,10 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Binds a handler to a particular Event (like Event.ONCLICK) for each matched element. The * handler is executed only once for each element. - * + * * The event handler is passed as a Function that you can use to prevent default behavior. To stop * both default action and event bubbling, the function event handler has to return false. - * + * * You can pass an additional Object data to your Function as the second parameter */ LazyGQuery<T> one(int eventbits, Object data, Function f); @@ -1609,7 +1609,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Get the ancestors of each element in the current set of matched elements, up to but not * including the element matched by the selector. - * + * */ LazyGQuery<T> parentsUntil(String selector); @@ -1641,7 +1641,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * All of the matched set of elements will be inserted at the beginning of the element(s) * specified by the parameter other. - * + * * The operation $(A).prependTo(B) is, essentially, the reverse of doing a regular * $(A).prepend(B), instead of prepending B to A, you're prepending A to B. */ @@ -1650,7 +1650,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * All of the matched set of elements will be inserted at the beginning of the element(s) * specified by the parameter other. - * + * * The operation $(A).prependTo(B) is, essentially, the reverse of doing a regular * $(A).prepend(B), instead of prepending B to A, you're prepending A to B. */ @@ -1659,7 +1659,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * All of the matched set of elements will be inserted at the beginning of the element(s) * specified by the parameter other. - * + * * The operation $(A).prependTo(B) is, essentially, the reverse of doing a regular * $(A).prepend(B), instead of prepending B to A, you're prepending A to B. */ @@ -1692,7 +1692,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Get all preceding siblings of each element up to but not including the element matched by the * <code>selector</code>. - * + * * The elements are returned in order from the closest sibling to the farthest. */ LazyGQuery<T> prevUntil(String selector); @@ -1700,7 +1700,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Get all preceding siblings of each element up to but not including the <code>until</code> * element. - * + * * The elements are returned in order from the closest sibling to the farthest. */ LazyGQuery<T> prevUntil(Element until); @@ -1708,7 +1708,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Get all preceding siblings of each element up to but not including the <code>until</code> * element. - * + * * The elements are returned in order from the closest sibling to the farthest. */ LazyGQuery<T> prevUntil(GQuery until); @@ -1716,7 +1716,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Get all preceding siblings of each element matching the <code>filter</code> up to but not * including the element matched by the <code>selector</code>. - * + * * The elements are returned in order from the closest sibling to the farthest. */ LazyGQuery<T> prevUntil(String selector, String filter); @@ -1724,42 +1724,42 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Get all preceding siblings of each element matching the <code>filter</code> up to but not * including the <code>until</code> element. - * + * */ LazyGQuery<T> prevUntil(Element until, String filter); /** * Get all preceding siblings of each element matching the <code>filter</code> up to but not * including the element matched by the <code>until</code> element. - * + * */ LazyGQuery<T> prevUntil(GQuery until, String filter); /** * Accesses a boolean property on the first matched element. - * + * * @param key the name of the boolean property to be accessed - * + * * @return <code>true</code> if at least one element is matched and the specified boolean property * is set to <code>true</code> on the first matched element; <code>false</code> otherwise - * + * */ boolean prop(String key); /** * Sets a boolean property to a value on all matched elements. - * + * * @param key the name of the boolean property to be set * @param value the value the specified boolean property should be set to - * + * * @return this <code>GQuery</code> object - * + * */ LazyGQuery<T> prop(String key, boolean value); /** * Sets a boolean property to a computed value on all matched elements. - * + * * @param key the name of the boolean property to be set * @param closure the closure to be used to compute the value the specified boolean property * should be set to; the <code>closure</code> is @@ -1767,9 +1767,9 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * element and its index as arguments and is expected to return either a * <code>Boolean</code> value or an object whose textual representation is converted to a * <code>Boolean</code> value; <code>null</code> return values are ignored - * + * * @return this <code>GQuery</code> object - * + * */ LazyGQuery<T> prop(String key, Function closure); @@ -1780,26 +1780,26 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Put a set of {@link Function} at the end of the Effects queue. - * + * * Example: - * + * * <pre class="code"> * $("#foo").animate("left:'+=500'", 400) * .queue(new Function(){ * public void f(Element e){ * $(e).css(CSS.BACKGROUNG_COLOR.with(RGBColor.RED)); - * $(e).dequeue(); + * $(e).dequeue(); * } * }) * .animate("left:'-=500'", 400) * .queue(lazy().css("color", "yellow"); - * + * * </pre> - * + * * When this statement is executed, the element move to 500 px to left for 400 ms, then its * background color is changed to red and then move to 500px to right for 400ms, and finally its * color is set to yellow. - * + * * Please note that {@link #dequeue()} function is needed at the end of your function to start the * next function in the queue. In lazy() methods you should call dequeue() just before the done() * call. {@see #dequeue()} @@ -1814,9 +1814,9 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Put a set of {@link Function} at the end of a queue. - * + * * Example: - * + * * <pre class="code"> * $("#foo").queue("myQueue", new Function(){ * public void f(Element e){ @@ -1827,10 +1827,10 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * .delay(500, "myQueue") * .queue("myQueue", lazy().css(CSS.COLOR.with(RGBColor.YELLOW)).dequeue("myQueue").done()); * </pre> - * + * * When this statement is executed, the background color of the element is set to red, then wait * 500ms before to set the text color of the element to yellow. right for 400ms. - * + * * Please note that {@link #dequeue()} function is needed at the end of your function to start the * next function in the queue. In lazy() methods you should call dequeue() just before the done() * call. {@see #dequeue()} @@ -1854,7 +1854,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Removes the specified classes to each matched element. - * + * * If no arguments are provided, it removes all classes like jquery does. */ LazyGQuery<T> removeClass(String... classes); @@ -1868,7 +1868,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * Replaces the element <code>elem</code> by the specified selector with the matched elements. * This function is the complement to replaceWith() which does the same task with the parameters * reversed. - * + * * @return a {@link GQuery} object containing the new elements. */ LazyGQuery<T> replaceAll(Element elem); @@ -1876,7 +1876,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Replaces the elements matched by the target with the selected elements. This function is the * complement to replaceWith() which does the same task with the parameters reversed. - * + * * @return a {@link GQuery} object containing the new elements. */ LazyGQuery<T> replaceAll(GQuery target); @@ -1885,14 +1885,14 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * Replaces the elements matched by the specified selector with the matched elements. This * function is the complement to replaceWith() which does the same task with the parameters * reversed. - * + * * @return a {@link GQuery} object containing the new elements. */ LazyGQuery<T> replaceAll(String selector); /** * Replaces all matched elements with the specified element. - * + * * @return the GQuery element that was just replaced, which has been removed from the DOM and not * the new element that has replaced it. */ @@ -1900,7 +1900,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Replaces all matched elements with elements selected by <code>target</code> . - * + * * @return the GQuery element that was just replaced, which has been removed from the DOM and not * the new element that has replaced it. */ @@ -1908,7 +1908,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Replaces all matched elements with the specified HTML. - * + * * @return the GQuery element that was just replaced, which has been removed from the DOM and not * the new element that has replaced it. */ @@ -1917,11 +1917,11 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Bind a set of functions to the resize event of each matched element, or tigger the resize event * if no functions are provided. - * + * * Note that although all elements can be configured to handle resize events, by default only * window will trigger it when it is resized, for an arbitrary element you have to trigger the * event after resizing the object. - * + * */ LazyGQuery<T> resize(Function... f); @@ -1953,7 +1953,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Scrolls the first matched element into view. - * + * * If ensure == true, it crawls up the DOM hierarchy, adjusting the scrollLeft and scrollTop * properties of each scroll-able element to ensure that the specified element is completely in * view. It adjusts each scroll position by the minimum amount necessary. @@ -1973,14 +1973,14 @@ public interface LazyGQuery<T> extends LazyBase<T>{ LazyGQuery<T> scrollLeft(int left); /** - * + * * Scrolls the contents of all matched elements to the specified co-ordinate becoming the top left * corner of the viewable area. - * + * * This method is only useful where there are areas of the document not viewable within the * current viewable area of the window and the visible property of the window's scrollbar must be * set to true. - * + * */ LazyGQuery<T> scrollTo(int left, int top); @@ -2078,7 +2078,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * stopped. If, for instance, an element is being hidden with .slideUp() when .stop() is called, * the element will now still be displayed, but will be a fraction of its previous height. * Callback functions are not called but the next animation in the queue begins immediately. - * + * * If the clearQueue parameter is provided with a value of true, then the rest of the animations * in the queue are removed and never run. */ @@ -2089,10 +2089,10 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * stopped. If, for instance, an element is being hidden with .slideUp() when .stop() is called, * the element will now still be displayed, but will be a fraction of its previous height. * Callback functions are not called but the next animation in the queue begins immediately. - * + * * If the clearQueue parameter is provided with a value of true, then the rest of the animations * in the queue are removed and never run. - * + * * If the jumpToEnd property is provided with a value of true, the current animation stops, but * the element is immediately given its target values for each CSS property. The callback * functions are then immediately called, if provided. @@ -2134,7 +2134,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Adds or removes the specified classes to each matched element depending on the value of the * switch argument. - * + * * if addOrRemove is true, the class is added and in the case of false it is removed. */ LazyGQuery<T> toggleClass(String clz, boolean addOrRemove); @@ -2156,10 +2156,10 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Trigger a set of events on each matched element. - * + * * For keyboard events you can pass a second parameter which represents the key-code of the pushed * key. - * + * * Example: fire(Event.ONCLICK | Event.ONFOCUS) Example: fire(Event.ONKEYDOWN. 'a'); */ LazyGQuery<T> trigger(int eventbits, int... keys); @@ -2217,7 +2217,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * This method removes the element's parent. The matched elements replaces their parents within * the DOM structure. It is the inverse of {@link GQuery#wrap(GQuery)} method - * + * * @return */ LazyGQuery<T> unwrap(); @@ -2226,10 +2226,10 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * Gets the content of the value attribute of the first matched element, returns only the first * value even if it is a multivalued element. To get an array of all values in multivalues * elements use vals() - * + * * When the first element is a radio-button and is not checked, then it looks for the first * checked radio-button that has the same name in the list of matched elements. - * + * * When there are not matched elements it returns null. */ String val(); @@ -2237,7 +2237,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Sets the value attribute of every matched element based in the return value of the function * evaluated for this element. - * + * * NOTE: in jquery the function receives the arguments in different way, first index and them the * actual value, but we use the normal way in gquery Function, first the element and second the * index. @@ -2247,7 +2247,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Sets the 'value' attribute of every matched element, but does not set the checked flag to * checkboxes or radiobuttons. - * + * * If you wanted to set values in collections of checkboxes o radiobuttons use val(String[]) * instead */ @@ -2255,7 +2255,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Sets the value of every matched element. - * + * * There is a different behaviour depending on the element type: * <ul> * <li>select multiple: options whose value match any of the passed values will be set. @@ -2265,10 +2265,10 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * <li>textarea, button, and other input: value will set to a string result of joining with coma, * all passed values * </ul> - * + * * NOTE: if you wanted call this function with just one parameter, you have to pass an array * signature to avoid call the overloaded val(String) method: - * + * * $(...).val(new String[]{"value"}); */ LazyGQuery<T> val(String... values); @@ -2276,10 +2276,10 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Gets the content of the value attribute of the first matched element, returns more than one * value if it is a multiple select. - * + * * When the first element is a radio-button and is not checked, then it looks for a the first * checked radio-button that has the same name in the list of matched elements. - * + * * This method always returns an array. If no valid value can be determined the array will be * empty, otherwise it will contain one or more values. */ @@ -2302,10 +2302,10 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Return the list of attached widgets instance of the provided class matching the query. - * + * * This method is very useful for decoupled views, so as we can access widgets from other views * without maintaining methods which export them. - * + * */ <W extends Widget> List<W> widgets(Class<W> clazz); @@ -2352,7 +2352,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * .wrap() where each element in the matched set would get wrapped with an element. This wrapping * process is most useful for injecting additional structure into a document, without ruining the * original semantic qualities of a document. - * + * * This works by going through the first element provided (which is generated, on the fly, from * the provided HTML) and finds the deepest descendant element within its structure -- it is that * element that will enwrap everything else. @@ -2364,7 +2364,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * .wrap() where each element in the matched set would get wrapped with an element. This wrapping * process is most useful for injecting additional structure into a document, without ruining the * original semantic qualities of a document. - * + * * This works by going through the first element provided (which is generated, on the fly, from * the provided HTML) and finds the deepest descendant element within its structure -- it is that * element that will enwrap everything else. @@ -2376,7 +2376,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * .wrap() where each element in the matched set would get wrapped with an element. This wrapping * process is most useful for injecting additional structure into a document, without ruining the * original semantic qualities of a document. - * + * * This works by going through the first element provided (which is generated, on the fly, from * the provided HTML) and finds the deepest descendant element within its structure -- it is that * element that will enwrap everything else. diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Predicate.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Predicate.java index 268fa397..262e31fb 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Predicate.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Predicate.java @@ -1,12 +1,12 @@ /* * 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 @@ -25,19 +25,19 @@ public class Predicate { /** * Used by GQuery methods which loop over matched widgets and * invoke a callback on each widget expecting a boolean value. - * - * @param e - * the element for this call - * @param index - * the element position in the gquery elements array. + * + * @param e + * the element for this call + * @param index + * the element position in the gquery elements array. */ public boolean f(Element e, int index) { return f((Object)e, index); } - + public <T> boolean f(T e, int index) { return false; } - - + + } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java index 04f32985..4a2597a9 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java @@ -1,187 +1,187 @@ -/*
- * 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 com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArrayMixed;
-import com.google.gwt.query.client.js.JsCache;
-import com.google.gwt.query.client.js.JsUtils;
-
-/**
- * JSO for accessing Javascript objective literals used by GwtQuery functions.
- */
-public class Properties extends JavaScriptObject {
-
- public static Properties create() {
- return JsCache.create().cast();
- }
-
- public static Properties create(String properties) {
- if (properties != null && !properties.isEmpty()) {
- String p = wrapPropertiesString(properties);
- try {
- return JsUtils.parseJSON(p);
- } catch (Exception e) {
- System.err.println("Error creating Properties: \n> " + properties + "\n< " + p + "\n" + e.getMessage());
- }
- }
- return create();
- }
-
- public static String wrapPropertiesString(String s) {
- String ret = s //
- .replaceAll("\\s*/\\*[\\s\\S]*?\\*/\\s*", "") // Remove comments
- .replaceAll("([:\\)\\(,;}{'\"])\\s+" , "$1") // Remove spaces
- .replaceAll("\\s+([:\\)\\(,;}{'\"])" , "$1") // Remove spaces
- .replaceFirst("^[\\(]+(.*)[\\)]+$", "$1") // Remove ()
- .replaceAll("\\([\"']([^\\)]+)[\"']\\)" , "($1)") // Remove quotes
- .replaceAll("[;,]+([\\w-\\$]+):", ";$1:") // Change comma by semicolon
- .replaceAll("([^,;])([\\]}])", "$1;$2") // Put control semicolon used below
- .replaceAll(":\\s*[\"']?([^;\\{\\}\\[\\]\"']*)[\"']?\\s*([;,]+|$)", ":\"$1\";") // put quotes to all values (even empty)
- .replaceAll("[;,]+([\\w-]+):", ";$1:") // Change semicolon by comma
- .replaceAll("(^|[^\\w-\\$'])([\\w-\\$]+):(['\"\\[{])", "$1\"$2\":$3") // quote keys
- .replaceAll("(^|[^\\w-\\$'])([\\w-\\$]+):(['\"\\[{])", "$1\"$2\":$3") // quote keys second pass
- .replaceAll("(|[\\[\\]\\{\\},\\(])'([^']*)'", "$1\"$2\"") // Replace single-quote by double-quote
- .replaceAll(";([^:]+):", ",$1:") // change semicolon
- .replaceAll(";([^:]+):", ",$1:") // change semicolon second pass
- .replaceAll(":\"(-?\\d[\\d\\.]*|null|false|true)\"[;,]", ":$1,") // numbers do not need quote
- .replaceAll("[;,]+([\\]\\}]|$)", "$1") // remove endings
- ;
- ret = ret.matches("(^[\\[\\{].*[\\]\\}]$)") ? ret : "{" + ret + "}";
- return ret;
- }
-
- protected Properties() {
- }
-
- public final Properties $$(String key, String value) {
- set(key, value);
- return this;
- }
-
- private JsCache c() {
- return this.<JsCache>cast();
- }
-
- public final native Properties cloneProps() /*-{
- var props = {};
- for(p in this) {
- props[p] = this[p];
- }
- return props;
- }-*/;
-
- public final boolean defined(Object name) {
- return c().exists(String.valueOf(name));
- }
-
- @SuppressWarnings("unchecked")
- public final <T> T get(Object name) {
- // Casting because of issue_135
- return (T)c().get(String.valueOf(name));
- }
-
- public final boolean getBoolean(Object name) {
- return c().getBoolean(String.valueOf(name));
- }
-
- public final float getFloat(Object name) {
- return c().getFloat(String.valueOf(name));
- }
-
- public final Function getFunction(Object name) {
- final Object o = c().get(String.valueOf(name));
- if (o != null) {
- if (o instanceof Function) {
- return (Function)o;
- } else if (o instanceof JavaScriptObject) {
- Object f = ((JavaScriptObject)o).<Properties>cast().getObject("__f");
- if (f != null && f instanceof Function) {
- return (Function) f;
- }
- return new JsUtils.JsFunction((JavaScriptObject)o);
- }
- }
- return null;
- }
-
- public final int getInt(Object name) {
- return c().getInt(String.valueOf(name));
- }
-
- public final String getStr(Object name) {
- return c().getString(String.valueOf(name));
- }
-
- public final Object getObject(Object name) {
- return c().get(String.valueOf(name));
- }
-
- @SuppressWarnings("unchecked")
- public final <T extends JavaScriptObject> T getJavaScriptObject(Object name) {
- // Casting because of issue_135
- return (T)c().getJavaScriptObject(String.valueOf(name));
- }
-
- public final JsArrayMixed getArray(Object name) {
- return c().getArray(String.valueOf(name));
- }
-
- public final String[] keys() {
- return c().keys();
- }
-
- public final <T> void remove(T name) {
- c().delete(String.valueOf(name));
- }
-
- public final <T> void setNumber(T name, double val) {
- c().putNumber(name, val);
- }
-
- public final <T> void setBoolean(T name, boolean val) {
- c().putBoolean(name, val);
- }
-
- public final native <T> void setFunction(T name, Function f) /*-{
- this[name] = function() {
- f.@com.google.gwt.query.client.Function::fe(Ljava/lang/Object;)(arguments);
- }
- // We store the original function reference
- this[name].__f = f;
- }-*/;
-
- public final <T, O> void set(T name, O val) {
- c().put(String.valueOf(name), val);
- }
-
- public final String tostring() {
- return toJsonString();
- }
-
- public final String toJsonString() {
- return JsUtils.JSON2String(JsCache.checkNull(this));
- }
-
- public final String toQueryString() {
- return JsUtils.param(JsCache.checkNull(this));
- }
-
- public final boolean isEmpty(){
- return c().length() == 0;
- }
-
-}
+/* + * 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 com.google.gwt.core.client.JavaScriptObject; +import com.google.gwt.core.client.JsArrayMixed; +import com.google.gwt.query.client.js.JsCache; +import com.google.gwt.query.client.js.JsUtils; + +/** + * JSO for accessing Javascript objective literals used by GwtQuery functions. + */ +public class Properties extends JavaScriptObject { + + public static Properties create() { + return JsCache.create().cast(); + } + + public static Properties create(String properties) { + if (properties != null && !properties.isEmpty()) { + String p = wrapPropertiesString(properties); + try { + return JsUtils.parseJSON(p); + } catch (Exception e) { + System.err.println("Error creating Properties: \n> " + properties + "\n< " + p + "\n" + e.getMessage()); + } + } + return create(); + } + + public static String wrapPropertiesString(String s) { + String ret = s // + .replaceAll("\\s*/\\*[\\s\\S]*?\\*/\\s*", "") // Remove comments + .replaceAll("([:\\)\\(,;}{'\"])\\s+" , "$1") // Remove spaces + .replaceAll("\\s+([:\\)\\(,;}{'\"])" , "$1") // Remove spaces + .replaceFirst("^[\\(]+(.*)[\\)]+$", "$1") // Remove () + .replaceAll("\\([\"']([^\\)]+)[\"']\\)" , "($1)") // Remove quotes + .replaceAll("[;,]+([\\w-\\$]+):", ";$1:") // Change comma by semicolon + .replaceAll("([^,;])([\\]}])", "$1;$2") // Put control semicolon used below + .replaceAll(":\\s*[\"']?([^;\\{\\}\\[\\]\"']*)[\"']?\\s*([;,]+|$)", ":\"$1\";") // put quotes to all values (even empty) + .replaceAll("[;,]+([\\w-]+):", ";$1:") // Change semicolon by comma + .replaceAll("(^|[^\\w-\\$'])([\\w-\\$]+):(['\"\\[{])", "$1\"$2\":$3") // quote keys + .replaceAll("(^|[^\\w-\\$'])([\\w-\\$]+):(['\"\\[{])", "$1\"$2\":$3") // quote keys second pass + .replaceAll("(|[\\[\\]\\{\\},\\(])'([^']*)'", "$1\"$2\"") // Replace single-quote by double-quote + .replaceAll(";([^:]+):", ",$1:") // change semicolon + .replaceAll(";([^:]+):", ",$1:") // change semicolon second pass + .replaceAll(":\"(-?\\d[\\d\\.]*|null|false|true)\"[;,]", ":$1,") // numbers do not need quote + .replaceAll("[;,]+([\\]\\}]|$)", "$1") // remove endings + ; + ret = ret.matches("(^[\\[\\{].*[\\]\\}]$)") ? ret : "{" + ret + "}"; + return ret; + } + + protected Properties() { + } + + public final Properties $$(String key, String value) { + set(key, value); + return this; + } + + private JsCache c() { + return this.<JsCache>cast(); + } + + public final native Properties cloneProps() /*-{ + var props = {}; + for(p in this) { + props[p] = this[p]; + } + return props; + }-*/; + + public final boolean defined(Object name) { + return c().exists(String.valueOf(name)); + } + + @SuppressWarnings("unchecked") + public final <T> T get(Object name) { + // Casting because of issue_135 + return (T)c().get(String.valueOf(name)); + } + + public final boolean getBoolean(Object name) { + return c().getBoolean(String.valueOf(name)); + } + + public final float getFloat(Object name) { + return c().getFloat(String.valueOf(name)); + } + + public final Function getFunction(Object name) { + final Object o = c().get(String.valueOf(name)); + if (o != null) { + if (o instanceof Function) { + return (Function)o; + } else if (o instanceof JavaScriptObject) { + Object f = ((JavaScriptObject)o).<Properties>cast().getObject("__f"); + if (f != null && f instanceof Function) { + return (Function) f; + } + return new JsUtils.JsFunction((JavaScriptObject)o); + } + } + return null; + } + + public final int getInt(Object name) { + return c().getInt(String.valueOf(name)); + } + + public final String getStr(Object name) { + return c().getString(String.valueOf(name)); + } + + public final Object getObject(Object name) { + return c().get(String.valueOf(name)); + } + + @SuppressWarnings("unchecked") + public final <T extends JavaScriptObject> T getJavaScriptObject(Object name) { + // Casting because of issue_135 + return (T)c().getJavaScriptObject(String.valueOf(name)); + } + + public final JsArrayMixed getArray(Object name) { + return c().getArray(String.valueOf(name)); + } + + public final String[] keys() { + return c().keys(); + } + + public final <T> void remove(T name) { + c().delete(String.valueOf(name)); + } + + public final <T> void setNumber(T name, double val) { + c().putNumber(name, val); + } + + public final <T> void setBoolean(T name, boolean val) { + c().putBoolean(name, val); + } + + public final native <T> void setFunction(T name, Function f) /*-{ + this[name] = function() { + f.@com.google.gwt.query.client.Function::fe(Ljava/lang/Object;)(arguments); + } + // We store the original function reference + this[name].__f = f; + }-*/; + + public final <T, O> void set(T name, O val) { + c().put(String.valueOf(name), val); + } + + public final String tostring() { + return toJsonString(); + } + + public final String toJsonString() { + return JsUtils.JSON2String(JsCache.checkNull(this)); + } + + public final String toQueryString() { + return JsUtils.param(JsCache.checkNull(this)); + } + + public final boolean isEmpty(){ + return c().length() == 0; + } + +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Selector.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Selector.java index 0305ce9e..fbdcff73 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Selector.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Selector.java @@ -1,31 +1,31 @@ -/*
- * 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 java.lang.annotation.ElementType.METHOD;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Used to pass a CSS Selector to a generator at compile time
- */
-@Target({METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Selector {
-
- String value();
-}
+/* + * 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 java.lang.annotation.ElementType.METHOD; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used to pass a CSS Selector to a generator at compile time + */ +@Target({METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Selector { + + String value(); +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Selectors.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Selectors.java index b14021bb..6c44caed 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Selectors.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Selectors.java @@ -1,72 +1,72 @@ -/*
- * 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 com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Node;
-import com.google.gwt.dom.client.NodeList;
-
-/**
- * Tagging interface used to generate compile time selectors.
- */
-public interface Selectors {
-
- /**
- * A compiled selector that can be lazily turned into a GQuery.
- */
- public interface DeferredSelector {
-
- /**
- * Evaluate the compiled selector with the given DOM node as a context.
- *
- * Returns a NodeList as a result which you could transform into a GQuery
- * object passing it as argument to the $() function.
- */
- NodeList<Element> runSelector(Node ctx);
-
- /**
- * The selector which was compiled.
- */
- String getSelector();
- }
-
- /**
- * Return all the selectors defined for this interface, so as
- * we can get the css representation of each one and lazily evaluate it
- * in runtime.
- */
- DeferredSelector[] getAllSelectors();
-
- /**
- * Set the context for all the selectors.
- * By default they are evaluated in all the document.
- */
- public void setRoot(Node node);
-
- /**
- * Get the configured root context.
- */
- public Node getRoot();
-
- /**
- * Used for benchmarking purposes, it returns true if the selector engine
- * for this browser is using a pure javascript implementation or a native
- * one.
- *
- * It is useful to check if IE8 native selectors are being used.
- */
- public boolean isDegradated();
-}
+/* + * 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 com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.Node; +import com.google.gwt.dom.client.NodeList; + +/** + * Tagging interface used to generate compile time selectors. + */ +public interface Selectors { + + /** + * A compiled selector that can be lazily turned into a GQuery. + */ + public interface DeferredSelector { + + /** + * Evaluate the compiled selector with the given DOM node as a context. + * + * Returns a NodeList as a result which you could transform into a GQuery + * object passing it as argument to the $() function. + */ + NodeList<Element> runSelector(Node ctx); + + /** + * The selector which was compiled. + */ + String getSelector(); + } + + /** + * Return all the selectors defined for this interface, so as + * we can get the css representation of each one and lazily evaluate it + * in runtime. + */ + DeferredSelector[] getAllSelectors(); + + /** + * Set the context for all the selectors. + * By default they are evaluated in all the document. + */ + public void setRoot(Node node); + + /** + * Get the configured root context. + */ + public Node getRoot(); + + /** + * Used for benchmarking purposes, it returns true if the selector engine + * for this browser is using a pure javascript implementation or a native + * one. + * + * It is useful to check if IE8 native selectors are being used. + */ + public boolean isDegradated(); +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilder.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilder.java index 8850148f..41a7171c 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilder.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilder.java @@ -1,61 +1,61 @@ -/*
- * 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.builders;
-
-import com.google.gwt.query.client.Properties;
-
-/**
- * Tagging interface used to generate JsonBuilder classes.
- */
-public interface JsonBuilder {
-
- /**
- * load a properties object.
- */
- <J> J load(Object prp);
-
- /**
- * parses a json string and loads the resulting properties object.
- */
- <J> J parse(String json);
-
- /**
- * parses a json string and loads the resulting properties object,
- * if the param 'fix' is true, the syntax of the json string will be
- * checked previously and fixed when possible.
- */
- <J> J parse(String json, boolean fix);
-
- /**
- * Returns the javascript properties object.
- */
- Properties getProperties();
-
- /**
- * return a list of field names.
- */
- String[] getFieldNames();
-
- /**
- * return a string which represents the object with an alias for the className
- */
- String toJson();
-
- /**
- * return the Json name for this class
- */
- String getJsonName();
-}
+/* + * 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.builders; + +import com.google.gwt.query.client.Properties; + +/** + * Tagging interface used to generate JsonBuilder classes. + */ +public interface JsonBuilder { + + /** + * load a properties object. + */ + <J> J load(Object prp); + + /** + * parses a json string and loads the resulting properties object. + */ + <J> J parse(String json); + + /** + * parses a json string and loads the resulting properties object, + * if the param 'fix' is true, the syntax of the json string will be + * checked previously and fixed when possible. + */ + <J> J parse(String json, boolean fix); + + /** + * Returns the javascript properties object. + */ + Properties getProperties(); + + /** + * return a list of field names. + */ + String[] getFieldNames(); + + /** + * return a string which represents the object with an alias for the className + */ + String toJson(); + + /** + * return the Json name for this class + */ + String getJsonName(); +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilderBase.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilderBase.java index 43b892f7..ac3b3102 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilderBase.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilderBase.java @@ -1,12 +1,12 @@ /* * 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 @@ -22,19 +22,19 @@ import com.google.gwt.query.client.js.JsObjectArray; import com.google.gwt.query.client.js.JsUtils; public abstract class JsonBuilderBase<J extends JsonBuilderBase<?>> implements JsonBuilder { - + protected Properties p = Properties.create(); @SuppressWarnings("unchecked") public J parse(String json) { return load(JsUtils.parseJSON(json)); } - + @SuppressWarnings("unchecked") public J parse(String json, boolean fix) { return fix ? parse(Properties.wrapPropertiesString(json)) : parse(json); } - + @SuppressWarnings("unchecked") public J load(Object prp) { assert prp == null || prp instanceof JavaScriptObject || prp instanceof String; @@ -58,7 +58,7 @@ public abstract class JsonBuilderBase<J extends JsonBuilderBase<?>> implements J p.set(n, a); } } - + @SuppressWarnings("unchecked") protected <T> T[] getArrayBase(String n, T[] r, Class<T> clazz) { JsObjectArray<?> a = p.getArray(n).cast(); @@ -72,22 +72,22 @@ public abstract class JsonBuilderBase<J extends JsonBuilderBase<?>> implements J break; } c = c.getSuperclass(); - } while (c != null); + } while (c != null); } return r; } - + protected Properties getPropertiesBase(String n) { Properties r = p.getJavaScriptObject(n); return r != null ? r : Properties.create(); } - + public String toString() { return p.tostring(); } - + public Properties getProperties() { return p; } - + } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/Name.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/Name.java index 5507677e..0c75590d 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/Name.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/Name.java @@ -1,31 +1,31 @@ -/*
- * 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.builders;
-
-import static java.lang.annotation.ElementType.METHOD;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation used to specify the attribute, tag or property name
- * in Json or Xml builders.
- */
-@Target({METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Name {
- String value();
-}
+/* + * 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.builders; + +import static java.lang.annotation.ElementType.METHOD; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation used to specify the attribute, tag or property name + * in Json or Xml builders. + */ +@Target({METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Name { + String value(); +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/XmlBuilder.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/XmlBuilder.java index dfb110b4..930e7ef9 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/XmlBuilder.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/XmlBuilder.java @@ -1,81 +1,81 @@ -/*
- * 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.builders;
-
-import java.util.Date;
-
-import com.google.gwt.dom.client.Element;
-
-/**
- * Tagging interface used to generate XmlBuilder classes.
- */
-public interface XmlBuilder {
- /**
- * load a string or a documentElement.
- */
- <J> J load(Object o);
-
- /**
- * parses a xml string and loads the resulting documentElement.
- */
- <J> J parse(String xml);
-
- /**
- * Returns the documentElement.
- */
- Element getRootElement();
-
- /**
- * Appends a node
- */
- void append(XmlBuilder x);
-
- /**
- * Appends xml content
- */
- void append(String x);
-
- /**
- * Returns the text content of the element
- */
- String getText();
-
- /**
- * Sets the text content of the element
- */
- <J> J setText(String t);
-
- /**
- * Returns the text content of the element as a number
- */
- double getTextAsNumber();
-
- /**
- * Returns the text content of the element as a date
- */
- Date getTextAsDate();
-
- /**
- * Returns whether the text content of the element is true or false.
- * It is false when the string matches false, off, 0 or empty.
- */
- boolean getTextAsBoolean();
-
- /**
- * Returns the Enum value of the text content of the element.
- */
- <T extends Enum<T>> T getTextAsEnum(Class<T> clazz);
-}
+/* + * 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.builders; + +import java.util.Date; + +import com.google.gwt.dom.client.Element; + +/** + * Tagging interface used to generate XmlBuilder classes. + */ +public interface XmlBuilder { + /** + * load a string or a documentElement. + */ + <J> J load(Object o); + + /** + * parses a xml string and loads the resulting documentElement. + */ + <J> J parse(String xml); + + /** + * Returns the documentElement. + */ + Element getRootElement(); + + /** + * Appends a node + */ + void append(XmlBuilder x); + + /** + * Appends xml content + */ + void append(String x); + + /** + * Returns the text content of the element + */ + String getText(); + + /** + * Sets the text content of the element + */ + <J> J setText(String t); + + /** + * Returns the text content of the element as a number + */ + double getTextAsNumber(); + + /** + * Returns the text content of the element as a date + */ + Date getTextAsDate(); + + /** + * Returns whether the text content of the element is true or false. + * It is false when the string matches false, off, 0 or empty. + */ + boolean getTextAsBoolean(); + + /** + * Returns the Enum value of the text content of the element. + */ + <T extends Enum<T>> T getTextAsEnum(Class<T> clazz); +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/XmlBuilderBase.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/XmlBuilderBase.java index 24582c53..82bf32bd 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/XmlBuilderBase.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/XmlBuilderBase.java @@ -1,12 +1,12 @@ /* * 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 @@ -27,18 +27,18 @@ import com.google.gwt.query.client.Properties; import com.google.gwt.query.client.js.JsUtils; public abstract class XmlBuilderBase<J extends XmlBuilderBase<?>> implements XmlBuilder { - + //TODO empty document protected GQuery g = $((Element)JsUtils.parseXML("<root/>")); public void append(String xml) { g.append(JsUtils.parseXML(xml)); } - + public void append(XmlBuilder x) { g.append(x.getRootElement()); } - + protected Boolean getBooleanBase(String n) { return "true".equalsIgnoreCase(getStrBase(n)); } @@ -46,38 +46,38 @@ public abstract class XmlBuilderBase<J extends XmlBuilderBase<?>> implements Xml protected Element getElementBase(String n) { return g.children(n).get(0); } - + protected Element[] getElementsBase(String n) { return g.children(n).elements(); } - + protected float getFloatBase(String s) { String n = getStrBase(s).replaceAll("[^\\d\\-\\.]", ""); return n.isEmpty() ? 0 : Float.parseFloat(n); } - + protected Properties getPropertiesBase(String n) { // TODO: return null; } - + public Element getRootElement() { return g.get(0); } - + protected String getStrBase(String n) { return g.attr(n); } - + public String getText() { return g.text(); } - + public double getTextAsNumber() { String t = g.text().replaceAll("[^\\d\\.\\-]", ""); return t.isEmpty() ? 0 : Double.parseDouble(t); } - + public Date getTextAsDate() { String t = g.text().trim(); if (t.matches("\\d+")) { @@ -86,17 +86,17 @@ public abstract class XmlBuilderBase<J extends XmlBuilderBase<?>> implements Xml return new Date((long)JsDate.parse(t)); } } - + public boolean getTextAsBoolean() { String t = g.text().trim().toLowerCase(); return !t.matches("^(|false|off|0)$"); } - + public <T extends Enum<T>> T getTextAsEnum(Class<T> clazz) { String t = g.text().trim(); return Enum.valueOf(clazz, t); } - + @SuppressWarnings("unchecked") public J load(Object o) { assert o == null || o instanceof JavaScriptObject && JsUtils.isElement((JavaScriptObject)o) || o instanceof String; @@ -108,12 +108,12 @@ public abstract class XmlBuilderBase<J extends XmlBuilderBase<?>> implements Xml } return (J)this; } - + @SuppressWarnings("unchecked") public J parse(String xml) { return load(JsUtils.parseXML(xml)); } - + protected <T> void setArrayBase(String n, T[] r) { String v = ""; for (T t: r) { @@ -121,7 +121,7 @@ public abstract class XmlBuilderBase<J extends XmlBuilderBase<?>> implements Xml } setBase(n, v); } - + protected void setBase(String n, Object v) { g.attr(n, v); } @@ -131,7 +131,7 @@ public abstract class XmlBuilderBase<J extends XmlBuilderBase<?>> implements Xml g.text(t); return (T)this; } - + public String toString() { return g.toString(); } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundAttachmentProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundAttachmentProperty.java index 5ccb55d7..83e48f3b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundAttachmentProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundAttachmentProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundColorProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundColorProperty.java index 3c9f2494..0b29c7df 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundColorProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundColorProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundImageProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundImageProperty.java index 7145a7c3..126f1491 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundImageProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundImageProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundPositionProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundPositionProperty.java index f98598d9..c0b37fb4 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundPositionProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundPositionProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -27,9 +27,9 @@ public class BackgroundPositionProperty extends /** * Value for <i>background-position</i> property. - * + * * @author Julien Dramaix (julien.dramaix@gmail.com) - * + * */ public static class BackgroundPosition implements HasCssName { @@ -136,7 +136,7 @@ public class BackgroundPositionProperty extends BOTTOM = new BackgroundPosition(BOTTOM_VALUE); } - + /** * Return a {@link BackgroundPosition} by specifying the horizontal and * vertical position. Pixel will be used as Unit diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundProperty.java index e1868c72..a9b02c9d 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -27,7 +27,7 @@ import com.google.gwt.query.client.css.TakesCssValue.CssSetter; * <i>'background-image'</i>, <i>'background-repeat'</i>, * <i>'background-attachment'</i> and <i>'background-position'</i>) at the same * place in the style sheet. - * + * */ public class BackgroundProperty implements HasCssValue { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundRepeatProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundRepeatProperty.java index a528b0bf..cfd3e8c8 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundRepeatProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BackgroundRepeatProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderCollapseProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderCollapseProperty.java index 6d2d0fe5..7a626105 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderCollapseProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderCollapseProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderColorProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderColorProperty.java index 36435366..c6386ac0 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderColorProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderColorProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderProperty.java index 955f6a43..9ef84d99 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -26,8 +26,8 @@ import com.google.gwt.query.client.css.TakesCssValue.CssSetter; * <i>margin</i> and <i>padding</i> properties, the <i>border</i> property * cannot set different values on the four borders. To do so, one or more of the * other border properties must be used. - * - * + * + * */ public class BorderProperty implements HasCssValue { @@ -67,7 +67,7 @@ public class BorderProperty implements HasCssValue { RGBColor borderColor) { return new MultipleValueCssSetter(getCssName(), borderWidth, borderStyle, borderColor); } - + public CssSetter with(Length borderWidth, BorderStyle borderStyle, RGBColor borderColor) { return new MultipleValueCssSetter(getCssName(), borderWidth, borderStyle, borderColor); diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderSpacingProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderSpacingProperty.java index b6e65729..eee9f71d 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderSpacingProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderSpacingProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -29,7 +29,7 @@ public class BorderSpacingProperty extends /** * value for <i>border-spacing</i> property. - * + * */ public static class BorderSpacing implements HasCssName { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderStyleProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderStyleProperty.java index ff4f409f..714da3f8 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderStyleProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderStyleProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderWidthProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderWidthProperty.java index 8a89e0eb..a136c5dc 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderWidthProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/BorderWidthProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CSS.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CSS.java index 02be6b45..f88e9939 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CSS.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CSS.java @@ -1,12 +1,12 @@ /* * 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 @@ -74,7 +74,7 @@ public class CSS { * fixed with regard to the viewport (<i>'fixed'</i>) or scrolls along with * the containing block (<i>'scroll'</i>). * </p> - * + * * <p> * This property can only take a {@link BackgroundAttachment} object as value. * </p> @@ -86,7 +86,7 @@ public class CSS { * This property sets the background color of an element, either a color value * or the keyword 'transparent', to make the underlying colors shine through. * </p> - * + * * <p> * This property can only take a {@link RGBColor} object as value. * </p> @@ -101,12 +101,12 @@ public class CSS { * rendered on top of the background color. (Thus, the color is visible in the * transparent parts of the image). * </p> - * + * * <p> * This property takes a {@link UriValue} object as value. * </p> - * - * + * + * */ public static BackgroundImageProperty BACKGROUND_IMAGE; @@ -115,11 +115,11 @@ public class CSS { * If a background image has been specified, this property specifies its * initial position. * </p> - * + * * <p> * This property takes a {@link BackgroundPosition} object as value. * </p> - * + * */ public static BackgroundPositionProperty BACKGROUND_POSITION; @@ -129,11 +129,11 @@ public class CSS { * image is repeated (tiled), and how. All tiling covers the content and * padding areas of a box * </p> - * + * * <p> * This property takes a {@link BackgroundRepeat} object as value. * </p> - * + * */ public static BackgroundRepeatProperty BACKGROUND_REPEAT; @@ -145,7 +145,7 @@ public class CSS { * cannot set different values on the four borders. To do so, one or more of * the other border properties must be used. * </p> - * + * */ public static BorderProperty BORDER; @@ -154,7 +154,7 @@ public class CSS { * The <i>border-bottom</i> property is a shorthand property for setting the * width, style, and color of the bottom border of a box. * </p> - * + * */ public static BorderProperty BORDER_BOTTOM; @@ -163,11 +163,11 @@ public class CSS { * The <i>border-bottom-color</i> property specifies the color of the bottom * border of a box. * </p> - * + * * <p> * This property takes a {@link RGBColor} object as value. * </p> - * + * */ public static BorderColorProperty BORDER_BOTTOM_COLOR; @@ -176,7 +176,7 @@ public class CSS { * The <i>border-bottom-style</i> property specifies the line style of a box's * bottom border (solid, double, dashed, etc.). * </p> - * + * * <p> * This property takes a {@link BorderStyle} object as value. * </p> @@ -188,12 +188,12 @@ public class CSS { * The <i>border-bottom-width</i> property specifies the width of the bottom * border of a box. * </p> - * + * * <p> * This property takes a {@link BorderWidth} or a {@link Length} object as * value. * </p> - * + * */ public static BorderWidthProperty BORDER_BOTTOM_WIDTH; @@ -201,11 +201,11 @@ public class CSS { * <p> * The <i>border-collapse</i> selects a table's border model. * </p> - * + * * <p> * This property takes a {@link BorderCollapse} object as value. * </p> - * + * */ public static BorderCollapseProperty BORDER_COLLAPSE; @@ -214,11 +214,11 @@ public class CSS { * The <i>border-color</i> property specifies the color of the 4 borders of a * box. * </p> - * + * * <p> * This property takes a {@link RGBColor} object as value. * </p> - * + * */ public static BorderColorProperty BORDER_COLOR; @@ -235,11 +235,11 @@ public class CSS { * The <i>border-left-color</i> property specifies the color of the left * border of a box. * </p> - * + * * <p> * This property takes a {@link RGBColor} object as value. * </p> - * + * */ public static BorderColorProperty BORDER_LEFT_COLOR; @@ -248,11 +248,11 @@ public class CSS { * The <i>border-left-style</i> property specifies the line style of a box's * left border (solid, double, dashed, etc.). * </p> - * + * * <p> * This property takes a {@link BorderStyle} object as value. * </p> - * + * */ public static BorderStyleProperty BORDER_LEFT_STYLE; @@ -261,12 +261,12 @@ public class CSS { * The <i>border-left-width</i> property specifies the width of the left * border of a box. * </p> - * + * * <p> * This property takes a {@link BorderWidth} or a {@link Length} object as * value. * </p> - * + * */ public static BorderWidthProperty BORDER_LEFT_WIDTH; @@ -275,7 +275,7 @@ public class CSS { * The <i>border-right</i> property is a shorthand property for setting the * width, style, and color of the right border of a box. * </p> - * + * */ public static BorderProperty BORDER_RIGHT; @@ -284,11 +284,11 @@ public class CSS { * The <i>border-right-color</i> property specifies the color of the right * border of a box. * </p> - * + * * <p> * This property takes a {@link RGBColor} object as value. * </p> - * + * */ public static BorderColorProperty BORDER_RIGHT_COLOR; @@ -297,11 +297,11 @@ public class CSS { * The <i>border-right-style</i> property specifies the line style of a box's * right border (solid, double, dashed, etc.). * </p> - * + * * <p> * This property takes a {@link BorderStyle} object as value. * </p> - * + * */ public static BorderStyleProperty BORDER_RIGHT_STYLE; @@ -310,12 +310,12 @@ public class CSS { * The <i>border-right-width</i> property specifies the width of the right * border of a box. * </p> - * + * * <p> * This property takes a {@link BorderWidth} or a {@link Length} object as * value. * </p> - * + * */ public static BorderWidthProperty BORDER_RIGHT_WIDTH; @@ -327,11 +327,11 @@ public class CSS { * first gives the horizontal spacing and the second the vertical spacing. * Lengths may not be negative. * </p> - * + * * <p> * This property takes a {@link BorderSpacing} object as value. * </p> - * + * */ public static BorderSpacingProperty BORDER_SPACING; @@ -340,11 +340,11 @@ public class CSS { * The <i>border-style</i> property specifies the line style of the 4 borders * of a box (solid, double, dashed, etc.). * </p> - * + * * <p> * This property takes a {@link BorderStyle} object as value. * </p> - * + * */ public static BorderStyleProperty BORDER_STYLE; @@ -353,7 +353,7 @@ public class CSS { * The <i>border-top</i> property is a shorthand property for setting the * width, style, and color of the top border of a box. * </p> - * + * */ public static BorderProperty BORDER_TOP; @@ -362,11 +362,11 @@ public class CSS { * The <i>border-top-color</i> property specifies the color of the top border * of a box. * </p> - * + * * <p> * This property takes a {@link RGBColor} object as value. * </p> - * + * */ public static BorderColorProperty BORDER_TOP_COLOR; @@ -375,11 +375,11 @@ public class CSS { * The <i>border-top-style</i> property specifies the line style of a box's * top border (solid, double, dashed, etc.). * </p> - * + * * <p> * This property takes a {@link BorderStyle} object as value. * </p> - * + * */ public static BorderStyleProperty BORDER_TOP_STYLE; @@ -388,12 +388,12 @@ public class CSS { * The <i>border-top-width</i> property specifies the width of the top border * of a box. * </p> - * + * * <p> * This property takes a {@link BorderWidth} or a {@link Length} object as * value. * </p> - * + * */ public static BorderWidthProperty BORDER_TOP_WIDTH; @@ -402,12 +402,12 @@ public class CSS { * The <i>border-width</i> property specifies the width of the 4 border of a * box. * </p> - * + * * <p> * This property takes a {@link BorderWidth} or a {@link Length} object as * value. * </p> - * + * */ public static BorderWidthProperty BORDER_WIDTH; @@ -428,11 +428,11 @@ public class CSS { * <p> * For static positioned elements, the bottom property has no effect. * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> - * + * */ public static EdgePositionProperty BOTTOM; @@ -441,11 +441,11 @@ public class CSS { * The <i>caption-side</i> property specifies the position of the caption box * with respect to the table box. * </p> - * + * * <p> * This property takes a {@link CaptionSide} object as value. * </p> - * + * */ public static CaptionSideProperty CAPTION_SIDE; @@ -456,11 +456,11 @@ public class CSS { * itself has floating descendants; the <i>clear</i> property has no effect on * those.) * </p> - * + * * <p> * This property takes a {@link Clear} object as value. * </p> - * + * */ public static ClearProperty CLEAR; @@ -478,7 +478,7 @@ public class CSS { * <p> * This property takes a {@link Shape} object as value. * </p> - * + * */ public static ClipProperty CLIP; @@ -502,7 +502,7 @@ public class CSS { * <p> * This property takes a {@link Cursor} object as value. * </p> - * + * */ public static CursorProperty CURSOR; @@ -517,7 +517,7 @@ public class CSS { * <p> * This property takes a {@link Direction} object as value. * </p> - * + * */ public static DirectionProperty DIRECTION; @@ -525,7 +525,7 @@ public class CSS { * <p> * This property takes a {@link UnicodeBidi} object as value. * </p> - * + * */ public static UnicodeBidiProperty UNICODE_BIDI; @@ -537,7 +537,7 @@ public class CSS { * <p> * This property takes a {@link Display} object as value. * </p> - * + * */ public static DisplayProperty DISPLAY; @@ -560,11 +560,11 @@ public class CSS { * no visible content, the entire row behaves as if it had <i>display: * none</i>. * </p> - * + * * <p> * This property takes a {@link EmptyCells} object as value. * </p> - * + * */ public static EmptyCellsProperty EMPTY_CELLS; @@ -574,11 +574,11 @@ public class CSS { * right, or not at all. It may be set for elements that generate boxes that * are not absolutely positioned. * </p> - * + * * <p> * This property takes a {@link Float} object as value. * </p> - * + * */ public static FloatProperty FLOAT; @@ -587,11 +587,11 @@ public class CSS { * The <i>font-size</i> property requests normal (sometimes referred to as * "roman" or "upright"), italic, and oblique faces within a font family. * </p> - * + * * <p> * This property takes a {@link FontSize} or a {@link Length} object as value. * </p> - * + * */ public static FontSizeProperty FONT_SIZE; @@ -600,7 +600,7 @@ public class CSS { * The <i>font-style</i> property requests normal (sometimes referred to as * "roman" or "upright"), italic, and oblique faces within a font family. * </p> - * + * * <p> * This property takes a {@link FontStyle} object as value. * </p> @@ -616,7 +616,7 @@ public class CSS { * visible effect for scripts that are unicameral (having only one case, as * with most of the world's writing systems). * </p> - * + * * <p> * This property takes a {@link FontVariant} object as value. * </p> @@ -627,11 +627,11 @@ public class CSS { * <p> * The <i>font-weight</i> property specifies the weight of the font. * </p> - * + * * <p> * This property takes a {@link FontWeight} object as value. * </p> - * + * */ public static FontWeightProperty FONT_WEIGHT; @@ -645,11 +645,11 @@ public class CSS { * section on computing heights and margins for non-replaced inline elements * for the rules used instead. * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> - * + * */ public static HeightProperty HEIGHT; @@ -676,11 +676,11 @@ public class CSS { * <p> * For static positioned elements, the left property has no effect. * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> - * + * */ public static EdgePositionProperty LEFT; @@ -689,11 +689,11 @@ public class CSS { * The <i>letter-spacing</i> property specifies spacing behavior between text * characters. * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> - * + * */ public static LetterSpacingProperty LETTER_SPACING; @@ -703,14 +703,14 @@ public class CSS { * of inline-level elements, it specifies the minimal height of each generated * inline box. * </p> - * + * * <p> * If the property is set on an inline-level element, it specifies the exact * height of each box generated by the element. (Except for inline replaced * elements, where the height of the box is given by the <i>height</i> * property.) * </p> - * + * * <p> * This property takes a {@link Length} object or a {@link Integer} object or * a {@link Double} object as value as value. @@ -724,7 +724,7 @@ public class CSS { * three properties <i>list-style-type</i>, <i>list-style-image</i>, and * <i>list-style-position</i> at the same place in the style sheet. * </p> - * + * */ public static ListStyleProperty LIST_STYLE; @@ -734,11 +734,11 @@ public class CSS { * the list item marker. When the image is available, it will replace the * marker set with the <i>list-style-type</i> marker. * </p> - * + * * <p> * This property takes a {@link UriValue} object as value. * </p> - * + * */ public static ListStyleImageProperty LIST_STYLE_IMAGE; @@ -747,11 +747,11 @@ public class CSS { * The <i>list-style-position</i> property specifies the position of the * marker box in the principal block box. * </p> - * + * * <p> * This property takes a {@link ListStylePosition} object as value. * </p> - * + * */ public static ListStylePositionProperty LIST_STYLE_POSITION; @@ -764,12 +764,12 @@ public class CSS { * systems, and alphabetic systems. Note. Numbered lists improve document * accessibility by making lists easier to navigate. * </p> - * + * * <p> * Glyphs are specified with disc, circle, and square. Their exact rendering * depends on the user agent. * </p> - * + * * <p> * This property takes a {@link ListStyleType} object as value. * </p> @@ -782,7 +782,7 @@ public class CSS { * <i>margin-top</i>, <i>margin-right</i>, <i>margin-bottom</i>, and * <i>margin-left</i> at the same place in the style sheet. * </p> - * + * * <p> * If there is only one value, it applies to all sides. If there are two * values, the top and bottom margins are set to the first value and the right @@ -799,11 +799,11 @@ public class CSS { * The <i>margin-bottom</i> property specifies the width of the margin area of * the bottom of a box * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> - * + * */ public static MarginProperty MARGIN_BOTTOM; @@ -812,11 +812,11 @@ public class CSS { * The <i>margin-left</i> property specifies the width of the margin area of * the left side of a box * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> - * + * */ public static MarginProperty MARGIN_LEFT; @@ -825,11 +825,11 @@ public class CSS { * The <i>margin-right</i> property specifies the width of the margin area of * the right side of a box * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> - * + * */ public static MarginProperty MARGIN_RIGHT; @@ -838,7 +838,7 @@ public class CSS { * The <i>margin-top</i> property specifies the width of the margin area of * the top of a box * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> @@ -849,7 +849,7 @@ public class CSS { * <p> * The <i>max-height</i> property sets the maximum height of an element. * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> @@ -860,11 +860,11 @@ public class CSS { * <p> * The <i>max-width</i> property sets the maximum width of an element. * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> - * + * */ public static WidthProperty MAX_WIDTH; @@ -872,11 +872,11 @@ public class CSS { * <p> * The <i>min-height</i> property sets the minimum height of an element. * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> - * + * */ public static HeightProperty MIN_HEIGHT; @@ -884,7 +884,7 @@ public class CSS { * <p> * The <i>max-width</i> property sets the minimum width of an element. * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> @@ -908,7 +908,7 @@ public class CSS { * make the element "stand out". The outline-color property specifies the * color of an outline. * </p> - * + * * <p> * This property takes a {@link RGBColor} object as value. * </p> @@ -924,7 +924,7 @@ public class CSS { * <p> * This property takes a {@link BorderStyle} object as value. * </p> - * + * */ public static OutlineStyleProperty OUTLINE_STYLE; @@ -937,7 +937,7 @@ public class CSS { * <p> * This property takes a {@link BorderWidth} object as value. * </p> - * + * */ public static OutlineWidthProperty OUTLINE_WIDTH; @@ -947,11 +947,11 @@ public class CSS { * element is clipped when it overflows the element's box (which is acting as * a containing block for the content). * </p> - * + * * <p> * This property takes a {@link Overflow} object as value. * </p> - * + * */ public static OverflowProperty OVERFLOW; @@ -961,7 +961,7 @@ public class CSS { * <i>padding-top</i>, <i>padding-right</i>, <i>padding-bottom</i>, and * <i>padding-left</i> at the same place in the style sheet. * </p> - * + * * <p> * If there is only one component value, it applies to all sides. If there are * two values, the top and bottom paddings are set to the first value and the @@ -970,7 +970,7 @@ public class CSS { * second, and the bottom is set to the third. If there are four values, they * apply to the top, right, bottom, and left, respectively. * </p> - * + * */ public static ShorthandPaddingProperty PADDING; @@ -979,11 +979,11 @@ public class CSS { * The <i>padding-bottom</i> property specifies the width of the padding area * of the bottom of a box * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> - * + * */ public static PaddingProperty PADDING_BOTTOM; @@ -992,11 +992,11 @@ public class CSS { * The <i>padding-left</i> property specifies the width of the padding area of * the left side of a box * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> - * + * */ public static PaddingProperty PADDING_LEFT; @@ -1005,11 +1005,11 @@ public class CSS { * The <i>padding-right</i> property specifies the width of the padding area * of the right side of a box * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> - * + * */ public static PaddingProperty PADDING_RIGHT; @@ -1018,11 +1018,11 @@ public class CSS { * The <i>padding-top</i> property specifies the width of the padding area of * the top of a box * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> - * + * */ public static PaddingProperty PADDING_TOP; @@ -1031,11 +1031,11 @@ public class CSS { * The <i>position</i> property determines which of the CSS2 positioning * algorithms is used to calculate the position of a box. * </p> - * + * * <p> * This property takes a {@link Position} object as value. * </p> - * + * */ public static PositionProperty POSITION; @@ -1056,7 +1056,7 @@ public class CSS { * <p> * For static positioned elements, the right property has no effect. * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> @@ -1068,11 +1068,11 @@ public class CSS { * The <i>text-align</i> property describes how inline-level content of a * block container is aligned. * </p> - * + * * <p> * This property takes a {@link TextAlign} object as value. * </p> - * + * */ public static TextAlignProperty TEXT_ALIGN; @@ -1097,7 +1097,7 @@ public class CSS { * decorations on content that is not text. For example, images and inline * blocks must not be underlined. * </p> - * + * * <p> * This property takes a {@link TextDecoration} object as value. * </p> @@ -1111,14 +1111,14 @@ public class CSS { * of the first box that flows into the block's first line box. The box is * indented with respect to the left (or right, for right-to-left layout) edge * of the line box. User agents must render this indentation as blank space. - * + * * </p> * <p> * <i>Text-ident</i> only affects a line if it is the first formatted line of * an element. For example, the first line of an anonymous block box is only * affected if it is the first child of its parent element. * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> @@ -1133,7 +1133,7 @@ public class CSS { * <p> * This property takes a {@link TextTransform} object as value. * </p> - * + * */ public static TextTransformProperty TEXT_TRANSFORM; @@ -1153,11 +1153,11 @@ public class CSS { * <p> * For static positioned elements, the top property has no effect. * </p> - * + * * <p> * This property takes a {@link Length} object as value. * </p> - * + * */ public static EdgePositionProperty TOP; @@ -1166,11 +1166,11 @@ public class CSS { * The <i>vertical-align</i> property affects the vertical positioning inside * a line box of the boxes generated by an inline-level element. * </p> - * + * * <p> * This property takes a {@link VerticalAlign} object as value. * </p> - * + * */ public static VerticalAlignProperty VERTICAL_ALIGN; @@ -1181,11 +1181,11 @@ public class CSS { * <i>display<i> property to <i>none</i> to suppress box generation * altogether). * </p> - * + * * <p> * This property takes a {@link Visibility} object as value. * </p> - * + * */ public static VisibilityProperty VISIBILITY; @@ -1210,7 +1210,7 @@ public class CSS { * <p> * This property takes a {@link WhiteSpace} object as value. * </p> - * + * */ public static WhiteSpaceProperty WHITE_SPACE; @@ -1227,7 +1227,7 @@ public class CSS { * given by the their containing block, but may be shorted by the presence of * floats. * </p> - * + * * <p> * The width of a replaced element's box is intrinsic and may be scaled by the * user agent if the value of this property is different than <i>auto</i>. @@ -1255,7 +1255,7 @@ public class CSS { * <p> * This property takes a {@link Length} object as value. * </p> - * + * */ public static WordSpacingProperty WORD_SPACING; @@ -1266,13 +1266,13 @@ public class CSS { * <li>The stack level of the box in the current stacking context.</li> * <li>Whether the box establishes a local stacking context.</li> * </ul> - * + * * </p> - * + * * <p> * This property takes a {@link Integer} object as value. * </p> - * + * */ public static ZIndexProperty ZINDEX; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CaptionSideProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CaptionSideProperty.java index 34c3bfa0..a1fdce0a 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CaptionSideProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CaptionSideProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -26,7 +26,7 @@ public class CaptionSideProperty extends /** * Possible values for <i>caption-side</i> property. - * + * */ public enum CaptionSide implements HasCssName { /** diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ClearProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ClearProperty.java index d5488f86..97cfa4f6 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ClearProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ClearProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -25,7 +25,7 @@ public class ClearProperty extends CssProperty<ClearProperty.Clear> { /** * Possible values for <i>clear</i> property. - * + * */ public static enum Clear implements HasCssName { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ClipProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ClipProperty.java index 14314ac8..83dfb09e 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ClipProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ClipProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -27,7 +27,7 @@ public class ClipProperty extends CssProperty<ClipProperty.Shape> { /** * Object defining a clipping region used as value for <i>clip</i> property. - * + * */ public static class Shape implements HasCssName { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ColorProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ColorProperty.java index b92dfcdf..5e91709d 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ColorProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ColorProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CssProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CssProperty.java index 990a98b9..59cfc0c3 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CssProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CssProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -21,7 +21,7 @@ import com.google.gwt.dom.client.Style.HasCssName; /** * Base class for Css property - * + * * @param <T> Class of the value associated with the css property */ public class CssProperty<T extends HasCssName> implements @@ -41,7 +41,7 @@ public class CssProperty<T extends HasCssName> implements set(e.getStyle(), cssValue); } } - + private String cssName; protected CssProperty(String cssName) { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CursorProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CursorProperty.java index 3de194e0..ed706423 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CursorProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/CursorProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -32,7 +32,7 @@ public class CursorProperty extends CssProperty<Cursor> { private CursorProperty() { super(CSS_PROPERTY); } - + public CssSetter with(UriValue url){ return new SimpleCssSetter(this, url); } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/DirectionProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/DirectionProperty.java index de660013..601ace2a 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/DirectionProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/DirectionProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -29,7 +29,7 @@ public class DirectionProperty extends /** * Possible values for <i>direction</i> property. - * + * */ public static enum Direction implements HasCssName { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/DisplayProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/DisplayProperty.java index b0be34b3..e2095976 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/DisplayProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/DisplayProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/EdgePositionProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/EdgePositionProperty.java index 61c939b3..fe6dfd65 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/EdgePositionProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/EdgePositionProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -31,5 +31,5 @@ public class EdgePositionProperty extends CssProperty<Length> { private EdgePositionProperty(String value) { super(value); } - + } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/EmptyCellsProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/EmptyCellsProperty.java index acb080ed..e31746a7 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/EmptyCellsProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/EmptyCellsProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -29,7 +29,7 @@ public class EmptyCellsProperty extends /** * Possible values for <i>empty-cells</i> property.) - * + * */ public enum EmptyCells implements HasCssName { /** diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FloatProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FloatProperty.java index a6f92e37..feb4e8d0 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FloatProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FloatProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontSizeProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontSizeProperty.java index 04305a95..95c348aa 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontSizeProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontSizeProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontStyleProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontStyleProperty.java index 218dbbf2..a78f6785 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontStyleProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontStyleProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontVariantProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontVariantProperty.java index c65289cd..fb977b4d 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontVariantProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontVariantProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontWeightProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontWeightProperty.java index 044660c6..11f84b0f 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontWeightProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/FontWeightProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/HasCssValue.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/HasCssValue.java index da5e2b59..e219b4d8 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/HasCssValue.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/HasCssValue.java @@ -1,12 +1,12 @@ /* * 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 @@ -20,7 +20,7 @@ import com.google.gwt.dom.client.Style.HasCssName; /** * Minimal contract for an object defining a css property - * + * */ public interface HasCssValue extends HasCssName { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/HeightProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/HeightProperty.java index 36f75218..5ffcced5 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/HeightProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/HeightProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/Length.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/Length.java index 537c62f1..7ac531f8 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/Length.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/Length.java @@ -1,12 +1,12 @@ /* * 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 @@ -86,7 +86,7 @@ public class Length implements HasCssName { public static Length mm(double amt) { return new Length(amt + Unit.MM.getType()); } - + /** * Size in millimeters. */ diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/LetterSpacingProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/LetterSpacingProperty.java index 0b7ffeae..a5e7286b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/LetterSpacingProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/LetterSpacingProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/LineHeightProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/LineHeightProperty.java index b3510c71..112a1373 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/LineHeightProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/LineHeightProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -21,7 +21,7 @@ package com.google.gwt.query.client.css; * inline-level elements, it specifies the minimal height of each generated * inline box. * </p> - * + * * <p> * If the property is set on an inline-level element, it specifies the exact * height of each box generated by the element. (Except for inline replaced diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStyleImageProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStyleImageProperty.java index f3e1ec08..3f875994 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStyleImageProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStyleImageProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStylePositionProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStylePositionProperty.java index 61bcbeec..0fcb4c2e 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStylePositionProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStylePositionProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -26,7 +26,7 @@ public class ListStylePositionProperty extends /** * Possible values for <i>list-style-position</i> property. - * + * */ public static enum ListStylePosition implements HasCssName { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStyleProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStyleProperty.java index 3749c3af..5eed56a8 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStyleProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStyleProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStyleTypeProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStyleTypeProperty.java index 070e99c1..f32d74cd 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStyleTypeProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ListStyleTypeProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/MarginProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/MarginProperty.java index ecc8ba4a..00a5b16e 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/MarginProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/MarginProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/MultipleValueCssSetter.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/MultipleValueCssSetter.java index 52a93b53..290d7a65 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/MultipleValueCssSetter.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/MultipleValueCssSetter.java @@ -4,14 +4,14 @@ import com.google.gwt.dom.client.Style.HasCssName; public class MultipleValueCssSetter extends SimpleCssSetter { - + public MultipleValueCssSetter(String cssPropertyName, HasCssName... values) { super(cssPropertyName, computeValue(values)); } - + protected static String computeValue(HasCssName... values){ StringBuilder valueBuilder = new StringBuilder(); - + for (HasCssName cssValue : values){ valueBuilder.append(notNull(cssValue)); } @@ -23,5 +23,5 @@ public class MultipleValueCssSetter extends SimpleCssSetter { private static String notNull(HasCssName value) { return value != null ? value.getCssName() + " " : ""; } - + } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineColorProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineColorProperty.java index 6b2e5c7d..713e3d5e 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineColorProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineColorProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineProperty.java index bb780fa9..23405928 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -23,7 +23,7 @@ import com.google.gwt.query.client.css.TakesCssValue.CssSetter; /** * An outline is a line that is drawn around elements (outside the borders) to * make the element "stand out". - * + * * The outline shorthand property sets all the outline properties in one * declaration. */ diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineStyleProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineStyleProperty.java index 4baa84b5..b9f129a4 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineStyleProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineStyleProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineWidthProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineWidthProperty.java index de520702..6e35afc0 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineWidthProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OutlineWidthProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -34,7 +34,7 @@ public class OutlineWidthProperty extends CssProperty<BorderWidth> private OutlineWidthProperty() { super(CSS_PROPERTY); } - + public CssSetter with(Length value) { return new SimpleCssSetter(this, value); } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OverflowProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OverflowProperty.java index 0d6d0047..d7f810c3 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OverflowProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/OverflowProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/PaddingProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/PaddingProperty.java index e594fdb1..47474848 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/PaddingProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/PaddingProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/PositionProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/PositionProperty.java index dc148491..c89697c3 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/PositionProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/PositionProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/RGBColor.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/RGBColor.java index 7eae3165..d3b8aa71 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/RGBColor.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/RGBColor.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/SimpleCssSetter.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/SimpleCssSetter.java index 3ca9afa4..03297f7c 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/SimpleCssSetter.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/SimpleCssSetter.java @@ -1,12 +1,12 @@ /* * 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 @@ -28,7 +28,7 @@ public class SimpleCssSetter implements CssSetter { private String property; private String value; - + public SimpleCssSetter(HasCssValue property, HasCssName value) { this(property.getCssName(), value != null ? value.getCssName() : null); } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesCssValue.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesCssValue.java index 3aa91643..5f9d922d 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesCssValue.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesCssValue.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesInteger.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesInteger.java index bf9482a6..f298feaa 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesInteger.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesInteger.java @@ -1,12 +1,12 @@ /* * 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 @@ -20,7 +20,7 @@ import com.google.gwt.query.client.css.TakesCssValue.CssSetter; /** * Interface to be implemented by properties which take a integer as defined in * css2 specification - * + * * @see http://www.w3.org/TR/CSS21/syndata.html#value-def-number */ public interface TakesInteger extends HasCssValue { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesLength.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesLength.java index 29c798fc..f6326c5c 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesLength.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesLength.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesNumber.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesNumber.java index 1760dcd2..fb443198 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesNumber.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TakesNumber.java @@ -1,12 +1,12 @@ /* * 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 @@ -20,7 +20,7 @@ import com.google.gwt.query.client.css.TakesCssValue.CssSetter; /** * Interface to be implemented by properties which take a number as defined in * css2 specification - * + * * @see http://www.w3.org/TR/CSS21/syndata.html#value-def-number */ public interface TakesNumber extends TakesInteger { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextAlignProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextAlignProperty.java index b7f41cb7..bd245ae9 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextAlignProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextAlignProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -28,7 +28,7 @@ public class TextAlignProperty extends * Possible value for <i>text-align</i> property. */ public static enum TextAlign implements HasCssName { - + /** * Align the line box with the left side of the containing box. */ diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextDecorationProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextDecorationProperty.java index 730d2485..e89a9ec8 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextDecorationProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextDecorationProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextIdentProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextIdentProperty.java index a4ab92fa..b7c1deb7 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextIdentProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextIdentProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextTransformProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextTransformProperty.java index 58098941..5d80ca34 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextTransformProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/TextTransformProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/UnicodeBidiProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/UnicodeBidiProperty.java index ba737011..9d017cc8 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/UnicodeBidiProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/UnicodeBidiProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -25,7 +25,7 @@ public class UnicodeBidiProperty extends /** * Define possible values for <i>unicode-bidi</i> property - * + * */ public static enum UnicodeBidi implements HasCssName { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/UriValue.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/UriValue.java index cbd9096a..8059f389 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/UriValue.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/UriValue.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/VerticalAlignProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/VerticalAlignProperty.java index 2e066d1b..85a60f19 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/VerticalAlignProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/VerticalAlignProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/VisibilityProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/VisibilityProperty.java index 5d96c178..8cb4c59e 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/VisibilityProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/VisibilityProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/WhiteSpaceProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/WhiteSpaceProperty.java index 31237313..d944f0b9 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/WhiteSpaceProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/WhiteSpaceProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/WidthProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/WidthProperty.java index 2ebeb5fb..865eae3c 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/WidthProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/WidthProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/WordSpacingProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/WordSpacingProperty.java index 7be9ef16..c5552cd3 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/WordSpacingProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/WordSpacingProperty.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ZIndexProperty.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ZIndexProperty.java index 17ee1c09..e9da1ba1 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ZIndexProperty.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/css/ZIndexProperty.java @@ -1,12 +1,12 @@ /* * 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 @@ -20,10 +20,10 @@ import com.google.gwt.query.client.css.TakesCssValue.CssSetter; /** * The z-index property specifies the stack order of an element. - * + * * An element with greater stack order is always in front of an element with a * lower stack order. - * + * * The z-index property only works on positioned elements (position:absolute, * position:relative, or position:fixed). */ @@ -38,7 +38,7 @@ public class ZIndexProperty implements TakesInteger { private ZIndexProperty() { } - + public String getCssName() { return CSS_PROPERTY; } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/AttributeImpl.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/AttributeImpl.java index 29aeafa9..76fd335c 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/AttributeImpl.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/AttributeImpl.java @@ -1,11 +1,11 @@ /* 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 @@ -23,7 +23,7 @@ import com.google.gwt.query.client.js.JsUtils; * Helper class for setting and getting attribute on an element. */ public class AttributeImpl { - + /** * Interface used for attribute setter implementations. */ @@ -54,7 +54,7 @@ public class AttributeImpl { e.setAttribute(key, String.valueOf(value)); } } - + /** * value must be set on element directly */ @@ -102,7 +102,7 @@ public class AttributeImpl { super.setAttribute(e, key, key.toLowerCase()); } } - + /** * Id attribute. */ @@ -121,7 +121,7 @@ public class AttributeImpl { super.setAttribute(e, key, value); } } - + /** * For button and inputs, the type cannot be changed once the element is * attached to the dom ! diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/AttributeTridentImpl.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/AttributeTridentImpl.java index f746f54e..7bb9aeee 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/AttributeTridentImpl.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/AttributeTridentImpl.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImpl.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImpl.java index d57c5906..880278cb 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImpl.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImpl.java @@ -1,12 +1,12 @@ /* * 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 @@ -29,18 +29,18 @@ import com.google.gwt.user.client.DOM; * A helper class to get computed CSS styles for elements. */ public class DocumentStyleImpl { - + private static final JsRegexp cssNumberRegex = new JsRegexp("^(fillOpacity|fontWeight|lineHeight|opacity|orphans|widows|zIndex|zoom)$", "i"); private static final JsRegexp sizeRegex = new JsRegexp("^(client|offset|)(width|height)$", "i"); /** * Returns the numeric value of a css property. - * + * * The parameter force has a special meaning: * - When force is false, returns the value of the css property defined - * in the set of style attributes. - * - Otherwise it returns the real computed value. + * in the set of style attributes. + * - Otherwise it returns the real computed value. */ public double cur(Element elem, String prop, boolean force) { if (JsUtils.isWindow(elem)) { @@ -51,8 +51,8 @@ public class DocumentStyleImpl { return getContentDocument(elem).getClientHeight(); } elem = GQuery.body; - } - + } + if (force && sizeRegex.test(prop)) { // make curCSS below resolve width and height (issue #145) when force is true } else if (elem.getPropertyString(prop) != null @@ -69,20 +69,20 @@ public class DocumentStyleImpl { return (1); } if (!val.matches("^[\\d\\.]+.*$")) { - val = curCSS(elem, prop, false); + val = curCSS(elem, prop, false); } val = val.trim().replaceAll("[^\\d\\.\\-]+.*$", ""); return val.isEmpty() ? 0 : Double.parseDouble(val); } - + /** * Return the string value of a css property of an element. - * + * * The parameter force has a special meaning: * - When force is false, returns the value of the css property defined - * in the set of style attributes. - * - Otherwise it returns the real computed value. - * + * in the set of style attributes. + * - Otherwise it returns the real computed value. + * * For instance if you do not define 'display=none' in the element style but in * the css stylesheet, it will return an empty string unless you pass the * parameter force=true. @@ -94,15 +94,15 @@ public class DocumentStyleImpl { name = fixPropertyName(name); //value defined in the element style String ret = elem.getStyle().getProperty(name); - + if (force) { - + Element toDetach = null; if (JsUtils.isDetached(elem)) { // If the element is detached to the DOM we attach temporary to it toDetach = attachTemporary(elem); } - + if (sizeRegex.test(name)) { ret = getVisibleSize(elem, name) + "px"; } else if ("opacity".equalsIgnoreCase(name)) { @@ -110,7 +110,7 @@ public class DocumentStyleImpl { } else { ret = getComputedStyle(elem, JsUtils.hyphenize(name), name, null); } - + // If the element was previously attached, detached it. if (toDetach != null) { toDetach.removeFromParent(); @@ -119,10 +119,10 @@ public class DocumentStyleImpl { return ret == null ? "" : ret; } - + private Element attachTemporary(Element elem) { Element lastParent = $(elem).parents().last().get(0); - + if (lastParent == null){ //the element itself is detached lastParent = elem; @@ -144,7 +144,7 @@ public class DocumentStyleImpl { } return JsUtils.camelize(name); } - + public int getVisibleSize(Element e, String name) { int ret; if (!isVisible(e)) { @@ -173,7 +173,7 @@ public class DocumentStyleImpl { setStyleProperty(e, "height", "auto"); } } - + private int getSize(Element e, String name) { int ret = 0; if ("width".equals(name)) { @@ -187,21 +187,21 @@ public class DocumentStyleImpl { } else if ("offsetWidth".equals(name)) { ret = e.getOffsetWidth(); } else if ("offsetHeight".equals(name)) { - ret = e.getOffsetHeight(); + ret = e.getOffsetHeight(); } return ret; } - + public int getHeight(Element e) { fixInlineElement(e); return (int) (e.getClientHeight() - num(curCSS(e, "paddingTop", true)) - num(curCSS(e, "paddingBottom", true))); } - + public double getOpacity(Element e) { String o = e.getStyle().getOpacity(); return JsUtils.truth(o) ? num(o) : 1; } - + public int getWidth(Element e) { fixInlineElement(e); return (int) (e.getClientWidth() - num(curCSS(e, "paddingLeft", true)) - num(curCSS(e, "paddingRight", true))); @@ -225,7 +225,7 @@ public class DocumentStyleImpl { public void removeStyleProperty(Element elem, String prop) { elem.getStyle().setProperty(prop, ""); } - + /** * Set the value of a style property of an element. */ @@ -257,11 +257,11 @@ public class DocumentStyleImpl { return cStyle && cStyle.getPropertyValue ? cStyle.getPropertyValue(hyphenName) : null; } catch(e) {return null;} }-*/; - + protected static final JsNamedArray<String> elemdisplay = JsNamedArray.create(); - + /** - * Returns the default display value for each html tag. + * Returns the default display value for each html tag. */ public String defaultDisplay(String tagName) { String ret = elemdisplay.get(tagName); @@ -277,14 +277,14 @@ public class DocumentStyleImpl { } return ret; } - + public native Document getContentDocument(Node n) /*-{ var d = n.contentDocument || n.document || n.contentWindow.document; if (!d.body) this.@com.google.gwt.query.client.impl.DocumentStyleImpl::emptyDocument(Lcom/google/gwt/dom/client/Document;)(d); return d; }-*/; - + public native void emptyDocument(Document d) /*-{ d.open(); d.write("<head/><body/>"); diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImplIE.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImplIE.java index 1ab400e5..cb0e097c 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImplIE.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImplIE.java @@ -1,12 +1,12 @@ /* * 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 @@ -22,7 +22,7 @@ import com.google.gwt.dom.client.Style; * A helper class to get computed CSS styles for elements on IE6. */ public class DocumentStyleImplIE extends DocumentStyleImpl { - + /** * Fix style property names. */ @@ -58,7 +58,7 @@ public class DocumentStyleImplIE extends DocumentStyleImpl { return (int) (e.getOffsetWidth() - num(curCSS(e, "paddingLeft", true)) - num(curCSS(e, "paddingRight", true)) - num(curCSS(e, "borderRightWidth", true)) - num(curCSS(e, "borderRightWidth", true))); } - + /** * Remove a style property from an element. */ @@ -66,10 +66,10 @@ public class DocumentStyleImplIE extends DocumentStyleImpl { if (e && e.style && 'removeAttribute' in e) e.style.removeAttribute(prop); }-*/; - + /** - * Set the value of a style property of an element. + * Set the value of a style property of an element. * IE needs a special workaround to handle opacity */ @Override @@ -80,7 +80,7 @@ public class DocumentStyleImplIE extends DocumentStyleImpl { super.setStyleProperty(e, prop, val); } } - + @Override protected native String getComputedStyle(Element elem, String hyphenName, String camelName, String pseudo) /*-{ diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/HasSelector.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/HasSelector.java index 36a158f4..8ca0a3b7 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/HasSelector.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/HasSelector.java @@ -1,12 +1,12 @@ /* * 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 @@ -20,7 +20,7 @@ import com.google.gwt.dom.client.Node; import com.google.gwt.dom.client.NodeList; public interface HasSelector { - + /** * Parse and execute a given selector expression given a context. * diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngine.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngine.java index def31d91..638cbf46 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngine.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngine.java @@ -1,182 +1,182 @@ -/*
- * 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.impl;
-
-import com.google.gwt.core.client.GWT;
-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.query.client.js.JsNodeArray;
-import com.google.gwt.query.client.js.JsObjectArray;
-import com.google.gwt.query.client.js.JsRegexp;
-import com.google.gwt.query.client.js.JsUtils;
-
-/**
- * Core Selector engine functions, and native JS utility functions.
- */
-public class SelectorEngine implements HasSelector {
-
- private static DocumentStyleImpl styleImpl;
-
- public static native NodeList<Element> getElementsByClassName(String clazz,
- Node ctx) /*-{
- return ctx.getElementsByClassName(clazz);
- }-*/;
-
- public static native Node getNextSibling(Node n) /*-{
- return n.nextSibling || null;
- }-*/;
-
- public static native Node getPreviousSibling(Node n) /*-{
- return n.previousSibling || null;
- }-*/;
-
- public NodeList<Element> querySelectorAll(String selector, Node ctx) {
- if (!hasQuerySelector) {
- return impl.select(selector, ctx);
- }
- try {
- return querySelectorAllImpl(selector, ctx);
- } catch (Exception e) {
- return impl.select(selector, ctx);
- }
- }
-
- public static native NodeList<Element> querySelectorAllImpl(String selector,
- Node ctx) /*-{
- return ctx.querySelectorAll(selector);
- }-*/;
-
- public static native NodeList<Element> elementsByTagName(String selector,
- Node ctx) /*-{
- return ctx.getElementsByTagName(selector);
- }-*/;
-
- public static native NodeList<Element> elementsByClassName(String selector,
- Node ctx) /*-{
- return ctx.getElementsByClassName(selector);
- }-*/;
-
- public static NodeList<Element> veryQuickId(String id, Node ctx) {
- Document d = ctx.getNodeType() == Node.DOCUMENT_NODE
- ? ctx.<Document> cast() : ctx.getOwnerDocument();
- return JsNodeArray.create(d.getElementById(id));
- }
-
- public static NodeList<Element> xpathEvaluate(String selector, Node ctx) {
- return xpathEvaluate(selector, ctx, JsNodeArray.create());
- }
-
- public static native NodeList<Element> xpathEvaluate(String selector,
- Node ctx, JsNodeArray r) /*-{
- var node;
- var ownerDoc = ctx && (ctx.ownerDocument || ctx );
- var evalDoc = ownerDoc ? ownerDoc : $doc;
- var result = evalDoc.evaluate(selector, ctx, null, 0, null);
- while ((node = result.iterateNext())) {
- r.push(node);
- }
- return r;
- }-*/;
-
- public final SelectorEngineImpl impl;
-
- protected Node root = Document.get();
-
- public static final boolean hasQuerySelector = hasQuerySelectorAll();
-
- public SelectorEngine() {
- impl = (SelectorEngineImpl) GWT.create(SelectorEngineImpl.class);
- GWT.log("GQuery - Created SelectorEngineImpl: " + impl.getClass().getName());
- styleImpl = GWT.create(DocumentStyleImpl.class);
- GWT.log("GQuery - Created DocumentStyleImpl: " + styleImpl.getClass().getName());
- }
-
- public Node getRoot() {
- return root;
- }
-
- public NodeList<Element> filterByVisibility (NodeList<Element> nodes, boolean visible) {
- JsNodeArray res = JsNodeArray.create();
- for (int i = 0, l = nodes.getLength(), j = 0; i < l; i++) {
- Element e = nodes.getItem(i);
- if (visible == ((e.getOffsetWidth() + e.getOffsetHeight()) > 0 && styleImpl.isVisible(e))) {
- res.addNode(e, j++);
- }
- }
- return res;
- }
-
- // pseudo selectors which are computed by gquery
- JsRegexp p = new JsRegexp("(.*):((visible|hidden)|((button|checkbox|file|hidden|image|password|radio|reset|submit|text)\\s*(,|$)))(.*)", "i");
-
- public NodeList<Element> select(String selector, Node ctx) {
- if (p.test(selector)) {
- JsNodeArray res = JsNodeArray.create();
- for (String s : selector.trim().split("\\s*,\\s*")) {
- NodeList<Element> nodes;
- JsObjectArray<String> a = p.match(s);
- if (a.get(0) != null) {
- if (s.endsWith(":visible")) {
- nodes = filterByVisibility(select(s.substring(0, s.length() - 8), ctx), true);
- } else if (s.endsWith(":hidden")) {
- nodes = filterByVisibility(select(s.substring(0, s.length() - 7), ctx), false);
- } else {
- nodes = select((a.get(1) != null ? a.get(1) : "") + "[type=" + a.get(2) + "]", ctx);
- }
- } else {
- nodes = select(s, ctx);
- }
- JsUtils.copyNodeList(res, nodes, false);
- }
- return res.<NodeList<Element>> cast();
- } else {
- return impl.select(selector, ctx);
- }
- }
-
- public native boolean contains(Element a, Element b) /*-{
- return a.contains ? a != b && a.contains(b) : !!(a.compareDocumentPosition(b) & 16)
- }-*/;
-
- public void setRoot(Node root) {
- assert root != null;
- this.root = root;
- }
-
- public String getName() {
- return getClass().getName().replaceAll("^.*\\.", "");
- }
-
- public boolean isDegradated() {
- return !hasQuerySelector;
- }
-
- /**
- * Check if the browser has native support for css selectors
- */
- public static native boolean hasQuerySelectorAll() /*-{
- return $doc.location.href.indexOf("_force_no_native") < 0 &&
- $doc.querySelectorAll &&
- /native/.test(String($doc.querySelectorAll)) ? true : false;
- }-*/;
-
- public static native boolean hasXpathEvaluate() /*-{
- return $doc.evaluate ? true : false;
- }-*/;
-
-}
+/* + * 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.impl; + +import com.google.gwt.core.client.GWT; +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.query.client.js.JsNodeArray; +import com.google.gwt.query.client.js.JsObjectArray; +import com.google.gwt.query.client.js.JsRegexp; +import com.google.gwt.query.client.js.JsUtils; + +/** + * Core Selector engine functions, and native JS utility functions. + */ +public class SelectorEngine implements HasSelector { + + private static DocumentStyleImpl styleImpl; + + public static native NodeList<Element> getElementsByClassName(String clazz, + Node ctx) /*-{ + return ctx.getElementsByClassName(clazz); + }-*/; + + public static native Node getNextSibling(Node n) /*-{ + return n.nextSibling || null; + }-*/; + + public static native Node getPreviousSibling(Node n) /*-{ + return n.previousSibling || null; + }-*/; + + public NodeList<Element> querySelectorAll(String selector, Node ctx) { + if (!hasQuerySelector) { + return impl.select(selector, ctx); + } + try { + return querySelectorAllImpl(selector, ctx); + } catch (Exception e) { + return impl.select(selector, ctx); + } + } + + public static native NodeList<Element> querySelectorAllImpl(String selector, + Node ctx) /*-{ + return ctx.querySelectorAll(selector); + }-*/; + + public static native NodeList<Element> elementsByTagName(String selector, + Node ctx) /*-{ + return ctx.getElementsByTagName(selector); + }-*/; + + public static native NodeList<Element> elementsByClassName(String selector, + Node ctx) /*-{ + return ctx.getElementsByClassName(selector); + }-*/; + + public static NodeList<Element> veryQuickId(String id, Node ctx) { + Document d = ctx.getNodeType() == Node.DOCUMENT_NODE + ? ctx.<Document> cast() : ctx.getOwnerDocument(); + return JsNodeArray.create(d.getElementById(id)); + } + + public static NodeList<Element> xpathEvaluate(String selector, Node ctx) { + return xpathEvaluate(selector, ctx, JsNodeArray.create()); + } + + public static native NodeList<Element> xpathEvaluate(String selector, + Node ctx, JsNodeArray r) /*-{ + var node; + var ownerDoc = ctx && (ctx.ownerDocument || ctx ); + var evalDoc = ownerDoc ? ownerDoc : $doc; + var result = evalDoc.evaluate(selector, ctx, null, 0, null); + while ((node = result.iterateNext())) { + r.push(node); + } + return r; + }-*/; + + public final SelectorEngineImpl impl; + + protected Node root = Document.get(); + + public static final boolean hasQuerySelector = hasQuerySelectorAll(); + + public SelectorEngine() { + impl = (SelectorEngineImpl) GWT.create(SelectorEngineImpl.class); + GWT.log("GQuery - Created SelectorEngineImpl: " + impl.getClass().getName()); + styleImpl = GWT.create(DocumentStyleImpl.class); + GWT.log("GQuery - Created DocumentStyleImpl: " + styleImpl.getClass().getName()); + } + + public Node getRoot() { + return root; + } + + public NodeList<Element> filterByVisibility (NodeList<Element> nodes, boolean visible) { + JsNodeArray res = JsNodeArray.create(); + for (int i = 0, l = nodes.getLength(), j = 0; i < l; i++) { + Element e = nodes.getItem(i); + if (visible == ((e.getOffsetWidth() + e.getOffsetHeight()) > 0 && styleImpl.isVisible(e))) { + res.addNode(e, j++); + } + } + return res; + } + + // pseudo selectors which are computed by gquery + JsRegexp p = new JsRegexp("(.*):((visible|hidden)|((button|checkbox|file|hidden|image|password|radio|reset|submit|text)\\s*(,|$)))(.*)", "i"); + + public NodeList<Element> select(String selector, Node ctx) { + if (p.test(selector)) { + JsNodeArray res = JsNodeArray.create(); + for (String s : selector.trim().split("\\s*,\\s*")) { + NodeList<Element> nodes; + JsObjectArray<String> a = p.match(s); + if (a.get(0) != null) { + if (s.endsWith(":visible")) { + nodes = filterByVisibility(select(s.substring(0, s.length() - 8), ctx), true); + } else if (s.endsWith(":hidden")) { + nodes = filterByVisibility(select(s.substring(0, s.length() - 7), ctx), false); + } else { + nodes = select((a.get(1) != null ? a.get(1) : "") + "[type=" + a.get(2) + "]", ctx); + } + } else { + nodes = select(s, ctx); + } + JsUtils.copyNodeList(res, nodes, false); + } + return res.<NodeList<Element>> cast(); + } else { + return impl.select(selector, ctx); + } + } + + public native boolean contains(Element a, Element b) /*-{ + return a.contains ? a != b && a.contains(b) : !!(a.compareDocumentPosition(b) & 16) + }-*/; + + public void setRoot(Node root) { + assert root != null; + this.root = root; + } + + public String getName() { + return getClass().getName().replaceAll("^.*\\.", ""); + } + + public boolean isDegradated() { + return !hasQuerySelector; + } + + /** + * Check if the browser has native support for css selectors + */ + public static native boolean hasQuerySelectorAll() /*-{ + return $doc.location.href.indexOf("_force_no_native") < 0 && + $doc.querySelectorAll && + /native/.test(String($doc.querySelectorAll)) ? true : false; + }-*/; + + public static native boolean hasXpathEvaluate() /*-{ + return $doc.evaluate ? true : false; + }-*/; + +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineCssToXPath.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineCssToXPath.java index 0424378c..d6218abf 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineCssToXPath.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineCssToXPath.java @@ -1,275 +1,275 @@ -/*
- * 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.impl;
-
-import java.util.ArrayList;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.JsArray;
-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.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.JsRegexp;
-import com.google.gwt.query.client.js.JsUtils;
-import com.google.gwt.regexp.shared.RegExp;
-
-/**
- * Runtime selector engine implementation which translates selectors to XPath
- * and delegates to document.evaluate().
- * It is based on the regular expressions taken from Andrea Giammarchi's Css2Xpath
- */
-public class SelectorEngineCssToXPath extends SelectorEngineImpl {
-
- static JsNamedArray<String> cache;
-
- /**
- * Interface for callbacks in replaceAll operations.
- */
- public static interface ReplaceCallback {
- String foundMatch(ArrayList<String> s);
- }
-
- /**
- * Interface for replacer implementations (GWT and JVM).
- */
- public static interface Replacer {
- String replaceAll(String s, String expr, Object replacement);
- }
-
- private static SelectorEngineCssToXPath instance;
-
- private static ReplaceCallback rc_scp = new ReplaceCallback() {
- public String foundMatch(ArrayList<String> s) {
- return s.get(1) + s.get(2) +
- (s.get(3).startsWith(" ") ? "%S%" : s.get(3).startsWith("#") ? "%H%" : "%P%") +
- s.get(4) + s.get(5);
- }
- };
-
- private static ReplaceCallback rc_$Attr = new ReplaceCallback() {
- public String foundMatch(ArrayList<String> s) {
- return "[substring(@" + s.get(1) + ",string-length(@" + s.get(1) + ")-" + (s.get(2).replaceAll("'", "").length() - 1) + ")=" + s.get(2) + "]";
- }
- };
-
- private static ReplaceCallback rc_Not = new ReplaceCallback() {
- public String foundMatch(ArrayList<String> s) {
- return s.get(1) + "[not(" + getInstance().css2Xpath(s.get(2)).replaceAll("^[^\\[]+\\[([^\\]]*)\\].*$", "$1" + ")]");
- }
- };
-
- private static ReplaceCallback rc_nth_child = new ReplaceCallback() {
- public String foundMatch(ArrayList<String> s) {
- String s1 = s.get(1);
- String s2 = s.get(2);
-
- boolean noPrefix = s1 == null || s1.length() == 0;
-
- if ("n".equals(s2)) {
- return s1;
- }
- if ("even".equals(s2)) {
- return "*[position() mod 2=0 and position()>=0]" + (noPrefix ? "" : "/self::" + s1);
- }
- if ("odd".equals(s2)) {
- String prefix = noPrefix ? "" : s1;
- return prefix + "[(count(preceding-sibling::*) + 1) mod 2=1]";
- }
-
- if (!s2.contains("n")){
- return "*[position() = "+s2+"]" + (noPrefix ? "" : "/self::" + s1);
- }
-
- String[] t = s2.replaceAll("^([0-9]*)n.*?([0-9]*)?$", "$1+$2").split("\\+");
- String t0 = t[0];
- String t1 = t.length > 1 ? t[1] : "0";
- return "*[(position()-" + t1 + ") mod " + t0 + "=0 and position()>=" + t1 + "]" + (noPrefix ? "" : "/self::" + s1);
- }
- };
-
- public static Object[] regs = new Object[]{
- // scape some dots and spaces
- "(['\\[])([^'\\]]*)([\\s\\.#])([^'\\]]*)(['\\]])", rc_scp,
- // add @ for attrib
- "\\[([^@\\]~\\$\\*\\^\\|\\!]+)(=[^\\]]+)?\\]", "[@$1$2]",
- // multiple queries
- "\\s*,\\s*", "|.//",
- // , + ~ >
- "\\s*(\\+|~|>)\\s*", "$1",
- //* ~ + >
- "([\\w\\-\\*])~([\\w\\-\\*])", "$1/following-sibling::$2",
- "([\\w\\-\\*])\\+([\\w\\-\\*])", "$1/following-sibling::*[1]/self::$2",
- "([\\w\\-\\*])>([\\w\\-\\*])", "$1/$2",
- // all unescaped stuff escaped
- "\\[([^=]+)=([^'|\"][^\\]]*)\\]", "[$1='$2']",
- // all descendant or self to
- "(^|[^\\w\\-\\*])(#|\\.)([\\w\\-]+)", "$1*$2$3",
- "([\\>\\+\\|\\~\\,\\s])([a-zA-Z\\*]+)", "$1//$2",
- "\\s+//", "//",
- // :first-child
- "([\\w\\-\\*]+):first-child", "*[1]/self::$1",
- // :last-child
- "([\\w\\-\\*]+):last-child", "$1[not(following-sibling::*)]",
- // :only-child
- "([\\w\\-\\*]+):only-child", "*[last()=1]/self::$1",
- // :empty
- "([\\w\\-\\*]+):empty", "$1[not(*) and not(normalize-space())]",
- // :odd :even, this is intentional since sizzle behaves so
- ":odd" , ":nth-child(even)",
- ":even" , ":nth-child(odd)",
- // :not
- "(.+):not\\(([^\\)]*)\\)", rc_Not,
- // :nth-child
- "([a-zA-Z0-9\\_\\-\\*]*):nth-child\\(([^\\)]*)\\)", rc_nth_child,
- // :contains(selectors)
- ":contains\\(([^\\)]*)\\)", "[contains(string(.),'$1')]",
- // |= attrib
- "\\[([\\w\\-]+)\\|=([^\\]]+)\\]", "[@$1=$2 or starts-with(@$1,concat($2,'-'))]",
- // *= attrib
- "\\[([\\w\\-]+)\\*=([^\\]]+)\\]", "[contains(@$1,$2)]",
- // ~= attrib
- "\\[([\\w\\-]+)~=([^\\]]+)\\]", "[contains(concat(' ',normalize-space(@$1),' '),concat(' ',$2,' '))]",
- // ^= attrib
- "\\[([\\w\\-]+)\\^=([^\\]]+)\\]", "[starts-with(@$1,$2)]",
- // $= attrib
- "\\[([\\w\\-]+)\\$=([^\\]]+)\\]", rc_$Attr,
- // != attrib
- "\\[([\\w\\-]+)\\!=([^\\]]+)\\]", "[not(@$1) or @$1!=$2]",
- // ids and classes
- "#([\\w\\-]+)", "[@id='$1']",
- "\\.([\\w\\-]+)", "[contains(concat(' ',normalize-space(@class),' '),' $1 ')]",
- // normalize multiple filters
- "\\]\\[([^\\]]+)", " and ($1)",
- // tag:pseudo
- ":(enabled)", "[not(@disabled)]",
- ":(checked)", "[@$1='$1']",
- ":(disabled)", "[@$1]",
- ":(first)", "[1]",
- ":(last)", "[last()]",
- // put '*' when tag is omitted
- "(^|\\|[\\./]*)(\\[)", "$1*$2",
- // Replace escaped dots and spaces
- "%S%"," ",
- "%P%",".",
- "%H%","#",
- // Duplicated quotes
- "'+","'",
- };
-
- public static SelectorEngineCssToXPath getInstance() {
- if (instance == null) {
- instance = new SelectorEngineCssToXPath();
- }
- return instance;
- }
-
- // This replacer only works in browser, it must be replaced
- // when using this engine in generators and tests for the JVM
- private Replacer replacer = new Replacer() {
- public String replaceAll(String s, String r, Object o) {
- JsRegexp p = new JsRegexp(r);
- if (o instanceof ReplaceCallback) {
- ReplaceCallback callback = (ReplaceCallback) o;
- while (p.test(s)) {
- JsObjectArray<String> a = p.match(s);
- ArrayList<String> args = new ArrayList<String>();
- for (int i = 0; i < a.length(); i++) {
- args.add(a.get(i));
- }
- String f = callback.foundMatch(args);
- s = s.replaceFirst(r, f);
- }
- return s;
- } else {
- return s.replaceAll(r, o.toString());
- }
- }
- };
-
- /**
- * A replacer which works in both sides. Right now gquery JsRegexp is faster
- * than gwt shared RegExp and does not uses HashSet
- */
- public static final Replacer replacerGwt = new Replacer() {
- public String replaceAll(String s, String r, Object o) {
- RegExp p = RegExp.compile(r, "g");
- if (o instanceof ReplaceCallback) {
- ReplaceCallback callback = (ReplaceCallback) o;
- com.google.gwt.regexp.shared.MatchResult a = null;
- while ((a = p.exec(s)) != null) {
- ArrayList<String> args = new ArrayList<String>();
- for (int i = 0; i < a.getGroupCount(); i++) {
- args.add(a.getGroup(i));
- }
- String f = callback.foundMatch(args);
- s = s.replace(a.getGroup(0), f);
- p = RegExp.compile(r, "g");
- }
- return s;
- } else {
- return p.replace(s, o.toString());
- }
- }
- };
-
- public SelectorEngineCssToXPath() {
- instance = this;
- }
-
- public SelectorEngineCssToXPath(Replacer r) {
- replacer = r;
- instance = this;
- }
-
- public String css2Xpath(String selector) {
- String ret = selector;
- for (int i = 0; i < regs.length;) {
- ret = replacer.replaceAll(ret, regs[i++].toString(), regs[i++]);
- }
- return ".//" + ret;
- }
-
- public NodeList<Element> select(String sel, Node ctx) {
- if (cache == null) {
- cache = JsNamedArray.create();
- }
- String xsel = cache.get(sel);
- if (xsel == null) {
- xsel = sel.startsWith("./") || sel.startsWith("/") ? sel : css2Xpath(sel);
- cache.put(sel, xsel);
- }
-
- JsNodeArray elm = JsNodeArray.create();
- try {
- SelectorEngine.xpathEvaluate(xsel, ctx, elm);
- return JsUtils.unique(elm.<JsArray<Element>> cast()).cast();
- } catch (Exception e) {
- if (!GWT.isScript()) {
- if (!SelectorEngine.hasXpathEvaluate()) {
- throw new RuntimeException("This Browser does not support Xpath selectors.", e);
- }
- System.err.println("ERROR: xpathEvaluate invalid xpath expression:"
- + xsel + " css-selector:" + sel + "\n");
- e.printStackTrace();
- }
- return elm;
- }
- }
-
-}
+/* + * 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.impl; + +import java.util.ArrayList; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.JsArray; +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.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.JsRegexp; +import com.google.gwt.query.client.js.JsUtils; +import com.google.gwt.regexp.shared.RegExp; + +/** + * Runtime selector engine implementation which translates selectors to XPath + * and delegates to document.evaluate(). + * It is based on the regular expressions taken from Andrea Giammarchi's Css2Xpath + */ +public class SelectorEngineCssToXPath extends SelectorEngineImpl { + + static JsNamedArray<String> cache; + + /** + * Interface for callbacks in replaceAll operations. + */ + public static interface ReplaceCallback { + String foundMatch(ArrayList<String> s); + } + + /** + * Interface for replacer implementations (GWT and JVM). + */ + public static interface Replacer { + String replaceAll(String s, String expr, Object replacement); + } + + private static SelectorEngineCssToXPath instance; + + private static ReplaceCallback rc_scp = new ReplaceCallback() { + public String foundMatch(ArrayList<String> s) { + return s.get(1) + s.get(2) + + (s.get(3).startsWith(" ") ? "%S%" : s.get(3).startsWith("#") ? "%H%" : "%P%") + + s.get(4) + s.get(5); + } + }; + + private static ReplaceCallback rc_$Attr = new ReplaceCallback() { + public String foundMatch(ArrayList<String> s) { + return "[substring(@" + s.get(1) + ",string-length(@" + s.get(1) + ")-" + (s.get(2).replaceAll("'", "").length() - 1) + ")=" + s.get(2) + "]"; + } + }; + + private static ReplaceCallback rc_Not = new ReplaceCallback() { + public String foundMatch(ArrayList<String> s) { + return s.get(1) + "[not(" + getInstance().css2Xpath(s.get(2)).replaceAll("^[^\\[]+\\[([^\\]]*)\\].*$", "$1" + ")]"); + } + }; + + private static ReplaceCallback rc_nth_child = new ReplaceCallback() { + public String foundMatch(ArrayList<String> s) { + String s1 = s.get(1); + String s2 = s.get(2); + + boolean noPrefix = s1 == null || s1.length() == 0; + + if ("n".equals(s2)) { + return s1; + } + if ("even".equals(s2)) { + return "*[position() mod 2=0 and position()>=0]" + (noPrefix ? "" : "/self::" + s1); + } + if ("odd".equals(s2)) { + String prefix = noPrefix ? "" : s1; + return prefix + "[(count(preceding-sibling::*) + 1) mod 2=1]"; + } + + if (!s2.contains("n")){ + return "*[position() = "+s2+"]" + (noPrefix ? "" : "/self::" + s1); + } + + String[] t = s2.replaceAll("^([0-9]*)n.*?([0-9]*)?$", "$1+$2").split("\\+"); + String t0 = t[0]; + String t1 = t.length > 1 ? t[1] : "0"; + return "*[(position()-" + t1 + ") mod " + t0 + "=0 and position()>=" + t1 + "]" + (noPrefix ? "" : "/self::" + s1); + } + }; + + public static Object[] regs = new Object[]{ + // scape some dots and spaces + "(['\\[])([^'\\]]*)([\\s\\.#])([^'\\]]*)(['\\]])", rc_scp, + // add @ for attrib + "\\[([^@\\]~\\$\\*\\^\\|\\!]+)(=[^\\]]+)?\\]", "[@$1$2]", + // multiple queries + "\\s*,\\s*", "|.//", + // , + ~ > + "\\s*(\\+|~|>)\\s*", "$1", + //* ~ + > + "([\\w\\-\\*])~([\\w\\-\\*])", "$1/following-sibling::$2", + "([\\w\\-\\*])\\+([\\w\\-\\*])", "$1/following-sibling::*[1]/self::$2", + "([\\w\\-\\*])>([\\w\\-\\*])", "$1/$2", + // all unescaped stuff escaped + "\\[([^=]+)=([^'|\"][^\\]]*)\\]", "[$1='$2']", + // all descendant or self to + "(^|[^\\w\\-\\*])(#|\\.)([\\w\\-]+)", "$1*$2$3", + "([\\>\\+\\|\\~\\,\\s])([a-zA-Z\\*]+)", "$1//$2", + "\\s+//", "//", + // :first-child + "([\\w\\-\\*]+):first-child", "*[1]/self::$1", + // :last-child + "([\\w\\-\\*]+):last-child", "$1[not(following-sibling::*)]", + // :only-child + "([\\w\\-\\*]+):only-child", "*[last()=1]/self::$1", + // :empty + "([\\w\\-\\*]+):empty", "$1[not(*) and not(normalize-space())]", + // :odd :even, this is intentional since sizzle behaves so + ":odd" , ":nth-child(even)", + ":even" , ":nth-child(odd)", + // :not + "(.+):not\\(([^\\)]*)\\)", rc_Not, + // :nth-child + "([a-zA-Z0-9\\_\\-\\*]*):nth-child\\(([^\\)]*)\\)", rc_nth_child, + // :contains(selectors) + ":contains\\(([^\\)]*)\\)", "[contains(string(.),'$1')]", + // |= attrib + "\\[([\\w\\-]+)\\|=([^\\]]+)\\]", "[@$1=$2 or starts-with(@$1,concat($2,'-'))]", + // *= attrib + "\\[([\\w\\-]+)\\*=([^\\]]+)\\]", "[contains(@$1,$2)]", + // ~= attrib + "\\[([\\w\\-]+)~=([^\\]]+)\\]", "[contains(concat(' ',normalize-space(@$1),' '),concat(' ',$2,' '))]", + // ^= attrib + "\\[([\\w\\-]+)\\^=([^\\]]+)\\]", "[starts-with(@$1,$2)]", + // $= attrib + "\\[([\\w\\-]+)\\$=([^\\]]+)\\]", rc_$Attr, + // != attrib + "\\[([\\w\\-]+)\\!=([^\\]]+)\\]", "[not(@$1) or @$1!=$2]", + // ids and classes + "#([\\w\\-]+)", "[@id='$1']", + "\\.([\\w\\-]+)", "[contains(concat(' ',normalize-space(@class),' '),' $1 ')]", + // normalize multiple filters + "\\]\\[([^\\]]+)", " and ($1)", + // tag:pseudo + ":(enabled)", "[not(@disabled)]", + ":(checked)", "[@$1='$1']", + ":(disabled)", "[@$1]", + ":(first)", "[1]", + ":(last)", "[last()]", + // put '*' when tag is omitted + "(^|\\|[\\./]*)(\\[)", "$1*$2", + // Replace escaped dots and spaces + "%S%"," ", + "%P%",".", + "%H%","#", + // Duplicated quotes + "'+","'", + }; + + public static SelectorEngineCssToXPath getInstance() { + if (instance == null) { + instance = new SelectorEngineCssToXPath(); + } + return instance; + } + + // This replacer only works in browser, it must be replaced + // when using this engine in generators and tests for the JVM + private Replacer replacer = new Replacer() { + public String replaceAll(String s, String r, Object o) { + JsRegexp p = new JsRegexp(r); + if (o instanceof ReplaceCallback) { + ReplaceCallback callback = (ReplaceCallback) o; + while (p.test(s)) { + JsObjectArray<String> a = p.match(s); + ArrayList<String> args = new ArrayList<String>(); + for (int i = 0; i < a.length(); i++) { + args.add(a.get(i)); + } + String f = callback.foundMatch(args); + s = s.replaceFirst(r, f); + } + return s; + } else { + return s.replaceAll(r, o.toString()); + } + } + }; + + /** + * A replacer which works in both sides. Right now gquery JsRegexp is faster + * than gwt shared RegExp and does not uses HashSet + */ + public static final Replacer replacerGwt = new Replacer() { + public String replaceAll(String s, String r, Object o) { + RegExp p = RegExp.compile(r, "g"); + if (o instanceof ReplaceCallback) { + ReplaceCallback callback = (ReplaceCallback) o; + com.google.gwt.regexp.shared.MatchResult a = null; + while ((a = p.exec(s)) != null) { + ArrayList<String> args = new ArrayList<String>(); + for (int i = 0; i < a.getGroupCount(); i++) { + args.add(a.getGroup(i)); + } + String f = callback.foundMatch(args); + s = s.replace(a.getGroup(0), f); + p = RegExp.compile(r, "g"); + } + return s; + } else { + return p.replace(s, o.toString()); + } + } + }; + + public SelectorEngineCssToXPath() { + instance = this; + } + + public SelectorEngineCssToXPath(Replacer r) { + replacer = r; + instance = this; + } + + public String css2Xpath(String selector) { + String ret = selector; + for (int i = 0; i < regs.length;) { + ret = replacer.replaceAll(ret, regs[i++].toString(), regs[i++]); + } + return ".//" + ret; + } + + public NodeList<Element> select(String sel, Node ctx) { + if (cache == null) { + cache = JsNamedArray.create(); + } + String xsel = cache.get(sel); + if (xsel == null) { + xsel = sel.startsWith("./") || sel.startsWith("/") ? sel : css2Xpath(sel); + cache.put(sel, xsel); + } + + JsNodeArray elm = JsNodeArray.create(); + try { + SelectorEngine.xpathEvaluate(xsel, ctx, elm); + return JsUtils.unique(elm.<JsArray<Element>> cast()).cast(); + } catch (Exception e) { + if (!GWT.isScript()) { + if (!SelectorEngine.hasXpathEvaluate()) { + throw new RuntimeException("This Browser does not support Xpath selectors.", e); + } + System.err.println("ERROR: xpathEvaluate invalid xpath expression:" + + xsel + " css-selector:" + sel + "\n"); + e.printStackTrace(); + } + return elm; + } + } + +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineImpl.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineImpl.java index d968a5ff..fd9d518e 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineImpl.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineImpl.java @@ -1,24 +1,24 @@ -/*
- * 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.impl;
-
-/**
- * Base/Utility class for runtime selector engine implementations.
- */
-public abstract class SelectorEngineImpl implements HasSelector {
-
-
-}
+/* + * 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.impl; + +/** + * Base/Utility class for runtime selector engine implementations. + */ +public abstract class SelectorEngineImpl implements HasSelector { + + +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNative.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNative.java index d320fc34..0c5880ba 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNative.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNative.java @@ -1,12 +1,12 @@ /* * 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 @@ -27,25 +27,25 @@ import com.google.gwt.query.client.js.JsNamedArray; */ public class SelectorEngineNative extends SelectorEngineImpl { - // querySelectorAll unsupported selectors + // querySelectorAll unsupported selectors public static String NATIVE_EXCEPTIONS_REGEXP = "(^[\\./]/.*)|(.*(:contains|:first([^-]|$)|:last([^-]|$)|:even|:odd)).*"; - + private static HasSelector impl; - + static JsNamedArray<String> cache; - + public SelectorEngineNative() { if (impl == null) { impl = GWT.create(HasSelector.class); GWT.log("GQuery - Created HasSelector: " + impl.getClass().getName()); } } - + public NodeList<Element> select(String selector, Node ctx) { // querySelectorAllImpl does not support ids starting with a digit. // if (selector.matches("#[\\w\\-]+")) { // return SelectorEngine.veryQuickId(selector.substring(1), ctx); -// } else +// } else if (selector.contains("!=")) { if (cache == null) { cache = JsNamedArray.create(); @@ -57,9 +57,9 @@ public class SelectorEngineNative extends SelectorEngineImpl { } selector = xsel; } - + if (!SelectorEngine.hasQuerySelector || selector.matches(NATIVE_EXCEPTIONS_REGEXP)) { - return impl.select(selector, ctx); + return impl.select(selector, ctx); } else { try { return SelectorEngine.querySelectorAllImpl(selector, ctx); @@ -67,7 +67,7 @@ public class SelectorEngineNative extends SelectorEngineImpl { System.err.println("ERROR SelectorEngineNative " + e.getMessage() + " " + selector + ", falling back to " + impl.getClass().getName().replaceAll(".*\\.", "")); - return impl.select(selector, ctx); + return impl.select(selector, ctx); } } } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNativeIE8.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNativeIE8.java index 4f0df2a1..42c8dcfe 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNativeIE8.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNativeIE8.java @@ -1,12 +1,12 @@ /* * 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 @@ -22,25 +22,25 @@ import com.google.gwt.dom.client.NodeList; /** * Runtime selector engine implementation for IE with native * querySelectorAll support (IE8 standards mode). - * + * * It will fall back to Sizzle engine when QuerySelector were unavailable * or in the case of selectors unsupported by the IE8 native QuerySelector. - * + * */ public class SelectorEngineNativeIE8 extends SelectorEngineSizzleIE { - + public static String NATIVE_EXCEPTIONS_REGEXP = ".*(:contains|!=|:not|:nth-|:only-|:first|:last|:even|:odd).*"; - + public NodeList<Element> select(String selector, Node ctx) { if (!SelectorEngine.hasQuerySelector || selector.matches(NATIVE_EXCEPTIONS_REGEXP)) { - return super.select(selector, ctx); + return super.select(selector, ctx); } else { try { return SelectorEngine.querySelectorAllImpl(selector, ctx); } catch (Exception e) { - return super.select(selector, ctx); + return super.select(selector, ctx); } } } - + } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNativeMin.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNativeMin.java index 2bc30d4f..b5986e34 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNativeMin.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNativeMin.java @@ -1,12 +1,12 @@ /* * 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 @@ -23,12 +23,12 @@ import com.google.gwt.dom.client.NodeList; /** * Runtime selector engine implementation for browsers with native * querySelectorAll support. - * - * In the case of unsupported selectors, it will display an error message + * + * In the case of unsupported selectors, it will display an error message * instead of falling back to a pure js implementation. */ public class SelectorEngineNativeMin extends SelectorEngineImpl { - + public NodeList<Element> select(String selector, Node ctx) { try { return SelectorEngine.querySelectorAllImpl(selector, ctx); @@ -37,5 +37,5 @@ public class SelectorEngineNativeMin extends SelectorEngineImpl { return null; } } - + } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNativeMinIE8.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNativeMinIE8.java index 55e8560a..ce599c71 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNativeMinIE8.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineNativeMinIE8.java @@ -1,12 +1,12 @@ /* * 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 @@ -23,7 +23,7 @@ import com.google.gwt.dom.client.NodeList; /** * Runtime selector engine implementation for IE with native querySelectorAll * support (IE8 standards mode). - * + * * In the case of QuerySelector were unavailable or unsupported selectors, it * will display an error message instead of falling back to js. */ diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineSizzle.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineSizzle.java index 5d3e7c6c..8da92e2d 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineSizzle.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineSizzle.java @@ -1,12 +1,12 @@ /* * 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 @@ -28,8 +28,8 @@ import com.google.gwt.dom.client.NodeList; * instead of window.Sizzle to avoid interfering with the original one. */ public class SelectorEngineSizzle extends SelectorEngineImpl { - - + + public static native void initialize() /*-{ (function(){ @@ -57,14 +57,14 @@ var GQS = function(selector, context, results, seed) { if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } - + if ( !selector || typeof selector !== "string" ) { return results; } var parts = [], m, set, checkSet, extra, prune = true, contextXML = GQS.isXML(context), soFar = selector, ret, cur, pop, i; - + // Reset the position of the chunker regexp (start from head) do { chunker.exec(""); @@ -72,9 +72,9 @@ var GQS = function(selector, context, results, seed) { if ( m ) { soFar = m[3]; - + parts.push( m[1] ); - + if ( m[2] ) { extra = m[3]; break; @@ -96,7 +96,7 @@ var GQS = function(selector, context, results, seed) { if ( Expr.relative[ selector ] ) { selector += parts.shift(); } - + set = posProcess( selector, set ); } } @@ -208,7 +208,7 @@ GQS.find = function(expr, context, isXML){ for ( var i = 0, l = Expr.order.length; i < l; i++ ) { var type = Expr.order[i], match; - + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { var left = match[1]; match.splice(1,1); @@ -485,7 +485,7 @@ var Expr = GQS.selectors = { }, ATTR: function(match, curLoop, inplace, result, not, isXML){ var name = match[1].replace(/\\/g, ""); - + if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } @@ -511,7 +511,7 @@ var Expr = GQS.selectors = { } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } - + return match; }, POS: function(match){ @@ -632,18 +632,18 @@ var Expr = GQS.selectors = { case 'only': case 'first': while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } - if ( type === "first" ) { - return true; + if ( type === "first" ) { + return true; } node = elem; case 'last': while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } return true; @@ -653,20 +653,20 @@ var Expr = GQS.selectors = { if ( first === 1 && last === 0 ) { return true; } - + var doneName = match[0], parent = elem.parentNode; - + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { var count = 0; for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } - } + } parent.sizcache = doneName; } - + var diff = elem.nodeIndex - last; if ( first === 0 ) { return diff === 0; @@ -743,7 +743,7 @@ var makeArray = function(array, results) { results.push.apply( results, array ); return results; } - + return array; }; @@ -934,7 +934,7 @@ GQS.getText = function( elems ) { // if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { // return; // } -// +// // GQS = function(query, context, extra, seed){ // context = context || document; // @@ -945,7 +945,7 @@ GQS.getText = function( elems ) { // return makeArray( context.querySelectorAll(query), extra ); // } catch(e){} // } -// +// // return oldGQS(query, context, extra, seed); // }; // @@ -974,7 +974,7 @@ GQS.getText = function( elems ) { if ( div.getElementsByClassName("e").length === 1 ) { return; } - + Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function(match, context, isXML) { if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { @@ -1062,7 +1062,7 @@ GQS.contains = document.compareDocumentPosition ? function(a, b){ GQS.isXML = function(elem){ // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) + // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }; @@ -1093,22 +1093,22 @@ window.GQS = GQS; $wnd.GQS = GQS; })(); - + }-*/; - + private static native JsArray<Element> select(String selector, Node context, JsArray<Element> results, JsArray<Element> seed) /*-{ return $wnd.GQS(selector, context, results, seed); }-*/; - + static boolean initialized = false; - + public SelectorEngineSizzle() { if (!initialized) { initialize(); } } - + public NodeList<Element> select(String selector, Node context) { JsArray<Element> results = JavaScriptObject.createArray().cast(); return select(selector, context, results, null).cast(); diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineSizzleIE.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineSizzleIE.java index a5f27a0d..4c4755b0 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineSizzleIE.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineSizzleIE.java @@ -1,12 +1,12 @@ /* * 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 @@ -28,8 +28,8 @@ import com.google.gwt.dom.client.NodeList; * - It uses the window.IES instead of window.Sizzle to avoid interfering. * - All the stuff related with non IE browsers has been removed making this * implementation a bit faster and smaller. - * - * There are some reasons why we are using sizzle with IE instead of any other + * + * There are some reasons why we are using sizzle with IE instead of any other * implementation. * - Sizzle is the faster selector with IE we have tested. * - Only IE8 under some conditions and with a limited set of selectors @@ -40,8 +40,8 @@ import com.google.gwt.dom.client.NodeList; * IE are coming. */ public class SelectorEngineSizzleIE extends SelectorEngineImpl { - - + + public static native void initialize() /*-{ (function(){ @@ -59,14 +59,14 @@ var IES = function(selector, context, results, seed) { if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } - + if ( !selector || typeof selector !== "string" ) { return results; } var parts = [], m, set, checkSet, extra, prune = true, contextXML = IES.isXML(context), soFar = selector, ret, cur, pop, i; - + // Reset the position of the chunker regexp (start from head) do { chunker.exec(""); @@ -74,9 +74,9 @@ var IES = function(selector, context, results, seed) { if ( m ) { soFar = m[3]; - + parts.push( m[1] ); - + if ( m[2] ) { extra = m[3]; break; @@ -98,7 +98,7 @@ var IES = function(selector, context, results, seed) { if ( Expr.relative[ selector ] ) { selector += parts.shift(); } - + set = posProcess( selector, set ); } } @@ -210,7 +210,7 @@ IES.find = function(expr, context, isXML){ for ( var i = 0, l = Expr.order.length; i < l; i++ ) { var type = Expr.order[i], match; - + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { var left = match[1]; match.splice(1,1); @@ -499,7 +499,7 @@ var Expr = IES.selectors = { }, ATTR: function(match, curLoop, inplace, result, not, isXML){ var name = match[1].replace(/\\/g, ""); - + if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } @@ -525,7 +525,7 @@ var Expr = IES.selectors = { } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } - + return match; }, POS: function(match){ @@ -646,18 +646,18 @@ var Expr = IES.selectors = { case 'only': case 'first': while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } - if ( type === "first" ) { - return true; + if ( type === "first" ) { + return true; } node = elem; case 'last': while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } return true; @@ -667,20 +667,20 @@ var Expr = IES.selectors = { if ( first === 1 && last === 0 ) { return true; } - + var doneName = match[0], parent = elem.parentNode; - + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { var count = 0; for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } - } + } parent.sizcache = doneName; } - + var diff = elem.nodeIndex - last; if ( first === 0 ) { return diff === 0; @@ -758,7 +758,7 @@ var makeArray = function(array, results) { results.push.apply( results, array ); return results; } - + return array; }; @@ -902,7 +902,7 @@ IES.contains = function(a, b) { IES.isXML = function(elem){ // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) + // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }; @@ -933,22 +933,22 @@ window.IES = IES; $wnd.IES = IES; })(); - + }-*/; - + private static native JsArray<Element> select(String selector, Node context, JsArray<Element> results, JsArray<Element> seed) /*-{ return $wnd.IES(selector, context, results, seed); }-*/; - + static boolean initialized = false; - + public SelectorEngineSizzleIE() { if (!initialized) { initialize(); } } - + public NodeList<Element> select(String selector, Node context) { JsArray<Element> results = JavaScriptObject.createArray().cast(); return select(selector, context, results, null).cast(); diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineJS.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineJS.java index 0cf72d59..428913b2 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineJS.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineJS.java @@ -1,812 +1,812 @@ -/*
- * 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.impl.research;
-
-import static com.google.gwt.query.client.js.JsUtils.eq;
-import static com.google.gwt.query.client.js.JsUtils.truth;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-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.query.client.impl.SelectorEngine;
-import com.google.gwt.query.client.impl.SelectorEngineImpl;
-import com.google.gwt.query.client.js.JsNodeArray;
-import com.google.gwt.query.client.js.JsObjectArray;
-import com.google.gwt.query.client.js.JsRegexp;
-import com.google.gwt.query.client.js.JsUtils;
-
-/**
- * Runtime selector engine implementation with no-XPath/native support based on
- * DOMAssistant.
- */
-public class SelectorEngineJS extends SelectorEngineImpl {
-
-
- /**
- * Internal class.
- */
- protected static class Sequence {
-
- public int start;
-
- public int max;
-
- public int add;
-
- public int modVal;
- }
-
- /**
- * Internal class.
- */
- protected static class SplitRule {
-
- public String tag;
-
- public String id;
-
- public String allClasses;
-
- public String allAttr;
-
- public String allPseudos;
-
- public String tagRelation;
-
- public SplitRule(String tag, String id, String allClasses, String allAttr,
- String allPseudos) {
- this.tag = tag;
- this.id = id;
- this.allClasses = allClasses;
- this.allAttr = allAttr;
- this.allPseudos = allPseudos;
- }
-
- public SplitRule(String tag, String id, String allClasses, String allAttr,
- String allPseudos, String tagRelation) {
- this.tag = tag;
- this.id = id;
- this.allClasses = allClasses;
- this.allAttr = allAttr;
- this.allPseudos = allPseudos;
- this.tagRelation = tagRelation;
- }
- }
-
- protected static Sequence getSequence(String expression) {
- int start = 0, add = 2, max = -1, modVal = -1;
- JsRegexp expressionRegExp = new JsRegexp(
- "^((odd|even)|([1-9]\\d*)|((([1-9]\\d*)?)n((\\+|\\-)(\\d+))?)|(\\-(([1-9]\\d*)?)n\\+(\\d+)))$");
- JsObjectArray<String> pseudoValue = expressionRegExp.exec(expression);
- if (!truth(pseudoValue)) {
- return null;
- } else {
- if (truth(pseudoValue.get(2))) { // odd or even
- start = (eq(pseudoValue.get(2), "odd")) ? 1 : 2;
- modVal = (start == 1) ? 1 : 0;
- } else if (JsUtils
- .truth(pseudoValue.get(3))) { // single digit
- start = Integer.parseInt(pseudoValue.get(3), 10);
- add = 0;
- max = start;
- } else if (truth(pseudoValue.get(4))) { // an+b
- add = truth(pseudoValue.get(6)) ? Integer
- .parseInt(pseudoValue.get(6), 10) : 1;
- start = truth(pseudoValue.get(7)) ? Integer.parseInt(
- (pseudoValue.get(8).charAt(0) == '+' ? ""
- : pseudoValue.get(8)) + pseudoValue.get(9), 10) : 0;
- while (start < 1) {
- start += add;
- }
- modVal = (start > add) ? (start - add) % add
- : ((start == add) ? 0 : start);
- } else if (truth(pseudoValue.get(10))) { // -an+b
- add = truth(pseudoValue.get(12)) ? Integer
- .parseInt(pseudoValue.get(12), 10) : 1;
- start = max = Integer.parseInt(pseudoValue.get(13), 10);
- while (start > add) {
- start -= add;
- }
- modVal = (max > add) ? (max - add) % add : ((max == add) ? 0 : max);
- }
- }
- Sequence s = new Sequence();
- s.start = start;
- s.add = add;
- s.max = max;
- s.modVal = modVal;
- return s;
- }
-
- public static void clearAdded(JsNodeArray a) {
- for (int i = 0, len = a.size(); i < len; i++) {
- clearAdded(a.getNode(i));
- }
- }
-
- public static native void clearAdded(Node node) /*-{
- node.added = null;
- }-*/;
-
- public static native NodeList<Element> getElementsByClassName(String clazz,
- Node ctx) /*-{
- return ctx.getElementsByClassName(clazz);
- }-*/;
-
- public static native boolean isAdded(Node prevRef) /*-{
- return prevRef.added || false;
- }-*/;
-
- public static native void setAdded(Node prevRef, boolean added) /*-{
- prevRef.added = added;
- }-*/;
-
- public static native void setSkipTag(JsNodeArray prevElem, boolean skip) /*-{
- prevElem.skipTag = skip;
- }-*/;
-
- private static String attrToRegExp(String attrVal, String op) {
- if (JsUtils.eq("^", op)) {
- return "^" + attrVal;
- }
- if (JsUtils.eq("$", op)) {
- return attrVal + "$";
- }
- if (JsUtils.eq("*", op)) {
- return attrVal;
- }
- if (JsUtils.eq("|", op)) {
- return "(^" + attrVal + "(\\-\\w+)*$)";
- }
- if (JsUtils.eq("~", op)) {
- return "\\b" + attrVal + "\\b";
- }
- return JsUtils.truth(attrVal) ? "^" + attrVal + "$" : null;
- }
-
- private static native boolean checked(Node previous) /*-{
- return previous.checked || false;
- }-*/;
-
- private static void clearChildElms(JsNodeArray prevParents) {
- for (int n = 0, nl = prevParents.size(); n < nl; n++) {
- setHasChildElms(prevParents.getNode(n), false);
- }
- }
-
- private static native boolean enabled(Node node) /*-{
- return !node.disabled;
- }-*/;
-
- private static void getDescendantNodes(JsNodeArray matchingElms,
- String nextTagStr, Node prevRef) {
- NodeList<Element> children = getElementsByTagName(nextTagStr, prevRef);
- for (int k = 0, klen = children.getLength(); k < klen; k++) {
- Node child = children.getItem(k);
- if (child.getParentNode() == prevRef) {
- matchingElms.addNode(child);
- }
- }
- }
-
- private static NodeList<Element> getElementsByTagName(String tag, Node ctx) {
- if (ctx == null) {
- return JavaScriptObject.createArray().cast();
- }
- return ((Element) ctx).getElementsByTagName(tag);
- }
-
- private static void getGeneralSiblingNodes(JsNodeArray matchingElms,
- JsObjectArray<String> nextTag, JsRegexp nextRegExp, Node prevRef) {
- while (
- JsUtils.truth((prevRef = SelectorEngine.getNextSibling(prevRef)))
- && !isAdded(prevRef)) {
- if (!JsUtils.truth(nextTag) || nextRegExp
- .test(prevRef.getNodeName())) {
- setAdded(prevRef, true);
- matchingElms.addNode(prevRef);
- }
- }
- }
-
- private static void getSiblingNodes(JsNodeArray matchingElms, JsObjectArray<String> nextTag,
- JsRegexp nextRegExp, Node prevRef) {
- while (
- JsUtils.truth(prevRef = SelectorEngine.getNextSibling(prevRef))
- && prevRef.getNodeType() != Node.ELEMENT_NODE) {
- }
- if (JsUtils.truth(prevRef)) {
- if (!JsUtils.truth(nextTag) || nextRegExp
- .test(prevRef.getNodeName())) {
- matchingElms.addNode(prevRef);
- }
- }
- }
-
- private static native boolean hasChildElms(Node prevParent) /*-{
- return prevParent.childElms || false;
- }-*/;
-
- private static native boolean isSkipped(JsNodeArray prevElem) /*-{
- return prevElem.skipTag || false;
- }-*/;
-
- private static native void setHasChildElms(Node prevParent, boolean bool) /*-{
- prevParent.childElms = bool ? bool : null;
- }-*/;
-
- private static native JsNodeArray subtractArray(JsNodeArray previousMatch,
- JsNodeArray elementsByPseudo) /*-{
- for (var i=0, src1; (src1=arr1[i]); i++) {
- var found = false;
- for (var j=0, src2; (src2=arr2[j]); j++) {
- if (src2 === src1) {
- found = true;
- break;
- }
- }
- if (found) {
- arr1.splice(i--, 1);
- }
- }
- return arr;
- }-*/;
-
- private JsRegexp cssSelectorRegExp;
-
- private JsRegexp selectorSplitRegExp;
-
- private JsRegexp childOrSiblingRefRegExp;
-
- public SelectorEngineJS() {
- selectorSplitRegExp = new JsRegexp("[^\\s]+", "g");
- childOrSiblingRefRegExp = new JsRegexp("^(>|\\+|~)$");
- cssSelectorRegExp = new JsRegexp(
- "^(\\w+)?(#[\\w\\u00C0-\\uFFFF\\-\\_]+|(\\*))?((\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?((\\[\\w+(\\^|\\$|\\*|\\||~)?(=[\"']*[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+[\"']*)?\\]+)*)?(((:\\w+[\\w\\-]*)(\\((odd|even|\\-?\\d*n?((\\+|\\-)\\d+)?|[\\w\\u00C0-\\uFFFF\\-_]+|((\\w*\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?|(\\[#?\\w+(\\^|\\$|\\*|\\||~)?=?[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+\\]+)|(:\\w+[\\w\\-]*))\\))?)*)?");
- }
-
- public NodeList<Element> select(String sel, Node ctx) {
- String selectors[] = sel.replace("\\s*(,)\\s*", "$1").split(",");
- boolean identical = false;
- JsNodeArray elm = JsNodeArray.create();
- for (int a = 0, len = selectors.length; a < len; a++) {
- if (a > 0) {
- identical = false;
- for (int b = 0, bl = a; b < bl; b++) {
- if (JsUtils.eq(selectors[a], selectors[b])) {
- identical = true;
- break;
- }
- }
- if (identical) {
- continue;
- }
- }
- String currentRule = selectors[a];
- JsObjectArray<String> cssSelectors = selectorSplitRegExp.match(currentRule);
- JsNodeArray prevElem = JsNodeArray.create(ctx);
- for (int i = 0, slen = cssSelectors.length(); i < slen; i++) {
- JsNodeArray matchingElms = JsNodeArray.create();
- String rule = cssSelectors.get(i);
- if (i > 0 && childOrSiblingRefRegExp.test(rule)) {
- JsObjectArray<String> childOrSiblingRef = childOrSiblingRefRegExp.exec(rule);
- if (JsUtils.truth(childOrSiblingRef)) {
- JsObjectArray<String> nextTag = new JsRegexp("^\\w+")
- .exec(cssSelectors.get(i + 1));
- JsRegexp nextRegExp = null;
- String nextTagStr = null;
- if (JsUtils.truth(nextTag)) {
- nextTagStr = nextTag.get(0);
- nextRegExp = new JsRegexp("(^|\\s)" + nextTagStr + "(\\s|$)", "i");
- }
- for (int j = 0, jlen = prevElem.size(); j < jlen; j++) {
- Node prevRef = prevElem.getNode(j);
- String ref = childOrSiblingRef.get(0);
- if (JsUtils.eq(">", ref)) {
- getDescendantNodes(matchingElms, nextTagStr, prevRef);
- } else if (JsUtils.eq("+", ref)) {
- getSiblingNodes(matchingElms, nextTag, nextRegExp, prevRef);
- } else if (JsUtils.eq("~", ref)) {
- getGeneralSiblingNodes(matchingElms, nextTag, nextRegExp,
- prevRef);
- }
- }
- prevElem = matchingElms;
- clearAdded(prevElem);
- rule = cssSelectors.get(++i);
- if (new JsRegexp("^\\w+$").test(rule)) {
- continue;
- }
- setSkipTag(prevElem, true);
- }
- }
- JsObjectArray<String> cssSelector = cssSelectorRegExp.exec(rule);
- SplitRule splitRule = new SplitRule(
- !JsUtils.truth(cssSelector.get(1)) || JsUtils
- .eq(cssSelector.get(3), "*") ? "*" : cssSelector.get(1),
- !JsUtils.eq(cssSelector.get(3), "*") ? cssSelector
- .get(2) : null, cssSelector.get(4), cssSelector.get(6),
- cssSelector.get(10));
- if (JsUtils.truth(splitRule.id)) {
- Element domelem = Document.get()
- .getElementById(splitRule.id.substring(1));
- if (JsUtils.truth(domelem)) {
- matchingElms = JsNodeArray.create(domelem);
- }
- prevElem = matchingElms;
- } else if (JsUtils.truth(splitRule.tag) && !isSkipped(
- prevElem)) {
- if (i == 0 && matchingElms.size() == 0 && prevElem.size() == 1) {
- prevElem = matchingElms = JsNodeArray.create(
- getElementsByTagName(splitRule.tag, prevElem.getNode(0)));
- } else {
- NodeList<Element> tagCollectionMatches;
- for (int l = 0, ll = prevElem.size(); l < ll; l++) {
- tagCollectionMatches = getElementsByTagName(splitRule.tag,
- prevElem.getNode(l));
- for (int m = 0, mlen = tagCollectionMatches.getLength(); m < mlen;
- m++) {
- Node tagMatch = tagCollectionMatches.getItem(m);
-
- if (!isAdded(tagMatch)) {
- setAdded(tagMatch, true);
- matchingElms.addNode(tagMatch);
- }
- }
- }
- prevElem = matchingElms;
- clearAdded(prevElem);
- }
- if (matchingElms.size() == 0) {
- break;
- }
- setSkipTag(prevElem, false);
- if (JsUtils.truth(splitRule.allClasses)) {
- String[] allClasses = splitRule.allClasses.replaceFirst("^\\.", "")
- .split("\\.");
- JsRegexp[] regExpClassNames = new JsRegexp[allClasses.length];
- for (int n = 0, nl = allClasses.length; n < nl; n++) {
- regExpClassNames[n] = new JsRegexp(
- "(^|\\s)" + allClasses[n] + "(\\s|$)");
- }
- JsNodeArray matchingClassElms = JsNodeArray.create();
- for (int o = 0, olen = prevElem.size(); o < olen; o++) {
- Element current = prevElem.getElement(o);
- String elmClass = current.getClassName();
- boolean addElm = false;
- if (JsUtils.truth(elmClass) && !isAdded(current)) {
- for (int p = 0, pl = regExpClassNames.length; p < pl; p++) {
- addElm = regExpClassNames[p].test(elmClass);
- if (!addElm) {
- break;
- }
- }
- if (addElm) {
- setAdded(current, true);
- matchingClassElms.addNode(current);
- }
- }
- }
- clearAdded(prevElem);
- prevElem = matchingElms = matchingClassElms;
- }
- if (JsUtils.truth(splitRule.allAttr)) {
- JsObjectArray<String> allAttr = JsRegexp
- .match("\\[[^\\]]+\\]", "g", splitRule.allAttr);
- JsRegexp[] regExpAttributes = new JsRegexp[allAttr.length()];
- String[] regExpAttributesStr = new String[allAttr.length()];
- JsRegexp attributeMatchRegExp = new JsRegexp(
- "(\\w+)(\\^|\\$|\\*|\\||~)?=?[\"']?([\\w\u00C0-\uFFFF\\s\\-_\\.]+)?");
- for (int q = 0, ql = allAttr.length(); q < ql; q++) {
- JsObjectArray<String> attributeMatch = attributeMatchRegExp
- .exec(allAttr.get(q));
- String attributeValue =
- JsUtils.truth(attributeMatch.get(3))
- ? attributeMatch.get(3).replaceAll("\\.", "\\.")
- : null;
- String attrVal = attrToRegExp(attributeValue,
- (JsUtils.or(attributeMatch.get(2), null)));
- regExpAttributes[q] = (JsUtils.truth(attrVal) ? new JsRegexp(
- attrVal) : null);
- regExpAttributesStr[q] = attributeMatch.get(1);
- }
- JsNodeArray matchingAttributeElms = JsNodeArray.create();
-
- for (int r = 0, rlen = matchingElms.size(); r < rlen; r++) {
- Element current = matchingElms.getElement(r);
- boolean addElm = false;
- for (int s = 0, sl = regExpAttributes.length;
- s < sl; s++) {
- addElm = false;
- JsRegexp attributeRegexp = regExpAttributes[s];
- String currentAttr = getAttr(current, regExpAttributesStr[s]);
- if (JsUtils.truth(currentAttr)
- && currentAttr.length() != 0) {
- if (attributeRegexp == null || attributeRegexp
- .test(currentAttr)) {
- addElm = true;
- }
- }
- if (!addElm) {
- break;
- }
- }
- if (addElm) {
- matchingAttributeElms.addNode(current);
- }
- }
- prevElem = matchingElms = matchingAttributeElms;
- }
- if (JsUtils.truth(splitRule.allPseudos)) {
- JsRegexp pseudoSplitRegExp = new JsRegexp(
- ":(\\w[\\w\\-]*)(\\(([^\\)]+)\\))?");
-
- JsObjectArray<String> allPseudos = JsRegexp
- .match("(:\\w+[\\w\\-]*)(\\([^\\)]+\\))?", "g",
- splitRule.allPseudos);
- for (int t = 0, tl = allPseudos.length(); t < tl; t++) {
- JsObjectArray<String> pseudo = pseudoSplitRegExp.match(allPseudos.get(t));
- String pseudoClass = JsUtils.truth(pseudo.get(1))
- ? pseudo.get(1).toLowerCase() : null;
- String pseudoValue = JsUtils.truth(pseudo.get(3))
- ? pseudo.get(3) : null;
- matchingElms = getElementsByPseudo(matchingElms, pseudoClass,
- pseudoValue);
- clearAdded(matchingElms);
- }
- prevElem = matchingElms;
- }
- }
- }
- elm.pushAll(prevElem);
- }
-
- return JsUtils.unique(elm.<JsArray<Element>>cast()).cast();
- }
-
- protected String getAttr(Element current, String name) {
- return current.getAttribute(name);
- }
-
- private void getCheckedPseudo(JsNodeArray previousMatch, JsNodeArray matchingElms) {
- Node previous;
- for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) {
- previous = previousMatch.getNode(q);
- if (checked(previous)) {
- matchingElms.addNode(previous);
- }
- }
- }
-
- private void getContainsPseudo(JsNodeArray previousMatch, String pseudoValue,
- JsNodeArray matchingElms) {
- Node previous;
- for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) {
- previous = previousMatch.getNode(q);
- if (!isAdded(previous)) {
- if (((Element) previous).getInnerText().indexOf(pseudoValue) != -1) {
- setAdded(previous, true);
- matchingElms.addNode(previous);
- }
- }
- }
- }
-
- private void getDefaultPseudo(JsNodeArray previousMatch, String pseudoClass,
- String pseudoValue, JsNodeArray matchingElms) {
- Node previous;
- for (int w = 0, wlen = previousMatch.size(); w < wlen; w++) {
- previous = previousMatch.getElement(w);
- if (JsUtils
- .eq(((Element) previous).getAttribute(pseudoClass), pseudoValue)) {
- matchingElms.addNode(previous);
- }
- }
- }
-
- private void getDisabledPseudo(JsNodeArray previousMatch, JsNodeArray matchingElms) {
- Node previous;
- for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) {
- previous = previousMatch.getNode(q);
- if (!enabled(previous)) {
- matchingElms.addNode(previous);
- }
- }
- }
-
- private JsNodeArray getElementsByPseudo(JsNodeArray previousMatch, String pseudoClass,
- String pseudoValue) {
- JsNodeArray prevParents = JsNodeArray.create();
- boolean previousDir = pseudoClass.startsWith("first") ? true : false;
- JsNodeArray matchingElms = JsNodeArray.create();
- if (JsUtils.eq("first-child", pseudoClass) || JsUtils
- .eq("last-child", pseudoClass)) {
- getFirstChildPseudo(previousMatch, previousDir, matchingElms);
- } else if (JsUtils.eq("only-child", pseudoClass)) {
- getOnlyChildPseudo(previousMatch, matchingElms);
- } else if (JsUtils.eq("nth-child", pseudoClass)) {
- matchingElms = getNthChildPseudo(previousMatch, pseudoValue, prevParents,
- matchingElms);
- } else if (JsUtils.eq("first-of-type", pseudoClass) || JsUtils
- .eq("last-of-type", pseudoClass)) {
- getFirstOfTypePseudo(previousMatch, previousDir, matchingElms);
- } else if (JsUtils.eq("only-of-type", pseudoClass)) {
- getOnlyOfTypePseudo(previousMatch, matchingElms);
- } else if (JsUtils.eq("nth-of-type", pseudoClass)) {
- matchingElms = getNthOfTypePseudo(previousMatch, pseudoValue, prevParents,
- matchingElms);
- } else if (JsUtils.eq("empty", pseudoClass)) {
- getEmptyPseudo(previousMatch, matchingElms);
- } else if (JsUtils.eq("enabled", pseudoClass)) {
- getEnabledPseudo(previousMatch, matchingElms);
- } else if (JsUtils.eq("disabled", pseudoClass)) {
- getDisabledPseudo(previousMatch, matchingElms);
- } else if (JsUtils.eq("checked", pseudoClass)) {
- getCheckedPseudo(previousMatch, matchingElms);
- } else if (JsUtils.eq("contains", pseudoClass)) {
- getContainsPseudo(previousMatch, pseudoValue, matchingElms);
- } else if (JsUtils.eq("not", pseudoClass)) {
- matchingElms = getNotPseudo(previousMatch, pseudoValue, matchingElms);
- } else {
- getDefaultPseudo(previousMatch, pseudoClass, pseudoValue, matchingElms);
- }
- return matchingElms;
- }
-
- private void getEmptyPseudo(JsNodeArray previousMatch, JsNodeArray matchingElms) {
- Node previous;
- for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) {
- previous = previousMatch.getNode(q);
- if (!previous.hasChildNodes()) {
- matchingElms.addNode(previous);
- }
- }
- }
-
- private void getEnabledPseudo(JsNodeArray previousMatch, JsNodeArray matchingElms) {
- Node previous;
- for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) {
- previous = previousMatch.getNode(q);
- if (enabled(previous)) {
- matchingElms.addNode(previous);
- }
- }
- }
-
- private void getFirstChildPseudo(JsNodeArray previousMatch, boolean previousDir,
- JsNodeArray matchingElms) {
- Node next;
- Node previous;
- for (int j = 0, jlen = previousMatch.size(); j < jlen; j++) {
- previous = next = previousMatch.getElement(j);
- if (previousDir) {
- while (JsUtils
- .truth((next = SelectorEngine.getPreviousSibling(next)))
- && next.getNodeType() != Node.ELEMENT_NODE) {
- }
- } else {
- while (
- JsUtils.truth((next = SelectorEngine.getNextSibling(next)))
- && next.getNodeType() != Node.ELEMENT_NODE) {
- }
- }
- if (!JsUtils.truth(next)) {
- matchingElms.addNode(previous);
- }
- }
- }
-
- private void getFirstOfTypePseudo(JsNodeArray previousMatch, boolean previousDir,
- JsNodeArray matchingElms) {
- Node previous;
- Node next;
- for (int n = 0, nlen = previousMatch.size(); n < nlen; n++) {
- next = previous = previousMatch.getNode(n);
-
- if (previousDir) {
- while (
- JsUtils.truth(next = SelectorEngine.getPreviousSibling(next))
- && !JsUtils
- .eq(next.getNodeName(), previous.getNodeName())) {
- }
- } else {
- while (JsUtils.truth(next = SelectorEngine.getNextSibling(next))
- && !JsUtils.eq(next.getNodeName(), previous.getNodeName())) {
- }
- }
-
- if (!JsUtils.truth(next)) {
- matchingElms.addNode(previous);
- }
- }
- }
-
- private JsNodeArray getNotPseudo(JsNodeArray previousMatch, String pseudoValue,
- JsNodeArray matchingElms) {
- if (new JsRegexp("(:\\w+[\\w\\-]*)$").test(pseudoValue)) {
- matchingElms = subtractArray(previousMatch,
- getElementsByPseudo(previousMatch, pseudoValue.substring(1), ""));
- } else {
- pseudoValue = pseudoValue
- .replace("^\\[#([\\w\\u00C0-\\uFFFF\\-\\_]+)\\]$", "[id=$1]");
- JsObjectArray<String> notTag = new JsRegexp("^(\\w+)").exec(pseudoValue);
- JsObjectArray<String> notClass = new JsRegexp("^\\.([\\w\u00C0-\uFFFF\\-_]+)")
- .exec(pseudoValue);
- JsObjectArray<String> notAttr = new JsRegexp(
- "\\[(\\w+)(\\^|\\$|\\*|\\||~)?=?([\\w\\u00C0-\\uFFFF\\s\\-_\\.]+)?\\]")
- .exec(pseudoValue);
- JsRegexp notRegExp = new JsRegexp("(^|\\s)"
- + (JsUtils.truth(notTag) ? notTag.get(1)
- : JsUtils.truth(notClass) ? notClass.get(1) : "")
- + "(\\s|$)", "i");
- if (JsUtils.truth(notAttr)) {
- String notAttribute = JsUtils.truth(notAttr.get(3)) ? notAttr
- .get(3).replace("\\.", "\\.") : null;
- String notMatchingAttrVal = attrToRegExp(notAttribute,
- notAttr.get(2));
- notRegExp = new JsRegexp(notMatchingAttrVal, "i");
- }
- for (int v = 0, vlen = previousMatch.size(); v < vlen; v++) {
- Element notElm = previousMatch.getElement(v);
- Element addElm = null;
- if (JsUtils.truth(notTag) && !notRegExp
- .test(notElm.getNodeName())) {
- addElm = notElm;
- } else if (JsUtils.truth(notClass) && !notRegExp
- .test(notElm.getClassName())) {
- addElm = notElm;
- } else if (JsUtils.truth(notAttr)) {
- String att = getAttr(notElm, notAttr.get(1));
- if (!JsUtils.truth(att) || !notRegExp.test(att)) {
- addElm = notElm;
- }
- }
- if (JsUtils.truth(addElm) && !isAdded(addElm)) {
- setAdded(addElm, true);
- matchingElms.addNode(addElm);
- }
- }
- }
- return matchingElms;
- }
-
- private JsNodeArray getNthChildPseudo(JsNodeArray previousMatch, String pseudoValue,
- JsNodeArray prevParents, JsNodeArray matchingElms) {
- Node previous;
- if (JsUtils.eq(pseudoValue, "n")) {
- matchingElms = previousMatch;
- } else {
- Sequence sequence = getSequence(pseudoValue);
- if (sequence != null) {
- for (int l = 0, llen = previousMatch.size(); l < llen; l++) {
- previous = previousMatch.getNode(l);
- Node prevParent = previous.getParentNode();
- if (!hasChildElms(prevParent)) {
- int iteratorNext = sequence.start;
- int childCount = 0;
- Node childElm = prevParent.getFirstChild();
- while (childElm != null && (sequence.max < 0
- || iteratorNext <= sequence.max)) {
- if (childElm.getNodeType() == Node.ELEMENT_NODE) {
- if (++childCount == iteratorNext) {
- if (JsUtils
- .eq(childElm.getNodeName(), previous.getNodeName())) {
- matchingElms.addNode(childElm);
- }
- iteratorNext += sequence.add;
- }
- }
- childElm = SelectorEngine.getNextSibling(childElm);
- }
- setHasChildElms(prevParent, true);
- prevParents.addNode(prevParent);
- }
- }
- clearChildElms(prevParents);
- }
- }
- return matchingElms;
- }
-
- private JsNodeArray getNthOfTypePseudo(JsNodeArray previousMatch, String pseudoValue,
- JsNodeArray prevParents, JsNodeArray matchingElms) {
- Node previous;
- if (pseudoValue.startsWith("n")) {
- matchingElms = previousMatch;
- } else {
- Sequence sequence = getSequence(pseudoValue);
- if (sequence != null) {
- for (int p = 0, plen = previousMatch.size(); p < plen; p++) {
- previous = previousMatch.getNode(p);
- Node prevParent = previous.getParentNode();
- if (!hasChildElms(prevParent)) {
- int iteratorNext = sequence.start;
- int childCount = 0;
- Node childElm = prevParent.getFirstChild();
- while (JsUtils.truth(childElm) && (sequence.max < 0
- || iteratorNext <= sequence.max)) {
- if (JsUtils
- .eq(childElm.getNodeName(), previous.getNodeName())) {
- if (++childCount == iteratorNext) {
- matchingElms.addNode(childElm);
- iteratorNext += sequence.add;
- }
- }
- childElm = SelectorEngine.getNextSibling(childElm);
- }
- setHasChildElms(prevParent, true);
- prevParents.addNode(prevParent);
- }
- }
- clearChildElms(prevParents);
- }
- }
- return matchingElms;
- }
-
- private void getOnlyChildPseudo(JsNodeArray previousMatch, JsNodeArray matchingElms) {
- Node previous;
- Node next;
- Node prev;
- Node kParent = null;
- for (int k = 0, klen = previousMatch.size(); k < klen; k++) {
- prev = next = previous = previousMatch.getNode(k);
- Node prevParent = previous.getParentNode();
- if (prevParent != kParent) {
- while (
- JsUtils.truth(prev = SelectorEngine.getPreviousSibling(prev))
- && prev.getNodeType() != Node.ELEMENT_NODE) {
- }
- while (JsUtils.truth(next = SelectorEngine.getNextSibling(next))
- && next.getNodeType() != Node.ELEMENT_NODE) {
- }
- if (!JsUtils.truth(prev) && !JsUtils.truth(next)) {
- matchingElms.addNode(previous);
- }
- kParent = prevParent;
- }
- }
- }
-
- private void getOnlyOfTypePseudo(JsNodeArray previousMatch,
- JsNodeArray matchingElms) {
- Node previous;
- Node next;
- Node prev;
- Node oParent = null;
- for (int o = 0, olen = previousMatch.size(); o < olen; o++) {
- prev = next = previous = previousMatch.getNode(o);
- Node prevParent = previous.getParentNode();
- if (prevParent != oParent) {
- while (
- JsUtils.truth(prev = SelectorEngine.getPreviousSibling(prev))
- && !JsUtils
- .eq(prev.getNodeName(), previous.getNodeName())) {
- }
- while (JsUtils.truth(next = SelectorEngine.getNextSibling(next))
- && !JsUtils.eq(next.getNodeName(), previous.getNodeName())) {
- }
- if (!JsUtils.truth(prev) && !JsUtils.truth(next)) {
- matchingElms.addNode(previous);
- }
- oParent = prevParent;
- }
- }
- }
-}
+/* + * 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.impl.research; + +import static com.google.gwt.query.client.js.JsUtils.eq; +import static com.google.gwt.query.client.js.JsUtils.truth; + +import com.google.gwt.core.client.JavaScriptObject; +import com.google.gwt.core.client.JsArray; +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.query.client.impl.SelectorEngine; +import com.google.gwt.query.client.impl.SelectorEngineImpl; +import com.google.gwt.query.client.js.JsNodeArray; +import com.google.gwt.query.client.js.JsObjectArray; +import com.google.gwt.query.client.js.JsRegexp; +import com.google.gwt.query.client.js.JsUtils; + +/** + * Runtime selector engine implementation with no-XPath/native support based on + * DOMAssistant. + */ +public class SelectorEngineJS extends SelectorEngineImpl { + + + /** + * Internal class. + */ + protected static class Sequence { + + public int start; + + public int max; + + public int add; + + public int modVal; + } + + /** + * Internal class. + */ + protected static class SplitRule { + + public String tag; + + public String id; + + public String allClasses; + + public String allAttr; + + public String allPseudos; + + public String tagRelation; + + public SplitRule(String tag, String id, String allClasses, String allAttr, + String allPseudos) { + this.tag = tag; + this.id = id; + this.allClasses = allClasses; + this.allAttr = allAttr; + this.allPseudos = allPseudos; + } + + public SplitRule(String tag, String id, String allClasses, String allAttr, + String allPseudos, String tagRelation) { + this.tag = tag; + this.id = id; + this.allClasses = allClasses; + this.allAttr = allAttr; + this.allPseudos = allPseudos; + this.tagRelation = tagRelation; + } + } + + protected static Sequence getSequence(String expression) { + int start = 0, add = 2, max = -1, modVal = -1; + JsRegexp expressionRegExp = new JsRegexp( + "^((odd|even)|([1-9]\\d*)|((([1-9]\\d*)?)n((\\+|\\-)(\\d+))?)|(\\-(([1-9]\\d*)?)n\\+(\\d+)))$"); + JsObjectArray<String> pseudoValue = expressionRegExp.exec(expression); + if (!truth(pseudoValue)) { + return null; + } else { + if (truth(pseudoValue.get(2))) { // odd or even + start = (eq(pseudoValue.get(2), "odd")) ? 1 : 2; + modVal = (start == 1) ? 1 : 0; + } else if (JsUtils + .truth(pseudoValue.get(3))) { // single digit + start = Integer.parseInt(pseudoValue.get(3), 10); + add = 0; + max = start; + } else if (truth(pseudoValue.get(4))) { // an+b + add = truth(pseudoValue.get(6)) ? Integer + .parseInt(pseudoValue.get(6), 10) : 1; + start = truth(pseudoValue.get(7)) ? Integer.parseInt( + (pseudoValue.get(8).charAt(0) == '+' ? "" + : pseudoValue.get(8)) + pseudoValue.get(9), 10) : 0; + while (start < 1) { + start += add; + } + modVal = (start > add) ? (start - add) % add + : ((start == add) ? 0 : start); + } else if (truth(pseudoValue.get(10))) { // -an+b + add = truth(pseudoValue.get(12)) ? Integer + .parseInt(pseudoValue.get(12), 10) : 1; + start = max = Integer.parseInt(pseudoValue.get(13), 10); + while (start > add) { + start -= add; + } + modVal = (max > add) ? (max - add) % add : ((max == add) ? 0 : max); + } + } + Sequence s = new Sequence(); + s.start = start; + s.add = add; + s.max = max; + s.modVal = modVal; + return s; + } + + public static void clearAdded(JsNodeArray a) { + for (int i = 0, len = a.size(); i < len; i++) { + clearAdded(a.getNode(i)); + } + } + + public static native void clearAdded(Node node) /*-{ + node.added = null; + }-*/; + + public static native NodeList<Element> getElementsByClassName(String clazz, + Node ctx) /*-{ + return ctx.getElementsByClassName(clazz); + }-*/; + + public static native boolean isAdded(Node prevRef) /*-{ + return prevRef.added || false; + }-*/; + + public static native void setAdded(Node prevRef, boolean added) /*-{ + prevRef.added = added; + }-*/; + + public static native void setSkipTag(JsNodeArray prevElem, boolean skip) /*-{ + prevElem.skipTag = skip; + }-*/; + + private static String attrToRegExp(String attrVal, String op) { + if (JsUtils.eq("^", op)) { + return "^" + attrVal; + } + if (JsUtils.eq("$", op)) { + return attrVal + "$"; + } + if (JsUtils.eq("*", op)) { + return attrVal; + } + if (JsUtils.eq("|", op)) { + return "(^" + attrVal + "(\\-\\w+)*$)"; + } + if (JsUtils.eq("~", op)) { + return "\\b" + attrVal + "\\b"; + } + return JsUtils.truth(attrVal) ? "^" + attrVal + "$" : null; + } + + private static native boolean checked(Node previous) /*-{ + return previous.checked || false; + }-*/; + + private static void clearChildElms(JsNodeArray prevParents) { + for (int n = 0, nl = prevParents.size(); n < nl; n++) { + setHasChildElms(prevParents.getNode(n), false); + } + } + + private static native boolean enabled(Node node) /*-{ + return !node.disabled; + }-*/; + + private static void getDescendantNodes(JsNodeArray matchingElms, + String nextTagStr, Node prevRef) { + NodeList<Element> children = getElementsByTagName(nextTagStr, prevRef); + for (int k = 0, klen = children.getLength(); k < klen; k++) { + Node child = children.getItem(k); + if (child.getParentNode() == prevRef) { + matchingElms.addNode(child); + } + } + } + + private static NodeList<Element> getElementsByTagName(String tag, Node ctx) { + if (ctx == null) { + return JavaScriptObject.createArray().cast(); + } + return ((Element) ctx).getElementsByTagName(tag); + } + + private static void getGeneralSiblingNodes(JsNodeArray matchingElms, + JsObjectArray<String> nextTag, JsRegexp nextRegExp, Node prevRef) { + while ( + JsUtils.truth((prevRef = SelectorEngine.getNextSibling(prevRef))) + && !isAdded(prevRef)) { + if (!JsUtils.truth(nextTag) || nextRegExp + .test(prevRef.getNodeName())) { + setAdded(prevRef, true); + matchingElms.addNode(prevRef); + } + } + } + + private static void getSiblingNodes(JsNodeArray matchingElms, JsObjectArray<String> nextTag, + JsRegexp nextRegExp, Node prevRef) { + while ( + JsUtils.truth(prevRef = SelectorEngine.getNextSibling(prevRef)) + && prevRef.getNodeType() != Node.ELEMENT_NODE) { + } + if (JsUtils.truth(prevRef)) { + if (!JsUtils.truth(nextTag) || nextRegExp + .test(prevRef.getNodeName())) { + matchingElms.addNode(prevRef); + } + } + } + + private static native boolean hasChildElms(Node prevParent) /*-{ + return prevParent.childElms || false; + }-*/; + + private static native boolean isSkipped(JsNodeArray prevElem) /*-{ + return prevElem.skipTag || false; + }-*/; + + private static native void setHasChildElms(Node prevParent, boolean bool) /*-{ + prevParent.childElms = bool ? bool : null; + }-*/; + + private static native JsNodeArray subtractArray(JsNodeArray previousMatch, + JsNodeArray elementsByPseudo) /*-{ + for (var i=0, src1; (src1=arr1[i]); i++) { + var found = false; + for (var j=0, src2; (src2=arr2[j]); j++) { + if (src2 === src1) { + found = true; + break; + } + } + if (found) { + arr1.splice(i--, 1); + } + } + return arr; + }-*/; + + private JsRegexp cssSelectorRegExp; + + private JsRegexp selectorSplitRegExp; + + private JsRegexp childOrSiblingRefRegExp; + + public SelectorEngineJS() { + selectorSplitRegExp = new JsRegexp("[^\\s]+", "g"); + childOrSiblingRefRegExp = new JsRegexp("^(>|\\+|~)$"); + cssSelectorRegExp = new JsRegexp( + "^(\\w+)?(#[\\w\\u00C0-\\uFFFF\\-\\_]+|(\\*))?((\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?((\\[\\w+(\\^|\\$|\\*|\\||~)?(=[\"']*[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+[\"']*)?\\]+)*)?(((:\\w+[\\w\\-]*)(\\((odd|even|\\-?\\d*n?((\\+|\\-)\\d+)?|[\\w\\u00C0-\\uFFFF\\-_]+|((\\w*\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?|(\\[#?\\w+(\\^|\\$|\\*|\\||~)?=?[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+\\]+)|(:\\w+[\\w\\-]*))\\))?)*)?"); + } + + public NodeList<Element> select(String sel, Node ctx) { + String selectors[] = sel.replace("\\s*(,)\\s*", "$1").split(","); + boolean identical = false; + JsNodeArray elm = JsNodeArray.create(); + for (int a = 0, len = selectors.length; a < len; a++) { + if (a > 0) { + identical = false; + for (int b = 0, bl = a; b < bl; b++) { + if (JsUtils.eq(selectors[a], selectors[b])) { + identical = true; + break; + } + } + if (identical) { + continue; + } + } + String currentRule = selectors[a]; + JsObjectArray<String> cssSelectors = selectorSplitRegExp.match(currentRule); + JsNodeArray prevElem = JsNodeArray.create(ctx); + for (int i = 0, slen = cssSelectors.length(); i < slen; i++) { + JsNodeArray matchingElms = JsNodeArray.create(); + String rule = cssSelectors.get(i); + if (i > 0 && childOrSiblingRefRegExp.test(rule)) { + JsObjectArray<String> childOrSiblingRef = childOrSiblingRefRegExp.exec(rule); + if (JsUtils.truth(childOrSiblingRef)) { + JsObjectArray<String> nextTag = new JsRegexp("^\\w+") + .exec(cssSelectors.get(i + 1)); + JsRegexp nextRegExp = null; + String nextTagStr = null; + if (JsUtils.truth(nextTag)) { + nextTagStr = nextTag.get(0); + nextRegExp = new JsRegexp("(^|\\s)" + nextTagStr + "(\\s|$)", "i"); + } + for (int j = 0, jlen = prevElem.size(); j < jlen; j++) { + Node prevRef = prevElem.getNode(j); + String ref = childOrSiblingRef.get(0); + if (JsUtils.eq(">", ref)) { + getDescendantNodes(matchingElms, nextTagStr, prevRef); + } else if (JsUtils.eq("+", ref)) { + getSiblingNodes(matchingElms, nextTag, nextRegExp, prevRef); + } else if (JsUtils.eq("~", ref)) { + getGeneralSiblingNodes(matchingElms, nextTag, nextRegExp, + prevRef); + } + } + prevElem = matchingElms; + clearAdded(prevElem); + rule = cssSelectors.get(++i); + if (new JsRegexp("^\\w+$").test(rule)) { + continue; + } + setSkipTag(prevElem, true); + } + } + JsObjectArray<String> cssSelector = cssSelectorRegExp.exec(rule); + SplitRule splitRule = new SplitRule( + !JsUtils.truth(cssSelector.get(1)) || JsUtils + .eq(cssSelector.get(3), "*") ? "*" : cssSelector.get(1), + !JsUtils.eq(cssSelector.get(3), "*") ? cssSelector + .get(2) : null, cssSelector.get(4), cssSelector.get(6), + cssSelector.get(10)); + if (JsUtils.truth(splitRule.id)) { + Element domelem = Document.get() + .getElementById(splitRule.id.substring(1)); + if (JsUtils.truth(domelem)) { + matchingElms = JsNodeArray.create(domelem); + } + prevElem = matchingElms; + } else if (JsUtils.truth(splitRule.tag) && !isSkipped( + prevElem)) { + if (i == 0 && matchingElms.size() == 0 && prevElem.size() == 1) { + prevElem = matchingElms = JsNodeArray.create( + getElementsByTagName(splitRule.tag, prevElem.getNode(0))); + } else { + NodeList<Element> tagCollectionMatches; + for (int l = 0, ll = prevElem.size(); l < ll; l++) { + tagCollectionMatches = getElementsByTagName(splitRule.tag, + prevElem.getNode(l)); + for (int m = 0, mlen = tagCollectionMatches.getLength(); m < mlen; + m++) { + Node tagMatch = tagCollectionMatches.getItem(m); + + if (!isAdded(tagMatch)) { + setAdded(tagMatch, true); + matchingElms.addNode(tagMatch); + } + } + } + prevElem = matchingElms; + clearAdded(prevElem); + } + if (matchingElms.size() == 0) { + break; + } + setSkipTag(prevElem, false); + if (JsUtils.truth(splitRule.allClasses)) { + String[] allClasses = splitRule.allClasses.replaceFirst("^\\.", "") + .split("\\."); + JsRegexp[] regExpClassNames = new JsRegexp[allClasses.length]; + for (int n = 0, nl = allClasses.length; n < nl; n++) { + regExpClassNames[n] = new JsRegexp( + "(^|\\s)" + allClasses[n] + "(\\s|$)"); + } + JsNodeArray matchingClassElms = JsNodeArray.create(); + for (int o = 0, olen = prevElem.size(); o < olen; o++) { + Element current = prevElem.getElement(o); + String elmClass = current.getClassName(); + boolean addElm = false; + if (JsUtils.truth(elmClass) && !isAdded(current)) { + for (int p = 0, pl = regExpClassNames.length; p < pl; p++) { + addElm = regExpClassNames[p].test(elmClass); + if (!addElm) { + break; + } + } + if (addElm) { + setAdded(current, true); + matchingClassElms.addNode(current); + } + } + } + clearAdded(prevElem); + prevElem = matchingElms = matchingClassElms; + } + if (JsUtils.truth(splitRule.allAttr)) { + JsObjectArray<String> allAttr = JsRegexp + .match("\\[[^\\]]+\\]", "g", splitRule.allAttr); + JsRegexp[] regExpAttributes = new JsRegexp[allAttr.length()]; + String[] regExpAttributesStr = new String[allAttr.length()]; + JsRegexp attributeMatchRegExp = new JsRegexp( + "(\\w+)(\\^|\\$|\\*|\\||~)?=?[\"']?([\\w\u00C0-\uFFFF\\s\\-_\\.]+)?"); + for (int q = 0, ql = allAttr.length(); q < ql; q++) { + JsObjectArray<String> attributeMatch = attributeMatchRegExp + .exec(allAttr.get(q)); + String attributeValue = + JsUtils.truth(attributeMatch.get(3)) + ? attributeMatch.get(3).replaceAll("\\.", "\\.") + : null; + String attrVal = attrToRegExp(attributeValue, + (JsUtils.or(attributeMatch.get(2), null))); + regExpAttributes[q] = (JsUtils.truth(attrVal) ? new JsRegexp( + attrVal) : null); + regExpAttributesStr[q] = attributeMatch.get(1); + } + JsNodeArray matchingAttributeElms = JsNodeArray.create(); + + for (int r = 0, rlen = matchingElms.size(); r < rlen; r++) { + Element current = matchingElms.getElement(r); + boolean addElm = false; + for (int s = 0, sl = regExpAttributes.length; + s < sl; s++) { + addElm = false; + JsRegexp attributeRegexp = regExpAttributes[s]; + String currentAttr = getAttr(current, regExpAttributesStr[s]); + if (JsUtils.truth(currentAttr) + && currentAttr.length() != 0) { + if (attributeRegexp == null || attributeRegexp + .test(currentAttr)) { + addElm = true; + } + } + if (!addElm) { + break; + } + } + if (addElm) { + matchingAttributeElms.addNode(current); + } + } + prevElem = matchingElms = matchingAttributeElms; + } + if (JsUtils.truth(splitRule.allPseudos)) { + JsRegexp pseudoSplitRegExp = new JsRegexp( + ":(\\w[\\w\\-]*)(\\(([^\\)]+)\\))?"); + + JsObjectArray<String> allPseudos = JsRegexp + .match("(:\\w+[\\w\\-]*)(\\([^\\)]+\\))?", "g", + splitRule.allPseudos); + for (int t = 0, tl = allPseudos.length(); t < tl; t++) { + JsObjectArray<String> pseudo = pseudoSplitRegExp.match(allPseudos.get(t)); + String pseudoClass = JsUtils.truth(pseudo.get(1)) + ? pseudo.get(1).toLowerCase() : null; + String pseudoValue = JsUtils.truth(pseudo.get(3)) + ? pseudo.get(3) : null; + matchingElms = getElementsByPseudo(matchingElms, pseudoClass, + pseudoValue); + clearAdded(matchingElms); + } + prevElem = matchingElms; + } + } + } + elm.pushAll(prevElem); + } + + return JsUtils.unique(elm.<JsArray<Element>>cast()).cast(); + } + + protected String getAttr(Element current, String name) { + return current.getAttribute(name); + } + + private void getCheckedPseudo(JsNodeArray previousMatch, JsNodeArray matchingElms) { + Node previous; + for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) { + previous = previousMatch.getNode(q); + if (checked(previous)) { + matchingElms.addNode(previous); + } + } + } + + private void getContainsPseudo(JsNodeArray previousMatch, String pseudoValue, + JsNodeArray matchingElms) { + Node previous; + for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) { + previous = previousMatch.getNode(q); + if (!isAdded(previous)) { + if (((Element) previous).getInnerText().indexOf(pseudoValue) != -1) { + setAdded(previous, true); + matchingElms.addNode(previous); + } + } + } + } + + private void getDefaultPseudo(JsNodeArray previousMatch, String pseudoClass, + String pseudoValue, JsNodeArray matchingElms) { + Node previous; + for (int w = 0, wlen = previousMatch.size(); w < wlen; w++) { + previous = previousMatch.getElement(w); + if (JsUtils + .eq(((Element) previous).getAttribute(pseudoClass), pseudoValue)) { + matchingElms.addNode(previous); + } + } + } + + private void getDisabledPseudo(JsNodeArray previousMatch, JsNodeArray matchingElms) { + Node previous; + for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) { + previous = previousMatch.getNode(q); + if (!enabled(previous)) { + matchingElms.addNode(previous); + } + } + } + + private JsNodeArray getElementsByPseudo(JsNodeArray previousMatch, String pseudoClass, + String pseudoValue) { + JsNodeArray prevParents = JsNodeArray.create(); + boolean previousDir = pseudoClass.startsWith("first") ? true : false; + JsNodeArray matchingElms = JsNodeArray.create(); + if (JsUtils.eq("first-child", pseudoClass) || JsUtils + .eq("last-child", pseudoClass)) { + getFirstChildPseudo(previousMatch, previousDir, matchingElms); + } else if (JsUtils.eq("only-child", pseudoClass)) { + getOnlyChildPseudo(previousMatch, matchingElms); + } else if (JsUtils.eq("nth-child", pseudoClass)) { + matchingElms = getNthChildPseudo(previousMatch, pseudoValue, prevParents, + matchingElms); + } else if (JsUtils.eq("first-of-type", pseudoClass) || JsUtils + .eq("last-of-type", pseudoClass)) { + getFirstOfTypePseudo(previousMatch, previousDir, matchingElms); + } else if (JsUtils.eq("only-of-type", pseudoClass)) { + getOnlyOfTypePseudo(previousMatch, matchingElms); + } else if (JsUtils.eq("nth-of-type", pseudoClass)) { + matchingElms = getNthOfTypePseudo(previousMatch, pseudoValue, prevParents, + matchingElms); + } else if (JsUtils.eq("empty", pseudoClass)) { + getEmptyPseudo(previousMatch, matchingElms); + } else if (JsUtils.eq("enabled", pseudoClass)) { + getEnabledPseudo(previousMatch, matchingElms); + } else if (JsUtils.eq("disabled", pseudoClass)) { + getDisabledPseudo(previousMatch, matchingElms); + } else if (JsUtils.eq("checked", pseudoClass)) { + getCheckedPseudo(previousMatch, matchingElms); + } else if (JsUtils.eq("contains", pseudoClass)) { + getContainsPseudo(previousMatch, pseudoValue, matchingElms); + } else if (JsUtils.eq("not", pseudoClass)) { + matchingElms = getNotPseudo(previousMatch, pseudoValue, matchingElms); + } else { + getDefaultPseudo(previousMatch, pseudoClass, pseudoValue, matchingElms); + } + return matchingElms; + } + + private void getEmptyPseudo(JsNodeArray previousMatch, JsNodeArray matchingElms) { + Node previous; + for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) { + previous = previousMatch.getNode(q); + if (!previous.hasChildNodes()) { + matchingElms.addNode(previous); + } + } + } + + private void getEnabledPseudo(JsNodeArray previousMatch, JsNodeArray matchingElms) { + Node previous; + for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) { + previous = previousMatch.getNode(q); + if (enabled(previous)) { + matchingElms.addNode(previous); + } + } + } + + private void getFirstChildPseudo(JsNodeArray previousMatch, boolean previousDir, + JsNodeArray matchingElms) { + Node next; + Node previous; + for (int j = 0, jlen = previousMatch.size(); j < jlen; j++) { + previous = next = previousMatch.getElement(j); + if (previousDir) { + while (JsUtils + .truth((next = SelectorEngine.getPreviousSibling(next))) + && next.getNodeType() != Node.ELEMENT_NODE) { + } + } else { + while ( + JsUtils.truth((next = SelectorEngine.getNextSibling(next))) + && next.getNodeType() != Node.ELEMENT_NODE) { + } + } + if (!JsUtils.truth(next)) { + matchingElms.addNode(previous); + } + } + } + + private void getFirstOfTypePseudo(JsNodeArray previousMatch, boolean previousDir, + JsNodeArray matchingElms) { + Node previous; + Node next; + for (int n = 0, nlen = previousMatch.size(); n < nlen; n++) { + next = previous = previousMatch.getNode(n); + + if (previousDir) { + while ( + JsUtils.truth(next = SelectorEngine.getPreviousSibling(next)) + && !JsUtils + .eq(next.getNodeName(), previous.getNodeName())) { + } + } else { + while (JsUtils.truth(next = SelectorEngine.getNextSibling(next)) + && !JsUtils.eq(next.getNodeName(), previous.getNodeName())) { + } + } + + if (!JsUtils.truth(next)) { + matchingElms.addNode(previous); + } + } + } + + private JsNodeArray getNotPseudo(JsNodeArray previousMatch, String pseudoValue, + JsNodeArray matchingElms) { + if (new JsRegexp("(:\\w+[\\w\\-]*)$").test(pseudoValue)) { + matchingElms = subtractArray(previousMatch, + getElementsByPseudo(previousMatch, pseudoValue.substring(1), "")); + } else { + pseudoValue = pseudoValue + .replace("^\\[#([\\w\\u00C0-\\uFFFF\\-\\_]+)\\]$", "[id=$1]"); + JsObjectArray<String> notTag = new JsRegexp("^(\\w+)").exec(pseudoValue); + JsObjectArray<String> notClass = new JsRegexp("^\\.([\\w\u00C0-\uFFFF\\-_]+)") + .exec(pseudoValue); + JsObjectArray<String> notAttr = new JsRegexp( + "\\[(\\w+)(\\^|\\$|\\*|\\||~)?=?([\\w\\u00C0-\\uFFFF\\s\\-_\\.]+)?\\]") + .exec(pseudoValue); + JsRegexp notRegExp = new JsRegexp("(^|\\s)" + + (JsUtils.truth(notTag) ? notTag.get(1) + : JsUtils.truth(notClass) ? notClass.get(1) : "") + + "(\\s|$)", "i"); + if (JsUtils.truth(notAttr)) { + String notAttribute = JsUtils.truth(notAttr.get(3)) ? notAttr + .get(3).replace("\\.", "\\.") : null; + String notMatchingAttrVal = attrToRegExp(notAttribute, + notAttr.get(2)); + notRegExp = new JsRegexp(notMatchingAttrVal, "i"); + } + for (int v = 0, vlen = previousMatch.size(); v < vlen; v++) { + Element notElm = previousMatch.getElement(v); + Element addElm = null; + if (JsUtils.truth(notTag) && !notRegExp + .test(notElm.getNodeName())) { + addElm = notElm; + } else if (JsUtils.truth(notClass) && !notRegExp + .test(notElm.getClassName())) { + addElm = notElm; + } else if (JsUtils.truth(notAttr)) { + String att = getAttr(notElm, notAttr.get(1)); + if (!JsUtils.truth(att) || !notRegExp.test(att)) { + addElm = notElm; + } + } + if (JsUtils.truth(addElm) && !isAdded(addElm)) { + setAdded(addElm, true); + matchingElms.addNode(addElm); + } + } + } + return matchingElms; + } + + private JsNodeArray getNthChildPseudo(JsNodeArray previousMatch, String pseudoValue, + JsNodeArray prevParents, JsNodeArray matchingElms) { + Node previous; + if (JsUtils.eq(pseudoValue, "n")) { + matchingElms = previousMatch; + } else { + Sequence sequence = getSequence(pseudoValue); + if (sequence != null) { + for (int l = 0, llen = previousMatch.size(); l < llen; l++) { + previous = previousMatch.getNode(l); + Node prevParent = previous.getParentNode(); + if (!hasChildElms(prevParent)) { + int iteratorNext = sequence.start; + int childCount = 0; + Node childElm = prevParent.getFirstChild(); + while (childElm != null && (sequence.max < 0 + || iteratorNext <= sequence.max)) { + if (childElm.getNodeType() == Node.ELEMENT_NODE) { + if (++childCount == iteratorNext) { + if (JsUtils + .eq(childElm.getNodeName(), previous.getNodeName())) { + matchingElms.addNode(childElm); + } + iteratorNext += sequence.add; + } + } + childElm = SelectorEngine.getNextSibling(childElm); + } + setHasChildElms(prevParent, true); + prevParents.addNode(prevParent); + } + } + clearChildElms(prevParents); + } + } + return matchingElms; + } + + private JsNodeArray getNthOfTypePseudo(JsNodeArray previousMatch, String pseudoValue, + JsNodeArray prevParents, JsNodeArray matchingElms) { + Node previous; + if (pseudoValue.startsWith("n")) { + matchingElms = previousMatch; + } else { + Sequence sequence = getSequence(pseudoValue); + if (sequence != null) { + for (int p = 0, plen = previousMatch.size(); p < plen; p++) { + previous = previousMatch.getNode(p); + Node prevParent = previous.getParentNode(); + if (!hasChildElms(prevParent)) { + int iteratorNext = sequence.start; + int childCount = 0; + Node childElm = prevParent.getFirstChild(); + while (JsUtils.truth(childElm) && (sequence.max < 0 + || iteratorNext <= sequence.max)) { + if (JsUtils + .eq(childElm.getNodeName(), previous.getNodeName())) { + if (++childCount == iteratorNext) { + matchingElms.addNode(childElm); + iteratorNext += sequence.add; + } + } + childElm = SelectorEngine.getNextSibling(childElm); + } + setHasChildElms(prevParent, true); + prevParents.addNode(prevParent); + } + } + clearChildElms(prevParents); + } + } + return matchingElms; + } + + private void getOnlyChildPseudo(JsNodeArray previousMatch, JsNodeArray matchingElms) { + Node previous; + Node next; + Node prev; + Node kParent = null; + for (int k = 0, klen = previousMatch.size(); k < klen; k++) { + prev = next = previous = previousMatch.getNode(k); + Node prevParent = previous.getParentNode(); + if (prevParent != kParent) { + while ( + JsUtils.truth(prev = SelectorEngine.getPreviousSibling(prev)) + && prev.getNodeType() != Node.ELEMENT_NODE) { + } + while (JsUtils.truth(next = SelectorEngine.getNextSibling(next)) + && next.getNodeType() != Node.ELEMENT_NODE) { + } + if (!JsUtils.truth(prev) && !JsUtils.truth(next)) { + matchingElms.addNode(previous); + } + kParent = prevParent; + } + } + } + + private void getOnlyOfTypePseudo(JsNodeArray previousMatch, + JsNodeArray matchingElms) { + Node previous; + Node next; + Node prev; + Node oParent = null; + for (int o = 0, olen = previousMatch.size(); o < olen; o++) { + prev = next = previous = previousMatch.getNode(o); + Node prevParent = previous.getParentNode(); + if (prevParent != oParent) { + while ( + JsUtils.truth(prev = SelectorEngine.getPreviousSibling(prev)) + && !JsUtils + .eq(prev.getNodeName(), previous.getNodeName())) { + } + while (JsUtils.truth(next = SelectorEngine.getNextSibling(next)) + && !JsUtils.eq(next.getNodeName(), previous.getNodeName())) { + } + if (!JsUtils.truth(prev) && !JsUtils.truth(next)) { + matchingElms.addNode(previous); + } + oParent = prevParent; + } + } + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineJSIE.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineJSIE.java index 5cf231a3..370d3c6b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineJSIE.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineJSIE.java @@ -1,37 +1,37 @@ -/*
- * 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.impl.research;
-
-import com.google.gwt.dom.client.Element;
-
-/**
- * Runtime implementaton of non-XPath/native for IE that fixes some DOM
- * operation incompatibilities.
- */
-public class SelectorEngineJSIE extends SelectorEngineJS {
-
- public native String getAttr(Element elm, String attr) /*-{
- switch (attr) {
- case "id":
- return elm.id;
- case "for":
- return elm.htmlFor;
- case "class":
- return elm.className;
- }
- return elm.getAttribute(attr, 2);
- }-*/;
-}
+/* + * 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.impl.research; + +import com.google.gwt.dom.client.Element; + +/** + * Runtime implementaton of non-XPath/native for IE that fixes some DOM + * operation incompatibilities. + */ +public class SelectorEngineJSIE extends SelectorEngineJS { + + public native String getAttr(Element elm, String attr) /*-{ + switch (attr) { + case "id": + return elm.id; + case "for": + return elm.htmlFor; + case "class": + return elm.className; + } + return elm.getAttribute(attr, 2); + }-*/; +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineSizzleGwt.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineSizzleGwt.java index 6c72f8de..64156d60 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineSizzleGwt.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineSizzleGwt.java @@ -1,12 +1,12 @@ /* * 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 @@ -27,17 +27,17 @@ import com.google.gwt.query.client.js.JsUtils; /** * Pure Javascript Selector Engine Gwt Implementation based on * Sizzle CSS Selector Engine v1.0. - * + * * It has so many JSNI code, the idea is to make an entire implementation * using Java. Right now it performs worse than pure JSNI implementation - * + * */ public class SelectorEngineSizzleGwt extends SelectorEngineImpl { - + public static native boolean contains(Object a, Object b) /*-{ - var ret = + var ret = document.compareDocumentPosition ? - (a.compareDocumentPosition(b) & 16): + (a.compareDocumentPosition(b) & 16): a !== b && (a.contains ? a.contains(b) : true); return ret ? true : false; }-*/; @@ -55,7 +55,7 @@ public class SelectorEngineSizzleGwt extends SelectorEngineImpl { CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/, - CHUNKER: /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g + CHUNKER: /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g }, leftMatch: {}, attrMap: { @@ -334,18 +334,18 @@ public class SelectorEngineSizzleGwt extends SelectorEngineImpl { case 'only': case 'first': while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } - if ( type === "first" ) { - return true; + if ( type === "first" ) { + return true; } node = elem; case 'last': while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } return true; @@ -362,7 +362,7 @@ public class SelectorEngineSizzleGwt extends SelectorEngineImpl { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } - } + } parent.sizcache = doneName; } var diff = elem.nodeIndex - last; @@ -428,7 +428,7 @@ public class SelectorEngineSizzleGwt extends SelectorEngineImpl { return "\\" + (num - 0 + 1); })); } - + return $wnd.Expr; }-*/; @@ -462,7 +462,7 @@ public class SelectorEngineSizzleGwt extends SelectorEngineImpl { } } }-*/; - + public static native void dirNodeCheck(String dir, Object cur, int doneName, Object checkSet) /*-{ for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; @@ -488,11 +488,11 @@ public class SelectorEngineSizzleGwt extends SelectorEngineImpl { } } }-*/; - + public static void error(String msg) { throw new IllegalArgumentException("Syntax error, unrecognized expression: " + msg); } - + public static native JsArray<Node> filter(String expr, JsArray<Node> set, boolean inplace, Object not) /*-{ var old = expr, result = [], curLoop = set, match, anyFound; while ( expr && set.length ) { @@ -520,7 +520,7 @@ public class SelectorEngineSizzleGwt extends SelectorEngineImpl { if ( item ) { found = filter( item, match, i, curLoop ); var pass = not ^ !!found; - + if ( inplace && found != null ) { if ( pass ) { anyFound = true; @@ -556,7 +556,7 @@ public class SelectorEngineSizzleGwt extends SelectorEngineImpl { } old = expr; } - return curLoop; + return curLoop; }-*/; public static native JavaScriptObject find(String expr, Node context) /*-{ @@ -566,11 +566,11 @@ public class SelectorEngineSizzleGwt extends SelectorEngineImpl { } for ( var i = 0, l = $wnd.Expr.order.length; i < l; i++ ) { var type = $wnd.Expr.order[i], match; - + if ( (match = $wnd.Expr.leftMatch[ type ].exec( expr )) ) { var left = match[1]; match.splice(1,1); - + if ( left.substr( left.length - 1 ) !== "\\" ) { match[1] = (match[1] || "").replace(/\\/g, ""); set = $wnd.Expr.find[ type ]( match, context); @@ -584,9 +584,9 @@ public class SelectorEngineSizzleGwt extends SelectorEngineImpl { if ( !set ) { set = context.getElementsByTagName("*"); } - return {set: set, expr: expr}; + return {set: set, expr: expr}; }-*/; - + public static native String getText(Object elems) /*-{ var ret = "", elem; for ( var i = 0; elems[i]; i++ ) { @@ -601,7 +601,7 @@ public class SelectorEngineSizzleGwt extends SelectorEngineImpl { } return ret; }-*/; - + public static native JsArray<Node> makeArray(NodeList<Node> array, JsArray<Node> results) /*-{ var ret = results || []; if ( Object.prototype.toString.call(array) === "[object Array]" ) { @@ -617,9 +617,9 @@ public class SelectorEngineSizzleGwt extends SelectorEngineImpl { } } } - return ret; + return ret; }-*/; - + public static native JsArray<Element> posProcess(String selector, Node context) /*-{ var tmpSet = [], later = "", match, root = context.nodeType ? [context] : context; // Position selectors must be done after the filter @@ -633,8 +633,8 @@ public class SelectorEngineSizzleGwt extends SelectorEngineImpl { @com.google.gwt.query.client.impl.research.SelectorEngineSizzleGwt::select(Ljava/lang/String;Lcom/google/gwt/dom/client/Node;Lcom/google/gwt/core/client/JsArray;Lcom/google/gwt/core/client/JsArray;)(selector, root[i], tmpSet, null); } return @com.google.gwt.query.client.impl.research.SelectorEngineSizzleGwt::filter(Ljava/lang/String;Lcom/google/gwt/core/client/JsArray;ZLjava/lang/Object;)( later, tmpSet, false ); - }-*/; - + }-*/; + private static native JsArray<Element> select(String selector, Node context, JsArray<Element> results, JsArray<Element> seed) /*-{ results = results || []; var origContext = context = context || document; @@ -725,13 +725,13 @@ public class SelectorEngineSizzleGwt extends SelectorEngineImpl { if ( extra ) { @com.google.gwt.query.client.impl.research.SelectorEngineSizzleGwt::select(Ljava/lang/String;Lcom/google/gwt/dom/client/Node;Lcom/google/gwt/core/client/JsArray;Lcom/google/gwt/core/client/JsArray;)(extra, origContext, results, seed); } - return results; + return results; }-*/; - + public SelectorEngineSizzleGwt() { createExpr(); } - + public NodeList<Element> select(String selector, Node context) { JsArray<Element> results = JavaScriptObject.createArray().cast(); return JsUtils.unique(select(selector, context, results, null)).cast(); diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineXPath.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineXPath.java index dc1bb2b3..63fe9229 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineXPath.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/research/SelectorEngineXPath.java @@ -1,251 +1,251 @@ -/*
- * 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.impl.research;
-
-import static com.google.gwt.query.client.js.JsUtils.eq;
-import static com.google.gwt.query.client.js.JsUtils.truth;
-
-import com.google.gwt.core.client.JsArray;
-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.query.client.impl.SelectorEngine;
-import com.google.gwt.query.client.impl.SelectorEngineImpl;
-import com.google.gwt.query.client.impl.research.SelectorEngineJS.Sequence;
-import com.google.gwt.query.client.impl.research.SelectorEngineJS.SplitRule;
-import com.google.gwt.query.client.js.JsNodeArray;
-import com.google.gwt.query.client.js.JsObjectArray;
-import com.google.gwt.query.client.js.JsRegexp;
-import com.google.gwt.query.client.js.JsUtils;
-
-
-/**
- * Runtime selector engine implementation which translates selectors to XPath
- * and delegates to document.evaluate().
- */
-public class SelectorEngineXPath extends SelectorEngineImpl {
-
- private static String attrToXPath(String match, String p1, String p2,
- String p3) {
- if (eq("^", p2)) {
- return "starts-with(@" + p1 + ", '" + p3 + "')";
- }
- if (eq("$", p2)) {
- return "substring(@" + p1 + ", (string-length(@" + p1 + ") - "
- + (p3.length() - 1) + "), " + p3.length() + ") = '" + p3 + "'";
- }
- if (eq("*", p2)) {
- return "contains(concat(' ', @" + p1 + ", ' '), '" + p3 + "')";
- }
- if (eq("|", p2)) {
- return "(@" + p1 + "='" + p3 + "' or starts-with(@" + p1 + ", '" + p3
- + "-'))";
- }
- if (eq("~", p2)) {
- return "contains(concat(' ', @" + p1 + ", ' '), ' " + p3 + " ')";
- }
- return "@" + p1 + (truth(p3) ? "='" + p3 + "'" : "");
- }
-
- private JsRegexp cssSelectorRegExp;
-
- private JsRegexp selectorSplitRegExp;
-
- private JsRegexp combinator;
-
- public SelectorEngineXPath() {
- }
-
- public NodeList<Element> select(String sel, Node ctx) {
- init();
- String selectors[] = sel.replaceAll("\\s*(,)\\s*", "$1").split(",");
- boolean identical = false;
- JsNodeArray elm = JsNodeArray.create();
- for (int a = 0, len = selectors.length; a < len; a++) {
- if (a > 0) {
- identical = false;
- for (int b = 0, bl = a; b < bl; b++) {
- if (eq(selectors[a], selectors[b])) {
- identical = true;
- break;
- }
- }
- if (identical) {
- continue;
- }
- }
- String currentRule = selectors[a];
- JsObjectArray<String> cssSelectors = selectorSplitRegExp.match(currentRule);
- String xPathExpression = ".";
- for (int i = 0, slen = cssSelectors.length(); i < slen; i++) {
- String rule = cssSelectors.get(i);
- JsObjectArray<String> cssSelector = cssSelectorRegExp.exec(rule);
- SplitRule splitRule = new SplitRule(
- !truth(cssSelector.get(1)) || eq(cssSelector.get(3), "*")
- ? "*" : cssSelector.get(1),
- !eq(cssSelector.get(3), "*") ? cssSelector.get(2) : null,
- cssSelector.get(4), cssSelector.get(6),
- cssSelector.get(10), cssSelector.get(22));
- if (truth(splitRule.tagRelation)) {
- if (eq(">", splitRule.tagRelation)) {
- xPathExpression += "/child::";
- } else if (eq("+", splitRule.tagRelation)) {
- xPathExpression += "/following-sibling::*[1]/self::";
- } else if (eq("~", splitRule.tagRelation)) {
- xPathExpression += "/following-sibling::";
- }
- } else {
- xPathExpression +=
- (i > 0 && combinator.test(cssSelectors.get(i - 1)))
- ? splitRule.tag : ("/descendant::" + splitRule.tag);
- }
- if (truth(splitRule.id)) {
- xPathExpression += "[@id = '" + splitRule.id.replaceAll("^#", "")
- + "']";
- }
- if (truth(splitRule.allClasses)) {
- xPathExpression += splitRule.allClasses
- .replaceAll("\\.([\\w\\u00C0-\\uFFFF\\-_]+)",
- "[contains(concat(' ', @class, ' '), ' $1 ')]");
- }
- if (truth(splitRule.allAttr)) {
- xPathExpression += replaceAttr(
- JsUtils.or(splitRule.allAttr, ""));
- }
- if (truth(splitRule.allPseudos)) {
- JsRegexp pseudoSplitRegExp = new JsRegexp(
- ":(\\w[\\w\\-]*)(\\(([^\\)]+)\\))?");
- JsRegexp pseudoMatchRegExp = new JsRegexp(
- "(:\\w+[\\w\\-]*)(\\([^\\)]+\\))?", "g");
- JsObjectArray<String> allPseudos = pseudoMatchRegExp.match(splitRule.allPseudos);
- for (int k = 0, kl = allPseudos.length(); k < kl; k++) {
- JsObjectArray<String> pseudo = pseudoSplitRegExp.match(allPseudos.get(k));
- String pseudoClass = truth(pseudo.get(1)) ? pseudo.get(1)
- .toLowerCase() : null;
- String pseudoValue = truth(pseudo.get(3)) ? pseudo.get(3)
- : null;
- String xpath = pseudoToXPath(splitRule.tag, pseudoClass,
- pseudoValue);
- if (xpath.length() > 0) {
- xPathExpression += "[" + xpath + "]";
- }
- }
- }
- }
- SelectorEngine.xpathEvaluate(xPathExpression, ctx, elm);
- }
- return JsUtils.unique(elm.<JsArray<Element>>cast()).cast();
- }
-
- private void init() {
- if (cssSelectorRegExp == null) {
- cssSelectorRegExp = new JsRegexp(
- "^(\\w+)?(#[\\w\\u00C0-\\uFFFF\\-\\_]+|(\\*))?((\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?((\\[\\w+(\\^|\\$|\\*|\\||~)?(=[\"']*[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+[\"']*)?\\]+)*)?(((:\\w+[\\w\\-]*)(\\((odd|even|\\-?\\d*n?((\\+|\\-)\\d+)?|[\\w\\u00C0-\\uFFFF\\-_]+|((\\w*\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?|(\\[#?\\w+(\\^|\\$|\\*|\\||~)?=?[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+\\]+)|(:\\w+[\\w\\-]*))\\))?)*)?(>|\\+|~)?");
- selectorSplitRegExp = new JsRegexp("[^\\s]+", "g");
- combinator = new JsRegexp("(>|\\+|~)");
- }
- }
-
- private String pseudoToXPath(String tag, String pseudoClass,
- String pseudoValue) {
- String xpath = "";
- if (eq("first-child", pseudoClass)) {
- xpath = "not(preceding-sibling::*)";
- } else if (eq("first-of-type", pseudoClass)) {
- xpath = "not(preceding-sibling::" + tag + ")";
- } else if (eq("last-child", pseudoClass)) {
- xpath = "not(following-sibling::*)";
- } else if (eq("last-of-type", pseudoClass)) {
- xpath = "not(following-sibling::" + tag + ")";
- } else if (eq("only-child", pseudoClass)) {
- xpath = "not(preceding-sibling::* or following-sibling::*)";
- } else if (eq("only-of-type", pseudoClass)) {
- xpath = "not(preceding-sibling::" + tag + " or following-sibling::" + tag
- + ")";
- } else if (eq("nth-child", pseudoClass)) {
- if (!eq("n", pseudoClass)) {
- Sequence sequence = SelectorEngineJS.getSequence(pseudoValue);
- if (sequence != null) {
- if (sequence.start == sequence.max) {
- xpath = "count(preceding-sibling::*) = " + (sequence.start - 1);
- } else {
- xpath = "(count(preceding-sibling::*) + 1) mod " + sequence.add
- + " = " + sequence.modVal
- + ((sequence.start > 1) ? " and count(preceding-sibling::*) >= "
- + (sequence.start - 1) : "") + ((sequence.max > 0) ?
- " and count(preceding-sibling::*) <= " + (sequence.max - 1)
- : "");
- }
- }
- }
- } else if (eq("nth-of-type", pseudoClass)) {
- if (!pseudoValue.startsWith("n")) {
- Sequence sequence = SelectorEngineJS.getSequence(pseudoValue);
- if (sequence != null) {
- if (sequence.start == sequence.max) {
- xpath = pseudoValue;
- } else {
- xpath = "position() mod " + sequence.add + " = " + sequence.modVal
- + ((sequence.start > 1) ? " and position() >= " + sequence.start
- : "") + ((sequence.max > 0) ? " and position() <= "
- + sequence.max : "");
- }
- }
- }
- } else if (eq("empty", pseudoClass)) {
- xpath = "count(child::*) = 0 and string-length(text()) = 0";
- } else if (eq("contains", pseudoClass)) {
- xpath = "contains(., '" + pseudoValue + "')";
- } else if (eq("enabled", pseudoClass)) {
- xpath = "not(@disabled)";
- } else if (eq("disabled", pseudoClass)) {
- xpath = "@disabled";
- } else if (eq("checked", pseudoClass)) {
- xpath = "@checked='checked'"; // Doesn't work in Opera 9.24
- } else if (eq("not", pseudoClass)) {
- if (new JsRegexp("^(:\\w+[\\w\\-]*)$").test(pseudoValue)) {
- xpath = "not(" + pseudoToXPath(tag, pseudoValue.substring(1), "") + ")";
- } else {
-
- pseudoValue = pseudoValue
- .replaceFirst("^\\[#([\\w\\u00C0-\\uFFFF\\-\\_]+)\\]$", "[id=$1]");
- String notSelector = pseudoValue.replaceFirst("^(\\w+)", "self::$1");
- notSelector = notSelector.replaceAll("^\\.([\\w\\u00C0-\\uFFFF\\-_]+)",
- "contains(concat(' ', @class, ' '), ' $1 ')");
- notSelector = replaceAttr2(notSelector);
- xpath = "not(" + notSelector + ")";
- }
- } else {
- xpath = "@" + pseudoClass + "='" + pseudoValue + "'";
- }
-
- return xpath;
- }
-
- private native String replaceAttr(String allAttr) /*-{
- if(!allAttr) return "";
- return allAttr.replace(/["']+/g,'').replace(/(\w+)(\^|\$|\*|\||~)?=?([\w\u00C0-\uFFFF\s\-_\.]+)?/g,
- function(a,b,c,d) {
- return @com.google.gwt.query.client.impl.research.SelectorEngineXPath::attrToXPath(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)(a,b || "",c || "",d || "");
- });
-
- }-*/;
-
- private native String replaceAttr2(String allAttr) /*-{
- if(!allAttr) return "";
- return allAttr.replace(/\[(\w+)(\^|\$|\*|\||~)?=?([\w\u00C0-\uFFFF\s\-_\.]+)?\]/g, @com.google.gwt.query.client.impl.research.SelectorEngineXPath::attrToXPath(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;));
- }-*/;
-}
+/* + * 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.impl.research; + +import static com.google.gwt.query.client.js.JsUtils.eq; +import static com.google.gwt.query.client.js.JsUtils.truth; + +import com.google.gwt.core.client.JsArray; +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.query.client.impl.SelectorEngine; +import com.google.gwt.query.client.impl.SelectorEngineImpl; +import com.google.gwt.query.client.impl.research.SelectorEngineJS.Sequence; +import com.google.gwt.query.client.impl.research.SelectorEngineJS.SplitRule; +import com.google.gwt.query.client.js.JsNodeArray; +import com.google.gwt.query.client.js.JsObjectArray; +import com.google.gwt.query.client.js.JsRegexp; +import com.google.gwt.query.client.js.JsUtils; + + +/** + * Runtime selector engine implementation which translates selectors to XPath + * and delegates to document.evaluate(). + */ +public class SelectorEngineXPath extends SelectorEngineImpl { + + private static String attrToXPath(String match, String p1, String p2, + String p3) { + if (eq("^", p2)) { + return "starts-with(@" + p1 + ", '" + p3 + "')"; + } + if (eq("$", p2)) { + return "substring(@" + p1 + ", (string-length(@" + p1 + ") - " + + (p3.length() - 1) + "), " + p3.length() + ") = '" + p3 + "'"; + } + if (eq("*", p2)) { + return "contains(concat(' ', @" + p1 + ", ' '), '" + p3 + "')"; + } + if (eq("|", p2)) { + return "(@" + p1 + "='" + p3 + "' or starts-with(@" + p1 + ", '" + p3 + + "-'))"; + } + if (eq("~", p2)) { + return "contains(concat(' ', @" + p1 + ", ' '), ' " + p3 + " ')"; + } + return "@" + p1 + (truth(p3) ? "='" + p3 + "'" : ""); + } + + private JsRegexp cssSelectorRegExp; + + private JsRegexp selectorSplitRegExp; + + private JsRegexp combinator; + + public SelectorEngineXPath() { + } + + public NodeList<Element> select(String sel, Node ctx) { + init(); + String selectors[] = sel.replaceAll("\\s*(,)\\s*", "$1").split(","); + boolean identical = false; + JsNodeArray elm = JsNodeArray.create(); + for (int a = 0, len = selectors.length; a < len; a++) { + if (a > 0) { + identical = false; + for (int b = 0, bl = a; b < bl; b++) { + if (eq(selectors[a], selectors[b])) { + identical = true; + break; + } + } + if (identical) { + continue; + } + } + String currentRule = selectors[a]; + JsObjectArray<String> cssSelectors = selectorSplitRegExp.match(currentRule); + String xPathExpression = "."; + for (int i = 0, slen = cssSelectors.length(); i < slen; i++) { + String rule = cssSelectors.get(i); + JsObjectArray<String> cssSelector = cssSelectorRegExp.exec(rule); + SplitRule splitRule = new SplitRule( + !truth(cssSelector.get(1)) || eq(cssSelector.get(3), "*") + ? "*" : cssSelector.get(1), + !eq(cssSelector.get(3), "*") ? cssSelector.get(2) : null, + cssSelector.get(4), cssSelector.get(6), + cssSelector.get(10), cssSelector.get(22)); + if (truth(splitRule.tagRelation)) { + if (eq(">", splitRule.tagRelation)) { + xPathExpression += "/child::"; + } else if (eq("+", splitRule.tagRelation)) { + xPathExpression += "/following-sibling::*[1]/self::"; + } else if (eq("~", splitRule.tagRelation)) { + xPathExpression += "/following-sibling::"; + } + } else { + xPathExpression += + (i > 0 && combinator.test(cssSelectors.get(i - 1))) + ? splitRule.tag : ("/descendant::" + splitRule.tag); + } + if (truth(splitRule.id)) { + xPathExpression += "[@id = '" + splitRule.id.replaceAll("^#", "") + + "']"; + } + if (truth(splitRule.allClasses)) { + xPathExpression += splitRule.allClasses + .replaceAll("\\.([\\w\\u00C0-\\uFFFF\\-_]+)", + "[contains(concat(' ', @class, ' '), ' $1 ')]"); + } + if (truth(splitRule.allAttr)) { + xPathExpression += replaceAttr( + JsUtils.or(splitRule.allAttr, "")); + } + if (truth(splitRule.allPseudos)) { + JsRegexp pseudoSplitRegExp = new JsRegexp( + ":(\\w[\\w\\-]*)(\\(([^\\)]+)\\))?"); + JsRegexp pseudoMatchRegExp = new JsRegexp( + "(:\\w+[\\w\\-]*)(\\([^\\)]+\\))?", "g"); + JsObjectArray<String> allPseudos = pseudoMatchRegExp.match(splitRule.allPseudos); + for (int k = 0, kl = allPseudos.length(); k < kl; k++) { + JsObjectArray<String> pseudo = pseudoSplitRegExp.match(allPseudos.get(k)); + String pseudoClass = truth(pseudo.get(1)) ? pseudo.get(1) + .toLowerCase() : null; + String pseudoValue = truth(pseudo.get(3)) ? pseudo.get(3) + : null; + String xpath = pseudoToXPath(splitRule.tag, pseudoClass, + pseudoValue); + if (xpath.length() > 0) { + xPathExpression += "[" + xpath + "]"; + } + } + } + } + SelectorEngine.xpathEvaluate(xPathExpression, ctx, elm); + } + return JsUtils.unique(elm.<JsArray<Element>>cast()).cast(); + } + + private void init() { + if (cssSelectorRegExp == null) { + cssSelectorRegExp = new JsRegexp( + "^(\\w+)?(#[\\w\\u00C0-\\uFFFF\\-\\_]+|(\\*))?((\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?((\\[\\w+(\\^|\\$|\\*|\\||~)?(=[\"']*[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+[\"']*)?\\]+)*)?(((:\\w+[\\w\\-]*)(\\((odd|even|\\-?\\d*n?((\\+|\\-)\\d+)?|[\\w\\u00C0-\\uFFFF\\-_]+|((\\w*\\.[\\w\\u00C0-\\uFFFF\\-_]+)*)?|(\\[#?\\w+(\\^|\\$|\\*|\\||~)?=?[\\w\\u00C0-\\uFFFF\\s\\-\\_\\.]+\\]+)|(:\\w+[\\w\\-]*))\\))?)*)?(>|\\+|~)?"); + selectorSplitRegExp = new JsRegexp("[^\\s]+", "g"); + combinator = new JsRegexp("(>|\\+|~)"); + } + } + + private String pseudoToXPath(String tag, String pseudoClass, + String pseudoValue) { + String xpath = ""; + if (eq("first-child", pseudoClass)) { + xpath = "not(preceding-sibling::*)"; + } else if (eq("first-of-type", pseudoClass)) { + xpath = "not(preceding-sibling::" + tag + ")"; + } else if (eq("last-child", pseudoClass)) { + xpath = "not(following-sibling::*)"; + } else if (eq("last-of-type", pseudoClass)) { + xpath = "not(following-sibling::" + tag + ")"; + } else if (eq("only-child", pseudoClass)) { + xpath = "not(preceding-sibling::* or following-sibling::*)"; + } else if (eq("only-of-type", pseudoClass)) { + xpath = "not(preceding-sibling::" + tag + " or following-sibling::" + tag + + ")"; + } else if (eq("nth-child", pseudoClass)) { + if (!eq("n", pseudoClass)) { + Sequence sequence = SelectorEngineJS.getSequence(pseudoValue); + if (sequence != null) { + if (sequence.start == sequence.max) { + xpath = "count(preceding-sibling::*) = " + (sequence.start - 1); + } else { + xpath = "(count(preceding-sibling::*) + 1) mod " + sequence.add + + " = " + sequence.modVal + + ((sequence.start > 1) ? " and count(preceding-sibling::*) >= " + + (sequence.start - 1) : "") + ((sequence.max > 0) ? + " and count(preceding-sibling::*) <= " + (sequence.max - 1) + : ""); + } + } + } + } else if (eq("nth-of-type", pseudoClass)) { + if (!pseudoValue.startsWith("n")) { + Sequence sequence = SelectorEngineJS.getSequence(pseudoValue); + if (sequence != null) { + if (sequence.start == sequence.max) { + xpath = pseudoValue; + } else { + xpath = "position() mod " + sequence.add + " = " + sequence.modVal + + ((sequence.start > 1) ? " and position() >= " + sequence.start + : "") + ((sequence.max > 0) ? " and position() <= " + + sequence.max : ""); + } + } + } + } else if (eq("empty", pseudoClass)) { + xpath = "count(child::*) = 0 and string-length(text()) = 0"; + } else if (eq("contains", pseudoClass)) { + xpath = "contains(., '" + pseudoValue + "')"; + } else if (eq("enabled", pseudoClass)) { + xpath = "not(@disabled)"; + } else if (eq("disabled", pseudoClass)) { + xpath = "@disabled"; + } else if (eq("checked", pseudoClass)) { + xpath = "@checked='checked'"; // Doesn't work in Opera 9.24 + } else if (eq("not", pseudoClass)) { + if (new JsRegexp("^(:\\w+[\\w\\-]*)$").test(pseudoValue)) { + xpath = "not(" + pseudoToXPath(tag, pseudoValue.substring(1), "") + ")"; + } else { + + pseudoValue = pseudoValue + .replaceFirst("^\\[#([\\w\\u00C0-\\uFFFF\\-\\_]+)\\]$", "[id=$1]"); + String notSelector = pseudoValue.replaceFirst("^(\\w+)", "self::$1"); + notSelector = notSelector.replaceAll("^\\.([\\w\\u00C0-\\uFFFF\\-_]+)", + "contains(concat(' ', @class, ' '), ' $1 ')"); + notSelector = replaceAttr2(notSelector); + xpath = "not(" + notSelector + ")"; + } + } else { + xpath = "@" + pseudoClass + "='" + pseudoValue + "'"; + } + + return xpath; + } + + private native String replaceAttr(String allAttr) /*-{ + if(!allAttr) return ""; + return allAttr.replace(/["']+/g,'').replace(/(\w+)(\^|\$|\*|\||~)?=?([\w\u00C0-\uFFFF\s\-_\.]+)?/g, + function(a,b,c,d) { + return @com.google.gwt.query.client.impl.research.SelectorEngineXPath::attrToXPath(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)(a,b || "",c || "",d || ""); + }); + + }-*/; + + private native String replaceAttr2(String allAttr) /*-{ + if(!allAttr) return ""; + return allAttr.replace(/\[(\w+)(\^|\$|\*|\||~)?=?([\w\u00C0-\uFFFF\s\-_\.]+)?\]/g, @com.google.gwt.query.client.impl.research.SelectorEngineXPath::attrToXPath(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)); + }-*/; +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java index 9de4ebc1..0220dca6 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java @@ -1,12 +1,12 @@ /* * 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 @@ -27,7 +27,7 @@ public class JsCache extends JavaScriptObject { protected JsCache() { } - + public static JsCache create() { return createObject().cast(); } @@ -35,7 +35,7 @@ public class JsCache extends JavaScriptObject { public final native void concat(Object ary) /*-{ if (ary) this.concat(ary); }-*/; - + public final void pushAll(JavaScriptObject prevElem) { checkNull(); JsCache c = prevElem.cast(); @@ -43,23 +43,23 @@ public class JsCache extends JavaScriptObject { put(length(), c.get(i)); } } - + public final native <T> void delete(T name) /*-{ delete this[name]; }-*/; public final native <T> void clear() /*-{ if (this.length) { - for (i = this.length - 1; i >= 0; i--) + for (i = this.length - 1; i >= 0; i--) delete this[i]; - this.length = 0; + this.length = 0; } }-*/; public final native <T> boolean exists(T name) /*-{ return !!this[name]; }-*/; - + public final native <R, T> R get(T id) /*-{ var r = this[id], t = typeof r; return r && t != 'number' && t != 'boolean' ? r : null; @@ -68,18 +68,18 @@ public class JsCache extends JavaScriptObject { public final <T> JsCache getCache(int id) { return (JsCache)get(id); } - + public final native <T> boolean getBoolean(T id) /*-{ var r = this[id], t = typeof r; return 'boolean' == r ? r : 'true' == String(r); }-*/; - + public final <T> float getFloat(T id) { return (float)getDouble(id); } public final native <T> double getDouble(T id) /*-{ - // HtmlUnit prints an 'Unknown property name in get valueOf' + // HtmlUnit prints an 'Unknown property name in get valueOf' // error here, but it is ok. var r = this[id] ? Number(this[id]) : 0; return r ? r : 0; @@ -92,7 +92,7 @@ public class JsCache extends JavaScriptObject { public final native <T> String getString(T id) /*-{ return this[id] == null ? null : String(this[id]); }-*/; - + public final native <T> JsArrayMixed getArray(T id) /*-{ var r = this[id]; if (r && Object.prototype.toString.call(r) == '[object Array]') { @@ -100,9 +100,9 @@ public class JsCache extends JavaScriptObject { } return null; }-*/; - + public final <T extends JavaScriptObject> T getJavaScriptObject(Object name) { - Object o = get(name); + Object o = get(name); return (o != null && o instanceof JavaScriptObject) ? ((JavaScriptObject)o).<T>cast() : null; } @@ -110,15 +110,15 @@ public class JsCache extends JavaScriptObject { for (k in this) return false; return true; }-*/; - + public final native int indexOf(Object o) /*-{ return this.indexOf(o); }-*/; - + public final native <T> void putBoolean(T id, boolean b) /*-{ this[id] = b; }-*/; - + public final native <T> void putNumber(T id, double n) /*-{ this[id] = n; }-*/; @@ -128,15 +128,15 @@ public class JsCache extends JavaScriptObject { }-*/; public final native int length() /*-{ - if (typeof(this.length) == 'number') + if (typeof(this.length) == 'number') return this.length; - + var key, ret = 0; // Chrome in DevMode injects a property to JS objects for (key in this) if (key != "__gwt_ObjectId") ret ++; - return ret; + return ret; }-*/; - + public final int[] indexes() { checkNull(); JsArrayString a = keysImpl(); @@ -150,7 +150,7 @@ public class JsCache extends JavaScriptObject { } return ret; } - + public final String[] keys() { checkNull(); JsArrayString a = keysImpl(); @@ -160,7 +160,7 @@ public class JsCache extends JavaScriptObject { } return ret; } - + public final Object[] elements() { String[] keys = keys(); Object[] ret = new Object[keys.length]; @@ -170,7 +170,7 @@ public class JsCache extends JavaScriptObject { } return ret; } - + public final String tostring() { String ret = getClass().getName() + "{ "; for (String k: keys()){ @@ -178,19 +178,19 @@ public class JsCache extends JavaScriptObject { } return ret + "}"; } - + // In dev-mode a null object casted to JavascriptObject does not throw a NPE public final void checkNull() { checkNull(this); } - + private final native JsArrayString keysImpl() /*-{ var key, keys=[]; // Chrome in DevMode injects a property to JS objects for(key in this) if (key != '__gwt_ObjectId') keys.push(String(key)); return keys; }-*/; - + /** * Throw a NPE when a js is null */ diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsClosure.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsClosure.java index c477c6d5..e47c4a3b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsClosure.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsClosure.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsMap.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsMap.java index dde46218..b0c1ebb1 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsMap.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsMap.java @@ -1,12 +1,12 @@ /* * 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 @@ -22,10 +22,10 @@ import com.google.gwt.core.client.JavaScriptObject; * Lightweight JSO backed implemented of a Map, using Object.hashCode() as key. */ final public class JsMap<S, T> extends JavaScriptObject { - + protected JsMap() { } - + private JsCache c() { return cast(); } @@ -42,7 +42,7 @@ final public class JsMap<S, T> extends JavaScriptObject { public void put(S key, T val) { c().put(key.hashCode(), val); } - + public final String[] keys() { return c().keys(); } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsNamedArray.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsNamedArray.java index 8aa538cf..552a7d21 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsNamedArray.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsNamedArray.java @@ -1,12 +1,12 @@ /* * 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 @@ -22,10 +22,10 @@ import com.google.gwt.core.client.JavaScriptObject; * Lightweight JSO backed implemented of a named array */ final public class JsNamedArray<T> extends JavaScriptObject { - + protected JsNamedArray() { } - + private JsCache c() { return cast(); } @@ -38,11 +38,11 @@ final public class JsNamedArray<T> extends JavaScriptObject { public void put(String key, T val) { c().put(key, val); } - + public final String[] keys() { return c().keys(); } - + public int length() { return c().length(); } @@ -50,7 +50,7 @@ final public class JsNamedArray<T> extends JavaScriptObject { public final Object[] values() { return c().elements(); } - + public final boolean exists(String key){ return c().exists(key); } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsNodeArray.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsNodeArray.java index 102cecb1..8b989a50 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsNodeArray.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsNodeArray.java @@ -1,88 +1,88 @@ -/*
- * 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.js;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Node;
-import com.google.gwt.dom.client.NodeList;
-
-/**
- * A Lightweight JSO class easily handle a node list.
- */
-public class JsNodeArray extends NodeList<Element> {
-
- public static JsNodeArray create() {
- return create((Node)null);
- }
-
- public static native JsNodeArray create(Node node) /*-{
- return node ? [node] : [];
- }-*/;
-
- public static JsNodeArray create(NodeList<?> nl) {
- JsNodeArray ret = create((Node)null);
- ret.pushAll(nl);
- return ret;
- }
-
- protected JsNodeArray(){
- }
-
- public final void addNode(Node n){
- c().add(n);
- }
-
- public final void addNode(Node n, int i) {
- c().add(i, n);
- }
-
- public final void concat(JsNodeArray ary) {
- c().concat(ary.c());
- }
-
- public final Element get(int i) {
- return getElement(i);
- }
-
- public final Element getElement(int i) {
- return c().get(i).cast();
- }
-
- public final Node getNode(int i) {
- return c().get(i);
- }
-
- public final int size() {
- return c().length();
- }
-
- private JsObjectArray<Node> c() {
- return cast();
- }
-
- public final void pushAll(JavaScriptObject prevElem) {
- c().pushAll(prevElem);
- }
-
- public final Element[] elements() {
- Element[] ret = new Element[size()];
- for (int i=0 ; i<size(); i++) {
- ret[i] = getElement(i);
- }
- return ret;
- }
-}
+/* + * 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.js; + +import com.google.gwt.core.client.JavaScriptObject; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.Node; +import com.google.gwt.dom.client.NodeList; + +/** + * A Lightweight JSO class easily handle a node list. + */ +public class JsNodeArray extends NodeList<Element> { + + public static JsNodeArray create() { + return create((Node)null); + } + + public static native JsNodeArray create(Node node) /*-{ + return node ? [node] : []; + }-*/; + + public static JsNodeArray create(NodeList<?> nl) { + JsNodeArray ret = create((Node)null); + ret.pushAll(nl); + return ret; + } + + protected JsNodeArray(){ + } + + public final void addNode(Node n){ + c().add(n); + } + + public final void addNode(Node n, int i) { + c().add(i, n); + } + + public final void concat(JsNodeArray ary) { + c().concat(ary.c()); + } + + public final Element get(int i) { + return getElement(i); + } + + public final Element getElement(int i) { + return c().get(i).cast(); + } + + public final Node getNode(int i) { + return c().get(i); + } + + public final int size() { + return c().length(); + } + + private JsObjectArray<Node> c() { + return cast(); + } + + public final void pushAll(JavaScriptObject prevElem) { + c().pushAll(prevElem); + } + + public final Element[] elements() { + Element[] ret = new Element[size()]; + for (int i=0 ; i<size(); i++) { + ret[i] = getElement(i); + } + return ret; + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsObjectArray.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsObjectArray.java index bc6768cf..1e8cf6a6 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsObjectArray.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsObjectArray.java @@ -1,12 +1,12 @@ /* * 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 @@ -21,14 +21,14 @@ import com.google.gwt.core.client.JavaScriptObject; * Lightweight JSO based array class that can store objects. */ public final class JsObjectArray<T> extends JavaScriptObject { - + public static <T> JsObjectArray<T> create() { return JavaScriptObject.createArray().cast(); } - + protected JsObjectArray() { } - + private JsCache c() { return cast(); } @@ -55,7 +55,7 @@ public final class JsObjectArray<T> extends JavaScriptObject { public void set(int i, T val) { c().put(i, val); } - + public void concat(JsObjectArray<T> ary) { c().concat(ary); } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsRegexp.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsRegexp.java index 71dbd9c3..7eeb0da5 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsRegexp.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsRegexp.java @@ -1,74 +1,74 @@ -/*
- * 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.js;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-/**
- * A wrapper around Javascript Regexps.
- */
-public class JsRegexp {
-
- public static native JavaScriptObject compile(String pat) /*-{
- return new RegExp(pat);
- }-*/;
-
- public static native JavaScriptObject compileFlags(String pat, String flags) /*-{
- return new RegExp(pat, flags);
- }-*/;
-
- public static JsObjectArray<String> match(String regexp, String flags, String string) {
- return new JsRegexp(regexp, flags).match(string);
- }
-
- private static native JsObjectArray<String> exec0(JavaScriptObject regexp, String str) /*-{
- return regexp.exec(str);
- }-*/;
-
- private final JavaScriptObject regexp;
-
- public JsRegexp(String pattern) {
- this.regexp = compile(pattern);
- }
-
- public JsRegexp(String pat, String flags) {
- this.regexp = compileFlags(pat, flags);
- }
-
- public JsObjectArray<String> exec(String str) {
- return exec0(regexp, str);
- }
-
- public JsObjectArray<String> match(String currentRule) {
- return match0(regexp, currentRule);
- }
-
- public boolean test(String rule) {
- return test0(regexp, rule);
- }
-
- private native JsObjectArray<String> match0(JavaScriptObject regexp, String currentRule)/*-{
- return currentRule.match(regexp);
- }-*/;
-
- private native boolean test0(JavaScriptObject regexp, String rule) /*-{
- return regexp.test(rule);
- }-*/;
-
- public String getPattern(){
- return regexp.toString();
- };
-}
+/* + * 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.js; + +import com.google.gwt.core.client.JavaScriptObject; + +/** + * A wrapper around Javascript Regexps. + */ +public class JsRegexp { + + public static native JavaScriptObject compile(String pat) /*-{ + return new RegExp(pat); + }-*/; + + public static native JavaScriptObject compileFlags(String pat, String flags) /*-{ + return new RegExp(pat, flags); + }-*/; + + public static JsObjectArray<String> match(String regexp, String flags, String string) { + return new JsRegexp(regexp, flags).match(string); + } + + private static native JsObjectArray<String> exec0(JavaScriptObject regexp, String str) /*-{ + return regexp.exec(str); + }-*/; + + private final JavaScriptObject regexp; + + public JsRegexp(String pattern) { + this.regexp = compile(pattern); + } + + public JsRegexp(String pat, String flags) { + this.regexp = compileFlags(pat, flags); + } + + public JsObjectArray<String> exec(String str) { + return exec0(regexp, str); + } + + public JsObjectArray<String> match(String currentRule) { + return match0(regexp, currentRule); + } + + public boolean test(String rule) { + return test0(regexp, rule); + } + + private native JsObjectArray<String> match0(JavaScriptObject regexp, String currentRule)/*-{ + return currentRule.match(regexp); + }-*/; + + private native boolean test0(JavaScriptObject regexp, String rule) /*-{ + return regexp.test(rule); + }-*/; + + public String getPattern(){ + return regexp.toString(); + }; +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java index 3a44b60c..61abd67e 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java @@ -1,12 +1,12 @@ /* * 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 @@ -51,7 +51,7 @@ public class JsUtils { private native void exec(JavaScriptObject f, Object data) /*-{ f(data); }-*/; - + public void f() { if (jso != null) { exec(jso, getDataObject()); @@ -67,7 +67,7 @@ public class JsUtils { public native Properties parseJSON(String json) /*-{ return $wnd.JSON.parse(json); }-*/; - + public native String JSON2String(JavaScriptObject o) /*-{ return $wnd.JSON.stringify(o); }-*/; @@ -110,7 +110,7 @@ public class JsUtils { // a well-formed json string. return evalImpl("(" + json + ")"); } - + @Override public String JSON2String(JavaScriptObject js) { // This is a very basic implementation for IE6/IE7 of JSON.stringify @@ -274,18 +274,18 @@ public class JsUtils { return e.defaultPrevented || e.returnValue === false || e.getPreventDefault && e.getPreventDefault() ? true : false; }-*/; - + /** * Return whether a node is detached to the dom - * Be careful : This method works only on node that should be inserted within the body node. + * Be careful : This method works only on node that should be inserted within the body node. */ public static boolean isDetached(Node n) { assert n != null; - + if ("html".equalsIgnoreCase(n.getNodeName())){ return false; } - + return !getOwnerDocument(n).getBody().isOrHasChild(n); } @@ -334,7 +334,7 @@ public class JsUtils { ? false : !"HTML".equals(getOwnerDocument(o).getDocumentElement().getNodeName()); } - + /** * Load an external javascript library. The inserted script replaces the * element with the given id in the document. @@ -414,14 +414,14 @@ public class JsUtils { public static String XML2String(JavaScriptObject js) { return utilsImpl.XML2String(js); } - + public static String JSON2String(JavaScriptObject js) { return utilsImpl.JSON2String(js); } - + /** * Returns a QueryString representation of a JavascriptObject. - * TODO: jquery implementation accepts a second parameter (traditional) + * TODO: jquery implementation accepts a second parameter (traditional) */ public static String param(JavaScriptObject js) { Properties prop = js.cast(); @@ -447,7 +447,7 @@ public class JsUtils { String v = prop.getStr(k); if (v != null && !v.isEmpty() && !"null".equalsIgnoreCase(v)) { ret += k + "=" + v; - } + } } } } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Effects.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Effects.java index 604ab6e6..ff8eac49 100755 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Effects.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Effects.java @@ -1,599 +1,599 @@ -/*
- * 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.plugins;
-
-import com.google.gwt.animation.client.Animation;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.query.client.Function;
-import com.google.gwt.query.client.GQuery;
-import com.google.gwt.query.client.Properties;
-import com.google.gwt.query.client.plugins.effects.ClipAnimation;
-import com.google.gwt.query.client.plugins.effects.ClipAnimation.Action;
-import com.google.gwt.query.client.plugins.effects.ClipAnimation.Direction;
-import com.google.gwt.query.client.plugins.effects.Fx;
-import com.google.gwt.query.client.plugins.effects.PropertiesAnimation;
-import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing;
-
-/**
- * Effects plugin for Gwt Query.
- */
-public class Effects extends QueuePlugin<Effects> {
-
- /**
- * Class to access protected methods in Animation.
- */
- public static abstract class GQAnimation extends Animation {
-
- private static final String ACTUAL_ANIMATION = "EffectsRunnning";
-
- // Each Animation is associated to one element
- protected Element e;
-
- protected void onStart() {
- // Mark this animation as actual, so as we can stop it in the GQuery.stop() method
- $(e).data(ACTUAL_ANIMATION, this);
- super.onStart();
- }
- protected void onComplete() {
- // avoid memory leak (issue #132)
- $(e).removeData(ACTUAL_ANIMATION);
- super.onComplete();
- }
- public void cancel() {
- // avoid memory leak (issue #132)
- $(e).removeData(ACTUAL_ANIMATION);
- super.cancel();
- }
- }
-
- /**
- * Just a class to store predefined speed constant values.
- */
- public static class Speed {
- public static final int DEFAULT = 400;
- public static final int FAST = 200;
- public static final int SLOW = 600;
- }
-
-
- public static final Class<Effects> Effects = GQuery.registerPlugin(
- Effects.class, new Plugin<Effects>() {
- public Effects init(GQuery gq) {
- return new Effects(gq);
- }
- });
-
- protected Effects(GQuery gq) {
- super(gq);
- }
-
- private void queueAnimation(final Element e, final GQAnimation anim, final int duration) {
- if (isOff()) {
- anim.onStart();
- anim.onComplete();
- } else {
- queue(e, DEFAULT_NAME, new Function() {
- public void cancel(Element e) {
- Animation anim = (Animation) data(e, GQAnimation.ACTUAL_ANIMATION, null);
- if (anim != null) {
- anim.cancel();
- }
- }
- public void f(Element e) {
- anim.run(duration);
- }
- });
- }
- }
-
- protected boolean isOff() {
- return Fx.off;
- }
-
- /**
- * The animate() method allows you to create animation effects on any numeric
- * Attribute, CSS property, or color CSS property.
- *
- * Concerning to numeric properties, values are treated as a number of pixels
- * unless otherwise specified. The units em and % can be specified where
- * applicable.
- *
- * By default animate considers css properties, if you wanted to animate element
- * attributes you should to prepend the symbol dollar to the attribute name.
- *
- * Example:
- *
- * <pre class="code">
- * //move the element from its original position to the position top:500px and left:500px for 400ms.
- * //use a swing easing function for the transition
- * $("#foo").animate(Properties.create("{top:'500px',left:'500px'}"), 400, Easing.SWING);
- * // Change the width and border attributes of a table
- * $("table").animate(Properties.create("{$width: '500', $border: '10'}"), 400, Easing.LINEAR);
- * </pre>
- *
- * In addition to numeric values, each property can take the strings 'show',
- * 'hide', and 'toggle'. These shortcuts allow for custom hiding and showing
- * animations that take into account the display type of the element. Animated
- * properties can also be relative. If a value is supplied with a leading +=
- * or -= sequence of characters, then the target value is computed by adding
- * or subtracting the given number from the current value of the property.
- *
- * Example:
- *
- * <pre class="code">
- * //move the element from its original position to 500px to the left and 5OOpx down for 400ms.
- * //use a swing easing function for the transition
- * $("#foo").animate(Properties.create("{top:'+=500px',left:'+=500px'}"), 400, Easing.SWING);
- * </pre>
- *
- * For color css properties, values can be specified via hexadecimal or rgb or
- * literal values.
- *
- * Example:
- *
- * <pre class="code">
- * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'", 400, Easing.SWING);
- * $("#foo").animate($$("{backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'}"), 400, Easing.SWING);
- * </pre>
- *
- * @param p a {@link Properties} object containing css properties to animate.
- * @param funcs an array of {@link Function} called once the animation is
- * complete
- * @param duration the duration in milliseconds of the animation
- * @param easing the easing function to use for the transition
- */
- public Effects animate(Object stringOrProperties, final int duration,
- final Easing easing, final Function... funcs) {
-
- final Properties p = (stringOrProperties instanceof String)
- ? $$((String) stringOrProperties) : (Properties) stringOrProperties;
-
- for (Element e: elements()) {
- queueAnimation(e, new PropertiesAnimation(easing, e, p, funcs), duration);
- }
- return this;
- }
-
- /**
- *
- * The animate() method allows you to create animation effects on any numeric
- * Attribute, CSS property, or color CSS property.
- *
- * Concerning to numeric properties, values are treated as a number of pixels
- * unless otherwise specified. The units em and % can be specified where
- * applicable.
- *
- * By default animate considers css properties, if you wanted to animate element
- * attributes you should to prepend the symbol dollar to the attribute name.
- *
- * Example:
- *
- * <pre class="code">
- * //move the element from its original position to left:500px for 500ms
- * $("#foo").animate("left:'500'");
- * // Change the width attribute of a table
- * $("table").animate("$width:'500'"), 400, Easing.LINEAR);
- * </pre>
- *
- * In addition to numeric values, each property can take the strings 'show',
- * 'hide', and 'toggle'. These shortcuts allow for custom hiding and showing
- * animations that take into account the display type of the element. Animated
- * properties can also be relative. If a value is supplied with a leading +=
- * or -= sequence of characters, then the target value is computed by adding
- * or subtracting the given number from the current value of the property.
- *
- * Example:
- *
- * <pre class="code">
- * //move the element from its original position to 500px to the left for 500ms and
- * // change the background color of the element at the end of the animation
- * $("#foo").animate("left:'+=500'", new Function(){
- *
- * public void f(Element e){
- * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED);
- * }
- *
- * });
- * </pre>
- *
- * The duration of the animation is 500ms.
- *
- * For color css properties, values can be specified via hexadecimal or rgb or
- * literal values.
- *
- * Example:
- *
- * <pre class="code">
- * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'");
- * </pre>
- *
- * @param prop the property to animate : "cssName:'value'"
- * @param funcs an array of {@link Function} called once the animation is
- * complete
- */
- public Effects animate(Object stringOrProperties, Function... funcs) {
- return animate(stringOrProperties, 500, funcs);
- }
-
- /**
- * The animate() method allows you to create animation effects on any numeric
- * Attribute, CSS properties, or color CSS property.
- *
- * Concerning to numeric property, values are treated as a number of pixels
- * unless otherwise specified. The units em and % can be specified where
- * applicable.
- *
- * By default animate considers css properties, if you wanted to animate element
- * attributes you should to prepend the symbol dollar to the attribute name.
- *
- * Example:
- *
- * <pre class="code">
- * //move the element from its original position to left:500px for 2s
- * $("#foo").animate("left:'500px'", 2000);
- * // Change the width attribute of a table
- * $("table").animate("$width:'500'"), 400);
- * </pre>
- *
- * In addition to numeric values, each property can take the strings 'show',
- * 'hide', and 'toggle'. These shortcuts allow for custom hiding and showing
- * animations that take into account the display type of the element. Animated
- * properties can also be relative. If a value is supplied with a leading +=
- * or -= sequence of characters, then the target value is computed by adding
- * or subtracting the given number from the current value of the property.
- *
- * Example:
- *
- * <pre class="code">
- * //move the element from its original position to 500px to the left for 1000ms and
- * // change the background color of the element at the end of the animation
- * $("#foo").animate("left:'+=500'", 1000, new Function(){
- * public void f(Element e){
- * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED);
- * }
- * });
- * </pre>
- *
- *
- * For color css properties, values can be specified via hexadecimal or rgb or
- * literal values.
- *
- * Example:
- *
- * <pre class="code">
- * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)', 1000");
- * </pre>
- *
- *
- * @param prop the property to animate : "cssName:'value'"
- * @param funcs an array of {@link Function} called once the animation is
- * complete
- * @param duration the duration in milliseconds of the animation
- */
- public Effects animate(Object stringOrProperties, int duration, Function... funcs) {
- return animate(stringOrProperties, duration, Easing.LINEAR, funcs);
- }
-
- /**
- * Animate the set of matched elements using the clip property. It is possible
- * to show or hide a set of elements, specify the direction of the animation
- * and the start corner of the effect. Finally it executes the set of
- * functions passed as arguments.
- */
- public Effects clip(ClipAnimation.Action a, ClipAnimation.Corner c,
- ClipAnimation.Direction d, Function... f) {
- return clip(a, c, d, Speed.DEFAULT, f);
- }
-
- /**
- * Animate the set of matched elements using the clip property. It is possible
- * to show or hide a set of elements, specify the direction of the animation
- * and the start corner of the effect. Finally it executes the set of
- * functions passed as arguments.
- */
- public Effects clip(final ClipAnimation.Action a,
- final ClipAnimation.Corner c, final ClipAnimation.Direction d,
- final int duration, final Function... f) {
-
- for (Element e : elements()) {
- queueAnimation(e, new ClipAnimation(e, a, c, d, f), duration);
- }
- return this;
- }
-
- /**
- * Animate the set of matched elements using the clip property. It is possible
- * to show or hide a set of elements, specify the direction of the animation
- * and the start corner of the effect. Finally it executes the set of
- * functions passed as arguments.
- */
- public Effects clip(ClipAnimation.Action a, ClipAnimation.Corner c,
- Function... f) {
- return clip(a, c, Direction.BIDIRECTIONAL, Speed.DEFAULT, f);
- }
-
- /**
- * Reveal all matched elements by adjusting the clip property firing an
- * optional callback after completion. The effect goes from the center to the
- * perimeter.
- */
- public Effects clipAppear(Function... f) {
- return clipAppear(Speed.DEFAULT, f);
- }
-
- /**
- * Reveal all matched elements by adjusting the clip property firing an
- * optional callback after completion. The effect goes from the center to the
- * perimeter.
- */
- public Effects clipAppear(int millisecs, Function... f) {
- return clip(ClipAnimation.Action.SHOW, ClipAnimation.Corner.CENTER,
- ClipAnimation.Direction.BIDIRECTIONAL, millisecs, f);
- }
-
- /**
- * Hide all matched elements by adjusting the clip property firing an optional
- * callback after completion. The effect goes from the perimeter to the
- * center.
- */
- public Effects clipDisappear(Function... f) {
- return clipDisappear(Speed.DEFAULT, f);
- }
-
- /**
- * Hide all matched elements by adjusting the clip property firing an optional
- * callback after completion. The effect goes from the perimeter to the
- * center.
- */
- public Effects clipDisappear(int millisecs, Function... f) {
- return clip(ClipAnimation.Action.HIDE, ClipAnimation.Corner.CENTER,
- ClipAnimation.Direction.BIDIRECTIONAL, millisecs, f);
- }
-
- /**
- * Reveal all matched elements by adjusting the clip property firing an
- * optional callback after completion. The effect goes from the top to the
- * bottom.
- */
- public Effects clipDown(Function... f) {
- return clipDown(Speed.DEFAULT, f);
- }
-
- /**
- * Reveal all matched elements by adjusting the clip property firing an
- * optional callback after completion. The effect goes from the top to the
- * bottom.
- */
- public Effects clipDown(int millisecs, Function... f) {
- return clip(Action.SHOW, ClipAnimation.Corner.TOP_LEFT,
- ClipAnimation.Direction.BIDIRECTIONAL, millisecs, f);
- }
-
- /**
- * Toggle the visibility of all matched elements by adjusting the clip
- * property and firing an optional callback after completion. The effect goes
- * from the bottom to the top.
- */
- public Effects clipToggle(Function... f) {
- return clipToggle(Speed.DEFAULT, f);
- }
-
- /**
- * Toggle the visibility of all matched elements by adjusting the clip
- * property and firing an optional callback after completion. The effect goes
- * from the bottom to the top.
- */
- public Effects clipToggle(int millisecs, Function... f) {
- return clip(Action.TOGGLE, ClipAnimation.Corner.TOP_LEFT,
- ClipAnimation.Direction.VERTICAL, millisecs, f);
- }
-
- /**
- * Hide all matched elements by adjusting the clip property firing an optional
- * callback after completion. The effect goes from the bottom to the top.
- */
- public Effects clipUp(Function... f) {
- return clipUp(Speed.DEFAULT, f);
- }
-
- /**
- * Hide all matched elements by adjusting the clip property firing an optional
- * callback after completion. The effect goes from the bottom to the top.
- */
- public Effects clipUp(int millisecs, Function... f) {
- return clip(Action.HIDE, ClipAnimation.Corner.TOP_LEFT,
- ClipAnimation.Direction.BIDIRECTIONAL, millisecs, f);
- }
-
- /**
- * Fade in all matched elements by adjusting their opacity and firing an
- * optional callback after completion. Only the opacity is adjusted for this
- * animation, meaning that all of the matched elements should already have
- * some form of height and width associated with them.
- */
- public Effects fadeIn(Function... f) {
- return fadeIn(Speed.DEFAULT, f);
- }
-
- /**
- * Fade in all matched elements by adjusting their opacity and firing an
- * optional callback after completion. Only the opacity is adjusted for this
- * animation, meaning that all of the matched elements should already have
- * some form of height and width associated with them.
- */
- public Effects fadeIn(int millisecs, Function... f) {
- return animate("opacity: 'show'", millisecs, f);
- }
-
- /**
- * Fade out all matched elements by adjusting their opacity to 0, then setting
- * display to "none" and firing an optional callback after completion. Only
- * the opacity is adjusted for this animation, meaning that all of the matched
- * elements should already have some form of height and width associated with
- * them.
- */
- public Effects fadeOut(Function... f) {
- return fadeOut(Speed.DEFAULT, f);
- }
-
- /**
- * Fade out all matched elements by adjusting their opacity to 0, then setting
- * display to "none" and firing an optional callback after completion. Only
- * the opacity is adjusted for this animation, meaning that all of the matched
- * elements should already have some form of height and width associated with
- * them.
- */
- public Effects fadeOut(int millisecs, Function... f) {
- return animate("opacity: 'hide'", millisecs, f);
- };
-
- /**
- * Fade the opacity of all matched elements to a specified opacity and firing
- * an optional callback after completion. Only the opacity is adjusted for
- * this animation, meaning that all of the matched elements should already
- * have some form of height and width associated with them.
- */
- public Effects fadeTo(int millisecs, double opacity, Function... f) {
- return animate("opacity: " + opacity, millisecs, f);
- }
-
- /**
- * Display or hide the matched elements by animating their opacity. and firing
- * an optional callback after completion. Only the opacity is adjusted for
- * this animation, meaning that all of the matched elements should already
- * have some form of height and width associated with them.
- */
- public Effects fadeToggle(Function... f) {
- return fadeToggle(Speed.DEFAULT, f);
- }
-
- /**
- * Display or hide the matched elements by animating their opacity. and firing
- * an optional callback after completion. Only the opacity is adjusted for
- * this animation, meaning that all of the matched elements should already
- * have some form of height and width associated with them.
- */
- public Effects fadeToggle(int millisecs, Function... f) {
- return animate("opacity: 'toggle'", millisecs, f);
- };
-
- /**
- * Reveal all matched elements by adjusting their height and firing an
- * optional callback after completion.
- */
- public Effects slideDown(Function... f) {
- return slideDown(Speed.DEFAULT, f);
- }
-
- /**
- * Reveal all matched elements by adjusting their height and firing an
- * optional callback after completion.
- */
- public Effects slideDown(int millisecs, Function... f) {
- return animate("height: 'show'", millisecs, f);
- }
-
- /**
- * Hide all matched elements by adjusting their width and firing an optional
- * callback after completion.
- */
- public Effects slideLeft(Function... f) {
- return slideLeft(Speed.DEFAULT, f);
- }
-
- /**
- * Hide all matched elements by adjusting their width and firing an optional
- * callback after completion.
- */
- public Effects slideLeft(int millisecs, Function... f) {
- return animate("width: 'hide'", millisecs, f);
- }
-
- /**
- * Reveal all matched elements by adjusting their width and firing an optional
- * callback after completion.
- */
- public Effects slideRight(Function... f) {
- return slideRight(Speed.DEFAULT, f);
- }
-
- /**
- * Reveal all matched elements by adjusting their width and firing an optional
- * callback after completion.
- */
- public Effects slideRight(final int millisecs, Function... f) {
- return animate("width: 'show'", millisecs, f);
- }
-
- /**
- * Toggle the visibility of all matched elements by adjusting their height and
- * firing an optional callback after completion. Only the height is adjusted
- * for this animation, causing all matched elements to be hidden or shown in a
- * "sliding" manner
- */
- public Effects slideToggle(int millisecs, Function... f) {
- return animate("height: 'toggle'", millisecs, f);
- }
-
- /**
- * Hide all matched elements by adjusting their height and firing an optional
- * callback after completion.
- */
- public Effects slideUp(Function... f) {
- return slideUp(Speed.DEFAULT, f);
- }
-
- /**
- * Hide all matched elements by adjusting their height and firing an optional
- * callback after completion.
- */
- public Effects slideUp(int millisecs, Function... f) {
- return animate("height: 'hide'", millisecs, f);
- }
-
-
- /**
- * Toggle displaying each of the set of matched elements.
- *
- * @param showOrHide A Boolean indicating whether to show or hide the
- * elements.
- */
- // maybe move this function in GQuery class directly ?
- public Effects toggle(boolean showOrHide) {
- for (Element element : elements()) {
- GQuery $element = $(element);
- if (!showOrHide) {
- $element.hide();
- } else {
- $element.show();
- }
-
- }
- return this;
- }
-
- /**
- * Toggle displaying each of the set of matched elements by animating the
- * width, height, and opacity of the matched elements simultaneously. When
- * these properties reach 0 after a hiding animation, the display style
- * property is set to none to ensure that the element no longer affects the
- * layout of the page.
- */
- public Effects toggle(int millisecs, Function... f) {
- return animate("opacity: 'toggle', width : 'toggle', height : 'toggle'",
- millisecs, f);
- }
-}
+/* + * 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.plugins; + +import com.google.gwt.animation.client.Animation; +import com.google.gwt.dom.client.Element; +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.GQuery; +import com.google.gwt.query.client.Properties; +import com.google.gwt.query.client.plugins.effects.ClipAnimation; +import com.google.gwt.query.client.plugins.effects.ClipAnimation.Action; +import com.google.gwt.query.client.plugins.effects.ClipAnimation.Direction; +import com.google.gwt.query.client.plugins.effects.Fx; +import com.google.gwt.query.client.plugins.effects.PropertiesAnimation; +import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing; + +/** + * Effects plugin for Gwt Query. + */ +public class Effects extends QueuePlugin<Effects> { + + /** + * Class to access protected methods in Animation. + */ + public static abstract class GQAnimation extends Animation { + + private static final String ACTUAL_ANIMATION = "EffectsRunnning"; + + // Each Animation is associated to one element + protected Element e; + + protected void onStart() { + // Mark this animation as actual, so as we can stop it in the GQuery.stop() method + $(e).data(ACTUAL_ANIMATION, this); + super.onStart(); + } + protected void onComplete() { + // avoid memory leak (issue #132) + $(e).removeData(ACTUAL_ANIMATION); + super.onComplete(); + } + public void cancel() { + // avoid memory leak (issue #132) + $(e).removeData(ACTUAL_ANIMATION); + super.cancel(); + } + } + + /** + * Just a class to store predefined speed constant values. + */ + public static class Speed { + public static final int DEFAULT = 400; + public static final int FAST = 200; + public static final int SLOW = 600; + } + + + public static final Class<Effects> Effects = GQuery.registerPlugin( + Effects.class, new Plugin<Effects>() { + public Effects init(GQuery gq) { + return new Effects(gq); + } + }); + + protected Effects(GQuery gq) { + super(gq); + } + + private void queueAnimation(final Element e, final GQAnimation anim, final int duration) { + if (isOff()) { + anim.onStart(); + anim.onComplete(); + } else { + queue(e, DEFAULT_NAME, new Function() { + public void cancel(Element e) { + Animation anim = (Animation) data(e, GQAnimation.ACTUAL_ANIMATION, null); + if (anim != null) { + anim.cancel(); + } + } + public void f(Element e) { + anim.run(duration); + } + }); + } + } + + protected boolean isOff() { + return Fx.off; + } + + /** + * The animate() method allows you to create animation effects on any numeric + * Attribute, CSS property, or color CSS property. + * + * Concerning to numeric properties, values are treated as a number of pixels + * unless otherwise specified. The units em and % can be specified where + * applicable. + * + * By default animate considers css properties, if you wanted to animate element + * attributes you should to prepend the symbol dollar to the attribute name. + * + * Example: + * + * <pre class="code"> + * //move the element from its original position to the position top:500px and left:500px for 400ms. + * //use a swing easing function for the transition + * $("#foo").animate(Properties.create("{top:'500px',left:'500px'}"), 400, Easing.SWING); + * // Change the width and border attributes of a table + * $("table").animate(Properties.create("{$width: '500', $border: '10'}"), 400, Easing.LINEAR); + * </pre> + * + * In addition to numeric values, each property can take the strings 'show', + * 'hide', and 'toggle'. These shortcuts allow for custom hiding and showing + * animations that take into account the display type of the element. Animated + * properties can also be relative. If a value is supplied with a leading += + * or -= sequence of characters, then the target value is computed by adding + * or subtracting the given number from the current value of the property. + * + * Example: + * + * <pre class="code"> + * //move the element from its original position to 500px to the left and 5OOpx down for 400ms. + * //use a swing easing function for the transition + * $("#foo").animate(Properties.create("{top:'+=500px',left:'+=500px'}"), 400, Easing.SWING); + * </pre> + * + * For color css properties, values can be specified via hexadecimal or rgb or + * literal values. + * + * Example: + * + * <pre class="code"> + * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'", 400, Easing.SWING); + * $("#foo").animate($$("{backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'}"), 400, Easing.SWING); + * </pre> + * + * @param p a {@link Properties} object containing css properties to animate. + * @param funcs an array of {@link Function} called once the animation is + * complete + * @param duration the duration in milliseconds of the animation + * @param easing the easing function to use for the transition + */ + public Effects animate(Object stringOrProperties, final int duration, + final Easing easing, final Function... funcs) { + + final Properties p = (stringOrProperties instanceof String) + ? $$((String) stringOrProperties) : (Properties) stringOrProperties; + + for (Element e: elements()) { + queueAnimation(e, new PropertiesAnimation(easing, e, p, funcs), duration); + } + return this; + } + + /** + * + * The animate() method allows you to create animation effects on any numeric + * Attribute, CSS property, or color CSS property. + * + * Concerning to numeric properties, values are treated as a number of pixels + * unless otherwise specified. The units em and % can be specified where + * applicable. + * + * By default animate considers css properties, if you wanted to animate element + * attributes you should to prepend the symbol dollar to the attribute name. + * + * Example: + * + * <pre class="code"> + * //move the element from its original position to left:500px for 500ms + * $("#foo").animate("left:'500'"); + * // Change the width attribute of a table + * $("table").animate("$width:'500'"), 400, Easing.LINEAR); + * </pre> + * + * In addition to numeric values, each property can take the strings 'show', + * 'hide', and 'toggle'. These shortcuts allow for custom hiding and showing + * animations that take into account the display type of the element. Animated + * properties can also be relative. If a value is supplied with a leading += + * or -= sequence of characters, then the target value is computed by adding + * or subtracting the given number from the current value of the property. + * + * Example: + * + * <pre class="code"> + * //move the element from its original position to 500px to the left for 500ms and + * // change the background color of the element at the end of the animation + * $("#foo").animate("left:'+=500'", new Function(){ + * + * public void f(Element e){ + * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED); + * } + * + * }); + * </pre> + * + * The duration of the animation is 500ms. + * + * For color css properties, values can be specified via hexadecimal or rgb or + * literal values. + * + * Example: + * + * <pre class="code"> + * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'"); + * </pre> + * + * @param prop the property to animate : "cssName:'value'" + * @param funcs an array of {@link Function} called once the animation is + * complete + */ + public Effects animate(Object stringOrProperties, Function... funcs) { + return animate(stringOrProperties, 500, funcs); + } + + /** + * The animate() method allows you to create animation effects on any numeric + * Attribute, CSS properties, or color CSS property. + * + * Concerning to numeric property, values are treated as a number of pixels + * unless otherwise specified. The units em and % can be specified where + * applicable. + * + * By default animate considers css properties, if you wanted to animate element + * attributes you should to prepend the symbol dollar to the attribute name. + * + * Example: + * + * <pre class="code"> + * //move the element from its original position to left:500px for 2s + * $("#foo").animate("left:'500px'", 2000); + * // Change the width attribute of a table + * $("table").animate("$width:'500'"), 400); + * </pre> + * + * In addition to numeric values, each property can take the strings 'show', + * 'hide', and 'toggle'. These shortcuts allow for custom hiding and showing + * animations that take into account the display type of the element. Animated + * properties can also be relative. If a value is supplied with a leading += + * or -= sequence of characters, then the target value is computed by adding + * or subtracting the given number from the current value of the property. + * + * Example: + * + * <pre class="code"> + * //move the element from its original position to 500px to the left for 1000ms and + * // change the background color of the element at the end of the animation + * $("#foo").animate("left:'+=500'", 1000, new Function(){ + * public void f(Element e){ + * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED); + * } + * }); + * </pre> + * + * + * For color css properties, values can be specified via hexadecimal or rgb or + * literal values. + * + * Example: + * + * <pre class="code"> + * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)', 1000"); + * </pre> + * + * + * @param prop the property to animate : "cssName:'value'" + * @param funcs an array of {@link Function} called once the animation is + * complete + * @param duration the duration in milliseconds of the animation + */ + public Effects animate(Object stringOrProperties, int duration, Function... funcs) { + return animate(stringOrProperties, duration, Easing.LINEAR, funcs); + } + + /** + * Animate the set of matched elements using the clip property. It is possible + * to show or hide a set of elements, specify the direction of the animation + * and the start corner of the effect. Finally it executes the set of + * functions passed as arguments. + */ + public Effects clip(ClipAnimation.Action a, ClipAnimation.Corner c, + ClipAnimation.Direction d, Function... f) { + return clip(a, c, d, Speed.DEFAULT, f); + } + + /** + * Animate the set of matched elements using the clip property. It is possible + * to show or hide a set of elements, specify the direction of the animation + * and the start corner of the effect. Finally it executes the set of + * functions passed as arguments. + */ + public Effects clip(final ClipAnimation.Action a, + final ClipAnimation.Corner c, final ClipAnimation.Direction d, + final int duration, final Function... f) { + + for (Element e : elements()) { + queueAnimation(e, new ClipAnimation(e, a, c, d, f), duration); + } + return this; + } + + /** + * Animate the set of matched elements using the clip property. It is possible + * to show or hide a set of elements, specify the direction of the animation + * and the start corner of the effect. Finally it executes the set of + * functions passed as arguments. + */ + public Effects clip(ClipAnimation.Action a, ClipAnimation.Corner c, + Function... f) { + return clip(a, c, Direction.BIDIRECTIONAL, Speed.DEFAULT, f); + } + + /** + * Reveal all matched elements by adjusting the clip property firing an + * optional callback after completion. The effect goes from the center to the + * perimeter. + */ + public Effects clipAppear(Function... f) { + return clipAppear(Speed.DEFAULT, f); + } + + /** + * Reveal all matched elements by adjusting the clip property firing an + * optional callback after completion. The effect goes from the center to the + * perimeter. + */ + public Effects clipAppear(int millisecs, Function... f) { + return clip(ClipAnimation.Action.SHOW, ClipAnimation.Corner.CENTER, + ClipAnimation.Direction.BIDIRECTIONAL, millisecs, f); + } + + /** + * Hide all matched elements by adjusting the clip property firing an optional + * callback after completion. The effect goes from the perimeter to the + * center. + */ + public Effects clipDisappear(Function... f) { + return clipDisappear(Speed.DEFAULT, f); + } + + /** + * Hide all matched elements by adjusting the clip property firing an optional + * callback after completion. The effect goes from the perimeter to the + * center. + */ + public Effects clipDisappear(int millisecs, Function... f) { + return clip(ClipAnimation.Action.HIDE, ClipAnimation.Corner.CENTER, + ClipAnimation.Direction.BIDIRECTIONAL, millisecs, f); + } + + /** + * Reveal all matched elements by adjusting the clip property firing an + * optional callback after completion. The effect goes from the top to the + * bottom. + */ + public Effects clipDown(Function... f) { + return clipDown(Speed.DEFAULT, f); + } + + /** + * Reveal all matched elements by adjusting the clip property firing an + * optional callback after completion. The effect goes from the top to the + * bottom. + */ + public Effects clipDown(int millisecs, Function... f) { + return clip(Action.SHOW, ClipAnimation.Corner.TOP_LEFT, + ClipAnimation.Direction.BIDIRECTIONAL, millisecs, f); + } + + /** + * Toggle the visibility of all matched elements by adjusting the clip + * property and firing an optional callback after completion. The effect goes + * from the bottom to the top. + */ + public Effects clipToggle(Function... f) { + return clipToggle(Speed.DEFAULT, f); + } + + /** + * Toggle the visibility of all matched elements by adjusting the clip + * property and firing an optional callback after completion. The effect goes + * from the bottom to the top. + */ + public Effects clipToggle(int millisecs, Function... f) { + return clip(Action.TOGGLE, ClipAnimation.Corner.TOP_LEFT, + ClipAnimation.Direction.VERTICAL, millisecs, f); + } + + /** + * Hide all matched elements by adjusting the clip property firing an optional + * callback after completion. The effect goes from the bottom to the top. + */ + public Effects clipUp(Function... f) { + return clipUp(Speed.DEFAULT, f); + } + + /** + * Hide all matched elements by adjusting the clip property firing an optional + * callback after completion. The effect goes from the bottom to the top. + */ + public Effects clipUp(int millisecs, Function... f) { + return clip(Action.HIDE, ClipAnimation.Corner.TOP_LEFT, + ClipAnimation.Direction.BIDIRECTIONAL, millisecs, f); + } + + /** + * Fade in all matched elements by adjusting their opacity and firing an + * optional callback after completion. Only the opacity is adjusted for this + * animation, meaning that all of the matched elements should already have + * some form of height and width associated with them. + */ + public Effects fadeIn(Function... f) { + return fadeIn(Speed.DEFAULT, f); + } + + /** + * Fade in all matched elements by adjusting their opacity and firing an + * optional callback after completion. Only the opacity is adjusted for this + * animation, meaning that all of the matched elements should already have + * some form of height and width associated with them. + */ + public Effects fadeIn(int millisecs, Function... f) { + return animate("opacity: 'show'", millisecs, f); + } + + /** + * Fade out all matched elements by adjusting their opacity to 0, then setting + * display to "none" and firing an optional callback after completion. Only + * the opacity is adjusted for this animation, meaning that all of the matched + * elements should already have some form of height and width associated with + * them. + */ + public Effects fadeOut(Function... f) { + return fadeOut(Speed.DEFAULT, f); + } + + /** + * Fade out all matched elements by adjusting their opacity to 0, then setting + * display to "none" and firing an optional callback after completion. Only + * the opacity is adjusted for this animation, meaning that all of the matched + * elements should already have some form of height and width associated with + * them. + */ + public Effects fadeOut(int millisecs, Function... f) { + return animate("opacity: 'hide'", millisecs, f); + }; + + /** + * Fade the opacity of all matched elements to a specified opacity and firing + * an optional callback after completion. Only the opacity is adjusted for + * this animation, meaning that all of the matched elements should already + * have some form of height and width associated with them. + */ + public Effects fadeTo(int millisecs, double opacity, Function... f) { + return animate("opacity: " + opacity, millisecs, f); + } + + /** + * Display or hide the matched elements by animating their opacity. and firing + * an optional callback after completion. Only the opacity is adjusted for + * this animation, meaning that all of the matched elements should already + * have some form of height and width associated with them. + */ + public Effects fadeToggle(Function... f) { + return fadeToggle(Speed.DEFAULT, f); + } + + /** + * Display or hide the matched elements by animating their opacity. and firing + * an optional callback after completion. Only the opacity is adjusted for + * this animation, meaning that all of the matched elements should already + * have some form of height and width associated with them. + */ + public Effects fadeToggle(int millisecs, Function... f) { + return animate("opacity: 'toggle'", millisecs, f); + }; + + /** + * Reveal all matched elements by adjusting their height and firing an + * optional callback after completion. + */ + public Effects slideDown(Function... f) { + return slideDown(Speed.DEFAULT, f); + } + + /** + * Reveal all matched elements by adjusting their height and firing an + * optional callback after completion. + */ + public Effects slideDown(int millisecs, Function... f) { + return animate("height: 'show'", millisecs, f); + } + + /** + * Hide all matched elements by adjusting their width and firing an optional + * callback after completion. + */ + public Effects slideLeft(Function... f) { + return slideLeft(Speed.DEFAULT, f); + } + + /** + * Hide all matched elements by adjusting their width and firing an optional + * callback after completion. + */ + public Effects slideLeft(int millisecs, Function... f) { + return animate("width: 'hide'", millisecs, f); + } + + /** + * Reveal all matched elements by adjusting their width and firing an optional + * callback after completion. + */ + public Effects slideRight(Function... f) { + return slideRight(Speed.DEFAULT, f); + } + + /** + * Reveal all matched elements by adjusting their width and firing an optional + * callback after completion. + */ + public Effects slideRight(final int millisecs, Function... f) { + return animate("width: 'show'", millisecs, f); + } + + /** + * Toggle the visibility of all matched elements by adjusting their height and + * firing an optional callback after completion. Only the height is adjusted + * for this animation, causing all matched elements to be hidden or shown in a + * "sliding" manner + */ + public Effects slideToggle(int millisecs, Function... f) { + return animate("height: 'toggle'", millisecs, f); + } + + /** + * Hide all matched elements by adjusting their height and firing an optional + * callback after completion. + */ + public Effects slideUp(Function... f) { + return slideUp(Speed.DEFAULT, f); + } + + /** + * Hide all matched elements by adjusting their height and firing an optional + * callback after completion. + */ + public Effects slideUp(int millisecs, Function... f) { + return animate("height: 'hide'", millisecs, f); + } + + + /** + * Toggle displaying each of the set of matched elements. + * + * @param showOrHide A Boolean indicating whether to show or hide the + * elements. + */ + // maybe move this function in GQuery class directly ? + public Effects toggle(boolean showOrHide) { + for (Element element : elements()) { + GQuery $element = $(element); + if (!showOrHide) { + $element.hide(); + } else { + $element.show(); + } + + } + return this; + } + + /** + * Toggle displaying each of the set of matched elements by animating the + * width, height, and opacity of the matched elements simultaneously. When + * these properties reach 0 after a hiding animation, the display style + * property is set to none to ensure that the element no longer affects the + * layout of the page. + */ + public Effects toggle(int millisecs, Function... f) { + return animate("opacity: 'toggle', width : 'toggle', height : 'toggle'", + millisecs, f); + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Events.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Events.java index d655bd83..4b558fe8 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Events.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Events.java @@ -1,11 +1,11 @@ /* * 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 @@ -48,12 +48,12 @@ public class Events extends GQuery { /** * Binds a set of handlers to a particular Event for each matched element. - * + * * The event handlers are passed as Functions that you can use to prevent default behavior. To * stop both default action and event bubbling, the function event handler has to return false. - * + * * You can pass an additional Object data to your Function as the second parameter - * + * */ public Events bind(int eventbits, Object data, Function... funcs) { for (Element e : elements()) { @@ -66,15 +66,15 @@ public class Events extends GQuery { /** * Binds a set of handlers to a particular Event for each matched element. - * + * * The namespace is a way to group events of the same type, making easier unbind specific * handlers. - * + * * The event handlers are passed as Functions that you can use to prevent default behavior. To * stop both default action and event bubbling, the function event handler has to return false. - * + * * You can pass an additional Object data to your Function - * + * */ public Events bind(int eventbits, String namespace, Object data, Function... funcs) { for (Element e : elements()) { @@ -87,15 +87,15 @@ public class Events extends GQuery { /** * Binds a set of handlers to a particular Event for each matched element. - * + * * The name could contain a namespace which is a way to group events of the same type, making * easier unbind specific handlers. - * + * * The event handlers are passed as Functions that you can use to prevent default behavior. To * stop both default action and event bubbling, the function event handler has to return false. - * + * * You can pass an additional Object data to your Function - * + * */ public Events bind(String event, Object data, Function... funcs) { for (Element e : elements()) { @@ -139,7 +139,7 @@ public class Events extends GQuery { /** * Bind an event handler to be fired when the mouse enter an element, or trigger that handler on * an element if no functions are provided. - * + * * The mouseenter event differs from mouseover in the way it handles event bubbling. When * mouseover is used on an element having inner element(s), then when the mouse pointer moves * hover of the Inner element, the handler would be triggered. This is usually undesirable @@ -160,7 +160,7 @@ public class Events extends GQuery { /** * Bind an event handler to be fired when the mouse leaves an element, or trigger that handler on * an element if no functions are provided. - * + * * The mouseleave event differs from mouseout in the way it handles event bubbling. When mouseout * is used on an element having inner element(s), then when the mouse pointer moves out of the * Inner element, the handler would be triggered. This is usually undesirable behavior. The @@ -181,10 +181,10 @@ public class Events extends GQuery { /** * Binds a handler to a particular Event (like Event.ONCLICK) for each matched element. The * handler is executed only once for each element. - * + * * The event handler is passed as a Function that you can use to prevent default behavior. To stop * both default action and event bubbling, the function event handler has to return false. - * + * * You can pass an additional Object data to your Function as the second parameter */ public Events one(int eventbits, final Object data, final Function f) { @@ -198,12 +198,12 @@ public class Events extends GQuery { /** * Execute all handlers and behaviors attached to the matched elements for the given event types. - * + * * Different event types can be passed joining these using the or bit wise operator. - * + * * For keyboard events you can pass a second parameter which represents the key-code of the pushed * key. - * + * * Example: fire(Event.ONCLICK | Event.ONFOCUS) Example: fire(Event.ONKEYDOWN. 'a'); */ public Events trigger(int eventbits, int... keys) { @@ -262,7 +262,7 @@ public class Events extends GQuery { /** * Trigger a html event in all matched elements. - * + * * @param htmlEvent An string representing the html event desired * @functions a set of function to run if the event is not canceled. */ @@ -284,7 +284,7 @@ public class Events extends GQuery { /** * Removes all handlers, that matches the events bits passed, from each element. - * + * * Example: unbind(Event.ONCLICK | Event.ONMOUSEOVER) */ public Events unbind(int eventbits) { @@ -298,7 +298,7 @@ public class Events extends GQuery { /** * Removes all handlers, that matches the events bits and the namespace passed, from each element. - * + * * Example: unbind(Event.ONCLICK | Event.ONMOUSEOVER, "my.namespace") */ public Events unbind(int eventbits, String name, Function f) { @@ -312,9 +312,9 @@ public class Events extends GQuery { /** * Removes all handlers, that matches the event name passed. - * + * * This name could contain a namespace. - * + * * Example: unbind("click.my.namespace") */ public Events unbind(String name) { @@ -324,7 +324,7 @@ public class Events extends GQuery { /** * Removes the function passed as parameter from the event list matching the event name passed. * This name could contain a namespace. - * + * * Example: unbind("click.my.namespace", myFunction) */ public Events unbind(String name, Function f) { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEffects.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEffects.java index cca7db83..77e113cc 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEffects.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEffects.java @@ -1,12 +1,12 @@ /* * 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 @@ -32,16 +32,16 @@ public interface LazyEffects<T> extends LazyBase<T>{ /** * The animate() method allows you to create animation effects on any numeric * Attribute, CSS property, or color CSS property. - * + * * Concerning to numeric properties, values are treated as a number of pixels * unless otherwise specified. The units em and % can be specified where * applicable. - * + * * By default animate considers css properties, if you wanted to animate element * attributes you should to prepend the symbol dollar to the attribute name. - * + * * Example: - * + * * <pre class="code"> * //move the element from its original position to the position top:500px and left:500px for 400ms. * //use a swing easing function for the transition @@ -49,32 +49,32 @@ public interface LazyEffects<T> extends LazyBase<T>{ * // Change the width and border attributes of a table * $("table").animate(Properties.create("{$width: '500', $border: '10'}"), 400, Easing.LINEAR); * </pre> - * + * * In addition to numeric values, each property can take the strings 'show', * 'hide', and 'toggle'. These shortcuts allow for custom hiding and showing * animations that take into account the display type of the element. Animated * properties can also be relative. If a value is supplied with a leading += * or -= sequence of characters, then the target value is computed by adding * or subtracting the given number from the current value of the property. - * + * * Example: - * + * * <pre class="code"> * //move the element from its original position to 500px to the left and 5OOpx down for 400ms. * //use a swing easing function for the transition * $("#foo").animate(Properties.create("{top:'+=500px',left:'+=500px'}"), 400, Easing.SWING); * </pre> - * + * * For color css properties, values can be specified via hexadecimal or rgb or * literal values. - * + * * Example: - * + * * <pre class="code"> * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'", 400, Easing.SWING); * $("#foo").animate($$("{backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'}"), 400, Easing.SWING); * </pre> - * + * * @param p a {@link Properties} object containing css properties to animate. * @param funcs an array of {@link Function} called once the animation is * complete @@ -84,58 +84,58 @@ public interface LazyEffects<T> extends LazyBase<T>{ LazyEffects<T> animate(Object stringOrProperties, int duration, Easing easing, Function... funcs); /** - * + * * The animate() method allows you to create animation effects on any numeric * Attribute, CSS property, or color CSS property. - * + * * Concerning to numeric properties, values are treated as a number of pixels * unless otherwise specified. The units em and % can be specified where * applicable. - * + * * By default animate considers css properties, if you wanted to animate element * attributes you should to prepend the symbol dollar to the attribute name. - * + * * Example: - * + * * <pre class="code"> * //move the element from its original position to left:500px for 500ms * $("#foo").animate("left:'500'"); * // Change the width attribute of a table * $("table").animate("$width:'500'"), 400, Easing.LINEAR); * </pre> - * + * * In addition to numeric values, each property can take the strings 'show', * 'hide', and 'toggle'. These shortcuts allow for custom hiding and showing * animations that take into account the display type of the element. Animated * properties can also be relative. If a value is supplied with a leading += * or -= sequence of characters, then the target value is computed by adding * or subtracting the given number from the current value of the property. - * + * * Example: - * + * * <pre class="code"> * //move the element from its original position to 500px to the left for 500ms and * // change the background color of the element at the end of the animation * $("#foo").animate("left:'+=500'", new Function(){ - * + * * public void f(Element e){ * $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED); * } - * + * * }); * </pre> - * + * * The duration of the animation is 500ms. - * + * * For color css properties, values can be specified via hexadecimal or rgb or * literal values. - * + * * Example: - * + * * <pre class="code"> * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'"); * </pre> - * + * * @param prop the property to animate : "cssName:'value'" * @param funcs an array of {@link Function} called once the animation is * complete @@ -145,32 +145,32 @@ public interface LazyEffects<T> extends LazyBase<T>{ /** * The animate() method allows you to create animation effects on any numeric * Attribute, CSS properties, or color CSS property. - * + * * Concerning to numeric property, values are treated as a number of pixels * unless otherwise specified. The units em and % can be specified where * applicable. - * + * * By default animate considers css properties, if you wanted to animate element * attributes you should to prepend the symbol dollar to the attribute name. - * + * * Example: - * + * * <pre class="code"> * //move the element from its original position to left:500px for 2s * $("#foo").animate("left:'500px'", 2000); * // Change the width attribute of a table * $("table").animate("$width:'500'"), 400); * </pre> - * + * * In addition to numeric values, each property can take the strings 'show', * 'hide', and 'toggle'. These shortcuts allow for custom hiding and showing * animations that take into account the display type of the element. Animated * properties can also be relative. If a value is supplied with a leading += * or -= sequence of characters, then the target value is computed by adding * or subtracting the given number from the current value of the property. - * + * * Example: - * + * * <pre class="code"> * //move the element from its original position to 500px to the left for 1000ms and * // change the background color of the element at the end of the animation @@ -180,18 +180,18 @@ public interface LazyEffects<T> extends LazyBase<T>{ * } * }); * </pre> - * - * + * + * * For color css properties, values can be specified via hexadecimal or rgb or * literal values. - * + * * Example: - * + * * <pre class="code"> * $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)', 1000"); * </pre> - * - * + * + * * @param prop the property to animate : "cssName:'value'" * @param funcs an array of {@link Function} called once the animation is * complete @@ -407,7 +407,7 @@ public interface LazyEffects<T> extends LazyBase<T>{ /** * Toggle displaying each of the set of matched elements. - * + * * @param showOrHide A Boolean indicating whether to show or hide the * elements. */ diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java index f0983351..08b96e7b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java @@ -1,11 +1,11 @@ /* * 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 @@ -28,40 +28,40 @@ public interface LazyEvents<T> extends LazyBase<T>{ /** * Binds a set of handlers to a particular Event for each matched element. - * + * * The event handlers are passed as Functions that you can use to prevent default behavior. To * stop both default action and event bubbling, the function event handler has to return false. - * + * * You can pass an additional Object data to your Function as the second parameter - * + * */ LazyEvents<T> bind(int eventbits, Object data, Function... funcs); /** * Binds a set of handlers to a particular Event for each matched element. - * + * * The namespace is a way to group events of the same type, making easier unbind specific * handlers. - * + * * The event handlers are passed as Functions that you can use to prevent default behavior. To * stop both default action and event bubbling, the function event handler has to return false. - * + * * You can pass an additional Object data to your Function - * + * */ LazyEvents<T> bind(int eventbits, String namespace, Object data, Function... funcs); /** * Binds a set of handlers to a particular Event for each matched element. - * + * * The name could contain a namespace which is a way to group events of the same type, making * easier unbind specific handlers. - * + * * The event handlers are passed as Functions that you can use to prevent default behavior. To * stop both default action and event bubbling, the function event handler has to return false. - * + * * You can pass an additional Object data to your Function - * + * */ LazyEvents<T> bind(String event, Object data, Function... funcs); @@ -81,7 +81,7 @@ public interface LazyEvents<T> extends LazyBase<T>{ /** * Bind an event handler to be fired when the mouse enter an element, or trigger that handler on * an element if no functions are provided. - * + * * The mouseenter event differs from mouseover in the way it handles event bubbling. When * mouseover is used on an element having inner element(s), then when the mouse pointer moves * hover of the Inner element, the handler would be triggered. This is usually undesirable @@ -93,7 +93,7 @@ public interface LazyEvents<T> extends LazyBase<T>{ /** * Bind an event handler to be fired when the mouse leaves an element, or trigger that handler on * an element if no functions are provided. - * + * * The mouseleave event differs from mouseout in the way it handles event bubbling. When mouseout * is used on an element having inner element(s), then when the mouse pointer moves out of the * Inner element, the handler would be triggered. This is usually undesirable behavior. The @@ -105,29 +105,29 @@ public interface LazyEvents<T> extends LazyBase<T>{ /** * Binds a handler to a particular Event (like Event.ONCLICK) for each matched element. The * handler is executed only once for each element. - * + * * The event handler is passed as a Function that you can use to prevent default behavior. To stop * both default action and event bubbling, the function event handler has to return false. - * + * * You can pass an additional Object data to your Function as the second parameter */ LazyEvents<T> one(int eventbits, Object data, Function f); /** * Execute all handlers and behaviors attached to the matched elements for the given event types. - * + * * Different event types can be passed joining these using the or bit wise operator. - * + * * For keyboard events you can pass a second parameter which represents the key-code of the pushed * key. - * + * * Example: fire(Event.ONCLICK | Event.ONFOCUS) Example: fire(Event.ONKEYDOWN. 'a'); */ LazyEvents<T> trigger(int eventbits, int... keys); /** * Trigger a html event in all matched elements. - * + * * @param htmlEvent An string representing the html event desired * @functions a set of function to run if the event is not canceled. */ @@ -135,23 +135,23 @@ public interface LazyEvents<T> extends LazyBase<T>{ /** * Removes all handlers, that matches the events bits passed, from each element. - * + * * Example: unbind(Event.ONCLICK | Event.ONMOUSEOVER) */ LazyEvents<T> unbind(int eventbits); /** * Removes all handlers, that matches the events bits and the namespace passed, from each element. - * + * * Example: unbind(Event.ONCLICK | Event.ONMOUSEOVER, "my.namespace") */ LazyEvents<T> unbind(int eventbits, String name, Function f); /** * Removes all handlers, that matches the event name passed. - * + * * This name could contain a namespace. - * + * * Example: unbind("click.my.namespace") */ LazyEvents<T> unbind(String name); @@ -159,7 +159,7 @@ public interface LazyEvents<T> extends LazyBase<T>{ /** * Removes the function passed as parameter from the event list matching the event name passed. * This name could contain a namespace. - * + * * Example: unbind("click.my.namespace", myFunction) */ LazyEvents<T> unbind(String name, Function f); diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyWidgets.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyWidgets.java index 5dc95a2a..eb2baf68 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyWidgets.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyWidgets.java @@ -1,12 +1,12 @@ /* * 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 @@ -48,7 +48,7 @@ public interface LazyWidgets<T> extends LazyBase<T>{ * Create a {@link Button} widget for each selected element. The * <code>initializers</code> will be called on each new {@link Button} created * by passing them in parameter. - * + * */ LazyWidgets<T> button(); @@ -56,7 +56,7 @@ public interface LazyWidgets<T> extends LazyBase<T>{ * Create a {@link Button} widget for each selected element. The * <code>initializers</code> will be called on each new {@link Button} created * by passing them in parameter. - * + * */ LazyWidgets<T> button(WidgetInitializer<Button> initializers); @@ -73,7 +73,7 @@ public interface LazyWidgets<T> extends LazyBase<T>{ * Create a {@link PasswordTextBox} widget for each selected element. The * <code>initializers</code> will be called on each new * {@link PasswordTextBox} created by passing them in parameter. - * + * */ LazyWidgets<T> passwordBox(WidgetInitializer<PasswordTextBox> initializers); @@ -81,7 +81,7 @@ public interface LazyWidgets<T> extends LazyBase<T>{ * Create a {@link TextBox} widget for each selected element. The * <code>initializers</code> will be called on each new {@link TextBox} * created by passing them in parameter. - * + * */ LazyWidgets<T> textBox(); @@ -89,7 +89,7 @@ public interface LazyWidgets<T> extends LazyBase<T>{ * Create a {@link TextBox} widget for each selected element. The * <code>initializers</code> will be called on each new {@link TextBox} * created by passing them in parameter. - * + * */ LazyWidgets<T> textBox(WidgetInitializer<TextBox> initializers); @@ -97,7 +97,7 @@ public interface LazyWidgets<T> extends LazyBase<T>{ * Create a {@link TextArea} widget for each selected element. The * <code>initializers</code> will be called on each new {@link TextBox} * created by passing them in parameter. - * + * */ LazyWidgets<T> textArea(); @@ -105,7 +105,7 @@ public interface LazyWidgets<T> extends LazyBase<T>{ * Create a {@link TextArea} widget for each selected element. The * <code>initializers</code> will be called on each new {@link TextBox} * created by passing them in parameter. - * + * */ LazyWidgets<T> textArea(WidgetInitializer<TextArea> initializers); diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/MouseOptions.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/MouseOptions.java index 81d088f2..4d010276 100755 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/MouseOptions.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/MouseOptions.java @@ -1,12 +1,12 @@ /* * 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 @@ -17,7 +17,7 @@ package com.google.gwt.query.client.plugins; /** * Object use to configure a Plugin extending {@link MousePlugin} - * + * */ public class MouseOptions { @@ -34,7 +34,7 @@ public class MouseOptions { /** * Return an array of css selectors. The plugin will not start when the mouse * interacts with the elements selected by the selectors. - * + * */ public String[] getCancel() { return cancel; @@ -44,7 +44,7 @@ public class MouseOptions { * Return the tolerance, in pixels, for when plugin should start. If * specified, the plugin will not start until after mouse is dragged beyond * distance. - * + * */ public int getDelay() { return delay; @@ -59,7 +59,7 @@ public class MouseOptions { /** * Prevents starting of the plugin on specified elements - * + * * @param cancel * array of css selectors */ @@ -70,7 +70,7 @@ public class MouseOptions { /** * Time in milliseconds to define when the plugin should start. It helps * preventing unwanted selections when clicking on an element. - * + * */ public void setDelay(int delay) { this.delay = delay; @@ -80,7 +80,7 @@ public class MouseOptions { * Tolerance, in pixels, for when plugin should start. If specified, the * plugin will not start until after mouse is dragged beyond distance. Default * : 1 - * + * */ public void setDistance(int distance) { this.distance = distance; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/MousePlugin.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/MousePlugin.java index cfc23677..25a74334 100755 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/MousePlugin.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/MousePlugin.java @@ -1,339 +1,339 @@ -/*
- * 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.plugins;
-
-import com.google.gwt.core.client.Duration;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.query.client.Function;
-import com.google.gwt.query.client.GQuery;
-import com.google.gwt.query.client.plugins.events.GqEvent;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.RootPanel;
-
-/**
- * Base class for all plug-in that need to handle some mouse interactions.
- *
- */
-public abstract class MousePlugin extends UiPlugin {
-
- private GqEvent startEvent;
- private boolean started = false;
- private Duration mouseUpDuration;
- private MouseOptions options;
- private boolean preventClickEvent = false;
- private boolean touchSupported = false;
- private int startX = -1;
- private int startY = -1;
-
- protected MousePlugin(GQuery gq) {
- super(gq);
- }
-
- protected void destroyMouseHandler() {
- as(Events)
- .unbind(Event.ONMOUSEDOWN | Event.ONCLICK | Event.ONTOUCHSTART, getPluginName(), null);
- }
-
- /**
- * Return a String identifying the plugin. This string is used as namespace when we bind handlers.
- *
- */
- protected abstract String getPluginName();
-
- /**
- * This method initialize all needed handlers
- *
- */
- protected void initMouseHandler(MouseOptions options) {
- this.options = options;
-
- for (final Element e : elements()) {
-
- $(e).as(Events).bind(Event.ONMOUSEDOWN, getPluginName(), (Object) null, new Function() {
- @Override
- public boolean f(com.google.gwt.user.client.Event event) {
- if (touchSupported) {
- return true;
- }
- return mouseDown(e, GqEvent.create(event));
-
- }
- }).bind(Event.ONTOUCHSTART, getPluginName(), (Object) null, new Function() {
- public boolean f(com.google.gwt.user.client.Event event) {
- if (event.getTouches().length() > 1) {
- return true;
- }
-
- touchSupported = true;
- return mouseDown(e, GqEvent.create(event));
-
- }
- }).bind(Event.ONCLICK, getPluginName(), (Object) null, new Function() {
- @Override
- public boolean f(com.google.gwt.user.client.Event event) {
- preventClickEvent |= !mouseClick(e, GqEvent.create(event));
-
- if (preventClickEvent) {
-
- preventClickEvent = false;
- event.stopPropagation();
- event.preventDefault();
- return false;
- }
-
- return true;
- }
- });
- }
-
- }
-
- /**
- * Test if the mouse down event must be handled by the plugin or not.
- *
- */
- protected boolean mouseCapture(Element draggable, GqEvent event) {
- return true;
- }
-
- /**
- * Method called when mouse click
- *
- */
- protected boolean mouseClick(Element element, GqEvent event) {
- return true;
- }
-
- /**
- * Method called when mouse down occur on the element.
- *
- * You should not override this method. Instead, override {@link #mouseStart(Element, GqEvent)}
- * method
- *
- */
- protected boolean mouseDown(Element element, GqEvent event) {
-
- // test if an other plugin handle the mouseStart
- if (isEventAlreadyHandled(event)) {
- return false;
- }
-
- if (started) { // case where we missed a mouseup
- mouseUp(element, event);
- }
-
- // calculate all interesting variables
- reset(event);
-
- if (notHandleMouseDown(element, event)) {
- return true;
- }
-
- if (delayConditionMet() && distanceConditionMet(event)) {
- started = mouseStart(element, event);
- if (!started) {
- event.getOriginalEvent().preventDefault();
- return true;
- }
- }
-
- bindOtherEvents(element);
-
- if (!touchSupported){ //click event are not triggered if we call preventDefault on touchstart event.
- event.getOriginalEvent().preventDefault();
- }
-
- markEventAsHandled(event);
-
- return true;
- }
-
- /**
- * Method called when the mouse is dragging
- *
- */
- protected abstract boolean mouseDrag(Element element, GqEvent event);
-
- /**
- * Method called on MouseMove event.
- *
- * You should not override this method. Instead, override {@link #mouseMove(Element, GqEvent)}
- * method
- *
- */
- protected boolean mouseMove(Element element, GqEvent event) {
-
- if (started) {
- event.getOriginalEvent().preventDefault();
- return mouseDrag(element, event);
- }
-
- if (delayConditionMet() && distanceConditionMet(event)) {
- started = mouseStart(element, startEvent);
- if (started) {
- mouseDrag(element, event);
- } else {
- mouseUp(element, event);
- }
- }
-
- return !started;
- }
-
- /**
- * Method called when the mouse is clicked and all conditions for starting the plugin are met.
- *
- */
- protected abstract boolean mouseStart(Element element, GqEvent event);
-
- /**
- * Method called when the mouse button is released
- *
- */
- protected abstract boolean mouseStop(Element element, GqEvent event);
-
- /**
- * Method called when mouse is released..
- *
- * You should not override this method. Instead, override {@link #mouseStop(Element, GqEvent)}
- * method
- *
- */
- protected boolean mouseUp(Element element, GqEvent event) {
-
- unbindOtherEvents();
- if (started) {
- started = false;
- preventClickEvent = (event.getCurrentEventTarget() == startEvent.getCurrentEventTarget());
- mouseStop(element, event);
- }
-
- return true;
-
- }
-
- private void bindOtherEvents(final Element element) {
-
- int moveEvent = touchSupported ? Event.ONTOUCHMOVE : Event.ONMOUSEMOVE;
-
- int endEvents = touchSupported ? Event.ONTOUCHEND : Event.ONMOUSEUP;
-
- $(document).as(Events).bind(moveEvent, getPluginName(), (Object) null, new Function() {
- @Override
- public boolean f(com.google.gwt.user.client.Event e) {
- mouseMove(element, (GqEvent) GqEvent.create(e));
- return false;
- }
- }).bind(endEvents, getPluginName(), (Object) null, new Function() {
- @Override
- public boolean f(com.google.gwt.user.client.Event e) {
- mouseUp(element, (GqEvent) GqEvent.create(e));
- return false;
- }
- });
-
- // TODO Event.ONTOUCHEND | Event.ONTOUCHCANCEL don't work -> investigate
- if (touchSupported) {
- $(document).as(Events).bind(Event.ONTOUCHCANCEL, getPluginName(), (Object) null,
- new Function() {
- @Override
- public boolean f(com.google.gwt.user.client.Event e) {
- mouseUp(element, (GqEvent) GqEvent.create(e));
- return false;
- }
- });
-
- }
-
- }
-
- private boolean delayConditionMet() {
-
- if (mouseUpDuration == null) {
- return false;
- }
-
- return options.getDelay() <= mouseUpDuration.elapsedMillis();
- }
-
- private boolean distanceConditionMet(GqEvent event) {
- int neededDistance = options.getDistance();
- int xDistance = Math.abs(startX - getClientX(event));
- int yDistance = Math.abs(startY - getClientY(event));
- // in jQuery-ui we take the greater distance between x and y... not really
- // good !
- // int mouseDistance = Math.max(xMouseDistance, yMouseDistance);
- // use Pythagor theorem !!
-
- int mouseDistance = (int) Math.sqrt(xDistance * xDistance + yDistance * yDistance);
- return mouseDistance >= neededDistance;
- }
-
- private native boolean isEventAlreadyHandled(GqEvent event)/*-{
- var result = event.mouseHandled ? event.mouseHandled : false;
- return result;
- }-*/;
-
- private native void markEventAsHandled(GqEvent event)/*-{
- event.mouseHandled = true;
- }-*/;
-
- private boolean notHandleMouseDown(Element element, GqEvent mouseDownEvent) {
- boolean isNotBoutonLeft = mouseDownEvent.getButton() != NativeEvent.BUTTON_LEFT;
- Element eventTarget = mouseDownEvent.getEventTarget().cast();
-
- boolean isElementCancel = false;
- if (options.getCancel() != null) {
- isElementCancel =
- $(eventTarget).parents().add($(eventTarget)).filter(options.getCancel()).length() > 0;
- }
-
- return isNotBoutonLeft || isElementCancel || !mouseCapture(element, mouseDownEvent);
-
- }
-
- private void reset(GqEvent nativeEvent) {
- this.startEvent = nativeEvent;
- this.startX = getClientX(nativeEvent);
- this.startY = getClientY(nativeEvent);
- this.mouseUpDuration = new Duration();
- }
-
- private void unbindOtherEvents() {
- int events =
- touchSupported ? Event.ONTOUCHCANCEL | Event.ONTOUCHEND | Event.ONTOUCHMOVE
- : Event.ONMOUSEUP | Event.ONMOUSEMOVE;
-
- $(document).as(Events).unbind(events, getPluginName(), null);
- }
-
- protected int getClientX(Event e) {
- if (touchSupported) {
- return e.getTouches().get(0).getClientX();
- } else {
- return e.getClientX();
- }
- }
-
- protected int getClientY(Event e) {
- if (touchSupported) {
- return e.getTouches().get(0).getClientY();
- } else {
- return e.getClientY();
- }
- }
-
-}
+/* + * 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.plugins; + +import com.google.gwt.core.client.Duration; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.NativeEvent; +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.GQuery; +import com.google.gwt.query.client.plugins.events.GqEvent; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.RootPanel; + +/** + * Base class for all plug-in that need to handle some mouse interactions. + * + */ +public abstract class MousePlugin extends UiPlugin { + + private GqEvent startEvent; + private boolean started = false; + private Duration mouseUpDuration; + private MouseOptions options; + private boolean preventClickEvent = false; + private boolean touchSupported = false; + private int startX = -1; + private int startY = -1; + + protected MousePlugin(GQuery gq) { + super(gq); + } + + protected void destroyMouseHandler() { + as(Events) + .unbind(Event.ONMOUSEDOWN | Event.ONCLICK | Event.ONTOUCHSTART, getPluginName(), null); + } + + /** + * Return a String identifying the plugin. This string is used as namespace when we bind handlers. + * + */ + protected abstract String getPluginName(); + + /** + * This method initialize all needed handlers + * + */ + protected void initMouseHandler(MouseOptions options) { + this.options = options; + + for (final Element e : elements()) { + + $(e).as(Events).bind(Event.ONMOUSEDOWN, getPluginName(), (Object) null, new Function() { + @Override + public boolean f(com.google.gwt.user.client.Event event) { + if (touchSupported) { + return true; + } + return mouseDown(e, GqEvent.create(event)); + + } + }).bind(Event.ONTOUCHSTART, getPluginName(), (Object) null, new Function() { + public boolean f(com.google.gwt.user.client.Event event) { + if (event.getTouches().length() > 1) { + return true; + } + + touchSupported = true; + return mouseDown(e, GqEvent.create(event)); + + } + }).bind(Event.ONCLICK, getPluginName(), (Object) null, new Function() { + @Override + public boolean f(com.google.gwt.user.client.Event event) { + preventClickEvent |= !mouseClick(e, GqEvent.create(event)); + + if (preventClickEvent) { + + preventClickEvent = false; + event.stopPropagation(); + event.preventDefault(); + return false; + } + + return true; + } + }); + } + + } + + /** + * Test if the mouse down event must be handled by the plugin or not. + * + */ + protected boolean mouseCapture(Element draggable, GqEvent event) { + return true; + } + + /** + * Method called when mouse click + * + */ + protected boolean mouseClick(Element element, GqEvent event) { + return true; + } + + /** + * Method called when mouse down occur on the element. + * + * You should not override this method. Instead, override {@link #mouseStart(Element, GqEvent)} + * method + * + */ + protected boolean mouseDown(Element element, GqEvent event) { + + // test if an other plugin handle the mouseStart + if (isEventAlreadyHandled(event)) { + return false; + } + + if (started) { // case where we missed a mouseup + mouseUp(element, event); + } + + // calculate all interesting variables + reset(event); + + if (notHandleMouseDown(element, event)) { + return true; + } + + if (delayConditionMet() && distanceConditionMet(event)) { + started = mouseStart(element, event); + if (!started) { + event.getOriginalEvent().preventDefault(); + return true; + } + } + + bindOtherEvents(element); + + if (!touchSupported){ //click event are not triggered if we call preventDefault on touchstart event. + event.getOriginalEvent().preventDefault(); + } + + markEventAsHandled(event); + + return true; + } + + /** + * Method called when the mouse is dragging + * + */ + protected abstract boolean mouseDrag(Element element, GqEvent event); + + /** + * Method called on MouseMove event. + * + * You should not override this method. Instead, override {@link #mouseMove(Element, GqEvent)} + * method + * + */ + protected boolean mouseMove(Element element, GqEvent event) { + + if (started) { + event.getOriginalEvent().preventDefault(); + return mouseDrag(element, event); + } + + if (delayConditionMet() && distanceConditionMet(event)) { + started = mouseStart(element, startEvent); + if (started) { + mouseDrag(element, event); + } else { + mouseUp(element, event); + } + } + + return !started; + } + + /** + * Method called when the mouse is clicked and all conditions for starting the plugin are met. + * + */ + protected abstract boolean mouseStart(Element element, GqEvent event); + + /** + * Method called when the mouse button is released + * + */ + protected abstract boolean mouseStop(Element element, GqEvent event); + + /** + * Method called when mouse is released.. + * + * You should not override this method. Instead, override {@link #mouseStop(Element, GqEvent)} + * method + * + */ + protected boolean mouseUp(Element element, GqEvent event) { + + unbindOtherEvents(); + if (started) { + started = false; + preventClickEvent = (event.getCurrentEventTarget() == startEvent.getCurrentEventTarget()); + mouseStop(element, event); + } + + return true; + + } + + private void bindOtherEvents(final Element element) { + + int moveEvent = touchSupported ? Event.ONTOUCHMOVE : Event.ONMOUSEMOVE; + + int endEvents = touchSupported ? Event.ONTOUCHEND : Event.ONMOUSEUP; + + $(document).as(Events).bind(moveEvent, getPluginName(), (Object) null, new Function() { + @Override + public boolean f(com.google.gwt.user.client.Event e) { + mouseMove(element, (GqEvent) GqEvent.create(e)); + return false; + } + }).bind(endEvents, getPluginName(), (Object) null, new Function() { + @Override + public boolean f(com.google.gwt.user.client.Event e) { + mouseUp(element, (GqEvent) GqEvent.create(e)); + return false; + } + }); + + // TODO Event.ONTOUCHEND | Event.ONTOUCHCANCEL don't work -> investigate + if (touchSupported) { + $(document).as(Events).bind(Event.ONTOUCHCANCEL, getPluginName(), (Object) null, + new Function() { + @Override + public boolean f(com.google.gwt.user.client.Event e) { + mouseUp(element, (GqEvent) GqEvent.create(e)); + return false; + } + }); + + } + + } + + private boolean delayConditionMet() { + + if (mouseUpDuration == null) { + return false; + } + + return options.getDelay() <= mouseUpDuration.elapsedMillis(); + } + + private boolean distanceConditionMet(GqEvent event) { + int neededDistance = options.getDistance(); + int xDistance = Math.abs(startX - getClientX(event)); + int yDistance = Math.abs(startY - getClientY(event)); + // in jQuery-ui we take the greater distance between x and y... not really + // good ! + // int mouseDistance = Math.max(xMouseDistance, yMouseDistance); + // use Pythagor theorem !! + + int mouseDistance = (int) Math.sqrt(xDistance * xDistance + yDistance * yDistance); + return mouseDistance >= neededDistance; + } + + private native boolean isEventAlreadyHandled(GqEvent event)/*-{ + var result = event.mouseHandled ? event.mouseHandled : false; + return result; + }-*/; + + private native void markEventAsHandled(GqEvent event)/*-{ + event.mouseHandled = true; + }-*/; + + private boolean notHandleMouseDown(Element element, GqEvent mouseDownEvent) { + boolean isNotBoutonLeft = mouseDownEvent.getButton() != NativeEvent.BUTTON_LEFT; + Element eventTarget = mouseDownEvent.getEventTarget().cast(); + + boolean isElementCancel = false; + if (options.getCancel() != null) { + isElementCancel = + $(eventTarget).parents().add($(eventTarget)).filter(options.getCancel()).length() > 0; + } + + return isNotBoutonLeft || isElementCancel || !mouseCapture(element, mouseDownEvent); + + } + + private void reset(GqEvent nativeEvent) { + this.startEvent = nativeEvent; + this.startX = getClientX(nativeEvent); + this.startY = getClientY(nativeEvent); + this.mouseUpDuration = new Duration(); + } + + private void unbindOtherEvents() { + int events = + touchSupported ? Event.ONTOUCHCANCEL | Event.ONTOUCHEND | Event.ONTOUCHMOVE + : Event.ONMOUSEUP | Event.ONMOUSEMOVE; + + $(document).as(Events).unbind(events, getPluginName(), null); + } + + protected int getClientX(Event e) { + if (touchSupported) { + return e.getTouches().get(0).getClientX(); + } else { + return e.getClientX(); + } + } + + protected int getClientY(Event e) { + if (touchSupported) { + return e.getTouches().get(0).getClientY(); + } else { + return e.getClientY(); + } + } + +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Plugin.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Plugin.java index 1783e6eb..02b59737 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Plugin.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Plugin.java @@ -1,33 +1,33 @@ -/*
- * 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.plugins;
-
-import com.google.gwt.query.client.GQuery;
-
-/**
- * A GQuery plugin. All GQuery plugins must implement this interface.
- *
- * @param <T> the plugin class
- */
-public interface Plugin<T extends GQuery> {
-
- /**
- * Called by the GQuery.as() method in order to pass the current matched set.
- * Typically a plugin will want to call a super class copy constructor in
- * order to copy the internal matched set of elements.
- */
- T init(GQuery gQuery);
-}
+/* + * 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.plugins; + +import com.google.gwt.query.client.GQuery; + +/** + * A GQuery plugin. All GQuery plugins must implement this interface. + * + * @param <T> the plugin class + */ +public interface Plugin<T extends GQuery> { + + /** + * Called by the GQuery.as() method in order to pass the current matched set. + * Typically a plugin will want to call a super class copy constructor in + * order to copy the internal matched set of elements. + */ + T init(GQuery gQuery); +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/QueuePlugin.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/QueuePlugin.java index 9cf43b7d..cee848da 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/QueuePlugin.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/QueuePlugin.java @@ -1,12 +1,12 @@ /* * 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 @@ -27,7 +27,7 @@ import java.util.Queue; * Class used in plugins which need a queue system. */ public class QueuePlugin<T extends QueuePlugin<?>> extends GQuery { - + @SuppressWarnings("rawtypes") public static final Class<QueuePlugin> Queue = GQuery.registerPlugin( QueuePlugin.class, new Plugin<QueuePlugin>() { @@ -71,7 +71,7 @@ public class QueuePlugin<T extends QueuePlugin<?>> extends GQuery { protected QueuePlugin(GQuery gq) { super(gq); } - + /** * remove all queued functions from the effects queue */ @@ -96,7 +96,7 @@ public class QueuePlugin<T extends QueuePlugin<?>> extends GQuery { public T delay(int milliseconds, Function... f) { return delay(milliseconds, DEFAULT_NAME, f); } - + /** * Add a delay in the named queue */ @@ -131,7 +131,7 @@ public class QueuePlugin<T extends QueuePlugin<?>> extends GQuery { public int queue() { return queue(DEFAULT_NAME); } - + /** * Show the number of functions to be executed on the first matched element * in the named queue. @@ -140,9 +140,9 @@ public class QueuePlugin<T extends QueuePlugin<?>> extends GQuery { Queue<Object> q = isEmpty() ? null : queue(get(0), name, null); return q == null? 0 : q.size(); } - + /** - * Adds new functions, to be executed, onto the end of the effects + * Adds new functions, to be executed, onto the end of the effects * queue of all matched elements. */ @SuppressWarnings("unchecked") @@ -156,7 +156,7 @@ public class QueuePlugin<T extends QueuePlugin<?>> extends GQuery { } /** - * Adds new functions, to be executed, onto the end of the named + * Adds new functions, to be executed, onto the end of the named * queue of all matched elements. */ @SuppressWarnings("unchecked") @@ -168,12 +168,12 @@ public class QueuePlugin<T extends QueuePlugin<?>> extends GQuery { } return (T)this; } - + /** * Replaces the current effects queue with the given queue on all matched elements. */ public T queue(Queue<?> queue) { - return queue(DEFAULT_NAME, queue); + return queue(DEFAULT_NAME, queue); } /** @@ -188,15 +188,15 @@ public class QueuePlugin<T extends QueuePlugin<?>> extends GQuery { } /** - * Stop the function which is currently in execution, remove it from the + * Stop the function which is currently in execution, remove it from the * effects queue and start the next one. */ public T stop() { return stop(false); } - + /** - * Stop the function which is currently in execution, remove it from the + * Stop the function which is currently in execution, remove it from the * named queue and start the next one. */ public T stop(String name) { @@ -205,46 +205,46 @@ public class QueuePlugin<T extends QueuePlugin<?>> extends GQuery { /** * Stop the function which is currently in execution and depending on the - * value of the parameter: + * value of the parameter: * - remove it from the effects queue and start the next one. * - or remove all functions in the effects queue. */ public T stop(boolean clearQueue) { return stop(DEFAULT_NAME, clearQueue, false); } - + /** * Stop the function which is currently in execution and depending on the - * value of the parameter: + * value of the parameter: * - remove it from the effects queue and start the next one. * - or remove all functions in the effects queue. - * + * * If the parameter jump is true, the current stopped effect will set - * the final css properties like if the effect would be completely executed. + * the final css properties like if the effect would be completely executed. */ public T stop(boolean clearQueue, boolean jumpToEnd) { return stop(DEFAULT_NAME, clearQueue, jumpToEnd); } - + /** * Stop the function which is currently in execution and depending on the - * value of the parameter: + * value of the parameter: * - remove it from the named queue and start the next one. * - or remove all functions in the named queue. */ public T stop(String name, boolean clearQueue) { return stop(name, clearQueue, false); } - + /** * Stop the function which is currently in execution and depending on the - * value of the clear parameter: + * value of the clear parameter: * - remove it from the named queue and start the next one. * - or remove all functions in the queue. - * + * * If the parameter jump is true, the current stopped effect will set - * the final css properties like if the effect would be completely executed. - * + * the final css properties like if the effect would be completely executed. + * */ @SuppressWarnings("unchecked") public T stop(String name, boolean clearQueue, boolean jumpToEnd) { @@ -253,7 +253,7 @@ public class QueuePlugin<T extends QueuePlugin<?>> extends GQuery { } return (T) this; } - + private void dequeueCurrentAndRunNext(Element elem, String name) { Queue<?> q = queue(elem, name, null); if (q != null) { @@ -271,7 +271,7 @@ public class QueuePlugin<T extends QueuePlugin<?>> extends GQuery { } } } - + @SuppressWarnings("unchecked") protected <S> Queue<S> queue(Element elem, String name, S func) { if (elem != null) { @@ -291,7 +291,7 @@ public class QueuePlugin<T extends QueuePlugin<?>> extends GQuery { } return null; } - + /** * Dequeue the object and run the next if it is the first * in the queue. diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/UiPlugin.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/UiPlugin.java index 2d0d3d59..0d85e1fb 100755 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/UiPlugin.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/UiPlugin.java @@ -1,12 +1,12 @@ /* * 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 @@ -26,13 +26,13 @@ import com.google.gwt.query.client.Predicate; /** * GWT clone of jQueryUi-core. This class define some function present in the * jQuery-ui core and not directly in jQuery - * + * */ public class UiPlugin extends GQuery { /** * A POJO used to store dimension of an element - * + * */ public static class Dimension { private int height = 0; @@ -172,7 +172,7 @@ public class UiPlugin extends GQuery { /** * fire event and call callback function. - * + * */ protected void trigger(GwtEvent<?> e, Function callback, Element element) { trigger(e, callback, element, eventBus); diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Widgets.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Widgets.java index aaee7227..7e7f3462 100755 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Widgets.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Widgets.java @@ -1,197 +1,197 @@ -/*
- * 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.plugins;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.query.client.GQuery;
-import com.google.gwt.query.client.plugins.widgets.ButtonWidgetFactory;
-import com.google.gwt.query.client.plugins.widgets.HtmlPanelWidgetFactory;
-import com.google.gwt.query.client.plugins.widgets.LabelWidgetFactory;
-import com.google.gwt.query.client.plugins.widgets.PasswordTextBoxWidgetFactory;
-import com.google.gwt.query.client.plugins.widgets.TextAreaWidgetFactory;
-import com.google.gwt.query.client.plugins.widgets.TextBoxWidgetFactory;
-import com.google.gwt.query.client.plugins.widgets.WidgetFactory;
-import com.google.gwt.query.client.plugins.widgets.WidgetInitializer;
-import com.google.gwt.query.client.plugins.widgets.WidgetsUtils;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.PasswordTextBox;
-import com.google.gwt.user.client.ui.TextArea;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.Widget;
-
-/**
- * Widgets plugin for Gwt Query. Be careful, this plugin is still experimental.
- * The api can change in next releases.
- */
-public class Widgets extends QueuePlugin<Widgets> {
-
- public static final Class<Widgets> Widgets = Widgets.class;
-
- // list of html tags that cannot be replaced by a widget, in order to avoid to
- // break the html structure
- private static final String[] excludedTags = {
- "html", "body", "head", "tr", "thead", "tfoot", "options", "script",
- "noscript", "style", "title"};
-
- static {
- GQuery.registerPlugin(Widgets.class, new Plugin<Widgets>() {
- public Widgets init(GQuery gq) {
- return new Widgets(gq);
- }
- });
- }
-
- protected Widgets(GQuery gq) {
- super(gq);
- }
-
-
- /**
- * Try to create a widget using the given factory and the given options for
- * each element of the query. Returns a new gquery set of elements with the
- * new widgets created.
- */
- public <W extends Widget> Widgets widgets(WidgetFactory<W> factory,
- WidgetInitializer<W> initializers) {
- List<Element> result = new ArrayList<Element>();
- for (Element e : elements()) {
- W w = widget(e, factory, initializers);
- if (w != null) {
- result.add(w.getElement());
- }
- }
- return $(result).as(Widgets);
- }
-
- protected boolean isWidgetCreationAuthorizedFrom(Element e) {
- return !WidgetsUtils.matchesTags(e, excludedTags);
- }
-
- /**
- * Create and return a widget using the given factory and the given options
- */
- protected <W extends Widget> W widget(Element e, WidgetFactory<W> factory,
- WidgetInitializer<W> initializer) {
-
- if (!isWidgetCreationAuthorizedFrom(e)) {
- return null;
- }
-
- W widget = factory.create(e);
- if (initializer != null) {
- initializer.initialize(widget, e);
- }
- return widget;
- }
-
- /**
- * Create and return a widget using the given factory and the given options
- */
- protected <W extends Widget> W widget(WidgetFactory<W> factory,
- WidgetInitializer<W> initializers) {
- return widget(get(0), factory, initializers);
- }
-
- /**
- * Create a {@link Button} widget for each selected element. The
- * <code>initializers</code> will be called on each new {@link Button} created
- * by passing them in parameter.
- *
- */
- public Widgets button() {
- return widgets(new ButtonWidgetFactory(), null);
- }
-
- /**
- * Create a {@link Button} widget for each selected element. The
- * <code>initializers</code> will be called on each new {@link Button} created
- * by passing them in parameter.
- *
- */
- public Widgets button(WidgetInitializer<Button> initializers) {
- return widgets(new ButtonWidgetFactory(), initializers);
- }
-
- public Widgets panel() {
- return widgets(new HtmlPanelWidgetFactory(), null);
- }
-
- public Widgets label(WidgetInitializer<Label> initializers) {
- return widgets(new LabelWidgetFactory(), initializers);
- }
-
- /**
- * Create a {@link PasswordTextBox} widget for each selected element.
- */
- public Widgets passwordBox() {
- return widgets(new PasswordTextBoxWidgetFactory(), null);
- }
-
- /**
- * Create a {@link PasswordTextBox} widget for each selected element. The
- * <code>initializers</code> will be called on each new
- * {@link PasswordTextBox} created by passing them in parameter.
- *
- */
- public Widgets passwordBox(WidgetInitializer<PasswordTextBox> initializers) {
- return widgets(new PasswordTextBoxWidgetFactory(), initializers);
- }
-
-
- /**
- * Create a {@link TextBox} widget for each selected element. The
- * <code>initializers</code> will be called on each new {@link TextBox}
- * created by passing them in parameter.
- *
- */
- public Widgets textBox() {
- return widgets(new TextBoxWidgetFactory(), null);
- }
-
- /**
- * Create a {@link TextBox} widget for each selected element. The
- * <code>initializers</code> will be called on each new {@link TextBox}
- * created by passing them in parameter.
- *
- */
- public Widgets textBox(WidgetInitializer<TextBox> initializers) {
- return widgets(new TextBoxWidgetFactory(), initializers);
- }
-
- /**
- * Create a {@link TextArea} widget for each selected element. The
- * <code>initializers</code> will be called on each new {@link TextBox}
- * created by passing them in parameter.
- *
- */
- public Widgets textArea() {
- return widgets(new TextAreaWidgetFactory(), null);
- }
-
- /**
- * Create a {@link TextArea} widget for each selected element. The
- * <code>initializers</code> will be called on each new {@link TextBox}
- * created by passing them in parameter.
- *
- */
- public Widgets textArea(WidgetInitializer<TextArea> initializers) {
- return widgets(new TextAreaWidgetFactory(), initializers);
- }
-}
+/* + * 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.plugins; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gwt.dom.client.Element; +import com.google.gwt.query.client.GQuery; +import com.google.gwt.query.client.plugins.widgets.ButtonWidgetFactory; +import com.google.gwt.query.client.plugins.widgets.HtmlPanelWidgetFactory; +import com.google.gwt.query.client.plugins.widgets.LabelWidgetFactory; +import com.google.gwt.query.client.plugins.widgets.PasswordTextBoxWidgetFactory; +import com.google.gwt.query.client.plugins.widgets.TextAreaWidgetFactory; +import com.google.gwt.query.client.plugins.widgets.TextBoxWidgetFactory; +import com.google.gwt.query.client.plugins.widgets.WidgetFactory; +import com.google.gwt.query.client.plugins.widgets.WidgetInitializer; +import com.google.gwt.query.client.plugins.widgets.WidgetsUtils; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.PasswordTextBox; +import com.google.gwt.user.client.ui.TextArea; +import com.google.gwt.user.client.ui.TextBox; +import com.google.gwt.user.client.ui.Widget; + +/** + * Widgets plugin for Gwt Query. Be careful, this plugin is still experimental. + * The api can change in next releases. + */ +public class Widgets extends QueuePlugin<Widgets> { + + public static final Class<Widgets> Widgets = Widgets.class; + + // list of html tags that cannot be replaced by a widget, in order to avoid to + // break the html structure + private static final String[] excludedTags = { + "html", "body", "head", "tr", "thead", "tfoot", "options", "script", + "noscript", "style", "title"}; + + static { + GQuery.registerPlugin(Widgets.class, new Plugin<Widgets>() { + public Widgets init(GQuery gq) { + return new Widgets(gq); + } + }); + } + + protected Widgets(GQuery gq) { + super(gq); + } + + + /** + * Try to create a widget using the given factory and the given options for + * each element of the query. Returns a new gquery set of elements with the + * new widgets created. + */ + public <W extends Widget> Widgets widgets(WidgetFactory<W> factory, + WidgetInitializer<W> initializers) { + List<Element> result = new ArrayList<Element>(); + for (Element e : elements()) { + W w = widget(e, factory, initializers); + if (w != null) { + result.add(w.getElement()); + } + } + return $(result).as(Widgets); + } + + protected boolean isWidgetCreationAuthorizedFrom(Element e) { + return !WidgetsUtils.matchesTags(e, excludedTags); + } + + /** + * Create and return a widget using the given factory and the given options + */ + protected <W extends Widget> W widget(Element e, WidgetFactory<W> factory, + WidgetInitializer<W> initializer) { + + if (!isWidgetCreationAuthorizedFrom(e)) { + return null; + } + + W widget = factory.create(e); + if (initializer != null) { + initializer.initialize(widget, e); + } + return widget; + } + + /** + * Create and return a widget using the given factory and the given options + */ + protected <W extends Widget> W widget(WidgetFactory<W> factory, + WidgetInitializer<W> initializers) { + return widget(get(0), factory, initializers); + } + + /** + * Create a {@link Button} widget for each selected element. The + * <code>initializers</code> will be called on each new {@link Button} created + * by passing them in parameter. + * + */ + public Widgets button() { + return widgets(new ButtonWidgetFactory(), null); + } + + /** + * Create a {@link Button} widget for each selected element. The + * <code>initializers</code> will be called on each new {@link Button} created + * by passing them in parameter. + * + */ + public Widgets button(WidgetInitializer<Button> initializers) { + return widgets(new ButtonWidgetFactory(), initializers); + } + + public Widgets panel() { + return widgets(new HtmlPanelWidgetFactory(), null); + } + + public Widgets label(WidgetInitializer<Label> initializers) { + return widgets(new LabelWidgetFactory(), initializers); + } + + /** + * Create a {@link PasswordTextBox} widget for each selected element. + */ + public Widgets passwordBox() { + return widgets(new PasswordTextBoxWidgetFactory(), null); + } + + /** + * Create a {@link PasswordTextBox} widget for each selected element. The + * <code>initializers</code> will be called on each new + * {@link PasswordTextBox} created by passing them in parameter. + * + */ + public Widgets passwordBox(WidgetInitializer<PasswordTextBox> initializers) { + return widgets(new PasswordTextBoxWidgetFactory(), initializers); + } + + + /** + * Create a {@link TextBox} widget for each selected element. The + * <code>initializers</code> will be called on each new {@link TextBox} + * created by passing them in parameter. + * + */ + public Widgets textBox() { + return widgets(new TextBoxWidgetFactory(), null); + } + + /** + * Create a {@link TextBox} widget for each selected element. The + * <code>initializers</code> will be called on each new {@link TextBox} + * created by passing them in parameter. + * + */ + public Widgets textBox(WidgetInitializer<TextBox> initializers) { + return widgets(new TextBoxWidgetFactory(), initializers); + } + + /** + * Create a {@link TextArea} widget for each selected element. The + * <code>initializers</code> will be called on each new {@link TextBox} + * created by passing them in parameter. + * + */ + public Widgets textArea() { + return widgets(new TextAreaWidgetFactory(), null); + } + + /** + * Create a {@link TextArea} widget for each selected element. The + * <code>initializers</code> will be called on each new {@link TextBox} + * created by passing them in parameter. + * + */ + public Widgets textArea(WidgetInitializer<TextArea> initializers) { + return widgets(new TextAreaWidgetFactory(), initializers); + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/Ajax.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/Ajax.java index 832fda8b..96a3d35b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/Ajax.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/Ajax.java @@ -18,17 +18,17 @@ import com.google.gwt.user.client.ui.FormPanel; /** * Ajax class for GQuery. - * + * * The jQuery library has a full suite of AJAX capabilities, but GWT is plenty of classes to get * data from server side: RPC, XHR, RF, etc. - * + * * This class is not a substitute for the GWT utilities, but a complement to get server data in a * jquery way, specially when querying non java backends. - * + * * We do not pretend to clone all the jquery Ajax API inside gquery, just take its syntax and to * implement the most popular usage of it. This implementation is almost thought to be used as an * alternative to the GWT-XHR, GWT-XML and GWT-JSON modules. - * + * */ public class Ajax extends GQuery { @@ -78,10 +78,10 @@ public class Ajax extends GQuery { /** * Perform an ajax request to the server. - * - * + * + * * Example: - * + * * <pre> import static com.google.gwt.query.client.GQ.* ... @@ -97,7 +97,7 @@ public class Ajax extends GQuery { } }, properties); * </pre> - * + * * @param url The url to connect * @param onSuccess a function to execute in the case of success * @param onError the function to execute on error @@ -114,18 +114,18 @@ public class Ajax extends GQuery { if (onError != null) { onError.setElement(settings.getContext()); } - + Method httpMethod = resolveHttpMethod(settings); String data = resolveData(settings, httpMethod); final String url = resolveUrl(settings, httpMethod, data); final String dataType = settings.getDataType(); - + if ("jsonp".equalsIgnoreCase(dataType)) { int timeout = settings.getTimeout(); getJSONP(url, onSuccess, onError, timeout); return; } - + final RequestBuilder requestBuilder = createRequestBuilder(settings, httpMethod, url, data); requestBuilder.setCallback(new RequestCallback() { public void onError(Request request, Throwable exception) { @@ -157,7 +157,7 @@ public class Ajax extends GQuery { } catch (Exception e) { if (GWT.getUncaughtExceptionHandler() != null) { GWT.getUncaughtExceptionHandler().onUncaughtException(e); - } + } } onSuccess.fe(retData, "success", request, response); } @@ -190,7 +190,7 @@ public class Ajax extends GQuery { requestBuilder.setHeader("Content-Type", ctype); requestBuilder.setRequestData(data); } - + requestBuilder.setTimeoutMillis(settings.getTimeout()); String user = settings.getUsername(); @@ -202,7 +202,7 @@ public class Ajax extends GQuery { if (password != null) { requestBuilder.setPassword(password); } - + Properties headers = settings.getHeaders(); if (headers != null) { for (String headerKey : headers.keys()) { @@ -212,7 +212,7 @@ public class Ajax extends GQuery { return requestBuilder; } - + private static String resolveUrl(Settings settings, Method httpMethod, String data) { String url = settings.getUrl(); assert url != null : "no url found in settings"; @@ -226,7 +226,7 @@ public class Ajax extends GQuery { String data = settings.getDataString(); if (data == null && settings.getData() != null) { String type = settings.getDataType(); - if (type != null + if (type != null && (httpMethod == RequestBuilder.POST || httpMethod == RequestBuilder.PUT) && type.equalsIgnoreCase("json")) { data = settings.getData().toJsonString(); @@ -250,7 +250,7 @@ public class Ajax extends GQuery { }else if("head".equalsIgnoreCase(method)){ return RequestBuilder.HEAD; } - + GWT.log("unknow method type -> use POST as default method"); return RequestBuilder.POST; } @@ -311,7 +311,7 @@ public class Ajax extends GQuery { s.setSuccess(onSuccess); ajax(s); } - + public static void getJSONP(String url, Properties data, Function onSuccess) { Settings s = createSettings(); s.setUrl(url); @@ -321,7 +321,7 @@ public class Ajax extends GQuery { s.setSuccess(onSuccess); ajax(s); } - + public static void getJSONP(String url, Function success, Function error, int timeout) { if (!url.contains("=?") && !url.contains("callback=")) { url += (url.contains("?") ? "&" : "?") + "callback=?"; @@ -347,7 +347,7 @@ public class Ajax extends GQuery { protected Ajax(GQuery gq) { super(gq); } - + public Ajax load(String url, Properties data, final Function onSuccess) { Settings s = createSettings(); final String filter = url.contains(" ") ? url.replaceFirst("^[^\\s]+\\s+", "") : ""; @@ -358,18 +358,18 @@ public class Ajax extends GQuery { s.setSuccess(new Function() { public void f() { try { - // We clean up the returned string to smoothly append it to our document - // Note: using '\s\S' instead of '.' because gwt String emulation does + // We clean up the returned string to smoothly append it to our document + // Note: using '\s\S' instead of '.' because gwt String emulation does // not support java embedded flag expressions (?s) and javascript does // not have multidot flag. String s = getData()[0].toString().replaceAll("<![^>]+>\\s*", "") .replaceAll("</?html[\\s\\S]*?>\\s*", "") .replaceAll("<head[\\s\\S]*?</head>\\s*", "") .replaceAll("<script[\\s\\S]*?</script>\\s*", "") - .replaceAll("</?body[\\s\\S]*?>\\s*", ""); + .replaceAll("</?body[\\s\\S]*?>\\s*", ""); // We wrap the results in a div s = "<div>" + s + "</div>"; - + Ajax.this.empty().append(filter.isEmpty() ? $(s) : $(s).find(filter)); if (onSuccess != null) { onSuccess.setElement(Ajax.this.get(0)); @@ -385,9 +385,9 @@ public class Ajax extends GQuery { ajax(s); return this; } - + private static int callBackCounter = 0; - + public static native void getJsonpImpl(Element elem, String url, String charset, Function success, Function error, int timeout) /*-{ var fName = "__GQ_cb_" + @com.google.gwt.query.client.plugins.ajax.Ajax::callBackCounter ++; var done = false; @@ -408,7 +408,7 @@ public class Ajax extends GQuery { } if (timeout) { setTimeout(err, timeout); - } + } url = url.replace(/=\?/g,'=' + fName); var script = document.createElement("script" ); @@ -421,5 +421,5 @@ public class Ajax extends GQuery { err(); }; elem.insertBefore(script, elem.firstChild); - }-*/; + }-*/; } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/ClipAnimation.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/ClipAnimation.java index bb842815..e81e6340 100755 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/ClipAnimation.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/ClipAnimation.java @@ -1,146 +1,146 @@ -/*
- * 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.plugins.effects;
-
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.query.client.Function;
-import com.google.gwt.query.client.GQuery;
-import com.google.gwt.query.client.plugins.Effects;
-import com.google.gwt.query.client.plugins.Effects.GQAnimation;
-
-/**
- * Animation wich uses the css clip property to show/hide an element.
- */
-public class ClipAnimation extends GQAnimation {
-
- /**
- * Type of the effect action.
- */
- public static enum Action {
- HIDE, SHOW, TOGGLE
- }
-
- /**
- * Corner from which the effect starts.
- */
- public static enum Corner {
- BOTTOM_LEFT, BOTTOM_RIGHT, CENTER, TOP_LEFT, TOP_RIGHT
- }
-
- /**
- * Direction of the effect.
- */
- public static enum Direction {
- BIDIRECTIONAL, HORIZONTAL, VERTICAL
- }
-
- private static final String[] attrsToSave = new String[]{
- "position", "overflow", "visibility", "white-space", "top", "left"};
-
- Action action;
- Corner corner;
- Direction direction;
- int percent;
- private GQuery back = Effects.$();
- private Function[] funcs;
- private Effects g;
-
- public ClipAnimation(Element elem, Action a, Corner c, Direction d,
- final Function... funcs) {
- if (a == Action.TOGGLE) {
- a = GQuery.$(elem).isVisible() ? Action.HIDE : Action.SHOW;
- }
- this.action = a;
- this.corner = c;
- this.direction = d;
- this.funcs = funcs;
- e = elem;
- g = GQuery.$(e).as(Effects.Effects);
- }
-
- @Override
- public void onCancel() {
- Boolean jumpToEnd = Effects.$(e).data(Effects.JUMP_TO_END, Boolean.class);
- if (jumpToEnd != null && jumpToEnd){
- onComplete();
- } else {
- g.dequeue();
- }
- }
-
- @Override
- public void onComplete() {
- super.onComplete();
- if (action == Action.HIDE) {
- g.hide();
- }
- g.restoreCssAttrs(attrsToSave);
- back.remove();
- back = Effects.$();
- g.css("clip", "");
- g.each(funcs);
- g.dequeue();
- }
-
- @Override
- public void onStart() {
- g.show();
- g.saveCssAttrs(attrsToSave);
- if (!"absolute".equalsIgnoreCase(g.css("position", true))) {
- g.css("position", "absolute");
- g.css("top", g.offset().top + "px");
- g.css("left", g.offset().left + "px");
- back = back.add(g.before("<div></div>")).prev();
- back.height(g.height());
- back.width(g.width());
- }
- g.css("overflow", "hidden");
- g.css("visivility", "visible");
- super.onStart();
- }
-
- @Override
- public void onUpdate(double progress) {
- if (action == Action.HIDE) {
- progress = (1 - progress);
- }
- int top = 0;
- int left = 0;
- int right = g.width();
- int bottom = g.height();
-
- if (direction == Direction.VERTICAL || direction == Direction.BIDIRECTIONAL) {
- bottom = (int) (g.height() * progress);
- }
- if (direction == Direction.HORIZONTAL
- || direction == Direction.BIDIRECTIONAL) {
- right = (int) (g.width() * progress);
- }
- if (corner == Corner.CENTER) {
- top = (g.height() - bottom) / 2;
- left = (g.width() - right) / 2;
- } else if (corner == Corner.BOTTOM_LEFT) {
- top = (g.height() - bottom);
- } else if (corner == Corner.TOP_RIGHT) {
- left = (g.width() - right);
- } else if (corner == Corner.BOTTOM_RIGHT) {
- left = (g.width() - right);
- top = (g.height() - bottom);
- }
- String rect = top + "px " + right + "px " + bottom + "px " + left + "px";
- g.css("clip", "rect(" + rect + ")");
- }
-}
+/* + * 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.plugins.effects; + +import com.google.gwt.dom.client.Element; +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.GQuery; +import com.google.gwt.query.client.plugins.Effects; +import com.google.gwt.query.client.plugins.Effects.GQAnimation; + +/** + * Animation wich uses the css clip property to show/hide an element. + */ +public class ClipAnimation extends GQAnimation { + + /** + * Type of the effect action. + */ + public static enum Action { + HIDE, SHOW, TOGGLE + } + + /** + * Corner from which the effect starts. + */ + public static enum Corner { + BOTTOM_LEFT, BOTTOM_RIGHT, CENTER, TOP_LEFT, TOP_RIGHT + } + + /** + * Direction of the effect. + */ + public static enum Direction { + BIDIRECTIONAL, HORIZONTAL, VERTICAL + } + + private static final String[] attrsToSave = new String[]{ + "position", "overflow", "visibility", "white-space", "top", "left"}; + + Action action; + Corner corner; + Direction direction; + int percent; + private GQuery back = Effects.$(); + private Function[] funcs; + private Effects g; + + public ClipAnimation(Element elem, Action a, Corner c, Direction d, + final Function... funcs) { + if (a == Action.TOGGLE) { + a = GQuery.$(elem).isVisible() ? Action.HIDE : Action.SHOW; + } + this.action = a; + this.corner = c; + this.direction = d; + this.funcs = funcs; + e = elem; + g = GQuery.$(e).as(Effects.Effects); + } + + @Override + public void onCancel() { + Boolean jumpToEnd = Effects.$(e).data(Effects.JUMP_TO_END, Boolean.class); + if (jumpToEnd != null && jumpToEnd){ + onComplete(); + } else { + g.dequeue(); + } + } + + @Override + public void onComplete() { + super.onComplete(); + if (action == Action.HIDE) { + g.hide(); + } + g.restoreCssAttrs(attrsToSave); + back.remove(); + back = Effects.$(); + g.css("clip", ""); + g.each(funcs); + g.dequeue(); + } + + @Override + public void onStart() { + g.show(); + g.saveCssAttrs(attrsToSave); + if (!"absolute".equalsIgnoreCase(g.css("position", true))) { + g.css("position", "absolute"); + g.css("top", g.offset().top + "px"); + g.css("left", g.offset().left + "px"); + back = back.add(g.before("<div></div>")).prev(); + back.height(g.height()); + back.width(g.width()); + } + g.css("overflow", "hidden"); + g.css("visivility", "visible"); + super.onStart(); + } + + @Override + public void onUpdate(double progress) { + if (action == Action.HIDE) { + progress = (1 - progress); + } + int top = 0; + int left = 0; + int right = g.width(); + int bottom = g.height(); + + if (direction == Direction.VERTICAL || direction == Direction.BIDIRECTIONAL) { + bottom = (int) (g.height() * progress); + } + if (direction == Direction.HORIZONTAL + || direction == Direction.BIDIRECTIONAL) { + right = (int) (g.width() * progress); + } + if (corner == Corner.CENTER) { + top = (g.height() - bottom) / 2; + left = (g.width() - right) / 2; + } else if (corner == Corner.BOTTOM_LEFT) { + top = (g.height() - bottom); + } else if (corner == Corner.TOP_RIGHT) { + left = (g.width() - right); + } else if (corner == Corner.BOTTOM_RIGHT) { + left = (g.width() - right); + top = (g.height() - bottom); + } + String rect = top + "px " + right + "px " + bottom + "px " + left + "px"; + g.css("clip", "rect(" + rect + ")"); + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Fx.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Fx.java index 92c0ef42..408a993b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Fx.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Fx.java @@ -12,17 +12,17 @@ import com.google.gwt.query.client.js.JsRegexp; * A pojo to store effect values. */ public class Fx { - + /** * Public variable to enable/disable effects */ public static boolean off = false; - + /** * A pojo to store color effect values. */ public static class ColorFx extends Fx { - + /** * Specific class handle specific borderColor shortcut properties */ @@ -33,7 +33,7 @@ public class Fx { BorderColorProperty.BORDER_TOP_COLOR_PROPERTY, BorderColorProperty.BORDER_LEFT_COLOR_PROPERTY, BorderColorProperty.BORDER_RIGHT_COLOR_PROPERTY}; - + private JsNamedArray<int[]> startColors; public BorderColorFx(Element e, String endColorString) { @@ -62,7 +62,7 @@ public class Fx { // hexadecimal regex public static JsRegexp REGEX_HEX_COLOR_PATTERN = new JsRegexp( "#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})"); - + private static JsNamedArray<int[]> htmlColorToRgb; // rgb and rgba regex @@ -209,7 +209,7 @@ public class Fx { } } - + public String cssprop; public double end; public double start; @@ -245,9 +245,9 @@ public class Fx { } public String toString() { - return ("cssprop=" + cssprop + (attribute != null ? " attr=" + attribute : "") + return ("cssprop=" + cssprop + (attribute != null ? " attr=" + attribute : "") + " value=" + value + " start=" + start + " end=" + end + " unit=" + unit).replaceAll("\\.0([^\\d])", "$1"); } - + } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/PropertiesAnimation.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/PropertiesAnimation.java index 52199ff6..80b73d2a 100755 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/PropertiesAnimation.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/PropertiesAnimation.java @@ -1,280 +1,280 @@ -/*
- * 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.plugins.effects;
-
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.query.client.Function;
-import com.google.gwt.query.client.GQuery;
-import com.google.gwt.query.client.Properties;
-import com.google.gwt.query.client.js.JsObjectArray;
-import com.google.gwt.query.client.js.JsRegexp;
-import com.google.gwt.query.client.plugins.Effects;
-import com.google.gwt.query.client.plugins.Effects.GQAnimation;
-import com.google.gwt.query.client.plugins.effects.Fx.ColorFx;
-import com.google.gwt.query.client.plugins.effects.Fx.ColorFx.BorderColorFx;
-
-/**
- * Animation effects on any numeric CSS property.
- */
-public class PropertiesAnimation extends GQAnimation {
-
- /**
- * Easing method to use.
- */
- public static interface Easing {
- public double interpolate(double progress);
-
- public Easing LINEAR = new Easing() {
- public double interpolate(double progress) {
- return progress;
- }
- };
-
- public Easing SWING = new Easing() {
- public double interpolate(double progress) {
- return (1 + Math.cos(Math.PI + progress * Math.PI)) / 2;
- }
- };
- }
-
- private static final String[] ATTRS_TO_SAVE = new String[]{
- "overflow"};
-
- private static final JsRegexp REGEX_NUMBER_UNIT = new JsRegexp(
- "^([0-9+-.]+)(.*)?$");
-
- private static final JsRegexp REGEX_SYMBOL_NUMBER_UNIT = new JsRegexp(
- "^([+-]=)?([0-9+-.]+)(.*)?$");
-
- private static final JsRegexp REGEX_NON_PIXEL_ATTRS = new JsRegexp(
- "z-?index|font-?weight|opacity|zoom|line-?height|^\\$", "i");
-
- private static final JsRegexp REGEX_COLOR_ATTR = new JsRegexp(".*color$", "i");
-
- private static final JsRegexp REGEX_BORDERCOLOR = new JsRegexp("^bordercolor$", "i");
-
- private static final JsRegexp REGEX_BACKGROUNDCOLOR = new JsRegexp("^backgroundcolor$", "i");
-
-
-
- public static Fx computeFxProp(Element e, String key, String val,
- boolean hidden) {
-
- if (REGEX_COLOR_ATTR.test(key)) {
- return computeFxColorProp(e, key, val);
- }
-
- return computeFxNumericProp(e, key, val, hidden);
- }
-
- private static Fx computeFxColorProp(Element e, String key, String val) {
-
- if (REGEX_BORDERCOLOR.test(key)) {
- return new BorderColorFx(e, val);
- }
-
- String initialColor = null;
- if (REGEX_BACKGROUNDCOLOR.test(key)) {
- // find the first parent having a background-color value (other than
- // transparent)
- Element current = e;
-
- while ((initialColor == null || initialColor.length() == 0 || initialColor.equals("transparent"))
- && current != null) {
- initialColor = GQuery.$(current).css(key, false);
- current = !"body".equalsIgnoreCase(current.getTagName())
- ? current.getParentElement() : null;
- }
- if (initialColor == null || initialColor.length() == 0
- || initialColor.equals("transparent")) {
- initialColor = "white";
- }
- } else {
- initialColor = GQuery.$(e).css(key, true);
- }
-
- return new ColorFx(key, initialColor, val);
- }
-
- public static Fx computeFxNumericProp(Element e, String key, String val,
- boolean hidden) {
-
- GQuery g = Effects.$(e);
- String unit = "";
- if ("toggle".equals(val)) {
- val = hidden ? "show" : "hide";
- }
-
- if (("show".equals(val) && !hidden) || ("hide").equals(val) && hidden) {
- return null;
- }
-
- if (hidden) {
- g.show();
- }
-
- // If key starts with $ we animate node attributes, otherwise css properties
- double cur;
- String rkey = null;
- if (key.startsWith("$")) {
- rkey = key.substring(1).toLowerCase();
- String attr = g.attr(rkey);
- JsObjectArray<String> parts = REGEX_NUMBER_UNIT.match(attr);
- if (parts != null) {
- String $1 = parts.get(1);
- String $2 = parts.get(2);
- cur = Double.parseDouble($1);
- unit = $2 == null ? "" : $2;
- } else {
- cur = g.cur(key, true);
- key = rkey;
- }
- } else {
- cur = g.cur(key, true);
- }
-
- double start = cur, end = start;
-
- if ("show".equals(val)) {
- g.saveCssAttrs(key);
- start = 0;
- unit = REGEX_NON_PIXEL_ATTRS.test(key) ? "" : "px";
- } else if ("hide".equals(val)) {
- if (hidden) {
- return null;
- }
- g.saveCssAttrs(key);
- end = 0;
- unit = REGEX_NON_PIXEL_ATTRS.test(key) ? "" : "px";
- } else {
- JsObjectArray<String> parts = REGEX_SYMBOL_NUMBER_UNIT.match(val);
-
- if (parts != null) {
- String $1 = parts.get(1);
- String $2 = parts.get(2);
- String $3 = parts.get(3);
- end = Double.parseDouble($2);
-
- if (rkey == null) {
- unit = REGEX_NON_PIXEL_ATTRS.test(key) ? "" : //
- $3 == null || $3.isEmpty() ? "px" : $3;
- if (!"px".equals(unit)) {
- double to = end == 0 ? 1 : end;
- g.css(key, to + unit);
- start = to * start / g.cur(key, true);
- g.css(key, start + unit);
- }
- } else if ($3 != null && !$3.isEmpty()) {
- unit = $3;
- }
-
- if ($1 != null && !$1.isEmpty()) {
- end = (("-=".equals($1) ? -1 : 1) * end) + start;
- }
- }
- }
-
- return new Fx(key, val, start, end, unit, rkey);
- }
-
- private Easing easing = Easing.SWING;
- private JsObjectArray<Fx> effects = JsObjectArray.create();
- private Function[] funcs;
-
- private Effects g;
-
- private Properties prps;
-
- public PropertiesAnimation(Easing easing, Element elem, Properties p,
- Function... funcs) {
- this.easing = easing;
- this.e = elem;
- this.funcs = funcs;
- this.prps = p;
- g = Effects.$(e).as(Effects.Effects);
- }
-
- @Override
- public void onCancel() {
- Boolean jumpToEnd = Effects.$(e).data(Effects.JUMP_TO_END, Boolean.class);
- if (jumpToEnd != null && jumpToEnd){
- onComplete();
- } else {
- g.dequeue();
- g.restoreCssAttrs(ATTRS_TO_SAVE);
- }
- }
-
- @Override
- public void onComplete() {
- super.onComplete();
- for (int i = 0; i < effects.length(); i++) {
- Fx fx = effects.get(i);
- if ("hide".equals(fx.value)) {
- g.hide();
- g.restoreCssAttrs(fx.cssprop);
- } else if ("show".equals(fx.value)) {
- g.show();
- g.restoreCssAttrs(fx.cssprop);
- }
- }
- g.restoreCssAttrs(ATTRS_TO_SAVE);
- g.each(funcs);
- g.dequeue();
- }
-
- @Override
- public void onStart() {
- boolean resize = false;
- boolean move = false;
- boolean hidden = !g.isVisible();
- Fx fx;
- // g.show();
- for (String key : prps.keys()) {
- String val = prps.getStr(key);
- if ((fx = computeFxProp(e, key, val, hidden)) != null) {
- effects.add(fx);
- resize = resize || "height".equals(key) || "width".equals(key);
- move = move || "top".equals(key) || "left".equals(key);
- }
- }
- g.saveCssAttrs(ATTRS_TO_SAVE);
- if (resize) {
- g.css("overflow", "hidden");
- }
- if (move && !g.css("position", true).matches("absolute|relative")) {
- g.css("position", "relative");
- }
- super.onStart();
- }
-
- @Override
- public void onUpdate(double progress) {
- for (int i = 0; i < effects.length(); i++) {
- effects.get(i).applyValue(g, progress);
- }
- }
-
- @Override
- protected double interpolate(double progress) {
- if (easing != null) {
- return easing.interpolate(progress);
- }
- // maybe return super.interpolate() instead ?
- return progress;
- }
-
-}
+/* + * 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.plugins.effects; + +import com.google.gwt.dom.client.Element; +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.GQuery; +import com.google.gwt.query.client.Properties; +import com.google.gwt.query.client.js.JsObjectArray; +import com.google.gwt.query.client.js.JsRegexp; +import com.google.gwt.query.client.plugins.Effects; +import com.google.gwt.query.client.plugins.Effects.GQAnimation; +import com.google.gwt.query.client.plugins.effects.Fx.ColorFx; +import com.google.gwt.query.client.plugins.effects.Fx.ColorFx.BorderColorFx; + +/** + * Animation effects on any numeric CSS property. + */ +public class PropertiesAnimation extends GQAnimation { + + /** + * Easing method to use. + */ + public static interface Easing { + public double interpolate(double progress); + + public Easing LINEAR = new Easing() { + public double interpolate(double progress) { + return progress; + } + }; + + public Easing SWING = new Easing() { + public double interpolate(double progress) { + return (1 + Math.cos(Math.PI + progress * Math.PI)) / 2; + } + }; + } + + private static final String[] ATTRS_TO_SAVE = new String[]{ + "overflow"}; + + private static final JsRegexp REGEX_NUMBER_UNIT = new JsRegexp( + "^([0-9+-.]+)(.*)?$"); + + private static final JsRegexp REGEX_SYMBOL_NUMBER_UNIT = new JsRegexp( + "^([+-]=)?([0-9+-.]+)(.*)?$"); + + private static final JsRegexp REGEX_NON_PIXEL_ATTRS = new JsRegexp( + "z-?index|font-?weight|opacity|zoom|line-?height|^\\$", "i"); + + private static final JsRegexp REGEX_COLOR_ATTR = new JsRegexp(".*color$", "i"); + + private static final JsRegexp REGEX_BORDERCOLOR = new JsRegexp("^bordercolor$", "i"); + + private static final JsRegexp REGEX_BACKGROUNDCOLOR = new JsRegexp("^backgroundcolor$", "i"); + + + + public static Fx computeFxProp(Element e, String key, String val, + boolean hidden) { + + if (REGEX_COLOR_ATTR.test(key)) { + return computeFxColorProp(e, key, val); + } + + return computeFxNumericProp(e, key, val, hidden); + } + + private static Fx computeFxColorProp(Element e, String key, String val) { + + if (REGEX_BORDERCOLOR.test(key)) { + return new BorderColorFx(e, val); + } + + String initialColor = null; + if (REGEX_BACKGROUNDCOLOR.test(key)) { + // find the first parent having a background-color value (other than + // transparent) + Element current = e; + + while ((initialColor == null || initialColor.length() == 0 || initialColor.equals("transparent")) + && current != null) { + initialColor = GQuery.$(current).css(key, false); + current = !"body".equalsIgnoreCase(current.getTagName()) + ? current.getParentElement() : null; + } + if (initialColor == null || initialColor.length() == 0 + || initialColor.equals("transparent")) { + initialColor = "white"; + } + } else { + initialColor = GQuery.$(e).css(key, true); + } + + return new ColorFx(key, initialColor, val); + } + + public static Fx computeFxNumericProp(Element e, String key, String val, + boolean hidden) { + + GQuery g = Effects.$(e); + String unit = ""; + if ("toggle".equals(val)) { + val = hidden ? "show" : "hide"; + } + + if (("show".equals(val) && !hidden) || ("hide").equals(val) && hidden) { + return null; + } + + if (hidden) { + g.show(); + } + + // If key starts with $ we animate node attributes, otherwise css properties + double cur; + String rkey = null; + if (key.startsWith("$")) { + rkey = key.substring(1).toLowerCase(); + String attr = g.attr(rkey); + JsObjectArray<String> parts = REGEX_NUMBER_UNIT.match(attr); + if (parts != null) { + String $1 = parts.get(1); + String $2 = parts.get(2); + cur = Double.parseDouble($1); + unit = $2 == null ? "" : $2; + } else { + cur = g.cur(key, true); + key = rkey; + } + } else { + cur = g.cur(key, true); + } + + double start = cur, end = start; + + if ("show".equals(val)) { + g.saveCssAttrs(key); + start = 0; + unit = REGEX_NON_PIXEL_ATTRS.test(key) ? "" : "px"; + } else if ("hide".equals(val)) { + if (hidden) { + return null; + } + g.saveCssAttrs(key); + end = 0; + unit = REGEX_NON_PIXEL_ATTRS.test(key) ? "" : "px"; + } else { + JsObjectArray<String> parts = REGEX_SYMBOL_NUMBER_UNIT.match(val); + + if (parts != null) { + String $1 = parts.get(1); + String $2 = parts.get(2); + String $3 = parts.get(3); + end = Double.parseDouble($2); + + if (rkey == null) { + unit = REGEX_NON_PIXEL_ATTRS.test(key) ? "" : // + $3 == null || $3.isEmpty() ? "px" : $3; + if (!"px".equals(unit)) { + double to = end == 0 ? 1 : end; + g.css(key, to + unit); + start = to * start / g.cur(key, true); + g.css(key, start + unit); + } + } else if ($3 != null && !$3.isEmpty()) { + unit = $3; + } + + if ($1 != null && !$1.isEmpty()) { + end = (("-=".equals($1) ? -1 : 1) * end) + start; + } + } + } + + return new Fx(key, val, start, end, unit, rkey); + } + + private Easing easing = Easing.SWING; + private JsObjectArray<Fx> effects = JsObjectArray.create(); + private Function[] funcs; + + private Effects g; + + private Properties prps; + + public PropertiesAnimation(Easing easing, Element elem, Properties p, + Function... funcs) { + this.easing = easing; + this.e = elem; + this.funcs = funcs; + this.prps = p; + g = Effects.$(e).as(Effects.Effects); + } + + @Override + public void onCancel() { + Boolean jumpToEnd = Effects.$(e).data(Effects.JUMP_TO_END, Boolean.class); + if (jumpToEnd != null && jumpToEnd){ + onComplete(); + } else { + g.dequeue(); + g.restoreCssAttrs(ATTRS_TO_SAVE); + } + } + + @Override + public void onComplete() { + super.onComplete(); + for (int i = 0; i < effects.length(); i++) { + Fx fx = effects.get(i); + if ("hide".equals(fx.value)) { + g.hide(); + g.restoreCssAttrs(fx.cssprop); + } else if ("show".equals(fx.value)) { + g.show(); + g.restoreCssAttrs(fx.cssprop); + } + } + g.restoreCssAttrs(ATTRS_TO_SAVE); + g.each(funcs); + g.dequeue(); + } + + @Override + public void onStart() { + boolean resize = false; + boolean move = false; + boolean hidden = !g.isVisible(); + Fx fx; + // g.show(); + for (String key : prps.keys()) { + String val = prps.getStr(key); + if ((fx = computeFxProp(e, key, val, hidden)) != null) { + effects.add(fx); + resize = resize || "height".equals(key) || "width".equals(key); + move = move || "top".equals(key) || "left".equals(key); + } + } + g.saveCssAttrs(ATTRS_TO_SAVE); + if (resize) { + g.css("overflow", "hidden"); + } + if (move && !g.css("position", true).matches("absolute|relative")) { + g.css("position", "relative"); + } + super.onStart(); + } + + @Override + public void onUpdate(double progress) { + for (int i = 0; i < effects.length(); i++) { + effects.get(i).applyValue(g, progress); + } + } + + @Override + protected double interpolate(double progress) { + if (easing != null) { + return easing.interpolate(progress); + } + // maybe return super.interpolate() instead ? + return progress; + } + +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/EventsListener.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/EventsListener.java index 682876ca..886df5b9 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/EventsListener.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/EventsListener.java @@ -1,11 +1,11 @@ /* * 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 @@ -35,12 +35,12 @@ import java.util.List; /** * This class implements an event queue instance for one Element. The queue instance is configured * as the default event listener in GWT. - * + * * The reference to this queue is stored as a unique variable in the element's DOM - * + * * The class takes care of calling the appropriate functions for each browser event and it also * calls sinkEvents method. - * + * */ public class EventsListener implements EventListener { @@ -149,9 +149,9 @@ public class EventsListener implements EventListener { /** * Remove a set of events. The bind function will not be fire anymore for those events - * + * * @param eventBits the set of events to unsink - * + * */ public int unsink(int eventBits) { if (eventBits <= 0) { @@ -183,7 +183,7 @@ public class EventsListener implements EventListener { /** * {@link BindFunction} used for live() method. - * + * */ private static class LiveBindFunction extends BindFunction { @@ -285,7 +285,7 @@ public class EventsListener implements EventListener { /** * Tell if no {@link BindFunction} are linked to this object - * + * * @return */ public boolean isEmpty() { @@ -301,7 +301,7 @@ public class EventsListener implements EventListener { /** * Return the element whose the listener fired last. It represent the context element where the * {@link LiveBindFunction} was binded - * + * */ private Element getCurrentEventTarget(Event e) { EventTarget currentEventTarget = e.getCurrentEventTarget(); @@ -446,14 +446,14 @@ public class EventsListener implements EventListener { String[] parts = events.split("[\\s,]+"); for (String event : parts) { - + String nameSpace = null; String eventName = event; - + //seperate possible namespace //jDramaix: I removed old regex ^([^.]*)\.?(.*$) because it didn't work on IE8... String[] subparts = event.split("\\.", 2); - + if (subparts.length == 2){ nameSpace = subparts[1]; eventName = subparts[0]; @@ -601,11 +601,11 @@ public class EventsListener implements EventListener { for (String event : parts) { String nameSpace = null; String eventName = event; - + //seperate possible namespace //jDramaix: I removed old regex ^([^.]*)\.?(.*$) because it didn't work on IE8... String[] subparts = event.split("\\.", 2); - + if (subparts.length == 2){ nameSpace = subparts[1]; eventName = subparts[0]; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java index b8fbd90e..1a92374f 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java @@ -8,34 +8,34 @@ import com.google.gwt.user.client.Event; /** * This object allows you to have a full copy of the original Event and * implements some useful method of the jQuery event model. - * + * * This is also useful in Internet Explorer because it use the same javascript * object to fire MouseDownEvent, MouseMoveEvent or MouseStopEvent on the same * element. So, we cannot keep a copy of the MouseDownEvent during a dragging * for example. - * - * - * + * + * + * * Be Careful : the methods preventDefault() and stopPropagation must be called directly on the * original event. - * - * + * + * */ public class GqEvent extends Event { - + public static native void setOriginalEventType(NativeEvent evt, String originalEventName)/*-{ evt["__gwtquery_originalEventName"] = originalEventName; }-*/; - + public static native String getOriginalEventType(Event evt)/*-{ return evt["__gwtquery_originalEventName"] || null; }-*/; - // Gwt Events class has not this event defined, - // so we have to select one power of 2 which is unused in Event class + // Gwt Events class has not this event defined, + // so we have to select one power of 2 which is unused in Event class public static int ONSUBMIT = 0x10000000; public static int ONRESIZE = 0x8000000; - + /** * Create a new {@link GqEvent} by copying the <code>originalEvent</code>. */ @@ -52,7 +52,7 @@ public class GqEvent extends Event { } gQueryEvent.originalEvent = originalEvent; }-*/; - + protected GqEvent() { } @@ -63,10 +63,10 @@ public class GqEvent extends Event { public final native Event getOriginalEvent()/*-{ return this.originalEvent; }-*/; - + public final native void setCurrentElementTarget(Element e)/*-{ this.currentTarget = e; - + //ie don't have a currentEventTarget field on event try{ @com.google.gwt.dom.client.DOMImplTrident::currentEventTarget = e; @@ -75,7 +75,7 @@ public class GqEvent extends Event { /** * Tell whether ctrl or cmd key is pressed - * + * */ public final boolean isMetaKeyPressed() { return getMetaKey() || getCtrlKey(); @@ -83,7 +83,7 @@ public class GqEvent extends Event { /** * The mouse position relative to the left edge of the document - * + * */ public final int pageX() { if (getTouches() != null && getTouches().length() > 0){ @@ -95,7 +95,7 @@ public class GqEvent extends Event { /** * The mouse position relative to the top edge of the document. - * + * */ public final int pageY() { if (getTouches() != null && getTouches().length() > 0){ diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/ButtonWidgetFactory.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/ButtonWidgetFactory.java index 36d076f6..39028149 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/ButtonWidgetFactory.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/ButtonWidgetFactory.java @@ -1,12 +1,12 @@ /* * 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 @@ -32,11 +32,11 @@ public class ButtonWidgetFactory implements WidgetFactory<Button> { public Button create(Element e) { Button button = new Button(); button.getElement().setInnerText(e.getInnerText()); - + if ("button".equalsIgnoreCase(e.getTagName())){ copyAttributes((ButtonElement)e.cast(), (ButtonElement)button.getElement().cast()); } - + WidgetsUtils.replaceOrAppend(e, button); return button; } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/HtmlPanelWidgetFactory.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/HtmlPanelWidgetFactory.java index cda36110..e5c18f0a 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/HtmlPanelWidgetFactory.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/HtmlPanelWidgetFactory.java @@ -1,12 +1,12 @@ /* * Copyright 2012, 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 @@ -19,9 +19,9 @@ import com.google.gwt.dom.client.Element; import com.google.gwt.user.client.ui.HTMLPanel; public class HtmlPanelWidgetFactory implements WidgetFactory<HTMLPanel> { - + public HTMLPanel create(Element e) { return new WidgetsHtmlPanel(e); } - + }
\ No newline at end of file diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/LabelWidgetFactory.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/LabelWidgetFactory.java index 61636672..0beb81d6 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/LabelWidgetFactory.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/LabelWidgetFactory.java @@ -1,12 +1,12 @@ /* * 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 @@ -19,12 +19,12 @@ import com.google.gwt.dom.client.Element; import com.google.gwt.user.client.ui.Label; public class LabelWidgetFactory implements WidgetFactory<Label> { - + public Label create(Element e) { Label label = new Label(); label.setText(e.getInnerText()); WidgetsUtils.replaceOrAppend(e, label); return label; } - + }
\ No newline at end of file diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/PasswordTextBoxWidgetFactory.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/PasswordTextBoxWidgetFactory.java index 2d98e941..2211cbcc 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/PasswordTextBoxWidgetFactory.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/PasswordTextBoxWidgetFactory.java @@ -1,12 +1,12 @@ /* * 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 @@ -21,7 +21,7 @@ import com.google.gwt.user.client.ui.PasswordTextBox; * Factory used to create a {@link PasswordTextBox} widget. A * {@link PasswordTextBox} is created if the element is a <i>input</i> with type * <i>password</i>, a <i>div</i> or a<i>span</i> element. - * + * */ public class PasswordTextBoxWidgetFactory extends TextBoxBaseWidgetFactory<PasswordTextBox> { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextAreaWidgetFactory.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextAreaWidgetFactory.java index 2fab94c9..eff780f5 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextAreaWidgetFactory.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextAreaWidgetFactory.java @@ -1,12 +1,12 @@ /* * 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 @@ -21,7 +21,7 @@ import com.google.gwt.user.client.ui.TextArea; /** * Factory used to create a {@link TextArea} widget. - * + * */ public class TextAreaWidgetFactory extends TextBoxBaseWidgetFactory<TextArea> { @@ -29,7 +29,7 @@ public class TextAreaWidgetFactory extends TextBoxBaseWidgetFactory<TextArea> { protected void copyAttributes(Element src, Element dest) { TextAreaElement source= src.cast(); TextAreaElement destination = dest.cast(); - + destination.setAccessKey(source.getAccessKey()); destination.setCols(source.getCols()); destination.setDefaultValue(source.getDefaultValue()); @@ -39,13 +39,13 @@ public class TextAreaWidgetFactory extends TextBoxBaseWidgetFactory<TextArea> { destination.setRows(source.getRows()); destination.setValue(source.getValue()); } - + @Override protected String getEquivalentTagName() { return "textarea"; } - - + + protected TextArea createWidget() { return new TextArea(); } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextBoxBaseWidgetFactory.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextBoxBaseWidgetFactory.java index af82d241..a3190a95 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextBoxBaseWidgetFactory.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextBoxBaseWidgetFactory.java @@ -1,12 +1,12 @@ /* * 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 @@ -21,8 +21,8 @@ import com.google.gwt.query.client.GQuery; import com.google.gwt.user.client.ui.TextBoxBase; /** - * - * + * + * */ public abstract class TextBoxBaseWidgetFactory<T extends TextBoxBase> implements WidgetFactory<T> { @@ -40,7 +40,7 @@ public abstract class TextBoxBaseWidgetFactory<T extends TextBoxBase> return (T) textBox; } - + protected String getEquivalentTagName(){ return "input"; } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextBoxWidgetFactory.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextBoxWidgetFactory.java index 4cbe5c54..cf650fb3 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextBoxWidgetFactory.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextBoxWidgetFactory.java @@ -1,12 +1,12 @@ /* * 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 @@ -21,7 +21,7 @@ import com.google.gwt.user.client.ui.TextBox; * Factory used to create a {@link TextBox} widget. A {@link TextBox} is created * if the element is a <i>input</i> with type text, a <i>div</i> or a<i>span</i> * element. - * + * */ public class TextBoxWidgetFactory extends TextBoxBaseWidgetFactory<TextBox> { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetFactory.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetFactory.java index 101f2ca8..abd94ef1 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetFactory.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetFactory.java @@ -1,12 +1,12 @@ /* * 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 @@ -20,7 +20,7 @@ import com.google.gwt.user.client.ui.Widget; /** * Factory interface - * + * * @param <W> * @param <O> */ diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetInitializer.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetInitializer.java index edf22d2d..47369c82 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetInitializer.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetInitializer.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetsHtmlPanel.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetsHtmlPanel.java index cc186f52..657f1ff6 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetsHtmlPanel.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetsHtmlPanel.java @@ -1,12 +1,12 @@ /* * 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 @@ -38,7 +38,7 @@ public class WidgetsHtmlPanel extends HTMLPanel { if (e != null) { Widget w = $(e).widget(); if (w == null) { - // We convert the element to a gwt htmlPanel + // We convert the element to a gwt htmlPanel setElementImpl(e); WidgetsUtils.attachWidget(this, null); } else { @@ -58,9 +58,9 @@ public class WidgetsHtmlPanel extends HTMLPanel { } adoptSubWidgets(); } - + /** - * use jsni to access private attribute + * use jsni to access private attribute */ private native void setElementImpl(Element e)/*-{ this.@com.google.gwt.user.client.ui.UIObject::element = e; @@ -78,7 +78,7 @@ public class WidgetsHtmlPanel extends HTMLPanel { * Check if the {@link Element Element} <code>root</code> is attached to the * widget. If it is the case, adopt the widget. If not, check if the chidren * are linked to a widget to adopt them. - * + * */ protected void adoptSubWidgets(Element root) { @@ -99,7 +99,7 @@ public class WidgetsHtmlPanel extends HTMLPanel { * widget is an {@link HTMLPanel} or is null, the widget will not detach * physically in order to maintain the html structure. If the parent is an * other widget, it will be physically detach and reattach to this panel. - * + * * @param w */ protected void doAdopt(Widget w) { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetsUtils.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetsUtils.java index 7af9fe01..7b42787b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetsUtils.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/WidgetsUtils.java @@ -1,12 +1,12 @@ /* * 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 @@ -38,7 +38,7 @@ public class WidgetsUtils { static final String[] appendingTags = { "td", "th", "li"}; - + /** * Append a widget to a dom element, and hide it. * Element classes will be copied to the new widget. @@ -56,7 +56,7 @@ public class WidgetsUtils { /** * Test if the tag name of the element is one of tag names given in parameter - * + * * @param tagNames * @return */ @@ -77,7 +77,7 @@ public class WidgetsUtils { return e.getTagName().toUpperCase().matches(regExp.toString()); } - + /** * Replace a dom element by a widget. * Old element classes will be copied to the new widget. @@ -92,7 +92,7 @@ public class WidgetsUtils { attachWidget(widget, getFirstParentWidget(widget)); } } - + private static Widget getFirstParentWidget(Widget w) { Element e = w.getElement().getParentElement(); BodyElement body = Document.get().getBody(); @@ -107,7 +107,7 @@ public class WidgetsUtils { } return null; } - + private static void hideAndAfter(Element oldElement, Element newElement) { assert oldElement != null && newElement != null; GQuery.$(oldElement).hide().after(newElement); @@ -124,12 +124,12 @@ public class WidgetsUtils { */ private static void replaceOrAppend(Element oldElement, Element newElement) { assert oldElement != null && newElement != null; - + if(matchesTags(oldElement, appendingTags)){ GQuery.$(oldElement).html("").append(newElement); }else{ GQuery.$(oldElement).replaceWith(newElement); - + //copy class String c = oldElement.getClassName(); if (!c.isEmpty()) { @@ -139,10 +139,10 @@ public class WidgetsUtils { newElement.setId(oldElement.getId()); //ensure no duplicate id oldElement.setId(""); - + } } - + private static void replaceWidget(Widget oldWidget, Widget newWidget, boolean remove) { Widget parent = oldWidget.getParent(); boolean removed = false; @@ -169,13 +169,13 @@ public class WidgetsUtils { oldWidget.setVisible(false); } } - + /** * Attach a widget to the GWT widget list. - * + * * @param widget to attach - * @param firstParentWidget the parent widget, - * If it is null we just add the widget to the gwt detach list + * @param firstParentWidget the parent widget, + * If it is null we just add the widget to the gwt detach list */ public static void attachWidget(Widget widget, Widget firstParentWidget) { if (widget != null && widget.getParent() == null) { @@ -203,14 +203,14 @@ public class WidgetsUtils { } /** - * This method detach a widget of its parent without doing a physical + * This method detach a widget of its parent without doing a physical * detach (DOM manipulation) - * + * * @param w */ public static void doLogicalDetachFromHtmlPanel(Widget w) { Widget parent = w.getParent(); - + if (parent instanceof HTMLPanel) { complexPanelGetChildren((HTMLPanel) parent).remove(w); widgetSetParent(w, null); @@ -219,9 +219,9 @@ public class WidgetsUtils { "You can only use this method to detach a child from an HTMLPanel"); } } - + /** - * Return children of the first widget's panel + * Return children of the first widget's panel */ public static Iterator<Widget> getChildren(Widget w){ if(w instanceof Panel){ @@ -232,7 +232,7 @@ public class WidgetsUtils { } return null; } - + private static native void widgetOnAttach(Widget w) /*-{ w.@com.google.gwt.user.client.ui.Widget::onAttach()(); }-*/; @@ -240,11 +240,11 @@ public class WidgetsUtils { private static native void widgetSetParent(Widget w, Widget p) /*-{ w.@com.google.gwt.user.client.ui.Widget::setParent(Lcom/google/gwt/user/client/ui/Widget;)(p); }-*/; - + private static native Widget compositeGetWidget(Composite w) /*-{ return w.@com.google.gwt.user.client.ui.Composite::getWidget()(); }-*/; - + private static native WidgetCollection complexPanelGetChildren(ComplexPanel w) /*-{ return w.@com.google.gwt.user.client.ui.ComplexPanel::getChildren()(); }-*/; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/linker/IFrameWithDocTypeLinker.java b/gwtquery-core/src/main/java/com/google/gwt/query/linker/IFrameWithDocTypeLinker.java index 5198c1f7..ae5c3c9e 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/linker/IFrameWithDocTypeLinker.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/linker/IFrameWithDocTypeLinker.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/JsonBuilderGenerator.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/JsonBuilderGenerator.java index 83651e12..50d609f4 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/JsonBuilderGenerator.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/JsonBuilderGenerator.java @@ -1,282 +1,282 @@ -/*
- * 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.rebind;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.ext.Generator;
-import com.google.gwt.core.ext.GeneratorContext;
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.typeinfo.JArrayType;
-import com.google.gwt.core.ext.typeinfo.JClassType;
-import com.google.gwt.core.ext.typeinfo.JMethod;
-import com.google.gwt.core.ext.typeinfo.JParameter;
-import com.google.gwt.core.ext.typeinfo.JParameterizedType;
-import com.google.gwt.core.ext.typeinfo.JType;
-import com.google.gwt.core.ext.typeinfo.TypeOracle;
-import com.google.gwt.query.client.Function;
-import com.google.gwt.query.client.Properties;
-import com.google.gwt.query.client.builders.JsonBuilder;
-import com.google.gwt.query.client.builders.Name;
-import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
-import com.google.gwt.user.rebind.SourceWriter;
-
-import java.io.PrintWriter;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-/**
- */
-public class JsonBuilderGenerator extends Generator {
-
- static JClassType functionType;
- static JClassType jsonBuilderType;
- static JClassType jsType;
- static JClassType listType;
- static JClassType stringType;
- public static String capitalize(String s) {
- if (s.length() == 0)
- return s;
- return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
- }
-
- public static String classNameToJsonName(String name) {
- return deCapitalize(name.replaceAll("^.*[\\.\\$_]", ""));
- }
-
- public static String deCapitalize(String s) {
- return s == null || s.isEmpty() ? s :
- (s.substring(0, 1).toLowerCase() + (s.length() > 1 ? s.substring(1) : ""));
- }
-
- TypeOracle oracle;
-
- public String generate(TreeLogger treeLogger,
- GeneratorContext generatorContext, String requestedClass)
- throws UnableToCompleteException {
- oracle = generatorContext.getTypeOracle();
- JClassType clazz = oracle.findType(requestedClass);
- jsonBuilderType = oracle.findType(JsonBuilder.class.getName());
- stringType = oracle.findType(String.class.getName());
- jsType = oracle.findType(JavaScriptObject.class.getName());
- listType = oracle.findType(List.class.getName());
- functionType = oracle.findType(Function.class.getName());
-
- String t[] = generateClassName(clazz);
-
- SourceWriter sw = getSourceWriter(treeLogger, generatorContext, t[0], t[1],
- requestedClass);
- if (sw != null) {
- Set<String> attrs = new HashSet<String>();
- for (JMethod method : clazz.getInheritableMethods()) {
- String methName = method.getName();
- //skip method from JsonBuilder
- if(jsonBuilderType.findMethod(method.getName(), method.getParameterTypes()) != null){
- continue;
- }
-
- Name nameAnnotation = method.getAnnotation(Name.class);
- String name = nameAnnotation != null
- ? nameAnnotation.value()
- : methName.replaceFirst("^(get|set)", "");
- name = name.substring(0, 1).toLowerCase() + name.substring(1);
- attrs.add(name);
- generateMethod(sw, method, name, treeLogger);
- }
- generateFieldNamesMethod(sw, attrs, treeLogger);
- generateToJsonMethod(sw, t[3], treeLogger);
- sw.commit(treeLogger);
- }
- return t[2];
- }
-
- public String[] generateClassName(JType t) {
- String[] ret = new String[4];
- JClassType c = t.isClassOrInterface();
- ret[0] = c.getPackage().getName();
- ret[1] = c.getName().replace('.', '_') + "_JsonBuilder";
- ret[2] = ret[0] + "." + ret[1];
- ret[3] = classNameToJsonName(c.getName());
- return ret;
- }
-
- public void generateFieldNamesMethod(SourceWriter sw, Collection<String> attrs, TreeLogger logger) {
- String ret = "";
- for (Iterator<String> it = attrs.iterator(); it.hasNext();) {
- ret += (ret.isEmpty() ? "" : ",") + "\"" + it.next() + "\"";
- }
- sw.println("public final String[] getFieldNames() {return new String[]{" + ret + "};}");
- }
-
- public void generateMethod(SourceWriter sw, JMethod method, String name, TreeLogger logger)
- throws UnableToCompleteException {
- String ifaceName = method.getEnclosingType().getQualifiedSourceName();
-
- String retType = method.getReturnType().getParameterizedQualifiedSourceName();
- sw.print("public final " + retType + " " + method.getName());
- JParameter[] params = method.getParameters();
- if (params.length == 0) {
- JArrayType arr = method.getReturnType().isArray();
- JParameterizedType list = method.getReturnType().isParameterized();
-
- sw.println("() {");
- sw.indent();
- if (retType.matches("(java.lang.Boolean|boolean)")) {
- sw.println("return p.getBoolean(\"" + name + "\");");
- } else if (retType.matches("java.util.Date")) {
- sw.println("return new Date(java.lang.Long.parseLong(p.getStr(\"" + name + "\")));");
- } else if (method.getReturnType().isPrimitive() != null) {
- sw.println("return (" + retType + ")p.getFloat(\"" + name + "\");");
- } else if (retType.equals("java.lang.Character")) {
- sw.println("return (char) p.getFloat(\"" + name + "\");");
- } else if (retType.equals("java.lang.Byte")) {
- sw.println("return (byte) p.getFloat(\"" + name + "\");");
- } else if (retType.equals("java.lang.Integer")) {
- sw.println("return (int) p.getFloat(\"" + name + "\");");
- } else if (retType.equals("java.lang.Float")) {
- sw.println("return p.getFloat(\"" + name + "\");");
- } else if (retType.equals("java.lang.Double")) {
- sw.println("return (double) p.getFloat(\"" + name + "\");");
- } else if (retType.equals("java.lang.Long")) {
- sw.println("return (long) p.getFloat(\"" + name + "\");");
- } else if (retType.equals("java.lang.Byte")) {
- sw.println("return (byte) p.getFloat(\"" + name + "\");");
- } else if (isTypeAssignableTo(method.getReturnType(), stringType)) {
- sw.println("return p.getStr(\"" + name + "\");");
- } else if (isTypeAssignableTo(method.getReturnType(), jsonBuilderType)) {
- String q = method.getReturnType().getQualifiedSourceName();
- sw.println("return " + "((" + q + ")GWT.create(" + q + ".class))"
- + ".load(p.getJavaScriptObject(\"" + name + "\"));");
- } else if (retType.equals(Properties.class.getName())) {
- sw.println("return getPropertiesBase(\"" + name + "\");");
- } else if (isTypeAssignableTo(method.getReturnType(), jsType)) {
- sw.println("return p.getJavaScriptObject(\"" + name + "\");");
- } else if (isTypeAssignableTo(method.getReturnType(), functionType)) {
- sw.println("return p.getFunction(\"" + name + "\");");
- } else if (arr != null || list != null) {
- JType type = arr != null ? arr.getComponentType()
- : list.getTypeArgs()[0];
- boolean buildType = isTypeAssignableTo(type, jsonBuilderType);
- String t = type.getQualifiedSourceName();
- sw.println("JsArrayMixed a = p.getArray(\"" + name + "\");");
- sw.println("int l = a == null ? 0 : a.length();");
- String ret;
- if (buildType) {
- sw.println(t + "[] r = new " + t + "[l];");
- sw.println("JsObjectArray<?> a1 = p.getArray(\"" + name
- + "\").cast();");
- sw.println("int l1 = r.length;");
- sw.println("for (int i = 0 ; i < l1 ; i++) {");
- sw.println(" Object w = a1.get(i);");
- sw.println(" " + t + " instance = GWT.create(" + t + ".class);");
- sw.println(" r[i] = instance.load(w);");
- sw.println("}");
- ret = "r";
- } else {
- ret = "getArrayBase(\"" + name + "\", new " + t + "[l], " + t + ".class)";
- }
- if (arr != null) {
- sw.println("return " + ret + ";");
- } else {
- sw.println("return Arrays.asList(" + ret + ");");
- }
- } else if (method.getReturnType().isEnum() != null){
- sw.println("return "+method.getReturnType().getQualifiedSourceName()+".valueOf(p.getStr(\"" + name + "\"));");
- }else {
- sw.println("System.err.println(\"JsonBuilderGenerator WARN: unknown return type "
- + retType + " " + ifaceName + "." + name + "()\"); ");
- // We return the object because probably the user knows how to handle it
- sw.println("return p.get(\"" + name + "\");");
- }
- sw.outdent();
- sw.println("}");
- } else if (params.length == 1) {
- JType type = params[0].getType();
- JArrayType arr = type.isArray();
- JParameterizedType list = type.isParameterized();
-
- sw.print("(" + type.getParameterizedQualifiedSourceName() + " a)");
- sw.println("{");
- sw.indent();
- if (arr != null || list != null) {
- String a = "a";
- if (list != null) {
- a = "a.toArray(new " + list.getTypeArgs()[0].getQualifiedSourceName()
- + "[0])";
- }
- sw.println("setArrayBase(\"" + name + "\", " + a + ");");
- } else if (type.getParameterizedQualifiedSourceName().matches("java.util.Date")) {
- sw.println("p.setNumber(\"" + name + "\", a.getTime());");
- } else if (type.getParameterizedQualifiedSourceName().matches("(java.lang.(Character|Long|Double|Integer|Float|Byte)|(char|long|double|int|float|byte))")) {
- sw.println("p.setNumber(\"" + name + "\", a);");
- } else if (type.getParameterizedQualifiedSourceName().matches("(java.lang.Boolean|boolean)")) {
- sw.println("p.setBoolean(\"" + name + "\", a);");
- } else if (type.getParameterizedQualifiedSourceName().matches("com.google.gwt.query.client.Function")) {
- sw.println("p.setFunction(\"" + name + "\", a);");
- } else if (type.isEnum() != null){
- sw.println("p.set(\"" + name + "\", a.name());");
- }else {
- sw.println("p.set(\"" + name + "\", a);");
- }
- if (!"void".equals(retType)) {
- if (isTypeAssignableTo(method.getReturnType(),
- method.getEnclosingType())) {
- sw.println("return this;");
- } else {
- sw.println("return null;");
- }
- }
- sw.outdent();
- sw.println("}");
- }
- }
-
- public void generateToJsonMethod(SourceWriter sw, String name, TreeLogger logger) {
- sw.println("public final String getJsonName() {return \"" + name + "\";}");
- sw.println("public final String toJson() {return \"{\\\"\" + getJsonName() + \"\\\":\" + toString() + \"}\";}");
- }
-
- protected SourceWriter getSourceWriter(TreeLogger logger,
- GeneratorContext context, String packageName, String className,
- String... interfaceNames) {
- PrintWriter printWriter = context.tryCreate(logger, packageName, className);
- if (printWriter == null) {
- return null;
- }
- ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(
- packageName, className);
- composerFactory.setSuperclass("com.google.gwt.query.client.builders.JsonBuilderBase<"
- + packageName + "." + className + ">");
- composerFactory.addImport("com.google.gwt.query.client.js.*");
- composerFactory.addImport("com.google.gwt.query.client.*");
- composerFactory.addImport("com.google.gwt.core.client.*");
- composerFactory.addImport("com.google.gwt.dom.client.*");
- composerFactory.addImport("java.util.*");
-
- for (String interfaceName : interfaceNames) {
- composerFactory.addImplementedInterface(interfaceName);
- }
- return composerFactory.createSourceWriter(context, printWriter);
- }
-
- public boolean isTypeAssignableTo(JType t, JClassType o) {
- JClassType c = t.isClassOrInterface();
- return (c != null && c.isAssignableTo(o));
- }
-}
+/* + * 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.rebind; + +import com.google.gwt.core.client.JavaScriptObject; +import com.google.gwt.core.ext.Generator; +import com.google.gwt.core.ext.GeneratorContext; +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JArrayType; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.core.ext.typeinfo.JParameter; +import com.google.gwt.core.ext.typeinfo.JParameterizedType; +import com.google.gwt.core.ext.typeinfo.JType; +import com.google.gwt.core.ext.typeinfo.TypeOracle; +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.Properties; +import com.google.gwt.query.client.builders.JsonBuilder; +import com.google.gwt.query.client.builders.Name; +import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; +import com.google.gwt.user.rebind.SourceWriter; + +import java.io.PrintWriter; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +/** + */ +public class JsonBuilderGenerator extends Generator { + + static JClassType functionType; + static JClassType jsonBuilderType; + static JClassType jsType; + static JClassType listType; + static JClassType stringType; + public static String capitalize(String s) { + if (s.length() == 0) + return s; + return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase(); + } + + public static String classNameToJsonName(String name) { + return deCapitalize(name.replaceAll("^.*[\\.\\$_]", "")); + } + + public static String deCapitalize(String s) { + return s == null || s.isEmpty() ? s : + (s.substring(0, 1).toLowerCase() + (s.length() > 1 ? s.substring(1) : "")); + } + + TypeOracle oracle; + + public String generate(TreeLogger treeLogger, + GeneratorContext generatorContext, String requestedClass) + throws UnableToCompleteException { + oracle = generatorContext.getTypeOracle(); + JClassType clazz = oracle.findType(requestedClass); + jsonBuilderType = oracle.findType(JsonBuilder.class.getName()); + stringType = oracle.findType(String.class.getName()); + jsType = oracle.findType(JavaScriptObject.class.getName()); + listType = oracle.findType(List.class.getName()); + functionType = oracle.findType(Function.class.getName()); + + String t[] = generateClassName(clazz); + + SourceWriter sw = getSourceWriter(treeLogger, generatorContext, t[0], t[1], + requestedClass); + if (sw != null) { + Set<String> attrs = new HashSet<String>(); + for (JMethod method : clazz.getInheritableMethods()) { + String methName = method.getName(); + //skip method from JsonBuilder + if(jsonBuilderType.findMethod(method.getName(), method.getParameterTypes()) != null){ + continue; + } + + Name nameAnnotation = method.getAnnotation(Name.class); + String name = nameAnnotation != null + ? nameAnnotation.value() + : methName.replaceFirst("^(get|set)", ""); + name = name.substring(0, 1).toLowerCase() + name.substring(1); + attrs.add(name); + generateMethod(sw, method, name, treeLogger); + } + generateFieldNamesMethod(sw, attrs, treeLogger); + generateToJsonMethod(sw, t[3], treeLogger); + sw.commit(treeLogger); + } + return t[2]; + } + + public String[] generateClassName(JType t) { + String[] ret = new String[4]; + JClassType c = t.isClassOrInterface(); + ret[0] = c.getPackage().getName(); + ret[1] = c.getName().replace('.', '_') + "_JsonBuilder"; + ret[2] = ret[0] + "." + ret[1]; + ret[3] = classNameToJsonName(c.getName()); + return ret; + } + + public void generateFieldNamesMethod(SourceWriter sw, Collection<String> attrs, TreeLogger logger) { + String ret = ""; + for (Iterator<String> it = attrs.iterator(); it.hasNext();) { + ret += (ret.isEmpty() ? "" : ",") + "\"" + it.next() + "\""; + } + sw.println("public final String[] getFieldNames() {return new String[]{" + ret + "};}"); + } + + public void generateMethod(SourceWriter sw, JMethod method, String name, TreeLogger logger) + throws UnableToCompleteException { + String ifaceName = method.getEnclosingType().getQualifiedSourceName(); + + String retType = method.getReturnType().getParameterizedQualifiedSourceName(); + sw.print("public final " + retType + " " + method.getName()); + JParameter[] params = method.getParameters(); + if (params.length == 0) { + JArrayType arr = method.getReturnType().isArray(); + JParameterizedType list = method.getReturnType().isParameterized(); + + sw.println("() {"); + sw.indent(); + if (retType.matches("(java.lang.Boolean|boolean)")) { + sw.println("return p.getBoolean(\"" + name + "\");"); + } else if (retType.matches("java.util.Date")) { + sw.println("return new Date(java.lang.Long.parseLong(p.getStr(\"" + name + "\")));"); + } else if (method.getReturnType().isPrimitive() != null) { + sw.println("return (" + retType + ")p.getFloat(\"" + name + "\");"); + } else if (retType.equals("java.lang.Character")) { + sw.println("return (char) p.getFloat(\"" + name + "\");"); + } else if (retType.equals("java.lang.Byte")) { + sw.println("return (byte) p.getFloat(\"" + name + "\");"); + } else if (retType.equals("java.lang.Integer")) { + sw.println("return (int) p.getFloat(\"" + name + "\");"); + } else if (retType.equals("java.lang.Float")) { + sw.println("return p.getFloat(\"" + name + "\");"); + } else if (retType.equals("java.lang.Double")) { + sw.println("return (double) p.getFloat(\"" + name + "\");"); + } else if (retType.equals("java.lang.Long")) { + sw.println("return (long) p.getFloat(\"" + name + "\");"); + } else if (retType.equals("java.lang.Byte")) { + sw.println("return (byte) p.getFloat(\"" + name + "\");"); + } else if (isTypeAssignableTo(method.getReturnType(), stringType)) { + sw.println("return p.getStr(\"" + name + "\");"); + } else if (isTypeAssignableTo(method.getReturnType(), jsonBuilderType)) { + String q = method.getReturnType().getQualifiedSourceName(); + sw.println("return " + "((" + q + ")GWT.create(" + q + ".class))" + + ".load(p.getJavaScriptObject(\"" + name + "\"));"); + } else if (retType.equals(Properties.class.getName())) { + sw.println("return getPropertiesBase(\"" + name + "\");"); + } else if (isTypeAssignableTo(method.getReturnType(), jsType)) { + sw.println("return p.getJavaScriptObject(\"" + name + "\");"); + } else if (isTypeAssignableTo(method.getReturnType(), functionType)) { + sw.println("return p.getFunction(\"" + name + "\");"); + } else if (arr != null || list != null) { + JType type = arr != null ? arr.getComponentType() + : list.getTypeArgs()[0]; + boolean buildType = isTypeAssignableTo(type, jsonBuilderType); + String t = type.getQualifiedSourceName(); + sw.println("JsArrayMixed a = p.getArray(\"" + name + "\");"); + sw.println("int l = a == null ? 0 : a.length();"); + String ret; + if (buildType) { + sw.println(t + "[] r = new " + t + "[l];"); + sw.println("JsObjectArray<?> a1 = p.getArray(\"" + name + + "\").cast();"); + sw.println("int l1 = r.length;"); + sw.println("for (int i = 0 ; i < l1 ; i++) {"); + sw.println(" Object w = a1.get(i);"); + sw.println(" " + t + " instance = GWT.create(" + t + ".class);"); + sw.println(" r[i] = instance.load(w);"); + sw.println("}"); + ret = "r"; + } else { + ret = "getArrayBase(\"" + name + "\", new " + t + "[l], " + t + ".class)"; + } + if (arr != null) { + sw.println("return " + ret + ";"); + } else { + sw.println("return Arrays.asList(" + ret + ");"); + } + } else if (method.getReturnType().isEnum() != null){ + sw.println("return "+method.getReturnType().getQualifiedSourceName()+".valueOf(p.getStr(\"" + name + "\"));"); + }else { + sw.println("System.err.println(\"JsonBuilderGenerator WARN: unknown return type " + + retType + " " + ifaceName + "." + name + "()\"); "); + // We return the object because probably the user knows how to handle it + sw.println("return p.get(\"" + name + "\");"); + } + sw.outdent(); + sw.println("}"); + } else if (params.length == 1) { + JType type = params[0].getType(); + JArrayType arr = type.isArray(); + JParameterizedType list = type.isParameterized(); + + sw.print("(" + type.getParameterizedQualifiedSourceName() + " a)"); + sw.println("{"); + sw.indent(); + if (arr != null || list != null) { + String a = "a"; + if (list != null) { + a = "a.toArray(new " + list.getTypeArgs()[0].getQualifiedSourceName() + + "[0])"; + } + sw.println("setArrayBase(\"" + name + "\", " + a + ");"); + } else if (type.getParameterizedQualifiedSourceName().matches("java.util.Date")) { + sw.println("p.setNumber(\"" + name + "\", a.getTime());"); + } else if (type.getParameterizedQualifiedSourceName().matches("(java.lang.(Character|Long|Double|Integer|Float|Byte)|(char|long|double|int|float|byte))")) { + sw.println("p.setNumber(\"" + name + "\", a);"); + } else if (type.getParameterizedQualifiedSourceName().matches("(java.lang.Boolean|boolean)")) { + sw.println("p.setBoolean(\"" + name + "\", a);"); + } else if (type.getParameterizedQualifiedSourceName().matches("com.google.gwt.query.client.Function")) { + sw.println("p.setFunction(\"" + name + "\", a);"); + } else if (type.isEnum() != null){ + sw.println("p.set(\"" + name + "\", a.name());"); + }else { + sw.println("p.set(\"" + name + "\", a);"); + } + if (!"void".equals(retType)) { + if (isTypeAssignableTo(method.getReturnType(), + method.getEnclosingType())) { + sw.println("return this;"); + } else { + sw.println("return null;"); + } + } + sw.outdent(); + sw.println("}"); + } + } + + public void generateToJsonMethod(SourceWriter sw, String name, TreeLogger logger) { + sw.println("public final String getJsonName() {return \"" + name + "\";}"); + sw.println("public final String toJson() {return \"{\\\"\" + getJsonName() + \"\\\":\" + toString() + \"}\";}"); + } + + protected SourceWriter getSourceWriter(TreeLogger logger, + GeneratorContext context, String packageName, String className, + String... interfaceNames) { + PrintWriter printWriter = context.tryCreate(logger, packageName, className); + if (printWriter == null) { + return null; + } + ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory( + packageName, className); + composerFactory.setSuperclass("com.google.gwt.query.client.builders.JsonBuilderBase<" + + packageName + "." + className + ">"); + composerFactory.addImport("com.google.gwt.query.client.js.*"); + composerFactory.addImport("com.google.gwt.query.client.*"); + composerFactory.addImport("com.google.gwt.core.client.*"); + composerFactory.addImport("com.google.gwt.dom.client.*"); + composerFactory.addImport("java.util.*"); + + for (String interfaceName : interfaceNames) { + composerFactory.addImplementedInterface(interfaceName); + } + return composerFactory.createSourceWriter(context, printWriter); + } + + public boolean isTypeAssignableTo(JType t, JClassType o) { + JClassType c = t.isClassOrInterface(); + return (c != null && c.isAssignableTo(o)); + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/LazyGenerator.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/LazyGenerator.java index 56a15f18..504fb221 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/LazyGenerator.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/LazyGenerator.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorBase.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorBase.java index ed1d6b70..d2aff311 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorBase.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorBase.java @@ -1,205 +1,205 @@ -/*
- * 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.rebind;
-
-import com.google.gwt.core.ext.Generator;
-import com.google.gwt.core.ext.GeneratorContext;
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.typeinfo.JClassType;
-import com.google.gwt.core.ext.typeinfo.JMethod;
-import com.google.gwt.core.ext.typeinfo.JParameter;
-import com.google.gwt.core.ext.typeinfo.TypeOracle;
-import com.google.gwt.query.client.Selector;
-import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
-import com.google.gwt.user.rebind.SourceWriter;
-
-import java.io.PrintWriter;
-
-/**
- * Base class for compile time selector generators.
- */
-public abstract class SelectorGeneratorBase extends Generator {
-
- protected JClassType nodeType = null;
-
- private TreeLogger treeLogger;
-
- public String generate(TreeLogger treeLogger,
- GeneratorContext generatorContext, String requestedClass)
- throws UnableToCompleteException {
- this.treeLogger = treeLogger;
- TypeOracle oracle = generatorContext.getTypeOracle();
- nodeType = oracle.findType("com.google.gwt.dom.client.Node");
-
- JClassType selectorType = oracle.findType(requestedClass);
-
- String generatedPkgName = selectorType.getPackage().getName();
- String generatedClassName = selectorType.getName().replace('.', '_') + "_"
- + getImplSuffix();
-
- SourceWriter sw = getSourceWriter(treeLogger, generatorContext,
- generatedPkgName, generatedClassName, requestedClass);
- if (sw != null) {
- for (JMethod method : selectorType.getInheritableMethods()) {
- generateMethod(sw, method, treeLogger);
- }
- genGetAllMethod(sw, selectorType.getInheritableMethods(), treeLogger);
- sw.commit(treeLogger);
- }
-
- return generatedPkgName + "." + generatedClassName;
- }
-
- public void generateMethod(SourceWriter sw, JMethod method, TreeLogger logger)
- throws UnableToCompleteException {
- Selector selectorAnnotation = method.getAnnotation(Selector.class);
- if (selectorAnnotation == null) {
- return;
- }
-
- JParameter[] params = method.getParameters();
-
- String retType = method.getReturnType()
- .getParameterizedQualifiedSourceName();
- sw.print("public final " + retType + " " + method.getName());
- boolean hasContext = false;
- if (params.length == 0) {
- sw.print("()");
- } else if (params.length == 1) {
- JClassType type = params[0].getType().isClassOrInterface();
- if (type != null && type.isAssignableTo(nodeType)) {
- sw.print("(Node root)");
- hasContext = true;
- }
- }
- sw.println(" {");
- sw.indent();
- Selector sel = method.getAnnotation(Selector.class);
-
- if (sel != null && sel.value().matches("^#\\w+$")) {
- // short circuit #foo
- sw.println("return "
- + wrap(method, "JsNodeArray.create(((Document)root).getElementById(\""
- + sel.value().substring(1) + "\"))") + ";");
- } else if (sel != null && sel.value().matches("^\\w+$")) {
- // short circuit FOO
- sw.println("return "
- + wrap(method,
- "JsNodeArray.create(((Element)root).getElementsByTagName(\""
- + sel.value() + "\"))") + ";");
- } else if (sel != null && sel.value().matches("^\\.\\w+$")
- && hasGetElementsByClassName()) {
- // short circuit .foo for browsers with native getElementsByClassName
- sw.println("return "
- + wrap(method, "JsNodeArray.create(getElementsByClassName(\""
- + sel.value().substring(1) + "\", root))") + ";");
- } else {
- generateMethodBody(sw, method, logger, hasContext);
- }
- sw.outdent();
- sw.println("}");
- }
-
- protected void debug(String s) {
- // System.err.println(s);
- treeLogger.log(TreeLogger.DEBUG, s, null);
- }
-
- protected abstract void generateMethodBody(SourceWriter sw, JMethod method,
- TreeLogger logger, boolean hasContext) throws UnableToCompleteException;
-
- protected String getImplSuffix() {
- return "Impl";
- }
-
- protected SourceWriter getSourceWriter(TreeLogger logger,
- GeneratorContext context, String packageName, String className,
- String... interfaceNames) {
- PrintWriter printWriter = context.tryCreate(logger, packageName, className);
- if (printWriter == null) {
- return null;
- }
- ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(
- packageName, className);
- composerFactory.setSuperclass("com.google.gwt.query.client.impl.SelectorEngine");
- composerFactory.addImport("com.google.gwt.query.client.impl.*");
- composerFactory.addImport("com.google.gwt.query.client.js.*");
- composerFactory.addImport("com.google.gwt.query.client.Selectors.*");
- composerFactory.addImport("com.google.gwt.query.client.*");
- composerFactory.addImport("com.google.gwt.core.client.*");
- composerFactory.addImport("com.google.gwt.dom.client.*");
- for (String interfaceName : interfaceNames) {
- composerFactory.addImplementedInterface(interfaceName);
- }
-
- return composerFactory.createSourceWriter(context, printWriter);
- }
-
- protected boolean hasGetElementsByClassName() {
- return false;
- }
-
- protected boolean notNull(String s) {
- return s != null && !"".equals(s);
- }
-
- protected String wrap(JMethod method, String expr) {
- if ("NodeList".equals(method.getReturnType().getSimpleSourceName())) {
- return expr;
- } else {
- return "GQuery.$(" + expr + ")";
- }
- }
-
- protected String wrapJS(JMethod method, String expr) {
- if ("GQuery".equals(method.getReturnType().getSimpleSourceName())) {
- return expr;
- } else {
- return "GQuery.$(" + expr + ")";
- }
- }
-
- // used by benchmark harness
- private void genGetAllMethod(SourceWriter sw, JMethod[] methods,
- TreeLogger treeLogger) {
- sw.println("public DeferredSelector[] getAllSelectors() {return ds;}");
- sw.println("private final DeferredSelector[] ds = new DeferredSelector[] {");
- sw.indent();
- for (JMethod m : methods) {
- Selector selectorAnnotation = m.getAnnotation(Selector.class);
- if (selectorAnnotation == null) {
- continue;
- }
- String selector = selectorAnnotation.value();
-
- sw.println("new DeferredSelector() {");
- sw.indent();
- sw
- .println("public String getSelector() { return \"" + selector
- + "\"; }");
- sw
- .println("public NodeList<Element> runSelector(Node ctx) { return " +
- (m.getName() + (m.getParameters().length == 0 ? "()" : "(ctx)")) +
- ("NodeList".equals(m.getReturnType().getSimpleSourceName()) ? "" : ".get()") + ";}"
- ) ;
- sw.outdent();
- sw.println("},");
- }
- sw.outdent();
- sw.println("};");
- }
-}
+/* + * 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.rebind; + +import com.google.gwt.core.ext.Generator; +import com.google.gwt.core.ext.GeneratorContext; +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.core.ext.typeinfo.JParameter; +import com.google.gwt.core.ext.typeinfo.TypeOracle; +import com.google.gwt.query.client.Selector; +import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; +import com.google.gwt.user.rebind.SourceWriter; + +import java.io.PrintWriter; + +/** + * Base class for compile time selector generators. + */ +public abstract class SelectorGeneratorBase extends Generator { + + protected JClassType nodeType = null; + + private TreeLogger treeLogger; + + public String generate(TreeLogger treeLogger, + GeneratorContext generatorContext, String requestedClass) + throws UnableToCompleteException { + this.treeLogger = treeLogger; + TypeOracle oracle = generatorContext.getTypeOracle(); + nodeType = oracle.findType("com.google.gwt.dom.client.Node"); + + JClassType selectorType = oracle.findType(requestedClass); + + String generatedPkgName = selectorType.getPackage().getName(); + String generatedClassName = selectorType.getName().replace('.', '_') + "_" + + getImplSuffix(); + + SourceWriter sw = getSourceWriter(treeLogger, generatorContext, + generatedPkgName, generatedClassName, requestedClass); + if (sw != null) { + for (JMethod method : selectorType.getInheritableMethods()) { + generateMethod(sw, method, treeLogger); + } + genGetAllMethod(sw, selectorType.getInheritableMethods(), treeLogger); + sw.commit(treeLogger); + } + + return generatedPkgName + "." + generatedClassName; + } + + public void generateMethod(SourceWriter sw, JMethod method, TreeLogger logger) + throws UnableToCompleteException { + Selector selectorAnnotation = method.getAnnotation(Selector.class); + if (selectorAnnotation == null) { + return; + } + + JParameter[] params = method.getParameters(); + + String retType = method.getReturnType() + .getParameterizedQualifiedSourceName(); + sw.print("public final " + retType + " " + method.getName()); + boolean hasContext = false; + if (params.length == 0) { + sw.print("()"); + } else if (params.length == 1) { + JClassType type = params[0].getType().isClassOrInterface(); + if (type != null && type.isAssignableTo(nodeType)) { + sw.print("(Node root)"); + hasContext = true; + } + } + sw.println(" {"); + sw.indent(); + Selector sel = method.getAnnotation(Selector.class); + + if (sel != null && sel.value().matches("^#\\w+$")) { + // short circuit #foo + sw.println("return " + + wrap(method, "JsNodeArray.create(((Document)root).getElementById(\"" + + sel.value().substring(1) + "\"))") + ";"); + } else if (sel != null && sel.value().matches("^\\w+$")) { + // short circuit FOO + sw.println("return " + + wrap(method, + "JsNodeArray.create(((Element)root).getElementsByTagName(\"" + + sel.value() + "\"))") + ";"); + } else if (sel != null && sel.value().matches("^\\.\\w+$") + && hasGetElementsByClassName()) { + // short circuit .foo for browsers with native getElementsByClassName + sw.println("return " + + wrap(method, "JsNodeArray.create(getElementsByClassName(\"" + + sel.value().substring(1) + "\", root))") + ";"); + } else { + generateMethodBody(sw, method, logger, hasContext); + } + sw.outdent(); + sw.println("}"); + } + + protected void debug(String s) { + // System.err.println(s); + treeLogger.log(TreeLogger.DEBUG, s, null); + } + + protected abstract void generateMethodBody(SourceWriter sw, JMethod method, + TreeLogger logger, boolean hasContext) throws UnableToCompleteException; + + protected String getImplSuffix() { + return "Impl"; + } + + protected SourceWriter getSourceWriter(TreeLogger logger, + GeneratorContext context, String packageName, String className, + String... interfaceNames) { + PrintWriter printWriter = context.tryCreate(logger, packageName, className); + if (printWriter == null) { + return null; + } + ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory( + packageName, className); + composerFactory.setSuperclass("com.google.gwt.query.client.impl.SelectorEngine"); + composerFactory.addImport("com.google.gwt.query.client.impl.*"); + composerFactory.addImport("com.google.gwt.query.client.js.*"); + composerFactory.addImport("com.google.gwt.query.client.Selectors.*"); + composerFactory.addImport("com.google.gwt.query.client.*"); + composerFactory.addImport("com.google.gwt.core.client.*"); + composerFactory.addImport("com.google.gwt.dom.client.*"); + for (String interfaceName : interfaceNames) { + composerFactory.addImplementedInterface(interfaceName); + } + + return composerFactory.createSourceWriter(context, printWriter); + } + + protected boolean hasGetElementsByClassName() { + return false; + } + + protected boolean notNull(String s) { + return s != null && !"".equals(s); + } + + protected String wrap(JMethod method, String expr) { + if ("NodeList".equals(method.getReturnType().getSimpleSourceName())) { + return expr; + } else { + return "GQuery.$(" + expr + ")"; + } + } + + protected String wrapJS(JMethod method, String expr) { + if ("GQuery".equals(method.getReturnType().getSimpleSourceName())) { + return expr; + } else { + return "GQuery.$(" + expr + ")"; + } + } + + // used by benchmark harness + private void genGetAllMethod(SourceWriter sw, JMethod[] methods, + TreeLogger treeLogger) { + sw.println("public DeferredSelector[] getAllSelectors() {return ds;}"); + sw.println("private final DeferredSelector[] ds = new DeferredSelector[] {"); + sw.indent(); + for (JMethod m : methods) { + Selector selectorAnnotation = m.getAnnotation(Selector.class); + if (selectorAnnotation == null) { + continue; + } + String selector = selectorAnnotation.value(); + + sw.println("new DeferredSelector() {"); + sw.indent(); + sw + .println("public String getSelector() { return \"" + selector + + "\"; }"); + sw + .println("public NodeList<Element> runSelector(Node ctx) { return " + + (m.getName() + (m.getParameters().length == 0 ? "()" : "(ctx)")) + + ("NodeList".equals(m.getReturnType().getSimpleSourceName()) ? "" : ".get()") + ";}" + ) ; + sw.outdent(); + sw.println("},"); + } + sw.outdent(); + sw.println("};"); + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorCssToXPath.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorCssToXPath.java index a726b6bd..45b1a848 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorCssToXPath.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorCssToXPath.java @@ -1,110 +1,110 @@ -/*
- * 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.rebind;
-
-import java.util.ArrayList;
-import java.util.regex.MatchResult;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathFactory;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.typeinfo.JMethod;
-import com.google.gwt.query.client.Selector;
-import com.google.gwt.query.client.impl.SelectorEngineCssToXPath;
-import com.google.gwt.query.client.impl.SelectorEngineCssToXPath.ReplaceCallback;
-import com.google.gwt.query.client.impl.SelectorEngineCssToXPath.Replacer;
-import com.google.gwt.user.rebind.SourceWriter;
-
-/**
- * Compile time selector generator which translates selector into XPath at
- * compile time. It Uses the SelectorEngineCssToXpath to produce the xpath
- * selectors
- */
-public class SelectorGeneratorCssToXPath extends SelectorGeneratorBase {
-
- /**
- * The replacer implementation for the JVM.
- */
- public static final Replacer replacer = new Replacer() {
- public String replaceAll(String s, String r, Object o) {
- Pattern p = Pattern.compile(r);
- if (o instanceof ReplaceCallback) {
- final Matcher matcher = p.matcher(s);
- ReplaceCallback callback = (ReplaceCallback) o;
- while (matcher.find()) {
- final MatchResult matchResult = matcher.toMatchResult();
- ArrayList<String> argss = new ArrayList<String>();
- for (int i = 0; i < matchResult.groupCount() + 1; i++) {
- argss.add(matchResult.group(i));
- }
- final String replacement = callback.foundMatch(argss);
- s = s.substring(0, matchResult.start()) + replacement
- + s.substring(matchResult.end());
- matcher.reset(s);
- }
- return s;
- } else {
- return p.matcher(s).replaceAll(o.toString());
- }
- }
- };
-
- private SelectorEngineCssToXPath engine = new SelectorEngineCssToXPath(
- replacer);
-
- protected String css2Xpath(String s) {
- return engine.css2Xpath(s);
- }
-
- private XPathFactory factory = XPathFactory.newInstance();
- private XPath xpath = factory.newXPath();
-
- protected void generateMethodBody(SourceWriter sw, JMethod method,
- TreeLogger treeLogger, boolean hasContext)
- throws UnableToCompleteException {
-
- String selector = method.getAnnotation(Selector.class).value();
- String xselector = css2Xpath(selector);
-
- // Validate the generated xpath selector.
- try {
- validateXpath(xselector);
- } catch (XPathExpressionException e1) {
- System.err.println("Invalid XPath generated selector, please revise it: " + xselector);
- if (!selector.equals(xselector)) {
- System.err.println("If your css2 selector syntax is correct, open an issue in the gwtquery project. cssselector:"
- + selector + " xpath:" + xselector);
- }
- throw new UnableToCompleteException();
- }
-
- sw.println("return "
- + wrap(method, "xpathEvaluate(\"" + xselector + "\", root)") + ";");
- }
-
- public void validateXpath(String xselector) throws XPathExpressionException {
- xpath.compile(xselector);
- }
-
- protected String getImplSuffix() {
- return "CssToXPath" + super.getImplSuffix();
- }
-}
+/* + * 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.rebind; + +import java.util.ArrayList; +import java.util.regex.MatchResult; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.query.client.Selector; +import com.google.gwt.query.client.impl.SelectorEngineCssToXPath; +import com.google.gwt.query.client.impl.SelectorEngineCssToXPath.ReplaceCallback; +import com.google.gwt.query.client.impl.SelectorEngineCssToXPath.Replacer; +import com.google.gwt.user.rebind.SourceWriter; + +/** + * Compile time selector generator which translates selector into XPath at + * compile time. It Uses the SelectorEngineCssToXpath to produce the xpath + * selectors + */ +public class SelectorGeneratorCssToXPath extends SelectorGeneratorBase { + + /** + * The replacer implementation for the JVM. + */ + public static final Replacer replacer = new Replacer() { + public String replaceAll(String s, String r, Object o) { + Pattern p = Pattern.compile(r); + if (o instanceof ReplaceCallback) { + final Matcher matcher = p.matcher(s); + ReplaceCallback callback = (ReplaceCallback) o; + while (matcher.find()) { + final MatchResult matchResult = matcher.toMatchResult(); + ArrayList<String> argss = new ArrayList<String>(); + for (int i = 0; i < matchResult.groupCount() + 1; i++) { + argss.add(matchResult.group(i)); + } + final String replacement = callback.foundMatch(argss); + s = s.substring(0, matchResult.start()) + replacement + + s.substring(matchResult.end()); + matcher.reset(s); + } + return s; + } else { + return p.matcher(s).replaceAll(o.toString()); + } + } + }; + + private SelectorEngineCssToXPath engine = new SelectorEngineCssToXPath( + replacer); + + protected String css2Xpath(String s) { + return engine.css2Xpath(s); + } + + private XPathFactory factory = XPathFactory.newInstance(); + private XPath xpath = factory.newXPath(); + + protected void generateMethodBody(SourceWriter sw, JMethod method, + TreeLogger treeLogger, boolean hasContext) + throws UnableToCompleteException { + + String selector = method.getAnnotation(Selector.class).value(); + String xselector = css2Xpath(selector); + + // Validate the generated xpath selector. + try { + validateXpath(xselector); + } catch (XPathExpressionException e1) { + System.err.println("Invalid XPath generated selector, please revise it: " + xselector); + if (!selector.equals(xselector)) { + System.err.println("If your css2 selector syntax is correct, open an issue in the gwtquery project. cssselector:" + + selector + " xpath:" + xselector); + } + throw new UnableToCompleteException(); + } + + sw.println("return " + + wrap(method, "xpathEvaluate(\"" + xselector + "\", root)") + ";"); + } + + public void validateXpath(String xselector) throws XPathExpressionException { + xpath.compile(xselector); + } + + protected String getImplSuffix() { + return "CssToXPath" + super.getImplSuffix(); + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJS.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJS.java index 522843b0..256b2de6 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJS.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJS.java @@ -1,40 +1,40 @@ -/*
- * 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.rebind;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.typeinfo.JMethod;
-import com.google.gwt.query.client.Selector;
-import com.google.gwt.user.rebind.SourceWriter;
-
-/**
- * An implementation which simply defers to the runtime selector engine.
- */
-public class SelectorGeneratorJS extends SelectorGeneratorBase {
-
- protected String getImplSuffix() {
- return "JS" + super.getImplSuffix();
- }
-
- protected void generateMethodBody(SourceWriter sw, JMethod method,
- TreeLogger treeLogger, boolean hasContext)
- throws UnableToCompleteException {
- String selector = method.getAnnotation(Selector.class).value();
- sw.println("return "
- + wrap(method, "impl.select(\"" + selector + "\", root)") + ";");
- }
-}
+/* + * 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.rebind; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.query.client.Selector; +import com.google.gwt.user.rebind.SourceWriter; + +/** + * An implementation which simply defers to the runtime selector engine. + */ +public class SelectorGeneratorJS extends SelectorGeneratorBase { + + protected String getImplSuffix() { + return "JS" + super.getImplSuffix(); + } + + protected void generateMethodBody(SourceWriter sw, JMethod method, + TreeLogger treeLogger, boolean hasContext) + throws UnableToCompleteException { + String selector = method.getAnnotation(Selector.class).value(); + sw.println("return " + + wrap(method, "impl.select(\"" + selector + "\", root)") + ";"); + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJSOptimal.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJSOptimal.java index 92455d0c..7cbdcf13 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJSOptimal.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorJSOptimal.java @@ -1,189 +1,189 @@ -/*
- * 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.rebind;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.typeinfo.JMethod;
-import com.google.gwt.query.client.Selector;
-import com.google.gwt.user.rebind.SourceWriter;
-
-import java.util.regex.Pattern;
-
-/**
- *
- */
-public class SelectorGeneratorJSOptimal extends SelectorGeneratorBase {
-
- static class RuleMatcher {
-
- public Pattern re;
-
- public String fnTemplate;
-
- RuleMatcher(String pat, String fnT) {
- this.re = Pattern.compile(pat);
- this.fnTemplate = fnT;
- }
- }
-
- protected static Pattern nonSpace = Pattern.compile("\\S/");
-
- protected static final String trimReStr = "^\\s+|\\s+$";
-
- protected static Pattern trimRe = Pattern.compile(trimReStr);
-
- protected static Pattern tplRe = Pattern.compile("\\{(\\d+)\\}");
-
- protected static Pattern modeRe = Pattern
- .compile("^(\\s?[\\/>+~]\\s?|\\s|$)");
-
- protected static Pattern tagTokenRe = Pattern
- .compile("^(#)?([a-zA-Z_0-9-\\*]+)");
-
- protected static Pattern nthRe = Pattern.compile("(\\d*)n\\+?(\\d*)");
-
- protected static Pattern nthRe2 = Pattern.compile("\\D");
-
- protected static RuleMatcher[] matchers = new RuleMatcher[]{
- new RuleMatcher("^\\.([a-zA-Z_0-9-]+)",
- "n = byClassName(n, null, \"{0}\");"),
- new RuleMatcher("^\\:([a-zA-Z_0-9-]+)(?:\\(((?:[^ >]*|.*?))\\))?",
- "n = byPseudo(n, \"{0}\", \"{1}\");"), new RuleMatcher(
- "^(?:([\\[\\{])(?:@)?([a-zA-Z_0-9-]+)\\s?(?:(=|.=)\\s?['\"]?(.*?)[\"']?)?[\\]\\}])",
- "n = byAttribute(n, \"{1}\", \"{3}\", \"{2}\", \"{0}\");"),
- new RuleMatcher("^#([a-zA-Z_0-9-]+)", "n = byId(n, null, \"{0}\");")};
-
- protected void generateMethodBody(SourceWriter sw, JMethod method,
- TreeLogger treeLogger, boolean hasContext)
- throws UnableToCompleteException {
-
- String selector = method.getAnnotation(Selector.class).value();
-
- sw.println("return " + wrap(method,
- "impl.select(\"" + selector + "\", root)") + ";");
-// sw.println("JSArray n = JSArray.create();");
-// if(!hasContext) {
-// sw.println("Node root = Document.get();");
-// }
-//
-// // add root node as context.
-// // TODO: support any context
-// sw.println("n.addNode(root);");
-// String q = selector, lq = null;
-// Matcher lmode = modeRe.matcher(q);
-// Matcher mm = null;
-// String mode = "";
-// if (lmode.lookingAt() && notNull(lmode.group(1))) {
-// mode = lmode.group(1).replaceAll(trimReStr, "").trim();
-// q = q.replaceFirst("\\Q" + lmode.group(1) + "\\E", "");
-// }
-//
-// while (notNull(q) && !q.equals(lq)) {
-// debug("Doing q=" + q);
-//
-// lq = q;
-// Matcher tm = tagTokenRe.matcher(q);
-// if (tm.lookingAt()) {
-// if ("#".equals(tm.group(1))) {
-// sw.println("n = quickId(n, \"" + mode + "\", root, \"" + tm.group(2)
-// + "\");");
-// } else {
-// String tagName = tm.group(2);
-// tagName = "".equals(tagName) ? "*" : tagName;
-// // sw.println("if (n.size() == 0) { n=JSArray.create(); }");
-// String func = "";
-// if ("".equals(mode)) {
-// func = "getDescendentNodes";
-// } else if (">".equals(mode)) {
-// func = "getChildNodes";
-// } else if ("+".equals(mode)) {
-// func = "getSiblingNodes";
-// } else if ("~".equals(mode)) {
-// func = "getGeneralSiblingNodes";
-// } else {
-// treeLogger.log(TreeLogger.ERROR, "Error parsing selector, combiner "
-// + mode + " not recognized in " + selector, null);
-// throw new UnableToCompleteException();
-// }
-// sw.println("n = " + func + "(n, \"" + tagName + "\");");
-// }
-// debug("replacing in q, the value " + tm.group(0));
-// q = q.replaceFirst("\\Q" + tm.group(0) + "\\E", "");
-// } else {
-// String func = "";
-// String tagName = "*";
-// if ("".equals(mode)) {
-// func = "getDescendentNodes";
-// } else if (">".equals(mode)) {
-// func = "getChildNodes";
-// } else if ("+".equals(mode)) {
-// func = "getSiblingNodes";
-// } else if ("~".equals(mode)) {
-// func = "getGeneralSiblingNodes";
-// } else {
-// treeLogger.log(TreeLogger.ERROR, "Error parsing selector, combiner "
-// + mode + " not recognized in " + selector, null);
-// throw new UnableToCompleteException();
-// }
-// sw.println("n = " + func + "(n, \"" + tagName + "\");");
-// }
-//
-// while (!(mm = modeRe.matcher(q)).lookingAt()) {
-// debug("Looking at " + q);
-// boolean matched = false;
-// for (RuleMatcher rm : matchers) {
-// Matcher rmm = rm.re.matcher(q);
-// if (rmm.lookingAt()) {
-// String res[] = new String[rmm.groupCount()];
-// for (int i = 1; i <= rmm.groupCount(); i++) {
-// res[i - 1] = rmm.group(i);
-// debug("added param " + res[i - 1]);
-// }
-// Object[] r = res;
-// // inline enum, perhaps type-tightening will allow inlined eval()
-// // call
-// if (rm.fnTemplate.indexOf("byPseudo") != -1) {
-// sw.println("n = Pseudo."+res[0].toUpperCase().replace("-", "_") +
-// ".eval(n, \""+res[1]+"\");");
-// } else {
-// sw.println(MessageFormat.format(rm.fnTemplate, r));
-// }
-// q = q.replaceFirst("\\Q" + rmm.group(0) + "\\E", "");
-// matched = true;
-// break;
-// }
-// }
-// if (!matched) {
-// treeLogger
-// .log(TreeLogger.ERROR, "Error parsing selector at " + q, null);
-// throw new UnableToCompleteException();
-// }
-// }
-//
-// if (notNull(mm.group(1))) {
-// mode = mm.group(1).replaceAll(trimReStr, "");
-// debug("replacing q=" + q + " this part:" + mm.group(1));
-// q = q.replaceFirst("\\Q" + mm.group(1) + "\\E", "");
-// }
-// }
-// sw.println("return "+wrap(method, "nodup(n)")+";");
- }
-
- protected String getImplSuffix() {
- return "JS" + super.getImplSuffix();
- }
-}
+/* + * 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.rebind; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.query.client.Selector; +import com.google.gwt.user.rebind.SourceWriter; + +import java.util.regex.Pattern; + +/** + * + */ +public class SelectorGeneratorJSOptimal extends SelectorGeneratorBase { + + static class RuleMatcher { + + public Pattern re; + + public String fnTemplate; + + RuleMatcher(String pat, String fnT) { + this.re = Pattern.compile(pat); + this.fnTemplate = fnT; + } + } + + protected static Pattern nonSpace = Pattern.compile("\\S/"); + + protected static final String trimReStr = "^\\s+|\\s+$"; + + protected static Pattern trimRe = Pattern.compile(trimReStr); + + protected static Pattern tplRe = Pattern.compile("\\{(\\d+)\\}"); + + protected static Pattern modeRe = Pattern + .compile("^(\\s?[\\/>+~]\\s?|\\s|$)"); + + protected static Pattern tagTokenRe = Pattern + .compile("^(#)?([a-zA-Z_0-9-\\*]+)"); + + protected static Pattern nthRe = Pattern.compile("(\\d*)n\\+?(\\d*)"); + + protected static Pattern nthRe2 = Pattern.compile("\\D"); + + protected static RuleMatcher[] matchers = new RuleMatcher[]{ + new RuleMatcher("^\\.([a-zA-Z_0-9-]+)", + "n = byClassName(n, null, \"{0}\");"), + new RuleMatcher("^\\:([a-zA-Z_0-9-]+)(?:\\(((?:[^ >]*|.*?))\\))?", + "n = byPseudo(n, \"{0}\", \"{1}\");"), new RuleMatcher( + "^(?:([\\[\\{])(?:@)?([a-zA-Z_0-9-]+)\\s?(?:(=|.=)\\s?['\"]?(.*?)[\"']?)?[\\]\\}])", + "n = byAttribute(n, \"{1}\", \"{3}\", \"{2}\", \"{0}\");"), + new RuleMatcher("^#([a-zA-Z_0-9-]+)", "n = byId(n, null, \"{0}\");")}; + + protected void generateMethodBody(SourceWriter sw, JMethod method, + TreeLogger treeLogger, boolean hasContext) + throws UnableToCompleteException { + + String selector = method.getAnnotation(Selector.class).value(); + + sw.println("return " + wrap(method, + "impl.select(\"" + selector + "\", root)") + ";"); +// sw.println("JSArray n = JSArray.create();"); +// if(!hasContext) { +// sw.println("Node root = Document.get();"); +// } +// +// // add root node as context. +// // TODO: support any context +// sw.println("n.addNode(root);"); +// String q = selector, lq = null; +// Matcher lmode = modeRe.matcher(q); +// Matcher mm = null; +// String mode = ""; +// if (lmode.lookingAt() && notNull(lmode.group(1))) { +// mode = lmode.group(1).replaceAll(trimReStr, "").trim(); +// q = q.replaceFirst("\\Q" + lmode.group(1) + "\\E", ""); +// } +// +// while (notNull(q) && !q.equals(lq)) { +// debug("Doing q=" + q); +// +// lq = q; +// Matcher tm = tagTokenRe.matcher(q); +// if (tm.lookingAt()) { +// if ("#".equals(tm.group(1))) { +// sw.println("n = quickId(n, \"" + mode + "\", root, \"" + tm.group(2) +// + "\");"); +// } else { +// String tagName = tm.group(2); +// tagName = "".equals(tagName) ? "*" : tagName; +// // sw.println("if (n.size() == 0) { n=JSArray.create(); }"); +// String func = ""; +// if ("".equals(mode)) { +// func = "getDescendentNodes"; +// } else if (">".equals(mode)) { +// func = "getChildNodes"; +// } else if ("+".equals(mode)) { +// func = "getSiblingNodes"; +// } else if ("~".equals(mode)) { +// func = "getGeneralSiblingNodes"; +// } else { +// treeLogger.log(TreeLogger.ERROR, "Error parsing selector, combiner " +// + mode + " not recognized in " + selector, null); +// throw new UnableToCompleteException(); +// } +// sw.println("n = " + func + "(n, \"" + tagName + "\");"); +// } +// debug("replacing in q, the value " + tm.group(0)); +// q = q.replaceFirst("\\Q" + tm.group(0) + "\\E", ""); +// } else { +// String func = ""; +// String tagName = "*"; +// if ("".equals(mode)) { +// func = "getDescendentNodes"; +// } else if (">".equals(mode)) { +// func = "getChildNodes"; +// } else if ("+".equals(mode)) { +// func = "getSiblingNodes"; +// } else if ("~".equals(mode)) { +// func = "getGeneralSiblingNodes"; +// } else { +// treeLogger.log(TreeLogger.ERROR, "Error parsing selector, combiner " +// + mode + " not recognized in " + selector, null); +// throw new UnableToCompleteException(); +// } +// sw.println("n = " + func + "(n, \"" + tagName + "\");"); +// } +// +// while (!(mm = modeRe.matcher(q)).lookingAt()) { +// debug("Looking at " + q); +// boolean matched = false; +// for (RuleMatcher rm : matchers) { +// Matcher rmm = rm.re.matcher(q); +// if (rmm.lookingAt()) { +// String res[] = new String[rmm.groupCount()]; +// for (int i = 1; i <= rmm.groupCount(); i++) { +// res[i - 1] = rmm.group(i); +// debug("added param " + res[i - 1]); +// } +// Object[] r = res; +// // inline enum, perhaps type-tightening will allow inlined eval() +// // call +// if (rm.fnTemplate.indexOf("byPseudo") != -1) { +// sw.println("n = Pseudo."+res[0].toUpperCase().replace("-", "_") + +// ".eval(n, \""+res[1]+"\");"); +// } else { +// sw.println(MessageFormat.format(rm.fnTemplate, r)); +// } +// q = q.replaceFirst("\\Q" + rmm.group(0) + "\\E", ""); +// matched = true; +// break; +// } +// } +// if (!matched) { +// treeLogger +// .log(TreeLogger.ERROR, "Error parsing selector at " + q, null); +// throw new UnableToCompleteException(); +// } +// } +// +// if (notNull(mm.group(1))) { +// mode = mm.group(1).replaceAll(trimReStr, ""); +// debug("replacing q=" + q + " this part:" + mm.group(1)); +// q = q.replaceFirst("\\Q" + mm.group(1) + "\\E", ""); +// } +// } +// sw.println("return "+wrap(method, "nodup(n)")+";"); + } + + protected String getImplSuffix() { + return "JS" + super.getImplSuffix(); + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNative.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNative.java index b09a07dd..459df9af 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNative.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNative.java @@ -1,67 +1,67 @@ -/*
- * 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.rebind;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.typeinfo.JMethod;
-import com.google.gwt.query.client.Selector;
-import com.google.gwt.query.client.impl.SelectorEngineNative;
-import com.google.gwt.user.rebind.SourceWriter;
-
-/**
- * Compile time selector generator which delegates to native browser methods.
- */
-public class SelectorGeneratorNative extends SelectorGeneratorCssToXPath {
-
- @Override
- protected void generateMethodBody(SourceWriter sw, JMethod method,
- TreeLogger treeLogger, boolean hasContext)
- throws UnableToCompleteException {
-
- String selector = method.getAnnotation(Selector.class).value();
- if (selector.matches("#[\\w\\-]+")) {
- sw.println("return "
- + wrap(method, "veryQuickId(\"" + selector.substring(1) + "\", root)") + ";");
- } else if (selector.equals("*") || selector.matches("[\\w\\-]+")) {
- sw.println("return "
- + wrap(method, "elementsByTagName(\"" + selector + "\", root)") + ";");
- } else if (selector.matches("\\.[\\w\\-]+")) {
- sw.println("return "
- + wrap(method, "elementsByClassName(\"" + selector.substring(1) + "\", root)") + ";");
- } else if (selector.contains("!=")) {
- sw.println("return "
- + wrap(method, "querySelectorAll(\""
- + selector.replaceAll("(\\[\\w+)!(=[^\\]]+\\])", ":not($1$2)")
- + "\", root)") + ";");
- } else if (selector.matches(SelectorEngineNative.NATIVE_EXCEPTIONS_REGEXP)) {
- super.generateMethodBody(sw, method, treeLogger, hasContext);
- } else {
- sw.println("return "
- + wrap(method, "querySelectorAll(\"" + selector + "\", root)") + ";");
- }
- }
-
- @Override
- protected String getImplSuffix() {
- return "Native" + super.getImplSuffix();
- }
-
- @Override
- protected boolean hasGetElementsByClassName() {
- return true;
- }
+/* + * 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.rebind; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.query.client.Selector; +import com.google.gwt.query.client.impl.SelectorEngineNative; +import com.google.gwt.user.rebind.SourceWriter; + +/** + * Compile time selector generator which delegates to native browser methods. + */ +public class SelectorGeneratorNative extends SelectorGeneratorCssToXPath { + + @Override + protected void generateMethodBody(SourceWriter sw, JMethod method, + TreeLogger treeLogger, boolean hasContext) + throws UnableToCompleteException { + + String selector = method.getAnnotation(Selector.class).value(); + if (selector.matches("#[\\w\\-]+")) { + sw.println("return " + + wrap(method, "veryQuickId(\"" + selector.substring(1) + "\", root)") + ";"); + } else if (selector.equals("*") || selector.matches("[\\w\\-]+")) { + sw.println("return " + + wrap(method, "elementsByTagName(\"" + selector + "\", root)") + ";"); + } else if (selector.matches("\\.[\\w\\-]+")) { + sw.println("return " + + wrap(method, "elementsByClassName(\"" + selector.substring(1) + "\", root)") + ";"); + } else if (selector.contains("!=")) { + sw.println("return " + + wrap(method, "querySelectorAll(\"" + + selector.replaceAll("(\\[\\w+)!(=[^\\]]+\\])", ":not($1$2)") + + "\", root)") + ";"); + } else if (selector.matches(SelectorEngineNative.NATIVE_EXCEPTIONS_REGEXP)) { + super.generateMethodBody(sw, method, treeLogger, hasContext); + } else { + sw.println("return " + + wrap(method, "querySelectorAll(\"" + selector + "\", root)") + ";"); + } + } + + @Override + protected String getImplSuffix() { + return "Native" + super.getImplSuffix(); + } + + @Override + protected boolean hasGetElementsByClassName() { + return true; + } }
\ No newline at end of file diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNativeIE8.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNativeIE8.java index 4ec3f1c6..2aa28946 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNativeIE8.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNativeIE8.java @@ -1,61 +1,61 @@ -/*
- * 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.rebind;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.typeinfo.JMethod;
-import com.google.gwt.query.client.Selector;
-import com.google.gwt.query.client.impl.SelectorEngineNativeIE8;
-import com.google.gwt.user.rebind.SourceWriter;
-
-/**
- * Compile time selector generator which delegates to native browser methods.
- */
-public class SelectorGeneratorNativeIE8 extends SelectorGeneratorJS {
-
- @Override
- protected void generateMethodBody(SourceWriter sw, JMethod method,
- TreeLogger treeLogger, boolean hasContext)
- throws UnableToCompleteException {
- String selector = method.getAnnotation(Selector.class).value();
- if (selector.matches("#[\\w\\-]+")) {
- sw.println("return "
- + wrap(method, "veryQuickId(\"" + selector.substring(1) + "\", root)") + ";");
- } else if (selector.equals("*") || selector.matches("[\\w\\-]+")) {
- sw.println("return "
- + wrap(method, "elementsByTagName(\"" + selector + "\", root)") + ";");
- } else if (selector.matches("\\.[\\w\\-]+")) {
- sw.println("return "
- + wrap(method, "elementsByClassName(\"" + selector.substring(1) + "\", root)") + ";");
- } else if (selector.matches(SelectorEngineNativeIE8.NATIVE_EXCEPTIONS_REGEXP)) {
- super.generateMethodBody(sw, method, treeLogger, hasContext);
- } else {
- sw.println("return "
- + wrap(method, "querySelectorAll(\"" + selector + "\", root)") + ";");
- }
- }
-
- @Override
- protected String getImplSuffix() {
- return "IE8" + super.getImplSuffix();
- }
-
- @Override
- protected boolean hasGetElementsByClassName() {
- return false;
- }
+/* + * 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.rebind; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.query.client.Selector; +import com.google.gwt.query.client.impl.SelectorEngineNativeIE8; +import com.google.gwt.user.rebind.SourceWriter; + +/** + * Compile time selector generator which delegates to native browser methods. + */ +public class SelectorGeneratorNativeIE8 extends SelectorGeneratorJS { + + @Override + protected void generateMethodBody(SourceWriter sw, JMethod method, + TreeLogger treeLogger, boolean hasContext) + throws UnableToCompleteException { + String selector = method.getAnnotation(Selector.class).value(); + if (selector.matches("#[\\w\\-]+")) { + sw.println("return " + + wrap(method, "veryQuickId(\"" + selector.substring(1) + "\", root)") + ";"); + } else if (selector.equals("*") || selector.matches("[\\w\\-]+")) { + sw.println("return " + + wrap(method, "elementsByTagName(\"" + selector + "\", root)") + ";"); + } else if (selector.matches("\\.[\\w\\-]+")) { + sw.println("return " + + wrap(method, "elementsByClassName(\"" + selector.substring(1) + "\", root)") + ";"); + } else if (selector.matches(SelectorEngineNativeIE8.NATIVE_EXCEPTIONS_REGEXP)) { + super.generateMethodBody(sw, method, treeLogger, hasContext); + } else { + sw.println("return " + + wrap(method, "querySelectorAll(\"" + selector + "\", root)") + ";"); + } + } + + @Override + protected String getImplSuffix() { + return "IE8" + super.getImplSuffix(); + } + + @Override + protected boolean hasGetElementsByClassName() { + return false; + } }
\ No newline at end of file diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNativeIE9.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNativeIE9.java index af3a690d..899886ae 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNativeIE9.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorNativeIE9.java @@ -1,61 +1,61 @@ -/*
- * 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.rebind;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.typeinfo.JMethod;
-import com.google.gwt.query.client.Selector;
-import com.google.gwt.query.client.impl.SelectorEngineNative;
-import com.google.gwt.user.rebind.SourceWriter;
-
-/**
- * Compile time selector generator which delegates to native browser methods.
- */
-public class SelectorGeneratorNativeIE9 extends SelectorGeneratorJS {
-
- @Override
- protected void generateMethodBody(SourceWriter sw, JMethod method,
- TreeLogger treeLogger, boolean hasContext)
- throws UnableToCompleteException {
- String selector = method.getAnnotation(Selector.class).value();
- if (selector.matches("#[\\w\\-]+")) {
- sw.println("return "
- + wrap(method, "veryQuickId(\"" + selector.substring(1) + "\", root)") + ";");
- } else if (selector.equals("*") || selector.matches("[\\w\\-]+")) {
- sw.println("return "
- + wrap(method, "elementsByTagName(\"" + selector + "\", root)") + ";");
- } else if (selector.matches("\\.[\\w\\-]+")) {
- sw.println("return "
- + wrap(method, "elementsByClassName(\"" + selector.substring(1) + "\", root)") + ";");
- } else if (selector.matches(SelectorEngineNative.NATIVE_EXCEPTIONS_REGEXP)) {
- super.generateMethodBody(sw, method, treeLogger, hasContext);
- } else {
- sw.println("return "
- + wrap(method, "querySelectorAll(\"" + selector + "\", root)") + ";");
- }
- }
-
- @Override
- protected String getImplSuffix() {
- return "IE9" + super.getImplSuffix();
- }
-
- @Override
- protected boolean hasGetElementsByClassName() {
- return false;
- }
+/* + * 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.rebind; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.query.client.Selector; +import com.google.gwt.query.client.impl.SelectorEngineNative; +import com.google.gwt.user.rebind.SourceWriter; + +/** + * Compile time selector generator which delegates to native browser methods. + */ +public class SelectorGeneratorNativeIE9 extends SelectorGeneratorJS { + + @Override + protected void generateMethodBody(SourceWriter sw, JMethod method, + TreeLogger treeLogger, boolean hasContext) + throws UnableToCompleteException { + String selector = method.getAnnotation(Selector.class).value(); + if (selector.matches("#[\\w\\-]+")) { + sw.println("return " + + wrap(method, "veryQuickId(\"" + selector.substring(1) + "\", root)") + ";"); + } else if (selector.equals("*") || selector.matches("[\\w\\-]+")) { + sw.println("return " + + wrap(method, "elementsByTagName(\"" + selector + "\", root)") + ";"); + } else if (selector.matches("\\.[\\w\\-]+")) { + sw.println("return " + + wrap(method, "elementsByClassName(\"" + selector.substring(1) + "\", root)") + ";"); + } else if (selector.matches(SelectorEngineNative.NATIVE_EXCEPTIONS_REGEXP)) { + super.generateMethodBody(sw, method, treeLogger, hasContext); + } else { + sw.println("return " + + wrap(method, "querySelectorAll(\"" + selector + "\", root)") + ";"); + } + } + + @Override + protected String getImplSuffix() { + return "IE9" + super.getImplSuffix(); + } + + @Override + protected boolean hasGetElementsByClassName() { + return false; + } }
\ No newline at end of file diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorXPath.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorXPath.java index 11ff199a..fdc4838c 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorXPath.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/SelectorGeneratorXPath.java @@ -1,331 +1,331 @@ -/*
- * 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.rebind;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.typeinfo.JMethod;
-import com.google.gwt.query.client.Selector;
-import com.google.gwt.user.rebind.SourceWriter;
-
-import java.util.ArrayList;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Compile time selector generator which translates selector into XPath at
- * compile time.
- */
-public class SelectorGeneratorXPath extends SelectorGeneratorBase {
-
- static class Sequence {
-
- public int start;
-
- public int max;
-
- public int add;
-
- public int modVal;
- }
-
- static class SplitRule {
-
- public String tag;
-
- public String id;
-
- public String allClasses;
-
- public String allAttr;
-
- public String allPseudos;
-
- public String tagRelation;
- }
-
- private static Pattern cssSelectorRegExp = Pattern.compile(
- "^(\\w+)?(#[a-zA-Z_0-9\u00C0-\uFFFF\\-\\_]+|(\\*))?((\\.[a-zA-Z_0-9\u00C0-\uFFFF\\-_]+)*)?((\\[\\w+(\\^|\\$|\\*|\\||~)?(=[a-zA-Z_0-9\u00C0-\uFFFF\\s\\-\\_\\.]+)?\\]+)*)?(((:\\w+[a-zA-Z_0-9\\-]*)(\\((odd|even|\\-?\\d*n?((\\+|\\-)\\d+)?|[a-zA-Z_0-9\u00C0-\uFFFF\\-_]+|((\\w*\\.[a-zA-Z_0-9\u00C0-\uFFFF\\-_]+)*)?|(\\[#?\\w+(\\^|\\$|\\*|\\||~)?=?[a-zA-Z_0-9\u00C0-\uFFFF\\s\\-\\_\\.]+\\]+)|(:\\w+[a-zA-Z_0-9\\-]*))\\))?)*)?(>|\\+|~)?");
-
- private static Pattern selectorSplitRegExp = Pattern
- .compile("(?:\\[[^\\[]*\\]|\\(.*\\)|[^\\s\\+>~\\[\\(])+|[\\+>~]");
-
- private String prefix = "";
-
- protected void generateMethodBody(SourceWriter sw, JMethod method,
- TreeLogger treeLogger, boolean hasContext)
- throws UnableToCompleteException {
-
- String selector = method.getAnnotation(Selector.class).value();
- String[] cssRules = selector.replaceAll("\\s*(,)\\s*", "$1").split(",");
- String currentRule;
- boolean identical = false;
- String xPathExpression = ".";
-
- for (int i = 0; i < cssRules.length; i++) {
- currentRule = cssRules[i];
-
- if (i > 0) {
- identical = false;
- for (int x = 0, xl = i; x < xl; x++) {
- if (cssRules[i].equals(cssRules[x])) {
- identical = true;
- break;
- }
- }
- if (identical) {
- continue;
- }
- }
-
- ArrayList<String> cssSelectors = new ArrayList<String>();
- Matcher selm = selectorSplitRegExp.matcher(currentRule);
- while (selm.find()) {
- cssSelectors.add(selm.group(0));
- }
-
- Matcher cssSelector;
- for (int j = 0, jl = cssSelectors.size(); j < jl; j++) {
- cssSelector = cssSelectorRegExp.matcher(cssSelectors.get(j));
- if (cssSelector.matches()) {
-
- SplitRule splitRule = new SplitRule();
- splitRule.tag = prefix + ((!notNull(cssSelector.group(1)) || "*"
- .equals(cssSelector.group(3))) ? "*" : cssSelector.group(1));
- splitRule.id = (!"*".equals(cssSelector.group(3))) ? cssSelector
- .group(2) : null;
- splitRule.allClasses = cssSelector.group(4);
- splitRule.allAttr = cssSelector.group(6);
- splitRule.allPseudos = cssSelector.group(10);
- splitRule.tagRelation = cssSelector.group(22);
- if (notNull(splitRule.tagRelation)) {
- if (">".equals(splitRule.tagRelation)) {
- xPathExpression += "/child::";
- } else if ("+".equals(splitRule.tagRelation)) {
- xPathExpression += "/following-sibling::*[1]/self::";
- } else if ("~".equals(splitRule.tagRelation)) {
- xPathExpression += "/following-sibling::";
- }
- } else {
- xPathExpression +=
- (j > 0 && cssSelectors.get(j - 1).matches("(>|\\+|~)"))
- ? splitRule.tag : ("/descendant::" + splitRule.tag);
- }
-
- if (notNull(splitRule.id)) {
- xPathExpression += "[@id = '" + splitRule.id.replaceAll("^#", "")
- + "']";
- }
- if (notNull(splitRule.allClasses)) {
- xPathExpression += splitRule.allClasses
- .replaceAll("\\.([a-zA-Z_0-9\u00C0 -\uFFFF\\-_]+)",
- "[contains(concat(' ', @class, ' '), ' $1 ')]");
- }
- if (notNull(splitRule.allAttr)) {
- xPathExpression += attrToXPath(splitRule.allAttr,
- "(\\w+)(\\^|\\$|\\*|\\||~)?=?([a-zA-Z_0-9\u00C0-\uFFFF\\s\\-_\\.]+)?");
- }
- if (notNull(splitRule.allPseudos)) {
- Pattern pseudoSplitRegExp = Pattern
- .compile(":(\\w[a-zA-Z_0-9\\-]*)(\\(([^\\)]+)\\))?");
- Matcher m = Pattern
- .compile("(:\\w+[a-zA-Z_0-9\\-]*)(\\([^\\)]+\\))?")
- .matcher(splitRule.allPseudos);
- while (m.find()) {
- String str = m.group(0);
- Matcher pseudo = pseudoSplitRegExp
- .matcher(str == null ? "" : str);
- if (pseudo.matches()) {
- String pseudoClass = notNull(pseudo.group(1)) ? pseudo.group(1)
- .toLowerCase() : null;
- String pseudoValue = notNull(pseudo.group(3)) ? pseudo.group(3)
- : null;
- String xpath = pseudoToXPath(splitRule.tag, pseudoClass,
- pseudoValue);
- if (notNull(xpath)) {
- xPathExpression += "[" + xpath + "]";
- }
- }
- }
- }
- }
- }
- }
-
- sw.println("return " + wrap(method,
- "SelectorEngine.xpathEvaluate(\"" + xPathExpression + "\", root)")
- + ";");
- }
-
- protected String getImplSuffix() {
- return "XPath" + super.getImplSuffix();
- }
-
- private String attrToXPath(String notSelector, String pattern) {
- Pattern p = Pattern.compile(pattern);
- Matcher m = p.matcher(notSelector);
- m.reset();
- boolean result = m.find();
- if (result) {
- StringBuffer sb = new StringBuffer();
- do {
- String replacement;
- String p1 = m.group(1);
- String p2 = m.group(2);
- String p3 = m.group(3);
- if ("^".equals(p2)) {
- replacement = "starts-with(@" + p1 + ", '" + p3 + "')";
- } else if ("$".equals(p2)) {
- replacement = "substring(@" + p1 + ", (string-length(@" + p1 + ") - "
- + (p3.length() - 1) + "), " + p3.length() + ") = '" + p3 + "'";
- } else if ("*".equals(p2)) {
- replacement = "contains(concat(' ', @" + p1 + ", ' '), '" + p3 + "')";
- } else if ("|".equals(p2)) {
- replacement = "(@" + p1 + "='" + p3 + "' or starts-with(@" + p1
- + ", '" + p3 + "-'))";
- } else if ("~".equals(p2)) {
- replacement = "contains(concat(' ', @" + p1 + ", ' '), ' " + p3
- + " ')";
- } else {
- replacement = "@" + p1 + (notNull(p3) ? "='" + p3 + "'" : "");
- }
- debug("p1=" + p1 + " p2=" + p2 + " p3=" + p3 + " replacement is "
- + replacement);
- m.appendReplacement(sb, replacement.replace("$", "\\$"));
- result = m.find();
- } while (result);
- m.appendTail(sb);
- return sb.toString();
- }
- return notSelector;
- }
-
- private int getInt(String s, int i) {
- try {
- if (s.startsWith("+")) {
- s = s.substring(1);
- }
- return Integer.parseInt(s);
- } catch (Exception e) {
- debug("error parsing Integer " + s);
- return i;
- }
- }
-
- private Sequence getSequence(String expression) {
- int start = 0, add = 2, max = -1, modVal = -1;
- Pattern expressionRegExp = Pattern.compile(
- "^((odd|even)|([1-9]\\d*)|((([1-9]\\d*)?)n([\\+\\-]\\d+)?)|(\\-(([1-9]\\d*)?)n\\+(\\d+)))$");
- Matcher pseudoValue = expressionRegExp.matcher(expression);
- if (!pseudoValue.matches()) {
- return null;
- } else {
- if (notNull(pseudoValue.group(2))) { // odd or even
- start = ("odd".equals(pseudoValue.group(2))) ? 1 : 2;
- modVal = (start == 1) ? 1 : 0;
- } else if (notNull(pseudoValue.group(3))) { // single digit
- start = Integer.parseInt(pseudoValue.group(3), 10);
- add = 0;
- max = start;
- } else if (notNull(pseudoValue.group(4))) { // an+b
- add = notNull(pseudoValue.group(6)) ? getInt(pseudoValue.group(6), 1)
- : 1;
- start = notNull(pseudoValue.group(7)) ? getInt(pseudoValue.group(7), 0)
- : 0;
- while (start < 1) {
- start += add;
- }
- modVal = (start > add) ? (start - add) % add
- : ((start == add) ? 0 : start);
- } else if (notNull(pseudoValue.group(8))) { // -an+b
- add = notNull(pseudoValue.group(10)) ? Integer
- .parseInt(pseudoValue.group(10), 10) : 1;
- start = max = Integer.parseInt(pseudoValue.group(10), 10);
- while (start > add) {
- start -= add;
- }
- modVal = (max > add) ? (max - add) % add : ((max == add) ? 0 : max);
- }
- }
- Sequence s = new Sequence();
- s.start = start;
- s.add = add;
- s.max = max;
- s.modVal = modVal;
- return s;
- }
-
- private String pseudoToXPath(String tag, String pseudoClass,
- String pseudoValue) {
- tag = pseudoClass.matches(".*\\-child$") ? "*" : tag;
- String xpath = "";
- String pseudo[] = pseudoClass.split("-");
- if ("first".equals(pseudo[0])) {
- xpath = "not(preceding-sibling::" + tag + ")";
- } else if ("last".equals(pseudo[0])) {
- xpath = "not(following-sibling::" + tag + ")";
- } else if ("only".equals(pseudo[0])) {
- xpath = "not(preceding-sibling::" + tag + " or following-sibling::" + tag
- + ")";
- } else if ("nth".equals(pseudo[0])) {
- if (!pseudoValue.matches("^n$")) {
- String position =
- (("last".equals(pseudo[1])) ? "(count(following-sibling::"
- : "(count(preceding-sibling::") + tag + ") + 1)";
- Sequence sequence = getSequence(pseudoValue);
- if (sequence != null) {
- if (sequence.start == sequence.max) {
- xpath = position + " = " + sequence.start;
- } else {
- xpath = position + " mod " + sequence.add + " = " + sequence.modVal
- + ((sequence.start > 1) ? " and " + position + " >= "
- + sequence.start : "") + ((sequence.max > 0) ? " and "
- + position + " <= " + sequence.max : "");
- }
- }
- }
- } else if ("empty".equals(pseudo[0])) {
- xpath = "count(child::*) = 0 and string-length(text()) = 0";
- } else if ("contains".equals(pseudo[0])) {
- xpath = "contains(., '" + pseudoValue + "')";
- } else if ("enabled".equals(pseudo[0])) {
- xpath = "not(@disabled)";
- } else if ("disabled".equals(pseudo[0])) {
- xpath = "@disabled";
- } else if ("checked".equals(pseudo[0])) {
- xpath = "@checked='checked'"; // Doesn't work in Opera 9.24
- } else if ("not".equals(pseudo[0])) {
- if (pseudoValue.matches("^(:a-zA-Z_0-9+[a-zA-Z_0-9\\-]*)$")) {
- xpath = "not(" + pseudoToXPath(tag, pseudoValue.substring(1), "") + ")";
- } else {
- pseudoValue = pseudoValue
- .replaceAll("^\\[#([a-zA-Z_0-9\u00C0-\uFFFF\\-\\_]+)\\]$",
- "[id=$1]");
- String notSelector = pseudoValue
- .replaceFirst("^(a-zA-Z_0-9+)", "self::$1");
- notSelector = notSelector
- .replaceAll("^\\.([a-zA-Z_0-9\u00C0-\uFFFF\\-_]+)",
- "contains(concat(' ', @class, ' '), ' $1 ')");
- notSelector = attrToXPath(notSelector,
- "\\[(a-zA-Z_0-9+)(\\^|\\$|\\*|\\||~)?=?([a-zA-Z_0-9\u00C0-\uFFFF\\s\\-_\\.]+)?\\]");
- xpath = "not(" + notSelector + ")";
- }
- } else {
- xpath = "@" + pseudoClass + "='" + pseudoValue + "'";
- }
- return xpath;
- }
-}
+/* + * 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.rebind; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.query.client.Selector; +import com.google.gwt.user.rebind.SourceWriter; + +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Compile time selector generator which translates selector into XPath at + * compile time. + */ +public class SelectorGeneratorXPath extends SelectorGeneratorBase { + + static class Sequence { + + public int start; + + public int max; + + public int add; + + public int modVal; + } + + static class SplitRule { + + public String tag; + + public String id; + + public String allClasses; + + public String allAttr; + + public String allPseudos; + + public String tagRelation; + } + + private static Pattern cssSelectorRegExp = Pattern.compile( + "^(\\w+)?(#[a-zA-Z_0-9\u00C0-\uFFFF\\-\\_]+|(\\*))?((\\.[a-zA-Z_0-9\u00C0-\uFFFF\\-_]+)*)?((\\[\\w+(\\^|\\$|\\*|\\||~)?(=[a-zA-Z_0-9\u00C0-\uFFFF\\s\\-\\_\\.]+)?\\]+)*)?(((:\\w+[a-zA-Z_0-9\\-]*)(\\((odd|even|\\-?\\d*n?((\\+|\\-)\\d+)?|[a-zA-Z_0-9\u00C0-\uFFFF\\-_]+|((\\w*\\.[a-zA-Z_0-9\u00C0-\uFFFF\\-_]+)*)?|(\\[#?\\w+(\\^|\\$|\\*|\\||~)?=?[a-zA-Z_0-9\u00C0-\uFFFF\\s\\-\\_\\.]+\\]+)|(:\\w+[a-zA-Z_0-9\\-]*))\\))?)*)?(>|\\+|~)?"); + + private static Pattern selectorSplitRegExp = Pattern + .compile("(?:\\[[^\\[]*\\]|\\(.*\\)|[^\\s\\+>~\\[\\(])+|[\\+>~]"); + + private String prefix = ""; + + protected void generateMethodBody(SourceWriter sw, JMethod method, + TreeLogger treeLogger, boolean hasContext) + throws UnableToCompleteException { + + String selector = method.getAnnotation(Selector.class).value(); + String[] cssRules = selector.replaceAll("\\s*(,)\\s*", "$1").split(","); + String currentRule; + boolean identical = false; + String xPathExpression = "."; + + for (int i = 0; i < cssRules.length; i++) { + currentRule = cssRules[i]; + + if (i > 0) { + identical = false; + for (int x = 0, xl = i; x < xl; x++) { + if (cssRules[i].equals(cssRules[x])) { + identical = true; + break; + } + } + if (identical) { + continue; + } + } + + ArrayList<String> cssSelectors = new ArrayList<String>(); + Matcher selm = selectorSplitRegExp.matcher(currentRule); + while (selm.find()) { + cssSelectors.add(selm.group(0)); + } + + Matcher cssSelector; + for (int j = 0, jl = cssSelectors.size(); j < jl; j++) { + cssSelector = cssSelectorRegExp.matcher(cssSelectors.get(j)); + if (cssSelector.matches()) { + + SplitRule splitRule = new SplitRule(); + splitRule.tag = prefix + ((!notNull(cssSelector.group(1)) || "*" + .equals(cssSelector.group(3))) ? "*" : cssSelector.group(1)); + splitRule.id = (!"*".equals(cssSelector.group(3))) ? cssSelector + .group(2) : null; + splitRule.allClasses = cssSelector.group(4); + splitRule.allAttr = cssSelector.group(6); + splitRule.allPseudos = cssSelector.group(10); + splitRule.tagRelation = cssSelector.group(22); + if (notNull(splitRule.tagRelation)) { + if (">".equals(splitRule.tagRelation)) { + xPathExpression += "/child::"; + } else if ("+".equals(splitRule.tagRelation)) { + xPathExpression += "/following-sibling::*[1]/self::"; + } else if ("~".equals(splitRule.tagRelation)) { + xPathExpression += "/following-sibling::"; + } + } else { + xPathExpression += + (j > 0 && cssSelectors.get(j - 1).matches("(>|\\+|~)")) + ? splitRule.tag : ("/descendant::" + splitRule.tag); + } + + if (notNull(splitRule.id)) { + xPathExpression += "[@id = '" + splitRule.id.replaceAll("^#", "") + + "']"; + } + if (notNull(splitRule.allClasses)) { + xPathExpression += splitRule.allClasses + .replaceAll("\\.([a-zA-Z_0-9\u00C0 -\uFFFF\\-_]+)", + "[contains(concat(' ', @class, ' '), ' $1 ')]"); + } + if (notNull(splitRule.allAttr)) { + xPathExpression += attrToXPath(splitRule.allAttr, + "(\\w+)(\\^|\\$|\\*|\\||~)?=?([a-zA-Z_0-9\u00C0-\uFFFF\\s\\-_\\.]+)?"); + } + if (notNull(splitRule.allPseudos)) { + Pattern pseudoSplitRegExp = Pattern + .compile(":(\\w[a-zA-Z_0-9\\-]*)(\\(([^\\)]+)\\))?"); + Matcher m = Pattern + .compile("(:\\w+[a-zA-Z_0-9\\-]*)(\\([^\\)]+\\))?") + .matcher(splitRule.allPseudos); + while (m.find()) { + String str = m.group(0); + Matcher pseudo = pseudoSplitRegExp + .matcher(str == null ? "" : str); + if (pseudo.matches()) { + String pseudoClass = notNull(pseudo.group(1)) ? pseudo.group(1) + .toLowerCase() : null; + String pseudoValue = notNull(pseudo.group(3)) ? pseudo.group(3) + : null; + String xpath = pseudoToXPath(splitRule.tag, pseudoClass, + pseudoValue); + if (notNull(xpath)) { + xPathExpression += "[" + xpath + "]"; + } + } + } + } + } + } + } + + sw.println("return " + wrap(method, + "SelectorEngine.xpathEvaluate(\"" + xPathExpression + "\", root)") + + ";"); + } + + protected String getImplSuffix() { + return "XPath" + super.getImplSuffix(); + } + + private String attrToXPath(String notSelector, String pattern) { + Pattern p = Pattern.compile(pattern); + Matcher m = p.matcher(notSelector); + m.reset(); + boolean result = m.find(); + if (result) { + StringBuffer sb = new StringBuffer(); + do { + String replacement; + String p1 = m.group(1); + String p2 = m.group(2); + String p3 = m.group(3); + if ("^".equals(p2)) { + replacement = "starts-with(@" + p1 + ", '" + p3 + "')"; + } else if ("$".equals(p2)) { + replacement = "substring(@" + p1 + ", (string-length(@" + p1 + ") - " + + (p3.length() - 1) + "), " + p3.length() + ") = '" + p3 + "'"; + } else if ("*".equals(p2)) { + replacement = "contains(concat(' ', @" + p1 + ", ' '), '" + p3 + "')"; + } else if ("|".equals(p2)) { + replacement = "(@" + p1 + "='" + p3 + "' or starts-with(@" + p1 + + ", '" + p3 + "-'))"; + } else if ("~".equals(p2)) { + replacement = "contains(concat(' ', @" + p1 + ", ' '), ' " + p3 + + " ')"; + } else { + replacement = "@" + p1 + (notNull(p3) ? "='" + p3 + "'" : ""); + } + debug("p1=" + p1 + " p2=" + p2 + " p3=" + p3 + " replacement is " + + replacement); + m.appendReplacement(sb, replacement.replace("$", "\\$")); + result = m.find(); + } while (result); + m.appendTail(sb); + return sb.toString(); + } + return notSelector; + } + + private int getInt(String s, int i) { + try { + if (s.startsWith("+")) { + s = s.substring(1); + } + return Integer.parseInt(s); + } catch (Exception e) { + debug("error parsing Integer " + s); + return i; + } + } + + private Sequence getSequence(String expression) { + int start = 0, add = 2, max = -1, modVal = -1; + Pattern expressionRegExp = Pattern.compile( + "^((odd|even)|([1-9]\\d*)|((([1-9]\\d*)?)n([\\+\\-]\\d+)?)|(\\-(([1-9]\\d*)?)n\\+(\\d+)))$"); + Matcher pseudoValue = expressionRegExp.matcher(expression); + if (!pseudoValue.matches()) { + return null; + } else { + if (notNull(pseudoValue.group(2))) { // odd or even + start = ("odd".equals(pseudoValue.group(2))) ? 1 : 2; + modVal = (start == 1) ? 1 : 0; + } else if (notNull(pseudoValue.group(3))) { // single digit + start = Integer.parseInt(pseudoValue.group(3), 10); + add = 0; + max = start; + } else if (notNull(pseudoValue.group(4))) { // an+b + add = notNull(pseudoValue.group(6)) ? getInt(pseudoValue.group(6), 1) + : 1; + start = notNull(pseudoValue.group(7)) ? getInt(pseudoValue.group(7), 0) + : 0; + while (start < 1) { + start += add; + } + modVal = (start > add) ? (start - add) % add + : ((start == add) ? 0 : start); + } else if (notNull(pseudoValue.group(8))) { // -an+b + add = notNull(pseudoValue.group(10)) ? Integer + .parseInt(pseudoValue.group(10), 10) : 1; + start = max = Integer.parseInt(pseudoValue.group(10), 10); + while (start > add) { + start -= add; + } + modVal = (max > add) ? (max - add) % add : ((max == add) ? 0 : max); + } + } + Sequence s = new Sequence(); + s.start = start; + s.add = add; + s.max = max; + s.modVal = modVal; + return s; + } + + private String pseudoToXPath(String tag, String pseudoClass, + String pseudoValue) { + tag = pseudoClass.matches(".*\\-child$") ? "*" : tag; + String xpath = ""; + String pseudo[] = pseudoClass.split("-"); + if ("first".equals(pseudo[0])) { + xpath = "not(preceding-sibling::" + tag + ")"; + } else if ("last".equals(pseudo[0])) { + xpath = "not(following-sibling::" + tag + ")"; + } else if ("only".equals(pseudo[0])) { + xpath = "not(preceding-sibling::" + tag + " or following-sibling::" + tag + + ")"; + } else if ("nth".equals(pseudo[0])) { + if (!pseudoValue.matches("^n$")) { + String position = + (("last".equals(pseudo[1])) ? "(count(following-sibling::" + : "(count(preceding-sibling::") + tag + ") + 1)"; + Sequence sequence = getSequence(pseudoValue); + if (sequence != null) { + if (sequence.start == sequence.max) { + xpath = position + " = " + sequence.start; + } else { + xpath = position + " mod " + sequence.add + " = " + sequence.modVal + + ((sequence.start > 1) ? " and " + position + " >= " + + sequence.start : "") + ((sequence.max > 0) ? " and " + + position + " <= " + sequence.max : ""); + } + } + } + } else if ("empty".equals(pseudo[0])) { + xpath = "count(child::*) = 0 and string-length(text()) = 0"; + } else if ("contains".equals(pseudo[0])) { + xpath = "contains(., '" + pseudoValue + "')"; + } else if ("enabled".equals(pseudo[0])) { + xpath = "not(@disabled)"; + } else if ("disabled".equals(pseudo[0])) { + xpath = "@disabled"; + } else if ("checked".equals(pseudo[0])) { + xpath = "@checked='checked'"; // Doesn't work in Opera 9.24 + } else if ("not".equals(pseudo[0])) { + if (pseudoValue.matches("^(:a-zA-Z_0-9+[a-zA-Z_0-9\\-]*)$")) { + xpath = "not(" + pseudoToXPath(tag, pseudoValue.substring(1), "") + ")"; + } else { + pseudoValue = pseudoValue + .replaceAll("^\\[#([a-zA-Z_0-9\u00C0-\uFFFF\\-\\_]+)\\]$", + "[id=$1]"); + String notSelector = pseudoValue + .replaceFirst("^(a-zA-Z_0-9+)", "self::$1"); + notSelector = notSelector + .replaceAll("^\\.([a-zA-Z_0-9\u00C0-\uFFFF\\-_]+)", + "contains(concat(' ', @class, ' '), ' $1 ')"); + notSelector = attrToXPath(notSelector, + "\\[(a-zA-Z_0-9+)(\\^|\\$|\\*|\\||~)?=?([a-zA-Z_0-9\u00C0-\uFFFF\\s\\-_\\.]+)?\\]"); + xpath = "not(" + notSelector + ")"; + } + } else { + xpath = "@" + pseudoClass + "='" + pseudoValue + "'"; + } + return xpath; + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/XmlBuilderGenerator.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/XmlBuilderGenerator.java index a14d7901..1c70815b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/XmlBuilderGenerator.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/XmlBuilderGenerator.java @@ -1,167 +1,167 @@ -/*
- * 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.rebind;
-
-import java.io.PrintWriter;
-
-import com.google.gwt.core.ext.Generator;
-import com.google.gwt.core.ext.GeneratorContext;
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.typeinfo.JArrayType;
-import com.google.gwt.core.ext.typeinfo.JClassType;
-import com.google.gwt.core.ext.typeinfo.JMethod;
-import com.google.gwt.core.ext.typeinfo.JParameter;
-import com.google.gwt.core.ext.typeinfo.JType;
-import com.google.gwt.core.ext.typeinfo.TypeOracle;
-import com.google.gwt.query.client.Properties;
-import com.google.gwt.query.client.builders.Name;
-import com.google.gwt.query.client.builders.XmlBuilder;
-import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
-import com.google.gwt.user.rebind.SourceWriter;
-
-/**
- */
-public class XmlBuilderGenerator extends Generator {
- TypeOracle oracle;
- static JClassType xmlBuilderType;
- static JClassType stringType;
-
- public String generate(TreeLogger treeLogger,
- GeneratorContext generatorContext, String requestedClass)
- throws UnableToCompleteException {
- oracle = generatorContext.getTypeOracle();
- JClassType clazz = oracle.findType(requestedClass);
- xmlBuilderType = oracle.findType(XmlBuilder.class.getName());
- stringType = oracle.findType(String.class.getName());
-
- String t[] = generateClassName(clazz);
-
- SourceWriter sw = getSourceWriter(treeLogger, generatorContext, t[0],
- t[1], requestedClass);
- if (sw != null) {
- for (JMethod method : clazz.getInheritableMethods()) {
- //skip method from JsonBuilder
- if(xmlBuilderType.findMethod(method.getName(), method.getParameterTypes()) != null){
- continue;
- }
- generateMethod(sw, method, treeLogger);
- }
- sw.commit(treeLogger);
- }
- return t[2];
- }
-
- public String[] generateClassName(JType t) {
- String[] ret = new String[3];
- JClassType c = t.isClassOrInterface();
- ret[0] = c.getPackage().getName();
- ret[1] = c.getName().replace('.', '_') + "_XmlBuilder";
- ret[2] = ret[0] + "." + ret[1];
- return ret;
- }
-
- public boolean isTypeAssignableTo(JType t, JClassType o) {
- JClassType c = t.isClassOrInterface();
- return (c != null && c.isAssignableTo(o));
- }
-
- public void generateMethod(SourceWriter sw, JMethod method, TreeLogger logger)
- throws UnableToCompleteException {
- Name nameAnnotation = method.getAnnotation(Name.class);
- String name = nameAnnotation != null ? nameAnnotation.value()
- : method.getName().replaceFirst("^(get|set)", "").toLowerCase();
-
- String retType = method.getReturnType().getParameterizedQualifiedSourceName();
-
- sw.print("public final " + retType + " " + method.getName());
- JParameter[] params = method.getParameters();
- if (params.length == 0) {
- JArrayType arr = method.getReturnType().isArray();
- sw.println("() {");
- sw.indent();
- if (retType.matches("(java.lang.Boolean|boolean)")) {
- sw.println("return getBooleanBase(\"" + name + "\");");
- } else if (method.getReturnType().isPrimitive() != null) {
- sw.println("return (" + retType + ")getFloatBase(\"" + name + "\");");
- } else if (isTypeAssignableTo(method.getReturnType(), stringType)) {
- sw.println("return getStrBase(\"" + name + "\");");
- } else if (isTypeAssignableTo(method.getReturnType(), xmlBuilderType)) {
- String q = method.getReturnType().getQualifiedSourceName();
- sw.println("Element e = getElementBase(\"" + name + "\");");
- sw.println("return e == null ? null : (" + q + ")((" + q + ")GWT.create(" + q + ".class)).load(e);");
- } else if (retType.equals(Properties.class.getName())){
- sw.println("return getPropertiesBase(\"" + name + "\");");
- } else if (arr != null) {
- String q = arr.getComponentType().getQualifiedSourceName();
- sw.println("ArrayList<" + q + "> l = new ArrayList<" + q+ ">();");
- sw.println("for (Element e: getElementsBase(\"" + name + "\")) {");
- sw.println(" " + q + " c = GWT.create(" + q + ".class);");
- sw.println(" c.load(e);");
- sw.println(" l.add(c);");
- sw.println("}");
- sw.println("return l.toArray(new " + q + "[0]);");
- } else {
- sw.println("return null; // Unsupported return type: " + retType);
- }
- sw.outdent();
- sw.println("}");
- } else if (params.length == 1) {
- JType type = params[0].getType();
- JArrayType arr = type.isArray();
- String qname = type.getParameterizedQualifiedSourceName();
- sw.print("(" + qname + " a)");
- sw.println("{");
- sw.indent();
- if (arr != null) {
- sw.println("setArrayBase(\"" + name + "\", a);");
- } else {
- sw.println("setBase(\"" + name + "\", a);");
- }
- if (!"void".equals(retType)){
- if (isTypeAssignableTo(method.getReturnType(), method.getEnclosingType())) {
- sw.println("return this;");
- } else {
- sw.println("return null;");
- }
- }
- sw.outdent();
- sw.println("}");
- }
- }
-
- protected SourceWriter getSourceWriter(TreeLogger logger,
- GeneratorContext context, String packageName, String className,
- String... interfaceNames) {
- PrintWriter printWriter = context.tryCreate(logger, packageName, className);
- if (printWriter == null) {
- return null;
- }
- ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(
- packageName, className);
- composerFactory.setSuperclass("com.google.gwt.query.client.builders.XmlBuilderBase<"
- + packageName + "." + className + ">");
- composerFactory.addImport("com.google.gwt.query.client.js.*");
- composerFactory.addImport("com.google.gwt.query.client.*");
- composerFactory.addImport("com.google.gwt.core.client.*");
- composerFactory.addImport("com.google.gwt.dom.client.*");
- composerFactory.addImport("java.util.*");
- for (String interfaceName : interfaceNames) {
- composerFactory.addImplementedInterface(interfaceName);
- }
- return composerFactory.createSourceWriter(context, printWriter);
- }
-}
+/* + * 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.rebind; + +import java.io.PrintWriter; + +import com.google.gwt.core.ext.Generator; +import com.google.gwt.core.ext.GeneratorContext; +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JArrayType; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.core.ext.typeinfo.JParameter; +import com.google.gwt.core.ext.typeinfo.JType; +import com.google.gwt.core.ext.typeinfo.TypeOracle; +import com.google.gwt.query.client.Properties; +import com.google.gwt.query.client.builders.Name; +import com.google.gwt.query.client.builders.XmlBuilder; +import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; +import com.google.gwt.user.rebind.SourceWriter; + +/** + */ +public class XmlBuilderGenerator extends Generator { + TypeOracle oracle; + static JClassType xmlBuilderType; + static JClassType stringType; + + public String generate(TreeLogger treeLogger, + GeneratorContext generatorContext, String requestedClass) + throws UnableToCompleteException { + oracle = generatorContext.getTypeOracle(); + JClassType clazz = oracle.findType(requestedClass); + xmlBuilderType = oracle.findType(XmlBuilder.class.getName()); + stringType = oracle.findType(String.class.getName()); + + String t[] = generateClassName(clazz); + + SourceWriter sw = getSourceWriter(treeLogger, generatorContext, t[0], + t[1], requestedClass); + if (sw != null) { + for (JMethod method : clazz.getInheritableMethods()) { + //skip method from JsonBuilder + if(xmlBuilderType.findMethod(method.getName(), method.getParameterTypes()) != null){ + continue; + } + generateMethod(sw, method, treeLogger); + } + sw.commit(treeLogger); + } + return t[2]; + } + + public String[] generateClassName(JType t) { + String[] ret = new String[3]; + JClassType c = t.isClassOrInterface(); + ret[0] = c.getPackage().getName(); + ret[1] = c.getName().replace('.', '_') + "_XmlBuilder"; + ret[2] = ret[0] + "." + ret[1]; + return ret; + } + + public boolean isTypeAssignableTo(JType t, JClassType o) { + JClassType c = t.isClassOrInterface(); + return (c != null && c.isAssignableTo(o)); + } + + public void generateMethod(SourceWriter sw, JMethod method, TreeLogger logger) + throws UnableToCompleteException { + Name nameAnnotation = method.getAnnotation(Name.class); + String name = nameAnnotation != null ? nameAnnotation.value() + : method.getName().replaceFirst("^(get|set)", "").toLowerCase(); + + String retType = method.getReturnType().getParameterizedQualifiedSourceName(); + + sw.print("public final " + retType + " " + method.getName()); + JParameter[] params = method.getParameters(); + if (params.length == 0) { + JArrayType arr = method.getReturnType().isArray(); + sw.println("() {"); + sw.indent(); + if (retType.matches("(java.lang.Boolean|boolean)")) { + sw.println("return getBooleanBase(\"" + name + "\");"); + } else if (method.getReturnType().isPrimitive() != null) { + sw.println("return (" + retType + ")getFloatBase(\"" + name + "\");"); + } else if (isTypeAssignableTo(method.getReturnType(), stringType)) { + sw.println("return getStrBase(\"" + name + "\");"); + } else if (isTypeAssignableTo(method.getReturnType(), xmlBuilderType)) { + String q = method.getReturnType().getQualifiedSourceName(); + sw.println("Element e = getElementBase(\"" + name + "\");"); + sw.println("return e == null ? null : (" + q + ")((" + q + ")GWT.create(" + q + ".class)).load(e);"); + } else if (retType.equals(Properties.class.getName())){ + sw.println("return getPropertiesBase(\"" + name + "\");"); + } else if (arr != null) { + String q = arr.getComponentType().getQualifiedSourceName(); + sw.println("ArrayList<" + q + "> l = new ArrayList<" + q+ ">();"); + sw.println("for (Element e: getElementsBase(\"" + name + "\")) {"); + sw.println(" " + q + " c = GWT.create(" + q + ".class);"); + sw.println(" c.load(e);"); + sw.println(" l.add(c);"); + sw.println("}"); + sw.println("return l.toArray(new " + q + "[0]);"); + } else { + sw.println("return null; // Unsupported return type: " + retType); + } + sw.outdent(); + sw.println("}"); + } else if (params.length == 1) { + JType type = params[0].getType(); + JArrayType arr = type.isArray(); + String qname = type.getParameterizedQualifiedSourceName(); + sw.print("(" + qname + " a)"); + sw.println("{"); + sw.indent(); + if (arr != null) { + sw.println("setArrayBase(\"" + name + "\", a);"); + } else { + sw.println("setBase(\"" + name + "\", a);"); + } + if (!"void".equals(retType)){ + if (isTypeAssignableTo(method.getReturnType(), method.getEnclosingType())) { + sw.println("return this;"); + } else { + sw.println("return null;"); + } + } + sw.outdent(); + sw.println("}"); + } + } + + protected SourceWriter getSourceWriter(TreeLogger logger, + GeneratorContext context, String packageName, String className, + String... interfaceNames) { + PrintWriter printWriter = context.tryCreate(logger, packageName, className); + if (printWriter == null) { + return null; + } + ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory( + packageName, className); + composerFactory.setSuperclass("com.google.gwt.query.client.builders.XmlBuilderBase<" + + packageName + "." + className + ">"); + composerFactory.addImport("com.google.gwt.query.client.js.*"); + composerFactory.addImport("com.google.gwt.query.client.*"); + composerFactory.addImport("com.google.gwt.core.client.*"); + composerFactory.addImport("com.google.gwt.dom.client.*"); + composerFactory.addImport("java.util.*"); + for (String interfaceName : interfaceNames) { + composerFactory.addImplementedInterface(interfaceName); + } + return composerFactory.createSourceWriter(context, printWriter); + } +} diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryAjaxTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryAjaxTestGwt.java index 18ee1c58..c257971b 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryAjaxTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryAjaxTestGwt.java @@ -1,12 +1,12 @@ /* * 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 @@ -63,12 +63,12 @@ public class GQueryAjaxTestGwt extends GWTTestCase { e.setInnerHTML(""); } } - + interface Item extends JsonBuilder { Date getDate(); void setDate(Date d); } - + interface JsonExample extends JsonBuilder { int getA(); JsonExample getB(); @@ -87,7 +87,7 @@ public class GQueryAjaxTestGwt extends GWTTestCase { Function getF(); void setF(Function f); } - + boolean functionRun = false; public void testJsonBuilder() { @@ -111,7 +111,7 @@ public class GQueryAjaxTestGwt extends GWTTestCase { assertEquals(1234l, c.getD()); c.y("y"); assertEquals("y", c.y()); - + c.setF(new Function() { public void f() { functionRun = true; @@ -120,7 +120,7 @@ public class GQueryAjaxTestGwt extends GWTTestCase { assertFalse(functionRun); c.getF().f(); assertTrue(functionRun); - + Item i1 = GWT.create(Item.class); Item i2 = GWT.create(Item.class); i1.setDate(new Date(2000)); @@ -131,10 +131,10 @@ public class GQueryAjaxTestGwt extends GWTTestCase { assertEquals(3000l, c.getItems().get(1).getDate().getTime()); String s = "{'a':1,'b':{'a':2,'b':{'a':3}},'u':'url','d':1234,'t':['foo','bar'],'z':false,'y':'y','items':[{'date':2000},{'date':3000}]}"; assertEquals(s, c.toString().replaceAll("\"", "'")); - - + + } - + interface XmlExample extends XmlBuilder { interface T extends XmlBuilder { } @@ -145,20 +145,20 @@ public class GQueryAjaxTestGwt extends GWTTestCase { Boolean getB(); @Name("c") int getNumber(); - + XmlExample[] getX(); @Name("x") XmlExample getFirstX(); - + XmlExample setA(String s); @Name("c") XmlExample setNumber(int i); - + T getEnum(); T getBool(); T getNum(); } - + public void testXmlBuilder() { String xml = "<a a='ra' b='true' c='-1.48'><x a='xa1'> text</x><x a='xa2'/><enum>FOO</enum><bool>true</bool><num>333</num></a>"; XmlExample x = GWT.create(XmlExample.class); @@ -174,12 +174,12 @@ public class GQueryAjaxTestGwt extends GWTTestCase { assertEquals(" text", x.getFirstX().getText()); x.getX()[0].setText("pepe"); assertEquals("pepe", x.getFirstX().getText()); - + assertEquals(XmlExample.E.FOO, x.getEnum().getTextAsEnum(XmlExample.E.class)); assertEquals(true, x.getBool().getTextAsBoolean()); assertEquals(333d, x.getNum().getTextAsNumber()); } - + interface Feed extends XmlBuilder { interface Tag extends XmlBuilder { } @@ -206,10 +206,10 @@ public class GQueryAjaxTestGwt extends GWTTestCase { Tag getIssued(); Tag getId(); Author getAuthor(); - } + } Entry[] getEntry(); } - + // FIXME: gquery xml does not work well with htmlUnit, FF & Safari works // TODO: test in IE @DoNotRunWith({Platform.HtmlUnitLayout}) @@ -235,14 +235,14 @@ public class GQueryAjaxTestGwt extends GWTTestCase { + " </author>" + " </entry>" + "</feed>"; - + Feed f = GWT.create(Feed.class); f.parse(xml); assertEquals((int)f.getFullcount().getTextAsNumber(), f.getEntry().length); assertEquals(112, f.getModified().getTextAsDate().getYear()); assertEquals("AName", f.getEntry()[0].getAuthor().getName().getText()); } - + public void testJsonValidService() { delayTestFinish(5000); // Use a public json service @@ -270,11 +270,11 @@ public class GQueryAjaxTestGwt extends GWTTestCase { } }, 500); } - + public void testJsonTimeout() { delayTestFinish(5000); String nonJsonpUrl = "http://127.0.0.1/nopage"; - + Settings s = Ajax.createSettings(); s.setTimeout(1000); s.setSuccess(new Function(){ @@ -289,8 +289,8 @@ public class GQueryAjaxTestGwt extends GWTTestCase { }); s.setDataType("jsonp"); s.setUrl(nonJsonpUrl); - + Ajax.ajax(s); } - + } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTestGwt.java index 5ed82a34..a893741c 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTestGwt.java @@ -1,12 +1,12 @@ /* * 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 @@ -88,7 +88,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { $(e).remove(); e = null; } - + public void gwtSetUp() { if (e == null || DOM.getElementById("core-tst") == null) { testPanel = new HTML(); @@ -224,7 +224,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { }); assertHtmlEquals("<p>0</p><p>1</p><p>2</p>", $("p", e)); } - + public void testIFrameManipulation() { $(e).html("<iframe name='miframe' id='miframe' src=\"javascript:''\">"); // FF has to call empty to open and close the document before @@ -270,7 +270,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { $("p", e).empty(); assertHtmlEquals(expected, $(e).html()); } - + public void testInputValueMethods() { // imput text $(e).html("<input type='text'/>"); @@ -328,7 +328,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { gq.val(new String[]{"v1"}); assertEquals("v1", $("input:checked", e).val()); } - + public void testIssue23() { $(e).html( "<table><tr><td><input type='radio' name='n' value='v1'>1</input><input type='radio' name='n' value='v2' checked='checked'>2</input></td><td><button>Click</button></tr><td></table>"); @@ -474,14 +474,14 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals(1, g2.size()); assertEquals(expected, g2.toString()); } - + public void testAppendTo() { String txt = "<h2>Greetings</h2><div class='container'><div class='inner'>Hello</div><div class='inner'>Goodbye</div></div>"; String expected = "<h2>Greetings</h2><div class='container'><div class='inner'>Hello<p>Test</p></div><div class='inner'>Goodbye<p>Test</p></div></div>"; $(e).html(txt); $("<p>Test</p>").appendTo(".inner"); assertHtmlEquals(expected, $(e).html()); - + expected = "<div class='container'><div class='inner'>Hello</div><div class='inner'>Goodbye</div><h2>Greetings</h2></div>"; $(e).html(txt); $("h2", e).appendTo($(".container")); @@ -492,7 +492,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { $("h2", e).appendTo($("div")); assertHtmlEquals(expected, $(e).html()); } - + public void testOpacity() { $(e).html( "<p id='id1' style='opacity: 0.6; filter: alpha(opacity=60)'>Content 1</p>"); @@ -521,13 +521,13 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals(15, g.position().top); } - + public void testPropMethod(){ $(e).html("<input id=\"checkBox1\" type=\"checkbox\" checked=\"checked\" /> <input id=\"checkBox2\" type=\"checkbox\" />"); - + assertTrue($("#checkBox1",e).prop("checked")); assertFalse($("#checkBox2",e).prop("checked")); - + $("#checkBox1",e).prop("checked", false); $("#checkBox2",e).prop("checked", new Function() { @Override @@ -535,10 +535,10 @@ public class GQueryCoreTestGwt extends GWTTestCase { return Boolean.TRUE; } }); - + assertTrue($("#checkBox2",e).prop("checked")); assertFalse($("#checkBox1",e).prop("checked")); - + } @DoNotRunWith(Platform.Prod) @@ -550,7 +550,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { p = $$("({border:'1px solid black'})"); assertEquals(1, p.keys().length); assertNotNull(p.getStr("border")); - + try { // DevMode null casting returns an object // @see: @@ -610,7 +610,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals(1, $("span", e).parents().filter("body").size()); $("span", e).parents().filter("body").toString().trim().toLowerCase().contains( content.toLowerCase()); - + //parentsUntil() content = "<div id='mainDiv'><div id='subDiv1' class='subDiv'><div id='subSubDiv1'><p id='p1'>child1</p></div></div><div id='subDiv2' class='subDiv'><div id='subSubDiv2'><p id='p2'>child2</p></div></div></div>"; $(e).html(content); @@ -622,7 +622,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals("", $("#mainDiv", e).css(CSS.COLOR, false)); assertEquals("", $("#p1", e).css(CSS.COLOR, false)); assertEquals("", $("#p2", e).css(CSS.COLOR, false)); - + $("#p1",e).parentsUntil(".subDiv").css(CSS.COLOR.with(RGBColor.YELLOW)); assertEquals("red", $("#subDiv1", e).css(CSS.COLOR, false)); assertEquals("yellow", $("#subSubDiv1", e).css(CSS.COLOR, false)); @@ -659,7 +659,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { $(e).html(content); assertEquals(2, $("li.third-item", e).nextAll().size()); assertHtmlEquals(expected, $("li.third-item", e).nextAll()); - + expected = "<li class=\"last-item\">i5</li>"; assertEquals(1, $("li.third-item", e).nextAll(".last-item").size()); assertHtmlEquals(expected, $("li.third-item", e).nextAll(".last-item")); @@ -670,27 +670,27 @@ public class GQueryCoreTestGwt extends GWTTestCase { $(e).html(content); assertEquals(1, $("li.third-item", e).nextUntil(".five-item").size()); assertHtmlEquals(expected, $("li.third-item", e).nextUntil(".five-item")); - + GQuery nextUntil = $("li.five-item"); assertEquals(1, $("li.third-item", e).nextUntil(nextUntil).size()); assertHtmlEquals(expected, $("li.third-item", e).nextUntil(nextUntil)); - + Element nextUntilElement = nextUntil.get(0); assertEquals(1, $("li.third-item", e).nextUntil(nextUntilElement).size()); assertHtmlEquals(expected, $("li.third-item", e).nextUntil(nextUntilElement)); - - + + expected = "<li class='third-item'>i3</li>"; $(e).html(content); assertEquals(1, $("li.first-item", e).nextUntil(".five-item", "li.third-item").size()); assertHtmlEquals(expected, $("li.first-item", e).nextUntil(".five-item", "li.third-item")); - + assertEquals(1, $("li.first-item", e).nextUntil(nextUntil, "li.third-item").size()); assertHtmlEquals(expected, $("li.first-item", e).nextUntil(nextUntil, "li.third-item")); - + assertEquals(1, $("li.first-item", e).nextUntil(nextUntilElement, "li.third-item").size()); assertHtmlEquals(expected, $("li.first-item", e).nextUntil(nextUntilElement, "li.third-item")); - + // andSelf() content = "<ul><li>i1</li><li>i2</li><li class=\"third-item\">i3</li><li>i4</li><li>i5</li></ul>"; expected = "<li>i4</li><li>i5</li><li class=\"third-item\">i3</li>"; @@ -712,18 +712,18 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals(2, $("p", e).prev().size()); assertEquals(1, $("p", e).prev(".selected").size()); assertHtmlEquals(expected, $("p", e).prev(".selected").get(0).getString()); - + // prevAll() content = "<ul><li>i1</li><li>i2</li><li class='third-item'>i3</li><li>i4</li><li class='five-item'>i5</li></ul>"; expected = "<li>i4</li><li class='third-item'>i3</li><li>i2</li><li>i1</li>"; $(e).html(content); assertEquals(4, $("li.five-item", e).prevAll().size()); assertHtmlEquals(expected, $("li.five-item", e).prevAll()); - + expected = "<li class='third-item'>i3</li>"; assertEquals(1, $("li.five-item", e).prevAll(".third-item").size()); assertHtmlEquals(expected, $("li.five-item", e).prevAll(".third-item")); - + // prevUntil() content = "<ul><li class='item'>i1</li><li class='second-item'>i2</li><li class='third-item'>i3</li><li class='item'>i4</li><li class='five-item'>i5</li></ul>"; expected = "<li class='item'>i4</li>"; @@ -733,22 +733,22 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals(1, $("li.five-item", e).prevUntil($(".third-item")).size()); assertHtmlEquals(expected, $("li.five-item", e).prevUntil($(".third-item"))); - + Element until = $(".third-item").get(0); assertEquals(1, $("li.five-item", e).prevUntil(until).size()); assertHtmlEquals(expected, $("li.five-item", e).prevUntil(until)); - - + + assertEquals(0, $("li.five-item", e).prevUntil(".third-item", ".fake-class").size()); assertEquals(1, $("li.five-item", e).prevUntil(".second-item", ".item").size()); assertHtmlEquals(expected, $("li.five-item", e).prevUntil(".second-item", ".item")); - + assertEquals(0, $("li.five-item", e).prevUntil($(".third-item"), ".fake-class").size()); assertEquals(1, $("li.five-item", e).prevUntil($(".second-item"), ".item").size()); assertHtmlEquals(expected, $("li.five-item", e).prevUntil($(".second-item"), ".item")); - + assertEquals(0, $("li.five-item", e).prevUntil(until, ".fake-class").size()); - + until = $(".second-item").get(0); assertEquals(1, $("li.five-item", e).prevUntil(until, ".item").size()); assertHtmlEquals(expected, $("li.five-item", e).prevUntil(until, ".item")); @@ -828,7 +828,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { final GQuery sectA = $("#id1"); final GQuery sectB = $("#id2"); final GQuery sectC = $("#id3"); - + // hide() sectA.hide(); assertEquals("none", sectA.css("display", false)); @@ -869,11 +869,11 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals(2, $("p", e).slice(0, -1).size()); assertEquals(0, $("p", e).slice(3, 2).size()); } - + public void testGetEqLastFirstMethods(){ String content = "<div id='1'>blop1</div><div id='2'>blop2</div><div id='3'>blop3</div><div id='4'>blop4</div>"; $(e).html(content); - + GQuery divs =$("div",e); assertEquals(4, divs.size()); assertEquals("1", divs.get(0).getId()); @@ -884,13 +884,13 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals("2", divs.get(-3).getId()); assertEquals("3", divs.get(-2).getId()); assertEquals("4", divs.get(-1).getId()); - + assertEquals(1, divs.first().size()); assertEquals("1", divs.first().get(0).getId()); - + assertEquals(1, divs.last().size()); assertEquals("4", divs.last().get(0).getId()); - + assertEquals(1, divs.eq(0).size()); assertEquals("1", divs.eq(0).get(0).getId()); assertEquals(1, divs.eq(1).size()); @@ -899,7 +899,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals("3", divs.eq(2).get(0).getId()); assertEquals(1, divs.eq(3).size()); assertEquals("4", divs.eq(3).get(0).getId()); - + assertEquals(1, divs.eq(-4).size()); assertEquals("1", divs.eq(-4).get(0).getId()); assertEquals(1, divs.eq(-3).size()); @@ -908,8 +908,8 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals("3", divs.eq(-2).get(0).getId()); assertEquals(1, divs.eq(-1).size()); assertEquals("4", divs.eq(-1).get(0).getId()); - - + + } public void testUnique() { @@ -962,19 +962,19 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertFalse(JsUtils.truth(null)); assertFalse(JsUtils.truth("")); } - + public void testVal_issue98() { $(e).html("" +"<input type='text' id='inputText' name='inputText' value='original' />" +"<textarea id='textArea' name='textArea'>original</textarea>" +"<button id='button' name='button'value='original'>Click</button>" - + +"<select id='selectSingle' name='selectSingle'>" +"<option value='v0'>Single0</option>" +"<option value='v1'>Single1</option>" +"<option value='v2'>Single2</option>" +"</select>" - + +"<select id='selectMultiple' name='selectMultiple' multiple='multiple'>" +"<option value='v0'>Multiple0</option>" +"<option value='v1'>Multiple1</option>" @@ -984,12 +984,12 @@ public class GQueryCoreTestGwt extends GWTTestCase { +"<input type='checkbox' name='c' value='v0'/> check0" +"<input type='checkbox' name='c' value='v1'/> check1" +"<input type='checkbox' name='c' value='v2'/> check2" - + +"<input type='radio' name='r' value='v0'/> radio0" +"<input type='radio' name='r' value='v1'/> radio1" +"<input type='radio' name='r' value='v2'/> radio2" ); - + assertNull($().val()); assertEquals(0, $().vals().length); @@ -1000,7 +1000,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals("newval", $("#inputText", e).val()); assertEquals("newval", $("#textArea", e).val()); assertEquals("newval", $("#button", e).val()); - + assertEquals("v0", $("#selectSingle", e).val()); assertNull($("#selectMultiple", e).val()); $("#selectSingle, #selectMultiple", e).val("v2"); @@ -1017,16 +1017,16 @@ public class GQueryCoreTestGwt extends GWTTestCase { $("input[type='checkbox']", e).val(new String[]{"n0"}); assertEquals("n0", $("input[type='checkbox']", e).val()); assertNotNull($("input[type='checkbox']:checked", e).val()); - + assertEquals("v0", $("input[type='radio']", e).val()); assertNull($("input[type='radio']:checked", e).val()); $("input[type='radio']").eq(0).val("n0"); assertEquals("n0", $("input[type='radio']", e).val()); assertNull($("input[type='radio']:checked", e).val()); - + // evalJQuery("$('input, select, textarea, button').val(['whatever', 'v1', 'v2'])"); $("input, select, textarea, button").val("whatever", "v1", "v2"); - + String joinVals = "whatever,v1,v2"; assertEquals(joinVals, $("#inputText", e).val()); assertEquals(joinVals, $("#textArea", e).val()); @@ -1040,84 +1040,84 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals(1, $("input[type='radio']:checked", e).size()); assertEquals("v2", $("input[type='radio']:checked", e).val()); } - - + + public void testAttr_Issue97() { $(e).html("<input type='checkbox' id='cb' name='cb' value='1' />"); assertNull($("#cb:checked", e).val()); - + $("#cb", e).attr("checked", "checked"); assertEquals(1, $("#cb:checked", e).length()); assertEquals(true, InputElement.as($("#cb", e).get(0)).isChecked()); assertEquals("checked", $("#cb", e).get(0).getAttribute("checked")); assertEquals(true, $("#cb", e).get(0).getPropertyBoolean("checked")); - + $("#cb", e).removeAttr("checked"); assertEquals(0, $("#cb:checked", e).length()); assertEquals(false, InputElement.as($("#cb", e).get(0)).isChecked()); assertEquals("", $("#cb", e).get(0).getAttribute("checked")); assertEquals(false, $("#cb", e).get(0).getPropertyBoolean("checked")); - + $("#cb", e).attr("checked", true); assertEquals(1, $("#cb:checked", e).length()); assertEquals(true, InputElement.as($("#cb", e).get(0)).isChecked()); assertEquals("checked", $("#cb", e).get(0).getAttribute("checked")); assertEquals(true, $("#cb", e).get(0).getPropertyBoolean("checked")); - + $("#cb", e).attr("checked", false); assertEquals(0, $("#cb:checked", e).length()); assertEquals(false, InputElement.as($("#cb", e).get(0)).isChecked()); assertEquals("", $("#cb", e).get(0).getAttribute("checked")); assertEquals(false, $("#cb", e).get(0).getPropertyBoolean("checked")); - + $("#cb", e).attr("checked", ""); assertEquals(1, $("#cb:checked", e).length()); assertEquals(true, InputElement.as($("#cb", e).get(0)).isChecked()); assertEquals("checked", $("#cb", e).get(0).getAttribute("checked")); assertEquals(true, $("#cb", e).get(0).getPropertyBoolean("checked")); - + GQuery gq = $("<div></div>test<!-- a comment-->"); gq.attr("class", "test1"); - + assertEquals("test1", gq.get(0).getClassName()); assertEquals("test1", gq.attr("class")); assertNull(gq.get(0).getPropertyString("class")); - + gq.removeAttr("class"); assertEquals("", gq.get(0).getClassName()); assertEquals("", gq.attr("class")); - + //test on value $("#cb", e).attr("value", "mail"); assertEquals("mail", InputElement.as($("#cb", e).get(0)).getValue()); assertEquals("mail", $("#cb", e).get(0).getAttribute("value")); - + $("#cb", e).removeAttr("value"); String val = InputElement.as($("#cb", e).get(0)).getValue(); assertTrue(String.valueOf(val).matches("^(|null|on)$")); - + val = $("#cb", e).get(0).getAttribute("value"); assertTrue(String.valueOf(val).matches("^(|null|on)$")); - + try{ $("#cb", e).attr("type", "hidden"); fail("Cannnot change a type of an element already attached to the dom"); }catch (Exception e){} - + gq = $("<input type='text' value='blop'></input>"); gq.attr("type", "radio"); assertEquals("radio", InputElement.as(gq.get(0)).getType()); assertEquals("blop", InputElement.as(gq.get(0)).getValue()); - + gq.attr(Properties.create("{class:'test2', disabled:true}")); InputElement ie = InputElement.as(gq.get(0)); - + assertEquals("test2", ie.getClassName()); assertEquals(true, ie.isDisabled()); assertEquals("disabled", ie.getAttribute("disabled")); - + } - + @DoNotRunWith({Platform.Prod}) // FIXME: the hidden part does not work in FF nor Chrome public void testWidthHeight() { @@ -1140,10 +1140,10 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals(122, g.outerWidth()); assertEquals(142, g.outerHeight(true)); assertEquals(142, g.outerWidth(true)); - + // When hiding the element we should get the same sizes $(e).hide(); - + assertEquals(100, g.width()); assertEquals(100, g.height()); assertEquals("h1", 120, g.innerWidth()); @@ -1161,7 +1161,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals(142, g.outerHeight(true)); assertEquals(142, g.outerWidth(true)); } - + public void testWidthHeightInlineElement() { $(e).html( "<span style='border: 1px solid red; padding: 10px; margin:10px'>Content 1</span>"); @@ -1186,7 +1186,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertHtmlEquals(expected, $(e).html()); } - + public void testFilterBody() { GQuery myNewElement = $("<div>my new div</div>"); boolean isAttachedToTheDOM = myNewElement.parents().filter("body").size() > 0; @@ -1196,35 +1196,35 @@ public class GQueryCoreTestGwt extends GWTTestCase { isAttachedToTheDOM = myNewElement.parents().filter("body").size() > 0; assertEquals(true, isAttachedToTheDOM); } - + public void testFilterMethod(){ // first test filter on element attached to the DOM String content = "<div class='outer'><div class='inner first'>Hello <span>blop</span></div><div class='inner second'>And</div><div class='inner third'>Goodbye</div></div>"; $(e).html(content); - + assertEquals(5, $("*", e).length()); assertEquals(4, $("*", e).filter("div").length()); assertEquals(1, $("*", e).filter("div.outer").length()); assertEquals(3, $("*", e).filter("div.inner").length()); assertEquals(1, $("*", e).filter("span").length()); - + GQuery $html = $("<div>div1</div><div>div2</div><div>div3</div><span>span1</span>"); assertEquals(3, $html.filter("div").length()); assertEquals(1, $html.filter("span").length()); - + JsNodeArray array = JsNodeArray.create(); for (int i = 0 ; i < 3; i++){ array.addNode(DOM.createDiv()); } - assertEquals(3, $(array).filter("div").length()); - - + assertEquals(3, $(array).filter("div").length()); + + String content2 = "<div><div class='inner first'>Hello</div><div class='inner second'>And</div><div class='inner third'>Goodbye</div></div>"; $(e).html(content2); //the inner object contains the 3 div that are detached from the dom GQuery $inner = $(".inner").replaceWith("<h3>blop</h3>"); - assertEquals(3, $inner.filter("div").length()); + assertEquals(3, $inner.filter("div").length()); } public void testGQueryWidgets() { @@ -1253,9 +1253,9 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals(2, $(new Label(""), new TextArea()).size()); } - + public void testGQueryWidgetManipulation() { - + String content = "<div class='outer'></div>"; $(e).html(content); Button b = new Button("b"); @@ -1263,14 +1263,14 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertTrue(b.isAttached()); $("button").remove(); assertFalse(b.isAttached()); - + RootPanel.get().add(b); assertTrue(b.isAttached()); $(e).append($(b)); assertTrue(b.isAttached()); $(e).empty(); // FIXME: assertFalse(b.isAttached()); - + } public void testGQueryMap() { @@ -1308,33 +1308,33 @@ public class GQueryCoreTestGwt extends GWTTestCase { } public void testHtmlSnippet(){ - - GQuery gq = $("<div>blop</div><p>test</p><span>test</span>"); + + GQuery gq = $("<div>blop</div><p>test</p><span>test</span>"); assertEquals(3, gq.size()); assertEquals("DIV", gq.get(0).getTagName().toUpperCase()); assertEquals("P", gq.get(1).getTagName().toUpperCase()); assertEquals("SPAN", gq.get(2).getTagName().toUpperCase()); - + //xhtml tag - gq = $("<div/>"); + gq = $("<div/>"); assertEquals(1, gq.size()); assertEquals("DIV", gq.get(0).getTagName().toUpperCase()); - - gq = $("<a/>"); + + gq = $("<a/>"); assertEquals(1, gq.size()); assertEquals("A", gq.get(0).getTagName().toUpperCase()); - - gq = $("<div>"); + + gq = $("<div>"); assertEquals(1, gq.size()); assertEquals("DIV", gq.get(0).getTagName().toUpperCase()); - + //issue 81 : trailing spaces - gq = $(" <div>blop</div><p>test</p><span>test</span> "); + gq = $(" <div>blop</div><p>test</p><span>test</span> "); assertEquals(3, gq.size()); assertEquals("DIV", gq.get(0).getTagName().toUpperCase()); assertEquals("P", gq.get(1).getTagName().toUpperCase()); assertEquals("SPAN", gq.get(2).getTagName().toUpperCase()); - + //wrapping gq = $("<tr>blop</tr><tr>test</tr>"); assertEquals(2, gq.size()); @@ -1345,42 +1345,42 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals(2, gq.size()); assertEquals("TR", gq.get(0).getTagName().toUpperCase()); assertEquals("TR", gq.get(1).getTagName().toUpperCase()); - + gq = $("<td>blop</td><td>test</td>"); assertEquals(2, gq.size()); assertEquals("TD", gq.get(0).getTagName().toUpperCase()); assertEquals("TD", gq.get(1).getTagName().toUpperCase()); - + gq = $("<th>blop</th><th>test</th>"); assertEquals(2, gq.size()); assertEquals("TH", gq.get(0).getTagName().toUpperCase()); assertEquals("TH", gq.get(1).getTagName().toUpperCase()); - + gq = $("<col/><col/>"); assertEquals(2, gq.size()); assertEquals("COL", gq.get(0).getTagName().toUpperCase()); assertEquals("COL", gq.get(1).getTagName().toUpperCase()); - + gq = $("<area/><area/>"); assertEquals(2, gq.size()); assertEquals("AREA", gq.get(0).getTagName().toUpperCase()); assertEquals("AREA", gq.get(1).getTagName().toUpperCase()); - + gq = $("<option>blop</option><option>test</option>"); assertEquals(2, gq.size()); assertEquals("OPTION", gq.get(0).getTagName().toUpperCase()); assertEquals("OPTION", gq.get(1).getTagName().toUpperCase()); - + gq = $("<legend>blop</legend><legend>test</legend>"); assertEquals(2, gq.size()); assertEquals("LEGEND", gq.get(0).getTagName().toUpperCase()); assertEquals("LEGEND", gq.get(1).getTagName().toUpperCase()); - + gq = $("<thead>blop</thead><thead>test</thead>"); assertEquals(2, gq.size()); assertEquals("THEAD", gq.get(0).getTagName().toUpperCase()); assertEquals("THEAD", gq.get(1).getTagName().toUpperCase()); - + //issue gq = $("<select name=\"modificator\"><option value=\"work\" selected=\"selected" +"\">Work</option><option value=\"work_fax\" >Work fax</option><option " @@ -1391,11 +1391,11 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals("SELECT", gq.get(0).getTagName().toUpperCase()); assertEquals(6, gq.get(0).getChildCount()); - - + + } - - + + public void testNulls() { Assert.assertEquals(0, $((Node) null).size()); Assert.assertEquals(0, $((Element) null).size()); @@ -1404,247 +1404,247 @@ public class GQueryCoreTestGwt extends GWTTestCase { Assert.assertNull($((String) null).get(-1)); Assert.assertEquals(0, $((String) null).eq(0).size()); } - + public void testRemoveMethod(){ String html = "<div id='parent'>parent<div id='child'>child</div></div>"; $(e).html(html); - + Function failCallback = new Function(){ @Override public void f() { fail("Event binding not removed"); } }; - + Element parent = $("#parent", e).get(0); Element child = $("#child", e).get(0); - + $("#child", e).data("key", "child"); $("#child", e).click(failCallback); $("#parent", e).data("key", "parent"); $("#parent", e).click(failCallback); - + $("#parent", e).remove(); - + //child and the parent was removed assertEquals(0,$("#child", e).length()); assertEquals(0,$("#parent", e).length()); - + assertNull($(child).data("key")); assertNull($(parent).data("key")); //if failCallback is always binded, test fails... $(child).click(); $(parent).click(); - - - + + + } public void testRemoveMethodWithFilter(){ String html = "<div id='parent'>parent<div id='child'>child</div></div>"; $(e).html(html); - + Function failCallback = new Function(){ @Override public void f() { fail("Event binding not removed"); } }; - + Function noFailCallback = new Function(){ @Override public void f(Element e) { $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED)); } }; - + Element parent = $("#parent", e).get(0); Element child = $("#child", e).get(0); - + $("#child", e).data("key", "child"); $("#child", e).click(failCallback); $("#parent", e).data("key", "parent"); $("#parent", e).click(noFailCallback); - + $("div", e).remove("#child"); - + //child was removed but not the parent assertEquals(0,$("#child", e).length()); assertEquals(1,$("#parent", e).length()); - + assertNull($(child).data("key")); assertEquals("parent",$(parent).data("key")); - + //if failCallback is always binded, test fails... $(child).click(); - - + + $(parent).click(); assertEquals("red", $(parent).css(CSS.BACKGROUND_COLOR, false)); } - + public void testDetachMethod(){ String html = "<div id='parent'>parent<div id='child'>child</div></div>"; $(e).html(html); - + Function noFailCallback = new Function(){ @Override public void f(Element e) { $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED)); } }; - + Element parent = $("#parent", e).get(0); Element child = $("#child", e).get(0); - + $("#child", e).data("key", "child"); $("#child", e).click(noFailCallback); $("#parent", e).data("key", "parent"); $("#parent", e).click(noFailCallback); - + GQuery $parent = $("#parent", e).detach(); - + //test parent an child well detached assertEquals(0,$("#parent", e).length()); assertEquals(0,$("#child", e).length()); //test that data was not cleaned assertEquals("child",$(child).data("key")); assertEquals("parent",$(parent).data("key")); - + $(e).append($parent); - + assertEquals(1,$("#parent", e).length()); assertEquals(1,$("#child", e).length()); assertEquals("child",$("#child", e).data("key")); assertEquals("parent",$("#parent", e).data("key")); - + $("#child", e).click(); assertEquals("red", $(child).css(CSS.BACKGROUND_COLOR, false)); $("#parent", e).click(); assertEquals("red", $(parent).css(CSS.BACKGROUND_COLOR, false)); } - + public void testDetachMethodWithFilter(){ String html = "<div id='parent'>parent<div id='child'>child</div></div>"; $(e).html(html); - + Function noFailCallback = new Function(){ @Override public void f(Element e) { $(e).css(CSS.BACKGROUND_COLOR.with(RGBColor.RED)); } }; - + Element parent = $("#parent", e).get(0); Element child = $("#child", e).get(0); - + $("#child", e).data("key", "child"); $("#child", e).click(noFailCallback); $("#parent", e).data("key", "parent"); $("#parent", e).click(noFailCallback); - + $("div", e).detach("#child"); - + //child was removed but not the parent assertEquals(0,$("#child", e).length()); assertEquals(1,$("#parent", e).length()); - + //data must always exist assertEquals("child", $(child).data("key")); assertEquals("parent",$(parent).data("key")); - + $(e).append($(child)); - + assertEquals(1,$("#child", e).length()); assertEquals(1,$("#parent", e).length()); - + $(child).click(); assertEquals("red", $("#child", e).css(CSS.BACKGROUND_COLOR, false)); - + $(parent).click(); assertEquals("red", $("#parent", e).css(CSS.BACKGROUND_COLOR, false)); } - + public void testUnwrapMethod(){ String html = "<div class='parent'><div class='child'>child1</div><span>other child</span></div><div class='parent'><div class='child'>child2</div></div><div class='parent'><div class='child'>child3</div></div>"; $(e).html(html); - + assertEquals(3, $(".parent", e).length()); assertEquals(3, $(".child", e).length()); - + $(".child",e).unwrap(); - + assertEquals(0, $(".parent",e).length()); assertEquals(3, $(".child",e).length()); - + String expectedHtml = "<div class=\"child\">child1</div><span>other child</span><div class=\"child\">child2</div><div class=\"child\">child3</div>"; - + assertEquals(expectedHtml, $(e).html()); - + } - + public void testClosestMethod(){ String html = "<div><p><div id='firstDiv'><p id='firstP'><span><input id='firstInput' type='text'></input></span></p></div></p></div>"; $(e).html(html); - + GQuery closeP = $("input", e).closest("p,div"); - + assertEquals(1, closeP.length()); assertEquals("firstP", closeP.get(0).getId()); - + GQuery closeDiv = $("input", e).closest("div"); - + assertEquals(1, closeDiv.length()); assertEquals("firstDiv", closeDiv.get(0).getId()); - + GQuery closeInput = $("input", e).closest("input"); - + assertEquals(1, closeInput.length()); assertEquals("firstInput", closeInput.get(0).getId()); - + GQuery closeUnknown = $("input", e).closest("h1"); - + assertEquals(0, closeUnknown.length()); - + GQuery closePWithContext = $("input", e).closest("p,div",$("#firstDiv",e).get(0)); - + assertEquals(1, closePWithContext.length()); assertEquals("firstP", closePWithContext.get(0).getId()); - + GQuery closeDivWithContext = $("input", e).closest("div",$("#firstP",e).get(0)); - - assertEquals(0, closeDivWithContext.length()); - + + assertEquals(0, closeDivWithContext.length()); + } - + public void testClosestMethodWithArrayOfString(){ - + String html = "<div id='mainDiv'><div id='subDiv' class='test'><div id='subSubDiv'><p id='mainP'><span id='testSpan' class='test'><input id='firstInput' type='text'></input></span></p></div></div></div>"; $(e).html(html); - + JsNamedArray<NodeList<Element>> close = $("input", e).closest(new String[]{"p","div", ".test", "#unknown"}); - + assertEquals(3, close.length()); - + assertNotNull(close.get("p")); assertEquals(1,close.get("p").getLength()); assertEquals("mainP", close.get("p").getItem(0).getId()); - + assertNotNull(close.get("div")); assertEquals(3,close.get("div").getLength()); assertEquals("subSubDiv", close.get("div").getItem(0).getId()); assertEquals("subDiv", close.get("div").getItem(1).getId()); assertEquals("mainDiv", close.get("div").getItem(2).getId()); - + assertNotNull(close.get(".test")); assertEquals(2,close.get(".test").getLength()); assertEquals("testSpan", close.get(".test").getItem(0).getId()); assertEquals("subDiv", close.get(".test").getItem(1).getId()); - + assertNull(close.get("#unknown")); - + } - + public void testMap() { String html = "<div class='d' id='6'></div>" + "<span class='s' id='5'></span>" + @@ -1654,10 +1654,10 @@ public class GQueryCoreTestGwt extends GWTTestCase { "<i class='p' id='1'></i>" + "<strong></strong>"; $(e).html(html); - + GQuery c = $(e).children(); assertEquals(7, c.size()); - + // A list of lists containing tag,class,id, remove elements without id List<List<String>> m = $(e).children().map(new Function() { public List<String> f(Element e, int i) { @@ -1673,7 +1673,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { } }); assertEquals(6, m.size()); - + // Sort the list by id assertEquals("div", m.get(0).get(0).toLowerCase()); assertEquals("i", m.get(5).get(0).toLowerCase()); @@ -1685,13 +1685,13 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals("div", m.get(5).get(0).toLowerCase()); assertEquals("i", m.get(0).get(0).toLowerCase()); } - + public void testWindowSize() { GQuery w = $(GQuery.window); assertTrue(w.width() > 0); assertTrue(w.height() > 0); } - + public void testFunction() { $(e).html("<div id=fid>0</div>"); GQuery g = $("#fid", e); @@ -1728,7 +1728,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { } }); assertEquals("D0", g.text()); - + // EVENTS g.unbind(Event.ONCLICK).click(new Function(){ @Override @@ -1760,13 +1760,13 @@ public class GQueryCoreTestGwt extends GWTTestCase { } }).click(); assertEquals("ED", g.text()); - + // ELEMENTS AND WIDGETS Label label = new Label("1"); RootPanel.get().add(label); g = $("#fid, .gwt-Label"); assertEquals(2, g.size()); - + g.each(new Function() { @Override public void f(com.google.gwt.user.client.Element e) { @@ -1781,7 +1781,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { } }); assertEquals("DD", g.text()); - + g.each(new Function() { @Override public void f(com.google.gwt.user.client.Element e) { @@ -1804,7 +1804,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { } }); assertEquals("DW", g.text()); - + g.each(new Function() { @Override public Object f(com.google.gwt.user.client.Element e, int idx) { @@ -1876,7 +1876,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { label.removeFromParent(); } - + public void testXpathSelector() { $(e).html("<table border=1 id=idtest width=440><tr><td width=50%>A Text</td><td width=50%>B</td></tr></table>"); SelectorEngineCssToXPath s = new SelectorEngineCssToXPath(); @@ -1885,13 +1885,13 @@ public class GQueryCoreTestGwt extends GWTTestCase { assertEquals($(selector).size(), $(xselector).size()); } } - + public void testIssue81(){ GQuery test = $(" <div>blop</div><!-- comment --> <p>test2</p> "); test.addClass("test"); test.removeClass("test"); } - + public void testHas() { $(e).html("<ul>" +"<li>list item 1</li>" @@ -1901,7 +1901,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { +" <li>list item 2-b</li>" +" </ul>" +"</li>" - +"<li id='l3'>list item 3 <span>span</span>" + +"<li id='l3'>list item 3 <span>span</span>" +"</li>" +"<li>list item 4</li>" +"</ul>"); @@ -1912,16 +1912,16 @@ public class GQueryCoreTestGwt extends GWTTestCase { Element span = $("span", e).get(0); assertEquals("l3", $("li", e).has(span).id()); } - + public void testDetachedElement(){ GQuery view = $("<div id='view' style='width: 300px;'><div style='width: 50%'></div></div>"); - + int viewWidth = view.width(); - + assertEquals(300, viewWidth); - + int innerViewWidth = view.children().width(); - + assertEquals(150, innerViewWidth); } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCssTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCssTestGwt.java index 10ed3caa..ea9b91dd 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCssTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCssTestGwt.java @@ -1,12 +1,12 @@ /* * 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 @@ -70,7 +70,7 @@ public class GQueryCssTestGwt extends GWTTestCase { public String getModuleName() { return "com.google.gwt.query.Query"; } - + public void gwtTearDown() { $(e).remove(); e = null; @@ -135,12 +135,12 @@ public class GQueryCssTestGwt extends GWTTestCase { assertTrue($("#test").css("backgroundImage").contains("image.jpg")); assertTrue($("#test").css(CSS.BACKGROUND_IMAGE).contains("image.jpg")); } - + void assertMatches(String regex, String test) { boolean b = test.matches("^(" + regex + ")$"); assertTrue("assertMatches error, expected:" + regex + ", actual:" + test, b); } - + public void testBackgroundPositionProperty() { $(e).html("<div id='test'>Content</div>"); @@ -209,7 +209,7 @@ public class GQueryCssTestGwt extends GWTTestCase { CSS.BACKGROUND.with(RGBColor.TRANSPARENT, UriValue.url("back.jpg"), BackgroundRepeat.NO_REPEAT, BackgroundAttachment.SCROLL, BackgroundPosition.CENTER)); - + assertMatches(".*back.jpg.*no-repeat scroll (center|center center|50% 50%).*", $("#test").css("background")); } @@ -448,7 +448,7 @@ public class GQueryCssTestGwt extends GWTTestCase { $("#test").css(CSS.COLOR.with(RGBColor.BLACK)); assertEquals("black", $("#test").css(CSS.COLOR, false)); - + $("#test").css(CSS.COLOR.with(RGBColor.BLUE)); assertEquals("blue", $("#test").css(CSS.COLOR, false)); @@ -457,7 +457,7 @@ public class GQueryCssTestGwt extends GWTTestCase { $("#test").css(CSS.COLOR.with(RGBColor.GRAY)); assertEquals("gray", $("#test").css(CSS.COLOR, false)); - + $("#test").css(CSS.COLOR.with(RGBColor.GREY)); assertMatches("grey|rgb\\(128, *128, *128\\)", $("#test").css(CSS.COLOR, false)); @@ -663,7 +663,7 @@ public class GQueryCssTestGwt extends GWTTestCase { $("#test").css(CSS.HEIGHT.with(Length.pt(10))); assertEquals("10pt", $("#test").css(CSS.HEIGHT, false)); - + $("#test").css(CSS.HEIGHT.with(Length.px(10.1))); assertEquals("10.1px", $("#test").css(CSS.HEIGHT, false)); @@ -714,7 +714,7 @@ public class GQueryCssTestGwt extends GWTTestCase { $("#test").css(CSS.LINE_HEIGHT.with(2)); assertEquals("2", $("#test").css("lineHeight", false)); assertEquals("2", $("#test").css(CSS.LINE_HEIGHT, false)); - + $("#test").css(CSS.LINE_HEIGHT.with(2.5)); assertEquals("2.5", $("#test").css("lineHeight", false)); assertEquals("2.5", $("#test").css(CSS.LINE_HEIGHT, false)); @@ -746,7 +746,7 @@ public class GQueryCssTestGwt extends GWTTestCase { public void testListStyleProperty() { $(e).html("<ul id='test'><li>Content</li></ul>"); - + assertMatches("(disc |)(outside |)(none|)", $("#test").css("listStyle")); $("#test").css( @@ -754,7 +754,7 @@ public class GQueryCssTestGwt extends GWTTestCase { null)); assertMatches("disc outside( none|)", $("#test").css("listStyle")); assertMatches("disc outside( none|)", $("#test").css(CSS.LIST_STYLE)); - + $("#test").css( CSS.LIST_STYLE.with(ListStyleType.DISC, null, UriValue.url("square.jpg"))); assertMatches("disc (outside |)url\\(.*square.jpg.*\\)", $("#test").css("listStyle")); @@ -784,7 +784,7 @@ public class GQueryCssTestGwt extends GWTTestCase { assertEquals("10px 20px", $("#test").css("margin")); assertEquals("10px 20px", $("#test").css(CSS.MARGIN)); - + $("#test").css(CSS.MARGIN.with(Length.px(10), Length.px(20), Length.px(30))); assertEquals("10px 20px 30px", $("#test").css("margin")); @@ -1019,11 +1019,11 @@ public class GQueryCssTestGwt extends GWTTestCase { public void testVerticalAlignProperty() { $(e).html("<div id='test'>Content</div>"); - + $("#test").css(CSS.VERTICAL_ALIGN.with(Length.px(120))); assertEquals("120px", $("#test").css("verticalAlign")); assertEquals("120px", $("#test").css(CSS.VERTICAL_ALIGN)); - + $("#test").css(CSS.VERTICAL_ALIGN.with(VerticalAlign.BASELINE)); assertEquals("baseline", $("#test").css("verticalAlign")); assertEquals("baseline", $("#test").css(CSS.VERTICAL_ALIGN)); @@ -1127,7 +1127,7 @@ public class GQueryCssTestGwt extends GWTTestCase { $("#test").css(CSS.ZINDEX.with(1000)); assertEquals("1000", $("#test").css("zIndex", true)); assertEquals("1000", $("#test").css(CSS.ZINDEX, true)); - + $("#test").css(CSS.ZINDEX.with(null)); assertMatches("0|auto", $("#test").css("zIndex", true)); assertMatches("0|auto", $("#test").css(CSS.ZINDEX, true)); diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java index 4ef2e86e..531f58c3 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java @@ -1,12 +1,12 @@ /* * 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 @@ -64,10 +64,10 @@ public class GQueryEffectsTestGwt extends GWTTestCase { public void testClipAnimation() { $(e).html("<p id='idtest'>Content 1</p></p>"); - + final GQuery g = $("#idtest"); final int duration = 1000; - + // Clip effect places a relative div in the position of the original element // So check that there is not any div. GQuery back = $("div", e); @@ -78,10 +78,10 @@ public class GQueryEffectsTestGwt extends GWTTestCase { // Check that the back div has been created back = $("div", e); assertEquals(1, back.size()); - + // Configure the max duration for this test delayTestFinish(duration * 2); - + // each timer calls the next one //final Timer timer1 = new Timer() { //public void run() { @@ -102,24 +102,24 @@ public class GQueryEffectsTestGwt extends GWTTestCase { //timer1.schedule(duration/2 + 1); } }; - + // Start the first timer timer2.schedule(duration/2); - } + } public void testEffectsShouldBeQueued() { $(e).html("<p id='idtest'>Content 1</p></p>"); final GQuery g = $("#idtest").css("position", "absolute"); final Offset o = g.offset(); - + final int duration = 1000; g.as(Effects.Effects). animate($$("left: '+=100'"), duration, Easing.LINEAR). animate($$("top: '+=100'"), duration, Easing.LINEAR). animate($$("left: '-=100'"), duration, Easing.LINEAR). animate($$("top: '-=100'"), duration, Easing.LINEAR); - + // Configure the max duration for this test delayTestFinish(duration * 4); @@ -152,7 +152,7 @@ public class GQueryEffectsTestGwt extends GWTTestCase { // Start the first timer timer4.schedule(duration/2); } - + public void testFade() { $(e) .html( @@ -160,7 +160,7 @@ public class GQueryEffectsTestGwt extends GWTTestCase { final GQuery sectA = $("#id1"); final GQuery sectB = $("#id2"); - + // fadeIn() & fadeOut() are tested with delayed assertions sectA.hide(); sectA.fadeIn(2000); @@ -210,7 +210,7 @@ public class GQueryEffectsTestGwt extends GWTTestCase { // schedule the delayed assertions timerShortTime.schedule(200); timerMidTime.schedule(1200); - timerLongTime.schedule(2200); + timerLongTime.schedule(2200); } public void testPropertiesAnimationComputeEffects() { @@ -295,36 +295,36 @@ public class GQueryEffectsTestGwt extends GWTTestCase { PropertiesAnimation.computeFxProp(g.get(0), "padding", "20px", false) .toString()); } - + public void testColorEffectParsing(){ String html = "<div id='test' style='color: #112233'>Test</div>"; $(e).html(html); - + ColorFx effect = (ColorFx) PropertiesAnimation.computeFxProp($("#test",e).get(0), "color", "#ffffff", false); assertEquals(17, effect.getStartColor()[0]); //#11 assertEquals(34, effect.getStartColor()[1]); //#22 assertEquals(51, effect.getStartColor()[2]); //#33 - + assertEquals(255, effect.getEndColor()[0]); assertEquals(255, effect.getEndColor()[1]); assertEquals(255, effect.getEndColor()[2]); - + effect = (ColorFx) PropertiesAnimation.computeFxProp(e, "color", "rgb(255,255,255)", false); assertEquals(255, effect.getEndColor()[0]); assertEquals(255, effect.getEndColor()[1]); assertEquals(255, effect.getEndColor()[2]); - + effect = (ColorFx) PropertiesAnimation.computeFxProp(e, "color", "rgb(100%, 100%, 100%)", false); assertEquals(255, effect.getEndColor()[0]); assertEquals(255, effect.getEndColor()[1]); assertEquals(255, effect.getEndColor()[2]); - + effect = (ColorFx) PropertiesAnimation.computeFxProp(e, "color", "white", false); assertEquals(255, effect.getEndColor()[0]); assertEquals(255, effect.getEndColor()[1]); assertEquals(255, effect.getEndColor()[2]); } - + private void assertPosition(GQuery g, Offset min, Offset max) { int a = Math.min(min.top, max.top); int b = Math.max(min.top, max.top); @@ -342,21 +342,21 @@ public class GQueryEffectsTestGwt extends GWTTestCase { + " - " + b; assertTrue(msg, c); } - + public void testAttrEffect() { $(e).html("<table border=1 id=idtest width=440><tr><td width=50%>A</td><td width=50%>B</td></tr></table>"); final GQuery g = $("#idtest").css("position", "absolute"); final int duration = 500; - - assertEquals("cssprop=$width attr=width value=+=100 start=440 end=540 unit=", + + assertEquals("cssprop=$width attr=width value=+=100 start=440 end=540 unit=", PropertiesAnimation.computeFxProp(g.get(0), "$width", "+=100", false).toString()); - + delayTestFinish(duration * 3); g.as(Effects.Effects). animate($$("$width: +=100; $border: +=4"), duration, Easing.LINEAR); - + final Timer timer = new Timer() { public void run() { assertEquals(540.0, Double.parseDouble(g.attr("width"))); @@ -366,7 +366,7 @@ public class GQueryEffectsTestGwt extends GWTTestCase { }; timer.schedule(duration * 2); } - + public void testStop() { $(e) .html( @@ -375,28 +375,28 @@ public class GQueryEffectsTestGwt extends GWTTestCase { final GQuery sectA = $("#id1"); final GQuery sectB = $("#id2"); final GQuery sectC = $("#id2"); - + sectA.hide(); sectA.fadeIn(2000); sectB.fadeOut(2000).delay(500).fadeIn(1000); sectC.fadeOut(2000).delay(500).fadeIn(1000); - // Call stop + // Call stop Timer timerMidTime = new Timer() { public void run() { sectA.stop(); sectB.stop(true, true); sectC.stop(false, false); - + Double o = Double.valueOf(sectA.css("opacity")); sectA.data("opacityA", o); assertTrue( "'sectA' opacity must be in the interval 0.5-1 but is: " + o, o > 0.5 && o < 1); - + //animation should jump to the end assertEquals("none", sectB.css("display")); - + o = Double.valueOf(sectC.css("opacity")); sectC.data("opacityC", o); assertTrue( @@ -404,16 +404,16 @@ public class GQueryEffectsTestGwt extends GWTTestCase { o > 0 && o < 0.5); } }; - - + + Timer timerLongTime = new Timer() { public void run() { Double midAOpacity = sectA.data("opacityA", Double.class); //animation was stopped, opacity should not change assertEquals(midAOpacity, Double.valueOf(sectA.css("opacity"))); //animation was stopped and jumped to the end, the queue was cleared so no change too. - assertEquals("none", sectB.css("display")); - + assertEquals("none", sectB.css("display")); + //fadeOut was stopped but fadeIn should continue Double midCOpacity = sectC.data("opacityC", Double.class); Double laterCOpacity = Double.valueOf(sectC.css("opacity")); @@ -427,24 +427,24 @@ public class GQueryEffectsTestGwt extends GWTTestCase { timerMidTime.schedule(1200); // schedule timer timerLongTime.schedule(2200); - + } - + // This test is used to demonstrate the issue, dont run it normally to avoid // problems during the testing phase int animationRunCounter = 0; public void ignore_testQueuesAndDataLeaks_issue132() { - + final Widget w = new Label("some animation"); w.setVisible(false); RootPanel.get().add(w); w.getElement().setId("e"); GQuery g = $(w); - + int test_duration = 1000; int fx_duration = 200; final int loops = test_duration / fx_duration; - + // Queue a set of effects which will use the data cache for (int i = 0; i < loops ; i++) { final char[] bulk = new char[5*1024*1024]; // let's leak 5MBs @@ -455,14 +455,14 @@ public class GQueryEffectsTestGwt extends GWTTestCase { } }); } - + // Testing delay as well g.delay(fx_duration, new Function(){ public void f() { animationRunCounter ++; } }); - + // We do the assertions after all effects have been run g.queue(new Function() { public void f() { @@ -471,20 +471,20 @@ public class GQueryEffectsTestGwt extends GWTTestCase { $(this).dequeue(); // Check that all animations and the delayed function has been run assertEquals(loops + 1, animationRunCounter); - + // Check that nothings is left in the dataCache object assertEquals(0, GQuery.dataCache.length()); - + // Check that getting queue size does not initialize the data // object for this object assertEquals(0, $(this).queue()); assertEquals(0, GQuery.dataCache.length()); - + // Mark the test as success and stop delay timer finishTest(); }; }); - + // delay the test enough to run all animations delayTestFinish(test_duration * 2); } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java index abe708bb..fbc4c3e8 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java @@ -1,11 +1,11 @@ /* * 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 @@ -880,7 +880,7 @@ public class GQueryEventsTestGwt extends GWTTestCase { $("p", e, Events.Events).bind("click", "red",new Function() { public void f(Element elem) { $(elem).css(CSS.FONT_SIZE.with(Length.px(24))); - + assertEquals("red", getData()[0]); } }); @@ -958,7 +958,7 @@ public class GQueryEventsTestGwt extends GWTTestCase { finishTest(); } }); - + Window.resizeTo(w.width(), w.height() + 100); } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryJsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryJsTestGwt.java index 3884286c..f89c7aaa 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryJsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryJsTestGwt.java @@ -1,12 +1,12 @@ /* * 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 @@ -55,7 +55,7 @@ public class GQueryJsTestGwt extends GWTTestCase { public void testJsCache() { String[] slist = new String[]{"A", "B", "C"}; - + JsCache c = JsCache.create(); assertTrue(c.isEmpty()); for (int i=0; i < slist.length; i++) { @@ -77,52 +77,52 @@ public class GQueryJsTestGwt extends GWTTestCase { assertEquals(7, c.length()); assertEquals(7, c.keys().length); assertEquals(7, c.elements().length); - + assertTrue(c.exists(2)); assertFalse(c.exists(3)); assertTrue(c.exists("X")); assertFalse(c.exists("V")); - + c.delete(2); c.delete("C"); assertEquals(5, c.length()); - + c.put(-1, "N"); assertEquals(6, c.length()); assertEquals("N", c.get(-1)); } - + public void testChrome__gwt_ObjectId() { JsCache a = JsCache.create(); assertEquals(0, a.length()); assertEquals(0, a.keys().length); assertEquals(0, a.elements().length); - + a.put("obj", new Long(21)); assertEquals(1, a.length()); assertEquals(1, a.keys().length); assertEquals(1, a.elements().length); - + JsNodeArray n = JsNodeArray.create(); assertEquals(0, n.getLength()); assertEquals(0, n.<JsCache>cast().keys().length); assertEquals(0, n.elements().length); - + n.addNode($("<hr/>").get(0)); assertEquals(1, n.getLength()); assertEquals(1, n.<JsCache>cast().keys().length); assertEquals(1, n.elements().length); } - + public void testProperties() { Properties p = $$("b: 'a'; c: 1, /*gg: aadf*/d: url('https://test.com');"); assertEquals(3, p.keys().length); assertEquals("url(https://test.com)", p.getStr("d")); - + p = $$("color: 'rgb(0, 0,139)', background: red"); assertEquals(2, p.keys().length); assertEquals("rgb(0,0,139)", p.getStr("color")); - + p = $$("a: 1, b: 0.5, c: null, d: whatever, e: true, f: false"); assertEquals(1, p.getInt("a")); assertEquals(0.5f, p.getFloat("b")); diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQuerySelectorsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQuerySelectorsTestGwt.java index 96cce2e4..efd8953d 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQuerySelectorsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQuerySelectorsTestGwt.java @@ -1,12 +1,12 @@ /* * 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 @@ -42,22 +42,22 @@ import com.google.gwt.user.client.ui.RootPanel; * Test for selectors */ public class GQuerySelectorsTestGwt extends GWTTestCase { - + boolean runSlow = false; protected interface ParentSelector extends Selectors { @Selector("#parent") GQuery parentSelector(); - + } - + protected interface ExtendedSelector extends ParentSelector { - + @Selector("#child") GQuery childSelector(); } - - + + protected interface AllSelectors extends Selectors { @Selector("h1[id]:contains(Selectors)") NodeList<Element> h1IdContainsSelectors(); @@ -160,7 +160,7 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { GQuery branchB(); @Selector(".branchB") GQuery branchB(Node n); - + @Selector("div .target") GQuery divTarget(); @Selector("div .target") @@ -186,7 +186,7 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { $(e).remove(); e = null; } - + public void gwtSetUp() { if (e == null) { testPanel = new HTML(); @@ -197,19 +197,19 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { e.setInnerHTML(""); } } - + public void testInhiterance(){ final ExtendedSelector selector = GWT.create(ExtendedSelector.class); - + $(e).html("<div id=\"parent\">parent<div id=\"child\">child</div></div>"); - + assertEquals(1, selector.parentSelector().length()); assertEquals(1, selector.childSelector().length()); - + assertEquals("parentchild", selector.parentSelector().text()); assertEquals("child", selector.childSelector().text()); } - + public void testJQueryPseudoselectors() { $(e).html("<table border=1 id=idtest width=440><tr><td width=50%>A Text</td><td width=50%><a></a><p id=a></p><p id=b style='display: none'><span id=c>s</span></p></td></tr></table>"); assertEquals(9, $("* ", e).size()); @@ -228,7 +228,7 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { // TODO: fix these selectors // sel.divWithClassNotContainsMadeup().getLength() // sel.divCommaPA().getLength() - + // assertArrayContains(sel.title().getLength(), 1); assertEquals(1, sel.body().getLength()); assertArrayContains(sel.bodyDiv().getLength(), 53, 55); @@ -270,13 +270,13 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { assertArrayContains(sel.ulTocline2().getLength(), 12); assertArrayContains(sel.ulTocLiTocLine2().getLength(), 12); } - + public void testIssue12() { $(e).html("<table><tr><td><p myCustomAttr='whatever'><input disabled='disabled' type='radio' name='wantedName' value='v1'>1</input></p><input type='radio' name='n' value='v2' checked='checked'>2</input></td><td><button myCustomAttr='val'>Click</button></tr><td></table>"); executeSelectInAllImplementations(":checked", e, 1); executeSelectInAllImplementations(":disabled", e, 1); executeSelectInAllImplementations("input:enabled", e, 1); -// FIXME, these two selectors fails in prod with chrome when using both Xpath engines +// FIXME, these two selectors fails in prod with chrome when using both Xpath engines // executeSelectInAllImplementations("[myCustomAttr]", e, 2); // executeSelectInAllImplementations("*[myCustomAttr]", e, 2); executeSelectInAllImplementations("input[name=wantedName]", e, 1); @@ -325,7 +325,7 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { SelectorEngineImpl selEng = new SelectorEngineXPath(); executeSelectorEngineTests(selEng); } - + public void testSelectorsGeneratorNative() { $(e).html( "<input type='radio' name='n' value='v1'>1</input>" @@ -334,17 +334,17 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { TestSelectors selectors = GWT.create(TestSelectors.class); assertEquals(1, selectors.allChecked().size()); } - + public void testSelectorsInIframe() { $(e).html("<iframe name='miframe' id='miframe' src=\"javascript:''\">"); Element d = $("#miframe").contents().empty().get(0); assertNotNull(d); - + $(d).html( "<div class='branchA'><div class='target'>branchA target</div></div>" + "<div class='branchB'><div class='target'>branchB target</div></div>"); - - + + executeSelectInAllImplementations(".branchA .target", d, 1, 2); //FIXME: executeSelectInAllImplementations(".branchA .target", body, 0); executeSelectInAllImplementations("div .target", d, 2); @@ -357,7 +357,7 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { assertEquals(0, selectors.divTarget().length()); } - + public void testSelectorsWithContext() { $(e).append( "<div class='branchA'><div class='target'>branchA target</div></div>" @@ -387,11 +387,11 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { assertEquals(1, selectors.target().length()); assertEquals("branchB target", selectors.target().text()); } - + public void testUnique() { SelectorEngineImpl selSizz = new SelectorEngineSizzleGwt(); $(e).html(getTestContent()); - + JsArray<Element> a; a = selSizz.select("p", e).cast(); int n = a.length(); @@ -403,46 +403,46 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { a = JsUtils.unique(a); assertEquals(n, a.length()); } - + public void testOddEvenNthChild(){ - + $(e).append( "<div id='parent'><div id='first' class='evenClass'>branchA target</div><div id='second' class='oddClass'>branchA target</div><div id='third' class='evenClass'>branchA target</div><div id='fourth' class='oddClass'>branchA target</div></div>"); - + GQuery odd = $("#parent > div:odd",e); assertEquals(2, odd.size()); for (Element el : odd.elements()){ assertEquals("oddClass", el.getClassName()); } - + GQuery even = $("#parent > div:even", e); assertEquals(2, even.size()); for (Element el : even.elements()){ assertEquals("evenClass", el.getClassName()); } - + //test filter odd = $("#parent > div",e).filter(":odd"); assertEquals(2, odd.size()); for (Element el : odd.elements()){ assertEquals("oddClass", el.getClassName()); } - + even = $("#parent > div", e).filter(":even"); assertEquals(2, even.size()); for (Element el : even.elements()){ assertEquals("evenClass", el.getClassName()); } - + //test nth-child GQuery second = $("#parent > div",e).filter(":nth-child(2)"); assertEquals(1, second.size()); assertEquals("second", second.attr("id")); - + GQuery third =$("#parent > div:nth-child(3)", e); assertEquals(1, third.size()); assertEquals("third", third.attr("id")); - + //test nth-child with function GQuery secondAndFourth = $("#parent > div",e).filter(":nth-child(2n)"); assertEquals(2, secondAndFourth.size()); @@ -450,11 +450,11 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { assertEquals("fourth", secondAndFourth.eq(1).attr("id")); } - + private void assertArrayContains(Object result, Object... array) { assertArrayContains("", result, array); } - + private void assertArrayContains(String message, Object result, Object... array) { String values = ""; boolean done = false; @@ -467,7 +467,7 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { message = message + ", value (" + result + ") not found in: " + values; assertTrue(message, done); } - + private void executeSelectInAllImplementations(String selector, Element elem, Object... array) { SelectorEngineImpl selSizz = new SelectorEngineSizzle(); SelectorEngineImpl selSizzGwt = new SelectorEngineSizzleGwt(); @@ -481,7 +481,7 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { assertArrayContains(selector + " - (selJS)", selJS.select(selector, elem).getLength(), array); if (hasNativeSelector()) { assertArrayContains(selector + " - (selNative)", selNative.select(selector, elem).getLength(), array); - } + } assertArrayContains(selector + " - (selXpath)", selXpath.select(selector, elem).getLength(), array); assertArrayContains(selector + " - (selC2X)", selC2X.select(selector, elem).getLength(), array); } @@ -491,7 +491,7 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { assertArrayContains(selEng.select("body", document).getLength(), 1); assertArrayContains(selEng.select("body div", document).getLength(), 53, 55); - + assertArrayContains(selEng.select("tr:first", e).getLength(), 0, 1, 5); assertArrayContains(selEng.select("tr:last", e).getLength(), 0, 1, 5); assertArrayContains(selEng.select("p:contains(selectors)", e).getLength(), 54); @@ -531,7 +531,7 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { assertArrayContains(selEng.select("#title", e).getLength(), 1); // TODO: sizze_gwt returns 2 assertArrayContains(selEng.select("#title, h1#title", e).getLength(), 1, 2); - assertArrayContains(selEng.select("ul.toc li.tocline2", e).getLength(), 12); + assertArrayContains(selEng.select("ul.toc li.tocline2", e).getLength(), 12); assertArrayContains(selEng.select("h1[id]:contains(Selectors)", e).getLength(), 1); } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryWidgetsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryWidgetsTestGwt.java index 5946ed90..c5399e83 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryWidgetsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryWidgetsTestGwt.java @@ -1,12 +1,12 @@ /* * 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 @@ -52,17 +52,17 @@ public class GQueryWidgetsTestGwt extends GWTTestCase { Button b = new Button("test"); RootPanel.get().add(b); RootPanel.get().add(p); - + int nitems = 4; final String label1 = "I'm the label "; final String label2 = "Finally I'm just a simple label"; - + for (int i = 0; i < nitems; i++) { Label l = new Label(label1 + i); p.add(l); } $("<div>whatever</div").appendTo($(p)); - + b.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { $(".gwt-Label", p).each(new Function() { @@ -74,7 +74,7 @@ public class GQueryWidgetsTestGwt extends GWTTestCase { }); } }); - + $(".gwt-Label", p).each(new Function() { @Override public Object f(Widget w, int i) { @@ -82,7 +82,7 @@ public class GQueryWidgetsTestGwt extends GWTTestCase { return null; } }); - + $(b).click(); $(".gwt-Label", p).each(new Function() { @@ -90,7 +90,7 @@ public class GQueryWidgetsTestGwt extends GWTTestCase { assertEquals(label2, $(e).text()); } }); - + $("div", p).each(new Function() { public void f(Element e) { // Just to avoid the exception when non-widget elements match @@ -101,11 +101,11 @@ public class GQueryWidgetsTestGwt extends GWTTestCase { } } }); - + p.removeFromParent(); b.removeFromParent(); } - + class TestButtonWidgetFactory implements WidgetFactory<Button> { public Button create(Element e) { Button button = new Button(); @@ -114,14 +114,14 @@ public class GQueryWidgetsTestGwt extends GWTTestCase { return button; } } - + public void testGQueryWidgets() { final Button b1 = new Button("click-me"); RootPanel.get().add(b1); GQuery g = $(b1); Button b2 = (Button) g.as(Widgets.Widgets).widget(); assertEquals(b1, b2); - + b2 = $("<button>Click-me</button>").appendTo(document) .as(Widgets.Widgets).widgets(new TestButtonWidgetFactory(), null).widget(); b2.addClickHandler(new ClickHandler() { @@ -129,7 +129,7 @@ public class GQueryWidgetsTestGwt extends GWTTestCase { $(b1).css("color", "red"); } }); - + b2.click(); assertEquals("red", $(b1).css("color", false)); } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/JreQueryCoreTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/JreQueryCoreTest.java index 41aabee6..af755243 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/JreQueryCoreTest.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/JreQueryCoreTest.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTest.java index a3422438..2f1171c1 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTest.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTest.java @@ -1,12 +1,12 @@ /* * 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 @@ -22,62 +22,62 @@ import com.google.gwt.query.rebind.SelectorGeneratorCssToXPath; * Test for selector engine implementations */ public class SelectorEnginesTest extends GWTTestCase { - + public String getModuleName() { return null; } - + public void testCssToXpath() { SelectorEngineCssToXPath sel = new SelectorEngineCssToXPath(); - + if (getModuleName() == null) { sel = new SelectorEngineCssToXPath(SelectorEngineCssToXPath.replacerGwt); } - - - assertEquals(".//div[starts-with(@class,'exa') and (substring(@class,string-length(@class)-3)='mple')]", + + + assertEquals(".//div[starts-with(@class,'exa') and (substring(@class,string-length(@class)-3)='mple')]", sel.css2Xpath("div[class^=exa][class$=mple]")); assertEquals(".//div[not(contains(concat(' ',normalize-space(@class),' '),' example '))]", sel.css2Xpath("div:not(.example)")); - - assertEquals(".//p", + + assertEquals(".//p", sel.css2Xpath("p:nth-child(n)")); - assertEquals(".//p[(count(preceding-sibling::*) + 1) mod 2=1]", + assertEquals(".//p[(count(preceding-sibling::*) + 1) mod 2=1]", sel.css2Xpath("p:nth-child(odd)")); - assertEquals(".//*[(position()-0) mod 2=0 and position()>=0]/self::p", + assertEquals(".//*[(position()-0) mod 2=0 and position()>=0]/self::p", sel.css2Xpath("p:nth-child(2n)")); - - assertEquals(".//div[substring(@class,string-length(@class)-3)='mple']", + + assertEquals(".//div[substring(@class,string-length(@class)-3)='mple']", sel.css2Xpath("div[class$=mple]")); - assertEquals(".//div[substring(@class,string-length(@class)-5)='xample']", + assertEquals(".//div[substring(@class,string-length(@class)-5)='xample']", sel.css2Xpath("div[class$=xample]")); - - assertEquals(".//div[not(contains(concat(' ',normalize-space(@class),' '),' example '))]", + + assertEquals(".//div[not(contains(concat(' ',normalize-space(@class),' '),' example '))]", sel.css2Xpath("div:not(.example)")); - assertEquals(".//*", + assertEquals(".//*", sel.css2Xpath("*")); - - assertEquals(".//input[@checked='checked']", + + assertEquals(".//input[@checked='checked']", sel.css2Xpath("input:checked")); - assertEquals(".//*[@myAttr]", + assertEquals(".//*[@myAttr]", sel.css2Xpath("[myAttr]")); - assertEquals(".//tag[@myAttr='abcd']", + assertEquals(".//tag[@myAttr='abcd']", sel.css2Xpath("tag[myAttr=abcd]")); - - assertEquals(".//a[@href and (@lang) and (@class)]", + + assertEquals(".//a[@href and (@lang) and (@class)]", sel.css2Xpath("a[href][lang][class]")); - - assertEquals(".//*[@checked='checked']|.//*[not(@disabled)]|.//*[@disabled]", + + assertEquals(".//*[@checked='checked']|.//*[not(@disabled)]|.//*[@disabled]", sel.css2Xpath(":checked, :enabled, :disabled")); - - assertEquals(".//table[contains(string(.),'String With | @ ~= Space Points.s and Hash#es')]", + + assertEquals(".//table[contains(string(.),'String With | @ ~= Space Points.s and Hash#es')]", sel.css2Xpath("table:contains('String With | @ ~= Space Points.s and Hash#es')")); - - assertEquals(".//div[@class='comment' and (contains(string(.),'John'))]", - sel.css2Xpath("div[@class='comment']:contains('John')")); + + assertEquals(".//div[@class='comment' and (contains(string(.),'John'))]", + sel.css2Xpath("div[@class='comment']:contains('John')")); } } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTestGwt.java index 8ff63a51..57c7749a 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTestGwt.java @@ -1,12 +1,12 @@ /* * 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 @@ -20,7 +20,7 @@ package com.google.gwt.query.client.impl; * Test for selector engine implementations run in gwt */ public class SelectorEnginesTestGwt extends SelectorEnginesTest { - + @Override public String getModuleName() { return "com.google.gwt.query.Query"; diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/rebind/SelectorGeneratorsTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/rebind/SelectorGeneratorsTest.java index 5830e9ec..d5900b59 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/rebind/SelectorGeneratorsTest.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/rebind/SelectorGeneratorsTest.java @@ -1,12 +1,12 @@ /* * 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 @@ -29,9 +29,9 @@ import com.google.gwt.query.client.impl.SelectorEngineCssToXPath.ReplaceCallback public class SelectorGeneratorsTest extends GWTTestCase { public String getModuleName() { - return null; + return null; } - + public void assertReplacers(String s) { Object[] regs = SelectorEngineCssToXPath.regs; String r1 = s, r2 = s; @@ -42,71 +42,71 @@ public class SelectorGeneratorsTest extends GWTTestCase { } assertEquals(r1, r2); } - + public void testReplacers() { assertReplacers("table:contains('String With | @ ~= Space Points.s and Hash#es')"); } - + public void testCss2Xpath() throws Exception { - + SelectorGeneratorCssToXPath sel = new SelectorGeneratorCssToXPath(); - - assertEquals(".//div[starts-with(@class,'exa') and (substring(@class,string-length(@class)-3)='mple')]", + + assertEquals(".//div[starts-with(@class,'exa') and (substring(@class,string-length(@class)-3)='mple')]", sel.css2Xpath("div[class^=exa][class$=mple]")); assertEquals(".//div[not(contains(concat(' ',normalize-space(@class),' '),' example '))]", sel.css2Xpath("div:not(.example)")); - - assertEquals(".//p", + + assertEquals(".//p", sel.css2Xpath("p:nth-child(n)")); - assertEquals(".//p[(count(preceding-sibling::*) + 1) mod 2=1]", + assertEquals(".//p[(count(preceding-sibling::*) + 1) mod 2=1]", sel.css2Xpath("p:nth-child(odd)")); - assertEquals(".//*[(position()-0) mod 2=0 and position()>=0]/self::p", + assertEquals(".//*[(position()-0) mod 2=0 and position()>=0]/self::p", sel.css2Xpath("p:nth-child(2n)")); - - assertEquals(".//div[substring(@class,string-length(@class)-3)='mple']", + + assertEquals(".//div[substring(@class,string-length(@class)-3)='mple']", sel.css2Xpath("div[class$=mple]")); - assertEquals(".//div[substring(@class,string-length(@class)-5)='xample']", + assertEquals(".//div[substring(@class,string-length(@class)-5)='xample']", sel.css2Xpath("div[class$=xample]")); - - assertEquals(".//div[not(contains(concat(' ',normalize-space(@class),' '),' example '))]", + + assertEquals(".//div[not(contains(concat(' ',normalize-space(@class),' '),' example '))]", sel.css2Xpath("div:not(.example)")); - assertEquals(".//*", + assertEquals(".//*", sel.css2Xpath("*")); - - assertEquals(".//input[@checked='checked']", + + assertEquals(".//input[@checked='checked']", sel.css2Xpath("input:checked")); - assertEquals(".//*[@myAttr]", + assertEquals(".//*[@myAttr]", sel.css2Xpath("[myAttr]")); - assertEquals(".//tag[@myAttr='abcd']", + assertEquals(".//tag[@myAttr='abcd']", sel.css2Xpath("tag[myAttr=abcd]")); - - assertEquals(".//a[@href and (@lang) and (@class)]", + + assertEquals(".//a[@href and (@lang) and (@class)]", sel.css2Xpath("a[href][lang][class]")); - - assertEquals(".//*[@checked='checked']|.//*[not(@disabled)]|.//*[@disabled]", + + assertEquals(".//*[@checked='checked']|.//*[not(@disabled)]|.//*[@disabled]", sel.css2Xpath(":checked, :enabled, :disabled")); - - assertEquals(".//table[contains(string(.),'#String With | @ ~= Space Points.s and Hash#es#')]", + + assertEquals(".//table[contains(string(.),'#String With | @ ~= Space Points.s and Hash#es#')]", sel.css2Xpath("table:contains('#String With | @ ~= Space Points.s and Hash#es#')")); - - assertEquals(".//div[@class='comment' and (contains(string(.),'John'))]", + + assertEquals(".//div[@class='comment' and (contains(string(.),'John'))]", sel.css2Xpath("div[@class='comment']:contains('John')")); } public void testReplaceAll() { - assertEquals("<img src='thumbs/01'/> <img src='thumbs/03'/>", + assertEquals("<img src='thumbs/01'/> <img src='thumbs/03'/>", SelectorEngineCssToXPath.replacerGwt.replaceAll("/[thumb01]/ /[thumb03]/", "/\\[thumb(\\d+)\\]/", new ReplaceCallback() { public String foundMatch(ArrayList<String>s) { return "<img src='thumbs/" + s.get(1) + "'/>"; } })); } - + public void testValidation() throws XPathExpressionException { SelectorGeneratorCssToXPath sel = new SelectorGeneratorCssToXPath(); sel.validateXpath(sel.css2Xpath("path[to=1428],#from-1428")); diff --git a/jsquery/src/main/java/com/google/gwt/query/jsquery/JsQueryApi.gwt.xml b/jsquery/src/main/java/com/google/gwt/query/jsquery/JsQueryApi.gwt.xml index e30aed82..3ed71f16 100644 --- a/jsquery/src/main/java/com/google/gwt/query/jsquery/JsQueryApi.gwt.xml +++ b/jsquery/src/main/java/com/google/gwt/query/jsquery/JsQueryApi.gwt.xml @@ -1,27 +1,27 @@ <!-- - This Module creates a javascript library able to replace jquery.js + This Module creates a javascript library able to replace jquery.js --> <module rename-to='jsquery'> <inherits name='com.google.gwt.query.jsquery.JsQuery' /> - + <entry-point class="com.google.gwt.query.jsquery.client.JsQueryApi" /> <!-- Minimize JS --> <set-property name="compiler.stackMode" value="strip"/> - <!-- cross-site --> + <!-- cross-site --> <add-linker name="xsiframe"/> - - <!-- + + <!-- Hack to put code into the jsquery.nocache.js so as $ is available early - and we can handle the $().ready method which is widely used in jquery pages. + and we can handle the $().ready method which is widely used in jquery pages. Otherwise $ wont be available until the async loading of the gwt permutation - which happens after the page was ready. + which happens after the page was ready. --> <define-property name="onload" values="default, foo"/> <property-provider name="onload"> <![CDATA[ - $wnd.JsQuery = { + $wnd.JsQuery = { onLoadArray: [], onLoad: function() { for (i in $wnd.JsQuery.onLoadArray) diff --git a/jsquery/src/main/java/com/google/gwt/query/jsquery/client/GQueryOverlay.java b/jsquery/src/main/java/com/google/gwt/query/jsquery/client/GQueryOverlay.java index a48266c5..88a7acde 100644 --- a/jsquery/src/main/java/com/google/gwt/query/jsquery/client/GQueryOverlay.java +++ b/jsquery/src/main/java/com/google/gwt/query/jsquery/client/GQueryOverlay.java @@ -27,18 +27,18 @@ import com.google.gwt.user.client.Event; /** * Class used to expose GQuery methods and object to Javascript using * gwt-exporter annotations. - * + * * We prefer to overlay the original GQuery object instead of adding * the gwt-exporter dependency to the project. - * - * Because of the differences between java and js apis, we need to - * override some methods in order to deal with complex cases. + * + * Because of the differences between java and js apis, we need to + * override some methods in order to deal with complex cases. * */ @ExportPackage("JsQuery") @Export(value="fn", all=false) public class GQueryOverlay implements ExportOverlay<GQuery> { - + @ExportPackage("JsQuery") @Export("jFunction") @ExportClosure() @@ -54,7 +54,7 @@ public class GQueryOverlay implements ExportOverlay<GQuery> { public interface PredicateOverlay extends ExportOverlay<Predicate> { public boolean f(Element e, int i); } - + private GQueryOverlay(){} /** @@ -64,7 +64,7 @@ public class GQueryOverlay implements ExportOverlay<GQuery> { */ @ExportJsInitMethod public NodeList<Element> get() {return null;} - + /** * Customized JS code to execute after GQuery has been exported. */ @@ -74,7 +74,7 @@ public class GQueryOverlay implements ExportOverlay<GQuery> { window = $wnd; document = $doc; }-*/; - + @ExportStaticMethod("$wnd.$") public static GQuery $(Object o) { return GQuery.$(o); @@ -84,7 +84,7 @@ public class GQueryOverlay implements ExportOverlay<GQuery> { public static GQuery $(String s, Element ctx) { return GQuery.$(s, ctx); } - + @ExportStaticMethod("$wnd.$.extend") public static JavaScriptObject extend(Object...objs) { return JsQueryUtils.extend(objs); @@ -94,17 +94,17 @@ public class GQueryOverlay implements ExportOverlay<GQuery> { public static JavaScriptObject[] each(JavaScriptObject[] objs, Function f) { return JsQueryUtils.each(objs, f); } - + @ExportStaticMethod("$wnd.$.inArray") public static int inArray(Object o, Object arr) { return JsQueryUtils.inArray(o, arr); } - + @ExportStaticMethod("$wnd.$.isArray") public static boolean isArray(JavaScriptObject o) { return JsUtils.isArray(o); - } - + } + @ExportInstanceMethod public static GQuery ready(GQuery g, Function f) { f.fe(); @@ -115,11 +115,11 @@ public class GQueryOverlay implements ExportOverlay<GQuery> { // TODO: normally plugins adds new easing functions to jquery.easing array public static GQuery animate(GQuery g, Object stringOrProperties, int duration, String easing, Function... funcs) { return g.animate(stringOrProperties, duration, - "linear".equalsIgnoreCase(easing) + "linear".equalsIgnoreCase(easing) ? PropertiesAnimation.Easing.LINEAR : PropertiesAnimation.Easing.SWING, funcs); } - + @ExportInstanceMethod public static Object css(GQuery g, Object o) { if (o instanceof String) { @@ -133,18 +133,18 @@ public class GQueryOverlay implements ExportOverlay<GQuery> { public static GQuery css(GQuery g, String k, Object v) { return g.css(k, String.valueOf(v)); } - + @ExportInstanceMethod public static JavaScriptObject offset(GQuery instance) { Offset o = instance.offset(); return Properties.create("left: " + o.left + ", top:" + o.top); } - + @ExportInstanceMethod public static GQuery unbind(GQuery g, String s, Function o) { return g.unbind(s); } - + public String toString() {return null;} public GQuery add(GQuery previousObject) {return null;} public GQuery add(String selector) {return null;} @@ -153,7 +153,7 @@ public class GQueryOverlay implements ExportOverlay<GQuery> { public GQuery after(Node n) {return null;} public GQuery after(String html) {return null;} public GQuery andSelf() {return null;} - + // public GQuery animate(Object stringOrProperties, int duration, Easing easing, Function... funcs) {return null;} public GQuery animate(Object stringOrProperties, Function... funcs) {return null;} public GQuery animate(Object stringOrProperties, int duration, Function... funcs) {return null;} @@ -184,7 +184,7 @@ public class GQueryOverlay implements ExportOverlay<GQuery> { public GQuery change(Function... f) {return null;} public GQuery children() {return null;} public GQuery children(String... filters) {return null;} - public GQuery clearQueue() {return null;} + public GQuery clearQueue() {return null;} public GQuery clone() {return null;} public GQuery clearQueue(String queueName) {return null;} public GQuery click(Function... f) {return null;} @@ -204,7 +204,7 @@ public class GQueryOverlay implements ExportOverlay<GQuery> { // public <T> T data(String name, Class<T> clz) {return null;} public GQuery data(String name, Object value) {return null;} public GQuery dblclick(Function... f) {return null;} - + @ExportInstanceMethod public static GQuery delay(GQuery g, int milliseconds) { System.out.println("DDDDD"); diff --git a/jsquery/src/main/java/com/google/gwt/query/jsquery/client/JsQuery.java b/jsquery/src/main/java/com/google/gwt/query/jsquery/client/JsQuery.java index 6afe7f55..9211b0f8 100644 --- a/jsquery/src/main/java/com/google/gwt/query/jsquery/client/JsQuery.java +++ b/jsquery/src/main/java/com/google/gwt/query/jsquery/client/JsQuery.java @@ -8,7 +8,7 @@ import com.google.gwt.query.jsquery.client.GQueryOverlay.FunctionOverlay; import com.google.gwt.query.jsquery.client.GQueryOverlay.PredicateOverlay; public class JsQuery implements EntryPoint { - + public void onModuleLoad() { GWT.setUncaughtExceptionHandler(new GWT.UncaughtExceptionHandler() { Logger l = Logger.getLogger("JsQuery"); @@ -19,26 +19,26 @@ public class JsQuery implements EntryPoint { } l.info(r); } - }); - // We just export the api, but we do not call GQueryOverlay.onLoad() so as + }); + // We just export the api, but we do not call GQueryOverlay.onLoad() so as // apps and plugins could load their stuff before calling it export(); - + // Un comment for testing stuff below // testJs(); } - + public static void export() { GWT.create(FunctionOverlay.class); GWT.create(PredicateOverlay.class); GWT.create(GQueryOverlay.class); } - + public static native void onLoad() /*-{ $wnd.onJsQueryLoad && $wnd.onJsQueryLoad(); $wnd.JsQuery && $wnd.JsQuery.onLoad && $wnd.JsQuery.onLoad(); }-*/; - + /** * Used to paste jquery code and test it in dev mode */ @@ -47,8 +47,8 @@ public class JsQuery implements EntryPoint { window = $wnd; document = $doc; $ = $wnd.$; - + // Paste jquery code here - + }-*/; } diff --git a/jsquery/src/main/java/com/google/gwt/query/jsquery/client/JsQueryApi.java b/jsquery/src/main/java/com/google/gwt/query/jsquery/client/JsQueryApi.java index 2e466a93..1b74ebb7 100644 --- a/jsquery/src/main/java/com/google/gwt/query/jsquery/client/JsQueryApi.java +++ b/jsquery/src/main/java/com/google/gwt/query/jsquery/client/JsQueryApi.java @@ -3,7 +3,7 @@ package com.google.gwt.query.jsquery.client; import com.google.gwt.core.client.EntryPoint; public class JsQueryApi implements EntryPoint { - + public void onModuleLoad() { JsQuery.onLoad(); } diff --git a/jsquery/src/main/java/com/google/gwt/query/jsquery/client/JsQueryUtils.java b/jsquery/src/main/java/com/google/gwt/query/jsquery/client/JsQueryUtils.java index b84d86b4..94bf4c3b 100644 --- a/jsquery/src/main/java/com/google/gwt/query/jsquery/client/JsQueryUtils.java +++ b/jsquery/src/main/java/com/google/gwt/query/jsquery/client/JsQueryUtils.java @@ -15,7 +15,7 @@ import com.google.gwt.query.client.js.JsUtils; /** * These are a set of utility methods needed in jsquery because * either they are not in the GQuery core yet, or they are already - * there but we need to modify their behavior. + * there but we need to modify their behavior. * Most of them should be moved to the GQuery core api. * */ @@ -35,7 +35,7 @@ public abstract class JsQueryUtils { public static void ready(Function f) { f.f(); } - + public static int inArray(Object object, Object array) { if (array instanceof List) { return ((List<?>)array).indexOf(object); @@ -75,7 +75,7 @@ public abstract class JsQueryUtils { } private static native JavaScriptObject getDefaultPrototype() /*-{ - return $wnd.JsQuery && $wnd.JsQuery.fn + return $wnd.JsQuery && $wnd.JsQuery.fn ? $wnd.JsQuery.fn.prototype : null; }-*/; @@ -90,7 +90,7 @@ public abstract class JsQueryUtils { } return d; }-*/; - + public static JavaScriptObject[] each(JavaScriptObject[] objs, Function f) { ArrayList<Object> ret = new ArrayList<Object>(); for (Object o : objs) { diff --git a/jsquery/src/main/java/com/google/gwt/query/jsquery/public/JsQuery.html b/jsquery/src/main/java/com/google/gwt/query/jsquery/public/JsQuery.html index 59877b4d..21ca8aa1 100644 --- a/jsquery/src/main/java/com/google/gwt/query/jsquery/public/JsQuery.html +++ b/jsquery/src/main/java/com/google/gwt/query/jsquery/public/JsQuery.html @@ -14,7 +14,7 @@ if (window.$) { $(document).ready(onJsQueryLoad); onJsQueryLoad = null; - } + } </script> </body> </html> diff --git a/jsquery/src/main/java/gwtquery/jsplugins/menu/JsQueryMenu.gwt.xml b/jsquery/src/main/java/gwtquery/jsplugins/menu/JsQueryMenu.gwt.xml index 81153c56..a43e6e2c 100644 --- a/jsquery/src/main/java/gwtquery/jsplugins/menu/JsQueryMenu.gwt.xml +++ b/jsquery/src/main/java/gwtquery/jsplugins/menu/JsQueryMenu.gwt.xml @@ -1,7 +1,7 @@ <module rename-to='jsmenu'> <inherits name='com.google.gwt.query.jsquery.JsQuery' /> <entry-point class="gwtquery.jsplugins.menu.client.JsQueryMenu" /> - - + + </module> diff --git a/jsquery/src/main/java/gwtquery/jsplugins/menu/client/JsMenu.java b/jsquery/src/main/java/gwtquery/jsplugins/menu/client/JsMenu.java index 0977f6ce..5b0fd38d 100644 --- a/jsquery/src/main/java/gwtquery/jsplugins/menu/client/JsMenu.java +++ b/jsquery/src/main/java/gwtquery/jsplugins/menu/client/JsMenu.java @@ -1,20 +1,20 @@ package gwtquery.jsplugins.menu.client; /** - * + * * This class wraps the jquery menu plugin from: - * + * * http://p.sohei.org/jquery-plugins/menu/ * */ public abstract class JsMenu { - + public static native void loadPlugin() /*-{ var l = @com.google.gwt.query.jsquery.client.JsQueryUtils::log(Ljava/lang/Object;); var window = $wnd; var document = $doc; var jQuery = $wnd.$; - + (function($) { var menus = [], //list of all menus @@ -40,20 +40,20 @@ public abstract class JsMenu { onClick: null, arrowSrc: null, addExpando: false, - + // $.fn.menuFromElement options copyClassAttr: false }; - + $(function(){ $rootDiv.appendTo('body'); }); $.extend({ MenuCollection : function(items) { - + this.menus = []; - + this.init(items); } }); @@ -74,9 +74,9 @@ public abstract class JsMenu { { if ( menu instanceof $.Menu ) this.menus.push(menu); - + menu.menuCollection = this; - + var self = this; $(menu.target).hover(function(){ if ( menu.visible ) @@ -124,7 +124,7 @@ public abstract class JsMenu { //the user clicked on the target of the currenty open menu if ( visibleMenus.length && t == visibleMenus[0].target ) return; - + //get the last node before the #root-menu-div while ( t.parentNode && t.parentNode != $rootDiv[0] ) t = t.parentNode; @@ -332,8 +332,8 @@ public abstract class JsMenu { { if ( !this.visible ) return; - - var i, + + var i, pos = $.inArray(this, visibleMenus); this.$eDIV.hide(); @@ -362,7 +362,7 @@ public abstract class JsMenu { if ( activeMenu == this ) activeMenu = null; - + if ( this.settings.onClose ) this.settings.onClose.call(this); }, @@ -371,7 +371,7 @@ public abstract class JsMenu { if ( this.visible ) return; - var zi, + var zi, pmi = this.parentMenuItem; if ( this.menuItems.length ) //show only when it has items @@ -389,7 +389,7 @@ public abstract class JsMenu { if ( this.$eDIV.width() < this.settings.minWidth ) this.$eDIV.css('width', this.settings.minWidth); } - + this.setPosition(); this.$eDIV.css({display:'none', visibility: ''}).show(); @@ -400,7 +400,7 @@ public abstract class JsMenu { if ( this.settings.onOpen ) this.settings.onOpen.call(this); } - + if ( visibleMenus.length == 0 ) $(document).bind('mousedown', $.Menu.checkMouse).bind('keydown', $.Menu.checkKey); @@ -409,11 +409,11 @@ public abstract class JsMenu { }, setPosition : function() { - var $t, o, posX, posY, + var $t, o, posX, posY, pmo, //parent menu offset wst, //window scroll top wsl, //window scroll left - ww = $(window).width(), + ww = $(window).width(), wh = $(window).height(), pmi = this.parentMenuItem, height = this.$eDIV[0].clientHeight, @@ -432,7 +432,7 @@ public abstract class JsMenu { //position right below the target $t = $(this.target); o = $t.offset(); - + posX = o.left + this.settings.offsetLeft; posY = o.top + $t.height() + this.settings.offsetTop; } @@ -536,7 +536,7 @@ public abstract class JsMenu { var i, pos = 0, mil = this.menuItems.length, o = offset || 1; - + //get current pos for ( i = 0; i < mil; i++ ) { @@ -593,7 +593,7 @@ public abstract class JsMenu { if ( (pos = $.inArray(this, this.menuCollection.menus)) > -1 ) this.menuCollection.menus.splice(pos, 1); } - + this.$eDIV.remove(); } } @@ -620,7 +620,7 @@ public abstract class JsMenu { this.separator = false; this.init(); - + if ( obj.subMenu ) new $.Menu(this, obj.subMenu, options); } @@ -633,14 +633,14 @@ public abstract class JsMenu { var i, isStr, src = this.src, self = this; - + this.$eLI = $(menuItemElement.cloneNode(1)); if ( this.addClass ) this.$eLI[0].setAttribute('class', this.addClass); if ( this.settings.addExpando && this.data ) this.$eLI[0].menuData = this.data; - + if ( src == '' ) { this.$eLI.addClass('menu-separator'); @@ -692,7 +692,7 @@ public abstract class JsMenu { { this.removeTimer(); - var i, + var i, pms = this.parentMenu.subMenus, pmi = this.parentMenu.menuItems, self = this; @@ -703,7 +703,7 @@ public abstract class JsMenu { if ( !this.enabled ) return; - + //deactivate all menuItems on the same level for ( i = 0; i < pmi.length; i++ ) { @@ -737,7 +737,7 @@ public abstract class JsMenu { if ( !this.enabled ) return; - + if ( !this.subMenu || !this.subMenu.visible ) this.setInactive(); }, @@ -809,17 +809,17 @@ public abstract class JsMenu { } } }); - - + + $.extend($.fn, { menuFromElement : function(options, list, bar) { var createItems = function(ul) { - var menuItems = [], + var menuItems = [], subItems, menuItem, - lis, $li, i, subUL, submenu, target, + lis, $li, i, subUL, submenu, target, classNames = null; lis = getAllChilds(ul, 'LI'); @@ -846,17 +846,17 @@ public abstract class JsMenu { target = $li[0].childNodes[0].nodeValue; else target = $li[0].childNodes; - + if ( options && options.copyClassAttr ) classNames = $li.attr('class'); - + //create item menuItem = new $.MenuItem({src: target, addClass: classNames}, options); menuItems.push(menuItem); //add submenu if ( subItems.length ) new $.Menu(menuItem, subItems, options); - + } return menuItems; }; @@ -917,7 +917,7 @@ public abstract class JsMenu { return null; var n = elem.firstChild; - for ( ; n; n = n.nextSibling ) + for ( ; n; n = n.nextSibling ) { if ( n.nodeType == 1 && n.nodeName.toUpperCase() == name ) return n; @@ -932,7 +932,7 @@ public abstract class JsMenu { var r = [], n = elem.firstChild; - for ( ; n; n = n.nextSibling ) + for ( ; n; n = n.nextSibling ) { if ( n.nodeType == 1 && n.nodeName.toUpperCase() == name ) r[r.length] = n; @@ -941,6 +941,6 @@ public abstract class JsMenu { }; })(jQuery); - + }-*/; } diff --git a/jsquery/src/main/java/gwtquery/jsplugins/menu/client/JsQueryMenu.java b/jsquery/src/main/java/gwtquery/jsplugins/menu/client/JsQueryMenu.java index 438075d2..ef720b65 100644 --- a/jsquery/src/main/java/gwtquery/jsplugins/menu/client/JsQueryMenu.java +++ b/jsquery/src/main/java/gwtquery/jsplugins/menu/client/JsQueryMenu.java @@ -4,7 +4,7 @@ import com.google.gwt.core.client.EntryPoint; import com.google.gwt.query.jsquery.client.JsQuery; public class JsQueryMenu implements EntryPoint { - + public void onModuleLoad() { JsMenu.loadPlugin(); JsQuery.onLoad(); diff --git a/jsquery/src/main/java/gwtquery/jsplugins/menu/public/demo.html b/jsquery/src/main/java/gwtquery/jsplugins/menu/public/demo.html index 1e55c326..fe851bef 100644 --- a/jsquery/src/main/java/gwtquery/jsplugins/menu/public/demo.html +++ b/jsquery/src/main/java/gwtquery/jsplugins/menu/public/demo.html @@ -84,7 +84,7 @@ if (window.$) { <h1>Example one:</h1> <ul> <li>create a menubar from an unordered list</li> - <li>used on an unordered list, the plugin takes its direct <li>-children, which will be the root items (File, Edit...), + <li>used on an unordered list, the plugin takes its direct <li>-children, which will be the root items (File, Edit...), and searches each for an <ul>-child, which holds the menu-items (New window, Save, Print...).</li> <li>empty <li>-elements are used as seperators</li> </ul> @@ -188,7 +188,7 @@ if (window.$) { <div class="codeheader">JavaScript code:</div> <pre name="code" class="JScript"> var options = {minWidth: 120, arrowSrc: 'arrow_right.gif'}; - var items = [ {src: 'test', url:'http://www.jquery.com'}, + var items = [ {src: 'test', url:'http://www.jquery.com'}, {src: ''}, /* separator */ {src: 'test2', subMenu: [ {src: 'sub 1'}, {src: 'sub 2', url: 'http://p.sohei.org', target: '_blank'}, @@ -308,7 +308,7 @@ if (window.$) { <div class="codeheader">HTML markup:</div> <pre name="code" class="html"> <p id="menufive">Menu Button <img src="arrowdown.png" /> - Menu Button <img src="arrowdown.png" /> - Menu Button <img src="arrowdown.png" /></p> - + <ul id="menufivelist" style="display:none;"> <li>one</li> <li class="red">two</li> diff --git a/samples/src/main/java/gwtquery/samples/GwtQueryBench.gwt.xml b/samples/src/main/java/gwtquery/samples/GwtQueryBench.gwt.xml index 48603d99..2c42b543 100644 --- a/samples/src/main/java/gwtquery/samples/GwtQueryBench.gwt.xml +++ b/samples/src/main/java/gwtquery/samples/GwtQueryBench.gwt.xml @@ -3,4 +3,4 @@ <entry-point class='gwtquery.samples.client.GwtQueryBenchModule'/> <inherits name="com.google.gwt.precompress.Precompress"/> </module> - + diff --git a/samples/src/main/java/gwtquery/samples/GwtQueryDemo.gwt.xml b/samples/src/main/java/gwtquery/samples/GwtQueryDemo.gwt.xml index d4456538..d02d8034 100644 --- a/samples/src/main/java/gwtquery/samples/GwtQueryDemo.gwt.xml +++ b/samples/src/main/java/gwtquery/samples/GwtQueryDemo.gwt.xml @@ -2,4 +2,4 @@ <inherits name='com.google.gwt.query.Query'/> <entry-point class='gwtquery.samples.client.GwtQueryDemoModule'/> </module> - + diff --git a/samples/src/main/java/gwtquery/samples/GwtQueryEffects.gwt.xml b/samples/src/main/java/gwtquery/samples/GwtQueryEffects.gwt.xml index 39578f05..cdab49b2 100644 --- a/samples/src/main/java/gwtquery/samples/GwtQueryEffects.gwt.xml +++ b/samples/src/main/java/gwtquery/samples/GwtQueryEffects.gwt.xml @@ -2,4 +2,4 @@ <inherits name='com.google.gwt.query.Query'/> <entry-point class='gwtquery.samples.client.GwtQueryEffectsModule'/> </module> - + diff --git a/samples/src/main/java/gwtquery/samples/GwtQueryEffectsMin.gwt.xml b/samples/src/main/java/gwtquery/samples/GwtQueryEffectsMin.gwt.xml index ee40909c..ef8aae4d 100644 --- a/samples/src/main/java/gwtquery/samples/GwtQueryEffectsMin.gwt.xml +++ b/samples/src/main/java/gwtquery/samples/GwtQueryEffectsMin.gwt.xml @@ -2,4 +2,4 @@ <inherits name='com.google.gwt.query.QueryMin'/> <entry-point class='gwtquery.samples.client.GwtQueryEffectsModule'/> </module> - + diff --git a/samples/src/main/java/gwtquery/samples/GwtQueryImageZoom.gwt.xml b/samples/src/main/java/gwtquery/samples/GwtQueryImageZoom.gwt.xml index 25bf3507..ebd60404 100644 --- a/samples/src/main/java/gwtquery/samples/GwtQueryImageZoom.gwt.xml +++ b/samples/src/main/java/gwtquery/samples/GwtQueryImageZoom.gwt.xml @@ -4,4 +4,4 @@ <add-linker name="xsiframe"/> <set-property name="compiler.stackMode" value="strip"/> </module> - + diff --git a/samples/src/main/java/gwtquery/samples/GwtQuerySample.gwt.xml b/samples/src/main/java/gwtquery/samples/GwtQuerySample.gwt.xml index af51bf7d..9d9e147f 100644 --- a/samples/src/main/java/gwtquery/samples/GwtQuerySample.gwt.xml +++ b/samples/src/main/java/gwtquery/samples/GwtQuerySample.gwt.xml @@ -2,4 +2,4 @@ <inherits name='com.google.gwt.query.Query'/> <entry-point class='gwtquery.samples.client.GwtQuerySampleModule'/> </module> - + diff --git a/samples/src/main/java/gwtquery/samples/client/AnimationsSample.java b/samples/src/main/java/gwtquery/samples/client/AnimationsSample.java index be1e1ec1..d70235c2 100644 --- a/samples/src/main/java/gwtquery/samples/client/AnimationsSample.java +++ b/samples/src/main/java/gwtquery/samples/client/AnimationsSample.java @@ -1,12 +1,12 @@ /* * 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 @@ -29,39 +29,39 @@ import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing; public class AnimationsSample implements EntryPoint { - + public void onModuleLoad() { doMoveAnimation(); doColorAnimation(); - - $("#stopMove").click(new Function(){ + + $("#stopMove").click(new Function(){ public void f() { $(".foo").clearQueue().stop(); - + } }); - - $("#stopColor").click(new Function(){ + + $("#stopColor").click(new Function(){ public void f() { $(".foo").clearQueue("colorQueue"); } }); - - $("#startMove").click(new Function(){ + + $("#startMove").click(new Function(){ public void f() { $(".foo").css(CSS.LEFT.with(Length.px(0))); doMoveAnimation(); } }); - - $("#startColor").click(new Function(){ + + $("#startColor").click(new Function(){ public void f() { doColorAnimation(); } }); } - + private void doColorAnimation(){ $(".foo") .queue("colorQueue", lazy().css(CSS.BACKGROUND_COLOR.with(RGBColor.RED)).dequeue("colorQueue").done()) @@ -74,15 +74,15 @@ public class AnimationsSample implements EntryPoint { doColorAnimation(); $(".foo").dequeue("colorQueue"); } - + @Override public void cancel(Element e) { $(".foo").clearQueue().stop(); } }); - + } - + private void doMoveAnimation(){ $(".foo").animate(Properties.create("{left:'+=1000'}"), 2000, Easing.SWING) .delay(500) @@ -94,6 +94,6 @@ public class AnimationsSample implements EntryPoint { $(".foo").dequeue(); } }); - + } } diff --git a/samples/src/main/java/gwtquery/samples/client/GwtQueryBenchModule.java b/samples/src/main/java/gwtquery/samples/client/GwtQueryBenchModule.java index b6de78c2..1bb73954 100644 --- a/samples/src/main/java/gwtquery/samples/client/GwtQueryBenchModule.java +++ b/samples/src/main/java/gwtquery/samples/client/GwtQueryBenchModule.java @@ -1,2409 +1,2409 @@ -/*
- * 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 gwtquery.samples.client;
-
-import static com.google.gwt.query.client.GQuery.$;
-import static com.google.gwt.query.client.GQuery.document;
-
-import java.util.ArrayList;
-
-import com.google.gwt.core.client.EntryPoint;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.RepeatingCommand;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.query.client.Function;
-import com.google.gwt.query.client.GQuery;
-import com.google.gwt.query.client.Selectors.DeferredSelector;
-import com.google.gwt.query.client.impl.SelectorEngineCssToXPath;
-import com.google.gwt.query.client.impl.SelectorEngineImpl;
-import com.google.gwt.query.client.impl.SelectorEngineNative;
-import com.google.gwt.query.client.impl.SelectorEngineNativeIE8;
-import com.google.gwt.query.client.impl.SelectorEngineNativeMin;
-import com.google.gwt.query.client.impl.SelectorEngineNativeMinIE8;
-import com.google.gwt.query.client.impl.SelectorEngineSizzle;
-import com.google.gwt.query.client.impl.SelectorEngineSizzleIE;
-import com.google.gwt.query.client.impl.research.SelectorEngineJS;
-import com.google.gwt.query.client.impl.research.SelectorEngineSizzleGwt;
-import com.google.gwt.query.client.impl.research.SelectorEngineXPath;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.FlexTable;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.RootPanel;
-
-/**
- * Module to test and compare the performance of each Js-Library and
- * each Gwt selector implementation.
- *
- * It is possible to select which benchmarks to run. Be aware that
- * not all of them work in all browsers.
- * By default selected options are gwt_compiled, gwt_dynamic, jquery and prototype.
- *
- * It uses iframes to avoid interferences when updating the document.
- * By default the iframe is shared for all libraries, but you can use
- * a different one for each benchmark appending the parameter share=false.
- *
- * Parameters available in the url
- * share=false Use different iframes for each bench
- * min=200 Minimum time running each selector
- * track=false Don't draw the horse race
- * ask=false Run default benchmarks, don't ask the user.
- */
-public class GwtQueryBenchModule implements EntryPoint {
-
- public interface Benchmark {
- String getId();
- String getName();
- int runSelector(DeferredSelector dq);
- }
-
- /**
- * Benchmark for dynamic selectors
- */
- private class DynamicBenchmark implements Benchmark {
-
- protected SelectorEngineImpl engine;
- private String id;
-
- DynamicBenchmark(SelectorEngineImpl engine, String name) {
- this.id = name;
- this.engine = engine;
- }
-
- public String getId() {
- return id;
- }
-
- public String getName() {
- String name = engine.getClass().getName().replaceAll("^.*\\.", "");
- return name;
- }
-
- public int runSelector(DeferredSelector dq) {
- return engine.select(dq.getSelector(), gwtiframe).getLength();
- }
- }
-
- /**
- * Benchmark for the compiled selectors
- */
- private class GQueryCompiledBenchmark implements Benchmark {
-
- String id;
- String name;
-
- GQueryCompiledBenchmark(String id) {
- this.id = id;
- }
-
- public String getId() {
- return id;
- }
-
- public String getName() {
- if (name == null) {
- MySelectors s = GWT.create(MySelectors.class);
- s.body(document);
- name = s.getClass().getName().replaceAll("^.*_", "");
- if (s.isDegradated()) {
- name += " [degradated]";
- }
- }
- return name;
- }
-
- public int runSelector(DeferredSelector dq) {
- return dq.runSelector(gwtiframe).getLength();
- }
- }
-
- /**
- * Benchmark for external libraries
- */
- private class IframeBenchmark implements Benchmark {
- private String id;
-
- IframeBenchmark(String name) {
- this.id = name;
- }
-
- public String getId() {
- return id;
- }
-
- public String getName() {
- return id;
- }
-
- public int runSelector(DeferredSelector dq) {
- return runSelector(id, dq.getSelector());
- }
-
- public native int runSelector(String id, String selector) /*-{
- return eval("$wnd." + id + "benchmark('" + selector + "')");
- }-*/;
- }
-
- public static native void exportIframeReadyCallback(GwtQueryBenchModule bench) /*-{
- $wnd.iframebench_ready_callback = function() {
- bench.@gwtquery.samples.client.GwtQueryBenchModule::iframeReadyCallback()();
- };
- }-*/;
-
- private boolean ask = true;
-
- private Function askBenchMarks = new Function(){
- public void f() {
- if (!running && ask) {
- selectPanel.center();
- } else {
- runBenchMarks.f();
- }
- }
- };
-
- /**
- * List of available benchmarks.
- */
- private final Benchmark[] benchmarks = new Benchmark[] {
- new GQueryCompiledBenchmark("gwt_compiled"),
- new DynamicBenchmark((SelectorEngineImpl)GWT.create(SelectorEngineImpl.class), "gwt_dynamic"),
- new DynamicBenchmark(new SelectorEngineSizzle(), "gwt_sizzle_jsni"),
- new DynamicBenchmark(new SelectorEngineSizzleIE(), "gwt_sizzle_ie_jsni"),
- new DynamicBenchmark(new SelectorEngineSizzleGwt(), "gwt_sizzle_java"),
- new DynamicBenchmark(new SelectorEngineJS(), "gwt_domassist_java"),
- new DynamicBenchmark(new SelectorEngineXPath(), "gwt_xpath"),
- new DynamicBenchmark(new SelectorEngineCssToXPath(), "gwt_css2xpath"),
- new DynamicBenchmark(new SelectorEngineNative(), "gwt_native"),
- new DynamicBenchmark(new SelectorEngineNativeIE8(), "gwt_nativeIE8"),
- new DynamicBenchmark(new SelectorEngineNativeMin(), "gwt_native_min"),
- new DynamicBenchmark(new SelectorEngineNativeMinIE8(), "gwt_native_minIE8"),
- new IframeBenchmark("jquery"),
- new IframeBenchmark("dojo"),
- new IframeBenchmark("prototype"),
- new IframeBenchmark("sizzle"),
- new IframeBenchmark("domassistant")
- };
- /**
- * Pre-selected benchmarks
- */
- private String[] defaultBenchmarks = {"gwt_compiled", "gwt_dynamic", "jquery", "prototype", "dojo"};
-
- private DeferredSelector ds[];
-
- private FlexTable grid = new FlexTable();
-
- private Element gwtiframe;
- private int min_time = 200;
- private boolean running = false;
- /**
- * Main function to run all the selected benchmarks
- */
- private Function runBenchMarks = new Function() {
- public void f() {
-
- // Force to stop the race
- if (running) {
- running = false;
- $("#startrace").text("Run Again");
- return;
- }
- running = true;
-
- selectedBenchmarks = readBenchmarkSelection();
- selectPanel.hide();
- $("#startrace").text("Stop the race");
- $("#results").show();
-
- initResultsTable(ds, selectedBenchmarks);
- initTrack(selectedBenchmarks);
-
- Scheduler.get().scheduleIncremental(new RepeatingCommand() {
- int benchMarkNumber = 0;
- int numCalls = 0;
- int row = 0;
- double runTimes[] = new double[selectedBenchmarks.length];
- int selectorNumber = 0;
- double totalTimes[] = new double[selectedBenchmarks.length];
- int winner = -1;
- double winTime = Double.MAX_VALUE;
-
- public boolean execute() {
- // The race has been stopped
- if (!running) {
- return false;
- }
- if (benchMarkNumber >= selectedBenchmarks.length) {
- benchMarkNumber = 0;
- numCalls = 0;
- row ++;
-
- moveHorses(selectedBenchmarks, row, totalTimes);
- setResultClass(selectorNumber, winner);
-
- selectorNumber++;
- winner = -1;
- winTime = Double.MAX_VALUE;
- if (selectorNumber >= ds.length) {
- double min = Double.MAX_VALUE;
- for (int i = 0; i < totalTimes.length; i++) {
- if (totalTimes[i] < min) {
- min = totalTimes[i];
- }
- }
-
- d(selectorNumber, -1, "Total");
- for (int i = 0; i < totalTimes.length; i++) {
- d(selectorNumber, i, (((int) (totalTimes[i] * 100)) / 100.0) + " ms");
- if (totalTimes[i] <= min) {
- flagWinner(selectedBenchmarks[i].getId());
- $("#startrace").text("Run Again");
- setResultClass(selectorNumber, i);
- }
- }
- return false;
- }
- }
- DeferredSelector d = ds[selectorNumber];
- long start = System.currentTimeMillis();
- int num = 0;
- long end = start;
- Benchmark m = selectedBenchmarks[benchMarkNumber];
- double runtime = min_time;
- int found = 0;
- try {
- do {
- num += m.runSelector(d);
- end = System.currentTimeMillis();
- numCalls++;
- } while (end - start < min_time);
- runtime = (double) (end - start) / numCalls;
- if (runtime < winTime) {
- winTime = runtime;
- winner = benchMarkNumber;
- }
- found = num / numCalls;
- } catch (Exception e) {
- e.printStackTrace();
- found = -1;
- }
- runTimes[benchMarkNumber] = runtime;
- d(selectorNumber, benchMarkNumber, runtime, found);
- totalTimes[benchMarkNumber] += runtime;
- numCalls = 0;
- benchMarkNumber++;
- return true;
- }
- });
- }
- };
- private Benchmark[] selectedBenchmarks;
- private PopupPanel selectPanel = new PopupPanel() {{
- addStyleName("spanel");
- }};
- private PopupPanel helpPanel = new PopupPanel() {{
- setAutoHideEnabled(true);
- setWidget(new HTML($("#help").html()));
- addStyleName("help");
- }};
- private boolean shareIframes = true;
-
- private double trackWidth;
-
- private boolean useTrack = true;
-
- public void iframeReadyCallback() {
- writeTestContent($(".ibench").contents().find("body").get(0));
- gwtiframe = $(".ibench").eq(0).contents().get(0);
- $("#startrace").text("Start the race");
- $("#startrace").click(ask ? askBenchMarks: runBenchMarks);
- $("#about").click(new Function(){
- public void f() {
- helpPanel.center();
- }
- });
- }
-
- /**
- * EntryPoint
- */
- public void onModuleLoad() {
-
- final MySelectors m = GWT.create(MySelectors.class);
-
- ds = m.getAllSelectors();
-
- String par = Window.Location.getParameter("min");
- if (par != null) {
- min_time = Integer.parseInt(par);
- }
- par = Window.Location.getParameter("share");
- if (par != null && "false".equals(par)) {
- shareIframes = false;
- }
- par = Window.Location.getParameter("track");
- if (par != null && "false".equals(par)) {
- useTrack = false;
- }
- par = Window.Location.getParameter("ask");
- if (par != null && "false".equals(par)) {
- ask = false;
- }
-
- exportIframeReadyCallback(this);
- initSelects(benchmarks);
- initIFrames();
- $("#results").hide();
-
- }
-
- private void d(int selnumber, int benchnumber, double time, int found) {
- String text = found < 0 ? "Error" : "" + (((int) (time * 10)) / 10.0) + " ms | " + found + " found";
- d(selnumber, benchnumber, text);
- }
-
- private void d(int selnumber, int benchnumber, String text) {
- grid.setText(selnumber + 1, benchnumber + 1, text);
- Element td = grid.getCellFormatter().getElement(selnumber + 1, benchnumber + 1);
- DOM.scrollIntoView((com.google.gwt.user.client.Element) td);
- }
-
- private void flagWinner(String idWinner) {
- GQuery g = $("#" + idWinner + "horse" + " nobr");
- $(".flag").appendTo(g).show();
- }
-
- /**
- * Insert the iframes for benchmarking.
- * Depending on the parameter share, we will generate one iframe
- * for each benchmark or we will share the same one.
- */
- private void initIFrames() {
- String i = "<iframe class=ibench id=%ID%bench src=html/%ID%bench.html></iframe>";
- if (! shareIframes ) {
- $(i.replaceAll("%ID%", "gwt")).appendTo(document).hide();
- for (Benchmark b : benchmarks) {
- if (b instanceof IframeBenchmark) {
- $(i.replaceAll("%ID%", b.getId())).appendTo(document).hide();
- }
- }
- } else {
- $(i.replaceAll("%ID%", "iframe")).appendTo(document).hide();
- }
- }
-
- /**
- * Reset the result table
- */
- private void initResultsTable(DeferredSelector[] dg, Benchmark... benchs) {
- int numRows = dg.length;
- grid = new FlexTable();
- grid.addStyleName("resultstable");
- RootPanel.get("results").clear();
- RootPanel.get("results").add(grid);
-
- grid.setText(0, 0, "Selector");
- for (int i=0; i < benchs.length; i++) {
- grid.setText(0, i+1, benchs[i].getId());
- }
-
- for (int i = 0; i < numRows; i++) {
- grid.setText(i+1, 0, dg[i].getSelector());
- for (int j = 0; j < benchs.length; j++) {
- grid.setText(i+1, j+1, "-");
- }
- }
- }
-
- /**
- * Initialize the selects to choose the benchmarks to run
- */
- private void initSelects(Benchmark... benchs) {
- String opt = "<input type='checkbox' name='n' value='%ID%' %SEL%>%ID%</input><br/>";
- selectPanel.add(new HTML("<div id=selectcontainer><strong>Make your selection</strong><hr/></div>"));
- selectPanel.show();
- GQuery g = $("#selectcontainer");
- for (Benchmark b : benchs) {
- String select = opt;
- for (String s : defaultBenchmarks) {
- if (s.equals(b.getId())) {
- select = select.replaceAll("%SEL%", "checked='checked'");
- }
- }
- g.append(select.replaceAll("%ID%", b.getId() + " " + b.getName()).replaceAll("%SEL", ""));
- }
- g.append("<br/><button id=run>Run</button>");
- $("#run").click(runBenchMarks);
- selectPanel.hide();
- }
-
- /**
- * Initialize the track with the horses
- */
- private void initTrack(Benchmark... benchs) {
- if (!useTrack) return;
- String tpl = "<div id=%ID%horse class=horse><nobr><img class=himg src=images/bench/horse.gif><span>%ID%</span></nobr></div>";
- GQuery g = $("#racefield").html("");
- for (Benchmark b : benchs) {
- String id = b.getId();
- String lg = id.contains("gwt") ? "gwt" : id;
- String s = tpl.replaceAll("%ID%", id).replaceAll("%LG%", lg);
- g.append($(s));
- }
-
- GQuery flag = $("<img class=flag src='images/bench/animated-flag.gif'/>").appendTo(document);
-
- // These values are set in the css.
- int horseHeight = 35;
- int horseWidth = 150;
- int flagWidth = 35;
-
- int height = horseHeight * (benchs.length + 1);
- $("#racetrack").css("height", height + "px");
-
- trackWidth = g.width() - horseWidth - flagWidth;
- flag.hide();
- }
-
- /**
- * Update horse possition.
- * Note that the calculated position is relative with the faster horse,
- * so a horse could move back.
- */
- private void moveHorses(Benchmark[] b, int row, double[] totalTimes) {
- if (!useTrack) return;
- double winnerTime = Double.MAX_VALUE;
- for (double d : totalTimes) {
- winnerTime = Math.min(winnerTime, d);
- }
- double winnerPos = row * (double) trackWidth / (double) ds.length;
- for (int i = 0; i < b.length; i++) {
- GQuery g = $("#" + b[i].getId() + "horse");
- double pos = winnerPos * winnerTime / totalTimes[i];
- g.css("left", (int)pos + "px");
- }
- }
-
- private Benchmark[] readBenchmarkSelection() {
- ArrayList<Benchmark> bs = new ArrayList<Benchmark>();
- for (Element e : $("input", selectPanel.getElement()).elements()) {
- String val = $(e).val().replaceAll(" .*$", "");
- if ($(e).prop("checked")) {
- for (Benchmark b : benchmarks) {
- if (b.getId().equals(val)) {
- bs.add(b);
- }
- }
- }
- }
- return bs.toArray(new Benchmark[bs.size()]);
- }
-
- private void setResultClass(int selNumber, int winNumber) {
- Element e = grid.getCellFormatter().getElement(selNumber + 1, winNumber + 1);
- $(e).addClass("win").siblings().attr("class", "").addClass("tie").eq(0).removeClass("tie");
- }
-
- /**
- * This ugly method is used to initialize a huge html String
- * plenty of html tags which will be used for the tests,
- * because java 1.5 has a limitation in the size of static strings.
- */
- private void writeTestContent(Element e) {
- String ret = "";
- ret += "<html><head> </head><body><div>";
- ret += " <div class='head dialog'>";
- ret += " <p><a href='http://www.w3.org/'><img alt='W3C' src='' height='48' width='72'></a></p>";
- ret += " <h1 id='title'>Selectors</h1>";
- ret += " <em><span>.</span></em>";
- ret += " <h2>W3C Working Draft 15 December 2005</h2>";
- ret += " <dl>";
- ret += " <dt>This version:</dt>";
- ret += " <dd><a href='http://www.w3.org/TR/2005/WD-css3-selectors-20051215'>";
- ret += " http://www.w3.org/TR/2005/WD-css3-selectors-20051215</a></dd>";
- ret += " <dt>Latest version:";
- ret += " </dt><dd><a href='http://www.w3.org/TR/css3-selectors'>";
- ret += " http://www.w3.org/TR/css3-selectors</a>";
- ret += " </dd><dt>Previous version:";
- ret += " </dt><dd><a href='http://www.w3.org/TR/2001/CR-css3-selectors-20011113'>";
- ret += " http://www.w3.org/TR/2001/CR-css3-selectors-20011113</a>";
- ret += " </dd><dt><a name='editors-list'></a>Editors:";
- ret += " </dt><dd class='vcard'><span class='fn'>Daniel Glazman</span> (Invited";
- ret += " </dd>";
- ret += " <dd class='vcard'><a class='url fn' href='http://www.tantek.com/' lang='tr'>Tantek Çelik</a>";
- ret += " </dd><dd class='vcard'><a href='mailto:ian@hixie.ch' class='url fn'>Ian";
- ret += " Hickson</a> (<span class='company'><a href='http://www.google.com/'>Google</a></span>)";
- ret += " </dd><dd class='vcard'><span class='fn'>Peter Linss</span> (former";
- ret += " editor, <span class='company'><a href='http://www.netscape.com/'>Netscape/AOL</a></span>)";
- ret += " </dd><dd class='vcard'><span class='fn'>John Williams</span> (former editor, <span class='company'><a href='http://www.quark.com/'>Quark, Inc.</a></span>)";
- ret += " </dd></dl>";
- ret += " <p class='copyright'><a href='http://www.w3.org/Consortium/Legal/ipr-notice#Copyright'>";
- ret += " Copyright</a> © 2005 <a href='http://www.w3.org/'><abbr title='World Wide Web Consortium'>W3C</abbr></a><sup>®</sup>";
- ret += " (<a href='http://www.csail.mit.edu/'><abbr title='Massachusetts";
- ret += " Institute of Technology'>MIT</abbr></a>, <a href='http://www.ercim.org/'><acronym title='European Research";
- ret += " Consortium for Informatics and Mathematics'>ERCIM</acronym></a>, <a href='http://www.keio.ac.jp/'>Keio</a>), All Rights Reserved.";
- ret += " <a href='http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer'>liability</a>,";
- ret += " <a href='http://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks'>trademark</a>,";
- ret += " <a href='http://www.w3.org/Consortium/Legal/copyright-documents'>document";
- ret += " use</a> rules apply.";
- ret += " </p><hr title='Separator for header'>";
- ret += " </div>";
- ret += " <h2><a name='abstract'></a>Abstract</h2>";
- ret += " <p><em>Selectors</em> are patterns that match against elements in a";
- ret += " tree. Selectors have been optimized for use with HTML and XML, and";
- ret += " are designed to be usable in performance-critical code.</p>";
- ret += " <p><acronym title='Cascading Style Sheets'>CSS</acronym> (Cascading";
- ret += " Style Sheets) is a language for describing the rendering of <acronym title='Hypertext Markup Language'>HTML</acronym> and <acronym title='Extensible Markup Language'>XML</acronym> documents on";
- ret += " screen, on paper, in speech, etc. CSS uses Selectors for binding";
- ret += " describes extensions to the selectors defined in CSS level 2. These";
- ret += " extended selectors will be used by CSS level 3.";
- ret += " </p><p>Selectors define the following function:</p>";
- ret += " <pre>expression ∗ element → boolean</pre>";
- ret += " <p>That is, given an element and a selector, this specification";
- ret += " defines whether that element matches the selector.</p>";
- ret += " <p>These expressions can also be used, for instance, to select a set";
- ret += " subtree. <acronym title='Simple Tree Transformation";
- ret += " Sheets'>STTS</acronym> (Simple Tree Transformation Sheets), a";
- ret += " language for transforming XML trees, uses this mechanism. <a href='#refsSTTS'>[STTS]</a></p>";
- ret += " <h2><a name='status'></a>Status of this document</h2>";
- ret += " <p><em>This section describes the status of this document at the";
- ret += " of this technical report can be found in the <a href='http://www.w3.org/TR/'>W3C technical reports index at";
- ret += " http://www.w3.org/TR/.</a></em></p>";
- ret += " <p>This document describes the selectors that already exist in <a href='#refsCSS1'><abbr title='CSS level 1'>CSS1</abbr></a> and <a href='#refsCSS21'><abbr title='CSS level 2'>CSS2</abbr></a>, and";
- ret += " also proposes new selectors for <abbr title='CSS level";
- ret += " 3'>CSS3</abbr> and other languages that may need them.</p>";
- ret += " <p>The CSS Working Group doesn't expect that all implementations of";
- ret += " CSS3 will have to implement all selectors. Instead, there will";
- ret += " will include all of the selectors.</p>";
- ret += " <p>This specification is a last call working draft for the the <a href='http://www.w3.org/Style/CSS/members'>CSS Working Group</a>";
- ret += " (<a href='/Style/'>Style Activity</a>). This";
- ret += " document is a revision of the <a href='http://www.w3.org/TR/2001/CR-css3-selectors-20011113/'>Candidate";
- ret += " Recommendation dated 2001 November 13</a>, and has incorporated";
- ret += " be demonstrable.</p>";
- ret += " <p>All persons are encouraged to review and implement this";
- ret += " specification and return comments to the (<a href='http://lists.w3.org/Archives/Public/www-style/'>archived</a>)";
- ret += " public mailing list <a href='http://www.w3.org/Mail/Lists.html#www-style'>www-style</a>";
- ret += " (see <a href='http://www.w3.org/Mail/Request'>instructions</a>). W3C";
- ret += " The deadline for comments is 14 January 2006.</p>";
- ret += " <p>This is still a draft document and may be updated, replaced, or";
- ret += " </p><p>This document may be available in <a href='http://www.w3.org/Style/css3-selectors-updates/translations'>translation</a>.";
- ret += " </p><div class='subtoc'>";
- ret += " <h2><a name='contents'>Table of contents</a></h2>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline2'><a href='#context'>1. Introduction</a>";
- ret += " <ul>";
- ret += " <li><a href='#dependencies'>1.1. Dependencies</a></li>";
- ret += " <li><a href='#terminology'>1.2. Terminology</a></li>";
- ret += " <li><a href='#changesFromCSS2'>1.3. Changes from CSS2</a></li>";
- ret += " </ul>";
- ret += " </li><li class='tocline2'><a href='#selectors'>2. Selectors</a>";
- ret += " </li><li class='tocline2'><a href='#casesens'>3. Case sensitivity</a>";
- ret += " </li><li class='tocline2'><a href='#selector-syntax'>4. Selector syntax</a>";
- ret += " </li><li class='tocline2'><a href='#grouping'>5. Groups of selectors</a>";
- ret += " </li><li class='tocline2'><a href='#simple-selectors'>6. Simple selectors</a>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline3'><a href='#type-selectors'>6.1. Type";
- ret += " selectors</a>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline4'><a href='#typenmsp'>6.1.1. Type";
- ret += " selectors and namespaces</a></li>";
- ret += " </ul>";
- ret += " </li><li class='tocline3'><a href='#universal-selector'>6.2.";
- ret += " Universal selector</a>";
- ret += " <ul>";
- ret += " <li><a href='#univnmsp'>6.2.1. Universal selector and";
- ret += " namespaces</a></li>";
- ret += " </ul>";
- ret += " </li><li class='tocline3'><a href='#attribute-selectors'>6.3.";
- ret += " Attribute selectors</a>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline4'><a href='#attribute-representation'>6.3.1.";
- ret += " values</a>";
- ret += " </li><li><a href='#attribute-substrings'>6.3.2. Substring";
- ret += " matching attribute selectors</a>";
- ret += " </li><li class='tocline4'><a href='#attrnmsp'>6.3.3.";
- ret += " Attribute selectors and namespaces</a>";
- ret += " </li><li class='tocline4'><a href='#def-values'>6.3.4.";
- ret += " Default attribute values in DTDs</a></li>";
- ret += " </ul>";
- ret += " </li><li class='tocline3'><a href='#class-html'>6.4. Class";
- ret += " selectors</a>";
- ret += " </li><li class='tocline3'><a href='#id-selectors'>6.5. ID";
- ret += " selectors</a>";
- ret += " </li><li class='tocline3'><a href='#pseudo-classes'>6.6.";
- ret += " Pseudo-classes</a>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline4'><a href='#dynamic-pseudos'>6.6.1.";
- ret += " Dynamic pseudo-classes</a>";
- ret += " </li><li class='tocline4'><a href='#target-pseudo'>6.6.2. The";
- ret += " :target pseudo-class</a>";
- ret += " </li><li class='tocline4'><a href='#lang-pseudo'>6.6.3. The";
- ret += " :lang() pseudo-class</a>";
- ret += " </li><li class='tocline4'><a href='#UIstates'>6.6.4. UI";
- ret += " element states pseudo-classes</a>";
- ret += " </li><li class='tocline4'><a href='#structural-pseudos'>6.6.5.";
- ret += " Structural pseudo-classes</a>";
- ret += " <ul>";
- ret += " <li><a href='#root-pseudo'>:root";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#nth-child-pseudo'>:nth-child()";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#nth-last-child-pseudo'>:nth-last-child()</a>";
- ret += " </li><li><a href='#nth-of-type-pseudo'>:nth-of-type()";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#nth-last-of-type-pseudo'>:nth-last-of-type()</a>";
- ret += " </li><li><a href='#first-child-pseudo'>:first-child";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#last-child-pseudo'>:last-child";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#first-of-type-pseudo'>:first-of-type";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#last-of-type-pseudo'>:last-of-type";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#only-child-pseudo'>:only-child";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#only-of-type-pseudo'>:only-of-type";
- ret += " pseudo-class</a>";
- ret += " </li><li><a href='#empty-pseudo'>:empty";
- ret += " pseudo-class</a></li>";
- ret += " </ul>";
- ret += " </li><li class='tocline4'><a href='#negation'>6.6.7. The";
- ret += " negation pseudo-class</a></li>";
- ret += " </ul>";
- ret += " </li>";
- ret += " </ul>";
- ret += " </li><li><a href='#pseudo-elements'>7. Pseudo-elements</a>";
- ret += " <ul>";
- ret += " <li><a href='#first-line'>7.1. The ::first-line";
- ret += " pseudo-element</a>";
- ret += " </li><li><a href='#first-letter'>7.2. The ::first-letter";
- ret += " pseudo-element</a>";
- ret += " </li><li><a href='#UIfragments'>7.3. The ::selection";
- ret += " pseudo-element</a>";
- ret += " </li><li><a href='#gen-content'>7.4. The ::before and ::after";
- ret += " pseudo-elements</a></li>";
- ret += " </ul>";
- ret += " </li><li class='tocline2'><a href='#combinators'>8. Combinators</a>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline3'><a href='#descendant-combinators'>8.1.";
- ret += " Descendant combinators</a>";
- ret += " </li><li class='tocline3'><a href='#child-combinators'>8.2. Child";
- ret += " combinators</a>";
- ret += " </li><li class='tocline3'><a href='#sibling-combinators'>8.3. Sibling";
- ret += " combinators</a>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline4'><a href='#adjacent-sibling-combinators'>8.3.1.";
- ret += " Adjacent sibling combinator</a>";
- ret += " </li><li class='tocline4'><a href='#general-sibling-combinators'>8.3.2.";
- ret += " General sibling combinator</a></li>";
- ret += " </ul>";
- ret += " </li>";
- ret += " </ul>";
- ret += " </li><li class='tocline2'><a href='#specificity'>9. Calculating a selector's";
- ret += " specificity</a>";
- ret += " </li><li class='tocline2'><a href='#w3cselgrammar'>10. The grammar of";
- ret += " Selectors</a>";
- ret += " <ul class='toc'>";
- ret += " <li class='tocline3'><a href='#grammar'>10.1. Grammar</a>";
- ret += " </li><li class='tocline3'><a href='#lex'>10.2. Lexical scanner</a>";
- ret += " </li>";
- ret += " </ul>";
- ret += " </li><li class='tocline2'><a href='#downlevel'>11. Namespaces and down-level";
- ret += " clients</a>";
- ret += " </li><li class='tocline2'><a href='#profiling'>12. Profiles</a>";
- ret += " </li><li><a href='#Conformance'>13. Conformance and requirements</a>";
- ret += " </li><li><a href='#Tests'>14. Tests</a>";
- ret += " </li><li><a href='#ACKS'>15. Acknowledgements</a>";
- ret += " </li><li class='tocline2'><a href='#references'>16. References</a>";
- ret += " </li></ul>";
- ret += " </div>";
- ret += " <h2><a name='context'>1. Introduction</a></h2>";
- ret += " <h3><a name='dependencies'></a>1.1. Dependencies</h3>";
- ret += " <p>Some features of this specification are specific to CSS, or have";
- ret += " specification, these have been described in terms of CSS2.1. <a href='#refsCSS21'>[CSS21]</a></p>";
- ret += " <h3><a name='terminology'></a>1.2. Terminology</h3>";
- ret += " <p>All of the text of this specification is normative except";
- ret += " non-normative.</p>";
- ret += " <h3><a name='changesFromCSS2'></a>1.3. Changes from CSS2</h3>";
- ret += " <p><em>This section is non-normative.</em></p>";
- ret += " <p>The main differences between the selectors in CSS2 and those in";
- ret += " Selectors are:";
- ret += " </p><ul>";
- ret += " <li>the list of basic definitions (selector, group of selectors,";
- ret += " of simple selectors, and the term 'simple selector' is now used for";
- ret += " </li>";
- ret += " <li>an optional namespace component is now allowed in type element";
- ret += " selectors, the universal selector and attribute selectors";
- ret += " </li>";
- ret += " <li>a <a href='#general-sibling-combinators'>new combinator</a> has been";
- ret += " </li>";
- ret += " <li>new simple selectors including substring matching attribute";
- ret += " selectors, and new pseudo-classes";
- ret += " </li>";
- ret += " <li>new pseudo-elements, and introduction of the '::' convention";
- ret += " </li>";
- ret += " <li>the grammar has been rewritten</li>";
- ret += " <li>profiles to be added to specifications integrating Selectors";
- ret += " and defining the set of selectors which is actually supported by";
- ret += " </li>";
- ret += " <li>Selectors are now a CSS3 Module and an independent";
- ret += " </li>";
- ret += " <li>the specification now has its own test suite</li>";
- ret += " </ul>";
- ret += " <h2><a name='selectors'></a>2. Selectors</h2>";
- ret += " <p><em>This section is non-normative, as it merely summarizes the";
- ret += " following sections.</em></p>";
- ret += " <p>A Selector represents a structure. This structure can be used as a";
- ret += " HTML or XML fragment corresponding to that structure.</p>";
- ret += " <p>Selectors may range from simple element names to rich contextual";
- ret += " representations.</p>";
- ret += " <p>The following table summarizes the Selector syntax:</p>";
- ret += " <table class='selectorsReview'>";
- ret += " <thead>";
- ret += " <tr>";
- ret += " <th class='pattern'>Pattern</th>";
- ret += " <th class='meaning'>Meaning</th>";
- ret += " <th class='described'>Described in section</th>";
- ret += " <th class='origin'>First defined in CSS level</th>";
- ret += " </tr>";
- ret += " </thead><tbody>";
- ret += " <tr>";
- ret += " <td class='pattern'>*</td>";
- ret += " <td class='meaning'>any element</td>";
- ret += " <td class='described'><a href='#universal-selector'>Universal";
- ret += " selector</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E</td>";
- ret += " <td class='meaning'>an element of type E</td>";
- ret += " <td class='described'><a href='#type-selectors'>Type selector</a></td>";
- ret += " <td class='origin'>1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E[foo]</td>";
- ret += " <td class='meaning'>an E element with a 'foo' attribute</td>";
- ret += " <td class='described'><a href='#attribute-selectors'>Attribute";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E[foo='bar']</td>";
- ret += " <td class='meaning'>an E element whose 'foo' attribute value is exactly";
- ret += " </td>";
- ret += " <td class='described'><a href='#attribute-selectors'>Attribute";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E[foo~='bar']</td>";
- ret += " <td class='meaning'>an E element whose 'foo' attribute value is a list of";
- ret += " </td>";
- ret += " <td class='described'><a href='#attribute-selectors'>Attribute";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E[foo^='bar']</td>";
- ret += " <td class='meaning'>an E element whose 'foo' attribute value begins exactly";
- ret += " </td>";
- ret += " <td class='described'><a href='#attribute-selectors'>Attribute";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E[foo$='bar']</td>";
- ret += " <td class='meaning'>an E element whose 'foo' attribute value ends exactly";
- ret += " </td>";
- ret += " <td class='described'><a href='#attribute-selectors'>Attribute";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E[foo*='bar']</td>";
- ret += " <td class='meaning'>an E element whose 'foo' attribute value contains the";
- ret += " </td>";
- ret += " <td class='described'><a href='#attribute-selectors'>Attribute";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E[hreflang|='en']</td>";
- ret += " <td class='meaning'>an E element whose 'hreflang' attribute has a";
- ret += " </td>";
- ret += " <td class='described'><a href='#attribute-selectors'>Attribute";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:root</td>";
- ret += " <td class='meaning'>an E element, root of the document</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:nth-child(n)</td>";
- ret += " <td class='meaning'>an E element, the n-th child of its parent</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:nth-last-child(n)</td>";
- ret += " <td class='meaning'>an E element, the n-th child of its parent, counting";
- ret += " </td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:nth-of-type(n)</td>";
- ret += " <td class='meaning'>an E element, the n-th sibling of its type</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:nth-last-of-type(n)</td>";
- ret += " <td class='meaning'>an E element, the n-th sibling of its type, counting";
- ret += " </td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:first-child</td>";
- ret += " <td class='meaning'>an E element, first child of its parent</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:last-child</td>";
- ret += " <td class='meaning'>an E element, last child of its parent</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:first-of-type</td>";
- ret += " <td class='meaning'>an E element, first sibling of its type</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:last-of-type</td>";
- ret += " <td class='meaning'>an E element, last sibling of its type</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:only-child</td>";
- ret += " <td class='meaning'>an E element, only child of its parent</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:only-of-type</td>";
- ret += " <td class='meaning'>an E element, only sibling of its type</td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:empty</td>";
- ret += " <td class='meaning'>an E element that has no children (including text";
- ret += " </td>";
- ret += " <td class='described'><a href='#structural-pseudos'>Structural";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:link<br>E:visited</td>";
- ret += " <td class='meaning'>an E element being the source anchor of a hyperlink of";
- ret += " </td>";
- ret += " <td class='described'><a href='#link'>The link";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:active<br>E:hover<br>E:focus</td>";
- ret += " <td class='meaning'>an E element during certain user actions</td>";
- ret += " <td class='described'><a href='#useraction-pseudos'>The user";
- ret += " action pseudo-classes</a></td>";
- ret += " <td class='origin'>1 and 2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:target</td>";
- ret += " <td class='meaning'>an E element being the target of the referring URI</td>";
- ret += " <td class='described'><a href='#target-pseudo'>The target";
- ret += " pseudo-class</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:lang(fr)</td>";
- ret += " <td class='meaning'>an element of type E in language 'fr' (the document";
- ret += " </td>";
- ret += " <td class='described'><a href='#lang-pseudo'>The :lang()";
- ret += " pseudo-class</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:enabled<br>E:disabled</td>";
- ret += " <td class='meaning'>a user interface element E which is enabled or";
- ret += " </td>";
- ret += " <td class='described'><a href='#UIstates'>The UI element states";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:checked<!--<br>E:indeterminate--></td>";
- ret += " <td class='meaning'>a user interface element E which is checked<!-- or in an";
- ret += " indeterminate state--> (for instance a radio-button or checkbox)";
- ret += " </td>";
- ret += " <td class='described'><a href='#UIstates'>The UI element states";
- ret += " pseudo-classes</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E::first-line</td>";
- ret += " <td class='meaning'>the first formatted line of an E element</td>";
- ret += " <td class='described'><a href='#first-line'>The ::first-line";
- ret += " pseudo-element</a></td>";
- ret += " <td class='origin'>1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E::first-letter</td>";
- ret += " <td class='meaning'>the first formatted letter of an E element</td>";
- ret += " <td class='described'><a href='#first-letter'>The ::first-letter";
- ret += " pseudo-element</a></td>";
- ret += " <td class='origin'>1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E::selection</td>";
- ret += " <td class='meaning'>the portion of an E element that is currently";
- ret += " </td>";
- ret += " <td class='described'><a href='#UIfragments'>The UI element";
- ret += " fragments pseudo-elements</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E::before</td>";
- ret += " <td class='meaning'>generated content before an E element</td>";
- ret += " <td class='described'><a href='#gen-content'>The ::before";
- ret += " pseudo-element</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E::after</td>";
- ret += " <td class='meaning'>generated content after an E element</td>";
- ret += " <td class='described'><a href='#gen-content'>The ::after";
- ret += " pseudo-element</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E.warning</td>";
- ret += " <td class='meaning'>an E element whose class is";
- ret += " </td>";
- ret += " <td class='described'><a href='#class-html'>Class";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E#myid</td>";
- ret += " <td class='meaning'>an E element with ID equal to 'myid'.</td>";
- ret += " <td class='described'><a href='#id-selectors'>ID";
- ret += " selectors</a></td>";
- ret += " <td class='origin'>1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E:not(s)</td>";
- ret += " <td class='meaning'>an E element that does not match simple selector s</td>";
- ret += " <td class='described'><a href='#negation'>Negation";
- ret += " pseudo-class</a></td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E F</td>";
- ret += " <td class='meaning'>an F element descendant of an E element</td>";
- ret += " <td class='described'><a href='#descendant-combinators'>Descendant";
- ret += " combinator</a></td>";
- ret += " <td class='origin'>1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E > F</td>";
- ret += " <td class='meaning'>an F element child of an E element</td>";
- ret += " <td class='described'><a href='#child-combinators'>Child";
- ret += " combinator</a></td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E + F</td>";
- ret += " <td class='meaning'>an F element immediately preceded by an E element</td>";
- ret += " <td class='described'><a href='#adjacent-sibling-combinators'>Adjacent sibling combinator</a>";
- ret += " </td>";
- ret += " <td class='origin'>2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <td class='pattern'>E ~ F</td>";
- ret += " <td class='meaning'>an F element preceded by an E element</td>";
- ret += " <td class='described'><a href='#general-sibling-combinators'>General sibling combinator</a>";
- ret += " </td>";
- ret += " <td class='origin'>3</td>";
- ret += " </tr>";
- ret += " </tbody>";
- ret += " </table>";
- ret += " <p>The meaning of each selector is derived from the table above by";
- ret += " column.</p>";
- ret += " <h2><a name='casesens'>3. Case sensitivity</a></h2>";
- ret += " <p>The case sensitivity of document language element names, attribute";
- ret += " names, and attribute values in selectors depends on the document";
- ret += " but in XML, they are case-sensitive.</p>";
- ret += " <h2><a name='selector-syntax'>4. Selector syntax</a></h2>";
- ret += " <p>A <dfn><a name='selector'>selector</a></dfn> is a chain of one";
- ret += " or more <a href='#sequence'>sequences of simple selectors</a>";
- ret += " separated by <a href='#combinators'>combinators</a>.</p>";
- ret += " <p>A <dfn><a name='sequence'>sequence of simple selectors</a></dfn>";
- ret += " is a chain of <a href='#simple-selectors-dfn'>simple selectors</a>";
- ret += " that are not separated by a <a href='#combinators'>combinator</a>. It";
- ret += " always begins with a <a href='#type-selectors'>type selector</a> or a";
- ret += " <a href='#universal-selector'>universal selector</a>. No other type";
- ret += " selector or universal selector is allowed in the sequence.</p>";
- ret += " <p>A <dfn><a name='simple-selectors-dfn'></a><a href='#simple-selectors'>simple selector</a></dfn> is either a <a href='#type-selectors'>type selector</a>, <a href='#universal-selector'>universal selector</a>, <a href='#attribute-selectors'>attribute selector</a>, <a href='#class-html'>class selector</a>, <a href='#id-selectors'>ID selector</a>, <a href='#content-selectors'>content selector</a>, or <a href='#pseudo-classes'>pseudo-class</a>. One <a href='#pseudo-elements'>pseudo-element</a> may be appended to the last";
- ret += " sequence of simple selectors.</p>";
- ret += " <p><dfn>Combinators</dfn> are: white space, 'greater-than";
- ret += " sign' (U+003E, <code>></code>), 'plus sign' (U+002B,";
- ret += " <code>+</code>) and 'tilde' (U+007E, <code>~</code>). White";
- ret += " space may appear between a combinator and the simple selectors around";
- ret += " it. <a name='whitespace'></a>Only the characters 'space' (U+0020), 'tab'";
- ret += " never part of white space.</p>";
- ret += " <p>The elements of a document tree that are represented by a selector";
- ret += " are the <dfn><a name='subject'></a>subjects of the selector</dfn>. A";
- ret += " selector consisting of a single sequence of simple selectors";
- ret += " sequence of simple selectors and a combinator to a sequence imposes";
- ret += " simple selectors.</p>";
- ret += " <p>An empty selector, containing no sequence of simple selectors and";
- ret += " no pseudo-element, is an <a href='#Conformance'>invalid";
- ret += " selector</a>.</p>";
- ret += " <h2><a name='grouping'>5. Groups of selectors</a></h2>";
- ret += " <p>When several selectors share the same declarations, they may be";
- ret += " grouped into a comma-separated list. (A comma is U+002C.)</p>";
- ret += " <div class='example'>";
- ret += " <p>CSS examples:</p>";
- ret += " <p>In this example, we condense three rules with identical";
- ret += " declarations into one. Thus,</p>";
- ret += " <pre>h1 { font-family: sans-serif }";
- ret += " h3 { font-family: sans-serif }</pre>";
- ret += " <p>is equivalent to:</p>";
- ret += " <pre>h1, h2, h3 { font-family: sans-serif }</pre>";
- ret += " </div>";
- ret += " <p><strong>Warning</strong>: the equivalence is true in this example";
- ret += " because all the selectors are valid selectors. If just one of these";
- ret += " selectors were invalid, the entire group of selectors would be";
- ret += " heading rules would be invalidated.</p>";
- ret += " <h2><a name='simple-selectors'>6. Simple selectors</a></h2>";
- ret += " <h3><a name='type-selectors'>6.1. Type selector</a></h3>";
- ret += " <p>A <dfn>type selector</dfn> is the name of a document language";
- ret += " type in the document tree.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>The following selector represents an <code>h1</code> element in the";
- ret += " document tree:</p>";
- ret += " <pre>h1</pre>";
- ret += " </div>";
- ret += " <h4><a name='typenmsp'>6.1.1. Type selectors and namespaces</a></h4>";
- ret += " <p>Type selectors allow an optional namespace (<a href='#refsXMLNAMES'>[XMLNAMES]</a>) component. A namespace prefix";
- ret += " (U+007C, <code>|</code>).</p>";
- ret += " <p>The namespace component may be left empty to indicate that the";
- ret += " selector is only to represent elements with no declared namespace.</p>";
- ret += " <p>An asterisk may be used for the namespace prefix, indicating that";
- ret += " with no namespace).</p>";
- ret += " <p>Element type selectors that have no namespace component (no";
- ret += " element's namespace (equivalent to '<code>*|</code>') unless a default";
- ret += " namespace.</p>";
- ret += " <p>A type selector containing a namespace prefix that has not been";
- ret += " previously declared is an <a href='#Conformance'>invalid</a> selector.";
- ret += " language implementing Selectors. In CSS, such a mechanism is defined";
- ret += " in the General Syntax module.</p>";
- ret += " <p>In a namespace-aware client, element type selectors will only match";
- ret += " against the <a href='http://www.w3.org/TR/REC-xml-names/#NT-LocalPart'>local";
- ret += " part</a>";
- ret += " of the element's <a href='http://www.w3.org/TR/REC-xml-names/#ns-qualnames'>qualified";
- ret += " name</a>. See <a href='#downlevel'>below</a> for notes about matching";
- ret += " behaviors in down-level clients.</p>";
- ret += " <p>In summary:</p>";
- ret += " <dl>";
- ret += " <dt><code>ns|E</code></dt>";
- ret += " <dd>elements with name E in namespace ns</dd>";
- ret += " <dt><code>*|E</code></dt>";
- ret += " <dd>elements with name E in any namespace, including those without any";
- ret += " </dd>";
- ret += " <dt><code>|E</code></dt>";
- ret += " <dd>elements with name E without any declared namespace</dd>";
- ret += " <dt><code>E</code></dt>";
- ret += " <dd>if no default namespace has been specified, this is equivalent to *|E.";
- ret += " </dd>";
- ret += " </dl>";
- ret += " <div class='example'>";
- ret += " <p>CSS examples:</p>";
- ret += " <pre>@namespace foo url(http://www.example.com);";
- ret += " h1 { color: green }</pre>";
- ret += " <p>The first rule will match only <code>h1</code> elements in the";
- ret += " 'http://www.example.com' namespace.</p>";
- ret += " <p>The second rule will match all elements in the";
- ret += " 'http://www.example.com' namespace.</p>";
- ret += " <p>The third rule will match only <code>h1</code> elements without";
- ret += " any declared namespace.</p>";
- ret += " <p>The fourth rule will match <code>h1</code> elements in any";
- ret += " namespace (including those without any declared namespace).</p>";
- ret += " <p>The last rule is equivalent to the fourth rule because no default";
- ret += " namespace has been defined.</p>";
- ret += " </div>";
- ret += " <h3><a name='universal-selector'>6.2. Universal selector</a></h3>";
- ret += " <p>The <dfn>universal selector</dfn>, written 'asterisk'";
- ret += " (<code>*</code>), represents the qualified name of any element";
- ret += " specified, see <a href='#univnmsp'>Universal selector and";
- ret += " Namespaces</a> below.</p>";
- ret += " <p>If the universal selector is not the only component of a sequence";
- ret += " of simple selectors, the <code>*</code> may be omitted.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <ul>";
- ret += " <li><code>*[hreflang|=en]</code> and <code>[hreflang|=en]</code> are";
- ret += " </li>";
- ret += " <li><code>*.warning</code> and <code>.warning</code> are equivalent,";
- ret += " </li>";
- ret += " <li><code>*#myid</code> and <code>#myid</code> are equivalent.</li>";
- ret += " </ul>";
- ret += " </div>";
- ret += " <p class='note'><strong>Note:</strong> it is recommended that the";
- ret += " <code>*</code>, representing the universal selector, not be";
- ret += " omitted.</p>";
- ret += " <h4><a name='univnmsp'>6.2.1. Universal selector and namespaces</a></h4>";
- ret += " <p>The universal selector allows an optional namespace component. It";
- ret += " is used as follows:</p>";
- ret += " <dl>";
- ret += " <dt><code>ns|*</code></dt>";
- ret += " <dd>all elements in namespace ns</dd>";
- ret += " <dt><code>*|*</code></dt>";
- ret += " <dd>all elements</dd>";
- ret += " <dt><code>|*</code></dt>";
- ret += " <dd>all elements without any declared namespace</dd>";
- ret += " <dt><code>*</code></dt>";
- ret += " <dd>if no default namespace has been specified, this is equivalent to *|*.";
- ret += " </dd>";
- ret += " </dl>";
- ret += " <p>A universal selector containing a namespace prefix that has not";
- ret += " been previously declared is an <a href='#Conformance'>invalid</a>";
- ret += " to the language implementing Selectors. In CSS, such a mechanism is";
- ret += " defined in the General Syntax module.</p>";
- ret += " <h3><a name='attribute-selectors'>6.3. Attribute selectors</a></h3>";
- ret += " <p>Selectors allow the representation of an element's attributes. When";
- ret += " attribute selectors must be considered to match an element if that";
- ret += " attribute selector.</p>";
- ret += " <h4><a name='attribute-representation'>6.3.1. Attribute presence and values";
- ret += " selectors</a></h4>";
- ret += " <p>CSS2 introduced four attribute selectors:</p>";
- ret += " <dl>";
- ret += " <dt><code>[att]</code>";
- ret += " </dt><dd>Represents an element with the <code>att</code> attribute, whatever the";
- ret += " </dd>";
- ret += " <dt><code>[att=val]</code></dt>";
- ret += " <dd>Represents an element with the <code>att</code> attribute whose value is";
- ret += " </dd>";
- ret += " <dt><code>[att~=val]</code></dt>";
- ret += " <dd>Represents an element with the <code>att</code> attribute whose value is";
- ret += " a <a href='#whitespace'>whitespace</a>-separated list of words, one";
- ret += " represent anything (since the words are <em>separated</em> by";
- ret += " </dd>";
- ret += " <dt><code>[att|=val]</code>";
- ret += " </dt><dd>Represents an element with the <code>att</code> attribute, its value";
- ret += " matches (e.g., the <code>hreflang</code> attribute on the";
- ret += " <code>link</code> element in HTML) as described in RFC 3066 (<a href='#refsRFC3066'>[RFC3066]</a>). For <code>lang</code> (or";
- ret += " <code>xml:lang</code>) language subcode matching, please see <a href='#lang-pseudo'>the <code>:lang</code> pseudo-class</a>.";
- ret += " </dd>";
- ret += " </dl>";
- ret += " <p>Attribute values must be identifiers or strings. The";
- ret += " case-sensitivity of attribute names and values in selectors depends on";
- ret += " the document language.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following attribute selector represents an <code>h1</code>";
- ret += " element that carries the <code>title</code> attribute, whatever its";
- ret += " value:</p>";
- ret += " <pre>h1[title]</pre>";
- ret += " <p>In the following example, the selector represents a";
- ret += " <code>span</code> element whose <code>class</code> attribute has";
- ret += " exactly the value 'example':</p>";
- ret += " <pre>span[class='example']</pre>";
- ret += " <p>Multiple attribute selectors can be used to represent several";
- ret += " attribute. Here, the selector represents a <code>span</code> element";
- ret += " whose <code>hello</code> attribute has exactly the value 'Cleveland'";
- ret += " and whose <code>goodbye</code> attribute has exactly the value";
- ret += " 'Columbus':</p>";
- ret += " <pre>span[hello='Cleveland'][goodbye='Columbus']</pre>";
- ret += " <p>The following selectors illustrate the differences between '='";
- ret += " 'copyright copyleft copyeditor' on a <code>rel</code> attribute. The";
- ret += " second selector will only represent an <code>a</code> element with";
- ret += " an <code>href</code> attribute having the exact value";
- ret += " 'http://www.w3.org/'.</p>";
- ret += " <pre>a[rel~='copyright']";
- ret += " a[href='http://www.w3.org/']</pre>";
- ret += " <p>The following selector represents a <code>link</code> element";
- ret += " whose <code>hreflang</code> attribute is exactly 'fr'.</p>";
- ret += " <pre>link[hreflang=fr]</pre>";
- ret += " <p>The following selector represents a <code>link</code> element for";
- ret += " which the values of the <code>hreflang</code> attribute begins with";
- ret += " 'en', including 'en', 'en-US', and 'en-cockney':</p>";
- ret += " <pre>link[hreflang|='en']</pre>";
- ret += " <p>Similarly, the following selectors represents a";
- ret += " <code>DIALOGUE</code> element whenever it has one of two different";
- ret += " values for an attribute <code>character</code>:</p>";
- ret += " <pre>DIALOGUE[character=romeo]";
- ret += " DIALOGUE[character=juliet]</pre>";
- ret += " </div>";
- ret += " <h4><a name='attribute-substrings'></a>6.3.2. Substring matching attribute";
- ret += " selectors</h4>";
- ret += " <p>Three additional attribute selectors are provided for matching";
- ret += " substrings in the value of an attribute:</p>";
- ret += " <dl>";
- ret += " <dt><code>[att^=val]</code></dt>";
- ret += " <dd>Represents an element with the <code>att</code> attribute whose value";
- ret += " </dd>";
- ret += " <dt><code>[att$=val]</code>";
- ret += " </dt><dd>Represents an element with the <code>att</code> attribute whose value";
- ret += " </dd>";
- ret += " <dt><code>[att*=val]</code>";
- ret += " </dt><dd>Represents an element with the <code>att</code> attribute whose value";
- ret += " </dd>";
- ret += " </dl>";
- ret += " <p>Attribute values must be identifiers or strings. The";
- ret += " case-sensitivity of attribute names in selectors depends on the";
- ret += " document language.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following selector represents an HTML <code>object</code>,";
- ret += " image:</p>";
- ret += " <pre>object[type^='image/']</pre>";
- ret += " <p>The following selector represents an HTML anchor <code>a</code> with an";
- ret += " <code>href</code> attribute whose value ends with '.html'.</p>";
- ret += " <pre>a[href$='.html']</pre>";
- ret += " <p>The following selector represents an HTML paragraph with a";
- ret += " <code>title</code>";
- ret += " attribute whose value contains the substring 'hello'</p>";
- ret += " <pre>p[title*='hello']</pre>";
- ret += " </div>";
- ret += " <h4><a name='attrnmsp'>6.3.3. Attribute selectors and namespaces</a></h4>";
- ret += " <p>Attribute selectors allow an optional namespace component to the";
- ret += " separator 'vertical bar' (<code>|</code>). In keeping with";
- ret += " apply to attributes, therefore attribute selectors without a namespace";
- ret += " (equivalent to '<code>|attr</code>'). An asterisk may be used for the";
- ret += " </p><p>An attribute selector with an attribute name containing a namespace";
- ret += " prefix that has not been previously declared is an <a href='#Conformance'>invalid</a> selector. The mechanism for";
- ret += " a namespace prefix is left up to the language implementing Selectors.";
- ret += " </p><div class='example'>";
- ret += " <p>CSS examples:</p>";
- ret += " <pre>@namespace foo 'http://www.example.com';";
- ret += " [att] { color: green }</pre>";
- ret += " <p>The first rule will match only elements with the attribute";
- ret += " <code>att</code> in the 'http://www.example.com' namespace with the";
- ret += " value 'val'.</p>";
- ret += " <p>The second rule will match only elements with the attribute";
- ret += " <code>att</code> regardless of the namespace of the attribute";
- ret += " (including no declared namespace).</p>";
- ret += " <p>The last two rules are equivalent and will match only elements";
- ret += " with the attribute <code>att</code> where the attribute is not";
- ret += " declared to be in a namespace.</p>";
- ret += " </div>";
- ret += " <h4><a name='def-values'>6.3.4. Default attribute values in DTDs</a></h4>";
- ret += " <p>Attribute selectors represent explicitly set attribute values in";
- ret += " selectors. Selectors should be designed so that they work even if the";
- ret += " default values are not included in the document tree.</p>";
- ret += " <p>More precisely, a UA is <em>not</em> required to read an 'external";
- ret += " subset' of the DTD but <em>is</em> required to look for default";
- ret += " attribute values in the document's 'internal subset.' (See <a href='#refsXML10'>[XML10]</a> for definitions of these subsets.)</p>";
- ret += " <p>A UA that recognizes an XML namespace <a href='#refsXMLNAMES'>[XMLNAMES]</a> is not required to use its";
- ret += " required to use its built-in knowledge of the XHTML DTD.)</p>";
- ret += " <p class='note'><strong>Note:</strong> Typically, implementations";
- ret += " choose to ignore external subsets.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>Consider an element EXAMPLE with an attribute 'notation' that has a";
- ret += " default value of 'decimal'. The DTD fragment might be</p>";
- ret += " <pre class='dtd-example'><!ATTLIST EXAMPLE notation (decimal,octal) 'decimal'></pre>";
- ret += " <p>If the style sheet contains the rules</p>";
- ret += " <pre>EXAMPLE[notation=decimal] { /*... default property settings ...*/ }";
- ret += " EXAMPLE[notation=octal] { /*... other settings...*/ }</pre>";
- ret += " <p>the first rule will not match elements whose 'notation' attribute";
- ret += " attribute selector for the default value must be dropped:</p>";
- ret += " <pre>EXAMPLE { /*... default property settings ...*/ }";
- ret += " EXAMPLE[notation=octal] { /*... other settings...*/ }</pre>";
- ret += " <p>Here, because the selector <code>EXAMPLE[notation=octal]</code> is";
- ret += " cases' style rules.</p>";
- ret += " </div>";
- ret += " <h3><a name='class-html'>6.4. Class selectors</a></h3>";
- ret += " <p>Working with HTML, authors may use the period (U+002E,";
- ret += " <code>.</code>) notation as an alternative to the <code>~=</code>";
- ret += " notation when representing the <code>class</code> attribute. Thus, for";
- ret += " HTML, <code>div.value</code> and <code>div[class~=value]</code> have";
- ret += " 'period' (<code>.</code>).</p>";
- ret += " <p>UAs may apply selectors using the period (.) notation in XML";
- ret += " 1.0 <a href='#refsSVG'>[SVG]</a> describes the <a href='http://www.w3.org/TR/2001/PR-SVG-20010719/styling.html#ClassAttribute'>SVG";
- ret += " 'class' attribute</a> and how a UA should interpret it, and";
- ret += " similarly MathML 1.01 <a href='#refsMATH'>[MATH]</a> describes the <a href='http://www.w3.org/1999/07/REC-MathML-19990707/chapter2.html#sec2.3.4'>MathML";
- ret += " 'class' attribute</a>.)</p>";
- ret += " <div class='example'>";
- ret += " <p>CSS examples:</p>";
- ret += " <p>We can assign style information to all elements with";
- ret += " <code>class~='pastoral'</code> as follows:</p>";
- ret += " <pre>*.pastoral { color: green } /* all elements with class~=pastoral */</pre>";
- ret += " <p>or just</p>";
- ret += " <pre>.pastoral { color: green } /* all elements with class~=pastoral */</pre>";
- ret += " <p>The following assigns style only to H1 elements with";
- ret += " <code>class~='pastoral'</code>:</p>";
- ret += " <pre>H1.pastoral { color: green } /* H1 elements with class~=pastoral */</pre>";
- ret += " <p>Given these rules, the first H1 instance below would not have";
- ret += " green text, while the second would:</p>";
- ret += " <pre><H1>Not green</H1>";
- ret += " <H1 class='pastoral'>Very green</H1></pre>";
- ret += " </div>";
- ret += " <p>To represent a subset of 'class' values, each value must be preceded";
- ret += " by a '.', in any order.</p>";
- ret += " <div class='example'>";
- ret += " <p>CSS example:</p>";
- ret += " <p>The following rule matches any P element whose 'class' attribute";
- ret += " has been assigned a list of <a href='#whitespace'>whitespace</a>-separated values that includes";
- ret += " 'pastoral' and 'marine':</p>";
- ret += " <pre>p.pastoral.marine { color: green }</pre>";
- ret += " <p>This rule matches when <code>class='pastoral blue aqua";
- ret += " marine'</code> but does not match for <code>class='pastoral";
- ret += " blue'</code>.</p>";
- ret += " </div>";
- ret += " <p class='note'><strong>Note:</strong> Because CSS gives considerable";
- ret += " not.</p>";
- ret += " <p class='note'><strong>Note:</strong> If an element has multiple";
- ret += " this specification.</p>";
- ret += " <h3><a name='id-selectors'>6.5. ID selectors</a></h3>";
- ret += " <p>Document languages may contain attributes that are declared to be";
- ret += " applies.</p>";
- ret += " <p>An ID-typed attribute of a document language allows authors to";
- ret += " ID selectors represent an element instance based on its identifier. An";
- ret += " <code>#</code>) immediately followed by the ID value, which must be an";
- ret += " identifier.</p>";
- ret += " <p>Selectors does not specify how a UA knows the ID-typed attribute of";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following ID selector represents an <code>h1</code> element";
- ret += " whose ID-typed attribute has the value 'chapter1':</p>";
- ret += " <pre>h1#chapter1</pre>";
- ret += " <p>The following ID selector represents any element whose ID-typed";
- ret += " attribute has the value 'chapter1':</p>";
- ret += " <pre>#chapter1</pre>";
- ret += " <p>The following selector represents any element whose ID-typed";
- ret += " attribute has the value 'z98y'.</p>";
- ret += " <pre>*#z98y</pre>";
- ret += " </div>";
- ret += " <p class='note'><strong>Note.</strong> In XML 1.0 <a href='#refsXML10'>[XML10]</a>, the information about which attribute";
- ret += " should use normal attribute selectors instead:";
- ret += " <code>[name=p371]</code> instead of <code>#p371</code>. Elements in";
- ret += " XML 1.0 documents without a DTD do not have IDs at all.</p>";
- ret += " <p>If an element has multiple ID attributes, all of them must be";
- ret += " DOM3 Core, XML DTDs, and namespace-specific knowledge.</p>";
- ret += " <h3><a name='pseudo-classes'>6.6. Pseudo-classes</a></h3>";
- ret += " <p>The pseudo-class concept is introduced to permit selection based on";
- ret += " expressed using the other simple selectors.</p>";
- ret += " <p>A pseudo-class always consists of a 'colon'";
- ret += " (<code>:</code>) followed by the name of the pseudo-class and";
- ret += " optionally by a value between parentheses.</p>";
- ret += " <p>Pseudo-classes are allowed in all sequences of simple selectors";
- ret += " sequences of simple selectors, after the leading type selector or";
- ret += " document.</p>";
- ret += " <h4><a name='dynamic-pseudos'>6.6.1. Dynamic pseudo-classes</a></h4>";
- ret += " <p>Dynamic pseudo-classes classify elements on characteristics other";
- ret += " that cannot be deduced from the document tree.</p>";
- ret += " <p>Dynamic pseudo-classes do not appear in the document source or";
- ret += " document tree.</p>";
- ret += " <h5>The <a name='link'>link pseudo-classes: :link and :visited</a></h5>";
- ret += " <p>User agents commonly display unvisited links differently from";
- ret += " previously visited ones. Selectors";
- ret += " provides the pseudo-classes <code>:link</code> and";
- ret += " <code>:visited</code> to distinguish them:</p>";
- ret += " <ul>";
- ret += " <li>The <code>:link</code> pseudo-class applies to links that have";
- ret += " </li>";
- ret += " <li>The <code>:visited</code> pseudo-class applies once the link has";
- ret += " </li>";
- ret += " </ul>";
- ret += " <p>After some amount of time, user agents may choose to return a";
- ret += " visited link to the (unvisited) ':link' state.</p>";
- ret += " <p>The two states are mutually exclusive.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>The following selector represents links carrying class";
- ret += " <code>external</code> and already visited:</p>";
- ret += " <pre>a.external:visited</pre>";
- ret += " </div>";
- ret += " <p class='note'><strong>Note:</strong> It is possible for style sheet";
- ret += " </p><p>UAs may therefore treat all links as unvisited links, or implement";
- ret += " and unvisited links differently.</p>";
- ret += " <h5>The <a name='useraction-pseudos'>user action pseudo-classes";
- ret += " :hover, :active, and :focus</a></h5>";
- ret += " <p>Interactive user agents sometimes change the rendering in response";
- ret += " to user actions. Selectors provides";
- ret += " acting on.</p>";
- ret += " <ul>";
- ret += " <li>The <code>:hover</code> pseudo-class applies while the user";
- ret += " element. User agents not that do not support <a href='http://www.w3.org/TR/REC-CSS2/media.html#interactive-media-group'>interactive";
- ret += " media</a> do not have to support this pseudo-class. Some conforming";
- ret += " user agents that support <a href='http://www.w3.org/TR/REC-CSS2/media.html#interactive-media-group'>interactive";
- ret += " media</a> may not be able to support this pseudo-class (e.g., a pen";
- ret += " </li>";
- ret += " <li>The <code>:active</code> pseudo-class applies while an element";
- ret += " </li>";
- ret += " <li>The <code>:focus</code> pseudo-class applies while an element";
- ret += " </li>";
- ret += " </ul>";
- ret += " <p>There may be document language or implementation specific limits on";
- ret += " which elements can become <code>:active</code> or acquire";
- ret += " <code>:focus</code>.</p>";
- ret += " <p>These pseudo-classes are not mutually exclusive. An element may";
- ret += " match several pseudo-classes at the same time.</p>";
- ret += " <p>Selectors doesn't define if the parent of an element that is";
- ret += " ':active' or ':hover' is also in that state.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <pre>a:link /* unvisited links */";
- ret += " a:active /* active links */</pre>";
- ret += " <p>An example of combining dynamic pseudo-classes:</p>";
- ret += " <pre>a:focus";
- ret += " a:focus:hover</pre>";
- ret += " <p>The last selector matches <code>a</code> elements that are in";
- ret += " the pseudo-class :focus and in the pseudo-class :hover.</p>";
- ret += " </div>";
- ret += " <p class='note'><strong>Note:</strong> An element can be both ':visited'";
- ret += " and ':active' (or ':link' and ':active').</p>";
- ret += " <h4><a name='target-pseudo'>6.6.2. The target pseudo-class :target</a></h4>";
- ret += " <p>Some URIs refer to a location within a resource. This kind of URI";
- ret += " identifier (called the fragment identifier).</p>";
- ret += " <p>URIs with fragment identifiers link to a certain element within the";
- ret += " pointing to an anchor named <code>section_2</code> in an HTML";
- ret += " document:</p>";
- ret += " <pre>http://example.com/html/top.html#section_2</pre>";
- ret += " <p>A target element can be represented by the <code>:target</code>";
- ret += " the document has no target element.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <pre>p.note:target</pre>";
- ret += " <p>This selector represents a <code>p</code> element of class";
- ret += " <code>note</code> that is the target element of the referring";
- ret += " URI.</p>";
- ret += " </div>";
- ret += " <div class='example'>";
- ret += " <p>CSS example:</p>";
- ret += " <p>Here, the <code>:target</code> pseudo-class is used to make the";
- ret += " target element red and place an image before it, if there is one:</p>";
- ret += " <pre>*:target { color : red }";
- ret += " *:target::before { content : url(target.png) }</pre>";
- ret += " </div>";
- ret += " <h4><a name='lang-pseudo'>6.6.3. The language pseudo-class :lang</a></h4>";
- ret += " <p>If the document language specifies how the human language of an";
- ret += " element is determined, it is possible to write selectors that";
- ret += " represent an element based on its language. For example, in HTML <a href='#refsHTML4'>[HTML4]</a>, the language is determined by a";
- ret += " combination of the <code>lang</code> attribute, the <code>meta</code>";
- ret += " headers). XML uses an attribute called <code>xml:lang</code>, and";
- ret += " the language.</p>";
- ret += " <p>The pseudo-class <code>:lang(C)</code> represents an element that";
- ret += " <code>:lang()</code> selector is based solely on the identifier C";
- ret += " element's language value, in the same way as if performed by the <a href='#attribute-representation'>'|='</a> operator in attribute";
- ret += " selectors. The identifier C does not have to be a valid language";
- ret += " name.</p>";
- ret += " <p>C must not be empty. (If it is, the selector is invalid.)</p>";
- ret += " <p class='note'><strong>Note:</strong> It is recommended that";
- ret += " documents and protocols indicate language using codes from RFC 3066 <a href='#refsRFC3066'>[RFC3066]</a> or its successor, and by means of";
- ret += " 'xml:lang' attributes in the case of XML-based documents <a href='#refsXML10'>[XML10]</a>. See <a href='http://www.w3.org/International/questions/qa-lang-2or3.html'>";
- ret += " 'FAQ: Two-letter or three-letter language codes.'</a></p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The two following selectors represent an HTML document that is in";
- ret += " Belgian, French, or German. The two next selectors represent";
- ret += " <code>q</code> quotations in an arbitrary element in Belgian, French,";
- ret += " or German.</p>";
- ret += " <pre>html:lang(fr-be)";
- ret += " :lang(de) > q</pre>";
- ret += " </div>";
- ret += " <h4><a name='UIstates'>6.6.4. The UI element states pseudo-classes</a></h4>";
- ret += " <h5><a name='enableddisabled'>The :enabled and :disabled pseudo-classes</a></h5>";
- ret += " <p>The <code>:enabled</code> pseudo-class allows authors to customize";
- ret += " an enabled <code>input</code> element without also specifying what it";
- ret += " would look like when it was disabled.</p>";
- ret += " <p>Similar to <code>:enabled</code>, <code>:disabled</code> allows the";
- ret += " element should look.</p>";
- ret += " <p>Most elements will be neither enabled nor disabled. An element is";
- ret += " presently activate it or transfer focus to it.</p>";
- ret += " <h5><a name='checked'>The :checked pseudo-class</a></h5>";
- ret += " <p>Radio and checkbox elements can be toggled by the user. Some menu";
- ret += " toggled 'on' the <code>:checked</code> pseudo-class applies. The";
- ret += " <code>:checked</code> pseudo-class initially applies to such elements";
- ret += " that have the HTML4 <code>selected</code> and <code>checked</code>";
- ret += " attributes as described in <a href='http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.2.1'>Section";
- ret += " 17.2.1 of HTML4</a>, but of course the user can toggle 'off' such";
- ret += " elements in which case the <code>:checked</code> pseudo-class would no";
- ret += " longer apply. While the <code>:checked</code> pseudo-class is dynamic";
- ret += " on the presence of the semantic HTML4 <code>selected</code> and";
- ret += " <code>checked</code> attributes, it applies to all media.";
- ret += " </p><h5><a name='indeterminate'>The :indeterminate pseudo-class</a></h5>";
- ret += " <div class='note'>";
- ret += " <p>Radio and checkbox elements can be toggled by the user, but are";
- ret += " This can be due to an element attribute, or DOM manipulation.</p>";
- ret += " <p>A future version of this specification may introduce an";
- ret += " <code>:indeterminate</code> pseudo-class that applies to such elements.";
- ret += " <!--While the <code>:indeterminate</code> pseudo-class is dynamic in";
- ret += " the presence of an element attribute, it applies to all media.</p>";
- ret += " <p>Components of a radio-group initialized with no pre-selected choice";
- ret += " are an example of :indeterminate state.--></p>";
- ret += " </div>";
- ret += " <h4><a name='structural-pseudos'>6.6.5. Structural pseudo-classes</a></h4>";
- ret += " <p>Selectors introduces the concept of <dfn>structural";
- ret += " pseudo-classes</dfn> to permit selection based on extra information that";
- ret += " the document tree but cannot be represented by other simple selectors or";
- ret += " </p><p>Note that standalone pieces of PCDATA (text nodes in the DOM) are";
- ret += " </p><h5><a name='root-pseudo'>:root pseudo-class</a></h5>";
- ret += " <p>The <code>:root</code> pseudo-class represents an element that is";
- ret += " <code>HTML</code> element.";
- ret += " </p><h5><a name='nth-child-pseudo'>:nth-child() pseudo-class</a></h5>";
- ret += " <p>The";
- ret += " <code>:nth-child(<var>a</var><code>n</code>+<var>b</var>)</code>";
- ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings";
- ret += " <strong>before</strong> it in the document tree, for a given positive";
- ret += " integer or zero value of <code>n</code>, and has a parent element. In";
- ret += " other words, this matches the <var>b</var>th child of an element after";
- ret += " all the children have been split into groups of <var>a</var> elements";
- ret += " each. For example, this allows the selectors to address every other";
- ret += " of paragraph text in a cycle of four. The <var>a</var> and";
- ret += " <var>b</var> values must be zero, negative integers or positive";
- ret += " </p><p>In addition to this, <code>:nth-child()</code> can take";
- ret += " '<code>odd</code>' and '<code>even</code>' as arguments instead.";
- ret += " '<code>odd</code>' has the same signification as <code>2n+1</code>,";
- ret += " and '<code>even</code>' has the same signification as <code>2n</code>.";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <pre>tr:nth-child(2n+1) /* represents every odd row of an HTML table */";
- ret += " p:nth-child(4n+4) { color: purple; }</pre>";
- ret += " </div>";
- ret += " <p>When <var>a</var>=0, no repeating is used, so for example";
- ret += " <code>:nth-child(0n+5)</code> matches only the fifth child. When";
- ret += " <var>a</var>=0, the <var>a</var><code>n</code> part need not be";
- ret += " <code>:nth-child(<var>b</var>)</code> and the last example simplifies";
- ret += " to <code>:nth-child(5)</code>.";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <pre>foo:nth-child(0n+1) /* represents an element foo, first child of its parent element */";
- ret += " foo:nth-child(1) /* same */</pre>";
- ret += " </div>";
- ret += " <p>When <var>a</var>=1, the number may be omitted from the rule.";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following selectors are therefore equivalent:</p>";
- ret += " <pre>bar:nth-child(1n+0) /* represents all bar elements, specificity (0,1,1) */";
- ret += " bar /* same but lower specificity (0,0,1) */</pre>";
- ret += " </div>";
- ret += " <p>If <var>b</var>=0, then every <var>a</var>th element is picked. In";
- ret += " such a case, the <var>b</var> part may be omitted.";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <pre>tr:nth-child(2n+0) /* represents every even row of an HTML table */";
- ret += " tr:nth-child(2n) /* same */</pre>";
- ret += " </div>";
- ret += " <p>If both <var>a</var> and <var>b</var> are equal to zero, the";
- ret += " pseudo-class represents no element in the document tree.</p>";
- ret += " <p>The value <var>a</var> can be negative, but only the positive";
- ret += " values of <var>a</var><code>n</code>+<var>b</var>, for";
- ret += " <code>n</code>≥0, may represent an element in the document";
- ret += " tree.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <pre>html|tr:nth-child(-n+6) /* represents the 6 first rows of XHTML tables */</pre>";
- ret += " </div>";
- ret += " <p>When the value <var>b</var> is negative, the '+' character in the";
- ret += " character indicating the negative value of <var>b</var>).</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <pre>:nth-child(10n-1) /* represents the 9th, 19th, 29th, etc, element */";
- ret += " :nth-child(10n+-1) /* Syntactically invalid, and would be ignored */</pre>";
- ret += " </div>";
- ret += " <h5><a name='nth-last-child-pseudo'>:nth-last-child() pseudo-class</a></h5>";
- ret += " <p>The <code>:nth-last-child(<var>a</var>n+<var>b</var>)</code>";
- ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings";
- ret += " <strong>after</strong> it in the document tree, for a given positive";
- ret += " integer or zero value of <code>n</code>, and has a parent element. See";
- ret += " <code>:nth-child()</code> pseudo-class for the syntax of its argument.";
- ret += " It also accepts the '<code>even</code>' and '<code>odd</code>' values";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <pre>tr:nth-last-child(-n+2) /* represents the two last rows of an HTML table */";
- ret += " counting from the last one */</pre>";
- ret += " </div>";
- ret += " <h5><a name='nth-of-type-pseudo'>:nth-of-type() pseudo-class</a></h5>";
- ret += " <p>The <code>:nth-of-type(<var>a</var>n+<var>b</var>)</code>";
- ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings with the same";
- ret += " element name <strong>before</strong> it in the document tree, for a";
- ret += " given zero or positive integer value of <code>n</code>, and has a";
- ret += " parent element. In other words, this matches the <var>b</var>th child";
- ret += " groups of a elements each. See <code>:nth-child()</code> pseudo-class";
- ret += " '<code>even</code>' and '<code>odd</code>' values.";
- ret += " </p><div class='example'>";
- ret += " <p>CSS example:</p>";
- ret += " <p>This allows an author to alternate the position of floated images:</p>";
- ret += " <pre>img:nth-of-type(2n+1) { float: right; }";
- ret += " img:nth-of-type(2n) { float: left; }</pre>";
- ret += " </div>";
- ret += " <h5><a name='nth-last-of-type-pseudo'>:nth-last-of-type() pseudo-class</a></h5>";
- ret += " <p>The <code>:nth-last-of-type(<var>a</var>n+<var>b</var>)</code>";
- ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings with the same";
- ret += " element name <strong>after</strong> it in the document tree, for a";
- ret += " given zero or positive integer value of <code>n</code>, and has a";
- ret += " parent element. See <code>:nth-child()</code> pseudo-class for the";
- ret += " syntax of its argument. It also accepts the '<code>even</code>' and '<code>odd</code>'";
- ret += " </p><div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>To represent all <code>h2</code> children of an XHTML";
- ret += " <code>body</code> except the first and last, one could use the";
- ret += " following selector:</p>";
- ret += " <pre>body > h2:nth-of-type(n+2):nth-last-of-type(n+2)</pre>";
- ret += " <p>In this case, one could also use <code>:not()</code>, although the";
- ret += " selector ends up being just as long:</p>";
- ret += " <pre>body > h2:not(:first-of-type):not(:last-of-type)</pre>";
- ret += " </div>";
- ret += " <h5><a name='first-child-pseudo'>:first-child pseudo-class</a></h5>";
- ret += " <p>Same as <code>:nth-child(1)</code>. The <code>:first-child</code>";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following selector represents a <code>p</code> element that is";
- ret += " the first child of a <code>div</code> element:</p>";
- ret += " <pre>div > p:first-child</pre>";
- ret += " <p>This selector can represent the <code>p</code> inside the";
- ret += " <code>div</code> of the following fragment:</p>";
- ret += " <pre><p> The last P before the note.</p>";
- ret += " </div></pre>";
- ret += " but cannot represent the second <code>p</code> in the following";
- ret += " <pre><p> The last P before the note.</p>";
- ret += " </div></pre>";
- ret += " <p>The following two selectors are usually equivalent:</p>";
- ret += " <pre>* > a:first-child /* a is first child of any element */";
- ret += " a:first-child /* Same (assuming a is not the root element) */</pre>";
- ret += " </div>";
- ret += " <h5><a name='last-child-pseudo'>:last-child pseudo-class</a></h5>";
- ret += " <p>Same as <code>:nth-last-child(1)</code>. The <code>:last-child</code>";
- ret += " </p><div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>The following selector represents a list item <code>li</code> that";
- ret += " is the last child of an ordered list <code>ol</code>.";
- ret += " </p><pre>ol > li:last-child</pre>";
- ret += " </div>";
- ret += " <h5><a name='first-of-type-pseudo'>:first-of-type pseudo-class</a></h5>";
- ret += " <p>Same as <code>:nth-of-type(1)</code>. The <code>:first-of-type</code>";
- ret += " </p><div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>The following selector represents a definition title";
- ret += " <code>dt</code> inside a definition list <code>dl</code>, this";
- ret += " <code>dt</code> being the first of its type in the list of children of";
- ret += " its parent element.</p>";
- ret += " <pre>dl dt:first-of-type</pre>";
- ret += " <p>It is a valid description for the first two <code>dt</code>";
- ret += " elements in the following example but not for the third one:</p>";
- ret += " <pre><dl>";
- ret += " </dl></pre>";
- ret += " </div>";
- ret += " <h5><a name='last-of-type-pseudo'>:last-of-type pseudo-class</a></h5>";
- ret += " <p>Same as <code>:nth-last-of-type(1)</code>. The";
- ret += " <code>:last-of-type</code> pseudo-class represents an element that is";
- ret += " element.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>The following selector represents the last data cell";
- ret += " <code>td</code> of a table row.</p>";
- ret += " <pre>tr > td:last-of-type</pre>";
- ret += " </div>";
- ret += " <h5><a name='only-child-pseudo'>:only-child pseudo-class</a></h5>";
- ret += " <p>Represents an element that has a parent element and whose parent";
- ret += " <code>:first-child:last-child</code> or";
- ret += " <code>:nth-child(1):nth-last-child(1)</code>, but with a lower";
- ret += " specificity.</p>";
- ret += " <h5><a name='only-of-type-pseudo'>:only-of-type pseudo-class</a></h5>";
- ret += " <p>Represents an element that has a parent element and whose parent";
- ret += " as <code>:first-of-type:last-of-type</code> or";
- ret += " <code>:nth-of-type(1):nth-last-of-type(1)</code>, but with a lower";
- ret += " specificity.</p>";
- ret += " <h5><a name='empty-pseudo'></a>:empty pseudo-class</h5>";
- ret += " <p>The <code>:empty</code> pseudo-class represents an element that has";
- ret += " empty or not.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p><code>p:empty</code> is a valid representation of the following fragment:";
- ret += " </p>";
- ret += " <pre><p></p></pre>";
- ret += " <p><code>foo:empty</code> is not a valid representation for the";
- ret += " following fragments:</p>";
- ret += " <pre><foo>bar</foo></pre>";
- ret += " <pre><foo><bar>bla</bar></foo></pre>";
- ret += " <pre><foo>this is not <bar>:empty</bar></foo></pre>";
- ret += " </div>";
- ret += " <h4><a name='content-selectors'>6.6.6. Blank</a></h4>";
- ret += " <!-- It's the Return of Appendix H!!! Run away! -->";
- ret += " <p>This section intentionally left blank.</p>";
- ret += " <!-- (used to be :contains()) -->";
- ret += " <h4><a name='negation'></a>6.6.7. The negation pseudo-class</h4>";
- ret += " <p>The negation pseudo-class, <code>:not(<var>X</var>)</code>, is a";
- ret += " functional notation taking a <a href='#simple-selectors-dfn'>simple";
- ret += " selector</a> (excluding the negation pseudo-class itself and";
- ret += " <!-- pseudo-elements are not simple selectors, so the above paragraph";
- ret += " may be a bit confusing -->";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following CSS selector matches all <code>button</code>";
- ret += " elements in an HTML document that are not disabled.</p>";
- ret += " <pre>button:not([DISABLED])</pre>";
- ret += " <p>The following selector represents all but <code>FOO</code>";
- ret += " elements.</p>";
- ret += " <pre>*:not(FOO)</pre>";
- ret += " <p>The following group of selectors represents all HTML elements";
- ret += " except links.</p>";
- ret += " <pre>html|*:not(:link):not(:visited)</pre>";
- ret += " </div>";
- ret += " <p>Default namespace declarations do not affect the argument of the";
- ret += " type selector.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>Assuming that the default namespace is bound to";
- ret += " elements that are not in that namespace:</p>";
- ret += " <pre>*|*:not(*)</pre>";
- ret += " <p>The following CSS selector matches any element being hovered,";
- ret += " rule when they <em>are</em> being hovered.</p>";
- ret += " <pre>*|*:not(:hover)</pre>";
- ret += " </div>";
- ret += " <p class='note'><strong>Note</strong>: the :not() pseudo allows";
- ret += " useless selectors to be written. For instance <code>:not(*|*)</code>,";
- ret += " which represents no element at all, or <code>foo:not(bar)</code>,";
- ret += " which is equivalent to <code>foo</code> but with a higher";
- ret += " specificity.</p>";
- ret += " <h3><a name='pseudo-elements'>7. Pseudo-elements</a></h3>";
- ret += " <p>Pseudo-elements create abstractions about the document tree beyond";
- ret += " source document (e.g., the <code>::before</code> and";
- ret += " <code>::after</code> pseudo-elements give access to generated";
- ret += " content).</p>";
- ret += " <p>A pseudo-element is made of two colons (<code>::</code>) followed";
- ret += " by the name of the pseudo-element.</p>";
- ret += " <p>This <code>::</code> notation is introduced by the current document";
- ret += " <code>:first-line</code>, <code>:first-letter</code>,";
- ret += " <code>:before</code> and <code>:after</code>). This compatibility is";
- ret += " not allowed for the new pseudo-elements introduced in CSS level 3.</p>";
- ret += " <p>Only one pseudo-element may appear per selector, and if present it";
- ret += " must appear after the sequence of simple selectors that represents the";
- ret += " <a href='#subject'>subjects</a> of the selector. <span class='note'>A";
- ret += " pesudo-elements per selector.</span></p>";
- ret += " <h4><a name='first-line'>7.1. The ::first-line pseudo-element</a></h4>";
- ret += " <p>The <code>::first-line</code> pseudo-element describes the contents";
- ret += " </p><div class='example'>";
- ret += " <p>CSS example:</p>";
- ret += " <pre>p::first-line { text-transform: uppercase }</pre>";
- ret += " <p>The above rule means 'change the letters of the first line of every";
- ret += " paragraph to uppercase'.</p>";
- ret += " </div>";
- ret += " <p>The selector <code>p::first-line</code> does not match any real";
- ret += " agents will insert at the beginning of every paragraph.</p>";
- ret += " <p>Note that the length of the first line depends on a number of";
- ret += " an ordinary HTML paragraph such as:</p>";
- ret += " <pre> <P>This is a somewhat long HTML ";
- ret += " </pre>";
- ret += " <p>the lines of which happen to be broken as follows:";
- ret += " </p><pre> THIS IS A SOMEWHAT LONG HTML PARAGRAPH THAT";
- ret += " </pre>";
- ret += " <p>This paragraph might be 'rewritten' by user agents to include the";
- ret += " <em>fictional tag sequence</em> for <code>::first-line</code>. This";
- ret += " fictional tag sequence helps to show how properties are inherited.</p>";
- ret += " <pre> <P><b><P::first-line></b> This is a somewhat long HTML ";
- ret += " paragraph that <b></P::first-line></b> will be broken into several";
- ret += " </pre>";
- ret += " <p>If a pseudo-element breaks up a real element, the desired effect";
- ret += " with a <code>span</code> element:</p>";
- ret += " <pre> <P><b><SPAN class='test'></b> This is a somewhat long HTML";
- ret += " lines.<b></SPAN></b> The first line will be identified";
- ret += " </pre>";
- ret += " <p>the user agent could simulate start and end tags for";
- ret += " <code>span</code> when inserting the fictional tag sequence for";
- ret += " <code>::first-line</code>.";
- ret += " </p><pre> <P><P::first-line><b><SPAN class='test'></b> This is a";
- ret += " paragraph that will <b></SPAN></b></P::first-line><b><SPAN";
- ret += " class='test'></b> be";
- ret += " lines.<b></SPAN></b> The first line will be identified";
- ret += " </pre>";
- ret += " <p>In CSS, the <code>::first-line</code> pseudo-element can only be";
- ret += " or a table-cell.</p>";
- ret += " <p><a name='first-formatted-line'></a>The 'first formatted line' of an";
- ret += " line of the <code>div</code> in <code><DIV><P>This";
- ret += " line...</P></DIV></code> is the first line of the <code>p</code>";
- ret += " that both <code>p</code> and <code>div</code> are block-level).";
- ret += " </p><p>The first line of a table-cell or inline-block cannot be the first";
- ret += " formatted line of an ancestor element. Thus, in <code><DIV><P";
- ret += " etcetera</DIV></code> the first formatted line of the";
- ret += " <code>div</code> is not the line 'Hello'.";
- ret += " </p><p class='note'>Note that the first line of the <code>p</code> in this";
- ret += " fragment: <code><p><br>First...</code> doesn't contain any";
- ret += " letters (assuming the default style for <code>br</code> in HTML";
- ret += " </p><p>A UA should act as if the fictional start tags of the";
- ret += " <code>::first-line</code> pseudo-elements were nested just inside the";
- ret += " is an example. The fictional tag sequence for</p>";
- ret += " <pre> <DIV>";
- ret += " </pre>";
- ret += " <p>is</p>";
- ret += " <pre> <DIV>";
- ret += " </pre>";
- ret += " <p>The <code>::first-line</code> pseudo-element is similar to an";
- ret += " following properties apply to a <code>::first-line</code>";
- ret += " properties as well.</p>";
- ret += " <h4><a name='first-letter'>7.2. The ::first-letter pseudo-element</a></h4>";
- ret += " <p>The <code>::first-letter</code> pseudo-element represents the first";
- ret += " is 'none'; otherwise, it is similar to a floated element.</p>";
- ret += " <p>In CSS, these are the properties that apply to <code>::first-letter</code>";
- ret += " of the letter, unlike for normal elements.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>This example shows a possible rendering of an initial cap. Note";
- ret += " <code>::first-letter</code>";
- ret += " fictional start tag of the first letter is inside the <span>span</span>,";
- ret += " the font weight of the first letter is normal, not bold as the <span>span</span>:";
- ret += " </p><pre> p { line-height: 1.1 }";
- ret += " </pre>";
- ret += " <div class='figure'>";
- ret += " <p><img src='' alt='Image illustrating the ::first-letter pseudo-element'>";
- ret += " </p></div>";
- ret += " </div>";
- ret += " <div class='example'>";
- ret += " <p>The following CSS will make a drop cap initial letter span about two";
- ret += " lines:</p>";
- ret += " <pre> <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN'>";
- ret += " </pre>";
- ret += " <p>This example might be formatted as follows:</p>";
- ret += " <div class='figure'>";
- ret += " <p><img src='' alt='Image illustrating the combined effect of the ::first-letter and ::first-line pseudo-elements'>";
- ret += " </p>";
- ret += " </div>";
- ret += " <p>The <span class='index-inst' title='fictional tag";
- ret += " sequence'>fictional tag sequence</span> is:</p>";
- ret += " <pre> <P>";
- ret += " </pre>";
- ret += " <p>Note that the <code>::first-letter</code> pseudo-element tags abut";
- ret += " block element.</p></div>";
- ret += " <p>In order to achieve traditional drop caps formatting, user agents";
- ret += " glyph outline may be taken into account when formatting.</p>";
- ret += " <p>Punctuation (i.e, characters defined in Unicode in the 'open' (Ps),";
- ret += " be included. <a href='#refsUNICODE'>[UNICODE]</a></p>";
- ret += " <div class='figure'>";
- ret += " <p><img src='' alt='Quotes that precede the";
- ret += " first letter should be included.'></p>";
- ret += " </div>";
- ret += " <p>The <code>::first-letter</code> also applies if the first letter is";
- ret += " money.'</p>";
- ret += " <p>In CSS, the <code>::first-letter</code> pseudo-element applies to";
- ret += " elements. <span class='note'>A future version of this specification";
- ret += " types.</span></p>";
- ret += " <p>The <code>::first-letter</code> pseudo-element can be used with all";
- ret += " the element, even if that first text is in a descendant.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>The fictional tag sequence for this HTMLfragment:";
- ret += " </p><pre><div>";
- ret += " <p>The first text.</pre>";
- ret += " <p>is:";
- ret += " </p><pre><div>";
- ret += " <p><div::first-letter><p::first-letter>T</...></...>he first text.</pre>";
- ret += " </div>";
- ret += " <p>The first letter of a table-cell or inline-block cannot be the";
- ret += " first letter of an ancestor element. Thus, in <code><DIV><P";
- ret += " etcetera</DIV></code> the first letter of the <code>div</code> is";
- ret += " letter 'H'. In fact, the <code>div</code> doesn't have a first letter.";
- ret += " </p><p>The first letter must occur on the <a href='#first-formatted-line'>first formatted line.</a> For example, in";
- ret += " this fragment: <code><p><br>First...</code> the first line";
- ret += " doesn't contain any letters and <code>::first-letter</code> doesn't";
- ret += " match anything (assuming the default style for <code>br</code> in HTML";
- ret += " </p><p>In CSS, if an element is a list item ('display: list-item'), the";
- ret += " <code>::first-letter</code> applies to the first letter in the";
- ret += " <code>::first-letter</code> on list items with 'list-style-position:";
- ret += " inside'. If an element has <code>::before</code> or";
- ret += " <code>::after</code> content, the <code>::first-letter</code> applies";
- ret += " to the first letter of the element <em>including</em> that content.";
- ret += " </p><div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p>After the rule 'p::before {content: 'Note: '}', the selector";
- ret += " 'p::first-letter' matches the 'N' of 'Note'.</p>";
- ret += " </div>";
- ret += " <p>Some languages may have specific rules about how to treat certain";
- ret += " considered within the <code>::first-letter</code> pseudo-element.";
- ret += " </p><p>If the letters that would form the ::first-letter are not in the";
- ret += " same element, such as ''T' in <code><p>'<em>T...</code>, the UA";
- ret += " both elements, or simply not create a pseudo-element.</p>";
- ret += " <p>Similarly, if the first letter(s) of the block are not at the start";
- ret += " </p><div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <p><a name='overlapping-example'>The following example</a> illustrates";
- ret += " paragraph will be 'red'.</p>";
- ret += " <pre>p { color: red; font-size: 12pt }";
- ret += " <P>Some text that ends up on two lines</P></pre>";
- ret += " <p>Assuming that a line break will occur before the word 'ends', the";
- ret += " <span class='index-inst' title='fictional tag sequence'>fictional tag";
- ret += " sequence</span> for this fragment might be:</p>";
- ret += " <pre><P>";
- ret += " </P></pre>";
- ret += " <p>Note that the <code>::first-letter</code> element is inside the <code>::first-line</code>";
- ret += " element. Properties set on <code>::first-line</code> are inherited by";
- ret += " <code>::first-letter</code>, but are overridden if the same property is";
- ret += " <code>::first-letter</code>.</p>";
- ret += " </div>";
- ret += " <h4><a name='UIfragments'>7.3.</a> <a name='selection'>The ::selection";
- ret += " pseudo-element</a></h4>";
- ret += " <p>The <code>::selection</code> pseudo-element applies to the portion";
- ret += " field. This pseudo-element should not be confused with the <code><a href='#checked'>:checked</a></code> pseudo-class (which used to be";
- ret += " named <code>:selected</code>)";
- ret += " </p><p>Although the <code>::selection</code> pseudo-element is dynamic in";
- ret += " <a href='#refsCSS21'>[CSS21]</a>) which was originally rendered to a";
- ret += " <code>::selection</code> state to that other medium, and have all the";
- ret += " required — UAs may omit the <code>::selection</code>";
- ret += " </p><p>These are the CSS properties that apply to <code>::selection</code>";
- ret += " <code>::selection</code> may be ignored.";
- ret += " </p><h4><a name='gen-content'>7.4. The ::before and ::after pseudo-elements</a></h4>";
- ret += " <p>The <code>::before</code> and <code>::after</code> pseudo-elements";
- ret += " content. They are explained in CSS 2.1 <a href='#refsCSS21'>[CSS21]</a>.</p>";
- ret += " <p>When the <code>::first-letter</code> and <code>::first-line</code>";
- ret += " pseudo-elements are combined with <code>::before</code> and";
- ret += " <code>::after</code>, they apply to the first letter or line of the";
- ret += " element including the inserted text.</p>";
- ret += " <h2><a name='combinators'>8. Combinators</a></h2>";
- ret += " <h3><a name='descendant-combinators'>8.1. Descendant combinator</a></h3>";
- ret += " <p>At times, authors may want selectors to describe an element that is";
- ret += " <code>EM</code> element that is contained within an <code>H1</code>";
- ret += " descendant combinator is <a href='#whitespace'>white space</a> that";
- ret += " separates two sequences of simple selectors. A selector of the form";
- ret += " '<code>A B</code>' represents an element <code>B</code> that is an";
- ret += " arbitrary descendant of some ancestor element <code>A</code>.";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>For example, consider the following selector:</p>";
- ret += " <pre>h1 em</pre>";
- ret += " <p>It represents an <code>em</code> element being the descendant of";
- ret += " an <code>h1</code> element. It is a correct and valid, but partial,";
- ret += " description of the following fragment:</p>";
- ret += " <pre><h1>This <span class='myclass'>headline";
- ret += " is <em>very</em> important</span></h1></pre>";
- ret += " <p>The following selector:</p>";
- ret += " <pre>div * p</pre>";
- ret += " <p>represents a <code>p</code> element that is a grandchild or later";
- ret += " descendant of a <code>div</code> element. Note the whitespace on";
- ret += " of the P.</p>";
- ret += " <p>The following selector, which combines descendant combinators and";
- ret += " <a href='#attribute-selectors'>attribute selectors</a>, represents an";
- ret += " element that (1) has the <code>href</code> attribute set and (2) is";
- ret += " inside a <code>p</code> that is itself inside a <code>div</code>:</p>";
- ret += " <pre>div p *[href]</pre>";
- ret += " </div>";
- ret += " <h3><a name='child-combinators'>8.2. Child combinators</a></h3>";
- ret += " <p>A <dfn>child combinator</dfn> describes a childhood relationship";
- ret += " 'greater-than sign' (<code>></code>) character and";
- ret += " separates two sequences of simple selectors.";
- ret += " </p><div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following selector represents a <code>p</code> element that is";
- ret += " child of <code>body</code>:</p>";
- ret += " <pre>body > p</pre>";
- ret += " <p>The following example combines descendant combinators and child";
- ret += " combinators.</p>";
- ret += " <pre>div ol>li p</pre>";
- ret += " <!-- LEAVE THOSE SPACES OUT! see below -->";
- ret += " <p>It represents a <code>p</code> element that is a descendant of an";
- ret += " <code>li</code> element; the <code>li</code> element must be the";
- ret += " child of an <code>ol</code> element; the <code>ol</code> element must";
- ret += " be a descendant of a <code>div</code>. Notice that the optional white";
- ret += " space around the '>' combinator has been left out.</p>";
- ret += " </div>";
- ret += " <p>For information on selecting the first child of an element, please";
- ret += " see the section on the <code><a href='#structural-pseudos'>:first-child</a></code> pseudo-class";
- ret += " above.</p>";
- ret += " <h3><a name='sibling-combinators'>8.3. Sibling combinators</a></h3>";
- ret += " <p>There are two different sibling combinators: the adjacent sibling";
- ret += " considering adjacency of elements.</p>";
- ret += " <h4><a name='adjacent-sibling-combinators'>8.3.1. Adjacent sibling combinator</a>";
- ret += " </h4>";
- ret += " <p>The adjacent sibling combinator is made of the 'plus";
- ret += " sign' (U+002B, <code>+</code>) character that separates two";
- ret += " sequences of simple selectors. The elements represented by the two";
- ret += " represented by the second one.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <p>The following selector represents a <code>p</code> element";
- ret += " immediately following a <code>math</code> element:</p>";
- ret += " <pre>math + p</pre>";
- ret += " <p>The following selector is conceptually similar to the one in the";
- ret += " adds a constraint to the <code>h1</code> element, that it must have";
- ret += " <code>class='opener'</code>:</p>";
- ret += " <pre>h1.opener + h2</pre>";
- ret += " </div>";
- ret += " <h4><a name='general-sibling-combinators'>8.3.2. General sibling combinator</a>";
- ret += " </h4>";
- ret += " <p>The general sibling combinator is made of the 'tilde'";
- ret += " (U+007E, <code>~</code>) character that separates two sequences of";
- ret += " simple selectors. The elements represented by the two sequences share";
- ret += " represented by the second one.</p>";
- ret += " <div class='example'>";
- ret += " <p>Example:</p>";
- ret += " <pre>h1 ~ pre</pre>";
- ret += " <p>represents a <code>pre</code> element following an <code>h1</code>. It";
- ret += " is a correct and valid, but partial, description of:</p>";
- ret += " <pre><h1>Definition of the function a</h1>";
- ret += " <pre>function a(x) = 12x/13.5</pre></pre>";
- ret += " </div>";
- ret += " <h2><a name='specificity'>9. Calculating a selector's specificity</a></h2>";
- ret += " <p>A selector's specificity is calculated as follows:</p>";
- ret += " <ul>";
- ret += " <li>count the number of ID selectors in the selector (= a)</li>";
- ret += " <li>count the number of class selectors, attributes selectors, and";
- ret += " </li>";
- ret += " <li>count the number of element names in the selector (= c)</li>";
- ret += " <li>ignore pseudo-elements</li>";
- ret += " </ul>";
- ret += " <p>Selectors inside <a href='#negation'>the negation pseudo-class</a>";
- ret += " a pseudo-class.</p>";
- ret += " <p>Concatenating the three numbers a-b-c (in a number system with a";
- ret += " large base) gives the specificity.</p>";
- ret += " <div class='example'>";
- ret += " <p>Examples:</p>";
- ret += " <pre>* /* a=0 b=0 c=0 -> specificity = 0 */";
- ret += " </pre>";
- ret += " </div>";
- ret += " <p class='note'><strong>Note:</strong> the specificity of the styles";
- ret += " specified in an HTML <code>style</code> attribute is described in CSS";
- ret += " 2.1. <a href='#refsCSS21'>[CSS21]</a>.</p>";
- ret += " <h2><a name='w3cselgrammar'>10. The grammar of Selectors</a></h2>";
- ret += " <h3><a name='grammar'>10.1. Grammar</a></h3>";
- ret += " <p>The grammar below defines the syntax of Selectors. It is globally";
- ret += " shorthand notations beyond Yacc (see <a href='#refsYACC'>[YACC]</a>)";
- ret += " are used:</p>";
- ret += " <ul>";
- ret += " <li><b>*</b>: 0 or more";
- ret += " </li><li><b>+</b>: 1 or more";
- ret += " </li><li><b>?</b>: 0 or 1";
- ret += " </li><li><b>|</b>: separates alternatives";
- ret += " </li><li><b>[ ]</b>: grouping</li>";
- ret += " </ul>";
- ret += " <p>The productions are:</p>";
- ret += " <pre>selectors_group";
- ret += " ;</pre>";
- ret += " <h3><a name='lex'>10.2. Lexical scanner</a></h3>";
- ret += " <p>The following is the <a name='x3'>tokenizer</a>, written in Flex (see";
- ret += " <a href='#refsFLEX'>[FLEX]</a>) notation. The tokenizer is";
- ret += " case-insensitive.</p>";
- ret += " <p>The two occurrences of '\377' represent the highest character";
- ret += " possible code point in Unicode/ISO-10646. <a href='#refsUNICODE'>[UNICODE]</a></p>";
- ret += " <pre>%option case-insensitive";
- ret += " . return *yytext;</pre>";
- ret += " <h2><a name='downlevel'>11. Namespaces and down-level clients</a></h2>";
- ret += " <p>An important issue is the interaction of CSS selectors with XML";
- ret += " to construct a CSS style sheet which will properly match selectors in";
- ret += " is possible to construct a style sheet in which selectors would match";
- ret += " elements and attributes correctly.</p>";
- ret += " <p>It should be noted that a down-level CSS client will (if it";
- ret += " <code>@namespace</code> at-rules, as well as all style rules that make";
- ret += " use of namespace qualified element type or attribute selectors. The";
- ret += " than possibly match them incorrectly.</p>";
- ret += " <p>The use of default namespaces in CSS makes it possible to write";
- ret += " element type selectors that will function in both namespace aware CSS";
- ret += " down-level clients may incorrectly match selectors against XML";
- ret += " elements in other namespaces.</p>";
- ret += " <p>The following are scenarios and examples in which it is possible to";
- ret += " that do not implement this proposal.</p>";
- ret += " <ol>";
- ret += " <li>";
- ret += " <p>The XML document does not use namespaces.</p>";
- ret += " <ul>";
- ret += " <li>In this case, it is obviously not necessary to declare or use";
- ret += " attribute selectors will function adequately in a down-level";
- ret += " </li>";
- ret += " <li>In a CSS namespace aware client, the default behavior of";
- ret += " element selectors matching without regard to namespace will";
- ret += " present. However, the use of specific element type selectors";
- ret += " match only elements that have no namespace ('<code>|name</code>')";
- ret += " will guarantee that selectors will match only XML elements that";
- ret += " </li>";
- ret += " </ul>";
- ret += " </li>";
- ret += " <li>";
- ret += " <p>The XML document defines a single, default namespace used";
- ret += " names.</p>";
- ret += " <ul>";
- ret += " <li>In this case, a down-level client will function as if";
- ret += " element type and attribute selectors will match against all";
- ret += " </li>";
- ret += " </ul>";
- ret += " </li>";
- ret += " <li>";
- ret += " <p>The XML document does <b>not</b> use a default namespace, all";
- ret += " to the same URI).</p>";
- ret += " <ul>";
- ret += " <li>In this case, the down-level client will view and match";
- ret += " element type and attribute selectors based on their fully";
- ret += " qualified name, not the local part as outlined in the <a href='#typenmsp'>Type selectors and Namespaces</a>";
- ret += " selectors may be declared using an escaped colon";
- ret += " '<code>\\:</code>'";
- ret += " '<code>html\\:h1</code>' will match";
- ret += " <code><html:h1></code>. Selectors using the qualified name";
- ret += " </li>";
- ret += " <li>Note that selectors declared in this fashion will";
- ret += " <em>only</em> match in down-level clients. A CSS namespace aware";
- ret += " client will match element type and attribute selectors based on";
- ret += " the name's local part. Selectors declared with the fully";
- ret += " </li>";
- ret += " </ul>";
- ret += " </li>";
- ret += " </ol>";
- ret += " <p>In other scenarios: when the namespace prefixes used in the XML are";
- ret += " <em>different</em> namespace URIs within the same document, or in";
- ret += " a CSS and XML namespace aware client.</p>";
- ret += " <h2><a name='profiling'>12. Profiles</a></h2>";
- ret += " <p>Each specification using Selectors must define the subset of W3C";
- ret += " Selectors it allows and excludes, and describe the local meaning of";
- ret += " all the components of that subset.</p>";
- ret += " <p>Non normative examples:";
- ret += " </p><div class='profile'>";
- ret += " <table class='tprofile'>";
- ret += " <tbody>";
- ret += " <tr>";
- ret += " <th class='title' colspan='2'>Selectors profile</th>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Specification</th>";
- ret += " <td>CSS level 1</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Accepts</th>";
- ret += " <td>type selectors<br>class selectors<br>ID selectors<br>:link,";
- ret += " :visited and :active pseudo-classes<br>descendant combinator";
- ret += " <br>::first-line and ::first-letter pseudo-elements";
- ret += " </td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Excludes</th>";
- ret += " <td>";
- ret += " <p>universal selector<br>attribute selectors<br>:hover and";
- ret += " pseudo-classes<br>:target pseudo-class<br>:lang()";
- ret += " pseudo-class<br>all UI";
- ret += " element states pseudo-classes<br>all structural";
- ret += " pseudo-classes<br>negation pseudo-class<br>all";
- ret += " UI element fragments pseudo-elements<br>::before and ::after";
- ret += " pseudo-elements<br>child combinators<br>sibling combinators";
- ret += " </p><p>namespaces</p></td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Extra constraints</th>";
- ret += " <td>only one class selector allowed per sequence of simple";
- ret += " selectors";
- ret += " </td>";
- ret += " </tr>";
- ret += " </tbody>";
- ret += " </table>";
- ret += " <br><br>";
- ret += " <table class='tprofile'>";
- ret += " <tbody>";
- ret += " <tr>";
- ret += " <th class='title' colspan='2'>Selectors profile</th>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Specification</th>";
- ret += " <td>CSS level 2</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Accepts</th>";
- ret += " <td>type selectors<br>universal selector<br>attribute presence and";
- ret += " values selectors<br>class selectors<br>ID selectors<br>:link,";
- ret += " <br>descendant combinator<br>child combinator<br>adjacent";
- ret += " combinator<br>::first-line and ::first-letter";
- ret += " pseudo-elements<br>::before";
- ret += " </td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Excludes</th>";
- ret += " <td>";
- ret += " <p>content selectors<br>substring matching attribute";
- ret += " selectors<br>:target pseudo-classes<br>all UI element";
- ret += " states pseudo-classes<br>all structural pseudo-classes other";
- ret += " than :first-child<br>negation pseudo-class<br>all UI element";
- ret += " fragments pseudo-elements<br>general sibling combinators";
- ret += " </p><p>namespaces</p></td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Extra constraints</th>";
- ret += " <td>more than one class selector per sequence of simple selectors";
- ret += " </td>";
- ret += " </tr>";
- ret += " </tbody>";
- ret += " </table>";
- ret += " <p>In CSS, selectors express pattern matching rules that determine which";
- ret += " </p><p>The following selector (CSS level 2) will <b>match</b> all anchors <code>a</code>";
- ret += " with attribute <code>name</code> set inside a section 1 header";
- ret += " <code>h1</code>:";
- ret += " </p><pre>h1 a[name]</pre>";
- ret += " <p>All CSS declarations attached to such a selector are applied to elements";
- ret += " matching it.</p></div>";
- ret += " <div class='profile'>";
- ret += " <table class='tprofile'>";
- ret += " <tbody>";
- ret += " <tr>";
- ret += " <th class='title' colspan='2'>Selectors profile</th>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Specification</th>";
- ret += " <td>STTS 3</td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Accepts</th>";
- ret += " <td>";
- ret += " <p>type selectors<br>universal selectors<br>attribute";
- ret += " selectors<br>class";
- ret += " selectors<br>ID selectors<br>all structural";
- ret += " pseudo-classes<br>";
- ret += " </p><p>namespaces</p></td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Excludes</th>";
- ret += " <td>non-accepted pseudo-classes<br>pseudo-elements<br></td>";
- ret += " </tr>";
- ret += " <tr>";
- ret += " <th>Extra constraints</th>";
- ret += " <td>some selectors and combinators are not allowed in fragment";
- ret += " </td>";
- ret += " </tr>";
- ret += " </tbody>";
- ret += " </table>";
- ret += " <p>Selectors can be used in STTS 3 in two different";
- ret += " </p><ol>";
- ret += " <li>a selection mechanism equivalent to CSS selection mechanism:";
- ret += " </li><li>fragment descriptions that appear on the right side of declarations.";
- ret += " </li>";
- ret += " </ol>";
- ret += " </div>";
- ret += " <h2><a name='Conformance'></a>13. Conformance and requirements</h2>";
- ret += " <p>This section defines conformance with the present specification only.";
- ret += " </p><p>The inability of a user agent to implement part of this specification due to";
- ret += " </p><p>All specifications reusing Selectors must contain a <a href='#profiling'>Profile</a> listing the";
- ret += " subset of Selectors it accepts or excludes, and describing the constraints";
- ret += " </p><p>Invalidity is caused by a parsing error, e.g. an unrecognized token or a";
- ret += " </p><p>User agents must observe the rules for handling parsing errors:";
- ret += " </p><ul>";
- ret += " <li>a simple selector containing an undeclared namespace prefix is invalid";
- ret += " </li>";
- ret += " <li>a selector containing an invalid simple selector, an invalid combinator";
- ret += " </li>";
- ret += " <li>a group of selectors containing an invalid selector is invalid.</li>";
- ret += " </ul>";
- ret += " <p>Specifications reusing Selectors must define how to handle parsing";
- ret += " used is dropped.)</p>";
- ret += " <!-- Apparently all these references are out of date:";
- ret += " <p>Implementations of this specification must behave as";
- ret += " 'recipients of text data' as defined by <a href='#refsCWWW'>[CWWW]</a>";
- ret += " when parsing selectors and attempting matches. (In particular,";
- ret += " <a href='#refsCWWW'>[CWWW]</a> and <a";
- ret += " href='#refsUNICODE'>[UNICODE]</a> and apply to implementations of this";
- ret += " specification.</p>-->";
- ret += " <h2><a name='Tests'></a>14. Tests</h2>";
- ret += " <p>This specification has <a href='http://www.w3.org/Style/CSS/Test/CSS3/Selectors/current/'>a test";
- ret += " suite</a> allowing user agents to verify their basic conformance to";
- ret += " and does not cover all possible combined cases of Selectors.</p>";
- ret += " <h2><a name='ACKS'></a>15. Acknowledgements</h2>";
- ret += " <p>The CSS working group would like to thank everyone who has sent";
- ret += " comments on this specification over the years.</p>";
- ret += " <p>The working group would like to extend special thanks to Donna";
- ret += " the final editorial review.</p>";
- ret += " <h2><a name='references'>16. References</a></h2>";
- ret += " <dl class='refs'>";
- ret += " <dt>[CSS1]";
- ret += " </dt><dd><a name='refsCSS1'></a> Bert Bos, Håkon Wium Lie; '<cite>Cascading";
- ret += " Style Sheets, level 1</cite>', W3C Recommendation, 17 Dec 1996, revised";
- ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/REC-CSS1'>http://www.w3.org/TR/REC-CSS1</a></code>)";
- ret += " </dd><dt>[CSS21]";
- ret += " </dt><dd><a name='refsCSS21'></a> Bert Bos, Tantek Çelik, Ian Hickson, Håkon";
- ret += " Wium Lie, editors; '<cite>Cascading Style Sheets, level 2 revision";
- ret += " 1</cite>', W3C Working Draft, 13 June 2005";
- ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/CSS21'>http://www.w3.org/TR/CSS21</a></code>)";
- ret += " </dd><dt>[CWWW]";
- ret += " </dt><dd><a name='refsCWWW'></a> Martin J. Dürst, François Yergeau,";
- ret += " Misha Wolf, Asmus Freytag, Tex Texin, editors; '<cite>Character Model";
- ret += " for the World Wide Web</cite>', W3C Recommendation, 15 February 2005";
- ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/charmod/'>http://www.w3.org/TR/charmod/</a></code>)";
- ret += " </dd><dt>[FLEX]";
- ret += " </dt><dd><a name='refsFLEX'></a> '<cite>Flex: The Lexical Scanner";
- ret += " Generator</cite>', Version 2.3.7, ISBN 1882114213";
- ret += " </dd><dt>[HTML4]";
- ret += " </dt><dd><a name='refsHTML4'></a> Dave Ragget, Arnaud Le Hors, Ian Jacobs,";
- ret += " editors; '<cite>HTML 4.01 Specification</cite>', W3C Recommendation, 24";
- ret += " </dd><dd>";
- ret += " (<a href='http://www.w3.org/TR/html4/'><code>http://www.w3.org/TR/html4/</code></a>)";
- ret += " </dd><dt>[MATH]";
- ret += " </dt><dd><a name='refsMATH'></a> Patrick Ion, Robert Miner, editors; '<cite>Mathematical";
- ret += " Markup Language (MathML) 1.01</cite>', W3C Recommendation, revision of 7";
- ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/REC-MathML/'>http://www.w3.org/TR/REC-MathML/</a></code>)";
- ret += " </dd><dt>[RFC3066]";
- ret += " </dt><dd><a name='refsRFC3066'></a> H. Alvestrand; '<cite>Tags for the";
- ret += " Identification of Languages</cite>', Request for Comments 3066, January";
- ret += " </dd><dd>(<a href='http://www.ietf.org/rfc/rfc3066.txt'><code>http://www.ietf.org/rfc/rfc3066.txt</code></a>)";
- ret += " </dd><dt>[STTS]";
- ret += " </dt><dd><a name='refsSTTS'></a> Daniel Glazman; '<cite>Simple Tree Transformation";
- ret += " Sheets 3</cite>', Electricité de France, submission to the W3C,";
- ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/NOTE-STTS3'>http://www.w3.org/TR/NOTE-STTS3</a></code>)";
- ret += " </dd><dt>[SVG]";
- ret += " </dt><dd><a name='refsSVG'></a> Jon Ferraiolo, 藤沢 淳, Dean";
- ret += " Jackson, editors; '<cite>Scalable Vector Graphics (SVG) 1.1";
- ret += " Specification</cite>', W3C Recommendation, 14 January 2003";
- ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/SVG/'>http://www.w3.org/TR/SVG/</a></code>)";
- ret += " </dd><dt>[UNICODE]</dt>";
- ret += " <dd><a name='refsUNICODE'></a> <cite><a href='http://www.unicode.org/versions/Unicode4.1.0/'>The Unicode";
- ret += " Standard, Version 4.1</a></cite>, The Unicode Consortium. Boston, MA,";
- ret += " Addison-Wesley, March 2005. ISBN 0-321-18578-1, as amended by <a href='http://www.unicode.org/versions/Unicode4.0.1/'>Unicode";
- ret += " 4.0.1</a> and <a href='http://www.unicode.org/versions/Unicode4.1.0/'>Unicode";
- ret += " 4.1.0</a>.";
- ret += " </dd><dd>(<code><a href='http://www.unicode.org/versions/'>http://www.unicode.org/versions/</a></code>)";
- ret += " </dd>";
- ret += " <dt>[XML10]";
- ret += " </dt><dd><a name='refsXML10'></a> Tim Bray, Jean Paoli, C. M. Sperberg-McQueen,";
- ret += " Eve Maler, François Yergeau, editors; '<cite>Extensible Markup";
- ret += " Language (XML) 1.0 (Third Edition)</cite>', W3C Recommendation, 4";
- ret += " </dd><dd>(<a href='http://www.w3.org/TR/REC-xml/'><code>http://www.w3.org/TR/REC-xml/</code></a>)";
- ret += " </dd><dt>[XMLNAMES]";
- ret += " </dt><dd><a name='refsXMLNAMES'></a> Tim Bray, Dave Hollander, Andrew Layman,";
- ret += " editors; '<cite>Namespaces in XML</cite>', W3C Recommendation, 14";
- ret += " </dd><dd>(<a href='http://www.w3.org/TR/REC-xml-names/'><code>http://www.w3.org/TR/REC-xml-names/</code></a>)";
- ret += " </dd><dt>[YACC]";
- ret += " </dt><dd><a name='refsYACC'></a> S. C. Johnson; '<cite>YACC — Yet another";
- ret += " compiler compiler</cite>', Technical Report, Murray Hill, 1975";
- ret += " </dd></dl>'; </div>";
- ret += " <input name='n' value='v1' type='radio'>1";
- ret += " <input name='n' value='v2' checked='checked' type='radio'>2";
- $(e).html(ret);
- }
-
-}
+/* + * 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 gwtquery.samples.client; + +import static com.google.gwt.query.client.GQuery.$; +import static com.google.gwt.query.client.GQuery.document; + +import java.util.ArrayList; + +import com.google.gwt.core.client.EntryPoint; +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.core.client.Scheduler.RepeatingCommand; +import com.google.gwt.dom.client.Element; +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.GQuery; +import com.google.gwt.query.client.Selectors.DeferredSelector; +import com.google.gwt.query.client.impl.SelectorEngineCssToXPath; +import com.google.gwt.query.client.impl.SelectorEngineImpl; +import com.google.gwt.query.client.impl.SelectorEngineNative; +import com.google.gwt.query.client.impl.SelectorEngineNativeIE8; +import com.google.gwt.query.client.impl.SelectorEngineNativeMin; +import com.google.gwt.query.client.impl.SelectorEngineNativeMinIE8; +import com.google.gwt.query.client.impl.SelectorEngineSizzle; +import com.google.gwt.query.client.impl.SelectorEngineSizzleIE; +import com.google.gwt.query.client.impl.research.SelectorEngineJS; +import com.google.gwt.query.client.impl.research.SelectorEngineSizzleGwt; +import com.google.gwt.query.client.impl.research.SelectorEngineXPath; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.FlexTable; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.PopupPanel; +import com.google.gwt.user.client.ui.RootPanel; + +/** + * Module to test and compare the performance of each Js-Library and + * each Gwt selector implementation. + * + * It is possible to select which benchmarks to run. Be aware that + * not all of them work in all browsers. + * By default selected options are gwt_compiled, gwt_dynamic, jquery and prototype. + * + * It uses iframes to avoid interferences when updating the document. + * By default the iframe is shared for all libraries, but you can use + * a different one for each benchmark appending the parameter share=false. + * + * Parameters available in the url + * share=false Use different iframes for each bench + * min=200 Minimum time running each selector + * track=false Don't draw the horse race + * ask=false Run default benchmarks, don't ask the user. + */ +public class GwtQueryBenchModule implements EntryPoint { + + public interface Benchmark { + String getId(); + String getName(); + int runSelector(DeferredSelector dq); + } + + /** + * Benchmark for dynamic selectors + */ + private class DynamicBenchmark implements Benchmark { + + protected SelectorEngineImpl engine; + private String id; + + DynamicBenchmark(SelectorEngineImpl engine, String name) { + this.id = name; + this.engine = engine; + } + + public String getId() { + return id; + } + + public String getName() { + String name = engine.getClass().getName().replaceAll("^.*\\.", ""); + return name; + } + + public int runSelector(DeferredSelector dq) { + return engine.select(dq.getSelector(), gwtiframe).getLength(); + } + } + + /** + * Benchmark for the compiled selectors + */ + private class GQueryCompiledBenchmark implements Benchmark { + + String id; + String name; + + GQueryCompiledBenchmark(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public String getName() { + if (name == null) { + MySelectors s = GWT.create(MySelectors.class); + s.body(document); + name = s.getClass().getName().replaceAll("^.*_", ""); + if (s.isDegradated()) { + name += " [degradated]"; + } + } + return name; + } + + public int runSelector(DeferredSelector dq) { + return dq.runSelector(gwtiframe).getLength(); + } + } + + /** + * Benchmark for external libraries + */ + private class IframeBenchmark implements Benchmark { + private String id; + + IframeBenchmark(String name) { + this.id = name; + } + + public String getId() { + return id; + } + + public String getName() { + return id; + } + + public int runSelector(DeferredSelector dq) { + return runSelector(id, dq.getSelector()); + } + + public native int runSelector(String id, String selector) /*-{ + return eval("$wnd." + id + "benchmark('" + selector + "')"); + }-*/; + } + + public static native void exportIframeReadyCallback(GwtQueryBenchModule bench) /*-{ + $wnd.iframebench_ready_callback = function() { + bench.@gwtquery.samples.client.GwtQueryBenchModule::iframeReadyCallback()(); + }; + }-*/; + + private boolean ask = true; + + private Function askBenchMarks = new Function(){ + public void f() { + if (!running && ask) { + selectPanel.center(); + } else { + runBenchMarks.f(); + } + } + }; + + /** + * List of available benchmarks. + */ + private final Benchmark[] benchmarks = new Benchmark[] { + new GQueryCompiledBenchmark("gwt_compiled"), + new DynamicBenchmark((SelectorEngineImpl)GWT.create(SelectorEngineImpl.class), "gwt_dynamic"), + new DynamicBenchmark(new SelectorEngineSizzle(), "gwt_sizzle_jsni"), + new DynamicBenchmark(new SelectorEngineSizzleIE(), "gwt_sizzle_ie_jsni"), + new DynamicBenchmark(new SelectorEngineSizzleGwt(), "gwt_sizzle_java"), + new DynamicBenchmark(new SelectorEngineJS(), "gwt_domassist_java"), + new DynamicBenchmark(new SelectorEngineXPath(), "gwt_xpath"), + new DynamicBenchmark(new SelectorEngineCssToXPath(), "gwt_css2xpath"), + new DynamicBenchmark(new SelectorEngineNative(), "gwt_native"), + new DynamicBenchmark(new SelectorEngineNativeIE8(), "gwt_nativeIE8"), + new DynamicBenchmark(new SelectorEngineNativeMin(), "gwt_native_min"), + new DynamicBenchmark(new SelectorEngineNativeMinIE8(), "gwt_native_minIE8"), + new IframeBenchmark("jquery"), + new IframeBenchmark("dojo"), + new IframeBenchmark("prototype"), + new IframeBenchmark("sizzle"), + new IframeBenchmark("domassistant") + }; + /** + * Pre-selected benchmarks + */ + private String[] defaultBenchmarks = {"gwt_compiled", "gwt_dynamic", "jquery", "prototype", "dojo"}; + + private DeferredSelector ds[]; + + private FlexTable grid = new FlexTable(); + + private Element gwtiframe; + private int min_time = 200; + private boolean running = false; + /** + * Main function to run all the selected benchmarks + */ + private Function runBenchMarks = new Function() { + public void f() { + + // Force to stop the race + if (running) { + running = false; + $("#startrace").text("Run Again"); + return; + } + running = true; + + selectedBenchmarks = readBenchmarkSelection(); + selectPanel.hide(); + $("#startrace").text("Stop the race"); + $("#results").show(); + + initResultsTable(ds, selectedBenchmarks); + initTrack(selectedBenchmarks); + + Scheduler.get().scheduleIncremental(new RepeatingCommand() { + int benchMarkNumber = 0; + int numCalls = 0; + int row = 0; + double runTimes[] = new double[selectedBenchmarks.length]; + int selectorNumber = 0; + double totalTimes[] = new double[selectedBenchmarks.length]; + int winner = -1; + double winTime = Double.MAX_VALUE; + + public boolean execute() { + // The race has been stopped + if (!running) { + return false; + } + if (benchMarkNumber >= selectedBenchmarks.length) { + benchMarkNumber = 0; + numCalls = 0; + row ++; + + moveHorses(selectedBenchmarks, row, totalTimes); + setResultClass(selectorNumber, winner); + + selectorNumber++; + winner = -1; + winTime = Double.MAX_VALUE; + if (selectorNumber >= ds.length) { + double min = Double.MAX_VALUE; + for (int i = 0; i < totalTimes.length; i++) { + if (totalTimes[i] < min) { + min = totalTimes[i]; + } + } + + d(selectorNumber, -1, "Total"); + for (int i = 0; i < totalTimes.length; i++) { + d(selectorNumber, i, (((int) (totalTimes[i] * 100)) / 100.0) + " ms"); + if (totalTimes[i] <= min) { + flagWinner(selectedBenchmarks[i].getId()); + $("#startrace").text("Run Again"); + setResultClass(selectorNumber, i); + } + } + return false; + } + } + DeferredSelector d = ds[selectorNumber]; + long start = System.currentTimeMillis(); + int num = 0; + long end = start; + Benchmark m = selectedBenchmarks[benchMarkNumber]; + double runtime = min_time; + int found = 0; + try { + do { + num += m.runSelector(d); + end = System.currentTimeMillis(); + numCalls++; + } while (end - start < min_time); + runtime = (double) (end - start) / numCalls; + if (runtime < winTime) { + winTime = runtime; + winner = benchMarkNumber; + } + found = num / numCalls; + } catch (Exception e) { + e.printStackTrace(); + found = -1; + } + runTimes[benchMarkNumber] = runtime; + d(selectorNumber, benchMarkNumber, runtime, found); + totalTimes[benchMarkNumber] += runtime; + numCalls = 0; + benchMarkNumber++; + return true; + } + }); + } + }; + private Benchmark[] selectedBenchmarks; + private PopupPanel selectPanel = new PopupPanel() {{ + addStyleName("spanel"); + }}; + private PopupPanel helpPanel = new PopupPanel() {{ + setAutoHideEnabled(true); + setWidget(new HTML($("#help").html())); + addStyleName("help"); + }}; + private boolean shareIframes = true; + + private double trackWidth; + + private boolean useTrack = true; + + public void iframeReadyCallback() { + writeTestContent($(".ibench").contents().find("body").get(0)); + gwtiframe = $(".ibench").eq(0).contents().get(0); + $("#startrace").text("Start the race"); + $("#startrace").click(ask ? askBenchMarks: runBenchMarks); + $("#about").click(new Function(){ + public void f() { + helpPanel.center(); + } + }); + } + + /** + * EntryPoint + */ + public void onModuleLoad() { + + final MySelectors m = GWT.create(MySelectors.class); + + ds = m.getAllSelectors(); + + String par = Window.Location.getParameter("min"); + if (par != null) { + min_time = Integer.parseInt(par); + } + par = Window.Location.getParameter("share"); + if (par != null && "false".equals(par)) { + shareIframes = false; + } + par = Window.Location.getParameter("track"); + if (par != null && "false".equals(par)) { + useTrack = false; + } + par = Window.Location.getParameter("ask"); + if (par != null && "false".equals(par)) { + ask = false; + } + + exportIframeReadyCallback(this); + initSelects(benchmarks); + initIFrames(); + $("#results").hide(); + + } + + private void d(int selnumber, int benchnumber, double time, int found) { + String text = found < 0 ? "Error" : "" + (((int) (time * 10)) / 10.0) + " ms | " + found + " found"; + d(selnumber, benchnumber, text); + } + + private void d(int selnumber, int benchnumber, String text) { + grid.setText(selnumber + 1, benchnumber + 1, text); + Element td = grid.getCellFormatter().getElement(selnumber + 1, benchnumber + 1); + DOM.scrollIntoView((com.google.gwt.user.client.Element) td); + } + + private void flagWinner(String idWinner) { + GQuery g = $("#" + idWinner + "horse" + " nobr"); + $(".flag").appendTo(g).show(); + } + + /** + * Insert the iframes for benchmarking. + * Depending on the parameter share, we will generate one iframe + * for each benchmark or we will share the same one. + */ + private void initIFrames() { + String i = "<iframe class=ibench id=%ID%bench src=html/%ID%bench.html></iframe>"; + if (! shareIframes ) { + $(i.replaceAll("%ID%", "gwt")).appendTo(document).hide(); + for (Benchmark b : benchmarks) { + if (b instanceof IframeBenchmark) { + $(i.replaceAll("%ID%", b.getId())).appendTo(document).hide(); + } + } + } else { + $(i.replaceAll("%ID%", "iframe")).appendTo(document).hide(); + } + } + + /** + * Reset the result table + */ + private void initResultsTable(DeferredSelector[] dg, Benchmark... benchs) { + int numRows = dg.length; + grid = new FlexTable(); + grid.addStyleName("resultstable"); + RootPanel.get("results").clear(); + RootPanel.get("results").add(grid); + + grid.setText(0, 0, "Selector"); + for (int i=0; i < benchs.length; i++) { + grid.setText(0, i+1, benchs[i].getId()); + } + + for (int i = 0; i < numRows; i++) { + grid.setText(i+1, 0, dg[i].getSelector()); + for (int j = 0; j < benchs.length; j++) { + grid.setText(i+1, j+1, "-"); + } + } + } + + /** + * Initialize the selects to choose the benchmarks to run + */ + private void initSelects(Benchmark... benchs) { + String opt = "<input type='checkbox' name='n' value='%ID%' %SEL%>%ID%</input><br/>"; + selectPanel.add(new HTML("<div id=selectcontainer><strong>Make your selection</strong><hr/></div>")); + selectPanel.show(); + GQuery g = $("#selectcontainer"); + for (Benchmark b : benchs) { + String select = opt; + for (String s : defaultBenchmarks) { + if (s.equals(b.getId())) { + select = select.replaceAll("%SEL%", "checked='checked'"); + } + } + g.append(select.replaceAll("%ID%", b.getId() + " " + b.getName()).replaceAll("%SEL", "")); + } + g.append("<br/><button id=run>Run</button>"); + $("#run").click(runBenchMarks); + selectPanel.hide(); + } + + /** + * Initialize the track with the horses + */ + private void initTrack(Benchmark... benchs) { + if (!useTrack) return; + String tpl = "<div id=%ID%horse class=horse><nobr><img class=himg src=images/bench/horse.gif><span>%ID%</span></nobr></div>"; + GQuery g = $("#racefield").html(""); + for (Benchmark b : benchs) { + String id = b.getId(); + String lg = id.contains("gwt") ? "gwt" : id; + String s = tpl.replaceAll("%ID%", id).replaceAll("%LG%", lg); + g.append($(s)); + } + + GQuery flag = $("<img class=flag src='images/bench/animated-flag.gif'/>").appendTo(document); + + // These values are set in the css. + int horseHeight = 35; + int horseWidth = 150; + int flagWidth = 35; + + int height = horseHeight * (benchs.length + 1); + $("#racetrack").css("height", height + "px"); + + trackWidth = g.width() - horseWidth - flagWidth; + flag.hide(); + } + + /** + * Update horse possition. + * Note that the calculated position is relative with the faster horse, + * so a horse could move back. + */ + private void moveHorses(Benchmark[] b, int row, double[] totalTimes) { + if (!useTrack) return; + double winnerTime = Double.MAX_VALUE; + for (double d : totalTimes) { + winnerTime = Math.min(winnerTime, d); + } + double winnerPos = row * (double) trackWidth / (double) ds.length; + for (int i = 0; i < b.length; i++) { + GQuery g = $("#" + b[i].getId() + "horse"); + double pos = winnerPos * winnerTime / totalTimes[i]; + g.css("left", (int)pos + "px"); + } + } + + private Benchmark[] readBenchmarkSelection() { + ArrayList<Benchmark> bs = new ArrayList<Benchmark>(); + for (Element e : $("input", selectPanel.getElement()).elements()) { + String val = $(e).val().replaceAll(" .*$", ""); + if ($(e).prop("checked")) { + for (Benchmark b : benchmarks) { + if (b.getId().equals(val)) { + bs.add(b); + } + } + } + } + return bs.toArray(new Benchmark[bs.size()]); + } + + private void setResultClass(int selNumber, int winNumber) { + Element e = grid.getCellFormatter().getElement(selNumber + 1, winNumber + 1); + $(e).addClass("win").siblings().attr("class", "").addClass("tie").eq(0).removeClass("tie"); + } + + /** + * This ugly method is used to initialize a huge html String + * plenty of html tags which will be used for the tests, + * because java 1.5 has a limitation in the size of static strings. + */ + private void writeTestContent(Element e) { + String ret = ""; + ret += "<html><head> </head><body><div>"; + ret += " <div class='head dialog'>"; + ret += " <p><a href='http://www.w3.org/'><img alt='W3C' src='' height='48' width='72'></a></p>"; + ret += " <h1 id='title'>Selectors</h1>"; + ret += " <em><span>.</span></em>"; + ret += " <h2>W3C Working Draft 15 December 2005</h2>"; + ret += " <dl>"; + ret += " <dt>This version:</dt>"; + ret += " <dd><a href='http://www.w3.org/TR/2005/WD-css3-selectors-20051215'>"; + ret += " http://www.w3.org/TR/2005/WD-css3-selectors-20051215</a></dd>"; + ret += " <dt>Latest version:"; + ret += " </dt><dd><a href='http://www.w3.org/TR/css3-selectors'>"; + ret += " http://www.w3.org/TR/css3-selectors</a>"; + ret += " </dd><dt>Previous version:"; + ret += " </dt><dd><a href='http://www.w3.org/TR/2001/CR-css3-selectors-20011113'>"; + ret += " http://www.w3.org/TR/2001/CR-css3-selectors-20011113</a>"; + ret += " </dd><dt><a name='editors-list'></a>Editors:"; + ret += " </dt><dd class='vcard'><span class='fn'>Daniel Glazman</span> (Invited"; + ret += " </dd>"; + ret += " <dd class='vcard'><a class='url fn' href='http://www.tantek.com/' lang='tr'>Tantek Çelik</a>"; + ret += " </dd><dd class='vcard'><a href='mailto:ian@hixie.ch' class='url fn'>Ian"; + ret += " Hickson</a> (<span class='company'><a href='http://www.google.com/'>Google</a></span>)"; + ret += " </dd><dd class='vcard'><span class='fn'>Peter Linss</span> (former"; + ret += " editor, <span class='company'><a href='http://www.netscape.com/'>Netscape/AOL</a></span>)"; + ret += " </dd><dd class='vcard'><span class='fn'>John Williams</span> (former editor, <span class='company'><a href='http://www.quark.com/'>Quark, Inc.</a></span>)"; + ret += " </dd></dl>"; + ret += " <p class='copyright'><a href='http://www.w3.org/Consortium/Legal/ipr-notice#Copyright'>"; + ret += " Copyright</a> © 2005 <a href='http://www.w3.org/'><abbr title='World Wide Web Consortium'>W3C</abbr></a><sup>®</sup>"; + ret += " (<a href='http://www.csail.mit.edu/'><abbr title='Massachusetts"; + ret += " Institute of Technology'>MIT</abbr></a>, <a href='http://www.ercim.org/'><acronym title='European Research"; + ret += " Consortium for Informatics and Mathematics'>ERCIM</acronym></a>, <a href='http://www.keio.ac.jp/'>Keio</a>), All Rights Reserved."; + ret += " <a href='http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer'>liability</a>,"; + ret += " <a href='http://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks'>trademark</a>,"; + ret += " <a href='http://www.w3.org/Consortium/Legal/copyright-documents'>document"; + ret += " use</a> rules apply."; + ret += " </p><hr title='Separator for header'>"; + ret += " </div>"; + ret += " <h2><a name='abstract'></a>Abstract</h2>"; + ret += " <p><em>Selectors</em> are patterns that match against elements in a"; + ret += " tree. Selectors have been optimized for use with HTML and XML, and"; + ret += " are designed to be usable in performance-critical code.</p>"; + ret += " <p><acronym title='Cascading Style Sheets'>CSS</acronym> (Cascading"; + ret += " Style Sheets) is a language for describing the rendering of <acronym title='Hypertext Markup Language'>HTML</acronym> and <acronym title='Extensible Markup Language'>XML</acronym> documents on"; + ret += " screen, on paper, in speech, etc. CSS uses Selectors for binding"; + ret += " describes extensions to the selectors defined in CSS level 2. These"; + ret += " extended selectors will be used by CSS level 3."; + ret += " </p><p>Selectors define the following function:</p>"; + ret += " <pre>expression ∗ element → boolean</pre>"; + ret += " <p>That is, given an element and a selector, this specification"; + ret += " defines whether that element matches the selector.</p>"; + ret += " <p>These expressions can also be used, for instance, to select a set"; + ret += " subtree. <acronym title='Simple Tree Transformation"; + ret += " Sheets'>STTS</acronym> (Simple Tree Transformation Sheets), a"; + ret += " language for transforming XML trees, uses this mechanism. <a href='#refsSTTS'>[STTS]</a></p>"; + ret += " <h2><a name='status'></a>Status of this document</h2>"; + ret += " <p><em>This section describes the status of this document at the"; + ret += " of this technical report can be found in the <a href='http://www.w3.org/TR/'>W3C technical reports index at"; + ret += " http://www.w3.org/TR/.</a></em></p>"; + ret += " <p>This document describes the selectors that already exist in <a href='#refsCSS1'><abbr title='CSS level 1'>CSS1</abbr></a> and <a href='#refsCSS21'><abbr title='CSS level 2'>CSS2</abbr></a>, and"; + ret += " also proposes new selectors for <abbr title='CSS level"; + ret += " 3'>CSS3</abbr> and other languages that may need them.</p>"; + ret += " <p>The CSS Working Group doesn't expect that all implementations of"; + ret += " CSS3 will have to implement all selectors. Instead, there will"; + ret += " will include all of the selectors.</p>"; + ret += " <p>This specification is a last call working draft for the the <a href='http://www.w3.org/Style/CSS/members'>CSS Working Group</a>"; + ret += " (<a href='/Style/'>Style Activity</a>). This"; + ret += " document is a revision of the <a href='http://www.w3.org/TR/2001/CR-css3-selectors-20011113/'>Candidate"; + ret += " Recommendation dated 2001 November 13</a>, and has incorporated"; + ret += " be demonstrable.</p>"; + ret += " <p>All persons are encouraged to review and implement this"; + ret += " specification and return comments to the (<a href='http://lists.w3.org/Archives/Public/www-style/'>archived</a>)"; + ret += " public mailing list <a href='http://www.w3.org/Mail/Lists.html#www-style'>www-style</a>"; + ret += " (see <a href='http://www.w3.org/Mail/Request'>instructions</a>). W3C"; + ret += " The deadline for comments is 14 January 2006.</p>"; + ret += " <p>This is still a draft document and may be updated, replaced, or"; + ret += " </p><p>This document may be available in <a href='http://www.w3.org/Style/css3-selectors-updates/translations'>translation</a>."; + ret += " </p><div class='subtoc'>"; + ret += " <h2><a name='contents'>Table of contents</a></h2>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline2'><a href='#context'>1. Introduction</a>"; + ret += " <ul>"; + ret += " <li><a href='#dependencies'>1.1. Dependencies</a></li>"; + ret += " <li><a href='#terminology'>1.2. Terminology</a></li>"; + ret += " <li><a href='#changesFromCSS2'>1.3. Changes from CSS2</a></li>"; + ret += " </ul>"; + ret += " </li><li class='tocline2'><a href='#selectors'>2. Selectors</a>"; + ret += " </li><li class='tocline2'><a href='#casesens'>3. Case sensitivity</a>"; + ret += " </li><li class='tocline2'><a href='#selector-syntax'>4. Selector syntax</a>"; + ret += " </li><li class='tocline2'><a href='#grouping'>5. Groups of selectors</a>"; + ret += " </li><li class='tocline2'><a href='#simple-selectors'>6. Simple selectors</a>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline3'><a href='#type-selectors'>6.1. Type"; + ret += " selectors</a>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline4'><a href='#typenmsp'>6.1.1. Type"; + ret += " selectors and namespaces</a></li>"; + ret += " </ul>"; + ret += " </li><li class='tocline3'><a href='#universal-selector'>6.2."; + ret += " Universal selector</a>"; + ret += " <ul>"; + ret += " <li><a href='#univnmsp'>6.2.1. Universal selector and"; + ret += " namespaces</a></li>"; + ret += " </ul>"; + ret += " </li><li class='tocline3'><a href='#attribute-selectors'>6.3."; + ret += " Attribute selectors</a>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline4'><a href='#attribute-representation'>6.3.1."; + ret += " values</a>"; + ret += " </li><li><a href='#attribute-substrings'>6.3.2. Substring"; + ret += " matching attribute selectors</a>"; + ret += " </li><li class='tocline4'><a href='#attrnmsp'>6.3.3."; + ret += " Attribute selectors and namespaces</a>"; + ret += " </li><li class='tocline4'><a href='#def-values'>6.3.4."; + ret += " Default attribute values in DTDs</a></li>"; + ret += " </ul>"; + ret += " </li><li class='tocline3'><a href='#class-html'>6.4. Class"; + ret += " selectors</a>"; + ret += " </li><li class='tocline3'><a href='#id-selectors'>6.5. ID"; + ret += " selectors</a>"; + ret += " </li><li class='tocline3'><a href='#pseudo-classes'>6.6."; + ret += " Pseudo-classes</a>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline4'><a href='#dynamic-pseudos'>6.6.1."; + ret += " Dynamic pseudo-classes</a>"; + ret += " </li><li class='tocline4'><a href='#target-pseudo'>6.6.2. The"; + ret += " :target pseudo-class</a>"; + ret += " </li><li class='tocline4'><a href='#lang-pseudo'>6.6.3. The"; + ret += " :lang() pseudo-class</a>"; + ret += " </li><li class='tocline4'><a href='#UIstates'>6.6.4. UI"; + ret += " element states pseudo-classes</a>"; + ret += " </li><li class='tocline4'><a href='#structural-pseudos'>6.6.5."; + ret += " Structural pseudo-classes</a>"; + ret += " <ul>"; + ret += " <li><a href='#root-pseudo'>:root"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#nth-child-pseudo'>:nth-child()"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#nth-last-child-pseudo'>:nth-last-child()</a>"; + ret += " </li><li><a href='#nth-of-type-pseudo'>:nth-of-type()"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#nth-last-of-type-pseudo'>:nth-last-of-type()</a>"; + ret += " </li><li><a href='#first-child-pseudo'>:first-child"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#last-child-pseudo'>:last-child"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#first-of-type-pseudo'>:first-of-type"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#last-of-type-pseudo'>:last-of-type"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#only-child-pseudo'>:only-child"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#only-of-type-pseudo'>:only-of-type"; + ret += " pseudo-class</a>"; + ret += " </li><li><a href='#empty-pseudo'>:empty"; + ret += " pseudo-class</a></li>"; + ret += " </ul>"; + ret += " </li><li class='tocline4'><a href='#negation'>6.6.7. The"; + ret += " negation pseudo-class</a></li>"; + ret += " </ul>"; + ret += " </li>"; + ret += " </ul>"; + ret += " </li><li><a href='#pseudo-elements'>7. Pseudo-elements</a>"; + ret += " <ul>"; + ret += " <li><a href='#first-line'>7.1. The ::first-line"; + ret += " pseudo-element</a>"; + ret += " </li><li><a href='#first-letter'>7.2. The ::first-letter"; + ret += " pseudo-element</a>"; + ret += " </li><li><a href='#UIfragments'>7.3. The ::selection"; + ret += " pseudo-element</a>"; + ret += " </li><li><a href='#gen-content'>7.4. The ::before and ::after"; + ret += " pseudo-elements</a></li>"; + ret += " </ul>"; + ret += " </li><li class='tocline2'><a href='#combinators'>8. Combinators</a>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline3'><a href='#descendant-combinators'>8.1."; + ret += " Descendant combinators</a>"; + ret += " </li><li class='tocline3'><a href='#child-combinators'>8.2. Child"; + ret += " combinators</a>"; + ret += " </li><li class='tocline3'><a href='#sibling-combinators'>8.3. Sibling"; + ret += " combinators</a>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline4'><a href='#adjacent-sibling-combinators'>8.3.1."; + ret += " Adjacent sibling combinator</a>"; + ret += " </li><li class='tocline4'><a href='#general-sibling-combinators'>8.3.2."; + ret += " General sibling combinator</a></li>"; + ret += " </ul>"; + ret += " </li>"; + ret += " </ul>"; + ret += " </li><li class='tocline2'><a href='#specificity'>9. Calculating a selector's"; + ret += " specificity</a>"; + ret += " </li><li class='tocline2'><a href='#w3cselgrammar'>10. The grammar of"; + ret += " Selectors</a>"; + ret += " <ul class='toc'>"; + ret += " <li class='tocline3'><a href='#grammar'>10.1. Grammar</a>"; + ret += " </li><li class='tocline3'><a href='#lex'>10.2. Lexical scanner</a>"; + ret += " </li>"; + ret += " </ul>"; + ret += " </li><li class='tocline2'><a href='#downlevel'>11. Namespaces and down-level"; + ret += " clients</a>"; + ret += " </li><li class='tocline2'><a href='#profiling'>12. Profiles</a>"; + ret += " </li><li><a href='#Conformance'>13. Conformance and requirements</a>"; + ret += " </li><li><a href='#Tests'>14. Tests</a>"; + ret += " </li><li><a href='#ACKS'>15. Acknowledgements</a>"; + ret += " </li><li class='tocline2'><a href='#references'>16. References</a>"; + ret += " </li></ul>"; + ret += " </div>"; + ret += " <h2><a name='context'>1. Introduction</a></h2>"; + ret += " <h3><a name='dependencies'></a>1.1. Dependencies</h3>"; + ret += " <p>Some features of this specification are specific to CSS, or have"; + ret += " specification, these have been described in terms of CSS2.1. <a href='#refsCSS21'>[CSS21]</a></p>"; + ret += " <h3><a name='terminology'></a>1.2. Terminology</h3>"; + ret += " <p>All of the text of this specification is normative except"; + ret += " non-normative.</p>"; + ret += " <h3><a name='changesFromCSS2'></a>1.3. Changes from CSS2</h3>"; + ret += " <p><em>This section is non-normative.</em></p>"; + ret += " <p>The main differences between the selectors in CSS2 and those in"; + ret += " Selectors are:"; + ret += " </p><ul>"; + ret += " <li>the list of basic definitions (selector, group of selectors,"; + ret += " of simple selectors, and the term 'simple selector' is now used for"; + ret += " </li>"; + ret += " <li>an optional namespace component is now allowed in type element"; + ret += " selectors, the universal selector and attribute selectors"; + ret += " </li>"; + ret += " <li>a <a href='#general-sibling-combinators'>new combinator</a> has been"; + ret += " </li>"; + ret += " <li>new simple selectors including substring matching attribute"; + ret += " selectors, and new pseudo-classes"; + ret += " </li>"; + ret += " <li>new pseudo-elements, and introduction of the '::' convention"; + ret += " </li>"; + ret += " <li>the grammar has been rewritten</li>"; + ret += " <li>profiles to be added to specifications integrating Selectors"; + ret += " and defining the set of selectors which is actually supported by"; + ret += " </li>"; + ret += " <li>Selectors are now a CSS3 Module and an independent"; + ret += " </li>"; + ret += " <li>the specification now has its own test suite</li>"; + ret += " </ul>"; + ret += " <h2><a name='selectors'></a>2. Selectors</h2>"; + ret += " <p><em>This section is non-normative, as it merely summarizes the"; + ret += " following sections.</em></p>"; + ret += " <p>A Selector represents a structure. This structure can be used as a"; + ret += " HTML or XML fragment corresponding to that structure.</p>"; + ret += " <p>Selectors may range from simple element names to rich contextual"; + ret += " representations.</p>"; + ret += " <p>The following table summarizes the Selector syntax:</p>"; + ret += " <table class='selectorsReview'>"; + ret += " <thead>"; + ret += " <tr>"; + ret += " <th class='pattern'>Pattern</th>"; + ret += " <th class='meaning'>Meaning</th>"; + ret += " <th class='described'>Described in section</th>"; + ret += " <th class='origin'>First defined in CSS level</th>"; + ret += " </tr>"; + ret += " </thead><tbody>"; + ret += " <tr>"; + ret += " <td class='pattern'>*</td>"; + ret += " <td class='meaning'>any element</td>"; + ret += " <td class='described'><a href='#universal-selector'>Universal"; + ret += " selector</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E</td>"; + ret += " <td class='meaning'>an element of type E</td>"; + ret += " <td class='described'><a href='#type-selectors'>Type selector</a></td>"; + ret += " <td class='origin'>1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E[foo]</td>"; + ret += " <td class='meaning'>an E element with a 'foo' attribute</td>"; + ret += " <td class='described'><a href='#attribute-selectors'>Attribute"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E[foo='bar']</td>"; + ret += " <td class='meaning'>an E element whose 'foo' attribute value is exactly"; + ret += " </td>"; + ret += " <td class='described'><a href='#attribute-selectors'>Attribute"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E[foo~='bar']</td>"; + ret += " <td class='meaning'>an E element whose 'foo' attribute value is a list of"; + ret += " </td>"; + ret += " <td class='described'><a href='#attribute-selectors'>Attribute"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E[foo^='bar']</td>"; + ret += " <td class='meaning'>an E element whose 'foo' attribute value begins exactly"; + ret += " </td>"; + ret += " <td class='described'><a href='#attribute-selectors'>Attribute"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E[foo$='bar']</td>"; + ret += " <td class='meaning'>an E element whose 'foo' attribute value ends exactly"; + ret += " </td>"; + ret += " <td class='described'><a href='#attribute-selectors'>Attribute"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E[foo*='bar']</td>"; + ret += " <td class='meaning'>an E element whose 'foo' attribute value contains the"; + ret += " </td>"; + ret += " <td class='described'><a href='#attribute-selectors'>Attribute"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E[hreflang|='en']</td>"; + ret += " <td class='meaning'>an E element whose 'hreflang' attribute has a"; + ret += " </td>"; + ret += " <td class='described'><a href='#attribute-selectors'>Attribute"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:root</td>"; + ret += " <td class='meaning'>an E element, root of the document</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:nth-child(n)</td>"; + ret += " <td class='meaning'>an E element, the n-th child of its parent</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:nth-last-child(n)</td>"; + ret += " <td class='meaning'>an E element, the n-th child of its parent, counting"; + ret += " </td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:nth-of-type(n)</td>"; + ret += " <td class='meaning'>an E element, the n-th sibling of its type</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:nth-last-of-type(n)</td>"; + ret += " <td class='meaning'>an E element, the n-th sibling of its type, counting"; + ret += " </td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:first-child</td>"; + ret += " <td class='meaning'>an E element, first child of its parent</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:last-child</td>"; + ret += " <td class='meaning'>an E element, last child of its parent</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:first-of-type</td>"; + ret += " <td class='meaning'>an E element, first sibling of its type</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:last-of-type</td>"; + ret += " <td class='meaning'>an E element, last sibling of its type</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:only-child</td>"; + ret += " <td class='meaning'>an E element, only child of its parent</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:only-of-type</td>"; + ret += " <td class='meaning'>an E element, only sibling of its type</td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:empty</td>"; + ret += " <td class='meaning'>an E element that has no children (including text"; + ret += " </td>"; + ret += " <td class='described'><a href='#structural-pseudos'>Structural"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:link<br>E:visited</td>"; + ret += " <td class='meaning'>an E element being the source anchor of a hyperlink of"; + ret += " </td>"; + ret += " <td class='described'><a href='#link'>The link"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:active<br>E:hover<br>E:focus</td>"; + ret += " <td class='meaning'>an E element during certain user actions</td>"; + ret += " <td class='described'><a href='#useraction-pseudos'>The user"; + ret += " action pseudo-classes</a></td>"; + ret += " <td class='origin'>1 and 2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:target</td>"; + ret += " <td class='meaning'>an E element being the target of the referring URI</td>"; + ret += " <td class='described'><a href='#target-pseudo'>The target"; + ret += " pseudo-class</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:lang(fr)</td>"; + ret += " <td class='meaning'>an element of type E in language 'fr' (the document"; + ret += " </td>"; + ret += " <td class='described'><a href='#lang-pseudo'>The :lang()"; + ret += " pseudo-class</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:enabled<br>E:disabled</td>"; + ret += " <td class='meaning'>a user interface element E which is enabled or"; + ret += " </td>"; + ret += " <td class='described'><a href='#UIstates'>The UI element states"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:checked<!--<br>E:indeterminate--></td>"; + ret += " <td class='meaning'>a user interface element E which is checked<!-- or in an"; + ret += " indeterminate state--> (for instance a radio-button or checkbox)"; + ret += " </td>"; + ret += " <td class='described'><a href='#UIstates'>The UI element states"; + ret += " pseudo-classes</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E::first-line</td>"; + ret += " <td class='meaning'>the first formatted line of an E element</td>"; + ret += " <td class='described'><a href='#first-line'>The ::first-line"; + ret += " pseudo-element</a></td>"; + ret += " <td class='origin'>1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E::first-letter</td>"; + ret += " <td class='meaning'>the first formatted letter of an E element</td>"; + ret += " <td class='described'><a href='#first-letter'>The ::first-letter"; + ret += " pseudo-element</a></td>"; + ret += " <td class='origin'>1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E::selection</td>"; + ret += " <td class='meaning'>the portion of an E element that is currently"; + ret += " </td>"; + ret += " <td class='described'><a href='#UIfragments'>The UI element"; + ret += " fragments pseudo-elements</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E::before</td>"; + ret += " <td class='meaning'>generated content before an E element</td>"; + ret += " <td class='described'><a href='#gen-content'>The ::before"; + ret += " pseudo-element</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E::after</td>"; + ret += " <td class='meaning'>generated content after an E element</td>"; + ret += " <td class='described'><a href='#gen-content'>The ::after"; + ret += " pseudo-element</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E.warning</td>"; + ret += " <td class='meaning'>an E element whose class is"; + ret += " </td>"; + ret += " <td class='described'><a href='#class-html'>Class"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E#myid</td>"; + ret += " <td class='meaning'>an E element with ID equal to 'myid'.</td>"; + ret += " <td class='described'><a href='#id-selectors'>ID"; + ret += " selectors</a></td>"; + ret += " <td class='origin'>1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E:not(s)</td>"; + ret += " <td class='meaning'>an E element that does not match simple selector s</td>"; + ret += " <td class='described'><a href='#negation'>Negation"; + ret += " pseudo-class</a></td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E F</td>"; + ret += " <td class='meaning'>an F element descendant of an E element</td>"; + ret += " <td class='described'><a href='#descendant-combinators'>Descendant"; + ret += " combinator</a></td>"; + ret += " <td class='origin'>1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E > F</td>"; + ret += " <td class='meaning'>an F element child of an E element</td>"; + ret += " <td class='described'><a href='#child-combinators'>Child"; + ret += " combinator</a></td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E + F</td>"; + ret += " <td class='meaning'>an F element immediately preceded by an E element</td>"; + ret += " <td class='described'><a href='#adjacent-sibling-combinators'>Adjacent sibling combinator</a>"; + ret += " </td>"; + ret += " <td class='origin'>2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <td class='pattern'>E ~ F</td>"; + ret += " <td class='meaning'>an F element preceded by an E element</td>"; + ret += " <td class='described'><a href='#general-sibling-combinators'>General sibling combinator</a>"; + ret += " </td>"; + ret += " <td class='origin'>3</td>"; + ret += " </tr>"; + ret += " </tbody>"; + ret += " </table>"; + ret += " <p>The meaning of each selector is derived from the table above by"; + ret += " column.</p>"; + ret += " <h2><a name='casesens'>3. Case sensitivity</a></h2>"; + ret += " <p>The case sensitivity of document language element names, attribute"; + ret += " names, and attribute values in selectors depends on the document"; + ret += " but in XML, they are case-sensitive.</p>"; + ret += " <h2><a name='selector-syntax'>4. Selector syntax</a></h2>"; + ret += " <p>A <dfn><a name='selector'>selector</a></dfn> is a chain of one"; + ret += " or more <a href='#sequence'>sequences of simple selectors</a>"; + ret += " separated by <a href='#combinators'>combinators</a>.</p>"; + ret += " <p>A <dfn><a name='sequence'>sequence of simple selectors</a></dfn>"; + ret += " is a chain of <a href='#simple-selectors-dfn'>simple selectors</a>"; + ret += " that are not separated by a <a href='#combinators'>combinator</a>. It"; + ret += " always begins with a <a href='#type-selectors'>type selector</a> or a"; + ret += " <a href='#universal-selector'>universal selector</a>. No other type"; + ret += " selector or universal selector is allowed in the sequence.</p>"; + ret += " <p>A <dfn><a name='simple-selectors-dfn'></a><a href='#simple-selectors'>simple selector</a></dfn> is either a <a href='#type-selectors'>type selector</a>, <a href='#universal-selector'>universal selector</a>, <a href='#attribute-selectors'>attribute selector</a>, <a href='#class-html'>class selector</a>, <a href='#id-selectors'>ID selector</a>, <a href='#content-selectors'>content selector</a>, or <a href='#pseudo-classes'>pseudo-class</a>. One <a href='#pseudo-elements'>pseudo-element</a> may be appended to the last"; + ret += " sequence of simple selectors.</p>"; + ret += " <p><dfn>Combinators</dfn> are: white space, 'greater-than"; + ret += " sign' (U+003E, <code>></code>), 'plus sign' (U+002B,"; + ret += " <code>+</code>) and 'tilde' (U+007E, <code>~</code>). White"; + ret += " space may appear between a combinator and the simple selectors around"; + ret += " it. <a name='whitespace'></a>Only the characters 'space' (U+0020), 'tab'"; + ret += " never part of white space.</p>"; + ret += " <p>The elements of a document tree that are represented by a selector"; + ret += " are the <dfn><a name='subject'></a>subjects of the selector</dfn>. A"; + ret += " selector consisting of a single sequence of simple selectors"; + ret += " sequence of simple selectors and a combinator to a sequence imposes"; + ret += " simple selectors.</p>"; + ret += " <p>An empty selector, containing no sequence of simple selectors and"; + ret += " no pseudo-element, is an <a href='#Conformance'>invalid"; + ret += " selector</a>.</p>"; + ret += " <h2><a name='grouping'>5. Groups of selectors</a></h2>"; + ret += " <p>When several selectors share the same declarations, they may be"; + ret += " grouped into a comma-separated list. (A comma is U+002C.)</p>"; + ret += " <div class='example'>"; + ret += " <p>CSS examples:</p>"; + ret += " <p>In this example, we condense three rules with identical"; + ret += " declarations into one. Thus,</p>"; + ret += " <pre>h1 { font-family: sans-serif }"; + ret += " h3 { font-family: sans-serif }</pre>"; + ret += " <p>is equivalent to:</p>"; + ret += " <pre>h1, h2, h3 { font-family: sans-serif }</pre>"; + ret += " </div>"; + ret += " <p><strong>Warning</strong>: the equivalence is true in this example"; + ret += " because all the selectors are valid selectors. If just one of these"; + ret += " selectors were invalid, the entire group of selectors would be"; + ret += " heading rules would be invalidated.</p>"; + ret += " <h2><a name='simple-selectors'>6. Simple selectors</a></h2>"; + ret += " <h3><a name='type-selectors'>6.1. Type selector</a></h3>"; + ret += " <p>A <dfn>type selector</dfn> is the name of a document language"; + ret += " type in the document tree.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>The following selector represents an <code>h1</code> element in the"; + ret += " document tree:</p>"; + ret += " <pre>h1</pre>"; + ret += " </div>"; + ret += " <h4><a name='typenmsp'>6.1.1. Type selectors and namespaces</a></h4>"; + ret += " <p>Type selectors allow an optional namespace (<a href='#refsXMLNAMES'>[XMLNAMES]</a>) component. A namespace prefix"; + ret += " (U+007C, <code>|</code>).</p>"; + ret += " <p>The namespace component may be left empty to indicate that the"; + ret += " selector is only to represent elements with no declared namespace.</p>"; + ret += " <p>An asterisk may be used for the namespace prefix, indicating that"; + ret += " with no namespace).</p>"; + ret += " <p>Element type selectors that have no namespace component (no"; + ret += " element's namespace (equivalent to '<code>*|</code>') unless a default"; + ret += " namespace.</p>"; + ret += " <p>A type selector containing a namespace prefix that has not been"; + ret += " previously declared is an <a href='#Conformance'>invalid</a> selector."; + ret += " language implementing Selectors. In CSS, such a mechanism is defined"; + ret += " in the General Syntax module.</p>"; + ret += " <p>In a namespace-aware client, element type selectors will only match"; + ret += " against the <a href='http://www.w3.org/TR/REC-xml-names/#NT-LocalPart'>local"; + ret += " part</a>"; + ret += " of the element's <a href='http://www.w3.org/TR/REC-xml-names/#ns-qualnames'>qualified"; + ret += " name</a>. See <a href='#downlevel'>below</a> for notes about matching"; + ret += " behaviors in down-level clients.</p>"; + ret += " <p>In summary:</p>"; + ret += " <dl>"; + ret += " <dt><code>ns|E</code></dt>"; + ret += " <dd>elements with name E in namespace ns</dd>"; + ret += " <dt><code>*|E</code></dt>"; + ret += " <dd>elements with name E in any namespace, including those without any"; + ret += " </dd>"; + ret += " <dt><code>|E</code></dt>"; + ret += " <dd>elements with name E without any declared namespace</dd>"; + ret += " <dt><code>E</code></dt>"; + ret += " <dd>if no default namespace has been specified, this is equivalent to *|E."; + ret += " </dd>"; + ret += " </dl>"; + ret += " <div class='example'>"; + ret += " <p>CSS examples:</p>"; + ret += " <pre>@namespace foo url(http://www.example.com);"; + ret += " h1 { color: green }</pre>"; + ret += " <p>The first rule will match only <code>h1</code> elements in the"; + ret += " 'http://www.example.com' namespace.</p>"; + ret += " <p>The second rule will match all elements in the"; + ret += " 'http://www.example.com' namespace.</p>"; + ret += " <p>The third rule will match only <code>h1</code> elements without"; + ret += " any declared namespace.</p>"; + ret += " <p>The fourth rule will match <code>h1</code> elements in any"; + ret += " namespace (including those without any declared namespace).</p>"; + ret += " <p>The last rule is equivalent to the fourth rule because no default"; + ret += " namespace has been defined.</p>"; + ret += " </div>"; + ret += " <h3><a name='universal-selector'>6.2. Universal selector</a></h3>"; + ret += " <p>The <dfn>universal selector</dfn>, written 'asterisk'"; + ret += " (<code>*</code>), represents the qualified name of any element"; + ret += " specified, see <a href='#univnmsp'>Universal selector and"; + ret += " Namespaces</a> below.</p>"; + ret += " <p>If the universal selector is not the only component of a sequence"; + ret += " of simple selectors, the <code>*</code> may be omitted.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <ul>"; + ret += " <li><code>*[hreflang|=en]</code> and <code>[hreflang|=en]</code> are"; + ret += " </li>"; + ret += " <li><code>*.warning</code> and <code>.warning</code> are equivalent,"; + ret += " </li>"; + ret += " <li><code>*#myid</code> and <code>#myid</code> are equivalent.</li>"; + ret += " </ul>"; + ret += " </div>"; + ret += " <p class='note'><strong>Note:</strong> it is recommended that the"; + ret += " <code>*</code>, representing the universal selector, not be"; + ret += " omitted.</p>"; + ret += " <h4><a name='univnmsp'>6.2.1. Universal selector and namespaces</a></h4>"; + ret += " <p>The universal selector allows an optional namespace component. It"; + ret += " is used as follows:</p>"; + ret += " <dl>"; + ret += " <dt><code>ns|*</code></dt>"; + ret += " <dd>all elements in namespace ns</dd>"; + ret += " <dt><code>*|*</code></dt>"; + ret += " <dd>all elements</dd>"; + ret += " <dt><code>|*</code></dt>"; + ret += " <dd>all elements without any declared namespace</dd>"; + ret += " <dt><code>*</code></dt>"; + ret += " <dd>if no default namespace has been specified, this is equivalent to *|*."; + ret += " </dd>"; + ret += " </dl>"; + ret += " <p>A universal selector containing a namespace prefix that has not"; + ret += " been previously declared is an <a href='#Conformance'>invalid</a>"; + ret += " to the language implementing Selectors. In CSS, such a mechanism is"; + ret += " defined in the General Syntax module.</p>"; + ret += " <h3><a name='attribute-selectors'>6.3. Attribute selectors</a></h3>"; + ret += " <p>Selectors allow the representation of an element's attributes. When"; + ret += " attribute selectors must be considered to match an element if that"; + ret += " attribute selector.</p>"; + ret += " <h4><a name='attribute-representation'>6.3.1. Attribute presence and values"; + ret += " selectors</a></h4>"; + ret += " <p>CSS2 introduced four attribute selectors:</p>"; + ret += " <dl>"; + ret += " <dt><code>[att]</code>"; + ret += " </dt><dd>Represents an element with the <code>att</code> attribute, whatever the"; + ret += " </dd>"; + ret += " <dt><code>[att=val]</code></dt>"; + ret += " <dd>Represents an element with the <code>att</code> attribute whose value is"; + ret += " </dd>"; + ret += " <dt><code>[att~=val]</code></dt>"; + ret += " <dd>Represents an element with the <code>att</code> attribute whose value is"; + ret += " a <a href='#whitespace'>whitespace</a>-separated list of words, one"; + ret += " represent anything (since the words are <em>separated</em> by"; + ret += " </dd>"; + ret += " <dt><code>[att|=val]</code>"; + ret += " </dt><dd>Represents an element with the <code>att</code> attribute, its value"; + ret += " matches (e.g., the <code>hreflang</code> attribute on the"; + ret += " <code>link</code> element in HTML) as described in RFC 3066 (<a href='#refsRFC3066'>[RFC3066]</a>). For <code>lang</code> (or"; + ret += " <code>xml:lang</code>) language subcode matching, please see <a href='#lang-pseudo'>the <code>:lang</code> pseudo-class</a>."; + ret += " </dd>"; + ret += " </dl>"; + ret += " <p>Attribute values must be identifiers or strings. The"; + ret += " case-sensitivity of attribute names and values in selectors depends on"; + ret += " the document language.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following attribute selector represents an <code>h1</code>"; + ret += " element that carries the <code>title</code> attribute, whatever its"; + ret += " value:</p>"; + ret += " <pre>h1[title]</pre>"; + ret += " <p>In the following example, the selector represents a"; + ret += " <code>span</code> element whose <code>class</code> attribute has"; + ret += " exactly the value 'example':</p>"; + ret += " <pre>span[class='example']</pre>"; + ret += " <p>Multiple attribute selectors can be used to represent several"; + ret += " attribute. Here, the selector represents a <code>span</code> element"; + ret += " whose <code>hello</code> attribute has exactly the value 'Cleveland'"; + ret += " and whose <code>goodbye</code> attribute has exactly the value"; + ret += " 'Columbus':</p>"; + ret += " <pre>span[hello='Cleveland'][goodbye='Columbus']</pre>"; + ret += " <p>The following selectors illustrate the differences between '='"; + ret += " 'copyright copyleft copyeditor' on a <code>rel</code> attribute. The"; + ret += " second selector will only represent an <code>a</code> element with"; + ret += " an <code>href</code> attribute having the exact value"; + ret += " 'http://www.w3.org/'.</p>"; + ret += " <pre>a[rel~='copyright']"; + ret += " a[href='http://www.w3.org/']</pre>"; + ret += " <p>The following selector represents a <code>link</code> element"; + ret += " whose <code>hreflang</code> attribute is exactly 'fr'.</p>"; + ret += " <pre>link[hreflang=fr]</pre>"; + ret += " <p>The following selector represents a <code>link</code> element for"; + ret += " which the values of the <code>hreflang</code> attribute begins with"; + ret += " 'en', including 'en', 'en-US', and 'en-cockney':</p>"; + ret += " <pre>link[hreflang|='en']</pre>"; + ret += " <p>Similarly, the following selectors represents a"; + ret += " <code>DIALOGUE</code> element whenever it has one of two different"; + ret += " values for an attribute <code>character</code>:</p>"; + ret += " <pre>DIALOGUE[character=romeo]"; + ret += " DIALOGUE[character=juliet]</pre>"; + ret += " </div>"; + ret += " <h4><a name='attribute-substrings'></a>6.3.2. Substring matching attribute"; + ret += " selectors</h4>"; + ret += " <p>Three additional attribute selectors are provided for matching"; + ret += " substrings in the value of an attribute:</p>"; + ret += " <dl>"; + ret += " <dt><code>[att^=val]</code></dt>"; + ret += " <dd>Represents an element with the <code>att</code> attribute whose value"; + ret += " </dd>"; + ret += " <dt><code>[att$=val]</code>"; + ret += " </dt><dd>Represents an element with the <code>att</code> attribute whose value"; + ret += " </dd>"; + ret += " <dt><code>[att*=val]</code>"; + ret += " </dt><dd>Represents an element with the <code>att</code> attribute whose value"; + ret += " </dd>"; + ret += " </dl>"; + ret += " <p>Attribute values must be identifiers or strings. The"; + ret += " case-sensitivity of attribute names in selectors depends on the"; + ret += " document language.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following selector represents an HTML <code>object</code>,"; + ret += " image:</p>"; + ret += " <pre>object[type^='image/']</pre>"; + ret += " <p>The following selector represents an HTML anchor <code>a</code> with an"; + ret += " <code>href</code> attribute whose value ends with '.html'.</p>"; + ret += " <pre>a[href$='.html']</pre>"; + ret += " <p>The following selector represents an HTML paragraph with a"; + ret += " <code>title</code>"; + ret += " attribute whose value contains the substring 'hello'</p>"; + ret += " <pre>p[title*='hello']</pre>"; + ret += " </div>"; + ret += " <h4><a name='attrnmsp'>6.3.3. Attribute selectors and namespaces</a></h4>"; + ret += " <p>Attribute selectors allow an optional namespace component to the"; + ret += " separator 'vertical bar' (<code>|</code>). In keeping with"; + ret += " apply to attributes, therefore attribute selectors without a namespace"; + ret += " (equivalent to '<code>|attr</code>'). An asterisk may be used for the"; + ret += " </p><p>An attribute selector with an attribute name containing a namespace"; + ret += " prefix that has not been previously declared is an <a href='#Conformance'>invalid</a> selector. The mechanism for"; + ret += " a namespace prefix is left up to the language implementing Selectors."; + ret += " </p><div class='example'>"; + ret += " <p>CSS examples:</p>"; + ret += " <pre>@namespace foo 'http://www.example.com';"; + ret += " [att] { color: green }</pre>"; + ret += " <p>The first rule will match only elements with the attribute"; + ret += " <code>att</code> in the 'http://www.example.com' namespace with the"; + ret += " value 'val'.</p>"; + ret += " <p>The second rule will match only elements with the attribute"; + ret += " <code>att</code> regardless of the namespace of the attribute"; + ret += " (including no declared namespace).</p>"; + ret += " <p>The last two rules are equivalent and will match only elements"; + ret += " with the attribute <code>att</code> where the attribute is not"; + ret += " declared to be in a namespace.</p>"; + ret += " </div>"; + ret += " <h4><a name='def-values'>6.3.4. Default attribute values in DTDs</a></h4>"; + ret += " <p>Attribute selectors represent explicitly set attribute values in"; + ret += " selectors. Selectors should be designed so that they work even if the"; + ret += " default values are not included in the document tree.</p>"; + ret += " <p>More precisely, a UA is <em>not</em> required to read an 'external"; + ret += " subset' of the DTD but <em>is</em> required to look for default"; + ret += " attribute values in the document's 'internal subset.' (See <a href='#refsXML10'>[XML10]</a> for definitions of these subsets.)</p>"; + ret += " <p>A UA that recognizes an XML namespace <a href='#refsXMLNAMES'>[XMLNAMES]</a> is not required to use its"; + ret += " required to use its built-in knowledge of the XHTML DTD.)</p>"; + ret += " <p class='note'><strong>Note:</strong> Typically, implementations"; + ret += " choose to ignore external subsets.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>Consider an element EXAMPLE with an attribute 'notation' that has a"; + ret += " default value of 'decimal'. The DTD fragment might be</p>"; + ret += " <pre class='dtd-example'><!ATTLIST EXAMPLE notation (decimal,octal) 'decimal'></pre>"; + ret += " <p>If the style sheet contains the rules</p>"; + ret += " <pre>EXAMPLE[notation=decimal] { /*... default property settings ...*/ }"; + ret += " EXAMPLE[notation=octal] { /*... other settings...*/ }</pre>"; + ret += " <p>the first rule will not match elements whose 'notation' attribute"; + ret += " attribute selector for the default value must be dropped:</p>"; + ret += " <pre>EXAMPLE { /*... default property settings ...*/ }"; + ret += " EXAMPLE[notation=octal] { /*... other settings...*/ }</pre>"; + ret += " <p>Here, because the selector <code>EXAMPLE[notation=octal]</code> is"; + ret += " cases' style rules.</p>"; + ret += " </div>"; + ret += " <h3><a name='class-html'>6.4. Class selectors</a></h3>"; + ret += " <p>Working with HTML, authors may use the period (U+002E,"; + ret += " <code>.</code>) notation as an alternative to the <code>~=</code>"; + ret += " notation when representing the <code>class</code> attribute. Thus, for"; + ret += " HTML, <code>div.value</code> and <code>div[class~=value]</code> have"; + ret += " 'period' (<code>.</code>).</p>"; + ret += " <p>UAs may apply selectors using the period (.) notation in XML"; + ret += " 1.0 <a href='#refsSVG'>[SVG]</a> describes the <a href='http://www.w3.org/TR/2001/PR-SVG-20010719/styling.html#ClassAttribute'>SVG"; + ret += " 'class' attribute</a> and how a UA should interpret it, and"; + ret += " similarly MathML 1.01 <a href='#refsMATH'>[MATH]</a> describes the <a href='http://www.w3.org/1999/07/REC-MathML-19990707/chapter2.html#sec2.3.4'>MathML"; + ret += " 'class' attribute</a>.)</p>"; + ret += " <div class='example'>"; + ret += " <p>CSS examples:</p>"; + ret += " <p>We can assign style information to all elements with"; + ret += " <code>class~='pastoral'</code> as follows:</p>"; + ret += " <pre>*.pastoral { color: green } /* all elements with class~=pastoral */</pre>"; + ret += " <p>or just</p>"; + ret += " <pre>.pastoral { color: green } /* all elements with class~=pastoral */</pre>"; + ret += " <p>The following assigns style only to H1 elements with"; + ret += " <code>class~='pastoral'</code>:</p>"; + ret += " <pre>H1.pastoral { color: green } /* H1 elements with class~=pastoral */</pre>"; + ret += " <p>Given these rules, the first H1 instance below would not have"; + ret += " green text, while the second would:</p>"; + ret += " <pre><H1>Not green</H1>"; + ret += " <H1 class='pastoral'>Very green</H1></pre>"; + ret += " </div>"; + ret += " <p>To represent a subset of 'class' values, each value must be preceded"; + ret += " by a '.', in any order.</p>"; + ret += " <div class='example'>"; + ret += " <p>CSS example:</p>"; + ret += " <p>The following rule matches any P element whose 'class' attribute"; + ret += " has been assigned a list of <a href='#whitespace'>whitespace</a>-separated values that includes"; + ret += " 'pastoral' and 'marine':</p>"; + ret += " <pre>p.pastoral.marine { color: green }</pre>"; + ret += " <p>This rule matches when <code>class='pastoral blue aqua"; + ret += " marine'</code> but does not match for <code>class='pastoral"; + ret += " blue'</code>.</p>"; + ret += " </div>"; + ret += " <p class='note'><strong>Note:</strong> Because CSS gives considerable"; + ret += " not.</p>"; + ret += " <p class='note'><strong>Note:</strong> If an element has multiple"; + ret += " this specification.</p>"; + ret += " <h3><a name='id-selectors'>6.5. ID selectors</a></h3>"; + ret += " <p>Document languages may contain attributes that are declared to be"; + ret += " applies.</p>"; + ret += " <p>An ID-typed attribute of a document language allows authors to"; + ret += " ID selectors represent an element instance based on its identifier. An"; + ret += " <code>#</code>) immediately followed by the ID value, which must be an"; + ret += " identifier.</p>"; + ret += " <p>Selectors does not specify how a UA knows the ID-typed attribute of"; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following ID selector represents an <code>h1</code> element"; + ret += " whose ID-typed attribute has the value 'chapter1':</p>"; + ret += " <pre>h1#chapter1</pre>"; + ret += " <p>The following ID selector represents any element whose ID-typed"; + ret += " attribute has the value 'chapter1':</p>"; + ret += " <pre>#chapter1</pre>"; + ret += " <p>The following selector represents any element whose ID-typed"; + ret += " attribute has the value 'z98y'.</p>"; + ret += " <pre>*#z98y</pre>"; + ret += " </div>"; + ret += " <p class='note'><strong>Note.</strong> In XML 1.0 <a href='#refsXML10'>[XML10]</a>, the information about which attribute"; + ret += " should use normal attribute selectors instead:"; + ret += " <code>[name=p371]</code> instead of <code>#p371</code>. Elements in"; + ret += " XML 1.0 documents without a DTD do not have IDs at all.</p>"; + ret += " <p>If an element has multiple ID attributes, all of them must be"; + ret += " DOM3 Core, XML DTDs, and namespace-specific knowledge.</p>"; + ret += " <h3><a name='pseudo-classes'>6.6. Pseudo-classes</a></h3>"; + ret += " <p>The pseudo-class concept is introduced to permit selection based on"; + ret += " expressed using the other simple selectors.</p>"; + ret += " <p>A pseudo-class always consists of a 'colon'"; + ret += " (<code>:</code>) followed by the name of the pseudo-class and"; + ret += " optionally by a value between parentheses.</p>"; + ret += " <p>Pseudo-classes are allowed in all sequences of simple selectors"; + ret += " sequences of simple selectors, after the leading type selector or"; + ret += " document.</p>"; + ret += " <h4><a name='dynamic-pseudos'>6.6.1. Dynamic pseudo-classes</a></h4>"; + ret += " <p>Dynamic pseudo-classes classify elements on characteristics other"; + ret += " that cannot be deduced from the document tree.</p>"; + ret += " <p>Dynamic pseudo-classes do not appear in the document source or"; + ret += " document tree.</p>"; + ret += " <h5>The <a name='link'>link pseudo-classes: :link and :visited</a></h5>"; + ret += " <p>User agents commonly display unvisited links differently from"; + ret += " previously visited ones. Selectors"; + ret += " provides the pseudo-classes <code>:link</code> and"; + ret += " <code>:visited</code> to distinguish them:</p>"; + ret += " <ul>"; + ret += " <li>The <code>:link</code> pseudo-class applies to links that have"; + ret += " </li>"; + ret += " <li>The <code>:visited</code> pseudo-class applies once the link has"; + ret += " </li>"; + ret += " </ul>"; + ret += " <p>After some amount of time, user agents may choose to return a"; + ret += " visited link to the (unvisited) ':link' state.</p>"; + ret += " <p>The two states are mutually exclusive.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>The following selector represents links carrying class"; + ret += " <code>external</code> and already visited:</p>"; + ret += " <pre>a.external:visited</pre>"; + ret += " </div>"; + ret += " <p class='note'><strong>Note:</strong> It is possible for style sheet"; + ret += " </p><p>UAs may therefore treat all links as unvisited links, or implement"; + ret += " and unvisited links differently.</p>"; + ret += " <h5>The <a name='useraction-pseudos'>user action pseudo-classes"; + ret += " :hover, :active, and :focus</a></h5>"; + ret += " <p>Interactive user agents sometimes change the rendering in response"; + ret += " to user actions. Selectors provides"; + ret += " acting on.</p>"; + ret += " <ul>"; + ret += " <li>The <code>:hover</code> pseudo-class applies while the user"; + ret += " element. User agents not that do not support <a href='http://www.w3.org/TR/REC-CSS2/media.html#interactive-media-group'>interactive"; + ret += " media</a> do not have to support this pseudo-class. Some conforming"; + ret += " user agents that support <a href='http://www.w3.org/TR/REC-CSS2/media.html#interactive-media-group'>interactive"; + ret += " media</a> may not be able to support this pseudo-class (e.g., a pen"; + ret += " </li>"; + ret += " <li>The <code>:active</code> pseudo-class applies while an element"; + ret += " </li>"; + ret += " <li>The <code>:focus</code> pseudo-class applies while an element"; + ret += " </li>"; + ret += " </ul>"; + ret += " <p>There may be document language or implementation specific limits on"; + ret += " which elements can become <code>:active</code> or acquire"; + ret += " <code>:focus</code>.</p>"; + ret += " <p>These pseudo-classes are not mutually exclusive. An element may"; + ret += " match several pseudo-classes at the same time.</p>"; + ret += " <p>Selectors doesn't define if the parent of an element that is"; + ret += " ':active' or ':hover' is also in that state.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <pre>a:link /* unvisited links */"; + ret += " a:active /* active links */</pre>"; + ret += " <p>An example of combining dynamic pseudo-classes:</p>"; + ret += " <pre>a:focus"; + ret += " a:focus:hover</pre>"; + ret += " <p>The last selector matches <code>a</code> elements that are in"; + ret += " the pseudo-class :focus and in the pseudo-class :hover.</p>"; + ret += " </div>"; + ret += " <p class='note'><strong>Note:</strong> An element can be both ':visited'"; + ret += " and ':active' (or ':link' and ':active').</p>"; + ret += " <h4><a name='target-pseudo'>6.6.2. The target pseudo-class :target</a></h4>"; + ret += " <p>Some URIs refer to a location within a resource. This kind of URI"; + ret += " identifier (called the fragment identifier).</p>"; + ret += " <p>URIs with fragment identifiers link to a certain element within the"; + ret += " pointing to an anchor named <code>section_2</code> in an HTML"; + ret += " document:</p>"; + ret += " <pre>http://example.com/html/top.html#section_2</pre>"; + ret += " <p>A target element can be represented by the <code>:target</code>"; + ret += " the document has no target element.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <pre>p.note:target</pre>"; + ret += " <p>This selector represents a <code>p</code> element of class"; + ret += " <code>note</code> that is the target element of the referring"; + ret += " URI.</p>"; + ret += " </div>"; + ret += " <div class='example'>"; + ret += " <p>CSS example:</p>"; + ret += " <p>Here, the <code>:target</code> pseudo-class is used to make the"; + ret += " target element red and place an image before it, if there is one:</p>"; + ret += " <pre>*:target { color : red }"; + ret += " *:target::before { content : url(target.png) }</pre>"; + ret += " </div>"; + ret += " <h4><a name='lang-pseudo'>6.6.3. The language pseudo-class :lang</a></h4>"; + ret += " <p>If the document language specifies how the human language of an"; + ret += " element is determined, it is possible to write selectors that"; + ret += " represent an element based on its language. For example, in HTML <a href='#refsHTML4'>[HTML4]</a>, the language is determined by a"; + ret += " combination of the <code>lang</code> attribute, the <code>meta</code>"; + ret += " headers). XML uses an attribute called <code>xml:lang</code>, and"; + ret += " the language.</p>"; + ret += " <p>The pseudo-class <code>:lang(C)</code> represents an element that"; + ret += " <code>:lang()</code> selector is based solely on the identifier C"; + ret += " element's language value, in the same way as if performed by the <a href='#attribute-representation'>'|='</a> operator in attribute"; + ret += " selectors. The identifier C does not have to be a valid language"; + ret += " name.</p>"; + ret += " <p>C must not be empty. (If it is, the selector is invalid.)</p>"; + ret += " <p class='note'><strong>Note:</strong> It is recommended that"; + ret += " documents and protocols indicate language using codes from RFC 3066 <a href='#refsRFC3066'>[RFC3066]</a> or its successor, and by means of"; + ret += " 'xml:lang' attributes in the case of XML-based documents <a href='#refsXML10'>[XML10]</a>. See <a href='http://www.w3.org/International/questions/qa-lang-2or3.html'>"; + ret += " 'FAQ: Two-letter or three-letter language codes.'</a></p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The two following selectors represent an HTML document that is in"; + ret += " Belgian, French, or German. The two next selectors represent"; + ret += " <code>q</code> quotations in an arbitrary element in Belgian, French,"; + ret += " or German.</p>"; + ret += " <pre>html:lang(fr-be)"; + ret += " :lang(de) > q</pre>"; + ret += " </div>"; + ret += " <h4><a name='UIstates'>6.6.4. The UI element states pseudo-classes</a></h4>"; + ret += " <h5><a name='enableddisabled'>The :enabled and :disabled pseudo-classes</a></h5>"; + ret += " <p>The <code>:enabled</code> pseudo-class allows authors to customize"; + ret += " an enabled <code>input</code> element without also specifying what it"; + ret += " would look like when it was disabled.</p>"; + ret += " <p>Similar to <code>:enabled</code>, <code>:disabled</code> allows the"; + ret += " element should look.</p>"; + ret += " <p>Most elements will be neither enabled nor disabled. An element is"; + ret += " presently activate it or transfer focus to it.</p>"; + ret += " <h5><a name='checked'>The :checked pseudo-class</a></h5>"; + ret += " <p>Radio and checkbox elements can be toggled by the user. Some menu"; + ret += " toggled 'on' the <code>:checked</code> pseudo-class applies. The"; + ret += " <code>:checked</code> pseudo-class initially applies to such elements"; + ret += " that have the HTML4 <code>selected</code> and <code>checked</code>"; + ret += " attributes as described in <a href='http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.2.1'>Section"; + ret += " 17.2.1 of HTML4</a>, but of course the user can toggle 'off' such"; + ret += " elements in which case the <code>:checked</code> pseudo-class would no"; + ret += " longer apply. While the <code>:checked</code> pseudo-class is dynamic"; + ret += " on the presence of the semantic HTML4 <code>selected</code> and"; + ret += " <code>checked</code> attributes, it applies to all media."; + ret += " </p><h5><a name='indeterminate'>The :indeterminate pseudo-class</a></h5>"; + ret += " <div class='note'>"; + ret += " <p>Radio and checkbox elements can be toggled by the user, but are"; + ret += " This can be due to an element attribute, or DOM manipulation.</p>"; + ret += " <p>A future version of this specification may introduce an"; + ret += " <code>:indeterminate</code> pseudo-class that applies to such elements."; + ret += " <!--While the <code>:indeterminate</code> pseudo-class is dynamic in"; + ret += " the presence of an element attribute, it applies to all media.</p>"; + ret += " <p>Components of a radio-group initialized with no pre-selected choice"; + ret += " are an example of :indeterminate state.--></p>"; + ret += " </div>"; + ret += " <h4><a name='structural-pseudos'>6.6.5. Structural pseudo-classes</a></h4>"; + ret += " <p>Selectors introduces the concept of <dfn>structural"; + ret += " pseudo-classes</dfn> to permit selection based on extra information that"; + ret += " the document tree but cannot be represented by other simple selectors or"; + ret += " </p><p>Note that standalone pieces of PCDATA (text nodes in the DOM) are"; + ret += " </p><h5><a name='root-pseudo'>:root pseudo-class</a></h5>"; + ret += " <p>The <code>:root</code> pseudo-class represents an element that is"; + ret += " <code>HTML</code> element."; + ret += " </p><h5><a name='nth-child-pseudo'>:nth-child() pseudo-class</a></h5>"; + ret += " <p>The"; + ret += " <code>:nth-child(<var>a</var><code>n</code>+<var>b</var>)</code>"; + ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings"; + ret += " <strong>before</strong> it in the document tree, for a given positive"; + ret += " integer or zero value of <code>n</code>, and has a parent element. In"; + ret += " other words, this matches the <var>b</var>th child of an element after"; + ret += " all the children have been split into groups of <var>a</var> elements"; + ret += " each. For example, this allows the selectors to address every other"; + ret += " of paragraph text in a cycle of four. The <var>a</var> and"; + ret += " <var>b</var> values must be zero, negative integers or positive"; + ret += " </p><p>In addition to this, <code>:nth-child()</code> can take"; + ret += " '<code>odd</code>' and '<code>even</code>' as arguments instead."; + ret += " '<code>odd</code>' has the same signification as <code>2n+1</code>,"; + ret += " and '<code>even</code>' has the same signification as <code>2n</code>."; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <pre>tr:nth-child(2n+1) /* represents every odd row of an HTML table */"; + ret += " p:nth-child(4n+4) { color: purple; }</pre>"; + ret += " </div>"; + ret += " <p>When <var>a</var>=0, no repeating is used, so for example"; + ret += " <code>:nth-child(0n+5)</code> matches only the fifth child. When"; + ret += " <var>a</var>=0, the <var>a</var><code>n</code> part need not be"; + ret += " <code>:nth-child(<var>b</var>)</code> and the last example simplifies"; + ret += " to <code>:nth-child(5)</code>."; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <pre>foo:nth-child(0n+1) /* represents an element foo, first child of its parent element */"; + ret += " foo:nth-child(1) /* same */</pre>"; + ret += " </div>"; + ret += " <p>When <var>a</var>=1, the number may be omitted from the rule."; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following selectors are therefore equivalent:</p>"; + ret += " <pre>bar:nth-child(1n+0) /* represents all bar elements, specificity (0,1,1) */"; + ret += " bar /* same but lower specificity (0,0,1) */</pre>"; + ret += " </div>"; + ret += " <p>If <var>b</var>=0, then every <var>a</var>th element is picked. In"; + ret += " such a case, the <var>b</var> part may be omitted."; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <pre>tr:nth-child(2n+0) /* represents every even row of an HTML table */"; + ret += " tr:nth-child(2n) /* same */</pre>"; + ret += " </div>"; + ret += " <p>If both <var>a</var> and <var>b</var> are equal to zero, the"; + ret += " pseudo-class represents no element in the document tree.</p>"; + ret += " <p>The value <var>a</var> can be negative, but only the positive"; + ret += " values of <var>a</var><code>n</code>+<var>b</var>, for"; + ret += " <code>n</code>≥0, may represent an element in the document"; + ret += " tree.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <pre>html|tr:nth-child(-n+6) /* represents the 6 first rows of XHTML tables */</pre>"; + ret += " </div>"; + ret += " <p>When the value <var>b</var> is negative, the '+' character in the"; + ret += " character indicating the negative value of <var>b</var>).</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <pre>:nth-child(10n-1) /* represents the 9th, 19th, 29th, etc, element */"; + ret += " :nth-child(10n+-1) /* Syntactically invalid, and would be ignored */</pre>"; + ret += " </div>"; + ret += " <h5><a name='nth-last-child-pseudo'>:nth-last-child() pseudo-class</a></h5>"; + ret += " <p>The <code>:nth-last-child(<var>a</var>n+<var>b</var>)</code>"; + ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings"; + ret += " <strong>after</strong> it in the document tree, for a given positive"; + ret += " integer or zero value of <code>n</code>, and has a parent element. See"; + ret += " <code>:nth-child()</code> pseudo-class for the syntax of its argument."; + ret += " It also accepts the '<code>even</code>' and '<code>odd</code>' values"; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <pre>tr:nth-last-child(-n+2) /* represents the two last rows of an HTML table */"; + ret += " counting from the last one */</pre>"; + ret += " </div>"; + ret += " <h5><a name='nth-of-type-pseudo'>:nth-of-type() pseudo-class</a></h5>"; + ret += " <p>The <code>:nth-of-type(<var>a</var>n+<var>b</var>)</code>"; + ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings with the same"; + ret += " element name <strong>before</strong> it in the document tree, for a"; + ret += " given zero or positive integer value of <code>n</code>, and has a"; + ret += " parent element. In other words, this matches the <var>b</var>th child"; + ret += " groups of a elements each. See <code>:nth-child()</code> pseudo-class"; + ret += " '<code>even</code>' and '<code>odd</code>' values."; + ret += " </p><div class='example'>"; + ret += " <p>CSS example:</p>"; + ret += " <p>This allows an author to alternate the position of floated images:</p>"; + ret += " <pre>img:nth-of-type(2n+1) { float: right; }"; + ret += " img:nth-of-type(2n) { float: left; }</pre>"; + ret += " </div>"; + ret += " <h5><a name='nth-last-of-type-pseudo'>:nth-last-of-type() pseudo-class</a></h5>"; + ret += " <p>The <code>:nth-last-of-type(<var>a</var>n+<var>b</var>)</code>"; + ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings with the same"; + ret += " element name <strong>after</strong> it in the document tree, for a"; + ret += " given zero or positive integer value of <code>n</code>, and has a"; + ret += " parent element. See <code>:nth-child()</code> pseudo-class for the"; + ret += " syntax of its argument. It also accepts the '<code>even</code>' and '<code>odd</code>'"; + ret += " </p><div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>To represent all <code>h2</code> children of an XHTML"; + ret += " <code>body</code> except the first and last, one could use the"; + ret += " following selector:</p>"; + ret += " <pre>body > h2:nth-of-type(n+2):nth-last-of-type(n+2)</pre>"; + ret += " <p>In this case, one could also use <code>:not()</code>, although the"; + ret += " selector ends up being just as long:</p>"; + ret += " <pre>body > h2:not(:first-of-type):not(:last-of-type)</pre>"; + ret += " </div>"; + ret += " <h5><a name='first-child-pseudo'>:first-child pseudo-class</a></h5>"; + ret += " <p>Same as <code>:nth-child(1)</code>. The <code>:first-child</code>"; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following selector represents a <code>p</code> element that is"; + ret += " the first child of a <code>div</code> element:</p>"; + ret += " <pre>div > p:first-child</pre>"; + ret += " <p>This selector can represent the <code>p</code> inside the"; + ret += " <code>div</code> of the following fragment:</p>"; + ret += " <pre><p> The last P before the note.</p>"; + ret += " </div></pre>"; + ret += " but cannot represent the second <code>p</code> in the following"; + ret += " <pre><p> The last P before the note.</p>"; + ret += " </div></pre>"; + ret += " <p>The following two selectors are usually equivalent:</p>"; + ret += " <pre>* > a:first-child /* a is first child of any element */"; + ret += " a:first-child /* Same (assuming a is not the root element) */</pre>"; + ret += " </div>"; + ret += " <h5><a name='last-child-pseudo'>:last-child pseudo-class</a></h5>"; + ret += " <p>Same as <code>:nth-last-child(1)</code>. The <code>:last-child</code>"; + ret += " </p><div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>The following selector represents a list item <code>li</code> that"; + ret += " is the last child of an ordered list <code>ol</code>."; + ret += " </p><pre>ol > li:last-child</pre>"; + ret += " </div>"; + ret += " <h5><a name='first-of-type-pseudo'>:first-of-type pseudo-class</a></h5>"; + ret += " <p>Same as <code>:nth-of-type(1)</code>. The <code>:first-of-type</code>"; + ret += " </p><div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>The following selector represents a definition title"; + ret += " <code>dt</code> inside a definition list <code>dl</code>, this"; + ret += " <code>dt</code> being the first of its type in the list of children of"; + ret += " its parent element.</p>"; + ret += " <pre>dl dt:first-of-type</pre>"; + ret += " <p>It is a valid description for the first two <code>dt</code>"; + ret += " elements in the following example but not for the third one:</p>"; + ret += " <pre><dl>"; + ret += " </dl></pre>"; + ret += " </div>"; + ret += " <h5><a name='last-of-type-pseudo'>:last-of-type pseudo-class</a></h5>"; + ret += " <p>Same as <code>:nth-last-of-type(1)</code>. The"; + ret += " <code>:last-of-type</code> pseudo-class represents an element that is"; + ret += " element.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>The following selector represents the last data cell"; + ret += " <code>td</code> of a table row.</p>"; + ret += " <pre>tr > td:last-of-type</pre>"; + ret += " </div>"; + ret += " <h5><a name='only-child-pseudo'>:only-child pseudo-class</a></h5>"; + ret += " <p>Represents an element that has a parent element and whose parent"; + ret += " <code>:first-child:last-child</code> or"; + ret += " <code>:nth-child(1):nth-last-child(1)</code>, but with a lower"; + ret += " specificity.</p>"; + ret += " <h5><a name='only-of-type-pseudo'>:only-of-type pseudo-class</a></h5>"; + ret += " <p>Represents an element that has a parent element and whose parent"; + ret += " as <code>:first-of-type:last-of-type</code> or"; + ret += " <code>:nth-of-type(1):nth-last-of-type(1)</code>, but with a lower"; + ret += " specificity.</p>"; + ret += " <h5><a name='empty-pseudo'></a>:empty pseudo-class</h5>"; + ret += " <p>The <code>:empty</code> pseudo-class represents an element that has"; + ret += " empty or not.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p><code>p:empty</code> is a valid representation of the following fragment:"; + ret += " </p>"; + ret += " <pre><p></p></pre>"; + ret += " <p><code>foo:empty</code> is not a valid representation for the"; + ret += " following fragments:</p>"; + ret += " <pre><foo>bar</foo></pre>"; + ret += " <pre><foo><bar>bla</bar></foo></pre>"; + ret += " <pre><foo>this is not <bar>:empty</bar></foo></pre>"; + ret += " </div>"; + ret += " <h4><a name='content-selectors'>6.6.6. Blank</a></h4>"; + ret += " <!-- It's the Return of Appendix H!!! Run away! -->"; + ret += " <p>This section intentionally left blank.</p>"; + ret += " <!-- (used to be :contains()) -->"; + ret += " <h4><a name='negation'></a>6.6.7. The negation pseudo-class</h4>"; + ret += " <p>The negation pseudo-class, <code>:not(<var>X</var>)</code>, is a"; + ret += " functional notation taking a <a href='#simple-selectors-dfn'>simple"; + ret += " selector</a> (excluding the negation pseudo-class itself and"; + ret += " <!-- pseudo-elements are not simple selectors, so the above paragraph"; + ret += " may be a bit confusing -->"; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following CSS selector matches all <code>button</code>"; + ret += " elements in an HTML document that are not disabled.</p>"; + ret += " <pre>button:not([DISABLED])</pre>"; + ret += " <p>The following selector represents all but <code>FOO</code>"; + ret += " elements.</p>"; + ret += " <pre>*:not(FOO)</pre>"; + ret += " <p>The following group of selectors represents all HTML elements"; + ret += " except links.</p>"; + ret += " <pre>html|*:not(:link):not(:visited)</pre>"; + ret += " </div>"; + ret += " <p>Default namespace declarations do not affect the argument of the"; + ret += " type selector.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>Assuming that the default namespace is bound to"; + ret += " elements that are not in that namespace:</p>"; + ret += " <pre>*|*:not(*)</pre>"; + ret += " <p>The following CSS selector matches any element being hovered,"; + ret += " rule when they <em>are</em> being hovered.</p>"; + ret += " <pre>*|*:not(:hover)</pre>"; + ret += " </div>"; + ret += " <p class='note'><strong>Note</strong>: the :not() pseudo allows"; + ret += " useless selectors to be written. For instance <code>:not(*|*)</code>,"; + ret += " which represents no element at all, or <code>foo:not(bar)</code>,"; + ret += " which is equivalent to <code>foo</code> but with a higher"; + ret += " specificity.</p>"; + ret += " <h3><a name='pseudo-elements'>7. Pseudo-elements</a></h3>"; + ret += " <p>Pseudo-elements create abstractions about the document tree beyond"; + ret += " source document (e.g., the <code>::before</code> and"; + ret += " <code>::after</code> pseudo-elements give access to generated"; + ret += " content).</p>"; + ret += " <p>A pseudo-element is made of two colons (<code>::</code>) followed"; + ret += " by the name of the pseudo-element.</p>"; + ret += " <p>This <code>::</code> notation is introduced by the current document"; + ret += " <code>:first-line</code>, <code>:first-letter</code>,"; + ret += " <code>:before</code> and <code>:after</code>). This compatibility is"; + ret += " not allowed for the new pseudo-elements introduced in CSS level 3.</p>"; + ret += " <p>Only one pseudo-element may appear per selector, and if present it"; + ret += " must appear after the sequence of simple selectors that represents the"; + ret += " <a href='#subject'>subjects</a> of the selector. <span class='note'>A"; + ret += " pesudo-elements per selector.</span></p>"; + ret += " <h4><a name='first-line'>7.1. The ::first-line pseudo-element</a></h4>"; + ret += " <p>The <code>::first-line</code> pseudo-element describes the contents"; + ret += " </p><div class='example'>"; + ret += " <p>CSS example:</p>"; + ret += " <pre>p::first-line { text-transform: uppercase }</pre>"; + ret += " <p>The above rule means 'change the letters of the first line of every"; + ret += " paragraph to uppercase'.</p>"; + ret += " </div>"; + ret += " <p>The selector <code>p::first-line</code> does not match any real"; + ret += " agents will insert at the beginning of every paragraph.</p>"; + ret += " <p>Note that the length of the first line depends on a number of"; + ret += " an ordinary HTML paragraph such as:</p>"; + ret += " <pre> <P>This is a somewhat long HTML "; + ret += " </pre>"; + ret += " <p>the lines of which happen to be broken as follows:"; + ret += " </p><pre> THIS IS A SOMEWHAT LONG HTML PARAGRAPH THAT"; + ret += " </pre>"; + ret += " <p>This paragraph might be 'rewritten' by user agents to include the"; + ret += " <em>fictional tag sequence</em> for <code>::first-line</code>. This"; + ret += " fictional tag sequence helps to show how properties are inherited.</p>"; + ret += " <pre> <P><b><P::first-line></b> This is a somewhat long HTML "; + ret += " paragraph that <b></P::first-line></b> will be broken into several"; + ret += " </pre>"; + ret += " <p>If a pseudo-element breaks up a real element, the desired effect"; + ret += " with a <code>span</code> element:</p>"; + ret += " <pre> <P><b><SPAN class='test'></b> This is a somewhat long HTML"; + ret += " lines.<b></SPAN></b> The first line will be identified"; + ret += " </pre>"; + ret += " <p>the user agent could simulate start and end tags for"; + ret += " <code>span</code> when inserting the fictional tag sequence for"; + ret += " <code>::first-line</code>."; + ret += " </p><pre> <P><P::first-line><b><SPAN class='test'></b> This is a"; + ret += " paragraph that will <b></SPAN></b></P::first-line><b><SPAN"; + ret += " class='test'></b> be"; + ret += " lines.<b></SPAN></b> The first line will be identified"; + ret += " </pre>"; + ret += " <p>In CSS, the <code>::first-line</code> pseudo-element can only be"; + ret += " or a table-cell.</p>"; + ret += " <p><a name='first-formatted-line'></a>The 'first formatted line' of an"; + ret += " line of the <code>div</code> in <code><DIV><P>This"; + ret += " line...</P></DIV></code> is the first line of the <code>p</code>"; + ret += " that both <code>p</code> and <code>div</code> are block-level)."; + ret += " </p><p>The first line of a table-cell or inline-block cannot be the first"; + ret += " formatted line of an ancestor element. Thus, in <code><DIV><P"; + ret += " etcetera</DIV></code> the first formatted line of the"; + ret += " <code>div</code> is not the line 'Hello'."; + ret += " </p><p class='note'>Note that the first line of the <code>p</code> in this"; + ret += " fragment: <code><p><br>First...</code> doesn't contain any"; + ret += " letters (assuming the default style for <code>br</code> in HTML"; + ret += " </p><p>A UA should act as if the fictional start tags of the"; + ret += " <code>::first-line</code> pseudo-elements were nested just inside the"; + ret += " is an example. The fictional tag sequence for</p>"; + ret += " <pre> <DIV>"; + ret += " </pre>"; + ret += " <p>is</p>"; + ret += " <pre> <DIV>"; + ret += " </pre>"; + ret += " <p>The <code>::first-line</code> pseudo-element is similar to an"; + ret += " following properties apply to a <code>::first-line</code>"; + ret += " properties as well.</p>"; + ret += " <h4><a name='first-letter'>7.2. The ::first-letter pseudo-element</a></h4>"; + ret += " <p>The <code>::first-letter</code> pseudo-element represents the first"; + ret += " is 'none'; otherwise, it is similar to a floated element.</p>"; + ret += " <p>In CSS, these are the properties that apply to <code>::first-letter</code>"; + ret += " of the letter, unlike for normal elements.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>This example shows a possible rendering of an initial cap. Note"; + ret += " <code>::first-letter</code>"; + ret += " fictional start tag of the first letter is inside the <span>span</span>,"; + ret += " the font weight of the first letter is normal, not bold as the <span>span</span>:"; + ret += " </p><pre> p { line-height: 1.1 }"; + ret += " </pre>"; + ret += " <div class='figure'>"; + ret += " <p><img src='' alt='Image illustrating the ::first-letter pseudo-element'>"; + ret += " </p></div>"; + ret += " </div>"; + ret += " <div class='example'>"; + ret += " <p>The following CSS will make a drop cap initial letter span about two"; + ret += " lines:</p>"; + ret += " <pre> <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN'>"; + ret += " </pre>"; + ret += " <p>This example might be formatted as follows:</p>"; + ret += " <div class='figure'>"; + ret += " <p><img src='' alt='Image illustrating the combined effect of the ::first-letter and ::first-line pseudo-elements'>"; + ret += " </p>"; + ret += " </div>"; + ret += " <p>The <span class='index-inst' title='fictional tag"; + ret += " sequence'>fictional tag sequence</span> is:</p>"; + ret += " <pre> <P>"; + ret += " </pre>"; + ret += " <p>Note that the <code>::first-letter</code> pseudo-element tags abut"; + ret += " block element.</p></div>"; + ret += " <p>In order to achieve traditional drop caps formatting, user agents"; + ret += " glyph outline may be taken into account when formatting.</p>"; + ret += " <p>Punctuation (i.e, characters defined in Unicode in the 'open' (Ps),"; + ret += " be included. <a href='#refsUNICODE'>[UNICODE]</a></p>"; + ret += " <div class='figure'>"; + ret += " <p><img src='' alt='Quotes that precede the"; + ret += " first letter should be included.'></p>"; + ret += " </div>"; + ret += " <p>The <code>::first-letter</code> also applies if the first letter is"; + ret += " money.'</p>"; + ret += " <p>In CSS, the <code>::first-letter</code> pseudo-element applies to"; + ret += " elements. <span class='note'>A future version of this specification"; + ret += " types.</span></p>"; + ret += " <p>The <code>::first-letter</code> pseudo-element can be used with all"; + ret += " the element, even if that first text is in a descendant.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>The fictional tag sequence for this HTMLfragment:"; + ret += " </p><pre><div>"; + ret += " <p>The first text.</pre>"; + ret += " <p>is:"; + ret += " </p><pre><div>"; + ret += " <p><div::first-letter><p::first-letter>T</...></...>he first text.</pre>"; + ret += " </div>"; + ret += " <p>The first letter of a table-cell or inline-block cannot be the"; + ret += " first letter of an ancestor element. Thus, in <code><DIV><P"; + ret += " etcetera</DIV></code> the first letter of the <code>div</code> is"; + ret += " letter 'H'. In fact, the <code>div</code> doesn't have a first letter."; + ret += " </p><p>The first letter must occur on the <a href='#first-formatted-line'>first formatted line.</a> For example, in"; + ret += " this fragment: <code><p><br>First...</code> the first line"; + ret += " doesn't contain any letters and <code>::first-letter</code> doesn't"; + ret += " match anything (assuming the default style for <code>br</code> in HTML"; + ret += " </p><p>In CSS, if an element is a list item ('display: list-item'), the"; + ret += " <code>::first-letter</code> applies to the first letter in the"; + ret += " <code>::first-letter</code> on list items with 'list-style-position:"; + ret += " inside'. If an element has <code>::before</code> or"; + ret += " <code>::after</code> content, the <code>::first-letter</code> applies"; + ret += " to the first letter of the element <em>including</em> that content."; + ret += " </p><div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p>After the rule 'p::before {content: 'Note: '}', the selector"; + ret += " 'p::first-letter' matches the 'N' of 'Note'.</p>"; + ret += " </div>"; + ret += " <p>Some languages may have specific rules about how to treat certain"; + ret += " considered within the <code>::first-letter</code> pseudo-element."; + ret += " </p><p>If the letters that would form the ::first-letter are not in the"; + ret += " same element, such as ''T' in <code><p>'<em>T...</code>, the UA"; + ret += " both elements, or simply not create a pseudo-element.</p>"; + ret += " <p>Similarly, if the first letter(s) of the block are not at the start"; + ret += " </p><div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <p><a name='overlapping-example'>The following example</a> illustrates"; + ret += " paragraph will be 'red'.</p>"; + ret += " <pre>p { color: red; font-size: 12pt }"; + ret += " <P>Some text that ends up on two lines</P></pre>"; + ret += " <p>Assuming that a line break will occur before the word 'ends', the"; + ret += " <span class='index-inst' title='fictional tag sequence'>fictional tag"; + ret += " sequence</span> for this fragment might be:</p>"; + ret += " <pre><P>"; + ret += " </P></pre>"; + ret += " <p>Note that the <code>::first-letter</code> element is inside the <code>::first-line</code>"; + ret += " element. Properties set on <code>::first-line</code> are inherited by"; + ret += " <code>::first-letter</code>, but are overridden if the same property is"; + ret += " <code>::first-letter</code>.</p>"; + ret += " </div>"; + ret += " <h4><a name='UIfragments'>7.3.</a> <a name='selection'>The ::selection"; + ret += " pseudo-element</a></h4>"; + ret += " <p>The <code>::selection</code> pseudo-element applies to the portion"; + ret += " field. This pseudo-element should not be confused with the <code><a href='#checked'>:checked</a></code> pseudo-class (which used to be"; + ret += " named <code>:selected</code>)"; + ret += " </p><p>Although the <code>::selection</code> pseudo-element is dynamic in"; + ret += " <a href='#refsCSS21'>[CSS21]</a>) which was originally rendered to a"; + ret += " <code>::selection</code> state to that other medium, and have all the"; + ret += " required — UAs may omit the <code>::selection</code>"; + ret += " </p><p>These are the CSS properties that apply to <code>::selection</code>"; + ret += " <code>::selection</code> may be ignored."; + ret += " </p><h4><a name='gen-content'>7.4. The ::before and ::after pseudo-elements</a></h4>"; + ret += " <p>The <code>::before</code> and <code>::after</code> pseudo-elements"; + ret += " content. They are explained in CSS 2.1 <a href='#refsCSS21'>[CSS21]</a>.</p>"; + ret += " <p>When the <code>::first-letter</code> and <code>::first-line</code>"; + ret += " pseudo-elements are combined with <code>::before</code> and"; + ret += " <code>::after</code>, they apply to the first letter or line of the"; + ret += " element including the inserted text.</p>"; + ret += " <h2><a name='combinators'>8. Combinators</a></h2>"; + ret += " <h3><a name='descendant-combinators'>8.1. Descendant combinator</a></h3>"; + ret += " <p>At times, authors may want selectors to describe an element that is"; + ret += " <code>EM</code> element that is contained within an <code>H1</code>"; + ret += " descendant combinator is <a href='#whitespace'>white space</a> that"; + ret += " separates two sequences of simple selectors. A selector of the form"; + ret += " '<code>A B</code>' represents an element <code>B</code> that is an"; + ret += " arbitrary descendant of some ancestor element <code>A</code>."; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>For example, consider the following selector:</p>"; + ret += " <pre>h1 em</pre>"; + ret += " <p>It represents an <code>em</code> element being the descendant of"; + ret += " an <code>h1</code> element. It is a correct and valid, but partial,"; + ret += " description of the following fragment:</p>"; + ret += " <pre><h1>This <span class='myclass'>headline"; + ret += " is <em>very</em> important</span></h1></pre>"; + ret += " <p>The following selector:</p>"; + ret += " <pre>div * p</pre>"; + ret += " <p>represents a <code>p</code> element that is a grandchild or later"; + ret += " descendant of a <code>div</code> element. Note the whitespace on"; + ret += " of the P.</p>"; + ret += " <p>The following selector, which combines descendant combinators and"; + ret += " <a href='#attribute-selectors'>attribute selectors</a>, represents an"; + ret += " element that (1) has the <code>href</code> attribute set and (2) is"; + ret += " inside a <code>p</code> that is itself inside a <code>div</code>:</p>"; + ret += " <pre>div p *[href]</pre>"; + ret += " </div>"; + ret += " <h3><a name='child-combinators'>8.2. Child combinators</a></h3>"; + ret += " <p>A <dfn>child combinator</dfn> describes a childhood relationship"; + ret += " 'greater-than sign' (<code>></code>) character and"; + ret += " separates two sequences of simple selectors."; + ret += " </p><div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following selector represents a <code>p</code> element that is"; + ret += " child of <code>body</code>:</p>"; + ret += " <pre>body > p</pre>"; + ret += " <p>The following example combines descendant combinators and child"; + ret += " combinators.</p>"; + ret += " <pre>div ol>li p</pre>"; + ret += " <!-- LEAVE THOSE SPACES OUT! see below -->"; + ret += " <p>It represents a <code>p</code> element that is a descendant of an"; + ret += " <code>li</code> element; the <code>li</code> element must be the"; + ret += " child of an <code>ol</code> element; the <code>ol</code> element must"; + ret += " be a descendant of a <code>div</code>. Notice that the optional white"; + ret += " space around the '>' combinator has been left out.</p>"; + ret += " </div>"; + ret += " <p>For information on selecting the first child of an element, please"; + ret += " see the section on the <code><a href='#structural-pseudos'>:first-child</a></code> pseudo-class"; + ret += " above.</p>"; + ret += " <h3><a name='sibling-combinators'>8.3. Sibling combinators</a></h3>"; + ret += " <p>There are two different sibling combinators: the adjacent sibling"; + ret += " considering adjacency of elements.</p>"; + ret += " <h4><a name='adjacent-sibling-combinators'>8.3.1. Adjacent sibling combinator</a>"; + ret += " </h4>"; + ret += " <p>The adjacent sibling combinator is made of the 'plus"; + ret += " sign' (U+002B, <code>+</code>) character that separates two"; + ret += " sequences of simple selectors. The elements represented by the two"; + ret += " represented by the second one.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <p>The following selector represents a <code>p</code> element"; + ret += " immediately following a <code>math</code> element:</p>"; + ret += " <pre>math + p</pre>"; + ret += " <p>The following selector is conceptually similar to the one in the"; + ret += " adds a constraint to the <code>h1</code> element, that it must have"; + ret += " <code>class='opener'</code>:</p>"; + ret += " <pre>h1.opener + h2</pre>"; + ret += " </div>"; + ret += " <h4><a name='general-sibling-combinators'>8.3.2. General sibling combinator</a>"; + ret += " </h4>"; + ret += " <p>The general sibling combinator is made of the 'tilde'"; + ret += " (U+007E, <code>~</code>) character that separates two sequences of"; + ret += " simple selectors. The elements represented by the two sequences share"; + ret += " represented by the second one.</p>"; + ret += " <div class='example'>"; + ret += " <p>Example:</p>"; + ret += " <pre>h1 ~ pre</pre>"; + ret += " <p>represents a <code>pre</code> element following an <code>h1</code>. It"; + ret += " is a correct and valid, but partial, description of:</p>"; + ret += " <pre><h1>Definition of the function a</h1>"; + ret += " <pre>function a(x) = 12x/13.5</pre></pre>"; + ret += " </div>"; + ret += " <h2><a name='specificity'>9. Calculating a selector's specificity</a></h2>"; + ret += " <p>A selector's specificity is calculated as follows:</p>"; + ret += " <ul>"; + ret += " <li>count the number of ID selectors in the selector (= a)</li>"; + ret += " <li>count the number of class selectors, attributes selectors, and"; + ret += " </li>"; + ret += " <li>count the number of element names in the selector (= c)</li>"; + ret += " <li>ignore pseudo-elements</li>"; + ret += " </ul>"; + ret += " <p>Selectors inside <a href='#negation'>the negation pseudo-class</a>"; + ret += " a pseudo-class.</p>"; + ret += " <p>Concatenating the three numbers a-b-c (in a number system with a"; + ret += " large base) gives the specificity.</p>"; + ret += " <div class='example'>"; + ret += " <p>Examples:</p>"; + ret += " <pre>* /* a=0 b=0 c=0 -> specificity = 0 */"; + ret += " </pre>"; + ret += " </div>"; + ret += " <p class='note'><strong>Note:</strong> the specificity of the styles"; + ret += " specified in an HTML <code>style</code> attribute is described in CSS"; + ret += " 2.1. <a href='#refsCSS21'>[CSS21]</a>.</p>"; + ret += " <h2><a name='w3cselgrammar'>10. The grammar of Selectors</a></h2>"; + ret += " <h3><a name='grammar'>10.1. Grammar</a></h3>"; + ret += " <p>The grammar below defines the syntax of Selectors. It is globally"; + ret += " shorthand notations beyond Yacc (see <a href='#refsYACC'>[YACC]</a>)"; + ret += " are used:</p>"; + ret += " <ul>"; + ret += " <li><b>*</b>: 0 or more"; + ret += " </li><li><b>+</b>: 1 or more"; + ret += " </li><li><b>?</b>: 0 or 1"; + ret += " </li><li><b>|</b>: separates alternatives"; + ret += " </li><li><b>[ ]</b>: grouping</li>"; + ret += " </ul>"; + ret += " <p>The productions are:</p>"; + ret += " <pre>selectors_group"; + ret += " ;</pre>"; + ret += " <h3><a name='lex'>10.2. Lexical scanner</a></h3>"; + ret += " <p>The following is the <a name='x3'>tokenizer</a>, written in Flex (see"; + ret += " <a href='#refsFLEX'>[FLEX]</a>) notation. The tokenizer is"; + ret += " case-insensitive.</p>"; + ret += " <p>The two occurrences of '\377' represent the highest character"; + ret += " possible code point in Unicode/ISO-10646. <a href='#refsUNICODE'>[UNICODE]</a></p>"; + ret += " <pre>%option case-insensitive"; + ret += " . return *yytext;</pre>"; + ret += " <h2><a name='downlevel'>11. Namespaces and down-level clients</a></h2>"; + ret += " <p>An important issue is the interaction of CSS selectors with XML"; + ret += " to construct a CSS style sheet which will properly match selectors in"; + ret += " is possible to construct a style sheet in which selectors would match"; + ret += " elements and attributes correctly.</p>"; + ret += " <p>It should be noted that a down-level CSS client will (if it"; + ret += " <code>@namespace</code> at-rules, as well as all style rules that make"; + ret += " use of namespace qualified element type or attribute selectors. The"; + ret += " than possibly match them incorrectly.</p>"; + ret += " <p>The use of default namespaces in CSS makes it possible to write"; + ret += " element type selectors that will function in both namespace aware CSS"; + ret += " down-level clients may incorrectly match selectors against XML"; + ret += " elements in other namespaces.</p>"; + ret += " <p>The following are scenarios and examples in which it is possible to"; + ret += " that do not implement this proposal.</p>"; + ret += " <ol>"; + ret += " <li>"; + ret += " <p>The XML document does not use namespaces.</p>"; + ret += " <ul>"; + ret += " <li>In this case, it is obviously not necessary to declare or use"; + ret += " attribute selectors will function adequately in a down-level"; + ret += " </li>"; + ret += " <li>In a CSS namespace aware client, the default behavior of"; + ret += " element selectors matching without regard to namespace will"; + ret += " present. However, the use of specific element type selectors"; + ret += " match only elements that have no namespace ('<code>|name</code>')"; + ret += " will guarantee that selectors will match only XML elements that"; + ret += " </li>"; + ret += " </ul>"; + ret += " </li>"; + ret += " <li>"; + ret += " <p>The XML document defines a single, default namespace used"; + ret += " names.</p>"; + ret += " <ul>"; + ret += " <li>In this case, a down-level client will function as if"; + ret += " element type and attribute selectors will match against all"; + ret += " </li>"; + ret += " </ul>"; + ret += " </li>"; + ret += " <li>"; + ret += " <p>The XML document does <b>not</b> use a default namespace, all"; + ret += " to the same URI).</p>"; + ret += " <ul>"; + ret += " <li>In this case, the down-level client will view and match"; + ret += " element type and attribute selectors based on their fully"; + ret += " qualified name, not the local part as outlined in the <a href='#typenmsp'>Type selectors and Namespaces</a>"; + ret += " selectors may be declared using an escaped colon"; + ret += " '<code>\\:</code>'"; + ret += " '<code>html\\:h1</code>' will match"; + ret += " <code><html:h1></code>. Selectors using the qualified name"; + ret += " </li>"; + ret += " <li>Note that selectors declared in this fashion will"; + ret += " <em>only</em> match in down-level clients. A CSS namespace aware"; + ret += " client will match element type and attribute selectors based on"; + ret += " the name's local part. Selectors declared with the fully"; + ret += " </li>"; + ret += " </ul>"; + ret += " </li>"; + ret += " </ol>"; + ret += " <p>In other scenarios: when the namespace prefixes used in the XML are"; + ret += " <em>different</em> namespace URIs within the same document, or in"; + ret += " a CSS and XML namespace aware client.</p>"; + ret += " <h2><a name='profiling'>12. Profiles</a></h2>"; + ret += " <p>Each specification using Selectors must define the subset of W3C"; + ret += " Selectors it allows and excludes, and describe the local meaning of"; + ret += " all the components of that subset.</p>"; + ret += " <p>Non normative examples:"; + ret += " </p><div class='profile'>"; + ret += " <table class='tprofile'>"; + ret += " <tbody>"; + ret += " <tr>"; + ret += " <th class='title' colspan='2'>Selectors profile</th>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Specification</th>"; + ret += " <td>CSS level 1</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Accepts</th>"; + ret += " <td>type selectors<br>class selectors<br>ID selectors<br>:link,"; + ret += " :visited and :active pseudo-classes<br>descendant combinator"; + ret += " <br>::first-line and ::first-letter pseudo-elements"; + ret += " </td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Excludes</th>"; + ret += " <td>"; + ret += " <p>universal selector<br>attribute selectors<br>:hover and"; + ret += " pseudo-classes<br>:target pseudo-class<br>:lang()"; + ret += " pseudo-class<br>all UI"; + ret += " element states pseudo-classes<br>all structural"; + ret += " pseudo-classes<br>negation pseudo-class<br>all"; + ret += " UI element fragments pseudo-elements<br>::before and ::after"; + ret += " pseudo-elements<br>child combinators<br>sibling combinators"; + ret += " </p><p>namespaces</p></td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Extra constraints</th>"; + ret += " <td>only one class selector allowed per sequence of simple"; + ret += " selectors"; + ret += " </td>"; + ret += " </tr>"; + ret += " </tbody>"; + ret += " </table>"; + ret += " <br><br>"; + ret += " <table class='tprofile'>"; + ret += " <tbody>"; + ret += " <tr>"; + ret += " <th class='title' colspan='2'>Selectors profile</th>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Specification</th>"; + ret += " <td>CSS level 2</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Accepts</th>"; + ret += " <td>type selectors<br>universal selector<br>attribute presence and"; + ret += " values selectors<br>class selectors<br>ID selectors<br>:link,"; + ret += " <br>descendant combinator<br>child combinator<br>adjacent"; + ret += " combinator<br>::first-line and ::first-letter"; + ret += " pseudo-elements<br>::before"; + ret += " </td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Excludes</th>"; + ret += " <td>"; + ret += " <p>content selectors<br>substring matching attribute"; + ret += " selectors<br>:target pseudo-classes<br>all UI element"; + ret += " states pseudo-classes<br>all structural pseudo-classes other"; + ret += " than :first-child<br>negation pseudo-class<br>all UI element"; + ret += " fragments pseudo-elements<br>general sibling combinators"; + ret += " </p><p>namespaces</p></td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Extra constraints</th>"; + ret += " <td>more than one class selector per sequence of simple selectors"; + ret += " </td>"; + ret += " </tr>"; + ret += " </tbody>"; + ret += " </table>"; + ret += " <p>In CSS, selectors express pattern matching rules that determine which"; + ret += " </p><p>The following selector (CSS level 2) will <b>match</b> all anchors <code>a</code>"; + ret += " with attribute <code>name</code> set inside a section 1 header"; + ret += " <code>h1</code>:"; + ret += " </p><pre>h1 a[name]</pre>"; + ret += " <p>All CSS declarations attached to such a selector are applied to elements"; + ret += " matching it.</p></div>"; + ret += " <div class='profile'>"; + ret += " <table class='tprofile'>"; + ret += " <tbody>"; + ret += " <tr>"; + ret += " <th class='title' colspan='2'>Selectors profile</th>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Specification</th>"; + ret += " <td>STTS 3</td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Accepts</th>"; + ret += " <td>"; + ret += " <p>type selectors<br>universal selectors<br>attribute"; + ret += " selectors<br>class"; + ret += " selectors<br>ID selectors<br>all structural"; + ret += " pseudo-classes<br>"; + ret += " </p><p>namespaces</p></td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Excludes</th>"; + ret += " <td>non-accepted pseudo-classes<br>pseudo-elements<br></td>"; + ret += " </tr>"; + ret += " <tr>"; + ret += " <th>Extra constraints</th>"; + ret += " <td>some selectors and combinators are not allowed in fragment"; + ret += " </td>"; + ret += " </tr>"; + ret += " </tbody>"; + ret += " </table>"; + ret += " <p>Selectors can be used in STTS 3 in two different"; + ret += " </p><ol>"; + ret += " <li>a selection mechanism equivalent to CSS selection mechanism:"; + ret += " </li><li>fragment descriptions that appear on the right side of declarations."; + ret += " </li>"; + ret += " </ol>"; + ret += " </div>"; + ret += " <h2><a name='Conformance'></a>13. Conformance and requirements</h2>"; + ret += " <p>This section defines conformance with the present specification only."; + ret += " </p><p>The inability of a user agent to implement part of this specification due to"; + ret += " </p><p>All specifications reusing Selectors must contain a <a href='#profiling'>Profile</a> listing the"; + ret += " subset of Selectors it accepts or excludes, and describing the constraints"; + ret += " </p><p>Invalidity is caused by a parsing error, e.g. an unrecognized token or a"; + ret += " </p><p>User agents must observe the rules for handling parsing errors:"; + ret += " </p><ul>"; + ret += " <li>a simple selector containing an undeclared namespace prefix is invalid"; + ret += " </li>"; + ret += " <li>a selector containing an invalid simple selector, an invalid combinator"; + ret += " </li>"; + ret += " <li>a group of selectors containing an invalid selector is invalid.</li>"; + ret += " </ul>"; + ret += " <p>Specifications reusing Selectors must define how to handle parsing"; + ret += " used is dropped.)</p>"; + ret += " <!-- Apparently all these references are out of date:"; + ret += " <p>Implementations of this specification must behave as"; + ret += " 'recipients of text data' as defined by <a href='#refsCWWW'>[CWWW]</a>"; + ret += " when parsing selectors and attempting matches. (In particular,"; + ret += " <a href='#refsCWWW'>[CWWW]</a> and <a"; + ret += " href='#refsUNICODE'>[UNICODE]</a> and apply to implementations of this"; + ret += " specification.</p>-->"; + ret += " <h2><a name='Tests'></a>14. Tests</h2>"; + ret += " <p>This specification has <a href='http://www.w3.org/Style/CSS/Test/CSS3/Selectors/current/'>a test"; + ret += " suite</a> allowing user agents to verify their basic conformance to"; + ret += " and does not cover all possible combined cases of Selectors.</p>"; + ret += " <h2><a name='ACKS'></a>15. Acknowledgements</h2>"; + ret += " <p>The CSS working group would like to thank everyone who has sent"; + ret += " comments on this specification over the years.</p>"; + ret += " <p>The working group would like to extend special thanks to Donna"; + ret += " the final editorial review.</p>"; + ret += " <h2><a name='references'>16. References</a></h2>"; + ret += " <dl class='refs'>"; + ret += " <dt>[CSS1]"; + ret += " </dt><dd><a name='refsCSS1'></a> Bert Bos, Håkon Wium Lie; '<cite>Cascading"; + ret += " Style Sheets, level 1</cite>', W3C Recommendation, 17 Dec 1996, revised"; + ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/REC-CSS1'>http://www.w3.org/TR/REC-CSS1</a></code>)"; + ret += " </dd><dt>[CSS21]"; + ret += " </dt><dd><a name='refsCSS21'></a> Bert Bos, Tantek Çelik, Ian Hickson, Håkon"; + ret += " Wium Lie, editors; '<cite>Cascading Style Sheets, level 2 revision"; + ret += " 1</cite>', W3C Working Draft, 13 June 2005"; + ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/CSS21'>http://www.w3.org/TR/CSS21</a></code>)"; + ret += " </dd><dt>[CWWW]"; + ret += " </dt><dd><a name='refsCWWW'></a> Martin J. Dürst, François Yergeau,"; + ret += " Misha Wolf, Asmus Freytag, Tex Texin, editors; '<cite>Character Model"; + ret += " for the World Wide Web</cite>', W3C Recommendation, 15 February 2005"; + ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/charmod/'>http://www.w3.org/TR/charmod/</a></code>)"; + ret += " </dd><dt>[FLEX]"; + ret += " </dt><dd><a name='refsFLEX'></a> '<cite>Flex: The Lexical Scanner"; + ret += " Generator</cite>', Version 2.3.7, ISBN 1882114213"; + ret += " </dd><dt>[HTML4]"; + ret += " </dt><dd><a name='refsHTML4'></a> Dave Ragget, Arnaud Le Hors, Ian Jacobs,"; + ret += " editors; '<cite>HTML 4.01 Specification</cite>', W3C Recommendation, 24"; + ret += " </dd><dd>"; + ret += " (<a href='http://www.w3.org/TR/html4/'><code>http://www.w3.org/TR/html4/</code></a>)"; + ret += " </dd><dt>[MATH]"; + ret += " </dt><dd><a name='refsMATH'></a> Patrick Ion, Robert Miner, editors; '<cite>Mathematical"; + ret += " Markup Language (MathML) 1.01</cite>', W3C Recommendation, revision of 7"; + ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/REC-MathML/'>http://www.w3.org/TR/REC-MathML/</a></code>)"; + ret += " </dd><dt>[RFC3066]"; + ret += " </dt><dd><a name='refsRFC3066'></a> H. Alvestrand; '<cite>Tags for the"; + ret += " Identification of Languages</cite>', Request for Comments 3066, January"; + ret += " </dd><dd>(<a href='http://www.ietf.org/rfc/rfc3066.txt'><code>http://www.ietf.org/rfc/rfc3066.txt</code></a>)"; + ret += " </dd><dt>[STTS]"; + ret += " </dt><dd><a name='refsSTTS'></a> Daniel Glazman; '<cite>Simple Tree Transformation"; + ret += " Sheets 3</cite>', Electricité de France, submission to the W3C,"; + ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/NOTE-STTS3'>http://www.w3.org/TR/NOTE-STTS3</a></code>)"; + ret += " </dd><dt>[SVG]"; + ret += " </dt><dd><a name='refsSVG'></a> Jon Ferraiolo, 藤沢 淳, Dean"; + ret += " Jackson, editors; '<cite>Scalable Vector Graphics (SVG) 1.1"; + ret += " Specification</cite>', W3C Recommendation, 14 January 2003"; + ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/SVG/'>http://www.w3.org/TR/SVG/</a></code>)"; + ret += " </dd><dt>[UNICODE]</dt>"; + ret += " <dd><a name='refsUNICODE'></a> <cite><a href='http://www.unicode.org/versions/Unicode4.1.0/'>The Unicode"; + ret += " Standard, Version 4.1</a></cite>, The Unicode Consortium. Boston, MA,"; + ret += " Addison-Wesley, March 2005. ISBN 0-321-18578-1, as amended by <a href='http://www.unicode.org/versions/Unicode4.0.1/'>Unicode"; + ret += " 4.0.1</a> and <a href='http://www.unicode.org/versions/Unicode4.1.0/'>Unicode"; + ret += " 4.1.0</a>."; + ret += " </dd><dd>(<code><a href='http://www.unicode.org/versions/'>http://www.unicode.org/versions/</a></code>)"; + ret += " </dd>"; + ret += " <dt>[XML10]"; + ret += " </dt><dd><a name='refsXML10'></a> Tim Bray, Jean Paoli, C. M. Sperberg-McQueen,"; + ret += " Eve Maler, François Yergeau, editors; '<cite>Extensible Markup"; + ret += " Language (XML) 1.0 (Third Edition)</cite>', W3C Recommendation, 4"; + ret += " </dd><dd>(<a href='http://www.w3.org/TR/REC-xml/'><code>http://www.w3.org/TR/REC-xml/</code></a>)"; + ret += " </dd><dt>[XMLNAMES]"; + ret += " </dt><dd><a name='refsXMLNAMES'></a> Tim Bray, Dave Hollander, Andrew Layman,"; + ret += " editors; '<cite>Namespaces in XML</cite>', W3C Recommendation, 14"; + ret += " </dd><dd>(<a href='http://www.w3.org/TR/REC-xml-names/'><code>http://www.w3.org/TR/REC-xml-names/</code></a>)"; + ret += " </dd><dt>[YACC]"; + ret += " </dt><dd><a name='refsYACC'></a> S. C. Johnson; '<cite>YACC — Yet another"; + ret += " compiler compiler</cite>', Technical Report, Murray Hill, 1975"; + ret += " </dd></dl>'; </div>"; + ret += " <input name='n' value='v1' type='radio'>1"; + ret += " <input name='n' value='v2' checked='checked' type='radio'>2"; + $(e).html(ret); + } + +} diff --git a/samples/src/main/java/gwtquery/samples/client/GwtQueryDemoModule.java b/samples/src/main/java/gwtquery/samples/client/GwtQueryDemoModule.java index 5bc16db9..82b46944 100644 --- a/samples/src/main/java/gwtquery/samples/client/GwtQueryDemoModule.java +++ b/samples/src/main/java/gwtquery/samples/client/GwtQueryDemoModule.java @@ -1,103 +1,103 @@ -/*
- * 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 gwtquery.samples.client;
-
-import static com.google.gwt.query.client.GQuery.$;
-import static com.google.gwt.query.client.plugins.Effects.Effects;
-
-import com.google.gwt.core.client.EntryPoint;
-import com.google.gwt.core.client.GWT;
-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.query.client.Function;
-import com.google.gwt.query.client.GQuery;
-import com.google.gwt.query.client.Selector;
-import com.google.gwt.query.client.Selectors;
-import com.google.gwt.query.client.plugins.Effects.Speed;
-import com.google.gwt.user.client.Event;
-
-/**
- *
- */
-public class GwtQueryDemoModule implements EntryPoint {
-
- // Compile-time Selectors!
- public interface Slide extends Selectors {
-
- // find all LI elements in DIV.slide elements
- @Selector("div.slide li")
- NodeList<Element> allSlideBullets();
-
- // Find all DIV elements with class 'slide'
- @Selector("div.slide")
- NodeList<Element> allSlides();
-
- // find all LI elements rooted at ctx
- @Selector("li")
- NodeList<Element> slideBulletsCtx(Node ctx);
- }
-
- public void onModuleLoad() {
- // Ask GWT compiler to generate our interface
- final Slide s = GWT.create(Slide.class);
- final GQuery slides = $(s.allSlides());
-
- // we initially hide all slides and bullets
- slides.hide().eq(0).as(Effects).clipAppear();
- $(s.allSlideBullets()).hide();
-
-
- // add onclick handler to body element
- $(slides).click(new Function() {
- // two state variables to note current slide being shown
- // and current bullet
- int curSlide = 0;
- int curBullets = 0;
-
- // query and store all bullets of current slide
- GQuery bullets = $(s.slideBulletsCtx(slides.get(curSlide)));
-
- public boolean f(Event e) {
- // onclick, if not all bullets shown, show a bullet and increment
- if (curBullets < bullets.size()) {
- bullets.eq(curBullets++).as(Effects).fadeIn(Speed.SLOW);
- } else {
- // all bullets shown, hide them and current slide
- bullets.hide();
-
- // move to next slide, checking for wrap around
- int lastSlide = curSlide++;
- if (curSlide == slides.size()) {
- curSlide = 0;
- }
-
- // query for new set of bullets, and show next slide
- curBullets = 0;
- bullets = $(s.slideBulletsCtx(slides.get(curSlide)));
-
- // Hide the last slide and show the next when the effects finishes
- slides.eq(lastSlide).as(Effects).fadeOut(new Function() {
- public void f(Element e) {
- slides.eq(curSlide).as(Effects).clipAppear();
- }
- });
- }
- return true;
- }
- });
- }
-}
+/* + * 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 gwtquery.samples.client; + +import static com.google.gwt.query.client.GQuery.$; +import static com.google.gwt.query.client.plugins.Effects.Effects; + +import com.google.gwt.core.client.EntryPoint; +import com.google.gwt.core.client.GWT; +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.query.client.Function; +import com.google.gwt.query.client.GQuery; +import com.google.gwt.query.client.Selector; +import com.google.gwt.query.client.Selectors; +import com.google.gwt.query.client.plugins.Effects.Speed; +import com.google.gwt.user.client.Event; + +/** + * + */ +public class GwtQueryDemoModule implements EntryPoint { + + // Compile-time Selectors! + public interface Slide extends Selectors { + + // find all LI elements in DIV.slide elements + @Selector("div.slide li") + NodeList<Element> allSlideBullets(); + + // Find all DIV elements with class 'slide' + @Selector("div.slide") + NodeList<Element> allSlides(); + + // find all LI elements rooted at ctx + @Selector("li") + NodeList<Element> slideBulletsCtx(Node ctx); + } + + public void onModuleLoad() { + // Ask GWT compiler to generate our interface + final Slide s = GWT.create(Slide.class); + final GQuery slides = $(s.allSlides()); + + // we initially hide all slides and bullets + slides.hide().eq(0).as(Effects).clipAppear(); + $(s.allSlideBullets()).hide(); + + + // add onclick handler to body element + $(slides).click(new Function() { + // two state variables to note current slide being shown + // and current bullet + int curSlide = 0; + int curBullets = 0; + + // query and store all bullets of current slide + GQuery bullets = $(s.slideBulletsCtx(slides.get(curSlide))); + + public boolean f(Event e) { + // onclick, if not all bullets shown, show a bullet and increment + if (curBullets < bullets.size()) { + bullets.eq(curBullets++).as(Effects).fadeIn(Speed.SLOW); + } else { + // all bullets shown, hide them and current slide + bullets.hide(); + + // move to next slide, checking for wrap around + int lastSlide = curSlide++; + if (curSlide == slides.size()) { + curSlide = 0; + } + + // query for new set of bullets, and show next slide + curBullets = 0; + bullets = $(s.slideBulletsCtx(slides.get(curSlide))); + + // Hide the last slide and show the next when the effects finishes + slides.eq(lastSlide).as(Effects).fadeOut(new Function() { + public void f(Element e) { + slides.eq(curSlide).as(Effects).clipAppear(); + } + }); + } + return true; + } + }); + } +} diff --git a/samples/src/main/java/gwtquery/samples/client/GwtQueryEffectsModule.java b/samples/src/main/java/gwtquery/samples/client/GwtQueryEffectsModule.java index 8f5157ad..563f29e7 100644 --- a/samples/src/main/java/gwtquery/samples/client/GwtQueryEffectsModule.java +++ b/samples/src/main/java/gwtquery/samples/client/GwtQueryEffectsModule.java @@ -1,123 +1,123 @@ -/*
- * 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 gwtquery.samples.client;
-
-import static com.google.gwt.query.client.GQuery.$;
-import static com.google.gwt.query.client.GQuery.$$;
-import static com.google.gwt.query.client.GQuery.lazy;
-
-import com.google.gwt.core.client.EntryPoint;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Style.Position;
-import com.google.gwt.query.client.Function;
-import com.google.gwt.query.client.css.CSS;
-import com.google.gwt.query.client.css.Length;
-import com.google.gwt.query.client.css.RGBColor;
-import com.google.gwt.query.client.plugins.Effects;
-import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing;
-import com.google.gwt.user.client.Event;
-
-public class GwtQueryEffectsModule implements EntryPoint {
-
- public void onModuleLoad() {
- $("div > div").css(CSS.COLOR.with(RGBColor.BLUE))
- .hover(lazy().css(CSS.COLOR.with(RGBColor.RED)).done(),
- lazy().css(CSS.COLOR.with(RGBColor.BLUE)).done());
-
- $("div.outer > div").css(CSS.POSITION.with(Position.RELATIVE)).dblclick(new Function() {
- public boolean f(Event e) {
- $("div.outer > div").as(Effects.Effects).
- animate($$("left: '+=100'"), 400, Easing.LINEAR).
- animate($$("top: '+=100'"), 400, Easing.LINEAR).
- animate($$("left: '-=100'"), 400, Easing.LINEAR).
- animate($$("top: '-=100'"), 400, Easing.LINEAR);
- return true;
- }
- });
- $(".note").click(lazy().fadeOut().done());
- $(".note").append(" Hello");
-
- final Effects a = $(".a, .b > div:nth-child(2)").as(Effects.Effects);
- final Effects b = $(".b > div:nth-child(odd)").as(Effects.Effects);
-
- $("#b0").width(150).css(CSS.FONT_SIZE.with(Length.px(10))).toggle(new Function() {
- public void f(Element e) {
- $("#b0").as(Effects.Effects).animate(" width: '400', opacity: '0.4', marginLeft: '0.6in', fontSize: '24px'");
- }
- }, new Function() {
- public void f(Element e) {
- $("#b0").as(Effects.Effects).animate(" width: '150', opacity: '1', marginLeft: '0', fontSize: '10px'");
- }
- });
-
- $("#b1").toggle(new Function() {
- public void f(Element e) {
- $(".a").toggle();
- }
- }, new Function() {
- public void f(Element e) {
- a.fadeOut();
- }
- }, new Function() {
- public void f(Element e) {
- a.fadeIn();
- }
- }, new Function() {
- public void f(Element e) {
- a.slideUp();
- }
- }, new Function() {
- public void f(Element e) {
- a.slideDown();
- }
- }, new Function() {
- public void f(Element e) {
- a.slideLeft();
- }
- }, new Function() {
- public void f(Element e) {
- a.slideRight();
- }
- }, new Function() {
- public void f(Element e) {
- a.animate("left: '+=300', width: 'hide'");
- }
- }, new Function() {
- public void f(Element e) {
- a.animate("left: '-=300', width: 'show'");
- }
- });
-
- $("#b2").toggle(new Function() {
- public void f(Element e) {
- b.as(Effects.Effects).clipUp();
- }
- }, new Function() {
- public void f(Element e) {
- b.as(Effects.Effects).clipDown();
- }
- }, new Function() {
- public void f(Element e) {
- b.as(Effects.Effects).clipDisappear();
- }
- }, new Function() {
- public void f(Element e) {
- b.as(Effects.Effects).clipAppear();
- }
- });
-
- }
-}
+/* + * 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 gwtquery.samples.client; + +import static com.google.gwt.query.client.GQuery.$; +import static com.google.gwt.query.client.GQuery.$$; +import static com.google.gwt.query.client.GQuery.lazy; + +import com.google.gwt.core.client.EntryPoint; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.Style.Position; +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.css.CSS; +import com.google.gwt.query.client.css.Length; +import com.google.gwt.query.client.css.RGBColor; +import com.google.gwt.query.client.plugins.Effects; +import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing; +import com.google.gwt.user.client.Event; + +public class GwtQueryEffectsModule implements EntryPoint { + + public void onModuleLoad() { + $("div > div").css(CSS.COLOR.with(RGBColor.BLUE)) + .hover(lazy().css(CSS.COLOR.with(RGBColor.RED)).done(), + lazy().css(CSS.COLOR.with(RGBColor.BLUE)).done()); + + $("div.outer > div").css(CSS.POSITION.with(Position.RELATIVE)).dblclick(new Function() { + public boolean f(Event e) { + $("div.outer > div").as(Effects.Effects). + animate($$("left: '+=100'"), 400, Easing.LINEAR). + animate($$("top: '+=100'"), 400, Easing.LINEAR). + animate($$("left: '-=100'"), 400, Easing.LINEAR). + animate($$("top: '-=100'"), 400, Easing.LINEAR); + return true; + } + }); + $(".note").click(lazy().fadeOut().done()); + $(".note").append(" Hello"); + + final Effects a = $(".a, .b > div:nth-child(2)").as(Effects.Effects); + final Effects b = $(".b > div:nth-child(odd)").as(Effects.Effects); + + $("#b0").width(150).css(CSS.FONT_SIZE.with(Length.px(10))).toggle(new Function() { + public void f(Element e) { + $("#b0").as(Effects.Effects).animate(" width: '400', opacity: '0.4', marginLeft: '0.6in', fontSize: '24px'"); + } + }, new Function() { + public void f(Element e) { + $("#b0").as(Effects.Effects).animate(" width: '150', opacity: '1', marginLeft: '0', fontSize: '10px'"); + } + }); + + $("#b1").toggle(new Function() { + public void f(Element e) { + $(".a").toggle(); + } + }, new Function() { + public void f(Element e) { + a.fadeOut(); + } + }, new Function() { + public void f(Element e) { + a.fadeIn(); + } + }, new Function() { + public void f(Element e) { + a.slideUp(); + } + }, new Function() { + public void f(Element e) { + a.slideDown(); + } + }, new Function() { + public void f(Element e) { + a.slideLeft(); + } + }, new Function() { + public void f(Element e) { + a.slideRight(); + } + }, new Function() { + public void f(Element e) { + a.animate("left: '+=300', width: 'hide'"); + } + }, new Function() { + public void f(Element e) { + a.animate("left: '-=300', width: 'show'"); + } + }); + + $("#b2").toggle(new Function() { + public void f(Element e) { + b.as(Effects.Effects).clipUp(); + } + }, new Function() { + public void f(Element e) { + b.as(Effects.Effects).clipDown(); + } + }, new Function() { + public void f(Element e) { + b.as(Effects.Effects).clipDisappear(); + } + }, new Function() { + public void f(Element e) { + b.as(Effects.Effects).clipAppear(); + } + }); + + } +} diff --git a/samples/src/main/java/gwtquery/samples/client/GwtQueryImageZoom.java b/samples/src/main/java/gwtquery/samples/client/GwtQueryImageZoom.java index 130ae116..95f55410 100644 --- a/samples/src/main/java/gwtquery/samples/client/GwtQueryImageZoom.java +++ b/samples/src/main/java/gwtquery/samples/client/GwtQueryImageZoom.java @@ -1,46 +1,46 @@ -/*
- * 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 gwtquery.samples.client;
-
-import static com.google.gwt.query.client.GQuery.$;
-
-import com.google.gwt.core.client.EntryPoint;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.query.client.Function;
-import com.google.gwt.query.client.plugins.Effects;
-
-/**
- * @author Manolo Carrasco
- */
-public class GwtQueryImageZoom implements EntryPoint {
-
- public void onModuleLoad() {
- // Fancy Thumbnail Hover Effect w/ jQuery - by Soh Tanaka
- // http://www.sohtanaka.com/web-design/examples/image-zoom/
- $("ul.thumb li").hover(new Function() {
- public void f(Element e) {
- $(e).css("z-index", "10").find("img").addClass("hover")
- .as(Effects.Effects).stop()
- .animate("marginTop: '-110px', marginLeft: '-110px', top: '50%', left: '50%', width: '174px', height: '174px', padding: '20px'", 200);
- }} , new Function() {
- public void f(Element e) {
- $(e).css("z-index", "0").find("img").removeClass("hover")
- .as(Effects.Effects).stop()
- .animate("marginTop: '0', marginLeft: '0', top: '0%', left: '0%', width: '100px', height: '100px', padding: '5px'", 600);
- }});
-
- }
-}
+/* + * 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 gwtquery.samples.client; + +import static com.google.gwt.query.client.GQuery.$; + +import com.google.gwt.core.client.EntryPoint; +import com.google.gwt.dom.client.Element; +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.plugins.Effects; + +/** + * @author Manolo Carrasco + */ +public class GwtQueryImageZoom implements EntryPoint { + + public void onModuleLoad() { + // Fancy Thumbnail Hover Effect w/ jQuery - by Soh Tanaka + // http://www.sohtanaka.com/web-design/examples/image-zoom/ + $("ul.thumb li").hover(new Function() { + public void f(Element e) { + $(e).css("z-index", "10").find("img").addClass("hover") + .as(Effects.Effects).stop() + .animate("marginTop: '-110px', marginLeft: '-110px', top: '50%', left: '50%', width: '174px', height: '174px', padding: '20px'", 200); + }} , new Function() { + public void f(Element e) { + $(e).css("z-index", "0").find("img").removeClass("hover") + .as(Effects.Effects).stop() + .animate("marginTop: '0', marginLeft: '0', top: '0%', left: '0%', width: '100px', height: '100px', padding: '5px'", 600); + }}); + + } +} diff --git a/samples/src/main/java/gwtquery/samples/client/GwtQuerySampleModule.java b/samples/src/main/java/gwtquery/samples/client/GwtQuerySampleModule.java index 581d34ae..0d35c10e 100644 --- a/samples/src/main/java/gwtquery/samples/client/GwtQuerySampleModule.java +++ b/samples/src/main/java/gwtquery/samples/client/GwtQuerySampleModule.java @@ -1,80 +1,80 @@ -/*
- * 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 gwtquery.samples.client;
-
-import static com.google.gwt.query.client.GQuery.$;
-import static com.google.gwt.query.client.GQuery.document;
-import static com.google.gwt.query.client.GQuery.lazy;
-import static com.google.gwt.query.client.plugins.Widgets.Widgets;
-
-import com.google.gwt.core.client.EntryPoint;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Style.Cursor;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.query.client.GQuery;
-import com.google.gwt.query.client.Selector;
-import com.google.gwt.query.client.Selectors;
-import com.google.gwt.query.client.css.CSS;
-import com.google.gwt.query.client.css.RGBColor;
-import com.google.gwt.query.client.plugins.widgets.WidgetInitializer;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Label;
-
-public class GwtQuerySampleModule implements EntryPoint {
-
- public interface Sample extends Selectors {
- @Selector(".note")
- GQuery allNotes();
- }
-
- public void onModuleLoad() {
- // Use compiled selectors
- Sample s = GWT.create(Sample.class);
-
- // Just a simple usage of dom manipulation, events, and lazy usage
- s.allNotes().text("Hello Google I/O").
- css(CSS.CURSOR.with(Cursor.POINTER)).
- toggle(
- lazy().css(CSS.COLOR.with(RGBColor.RED)).done(),
- lazy().css(CSS.COLOR.with(null)).done()
- );
- // Cascade effects
- $("<div id='id' style='font-size: 150%;'>Cascade Efects</div>").appendTo(document).hide().fadeIn(5000).fadeOut(3000);
-
- // Widgets
- $(".btn").as(Widgets).button(new WidgetInitializer<Button>() {
- public void initialize(Button button, Element e) {
- final String tag = e.getTagName();
- button.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent event) {
- Window.alert("You click on a GWT Button created from a " + tag);
- }
- });
- }
- });
- $(".inputText").as(Widgets).textBox();
- $(".inputPsw").as(Widgets).passwordBox();
- $(".textArea").as(Widgets).textArea();
- $(".label").as(Widgets).label(new WidgetInitializer<Label>() {
- public void initialize(Label label, Element e) {
- label.setText("I'm a gwt label, created from a " + e.getTagName());
- }
- });
- }
-}
+/* + * 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 gwtquery.samples.client; + +import static com.google.gwt.query.client.GQuery.$; +import static com.google.gwt.query.client.GQuery.document; +import static com.google.gwt.query.client.GQuery.lazy; +import static com.google.gwt.query.client.plugins.Widgets.Widgets; + +import com.google.gwt.core.client.EntryPoint; +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.Style.Cursor; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.query.client.GQuery; +import com.google.gwt.query.client.Selector; +import com.google.gwt.query.client.Selectors; +import com.google.gwt.query.client.css.CSS; +import com.google.gwt.query.client.css.RGBColor; +import com.google.gwt.query.client.plugins.widgets.WidgetInitializer; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.Label; + +public class GwtQuerySampleModule implements EntryPoint { + + public interface Sample extends Selectors { + @Selector(".note") + GQuery allNotes(); + } + + public void onModuleLoad() { + // Use compiled selectors + Sample s = GWT.create(Sample.class); + + // Just a simple usage of dom manipulation, events, and lazy usage + s.allNotes().text("Hello Google I/O"). + css(CSS.CURSOR.with(Cursor.POINTER)). + toggle( + lazy().css(CSS.COLOR.with(RGBColor.RED)).done(), + lazy().css(CSS.COLOR.with(null)).done() + ); + // Cascade effects + $("<div id='id' style='font-size: 150%;'>Cascade Efects</div>").appendTo(document).hide().fadeIn(5000).fadeOut(3000); + + // Widgets + $(".btn").as(Widgets).button(new WidgetInitializer<Button>() { + public void initialize(Button button, Element e) { + final String tag = e.getTagName(); + button.addClickHandler(new ClickHandler() { + public void onClick(ClickEvent event) { + Window.alert("You click on a GWT Button created from a " + tag); + } + }); + } + }); + $(".inputText").as(Widgets).textBox(); + $(".inputPsw").as(Widgets).passwordBox(); + $(".textArea").as(Widgets).textArea(); + $(".label").as(Widgets).label(new WidgetInitializer<Label>() { + public void initialize(Label label, Element e) { + label.setText("I'm a gwt label, created from a " + e.getTagName()); + } + }); + } +} diff --git a/samples/src/main/java/gwtquery/samples/client/HomePageSample.java b/samples/src/main/java/gwtquery/samples/client/HomePageSample.java index ca845aff..c99c1a90 100644 --- a/samples/src/main/java/gwtquery/samples/client/HomePageSample.java +++ b/samples/src/main/java/gwtquery/samples/client/HomePageSample.java @@ -1,12 +1,12 @@ /* * 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 @@ -25,14 +25,14 @@ import com.google.gwt.query.client.css.Length; public class HomePageSample implements EntryPoint { - + public void onModuleLoad() { //Hide the text and set the width and append an h1 element $("#text").hide().css(CSS.WIDTH.with(Length.px(400))).prepend("<h1>GwtQuery Rocks !</h1>"); - + //add a click handler on the button $("button").click(new Function(){ - + public void f() { //display the text with effects and animate its background color $("#text").as(Effects) @@ -41,8 +41,8 @@ public class HomePageSample implements EntryPoint { .delay(1000) .animate("backgroundColor: '#fff'", 1500); } - + }); } - + } diff --git a/samples/src/main/java/gwtquery/samples/client/JsCollectionVsJavaCollection.java b/samples/src/main/java/gwtquery/samples/client/JsCollectionVsJavaCollection.java index c5bacd46..6d0c92d5 100644 --- a/samples/src/main/java/gwtquery/samples/client/JsCollectionVsJavaCollection.java +++ b/samples/src/main/java/gwtquery/samples/client/JsCollectionVsJavaCollection.java @@ -18,31 +18,31 @@ import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; public class JsCollectionVsJavaCollection implements EntryPoint{ - + public static final int MAX_ITEMS = GWT.isScript() ? 100000 : 100; - - + + public void onModuleLoad() { Button b = new Button("run test"); b.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { $(".gwt-label").remove(); - testJsMapVsHashMap(); + testJsMapVsHashMap(); } }); RootPanel.get().add(b); } - + public void testJsMapVsHashMap() { log("-------------"); for (int i = 0; i < MAX_ITEMS; i++){ new String(""+i); } - double ellapsedTime, totalTime; - + double ellapsedTime, totalTime; + JsCache cache = JsCache.create(); - + log("Testing cache : put "+MAX_ITEMS+" items in the cache :"); totalTime = ellapsedTime = Duration.currentTimeMillis(); for (int i = 0; i < MAX_ITEMS; i++){ @@ -50,7 +50,7 @@ public class JsCollectionVsJavaCollection implements EntryPoint{ } ellapsedTime = Duration.currentTimeMillis() - ellapsedTime; log(" ellapsed Time : "+ellapsedTime); - + log("Testing cache : get "+MAX_ITEMS+" from the cache :"); ellapsedTime = Duration.currentTimeMillis(); for (int i = 0 ; i < MAX_ITEMS; i++){ @@ -59,7 +59,7 @@ public class JsCollectionVsJavaCollection implements EntryPoint{ } ellapsedTime = Duration.currentTimeMillis() - ellapsedTime; log(" ellapsed Time : "+ellapsedTime); - + log("Testing cache : run "+MAX_ITEMS+" exist() in the cache :"); ellapsedTime = Duration.currentTimeMillis(); for (int i = 0 ; i < MAX_ITEMS; i++){ @@ -68,28 +68,28 @@ public class JsCollectionVsJavaCollection implements EntryPoint{ } ellapsedTime = Duration.currentTimeMillis() - ellapsedTime; log(" ellapsed Time : "+ellapsedTime); - + log("Testing cache : visit all keys() :"); ellapsedTime = Duration.currentTimeMillis(); for (String s: cache.keys()) { } ellapsedTime = Duration.currentTimeMillis() - ellapsedTime; log(" ellapsed Time : "+ellapsedTime); - + log("Testing cache : visit all values() :"); ellapsedTime = Duration.currentTimeMillis(); for (Object o: cache.elements()) { } ellapsedTime = Duration.currentTimeMillis() - ellapsedTime; log(" ellapsed Time : "+ellapsedTime); - + totalTime = Duration.currentTimeMillis() - totalTime; log(" Total : "+ totalTime + " ms."); log("-------------"); log(""); - + HashMap<String, Object> hashMap = new HashMap<String, Object>(); - + log("Testing hashMap : put "+MAX_ITEMS+" items in the map :"); totalTime = ellapsedTime = Duration.currentTimeMillis(); for (int i = 0; i < MAX_ITEMS; i++){ @@ -97,7 +97,7 @@ public class JsCollectionVsJavaCollection implements EntryPoint{ } ellapsedTime = Duration.currentTimeMillis() - ellapsedTime; log(" ellapsed Time : "+ellapsedTime); - + log("Testing hashMap : get "+MAX_ITEMS+" from the map :"); ellapsedTime = Duration.currentTimeMillis(); for (int i = 0 ; i < MAX_ITEMS; i++){ @@ -106,7 +106,7 @@ public class JsCollectionVsJavaCollection implements EntryPoint{ } ellapsedTime = Duration.currentTimeMillis() - ellapsedTime; log(" ellapsed Time : "+ellapsedTime); - + log("Testing hashMap : run "+MAX_ITEMS+" containsKey() in the map :"); ellapsedTime = Duration.currentTimeMillis(); for (int i = 0 ; i < MAX_ITEMS; i++){ @@ -115,21 +115,21 @@ public class JsCollectionVsJavaCollection implements EntryPoint{ } ellapsedTime = Duration.currentTimeMillis() - ellapsedTime; log(" ellapsed Time : "+ellapsedTime); - + log("Testing hashMap : visit all keySet() :"); ellapsedTime = Duration.currentTimeMillis(); for (String s: hashMap.keySet()) { } ellapsedTime = Duration.currentTimeMillis() - ellapsedTime; log(" ellapsed Time : "+ellapsedTime); - + log("Testing hashMap : visit all values() :"); ellapsedTime = Duration.currentTimeMillis(); for (Object o : hashMap.values()) { } ellapsedTime = Duration.currentTimeMillis() - ellapsedTime; log(" ellapsed Time : "+ellapsedTime); - + totalTime = Duration.currentTimeMillis() - totalTime; log(" Total : "+ totalTime + " ms."); log("-------------"); diff --git a/samples/src/main/java/gwtquery/samples/client/MySelectors.java b/samples/src/main/java/gwtquery/samples/client/MySelectors.java index a48f3c46..40ca11eb 100644 --- a/samples/src/main/java/gwtquery/samples/client/MySelectors.java +++ b/samples/src/main/java/gwtquery/samples/client/MySelectors.java @@ -1,12 +1,12 @@ /* * 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 diff --git a/samples/src/main/java/gwtquery/samples/client/effects/ColorEffectsSample.java b/samples/src/main/java/gwtquery/samples/client/effects/ColorEffectsSample.java index ffecd342..37a9bd81 100644 --- a/samples/src/main/java/gwtquery/samples/client/effects/ColorEffectsSample.java +++ b/samples/src/main/java/gwtquery/samples/client/effects/ColorEffectsSample.java @@ -1,12 +1,12 @@ /* * 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 @@ -26,17 +26,17 @@ public class ColorEffectsSample implements EntryPoint { public void onModuleLoad() { $("#shoot").click(new Function() { - + public void f() { $("body").animate("backgroundColor: 'red'", 400) .delay(1000) .animate("backgroundColor: 'white'", 2000); } - + }); - + $("#startAnim2").click(new Function(){ - + public void f() { $(".bar").animate("backgroundColor: 'yellow'", 1000) .delay(200) @@ -44,15 +44,15 @@ public class ColorEffectsSample implements EntryPoint { .delay(200) .animate("color:'rgb(255, 255, 255)'", 1000); } - + }); - + $("#resetAnim2").click(new Function(){ - + public void f() { $(".bar").css(CSS.BACKGROUND_COLOR.with(null), CSS.BORDER_COLOR.with(null), CSS.COLOR.with(null)); } - + }); } diff --git a/samples/src/main/java/gwtquery/samples/client/effects/FadeEffectsSample.java b/samples/src/main/java/gwtquery/samples/client/effects/FadeEffectsSample.java index 602208fc..e271f78c 100644 --- a/samples/src/main/java/gwtquery/samples/client/effects/FadeEffectsSample.java +++ b/samples/src/main/java/gwtquery/samples/client/effects/FadeEffectsSample.java @@ -1,12 +1,12 @@ /* * 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 @@ -25,7 +25,7 @@ import static com.google.gwt.query.client.GQuery.$; public class FadeEffectsSample implements EntryPoint { public void onModuleLoad() { - + // FadeIn sample $("#fadeIn div.foo").hide(); $("#fadeIn > button").click(new Function() { @@ -34,15 +34,15 @@ public class FadeEffectsSample implements EntryPoint { $("#fadeIn div.foo").as(Effects).fadeIn(2000); } }); - + $("#fadeIn > button.reset").click(new Function() { @Override public void f(Element e) { $("#fadeIn div.foo").hide(); } }); - - + + // FadeOut sample $("#fadeOut > button").click(new Function() { @Override @@ -50,7 +50,7 @@ public class FadeEffectsSample implements EntryPoint { $("#fadeOut div.foo").as(Effects).fadeOut(2000); } }); - + $("#fadeOut > button.reset").click(new Function() { @Override public void f(Element e) { @@ -65,7 +65,7 @@ public class FadeEffectsSample implements EntryPoint { $("#fadeToogle div.foo").as(Effects).fadeToggle(2000); } }); - + //Toogle sample $("#toogle > button").click(new Function() { diff --git a/samples/src/main/java/gwtquery/samples/client/effects/SlideEffectsSample.java b/samples/src/main/java/gwtquery/samples/client/effects/SlideEffectsSample.java index 0af1684e..2e3a1d81 100644 --- a/samples/src/main/java/gwtquery/samples/client/effects/SlideEffectsSample.java +++ b/samples/src/main/java/gwtquery/samples/client/effects/SlideEffectsSample.java @@ -1,12 +1,12 @@ /* * 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 @@ -33,7 +33,7 @@ public class SlideEffectsSample implements EntryPoint { $("#slideUp div.foo").as(Effects).slideUp(); } }); - + $("#slideUp > button.reset").click(new Function() { @Override public void f(Element e) { @@ -49,7 +49,7 @@ public class SlideEffectsSample implements EntryPoint { $("#slideDown div.foo").as(Effects).slideDown(); } }); - + $("#slideDown > button.reset").click(new Function() { @Override public void f(Element e) { @@ -64,7 +64,7 @@ public class SlideEffectsSample implements EntryPoint { $("#slideToogle div.foo").as(Effects).slideToggle(400); } }); - + // SlideLeft sample $("#slideLeft > button").click(new Function() { @Override @@ -72,15 +72,15 @@ public class SlideEffectsSample implements EntryPoint { $("#slideLeft div.foo").as(Effects).slideLeft(); } }); - + $("#slideLeft > button.reset").click(new Function() { @Override public void f(Element e) { $("#slideLeft div.foo").show(); } }); - - + + // SlideRight sample $("#slideRight div.foo").hide(); $("#slideRight > button").click(new Function() { @@ -89,14 +89,14 @@ public class SlideEffectsSample implements EntryPoint { $("#slideRight div.foo").as(Effects).slideRight(); } }); - + $("#slideRight > button.reset").click(new Function() { @Override public void f(Element e) { $("#slideRight div.foo").hide(); } }); - + } } diff --git a/samples/src/main/java/gwtquery/samples/public/AnimationsSample.html b/samples/src/main/java/gwtquery/samples/public/AnimationsSample.html index 83ab64ca..da9fb837 100644 --- a/samples/src/main/java/gwtquery/samples/public/AnimationsSample.html +++ b/samples/src/main/java/gwtquery/samples/public/AnimationsSample.html @@ -1,31 +1,31 @@ -<!doctype html>
-<html>
-<head>
-<title>GQuery Effects Sample</title>
-<script language="javascript" src="AnimationsSample.nocache.js"></script>
-<style type="text/css">
- body {
- font-family: Helvetica;
- }
- .reset {
- float: left;
- }
- .foo {
- border: 1px solid black;
- height:200px;
- width:200px;
- }
-</style>
-</head>
-<body>
-<h1>Animation, queue and delay methods</h1>
-<p>This example shows you how using gwtquery to make animation</p>
-<div>
-<button id="startMove">start movement animation</button><button id="stopMove">stop movement animation</button>
-</div>
-<div>
-<button id="startColor">start color animation</button><button id="stopColor">stop color animation</button>
-</div>
-<div class="foo"></div>
-</body>
-</html>
+<!doctype html> +<html> +<head> +<title>GQuery Effects Sample</title> +<script language="javascript" src="AnimationsSample.nocache.js"></script> +<style type="text/css"> + body { + font-family: Helvetica; + } + .reset { + float: left; + } + .foo { + border: 1px solid black; + height:200px; + width:200px; + } +</style> +</head> +<body> +<h1>Animation, queue and delay methods</h1> +<p>This example shows you how using gwtquery to make animation</p> +<div> +<button id="startMove">start movement animation</button><button id="stopMove">stop movement animation</button> +</div> +<div> +<button id="startColor">start color animation</button><button id="stopColor">stop color animation</button> +</div> +<div class="foo"></div> +</body> +</html> diff --git a/samples/src/main/java/gwtquery/samples/public/ColorEffectsSample.html b/samples/src/main/java/gwtquery/samples/public/ColorEffectsSample.html index 9624dd03..fe55faa2 100644 --- a/samples/src/main/java/gwtquery/samples/public/ColorEffectsSample.html +++ b/samples/src/main/java/gwtquery/samples/public/ColorEffectsSample.html @@ -1,51 +1,51 @@ -<!doctype html>
-<html>
-<head>
-<title>GQuery Effects Sample</title>
-<script language="javascript" src="ColorEffectsSample.nocache.js"></script>
-<style type="text/css">
-body {
- font-family: Helvetica;
-}
-
-.reset {
- float: left;
-}
-
-.foo {
- margin-top: 100px;
- margin-bottom: 100px; width : 100%;
- color: white;
- font-size: 60px;
- text-align: center;
- width: 100%;
-}
-
-.bar {
- border: solid 10px black;
- border-left-color: silver;
- border-right-color: silver;
- width : 200px;
- height: 200px;
- padding-top: 70px;
- font-size: 30px;
- text-align: center;
- width: 200px;
-}
-</style>
-</head>
-<body>
-<h1>Animate css color properties</h1>
-<p>This example shows you how using gwtquery to perform animation on
-color css properties (backgroundColor, color, corderColor...). Have a look at the <a href="http://code.google.com/p/gwtquery/source/browse/trunk/samples/src/main/java/gwtquery/samples/client/effects/ColorEffectsSample.java">java code</a></p>
-<div>
-<button id="shoot">Shoot This page!</button>
-</div>
-<div class="foo">BANG !</div>
-<div>
-<button id="startAnim2">Start animation</button>
-<button id="resetAnim2">Reset animation</button>
-</div>
-<div class="bar">GwtQuery</div>
-</body>
-</html>
+<!doctype html> +<html> +<head> +<title>GQuery Effects Sample</title> +<script language="javascript" src="ColorEffectsSample.nocache.js"></script> +<style type="text/css"> +body { + font-family: Helvetica; +} + +.reset { + float: left; +} + +.foo { + margin-top: 100px; + margin-bottom: 100px; width : 100%; + color: white; + font-size: 60px; + text-align: center; + width: 100%; +} + +.bar { + border: solid 10px black; + border-left-color: silver; + border-right-color: silver; + width : 200px; + height: 200px; + padding-top: 70px; + font-size: 30px; + text-align: center; + width: 200px; +} +</style> +</head> +<body> +<h1>Animate css color properties</h1> +<p>This example shows you how using gwtquery to perform animation on +color css properties (backgroundColor, color, corderColor...). Have a look at the <a href="http://code.google.com/p/gwtquery/source/browse/trunk/samples/src/main/java/gwtquery/samples/client/effects/ColorEffectsSample.java">java code</a></p> +<div> +<button id="shoot">Shoot This page!</button> +</div> +<div class="foo">BANG !</div> +<div> +<button id="startAnim2">Start animation</button> +<button id="resetAnim2">Reset animation</button> +</div> +<div class="bar">GwtQuery</div> +</body> +</html> diff --git a/samples/src/main/java/gwtquery/samples/public/GwtQueryBench.html b/samples/src/main/java/gwtquery/samples/public/GwtQueryBench.html index ac758024..3cfced81 100644 --- a/samples/src/main/java/gwtquery/samples/public/GwtQueryBench.html +++ b/samples/src/main/java/gwtquery/samples/public/GwtQueryBench.html @@ -1,176 +1,176 @@ -<!doctype html>
-
-<html>
-<head>
- <title>GwtQuery Benchmarks</title>
- <style>
- * {
- font-family: "Lucida Grande", Helvetica, Arial, sans-serif;
- color: white;
- font-size: 14px;
- }
- .resultstable {
- width: 100%;
- }
- .resultstable td {
- font-size: 10px;
- }
-
- #startrace {
- cursor: pointer;
- }
- body, select {
- background-color: black;
- }
-
- .win {
- background-color: green;
- color: white
- }
- .tie {
- background-color: orange;
- color: white
- }
- .lose {
- background-color: red;
- color: white
- }
- .broke {
- background-color: black;
- color: white
- }
-
- img.himg, img.flag {
- height: 35px;
- }
- img.logo {
- max-width: 100px;
- max-height: 30px;
- }
- .horse {
- position: relative;
- width: 150px;
- }
- .horse span {
- font-weight: bold;
- font-size: 12px;
- color: white;
- }
- #racefield {
- background-image: url(images/bench/grass-texture-small.jpg);
- background-repeat: repeat;
- border-radius: 9px;
- }
-
- .base {
- margin-top: 20px;
- margin-left: auto;
- margin-right: auto;
- width: 170px;
- }
- .base, .base a {
- font-size: 85%;
- color: green;
- }
- .lnk {
- float: right;
- margin-left: 20px;
- color: plum;
- margin-top: 10px;
- font-size: 12px;
- text-decoration: underline;
- cursor: pointer;
- }
- .lnk:hover {
- color: red;
- }
- h2 {
- float: left;
- color: white;
- border-bottom: 1px solid gray;
- width: 400px;
- }
-
- .gwt-PopupPanel {
- max-width: 80%;
- }
- .popupContent {
- background-color: LightSlateGrey;
- border: 2px solid grey;
- overflow: auto;
- border-radius: 7px;
- padding: 14px;
- }
- .clear {
- clear: both;
- }
- button {
- color: black;
- }
- </style>
-</head>
-<body>
- <h2>
- GwtQuery benchmarks
- </h2>
- <div class='lnk' id="about">About</div>
- <div class='lnk' id="startrace" >Loading Javascript frameworks, please wait ...</div><br/>
- <div class='clear'></div>
- <div id="racetrack" style="height: 0px; overflow: hidden;">
- <div id="racefield">
- </div>
- </div>
-
- <div id ="results" style="display: block; height: 300px; overflow-y:scroll; overflow-x: hidden; margin: 0">
- <table id="resultstable" border="1" style="width: 100%; border-collapse: collapse">
- </table>
- </div>
-
- <script language="javascript" src="gwtquery.samples.GwtQueryBench.nocache.js"></script>
-
- <div id='help' style='display: none'>
- This application has been designed to compare the speed between the different css selector-engines existing in <a href='http://gwtquery.googlecode.com'>gwtquery</a>, and against other javascript libraries.
- <br/>
- The html document and selectors used for the benchmark have been taken from the <a href='http://mootools.net/slickspeed/'>SlickSpeed</a> test.
- <br/>
- <br/>
- Click 'start the race' to test the selectors against most popular frameworks.
- <br/>
- If you wanted to experiment with other frameworks or different gquery engine implementations, append the parameter ask=true to the url and select the options in the popup window after clicking 'start'.
- <br/>
- Because normally css selectors takes less than 1 or 2 millisecons, each selector is run during a minimum of 200ms for each engine, then we divide the total time between the number of iterations and put this value in the cell, <br/>
- marking in green the faster engine.
- <br/>
- If an engine does not support a selector we put the word 'Error' in the corresponding cell and penalize the engine setting a value of 200ms for that iteration.
- <br/>
- The last row represents the acumulated time of the test for each engine.
- <br/>
- <br/>
-
- Some times, you could obtain different results when running the test with the same browser.
- <br/>
- This is due to random browser or system events which makes the current selector running delay some milliseconds.
- <br/>
- To avoid that, try to run the test in a browser running just one window and one tab, and in a computer without activity: close all applications, do not move the mouse etc.
- <br/>
- <br/>
- Leyend:
- <br/>
- - gwt_compiled: run css selectors which were optimized during the gwt compilation.
- <br/>
- - gwt_dynamic: evaluates selectors in runtime using the most suitable engine for this browser.
- <br/>
- - jquery, dojo, prototype ... : runs the selectors using those external libraries.
- <br/>
- - gwt_*: different runtime engines, some are experimental, and they could fail depending on the browser.
- <br/>
- <br/>
- Sources:
- <br/>
- <a href='http://code.google.com/p/gwtquery/source/browse/trunk/samples/src/main/java/gwtquery/samples/client/GwtQueryBenchModule.java'>Source code of this application</a> is available in the samples module of gwtquery.
- <br/>
- <br/>
- - The GwtQuery team.
- </div>
-</body>
-</html>
+<!doctype html> + +<html> +<head> + <title>GwtQuery Benchmarks</title> + <style> + * { + font-family: "Lucida Grande", Helvetica, Arial, sans-serif; + color: white; + font-size: 14px; + } + .resultstable { + width: 100%; + } + .resultstable td { + font-size: 10px; + } + + #startrace { + cursor: pointer; + } + body, select { + background-color: black; + } + + .win { + background-color: green; + color: white + } + .tie { + background-color: orange; + color: white + } + .lose { + background-color: red; + color: white + } + .broke { + background-color: black; + color: white + } + + img.himg, img.flag { + height: 35px; + } + img.logo { + max-width: 100px; + max-height: 30px; + } + .horse { + position: relative; + width: 150px; + } + .horse span { + font-weight: bold; + font-size: 12px; + color: white; + } + #racefield { + background-image: url(images/bench/grass-texture-small.jpg); + background-repeat: repeat; + border-radius: 9px; + } + + .base { + margin-top: 20px; + margin-left: auto; + margin-right: auto; + width: 170px; + } + .base, .base a { + font-size: 85%; + color: green; + } + .lnk { + float: right; + margin-left: 20px; + color: plum; + margin-top: 10px; + font-size: 12px; + text-decoration: underline; + cursor: pointer; + } + .lnk:hover { + color: red; + } + h2 { + float: left; + color: white; + border-bottom: 1px solid gray; + width: 400px; + } + + .gwt-PopupPanel { + max-width: 80%; + } + .popupContent { + background-color: LightSlateGrey; + border: 2px solid grey; + overflow: auto; + border-radius: 7px; + padding: 14px; + } + .clear { + clear: both; + } + button { + color: black; + } + </style> +</head> +<body> + <h2> + GwtQuery benchmarks + </h2> + <div class='lnk' id="about">About</div> + <div class='lnk' id="startrace" >Loading Javascript frameworks, please wait ...</div><br/> + <div class='clear'></div> + <div id="racetrack" style="height: 0px; overflow: hidden;"> + <div id="racefield"> + </div> + </div> + + <div id ="results" style="display: block; height: 300px; overflow-y:scroll; overflow-x: hidden; margin: 0"> + <table id="resultstable" border="1" style="width: 100%; border-collapse: collapse"> + </table> + </div> + + <script language="javascript" src="gwtquery.samples.GwtQueryBench.nocache.js"></script> + + <div id='help' style='display: none'> + This application has been designed to compare the speed between the different css selector-engines existing in <a href='http://gwtquery.googlecode.com'>gwtquery</a>, and against other javascript libraries. + <br/> + The html document and selectors used for the benchmark have been taken from the <a href='http://mootools.net/slickspeed/'>SlickSpeed</a> test. + <br/> + <br/> + Click 'start the race' to test the selectors against most popular frameworks. + <br/> + If you wanted to experiment with other frameworks or different gquery engine implementations, append the parameter ask=true to the url and select the options in the popup window after clicking 'start'. + <br/> + Because normally css selectors takes less than 1 or 2 millisecons, each selector is run during a minimum of 200ms for each engine, then we divide the total time between the number of iterations and put this value in the cell, <br/> + marking in green the faster engine. + <br/> + If an engine does not support a selector we put the word 'Error' in the corresponding cell and penalize the engine setting a value of 200ms for that iteration. + <br/> + The last row represents the acumulated time of the test for each engine. + <br/> + <br/> + + Some times, you could obtain different results when running the test with the same browser. + <br/> + This is due to random browser or system events which makes the current selector running delay some milliseconds. + <br/> + To avoid that, try to run the test in a browser running just one window and one tab, and in a computer without activity: close all applications, do not move the mouse etc. + <br/> + <br/> + Leyend: + <br/> + - gwt_compiled: run css selectors which were optimized during the gwt compilation. + <br/> + - gwt_dynamic: evaluates selectors in runtime using the most suitable engine for this browser. + <br/> + - jquery, dojo, prototype ... : runs the selectors using those external libraries. + <br/> + - gwt_*: different runtime engines, some are experimental, and they could fail depending on the browser. + <br/> + <br/> + Sources: + <br/> + <a href='http://code.google.com/p/gwtquery/source/browse/trunk/samples/src/main/java/gwtquery/samples/client/GwtQueryBenchModule.java'>Source code of this application</a> is available in the samples module of gwtquery. + <br/> + <br/> + - The GwtQuery team. + </div> +</body> +</html> diff --git a/samples/src/main/java/gwtquery/samples/public/GwtQueryDemo.html b/samples/src/main/java/gwtquery/samples/public/GwtQueryDemo.html index 211e3e0f..c9a78113 100644 --- a/samples/src/main/java/gwtquery/samples/public/GwtQueryDemo.html +++ b/samples/src/main/java/gwtquery/samples/public/GwtQueryDemo.html @@ -1,50 +1,50 @@ -<html>
-<head>
- <title>GQuery Demo</title>
- <script language="javascript"
- src="gwtquery.samples.GwtQueryDemo.nocache.js"></script>
- <style type="text/css">
- body {
- font-family: Helvetica;
- }
- .slide {
- border: 1px solid black;
- width: 800px;
- height: 600px;
- background-color: #505050;
- -webkit-user-select:none;
- -moz-user-select:none;
- }
- .slide, .slide * {
- color: #ffffff;
- font-size: 150%;
- }
- </style>
-</head>
-<body>
-<p>
- Short example of how to do progressively enhance DIV, UL, LI elements into
- powerpoint-like slides
-</p>
-
-<div class="slide transition-appear">
- Slide 1
- <ul class="transition-appear">
- <li>jQuery is</li>
- <li>such a</li>
- <li>Cool Library</li>
- </ul>
-</div>
-<div class="slide transition-appear">
- Slide 2
- <ul class="transition-appear">
- <li>Now GWT</li>
- <li>has a</li>
- <li>jQuery-like API Too!</li>
- <li>GwtQuery Rocks!</li>
- </ul>
-</div>
-
-</body>
-</html>
-
\ No newline at end of file +<html> +<head> + <title>GQuery Demo</title> + <script language="javascript" + src="gwtquery.samples.GwtQueryDemo.nocache.js"></script> + <style type="text/css"> + body { + font-family: Helvetica; + } + .slide { + border: 1px solid black; + width: 800px; + height: 600px; + background-color: #505050; + -webkit-user-select:none; + -moz-user-select:none; + } + .slide, .slide * { + color: #ffffff; + font-size: 150%; + } + </style> +</head> +<body> +<p> + Short example of how to do progressively enhance DIV, UL, LI elements into + powerpoint-like slides +</p> + +<div class="slide transition-appear"> + Slide 1 + <ul class="transition-appear"> + <li>jQuery is</li> + <li>such a</li> + <li>Cool Library</li> + </ul> +</div> +<div class="slide transition-appear"> + Slide 2 + <ul class="transition-appear"> + <li>Now GWT</li> + <li>has a</li> + <li>jQuery-like API Too!</li> + <li>GwtQuery Rocks!</li> + </ul> +</div> + +</body> +</html> + diff --git a/samples/src/main/java/gwtquery/samples/public/GwtQueryEffects.html b/samples/src/main/java/gwtquery/samples/public/GwtQueryEffects.html index e1bb5861..b0a2d8d4 100644 --- a/samples/src/main/java/gwtquery/samples/public/GwtQueryEffects.html +++ b/samples/src/main/java/gwtquery/samples/public/GwtQueryEffects.html @@ -1,65 +1,65 @@ -<!--<!doctype html>-->
-
-<html>
-<head>
- <title>GQuery Demo</title>
- <script language="javascript"
- src="gwtquery.samples.GwtQueryEffects.nocache.js"></script>
- <style type="text/css">
- body {
- font-family: Helvetica;
- }
- .box {
- border-style: groove;
- border-color: green;
- border-width: 5px;
- }
- .a {
- border-style: solid;
- border-color: black;
- border-width: 7px;
- background: pink;
- width: 50%;
- padding: 10px;
- display: none;
- height: 24px;
- }
- .outer {
- -webkit-user-select:none;
- -moz-user-select:none;
- }
- </style>
-</head>
-<body>
-<div class="outer">
- Click or DblClick on these notes
- <div>Foo <span class="note">bar</span> baz</div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
-</div>
-<br/>
-<button id="b0">Animate me</button><br/>
-<button id="b1">Toggle Animate effects</button>
-<button id="b2">Toggle Clip effects</button>
-<br/>
-<br/>
-<div class="a">
-<span id="i1" class="box">Span 1</span>
-<span id="i2" class="box">Span 2</span>
-<span id="i3" class="box">Span 3</span>
-</div>
-<br/>
-<div class="b">
-<div class="box">Div 1</div>
-<div class="box">Div 2</div>
-<div class="box">Div 3</div>
-<div class="box">Div 4</div>
-</div>
-</body>
-</html>
-
\ No newline at end of file +<!--<!doctype html>--> + +<html> +<head> + <title>GQuery Demo</title> + <script language="javascript" + src="gwtquery.samples.GwtQueryEffects.nocache.js"></script> + <style type="text/css"> + body { + font-family: Helvetica; + } + .box { + border-style: groove; + border-color: green; + border-width: 5px; + } + .a { + border-style: solid; + border-color: black; + border-width: 7px; + background: pink; + width: 50%; + padding: 10px; + display: none; + height: 24px; + } + .outer { + -webkit-user-select:none; + -moz-user-select:none; + } + </style> +</head> +<body> +<div class="outer"> + Click or DblClick on these notes + <div>Foo <span class="note">bar</span> baz</div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> +</div> +<br/> +<button id="b0">Animate me</button><br/> +<button id="b1">Toggle Animate effects</button> +<button id="b2">Toggle Clip effects</button> +<br/> +<br/> +<div class="a"> +<span id="i1" class="box">Span 1</span> +<span id="i2" class="box">Span 2</span> +<span id="i3" class="box">Span 3</span> +</div> +<br/> +<div class="b"> +<div class="box">Div 1</div> +<div class="box">Div 2</div> +<div class="box">Div 3</div> +<div class="box">Div 4</div> +</div> +</body> +</html> + diff --git a/samples/src/main/java/gwtquery/samples/public/GwtQueryEffectsMin.html b/samples/src/main/java/gwtquery/samples/public/GwtQueryEffectsMin.html index 021f6ef5..857e9fd3 100644 --- a/samples/src/main/java/gwtquery/samples/public/GwtQueryEffectsMin.html +++ b/samples/src/main/java/gwtquery/samples/public/GwtQueryEffectsMin.html @@ -1,65 +1,65 @@ -<!--<!doctype html>-->
-
-<html>
-<head>
- <title>GQuery Demo</title>
- <script language="javascript"
- src="gwtquery.samples.GwtQueryEffectsMin.nocache.js"></script>
- <style type="text/css">
- body {
- font-family: Helvetica;
- }
- .box {
- border-style: groove;
- border-color: green;
- border-width: 5px;
- }
- .a {
- border-style: solid;
- border-color: black;
- border-width: 7px;
- background: pink;
- width: 50%;
- padding: 10px;
- display: none;
- height: 24px;
- }
- .outer {
- -webkit-user-select:none;
- -moz-user-select:none;
- }
- </style>
-</head>
-<body>
-<div class="outer">
- Click or DblClick on these notes
- <div>Foo <span class="note">bar</span> baz</div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
-</div>
-<br/>
-<button id="b0">Animate me</button><br/>
-<button id="b1">Toggle Animate effects</button>
-<button id="b2">Toggle Clip effects</button>
-<br/>
-<br/>
-<div class="a">
-<span id="i1" class="box">Span 1</span>
-<span id="i2" class="box">Span 2</span>
-<span id="i3" class="box">Span 3</span>
-</div>
-<br/>
-<div class="b">
-<div class="box">Div 1</div>
-<div class="box">Div 2</div>
-<div class="box">Div 3</div>
-<div class="box">Div 4</div>
-</div>
-</body>
-</html>
-
\ No newline at end of file +<!--<!doctype html>--> + +<html> +<head> + <title>GQuery Demo</title> + <script language="javascript" + src="gwtquery.samples.GwtQueryEffectsMin.nocache.js"></script> + <style type="text/css"> + body { + font-family: Helvetica; + } + .box { + border-style: groove; + border-color: green; + border-width: 5px; + } + .a { + border-style: solid; + border-color: black; + border-width: 7px; + background: pink; + width: 50%; + padding: 10px; + display: none; + height: 24px; + } + .outer { + -webkit-user-select:none; + -moz-user-select:none; + } + </style> +</head> +<body> +<div class="outer"> + Click or DblClick on these notes + <div>Foo <span class="note">bar</span> baz</div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> +</div> +<br/> +<button id="b0">Animate me</button><br/> +<button id="b1">Toggle Animate effects</button> +<button id="b2">Toggle Clip effects</button> +<br/> +<br/> +<div class="a"> +<span id="i1" class="box">Span 1</span> +<span id="i2" class="box">Span 2</span> +<span id="i3" class="box">Span 3</span> +</div> +<br/> +<div class="b"> +<div class="box">Div 1</div> +<div class="box">Div 2</div> +<div class="box">Div 3</div> +<div class="box">Div 4</div> +</div> +</body> +</html> + diff --git a/samples/src/main/java/gwtquery/samples/public/GwtQueryImageZoom.html b/samples/src/main/java/gwtquery/samples/public/GwtQueryImageZoom.html index 9c01206d..659baad8 100644 --- a/samples/src/main/java/gwtquery/samples/public/GwtQueryImageZoom.html +++ b/samples/src/main/java/gwtquery/samples/public/GwtQueryImageZoom.html @@ -6,11 +6,11 @@ <style type="text/css"> body { font-family: verdana; - margin: 0; + margin: 0; padding: 0; } * { - margin: 0; + margin: 0; padding: 0; } img { @@ -43,7 +43,7 @@ background: #f0f0f0; position: absolute; left: 0; top: 0; - -ms-interpolation-mode: bicubic; + -ms-interpolation-mode: bicubic; } ul.thumb li img.hover { background:url(images/zoom/thumb_bg.png) no-repeat center center; @@ -71,38 +71,38 @@ <li><a href="#"><img src="images/zoom/thumb9.jpg" alt="" /></a></li> </ul> </div> -<!-- Original jQuery code +<!-- Original jQuery code <script language="javascript" src="http://code.jquery.com/jquery-latest.js"></script> -<script type="text/javascript"> +<script type="text/javascript"> $(document).ready(function(){ $("ul.thumb li").hover(function() { $(this).css({'z-index' : '10'}); $(this).find('img').addClass("hover").stop() .animate({ - marginTop: '-110px', - marginLeft: '-110px', - top: '50%', - left: '50%', - width: '174px', + marginTop: '-110px', + marginLeft: '-110px', + top: '50%', + left: '50%', + width: '174px', height: '174px', - padding: '20px' + padding: '20px' }, 200); - + } , function() { $(this).css({'z-index' : '0'}); $(this).find('img').removeClass("hover").stop() .animate({ - marginTop: '0', + marginTop: '0', marginLeft: '0', - top: '0', - left: '0', - width: '100px', - height: '100px', + top: '0', + left: '0', + width: '100px', + height: '100px', padding: '5px' }, 400); }); }); -</script> +</script> --> </body> </html> diff --git a/samples/src/main/java/gwtquery/samples/public/GwtQuerySample.html b/samples/src/main/java/gwtquery/samples/public/GwtQuerySample.html index 352a2c2c..58ff9b8d 100644 --- a/samples/src/main/java/gwtquery/samples/public/GwtQuerySample.html +++ b/samples/src/main/java/gwtquery/samples/public/GwtQuerySample.html @@ -1,49 +1,49 @@ -<html>
-<head>
- <title>GQuery Demo</title>
- <script language="javascript" src="gwtquery.samples.GwtQuerySample.nocache.js"></script>
-</head>
-<body>
- <div class="outer">
- <div>Foo <span class="note">bar</span> baz</div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>
- </div>
- <div class="outer">
- <div class="btn">Make me a button 1!</div>
- <a class="btn">Make me a button 2!</a>
- <span class="btn">Make me a button 3!</span>
- <button class="btn">Make me a button 4!</button>
- <div class="btn">Make me a button 5!</div>
- <div class="btn">Make me a button 6!</div>
- </div>
- <div class="outer">
- <div class="inputText">I will be a text input</div>
- <span class="inputText">I will be a text input</span>
- <input class="inputText" type="text" value="I will be a text input"></input>
- </div>
- <div class="outer">
- <div class="inputPsw">I will be an password input</div>
- <span class="inputPsw">I will be an password input</span>
- <input class="inputPsw" type="password" value="I will be an password input"></input>
- </div>
- <div class="outer">
- <div class="textArea">I will be a text area</div>
- <span class="textArea">I will be a text area</span>
- <textarea class="textArea">I will be a text area</textarea>
- </div>
- <div class="outer">
- <div class="label">I will be a label</div>
- <span class="label">I will be a label</span>
- <h1 class="label">I will be a label</h1>
- </div>
-</body>
-<script>
-</script>
-</html>
-
\ No newline at end of file +<html> +<head> + <title>GQuery Demo</title> + <script language="javascript" src="gwtquery.samples.GwtQuerySample.nocache.js"></script> +</head> +<body> + <div class="outer"> + <div>Foo <span class="note">bar</span> baz</div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + <div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div> + </div> + <div class="outer"> + <div class="btn">Make me a button 1!</div> + <a class="btn">Make me a button 2!</a> + <span class="btn">Make me a button 3!</span> + <button class="btn">Make me a button 4!</button> + <div class="btn">Make me a button 5!</div> + <div class="btn">Make me a button 6!</div> + </div> + <div class="outer"> + <div class="inputText">I will be a text input</div> + <span class="inputText">I will be a text input</span> + <input class="inputText" type="text" value="I will be a text input"></input> + </div> + <div class="outer"> + <div class="inputPsw">I will be an password input</div> + <span class="inputPsw">I will be an password input</span> + <input class="inputPsw" type="password" value="I will be an password input"></input> + </div> + <div class="outer"> + <div class="textArea">I will be a text area</div> + <span class="textArea">I will be a text area</span> + <textarea class="textArea">I will be a text area</textarea> + </div> + <div class="outer"> + <div class="label">I will be a label</div> + <span class="label">I will be a label</span> + <h1 class="label">I will be a label</h1> + </div> +</body> +<script> +</script> +</html> + diff --git a/samples/src/main/java/gwtquery/samples/public/SlideEffectsSample.html b/samples/src/main/java/gwtquery/samples/public/SlideEffectsSample.html index 3846ebfb..768c2727 100644 --- a/samples/src/main/java/gwtquery/samples/public/SlideEffectsSample.html +++ b/samples/src/main/java/gwtquery/samples/public/SlideEffectsSample.html @@ -1,100 +1,100 @@ -<!doctype html>
-<html>
-<head>
-<title>GQuery Effects Sample</title>
-<script language="javascript" src="SlideEffectsSample.nocache.js"></script>
-<style type="text/css">
- body {
- font-family: Helvetica;
- }
- .reset {
- float: left;
- }
- .foo {
- border: 1px solid black;
- font-size: 80%;
- }
-</style>
-</head>
-<body>
-<h1>Slide Effects Sample</h1>
-<p>This page lists and shows all slide effects available in GwtQuery</p>
-
-<table cellpadding="10" cellspacing="10">
- <tr>
- <td>
- <h2>SlideUp</h2>
- <div id="slideUp">
- <div class="foo" style="width: 200px;">Lorem ipsum dolor
- sit amet, consectetur adipiscing elit. Vestibulum ultricies
- nulla condimentum diam viverra vitae hendrerit lorem tempus. Sed
- vel enim nec libero ullamcorper hendrerit auctor a nibh. Nullam
- venenatis dictum sem, eget euismod dui laoreet non. Morbi in
- diam nibh.</div>
- <button>SlideUp !</button>
- <button class="reset">Reset</button>
- </div>
- </td>
- <td>
- <h2>SlideLeft</h2>
- <div id="slideLeft">
- <div class="foo" style="width: 200px; height: 200px;">Lorem
- ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum
- ultricies nulla condimentum diam viverra vitae hendrerit lorem
- tempus. Sed vel enim nec libero ullamcorper hendrerit auctor a
- nibh. Nullam venenatis dictum sem, eget euismod dui laoreet non.
- Morbi in diam nibh.</div>
- <button>SlideLeft</button>
- <button class="reset">Reset</button>
- </div>
- </td>
- </tr>
- <tr>
- <td>
- <h2>SlideDown</h2>
- <div id="slideDown">
- <div class="foo" style="width: 200px;">Lorem ipsum dolor
- sit amet, consectetur adipiscing elit. Vestibulum ultricies
- nulla condimentum diam viverra vitae hendrerit lorem tempus. Sed
- vel enim nec libero ullamcorper hendrerit auctor a nibh. Nullam
- venenatis dictum sem, eget euismod dui laoreet non. Morbi in
- diam nibh.</div>
- <button>SlideDown</button>
- <button class="reset">Reset</button>
- </div>
- </td>
- <td>
- <h2>SlideRight</h2>
- <div id="slideRight">
- <div class="foo" style="width: 200px; height: 200px;">Lorem
- ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum
- ultricies nulla condimentum diam viverra vitae hendrerit lorem
- tempus. Sed vel enim nec libero ullamcorper hendrerit auctor a
- nibh. Nullam venenatis dictum sem, eget euismod dui laoreet non.
- Morbi in diam nibh.</div>
- <button>SlideRight</button>
- <button class="reset">Reset</button>
- </div>
- </td>
- </tr>
- <tr>
- <td>
- <h2>SlideToogle</h2>
- <div id="slideToogle">
- <div class="foo" style="width: 200px;">Lorem ipsum dolor
- sit amet, consectetur adipiscing elit. Vestibulum ultricies
- nulla condimentum diam viverra vitae hendrerit lorem tempus. Sed
- vel enim nec libero ullamcorper hendrerit auctor a nibh. Nullam
- venenatis dictum sem, eget euismod dui laoreet non. Morbi in
- diam nibh.</div>
- <button>SlideToggle</button>
- </td>
- <td></td>
- </div>
- </tr>
-
-
-
-</table>
-</body>
-</html>
+<!doctype html> +<html> +<head> +<title>GQuery Effects Sample</title> +<script language="javascript" src="SlideEffectsSample.nocache.js"></script> +<style type="text/css"> + body { + font-family: Helvetica; + } + .reset { + float: left; + } + .foo { + border: 1px solid black; + font-size: 80%; + } +</style> +</head> +<body> +<h1>Slide Effects Sample</h1> +<p>This page lists and shows all slide effects available in GwtQuery</p> + +<table cellpadding="10" cellspacing="10"> + <tr> + <td> + <h2>SlideUp</h2> + <div id="slideUp"> + <div class="foo" style="width: 200px;">Lorem ipsum dolor + sit amet, consectetur adipiscing elit. Vestibulum ultricies + nulla condimentum diam viverra vitae hendrerit lorem tempus. Sed + vel enim nec libero ullamcorper hendrerit auctor a nibh. Nullam + venenatis dictum sem, eget euismod dui laoreet non. Morbi in + diam nibh.</div> + <button>SlideUp !</button> + <button class="reset">Reset</button> + </div> + </td> + <td> + <h2>SlideLeft</h2> + <div id="slideLeft"> + <div class="foo" style="width: 200px; height: 200px;">Lorem + ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum + ultricies nulla condimentum diam viverra vitae hendrerit lorem + tempus. Sed vel enim nec libero ullamcorper hendrerit auctor a + nibh. Nullam venenatis dictum sem, eget euismod dui laoreet non. + Morbi in diam nibh.</div> + <button>SlideLeft</button> + <button class="reset">Reset</button> + </div> + </td> + </tr> + <tr> + <td> + <h2>SlideDown</h2> + <div id="slideDown"> + <div class="foo" style="width: 200px;">Lorem ipsum dolor + sit amet, consectetur adipiscing elit. Vestibulum ultricies + nulla condimentum diam viverra vitae hendrerit lorem tempus. Sed + vel enim nec libero ullamcorper hendrerit auctor a nibh. Nullam + venenatis dictum sem, eget euismod dui laoreet non. Morbi in + diam nibh.</div> + <button>SlideDown</button> + <button class="reset">Reset</button> + </div> + </td> + <td> + <h2>SlideRight</h2> + <div id="slideRight"> + <div class="foo" style="width: 200px; height: 200px;">Lorem + ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum + ultricies nulla condimentum diam viverra vitae hendrerit lorem + tempus. Sed vel enim nec libero ullamcorper hendrerit auctor a + nibh. Nullam venenatis dictum sem, eget euismod dui laoreet non. + Morbi in diam nibh.</div> + <button>SlideRight</button> + <button class="reset">Reset</button> + </div> + </td> + </tr> + <tr> + <td> + <h2>SlideToogle</h2> + <div id="slideToogle"> + <div class="foo" style="width: 200px;">Lorem ipsum dolor + sit amet, consectetur adipiscing elit. Vestibulum ultricies + nulla condimentum diam viverra vitae hendrerit lorem tempus. Sed + vel enim nec libero ullamcorper hendrerit auctor a nibh. Nullam + venenatis dictum sem, eget euismod dui laoreet non. Morbi in + diam nibh.</div> + <button>SlideToggle</button> + </td> + <td></td> + </div> + </tr> + + + +</table> +</body> +</html> diff --git a/samples/src/main/java/gwtquery/samples/public/html/dojobench.html b/samples/src/main/java/gwtquery/samples/public/html/dojobench.html index 4f4e94db..6979a121 100644 --- a/samples/src/main/java/gwtquery/samples/public/html/dojobench.html +++ b/samples/src/main/java/gwtquery/samples/public/html/dojobench.html @@ -1,13 +1,13 @@ -<html>
-<head>
- <title>Dojo</title>
- <script type="text/javascript" src="../js/dojo.js"></script>
- <script type="text/javascript">
- window.parent.dojobenchmark = function(sel) {
- return dojo.query(sel).length;
- }
- </script>
-</head>
-<body>
-</body>
-</html>
+<html> +<head> + <title>Dojo</title> + <script type="text/javascript" src="../js/dojo.js"></script> + <script type="text/javascript"> + window.parent.dojobenchmark = function(sel) { + return dojo.query(sel).length; + } + </script> +</head> +<body> +</body> +</html> diff --git a/samples/src/main/java/gwtquery/samples/public/html/domassistantbench.html b/samples/src/main/java/gwtquery/samples/public/html/domassistantbench.html index fc1dab7a..4e65be0c 100644 --- a/samples/src/main/java/gwtquery/samples/public/html/domassistantbench.html +++ b/samples/src/main/java/gwtquery/samples/public/html/domassistantbench.html @@ -1,13 +1,13 @@ -<html>
-<head>
- <title>DomAssistant</title>
- <script type="text/javascript" src="../js/DOMAssistantComplete-2.7.js"></script>
- <script type="text/javascript">
- window.parent.domassistantbenchmark = function(sel) {
- return $(sel).length;
- }
- </script>
-</head>
-<body>
-</body>
-</html>
+<html> +<head> + <title>DomAssistant</title> + <script type="text/javascript" src="../js/DOMAssistantComplete-2.7.js"></script> + <script type="text/javascript"> + window.parent.domassistantbenchmark = function(sel) { + return $(sel).length; + } + </script> +</head> +<body> +</body> +</html> diff --git a/samples/src/main/java/gwtquery/samples/public/html/gwtbench.html b/samples/src/main/java/gwtquery/samples/public/html/gwtbench.html index 913ae711..dd32d1bd 100644 --- a/samples/src/main/java/gwtquery/samples/public/html/gwtbench.html +++ b/samples/src/main/java/gwtquery/samples/public/html/gwtbench.html @@ -4,7 +4,7 @@ <script type="text/javascript"> // Notify the application that the content can be written window.parent.iframebench_ready_callback(); - </script> + </script> </head> <body> </body> diff --git a/samples/src/main/java/gwtquery/samples/public/html/iframebench.html b/samples/src/main/java/gwtquery/samples/public/html/iframebench.html index 78962fe2..79e717dd 100644 --- a/samples/src/main/java/gwtquery/samples/public/html/iframebench.html +++ b/samples/src/main/java/gwtquery/samples/public/html/iframebench.html @@ -1,42 +1,42 @@ -<html>
- <head>
- <script type="text/javascript" src="../js/dojo.js"></script>
- <script type="text/javascript">
- window.parent.dojobenchmark = function(sel) {
- return dojo.query(sel).length;
- }
- </script>
- <script type="text/javascript" src="../js/sizzle.js"></script>
- <script type="text/javascript">
- window.parent.sizzlebenchmark = function(sel) {
- return Sizzle(sel).length;
- }
- </script>
- <script type="text/javascript" src="../js/DOMAssistantComplete-2.7.js"></script>
- <script type="text/javascript">
- DOMAssistant.harmonize();
- window.parent.domassistantbenchmark = function(sel) {
- return DOMAssistant.$(sel).length;
- }
- </script>
- <script language="javascript" src="../js/jquery-1.6.2.js"></script>
- <script type="text/javascript">
- jQuery.noConflict()
- window.parent.jquerybenchmark = function(sel) {
- return jQuery(sel).length;
- }
- </script>
- <script type="text/javascript" src="../js/prototype-1.6.0.3.js"></script>
- <script type="text/javascript">
- window.parent.prototypebenchmark = function(sel) {
- return $$(sel).length;
- }
- </script>
- <script type="text/javascript">
- // Notify the application that the content can be written
- window.parent.iframebench_ready_callback();
- </script>
- </head>
- <body>
- </body>
-</html>
+<html> + <head> + <script type="text/javascript" src="../js/dojo.js"></script> + <script type="text/javascript"> + window.parent.dojobenchmark = function(sel) { + return dojo.query(sel).length; + } + </script> + <script type="text/javascript" src="../js/sizzle.js"></script> + <script type="text/javascript"> + window.parent.sizzlebenchmark = function(sel) { + return Sizzle(sel).length; + } + </script> + <script type="text/javascript" src="../js/DOMAssistantComplete-2.7.js"></script> + <script type="text/javascript"> + DOMAssistant.harmonize(); + window.parent.domassistantbenchmark = function(sel) { + return DOMAssistant.$(sel).length; + } + </script> + <script language="javascript" src="../js/jquery-1.6.2.js"></script> + <script type="text/javascript"> + jQuery.noConflict() + window.parent.jquerybenchmark = function(sel) { + return jQuery(sel).length; + } + </script> + <script type="text/javascript" src="../js/prototype-1.6.0.3.js"></script> + <script type="text/javascript"> + window.parent.prototypebenchmark = function(sel) { + return $$(sel).length; + } + </script> + <script type="text/javascript"> + // Notify the application that the content can be written + window.parent.iframebench_ready_callback(); + </script> + </head> + <body> + </body> +</html> diff --git a/samples/src/main/java/gwtquery/samples/public/html/jquerybench.html b/samples/src/main/java/gwtquery/samples/public/html/jquerybench.html index 45238eaa..9ad083f2 100644 --- a/samples/src/main/java/gwtquery/samples/public/html/jquerybench.html +++ b/samples/src/main/java/gwtquery/samples/public/html/jquerybench.html @@ -1,13 +1,13 @@ -<html>
-<head>
- <title>JQuery</title>
- <script language="javascript" src="../js/jquery-1.6.2.js"></script>
- <script type="text/javascript">
- window.parent.jquerybenchmark = function(sel) {
- return $(sel).length;
- }
- </script>
-</head>
-<body>
-</body>
-</html>
+<html> +<head> + <title>JQuery</title> + <script language="javascript" src="../js/jquery-1.6.2.js"></script> + <script type="text/javascript"> + window.parent.jquerybenchmark = function(sel) { + return $(sel).length; + } + </script> +</head> +<body> +</body> +</html> diff --git a/samples/src/main/java/gwtquery/samples/public/html/prototypebench.html b/samples/src/main/java/gwtquery/samples/public/html/prototypebench.html index 448e031b..78855778 100644 --- a/samples/src/main/java/gwtquery/samples/public/html/prototypebench.html +++ b/samples/src/main/java/gwtquery/samples/public/html/prototypebench.html @@ -1,13 +1,13 @@ -<html>
-<head>
- <title>Prototype</title>
- <script type="text/javascript" src="../js/prototype-1.6.0.3.js"></script>
- <script type="text/javascript">
- window.parent.prototypebenchmark = function(sel) {
- return $$(sel).length;
- }
- </script>
-</head>
-<body>
-</body>
-</html>
+<html> +<head> + <title>Prototype</title> + <script type="text/javascript" src="../js/prototype-1.6.0.3.js"></script> + <script type="text/javascript"> + window.parent.prototypebenchmark = function(sel) { + return $$(sel).length; + } + </script> +</head> +<body> +</body> +</html> diff --git a/samples/src/main/java/gwtquery/samples/public/html/sizzlebench.html b/samples/src/main/java/gwtquery/samples/public/html/sizzlebench.html index acc7c326..6b2be22e 100644 --- a/samples/src/main/java/gwtquery/samples/public/html/sizzlebench.html +++ b/samples/src/main/java/gwtquery/samples/public/html/sizzlebench.html @@ -1,13 +1,13 @@ -<html>
-<head>
- <title>Sizzle</title>
- <script type="text/javascript" src="../js/sizzle.js"></script>
- <script type="text/javascript">
- window.parent.sizzlebenchmark = function(sel) {
- return Sizzle(sel).length;
- }
- </script>
-</head>
-<body>
-</body>
-</html>
+<html> +<head> + <title>Sizzle</title> + <script type="text/javascript" src="../js/sizzle.js"></script> + <script type="text/javascript"> + window.parent.sizzlebenchmark = function(sel) { + return Sizzle(sel).length; + } + </script> +</head> +<body> +</body> +</html> |