<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<configuration>
- <style>PRETTY</style>
+ <!-- <style>PRETTY</style> -->
<gwtVersion>${gwtversion}</gwtVersion>
<modules>
<module>com.google.gwt.query.DevTestRunner</module>
import static com.google.gwt.query.client.GQuery.$;\r
\r
import com.google.gwt.core.client.EntryPoint;\r
+import com.google.gwt.core.client.GWT;\r
+import com.google.gwt.core.client.JsArray;\r
import com.google.gwt.dom.client.Document;\r
import com.google.gwt.dom.client.Element;\r
-import com.google.gwt.user.client.Event;\r
+import com.google.gwt.dom.client.Node;\r
+import com.google.gwt.dom.client.NodeList;\r
+import com.google.gwt.query.client.impl.SelectorEngineCssToXPath;\r
+import com.google.gwt.query.client.impl.SelectorEngineImpl;\r
+import com.google.gwt.query.client.impl.SelectorEngineJS;\r
+import com.google.gwt.query.client.impl.SelectorEngineNative;\r
+import com.google.gwt.query.client.impl.SelectorEngineSizzle;\r
+import com.google.gwt.query.client.impl.SelectorEngineXPath;\r
+import com.google.gwt.user.client.Timer;\r
+import com.google.gwt.user.client.Window;\r
+import com.google.gwt.user.client.ui.HTML;\r
+import com.google.gwt.user.client.ui.RootPanel;\r
\r
/**\r
* This module is thought to emulate a test environment similar to\r
try {\r
gwtSetUp();\r
\r
- testIssue23();\r
-\r
- $(e).after("<div>OK</div>");\r
+ testCompiledSelectors();\r
+ testIssue12();\r
+ testSelectElementsInsideContext();\r
+ testSelectorEngineDomAssistant();\r
+ testSelectorEngineSizzle();\r
+ testSelectorEngineXpath();\r
+ testSelectorEngineCssToXpath();\r
+ testSelectorEngineNative();\r
+ testSelectorsGeneratorNative();\r
+ testSelectorsWithContext();\r
+ testUnique();\r
+ \r
+ testFade();\r
+ \r
+// $(e).html("").after("<div>OK</div>");\r
} catch (Exception ex) {\r
ex.printStackTrace();\r
- $(e).after("<div>ERROR: " + ex.getMessage() + "</div>");\r
+ $(e).html("").after("<div>ERROR: " + ex.getMessage() + "</div>");\r
}\r
}\r
+\r
+ public void testFade() {\r
+ $(e)\r
+ .html(\r
+ "<p id='id1' style='display: inline'>Content 1</p><p id='id2'>Content 2</p><p id='id3'>Content 3</p>");\r
+\r
+ final GQuery sectA = $("#id1");\r
+ final GQuery sectB = $("#id2");\r
+ \r
+ // fadeIn() & fadeOut() are tested with delayed assertions\r
+ sectA.hide();\r
+ sectA.fadeIn(2000);\r
+ sectB.fadeOut(2000);\r
+\r
+ // Configure the max duration for this test\r
+ // If the test exceeds the timeout without calling finishTest() it will fail\r
+ delayTestFinish(2500);\r
+\r
+ // Delayed assertions at different intervals\r
+ Timer timerShortTime = new Timer() {\r
+ public void run() {\r
+ double o = Double.valueOf(sectA.css("opacity"));\r
+ assertTrue(\r
+ "'sectA' opacity must be in the interval 0-0.5 but is: " + o, o > 0\r
+ && o < 0.5);\r
+ o = Double.valueOf(sectB.css("opacity"));\r
+ assertTrue(\r
+ "'sectB' opacity must be in the interval 0.5-1 but is: " + o,\r
+ o > 0.5 && o < 1);\r
+ }\r
+ };\r
+ Timer timerMidTime = new Timer() {\r
+ public void run() {\r
+ assertEquals("inline", sectA.css("display"));\r
+ assertEquals("", sectB.css("display"));\r
+ double o = Double.valueOf(sectA.css("opacity"));\r
+ assertTrue(\r
+ "'sectA' opacity must be in the interval 0.5-1 but is: " + o,\r
+ o > 0.5 && o < 1);\r
+ o = Double.valueOf(sectB.css("opacity"));\r
+ assertTrue(\r
+ "'sectB' opacity must be in the interval 0-0.5 but is: " + o, o > 0\r
+ && o < 0.5);\r
+ }\r
+ };\r
+ Timer timerLongTime = new Timer() {\r
+ public void run() {\r
+ assertEquals("inline", sectA.css("display"));\r
+ assertEquals("none", sectB.css("display"));\r
+ // Last delayed assertion has to stop the test to avoid a timeout\r
+ // failure\r
+ finishTest();\r
+ }\r
+ };\r
+\r
+ // schedule the delayed assertions\r
+ timerShortTime.schedule(200);\r
+ timerMidTime.schedule(1200);\r
+ timerLongTime.schedule(2200); \r
+ } \r
\r
- int done = 0;\r
+ protected interface AllSelectors extends Selectors {\r
+ // @Selector("h1[id]:contains(Selectors)")\r
+ // NodeList<Element> h1IdContainsSelectors();\r
+ // @Selector("*:first")\r
+ // NodeList<Element> allFirst();\r
+ // @Selector("div[class!=madeup]")\r
+ // NodeList<Element> divWithClassNotContainsMadeup();\r
+ // @Selector("div, p a")\r
+ // NodeList<Element> divCommaPA();\r
+ // @Selector("p:contains(selectors)")\r
+ // NodeList<Element> pContainsSelectors();\r
+ @Selector("a[href][lang][class]")\r
+ NodeList<Element> aHrefLangClass();\r
+ @Selector("*:checked")\r
+ NodeList<Element> allChecked();\r
+ @Selector("body")\r
+ NodeList<Element> body();\r
+ @Selector("body div")\r
+ NodeList<Element> bodyDiv();\r
+ @Selector("div .example")\r
+ NodeList<Element> divExample();\r
+ @Selector("div > div")\r
+ NodeList<Element> divGtP();\r
+ @Selector("div:not(.example)")\r
+ NodeList<Element> divNotExample();\r
+ @Selector("div p")\r
+ NodeList<Element> divP();\r
+ @Selector("div p a")\r
+ NodeList<Element> divPA();\r
+ @Selector("div + p")\r
+ NodeList<Element> divPlusP();\r
+ @Selector("div[class^=exa][class$=mple]")\r
+ NodeList<Element> divPrefixExaSuffixMple();\r
+ @Selector("div #title")\r
+ NodeList<Element> divSpaceTitle();\r
+ @Selector("div ~ p")\r
+ NodeList<Element> divTildeP();\r
+ @Selector("div[class]")\r
+ NodeList<Element> divWithClass();\r
+ @Selector("div[class~=dialog]")\r
+ NodeList<Element> divWithClassContainsDialog();\r
+ @Selector("div[class*=e]")\r
+ NodeList<Element> divWithClassContainsE();\r
+ @Selector("div[class=example]")\r
+ NodeList<Element> divWithClassExample();\r
+ @Selector("div[class~=dialog]")\r
+ NodeList<Element> divWithClassListContainsDialog();\r
+ @Selector("div[class^=exa]")\r
+ NodeList<Element> divWithClassPrefixExa();\r
+ @Selector("div[class$=mple]")\r
+ NodeList<Element> divWithClassSuffixMple();\r
+ @Selector("p:first-child")\r
+ NodeList<Element> firstChild();\r
+ @Selector("h1#title")\r
+ NodeList<Element> h1Title();\r
+ @Selector("h1#title + em > span")\r
+ NodeList<Element> h1TitlePlusEmGtSpan();\r
+ @Selector("p:last-child")\r
+ NodeList<Element> lastChild();\r
+ @Selector(".note")\r
+ NodeList<Element> note();\r
+ @Selector("p:nth-child(n)")\r
+ NodeList<Element> nthChild();\r
+ @Selector("p:nth-child(2n)")\r
+ NodeList<Element> nThChild2n();\r
+ @Selector("p:nth-child(2n+1)")\r
+ NodeList<Element> nThChild2nPlus1();\r
+ @Selector("p:nth-child(even)")\r
+ NodeList<Element> nThChildEven();\r
+ @Selector("p:nth-child(odd)")\r
+ NodeList<Element> nThChildOdd();\r
+ @Selector("p:only-child")\r
+ NodeList<Element> onlyChild();\r
+ @Selector("#title")\r
+ NodeList<Element> title();\r
+ @Selector("#title,h1#title")\r
+ NodeList<Element> titleAndh1Title();\r
+ @Selector("ul .tocline2")\r
+ NodeList<Element> ulTocline2();\r
+ @Selector("ul.toc li.tocline2")\r
+ NodeList<Element> ulTocLiTocLine2();\r
+ }\r
+\r
+ protected interface TestSelectors extends Selectors {\r
+ @Selector("*:checked")\r
+ GQuery allChecked();\r
+ @Selector("*:checked")\r
+ GQuery allChecked(Node n);\r
+ @Selector(".branchA")\r
+ GQuery branchA();\r
+ @Selector(".branchA")\r
+ GQuery branchA(Node n);\r
+ @Selector(".branchB")\r
+ GQuery branchB();\r
+ @Selector(".branchB")\r
+ GQuery branchB(Node n);\r
+ @Selector(".target")\r
+ GQuery target();\r
+ @Selector(".target")\r
+ GQuery target(Node n);\r
+ }\r
+\r
+ static Element e = null;\r
+ static HTML testPanel = null;\r
+\r
+ public String getModuleName() {\r
+ return "com.google.gwt.query.Query";\r
+ }\r
+\r
+ public void gwtSetUp() {\r
+ if (e == null) {\r
+ testPanel = new HTML();\r
+ RootPanel.get().add(testPanel);\r
+ e = testPanel.getElement();\r
+ e.setId("select-tst");\r
+ } else {\r
+ e.setInnerHTML("");\r
+ }\r
+ }\r
+\r
+ public void testCompiledSelectors() {\r
+ final AllSelectors sel = GWT.create(AllSelectors.class);\r
+ $(e).html(getTestContent());\r
+\r
+ // TODO: fix these selectors\r
+ // sel.h1IdContainsSelectors().getLength()\r
+ // sel.allFirst().getLength()\r
+ // sel.divWithClassNotContainsMadeup().getLength()\r
+ // sel.divCommaPA().getLength()\r
+ // sel.pContainsSelectors().getLength()\r
+ // assertArrayContains(sel.title().getLength(), 1);\r
+\r
+ assertEquals(1, sel.body().getLength());\r
+ assertArrayContains(sel.bodyDiv().getLength(), 53, 55);\r
+ sel.setRoot(e);\r
+ assertArrayContains(sel.aHrefLangClass().getLength(), 0, 1);\r
+ assertArrayContains(sel.allChecked().getLength(), 1);\r
+ assertArrayContains(sel.divExample().getLength(), 43);\r
+ assertArrayContains(sel.divGtP().getLength(), 51, 52);\r
+ assertArrayContains(sel.divNotExample().getLength(), 9, 10);\r
+ assertArrayContains(sel.divP().getLength(), 324);\r
+ assertArrayContains(sel.divPA().getLength(), 84);\r
+ assertArrayContains(sel.divPlusP().getLength(), 22);\r
+ assertArrayContains(sel.divPrefixExaSuffixMple().getLength(), 43);\r
+ assertArrayContains(sel.divSpaceTitle().getLength(), 1);\r
+ assertArrayContains(sel.divTildeP().getLength(), 183);\r
+ assertArrayContains(sel.divWithClass().getLength(), 51, 52);\r
+ assertArrayContains(sel.divWithClassContainsDialog().getLength(), 1);\r
+ assertArrayContains(sel.divWithClassContainsE().getLength(), 50);\r
+ assertArrayContains(sel.divWithClassExample().getLength(), 43);\r
+ assertArrayContains(sel.divWithClassListContainsDialog().getLength(), 1);\r
+ assertArrayContains(sel.divWithClassPrefixExa().getLength(), 43);\r
+ assertArrayContains(sel.divWithClassSuffixMple().getLength(), 43);\r
+ assertArrayContains(sel.firstChild().getLength(), 54);\r
+ assertArrayContains(sel.h1Title().getLength(), 1);\r
+ assertArrayContains(sel.h1TitlePlusEmGtSpan().getLength(), 1);\r
+ assertArrayContains(sel.lastChild().getLength(), 19);\r
+ assertArrayContains(sel.note().getLength(), 14);\r
+ assertArrayContains(sel.nthChild().getLength(), 324);\r
+ assertArrayContains(sel.nThChild2n().getLength(), 159);\r
+ assertArrayContains(sel.nThChild2nPlus1().getLength(), 165);\r
+ assertArrayContains(sel.nThChildEven().getLength(), 159);\r
+ assertArrayContains(sel.nThChildOdd().getLength(), 165);\r
+ assertArrayContains(sel.onlyChild().getLength(), 3);\r
+ assertArrayContains(sel.titleAndh1Title().getLength(), 0, 1);\r
+ assertArrayContains(sel.ulTocline2().getLength(), 12);\r
+ assertArrayContains(sel.ulTocLiTocLine2().getLength(), 12);\r
+ }\r
+\r
+ public void testIssue12() {\r
+ $(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>");\r
+ executeSelectInAllImplementations(":checked", e, 1);\r
+ executeSelectInAllImplementations(":disabled", e, 1);\r
+ executeSelectInAllImplementations("input:enabled", e, 1);\r
+ executeSelectInAllImplementations("[myCustomAttr]", e, 2);\r
+ executeSelectInAllImplementations("*[myCustomAttr]", e, 2);\r
+ executeSelectInAllImplementations("input[name=wantedName]", e, 1);\r
+ executeSelectInAllImplementations("input[name='wantedName']", e, 1);\r
+ executeSelectInAllImplementations("input[name=\"wantedName\"]", e, 1);\r
+ }\r
\r
- public void testIssue23() {\r
- $(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>");\r
- $("button").click(new Function() {\r
- public boolean f(Event e) {\r
- $("table > tbody > tr > td > input:checked").each(new Function() {\r
- public void f(Element e) {\r
- done ++;\r
- }\r
- });\r
- return true;\r
- }\r
- });\r
- done = 0;\r
- $("button").click();\r
- assertEquals(1,done);\r
+ public void testSelectElementsInsideContext() {\r
+ $(e).html("<spam><p>s</p></spam>");\r
+ GQuery q = $("spam", e);\r
+ // TODO: in XPath engine it returns 2 when it should return 1\r
+ executeSelectInAllImplementations("*", q.get(0), 1, 2);\r
+ }\r
+\r
+ public void testSelectorEngineDomAssistant() {\r
+ // This test runs very slow in chrome\r
+ SelectorEngineImpl selEng = new SelectorEngineJS();\r
+ executeSelectorEngineTests(selEng);\r
+ }\r
+\r
+ public void testSelectorEngineSizzle() {\r
+ SelectorEngineImpl selEng = new SelectorEngineSizzle();\r
+ executeSelectorEngineTests(selEng);\r
+ }\r
+\r
+ public void testSelectorEngineNative() {\r
+ SelectorEngineImpl selEng = new SelectorEngineNative();\r
+ if (hasNativeSelector()) {\r
+ Window.alert("Testing native selector");\r
+ executeSelectorEngineTests(selEng);\r
+ }\r
+ }\r
+\r
+ public void testSelectorEngineXpath() {\r
+ SelectorEngineImpl selEng = new SelectorEngineXPath();\r
+ executeSelectorEngineTests(selEng);\r
+ }\r
+\r
+ public void testSelectorEngineCssToXpath() {\r
+ SelectorEngineImpl selEng = new SelectorEngineCssToXPath();\r
+ executeSelectorEngineTests(selEng);\r
+ }\r
+\r
+ public void testSelectorsGeneratorNative() {\r
+ $(e).html(\r
+ "<input type='radio' name='n' value='v1'>1</input>"\r
+ + "<input type='radio' name='n' value='v2' checked='checked'>2</input>");\r
+\r
+ TestSelectors selectors = GWT.create(TestSelectors.class);\r
+ assertEquals(1, selectors.allChecked().size());\r
}\r
\r
- public void testDomManip() {\r
- String content = "<span class='branchA'><span class='target'>branchA target</span></span>"\r
- + "<span class='branchB'><span class='target'>branchB target</span></span>";\r
+ public void testSelectorsWithContext() {\r
+ $(e).append(\r
+ "<div class='branchA'><div class='target'>branchA target</div></div>"\r
+ + "<div class='branchB'><div class='target'>branchB target</div></div>");\r
+\r
+ TestSelectors selectors = GWT.create(TestSelectors.class);\r
+\r
+ assertEquals(2, selectors.target().length());\r
+ Element branchA = selectors.branchA().get(0);\r
+ Element branchB = selectors.branchB().get(0);\r
+ assertNotNull(selectors.branchA().get(0));\r
+ assertNotNull(selectors.branchB().get(0));\r
+\r
+ assertEquals(2, selectors.target(RootPanel.getBodyElement()).length());\r
+ branchA = selectors.branchA(RootPanel.getBodyElement()).get(0);\r
+ branchB = selectors.branchB(RootPanel.getBodyElement()).get(0);\r
+ assertNotNull(branchA);\r
+ assertNotNull(branchB);\r
+ assertEquals("branchA target", selectors.target(branchA).text());\r
+ assertEquals("branchB target", selectors.target(branchB).text());\r
+\r
+ selectors.setRoot(branchA);\r
+ assertEquals(1, selectors.target().length());\r
+ assertEquals("branchA target", selectors.target().text());\r
+\r
+ selectors.setRoot(branchB);\r
+ assertEquals(1, selectors.target().length());\r
+ assertEquals("branchB target", selectors.target().text());\r
+ }\r
+ \r
+ public void testUnique() {\r
+ SelectorEngineImpl selSizz = new SelectorEngineSizzle();\r
+ $(e).html(getTestContent());\r
\r
- $(e).html("");\r
- $(e).append(content);\r
- assertEquals(4, $("span", e).size());\r
- assertEquals(2, $("span.target", e).size());\r
- assertHtmlEquals(content, $(e).html());\r
+ JsArray<Element> a;\r
+ a = selSizz.select("p", e).cast();\r
+ int n = a.length();\r
+ assertTrue(n > 300);\r
+ for (int i=0; i<n; i++) {\r
+ a.push(a.get(i));\r
+ }\r
+ assertEquals(n * 2 , a.length());\r
+ a = SelectorEngineImpl.unique(a);\r
+ assertEquals(n, a.length());\r
+ }\r
+ \r
+ private void executeSelectInAllImplementations(String selector, Element elem, Object... array) {\r
+ SelectorEngineImpl selSizz = new SelectorEngineSizzle();\r
+ SelectorEngineImpl selJS = new SelectorEngineJS();\r
+ SelectorEngineImpl selXpath = new SelectorEngineXPath();\r
+ SelectorEngineImpl selC2X = new SelectorEngineCssToXPath();\r
+ SelectorEngineImpl selNative = new SelectorEngineNative();\r
+ assertArrayContains(selector, selSizz.select(selector, elem).getLength(), array);\r
+ assertArrayContains(selector, selJS.select(selector, elem).getLength(), array);\r
+ if (hasNativeSelector()) {\r
+ assertArrayContains(selector, selNative.select(selector, elem).getLength(), array);\r
+ } \r
+// assertArrayContains(selector, selXpath.select(selector, elem).getLength(), array);\r
+// assertArrayContains(selector, selC2X.select(selector, elem).getLength(), array);\r
+ \r
+ }\r
+ \r
+ private static native boolean hasNativeSelector() /*-{\r
+// alert(document.querySelectorAll + " " + document.querySelector);\r
+ return !!(document.querySelectorAll && /native/.test(String(document.querySelectorAll)));\r
+ }-*/;\r
+\r
+ private void executeSelectorEngineTests(SelectorEngineImpl selEng) {\r
+ $(e).html(getTestContent());\r
+\r
+ assertArrayContains(selEng.select("body", Document.get()).getLength(), 1);\r
+ assertArrayContains(selEng.select("body div", Document.get()).getLength(), 53, 55);\r
+\r
+ assertArrayContains(selEng.select("h1[id]:contains(Selectors)", e).getLength(), 1);\r
+ assertArrayContains(selEng.select("div[class!=madeup]", e).getLength(), 52, 53);\r
+ assertArrayContains(selEng.select("div, p a", e).getLength(), 136, 137, 138);\r
+ assertArrayContains(selEng.select("p:contains(selectors)", e).getLength(), 54, 55);\r
+ assertArrayContains(selEng.select("a[href][lang][class]", e).getLength(), 1);\r
+ assertArrayContains(selEng.select("*:checked", e).getLength(), 1);\r
+ assertArrayContains(selEng.select("div .example", e).getLength(), 43);\r
+ assertArrayContains(selEng.select("div > div", e).getLength(), 51, 52);\r
+ assertArrayContains(selEng.select("div:not(.example)", e).getLength(), 9, 10);\r
+ assertArrayContains(selEng.select("div p", e).getLength(), 324);\r
+ assertArrayContains(selEng.select("div p a", e).getLength(), 85, 84);\r
+ assertArrayContains(selEng.select("div + p", e).getLength(), 22);\r
+ assertArrayContains(selEng.select("div[class^=exa][class$=mple]", e).getLength(), 43);\r
+ assertArrayContains(selEng.select("div #title", e).getLength(), 1);\r
+ assertArrayContains(selEng.select("div ~ p", e).getLength(), 183);\r
+ assertArrayContains(selEng.select("div[class]", e).getLength(), 51, 52);\r
+ assertArrayContains(selEng.select("div[class~=dialog]", e).getLength(), 1);\r
+ assertArrayContains(selEng.select("div[class*=e]", e).getLength(), 50);\r
+ assertArrayContains(selEng.select("div[class=example]", e).getLength(), 43);\r
+ assertArrayContains(selEng.select("div[class~=dialog]", e).getLength(), 1);\r
+ assertArrayContains(selEng.select("div[class^=exa]", e).getLength(), 43);\r
+ assertArrayContains(selEng.select("div[class$=mple]", e).getLength(), 43);\r
+ assertArrayContains(selEng.select("p:first-child", e).getLength(), 54);\r
+ assertArrayContains(selEng.select("h1#title", e).getLength(), 1);\r
+ assertArrayContains(selEng.select("h1#title + em > span", e).getLength(), 1);\r
+ assertArrayContains(selEng.select("p:last-child", e).getLength(), 19, 22);\r
+ assertArrayContains(selEng.select(".note", e).getLength(), 14);\r
+ assertArrayContains(selEng.select("p:nth-child(n)", e).getLength(), 324);\r
+ assertArrayContains(selEng.select("p:nth-child(2n)", e).getLength(), 159);\r
+ assertArrayContains(selEng.select("p:nth-child(2n+1)", e).getLength(), 165);\r
+ assertArrayContains(selEng.select("p:nth-child(even)", e).getLength(), 159);\r
+ assertArrayContains(selEng.select("p:nth-child(odd)", e).getLength(), 165);\r
+ assertArrayContains(selEng.select("p:only-child", e).getLength(), 3);\r
+ assertArrayContains(selEng.select("#title", e).getLength(), 1);\r
+ assertArrayContains(selEng.select("#title, h1#title", e).getLength(), 1);\r
+ assertArrayContains(selEng.select("ul.toc li.tocline2", e).getLength(), 12); \r
+// assertArrayContains(selEng.select("h1[id]:contains(Selectors)", e).getLength(), 1);\r
+ }\r
+\r
+ // This method is used to initialize a huge html String, because\r
+ // java 1.5 has a limitation in the size of static strings.\r
+ private String getTestContent() {\r
+ String ret = "";\r
+ ret += "<html><head> </head><body><div>";\r
+ ret += " <div class='head dialog'>";\r
+ ret += " <p><a href='http://www.w3.org/'><img alt='W3C' src='' height='48' width='72'></a></p>";\r
+ ret += " <h1 id='title'>Selectors</h1>";\r
+ ret += " <em><span>.</span></em>";\r
+ ret += " <h2>W3C Working Draft 15 December 2005</h2>";\r
+ ret += " <dl>";\r
+ ret += " <dt>This version:</dt>";\r
+ ret += " <dd><a href='http://www.w3.org/TR/2005/WD-css3-selectors-20051215'>";\r
+ ret += " http://www.w3.org/TR/2005/WD-css3-selectors-20051215</a></dd>";\r
+ ret += " <dt>Latest version:";\r
+ ret += " </dt><dd><a href='http://www.w3.org/TR/css3-selectors'>";\r
+ ret += " http://www.w3.org/TR/css3-selectors</a>";\r
+ ret += " </dd><dt>Previous version:";\r
+ ret += " </dt><dd><a href='http://www.w3.org/TR/2001/CR-css3-selectors-20011113'>";\r
+ ret += " http://www.w3.org/TR/2001/CR-css3-selectors-20011113</a>";\r
+ ret += " </dd><dt><a name='editors-list'></a>Editors:";\r
+ ret += " </dt><dd class='vcard'><span class='fn'>Daniel Glazman</span> (Invited";\r
+ ret += " </dd>";\r
+ ret += " <dd class='vcard'><a class='url fn' href='http://www.tantek.com/' lang='tr'>Tantek Çelik</a>";\r
+ ret += " </dd><dd class='vcard'><a href='mailto:ian@hixie.ch' class='url fn'>Ian";\r
+ ret += " Hickson</a> (<span class='company'><a href='http://www.google.com/'>Google</a></span>)";\r
+ ret += " </dd><dd class='vcard'><span class='fn'>Peter Linss</span> (former";\r
+ ret += " editor, <span class='company'><a href='http://www.netscape.com/'>Netscape/AOL</a></span>)";\r
+ 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>)";\r
+ ret += " </dd></dl>";\r
+ ret += " <p class='copyright'><a href='http://www.w3.org/Consortium/Legal/ipr-notice#Copyright'>";\r
+ ret += " Copyright</a> © 2005 <a href='http://www.w3.org/'><abbr title='World Wide Web Consortium'>W3C</abbr></a><sup>®</sup>";\r
+ ret += " (<a href='http://www.csail.mit.edu/'><abbr title='Massachusetts";\r
+ ret += " Institute of Technology'>MIT</abbr></a>, <a href='http://www.ercim.org/'><acronym title='European Research";\r
+ ret += " Consortium for Informatics and Mathematics'>ERCIM</acronym></a>, <a href='http://www.keio.ac.jp/'>Keio</a>), All Rights Reserved.";\r
+ ret += " <a href='http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer'>liability</a>,";\r
+ ret += " <a href='http://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks'>trademark</a>,";\r
+ ret += " <a href='http://www.w3.org/Consortium/Legal/copyright-documents'>document";\r
+ ret += " use</a> rules apply.";\r
+ ret += " </p><hr title='Separator for header'>";\r
+ ret += " </div>";\r
+ ret += " <h2><a name='abstract'></a>Abstract</h2>";\r
+ ret += " <p><em>Selectors</em> are patterns that match against elements in a";\r
+ ret += " tree. Selectors have been optimized for use with HTML and XML, and";\r
+ ret += " are designed to be usable in performance-critical code.</p>";\r
+ ret += " <p><acronym title='Cascading Style Sheets'>CSS</acronym> (Cascading";\r
+ 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";\r
+ ret += " screen, on paper, in speech, etc. CSS uses Selectors for binding";\r
+ ret += " describes extensions to the selectors defined in CSS level 2. These";\r
+ ret += " extended selectors will be used by CSS level 3.";\r
+ ret += " </p><p>Selectors define the following function:</p>";\r
+ ret += " <pre>expression ∗ element → boolean</pre>";\r
+ ret += " <p>That is, given an element and a selector, this specification";\r
+ ret += " defines whether that element matches the selector.</p>";\r
+ ret += " <p>These expressions can also be used, for instance, to select a set";\r
+ ret += " subtree. <acronym title='Simple Tree Transformation";\r
+ ret += " Sheets'>STTS</acronym> (Simple Tree Transformation Sheets), a";\r
+ ret += " language for transforming XML trees, uses this mechanism. <a href='#refsSTTS'>[STTS]</a></p>";\r
+ ret += " <h2><a name='status'></a>Status of this document</h2>";\r
+ ret += " <p><em>This section describes the status of this document at the";\r
+ ret += " of this technical report can be found in the <a href='http://www.w3.org/TR/'>W3C technical reports index at";\r
+ ret += " http://www.w3.org/TR/.</a></em></p>";\r
+ 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";\r
+ ret += " also proposes new selectors for <abbr title='CSS level";\r
+ ret += " 3'>CSS3</abbr> and other languages that may need them.</p>";\r
+ ret += " <p>The CSS Working Group doesn't expect that all implementations of";\r
+ ret += " CSS3 will have to implement all selectors. Instead, there will";\r
+ ret += " will include all of the selectors.</p>";\r
+ 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>";\r
+ ret += " (<a href='/Style/'>Style Activity</a>). This";\r
+ ret += " document is a revision of the <a href='http://www.w3.org/TR/2001/CR-css3-selectors-20011113/'>Candidate";\r
+ ret += " Recommendation dated 2001 November 13</a>, and has incorporated";\r
+ ret += " be demonstrable.</p>";\r
+ ret += " <p>All persons are encouraged to review and implement this";\r
+ ret += " specification and return comments to the (<a href='http://lists.w3.org/Archives/Public/www-style/'>archived</a>)";\r
+ ret += " public mailing list <a href='http://www.w3.org/Mail/Lists.html#www-style'>www-style</a>";\r
+ ret += " (see <a href='http://www.w3.org/Mail/Request'>instructions</a>). W3C";\r
+ ret += " The deadline for comments is 14 January 2006.</p>";\r
+ ret += " <p>This is still a draft document and may be updated, replaced, or";\r
+ ret += " </p><p>This document may be available in <a href='http://www.w3.org/Style/css3-selectors-updates/translations'>translation</a>.";\r
+ ret += " </p><div class='subtoc'>";\r
+ ret += " <h2><a name='contents'>Table of contents</a></h2>";\r
+ ret += " <ul class='toc'>";\r
+ ret += " <li class='tocline2'><a href='#context'>1. Introduction</a>";\r
+ ret += " <ul>";\r
+ ret += " <li><a href='#dependencies'>1.1. Dependencies</a></li>";\r
+ ret += " <li><a href='#terminology'>1.2. Terminology</a></li>";\r
+ ret += " <li><a href='#changesFromCSS2'>1.3. Changes from CSS2</a></li>";\r
+ ret += " </ul>";\r
+ ret += " </li><li class='tocline2'><a href='#selectors'>2. Selectors</a>";\r
+ ret += " </li><li class='tocline2'><a href='#casesens'>3. Case sensitivity</a>";\r
+ ret += " </li><li class='tocline2'><a href='#selector-syntax'>4. Selector syntax</a>";\r
+ ret += " </li><li class='tocline2'><a href='#grouping'>5. Groups of selectors</a>";\r
+ ret += " </li><li class='tocline2'><a href='#simple-selectors'>6. Simple selectors</a>";\r
+ ret += " <ul class='toc'>";\r
+ ret += " <li class='tocline3'><a href='#type-selectors'>6.1. Type";\r
+ ret += " selectors</a>";\r
+ ret += " <ul class='toc'>";\r
+ ret += " <li class='tocline4'><a href='#typenmsp'>6.1.1. Type";\r
+ ret += " selectors and namespaces</a></li>";\r
+ ret += " </ul>";\r
+ ret += " </li><li class='tocline3'><a href='#universal-selector'>6.2.";\r
+ ret += " Universal selector</a>";\r
+ ret += " <ul>";\r
+ ret += " <li><a href='#univnmsp'>6.2.1. Universal selector and";\r
+ ret += " namespaces</a></li>";\r
+ ret += " </ul>";\r
+ ret += " </li><li class='tocline3'><a href='#attribute-selectors'>6.3.";\r
+ ret += " Attribute selectors</a>";\r
+ ret += " <ul class='toc'>";\r
+ ret += " <li class='tocline4'><a href='#attribute-representation'>6.3.1.";\r
+ ret += " values</a>";\r
+ ret += " </li><li><a href='#attribute-substrings'>6.3.2. Substring";\r
+ ret += " matching attribute selectors</a>";\r
+ ret += " </li><li class='tocline4'><a href='#attrnmsp'>6.3.3.";\r
+ ret += " Attribute selectors and namespaces</a>";\r
+ ret += " </li><li class='tocline4'><a href='#def-values'>6.3.4.";\r
+ ret += " Default attribute values in DTDs</a></li>";\r
+ ret += " </ul>";\r
+ ret += " </li><li class='tocline3'><a href='#class-html'>6.4. Class";\r
+ ret += " selectors</a>";\r
+ ret += " </li><li class='tocline3'><a href='#id-selectors'>6.5. ID";\r
+ ret += " selectors</a>";\r
+ ret += " </li><li class='tocline3'><a href='#pseudo-classes'>6.6.";\r
+ ret += " Pseudo-classes</a>";\r
+ ret += " <ul class='toc'>";\r
+ ret += " <li class='tocline4'><a href='#dynamic-pseudos'>6.6.1.";\r
+ ret += " Dynamic pseudo-classes</a>";\r
+ ret += " </li><li class='tocline4'><a href='#target-pseudo'>6.6.2. The";\r
+ ret += " :target pseudo-class</a>";\r
+ ret += " </li><li class='tocline4'><a href='#lang-pseudo'>6.6.3. The";\r
+ ret += " :lang() pseudo-class</a>";\r
+ ret += " </li><li class='tocline4'><a href='#UIstates'>6.6.4. UI";\r
+ ret += " element states pseudo-classes</a>";\r
+ ret += " </li><li class='tocline4'><a href='#structural-pseudos'>6.6.5.";\r
+ ret += " Structural pseudo-classes</a>";\r
+ ret += " <ul>";\r
+ ret += " <li><a href='#root-pseudo'>:root";\r
+ ret += " pseudo-class</a>";\r
+ ret += " </li><li><a href='#nth-child-pseudo'>:nth-child()";\r
+ ret += " pseudo-class</a>";\r
+ ret += " </li><li><a href='#nth-last-child-pseudo'>:nth-last-child()</a>";\r
+ ret += " </li><li><a href='#nth-of-type-pseudo'>:nth-of-type()";\r
+ ret += " pseudo-class</a>";\r
+ ret += " </li><li><a href='#nth-last-of-type-pseudo'>:nth-last-of-type()</a>";\r
+ ret += " </li><li><a href='#first-child-pseudo'>:first-child";\r
+ ret += " pseudo-class</a>";\r
+ ret += " </li><li><a href='#last-child-pseudo'>:last-child";\r
+ ret += " pseudo-class</a>";\r
+ ret += " </li><li><a href='#first-of-type-pseudo'>:first-of-type";\r
+ ret += " pseudo-class</a>";\r
+ ret += " </li><li><a href='#last-of-type-pseudo'>:last-of-type";\r
+ ret += " pseudo-class</a>";\r
+ ret += " </li><li><a href='#only-child-pseudo'>:only-child";\r
+ ret += " pseudo-class</a>";\r
+ ret += " </li><li><a href='#only-of-type-pseudo'>:only-of-type";\r
+ ret += " pseudo-class</a>";\r
+ ret += " </li><li><a href='#empty-pseudo'>:empty";\r
+ ret += " pseudo-class</a></li>";\r
+ ret += " </ul>";\r
+ ret += " </li><li class='tocline4'><a href='#negation'>6.6.7. The";\r
+ ret += " negation pseudo-class</a></li>";\r
+ ret += " </ul>";\r
+ ret += " </li>";\r
+ ret += " </ul>";\r
+ ret += " </li><li><a href='#pseudo-elements'>7. Pseudo-elements</a>";\r
+ ret += " <ul>";\r
+ ret += " <li><a href='#first-line'>7.1. The ::first-line";\r
+ ret += " pseudo-element</a>";\r
+ ret += " </li><li><a href='#first-letter'>7.2. The ::first-letter";\r
+ ret += " pseudo-element</a>";\r
+ ret += " </li><li><a href='#UIfragments'>7.3. The ::selection";\r
+ ret += " pseudo-element</a>";\r
+ ret += " </li><li><a href='#gen-content'>7.4. The ::before and ::after";\r
+ ret += " pseudo-elements</a></li>";\r
+ ret += " </ul>";\r
+ ret += " </li><li class='tocline2'><a href='#combinators'>8. Combinators</a>";\r
+ ret += " <ul class='toc'>";\r
+ ret += " <li class='tocline3'><a href='#descendant-combinators'>8.1.";\r
+ ret += " Descendant combinators</a>";\r
+ ret += " </li><li class='tocline3'><a href='#child-combinators'>8.2. Child";\r
+ ret += " combinators</a>";\r
+ ret += " </li><li class='tocline3'><a href='#sibling-combinators'>8.3. Sibling";\r
+ ret += " combinators</a>";\r
+ ret += " <ul class='toc'>";\r
+ ret += " <li class='tocline4'><a href='#adjacent-sibling-combinators'>8.3.1.";\r
+ ret += " Adjacent sibling combinator</a>";\r
+ ret += " </li><li class='tocline4'><a href='#general-sibling-combinators'>8.3.2.";\r
+ ret += " General sibling combinator</a></li>";\r
+ ret += " </ul>";\r
+ ret += " </li>";\r
+ ret += " </ul>";\r
+ ret += " </li><li class='tocline2'><a href='#specificity'>9. Calculating a selector's";\r
+ ret += " specificity</a>";\r
+ ret += " </li><li class='tocline2'><a href='#w3cselgrammar'>10. The grammar of";\r
+ ret += " Selectors</a>";\r
+ ret += " <ul class='toc'>";\r
+ ret += " <li class='tocline3'><a href='#grammar'>10.1. Grammar</a>";\r
+ ret += " </li><li class='tocline3'><a href='#lex'>10.2. Lexical scanner</a>";\r
+ ret += " </li>";\r
+ ret += " </ul>";\r
+ ret += " </li><li class='tocline2'><a href='#downlevel'>11. Namespaces and down-level";\r
+ ret += " clients</a>";\r
+ ret += " </li><li class='tocline2'><a href='#profiling'>12. Profiles</a>";\r
+ ret += " </li><li><a href='#Conformance'>13. Conformance and requirements</a>";\r
+ ret += " </li><li><a href='#Tests'>14. Tests</a>";\r
+ ret += " </li><li><a href='#ACKS'>15. Acknowledgements</a>";\r
+ ret += " </li><li class='tocline2'><a href='#references'>16. References</a>";\r
+ ret += " </li></ul>";\r
+ ret += " </div>";\r
+ ret += " <h2><a name='context'>1. Introduction</a></h2>";\r
+ ret += " <h3><a name='dependencies'></a>1.1. Dependencies</h3>";\r
+ ret += " <p>Some features of this specification are specific to CSS, or have";\r
+ ret += " specification, these have been described in terms of CSS2.1. <a href='#refsCSS21'>[CSS21]</a></p>";\r
+ ret += " <h3><a name='terminology'></a>1.2. Terminology</h3>";\r
+ ret += " <p>All of the text of this specification is normative except";\r
+ ret += " non-normative.</p>";\r
+ ret += " <h3><a name='changesFromCSS2'></a>1.3. Changes from CSS2</h3>";\r
+ ret += " <p><em>This section is non-normative.</em></p>";\r
+ ret += " <p>The main differences between the selectors in CSS2 and those in";\r
+ ret += " Selectors are:";\r
+ ret += " </p><ul>";\r
+ ret += " <li>the list of basic definitions (selector, group of selectors,";\r
+ ret += " of simple selectors, and the term 'simple selector' is now used for";\r
+ ret += " </li>";\r
+ ret += " <li>an optional namespace component is now allowed in type element";\r
+ ret += " selectors, the universal selector and attribute selectors";\r
+ ret += " </li>";\r
+ ret += " <li>a <a href='#general-sibling-combinators'>new combinator</a> has been";\r
+ ret += " </li>";\r
+ ret += " <li>new simple selectors including substring matching attribute";\r
+ ret += " selectors, and new pseudo-classes";\r
+ ret += " </li>";\r
+ ret += " <li>new pseudo-elements, and introduction of the '::' convention";\r
+ ret += " </li>";\r
+ ret += " <li>the grammar has been rewritten</li>";\r
+ ret += " <li>profiles to be added to specifications integrating Selectors";\r
+ ret += " and defining the set of selectors which is actually supported by";\r
+ ret += " </li>";\r
+ ret += " <li>Selectors are now a CSS3 Module and an independent";\r
+ ret += " </li>";\r
+ ret += " <li>the specification now has its own test suite</li>";\r
+ ret += " </ul>";\r
+ ret += " <h2><a name='selectors'></a>2. Selectors</h2>";\r
+ ret += " <p><em>This section is non-normative, as it merely summarizes the";\r
+ ret += " following sections.</em></p>";\r
+ ret += " <p>A Selector represents a structure. This structure can be used as a";\r
+ ret += " HTML or XML fragment corresponding to that structure.</p>";\r
+ ret += " <p>Selectors may range from simple element names to rich contextual";\r
+ ret += " representations.</p>";\r
+ ret += " <p>The following table summarizes the Selector syntax:</p>";\r
+ ret += " <table class='selectorsReview'>";\r
+ ret += " <thead>";\r
+ ret += " <tr>";\r
+ ret += " <th class='pattern'>Pattern</th>";\r
+ ret += " <th class='meaning'>Meaning</th>";\r
+ ret += " <th class='described'>Described in section</th>";\r
+ ret += " <th class='origin'>First defined in CSS level</th>";\r
+ ret += " </tr>";\r
+ ret += " </thead><tbody>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>*</td>";\r
+ ret += " <td class='meaning'>any element</td>";\r
+ ret += " <td class='described'><a href='#universal-selector'>Universal";\r
+ ret += " selector</a></td>";\r
+ ret += " <td class='origin'>2</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E</td>";\r
+ ret += " <td class='meaning'>an element of type E</td>";\r
+ ret += " <td class='described'><a href='#type-selectors'>Type selector</a></td>";\r
+ ret += " <td class='origin'>1</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E[foo]</td>";\r
+ ret += " <td class='meaning'>an E element with a 'foo' attribute</td>";\r
+ ret += " <td class='described'><a href='#attribute-selectors'>Attribute";\r
+ ret += " selectors</a></td>";\r
+ ret += " <td class='origin'>2</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E[foo='bar']</td>";\r
+ ret += " <td class='meaning'>an E element whose 'foo' attribute value is exactly";\r
+ ret += " </td>";\r
+ ret += " <td class='described'><a href='#attribute-selectors'>Attribute";\r
+ ret += " selectors</a></td>";\r
+ ret += " <td class='origin'>2</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E[foo~='bar']</td>";\r
+ ret += " <td class='meaning'>an E element whose 'foo' attribute value is a list of";\r
+ ret += " </td>";\r
+ ret += " <td class='described'><a href='#attribute-selectors'>Attribute";\r
+ ret += " selectors</a></td>";\r
+ ret += " <td class='origin'>2</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E[foo^='bar']</td>";\r
+ ret += " <td class='meaning'>an E element whose 'foo' attribute value begins exactly";\r
+ ret += " </td>";\r
+ ret += " <td class='described'><a href='#attribute-selectors'>Attribute";\r
+ ret += " selectors</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E[foo$='bar']</td>";\r
+ ret += " <td class='meaning'>an E element whose 'foo' attribute value ends exactly";\r
+ ret += " </td>";\r
+ ret += " <td class='described'><a href='#attribute-selectors'>Attribute";\r
+ ret += " selectors</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E[foo*='bar']</td>";\r
+ ret += " <td class='meaning'>an E element whose 'foo' attribute value contains the";\r
+ ret += " </td>";\r
+ ret += " <td class='described'><a href='#attribute-selectors'>Attribute";\r
+ ret += " selectors</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E[hreflang|='en']</td>";\r
+ ret += " <td class='meaning'>an E element whose 'hreflang' attribute has a";\r
+ ret += " </td>";\r
+ ret += " <td class='described'><a href='#attribute-selectors'>Attribute";\r
+ ret += " selectors</a></td>";\r
+ ret += " <td class='origin'>2</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:root</td>";\r
+ ret += " <td class='meaning'>an E element, root of the document</td>";\r
+ ret += " <td class='described'><a href='#structural-pseudos'>Structural";\r
+ ret += " pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:nth-child(n)</td>";\r
+ ret += " <td class='meaning'>an E element, the n-th child of its parent</td>";\r
+ ret += " <td class='described'><a href='#structural-pseudos'>Structural";\r
+ ret += " pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:nth-last-child(n)</td>";\r
+ ret += " <td class='meaning'>an E element, the n-th child of its parent, counting";\r
+ ret += " </td>";\r
+ ret += " <td class='described'><a href='#structural-pseudos'>Structural";\r
+ ret += " pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:nth-of-type(n)</td>";\r
+ ret += " <td class='meaning'>an E element, the n-th sibling of its type</td>";\r
+ ret += " <td class='described'><a href='#structural-pseudos'>Structural";\r
+ ret += " pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:nth-last-of-type(n)</td>";\r
+ ret += " <td class='meaning'>an E element, the n-th sibling of its type, counting";\r
+ ret += " </td>";\r
+ ret += " <td class='described'><a href='#structural-pseudos'>Structural";\r
+ ret += " pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:first-child</td>";\r
+ ret += " <td class='meaning'>an E element, first child of its parent</td>";\r
+ ret += " <td class='described'><a href='#structural-pseudos'>Structural";\r
+ ret += " pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>2</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:last-child</td>";\r
+ ret += " <td class='meaning'>an E element, last child of its parent</td>";\r
+ ret += " <td class='described'><a href='#structural-pseudos'>Structural";\r
+ ret += " pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:first-of-type</td>";\r
+ ret += " <td class='meaning'>an E element, first sibling of its type</td>";\r
+ ret += " <td class='described'><a href='#structural-pseudos'>Structural";\r
+ ret += " pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:last-of-type</td>";\r
+ ret += " <td class='meaning'>an E element, last sibling of its type</td>";\r
+ ret += " <td class='described'><a href='#structural-pseudos'>Structural";\r
+ ret += " pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:only-child</td>";\r
+ ret += " <td class='meaning'>an E element, only child of its parent</td>";\r
+ ret += " <td class='described'><a href='#structural-pseudos'>Structural";\r
+ ret += " pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:only-of-type</td>";\r
+ ret += " <td class='meaning'>an E element, only sibling of its type</td>";\r
+ ret += " <td class='described'><a href='#structural-pseudos'>Structural";\r
+ ret += " pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:empty</td>";\r
+ ret += " <td class='meaning'>an E element that has no children (including text";\r
+ ret += " </td>";\r
+ ret += " <td class='described'><a href='#structural-pseudos'>Structural";\r
+ ret += " pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:link<br>E:visited</td>";\r
+ ret += " <td class='meaning'>an E element being the source anchor of a hyperlink of";\r
+ ret += " </td>";\r
+ ret += " <td class='described'><a href='#link'>The link";\r
+ ret += " pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>1</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:active<br>E:hover<br>E:focus</td>";\r
+ ret += " <td class='meaning'>an E element during certain user actions</td>";\r
+ ret += " <td class='described'><a href='#useraction-pseudos'>The user";\r
+ ret += " action pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>1 and 2</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:target</td>";\r
+ ret += " <td class='meaning'>an E element being the target of the referring URI</td>";\r
+ ret += " <td class='described'><a href='#target-pseudo'>The target";\r
+ ret += " pseudo-class</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:lang(fr)</td>";\r
+ ret += " <td class='meaning'>an element of type E in language 'fr' (the document";\r
+ ret += " </td>";\r
+ ret += " <td class='described'><a href='#lang-pseudo'>The :lang()";\r
+ ret += " pseudo-class</a></td>";\r
+ ret += " <td class='origin'>2</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:enabled<br>E:disabled</td>";\r
+ ret += " <td class='meaning'>a user interface element E which is enabled or";\r
+ ret += " </td>";\r
+ ret += " <td class='described'><a href='#UIstates'>The UI element states";\r
+ ret += " pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:checked<!--<br>E:indeterminate--></td>";\r
+ ret += " <td class='meaning'>a user interface element E which is checked<!-- or in an";\r
+ ret += " indeterminate state--> (for instance a radio-button or checkbox)";\r
+ ret += " </td>";\r
+ ret += " <td class='described'><a href='#UIstates'>The UI element states";\r
+ ret += " pseudo-classes</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E::first-line</td>";\r
+ ret += " <td class='meaning'>the first formatted line of an E element</td>";\r
+ ret += " <td class='described'><a href='#first-line'>The ::first-line";\r
+ ret += " pseudo-element</a></td>";\r
+ ret += " <td class='origin'>1</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E::first-letter</td>";\r
+ ret += " <td class='meaning'>the first formatted letter of an E element</td>";\r
+ ret += " <td class='described'><a href='#first-letter'>The ::first-letter";\r
+ ret += " pseudo-element</a></td>";\r
+ ret += " <td class='origin'>1</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E::selection</td>";\r
+ ret += " <td class='meaning'>the portion of an E element that is currently";\r
+ ret += " </td>";\r
+ ret += " <td class='described'><a href='#UIfragments'>The UI element";\r
+ ret += " fragments pseudo-elements</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E::before</td>";\r
+ ret += " <td class='meaning'>generated content before an E element</td>";\r
+ ret += " <td class='described'><a href='#gen-content'>The ::before";\r
+ ret += " pseudo-element</a></td>";\r
+ ret += " <td class='origin'>2</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E::after</td>";\r
+ ret += " <td class='meaning'>generated content after an E element</td>";\r
+ ret += " <td class='described'><a href='#gen-content'>The ::after";\r
+ ret += " pseudo-element</a></td>";\r
+ ret += " <td class='origin'>2</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E.warning</td>";\r
+ ret += " <td class='meaning'>an E element whose class is";\r
+ ret += " </td>";\r
+ ret += " <td class='described'><a href='#class-html'>Class";\r
+ ret += " selectors</a></td>";\r
+ ret += " <td class='origin'>1</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E#myid</td>";\r
+ ret += " <td class='meaning'>an E element with ID equal to 'myid'.</td>";\r
+ ret += " <td class='described'><a href='#id-selectors'>ID";\r
+ ret += " selectors</a></td>";\r
+ ret += " <td class='origin'>1</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E:not(s)</td>";\r
+ ret += " <td class='meaning'>an E element that does not match simple selector s</td>";\r
+ ret += " <td class='described'><a href='#negation'>Negation";\r
+ ret += " pseudo-class</a></td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E F</td>";\r
+ ret += " <td class='meaning'>an F element descendant of an E element</td>";\r
+ ret += " <td class='described'><a href='#descendant-combinators'>Descendant";\r
+ ret += " combinator</a></td>";\r
+ ret += " <td class='origin'>1</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E > F</td>";\r
+ ret += " <td class='meaning'>an F element child of an E element</td>";\r
+ ret += " <td class='described'><a href='#child-combinators'>Child";\r
+ ret += " combinator</a></td>";\r
+ ret += " <td class='origin'>2</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E + F</td>";\r
+ ret += " <td class='meaning'>an F element immediately preceded by an E element</td>";\r
+ ret += " <td class='described'><a href='#adjacent-sibling-combinators'>Adjacent sibling combinator</a>";\r
+ ret += " </td>";\r
+ ret += " <td class='origin'>2</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <td class='pattern'>E ~ F</td>";\r
+ ret += " <td class='meaning'>an F element preceded by an E element</td>";\r
+ ret += " <td class='described'><a href='#general-sibling-combinators'>General sibling combinator</a>";\r
+ ret += " </td>";\r
+ ret += " <td class='origin'>3</td>";\r
+ ret += " </tr>";\r
+ ret += " </tbody>";\r
+ ret += " </table>";\r
+ ret += " <p>The meaning of each selector is derived from the table above by";\r
+ ret += " column.</p>";\r
+ ret += " <h2><a name='casesens'>3. Case sensitivity</a></h2>";\r
+ ret += " <p>The case sensitivity of document language element names, attribute";\r
+ ret += " names, and attribute values in selectors depends on the document";\r
+ ret += " but in XML, they are case-sensitive.</p>";\r
+ ret += " <h2><a name='selector-syntax'>4. Selector syntax</a></h2>";\r
+ ret += " <p>A <dfn><a name='selector'>selector</a></dfn> is a chain of one";\r
+ ret += " or more <a href='#sequence'>sequences of simple selectors</a>";\r
+ ret += " separated by <a href='#combinators'>combinators</a>.</p>";\r
+ ret += " <p>A <dfn><a name='sequence'>sequence of simple selectors</a></dfn>";\r
+ ret += " is a chain of <a href='#simple-selectors-dfn'>simple selectors</a>";\r
+ ret += " that are not separated by a <a href='#combinators'>combinator</a>. It";\r
+ ret += " always begins with a <a href='#type-selectors'>type selector</a> or a";\r
+ ret += " <a href='#universal-selector'>universal selector</a>. No other type";\r
+ ret += " selector or universal selector is allowed in the sequence.</p>";\r
+ 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";\r
+ ret += " sequence of simple selectors.</p>";\r
+ ret += " <p><dfn>Combinators</dfn> are: white space, 'greater-than";\r
+ ret += " sign' (U+003E, <code>></code>), 'plus sign' (U+002B,";\r
+ ret += " <code>+</code>) and 'tilde' (U+007E, <code>~</code>). White";\r
+ ret += " space may appear between a combinator and the simple selectors around";\r
+ ret += " it. <a name='whitespace'></a>Only the characters 'space' (U+0020), 'tab'";\r
+ ret += " never part of white space.</p>";\r
+ ret += " <p>The elements of a document tree that are represented by a selector";\r
+ ret += " are the <dfn><a name='subject'></a>subjects of the selector</dfn>. A";\r
+ ret += " selector consisting of a single sequence of simple selectors";\r
+ ret += " sequence of simple selectors and a combinator to a sequence imposes";\r
+ ret += " simple selectors.</p>";\r
+ ret += " <p>An empty selector, containing no sequence of simple selectors and";\r
+ ret += " no pseudo-element, is an <a href='#Conformance'>invalid";\r
+ ret += " selector</a>.</p>";\r
+ ret += " <h2><a name='grouping'>5. Groups of selectors</a></h2>";\r
+ ret += " <p>When several selectors share the same declarations, they may be";\r
+ ret += " grouped into a comma-separated list. (A comma is U+002C.)</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>CSS examples:</p>";\r
+ ret += " <p>In this example, we condense three rules with identical";\r
+ ret += " declarations into one. Thus,</p>";\r
+ ret += " <pre>h1 { font-family: sans-serif }";\r
+ ret += " h3 { font-family: sans-serif }</pre>";\r
+ ret += " <p>is equivalent to:</p>";\r
+ ret += " <pre>h1, h2, h3 { font-family: sans-serif }</pre>";\r
+ ret += " </div>";\r
+ ret += " <p><strong>Warning</strong>: the equivalence is true in this example";\r
+ ret += " because all the selectors are valid selectors. If just one of these";\r
+ ret += " selectors were invalid, the entire group of selectors would be";\r
+ ret += " heading rules would be invalidated.</p>";\r
+ ret += " <h2><a name='simple-selectors'>6. Simple selectors</a></h2>";\r
+ ret += " <h3><a name='type-selectors'>6.1. Type selector</a></h3>";\r
+ ret += " <p>A <dfn>type selector</dfn> is the name of a document language";\r
+ ret += " type in the document tree.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Example:</p>";\r
+ ret += " <p>The following selector represents an <code>h1</code> element in the";\r
+ ret += " document tree:</p>";\r
+ ret += " <pre>h1</pre>";\r
+ ret += " </div>";\r
+ ret += " <h4><a name='typenmsp'>6.1.1. Type selectors and namespaces</a></h4>";\r
+ ret += " <p>Type selectors allow an optional namespace (<a href='#refsXMLNAMES'>[XMLNAMES]</a>) component. A namespace prefix";\r
+ ret += " (U+007C, <code>|</code>).</p>";\r
+ ret += " <p>The namespace component may be left empty to indicate that the";\r
+ ret += " selector is only to represent elements with no declared namespace.</p>";\r
+ ret += " <p>An asterisk may be used for the namespace prefix, indicating that";\r
+ ret += " with no namespace).</p>";\r
+ ret += " <p>Element type selectors that have no namespace component (no";\r
+ ret += " element's namespace (equivalent to '<code>*|</code>') unless a default";\r
+ ret += " namespace.</p>";\r
+ ret += " <p>A type selector containing a namespace prefix that has not been";\r
+ ret += " previously declared is an <a href='#Conformance'>invalid</a> selector.";\r
+ ret += " language implementing Selectors. In CSS, such a mechanism is defined";\r
+ ret += " in the General Syntax module.</p>";\r
+ ret += " <p>In a namespace-aware client, element type selectors will only match";\r
+ ret += " against the <a href='http://www.w3.org/TR/REC-xml-names/#NT-LocalPart'>local";\r
+ ret += " part</a>";\r
+ ret += " of the element's <a href='http://www.w3.org/TR/REC-xml-names/#ns-qualnames'>qualified";\r
+ ret += " name</a>. See <a href='#downlevel'>below</a> for notes about matching";\r
+ ret += " behaviors in down-level clients.</p>";\r
+ ret += " <p>In summary:</p>";\r
+ ret += " <dl>";\r
+ ret += " <dt><code>ns|E</code></dt>";\r
+ ret += " <dd>elements with name E in namespace ns</dd>";\r
+ ret += " <dt><code>*|E</code></dt>";\r
+ ret += " <dd>elements with name E in any namespace, including those without any";\r
+ ret += " </dd>";\r
+ ret += " <dt><code>|E</code></dt>";\r
+ ret += " <dd>elements with name E without any declared namespace</dd>";\r
+ ret += " <dt><code>E</code></dt>";\r
+ ret += " <dd>if no default namespace has been specified, this is equivalent to *|E.";\r
+ ret += " </dd>";\r
+ ret += " </dl>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>CSS examples:</p>";\r
+ ret += " <pre>@namespace foo url(http://www.example.com);";\r
+ ret += " h1 { color: green }</pre>";\r
+ ret += " <p>The first rule will match only <code>h1</code> elements in the";\r
+ ret += " 'http://www.example.com' namespace.</p>";\r
+ ret += " <p>The second rule will match all elements in the";\r
+ ret += " 'http://www.example.com' namespace.</p>";\r
+ ret += " <p>The third rule will match only <code>h1</code> elements without";\r
+ ret += " any declared namespace.</p>";\r
+ ret += " <p>The fourth rule will match <code>h1</code> elements in any";\r
+ ret += " namespace (including those without any declared namespace).</p>";\r
+ ret += " <p>The last rule is equivalent to the fourth rule because no default";\r
+ ret += " namespace has been defined.</p>";\r
+ ret += " </div>";\r
+ ret += " <h3><a name='universal-selector'>6.2. Universal selector</a></h3>";\r
+ ret += " <p>The <dfn>universal selector</dfn>, written 'asterisk'";\r
+ ret += " (<code>*</code>), represents the qualified name of any element";\r
+ ret += " specified, see <a href='#univnmsp'>Universal selector and";\r
+ ret += " Namespaces</a> below.</p>";\r
+ ret += " <p>If the universal selector is not the only component of a sequence";\r
+ ret += " of simple selectors, the <code>*</code> may be omitted.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <ul>";\r
+ ret += " <li><code>*[hreflang|=en]</code> and <code>[hreflang|=en]</code> are";\r
+ ret += " </li>";\r
+ ret += " <li><code>*.warning</code> and <code>.warning</code> are equivalent,";\r
+ ret += " </li>";\r
+ ret += " <li><code>*#myid</code> and <code>#myid</code> are equivalent.</li>";\r
+ ret += " </ul>";\r
+ ret += " </div>";\r
+ ret += " <p class='note'><strong>Note:</strong> it is recommended that the";\r
+ ret += " <code>*</code>, representing the universal selector, not be";\r
+ ret += " omitted.</p>";\r
+ ret += " <h4><a name='univnmsp'>6.2.1. Universal selector and namespaces</a></h4>";\r
+ ret += " <p>The universal selector allows an optional namespace component. It";\r
+ ret += " is used as follows:</p>";\r
+ ret += " <dl>";\r
+ ret += " <dt><code>ns|*</code></dt>";\r
+ ret += " <dd>all elements in namespace ns</dd>";\r
+ ret += " <dt><code>*|*</code></dt>";\r
+ ret += " <dd>all elements</dd>";\r
+ ret += " <dt><code>|*</code></dt>";\r
+ ret += " <dd>all elements without any declared namespace</dd>";\r
+ ret += " <dt><code>*</code></dt>";\r
+ ret += " <dd>if no default namespace has been specified, this is equivalent to *|*.";\r
+ ret += " </dd>";\r
+ ret += " </dl>";\r
+ ret += " <p>A universal selector containing a namespace prefix that has not";\r
+ ret += " been previously declared is an <a href='#Conformance'>invalid</a>";\r
+ ret += " to the language implementing Selectors. In CSS, such a mechanism is";\r
+ ret += " defined in the General Syntax module.</p>";\r
+ ret += " <h3><a name='attribute-selectors'>6.3. Attribute selectors</a></h3>";\r
+ ret += " <p>Selectors allow the representation of an element's attributes. When";\r
+ ret += " attribute selectors must be considered to match an element if that";\r
+ ret += " attribute selector.</p>";\r
+ ret += " <h4><a name='attribute-representation'>6.3.1. Attribute presence and values";\r
+ ret += " selectors</a></h4>";\r
+ ret += " <p>CSS2 introduced four attribute selectors:</p>";\r
+ ret += " <dl>";\r
+ ret += " <dt><code>[att]</code>";\r
+ ret += " </dt><dd>Represents an element with the <code>att</code> attribute, whatever the";\r
+ ret += " </dd>";\r
+ ret += " <dt><code>[att=val]</code></dt>";\r
+ ret += " <dd>Represents an element with the <code>att</code> attribute whose value is";\r
+ ret += " </dd>";\r
+ ret += " <dt><code>[att~=val]</code></dt>";\r
+ ret += " <dd>Represents an element with the <code>att</code> attribute whose value is";\r
+ ret += " a <a href='#whitespace'>whitespace</a>-separated list of words, one";\r
+ ret += " represent anything (since the words are <em>separated</em> by";\r
+ ret += " </dd>";\r
+ ret += " <dt><code>[att|=val]</code>";\r
+ ret += " </dt><dd>Represents an element with the <code>att</code> attribute, its value";\r
+ ret += " matches (e.g., the <code>hreflang</code> attribute on the";\r
+ ret += " <code>link</code> element in HTML) as described in RFC 3066 (<a href='#refsRFC3066'>[RFC3066]</a>). For <code>lang</code> (or";\r
+ ret += " <code>xml:lang</code>) language subcode matching, please see <a href='#lang-pseudo'>the <code>:lang</code> pseudo-class</a>.";\r
+ ret += " </dd>";\r
+ ret += " </dl>";\r
+ ret += " <p>Attribute values must be identifiers or strings. The";\r
+ ret += " case-sensitivity of attribute names and values in selectors depends on";\r
+ ret += " the document language.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <p>The following attribute selector represents an <code>h1</code>";\r
+ ret += " element that carries the <code>title</code> attribute, whatever its";\r
+ ret += " value:</p>";\r
+ ret += " <pre>h1[title]</pre>";\r
+ ret += " <p>In the following example, the selector represents a";\r
+ ret += " <code>span</code> element whose <code>class</code> attribute has";\r
+ ret += " exactly the value 'example':</p>";\r
+ ret += " <pre>span[class='example']</pre>";\r
+ ret += " <p>Multiple attribute selectors can be used to represent several";\r
+ ret += " attribute. Here, the selector represents a <code>span</code> element";\r
+ ret += " whose <code>hello</code> attribute has exactly the value 'Cleveland'";\r
+ ret += " and whose <code>goodbye</code> attribute has exactly the value";\r
+ ret += " 'Columbus':</p>";\r
+ ret += " <pre>span[hello='Cleveland'][goodbye='Columbus']</pre>";\r
+ ret += " <p>The following selectors illustrate the differences between '='";\r
+ ret += " 'copyright copyleft copyeditor' on a <code>rel</code> attribute. The";\r
+ ret += " second selector will only represent an <code>a</code> element with";\r
+ ret += " an <code>href</code> attribute having the exact value";\r
+ ret += " 'http://www.w3.org/'.</p>";\r
+ ret += " <pre>a[rel~='copyright']";\r
+ ret += " a[href='http://www.w3.org/']</pre>";\r
+ ret += " <p>The following selector represents a <code>link</code> element";\r
+ ret += " whose <code>hreflang</code> attribute is exactly 'fr'.</p>";\r
+ ret += " <pre>link[hreflang=fr]</pre>";\r
+ ret += " <p>The following selector represents a <code>link</code> element for";\r
+ ret += " which the values of the <code>hreflang</code> attribute begins with";\r
+ ret += " 'en', including 'en', 'en-US', and 'en-cockney':</p>";\r
+ ret += " <pre>link[hreflang|='en']</pre>";\r
+ ret += " <p>Similarly, the following selectors represents a";\r
+ ret += " <code>DIALOGUE</code> element whenever it has one of two different";\r
+ ret += " values for an attribute <code>character</code>:</p>";\r
+ ret += " <pre>DIALOGUE[character=romeo]";\r
+ ret += " DIALOGUE[character=juliet]</pre>";\r
+ ret += " </div>";\r
+ ret += " <h4><a name='attribute-substrings'></a>6.3.2. Substring matching attribute";\r
+ ret += " selectors</h4>";\r
+ ret += " <p>Three additional attribute selectors are provided for matching";\r
+ ret += " substrings in the value of an attribute:</p>";\r
+ ret += " <dl>";\r
+ ret += " <dt><code>[att^=val]</code></dt>";\r
+ ret += " <dd>Represents an element with the <code>att</code> attribute whose value";\r
+ ret += " </dd>";\r
+ ret += " <dt><code>[att$=val]</code>";\r
+ ret += " </dt><dd>Represents an element with the <code>att</code> attribute whose value";\r
+ ret += " </dd>";\r
+ ret += " <dt><code>[att*=val]</code>";\r
+ ret += " </dt><dd>Represents an element with the <code>att</code> attribute whose value";\r
+ ret += " </dd>";\r
+ ret += " </dl>";\r
+ ret += " <p>Attribute values must be identifiers or strings. The";\r
+ ret += " case-sensitivity of attribute names in selectors depends on the";\r
+ ret += " document language.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <p>The following selector represents an HTML <code>object</code>,";\r
+ ret += " image:</p>";\r
+ ret += " <pre>object[type^='image/']</pre>";\r
+ ret += " <p>The following selector represents an HTML anchor <code>a</code> with an";\r
+ ret += " <code>href</code> attribute whose value ends with '.html'.</p>";\r
+ ret += " <pre>a[href$='.html']</pre>";\r
+ ret += " <p>The following selector represents an HTML paragraph with a";\r
+ ret += " <code>title</code>";\r
+ ret += " attribute whose value contains the substring 'hello'</p>";\r
+ ret += " <pre>p[title*='hello']</pre>";\r
+ ret += " </div>";\r
+ ret += " <h4><a name='attrnmsp'>6.3.3. Attribute selectors and namespaces</a></h4>";\r
+ ret += " <p>Attribute selectors allow an optional namespace component to the";\r
+ ret += " separator 'vertical bar' (<code>|</code>). In keeping with";\r
+ ret += " apply to attributes, therefore attribute selectors without a namespace";\r
+ ret += " (equivalent to '<code>|attr</code>'). An asterisk may be used for the";\r
+ ret += " </p><p>An attribute selector with an attribute name containing a namespace";\r
+ ret += " prefix that has not been previously declared is an <a href='#Conformance'>invalid</a> selector. The mechanism for";\r
+ ret += " a namespace prefix is left up to the language implementing Selectors.";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>CSS examples:</p>";\r
+ ret += " <pre>@namespace foo 'http://www.example.com';";\r
+ ret += " [att] { color: green }</pre>";\r
+ ret += " <p>The first rule will match only elements with the attribute";\r
+ ret += " <code>att</code> in the 'http://www.example.com' namespace with the";\r
+ ret += " value 'val'.</p>";\r
+ ret += " <p>The second rule will match only elements with the attribute";\r
+ ret += " <code>att</code> regardless of the namespace of the attribute";\r
+ ret += " (including no declared namespace).</p>";\r
+ ret += " <p>The last two rules are equivalent and will match only elements";\r
+ ret += " with the attribute <code>att</code> where the attribute is not";\r
+ ret += " declared to be in a namespace.</p>";\r
+ ret += " </div>";\r
+ ret += " <h4><a name='def-values'>6.3.4. Default attribute values in DTDs</a></h4>";\r
+ ret += " <p>Attribute selectors represent explicitly set attribute values in";\r
+ ret += " selectors. Selectors should be designed so that they work even if the";\r
+ ret += " default values are not included in the document tree.</p>";\r
+ ret += " <p>More precisely, a UA is <em>not</em> required to read an 'external";\r
+ ret += " subset' of the DTD but <em>is</em> required to look for default";\r
+ ret += " attribute values in the document's 'internal subset.' (See <a href='#refsXML10'>[XML10]</a> for definitions of these subsets.)</p>";\r
+ ret += " <p>A UA that recognizes an XML namespace <a href='#refsXMLNAMES'>[XMLNAMES]</a> is not required to use its";\r
+ ret += " required to use its built-in knowledge of the XHTML DTD.)</p>";\r
+ ret += " <p class='note'><strong>Note:</strong> Typically, implementations";\r
+ ret += " choose to ignore external subsets.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Example:</p>";\r
+ ret += " <p>Consider an element EXAMPLE with an attribute 'notation' that has a";\r
+ ret += " default value of 'decimal'. The DTD fragment might be</p>";\r
+ ret += " <pre class='dtd-example'><!ATTLIST EXAMPLE notation (decimal,octal) 'decimal'></pre>";\r
+ ret += " <p>If the style sheet contains the rules</p>";\r
+ ret += " <pre>EXAMPLE[notation=decimal] { /*... default property settings ...*/ }";\r
+ ret += " EXAMPLE[notation=octal] { /*... other settings...*/ }</pre>";\r
+ ret += " <p>the first rule will not match elements whose 'notation' attribute";\r
+ ret += " attribute selector for the default value must be dropped:</p>";\r
+ ret += " <pre>EXAMPLE { /*... default property settings ...*/ }";\r
+ ret += " EXAMPLE[notation=octal] { /*... other settings...*/ }</pre>";\r
+ ret += " <p>Here, because the selector <code>EXAMPLE[notation=octal]</code> is";\r
+ ret += " cases' style rules.</p>";\r
+ ret += " </div>";\r
+ ret += " <h3><a name='class-html'>6.4. Class selectors</a></h3>";\r
+ ret += " <p>Working with HTML, authors may use the period (U+002E,";\r
+ ret += " <code>.</code>) notation as an alternative to the <code>~=</code>";\r
+ ret += " notation when representing the <code>class</code> attribute. Thus, for";\r
+ ret += " HTML, <code>div.value</code> and <code>div[class~=value]</code> have";\r
+ ret += " 'period' (<code>.</code>).</p>";\r
+ ret += " <p>UAs may apply selectors using the period (.) notation in XML";\r
+ 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";\r
+ ret += " 'class' attribute</a> and how a UA should interpret it, and";\r
+ 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";\r
+ ret += " 'class' attribute</a>.)</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>CSS examples:</p>";\r
+ ret += " <p>We can assign style information to all elements with";\r
+ ret += " <code>class~='pastoral'</code> as follows:</p>";\r
+ ret += " <pre>*.pastoral { color: green } /* all elements with class~=pastoral */</pre>";\r
+ ret += " <p>or just</p>";\r
+ ret += " <pre>.pastoral { color: green } /* all elements with class~=pastoral */</pre>";\r
+ ret += " <p>The following assigns style only to H1 elements with";\r
+ ret += " <code>class~='pastoral'</code>:</p>";\r
+ ret += " <pre>H1.pastoral { color: green } /* H1 elements with class~=pastoral */</pre>";\r
+ ret += " <p>Given these rules, the first H1 instance below would not have";\r
+ ret += " green text, while the second would:</p>";\r
+ ret += " <pre><H1>Not green</H1>";\r
+ ret += " <H1 class='pastoral'>Very green</H1></pre>";\r
+ ret += " </div>";\r
+ ret += " <p>To represent a subset of 'class' values, each value must be preceded";\r
+ ret += " by a '.', in any order.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>CSS example:</p>";\r
+ ret += " <p>The following rule matches any P element whose 'class' attribute";\r
+ ret += " has been assigned a list of <a href='#whitespace'>whitespace</a>-separated values that includes";\r
+ ret += " 'pastoral' and 'marine':</p>";\r
+ ret += " <pre>p.pastoral.marine { color: green }</pre>";\r
+ ret += " <p>This rule matches when <code>class='pastoral blue aqua";\r
+ ret += " marine'</code> but does not match for <code>class='pastoral";\r
+ ret += " blue'</code>.</p>";\r
+ ret += " </div>";\r
+ ret += " <p class='note'><strong>Note:</strong> Because CSS gives considerable";\r
+ ret += " not.</p>";\r
+ ret += " <p class='note'><strong>Note:</strong> If an element has multiple";\r
+ ret += " this specification.</p>";\r
+ ret += " <h3><a name='id-selectors'>6.5. ID selectors</a></h3>";\r
+ ret += " <p>Document languages may contain attributes that are declared to be";\r
+ ret += " applies.</p>";\r
+ ret += " <p>An ID-typed attribute of a document language allows authors to";\r
+ ret += " ID selectors represent an element instance based on its identifier. An";\r
+ ret += " <code>#</code>) immediately followed by the ID value, which must be an";\r
+ ret += " identifier.</p>";\r
+ ret += " <p>Selectors does not specify how a UA knows the ID-typed attribute of";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <p>The following ID selector represents an <code>h1</code> element";\r
+ ret += " whose ID-typed attribute has the value 'chapter1':</p>";\r
+ ret += " <pre>h1#chapter1</pre>";\r
+ ret += " <p>The following ID selector represents any element whose ID-typed";\r
+ ret += " attribute has the value 'chapter1':</p>";\r
+ ret += " <pre>#chapter1</pre>";\r
+ ret += " <p>The following selector represents any element whose ID-typed";\r
+ ret += " attribute has the value 'z98y'.</p>";\r
+ ret += " <pre>*#z98y</pre>";\r
+ ret += " </div>";\r
+ ret += " <p class='note'><strong>Note.</strong> In XML 1.0 <a href='#refsXML10'>[XML10]</a>, the information about which attribute";\r
+ ret += " should use normal attribute selectors instead:";\r
+ ret += " <code>[name=p371]</code> instead of <code>#p371</code>. Elements in";\r
+ ret += " XML 1.0 documents without a DTD do not have IDs at all.</p>";\r
+ ret += " <p>If an element has multiple ID attributes, all of them must be";\r
+ ret += " DOM3 Core, XML DTDs, and namespace-specific knowledge.</p>";\r
+ ret += " <h3><a name='pseudo-classes'>6.6. Pseudo-classes</a></h3>";\r
+ ret += " <p>The pseudo-class concept is introduced to permit selection based on";\r
+ ret += " expressed using the other simple selectors.</p>";\r
+ ret += " <p>A pseudo-class always consists of a 'colon'";\r
+ ret += " (<code>:</code>) followed by the name of the pseudo-class and";\r
+ ret += " optionally by a value between parentheses.</p>";\r
+ ret += " <p>Pseudo-classes are allowed in all sequences of simple selectors";\r
+ ret += " sequences of simple selectors, after the leading type selector or";\r
+ ret += " document.</p>";\r
+ ret += " <h4><a name='dynamic-pseudos'>6.6.1. Dynamic pseudo-classes</a></h4>";\r
+ ret += " <p>Dynamic pseudo-classes classify elements on characteristics other";\r
+ ret += " that cannot be deduced from the document tree.</p>";\r
+ ret += " <p>Dynamic pseudo-classes do not appear in the document source or";\r
+ ret += " document tree.</p>";\r
+ ret += " <h5>The <a name='link'>link pseudo-classes: :link and :visited</a></h5>";\r
+ ret += " <p>User agents commonly display unvisited links differently from";\r
+ ret += " previously visited ones. Selectors";\r
+ ret += " provides the pseudo-classes <code>:link</code> and";\r
+ ret += " <code>:visited</code> to distinguish them:</p>";\r
+ ret += " <ul>";\r
+ ret += " <li>The <code>:link</code> pseudo-class applies to links that have";\r
+ ret += " </li>";\r
+ ret += " <li>The <code>:visited</code> pseudo-class applies once the link has";\r
+ ret += " </li>";\r
+ ret += " </ul>";\r
+ ret += " <p>After some amount of time, user agents may choose to return a";\r
+ ret += " visited link to the (unvisited) ':link' state.</p>";\r
+ ret += " <p>The two states are mutually exclusive.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Example:</p>";\r
+ ret += " <p>The following selector represents links carrying class";\r
+ ret += " <code>external</code> and already visited:</p>";\r
+ ret += " <pre>a.external:visited</pre>";\r
+ ret += " </div>";\r
+ ret += " <p class='note'><strong>Note:</strong> It is possible for style sheet";\r
+ ret += " </p><p>UAs may therefore treat all links as unvisited links, or implement";\r
+ ret += " and unvisited links differently.</p>";\r
+ ret += " <h5>The <a name='useraction-pseudos'>user action pseudo-classes";\r
+ ret += " :hover, :active, and :focus</a></h5>";\r
+ ret += " <p>Interactive user agents sometimes change the rendering in response";\r
+ ret += " to user actions. Selectors provides";\r
+ ret += " acting on.</p>";\r
+ ret += " <ul>";\r
+ ret += " <li>The <code>:hover</code> pseudo-class applies while the user";\r
+ ret += " element. User agents not that do not support <a href='http://www.w3.org/TR/REC-CSS2/media.html#interactive-media-group'>interactive";\r
+ ret += " media</a> do not have to support this pseudo-class. Some conforming";\r
+ ret += " user agents that support <a href='http://www.w3.org/TR/REC-CSS2/media.html#interactive-media-group'>interactive";\r
+ ret += " media</a> may not be able to support this pseudo-class (e.g., a pen";\r
+ ret += " </li>";\r
+ ret += " <li>The <code>:active</code> pseudo-class applies while an element";\r
+ ret += " </li>";\r
+ ret += " <li>The <code>:focus</code> pseudo-class applies while an element";\r
+ ret += " </li>";\r
+ ret += " </ul>";\r
+ ret += " <p>There may be document language or implementation specific limits on";\r
+ ret += " which elements can become <code>:active</code> or acquire";\r
+ ret += " <code>:focus</code>.</p>";\r
+ ret += " <p>These pseudo-classes are not mutually exclusive. An element may";\r
+ ret += " match several pseudo-classes at the same time.</p>";\r
+ ret += " <p>Selectors doesn't define if the parent of an element that is";\r
+ ret += " ':active' or ':hover' is also in that state.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <pre>a:link /* unvisited links */";\r
+ ret += " a:active /* active links */</pre>";\r
+ ret += " <p>An example of combining dynamic pseudo-classes:</p>";\r
+ ret += " <pre>a:focus";\r
+ ret += " a:focus:hover</pre>";\r
+ ret += " <p>The last selector matches <code>a</code> elements that are in";\r
+ ret += " the pseudo-class :focus and in the pseudo-class :hover.</p>";\r
+ ret += " </div>";\r
+ ret += " <p class='note'><strong>Note:</strong> An element can be both ':visited'";\r
+ ret += " and ':active' (or ':link' and ':active').</p>";\r
+ ret += " <h4><a name='target-pseudo'>6.6.2. The target pseudo-class :target</a></h4>";\r
+ ret += " <p>Some URIs refer to a location within a resource. This kind of URI";\r
+ ret += " identifier (called the fragment identifier).</p>";\r
+ ret += " <p>URIs with fragment identifiers link to a certain element within the";\r
+ ret += " pointing to an anchor named <code>section_2</code> in an HTML";\r
+ ret += " document:</p>";\r
+ ret += " <pre>http://example.com/html/top.html#section_2</pre>";\r
+ ret += " <p>A target element can be represented by the <code>:target</code>";\r
+ ret += " the document has no target element.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Example:</p>";\r
+ ret += " <pre>p.note:target</pre>";\r
+ ret += " <p>This selector represents a <code>p</code> element of class";\r
+ ret += " <code>note</code> that is the target element of the referring";\r
+ ret += " URI.</p>";\r
+ ret += " </div>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>CSS example:</p>";\r
+ ret += " <p>Here, the <code>:target</code> pseudo-class is used to make the";\r
+ ret += " target element red and place an image before it, if there is one:</p>";\r
+ ret += " <pre>*:target { color : red }";\r
+ ret += " *:target::before { content : url(target.png) }</pre>";\r
+ ret += " </div>";\r
+ ret += " <h4><a name='lang-pseudo'>6.6.3. The language pseudo-class :lang</a></h4>";\r
+ ret += " <p>If the document language specifies how the human language of an";\r
+ ret += " element is determined, it is possible to write selectors that";\r
+ ret += " represent an element based on its language. For example, in HTML <a href='#refsHTML4'>[HTML4]</a>, the language is determined by a";\r
+ ret += " combination of the <code>lang</code> attribute, the <code>meta</code>";\r
+ ret += " headers). XML uses an attribute called <code>xml:lang</code>, and";\r
+ ret += " the language.</p>";\r
+ ret += " <p>The pseudo-class <code>:lang(C)</code> represents an element that";\r
+ ret += " <code>:lang()</code> selector is based solely on the identifier C";\r
+ ret += " element's language value, in the same way as if performed by the <a href='#attribute-representation'>'|='</a> operator in attribute";\r
+ ret += " selectors. The identifier C does not have to be a valid language";\r
+ ret += " name.</p>";\r
+ ret += " <p>C must not be empty. (If it is, the selector is invalid.)</p>";\r
+ ret += " <p class='note'><strong>Note:</strong> It is recommended that";\r
+ ret += " documents and protocols indicate language using codes from RFC 3066 <a href='#refsRFC3066'>[RFC3066]</a> or its successor, and by means of";\r
+ 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'>";\r
+ ret += " 'FAQ: Two-letter or three-letter language codes.'</a></p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <p>The two following selectors represent an HTML document that is in";\r
+ ret += " Belgian, French, or German. The two next selectors represent";\r
+ ret += " <code>q</code> quotations in an arbitrary element in Belgian, French,";\r
+ ret += " or German.</p>";\r
+ ret += " <pre>html:lang(fr-be)";\r
+ ret += " :lang(de) > q</pre>";\r
+ ret += " </div>";\r
+ ret += " <h4><a name='UIstates'>6.6.4. The UI element states pseudo-classes</a></h4>";\r
+ ret += " <h5><a name='enableddisabled'>The :enabled and :disabled pseudo-classes</a></h5>";\r
+ ret += " <p>The <code>:enabled</code> pseudo-class allows authors to customize";\r
+ ret += " an enabled <code>input</code> element without also specifying what it";\r
+ ret += " would look like when it was disabled.</p>";\r
+ ret += " <p>Similar to <code>:enabled</code>, <code>:disabled</code> allows the";\r
+ ret += " element should look.</p>";\r
+ ret += " <p>Most elements will be neither enabled nor disabled. An element is";\r
+ ret += " presently activate it or transfer focus to it.</p>";\r
+ ret += " <h5><a name='checked'>The :checked pseudo-class</a></h5>";\r
+ ret += " <p>Radio and checkbox elements can be toggled by the user. Some menu";\r
+ ret += " toggled 'on' the <code>:checked</code> pseudo-class applies. The";\r
+ ret += " <code>:checked</code> pseudo-class initially applies to such elements";\r
+ ret += " that have the HTML4 <code>selected</code> and <code>checked</code>";\r
+ ret += " attributes as described in <a href='http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.2.1'>Section";\r
+ ret += " 17.2.1 of HTML4</a>, but of course the user can toggle 'off' such";\r
+ ret += " elements in which case the <code>:checked</code> pseudo-class would no";\r
+ ret += " longer apply. While the <code>:checked</code> pseudo-class is dynamic";\r
+ ret += " on the presence of the semantic HTML4 <code>selected</code> and";\r
+ ret += " <code>checked</code> attributes, it applies to all media.";\r
+ ret += " </p><h5><a name='indeterminate'>The :indeterminate pseudo-class</a></h5>";\r
+ ret += " <div class='note'>";\r
+ ret += " <p>Radio and checkbox elements can be toggled by the user, but are";\r
+ ret += " This can be due to an element attribute, or DOM manipulation.</p>";\r
+ ret += " <p>A future version of this specification may introduce an";\r
+ ret += " <code>:indeterminate</code> pseudo-class that applies to such elements.";\r
+ ret += " <!--While the <code>:indeterminate</code> pseudo-class is dynamic in";\r
+ ret += " the presence of an element attribute, it applies to all media.</p>";\r
+ ret += " <p>Components of a radio-group initialized with no pre-selected choice";\r
+ ret += " are an example of :indeterminate state.--></p>";\r
+ ret += " </div>";\r
+ ret += " <h4><a name='structural-pseudos'>6.6.5. Structural pseudo-classes</a></h4>";\r
+ ret += " <p>Selectors introduces the concept of <dfn>structural";\r
+ ret += " pseudo-classes</dfn> to permit selection based on extra information that";\r
+ ret += " the document tree but cannot be represented by other simple selectors or";\r
+ ret += " </p><p>Note that standalone pieces of PCDATA (text nodes in the DOM) are";\r
+ ret += " </p><h5><a name='root-pseudo'>:root pseudo-class</a></h5>";\r
+ ret += " <p>The <code>:root</code> pseudo-class represents an element that is";\r
+ ret += " <code>HTML</code> element.";\r
+ ret += " </p><h5><a name='nth-child-pseudo'>:nth-child() pseudo-class</a></h5>";\r
+ ret += " <p>The";\r
+ ret += " <code>:nth-child(<var>a</var><code>n</code>+<var>b</var>)</code>";\r
+ ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings";\r
+ ret += " <strong>before</strong> it in the document tree, for a given positive";\r
+ ret += " integer or zero value of <code>n</code>, and has a parent element. In";\r
+ ret += " other words, this matches the <var>b</var>th child of an element after";\r
+ ret += " all the children have been split into groups of <var>a</var> elements";\r
+ ret += " each. For example, this allows the selectors to address every other";\r
+ ret += " of paragraph text in a cycle of four. The <var>a</var> and";\r
+ ret += " <var>b</var> values must be zero, negative integers or positive";\r
+ ret += " </p><p>In addition to this, <code>:nth-child()</code> can take";\r
+ ret += " '<code>odd</code>' and '<code>even</code>' as arguments instead.";\r
+ ret += " '<code>odd</code>' has the same signification as <code>2n+1</code>,";\r
+ ret += " and '<code>even</code>' has the same signification as <code>2n</code>.";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <pre>tr:nth-child(2n+1) /* represents every odd row of an HTML table */";\r
+ ret += " p:nth-child(4n+4) { color: purple; }</pre>";\r
+ ret += " </div>";\r
+ ret += " <p>When <var>a</var>=0, no repeating is used, so for example";\r
+ ret += " <code>:nth-child(0n+5)</code> matches only the fifth child. When";\r
+ ret += " <var>a</var>=0, the <var>a</var><code>n</code> part need not be";\r
+ ret += " <code>:nth-child(<var>b</var>)</code> and the last example simplifies";\r
+ ret += " to <code>:nth-child(5)</code>.";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <pre>foo:nth-child(0n+1) /* represents an element foo, first child of its parent element */";\r
+ ret += " foo:nth-child(1) /* same */</pre>";\r
+ ret += " </div>";\r
+ ret += " <p>When <var>a</var>=1, the number may be omitted from the rule.";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <p>The following selectors are therefore equivalent:</p>";\r
+ ret += " <pre>bar:nth-child(1n+0) /* represents all bar elements, specificity (0,1,1) */";\r
+ ret += " bar /* same but lower specificity (0,0,1) */</pre>";\r
+ ret += " </div>";\r
+ ret += " <p>If <var>b</var>=0, then every <var>a</var>th element is picked. In";\r
+ ret += " such a case, the <var>b</var> part may be omitted.";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <pre>tr:nth-child(2n+0) /* represents every even row of an HTML table */";\r
+ ret += " tr:nth-child(2n) /* same */</pre>";\r
+ ret += " </div>";\r
+ ret += " <p>If both <var>a</var> and <var>b</var> are equal to zero, the";\r
+ ret += " pseudo-class represents no element in the document tree.</p>";\r
+ ret += " <p>The value <var>a</var> can be negative, but only the positive";\r
+ ret += " values of <var>a</var><code>n</code>+<var>b</var>, for";\r
+ ret += " <code>n</code>≥0, may represent an element in the document";\r
+ ret += " tree.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Example:</p>";\r
+ ret += " <pre>html|tr:nth-child(-n+6) /* represents the 6 first rows of XHTML tables */</pre>";\r
+ ret += " </div>";\r
+ ret += " <p>When the value <var>b</var> is negative, the '+' character in the";\r
+ ret += " character indicating the negative value of <var>b</var>).</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <pre>:nth-child(10n-1) /* represents the 9th, 19th, 29th, etc, element */";\r
+ ret += " :nth-child(10n+-1) /* Syntactically invalid, and would be ignored */</pre>";\r
+ ret += " </div>";\r
+ ret += " <h5><a name='nth-last-child-pseudo'>:nth-last-child() pseudo-class</a></h5>";\r
+ ret += " <p>The <code>:nth-last-child(<var>a</var>n+<var>b</var>)</code>";\r
+ ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings";\r
+ ret += " <strong>after</strong> it in the document tree, for a given positive";\r
+ ret += " integer or zero value of <code>n</code>, and has a parent element. See";\r
+ ret += " <code>:nth-child()</code> pseudo-class for the syntax of its argument.";\r
+ ret += " It also accepts the '<code>even</code>' and '<code>odd</code>' values";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <pre>tr:nth-last-child(-n+2) /* represents the two last rows of an HTML table */";\r
+ ret += " counting from the last one */</pre>";\r
+ ret += " </div>";\r
+ ret += " <h5><a name='nth-of-type-pseudo'>:nth-of-type() pseudo-class</a></h5>";\r
+ ret += " <p>The <code>:nth-of-type(<var>a</var>n+<var>b</var>)</code>";\r
+ ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings with the same";\r
+ ret += " element name <strong>before</strong> it in the document tree, for a";\r
+ ret += " given zero or positive integer value of <code>n</code>, and has a";\r
+ ret += " parent element. In other words, this matches the <var>b</var>th child";\r
+ ret += " groups of a elements each. See <code>:nth-child()</code> pseudo-class";\r
+ ret += " '<code>even</code>' and '<code>odd</code>' values.";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>CSS example:</p>";\r
+ ret += " <p>This allows an author to alternate the position of floated images:</p>";\r
+ ret += " <pre>img:nth-of-type(2n+1) { float: right; }";\r
+ ret += " img:nth-of-type(2n) { float: left; }</pre>";\r
+ ret += " </div>";\r
+ ret += " <h5><a name='nth-last-of-type-pseudo'>:nth-last-of-type() pseudo-class</a></h5>";\r
+ ret += " <p>The <code>:nth-last-of-type(<var>a</var>n+<var>b</var>)</code>";\r
+ ret += " <var>a</var><code>n</code>+<var>b</var>-1 siblings with the same";\r
+ ret += " element name <strong>after</strong> it in the document tree, for a";\r
+ ret += " given zero or positive integer value of <code>n</code>, and has a";\r
+ ret += " parent element. See <code>:nth-child()</code> pseudo-class for the";\r
+ ret += " syntax of its argument. It also accepts the '<code>even</code>' and '<code>odd</code>'";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>Example:</p>";\r
+ ret += " <p>To represent all <code>h2</code> children of an XHTML";\r
+ ret += " <code>body</code> except the first and last, one could use the";\r
+ ret += " following selector:</p>";\r
+ ret += " <pre>body > h2:nth-of-type(n+2):nth-last-of-type(n+2)</pre>";\r
+ ret += " <p>In this case, one could also use <code>:not()</code>, although the";\r
+ ret += " selector ends up being just as long:</p>";\r
+ ret += " <pre>body > h2:not(:first-of-type):not(:last-of-type)</pre>";\r
+ ret += " </div>";\r
+ ret += " <h5><a name='first-child-pseudo'>:first-child pseudo-class</a></h5>";\r
+ ret += " <p>Same as <code>:nth-child(1)</code>. The <code>:first-child</code>";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <p>The following selector represents a <code>p</code> element that is";\r
+ ret += " the first child of a <code>div</code> element:</p>";\r
+ ret += " <pre>div > p:first-child</pre>";\r
+ ret += " <p>This selector can represent the <code>p</code> inside the";\r
+ ret += " <code>div</code> of the following fragment:</p>";\r
+ ret += " <pre><p> The last P before the note.</p>";\r
+ ret += " </div></pre>";\r
+ ret += " but cannot represent the second <code>p</code> in the following";\r
+ ret += " <pre><p> The last P before the note.</p>";\r
+ ret += " </div></pre>";\r
+ ret += " <p>The following two selectors are usually equivalent:</p>";\r
+ ret += " <pre>* > a:first-child /* a is first child of any element */";\r
+ ret += " a:first-child /* Same (assuming a is not the root element) */</pre>";\r
+ ret += " </div>";\r
+ ret += " <h5><a name='last-child-pseudo'>:last-child pseudo-class</a></h5>";\r
+ ret += " <p>Same as <code>:nth-last-child(1)</code>. The <code>:last-child</code>";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>Example:</p>";\r
+ ret += " <p>The following selector represents a list item <code>li</code> that";\r
+ ret += " is the last child of an ordered list <code>ol</code>.";\r
+ ret += " </p><pre>ol > li:last-child</pre>";\r
+ ret += " </div>";\r
+ ret += " <h5><a name='first-of-type-pseudo'>:first-of-type pseudo-class</a></h5>";\r
+ ret += " <p>Same as <code>:nth-of-type(1)</code>. The <code>:first-of-type</code>";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>Example:</p>";\r
+ ret += " <p>The following selector represents a definition title";\r
+ ret += " <code>dt</code> inside a definition list <code>dl</code>, this";\r
+ ret += " <code>dt</code> being the first of its type in the list of children of";\r
+ ret += " its parent element.</p>";\r
+ ret += " <pre>dl dt:first-of-type</pre>";\r
+ ret += " <p>It is a valid description for the first two <code>dt</code>";\r
+ ret += " elements in the following example but not for the third one:</p>";\r
+ ret += " <pre><dl>";\r
+ ret += " </dl></pre>";\r
+ ret += " </div>";\r
+ ret += " <h5><a name='last-of-type-pseudo'>:last-of-type pseudo-class</a></h5>";\r
+ ret += " <p>Same as <code>:nth-last-of-type(1)</code>. The";\r
+ ret += " <code>:last-of-type</code> pseudo-class represents an element that is";\r
+ ret += " element.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Example:</p>";\r
+ ret += " <p>The following selector represents the last data cell";\r
+ ret += " <code>td</code> of a table row.</p>";\r
+ ret += " <pre>tr > td:last-of-type</pre>";\r
+ ret += " </div>";\r
+ ret += " <h5><a name='only-child-pseudo'>:only-child pseudo-class</a></h5>";\r
+ ret += " <p>Represents an element that has a parent element and whose parent";\r
+ ret += " <code>:first-child:last-child</code> or";\r
+ ret += " <code>:nth-child(1):nth-last-child(1)</code>, but with a lower";\r
+ ret += " specificity.</p>";\r
+ ret += " <h5><a name='only-of-type-pseudo'>:only-of-type pseudo-class</a></h5>";\r
+ ret += " <p>Represents an element that has a parent element and whose parent";\r
+ ret += " as <code>:first-of-type:last-of-type</code> or";\r
+ ret += " <code>:nth-of-type(1):nth-last-of-type(1)</code>, but with a lower";\r
+ ret += " specificity.</p>";\r
+ ret += " <h5><a name='empty-pseudo'></a>:empty pseudo-class</h5>";\r
+ ret += " <p>The <code>:empty</code> pseudo-class represents an element that has";\r
+ ret += " empty or not.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <p><code>p:empty</code> is a valid representation of the following fragment:";\r
+ ret += " </p>";\r
+ ret += " <pre><p></p></pre>";\r
+ ret += " <p><code>foo:empty</code> is not a valid representation for the";\r
+ ret += " following fragments:</p>";\r
+ ret += " <pre><foo>bar</foo></pre>";\r
+ ret += " <pre><foo><bar>bla</bar></foo></pre>";\r
+ ret += " <pre><foo>this is not <bar>:empty</bar></foo></pre>";\r
+ ret += " </div>";\r
+ ret += " <h4><a name='content-selectors'>6.6.6. Blank</a></h4>";\r
+ ret += " <!-- It's the Return of Appendix H!!! Run away! -->";\r
+ ret += " <p>This section intentionally left blank.</p>";\r
+ ret += " <!-- (used to be :contains()) -->";\r
+ ret += " <h4><a name='negation'></a>6.6.7. The negation pseudo-class</h4>";\r
+ ret += " <p>The negation pseudo-class, <code>:not(<var>X</var>)</code>, is a";\r
+ ret += " functional notation taking a <a href='#simple-selectors-dfn'>simple";\r
+ ret += " selector</a> (excluding the negation pseudo-class itself and";\r
+ ret += " <!-- pseudo-elements are not simple selectors, so the above paragraph";\r
+ ret += " may be a bit confusing -->";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <p>The following CSS selector matches all <code>button</code>";\r
+ ret += " elements in an HTML document that are not disabled.</p>";\r
+ ret += " <pre>button:not([DISABLED])</pre>";\r
+ ret += " <p>The following selector represents all but <code>FOO</code>";\r
+ ret += " elements.</p>";\r
+ ret += " <pre>*:not(FOO)</pre>";\r
+ ret += " <p>The following group of selectors represents all HTML elements";\r
+ ret += " except links.</p>";\r
+ ret += " <pre>html|*:not(:link):not(:visited)</pre>";\r
+ ret += " </div>";\r
+ ret += " <p>Default namespace declarations do not affect the argument of the";\r
+ ret += " type selector.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <p>Assuming that the default namespace is bound to";\r
+ ret += " elements that are not in that namespace:</p>";\r
+ ret += " <pre>*|*:not(*)</pre>";\r
+ ret += " <p>The following CSS selector matches any element being hovered,";\r
+ ret += " rule when they <em>are</em> being hovered.</p>";\r
+ ret += " <pre>*|*:not(:hover)</pre>";\r
+ ret += " </div>";\r
+ ret += " <p class='note'><strong>Note</strong>: the :not() pseudo allows";\r
+ ret += " useless selectors to be written. For instance <code>:not(*|*)</code>,";\r
+ ret += " which represents no element at all, or <code>foo:not(bar)</code>,";\r
+ ret += " which is equivalent to <code>foo</code> but with a higher";\r
+ ret += " specificity.</p>";\r
+ ret += " <h3><a name='pseudo-elements'>7. Pseudo-elements</a></h3>";\r
+ ret += " <p>Pseudo-elements create abstractions about the document tree beyond";\r
+ ret += " source document (e.g., the <code>::before</code> and";\r
+ ret += " <code>::after</code> pseudo-elements give access to generated";\r
+ ret += " content).</p>";\r
+ ret += " <p>A pseudo-element is made of two colons (<code>::</code>) followed";\r
+ ret += " by the name of the pseudo-element.</p>";\r
+ ret += " <p>This <code>::</code> notation is introduced by the current document";\r
+ ret += " <code>:first-line</code>, <code>:first-letter</code>,";\r
+ ret += " <code>:before</code> and <code>:after</code>). This compatibility is";\r
+ ret += " not allowed for the new pseudo-elements introduced in CSS level 3.</p>";\r
+ ret += " <p>Only one pseudo-element may appear per selector, and if present it";\r
+ ret += " must appear after the sequence of simple selectors that represents the";\r
+ ret += " <a href='#subject'>subjects</a> of the selector. <span class='note'>A";\r
+ ret += " pesudo-elements per selector.</span></p>";\r
+ ret += " <h4><a name='first-line'>7.1. The ::first-line pseudo-element</a></h4>";\r
+ ret += " <p>The <code>::first-line</code> pseudo-element describes the contents";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>CSS example:</p>";\r
+ ret += " <pre>p::first-line { text-transform: uppercase }</pre>";\r
+ ret += " <p>The above rule means 'change the letters of the first line of every";\r
+ ret += " paragraph to uppercase'.</p>";\r
+ ret += " </div>";\r
+ ret += " <p>The selector <code>p::first-line</code> does not match any real";\r
+ ret += " agents will insert at the beginning of every paragraph.</p>";\r
+ ret += " <p>Note that the length of the first line depends on a number of";\r
+ ret += " an ordinary HTML paragraph such as:</p>";\r
+ ret += " <pre> <P>This is a somewhat long HTML ";\r
+ ret += " </pre>";\r
+ ret += " <p>the lines of which happen to be broken as follows:";\r
+ ret += " </p><pre> THIS IS A SOMEWHAT LONG HTML PARAGRAPH THAT";\r
+ ret += " </pre>";\r
+ ret += " <p>This paragraph might be 'rewritten' by user agents to include the";\r
+ ret += " <em>fictional tag sequence</em> for <code>::first-line</code>. This";\r
+ ret += " fictional tag sequence helps to show how properties are inherited.</p>";\r
+ ret += " <pre> <P><b><P::first-line></b> This is a somewhat long HTML ";\r
+ ret += " paragraph that <b></P::first-line></b> will be broken into several";\r
+ ret += " </pre>";\r
+ ret += " <p>If a pseudo-element breaks up a real element, the desired effect";\r
+ ret += " with a <code>span</code> element:</p>";\r
+ ret += " <pre> <P><b><SPAN class='test'></b> This is a somewhat long HTML";\r
+ ret += " lines.<b></SPAN></b> The first line will be identified";\r
+ ret += " </pre>";\r
+ ret += " <p>the user agent could simulate start and end tags for";\r
+ ret += " <code>span</code> when inserting the fictional tag sequence for";\r
+ ret += " <code>::first-line</code>.";\r
+ ret += " </p><pre> <P><P::first-line><b><SPAN class='test'></b> This is a";\r
+ ret += " paragraph that will <b></SPAN></b></P::first-line><b><SPAN";\r
+ ret += " class='test'></b> be";\r
+ ret += " lines.<b></SPAN></b> The first line will be identified";\r
+ ret += " </pre>";\r
+ ret += " <p>In CSS, the <code>::first-line</code> pseudo-element can only be";\r
+ ret += " or a table-cell.</p>";\r
+ ret += " <p><a name='first-formatted-line'></a>The 'first formatted line' of an";\r
+ ret += " line of the <code>div</code> in <code><DIV><P>This";\r
+ ret += " line...</P></DIV></code> is the first line of the <code>p</code>";\r
+ ret += " that both <code>p</code> and <code>div</code> are block-level).";\r
+ ret += " </p><p>The first line of a table-cell or inline-block cannot be the first";\r
+ ret += " formatted line of an ancestor element. Thus, in <code><DIV><P";\r
+ ret += " etcetera</DIV></code> the first formatted line of the";\r
+ ret += " <code>div</code> is not the line 'Hello'.";\r
+ ret += " </p><p class='note'>Note that the first line of the <code>p</code> in this";\r
+ ret += " fragment: <code><p><br>First...</code> doesn't contain any";\r
+ ret += " letters (assuming the default style for <code>br</code> in HTML";\r
+ ret += " </p><p>A UA should act as if the fictional start tags of the";\r
+ ret += " <code>::first-line</code> pseudo-elements were nested just inside the";\r
+ ret += " is an example. The fictional tag sequence for</p>";\r
+ ret += " <pre> <DIV>";\r
+ ret += " </pre>";\r
+ ret += " <p>is</p>";\r
+ ret += " <pre> <DIV>";\r
+ ret += " </pre>";\r
+ ret += " <p>The <code>::first-line</code> pseudo-element is similar to an";\r
+ ret += " following properties apply to a <code>::first-line</code>";\r
+ ret += " properties as well.</p>";\r
+ ret += " <h4><a name='first-letter'>7.2. The ::first-letter pseudo-element</a></h4>";\r
+ ret += " <p>The <code>::first-letter</code> pseudo-element represents the first";\r
+ ret += " is 'none'; otherwise, it is similar to a floated element.</p>";\r
+ ret += " <p>In CSS, these are the properties that apply to <code>::first-letter</code>";\r
+ ret += " of the letter, unlike for normal elements.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Example:</p>";\r
+ ret += " <p>This example shows a possible rendering of an initial cap. Note";\r
+ ret += " <code>::first-letter</code>";\r
+ ret += " fictional start tag of the first letter is inside the <span>span</span>,";\r
+ ret += " the font weight of the first letter is normal, not bold as the <span>span</span>:";\r
+ ret += " </p><pre> p { line-height: 1.1 }";\r
+ ret += " </pre>";\r
+ ret += " <div class='figure'>";\r
+ ret += " <p><img src='' alt='Image illustrating the ::first-letter pseudo-element'>";\r
+ ret += " </p></div>";\r
+ ret += " </div>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>The following CSS will make a drop cap initial letter span about two";\r
+ ret += " lines:</p>";\r
+ ret += " <pre> <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN'>";\r
+ ret += " </pre>";\r
+ ret += " <p>This example might be formatted as follows:</p>";\r
+ ret += " <div class='figure'>";\r
+ ret += " <p><img src='' alt='Image illustrating the combined effect of the ::first-letter and ::first-line pseudo-elements'>";\r
+ ret += " </p>";\r
+ ret += " </div>";\r
+ ret += " <p>The <span class='index-inst' title='fictional tag";\r
+ ret += " sequence'>fictional tag sequence</span> is:</p>";\r
+ ret += " <pre> <P>";\r
+ ret += " </pre>";\r
+ ret += " <p>Note that the <code>::first-letter</code> pseudo-element tags abut";\r
+ ret += " block element.</p></div>";\r
+ ret += " <p>In order to achieve traditional drop caps formatting, user agents";\r
+ ret += " glyph outline may be taken into account when formatting.</p>";\r
+ ret += " <p>Punctuation (i.e, characters defined in Unicode in the 'open' (Ps),";\r
+ ret += " be included. <a href='#refsUNICODE'>[UNICODE]</a></p>";\r
+ ret += " <div class='figure'>";\r
+ ret += " <p><img src='' alt='Quotes that precede the";\r
+ ret += " first letter should be included.'></p>";\r
+ ret += " </div>";\r
+ ret += " <p>The <code>::first-letter</code> also applies if the first letter is";\r
+ ret += " money.'</p>";\r
+ ret += " <p>In CSS, the <code>::first-letter</code> pseudo-element applies to";\r
+ ret += " elements. <span class='note'>A future version of this specification";\r
+ ret += " types.</span></p>";\r
+ ret += " <p>The <code>::first-letter</code> pseudo-element can be used with all";\r
+ ret += " the element, even if that first text is in a descendant.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Example:</p>";\r
+ ret += " <p>The fictional tag sequence for this HTMLfragment:";\r
+ ret += " </p><pre><div>";\r
+ ret += " <p>The first text.</pre>";\r
+ ret += " <p>is:";\r
+ ret += " </p><pre><div>";\r
+ ret += " <p><div::first-letter><p::first-letter>T</...></...>he first text.</pre>";\r
+ ret += " </div>";\r
+ ret += " <p>The first letter of a table-cell or inline-block cannot be the";\r
+ ret += " first letter of an ancestor element. Thus, in <code><DIV><P";\r
+ ret += " etcetera</DIV></code> the first letter of the <code>div</code> is";\r
+ ret += " letter 'H'. In fact, the <code>div</code> doesn't have a first letter.";\r
+ ret += " </p><p>The first letter must occur on the <a href='#first-formatted-line'>first formatted line.</a> For example, in";\r
+ ret += " this fragment: <code><p><br>First...</code> the first line";\r
+ ret += " doesn't contain any letters and <code>::first-letter</code> doesn't";\r
+ ret += " match anything (assuming the default style for <code>br</code> in HTML";\r
+ ret += " </p><p>In CSS, if an element is a list item ('display: list-item'), the";\r
+ ret += " <code>::first-letter</code> applies to the first letter in the";\r
+ ret += " <code>::first-letter</code> on list items with 'list-style-position:";\r
+ ret += " inside'. If an element has <code>::before</code> or";\r
+ ret += " <code>::after</code> content, the <code>::first-letter</code> applies";\r
+ ret += " to the first letter of the element <em>including</em> that content.";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>Example:</p>";\r
+ ret += " <p>After the rule 'p::before {content: 'Note: '}', the selector";\r
+ ret += " 'p::first-letter' matches the 'N' of 'Note'.</p>";\r
+ ret += " </div>";\r
+ ret += " <p>Some languages may have specific rules about how to treat certain";\r
+ ret += " considered within the <code>::first-letter</code> pseudo-element.";\r
+ ret += " </p><p>If the letters that would form the ::first-letter are not in the";\r
+ ret += " same element, such as ''T' in <code><p>'<em>T...</code>, the UA";\r
+ ret += " both elements, or simply not create a pseudo-element.</p>";\r
+ ret += " <p>Similarly, if the first letter(s) of the block are not at the start";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>Example:</p>";\r
+ ret += " <p><a name='overlapping-example'>The following example</a> illustrates";\r
+ ret += " paragraph will be 'red'.</p>";\r
+ ret += " <pre>p { color: red; font-size: 12pt }";\r
+ ret += " <P>Some text that ends up on two lines</P></pre>";\r
+ ret += " <p>Assuming that a line break will occur before the word 'ends', the";\r
+ ret += " <span class='index-inst' title='fictional tag sequence'>fictional tag";\r
+ ret += " sequence</span> for this fragment might be:</p>";\r
+ ret += " <pre><P>";\r
+ ret += " </P></pre>";\r
+ ret += " <p>Note that the <code>::first-letter</code> element is inside the <code>::first-line</code>";\r
+ ret += " element. Properties set on <code>::first-line</code> are inherited by";\r
+ ret += " <code>::first-letter</code>, but are overridden if the same property is";\r
+ ret += " <code>::first-letter</code>.</p>";\r
+ ret += " </div>";\r
+ ret += " <h4><a name='UIfragments'>7.3.</a> <a name='selection'>The ::selection";\r
+ ret += " pseudo-element</a></h4>";\r
+ ret += " <p>The <code>::selection</code> pseudo-element applies to the portion";\r
+ ret += " field. This pseudo-element should not be confused with the <code><a href='#checked'>:checked</a></code> pseudo-class (which used to be";\r
+ ret += " named <code>:selected</code>)";\r
+ ret += " </p><p>Although the <code>::selection</code> pseudo-element is dynamic in";\r
+ ret += " <a href='#refsCSS21'>[CSS21]</a>) which was originally rendered to a";\r
+ ret += " <code>::selection</code> state to that other medium, and have all the";\r
+ ret += " required — UAs may omit the <code>::selection</code>";\r
+ ret += " </p><p>These are the CSS properties that apply to <code>::selection</code>";\r
+ ret += " <code>::selection</code> may be ignored.";\r
+ ret += " </p><h4><a name='gen-content'>7.4. The ::before and ::after pseudo-elements</a></h4>";\r
+ ret += " <p>The <code>::before</code> and <code>::after</code> pseudo-elements";\r
+ ret += " content. They are explained in CSS 2.1 <a href='#refsCSS21'>[CSS21]</a>.</p>";\r
+ ret += " <p>When the <code>::first-letter</code> and <code>::first-line</code>";\r
+ ret += " pseudo-elements are combined with <code>::before</code> and";\r
+ ret += " <code>::after</code>, they apply to the first letter or line of the";\r
+ ret += " element including the inserted text.</p>";\r
+ ret += " <h2><a name='combinators'>8. Combinators</a></h2>";\r
+ ret += " <h3><a name='descendant-combinators'>8.1. Descendant combinator</a></h3>";\r
+ ret += " <p>At times, authors may want selectors to describe an element that is";\r
+ ret += " <code>EM</code> element that is contained within an <code>H1</code>";\r
+ ret += " descendant combinator is <a href='#whitespace'>white space</a> that";\r
+ ret += " separates two sequences of simple selectors. A selector of the form";\r
+ ret += " '<code>A B</code>' represents an element <code>B</code> that is an";\r
+ ret += " arbitrary descendant of some ancestor element <code>A</code>.";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <p>For example, consider the following selector:</p>";\r
+ ret += " <pre>h1 em</pre>";\r
+ ret += " <p>It represents an <code>em</code> element being the descendant of";\r
+ ret += " an <code>h1</code> element. It is a correct and valid, but partial,";\r
+ ret += " description of the following fragment:</p>";\r
+ ret += " <pre><h1>This <span class='myclass'>headline";\r
+ ret += " is <em>very</em> important</span></h1></pre>";\r
+ ret += " <p>The following selector:</p>";\r
+ ret += " <pre>div * p</pre>";\r
+ ret += " <p>represents a <code>p</code> element that is a grandchild or later";\r
+ ret += " descendant of a <code>div</code> element. Note the whitespace on";\r
+ ret += " of the P.</p>";\r
+ ret += " <p>The following selector, which combines descendant combinators and";\r
+ ret += " <a href='#attribute-selectors'>attribute selectors</a>, represents an";\r
+ ret += " element that (1) has the <code>href</code> attribute set and (2) is";\r
+ ret += " inside a <code>p</code> that is itself inside a <code>div</code>:</p>";\r
+ ret += " <pre>div p *[href]</pre>";\r
+ ret += " </div>";\r
+ ret += " <h3><a name='child-combinators'>8.2. Child combinators</a></h3>";\r
+ ret += " <p>A <dfn>child combinator</dfn> describes a childhood relationship";\r
+ ret += " 'greater-than sign' (<code>></code>) character and";\r
+ ret += " separates two sequences of simple selectors.";\r
+ ret += " </p><div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <p>The following selector represents a <code>p</code> element that is";\r
+ ret += " child of <code>body</code>:</p>";\r
+ ret += " <pre>body > p</pre>";\r
+ ret += " <p>The following example combines descendant combinators and child";\r
+ ret += " combinators.</p>";\r
+ ret += " <pre>div ol>li p</pre>";\r
+ ret += " <!-- LEAVE THOSE SPACES OUT! see below -->";\r
+ ret += " <p>It represents a <code>p</code> element that is a descendant of an";\r
+ ret += " <code>li</code> element; the <code>li</code> element must be the";\r
+ ret += " child of an <code>ol</code> element; the <code>ol</code> element must";\r
+ ret += " be a descendant of a <code>div</code>. Notice that the optional white";\r
+ ret += " space around the '>' combinator has been left out.</p>";\r
+ ret += " </div>";\r
+ ret += " <p>For information on selecting the first child of an element, please";\r
+ ret += " see the section on the <code><a href='#structural-pseudos'>:first-child</a></code> pseudo-class";\r
+ ret += " above.</p>";\r
+ ret += " <h3><a name='sibling-combinators'>8.3. Sibling combinators</a></h3>";\r
+ ret += " <p>There are two different sibling combinators: the adjacent sibling";\r
+ ret += " considering adjacency of elements.</p>";\r
+ ret += " <h4><a name='adjacent-sibling-combinators'>8.3.1. Adjacent sibling combinator</a>";\r
+ ret += " </h4>";\r
+ ret += " <p>The adjacent sibling combinator is made of the 'plus";\r
+ ret += " sign' (U+002B, <code>+</code>) character that separates two";\r
+ ret += " sequences of simple selectors. The elements represented by the two";\r
+ ret += " represented by the second one.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <p>The following selector represents a <code>p</code> element";\r
+ ret += " immediately following a <code>math</code> element:</p>";\r
+ ret += " <pre>math + p</pre>";\r
+ ret += " <p>The following selector is conceptually similar to the one in the";\r
+ ret += " adds a constraint to the <code>h1</code> element, that it must have";\r
+ ret += " <code>class='opener'</code>:</p>";\r
+ ret += " <pre>h1.opener + h2</pre>";\r
+ ret += " </div>";\r
+ ret += " <h4><a name='general-sibling-combinators'>8.3.2. General sibling combinator</a>";\r
+ ret += " </h4>";\r
+ ret += " <p>The general sibling combinator is made of the 'tilde'";\r
+ ret += " (U+007E, <code>~</code>) character that separates two sequences of";\r
+ ret += " simple selectors. The elements represented by the two sequences share";\r
+ ret += " represented by the second one.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Example:</p>";\r
+ ret += " <pre>h1 ~ pre</pre>";\r
+ ret += " <p>represents a <code>pre</code> element following an <code>h1</code>. It";\r
+ ret += " is a correct and valid, but partial, description of:</p>";\r
+ ret += " <pre><h1>Definition of the function a</h1>";\r
+ ret += " <pre>function a(x) = 12x/13.5</pre></pre>";\r
+ ret += " </div>";\r
+ ret += " <h2><a name='specificity'>9. Calculating a selector's specificity</a></h2>";\r
+ ret += " <p>A selector's specificity is calculated as follows:</p>";\r
+ ret += " <ul>";\r
+ ret += " <li>count the number of ID selectors in the selector (= a)</li>";\r
+ ret += " <li>count the number of class selectors, attributes selectors, and";\r
+ ret += " </li>";\r
+ ret += " <li>count the number of element names in the selector (= c)</li>";\r
+ ret += " <li>ignore pseudo-elements</li>";\r
+ ret += " </ul>";\r
+ ret += " <p>Selectors inside <a href='#negation'>the negation pseudo-class</a>";\r
+ ret += " a pseudo-class.</p>";\r
+ ret += " <p>Concatenating the three numbers a-b-c (in a number system with a";\r
+ ret += " large base) gives the specificity.</p>";\r
+ ret += " <div class='example'>";\r
+ ret += " <p>Examples:</p>";\r
+ ret += " <pre>* /* a=0 b=0 c=0 -> specificity = 0 */";\r
+ ret += " </pre>";\r
+ ret += " </div>";\r
+ ret += " <p class='note'><strong>Note:</strong> the specificity of the styles";\r
+ ret += " specified in an HTML <code>style</code> attribute is described in CSS";\r
+ ret += " 2.1. <a href='#refsCSS21'>[CSS21]</a>.</p>";\r
+ ret += " <h2><a name='w3cselgrammar'>10. The grammar of Selectors</a></h2>";\r
+ ret += " <h3><a name='grammar'>10.1. Grammar</a></h3>";\r
+ ret += " <p>The grammar below defines the syntax of Selectors. It is globally";\r
+ ret += " shorthand notations beyond Yacc (see <a href='#refsYACC'>[YACC]</a>)";\r
+ ret += " are used:</p>";\r
+ ret += " <ul>";\r
+ ret += " <li><b>*</b>: 0 or more";\r
+ ret += " </li><li><b>+</b>: 1 or more";\r
+ ret += " </li><li><b>?</b>: 0 or 1";\r
+ ret += " </li><li><b>|</b>: separates alternatives";\r
+ ret += " </li><li><b>[ ]</b>: grouping</li>";\r
+ ret += " </ul>";\r
+ ret += " <p>The productions are:</p>";\r
+ ret += " <pre>selectors_group";\r
+ ret += " ;</pre>";\r
+ ret += " <h3><a name='lex'>10.2. Lexical scanner</a></h3>";\r
+ ret += " <p>The following is the <a name='x3'>tokenizer</a>, written in Flex (see";\r
+ ret += " <a href='#refsFLEX'>[FLEX]</a>) notation. The tokenizer is";\r
+ ret += " case-insensitive.</p>";\r
+ ret += " <p>The two occurrences of '\377' represent the highest character";\r
+ ret += " possible code point in Unicode/ISO-10646. <a href='#refsUNICODE'>[UNICODE]</a></p>";\r
+ ret += " <pre>%option case-insensitive";\r
+ ret += " . return *yytext;</pre>";\r
+ ret += " <h2><a name='downlevel'>11. Namespaces and down-level clients</a></h2>";\r
+ ret += " <p>An important issue is the interaction of CSS selectors with XML";\r
+ ret += " to construct a CSS style sheet which will properly match selectors in";\r
+ ret += " is possible to construct a style sheet in which selectors would match";\r
+ ret += " elements and attributes correctly.</p>";\r
+ ret += " <p>It should be noted that a down-level CSS client will (if it";\r
+ ret += " <code>@namespace</code> at-rules, as well as all style rules that make";\r
+ ret += " use of namespace qualified element type or attribute selectors. The";\r
+ ret += " than possibly match them incorrectly.</p>";\r
+ ret += " <p>The use of default namespaces in CSS makes it possible to write";\r
+ ret += " element type selectors that will function in both namespace aware CSS";\r
+ ret += " down-level clients may incorrectly match selectors against XML";\r
+ ret += " elements in other namespaces.</p>";\r
+ ret += " <p>The following are scenarios and examples in which it is possible to";\r
+ ret += " that do not implement this proposal.</p>";\r
+ ret += " <ol>";\r
+ ret += " <li>";\r
+ ret += " <p>The XML document does not use namespaces.</p>";\r
+ ret += " <ul>";\r
+ ret += " <li>In this case, it is obviously not necessary to declare or use";\r
+ ret += " attribute selectors will function adequately in a down-level";\r
+ ret += " </li>";\r
+ ret += " <li>In a CSS namespace aware client, the default behavior of";\r
+ ret += " element selectors matching without regard to namespace will";\r
+ ret += " present. However, the use of specific element type selectors";\r
+ ret += " match only elements that have no namespace ('<code>|name</code>')";\r
+ ret += " will guarantee that selectors will match only XML elements that";\r
+ ret += " </li>";\r
+ ret += " </ul>";\r
+ ret += " </li>";\r
+ ret += " <li>";\r
+ ret += " <p>The XML document defines a single, default namespace used";\r
+ ret += " names.</p>";\r
+ ret += " <ul>";\r
+ ret += " <li>In this case, a down-level client will function as if";\r
+ ret += " element type and attribute selectors will match against all";\r
+ ret += " </li>";\r
+ ret += " </ul>";\r
+ ret += " </li>";\r
+ ret += " <li>";\r
+ ret += " <p>The XML document does <b>not</b> use a default namespace, all";\r
+ ret += " to the same URI).</p>";\r
+ ret += " <ul>";\r
+ ret += " <li>In this case, the down-level client will view and match";\r
+ ret += " element type and attribute selectors based on their fully";\r
+ ret += " qualified name, not the local part as outlined in the <a href='#typenmsp'>Type selectors and Namespaces</a>";\r
+ ret += " selectors may be declared using an escaped colon";\r
+ ret += " '<code>\\:</code>'";\r
+ ret += " '<code>html\\:h1</code>' will match";\r
+ ret += " <code><html:h1></code>. Selectors using the qualified name";\r
+ ret += " </li>";\r
+ ret += " <li>Note that selectors declared in this fashion will";\r
+ ret += " <em>only</em> match in down-level clients. A CSS namespace aware";\r
+ ret += " client will match element type and attribute selectors based on";\r
+ ret += " the name's local part. Selectors declared with the fully";\r
+ ret += " </li>";\r
+ ret += " </ul>";\r
+ ret += " </li>";\r
+ ret += " </ol>";\r
+ ret += " <p>In other scenarios: when the namespace prefixes used in the XML are";\r
+ ret += " <em>different</em> namespace URIs within the same document, or in";\r
+ ret += " a CSS and XML namespace aware client.</p>";\r
+ ret += " <h2><a name='profiling'>12. Profiles</a></h2>";\r
+ ret += " <p>Each specification using Selectors must define the subset of W3C";\r
+ ret += " Selectors it allows and excludes, and describe the local meaning of";\r
+ ret += " all the components of that subset.</p>";\r
+ ret += " <p>Non normative examples:";\r
+ ret += " </p><div class='profile'>";\r
+ ret += " <table class='tprofile'>";\r
+ ret += " <tbody>";\r
+ ret += " <tr>";\r
+ ret += " <th class='title' colspan='2'>Selectors profile</th>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <th>Specification</th>";\r
+ ret += " <td>CSS level 1</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <th>Accepts</th>";\r
+ ret += " <td>type selectors<br>class selectors<br>ID selectors<br>:link,";\r
+ ret += " :visited and :active pseudo-classes<br>descendant combinator";\r
+ ret += " <br>::first-line and ::first-letter pseudo-elements";\r
+ ret += " </td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <th>Excludes</th>";\r
+ ret += " <td>";\r
+ ret += " <p>universal selector<br>attribute selectors<br>:hover and";\r
+ ret += " pseudo-classes<br>:target pseudo-class<br>:lang()";\r
+ ret += " pseudo-class<br>all UI";\r
+ ret += " element states pseudo-classes<br>all structural";\r
+ ret += " pseudo-classes<br>negation pseudo-class<br>all";\r
+ ret += " UI element fragments pseudo-elements<br>::before and ::after";\r
+ ret += " pseudo-elements<br>child combinators<br>sibling combinators";\r
+ ret += " </p><p>namespaces</p></td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <th>Extra constraints</th>";\r
+ ret += " <td>only one class selector allowed per sequence of simple";\r
+ ret += " selectors";\r
+ ret += " </td>";\r
+ ret += " </tr>";\r
+ ret += " </tbody>";\r
+ ret += " </table>";\r
+ ret += " <br><br>";\r
+ ret += " <table class='tprofile'>";\r
+ ret += " <tbody>";\r
+ ret += " <tr>";\r
+ ret += " <th class='title' colspan='2'>Selectors profile</th>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <th>Specification</th>";\r
+ ret += " <td>CSS level 2</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <th>Accepts</th>";\r
+ ret += " <td>type selectors<br>universal selector<br>attribute presence and";\r
+ ret += " values selectors<br>class selectors<br>ID selectors<br>:link,";\r
+ ret += " <br>descendant combinator<br>child combinator<br>adjacent";\r
+ ret += " combinator<br>::first-line and ::first-letter";\r
+ ret += " pseudo-elements<br>::before";\r
+ ret += " </td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <th>Excludes</th>";\r
+ ret += " <td>";\r
+ ret += " <p>content selectors<br>substring matching attribute";\r
+ ret += " selectors<br>:target pseudo-classes<br>all UI element";\r
+ ret += " states pseudo-classes<br>all structural pseudo-classes other";\r
+ ret += " than :first-child<br>negation pseudo-class<br>all UI element";\r
+ ret += " fragments pseudo-elements<br>general sibling combinators";\r
+ ret += " </p><p>namespaces</p></td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <th>Extra constraints</th>";\r
+ ret += " <td>more than one class selector per sequence of simple selectors";\r
+ ret += " </td>";\r
+ ret += " </tr>";\r
+ ret += " </tbody>";\r
+ ret += " </table>";\r
+ ret += " <p>In CSS, selectors express pattern matching rules that determine which";\r
+ ret += " </p><p>The following selector (CSS level 2) will <b>match</b> all anchors <code>a</code>";\r
+ ret += " with attribute <code>name</code> set inside a section 1 header";\r
+ ret += " <code>h1</code>:";\r
+ ret += " </p><pre>h1 a[name]</pre>";\r
+ ret += " <p>All CSS declarations attached to such a selector are applied to elements";\r
+ ret += " matching it.</p></div>";\r
+ ret += " <div class='profile'>";\r
+ ret += " <table class='tprofile'>";\r
+ ret += " <tbody>";\r
+ ret += " <tr>";\r
+ ret += " <th class='title' colspan='2'>Selectors profile</th>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <th>Specification</th>";\r
+ ret += " <td>STTS 3</td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <th>Accepts</th>";\r
+ ret += " <td>";\r
+ ret += " <p>type selectors<br>universal selectors<br>attribute";\r
+ ret += " selectors<br>class";\r
+ ret += " selectors<br>ID selectors<br>all structural";\r
+ ret += " pseudo-classes<br>";\r
+ ret += " </p><p>namespaces</p></td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <th>Excludes</th>";\r
+ ret += " <td>non-accepted pseudo-classes<br>pseudo-elements<br></td>";\r
+ ret += " </tr>";\r
+ ret += " <tr>";\r
+ ret += " <th>Extra constraints</th>";\r
+ ret += " <td>some selectors and combinators are not allowed in fragment";\r
+ ret += " </td>";\r
+ ret += " </tr>";\r
+ ret += " </tbody>";\r
+ ret += " </table>";\r
+ ret += " <p>Selectors can be used in STTS 3 in two different";\r
+ ret += " </p><ol>";\r
+ ret += " <li>a selection mechanism equivalent to CSS selection mechanism:";\r
+ ret += " </li><li>fragment descriptions that appear on the right side of declarations.";\r
+ ret += " </li>";\r
+ ret += " </ol>";\r
+ ret += " </div>";\r
+ ret += " <h2><a name='Conformance'></a>13. Conformance and requirements</h2>";\r
+ ret += " <p>This section defines conformance with the present specification only.";\r
+ ret += " </p><p>The inability of a user agent to implement part of this specification due to";\r
+ ret += " </p><p>All specifications reusing Selectors must contain a <a href='#profiling'>Profile</a> listing the";\r
+ ret += " subset of Selectors it accepts or excludes, and describing the constraints";\r
+ ret += " </p><p>Invalidity is caused by a parsing error, e.g. an unrecognized token or a";\r
+ ret += " </p><p>User agents must observe the rules for handling parsing errors:";\r
+ ret += " </p><ul>";\r
+ ret += " <li>a simple selector containing an undeclared namespace prefix is invalid";\r
+ ret += " </li>";\r
+ ret += " <li>a selector containing an invalid simple selector, an invalid combinator";\r
+ ret += " </li>";\r
+ ret += " <li>a group of selectors containing an invalid selector is invalid.</li>";\r
+ ret += " </ul>";\r
+ ret += " <p>Specifications reusing Selectors must define how to handle parsing";\r
+ ret += " used is dropped.)</p>";\r
+ ret += " <!-- Apparently all these references are out of date:";\r
+ ret += " <p>Implementations of this specification must behave as";\r
+ ret += " 'recipients of text data' as defined by <a href='#refsCWWW'>[CWWW]</a>";\r
+ ret += " when parsing selectors and attempting matches. (In particular,";\r
+ ret += " <a href='#refsCWWW'>[CWWW]</a> and <a";\r
+ ret += " href='#refsUNICODE'>[UNICODE]</a> and apply to implementations of this";\r
+ ret += " specification.</p>-->";\r
+ ret += " <h2><a name='Tests'></a>14. Tests</h2>";\r
+ ret += " <p>This specification has <a href='http://www.w3.org/Style/CSS/Test/CSS3/Selectors/current/'>a test";\r
+ ret += " suite</a> allowing user agents to verify their basic conformance to";\r
+ ret += " and does not cover all possible combined cases of Selectors.</p>";\r
+ ret += " <h2><a name='ACKS'></a>15. Acknowledgements</h2>";\r
+ ret += " <p>The CSS working group would like to thank everyone who has sent";\r
+ ret += " comments on this specification over the years.</p>";\r
+ ret += " <p>The working group would like to extend special thanks to Donna";\r
+ ret += " the final editorial review.</p>";\r
+ ret += " <h2><a name='references'>16. References</a></h2>";\r
+ ret += " <dl class='refs'>";\r
+ ret += " <dt>[CSS1]";\r
+ ret += " </dt><dd><a name='refsCSS1'></a> Bert Bos, HÃ¥kon Wium Lie; '<cite>Cascading";\r
+ ret += " Style Sheets, level 1</cite>', W3C Recommendation, 17 Dec 1996, revised";\r
+ ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/REC-CSS1'>http://www.w3.org/TR/REC-CSS1</a></code>)";\r
+ ret += " </dd><dt>[CSS21]";\r
+ ret += " </dt><dd><a name='refsCSS21'></a> Bert Bos, Tantek Çelik, Ian Hickson, Håkon";\r
+ ret += " Wium Lie, editors; '<cite>Cascading Style Sheets, level 2 revision";\r
+ ret += " 1</cite>', W3C Working Draft, 13 June 2005";\r
+ ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/CSS21'>http://www.w3.org/TR/CSS21</a></code>)";\r
+ ret += " </dd><dt>[CWWW]";\r
+ ret += " </dt><dd><a name='refsCWWW'></a> Martin J. Dürst, François Yergeau,";\r
+ ret += " Misha Wolf, Asmus Freytag, Tex Texin, editors; '<cite>Character Model";\r
+ ret += " for the World Wide Web</cite>', W3C Recommendation, 15 February 2005";\r
+ ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/charmod/'>http://www.w3.org/TR/charmod/</a></code>)";\r
+ ret += " </dd><dt>[FLEX]";\r
+ ret += " </dt><dd><a name='refsFLEX'></a> '<cite>Flex: The Lexical Scanner";\r
+ ret += " Generator</cite>', Version 2.3.7, ISBN 1882114213";\r
+ ret += " </dd><dt>[HTML4]";\r
+ ret += " </dt><dd><a name='refsHTML4'></a> Dave Ragget, Arnaud Le Hors, Ian Jacobs,";\r
+ ret += " editors; '<cite>HTML 4.01 Specification</cite>', W3C Recommendation, 24";\r
+ ret += " </dd><dd>";\r
+ ret += " (<a href='http://www.w3.org/TR/html4/'><code>http://www.w3.org/TR/html4/</code></a>)";\r
+ ret += " </dd><dt>[MATH]";\r
+ ret += " </dt><dd><a name='refsMATH'></a> Patrick Ion, Robert Miner, editors; '<cite>Mathematical";\r
+ ret += " Markup Language (MathML) 1.01</cite>', W3C Recommendation, revision of 7";\r
+ ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/REC-MathML/'>http://www.w3.org/TR/REC-MathML/</a></code>)";\r
+ ret += " </dd><dt>[RFC3066]";\r
+ ret += " </dt><dd><a name='refsRFC3066'></a> H. Alvestrand; '<cite>Tags for the";\r
+ ret += " Identification of Languages</cite>', Request for Comments 3066, January";\r
+ ret += " </dd><dd>(<a href='http://www.ietf.org/rfc/rfc3066.txt'><code>http://www.ietf.org/rfc/rfc3066.txt</code></a>)";\r
+ ret += " </dd><dt>[STTS]";\r
+ ret += " </dt><dd><a name='refsSTTS'></a> Daniel Glazman; '<cite>Simple Tree Transformation";\r
+ ret += " Sheets 3</cite>', Electricité de France, submission to the W3C,";\r
+ ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/NOTE-STTS3'>http://www.w3.org/TR/NOTE-STTS3</a></code>)";\r
+ ret += " </dd><dt>[SVG]";\r
+ ret += " </dt><dd><a name='refsSVG'></a> Jon Ferraiolo, 藤沢 淳, Dean";\r
+ ret += " Jackson, editors; '<cite>Scalable Vector Graphics (SVG) 1.1";\r
+ ret += " Specification</cite>', W3C Recommendation, 14 January 2003";\r
+ ret += " </dd><dd>(<code><a href='http://www.w3.org/TR/SVG/'>http://www.w3.org/TR/SVG/</a></code>)";\r
+ ret += " </dd><dt>[UNICODE]</dt>";\r
+ ret += " <dd><a name='refsUNICODE'></a> <cite><a href='http://www.unicode.org/versions/Unicode4.1.0/'>The Unicode";\r
+ ret += " Standard, Version 4.1</a></cite>, The Unicode Consortium. Boston, MA,";\r
+ ret += " Addison-Wesley, March 2005. ISBN 0-321-18578-1, as amended by <a href='http://www.unicode.org/versions/Unicode4.0.1/'>Unicode";\r
+ ret += " 4.0.1</a> and <a href='http://www.unicode.org/versions/Unicode4.1.0/'>Unicode";\r
+ ret += " 4.1.0</a>.";\r
+ ret += " </dd><dd>(<code><a href='http://www.unicode.org/versions/'>http://www.unicode.org/versions/</a></code>)";\r
+ ret += " </dd>";\r
+ ret += " <dt>[XML10]";\r
+ ret += " </dt><dd><a name='refsXML10'></a> Tim Bray, Jean Paoli, C. M. Sperberg-McQueen,";\r
+ ret += " Eve Maler, François Yergeau, editors; '<cite>Extensible Markup";\r
+ ret += " Language (XML) 1.0 (Third Edition)</cite>', W3C Recommendation, 4";\r
+ ret += " </dd><dd>(<a href='http://www.w3.org/TR/REC-xml/'><code>http://www.w3.org/TR/REC-xml/</code></a>)";\r
+ ret += " </dd><dt>[XMLNAMES]";\r
+ ret += " </dt><dd><a name='refsXMLNAMES'></a> Tim Bray, Dave Hollander, Andrew Layman,";\r
+ ret += " editors; '<cite>Namespaces in XML</cite>', W3C Recommendation, 14";\r
+ ret += " </dd><dd>(<a href='http://www.w3.org/TR/REC-xml-names/'><code>http://www.w3.org/TR/REC-xml-names/</code></a>)";\r
+ ret += " </dd><dt>[YACC]";\r
+ ret += " </dt><dd><a name='refsYACC'></a> S. C. Johnson; '<cite>YACC — Yet another";\r
+ ret += " compiler compiler</cite>', Technical Report, Murray Hill, 1975";\r
+ ret += " </dd></dl>'; </div>";\r
+ ret += " <input name='n' value='v1' type='radio'>1";\r
+ ret += " <input name='n' value='v2' checked='checked' type='radio'>2";\r
+ ret += "</body></html>";\r
+ return ret;\r
}\r
\r
}\r
package com.google.gwt.query.client;\r
\r
import com.google.gwt.dom.client.Element;\r
+import com.google.gwt.user.client.Timer;\r
import com.google.gwt.user.client.ui.HTML;\r
import com.google.gwt.user.client.ui.RootPanel;\r
\r
/**\r
- * Just a simple class to emulate JUnit TestCase\r
+ * Just a simple class to emulate JUnit TestCase.\r
*/\r
public class MyTestCase {\r
\r
static Element e = null;\r
static HTML testPanel = null;\r
\r
- public void gwtSetUp() {\r
- if (e == null) {\r
- testPanel = new HTML();\r
- RootPanel.get().add(testPanel);\r
- e = testPanel.getElement();\r
- e.setId("core-tst");\r
- } else {\r
- e.setInnerHTML("");\r
- }\r
+ public static void assertEquals(Object a, Object b) {\r
+ check(a.equals(b), "assertEquals: expected=" + a + " actual=" + b);\r
}\r
\r
- public static void assertNotNull(Object a) {\r
- check(a != null, "assertNotNull: actual object is null");\r
+ public static void assertFalse(boolean b) {\r
+ check(!b, "assertTrue: actual should be false but is true");\r
}\r
\r
- public static void assertEquals(Object a, Object b) {\r
- check(a.equals(b), "assertEquals: expected=" + a + " actual=" + b);\r
+ public static void assertNotNull(Object a) {\r
+ check(a != null, "assertNotNull: actual object is null");\r
}\r
\r
public static void assertTrue(boolean b) {\r
check(b, "assertTrue: actual should be true but is false");\r
}\r
\r
- public static void assertFalse(boolean b) {\r
- check(!b, "assertTrue: actual should be false but is true");\r
+ public static void assertTrue(String msg, boolean b) {\r
+ check(b, msg);\r
}\r
\r
public static void check(boolean condition, String message) {\r
if (!condition) {\r
- RuntimeException e = new RuntimeException(message);\r
- e.printStackTrace();\r
- throw e;\r
+ RuntimeException ex = new RuntimeException(message);\r
+ ex.printStackTrace();\r
+ throw ex;\r
}\r
}\r
\r
protected static void assertHtmlEquals(Object expected, Object actual) {\r
assertEquals(iExplorerFixHtml(expected), iExplorerFixHtml(actual));\r
}\r
-\r
+ \r
protected static String iExplorerFixHtml(Object s) {\r
- return s.toString().trim().toLowerCase().\r
- replaceAll("[\r\n]", "").\r
- replaceAll(" ([\\w]+)=[\"']([^\"']+)[\"']", " $1=$2").\r
- replaceAll("\\s+\\$h=\"[^\"]+\"", "").\r
- replaceAll(" added=[^ >]+", "");\r
+ return s.toString().trim().toLowerCase().replaceAll(\r
+ "[\r\n]", "").replaceAll(\r
+ " ([\\w]+)=[\"']([^\"']+)[\"']", " $1=$2").replaceAll(\r
+ "\\s+\\$h=\"[^\"]+\"", "").replaceAll(\r
+ " added=[^ >]+", "");\r
}\r
+\r
+ public void gwtSetUp() {\r
+ if (e == null) {\r
+ testPanel = new HTML();\r
+ RootPanel.get().add(testPanel);\r
+ e = testPanel.getElement();\r
+ e.setId("core-tst");\r
+ } else {\r
+ e.setInnerHTML("");\r
+ }\r
+ }\r
+ \r
+ protected static void assertArrayContains(Object result, Object... array) {\r
+ assertArrayContains("", result, array);\r
+ }\r
+ \r
+ protected static void assertArrayContains(String message, Object result, Object... array) {\r
+ String values = "";\r
+ boolean done = false;\r
+ for (Object o : array) {\r
+ values += o.toString() + " ";\r
+ if (result.equals(o)) {\r
+ done = true;\r
+ }\r
+ }\r
+ message = message + ", value (" + result + ") not found in: " + values;\r
+ assertTrue(message, done);\r
+ } \r
+ \r
+ private boolean testRunning = false;\r
\r
+ protected void delayTestFinish(int millis) {\r
+ testRunning = true;\r
+ new Timer(){\r
+ public void run() {\r
+ assertFalse(testRunning);\r
+ }\r
+ }.schedule(millis);\r
+ }\r
+ \r
+ protected void finishTest() {\r
+ testRunning = false;\r
+ }\r
\r
\r
}\r
--- /dev/null
+#!/usr/bin/perl
+
+## Just a perl script to extract an interface from a class.
+## It extract all public methods and copies the javadoc.
+## - With the option --lazy it does the work for Lazy classes
+## and generates the file with the 'Lazy' prefix
+## - Without --lazy it generates a file with the 'I' prefix
+
+my ($i, $o, $lazy);
+
+foreach (@ARGV) {
+ if (/^--input=(.*)$/) {
+ $o = $i = $1;
+ } elsif (/^--lazy$/) {
+ $lazy = 1;
+ }
+}
+
+my $iclass = $1 if ($i =~ /^.*\/([^\.]+)\.java$/);
+my $oclass = ($lazy ? "Lazy" : "I") . $iclass;
+
+$o =~ s/$iclass/$oclass/;
+my $c = 0;
+
+open(F, $i) || die $!;
+my ($in, $com, $ingq, $inclass, $inh, $head, $body, $inmeth, $meth) = (0, "", 0, 0, 1, "", "", 0, "");
+my ($a, $b) = (0,0);
+while(<F>) {
+ s/\r+//g;
+ s/^\s+//g;
+ s/^(\*.*)$/ $1/g;
+ $inh = 0 if (/^\/\*\*/);
+ $head .= $_ if ($inh);
+ $inclass=1 if ($ingq && m/(^|\s+|\()(class|enum|new) /);
+ if ($ingq && !$inclass) {
+ $in = 1 if (/^\/\**\s*$/);
+ $com = "" if (/^\/\**\s*$/);
+ next if /static/;
+ next if /$iclass\s*\(/;
+ $inmeth = 1 if (!$inmeth && !$in && /(public .*?\(.*)\s*$/);
+ $meth .= $_ if ($inmeth);
+ if ($inmeth && /\{/) {
+ $meth =~ s/final\s+//g;
+ $meth =~ s/public\s+//g;
+ $meth =~ s/\{\s*//g;
+ $meth =~ s/\s+$//g;
+ if (!/$oclass/) {
+ $meth =~ s/([^\(]*?)$iclass(\s+.*\()/$1$oclass<T>$2/g if ($lazy);
+ $meth =~ s/\n/ /g;
+ $meth =~ s/ +/ /g;
+ $body .= "$com" if (!$in);
+ $body .= " " .$meth . ";\n\n";
+ }
+ $com = "";
+ $meth = "";
+ $inmeth = 0;
+ }
+ $com .= " " . $_ if ($in);
+ $in = 0 if (/^\s+\*\/\s*$/);
+ }
+ if ($inclass) {
+ my $l = $_;
+ $a ++ while($l =~ /(\{)/g);
+ $b ++ while($l =~ /(\})/g);
+ $inclass = $a = $b = 0 if ($a == $b);
+ }
+ $ingq = 1 if (!$ingq && m/(^|\s+)class /);
+ #$body .= "$c $ingq $inclass $a $b\n";
+ $c ++;
+}
+close(F);
+
+my $class = "public interface $oclass";
+if ($lazy) {
+ $class .= "<T> extends LazyBase<T>" if ($lazy);
+ $head .= "import com.google.gwt.query.client.LazyBase;\n\n";
+}
+
+open(F, ">$o") || die $!;
+print F $head . $class . "{\n\n" . $body . "}\n";
+close(F);
--- /dev/null
+
+
+perl extractInterface.pl --lazy --input=./gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Events.java
+perl extractInterface.pl --lazy --input=./gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Effects.java
+perl extractInterface.pl --lazy --input=./gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java
+++ /dev/null
-/*\r
- * Copyright 2009 Google Inc.\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.google.gwt.query.client;\r
-\r
-import com.google.gwt.core.client.Duration;\r
-import com.google.gwt.dom.client.Element;\r
-import com.google.gwt.dom.client.NodeList;\r
-import com.google.gwt.user.client.Timer;\r
-\r
-/**\r
- * Effects plugin for Gwt Query.\r
- */\r
-public class Effects extends GQueryQueue {\r
-\r
- /**\r
- * Built in easing functions.\r
- */\r
- public enum Easing {\r
-\r
- /**\r
- * Linear easing function.\r
- */\r
- LINEAR {\r
- public double ease(double p, double n, double firstNum, double diff) {\r
- return firstNum + diff * p;\r
- }\r
- },\r
- /**\r
- * Sinusoidal easing function.\r
- */\r
- SWING {\r
- public double ease(double p, double n, double firstNum, double diff) {\r
- return ((-Math.cos(p * Math.PI) / 2) + 0.5) * diff + firstNum;\r
- }\r
- };\r
-\r
- /**\r
- * Override to implement custom easing functions.\r
- */\r
- public abstract double ease(double p, double n, double firstNum,\r
- double diff);\r
- }\r
-\r
- /**\r
- * Build in speed constants.\r
- */\r
- public enum Speed {\r
-\r
- /**\r
- * 400 millisecond animation.\r
- */\r
- DEFAULT(400),\r
- /**\r
- * 200 millisecond animation.\r
- */\r
- FAST(200),\r
- /**\r
- * 600 millisecond animation.\r
- */\r
- SLOW(600);\r
-\r
- private final int duration;\r
-\r
- Speed(int dur) {\r
- this.duration = dur;\r
- }\r
-\r
- public int getDuration() {\r
- return duration;\r
- }\r
- }\r
-\r
- /**\r
- * Utility class.\r
- */\r
- protected class PropFx {\r
-\r
- public Element elem;\r
-\r
- public SpeedOpts opt;\r
-\r
- public String prop;\r
-\r
- private double end;\r
-\r
- private double now;\r
-\r
- private double pos;\r
-\r
- private double start;\r
-\r
- private double startTime;\r
-\r
- private double state;\r
-\r
- private String unit;\r
-\r
- public double cur(boolean force) {\r
- if (elem.getPropertyString(prop) != null && (elem.getStyle() == null\r
- || elem.getStyle().getProperty(prop) == null)) {\r
- return elem.getPropertyDouble(prop);\r
- }\r
- double r = parseDouble(GQuery.curCSS(elem, prop, force));\r
- r = !Double.isNaN(r) && r > -10000 ? r\r
- : parseDouble(GQuery.curCSS(elem, prop, false));\r
- if (Double.isNaN(r)) {\r
- r = 0;\r
- }\r
- return r;\r
- }\r
-\r
- public void hide() {\r
- opt.cache.put(prop, elem.getStyle().getProperty(prop));\r
- opt.hide = true;\r
- custom(cur(false), 0);\r
- }\r
-\r
- public Effects hide(Speed speed) {\r
- return hide(speed, null);\r
- }\r
-\r
- public Effects hide(Speed speed, Function callback) {\r
- return animate(genFx("hide", 3), speed, Easing.LINEAR, callback);\r
- }\r
-\r
- public void show() {\r
- opt.cache.put(prop, elem.getStyle().getProperty(prop));\r
- opt.show = true;\r
- custom("width".equals(prop) || "height".equals(prop) ? 1 : 0, cur(false));\r
- $(elem).show();\r
- }\r
-\r
- public Effects show(Speed speed) {\r
- return show(speed, null);\r
- }\r
-\r
- public Effects show(Speed speed, Function callback) {\r
- return animate(genFx("show", 3), speed, Easing.LINEAR, callback);\r
- }\r
-\r
- public Effects toggle(Speed speed) {\r
- return hide(speed, null);\r
- }\r
-\r
- public Effects toggle(Speed speed, Function callback) {\r
- return animate(genFx("toggle", 3), speed, Easing.LINEAR, callback);\r
- }\r
-\r
- public void update() {\r
- if ("opacity".equals(prop)) {\r
- GQuery.setStyleProperty(prop, "" + now, elem);\r
- } else {\r
- if (elem.getStyle() != null\r
- && elem.getStyle().getProperty(prop) != null) {\r
- elem.getStyle().setProperty(prop, now + unit);\r
- } else {\r
- elem.setPropertyString(prop, "" + now);\r
- }\r
- }\r
- if (("height".equals(prop) || "width".equals(prop))\r
- && elem.getStyle() != null) {\r
- elem.getStyle().setProperty("display", "block");\r
- }\r
- }\r
-\r
- private void custom(double from, double to) {\r
- custom(from, to, "px");\r
- }\r
-\r
- private void custom(double from, double to, String unit) {\r
- startTime = Duration.currentTimeMillis();\r
- start = from;\r
- end = to;\r
- now = start;\r
- this.unit = unit;\r
- Timer t = new Timer() {\r
- @Override\r
- public void run() {\r
- if (!step(false)) {\r
- cancel();\r
- }\r
- }\r
- };\r
- t.scheduleRepeating(13);\r
- }\r
-\r
- private boolean step(boolean gotoEnd) {\r
- double t = Duration.currentTimeMillis();\r
-\r
- if (gotoEnd || t >= opt.duration + startTime) {\r
- now = end;\r
- pos = start = 1;\r
- update();\r
- opt.curAnim.set(prop, "true");\r
- boolean done = true;\r
- for (String key : opt.curAnim.keys()) {\r
- if (!"true".equals(opt.curAnim.get(key))) {\r
- done = false;\r
- }\r
- }\r
- if (done) {\r
- if (opt.display != null) {\r
- elem.getStyle().setProperty("overflow", opt.overflow);\r
- elem.getStyle().setProperty("display", opt.display);\r
- if ("none".equals(GQuery.curCSS(elem, "display", false))) {\r
- elem.getStyle().setProperty("display", "block");\r
- }\r
- }\r
- if (opt.hide) {\r
- $(elem).hide();\r
- }\r
- if (opt.hide || opt.show) {\r
- for (String key : opt.curAnim.keys()) {\r
- elem.getStyle().setProperty(key, opt.cache.getString(key));\r
- }\r
- }\r
- opt.complete(elem);\r
- }\r
- return false;\r
- } else {\r
- double n = t - startTime;\r
- state = n / opt.duration;\r
- pos = opt.easing.ease(this.state, n, 0, 1);\r
- now = start + ((this.end - this.start) * this.pos);\r
-\r
- update();\r
- return true;\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * Used to register the plugin.\r
- */\r
- private static class EffectsPlugin implements Plugin<Effects> {\r
-\r
- public Effects init(GQuery gq) {\r
- return new Effects(gq.get());\r
- }\r
- }\r
-\r
- private class SpeedOpts {\r
-\r
- public Properties curAnim;\r
-\r
- public String display;\r
-\r
- public boolean hide;\r
-\r
- public String overflow;\r
-\r
- public boolean show;\r
-\r
- private GQuery.DataCache cache = DataCache.createObject().cast();\r
-\r
- private Function complete;\r
-\r
- private int duration;\r
-\r
- private Effects.Easing easing;\r
-\r
- private Properties properties;\r
-\r
- private boolean queue = true;\r
-\r
- protected SpeedOpts(int speed, Easing easing, Function complete) {\r
- this.complete = complete;\r
- this.easing = easing;\r
- this.duration = speed;\r
- }\r
-\r
- protected SpeedOpts(Speed speed, Easing easing, Function complete) {\r
- this.complete = complete;\r
- this.easing = easing;\r
- this.duration = speed.getDuration();\r
- }\r
-\r
- public void complete(Element elem) {\r
- if (queue) {\r
- new Effects(elem).dequeue();\r
- }\r
- if (complete != null) {\r
- complete.f(elem);\r
- }\r
- }\r
-\r
- public Function getComplete() {\r
- return complete;\r
- }\r
-\r
- public int getDuration() {\r
- return duration;\r
- }\r
-\r
- public Easing getEasing() {\r
- return easing;\r
- }\r
-\r
- public Properties getProperties() {\r
- return properties;\r
- }\r
-\r
- public boolean isQueue() {\r
- return queue;\r
- }\r
-\r
- public void setComplete(Function complete) {\r
- this.complete = complete;\r
- }\r
-\r
- public void setDuration(int duration) {\r
- this.duration = duration;\r
- }\r
-\r
- public void setEasing(Easing easing) {\r
- this.easing = easing;\r
- }\r
-\r
- public void setProperties(Properties properties) {\r
- this.properties = properties;\r
- }\r
-\r
- public void setQueue(boolean queue) {\r
- this.queue = queue;\r
- }\r
- }\r
-\r
- public static final Class<Effects> Effects = Effects.class;\r
-\r
- private static String[][] fxAttrs = {\r
- {"height", "marginTop", "marginBottom", "paddingTop", "paddingBottom"},\r
- {"width", "marginLeft", "marginRight", "paddingLeft", "paddingRight"},\r
- {"opacity"}};\r
-\r
- static {\r
- GQuery.registerPlugin(Effects.class, new EffectsPlugin());\r
- }\r
-\r
- private static Properties genFx(String type, int num) {\r
- Properties prop = Properties.createObject().cast();\r
- for (int i = 0; i < num; i++) {\r
- for (int j = 0; j < fxAttrs[i].length; j++) {\r
- prop.set(fxAttrs[i][j], type);\r
- }\r
- }\r
- return prop;\r
- }\r
-\r
- // don't valid double after parsing\r
- private static native double parseDouble(String dstr) /*-{\r
- return parseFloat(dstr);\r
- }-*/;\r
-\r
- private DataCache elemDisplay = DataCache.createObject().cast();\r
-\r
- public Effects(Element element) {\r
- super(element);\r
- }\r
-\r
- public Effects(JSArray elements) {\r
- super(elements);\r
- }\r
-\r
- public Effects(NodeList list) {\r
- super(list);\r
- }\r
-\r
- public Effects animate(final Properties properties, final int speed,\r
- final Easing easing, final Function complete) {\r
- if (!"false".equals(properties.get("queue"))) {\r
- queue(new Function() {\r
- final SpeedOpts optall = new SpeedOpts(speed, easing, complete);\r
-\r
- @Override\r
- public void f(Element e) {\r
- boolean hidden = !$(e).visible();\r
- for (String key : properties.keys()) {\r
- String prop = properties.get(key);\r
- if ("hide".equals(prop) && hidden\r
- || "show".equals(prop) && !hidden) {\r
- optall.complete(e);\r
- return;\r
- }\r
- if ("height".equals(key)\r
- || "width".equals(key) && e.getStyle() != null) {\r
- optall.display = $(e).css("display");\r
- optall.overflow = e.getStyle().getProperty("overflow");\r
- }\r
- }\r
- if (optall.overflow != null) {\r
- e.getStyle().setProperty("overflow", "hidden");\r
- }\r
- optall.curAnim = properties.cloneProps();\r
- for (String key : properties.keys()) {\r
- PropFx fx = new PropFx();\r
- String val = properties.get(key);\r
- fx.elem = e;\r
- fx.opt = optall;\r
- fx.prop = key;\r
- if ("toggle".equals(val)) {\r
- if (hidden) {\r
- fx.show();\r
- } else {\r
- fx.hide();\r
- }\r
- } else if ("show".equals(val)) {\r
- fx.show();\r
- } else if ("hide".equals(val)) {\r
- fx.hide();\r
- } else {\r
- JSArray parts = new Regexp("^([+-]=)?([0-9+-.]+)(.*)$")\r
- .match(val);\r
- double start = fx.cur(true);\r
-\r
- if (parts != null) {\r
- double end = parseDouble(parts.getStr(2));\r
- String unit = parts.getStr(3);\r
- if (unit == null) {\r
- unit = "px";\r
- }\r
- if (!"px".equals(unit)) {\r
- e.getStyle().setProperty(key, (end != 0 ? end : 1) + unit);\r
- start = (end != 0 ? end : 1) / fx.cur(true) * start;\r
- e.getStyle().setProperty(key, start + unit);\r
- }\r
- if (parts.getStr(1) != null) {\r
- end = (("-=".equals(parts.getStr(1)) ? -1 : 1) * end) + start;\r
- }\r
- fx.custom(start, end, unit);\r
- } else {\r
- fx.custom(start, parseDouble(val), "");\r
- }\r
- }\r
- }\r
- }\r
- });\r
- }\r
- return this;\r
- }\r
-\r
-\r
- public Effects animate(final Properties properties, final Speed speed,\r
- final Easing easing, final Function complete) {\r
- return animate(properties, speed.getDuration(), easing, complete);\r
- }\r
-\r
- /**\r
- * Fade in all matched elements by adjusting their opacity. Only the opacity\r
- * is adjusted for this animation, meaning that all of the matched elements\r
- * should already have some form of height and width associated with them.\r
- */\r
- public Effects fadeIn() {\r
- return fadeIn(Speed.DEFAULT);\r
- }\r
-\r
- /**\r
- * Fade in all matched elements by adjusting their opacity. Only the opacity\r
- * is adjusted for this animation, meaning that all of the matched elements\r
- * should already have some form of height and width associated with them.\r
- */\r
- public Effects fadeIn(int speed) {\r
- return fadeIn(speed, null);\r
- }\r
-\r
- /**\r
- * Fade in all matched elements by adjusting their opacity and firing an\r
- * optional callback after completion. Only the opacity is adjusted for this\r
- * animation, meaning that all of the matched elements should already have\r
- * some form of height and width associated with them.\r
- */\r
- public Effects fadeIn(int speed, Function callback) {\r
- return animate($$("opacity: \"show\""), speed, Easing.LINEAR, callback);\r
- }\r
-\r
- /**\r
- * Fade in all matched elements by adjusting their opacity. Only the opacity\r
- * is adjusted for this animation, meaning that all of the matched elements\r
- * should already have some form of height and width associated with them.\r
- */\r
- public Effects fadeIn(Speed speed) {\r
- return fadeIn(speed, null);\r
- }\r
-\r
- /**\r
- * Fade in all matched elements by adjusting their opacity and firing an\r
- * optional callback after completion. Only the opacity is adjusted for this\r
- * animation, meaning that all of the matched elements should already have\r
- * some form of height and width associated with them.\r
- */\r
- public Effects fadeIn(Speed speed, Function callback) {\r
- return fadeIn(speed.duration, callback);\r
- }\r
-\r
- /**\r
- * Fade out all matched elements by adjusting their opacity to 0, then setting\r
- * display to "none". Only the opacity is adjusted for this animation, meaning\r
- * that all of the matched elements should already have some form of height\r
- * and width associated with them.\r
- */\r
- public Effects fadeOut() {\r
- return fadeOut(Speed.DEFAULT);\r
- }\r
-\r
- /**\r
- * Fade out all matched elements by adjusting their opacity to 0, then setting\r
- * display to "none". Only the opacity is adjusted for this animation, meaning\r
- * that all of the matched elements should already have some form of height\r
- * and width associated with them.\r
- */\r
- public Effects fadeOut(int speed) {\r
- return fadeOut(speed, null);\r
- }\r
-\r
- /**\r
- * Fade out all matched elements by adjusting their opacity to 0, then setting\r
- * display to "none" and firing an optional callback after completion. Only\r
- * the opacity is adjusted for this animation, meaning that all of the matched\r
- * elements should already have some form of height and width associated with\r
- * them.\r
- */\r
- public Effects fadeOut(int speed, Function callback) {\r
- return animate($$("opacity: \"hide\""), speed, Easing.LINEAR, callback);\r
- }\r
-\r
- /**\r
- * Fade out all matched elements by adjusting their opacity to 0, then setting\r
- * display to "none". Only the opacity is adjusted for this animation, meaning\r
- * that all of the matched elements should already have some form of height\r
- * and width associated with them.\r
- */\r
- public Effects fadeOut(Speed speed) {\r
- return fadeOut(speed, null);\r
- }\r
-\r
- /**\r
- * Fade out all matched elements by adjusting their opacity to 0, then setting\r
- * display to "none" and firing an optional callback after completion. Only\r
- * the opacity is adjusted for this animation, meaning that all of the matched\r
- * elements should already have some form of height and width associated with\r
- * them.\r
- */\r
- public Effects fadeOut(Speed speed, Function callback) {\r
- return fadeOut(speed.duration, callback);\r
- }\r
-\r
- /**\r
- * Fade the opacity of all matched elements to a specified opacity. Only the\r
- * opacity is adjusted for this animation, meaning that all of the matched\r
- * elements should already have some form of height and width associated with\r
- * them.\r
- */\r
- public Effects fadeTo(Speed speed, double opacity) {\r
- return fadeTo(speed, opacity, null);\r
- }\r
-\r
- /**\r
- * Fade the opacity of all matched elements to a specified opacity and firing\r
- * an optional callback after completion. Only the opacity is adjusted for\r
- * this animation, meaning that all of the matched elements should already\r
- * have some form of height and width associated with them.\r
- */\r
- public Effects fadeTo(Speed speed, double opacity, Function callback) {\r
- return animate($$("opacity: " + opacity), speed, Easing.LINEAR, callback);\r
- }\r
-\r
- /**\r
- * Hides each of the set of matched elements if they are shown.\r
- */\r
- public Effects hide() {\r
- for (Element e : elements()) {\r
- GQuery q = $(e);\r
- String old = (String) q.data("olddisplay");\r
- if (old != null && !"none".equals(old)) {\r
- q.data("olddisplay", GQuery.curCSS(e, "display", false));\r
- }\r
- e.getStyle().setProperty("display", "none");\r
- }\r
- return this;\r
- }\r
-\r
- /**\r
- * Displays each of the set of matched elements if they are hidden.\r
- */\r
- public Effects show() {\r
- for (Element e : elements()) {\r
- GQuery q = $(e);\r
- String old = (String) q.data("olddisplay");\r
- e.getStyle().setProperty("display", SelectorEngine.or(old, ""));\r
- if ("none".equals(GQuery.curCSS(e, "display", false))) {\r
- String tagName = e.getTagName();\r
- String display = "";\r
- if (elemDisplay.getString(tagName) != null) {\r
- display = elemDisplay.getString(tagName);\r
- } else {\r
- Element elem = $("<" + tagName + ">").appendTo($("body")).get(0);\r
- display = GQuery.curCSS(elem, "display", false);\r
- if ("none".equals(display)) {\r
- display = "block";\r
- }\r
- }\r
- e.getStyle().setProperty("display", display);\r
- q.data("olddisplay", display);\r
- }\r
- }\r
- return this;\r
- }\r
-\r
- /**\r
- * Reveal all matched elements by adjusting their height .\r
- */\r
- public Effects slideDown() {\r
- return slideDown(Speed.DEFAULT, null);\r
- }\r
-\r
- /**\r
- * Reveal all matched elements by adjusting their height .\r
- */\r
- public Effects slideDown(Speed speed) {\r
- return slideDown(speed, null);\r
- }\r
-\r
- /**\r
- * Reveal all matched elements by adjusting their height and firing an\r
- * optional callback after completion.\r
- */\r
- public Effects slideDown(Speed speed, Function callback) {\r
- return animate(genFx("show", 1), speed, Easing.LINEAR, callback);\r
- }\r
-\r
- /**\r
- * Toggle the visibility of all matched elements by adjusting their height.\r
- * Only the height is adjusted for this animation, causing all matched\r
- * elements to be hidden or shown in a "sliding" manner\r
- */\r
- public Effects slideToggle() {\r
- return slideToggle(Speed.DEFAULT, null);\r
- }\r
-\r
- /**\r
- * Toggle the visibility of all matched elements by adjusting their height.\r
- * Only the height is adjusted for this animation, causing all matched\r
- * elements to be hidden or shown in a "sliding" manner\r
- */\r
- public Effects slideToggle(Speed speed) {\r
- return slideToggle(speed, null);\r
- }\r
-\r
- /**\r
- * Toggle the visibility of all matched elements by adjusting their height and\r
- * firing an optional callback after completion. Only the height is adjusted\r
- * for this animation, causing all matched elements to be hidden or shown in a\r
- * "sliding" manner\r
- */\r
- public Effects slideToggle(Speed speed, Function callback) {\r
- return animate(genFx("toggle", 1), speed, Easing.LINEAR, callback);\r
- }\r
-\r
- /**\r
- * Hide all matched elements by adjusting their height .\r
- */\r
- public Effects slideUp() {\r
- return slideUp(Speed.DEFAULT, null);\r
- }\r
-\r
- /**\r
- * Hide all matched elements by adjusting their height.\r
- */\r
- public Effects slideUp(Speed speed) {\r
- return slideUp(speed, null);\r
- }\r
-\r
- /**\r
- * Hide all matched elements by adjusting their height and firing an optional\r
- * callback after completion.\r
- */\r
- public Effects slideUp(Speed speed, Function callback) {\r
- return animate(genFx("hide", 1), speed, Easing.LINEAR, callback);\r
- }\r
-\r
- /**\r
- * Toggle displaying each of the set of matched elements.\r
- */\r
- public Effects toggle() {\r
- for (Element e : elements()) {\r
- Effects ef = new Effects(e);\r
- if (ef.visible()) {\r
- ef.hide();\r
- } else {\r
- ef.show();\r
- }\r
- }\r
- return this;\r
- }\r
-\r
- public boolean visible() {\r
- return !"none".equalsIgnoreCase(this.css("display"));\r
- }\r
-}\r
+++ /dev/null
-/*
- * 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
- * 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.NativeEvent;
-import com.google.gwt.dom.client.NodeList;
-import com.google.gwt.user.client.Event;
-
-/**
- * GQuery Plugin for handling and queuing browser events.
- */
-public class Events extends GQuery {
-
- public static final Class<Events> Events = Events.class;
-
- static {
- GQuery.registerPlugin(Events.class, new Plugin<Events>() {
- public Events init(GQuery gq) {
- return new Events(gq.get());
- }
- });
- }
-
- public Events(Element element) {
- super(element);
- }
-
- public Events(JSArray elements) {
- super(elements);
- }
-
- public Events(NodeList<Element> list) {
- super(list);
- }
-
- /**
- * 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, Object data, Function...funcs) {
- for (Element e : elements()) {
- EventsListener.getInstance(e).bind(eventbits, data, funcs);
- }
- return this;
- }
-
- /**
- * 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 GQuery trigger(int eventbits, int... keys) {
- if ((eventbits | Event.ONBLUR) == Event.ONBLUR)
- dispatchEvent(document.createBlurEvent());
- if ((eventbits | Event.ONCHANGE) == Event.ONCHANGE)
- dispatchEvent(document.createChangeEvent());
- if ((eventbits | Event.ONCLICK) == Event.ONCLICK)
- dispatchEvent(document.createClickEvent(0, 0, 0, 0, 0, false, false, false, false));
- if ((eventbits | Event.ONDBLCLICK) == Event.ONDBLCLICK)
- dispatchEvent(document.createDblClickEvent(0, 0, 0, 0, 0, false, false, false, false));
- if ((eventbits | Event.ONFOCUS) == Event.ONFOCUS)
- dispatchEvent(document.createFocusEvent());
- if ((eventbits | Event.ONKEYDOWN) == Event.ONKEYDOWN)
- dispatchEvent(document.createKeyDownEvent(false, false, false, false, keys[0], 0));
- if ((eventbits | Event.ONKEYPRESS) == Event.ONKEYPRESS)
- dispatchEvent(document.createKeyPressEvent(false, false, false, false, keys[0], 0));
- if ((eventbits | Event.ONKEYUP) == Event.ONKEYUP)
- dispatchEvent(document.createKeyUpEvent(false, false, false, false, keys[0], 0));
- if ((eventbits | Event.ONLOSECAPTURE) == Event.ONLOSECAPTURE)
- triggerHtmlEvent("losecapture");
- if ((eventbits | Event.ONMOUSEDOWN) == Event.ONMOUSEDOWN)
- dispatchEvent(document.createMouseDownEvent(0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT));
- if ((eventbits | Event.ONMOUSEMOVE) == Event.ONMOUSEMOVE)
- dispatchEvent(document.createMouseMoveEvent(0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT));
- if ((eventbits | Event.ONMOUSEOUT) == Event.ONMOUSEOUT)
- dispatchEvent(document.createMouseOutEvent(0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT, null));
- if ((eventbits | Event.ONMOUSEOVER) == Event.ONMOUSEOVER)
- dispatchEvent(document.createMouseOverEvent(0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT, null));
- if ((eventbits | Event.ONMOUSEUP) == Event.ONMOUSEUP)
- dispatchEvent(document.createMouseUpEvent(0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT));
- if ((eventbits | Event.ONSCROLL) == Event.ONSCROLL)
- dispatchEvent(document.createScrollEvent());
- if ((eventbits | Event.ONERROR) == Event.ONERROR)
- dispatchEvent(document.createErrorEvent());
- if ((eventbits | Event.ONMOUSEWHEEL) == Event.ONMOUSEWHEEL)
- dispatchEvent(document.createMouseEvent("mousewheel", true, true, 0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT, null));
- return this;
- }
-
- protected GQuery triggerHtmlEvent(String htmlEvent) {
- dispatchEvent(document.createHtmlEvent(htmlEvent, false, false));
- return this;
- }
-
- /**
- * Removes all handlers, that matches the events bits passed, from each
- * element.
- *
- * Example: unbind(Event.ONCLICK | Event.ONMOUSEOVER)
- */
- public GQuery unbind(int eventbits) {
- for (Element e : elements()) {
- EventsListener.getInstance(e).unbind(eventbits);
- }
- return this;
- }
-
- private void dispatchEvent(NativeEvent evt) {
- for (Element e : elements()) {
- e.dispatchEvent(evt);
- }
- }
-}
+++ /dev/null
-/*
- * 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
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.query.client;
-
-import com.google.gwt.core.client.Duration;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.EventListener;
-
-/**
- * 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.
- */
-class EventsListener implements EventListener {
-
- private static class BindFunction {
-
- Object data;
-
- Function function;
-
- int times = -1;
-
- int type;
-
- BindFunction(int t, Function f, Object d) {
- type = t;
- function = f;
- data = d;
- }
-
- BindFunction(int t, Function f, Object d, int times) {
- this(t, f, d);
- this.times = times;
- }
-
- public boolean fire(Event event) {
- if (times != 0) {
- times--;
- return function.f(event, data);
- }
- return true;
- }
-
- public boolean hasEventType(int etype) {
- return (type | etype) == type;
- }
- }
-
- public static EventsListener getInstance(Element e) {
- EventsListener ret = getGQueryEventLinstener(e);
- return ret != null ? ret : new EventsListener(e);
- }
-
- private static native EventsListener getGQueryEventLinstener(Element elem) /*-{
- return elem.__gqueryevent;
- }-*/;
-
- private static native EventListener getOriginalEventListener(Element elem) /*-{
- return elem.__listener;
- }-*/;
-
- private static native void setFocusable(Element elem) /*-{
- elem.tabIndex = 0;
- }-*/;
-
- private static native void setGQueryEventListener(Element elem,
- EventsListener gqevent) /*-{
- elem.__gqueryevent = gqevent;
- }-*/;
-
- private Element element;
-
- private JsObjectArray<EventsListener.BindFunction> elementEvents = JsObjectArray
- .createArray().cast();
- private EventListener originalEventListener;
-
- private EventsListener(Element element) {
- this.element = element;
- originalEventListener = getOriginalEventListener(element);
- setGQueryEventListener(element, this);
- DOM.setEventListener((com.google.gwt.user.client.Element) element, this);
- }
-
- public void bind(int eventbits, final Object data, Function...funcs) {
- for (Function function: funcs) {
- bind(eventbits, data, function, -1);
- }
- }
-
- public void bind(int eventbits, final Object data, final Function function,
- int times) {
- if (function == null) {
- unbind(eventbits);
- } else {
- DOM.sinkEvents((com.google.gwt.user.client.Element) element, eventbits
- | DOM.getEventsSunk((com.google.gwt.user.client.Element) element));
-
- if ((eventbits | Event.FOCUSEVENTS) == Event.FOCUSEVENTS) {
- setFocusable(element);
- }
-
- elementEvents.add(new EventsListener.BindFunction(eventbits, function,
- data, times));
- }
- }
-
- double lastEvnt=0;
- int lastType=0;
-
- public void onBrowserEvent(Event event) {
- // Workaround for Issue_20
- if (lastType == event.getTypeInt()
- && lastEvnt - Duration.currentTimeMillis() < 10
- && "body".equalsIgnoreCase(element.getTagName())) {
- return;
- }
- lastEvnt = Duration.currentTimeMillis();
- lastType = event.getTypeInt();
-
- if (originalEventListener != null) {
- originalEventListener.onBrowserEvent(event);
- }
-
- int etype = DOM.eventGetType(event);
- for (int i = 0; i < elementEvents.length(); i++) {
- EventsListener.BindFunction listener = elementEvents.get(i);
- if (listener.hasEventType(etype)) {
- if (!listener.fire(event)) {
- event.stopPropagation();
- event.preventDefault();
- }
- }
- }
- }
-
- public void unbind(int eventbits) {
- JsObjectArray<EventsListener.BindFunction> newList = JsObjectArray
- .createArray().cast();
- for (int i = 0; i < elementEvents.length(); i++) {
- EventsListener.BindFunction listener = elementEvents.get(i);
- if (!listener.hasEventType(eventbits)) {
- newList.add(listener);
- }
- }
- elementEvents = newList;
- }
-}
*/\r
package com.google.gwt.query.client;\r
\r
-import static com.google.gwt.query.client.Effects.Effects;\r
-import static com.google.gwt.query.client.Events.Events;\r
+\r
+import static com.google.gwt.query.client.plugins.Effects.Effects;\r
+import static com.google.gwt.query.client.plugins.Events.Events;\r
\r
import com.google.gwt.core.client.GWT;\r
import com.google.gwt.core.client.JavaScriptObject;\r
import com.google.gwt.dom.client.SelectElement;\r
import com.google.gwt.dom.client.Style;\r
import com.google.gwt.dom.client.TextAreaElement;\r
+import com.google.gwt.dom.client.Style.Display;\r
import com.google.gwt.query.client.css.CssProperty;\r
import com.google.gwt.query.client.css.Length;\r
import com.google.gwt.query.client.css.Percentage;\r
import com.google.gwt.query.client.css.TakesPercentage;\r
import com.google.gwt.query.client.impl.DocumentStyleImpl;\r
import com.google.gwt.query.client.impl.SelectorEngineImpl;\r
-import com.google.gwt.user.client.DOM;\r
import com.google.gwt.user.client.Event;\r
import com.google.gwt.user.client.Window;\r
\r
* A POJO used to store the top/left CSS positioning values of an element.\r
*/\r
public static class Offset {\r
-\r
- public int top;\r
-\r
public int left;\r
+ public int top;\r
\r
Offset(int left, int top) {\r
this.left = left;\r
protected DataCache() {\r
}\r
\r
- public native void delete(String name) /*-{\r
+ public native void delete(int name) /*-{\r
delete this[name];\r
}-*/;\r
\r
- public native void delete(int name) /*-{\r
+ public native void delete(String name) /*-{\r
delete this[name];\r
}-*/;\r
\r
return !!this[id];\r
}-*/;\r
\r
- public native JavaScriptObject get(String id) /*-{\r
+ public native JavaScriptObject get(int id) /*-{\r
return this[id];\r
}-*/;\r
\r
- public native JavaScriptObject get(int id) /*-{\r
+ public native JavaScriptObject get(String id) /*-{\r
return this[id];\r
}-*/;\r
\r
return get(id).cast();\r
}\r
\r
- public native double getDouble(String id) /*-{\r
+ public native double getDouble(int id) /*-{\r
return this[id];\r
}-*/;\r
\r
- public native double getDouble(int id) /*-{\r
+ public native double getDouble(String id) /*-{\r
return this[id];\r
}-*/;\r
\r
- public native int getInt(String id) /*-{\r
+ public native int getInt(int id) /*-{\r
return this[id];\r
}-*/;\r
\r
- public native int getInt(int id) /*-{\r
+ public native int getInt(String id) /*-{\r
return this[id];\r
}-*/;\r
\r
return this[id];\r
}-*/;\r
\r
- public native String getString(String id) /*-{\r
+ public native String getString(int id) /*-{\r
return this[id];\r
}-*/;\r
\r
- public native String getString(int id) /*-{\r
+ public native String getString(String id) /*-{\r
return this[id];\r
}-*/;\r
\r
return !foo;\r
}-*/;\r
\r
- public native void put(String id, Object obj) /*-{\r
+ public native void put(int id, Object obj) /*-{\r
this[id]=obj;\r
}-*/;\r
\r
- public native void put(int id, Object obj) /*-{\r
+ public native void put(String id, Object obj) /*-{\r
this[id]=obj;\r
}-*/;\r
}\r
\r
- public static final Element window = window();\r
public static final Document document = Document.get();\r
-\r
public static boolean fxOff = false;\r
\r
public static Class<GQuery> GQUERY = GQuery.class;\r
\r
- private static JsMap<Class<? extends GQuery>, Plugin<? extends GQuery>>\r
- plugins;\r
-\r
- private static Element windowData = null;\r
+ public static final Element window = window();\r
\r
private static DataCache dataCache = null;\r
\r
- private static DocumentStyleImpl styleImpl;\r
-\r
private static final int FUNC_PREPEND = 0, FUNC_APPEND = 1, FUNC_AFTER = 2,\r
FUNC_BEFORE = 3;\r
\r
+ private static JsMap<Class<? extends GQuery>, Plugin<? extends GQuery>>\r
+ plugins;\r
+\r
+ private static DocumentStyleImpl styleImpl;\r
+\r
+ private static Element windowData = null;\r
+\r
/**\r
* Create an empty GQuery object.\r
*/\r
return new GQuery(JSArray.create());\r
}\r
\r
+ /**\r
+ * Wrap a GQuery around an existing element.\r
+ */\r
+ public static GQuery $(Element element) {\r
+ JSArray a = JSArray.create();\r
+ a.addNode(element);\r
+ return new GQuery(a);\r
+ }\r
+\r
+ /**\r
+ * Wrap a GQuery around an event's target element.\r
+ */\r
+ public static GQuery $(Event event) {\r
+ return $((Element)event.getCurrentEventTarget().cast());\r
+ }\r
+\r
+ /**\r
+ * Wrap a GQuery around existing Elements.\r
+ */\r
+ public static GQuery $(NodeList<Element> elements) {\r
+ return new GQuery(elements);\r
+ }\r
+\r
/**\r
* This function accepts a string containing a CSS selector which is then used\r
* to match a set of elements, or it accepts raw HTML creating a GQuery\r
* element containing those elements.\r
*/\r
public static GQuery $(String selectorOrHtml) {\r
+ if (selectorOrHtml == null || selectorOrHtml.trim().length() == 0) {\r
+ return $();\r
+ }\r
if (selectorOrHtml.trim().charAt(0) == '<') {\r
return innerHtml(selectorOrHtml);\r
}\r
return $(selectorOrHtml, document);\r
}\r
\r
- public static <T extends GQuery> T $(T gq) {\r
- return gq;\r
- }\r
-\r
/**\r
* This function accepts a string containing a CSS selector which is then used\r
* to match a set of elements, or it accepts raw HTML creating a GQuery\r
}\r
}\r
\r
- /**\r
- * Wrap a GQuery around existing Elements.\r
- */\r
- public static GQuery $(NodeList<Element> elements) {\r
- return new GQuery(elements);\r
- }\r
-\r
- /**\r
- * Wrap a GQuery around an existing element.\r
- */\r
- public static GQuery $(Element element) {\r
- JSArray a = JSArray.create();\r
- a.addNode(element);\r
- return new GQuery(a);\r
- }\r
-\r
- /**\r
- * Wrap a GQuery around an event's target element.\r
- */\r
- public static GQuery $(Event event) {\r
- return $((Element)event.getCurrentEventTarget().cast());\r
+ public static <T extends GQuery> T $(T gq) {\r
+ return gq;\r
}\r
\r
/**\r
});\r
}-*/;\r
\r
+ /**\r
+ * Returns the numeric value of a css propery of the element.\r
+ */\r
+ public static double cur(Element elem, String prop) {\r
+ GQuery g = $(elem);\r
+ if ("height".equals(prop)) {\r
+ return g.clientHeight();\r
+ }\r
+ if ("width".equals(prop)) {\r
+ return g.clientWidth();\r
+ }\r
+ if ("absolute".equalsIgnoreCase(g.css("position"))) {\r
+ if ("left".equals(prop)) {\r
+ return g.offset().left;\r
+ }\r
+ if ("top".equals(prop)) {\r
+ return g.offset().top;\r
+ }\r
+ }\r
+ if ("opacity".equals(prop)) {\r
+ return Double.parseDouble(g.css("opacity"));\r
+ }\r
+ if (elem.getPropertyString(prop) != null\r
+ && (elem.getStyle() == null || elem.getStyle().getProperty(prop) == null)) {\r
+ return elem.getPropertyDouble(prop);\r
+ }\r
+ String val = g.css(prop);\r
+ if (val != null) {\r
+ if ("thick".equals(val)) {\r
+ return (5);\r
+ } else if ("medium".equals(val)) {\r
+ return (3);\r
+ } else if ("thin".equals(val)) {\r
+ return (1);\r
+ }\r
+ val = "0" + val.replaceAll("[^\\d\\.]+", "");\r
+ return Double.parseDouble(val);\r
+ }\r
+ return 0.0;\r
+ }\r
+ \r
+ /**\r
+ * Returns the string value of a css propery of the element.\r
+ * TODO: use implementations\r
+ */\r
public static String curCSS(Element elem, String name, boolean force) {\r
name = fixAttributeName(name);\r
Style s = elem.getStyle();\r
+ if ("opacity".equals(name)) {\r
+ String o = s.getProperty("filter");\r
+ if (o != null) { \r
+ return !o.matches(".*opacity=.*") ? "1" : \r
+ ("" + (Double.valueOf(o.replaceAll("[^\\d]", "")) / 100));\r
+ }\r
+ o = s.getProperty("opacity");\r
+ return o == null || o.length() == 0 ? "1" : o; \r
+ } \r
if (!force) {\r
if (SelectorEngine.truth(s.getProperty(name))) {\r
return s.getProperty(name);\r
}\r
- return name.equals("opacity") ? "1" : "";\r
} else {\r
return styleImpl.getCurrentStyle(elem, name);\r
}\r
+ return "";\r
}\r
-\r
+ \r
/**\r
* Return a lazy version of the GQuery interface. Lazy function calls are\r
* simply queued up and not executed immediately.\r
plugins.put(plugin, pluginFactory);\r
}\r
\r
+ protected static JSArray clean(String elem) {\r
+ String tags = elem.trim().toLowerCase();\r
+ String preWrap = "", postWrap = "";\r
+ int wrapPos = 0;\r
+ if (tags.contains("<opt")) {\r
+ wrapPos = 1;\r
+ preWrap = "<select multiple=\"multiple\">";\r
+ postWrap = "</select>";\r
+ } else if (tags.contains("<legend")) {\r
+ wrapPos = 1;\r
+ preWrap = "<fieldset>";\r
+ postWrap = "</fieldset>";\r
+ } else if (tags.matches("^<(thead|tbody|tfoot|colg|cap)")) {\r
+ wrapPos = 1;\r
+ preWrap = "<table>";\r
+ postWrap = "</table>";\r
+ } else if (tags.contains("<tr")) {\r
+ wrapPos = 2;\r
+ preWrap = "<table><tbody>";\r
+ postWrap = "</tbody></table>";\r
+ } else if (tags.contains("<td") || tags.contains("<th")) {\r
+ wrapPos = 3;\r
+ preWrap = "<table><tbody><tr>";\r
+ postWrap = "</tr></tbody></table>";\r
+ } else if (tags.contains("<col")) {\r
+ wrapPos = 2;\r
+ preWrap = "<table><tbody></tbody><colgroup>";\r
+ postWrap = "</colgroup></table>";\r
+ }\r
+ // TODO: fix IE link tag serialization\r
+ Element div = document.createDivElement();\r
+ div.setInnerHTML(preWrap + elem + postWrap);\r
+ Node n = div;\r
+ while (wrapPos-- != 0) {\r
+ n = n.getLastChild();\r
+ }\r
+ // TODO: add fixes for IE TBODY issue\r
+ return n.getChildNodes().cast();\r
+ }\r
+\r
+ protected static <S> Object data(Element item, String name, S value) {\r
+ if (dataCache == null) {\r
+ windowData = JavaScriptObject.createObject().cast();\r
+ dataCache = JavaScriptObject.createObject().cast();\r
+ }\r
+ item = item == window ? windowData : item;\r
+ if (item == null) {\r
+ return value;\r
+ }\r
+ int id = item.hashCode();\r
+ if (name != null && !dataCache.exists(id)) {\r
+ dataCache.put(id, DataCache.createObject().cast());\r
+ }\r
+\r
+ DataCache d = dataCache.get(id).cast();\r
+ if (name != null && value != null) {\r
+ d.put(name, value);\r
+ }\r
+ return name != null ? d.getObject(name) : id;\r
+ }\r
+\r
protected static String[] jsArrayToString(JsArrayString array) {\r
if (GWT.isScript()) {\r
return jsArrayToString0(array);\r
}\r
}\r
\r
+ private static String fixAttributeName(String key) {\r
+ ensureStyleImpl();\r
+ return styleImpl.getPropertyName(key);\r
+ }\r
+\r
private static boolean hasClass(Element e, String clz) {\r
return ((" " + e.getClassName() + " ").matches(".*\\s" + clz + "\\s.*"));\r
}\r
return res;\r
}\r
\r
+ private static native Element window() /*-{\r
+ return $wnd;\r
+ }-*/;\r
+\r
protected NodeList<Element> elements = null;\r
\r
private String currentSelector;\r
\r
private GQuery previousObject;\r
-\r
+ \r
public GQuery() {\r
elements = JavaScriptObject.createArray().cast();\r
}\r
\r
- public GQuery(NodeList<Element> list) {\r
- elements = list;\r
- }\r
-\r
- public GQuery(JSArray elements) {\r
- this.elements = elements;\r
- }\r
-\r
public GQuery(Element element) {\r
elements = JSArray.create(element);\r
}\r
- \r
+\r
public GQuery(GQuery gq) {\r
this(gq.get());\r
}\r
\r
- /**\r
- * Add elements to the set of matched elements if they are not included yet.\r
- */\r
+ public GQuery(JSArray elements) {\r
+ this.elements = elements;\r
+ }\r
\r
- public GQuery add(String selector) {\r
- return add($(selector));\r
+ public GQuery(NodeList<Element> list) {\r
+ elements = list;\r
}\r
\r
/**\r
getSelector() + "," + previousObject.getSelector());\r
}\r
\r
+ /**\r
+ * Add elements to the set of matched elements if they are not included yet.\r
+ */\r
+\r
+ public GQuery add(String selector) {\r
+ return add($(selector));\r
+ }\r
+\r
/**\r
* Adds the specified classes to each matched element.\r
*/\r
* already be inserted into the document (you can't insert an element after\r
* another if it's not in the page).\r
*/\r
- public GQuery after(Node n) {\r
- return domManip(JSArray.create(n), FUNC_AFTER);\r
+ public GQuery after(GQuery query) {\r
+ return domManip(query.elements, FUNC_AFTER);\r
}\r
\r
/**\r
* already be inserted into the document (you can't insert an element after\r
* another if it's not in the page).\r
*/\r
- public GQuery after(String html) {\r
- return domManip(html, FUNC_AFTER);\r
+ public GQuery after(Node n) {\r
+ return domManip(JSArray.create(n), FUNC_AFTER);\r
}\r
\r
/**\r
* already be inserted into the document (you can't insert an element after\r
* another if it's not in the page).\r
*/\r
- public GQuery after(GQuery query) {\r
- return domManip(query.elements, FUNC_AFTER);\r
+ public GQuery after(String html) {\r
+ return domManip(html, FUNC_AFTER);\r
}\r
\r
/**\r
* similar to doing an appendChild to all the specified elements, adding them\r
* into the document.\r
*/\r
- public GQuery append(String html) {\r
- return domManip(html, FUNC_APPEND);\r
+ public GQuery append(GQuery query) {\r
+ return domManip(query.elements, FUNC_APPEND);\r
}\r
\r
/**\r
* similar to doing an appendChild to all the specified elements, adding them\r
* into the document.\r
*/\r
- public GQuery append(GQuery query) {\r
- return domManip(query.elements, FUNC_APPEND);\r
+ public GQuery append(String html) {\r
+ return domManip(html, FUNC_APPEND);\r
}\r
\r
/**\r
throw new RuntimeException("No plugin registered for class " + plugin);\r
}\r
\r
- /**\r
- * Access a property on the first matched element. This method makes it easy\r
- * to retrieve a property value from the first matched element. If the element\r
- * does not have an attribute with such a name, undefined is returned.\r
- * Attributes include title, alt, src, href, width, style, etc.\r
- */\r
- public String attr(String name) {\r
- return elements.getItem(0).getAttribute(fixAttributeName(name));\r
- }\r
-\r
- /**\r
- * Set a single property to a value, on all matched elements.\r
- */\r
- public GQuery attr(String key, String value) {\r
- key = fixAttributeName(key);\r
- for (Element e : elements()) {\r
- e.setAttribute(key, value);\r
- }\r
- return this;\r
- }\r
-\r
/**\r
* Set a key/value object as properties to all matched elements.\r
*\r
return this;\r
}\r
\r
+ /**\r
+ * Access a property on the first matched element. This method makes it easy\r
+ * to retrieve a property value from the first matched element. If the element\r
+ * does not have an attribute with such a name, undefined is returned.\r
+ * Attributes include title, alt, src, href, width, style, etc.\r
+ */\r
+ public String attr(String name) {\r
+ return elements.getItem(0).getAttribute(fixAttributeName(name));\r
+ }\r
+\r
/**\r
* Set a single property to a computed value, on all matched elements.\r
*/\r
return this;\r
}\r
\r
+ /**\r
+ * Set a single property to a value, on all matched elements.\r
+ */\r
+ public GQuery attr(String key, String value) {\r
+ key = fixAttributeName(key);\r
+ for (Element e : elements()) {\r
+ e.setAttribute(key, value);\r
+ }\r
+ return this;\r
+ }\r
+\r
/**\r
* Insert content before each of the matched elements. The elements must\r
* already be inserted into the document (you can't insert an element before\r
* another if it's not in the page).\r
*/\r
- public GQuery before(Node n) {\r
- return domManip(JSArray.create(n), FUNC_BEFORE);\r
+ public GQuery before(GQuery query) {\r
+ return domManip(query.elements, FUNC_BEFORE);\r
}\r
\r
/**\r
* already be inserted into the document (you can't insert an element before\r
* another if it's not in the page).\r
*/\r
- public GQuery before(GQuery query) {\r
- return domManip(query.elements, FUNC_BEFORE);\r
+ public GQuery before(Node n) {\r
+ return domManip(JSArray.create(n), FUNC_BEFORE);\r
}\r
\r
/**\r
return as(Events).bind(eventbits, data, funcs);\r
}\r
\r
- /**\r
- * Bind Handlers or fire Events for each matched element. \r
- */\r
- private GQuery bindOrFire(int eventbits, final Object data, final Function...funcs) {\r
- if (funcs.length == 0) {\r
- return trigger(eventbits);\r
- } else {\r
- return bind(eventbits, data, funcs);\r
- }\r
- }\r
-\r
/**\r
* Bind a set of functions to the blur event of each matched element.\r
* Or trigger the event if no functions are provided.\r
public GQuery change(Function...f) {\r
return bindOrFire(Event.ONCHANGE, null, f);\r
}\r
-\r
- /**\r
- * Get a set of elements containing all of the unique children of each of the\r
- * matched set of elements. This set is filtered with the expressions that\r
- * will cause only elements matching any of the selectors to be collected.\r
- */\r
- public GQuery children(String... filters) {\r
- return find(filters);\r
- }\r
-\r
+ \r
/**\r
* Get a set of elements containing all of the unique immediate children of\r
* each of the matched set of elements. Also note: while parents() will look\r
return new GQuery(unique(result));\r
}\r
\r
+ /**\r
+ * Get a set of elements containing all of the unique children of each of the\r
+ * matched set of elements. This set is filtered with the expressions that\r
+ * will cause only elements matching any of the selectors to be collected.\r
+ */\r
+ public GQuery children(String... filters) {\r
+ return find(filters);\r
+ }\r
+\r
/**\r
* Bind a set of functions to the click event of each matched element.\r
* Or trigger the event if no functions are provided.\r
public GQuery click(Function...f) {\r
return bindOrFire(Event.ONCLICK, null, f);\r
}\r
- \r
+\r
+ /**\r
+ * Returns the inner height of the first matched element, including padding \r
+ * but not the vertical scrollbar height, border, or margin.\r
+ */\r
+ public int clientHeight() {\r
+ return get(0).getClientHeight();\r
+ }\r
+\r
+ /**\r
+ * Returns the inner width of the first matched element, including padding \r
+ * but not the vertical scrollbar width, border, or margin.\r
+ */\r
+ public int clientWidth() {\r
+ return get(0).getClientWidth();\r
+ }\r
+\r
/**\r
* Clone matched DOM Elements and select the clones. This is useful for moving\r
* copies of the elements to another location in the DOM.\r
}\r
\r
/**\r
- * Set CSS property on every matched element using type-safe enumerations.\r
+ * Set a key/value object as style properties to all matched elements. This\r
+ * serves as the best way to set a large number of style properties on all\r
+ * matched elements.\r
+ *\r
+ * Example: $(".item").css(Properties.create("color: 'red', background:\r
+ * 'blue'"))\r
*/\r
- public <S, T extends CssProperty<S>> GQuery css(T cssProperty, S value) {\r
- for (Element e : elements()) {\r
- cssProperty.set(e.getStyle(), value);\r
+ public GQuery css(Properties properties) {\r
+ for (String property : properties.keys()) {\r
+ css(property, properties.get(property));\r
}\r
return this;\r
}\r
\r
/**\r
- * Set CSS property on every matched element using type-safe enumerations.\r
+ * Return a style property on the first matched element.\r
*/\r
- public GQuery css(TakesLength cssProperty, Length value) {\r
- for (Element e : elements()) {\r
- cssProperty.setLength(e.getStyle(), value);\r
- }\r
- return this;\r
+ public String css(String name) {\r
+ return curCSS(get(0), name);\r
}\r
\r
/**\r
- * Set CSS property on every matched element using type-safe enumerations.\r
+ * Set a single style property to a value, on all matched elements.\r
*/\r
- public GQuery css(TakesPercentage cssProperty, Percentage value) {\r
+ public GQuery css(String prop, String val) {\r
+ prop = fixAttributeName(prop);\r
for (Element e : elements()) {\r
- cssProperty.setPercentage(e.getStyle(), value);\r
+ setStyleProperty(prop, val, e);\r
}\r
return this;\r
}\r
\r
/**\r
- * Return a style property on the first matched element.\r
+ * Set CSS property on every matched element using type-safe enumerations.\r
*/\r
- public String css(String name) {\r
- return curCSS(get(0), name);\r
+ public <S, T extends CssProperty<S>> GQuery css(T cssProperty, S value) {\r
+ for (Element e : elements()) {\r
+ cssProperty.set(e.getStyle(), value);\r
+ }\r
+ return this;\r
}\r
-\r
+ \r
/**\r
- * Set a key/value object as style properties to all matched elements. This\r
- * serves as the best way to set a large number of style properties on all\r
- * matched elements.\r
- *\r
- * Example: $(".item").css(Properties.create("color: 'red', background:\r
- * 'blue'"))\r
+ * Set CSS property on every matched element using type-safe enumerations.\r
*/\r
- public GQuery css(Properties properties) {\r
- for (String property : properties.keys()) {\r
- css(property, properties.get(property));\r
+ public GQuery css(TakesLength cssProperty, Length value) {\r
+ for (Element e : elements()) {\r
+ cssProperty.setLength(e.getStyle(), value);\r
}\r
return this;\r
}\r
\r
/**\r
- * Set a single style property to a value, on all matched elements.\r
+ * Set CSS property on every matched element using type-safe enumerations.\r
*/\r
- public GQuery css(String prop, String val) {\r
- prop = fixAttributeName(prop);\r
+ public GQuery css(TakesPercentage cssProperty, Percentage value) {\r
for (Element e : elements()) {\r
- setStyleProperty(prop, val, e);\r
+ cssProperty.setPercentage(e.getStyle(), value);\r
}\r
return this;\r
}\r
}\r
return this;\r
}\r
- \r
+\r
/**\r
* Bind a set of functions to the dblclick event of each matched element.\r
* Or trigger the event if no functions are provided.\r
}\r
}\r
return this;\r
- }\r
-\r
+ } \r
+ \r
/**\r
* Returns the working set of nodes as a Java array. <b>Do NOT</b attempt to\r
* modify this array, e.g. assign to its elements, or call Arrays.sort()\r
* Bind a set of functions to the error event of each matched element.\r
* Or trigger the event if no functions are provided.\r
*/\r
- public GQuery error(Function...f) {\r
+ public GQuery error(Function... f) {\r
return bindOrFire(Event.ONERROR, null, f);\r
- } \r
- \r
- /**\r
- * Fade in all matched elements by adjusting their opacity.\r
- */\r
- public GQuery fadeIn(int millisecs) {\r
- return $(as(Effects).fadeIn(millisecs));\r
}\r
\r
/**\r
* Fade in all matched elements by adjusting their opacity. The effect will\r
* take 1000 milliseconds to complete\r
*/\r
- public GQuery fadeIn() {\r
- return $(as(Effects).fadeIn());\r
+ public GQuery fadeIn(Function... f) {\r
+ return $(as(Effects).fadeIn(f));\r
}\r
\r
/**\r
- * Fade out all matched elements by adjusting their opacity.\r
+ * Fade in all matched elements by adjusting their opacity.\r
*/\r
- public GQuery fadeOut(int millisecs) {\r
- return as(Effects).fadeOut(millisecs);\r
+ public GQuery fadeIn(int millisecs, Function... f) {\r
+ return $(as(Effects).fadeIn(millisecs, f));\r
}\r
\r
/**\r
* Fade out all matched elements by adjusting their opacity. The effect will\r
* take 1000 milliseconds to complete\r
*/\r
- public GQuery fadeOut() {\r
- return $(as(Effects).fadeOut());\r
+ public GQuery fadeOut(Function... f) {\r
+ return $(as(Effects).fadeOut(f));\r
+ } \r
+ \r
+ /**\r
+ * Fade out all matched elements by adjusting their opacity.\r
+ */\r
+ public GQuery fadeOut(int millisecs, Function... f) {\r
+ return as(Effects).fadeOut(millisecs, f);\r
}\r
\r
/**\r
*/\r
public GQuery focus(Function...f) {\r
return bindOrFire(Event.ONFOCUS, null, f);\r
- } \r
- \r
+ }\r
+\r
/**\r
* Return all elements matched in the GQuery as a NodeList. @see #elements()\r
* for a method which returns them as an immutable Java array.\r
public GQuery gt(int pos) {\r
return $(slice(pos + 1, -1));\r
}\r
-\r
+ \r
/**\r
* Returns true any of the specified classes are present on any of the matched\r
* elements.\r
return false;\r
}\r
\r
+ /**\r
+ * Get the current computed, pixel, height of the first matched element.\r
+ */\r
+ public int height() {\r
+ return get(0).getOffsetHeight();\r
+ }\r
+\r
/**\r
* Set the height of every element in the matched set.\r
*/\r
return css("height", height);\r
}\r
\r
- /**\r
- * Get the current computed, pixel, height of the first matched element.\r
- */\r
- public int height() {\r
- return DOM.\r
- getElementPropertyInt((com.google.gwt.user.client.Element) get(0),\r
- "offsetHeight");\r
- }\r
-\r
/**\r
* Make invisible all matched elements.\r
*/\r
public GQuery hide() {\r
- return $(as(Effects).hide());\r
+ for (Element e : elements()) {\r
+ Object old = data(e, "oldDisplay", null);\r
+ if (old == null) {\r
+ data(e, "oldDisplay", e.getStyle().getDisplay());\r
+ }\r
+ e.getStyle().setDisplay(Display.NONE);\r
+ }\r
+ return this;\r
}\r
\r
/**\r
return -1;\r
}\r
\r
- /**\r
- * Insert all of the matched elements after another, specified, set of\r
- * elements.\r
- */\r
- public GQuery insertAfter(String selector) {\r
- return insertAfter($(selector));\r
- }\r
-\r
/**\r
* Insert all of the matched elements after another, specified, set of\r
* elements.\r
return this;\r
}\r
\r
+ /**\r
+ * Insert all of the matched elements after another, specified, set of\r
+ * elements.\r
+ */\r
+ public GQuery insertAfter(String selector) {\r
+ return insertAfter($(selector));\r
+ }\r
+\r
/**\r
* Insert all of the matched elements before another, specified, set of\r
* elements.\r
public GQuery insertBefore(Element item) {\r
return insertBefore($(item));\r
}\r
-\r
+ \r
/**\r
* Insert all of the matched elements before another, specified, set of\r
* elements.\r
query.before(e);\r
}\r
return this;\r
- }\r
+ } \r
\r
/**\r
* Insert all of the matched elements before another, specified, set of\r
*/\r
public boolean is(String... filters) {\r
return filter(filters).size() > 0;\r
- }\r
- \r
+ } \r
+\r
/**\r
* Bind a set of functions to the keydown event of each matched element.\r
* Or trigger the event if no functions are provided.\r
*/\r
public GQuery keydown(Function...f) {\r
return bindOrFire(Event.ONKEYDOWN, null, f);\r
- } \r
+ }\r
\r
/**\r
* Trigger a keydown event passing the key pushed\r
*/\r
public GQuery keydown(int key) {\r
return trigger(Event.ONKEYDOWN, key);\r
- }\r
+ } \r
\r
/**\r
* Bind a set of functions to the keypress event of each matched element.\r
*/\r
public GQuery keyup(Function...f) {\r
return bindOrFire(Event.ONKEYUP, null, f);\r
- } \r
+ }\r
\r
/**\r
* Trigger a keyup event passing the key pushed\r
*/\r
public GQuery keyup(int key) {\r
return trigger(Event.ONKEYUP, key);\r
- } \r
-\r
+ }\r
+ \r
/**\r
* Returns the number of elements currently matched. The size function will\r
* return the same value.\r
*/\r
public int length() {\r
return size();\r
- }\r
-\r
+ } \r
+ \r
/**\r
* Bind a function to the load event of each matched element.\r
*/\r
public GQuery load(Function f) {\r
return bind(Event.ONLOAD, null, f);\r
- }\r
+ } \r
\r
/**\r
* Reduce the set of matched elements to all elements before a given position.\r
*/\r
public GQuery lt(int pos) {\r
return $(slice(0, pos));\r
- }\r
- \r
+ } \r
+\r
/**\r
* Bind a set of functions to the mousedown event of each matched element.\r
* Or trigger the event if no functions are provided.\r
public GQuery mousedown(Function...f) {\r
return bindOrFire(Event.ONMOUSEDOWN, null, f);\r
} \r
- \r
+ \r
/**\r
* Bind a set of functions to the mousemove event of each matched element.\r
* Or trigger the event if no functions are provided.\r
*/\r
public GQuery mousemove(Function...f) {\r
return bindOrFire(Event.ONMOUSEMOVE, null, f);\r
- } \r
+ } \r
\r
/**\r
* Bind a set of functions to the mouseout event of each matched element.\r
*/\r
public GQuery mouseout(Function...f) {\r
return bindOrFire(Event.ONMOUSEOUT, null, f);\r
- } \r
+ }\r
\r
/**\r
* Bind a set of functions to the mouseover event of each matched element.\r
*/\r
public GQuery mouseover(Function...f) {\r
return bindOrFire(Event.ONMOUSEOVER, null, f);\r
- } \r
- \r
+ }\r
+\r
/**\r
* Bind a set of functions to the mouseup event of each matched element.\r
* Or trigger the event if no functions are provided.\r
*/\r
public GQuery mouseup(Function...f) {\r
return bindOrFire(Event.ONMOUSEUP, null, f);\r
- } \r
+ }\r
\r
/**\r
* Get a set of elements containing the unique next siblings of each of the\r
* the document. The returned object contains two integer properties, top and\r
* left. The method works only with visible elements.\r
*/\r
- public Offset offset() {\r
- return new Offset(get(0).getAbsoluteTop(), get(0).getAbsoluteLeft());\r
+ public com.google.gwt.query.client.GQuery.Offset offset() {\r
+ return new Offset(get(0).getAbsoluteLeft(), get(0).getAbsoluteTop());\r
}\r
\r
/**\r
* element. The handler is executed only once for each element.\r
*\r
* The event handler is passed as a Function that you can use to prevent\r
- * default behaviour. To stop both default action and event bubbling, the\r
+ * default behavior. To stop both default action and event bubbling, the\r
* function event handler has to return false.\r
*\r
* You can pass an additional Object data to your Function as the second\r
* parameter\r
*/\r
public GQuery one(int eventbits, final Object data, final Function f) {\r
- for (Element e : elements()) {\r
- EventsListener.getInstance(e).bind(eventbits, data, f, 1);\r
- }\r
- return this;\r
+ return as(Events).one(eventbits, data, f);\r
}\r
\r
/**\r
return parent().filter(filters);\r
}\r
\r
- /**\r
- * Get a set of elements containing the unique ancestors of the matched set of\r
- * elements (except for the root element). The matched elements are filtered,\r
- * returning those that match any of the filters.\r
- */\r
- public GQuery parents(String... filters) {\r
- return parents().filter(filters);\r
- }\r
-\r
/**\r
* Get a set of elements containing the unique ancestors of the matched set of\r
* elements (except for the root element).\r
return new GQuery(unique(result));\r
}\r
\r
+ /**\r
+ * Get a set of elements containing the unique ancestors of the matched set of\r
+ * elements (except for the root element). The matched elements are filtered,\r
+ * returning those that match any of the filters.\r
+ */\r
+ public GQuery parents(String... filters) {\r
+ return parents().filter(filters);\r
+ }\r
+\r
/**\r
* Gets the top and left position of an element relative to its offset parent.\r
* The returned object contains two Integer properties, top and left. For\r
* accurate calculations make sure to use pixel values for margins, borders\r
* and padding. This method only works with visible elements.\r
*/\r
- public Offset position() {\r
- return new Offset(get(0).getOffsetTop(), get(0).getAbsoluteLeft());\r
+ public com.google.gwt.query.client.GQuery.Offset position() {\r
+ return new Offset(get(0).getOffsetLeft(), get(0).getOffsetTop());\r
}\r
\r
/**\r
* the best way to insert elements inside, at the beginning, of all matched\r
* elements.\r
*/\r
- public GQuery prepend(String html) {\r
- return domManip(html, FUNC_PREPEND);\r
+ public GQuery prepend(GQuery query) {\r
+ return domManip(query.elements, FUNC_PREPEND);\r
}\r
\r
/**\r
* the best way to insert elements inside, at the beginning, of all matched\r
* elements.\r
*/\r
- public GQuery prepend(GQuery query) {\r
- return domManip(query.elements, FUNC_PREPEND);\r
+ public GQuery prepend(Node n) {\r
+ return domManip(JSArray.create(n), FUNC_PREPEND);\r
}\r
\r
/**\r
* the best way to insert elements inside, at the beginning, of all matched\r
* elements.\r
*/\r
- public GQuery prepend(Node n) {\r
- return domManip(JSArray.create(n), FUNC_PREPEND);\r
+ public GQuery prepend(String html) {\r
+ return domManip(html, FUNC_PREPEND);\r
}\r
\r
/**\r
return this;\r
}\r
\r
+ /**\r
+ * Replaces the elements matched by the specified selector with the matched\r
+ * elements. This function is the complement to replaceWith() which does the\r
+ * same task with the parameters reversed.\r
+ */\r
+ public GQuery replaceAll(Element elem) {\r
+ return replaceAll($(elem));\r
+ }\r
+\r
/**\r
* Replaces the elements matched by the specified selector with the matched\r
* elements. This function is the complement to replaceWith() which does the\r
return replaceAll($(html));\r
}\r
\r
+\r
/**\r
- * Replaces the elements matched by the specified selector with the matched\r
- * elements. This function is the complement to replaceWith() which does the\r
- * same task with the parameters reversed.\r
+ * Replaces all matched elements with the specified HTML or DOM elements. This\r
+ * returns the GQuery element that was just replaced, which has been removed\r
+ * from the DOM.\r
*/\r
- public GQuery replaceAll(Element elem) {\r
- return replaceAll($(elem));\r
- }\r
-\r
+ public GQuery replaceWith(Element elem) {\r
+ return replaceWith($(elem));\r
+ } \r
+ \r
/**\r
* Replaces all matched elements with the specified HTML or DOM elements. This\r
* returns the GQuery element that was just replaced, which has been removed\r
}\r
\r
/**\r
- * Replaces all matched elements with the specified HTML or DOM elements. This\r
- * returns the GQuery element that was just replaced, which has been removed\r
- * from the DOM.\r
+ * Save a set of Css properties of every matched element.\r
*/\r
- public GQuery replaceWith(Element elem) {\r
- return replaceWith($(elem));\r
+ public void restoreCssAttrs(String[] cssProps) {\r
+ for (Element e : elements()) {\r
+ for (String a : cssProps) {\r
+ setStyleProperty(a, (String) data(e, "old-" + a, null), e);\r
+ }\r
+ }\r
}\r
\r
+ /**\r
+ * Restore a set of previously saved Css properties in every matched element.\r
+ */\r
+ public void saveCssAttrs(String[] cssProps) {\r
+ for (Element e : elements()) {\r
+ for (String a : cssProps) {\r
+ data("old-" + a, curCSS(e, a));\r
+ }\r
+ }\r
+ }\r
\r
/**\r
* Bind a set of functions to the scroll event of each matched element.\r
*/\r
public GQuery scroll(Function...f) {\r
return bindOrFire(Event.ONSCROLL, null, f);\r
- } \r
- \r
- /**\r
- * When a value is passed in, the scroll left offset is set to that value on\r
- * all matched elements. This method works for both visible and hidden\r
- * elements.\r
- */\r
- public GQuery scrollLeft(int left) {\r
- for (Element e : elements()) {\r
- if (e == window || e == (Node) document) {\r
- Window.scrollTo(left, $(e).scrollTop());\r
- } else {\r
- e.setPropertyInt("scrollLeft", left);\r
- }\r
- }\r
- return this;\r
}\r
\r
/**\r
}\r
\r
/**\r
- * When a value is passed in, the scroll top offset is set to that value on\r
+ * When a value is passed in, the scroll left offset is set to that value on\r
* all matched elements. This method works for both visible and hidden\r
* elements.\r
*/\r
- public GQuery scrollTop(int top) {\r
+ public GQuery scrollLeft(int left) {\r
for (Element e : elements()) {\r
if (e == window || e == (Node) document) {\r
- Window.scrollTo($(e).scrollLeft(), top);\r
+ Window.scrollTo(left, $(e).scrollTop());\r
} else {\r
- e.setPropertyInt("scrollTop", top);\r
+ e.setPropertyInt("scrollLeft", left);\r
}\r
}\r
return this;\r
}\r
}\r
\r
+ /**\r
+ * When a value is passed in, the scroll top offset is set to that value on\r
+ * all matched elements. This method works for both visible and hidden\r
+ * elements.\r
+ */\r
+ public GQuery scrollTop(int top) {\r
+ for (Element e : elements()) {\r
+ if (e == window || e == (Node) document) {\r
+ Window.scrollTo($(e).scrollLeft(), top);\r
+ } else {\r
+ e.setPropertyInt("scrollTop", top);\r
+ }\r
+ }\r
+ return this;\r
+ }\r
+\r
public GQuery select() {\r
return as(Events).triggerHtmlEvent("select");\r
}\r
* elements\r
*/\r
public GQuery show() {\r
- return $(as(Effects).show());\r
+ for (Element e : elements()) {\r
+ Object old = data(e, "oldDisplay", null);\r
+ e.getStyle().setProperty("display", old != null? old.toString() : "");\r
+ }\r
+ return this;\r
}\r
\r
/**\r
* Toggle visibility of elements.\r
*/\r
public GQuery toggle() {\r
- return as(Effects).toggle();\r
+ for (Element e: elements()) {\r
+ if ($(e).visible()) {\r
+ $(e).hide();\r
+ } else {\r
+ $(e).show();\r
+ e.getStyle().setDisplay(Display.BLOCK);\r
+ }\r
+ }\r
+ return this;\r
}\r
\r
+\r
/**\r
* Toggle among two or more function calls every other click.\r
*/\r
return click(new Function() {\r
int click = 0;\r
public boolean f(Event e) {\r
- return fn[(click++ % fn.length)].f(e);\r
+ int n = fn.length == 1 ? 0 : (click++ % fn.length); \r
+ return fn[n].f(e);\r
}\r
});\r
}\r
return r;\r
}\r
\r
-\r
/**\r
* Trigger a set of events on each matched element.\r
* \r
* Return true if the first element is visible.\r
*/\r
public boolean visible() {\r
- return as(Effects).visible();\r
+ return !"none".equalsIgnoreCase(get(0).getStyle().getDisplay());\r
+ }\r
+\r
+ /**\r
+ * Get the current computed, pixel, width of the first matched element.\r
+ */\r
+ public int width() {\r
+ return get(0).getClientWidth();\r
}\r
\r
/**\r
return this;\r
}\r
\r
- /**\r
- * Get the current computed, pixel, width of the first matched element.\r
- */\r
- public int width() {\r
- return DOM.\r
- getElementPropertyInt((com.google.gwt.user.client.Element) get(0),\r
- "offsetWidth");\r
- }\r
-\r
/**\r
* Wrap each matched element with the specified HTML content. This wrapping\r
* process is most useful for injecting additional structure into a document,\r
* within its structure -- it is that element that will enwrap everything\r
* else.\r
*/\r
- public GQuery wrap(GQuery query) {\r
- for (Element e : elements()) {\r
- $(e).wrapAll(query);\r
- }\r
- return this;\r
+ public GQuery wrap(Element elem) {\r
+ return wrap($(elem));\r
}\r
\r
/**\r
* within its structure -- it is that element that will enwrap everything\r
* else.\r
*/\r
- public GQuery wrap(Element elem) {\r
- return wrap($(elem));\r
+ public GQuery wrap(GQuery query) {\r
+ for (Element e : elements()) {\r
+ $(e).wrapAll(query);\r
+ }\r
+ return this;\r
}\r
\r
/**\r
return wrap($(html));\r
}\r
\r
- /**\r
- * Wrap all the elements in the matched set into a single wrapper element.\r
- * This is different from .wrap() where each element in the matched set would\r
- * get wrapped with an element. This wrapping process is most useful for\r
- * injecting additional structure into a document, without ruining the\r
- * original semantic qualities of a document.\r
- *\r
- * This works by going through the first element provided (which is generated,\r
- * on the fly, from the provided HTML) and finds the deepest descendant\r
- * element within its structure -- it is that element that will enwrap\r
- * everything else.\r
- */\r
- public GQuery wrapAll(String html) {\r
- return wrapAll($(html));\r
- }\r
-\r
/**\r
* Wrap all the elements in the matched set into a single wrapper element.\r
* This is different from .wrap() where each element in the matched set would\r
return this;\r
}\r
\r
+ /**\r
+ * Wrap all the elements in the matched set into a single wrapper element.\r
+ * This is different from .wrap() where each element in the matched set would\r
+ * get wrapped with an element. This wrapping process is most useful for\r
+ * injecting additional structure into a document, without ruining the\r
+ * original semantic qualities of a document.\r
+ *\r
+ * This works by going through the first element provided (which is generated,\r
+ * on the fly, from the provided HTML) and finds the deepest descendant\r
+ * element within its structure -- it is that element that will enwrap\r
+ * everything else.\r
+ */\r
+ public GQuery wrapAll(String html) {\r
+ return wrapAll($(html));\r
+ }\r
+\r
/**\r
* Wrap the inner child contents of each matched element (including text\r
* nodes) with an HTML structure. This wrapping process is most useful for\r
* HTML) and finds the deepest ancestor element within its structure -- it is\r
* that element that will enwrap everything else.\r
*/\r
- public GQuery wrapInner(GQuery query) {\r
- for (Element e : elements()) {\r
- $(e).contents().wrapAll(query);\r
- }\r
- return this;\r
+ public GQuery wrapInner(Element elem) {\r
+ return wrapInner($(elem));\r
}\r
\r
/**\r
* HTML) and finds the deepest ancestor element within its structure -- it is\r
* that element that will enwrap everything else.\r
*/\r
- public GQuery wrapInner(String html) {\r
- return wrapInner($(html));\r
+ public GQuery wrapInner(GQuery query) {\r
+ for (Element e : elements()) {\r
+ $(e).contents().wrapAll(query);\r
+ }\r
+ return this;\r
}\r
\r
/**\r
* HTML) and finds the deepest ancestor element within its structure -- it is\r
* that element that will enwrap everything else.\r
*/\r
- public GQuery wrapInner(Element elem) {\r
- return wrapInner($(elem));\r
+ public GQuery wrapInner(String html) {\r
+ return wrapInner($(html));\r
}\r
\r
protected GQuery pushStack(JSArray elts, String name, String selector) {\r
}\r
}\r
\r
- protected static JSArray clean(String elem) {\r
- String tags = elem.trim().toLowerCase();\r
- String preWrap = "", postWrap = "";\r
- int wrapPos = 0;\r
- if (tags.contains("<opt")) {\r
- wrapPos = 1;\r
- preWrap = "<select multiple=\"multiple\">";\r
- postWrap = "</select>";\r
- } else if (tags.contains("<legend")) {\r
- wrapPos = 1;\r
- preWrap = "<fieldset>";\r
- postWrap = "</fieldset>";\r
- } else if (tags.matches("^<(thead|tbody|tfoot|colg|cap)")) {\r
- wrapPos = 1;\r
- preWrap = "<table>";\r
- postWrap = "</table>";\r
- } else if (tags.contains("<tr")) {\r
- wrapPos = 2;\r
- preWrap = "<table><tbody>";\r
- postWrap = "</tbody></table>";\r
- } else if (tags.contains("<td") || tags.contains("<th")) {\r
- wrapPos = 3;\r
- preWrap = "<table><tbody><tr>";\r
- postWrap = "</tr></tbody></table>";\r
- } else if (tags.contains("<col")) {\r
- wrapPos = 2;\r
- preWrap = "<table><tbody></tbody><colgroup>";\r
- postWrap = "</colgroup></table>";\r
- }\r
- // TODO: fix IE link tag serialization\r
- Element div = document.createDivElement();\r
- div.setInnerHTML(preWrap + elem + postWrap);\r
- Node n = div;\r
- while (wrapPos-- != 0) {\r
- n = n.getLastChild();\r
- }\r
- // TODO: add fixes for IE TBODY issue\r
- return n.getChildNodes().cast();\r
- }\r
-\r
- protected <S> Object data(Element item, String name, S value) {\r
- if (dataCache == null) {\r
- windowData = JavaScriptObject.createObject().cast();\r
- dataCache = JavaScriptObject.createObject().cast();\r
- }\r
- item = item == window ? windowData : item;\r
- if (item == null) {\r
- return value;\r
- }\r
- int id = item.hashCode();\r
- if (name != null && !dataCache.exists(id)) {\r
- dataCache.put(id, DataCache.createObject().cast());\r
- }\r
-\r
- DataCache d = dataCache.get(id).cast();\r
- if (name != null && value != null) {\r
- d.put(name, value);\r
+ /**\r
+ * Bind Handlers or fire Events for each matched element. \r
+ */\r
+ private GQuery bindOrFire(int eventbits, final Object data, final Function...funcs) {\r
+ if (funcs.length == 0) {\r
+ return trigger(eventbits);\r
+ } else {\r
+ return bind(eventbits, data, funcs);\r
}\r
- return name != null ? d.getObject(name) : id;\r
- }\r
-\r
- private GQuery domManip(String html, int func) {\r
- return domManip(clean(html), func);\r
}\r
\r
private GQuery domManip(NodeList<?> nodes, int func) {\r
if (nodes.getLength() > 1) {\r
n = n.cloneNode(true);\r
}\r
-\r
switch (func) {\r
case FUNC_PREPEND:\r
e.insertBefore(n, e.getFirstChild());\r
return this;\r
}\r
\r
- private static String fixAttributeName(String key) {\r
- ensureStyleImpl();\r
- return styleImpl.getPropertyName(key);\r
+ private GQuery domManip(String html, int func) {\r
+ return domManip(clean(html), func);\r
}\r
\r
private native Document getContentDocument(Node n) /*-{\r
return sib;\r
}-*/;\r
\r
- private void init(GQuery gQuery) {\r
- this.elements = gQuery.elements;\r
- }\r
-\r
private JSArray merge(NodeList<Element> first, NodeList<Element> second) {\r
JSArray res = copyNodeList(first);\r
for (int i = 0; i < second.getLength(); i++) {\r
}\r
return res;\r
}\r
-\r
- private int num(GQuery gQuery, String val) {\r
- Element elem = gQuery.get(0);\r
- try {\r
- if (elem != null) {\r
- String v = GQuery.curCSS(elem, val);\r
- return Integer.parseInt(v);\r
- }\r
- } catch (NumberFormatException e) {\r
- }\r
- return 0;\r
- }\r
-\r
+ \r
private void removeData(Element item, String name) {\r
if (dataCache == null) {\r
windowData = JavaScriptObject.createObject().cast();\r
} else {\r
dataCache.delete(id);\r
}\r
- }\r
-\r
- private static native Element window() /*-{\r
- return $wnd;\r
- }-*/;\r
+ } \r
}\r
+++ /dev/null
-/*
- * 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
- * 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.dom.client.Element;
-import com.google.gwt.dom.client.NodeList;
-
-/**
- * Class used in plugins which need a queue system.
- */
-public abstract class GQueryQueue extends GQuery {
-
- private static final class Queue<T> extends JavaScriptObject {
-
- public static Queue<?> newInstance() {
- return createArray().cast();
- }
-
- @SuppressWarnings("unused")
- protected Queue() {
- }
-
- public native T dequeue() /*-{
- return this.shift();
- }-*/;
-
- public native void enqueue(T foo) /*-{
- this.push(foo);
- }-*/;
-
- public native int length() /*-{
- return this.length;
- }-*/;
-
- public native T peek(int i) /*-{
- return this[i];
- }-*/;
- }
-
- public GQueryQueue(GQuery gq) {
- super(gq);
- }
-
- public GQueryQueue(JSArray elements) {
- super(elements);
- }
-
- public GQueryQueue(NodeList<Element> list) {
- super(list);
- }
-
- public GQueryQueue(Element element) {
- super(element);
- }
-
- /**
- * Removes a queued function from the front of the queue and executes it.
- */
- public GQueryQueue dequeue() {
- for (Element e : elements()) {
- dequeue(e);
- }
- return this;
- }
-
-
- /**
- * Adds a new function, to be executed, onto the end of the queue of all
- * matched elements.
- */
- public GQueryQueue queue(Function func) {
- for (Element e : elements()) {
- queue(e, func);
- }
- return this;
- }
-
- /**
- * Replaces the current queue with the given queue on all matched elements.
- */
- public GQueryQueue queue(Queue<?> queue) {
- for (Element e : elements()) {
- replacequeue(e, queue);
- }
- return this;
- }
-
- private void dequeue(Element elem) {
- Queue<Function> q = queue(elem, null);
- if (q != null) {
- Function f = q.dequeue();
- f = q.peek(0);
- if (f != null) {
- f.f(elem);
- }
- }
- }
-
- @SuppressWarnings("unchecked")
- private Queue<Function> queue(Element elem, Function func) {
- if (elem != null) {
- Queue<Function> q = (Queue<Function>) data(elem, getQueueType(), null);
- if (q == null) {
- q = (Queue<Function>) data(elem, getQueueType(), Queue.newInstance());
- }
- if (func != null) {
- q.enqueue(func);
- }
- if (q.length() == 1 && func != null) {
- func.f(elem);
- }
- return q;
- }
- return null;
- }
-
- private void replacequeue(Element elem, Queue<?> queue) {
- if (elem != null) {
- data(elem, getQueueType(), queue);
- }
- }
-
- protected String getQueueType() {
- return "GQueryQueue_" + this.getClass().getName();
- }
-}
+++ /dev/null
-package com.google.gwt.query.client;
-
-/**
- *
- */
-public interface LazyEffects extends LazyGQuery<Effects> {
-
- LazyEffects animate(Properties properties, Effects.Speed speed,
- Effects.Easing easing, Function complete);
-
- LazyEffects animate(Properties properties, int speed, Effects.Easing easing,
- Function complete);
-
- GQueryQueue dequeue();
-
- GQueryQueue dequeue(String type);
-
- LazyEffects fadeIn();
-
- LazyEffects fadeIn(Effects.Speed speed);
-
- LazyEffects fadeIn(Effects.Speed speed, Function callback);
-
- LazyEffects fadeIn(int speed);
-
- LazyEffects fadeIn(int speed, Function callback);
-
- LazyEffects fadeOut();
-
- LazyEffects fadeOut(Effects.Speed speed);
-
- LazyEffects fadeOut(Effects.Speed speed, Function callback);
-
- LazyEffects fadeOut(int speed);
-
- LazyEffects fadeOut(int speed, Function callback);
-
- LazyEffects fadeTo(Effects.Speed speed, double opacity);
-
- LazyEffects fadeTo(Effects.Speed speed, double opacity, Function callback);
-
- LazyEffects hide();
-
- GQueryQueue queue(Function data);
-
- GQueryQueue queue(String type, Function data);
-
- LazyEffects show();
-
- LazyEffects slideDown();
-
- LazyEffects slideDown(Effects.Speed speed);
-
- LazyEffects slideDown(Effects.Speed speed, Function callback);
-
- LazyEffects slideToggle();
-
- LazyEffects slideToggle(Effects.Speed speed);
-
- LazyEffects slideToggle(Effects.Speed speed, Function callback);
-
- LazyEffects slideUp();
-
- LazyEffects slideUp(Effects.Speed speed);
-
- LazyEffects slideUp(Effects.Speed speed, Function callback);
-
- LazyEffects toggle();
-}
+/*
+ * 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
+ * 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.Effects.Effects;
+import static com.google.gwt.query.client.plugins.Events.Events;
+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.JsArrayString;
+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.IFrameElement;
+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;
+import com.google.gwt.dom.client.TextAreaElement;
+import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.query.client.css.CssProperty;
+import com.google.gwt.query.client.css.Length;
+import com.google.gwt.query.client.css.Percentage;
+import com.google.gwt.query.client.css.TakesLength;
+import com.google.gwt.query.client.css.TakesPercentage;
+import com.google.gwt.query.client.impl.DocumentStyleImpl;
+import com.google.gwt.query.client.impl.SelectorEngineImpl;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.query.client.LazyBase;
-/**
- * Created by IntelliJ IDEA. User: ray Date: May 2, 2009 Time: 10:48:07 PM To
- * change this template use File | Settings | File Templates.
- */
-public interface LazyGQuery<T> extends LazyBase<T> {
+public interface LazyGQuery<T> extends LazyBase<T>{
/**
* Add elements to the set of matched elements if they are not included yet.
/**
* Convert to Plugin interface provided by Class literal.
*/
- <P extends GQuery> P as(Class<P> plugin);
+ <T extends GQuery> T as(Class<T> plugin);
+
+ /**
+ * 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, undefined is returned.
+ * Attributes include title, alt, src, href, width, style, etc.
+ */
+ String attr(String name);
/**
* Set a single property to a value, on all matched elements.
/**
* 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);
* parameter
*
*/
- LazyGQuery<T> bind(int eventbits, Object data, Function... f);
+ LazyGQuery<T> bind(int eventbits, Object data, Function...funcs);
/**
- * Bind a set of functions to the blur event of each matched element. Or
- * trigger the event if no functions are provided.
+ * Bind a set of functions to the blur event of each matched element.
+ * Or trigger the event if no functions are provided.
*/
- LazyGQuery<T> blur(Function... f);
+ LazyGQuery<T> blur(Function...f);
/**
- * Bind a set of functions to the change event of each matched element. Or
- * trigger the event if no functions are provided.
+ * Bind a set of functions to the change event of each matched element.
+ * Or trigger the event if no functions are provided.
*/
- LazyGQuery<T> change(Function... f);
+ LazyGQuery<T> change(Function...f);
/**
* Get a set of elements containing all of the unique children of each of the
LazyGQuery<T> children();
/**
- * Bind a set of functions to the click event of each matched element. Or
- * trigger the event if no functions are provided.
+ * Bind a set of functions to the click event of each matched element.
+ * Or trigger the event if no functions are provided.
*/
- LazyGQuery<T> click(Function... f);
+ LazyGQuery<T> click(Function...f);
/**
* Clone matched DOM Elements and select the clones. This is useful for moving
LazyGQuery<T> contents();
/**
- * Set a single style property to a value, on all matched elements using
- * type-safe overhead-free enumerations.
- *
- * @param property
- * a CSS property type
- * @param value
- * a legal value from the type T
- * @param <T>
- * inferred from the CSS property type
- * @return
+ * Set CSS property on every matched element using type-safe enumerations.
*/
- <S, P extends CssProperty<S>> LazyGQuery<T> css(P cssProperty, S value);
+ <S, T extends CssProperty<S>> LazyGQuery<T> css(T cssProperty, S value);
+ /**
+ * Set CSS property on every matched element using type-safe enumerations.
+ */
+ LazyGQuery<T> css(TakesLength cssProperty, Length value);
+
+ /**
+ * Set CSS property on every matched element using type-safe enumerations.
+ */
+ LazyGQuery<T> css(TakesPercentage cssProperty, Percentage value);
+
+ /**
+ * Return a style property on the first matched element.
+ */
+ String css(String name);
/**
* 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.
- *
+ *
* Example: $(".item").css(Properties.create("color: 'red', background:
* 'blue'"))
*/
LazyGQuery<T> css(String prop, String val);
/**
- * Bind a set of functions to the dblclick event of each matched element. Or
- * trigger the event if no functions are provided.
+ * Returns value at named data store for the element, as set by data(name,
+ * value).
*/
- LazyGQuery<T> dblclick(Function... f);
+ Object data(String name);
/**
- * 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)
+ * Returns value at named data store for the element, as set by data(name,
+ * value) with desired return type.
+ *
+ */
+ <T> T data(String name, Class<T> clz);
+
+ /**
+ * Stores the value in the named spot with desired return type.
+ */
+ Object data(String name, Object value);
+
+ /**
+ * Bind a set of functions to the dblclick event of each matched element.
+ * Or trigger the event if no functions are provided.
+ */
+ LazyGQuery<T> dblclick(Function...f);
+
+ /**
+ * 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)
*/
LazyGQuery<T> each(Function... f);
+ /**
+ * 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()
+ */
+ Element[] elements();
+
/**
* Remove all child nodes from the set of matched elements.
*/
LazyGQuery<T> eq(int pos);
/**
- * Bind a set of functions to the error event of each matched element. Or
- * trigger the event if no functions are provided.
+ * Bind a set of functions to the error event of each matched element.
+ * Or trigger the event if no functions are provided.
*/
LazyGQuery<T> error(Function... f);
/**
* Fade in all matched elements by adjusting their opacity.
*/
- LazyGQuery<T> fadeIn(int millisecs);
+ LazyGQuery<T> fadeIn(int millisecs, Function... f);
/**
* Fade in all matched elements by adjusting their opacity. The effect will
* take 1000 milliseconds to complete
*/
- LazyGQuery<T> fadeIn();
+ LazyGQuery<T> fadeIn(Function... f);
/**
* Fade out all matched elements by adjusting their opacity.
*/
- LazyGQuery<T> fadeOut(int millisecs);
+ LazyGQuery<T> fadeOut(int millisecs, Function... f);
/**
* Fade out all matched elements by adjusting their opacity. The effect will
* take 1000 milliseconds to complete
*/
- LazyGQuery<T> fadeOut();
+ LazyGQuery<T> fadeOut(Function... f);
/**
* Removes all elements from the set of matched elements that do not match the
* 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);
/**
- * Bind a set of functions to the focus event of each matched element. Or
- * trigger the event if no functions are provided.
+ * Bind a set of functions to the focus event of each matched element.
+ * Or trigger the event if no functions are provided.
*/
- LazyGQuery<T> focus(Function... f);
+ LazyGQuery<T> focus(Function...f);
+
+ /**
+ * Return all elements matched in the GQuery as a NodeList. @see #elements()
+ * for a method which returns them as an immutable Java array.
+ */
+ NodeList<Element> get();
+
+ /**
+ * Return the ith element matched.
+ */
+ Element get(int i);
/**
* Return the previous set of matched elements prior to the last destructive
*/
LazyGQuery<T> getPreviousObject();
+ /**
+ * Return the selector representing the current set of matched elements.
+ */
+ String getSelector();
+
/**
* 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.
*/
LazyGQuery<T> gt(int pos);
+ /**
+ * Returns true any of the specified classes are present on any of the matched
+ * elements.
+ */
+ boolean hasClass(String... classes);
+
/**
* Set the height of every element in the matched set.
*/
*/
LazyGQuery<T> height(String height);
+ /**
+ * Get the current computed, pixel, height of the first matched element.
+ */
+ int height();
+
+ /**
+ * Returns the inner height of the first matched element, including padding
+ * but not the vertical scrollbar height, border, or margin.
+ */
+ int clientHeight();
+
+ /**
+ * Returns the inner width of the first matched element, including padding
+ * but not the vertical scrollbar width, border, or margin.
+ */
+ int clientWidth();
+
/**
* Make invisible all matched elements.
*/
*/
LazyGQuery<T> hover(Function fover, Function fout);
+ /**
+ * Get the innerHTML of the first matched element.
+ */
+ String html();
+
/**
* Set the innerHTML of every matched element.
*/
LazyGQuery<T> html(String html);
+ /**
+ * Find the index of the specified Element.
+ */
+ int index(Element element);
+
/**
* Insert all of the matched elements after another, specified, set of
* elements.
/**
* 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).
*/
/**
* 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).
*/
/**
* 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).
*/
LazyGQuery<T> insertBefore(String selector);
/**
- * Bind a set of functions to the keydown event of each matched element. Or
- * trigger the event if no functions are provided.
+ * 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.
+ */
+ boolean is(String... filters);
+
+ /**
+ * Bind a set of functions to the keydown event of each matched element.
+ * Or trigger the event if no functions are provided.
*/
- LazyGQuery<T> keydown(Function... f);
+ LazyGQuery<T> keydown(Function...f);
/**
* Trigger a keydown event passing the key pushed
LazyGQuery<T> keydown(int key);
/**
- * Bind a set of functions to the keypress event of each matched element. Or
- * trigger the event if no functions are provided.
+ * Bind a set of functions to the keypress event of each matched element.
+ * Or trigger the event if no functions are provided.
*/
- LazyGQuery<T> keypress(Function... f);
+ LazyGQuery<T> keypress(Function...f);
/**
* Trigger a keypress event passing the key pushed
LazyGQuery<T> keypress(int key);
/**
- * Bind a set of functions to the keyup event of each matched element. Or
- * trigger the event if no functions are provided.
+ * Bind a set of functions to the keyup event of each matched element.
+ * Or trigger the event if no functions are provided.
*/
- LazyGQuery<T> keyup(Function... f);
+ LazyGQuery<T> keyup(Function...f);
/**
* Trigger a keyup event passing the key pushed
*/
LazyGQuery<T> keyup(int key);
+ /**
+ * Returns the number of elements currently matched. The size function will
+ * return the same value.
+ */
+ int length();
+
/**
* Bind a function to the load event of each matched element.
*/
LazyGQuery<T> lt(int pos);
/**
- * Bind a set of functions to the mousedown event of each matched element. Or
- * trigger the event if no functions are provided.
+ * Bind a set of functions to the mousedown event of each matched element.
+ * Or trigger the event if no functions are provided.
*/
- LazyGQuery<T> mousedown(Function... f);
+ LazyGQuery<T> mousedown(Function...f);
/**
- * Bind a set of functions to the mousemove event of each matched element. Or
- * trigger the event if no functions are provided.
+ * Bind a set of functions to the mousemove event of each matched element.
+ * Or trigger the event if no functions are provided.
*/
- LazyGQuery<T> mousemove(Function... f);
+ LazyGQuery<T> mousemove(Function...f);
/**
- * Bind a set of functions to the mouseout event of each matched element. Or
- * trigger the event if no functions are provided.
+ * Bind a set of functions to the mouseout event of each matched element.
+ * Or trigger the event if no functions are provided.
*/
- LazyGQuery<T> mouseout(Function... f);
+ LazyGQuery<T> mouseout(Function...f);
/**
- * Bind a set of functions to the mouseover event of each matched element. Or
- * trigger the event if no functions are provided.
+ * Bind a set of functions to the mouseover event of each matched element.
+ * Or trigger the event if no functions are provided.
*/
- LazyGQuery<T> mouseover(Function... f);
+ LazyGQuery<T> mouseover(Function...f);
/**
- * Bind a set of functions to the mouseup event of each matched element. Or
- * trigger the event if no functions are provided.
+ * Bind a set of functions to the mouseup event of each matched element.
+ * Or trigger the event if no functions are provided.
*/
- LazyGQuery<T> mouseup(Function... f);
+ LazyGQuery<T> mouseup(Function...f);
/**
* Get a set of elements containing the unique next siblings of each of the
*/
LazyGQuery<T> not(String... filters);
+ /**
+ * 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.
+ */
+ com.google.gwt.query.client.GQuery.Offset offset();
+
/**
* 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
/**
* 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 behaviour. To stop both default action and event bubbling, the
+ * 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> parents();
+ /**
+ * 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.
+ */
+ com.google.gwt.query.client.GQuery.Offset position();
+
/**
* 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
LazyGQuery<T> replaceWith(Element elem);
/**
- * Bind a set of functions to the scroll event of each matched element. Or
- * trigger the event if no functions are provided.
+ * Bind a set of functions to the scroll event of each matched element.
+ * Or trigger the event if no functions are provided.
*/
- LazyGQuery<T> scroll(Function... f);
+ LazyGQuery<T> scroll(Function...f);
/**
* When a value is passed in, the scroll left offset is set to that value on
LazyGQuery<T> select();
+ /**
+ * Set CSS property on the first element.
+ */
+ <S, T extends CssProperty<S>> LazyGQuery<T> setCss(T cssProperty, S value);
+
+ /**
+ * Set CSS property on first matched element using type-safe enumerations.
+ */
+ LazyGQuery<T> setCss(TakesLength cssProperty, Length value);
+
+ /**
+ * Set CSS property on first matched element using type-safe enumerations.
+ */
+ LazyGQuery<T> setCss(TakesPercentage cssProperty, Percentage value);
+
+ void setPreviousObject(GQuery previousObject);
+
+ void setSelector(String selector);
+
/**
* Return the number of elements in the matched set. Make visible all mached
* elements
*/
LazyGQuery<T> siblings(String... selectors);
+ /**
+ * Return the number of elements in the matched set.
+ */
+ int size();
+
/**
* Selects a subset of the matched elements.
*/
LazyGQuery<T> submit();
+ /**
+ * Return the text contained in the first matched element.
+ */
+ String text();
+
/**
* Set the innerText of every matched element.
*/
LazyGQuery<T> text(String txt);
+ /**
+ * Toggle visibility of elements.
+ */
+ LazyGQuery<T> toggle();
+
/**
* Toggle among two or more function calls every other click.
*/
LazyGQuery<T> toggle(Function... fn);
/**
- * Adds or removes the specified classes to each matched element.
+ * Adds or removes the specified classes to each matched element
+ * depending on the class's presence
*/
LazyGQuery<T> toggleClass(String... classes);
/**
- * Adds or removes the specified classes to each matched element.
+ * Adds or removes the specified classes to each matched element
+ * depending on the value of the switch argument.
+ *
+ * false it is removed.
+ */
+ LazyGQuery<T> toggleClass(String clz, boolean addOrRemove);
+
+ /**
+ * Produces a string representation of the matched elements.
*/
- LazyGQuery<T> toggleClass(String clz, boolean sw);
+ String toString();
/**
- * Trigger an event of type eventbits on every matched element.
+ * Produces a string representation of the matched elements.
+ */
+ String toString(boolean pretty);
+
+ /**
+ * 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);
*/
LazyGQuery<T> unbind(int eventbits);
+ /**
+ * Remove all duplicate elements from an array of elements. Note that this
+ * only works on arrays of DOM elements, not strings or numbers.
+ */
+ JSArray unique(JSArray result);
+
+ /**
+ * 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 a the first checked radio-button that has the same name in the list of
+ * matched elements.
+ */
+ String val();
+
/**
* Sets the value attribute of every matched element In the case of multivalue
* elements, all values are setted for other elements, only the first value is
*/
LazyGQuery<T> val(String... values);
+ /**
+ * 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.
+ */
+ String[] vals();
+
+ /**
+ * Return true if the first element is visible.
+ */
+ boolean visible();
+
/**
* Set the width of every matched element.
*/
LazyGQuery<T> width(int width);
+ /**
+ * Get the current computed, pixel, width of the first matched element.
+ */
+ int width();
+
/**
* Wrap each matched element with the specified HTML content. This wrapping
* process is most useful for injecting additional structure into a document,
* 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
* 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
* 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
* that element that will enwrap everything else.
*/
LazyGQuery<T> wrapInner(Element elem);
+
+ /**
+ * Save a set of Css properties of every matched element.
+ */
+ void restoreCssAttrs(String[] cssProps);
+
+ /**
+ * Restore a set of previously saved Css properties in every matched element.
+ */
+ void saveCssAttrs(String[] cssProps);
+
}
}-*/;\r
\r
protected static String wrapPropertiesString(String s) {\r
- return "({" + s.replaceFirst("^[({]+", "").replaceFirst("[})]+", "") + "})";\r
+ return "({" + s.replaceFirst("^[({]+", "").replaceFirst("[})]+$", "") + "})";\r
}\r
\r
protected Properties() {\r
public final native void set(String key, String val) /*-{\r
this[key]=val;\r
}-*/;\r
+ \r
+ public final String tostring() {\r
+ String ret = "";\r
+ for (String k : keys()){\r
+ ret += k + ": '" + get(k) + "', ";\r
+ }\r
+ return "({" + ret.replaceAll("[, ]+","") + "})";\r
+ }\r
}\r
}
return name;
}
+
+
// code lifted from jQuery
private native String getComputedStyle(Element elem, String name,
--- /dev/null
+/*\r
+ * Copyright 2009 Google Inc.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
+ * use this file except in compliance with the License. You may obtain a copy of\r
+ * the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
+ * License for the specific language governing permissions and limitations under\r
+ * the License.\r
+ */\r
+package com.google.gwt.query.client.plugins;\r
+\r
+import com.google.gwt.animation.client.Animation;\r
+import com.google.gwt.dom.client.Element;\r
+import com.google.gwt.query.client.Function;\r
+import com.google.gwt.query.client.GQuery;\r
+\r
+/**\r
+ * Animation wich uses the css clip property to show/hide an element.\r
+ */\r
+public class ClipAnimation extends Animation {\r
+\r
+ /**\r
+ * Type of the effect action.\r
+ */\r
+ public static enum Action {\r
+ HIDE, SHOW\r
+ }\r
+\r
+ /**\r
+ * Corner from which the effect starts.\r
+ */\r
+ public static enum Corner {\r
+ BOTTOM_LEFT, BOTTOM_RIGHT, CENTER, TOP_LEFT, TOP_RIGHT\r
+ }\r
+\r
+ /**\r
+ * Direction of the effect.\r
+ */\r
+ public static enum Direction {\r
+ BIDIRECTIONAL, HORIZONTAL, VERTICAL\r
+ }\r
+\r
+ private static final String[] attrsToSave = new String[] { "position",\r
+ "overflow", "visibility", "white-space", "top", "left" };\r
+\r
+ Action action;\r
+ Corner corner;\r
+ Direction direction;\r
+ Element e;\r
+ int percent;\r
+ private GQuery back = Effects.$();\r
+ private Function[] funcs;\r
+ private Effects g;\r
+\r
+ public ClipAnimation(Element elem, Action a, Corner c, Direction d,\r
+ final Function... funcs) {\r
+ this.action = a;\r
+ this.corner = c;\r
+ this.direction = d;\r
+ this.funcs = funcs;\r
+ e = elem;\r
+ g = new Effects(e);\r
+ }\r
+\r
+ @Override\r
+ public void onCancel() {\r
+ onComplete();\r
+ }\r
+\r
+ @Override\r
+ public void onComplete() {\r
+ super.onComplete();\r
+ if (action == Action.HIDE) {\r
+ g.hide();\r
+ }\r
+ g.restoreCssAttrs(attrsToSave);\r
+ back.remove();\r
+ back = Effects.$();\r
+ g.css("clip", "");\r
+ g.each(funcs);\r
+ g.dequeue();\r
+ }\r
+\r
+ @Override\r
+ public void onStart() {\r
+ g.show();\r
+ g.saveCssAttrs(attrsToSave);\r
+ if (!"absolute".equalsIgnoreCase(g.css("position"))) {\r
+ g.css("position", "absolute");\r
+ g.css("top", g.offset().top + "px");\r
+ g.css("left", g.offset().left + "px");\r
+ back = back.add(g.before("<div></div>")).prev();\r
+ back.height(g.height());\r
+ back.width(g.width());\r
+ }\r
+ g.css("overflow", "hidden");\r
+ g.css("visivility", "visible");\r
+ g.css("white-space", "nowrap");\r
+ super.onStart();\r
+ }\r
+\r
+ @Override\r
+ public void onUpdate(double progress) {\r
+ if (action == Action.HIDE) {\r
+ progress = (1 - progress);\r
+ }\r
+ int top = 0;\r
+ int left = 0;\r
+ int right = g.width();\r
+ int bottom = g.height();\r
+\r
+ if (direction == Direction.VERTICAL || direction == Direction.BIDIRECTIONAL) {\r
+ bottom = (int) (g.height() * progress);\r
+ }\r
+ if (direction == Direction.HORIZONTAL\r
+ || direction == Direction.BIDIRECTIONAL) {\r
+ right = (int) (g.width() * progress);\r
+ }\r
+ if (corner == Corner.CENTER) {\r
+ top = (g.height() - bottom) / 2;\r
+ left = (g.width() - right) / 2;\r
+ } else if (corner == Corner.BOTTOM_LEFT) {\r
+ top = (g.height() - bottom);\r
+ } else if (corner == Corner.TOP_RIGHT) {\r
+ left = (g.width() - right);\r
+ } else if (corner == Corner.BOTTOM_RIGHT) {\r
+ left = (g.width() - right);\r
+ top = (g.height() - bottom);\r
+ }\r
+ String rect = top + "px " + right + "px " + bottom + "px " + left + "px";\r
+ g.css("clip", "rect(" + rect + ")");\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2009 Google Inc.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
+ * use this file except in compliance with the License. You may obtain a copy of\r
+ * the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
+ * License for the specific language governing permissions and limitations under\r
+ * the License.\r
+ */\r
+package com.google.gwt.query.client.plugins;\r
+\r
+import com.google.gwt.dom.client.Element;\r
+import com.google.gwt.dom.client.NodeList;\r
+import com.google.gwt.query.client.Function;\r
+import com.google.gwt.query.client.GQuery;\r
+import com.google.gwt.query.client.JSArray;\r
+import com.google.gwt.query.client.Plugin;\r
+import com.google.gwt.query.client.Properties;\r
+import com.google.gwt.query.client.plugins.ClipAnimation.Action;\r
+import com.google.gwt.query.client.plugins.ClipAnimation.Direction;\r
+import com.google.gwt.query.client.plugins.PropertiesAnimation.Easing;\r
+\r
+/**\r
+ * Effects plugin for Gwt Query. \r
+ */\r
+public class Effects extends GQueryQueue {\r
+ \r
+ public static int DEFAULT_SPEED = 400;\r
+\r
+ public static Class<Effects> Effects = Effects.class;\r
+\r
+ public static int FAST = 200;\r
+\r
+ public static int SLOW = 600;\r
+ \r
+ static {\r
+ GQuery.registerPlugin(Effects.class, new Plugin<Effects>() {\r
+ public Effects init(GQuery gq) {\r
+ return new Effects(gq);\r
+ }\r
+ });\r
+ }\r
+\r
+ public Effects(final Element element) {\r
+ super(element);\r
+ }\r
+\r
+ public Effects(GQuery gq) {\r
+ super(gq);\r
+ }\r
+\r
+ public Effects(final JSArray elements) {\r
+ super(elements);\r
+ }\r
+\r
+ public Effects(final NodeList<Element> list) {\r
+ super(list);\r
+ }\r
+\r
+ /**\r
+ * The animate() method allows us to create animation effects on any numeric CSS property. \r
+ * The only required parameter is a map of CSS properties. \r
+ * This map is similar to the one that can be sent to the .css() method, \r
+ * except that the range of properties is more restrictive.\r
+ * All animated properties should be numeric, non-numeric cannot be animated using basic functionality. \r
+ * (For example, width, height, or left can be animated but background-color cannot be.) \r
+ * Property values are treated as a number of pixels unless otherwise specified.\r
+ * The units em and % can be specified where applicable.\r
+ * \r
+ * In addition to numeric values, each property can take the strings 'show', 'hide', and 'toggle'. \r
+ * These shortcuts allow for custom hiding and showing animations that take into account the display type of the element.\r
+ * Animated properties can also be relative. If a value is supplied with a leading += or -= \r
+ * sequence of characters, then the target value is computed by adding or subtracting the given number \r
+ * from the current value of the property.\r
+ */ \r
+ public Effects animate(final Properties p, final int duration,\r
+ final Easing easing, final Function... funcs) {\r
+ queue(new Function() {\r
+ public void f(Element e) {\r
+ new PropertiesAnimation(easing, e, p, funcs).run(duration);\r
+ }\r
+ });\r
+ return this;\r
+ }\r
+\r
+ /**\r
+ * The animate() method allows us to create animation effects on any numeric CSS property. \r
+ * The only required parameter is a map of CSS properties. \r
+ * This map is similar to the one that can be sent to the .css() method, \r
+ * except that the range of properties is more restrictive.\r
+ * All animated properties should be numeric, non-numeric cannot be animated using basic functionality. \r
+ * (For example, width, height, or left can be animated but background-color cannot be.) \r
+ * Property values are treated as a number of pixels unless otherwise specified.\r
+ * The units em and % can be specified where applicable.\r
+ * \r
+ * In addition to numeric values, each property can take the strings 'show', 'hide', and 'toggle'. \r
+ * These shortcuts allow for custom hiding and showing animations that take into account the display type of the element.\r
+ * Animated properties can also be relative. If a value is supplied with a leading += or -= \r
+ * sequence of characters, then the target value is computed by adding or subtracting the given number \r
+ * from the current value of the property.\r
+ */\r
+ public Effects animate(String prop, Function... funcs) {\r
+ return animate(prop, 500, funcs);\r
+ }\r
+\r
+ /**\r
+ * The animate() method allows us to create animation effects on any numeric CSS property. \r
+ * The only required parameter is a map of CSS properties. \r
+ * This map is similar to the one that can be sent to the .css() method, \r
+ * except that the range of properties is more restrictive.\r
+ * All animated properties should be numeric, non-numeric cannot be animated using basic functionality. \r
+ * (For example, width, height, or left can be animated but background-color cannot be.) \r
+ * Property values are treated as a number of pixels unless otherwise specified.\r
+ * The units em and % can be specified where applicable.\r
+ * \r
+ * In addition to numeric values, each property can take the strings 'show', 'hide', and 'toggle'. \r
+ * These shortcuts allow for custom hiding and showing animations that take into account the display type of the element.\r
+ * Animated properties can also be relative. If a value is supplied with a leading += or -= \r
+ * sequence of characters, then the target value is computed by adding or subtracting the given number \r
+ * from the current value of the property.\r
+ */ \r
+ public Effects animate(String prop, int duration, Function... funcs) {\r
+ return animate($$(prop), duration, Easing.SWING, funcs);\r
+ }\r
+\r
+ /**\r
+ * Animate the set of matched elements using the clip property.\r
+ * It is possible to show or hide a set of elements, \r
+ * specify the direction of the animation and the start corner of the effect.\r
+ * Finally it executes the set of functions passed as arguments.\r
+ */\r
+ public Effects clip(ClipAnimation.Action a, ClipAnimation.Corner c,\r
+ ClipAnimation.Direction d, Function... f) {\r
+ return clip(a, c, d, DEFAULT_SPEED, f);\r
+ }\r
+ \r
+ /**\r
+ * Animate the set of matched elements using the clip property.\r
+ * It is possible to show or hide a set of elements, \r
+ * specify the direction of the animation and the start corner of the effect.\r
+ * Finally it executes the set of functions passed as arguments.\r
+ */\r
+ public Effects clip(final ClipAnimation.Action a, final ClipAnimation.Corner c, \r
+ final ClipAnimation.Direction d, final int duration, final Function... f) {\r
+ queue(new Function() {\r
+ public void f(Element e) {\r
+ new ClipAnimation(e, a, c, d, f).run(duration);\r
+ }\r
+ });\r
+ return this;\r
+ }\r
+\r
+ /**\r
+ * Animate the set of matched elements using the clip property.\r
+ * It is possible to show or hide a set of elements, \r
+ * specify the direction of the animation and the start corner of the effect.\r
+ * Finally it executes the set of functions passed as arguments.\r
+ */\r
+ public Effects clip(ClipAnimation.Action a, ClipAnimation.Corner c,\r
+ Function... f) {\r
+ return clip(a, c, Direction.BIDIRECTIONAL, DEFAULT_SPEED, f);\r
+ }\r
+\r
+ /**\r
+ * Reveal all matched elements by adjusting the clip property firing an\r
+ * optional callback after completion.\r
+ * The effect goes from the center to the perimeter.\r
+ */\r
+ public Effects clipAppear(Function... f) {\r
+ return clipAppear(DEFAULT_SPEED, f);\r
+ }\r
+ \r
+ /**\r
+ * Reveal all matched elements by adjusting the clip property firing an\r
+ * optional callback after completion.\r
+ * The effect goes from the center to the perimeter.\r
+ */\r
+ public Effects clipAppear(int millisecs, Function... f) {\r
+ return clip(ClipAnimation.Action.SHOW, ClipAnimation.Corner.CENTER,\r
+ ClipAnimation.Direction.BIDIRECTIONAL, millisecs, f);\r
+ }\r
+\r
+ /**\r
+ * Hide all matched elements by adjusting the clip property firing an\r
+ * optional callback after completion.\r
+ * The effect goes from the perimeter to the center.\r
+ */\r
+ public Effects clipDisappear(Function... f) {\r
+ return clipDisappear(DEFAULT_SPEED, f);\r
+ }\r
+ \r
+ /**\r
+ * Hide all matched elements by adjusting the clip property firing an\r
+ * optional callback after completion.\r
+ * The effect goes from the perimeter to the center.\r
+ */\r
+ public Effects clipDisappear(int millisecs, Function... f) {\r
+ return clip(ClipAnimation.Action.HIDE, ClipAnimation.Corner.CENTER,\r
+ ClipAnimation.Direction.BIDIRECTIONAL, millisecs, f);\r
+ }\r
+\r
+ /**\r
+ * Reveal all matched elements by adjusting the clip property firing an\r
+ * optional callback after completion.\r
+ * The effect goes from the top to the bottom.\r
+ */\r
+ public Effects clipDown(Function... f) {\r
+ return clipDown(DEFAULT_SPEED, f);\r
+ }\r
+\r
+ /**\r
+ * Reveal all matched elements by adjusting the clip property firing an\r
+ * optional callback after completion.\r
+ * The effect goes from the top to the bottom.\r
+ */\r
+ public Effects clipDown(int millisecs, Function... f) {\r
+ return clip(Action.SHOW, ClipAnimation.Corner.TOP_LEFT,\r
+ ClipAnimation.Direction.BIDIRECTIONAL, millisecs, f);\r
+ }\r
+\r
+ /**\r
+ * Hide all matched elements by adjusting the clip property firing an\r
+ * optional callback after completion.\r
+ * The effect goes from the bottom to the top.\r
+ */\r
+ public Effects clipUp(Function... f) {\r
+ return clipUp(DEFAULT_SPEED, f);\r
+ }\r
+\r
+ /**\r
+ * Hide all matched elements by adjusting the clip property firing an\r
+ * optional callback after completion.\r
+ * The effect goes from the bottom to the top.\r
+ */\r
+ public Effects clipUp(int millisecs, Function... f) {\r
+ return clip(Action.HIDE, ClipAnimation.Corner.TOP_LEFT,\r
+ ClipAnimation.Direction.BIDIRECTIONAL, millisecs, f);\r
+ }\r
+\r
+ /**\r
+ * Fade in all matched elements by adjusting their opacity and firing an\r
+ * optional callback after completion. Only the opacity is adjusted for this\r
+ * animation, meaning that all of the matched elements should already have\r
+ * some form of height and width associated with them.\r
+ */ \r
+ public Effects fadeIn(Function... f) {\r
+ return fadeIn(DEFAULT_SPEED, f);\r
+ }\r
+\r
+ /**\r
+ * Fade in all matched elements by adjusting their opacity and firing an\r
+ * optional callback after completion. Only the opacity is adjusted for this\r
+ * animation, meaning that all of the matched elements should already have\r
+ * some form of height and width associated with them.\r
+ */\r
+ public Effects fadeIn(int millisecs, Function... f) {\r
+ return animate("opacity: 'show'", millisecs, f);\r
+ }\r
+\r
+ /**\r
+ * Fade out all matched elements by adjusting their opacity to 0, then setting\r
+ * display to "none" and firing an optional callback after completion. Only\r
+ * the opacity is adjusted for this animation, meaning that all of the matched\r
+ * elements should already have some form of height and width associated with\r
+ * them.\r
+ */ \r
+ public Effects fadeOut(Function... f) {\r
+ return fadeOut(DEFAULT_SPEED, f);\r
+ }\r
+\r
+ /**\r
+ * Fade out all matched elements by adjusting their opacity to 0, then setting\r
+ * display to "none" and firing an optional callback after completion. Only\r
+ * the opacity is adjusted for this animation, meaning that all of the matched\r
+ * elements should already have some form of height and width associated with\r
+ * them.\r
+ */ \r
+ public Effects fadeOut(int millisecs, Function... f) {\r
+ return animate("opacity: 'hide'", millisecs, f);\r
+ };\r
+ \r
+ /**\r
+ * Fade the opacity of all matched elements to a specified opacity and firing\r
+ * an optional callback after completion. Only the opacity is adjusted for\r
+ * this animation, meaning that all of the matched elements should already\r
+ * have some form of height and width associated with them.\r
+ */\r
+ public Effects fadeTo(int millisecs, double opacity, Function... f) {\r
+ return animate("opacity: " + opacity, millisecs, f);\r
+ }\r
+ \r
+ /**\r
+ * Reveal all matched elements by adjusting their height and firing an\r
+ * optional callback after completion.\r
+ */\r
+ public Effects slideDown(Function... f) {\r
+ return slideDown(DEFAULT_SPEED, f);\r
+ }\r
+\r
+ /**\r
+ * Reveal all matched elements by adjusting their height and firing an\r
+ * optional callback after completion.\r
+ */\r
+ public Effects slideDown(int millisecs, Function... f) {\r
+ return animate("height: 'show'", millisecs, f);\r
+ }\r
+\r
+ /**\r
+ * Hide all matched elements by adjusting their width and firing an optional\r
+ * callback after completion.\r
+ */\r
+ public Effects slideLeft(Function... f) {\r
+ return slideLeft(DEFAULT_SPEED, f);\r
+ }\r
+\r
+ /**\r
+ * Hide all matched elements by adjusting their width and firing an optional\r
+ * callback after completion.\r
+ */\r
+ public Effects slideLeft(int millisecs, Function... f) {\r
+ return animate("width: 'hide'", millisecs, f);\r
+ }\r
+\r
+ /**\r
+ * Reveal all matched elements by adjusting their width and firing an\r
+ * optional callback after completion.\r
+ */\r
+ public Effects slideRight(Function... f) {\r
+ return slideRight(DEFAULT_SPEED, f);\r
+ }\r
+\r
+ /**\r
+ * Reveal all matched elements by adjusting their width and firing an\r
+ * optional callback after completion.\r
+ */\r
+ public Effects slideRight(final int millisecs, Function... f) {\r
+ return animate("width: 'show'", millisecs, f);\r
+ }\r
+\r
+ /**\r
+ * Toggle the visibility of all matched elements by adjusting their height and\r
+ * firing an optional callback after completion. Only the height is adjusted\r
+ * for this animation, causing all matched elements to be hidden or shown in a\r
+ * "sliding" manner\r
+ */ \r
+ public Effects slideToggle(int millisecs, Function... f) {\r
+ return animate("height: 'toggle'", millisecs, f);\r
+ }\r
+\r
+ /**\r
+ * Hide all matched elements by adjusting their height and firing an optional\r
+ * callback after completion.\r
+ */\r
+ public Effects slideUp(Function... f) {\r
+ return slideUp(DEFAULT_SPEED, f);\r
+ }\r
+\r
+ /**\r
+ * Hide all matched elements by adjusting their height and firing an optional\r
+ * callback after completion.\r
+ */\r
+ public Effects slideUp(int millisecs, Function... f) {\r
+ return animate("height: 'hide'", millisecs, f);\r
+ }\r
+\r
+ /**\r
+ * Toggle displaying each of the set of matched elements.\r
+ */\r
+ @Override\r
+ public Effects toggle() {\r
+ return toggle(DEFAULT_SPEED);\r
+ }\r
+\r
+ /**\r
+ * Toggle displaying each of the set of matched elements.\r
+ */\r
+ public Effects toggle(int millisecs, Function... f) {\r
+ return animate("opacity: 'toggle'", millisecs, f);\r
+ }\r
+}\r
--- /dev/null
+/*
+ * 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.query.client.plugins;
+
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.NativeEvent;
+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.JSArray;
+import com.google.gwt.query.client.Plugin;
+import com.google.gwt.user.client.Event;
+
+/**
+ * GQuery Plugin for handling and queuing browser events.
+ */
+public class Events extends GQuery {
+
+ public static final Class<Events> Events = Events.class;
+
+ static {
+ GQuery.registerPlugin(Events.class, new Plugin<Events>() {
+ public Events init(GQuery gq) {
+ return new Events(gq.get());
+ }
+ });
+ }
+
+ public Events(Element element) {
+ super(element);
+ }
+
+ public Events(JSArray elements) {
+ super(elements);
+ }
+
+ public Events(NodeList<Element> list) {
+ super(list);
+ }
+
+ /**
+ * 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()) {
+ EventsListener.getInstance(e).bind(eventbits, data, funcs);
+ }
+ return this;
+ }
+
+ /**
+ * 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) {
+ for (Element e : elements()) {
+ EventsListener.getInstance(e).bind(eventbits, data, f, 1);
+ }
+ return this;
+ }
+
+ /**
+ * 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) {
+ if ((eventbits | Event.ONBLUR) == Event.ONBLUR)
+ dispatchEvent(document.createBlurEvent());
+ if ((eventbits | Event.ONCHANGE) == Event.ONCHANGE)
+ dispatchEvent(document.createChangeEvent());
+ if ((eventbits | Event.ONCLICK) == Event.ONCLICK)
+ dispatchEvent(document.createClickEvent(0, 0, 0, 0, 0, false, false, false, false));
+ if ((eventbits | Event.ONDBLCLICK) == Event.ONDBLCLICK)
+ dispatchEvent(document.createDblClickEvent(0, 0, 0, 0, 0, false, false, false, false));
+ if ((eventbits | Event.ONFOCUS) == Event.ONFOCUS)
+ dispatchEvent(document.createFocusEvent());
+ if ((eventbits | Event.ONKEYDOWN) == Event.ONKEYDOWN)
+ dispatchEvent(document.createKeyDownEvent(false, false, false, false, keys[0], 0));
+ if ((eventbits | Event.ONKEYPRESS) == Event.ONKEYPRESS)
+ dispatchEvent(document.createKeyPressEvent(false, false, false, false, keys[0], 0));
+ if ((eventbits | Event.ONKEYUP) == Event.ONKEYUP)
+ dispatchEvent(document.createKeyUpEvent(false, false, false, false, keys[0], 0));
+ if ((eventbits | Event.ONLOSECAPTURE) == Event.ONLOSECAPTURE)
+ triggerHtmlEvent("losecapture");
+ if ((eventbits | Event.ONMOUSEDOWN) == Event.ONMOUSEDOWN)
+ dispatchEvent(document.createMouseDownEvent(0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT));
+ if ((eventbits | Event.ONMOUSEMOVE) == Event.ONMOUSEMOVE)
+ dispatchEvent(document.createMouseMoveEvent(0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT));
+ if ((eventbits | Event.ONMOUSEOUT) == Event.ONMOUSEOUT)
+ dispatchEvent(document.createMouseOutEvent(0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT, null));
+ if ((eventbits | Event.ONMOUSEOVER) == Event.ONMOUSEOVER)
+ dispatchEvent(document.createMouseOverEvent(0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT, null));
+ if ((eventbits | Event.ONMOUSEUP) == Event.ONMOUSEUP)
+ dispatchEvent(document.createMouseUpEvent(0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT));
+ if ((eventbits | Event.ONSCROLL) == Event.ONSCROLL)
+ dispatchEvent(document.createScrollEvent());
+ if ((eventbits | Event.ONERROR) == Event.ONERROR)
+ dispatchEvent(document.createErrorEvent());
+ if ((eventbits | Event.ONMOUSEWHEEL) == Event.ONMOUSEWHEEL)
+ dispatchEvent(document.createMouseEvent("mousewheel", true, true, 0, 0, 0, 0, 0, false, false, false, false, NativeEvent.BUTTON_LEFT, null));
+ return this;
+ }
+
+ /**
+ * Trigger a html event in all matched elements.
+ *
+ * @param htmlEvent
+ * An string representing the html event desired
+ */
+ public Events triggerHtmlEvent(String htmlEvent) {
+ dispatchEvent(document.createHtmlEvent(htmlEvent, false, false));
+ return this;
+ }
+
+ /**
+ * Removes all handlers, that matches the events bits passed, from each
+ * element.
+ *
+ * Example: unbind(Event.ONCLICK | Event.ONMOUSEOVER)
+ */
+ public Events unbind(int eventbits) {
+ for (Element e : elements()) {
+ EventsListener.getInstance(e).unbind(eventbits);
+ }
+ return this;
+ }
+
+ private void dispatchEvent(NativeEvent evt) {
+ for (Element e : elements()) {
+ e.dispatchEvent(evt);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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
+ * 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.query.client.Function;
+import com.google.gwt.query.client.JsObjectArray;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.EventListener;
+
+/**
+ * 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.
+ */
+class EventsListener implements EventListener {
+
+ private static class BindFunction {
+
+ Object data;
+
+ Function function;
+
+ int times = -1;
+
+ int type;
+
+ BindFunction(int t, Function f, Object d) {
+ type = t;
+ function = f;
+ data = d;
+ }
+
+ BindFunction(int t, Function f, Object d, int times) {
+ this(t, f, d);
+ this.times = times;
+ }
+
+ public boolean fire(Event event) {
+ if (times != 0) {
+ times--;
+ return function.f(event, data);
+ }
+ return true;
+ }
+
+ public boolean hasEventType(int etype) {
+ return (type | etype) == type;
+ }
+ }
+
+ public static EventsListener getInstance(Element e) {
+ EventsListener ret = getGQueryEventLinstener(e);
+ return ret != null ? ret : new EventsListener(e);
+ }
+
+ private static native EventsListener getGQueryEventLinstener(Element elem) /*-{
+ return elem.__gqueryevent;
+ }-*/;
+
+ private static native EventListener getOriginalEventListener(Element elem) /*-{
+ return elem.__listener;
+ }-*/;
+
+ private static native void setFocusable(Element elem) /*-{
+ elem.tabIndex = 0;
+ }-*/;
+
+ private static native void setGQueryEventListener(Element elem,
+ EventsListener gqevent) /*-{
+ elem.__gqueryevent = gqevent;
+ }-*/;
+
+ private Element element;
+
+ private JsObjectArray<EventsListener.BindFunction> elementEvents = JsObjectArray
+ .createArray().cast();
+ private EventListener originalEventListener;
+
+ private EventsListener(Element element) {
+ this.element = element;
+ originalEventListener = getOriginalEventListener(element);
+ setGQueryEventListener(element, this);
+ DOM.setEventListener((com.google.gwt.user.client.Element) element, this);
+ }
+
+ public void bind(int eventbits, final Object data, Function...funcs) {
+ for (Function function: funcs) {
+ bind(eventbits, data, function, -1);
+ }
+ }
+
+ public void bind(int eventbits, final Object data, final Function function,
+ int times) {
+ if (function == null) {
+ unbind(eventbits);
+ } else {
+ DOM.sinkEvents((com.google.gwt.user.client.Element) element, eventbits
+ | DOM.getEventsSunk((com.google.gwt.user.client.Element) element));
+
+ if ((eventbits | Event.FOCUSEVENTS) == Event.FOCUSEVENTS) {
+ setFocusable(element);
+ }
+
+ elementEvents.add(new EventsListener.BindFunction(eventbits, function,
+ data, times));
+ }
+ }
+
+ double lastEvnt=0;
+ int lastType=0;
+
+ public void onBrowserEvent(Event event) {
+ // Workaround for Issue_20
+ if (lastType == event.getTypeInt()
+ && lastEvnt - Duration.currentTimeMillis() < 10
+ && "body".equalsIgnoreCase(element.getTagName())) {
+ return;
+ }
+ lastEvnt = Duration.currentTimeMillis();
+ lastType = event.getTypeInt();
+
+ if (originalEventListener != null) {
+ originalEventListener.onBrowserEvent(event);
+ }
+
+ int etype = DOM.eventGetType(event);
+ for (int i = 0; i < elementEvents.length(); i++) {
+ EventsListener.BindFunction listener = elementEvents.get(i);
+ if (listener.hasEventType(etype)) {
+ if (!listener.fire(event)) {
+ event.stopPropagation();
+ event.preventDefault();
+ }
+ }
+ }
+ }
+
+ public void unbind(int eventbits) {
+ JsObjectArray<EventsListener.BindFunction> newList = JsObjectArray
+ .createArray().cast();
+ for (int i = 0; i < elementEvents.length(); i++) {
+ EventsListener.BindFunction listener = elementEvents.get(i);
+ if (!listener.hasEventType(eventbits)) {
+ newList.add(listener);
+ }
+ }
+ elementEvents = newList;
+ }
+}
--- /dev/null
+/*
+ * 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.query.client.plugins;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+import com.google.gwt.dom.client.Element;
+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.JSArray;
+
+/**
+ * Class used in plugins which need a queue system.
+ */
+public abstract class GQueryQueue extends GQuery {
+
+ public GQueryQueue(Element element) {
+ super(element);
+ }
+
+ public GQueryQueue(GQuery gq) {
+ super(gq);
+ }
+
+ public GQueryQueue(JSArray elements) {
+ super(elements);
+ }
+
+ public GQueryQueue(NodeList<Element> list) {
+ super(list);
+ }
+
+ /**
+ * Removes a queued function from the front of the queue and executes it.
+ */
+ public GQueryQueue dequeue() {
+ for (Element e : elements()) {
+ dequeue(e);
+ }
+ return this;
+ }
+
+
+ /**
+ * Adds a new function, to be executed, onto the end of the queue of all
+ * matched elements.
+ */
+ public GQueryQueue queue(Function func) {
+ for (Element e : elements()) {
+ queue(e, func);
+ }
+ return this;
+ }
+
+ /**
+ * Replaces the current queue with the given queue on all matched elements.
+ */
+ public GQueryQueue queue(Queue<?> queue) {
+ for (Element e : elements()) {
+ replacequeue(e, queue);
+ }
+ return this;
+ }
+
+ protected String getQueueType() {
+ return "GQueryQueue_" + this.getClass().getName();
+ }
+
+ private void dequeue(Element elem) {
+ Queue<?> q = queue(elem, null);
+ if (q != null) {
+ q.poll();
+ Object f = q.peek();
+ if (f != null) {
+ if (f instanceof Function) {
+ ((Function)f).f(elem);
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private <S> Queue<S> queue(Element elem, S func) {
+ if (elem != null) {
+ Queue<S> q = (Queue<S>) data(elem, getQueueType(), null);
+ if (q == null) {
+ q = (Queue<S>) data(elem, getQueueType(), new LinkedList<S>());
+ }
+ if (func != null) {
+ q.add(func);
+ }
+ if (q.size() == 1 && func != null) {
+ if (func instanceof Function) {
+ ((Function)func).f(elem);
+ }
+ }
+ return q;
+ }
+ return null;
+ }
+
+ private void replacequeue(Element elem, Queue<?> queue) {
+ if (elem != null) {
+ data(elem, getQueueType(), queue);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.query.client.plugins;
+import com.google.gwt.dom.client.Element;
+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.JSArray;
+import com.google.gwt.query.client.Plugin;
+import com.google.gwt.query.client.Properties;
+import com.google.gwt.query.client.plugins.ClipAnimation.Action;
+import com.google.gwt.query.client.plugins.ClipAnimation.Direction;
+import com.google.gwt.query.client.plugins.PropertiesAnimation.Easing;
+import com.google.gwt.query.client.LazyBase;
+
+public interface LazyEffects<T> extends LazyBase<T>{
+
+ /**
+ * The animate() method allows us to create animation effects on any numeric CSS property.
+ * The only required parameter is a map of CSS properties.
+ * This map is similar to the one that can be sent to the .css() method,
+ * except that the range of properties is more restrictive.
+ * All animated properties should be numeric, non-numeric cannot be animated using basic functionality.
+ * (For example, width, height, or left can be animated but background-color cannot be.)
+ * Property values are treated as a number of pixels unless otherwise specified.
+ * The units em and % can be specified where applicable.
+ *
+ * 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.
+ */
+ LazyEffects<T> animate(Properties p, int duration, Easing easing, Function... funcs);
+
+ /**
+ * The animate() method allows us to create animation effects on any numeric CSS property.
+ * The only required parameter is a map of CSS properties.
+ * This map is similar to the one that can be sent to the .css() method,
+ * except that the range of properties is more restrictive.
+ * All animated properties should be numeric, non-numeric cannot be animated using basic functionality.
+ * (For example, width, height, or left can be animated but background-color cannot be.)
+ * Property values are treated as a number of pixels unless otherwise specified.
+ * The units em and % can be specified where applicable.
+ *
+ * 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.
+ */
+ LazyEffects<T> animate(String prop, Function... funcs);
+
+ /**
+ * The animate() method allows us to create animation effects on any numeric CSS property.
+ * The only required parameter is a map of CSS properties.
+ * This map is similar to the one that can be sent to the .css() method,
+ * except that the range of properties is more restrictive.
+ * All animated properties should be numeric, non-numeric cannot be animated using basic functionality.
+ * (For example, width, height, or left can be animated but background-color cannot be.)
+ * Property values are treated as a number of pixels unless otherwise specified.
+ * The units em and % can be specified where applicable.
+ *
+ * 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.
+ */
+ LazyEffects<T> animate(String prop, int duration, Function... 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.
+ */
+ LazyEffects<T> clip(ClipAnimation.Action a, ClipAnimation.Corner c, ClipAnimation.Direction d, Function... 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.
+ */
+ LazyEffects<T> clip(ClipAnimation.Action a, ClipAnimation.Corner c, ClipAnimation.Direction d, int duration, Function... 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.
+ */
+ LazyEffects<T> clip(ClipAnimation.Action a, ClipAnimation.Corner c, Function... 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.
+ */
+ LazyEffects<T> clipAppear(Function... 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.
+ */
+ LazyEffects<T> clipAppear(int millisecs, Function... 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.
+ */
+ LazyEffects<T> clipDisappear(Function... 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.
+ */
+ LazyEffects<T> clipDisappear(int millisecs, Function... 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.
+ */
+ LazyEffects<T> clipDown(Function... 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.
+ */
+ LazyEffects<T> clipDown(int millisecs, Function... 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.
+ */
+ LazyEffects<T> clipUp(Function... 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.
+ */
+ LazyEffects<T> clipUp(int millisecs, Function... 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.
+ */
+ LazyEffects<T> fadeIn(Function... 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.
+ */
+ LazyEffects<T> fadeIn(int millisecs, Function... 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.
+ */
+ LazyEffects<T> fadeOut(Function... 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.
+ */
+ LazyEffects<T> fadeOut(int millisecs, Function... 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.
+ */
+ LazyEffects<T> fadeTo(int millisecs, double opacity, Function... f);
+
+ /**
+ * Reveal all matched elements by adjusting their height and firing an
+ * optional callback after completion.
+ */
+ LazyEffects<T> slideDown(Function... f);
+
+ /**
+ * Reveal all matched elements by adjusting their height and firing an
+ * optional callback after completion.
+ */
+ LazyEffects<T> slideDown(int millisecs, Function... f);
+
+ /**
+ * Hide all matched elements by adjusting their width and firing an optional
+ * callback after completion.
+ */
+ LazyEffects<T> slideLeft(Function... f);
+
+ /**
+ * Hide all matched elements by adjusting their width and firing an optional
+ * callback after completion.
+ */
+ LazyEffects<T> slideLeft(int millisecs, Function... f);
+
+ /**
+ * Reveal all matched elements by adjusting their width and firing an
+ * optional callback after completion.
+ */
+ LazyEffects<T> slideRight(Function... f);
+
+ /**
+ * Reveal all matched elements by adjusting their width and firing an
+ * optional callback after completion.
+ */
+ LazyEffects<T> slideRight(int millisecs, Function... 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
+ */
+ LazyEffects<T> slideToggle(int millisecs, Function... f);
+
+ /**
+ * Hide all matched elements by adjusting their height and firing an optional
+ * callback after completion.
+ */
+ LazyEffects<T> slideUp(Function... f);
+
+ /**
+ * Hide all matched elements by adjusting their height and firing an optional
+ * callback after completion.
+ */
+ LazyEffects<T> slideUp(int millisecs, Function... f);
+
+ /**
+ * Toggle displaying each of the set of matched elements.
+ */
+ LazyEffects<T> toggle();
+
+ /**
+ * Toggle displaying each of the set of matched elements.
+ */
+ LazyEffects<T> toggle(int millisecs, Function... f);
+
+}
--- /dev/null
+/*
+ * 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.query.client.plugins;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.NativeEvent;
+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.JSArray;
+import com.google.gwt.query.client.Plugin;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.query.client.LazyBase;
+
+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 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
+ */
+ LazyEvents<T> triggerHtmlEvent(String htmlEvent);
+
+ /**
+ * Removes all handlers, that matches the events bits passed, from each
+ * element.
+ *
+ * Example: unbind(Event.ONCLICK | Event.ONMOUSEOVER)
+ */
+ LazyEvents<T> unbind(int eventbits);
+
+}
--- /dev/null
+/*\r
+ * Copyright 2009 Google Inc.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
+ * use this file except in compliance with the License. You may obtain a copy of\r
+ * the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
+ * License for the specific language governing permissions and limitations under\r
+ * the License.\r
+ */\r
+package com.google.gwt.query.client.plugins;\r
+\r
+import java.util.ArrayList;\r
+\r
+import com.google.gwt.animation.client.Animation;\r
+import com.google.gwt.dom.client.Element;\r
+import com.google.gwt.query.client.Function;\r
+import com.google.gwt.query.client.JSArray;\r
+import com.google.gwt.query.client.Properties;\r
+import com.google.gwt.query.client.Regexp;\r
+\r
+/**\r
+ * Animation effects on any numeric CSS property. \r
+ */\r
+public class PropertiesAnimation extends Animation {\r
+\r
+ /**\r
+ * Easing method to use.\r
+ */\r
+ public enum Easing {\r
+ LINEAR, SWING\r
+ }\r
+ \r
+ private static class Effect {\r
+ private static Regexp nonPx = new Regexp(\r
+ "z-?index|font-?weight|opacity|zoom|line-?height", "i");\r
+\r
+ public String attr;\r
+ public double end;\r
+ public String old;\r
+ public double start;\r
+ public String unit;\r
+ public String value;\r
+\r
+ Effect(String attr, String value, String old, double start, double end,\r
+ String unit) {\r
+ this.attr = attr;\r
+ this.value = value;\r
+ this.old = old;\r
+ this.start = start;\r
+ this.end = end;\r
+ this.unit = nonPx.test(attr) ? "" : unit == null ? "px" : unit;\r
+ }\r
+\r
+ public String getVal(double progress) {\r
+ double ret = (start + ((end - start) * progress));\r
+ return ("px".equals(unit) ? ((int) ret) : ret) + unit;\r
+ }\r
+ }\r
+\r
+ private static final String[] attrsToSave = new String[] { "overflow",\r
+ "visivility", "white-space" };\r
+ private Element e;\r
+ private Easing easing = Easing.SWING;\r
+ private ArrayList<Effect> effects = new ArrayList<Effect>();\r
+ private Function[] funcs;\r
+ private Effects g;\r
+\r
+ private Properties prps;\r
+\r
+ public PropertiesAnimation(Easing easing, Element elem, Properties p,\r
+ Function... funcs) {\r
+ this.easing = easing;\r
+ this.e = elem;\r
+ this.funcs = funcs;\r
+ this.prps = p;\r
+ g = Effects.$(e).as(Effects.Effects);\r
+ }\r
+\r
+ @Override\r
+ public void onCancel() {\r
+ onComplete();\r
+ }\r
+\r
+ @Override\r
+ public void onComplete() {\r
+ super.onComplete();\r
+ g.restoreCssAttrs(attrsToSave);\r
+ for (Effect l : effects) {\r
+ if ("hide".equals(l.value)) {\r
+ g.hide();\r
+ g.css(l.attr, l.old);\r
+ } else if ("show".equals(l.value)) {\r
+ g.show();\r
+ g.css(l.attr, l.old);\r
+ }\r
+ }\r
+ g.each(funcs);\r
+ g.dequeue();\r
+ }\r
+\r
+ @Override\r
+ public void onStart() {\r
+ boolean hidden = !g.visible();\r
+ g.show();\r
+ for (String key : prps.keys()) {\r
+ String val = prps.get(key);\r
+ if ("toggle".equals(val)) {\r
+ val = hidden ? "show" : "hide";\r
+ }\r
+ if (("top".equals(key) || "left".equals(key))\r
+ && !"absolute".equalsIgnoreCase(g.css("position"))) {\r
+ g.css("position", "relative");\r
+ }\r
+\r
+ JSArray parts = new Regexp("^([+-]=)?([0-9+-.]+)(.*)?$").match(val);\r
+ String unit = parts != null ? parts.getStr(3) : "";\r
+ double start = Effects.cur(e, key);\r
+ double end = start;\r
+ if (parts != null) {\r
+ end = Double.parseDouble(parts.getStr(2));\r
+ if (parts.getStr(1) != null) {\r
+ end = (("-=".equals(parts.getStr(1)) ? -1 : 1) * end) + start;\r
+ }\r
+ } else if ("show".equals(val)) {\r
+ if (!hidden) {\r
+ return;\r
+ }\r
+ start = 0;\r
+ } else if ("hide".equals(val)) {\r
+ if (hidden) {\r
+ return;\r
+ }\r
+ end = 0;\r
+ }\r
+ effects.add(new Effect(key, val, g.css(key), start, end, unit));\r
+ }\r
+ g.saveCssAttrs(attrsToSave);\r
+ g.css("overflow", "hidden");\r
+ g.css("visivility", "visible");\r
+ g.css("white-space", "nowrap");\r
+ super.onStart();\r
+ }\r
+\r
+ @Override\r
+ public void onUpdate(double progress) {\r
+ for (Effect fx : effects) {\r
+ g.css(fx.attr, fx.getVal(progress));\r
+ }\r
+ }\r
+\r
+ @Override\r
+ protected double interpolate(double progress) {\r
+ if (easing == Easing.SWING) {\r
+ return super.interpolate(progress);\r
+ } else {\r
+ return progress;\r
+ }\r
+ }\r
+\r
+}\r
+++ /dev/null
-package com.google.gwt.query.client.plugins;
-
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.dom.client.Element;
-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.JSArray;
-import com.google.gwt.query.client.Plugin;
-import com.google.gwt.query.client.Properties;
-import com.google.gwt.query.client.Regexp;
-import com.google.gwt.query.client.SelectorEngine;
-import com.google.gwt.user.client.Event;
-
-/**
- * Star Rating plugin.
- */
-public class Ratings extends GQuery {
-
- private static int calls;
-
- /**
- * Used to register the plugin.
- */
- private static class RatingsPlugin implements Plugin<Ratings> {
-
- public Ratings init(GQuery gq) {
- return new Ratings(gq.get());
- }
- }
-
- public static final Class<Ratings> Ratings = Ratings.class;
-
- static {
- GQuery.registerPlugin(Ratings.class, new RatingsPlugin());
- }
-
- public Ratings(Element element) {
- super(element);
- }
-
- public Ratings(JSArray elements) {
- super(elements);
- }
-
- public Ratings(NodeList<Element> list) {
- super(list);
- }
-
- public Ratings rating() {
- if (size() == 0) {
- return this;
- }
- calls++;
- not(".star-rating-applied").addClass("star-rating-applied");
- Control control = null;
- for (Element e : elements()) {
- GQuery input = $(e);
- String eid = SelectorEngine
- .or(e.getPropertyString("name"), "unnamed-rating")
- .replaceAll("\\[|\\]", "_").replaceAll("^\\_+|\\_$", "");
- GQuery context = $(getContext(e));
- Raters raters = (Raters) context.data("rating");
- if (raters == null || raters.getCalls() != calls) {
- raters = new Raters(0, calls);
- }
- GQuery rater = raters.get(eid);
- if (rater != null) {
- control = (Control) rater.data("rating");
- }
- if (rater != null && control != null) {
- control.bumpCount();
- } else {
- control = new Control();
- control.setSerial(raters.bumpCount());
- Properties metadata = getMetaData(input.get(0).getClassName());
- if (metadata != null && metadata.defined("split")) {
- control.setSplit(metadata.getInt("split"));
- }
- // create rating element
- rater = $("<span class=\"star-rating-control\"/>");
- input.before(rater);
-
- // Mark element for initialization (once all stars are ready)
- rater.addClass("rating-to-be-drawn");
-
- // Accept readOnly setting from 'disabled' property
- if (SelectorEngine.truth(input.attr("disabled"))) {
- control.setReadOnly(true);
- }
-
- // Create 'cancel' button
- GQuery query = $(
- "<div class=\"rating-cancel\"><a title=\"" + control.cancel + "\">"
- + control.cancelValue + "</a></div>").
- mouseover(new Function() {
- @Override
- public boolean f(Event e) {
- $(e).as(Ratings).drain();
- $(e).addClass("star-rating-hover");
- return true;
- }
- }).
- mouseout(new Function() {
- @Override
- public boolean f(Event e) {
- $(e).as(Ratings).draw();
- $(e).removeClass("star-rating-hover");
- return true;
- }
- }).
- click(new Function() {
- @Override
- public boolean f(Event e) {
- $(e).as(Ratings).selectStar();
- return true;
- }
- });
- control.cancelButton = query;
- query.data("rating", control);
- rater.append(query);
- }
- // insert rating star
- GQuery star = $("<div class=\"star-rating rater-" + control.getSerial()
- + "\"><a title=\""
- + (SelectorEngine.or(e.getTitle(), e.getPropertyString("value")))
- + "\">" + e.getPropertyString("value") + "</a></div>");
- rater.append(star);
-
- // inherit attributes from input element
- if (e.getId() != null) {
- star.attr("id", e.getId());
- }
- if (e.getClassName() != null) {
- star.addClass(e.getClassName());
- }
-
- // Half-stars?
- if (control.isHalf()) {
- control.setSplit(2);
- }
-
- // Prepare division control
- if (control.getSplit() > 0) {
- int stw = star.width();
- if (stw == 0) {
- stw = control.getStarWidth();
- }
-
- int spi = (control.getCount() % control.getSplit());
- int spw = (int) Math.floor(stw / control.getSplit());
-
- star.width(spw).find("a").css("margin-left", "-" + (spi * spw) + "px");
- }
- ;
-
- // readOnly?
- if (control.isReadOnly())//{ //save a byte!
- // Mark star as readOnly so user can customize display
- {
- star.addClass("star-rating-readonly");
- }
- //} //save a byte!
- else//{ //save a byte!
- // Enable hover css effects
- {
- star.addClass("star-rating-live")
- // Attach mouse events
- .mouseover(new Function() {
- @Override
- public boolean f(Event e) {
- $(e).as(Ratings).fill();
- $(e).as(Ratings).focusStar();
- return true;
- }
- }).mouseout(new Function() {
- @Override
- public boolean f(Event e) {
- $(e).as(Ratings).draw();
- $(e).as(Ratings).blurStar();
-
- return true;
- }
- }).click(new Function() {
- @Override
- public boolean f(Event e) {
- $(e).as(Ratings).selectStar();
- return true;
- }
- });
- }
- // set current selection
- if (e.getPropertyBoolean("checked")) {
- control.setCurrent(star);
- }
-
- // hide input element
- input.hide();
-
- // backward compatibility, form element to plugin
- input.change(new Function() {
- @Override
- public boolean f(Event e) {
- $(e).as(Ratings).selectStar();
- return true;
- }
- });
-
- // attach reference to star to input element and vice-versa
- star.data("rating.input", input.data("rating.star", star));
-
- // store control information in form (or body when form not available)
- control.addStar(star.get(0));
- control.addInput(input.get(0));
- control.setRater(rater);
- raters.put(eid, rater);
- control.setContext(context);
-
- input.data("rating", control);
- rater.data("rating", control);
- star.data("rating", control);
- context.data("rating", raters);
- }
- // Initialize ratings (first draw)
- $(".rating-to-be-drawn").as(Ratings).draw()
- .removeClass("rating-to-be-drawn");
-
- return this;
- }
-
- private Properties getMetaData(String className) {
- if (className.indexOf("{") == -1) {
- return Properties.createObject().cast();
- }
- Regexp re = new Regexp("{(.*)}");
- JSArray match = re.exec(className);
- if (match != null && match.size() > 1) {
- return Properties.create(match.getStr(1));
- }
- return Properties.createObject().cast();
- }
-
- public Ratings blurStar() {
- return this;
- }
-
- public Ratings focusStar() {
- Control control = (Control) this.data("rating");
- if (control == null) {
- return this;
- }
-// GQuery input = data("rating.input");
- return this;
- }
-
- public Ratings fill() {
- for (Element e : elements()) {
- GQuery self = $(e);
- Control control = nullControlIfShouldSkipStar(self);
- if (control == null) {
- continue;
- }
-
- // Reset all stars and highlight them up to this element
- self.as(Ratings).drain();
- self.prevAll().andSelf().filter(".rater-" + control.getSerial())
- .addClass("star-rating-hover");
-
- }
-
- return this;
- }
-
- public Ratings draw() {
- for (Element e : elements()) {
- GQuery self = $(e);
- Control control = nullControlIfShouldSkipStar(self);
- if (control == null) {
- continue;
- }
-
- // Clear all stars
- self.as(Ratings).drain();
- // Set control value
- if (control.getCurrent() != null) {
- ((GQuery) control.current.data("rating.input"))
- .attr("checked", "checked");
- control.current.prevAll().andSelf().filter(".rater-" + control.serial)
- .addClass("star-rating-on");
- } else {
- $(control.getInputs()).removeAttr("checked");
- }
-
- // Show/hide 'cancel' button
-// control.cancel[control.readOnly || control.required?'hide':'show']();
- // Add/remove read-only classes to remove hand pointer
- self.siblings().toggleClass("star-rating-readonly", control.isReadOnly());
- }
-
- return this;
- }
-
- public Ratings selectStar(int value) {
- for (Element e : elements()) {
- GQuery self = $(e);
- Control control = nullControlIfShouldSkipStar(self);
- if (control == null) {
- continue;
- }
-
- control.setCurrent(null);
- $(control.getStar(value)).as(Ratings).selectStar();
- }
- return this;
- }
-
- public Ratings selectStar() {
- for (Element e : elements()) {
- GQuery self = $(e);
- Control control = nullControlIfShouldSkipStar(self);
- if (control == null) {
- continue;
- }
-
- control.current = self.get(0).getTagName().equalsIgnoreCase("INPUT")
- ? (GQuery) self.data("rating.star")
- : self.is(".rater-" + control.getSerial()) ? this : null;
-
- // Update rating control state
- self.data("rating", control);
- // Update display
- self.as(Ratings).draw();
- // find data for event
- GQuery input = $(control.current != null ? (GQuery) control.current
- .data("rating.input") : null);
- // click callback, as requested here: http://plugins.jquery.com/node/1655
-// if(control.callback) control.callback.apply(input[0], [input.val(), $('a', control.current)[0]]);// callback event
- }
-
- return this;
- }
-
- private Control nullControlIfShouldSkipStar(GQuery q) {
- Control control = (Control) q.data("rating");
- if (control == null) {
- return null;
- }
- // do not execute when control is in read-only mode
- if (control.isReadOnly()) {
- return null;
- }
- return control;
- }
-
- public Ratings selectStar(String value) {
- for (Element e : elements()) {
- GQuery self = $(e);
- Control control = nullControlIfShouldSkipStar(self);
- if (control == null) {
- continue;
- }
- control.setCurrent(null);
- NodeList<Element> stars = control.getStars();
- for (int i = 0; i < stars.getLength(); i++) {
- String val = ((GQuery) $(stars.getItem(i)).data("rating.input")).val();
- if (val != null && val.equals(value)) {
- $(stars.getItem(i)).as(Ratings).selectStar();
- }
- }
- }
- return this;
- }
-
- public Ratings drain() {
- for (Element e : elements()) {
- GQuery self = $(e);
- Control control = nullControlIfShouldSkipStar(self);
- if (control == null) {
- continue;
- }
- control.rater.children().filter(".rater-" + control.getSerial())
- .removeClass("star-rating-on").removeClass("star-rating-hover");
- }
- return this;
- }
-
- public static class Control {
-
- private int count;
-
- private String cancel = "Cancel Rating";
-
- private String cancelValue = "";
-
- private int split = 0;
-
- private int starWidth = 16;
-
- private int serial;
-
- private boolean readOnly;
-
- private boolean half;
-
- private GQuery current;
-
- private GQuery context;
-
- private JsArray<Element> stars = JsArray.createArray().cast();
-
- private JsArray<Element> inputs = JsArray.createArray().cast();
-
- private GQuery rater;
-
- public GQuery cancelButton;
-
- public int bumpCount() {
- return count++;
- }
-
- public void setSerial(int serial) {
- this.serial = serial;
- }
-
- public void setReadOnly(boolean readOnly) {
- this.readOnly = readOnly;
- }
-
- public int getSerial() {
- return serial;
- }
-
- public boolean isHalf() {
- return half;
- }
-
- public void setSplit(int split) {
- this.split = split;
- }
-
- public int getSplit() {
- return split;
- }
-
- public int getStarWidth() {
- return starWidth;
- }
-
- public int getCount() {
- return count;
- }
-
- public boolean isReadOnly() {
- return readOnly;
- }
-
- public void setCurrent(GQuery current) {
- this.current = current;
- }
-
- public void setContext(GQuery context) {
- this.context = context;
- }
-
- public void addStar(Element element) {
- stars.set(stars.length(), element);
- }
-
- public void addInput(Element element) {
- inputs.set(inputs.length(), element);
- }
-
- public void setRater(GQuery rater) {
- this.rater = rater;
- }
-
- public Object getCurrent() {
- return current;
- }
-
- public NodeList<Element> getInputs() {
- return inputs.cast();
- }
-
- public Element getStar(int value) {
- return stars.get(value);
- }
-
- public NodeList<Element> getStars() {
- return stars.cast();
- }
- }
-
- public static class Raters {
-
- private int calls;
-
- private int count;
-
- private GQuery.DataCache cache = GQuery.DataCache.createObject().cast();
-
- public Raters(int count, int calls) {
- this.count = count;
- this.calls = calls;
- }
-
- public int getCalls() {
- return calls;
- }
-
- public GQuery get(String eid) {
- return (GQuery) cache.getObject(eid);
- }
-
- public void put(String eid, GQuery q) {
- cache.put(eid, q);
- }
-
- public int bumpCount() {
- return count++;
- }
- }
-
- private static native Element getContext(Element e) /*-{
- return this.form || $doc.body;
- }-*/;
-}
+++ /dev/null
-package com.google.gwt.query.client.plugins;
-
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.NodeList;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.query.client.GQuery;
-import com.google.gwt.query.client.JSArray;
-import com.google.gwt.query.client.Plugin;
-import com.google.gwt.user.client.ui.Button;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-/**
- * Experimental Gwt Query plugin for integrating Gwt Widgets.
- */
-public class Widgets extends GQuery {
-
- /**
- * Used to register the plugin.
- */
- private static class WidgetsPlugin implements Plugin<Widgets> {
-
- public Widgets init(GQuery gq) {
- return new Widgets(gq.get());
- }
- }
-
- public static final Class<Widgets> Widgets = Widgets.class;
-
- static {
- GQuery.registerPlugin(Widgets.class, new WidgetsPlugin());
- }
-
- public Widgets(Element element) {
- super(element);
- }
-
- public Widgets(JSArray elements) {
- super(elements);
- }
-
- public Widgets(NodeList list) {
- super(list);
- }
-
- /**
- * Create a builder capable of instantiating a GWT Button object over every
- * matched element. Call end() to execute builder and return to the current
- * query object.
- *
- * @return a ButtonBuilder
- */
- public ButtonBuilder button() {
- return new ButtonBuilder("*");
- }
-
- public class ButtonBuilder {
-
- private String selector;
-
- private String label = null;
-
- private String labelSelector = null;
-
- private Collection<ClickHandler> handlers = new ArrayList<ClickHandler>();
-
- public ButtonBuilder(String selector) {
- this.selector = selector;
- }
-
- public ButtonBuilder labelQuery(String label) {
- this.labelSelector = label;
- return this;
- }
-
- public ButtonBuilder label(String label) {
- this.label = label;
- return this;
- }
-
- public ButtonBuilder addClickHandler(ClickHandler handler) {
- handlers.add(handler);
- return this;
- }
-
- public Widgets end() {
- for (Element e : elements()) {
- Button b = null;
- if ("button".equalsIgnoreCase(e.getTagName())) {
- b = Button.wrap(e);
- } else {
- Element bElt = $("<button name='button' value='Click Me'>").get(0);
- $(e).hide().before(bElt);
- b = Button.wrap(bElt);
- }
-
- b.setText(label != null ? label
- : (labelSelector == null ? $(e) : $(labelSelector, e)).text());
- for (ClickHandler handler : handlers) {
- b.addClickHandler(handler);
- }
- }
- return Widgets.this;
- }
- }
-}
+++ /dev/null
-/* jQuery.Rating Plugin CSS - http://www.fyneworks.com/jquery/star-rating/ */
-div.rating-cancel,div.star-rating{float:left;width:17px;height:15px;text-indent:-999em;cursor:pointer;display:block;background:transparent;overflow:hidden}
-div.rating-cancel,div.rating-cancel a{background:url(delete.gif) no-repeat 0 -16px}
-div.star-rating,div.star-rating a{background:url(star.gif) no-repeat 0 0px}
-div.rating-cancel a,div.star-rating a{display:block;width:16px;height:100%;background-position:0 0px;border:0}
-div.star-rating-on a{background-position:0 -16px!important}
-div.star-rating-hover a{background-position:0 -32px}
-/* Read Only CSS */
-div.star-rating-readonly a{cursor:default !important}
-/* Partial Star CSS */
-div.star-rating{background:transparent!important;overflow:hidden!important}
-/* END jQuery.Rating Plugin CSS */
assertHtmlEquals(expected, $(e).html());
}
+ public void testShowHide() {
+ $(e)
+ .html(
+ "<p id='id1' style='display: inline'>Content 1</p><p id='id2'>Content 2</p><p id='id3'>Content 3</p>");
+
+ final GQuery sectA = $("#id1");
+ final GQuery sectB = $("#id2");
+ final GQuery sectC = $("#id3");
+
+ // hide()
+ sectA.hide();
+ assertEquals("none", sectA.css("display"));
+ sectB.hide();
+ assertEquals("none", sectB.css("display"));
+
+ // show()
+ sectA.show();
+ assertEquals("inline", sectA.css("display"));
+ sectB.show();
+ assertEquals("", sectB.css("display"));
+
+ // toggle()
+ assertEquals("", sectC.css("display"));
+ sectC.toggle();
+ assertEquals("none", sectC.css("display"));
+ sectC.toggle();
+ assertEquals("block", sectC.css("display"));
+ }
+
}
*/
package com.google.gwt.query.client;
-import static com.google.gwt.query.client.Effects.Effects;
-import static com.google.gwt.query.client.Effects.Easing.LINEAR;
import static com.google.gwt.query.client.GQuery.$;
import static com.google.gwt.query.client.GQuery.$$;
import com.google.gwt.dom.client.Element;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.query.client.GQuery.Offset;
+import com.google.gwt.query.client.plugins.Effects;
+import com.google.gwt.query.client.plugins.PropertiesAnimation.Easing;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
}
}
- public void testEffects() {
+ public void testFade() {
$(e)
- .html(
- "<p id='id1'>Content 1</p><p id='id2'>Content 2</p><p id='id3'>Content 3</p>");
+ .html(
+ "<p id='id1' style='display: inline'>Content 1</p><p id='id2'>Content 2</p><p id='id3'>Content 3</p>");
final GQuery sectA = $("#id1");
final GQuery sectB = $("#id2");
- final GQuery sectC = $("#id3");
-
- // hide()
- sectA.hide();
- assertEquals("none", sectA.css("display"));
-
- // show()
- sectB.show();
- assertEquals("", sectB.css("display"));
-
- // toggle()
- assertEquals("", sectC.css("display"));
- sectC.toggle();
- assertEquals("none", sectC.css("display"));
- sectC.toggle();
- assertEquals("", sectC.css("display"));
-
+
// fadeIn() & fadeOut() are tested with delayed assertions
+ sectA.hide();
sectA.fadeIn(2000);
sectB.fadeOut(2000);
};
Timer timerMidTime = new Timer() {
public void run() {
- assertEquals("", sectA.css("display"));
+ assertEquals("inline", sectA.css("display"));
assertEquals("", sectB.css("display"));
double o = Double.valueOf(sectA.css("opacity"));
assertTrue(
};
Timer timerLongTime = new Timer() {
public void run() {
- assertEquals("", sectA.css("display"));
+ assertEquals("inline", sectA.css("display"));
assertEquals("none", sectB.css("display"));
// Last delayed assertion has to stop the test to avoid a timeout
// failure
finishTest();
}
};
+
// schedule the delayed assertions
timerShortTime.schedule(200);
timerMidTime.schedule(1200);
- timerLongTime.schedule(2200);
- }
+ timerLongTime.schedule(2200);
+ }
public void testEffectsShouldBeQueued() {
$(e).html("<p id='idtest'>Content 1</p></p>");
final GQuery g = $("#idtest").css("position", "absolute");
final Offset o = g.offset();
- g.as(Effects).
- animate($$("left: '+=100'"), 400, LINEAR, null).
- animate($$("top: '+=100'"), 400, LINEAR, null).
- animate($$("left: '-=100'"), 400, LINEAR, null).
- animate($$("top: '-=100'"), 400, LINEAR, null);
-
+ g.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);
// Configure the max duration for this test
delayTestFinish(400 * 4);
// each timer calls the next one
final Timer timer1 = new Timer() {
public void run() {
- assertPosition(g, o.add(99, 0), o.add(1, 0));
+ assertPosition(g, o.add(0, 99), o.add(0, 1));
// Last timer should finish the test
finishTest();
}
};
final Timer timer2 = new Timer() {
public void run() {
- assertPosition(g, o.add(100, 99), o.add(100, 1));
+ assertPosition(g, o.add(99, 100), o.add(1, 100));
timer1.schedule(400);
}
};
final Timer timer3 = new Timer() {
public void run() {
- assertPosition(g, o.add(1, 100), o.add(99, 100));
+ assertPosition(g, o.add(100, 1), o.add(100, 99));
timer2.schedule(400);
}
};
final Timer timer4 = new Timer() {
public void run() {
- assertPosition(g, o.add(0, 1), o.add(0, 99));
+ assertPosition(g, o.add(1, 0), o.add(99, 0));
timer3.schedule(400);
}
};
import com.google.gwt.junit.Platform;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.query.client.css.CSS;
+import com.google.gwt.query.client.plugins.Events;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NodeList;
-import com.google.gwt.query.client.Effects;
import com.google.gwt.query.client.Function;
import com.google.gwt.query.client.GQuery;
import com.google.gwt.query.client.Plugin;
+import com.google.gwt.query.client.plugins.Effects;
import com.google.gwt.user.client.Event;
/**
<logLevel>${gwt.loglevel}</logLevel>
<style>${gwt.outputstyle}</style>
<gwtVersion>${gwtversion}</gwtVersion>
+ <soyc>true</soyc>
<modules>
- <module>
- gwtquery.samples.GwtQuerySample
- </module>
- <module>
- gwtquery.samples.GwtQueryBench
- </module>
- <module>
- gwtquery.samples.GwtQueryDemo
- </module>
- <module>
- gwtquery.samples.GwtQueryPlugin
- </module>
- <module>
- gwtquery.samples.GwtQueryWidgets
- </module>
- <module>
- gwtquery.samples.GwtQueryEffects
- </module>
+ <module>gwtquery.samples.GwtQueryEffects</module>
+ <module>gwtquery.samples.GwtQuerySample</module>
+ <module>gwtquery.samples.GwtQueryBench</module>
+ <module>gwtquery.samples.GwtQueryDemo</module>
+ <module>gwtquery.samples.GwtQueryPlugin</module>
+ <module>gwtquery.samples.GwtQueryWidgets</module>
</modules>
</configuration>
<executions>
</execution>
</executions>
</plugin>
-
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset><directory>src/main/webapp/gwtquery.samples.GwtQueryBench</directory></fileset>
+ <fileset><directory>src/main/webapp/gwtquery.samples.GwtQueryDemo</directory></fileset>
+ <fileset><directory>src/main/webapp/gwtquery.samples.GwtQueryEffects</directory></fileset>
+ <fileset><directory>src/main/webapp/gwtquery.samples.GwtQueryPlugin</directory></fileset>
+ <fileset><directory>src/main/webapp/gwtquery.samples.GwtQuerySample</directory></fileset>
+ <fileset><directory>src/main/webapp/gwtquery.samples.GwtQueryWidgets</directory></fileset>
+ <fileset><directory>src/main/webapp/WEB-INF/classes</directory></fileset>
+ <fileset><directory>tomcat</directory></fileset>
+ <fileset><directory>www-test</directory></fileset>
+ <fileset><directory>.gwt-tmp</directory></fileset>
+ </filesets>
+ </configuration>
+ </plugin>
</plugins>
</build>
\r
private static final String JQUERY = "jquery";\r
\r
- private static final String GDYNAMIC = "gwt";\r
+ private static final String GDYNAMIC = "dgwt";\r
\r
private static final String DOJO = "dojo";\r
\r
\r
final DeferredGQuery dg[] = m.getAllSelectors();\r
HTML h = HTML.wrap(Document.get().getElementById("startrace"));\r
- initResultsTable(dg, "GQuery", GCOMPILED, "jQuery"\r
+ initResultsTable(dg, "GQuery", GCOMPILED, "DGQuery", GDYNAMIC, "jQuery"\r
/*"DOMAssistant 2.7" */, JQUERY, "Dojo", DOJO, "Prototype", PROTOTYPE);\r
\r
h.addClickHandler(new ClickHandler() {\r
public void onClick(ClickEvent clickEvent) {\r
\r
- runBenchmarks(dg, new GQueryDynamicBenchmark(), new JQueryBenchmark(),\r
+ runBenchmarks(dg,new GQueryDynamicBenchmark(), new GQueryCompiledBenchmark(), new JQueryBenchmark(),\r
new DojoBenchmark(), new PrototypeBenchmark());\r
}\r
});\r
package gwtquery.samples.client;\r
\r
-import static com.google.gwt.query.client.Effects.Effects;\r
import static com.google.gwt.query.client.GQuery.$;\r
\r
import com.google.gwt.core.client.EntryPoint;\r
import com.google.gwt.core.client.GWT;\r
-import com.google.gwt.dom.client.Document;\r
import com.google.gwt.dom.client.Element;\r
import com.google.gwt.dom.client.Node;\r
import com.google.gwt.dom.client.NodeList;\r
import com.google.gwt.query.client.GQuery;\r
import com.google.gwt.query.client.Selector;\r
import com.google.gwt.query.client.Selectors;\r
+import com.google.gwt.query.client.plugins.Effects;\r
import com.google.gwt.user.client.Event;\r
\r
/**\r
public void onModuleLoad() {\r
// Ask GWT compiler to generate our interface\r
final Slide s = GWT.create(Slide.class);\r
+ final GQuery slides = $(s.allSlides());\r
\r
- $(s.allSlides()).hide().eq(0).show();\r
-\r
- // we initially hide all bullets\r
+ // we initially hide all slides and bullets\r
+ slides.hide().eq(0).as(Effects.Effects).clipAppear();\r
$(s.allSlideBullets()).hide();\r
\r
+\r
// add onclick handler to body element\r
- $(Document.get().getBody()).click(new Function() {\r
+ $(slides).click(new Function() {\r
// two state variables to note current slide being shown\r
// and current bullet\r
int curSlide = 0;\r
int curBullets = 0;\r
\r
- // query and store all slides, and bullets of current slide\r
- GQuery slides = $(s.allSlides());\r
+ // query and store all bullets of current slide\r
GQuery bullets = $(s.slideBulletsCtx(slides.get(curSlide)));\r
+ \r
public boolean f(Event e) {\r
// onclick, if not all bullets shown, show a bullet and increment\r
if (curBullets < bullets.size()) {\r
- bullets.eq(curBullets++).fadeIn();\r
+ bullets.eq(curBullets++).show();\r
} else {\r
// all bullets shown, hide them and current slide\r
bullets.hide();\r
- slides.eq(curSlide).as(Effects).hide();\r
// move to next slide, checking for wrap around\r
curSlide++;\r
if (curSlide == slides.size()) {\r
curBullets = 0;\r
// query for new set of bullets, and show next slide\r
bullets = $(s.slideBulletsCtx(slides.get(curSlide)));\r
- slides.eq(curSlide).show();\r
+ slides.eq(curSlide - 1).as(Effects.Effects).slideLeft(new Function() {\r
+ public void f(Element e) {\r
+ slides.eq(curSlide).as(Effects.Effects).clipAppear();\r
+ }\r
+ });\r
}\r
return true;\r
}\r
package gwtquery.samples.client;\r
\r
-import com.google.gwt.core.client.EntryPoint;\r
-import static com.google.gwt.query.client.Effects.Easing.LINEAR;\r
-import static com.google.gwt.query.client.Effects.Effects;\r
-import com.google.gwt.query.client.Function;\r
import static com.google.gwt.query.client.GQuery.$;\r
import static com.google.gwt.query.client.GQuery.$$;\r
import static com.google.gwt.query.client.GQuery.lazy;\r
+\r
+import com.google.gwt.core.client.EntryPoint;\r
+import com.google.gwt.dom.client.Element;\r
+import com.google.gwt.query.client.Function;\r
+import com.google.gwt.query.client.plugins.Effects;\r
+import com.google.gwt.query.client.plugins.PropertiesAnimation.Easing;\r
import com.google.gwt.user.client.Event;\r
\r
public class GwtQueryEffectsModule implements EntryPoint {\r
\r
public void onModuleLoad() {\r
-\r
- $("div > div").\r
- css("color", "blue").\r
- hover(lazy().\r
- css("color", "red").\r
- done(), lazy().\r
- css("color", "blue").\r
- done());\r
+ $("div > div").css("color", "blue")\r
+ .hover(lazy().css("color", "red").done(),\r
+ lazy().css("color", "blue").done());\r
\r
$("div.outer > div").css("position", "relative").dblclick(new Function() {\r
public boolean f(Event e) {\r
- $("div.outer > div").as(Effects).\r
- animate($$("left: '+=100'"), 400, LINEAR, null).\r
- animate($$("top: '+=100'"), 400, LINEAR, null).\r
- animate($$("left: '-=100'"), 400, LINEAR, null).\r
- animate($$("top: '-=100'"), 400, LINEAR, null);\r
-\r
+ $("div.outer > div").as(Effects.Effects).\r
+ animate($$("left: '+=100'"), 400, Easing.LINEAR).\r
+ animate($$("top: '+=100'"), 400, Easing.LINEAR).\r
+ animate($$("left: '-=100'"), 400, Easing.LINEAR).\r
+ animate($$("top: '-=100'"), 400, Easing.LINEAR);\r
return true;\r
}\r
});\r
$(".note").click(lazy().fadeOut().done());\r
$(".note").append(" Hello");\r
+ \r
+ final Effects a = $(".a, .b > div:nth-child(2)").as(Effects.Effects);\r
+ \r
+ $("#b1").toggle(new Function() {\r
+ public void f(Element e) {\r
+ $("#i1").as(Effects.Effects).animate(" width: '70%', opacity: '0.4', marginLeft: '0.6in', fontSize: '3em', borderWidth: '10px'");\r
+ }\r
+ }, new Function() {\r
+ public void f(Element e) {\r
+ $("#i1").as(Effects.Effects).animate(" width: '0%', opacity: '1', marginLeft: '0', fontSize: '1em', borderWidth: '5px'");\r
+ }\r
+ }, new Function() {\r
+ public void f(Element e) {\r
+ a.fadeOut();\r
+ }\r
+ }, new Function() {\r
+ public void f(Element e) {\r
+ a.fadeIn();\r
+ }\r
+ }, new Function() {\r
+ public void f(Element e) {\r
+ a.slideUp();\r
+ }\r
+ }, new Function() {\r
+ public void f(Element e) {\r
+ a.slideDown();\r
+ }\r
+ }, new Function() {\r
+ public void f(Element e) {\r
+ a.slideLeft();\r
+ }\r
+ }, new Function() {\r
+ public void f(Element e) {\r
+ a.slideRight();\r
+ }\r
+ }, new Function() {\r
+ public void f(Element e) {\r
+ a.animate("left: '+=25%', width: 'hide'");\r
+ }\r
+ }, new Function() {\r
+ public void f(Element e) {\r
+ a.animate("left: '-=25%', width: 'show'");\r
+ }\r
+ });\r
+ \r
+ $("#b2").toggle(new Function() {\r
+ public void f(Element e) {\r
+ a.as(Effects.Effects).clipUp();\r
+ }\r
+ }, new Function() {\r
+ public void f(Element e) {\r
+ a.as(Effects.Effects).clipDown();\r
+ }\r
+ }, new Function() {\r
+ public void f(Element e) {\r
+ a.as(Effects.Effects).clipDisappear();\r
+ }\r
+ }, new Function() {\r
+ public void f(Element e) {\r
+ a.as(Effects.Effects).clipAppear();\r
+ }\r
+ });\r
+ \r
}\r
}
\ No newline at end of file
*/
public interface MySelectors extends Selectors {
-// @Selector("h1[id]:contains(Selectors)")
-// NodeList<Element> h1IdContainsSelectors();
-
- //
+ @Selector("h1[id]:contains(Selectors)")
+ NodeList<Element> h1IdContainsSelectors();
@Selector("a[href][lang][class]")
NodeList<Element> aHrefLangClass();
// @Selector("*:first")
// NodeList<Element> allFirst();
- //
-
@Selector("div:not(.example)")
NodeList<Element> divNotExample();
@Selector("div[class=example]")
NodeList<Element> divWithClassExample();
-// @Selector("div[class!=madeup]")
-// NodeList<Element> divWithClassNotContainsMadeup();
-//
+ @Selector("div[class!=madeup]")
+ NodeList<Element> divWithClassNotContainsMadeup();
@Selector("div[class~=dialog]")
NodeList<Element> divWithClassListContainsDialog();
@Selector("p:last-child")
NodeList<Element> lastChild();
-// @Selector("div, p a")
-// NodeList<Element> divCommaPA();
+ @Selector("div, p a")
+ NodeList<Element> divCommaPA();
@Selector(".note")
NodeList<Element> note();
@Selector("p:nth-child(2n+1)")
NodeList<Element> nThChild2nPlus1();
-// @Selector("p:contains(selectors)")
-// NodeList<Element> pContainsSelectors();
+ @Selector("p:contains(selectors)")
+ NodeList<Element> pContainsSelectors();
@Selector("p:nth-child(even)")
NodeList<Element> nThChildEven();
<title>GQuery Demo</title>\r
<script language="javascript"\r
src="gwtquery.samples.GwtQueryEffects.nocache.js"></script>\r
- <link href='gquery-star-ratings.css' type="text/css" rel="stylesheet"/>\r
-\r
+ <style type="text/css">\r
+ .box {\r
+ border-style: groove;\r
+ border-color: green;\r
+ border-width: 5px;\r
+ }\r
+ .a {\r
+ border-style: solid;\r
+ border-color: black;\r
+ border-width: 7px;\r
+ background: pink;\r
+ width: 50%;\r
+ padding: 10px;\r
+ }\r
+ </style>\r
</head>\r
<body>\r
<div class="outer">\r
<div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>\r
<div>Foo <span class="note">bar</span> <span class="xyz">baz</span></div>\r
</div>\r
+<br/>\r
+<button id="b1">Toggle Animate effects</button>\r
+<button id="b2">Toggle Clip effects</button>\r
+<br/>\r
+<br/>\r
+<div class="a">\r
+<span id="i1" class="box">Span 1</span>\r
+<span id="i2" class="box">Span 2</span>\r
+<span id="i3" class="box">Span 3</span>\r
+</div>\r
+<br/>\r
+<div class="b">\r
+<div class="box">Div 1</div>\r
+<div class="box">Div 2</div>\r
+<div class="box">Div 3</div>\r
+<div class="box">Div 4</div>\r
+</div>\r
+\r
+<script src="jquery-1.3.1.js"></script>\r
+<script>\r
+// $("#b1").click(function(){\r
+// $("#i1").animate(({width: '70%', opacity: '0.4', marginLeft: '0.6in', fontSize: '3em', borderWidth: '10px'}));\r
+// });\r
+</script>\r
\r
\r
</body>\r
</script>
<style type="text/css">
img.himg {
- width: 124px;
- height: 73px;
+ height: 55px;
+ }
+ img.logo {
+ max-width: 100px;
}
.horse {
<div id="racefield"
style="width:790px; background-image: url(grass-texture-small.jpg); background-repeat: repeat;">
<div id="gwthorse" class="horse">
- <nobr><img class="himg" src="horse.gif"><img src="gwt-logo-cs.gif">
+ <nobr><img class="himg" src="horse.gif"><img class="logo" src="gwt-logo-cs.gif">
+ </nobr>
+ </div>
+ <div id="dgwthorse" class="horse">
+ <nobr><img class="himg" src="horse.gif"><img class="logo" src="gwt-logo-cs.gif">
</nobr>
</div>
<div id="jqueryhorse" class="horse">
- <nobr><img class="himg" src="horse.gif"><img src="logo_jquery.gif">
+ <nobr><img class="himg" src="horse.gif"><img class="logo" src="logo_jquery.gif">
</nobr>
</div>
<div id="dojohorse" class="horse">
- <img class="himg" src="horse.gif"><img src="dojo-logo-text.gif"></nobr>
+ <img class="himg" src="horse.gif"><img class="logo" src="dojo-logo-text.gif"></nobr>
</div>
<div id="prototypehorse" class="horse">
- <img class="himg" src="horse.gif"><img src="prototype_logo.gif"></nobr>
+ <img class="himg" src="horse.gif"><img class="logo" src="prototype_logo.gif"></nobr>
</div>
</div>