diff --git a/.travis.yml b/.travis.yml
index 25cad24..d8e2485 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,4 +4,4 @@ scala:
- 2.11.7
script:
- - sbt ++$TRAVIS_SCALA_VERSION compile
\ No newline at end of file
+ - sbt ++$TRAVIS_SCALA_VERSION test
\ No newline at end of file
diff --git a/build.sbt b/build.sbt
index 33ddd17..35f3888 100644
--- a/build.sbt
+++ b/build.sbt
@@ -15,11 +15,18 @@ scalacOptions in ThisBuild ++= Seq(
"-Xlint:_,-missing-interpolator,-adapted-args"
)
-libraryDependencies +=
- "org.scala-js" %%% "scalajs-dom" % "0.8.2"
+libraryDependencies ++= Seq(
+ "org.scala-js" %%% "scalajs-dom" % "0.8.2",
+ "org.scalatest" %%% "scalatest" % "3.0.0-M15" % Test,
+ "com.lihaoyi" %%% "scalatags" % "0.5.4" % Test
+)
jsDependencies +=
"org.webjars" % "jquery" % "2.2.0" / "2.2.0/jquery.js" minified "2.2.0/jquery.min.js"
+requiresDOM in Test := true
+persistLauncher in Test := false
+scalaJSUseRhino in Test := false
+
lazy val root = project.in(file("."))
.enablePlugins(ScalaJSPlugin)
\ No newline at end of file
diff --git a/src/main/scala/io/udash/wrappers/jquery/JQuery.scala b/src/main/scala/io/udash/wrappers/jquery/JQuery.scala
index 453c00b..fb1a94e 100644
--- a/src/main/scala/io/udash/wrappers/jquery/JQuery.scala
+++ b/src/main/scala/io/udash/wrappers/jquery/JQuery.scala
@@ -54,11 +54,11 @@ trait JQuery extends js.Object {
/** Perform a custom animation of a set of CSS properties.
* See: jQuery Docs */
- private[jquery] def animate(properties: js.Dictionary[js.Any], duration: Int, easing: String, callback: js.ThisFunction0[Element, Any]): JQuery = js.native
+ private[jquery] def animate(properties: js.Dictionary[Any], duration: Int, easing: String, callback: js.ThisFunction0[Element, Any]): JQuery = js.native
/** Perform a custom animation of a set of CSS properties.
* See: jQuery Docs */
- private[jquery] def animate(properties: js.Dictionary[js.Any], options: js.Dictionary[js.Any]): JQuery = js.native
+ private[jquery] def animate(properties: js.Dictionary[Any], options: js.Dictionary[Any]): JQuery = js.native
/** Insert content, specified by the parameter, to the end of each element in the set of matched elements.
* See: jQuery Docs */
@@ -130,20 +130,12 @@ trait JQuery extends js.Object {
/** For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
* See: jQuery Docs */
- def closest(selector: String): JQuery = js.native
+ def closest(selector: String | Element | JQuery): JQuery = js.native
/** For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
* See: jQuery Docs */
def closest(selector: String, context: Element): JQuery = js.native
- /** For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
- * See: jQuery Docs */
- def closest(selection: JQuery): JQuery = js.native
-
- /** For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
- * See: jQuery Docs */
- def closest(element: Element): JQuery = js.native
-
/** Get the children of each element in the set of matched elements, including text and comment nodes.
* See: jQuery Docs */
def contents(): JQuery = js.native
@@ -171,11 +163,11 @@ trait JQuery extends js.Object {
/** Store arbitrary data associated with the matched elements.
* See: jQuery Docs */
- def data(key: String, value: js.Any): JQuery = js.native
+ def data(key: String, value: Any): JQuery = js.native
/** Store arbitrary data associated with the matched elements.
* See: jQuery Docs */
- private[jquery] def data(obj: js.Dictionary[js.Any]): JQuery = js.native
+ private[jquery] def data(obj: js.Dictionary[Any]): JQuery = js.native
/** Return the value at the named data store for the first element in the jQuery collection, as set by data(name, value) or by an HTML5 data-* attribute.
* See: jQuery Docs */
@@ -183,7 +175,7 @@ trait JQuery extends js.Object {
/** Return the value at the named data store for the first element in the jQuery collection, as set by data(name, value) or by an HTML5 data-* attribute.
* See: jQuery Docs */
- private[jquery] def data(key: String): UndefOr[js.Any] = js.native
+ private[jquery] def data(key: String): UndefOr[Any] = js.native
/** Trigger dblclick event on an element.
* See: jQuery Docs */
@@ -234,7 +226,7 @@ trait JQuery extends js.Object {
/** Display the matched elements by fading them to opaque.
* See: jQuery Docs */
- private[jquery] def fadeIn(options: js.Dictionary[js.Any]): JQuery = js.native
+ private[jquery] def fadeIn(options: js.Dictionary[Any]): JQuery = js.native
/** Hide the matched elements by fading them to transparent.
* See: jQuery Docs */
@@ -246,7 +238,7 @@ trait JQuery extends js.Object {
/** Hide the matched elements by fading them to transparent.
* See: jQuery Docs */
- private[jquery] def fadeOut(options: js.Dictionary[js.Any]): JQuery = js.native
+ private[jquery] def fadeOut(options: js.Dictionary[Any]): JQuery = js.native
/** Adjust the opacity of the matched elements.
* See: jQuery Docs */
@@ -274,7 +266,7 @@ trait JQuery extends js.Object {
/** Display or hide the matched elements by animating their opacity.
* See: jQuery Docs */
- private[jquery] def fadeToggle(options: js.Dictionary[js.Any]): JQuery = js.native
+ private[jquery] def fadeToggle(options: js.Dictionary[Any]): JQuery = js.native
/** Reduce the set of matched elements to those that match the selector or pass the function's test.
* See: jQuery Docs */
@@ -352,7 +344,7 @@ trait JQuery extends js.Object {
/** Hide the matched elements.
* See: jQuery Docs */
- private[jquery] def hide(options: js.Dictionary[js.Any]): JQuery = js.native
+ private[jquery] def hide(options: js.Dictionary[Any]): JQuery = js.native
/** Get the HTML contents of the first element in the set of matched elements.
* See: jQuery Docs */
@@ -366,7 +358,7 @@ trait JQuery extends js.Object {
* See: jQuery Docs */
def index(): Int = js.native
- /** Search for a given element from among the matched elements.
+ /** Search for a given element from among the matched elements. If the element is not found, this method will return -1.
* See: jQuery Docs */
def index(selector: Selector | Element | JQuery): Int = js.native
@@ -649,15 +641,15 @@ trait JQuery extends js.Object {
/** Set one or more properties for the set of matched elements.
* See: jQuery Docs */
- private[jquery] def prop(properties: js.Dictionary[js.Any]): JQuery = js.native
+ private[jquery] def prop(properties: js.Dictionary[Any]): JQuery = js.native
/** Add a collection of DOM elements onto the jQuery stack.
* See: jQuery Docs */
- private[jquery] def pushStack(elements: js.Array[js.Any]): JQuery = js.native
+ private[jquery] def pushStack(elements: js.Array[Any]): JQuery = js.native
/** Add a collection of DOM elements onto the jQuery stack.
* See: jQuery Docs */
- private[jquery] def pushStack(elements: js.Array[js.Any], name: String, arguments: js.Array[js.Any]): JQuery = js.native
+ private[jquery] def pushStack(elements: js.Array[Any], name: String, arguments: js.Array[Any]): JQuery = js.native
/** Specify a function to execute when the DOM is fully loaded.
* See: jQuery Docs */
@@ -745,13 +737,13 @@ trait JQuery extends js.Object {
/** Display the matched elements.
* See: jQuery Docs */
- private[jquery] def show(options: js.Dictionary[js.Any]): JQuery = js.native
+ private[jquery] def show(options: js.Dictionary[Any]): JQuery = js.native
/** Get the siblings of each element in the set of matched elements, optionally filtered by a selector.
* See: jQuery Docs */
def siblings(selector: String = js.native): JQuery = js.native
- /** Reduce the set of matched elements to a subset specified by a range of indices.
+ /** Reduce the set of matched elements to a subset specified by a range of indices. Including `start`, without `end`.
* See: jQuery Docs */
def slice(start: Int, end: Int = js.native): JQuery = js.native
@@ -765,7 +757,7 @@ trait JQuery extends js.Object {
/** Display the matched elements with a sliding motion.
* See: jQuery Docs */
- private[jquery] def slideDown(options: js.Dictionary[js.Any]): JQuery = js.native
+ private[jquery] def slideDown(options: js.Dictionary[Any]): JQuery = js.native
/** Display or hide the matched elements with a sliding motion.
* See: jQuery Docs */
@@ -777,7 +769,7 @@ trait JQuery extends js.Object {
/** Display or hide the matched elements with a sliding motion.
* See: jQuery Docs */
- private[jquery] def slideToggle(options: js.Dictionary[js.Any]): JQuery = js.native
+ private[jquery] def slideToggle(options: js.Dictionary[Any]): JQuery = js.native
/** Hide the matched elements with a sliding motion.
* See: jQuery Docs */
@@ -789,7 +781,7 @@ trait JQuery extends js.Object {
/** Hide the matched elements with a sliding motion.
* See: jQuery Docs */
- private[jquery] def slideUp(options: js.Dictionary[js.Any]): JQuery = js.native
+ private[jquery] def slideUp(options: js.Dictionary[Any]): JQuery = js.native
/** Stop the currently-running animation on the matched elements.
* See: jQuery Docs */
@@ -813,7 +805,7 @@ trait JQuery extends js.Object {
/** Retrieve all the elements contained in the jQuery set, as an array.
* See: jQuery Docs */
- private[jquery] def toArray: js.Array[Element] = js.native
+ private[jquery] def toArray(): js.Array[Element] = js.native
/** Display or hide the matched elements.
* See: jQuery Docs */
@@ -829,7 +821,7 @@ trait JQuery extends js.Object {
/** Display or hide the matched elements.
* See: jQuery Docs */
- private[jquery] def toggle(options: js.Dictionary[js.Any]): JQuery = js.native
+ private[jquery] def toggle(options: js.Dictionary[Any]): JQuery = js.native
/** Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the state argument.
* See: jQuery Docs */
@@ -849,7 +841,7 @@ trait JQuery extends js.Object {
/** Execute all handlers and behaviors attached to the matched elements for the given event type.
* See: jQuery Docs */
- private[jquery] def trigger(event: String | JQueryEvent, extraParams: js.Dictionary[js.Any] | js.Array[js.Any]): JQuery = js.native
+ private[jquery] def trigger(event: String | JQueryEvent, extraParams: js.Dictionary[Any] | js.Array[Any]): JQuery = js.native
/** Execute all handlers attached to an element for an event.
* See: jQuery Docs */
@@ -857,7 +849,7 @@ trait JQuery extends js.Object {
/** Execute all handlers attached to an element for an event.
* See: jQuery Docs */
- private[jquery] def triggerHandler(event: String | JQueryEvent, extraParams: js.Dictionary[js.Any] | js.Array[js.Any]): JQuery = js.native
+ private[jquery] def triggerHandler(event: String | JQueryEvent, extraParams: js.Dictionary[Any] | js.Array[Any]): JQuery = js.native
/** Remove the parents of the set of matched elements from the DOM, leaving the matched elements in their place.
* See: jQuery Docs */
@@ -866,12 +858,12 @@ trait JQuery extends js.Object {
/** Get the current value of the first element in the set of matched elements.
* See: jQuery Docs */
@JSName("val")
- def value(): String | Number | js.Array[js.Any] = js.native
+ def value(): String | Number | js.Array[Any] = js.native
/** Set the value of each element in the set of matched elements.
* See: jQuery Docs */
@JSName("val")
- def value(value: String | Number | js.Array[js.Any]): JQuery = js.native
+ def value(value: String | Number | js.Array[Any]): JQuery = js.native
/** Set the value of each element in the set of matched elements.
* See: jQuery Docs */
@@ -933,8 +925,8 @@ object JQuery {
done: (JQueryPromise[js.Function1[js.Any, js.Any], js.Any], Boolean) => js.Any = null,
fail: (JQueryPromise[js.Function1[js.Any, js.Any], js.Any], Boolean) => js.Any = null,
always: (JQueryPromise[js.Function1[js.Any, js.Any], js.Any], Boolean) => js.Any = null) {
- def toJSDictionary: js.Dictionary[js.Any] = {
- val r = js.Dictionary[js.Any]()
+ def toJSDictionary: js.Dictionary[Any] = {
+ val r = js.Dictionary[Any]()
if (duration.isDefined) r.update("duration", duration.get)
if (easing != null) r.update("easing", easing)
if (queue.isDefined) r.update("queue", queue.get)
@@ -972,11 +964,11 @@ object JQuery {
/** Perform a custom animation of a set of CSS properties.
* See: jQuery Docs */
- def animate(properties: Map[String, js.Any], duration: Int = 400, easing: String = "swing", callback: (Element) => Any = (_) => {}): JQuery = jquery.animate(properties.toJSDictionary, duration, easing, callback)
+ def animate(properties: Map[String, Any], duration: Int = 400, easing: String = "swing", callback: (Element) => Any = (_) => {}): JQuery = jquery.animate(properties.toJSDictionary, duration, easing, callback)
/** Perform a custom animation of a set of CSS properties.
* See: jQuery Docs */
- def animate(properties: Map[String, js.Any], options: AnimationOptions): JQuery = jquery.animate(properties.toJSDictionary, options.toJSDictionary)
+ def animate(properties: Map[String, Any], options: AnimationOptions): JQuery = jquery.animate(properties.toJSDictionary, options.toJSDictionary)
/** Insert content, specified by the parameter, to the end of each element in the set of matched elements.
* See: jQuery Docs */
@@ -1052,7 +1044,7 @@ object JQuery {
/** Store arbitrary data associated with the matched elements.
* See: jQuery Docs */
- def data(obj: Map[String, js.Any]): JQuery = jquery.data(obj.toJSDictionary)
+ def data(obj: Map[String, Any]): JQuery = jquery.data(obj.toJSDictionary)
/** Bind an event handler to the "dblclick" JavaScript event on an element.
* See: jQuery Docs */
@@ -1339,19 +1331,18 @@ object JQuery {
/** Remove an event handler.
* See: jQuery Docs */
def off(event: String, callback: JQueryCallback): JQuery = {
- jquery
- .toArray
+ jquery.toArray()
.foreach( el => {
if (registrations.contains(el)) {
val jqueryRegs: mutable.Buffer[CallbackRegistrationRef] = registrations.get(el).get
- val founded: mutable.Buffer[CallbackRegistrationRef] = jqueryRegs.filter(r => {
+ val found: mutable.Buffer[CallbackRegistrationRef] = jqueryRegs.filter(r => {
r match {
case CallbackRegistrationRef(ev, cb, _) if cb == callback && ev == event => true
case _ => false
}
})
- founded.foreach( _.registration.unregister())
- jqueryRegs --= founded
+ found.foreach( _.registration.unregister())
+ jqueryRegs --= found
if (jqueryRegs.isEmpty) registrations.remove(el)
}
})
@@ -1412,15 +1403,15 @@ object JQuery {
/** Set one or more properties for the set of matched elements.
* See: jQuery Docs */
- def prop(properties: Map[String, js.Any]): JQuery = jquery.prop(properties.toJSDictionary)
+ def prop(properties: Map[String, Any]): JQuery = jquery.prop(properties.toJSDictionary)
/** Add a collection of DOM elements onto the jQuery stack.
* See: jQuery Docs */
- def pushStack(elements: Seq[js.Any]): JQuery = jquery.pushStack(elements.toJSArray)
+ def pushStack(elements: Seq[Any]): JQuery = jquery.pushStack(elements.toJSArray)
/** Add a collection of DOM elements onto the jQuery stack.
* See: jQuery Docs */
- def pushStack(elements: Seq[js.Any], name: String, arguments: Seq[js.Any]): JQuery = jquery.pushStack(elements.toJSArray, name, arguments.toJSArray)
+ def pushStack(elements: Seq[Any], name: String, arguments: Seq[Any]): JQuery = jquery.pushStack(elements.toJSArray, name, arguments.toJSArray)
/** Specify a function to execute when the DOM is fully loaded.
* See: jQuery Docs */
@@ -1504,7 +1495,7 @@ object JQuery {
/** Retrieve all the elements contained in the jQuery set, as an array.
* See: jQuery Docs */
- def toArray: Seq[Element] = jquery.toArray.toSeq
+ def toArray: Seq[Element] = jquery.toArray().toSeq
/** Display or hide the matched elements.
* See: jQuery Docs */
@@ -1524,19 +1515,19 @@ object JQuery {
/** Execute all handlers and behaviors attached to the matched elements for the given event type.
* See: jQuery Docs */
- def trigger(event: String | JQueryEvent, extraParams: Map[String, js.Any]): JQuery = jquery.trigger(event, extraParams.toJSDictionary)
+ def trigger(event: String | JQueryEvent, extraParams: Map[String, Any]): JQuery = jquery.trigger(event, extraParams.toJSDictionary)
/** Execute all handlers and behaviors attached to the matched elements for the given event type.
* See: jQuery Docs */
- def trigger(event: String | JQueryEvent, extraParams: Seq[js.Any]): JQuery = jquery.trigger(event, extraParams.toJSArray)
+ def trigger(event: String | JQueryEvent, extraParams: Seq[Any]): JQuery = jquery.trigger(event, extraParams.toJSArray)
/** Execute all handlers attached to an element for an event.
* See: jQuery Docs */
- def triggerHandler(event: String | JQueryEvent, extraParams: Map[String, js.Any]): JQuery = jquery.triggerHandler(event, extraParams.toJSDictionary)
+ def triggerHandler(event: String | JQueryEvent, extraParams: Map[String, Any]): JQuery = jquery.triggerHandler(event, extraParams.toJSDictionary)
/** Execute all handlers attached to an element for an event.
* See: jQuery Docs */
- def triggerHandler(event: String | JQueryEvent, extraParams: Seq[js.Any]): JQuery = jquery.triggerHandler(event, extraParams.toJSArray)
+ def triggerHandler(event: String | JQueryEvent, extraParams: Seq[Any]): JQuery = jquery.triggerHandler(event, extraParams.toJSArray)
/** Set the value of each element in the set of matched elements.
* See: jQuery Docs */
diff --git a/src/main/scala/io/udash/wrappers/jquery/JQueryStatic.scala b/src/main/scala/io/udash/wrappers/jquery/JQueryStatic.scala
index 060ec9a..be471d1 100644
--- a/src/main/scala/io/udash/wrappers/jquery/JQueryStatic.scala
+++ b/src/main/scala/io/udash/wrappers/jquery/JQueryStatic.scala
@@ -188,7 +188,7 @@ object JQueryStatic {
/** Return a collection of matched elements either found in the DOM based on passed argument(s) or created by passing an HTML string.
* See: jQuery Docs */
- def apply(elementArray: Seq[Element]): JQuery = jQueryStatic(elementArray.toJSArray)
+ def apply(elementArray: Element*): JQuery = jQueryStatic(elementArray.toJSArray)
/** Binds a function to be executed when the DOM has finished loading.
* See: jQuery Docs */
@@ -196,8 +196,8 @@ object JQueryStatic {
/** Binds a function to be executed when the DOM has finished loading.
* See: jQuery Docs */
- def apply(option: Option[Any]): JQuery = option match {
- case Some(element) => jQueryStatic.apply(element.asInstanceOf[js.Any])
+ def apply(option: Option[js.Any]): JQuery = option match {
+ case Some(element) => jQueryStatic.apply(element)
case None => jQueryStatic.apply()
}
diff --git a/src/test/scala/io/udash/wrappers/jquery_test/DomManipulationTest.scala b/src/test/scala/io/udash/wrappers/jquery_test/DomManipulationTest.scala
new file mode 100644
index 0000000..ede038d
--- /dev/null
+++ b/src/test/scala/io/udash/wrappers/jquery_test/DomManipulationTest.scala
@@ -0,0 +1,241 @@
+package io.udash.wrappers.jquery_test
+
+import org.scalatest.{Matchers, WordSpec}
+
+class DomManipulationTest extends WordSpec with Matchers {
+ import io.udash.wrappers.jquery._
+ import scalatags.JsDom.all._
+
+ "jQuery" should {
+ "set text content of DOM element" in {
+ val text = "test 123"
+ val dom = div().render
+
+ jQ(dom).text() should be("")
+ dom.textContent should be("")
+
+ jQ(dom).text(text)
+
+ jQ(dom).text() should be(text)
+ dom.textContent should be(text)
+ }
+
+ "set content of DOM element" in {
+ val text = "test 123"
+ val dom = div().render
+ val content = span(ul(li(text))).render
+
+ jQ(dom).html() should be("")
+ dom.textContent should be("")
+
+ jQ(dom).html(content)
+
+ jQ(dom).html() should be(s"")
+ jQ(dom).text() should be(text)
+ dom.textContent should be(text)
+ }
+
+ "set DOM element attribute" in {
+ val attrName = "attr"
+ val attrValue = "val"
+ val dom = div().render
+
+ jQ(dom).attr(attrName) should be(None)
+
+ jQ(dom).attr(attrName, attrValue)
+
+ jQ(dom).attr(attrName) should be(Some(attrValue))
+ dom.getAttribute(attrName) should be(attrValue)
+ }
+
+ "manage DOM element CSS classes" in {
+ val c1 = "c1"
+ val c2 = "c2"
+ val dom = div().render
+
+ jQ(dom).addClass(c1)
+ jQ(dom).addClass(c2)
+
+ dom.className.split(" ") should contain(c1)
+ dom.className.split(" ") should contain(c2)
+
+ jQ(dom).removeClass(c2)
+
+ dom.className.split(" ") should contain(c1)
+ dom.className.split(" ") shouldNot contain(c2)
+
+ jQ(dom).toggleClass(c1)
+ jQ(dom).toggleClass(c2)
+
+ dom.className.split(" ") shouldNot contain(c1)
+ dom.className.split(" ") should contain(c2)
+
+ jQ(dom).toggleClass(c1)
+ jQ(dom).toggleClass(c2)
+
+ dom.className.split(" ") should contain(c1)
+ dom.className.split(" ") shouldNot contain(c2)
+ }
+
+ "show/hide DOM elements" in {
+ val dom = div(
+ h1("a"),
+ span("b")
+ ).render
+
+ val h = jQ(dom).find("h1")
+ val s = jQ(dom).find("span")
+
+ h.hide()
+ h.css("display") should be("none")
+ s.css("display") shouldNot be("none")
+
+ s.hide()
+ h.css("display") should be("none")
+ s.css("display") should be("none")
+
+ h.show()
+ s.show()
+ h.css("display") shouldNot be("none")
+ s.css("display") shouldNot be("none")
+ }
+
+ "remove DOM elements" in {
+ val dom = div(
+ h1("a"),
+ span(cls :="c1")("b"),
+ h1("a"),
+ span("c"),
+ h1("a"),
+ span(cls :="c1")("d"),
+ h1("a"),
+ span("e", span("f"), "g")
+ ).render
+
+ val h = jQ(dom).find("h1")
+ val s = jQ(dom).find("span")
+ val c = jQ(dom).find(".c1")
+
+ dom.childElementCount should be(8)
+ dom.textContent should be("abacadaefg")
+
+ h.remove()
+
+ dom.childElementCount should be(4)
+ dom.textContent should be("bcdefg")
+
+ c.remove()
+
+ dom.childElementCount should be(2)
+ dom.textContent should be("cefg")
+
+ s.remove()
+
+ dom.childElementCount should be(0)
+ dom.textContent should be("")
+ }
+
+ "remove childrens of DOM elements" in {
+ val dom = div(
+ h1("a"),
+ span(cls :="c1")("b"),
+ h1("a"),
+ span("c"),
+ h1("a"),
+ span(cls :="c1")("d"),
+ h1("a"),
+ span("e", span("f"), "g")
+ ).render
+
+ val h = jQ(dom).find("h1")
+ val s = jQ(dom).find("span")
+ val c = jQ(dom).find(".c1")
+
+ dom.childElementCount should be(8)
+ dom.textContent should be("abacadaefg")
+
+ h.empty()
+
+ dom.childElementCount should be(8)
+ dom.textContent should be("bcdefg")
+
+ c.empty()
+
+ dom.childElementCount should be(8)
+ dom.textContent should be("cefg")
+
+ s.empty()
+
+ dom.childElementCount should be(8)
+ dom.textContent should be("")
+ }
+
+ "append/prepend DOM elements" in {
+ val dom = div(
+ span(), span(), span(), span()
+ ).render
+
+ val s = jQ(dom).find("span")
+
+ dom.childElementCount should be(4)
+ dom.textContent should be("")
+
+ s.append("a")
+
+ dom.childElementCount should be(4)
+ dom.textContent should be("aaaa")
+
+ s.prepend("b")
+
+ dom.childElementCount should be(4)
+ dom.textContent should be("babababa")
+
+ s.filter(":nth-child(2n)").append("c")
+
+ dom.childElementCount should be(4)
+ dom.textContent should be("babacbabac")
+
+ s.filter(":nth-child(2n+1)").prepend("d")
+
+ dom.childElementCount should be(4)
+ dom.textContent should be("dbabacdbabac")
+ }
+
+ "append/prepend DOM element into another element" in {
+ val dom = div().render
+
+ jQ(span("a").render).appendTo(dom)
+
+ dom.childElementCount should be(1)
+ dom.textContent should be("a")
+
+ jQ(span("b").render).appendTo(jQ(dom))
+
+ dom.childElementCount should be(2)
+ dom.textContent should be("ab")
+
+ jQ(span("x").render).prependTo(jQ(dom))
+
+ dom.childElementCount should be(3)
+ dom.textContent should be("xab")
+
+ jQ(span("y").render).prependTo(dom)
+
+ dom.childElementCount should be(4)
+ dom.textContent should be("yxab")
+ }
+
+ "manage input values" in {
+ val dom = input().render
+
+ jQ(dom).value("abc")
+ jQ(dom).value() should be("abc")
+ dom.value should be("abc")
+
+ jQ(dom).value("cba")
+ jQ(dom).value() should be("cba")
+ dom.value should be("cba")
+ }
+ }
+
+}
diff --git a/src/test/scala/io/udash/wrappers/jquery_test/EventsHandlingTest.scala b/src/test/scala/io/udash/wrappers/jquery_test/EventsHandlingTest.scala
new file mode 100644
index 0000000..42fea1c
--- /dev/null
+++ b/src/test/scala/io/udash/wrappers/jquery_test/EventsHandlingTest.scala
@@ -0,0 +1,73 @@
+import org.scalajs.dom.Element
+import org.scalajs.dom.html.Input
+import org.scalatest.{Matchers, WordSpec}
+
+class EventsHandlingTest extends WordSpec with Matchers {
+ import io.udash.wrappers.jquery._
+
+ import scalatags.JsDom.all._
+
+ class C(i: Int)
+
+ "jQuery" should {
+ "handle JS events" in {
+ val i = jQ(input().render)
+
+ var event: JQueryEvent = null
+
+ val callback: (Element, JQueryEvent) => Unit =
+ (el: Element, ev: JQueryEvent) =>
+ event = ev
+
+ i.on("change", callback)
+
+ i.trigger("change")
+ event shouldNot be(null)
+
+ i.off("change", callback)
+
+ event = null
+ i.trigger("change")
+ event should be(null)
+ }
+
+ "handle JS events (inlined)" in {
+ val i: Input = input().render
+ var event: JQueryEvent = null
+
+ val callback: (Element, JQueryEvent) => Unit =
+ (el: Element, ev: JQueryEvent) =>
+ event = ev
+
+ jQ(i).on("change", callback)
+
+ jQ(i).trigger("change")
+ event shouldNot be(null)
+
+ jQ(i).off("change", callback)
+
+ event = null
+ jQ(i).trigger("change")
+ event should be(null)
+ }
+
+ "handle JS events (one)" in {
+ val i: Input = input().render
+ var event: JQueryEvent = null
+
+ val callback: (Element, JQueryEvent) => Unit =
+ (el: Element, ev: JQueryEvent) =>
+ event = ev
+
+ jQ(i).one("change", callback)
+
+ jQ(i).trigger("change")
+ event shouldNot be(null)
+
+ event = null
+ jQ(i).trigger("change")
+ event should be(null)
+ }
+ }
+
+}
diff --git a/src/test/scala/io/udash/wrappers/jquery_test/MiscellaneousTest.scala b/src/test/scala/io/udash/wrappers/jquery_test/MiscellaneousTest.scala
new file mode 100644
index 0000000..c2630c7
--- /dev/null
+++ b/src/test/scala/io/udash/wrappers/jquery_test/MiscellaneousTest.scala
@@ -0,0 +1,48 @@
+package io.udash.wrappers.jquery_test
+
+import org.scalatest.{Matchers, WordSpec}
+
+class MiscellaneousTest extends WordSpec with Matchers {
+ import io.udash.wrappers.jquery._
+
+ import scalatags.JsDom.all._
+
+ class C(i: Int)
+
+ "jQuery" should {
+ "keep data in DOM elements" in {
+ val c = new C(5)
+ val f = (i: Int) => i + 1
+
+ val dom = div().render
+ val selection = jQ(dom)
+ selection.data(Map("key" -> "value", "int" -> 1, "cls" -> c, "func" -> f))
+
+ selection.data().key should be("value")
+ selection.data("key") should be(Some("value"))
+ selection.data().int should be(1)
+ selection.data("int") should be(Some(1))
+ selection.data().cls should be(c)
+ selection.data("cls") should be(Some(c))
+ selection.data().func should be(f)
+ selection.data("func") should be(Some(f))
+
+ selection.data("nothing") should be(None)
+ }
+
+ "find element index in selection" in {
+ val el1 = span.render
+ val el2 = span(id := "id").render
+ val el3 = h1.render
+ val el4 = h1(cls := "lolzy").render
+ val dom = div(el1, el2, el3).render
+
+ val selection = jQ(dom).children()
+ selection.index(el1) should be(0)
+ selection.index(el2) should be(1)
+ selection.index(jQ(el3)) should be(2)
+ selection.index(el4) should be(-1)
+ }
+ }
+
+}
diff --git a/src/test/scala/io/udash/wrappers/jquery_test/SelectorsTest.scala b/src/test/scala/io/udash/wrappers/jquery_test/SelectorsTest.scala
new file mode 100644
index 0000000..ede080c
--- /dev/null
+++ b/src/test/scala/io/udash/wrappers/jquery_test/SelectorsTest.scala
@@ -0,0 +1,57 @@
+package io.udash.wrappers.jquery_test
+
+import org.scalatest.{Matchers, WordSpec}
+
+class SelectorsTest extends WordSpec with Matchers {
+ import io.udash.wrappers.jquery._
+ import scalatags.JsDom.all._
+
+ "jQuery" should {
+ "select elements by class" in {
+ val el1 = span(cls := "c1").render
+ val el2 = span(cls := "c1 c2").render
+ val el3 = h1(cls := "c3").render
+ val dom = div(el1, el2, el3).render
+
+ jQ(dom).children(".c1").each((el, _, _) => jQ(el).attr("a1", 1))
+ jQ(dom).children(".c2").each((el, _, _) => jQ(el).attr("a2", 1))
+ jQ(dom).children(".c3").each((el, _, _) => jQ(el).attr("a3", 1))
+
+ jQ(el1).attr("a1") should be(Some("1"))
+ jQ(el1).attr("a2") should be(None)
+ jQ(el1).attr("a3") should be(None)
+
+ jQ(el2).attr("a1") should be(Some("1"))
+ jQ(el2).attr("a2") should be(Some("1"))
+ jQ(el2).attr("a3") should be(None)
+
+ jQ(el3).attr("a1") should be(None)
+ jQ(el3).attr("a2") should be(None)
+ jQ(el3).attr("a3") should be(Some("1"))
+ }
+
+ "select elements by id" in {
+ val el1 = span(id := "el1").render
+ val el2 = span(id := "el2").render
+ val el3 = h1(id := "el3").render
+ val dom = div(el1, el2, el3).render
+
+ jQ(dom).children("#el1").each((el, _, _) => jQ(el).attr("a1", 1))
+ jQ(dom).children("#el2").each((el, _, _) => jQ(el).attr("a2", 1))
+ jQ(dom).children("#el3").each((el, _, _) => jQ(el).attr("a3", 1))
+
+ jQ(el1).attr("a1") should be(Some("1"))
+ jQ(el1).attr("a2") should be(None)
+ jQ(el1).attr("a3") should be(None)
+
+ jQ(el2).attr("a1") should be(None)
+ jQ(el2).attr("a2") should be(Some("1"))
+ jQ(el2).attr("a3") should be(None)
+
+ jQ(el3).attr("a1") should be(None)
+ jQ(el3).attr("a2") should be(None)
+ jQ(el3).attr("a3") should be(Some("1"))
+ }
+ }
+
+}
diff --git a/src/test/scala/io/udash/wrappers/jquery_test/TraversingTest.scala b/src/test/scala/io/udash/wrappers/jquery_test/TraversingTest.scala
new file mode 100644
index 0000000..c9b1860
--- /dev/null
+++ b/src/test/scala/io/udash/wrappers/jquery_test/TraversingTest.scala
@@ -0,0 +1,169 @@
+package io.udash.wrappers.jquery_test
+
+import org.scalatest.{Matchers, WordSpec}
+
+class TraversingTest extends WordSpec with Matchers {
+ import io.udash.wrappers.jquery._
+
+ import scalatags.JsDom.all._
+
+ "jQuery" should {
+ "add elements to selection" in {
+ val el1 = span.render
+ val el2 = span.render
+ val el3 = h1.render
+
+ val j1 = jQ(el1)
+ j1.each((el, _, _) => jQ(el).attr("a1", 1))
+ val j2 = j1.add(el2)
+ j2.each((el, _, _) => jQ(el).attr("a2", 1))
+ val j3 = j2.add(el3)
+ j3.each((el, _, _) => jQ(el).attr("a3", 1))
+
+ jQ(el1).attr("a1") should be(Some("1"))
+ jQ(el1).attr("a2") should be(Some("1"))
+ jQ(el1).attr("a3") should be(Some("1"))
+
+ jQ(el2).attr("a1") should be(None)
+ jQ(el2).attr("a2") should be(Some("1"))
+ jQ(el2).attr("a3") should be(Some("1"))
+
+ jQ(el3).attr("a1") should be(None)
+ jQ(el3).attr("a2") should be(None)
+ jQ(el3).attr("a3") should be(Some("1"))
+ }
+
+ "iterate over a selection" in {
+ val el1 = span.render
+ val el2 = span.render
+ val el3 = h1.render
+
+ val selection = jQ(el1, el2, el3)
+ selection.each((el, _, _) => jQ(el).attr("a", 1))
+
+ jQ(el1).attr("a") should be(Some("1"))
+ jQ(el2).attr("a") should be(Some("1"))
+ jQ(el3).attr("a") should be(Some("1"))
+ }
+
+ "filter a selection" in {
+ val el1 = span.render
+ val el2 = span.render
+ val el3 = h1.render
+
+ val selection = jQ(el1, el2, el3)
+ selection.filter("h1").each((el, _, _) => jQ(el).attr("a", 1))
+
+ jQ(el1).attr("a") should be(None)
+ jQ(el2).attr("a") should be(None)
+ jQ(el3).attr("a") should be(Some("1"))
+ }
+
+ "find elements parent" in {
+ val el1 = span.render
+ val el2 = span.render
+ val el3 = h1.render
+ val p1 = div(el1).render
+ val p2 = div(el2).render
+ val p3 = div(el3).render
+
+ val selection = jQ(el1, el2, el3)
+ selection.parent().filter("div").length should be(3)
+ }
+
+ "find descendants" in {
+ val el1 = span.render
+ val el2 = span.render
+ val el3 = h1.render
+ val p1 = div(el1).render
+ val p2 = div(el2).render
+ val p3 = div(el3).render
+ val p = div(p1, p2, p3).render
+
+ jQ(p).find("span").length should be(2)
+ jQ(p).find("div").length should be(3)
+ jQ(p).find("h1").length should be(1)
+ }
+
+ "find elements parent (should be unique)" in {
+ val el1 = span.render
+ val el2 = span.render
+ val el3 = h1.render
+ val d = div(el1, el2, el3).render
+
+ val selection = jQ(el1, el2, el3)
+ selection.parent().filter("div").length should be(1)
+ }
+
+ "slice elements" in {
+ val el1 = span.render
+ val el2 = span.render
+ val el3 = h1.render
+
+ val selection = jQ(el1, el2, el3)
+ selection.slice(1).get() should be(Seq(el2, el3))
+ selection.slice(1, 2).get() should be(Seq(el2))
+ selection.slice(0, 2).get() should be(Seq(el1, el2))
+ selection.slice(0, 10).get() should be(Seq(el1, el2, el3))
+ intercept[Exception](selection.slice(-2, 1).get() should be(Seq(el1)))
+ intercept[Exception](selection.slice(1, 1).get() should be(Seq(el1)))
+ }
+
+ "find closest matching parent" in {
+ val dom = div(
+ div(cls := "a")(
+ div(cls := "b")(
+ span(cls := "d")
+ ),
+ div(cls := "b c")(
+ span(cls := "e")
+ )
+ )
+ ).render
+
+ val root = jQ(dom)
+ root.find("span").closest(".a").length should be(1)
+ root.find("span").closest(".b").length should be(2)
+ root.find("span").closest(".c").length should be(1)
+ root.find("span").closest(".d").length should be(1)
+ root.find("span").closest(".d").get(0).get.tagName.toLowerCase should be("span")
+ }
+
+ "find prev/next matching element" in {
+ val dom = div(
+ span("a"),
+ span("b"),
+ span(cls := "start")("c"),
+ span("d"),
+ span("e")
+ ).render
+
+ val root = jQ(dom).children(".start")
+ root.prev().text() should be("b")
+ root.prev("span").prev().text() should be("a")
+ root.prev().prev().prev().length should be(0)
+ root.next().text() should be("d")
+ root.next().next().text() should be("e")
+ root.next().next().next().length should be(0)
+ root.prev("a").length should be(0)
+ }
+
+ "find first/last matching element" in {
+ val dom = div(
+ span("a"),
+ span("b"),
+ span(cls := "start")("c"),
+ span("d"),
+ span("e")
+ ).render
+
+ val root = jQ(dom)
+ root.children("span").first().text() should be("a")
+ root.children("span").last().text() should be("e")
+ root.children(".start").first().text() should be("c")
+ root.children(".start").last().text() should be("c")
+ root.children("a").first().length should be(0)
+ root.children("a").last().length should be(0)
+ }
+ }
+}