Accessing JQuery From Kotlin?


#1

With the JQuery library being deprecated in the Kotlin JS 1.1 standard library there needs to be a way to access JQuery from Kotlin. Using the js function isn’t possible since parameter(s) need to be passed through. Need to write some JQuery helper functions for selecting an element by name/id/class in Kotlin but don’t know how to do it. JQuery doesn’t seem to have any functions for selecting elements (its all done using the quirky/hacky $ JS function).


#2

For modern browsers (IE>=8) try
document.querySelector()
document.querySelectorAll()

js function is not a function but hack to insert js AST into compiler output so it is possible to use it like this
fun testFunction(str: String, int: Int) = js("console.log(str + ' ' + int)")

which will compile to this js
function testFunction(str, int) { return console.log(str + ' ' + int); }


#3

@Konstantin-Khvan - Thank you for your suggestion. Have managed to get it working. Below is an example of interacting with JS:

fun firstElementByName(elementName: String): JQueryElement? {
    val element = js("$(elementName + ':first');")
    var result: JQueryElement? = null

    if (element != undefined) result = JQueryElement(element)
    return result
}

Now I have a strange issue going on where a JS array is returned and there is no way to call a JS function off an element in the array without an issue occuring. Below are the defined Kotlin functions:

private fun elementsToArray(elements: dynamic): Array<JQueryElement> {
    val tmp = mutableListOf<JQueryElement>()

    if (elements.length != false) {
        @Suppress("UnsafeCastFromDynamic")
        tmp.addAll((0..elements.length - 1).map { JQueryElement(elements[it]) })
    }
    return tmp.toTypedArray()
}

fun allElementsByName(elementName: String) = elementsToArray(js("$(elementName);"))

Here is the calling code which causes the issue:

allElementsByName("body")[0].prependHtml(container.createText())

Instead of having HTML inserted into the body element, text is inserted instead. Replacing the calling code with the following fixes the issue (not a permanent fix):

firstElementByName("body")?.prependHtml(container.createText())

#4

jquery with selector argument always returns a collection of elements with jquery api (this collection is called jquery) so you can chain methods. To convert jquery to array use https://api.jquery.com/toArray/

btw I would not spend any time wrapping jquery api. It is basically perl level perfect as it is. There is no point in writing small programs with kotlin js since its stdlib-js is 1.2MB, and there is no point in using jquery in big aps, it will lead to messy spaghetti code.


#5

Very surprising that the Kotlin JS standard library is bigger in size than the Kotlin standard library for Android (about 500 KB). Why are the Kotlin JS team not making any efforts to reduce the size of the Kotlin JS standard library?


#6

@Konstantin-Khvan - Are you saying that it is safe to use the standard DOM APIs (guaranteed to work across multiple web browsers without any major issues) instead of JQuery?


#7

Behaviour of JQuery is inconsistent at times. What is a JQuery Set? JS doesn’t have a built-in Set data type so why is JQuery inventing its own? If JQuery was using an actual JS array then it is highly likely there wouldn’t be any issues with interop. In the JS debugger what does [object Object] mean?


#8

Would be extremely helpful to have someone from the Kotlin JS team provide detailed information on Kotlin interop with JS (both ways):

  • Calling JS code from Kotlin and vice versa?
  • How to map Kotlin data types to JS and vice versa?
  • Major issues to consider when interacting with JS from Kotlin and vice versa?
  • How to generate a module for Kotlin code?
  • Mapping of Kotlin data types to JS 6 and vice versa?
  • How to generate a type definition file to access JS library/framework from Kotlin?
  • What is available in the Kotlin JS standard library for JS interop?
  • How to interact with the DOM from Kotlin?
  • Interop with standard Web APIs?
  • How does the Kotlin JS dynamic data type affect JS interop?

#9

welcome to js. You are lucky nowdays nobody using IE6. It will have given you wonderfull “error error” for almost anything. No dev tools too. Fun times :smiley:


#10

Very surprising that the Kotlin JS standard library is bigger in size than the Kotlin standard library for Android (about 500 KB)

Firsrt, you are measuring unminified version of stdlib-js. You can apply something like uglify.js (we use webpack + uglify.js plugin in our internal development) and then get code size closer to 500 Kb.

Second, Kotlin stdlib was initially designed for Java, where there are classes like ArrayList, HashMap, etc, and what Kotlin JVM does is aliasing its collections to Java collections. There’s nothing with similar interface in JS world, so, for compatibility reasons, we had to write our own collection library, which contributes to stdlib-js size.

Why are the Kotlin JS team not making any efforts to reduce the size of the Kotlin JS standard library?

The Kotlin JS team is not making any efforts since there are tons of work is should do as well, and it simply has no time to do something with code size. Please, be patient, and in some future releases you’ll get a way to reduce stdlib-js.


#11

@Alexey.Andreev - Do the monthly Kotlin security patches (minor version releases) cover optimisation as well as stability?


#12

Until Kotlin 1.1, JS backend had experimental status, and we could not provide compatibility guarantees similar to JVM backend. Minor updates in 1.0.x introduced new features for JS backend. Since 1.1 we remove “experimental” tag from JS, therefore monthly updates will only fix issues and improve tooling.