I got an issue with my EXIF viewer: While my JavaS...
# webassembly
s
I got an issue with my EXIF viewer: While my JavaScript code for highlighting on mouse over works in a local HTML, it does not work after being injected into the final code. Does JavaScript added by setting
innerHTML
not work in this context? How can I solve that? https://github.com/StefanOltmann/exif-viewer/issues/8
1
c
why do you need the javascript? there is a pseudo class
:hover
that you can use to style elements that are hovered. https://developer.mozilla.org/en-US/docs/Web/CSS/:hover?retiredLocale=de
👍 1
s
HTML specifies that a
<script>
tag inserted with
innerHTML
should not execute.
I overlooked this part. 😅
why do you need the javascript? there is a pseudo class
:hover
that you can use to style elements that are hovered.
It's more than that. I want to hover all elements that have the same class. Hover the values in the last column here and you will see.
c
have a look at all the css selectors, there should be one suitable for your usecase. https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors your javascript code was not that compilcated to not be able to be achieved with css.
🤔 1
But that should be discussed in another workspace - all of it is not related to Kotlin 🙂
s
I doubt that this can be done with one of the css selectors. 🤔 I moved the JavaScript to my index.html, because it won't work with
innerHTML
. I don't feel that the question does not belong here: My JavaScript generally works and I'm not asking how to replace it. It stops working in this Kotlin/WASM (or Kotlin/JS?) context for some reason. Maybe I need to execute some of that using
js("code")
instead?
Oh... I suspect that the JavaScript
document.querySelectorAll()
may not look into the
innerHTML
of my DIV tags. If that's the reason I don't know how I otherwise could inject HTML from Kotlin into my index.html ... maybe the feature I wanted to add is not possible.
c
Maybe I need to execute some of that using
js("code")
instead?
why do you not use kotlin for the whole javascript “string” that you inject somewhere?
s
.hex-box span:hover {
background-color: yellow;
}
This will only color the span I hovered. There are always two spans with the same class present - the label & the value.
c
Oh...
I suspect that the JavaScript
document.querySelectorAll()
may not look into the
innerHTML
of my DIV tags. If that’s the reason I don’t know how I otherwise could inject HTML from Kotlin into my index.html ... maybe the feature I wanted to add is not possible.
are you sure you use Kotlin/WASM correctly. You do not add anything in your html. you would just “load” the generated wasm file and execute it as part of the HTML.
s
We may come closer to the root of my problem 😅 Nope, I'm not sure that I use Kotlin/WASM correctly. I insert my HTML using innerHTML here: https://github.com/StefanOltmann/exif-viewer/blob/035d09a1a930d739353df183131b6a95e765cb27/app/src/wasmJsMain/kotlin/Main.kt#L104 I do it because this was the way I found working. 😅 Would love to see a better solution for it.
c
so you usually write you code in kotlin, then compile it to WASM. serve it as a resource like any javascript file from your “server” and then load it in your HTML. https://developer.mozilla.org/en-US/docs/WebAssembly/Loading_and_running
s
Like I call
exports.default.processFile(uInt8Bytes);
I should call a second exported method that generates the HTML? But what would I do with it if not setting the inner HTML? It's not like JSP here.
c
I guess I complete miss your use case. you have javascript all over the HTML https://github.com/StefanOltmann/exif-viewer/blob/035d09a1a930d739353df183131b6a95e765cb27/app/src/wasmJsMain/resources/index.html#L198 so you want do call your Kotlin/WASM code from in there?
s
Yes, I needed a way to get the ByteArray of a user selected file, process it in Kotlin/WASM (generating HTML) and building a page out of it. Instead of setting the innerHtml, which seems to have limitations, I guess the next thing I can try is building the page like the sample here: https://github.com/Kotlin/kotlin-wasm-examples/blob/068c94953eb47fef47e800f49d203b4a4286e8bc/browser-example/src/wasmJsMain/kotlin/Simple.kt#L9 Maybe that works. 🤷‍♂️ To understand my use case you may try my tool online: https://stefanoltmann.github.io/exif-viewer/
c
ah, okay, well, you you should not use Koltin/WASM to create
html
and alter the DOM in the initial html site. there are frameworks for it like react and vue. that would make you life much easier. Or even create a Compose Web Application then you would not have to deal with anything else than kotlin.
You’ll run into a big maintanabliliy issue with your approach, mixing too much html, javascript and wasm.
s
Compose for Web is not ready for that use case.
Ok, so my question remains open why the JavaScript does not affect my HTML. I need to research if this has to do with innerHtml
c
Because it’s runs on „startup“ and there are not elements it can react on. You add them later. 😉
Compose web with html should be ready it does the same as you do - manipulating the Dom tree.
s
As far as I know I can’t use Compose HTML with WASM. I tried that first.
Only canvas based Compose for Web works, but has limitations.
c
Again, use compose html for the ui work and keep your wasm in a separate module. 😅 think of it like having a ui layer calling business from a library.
s
I think that is not yet possible.
c
Sure why not? You do the same. Compose HTML will just be a JavaScript library that then calls your wasm code.
s
There was a discussion in this channel somewhere. I picked up that Compose HTML works only in Kotlin/JS projects and not yet in Kotlin/WASM. None of the WASM samples uses it, too. I feel it should work, but it does not look like it, Do you have a proof it works? 🤔
c
No, just that you already do it. What’s not possible is to combine it directly in Kotlin code. You have to do the bridging in JavaScript.
s
Whatever bridging in JS means 😅 That’s all new stuff for me and sounds complicated. I look for easy and simple solutions 🙂
What’s an easy way to make my JS work is my question. Not how complicated it can get 😬
c
👍🏻 good luck with that. 😊
But, your JavaScript will never work. 😉
s
Wh not?
For a big enterprise solution I would of course go your suggested React / vue.js route, but the exif viewer is really a simple and small tool - big frameworks are just overkill here.
c
You are trying to do something that’s not possible with JavaScript. You cannot access Dom nodes that are not present in the tree at runtime. You add nodes but won’t to trigger event on then that are registered at a point whenever they are not there.
s
InnerHTML is not present in the DOM? Is this a JavaScript rule?
If I rework my code to do it like the example code and manipulate the DOM instead of using innerHtml my JS should work, right?
c
Sure but not when your JavaScript function is run that is part of the html site.
You cannot add a script element in the inner html as we learned it will not execute and you need to add your listeners after calling innerhtml.
s
Ok, wait… the innerHtml can be kept if I implement the listener now done in JavaScript in Kotlin and apply it afterwards? Then innerHtml is part of the DOM?
👍 1
c
Yes, that should work. Innerhtml and createelement both manipulate the Dom tree. Your issue is the registering of the listeners that need to happen after the nodes are actually added.
s
Okay, that makes sense. That means my JS is executed only one time when the site initially loads and the spans are not yet there. For some reason I was expecting that the
DOMContentLoaded
event would be triggered every time the DOM gets manipulated. This is my first web project ever 😅 I don't like JavaScript and used to develop solely on Desktop & mobile in the past 17 years. 😄 Kotlin for WebAssembly is a good reason to dive into web dev now. If that works I will rewrite all the JS functions of the app in Kotlin, because I prefer to have everything in Kotlin. 🙂
@Chrimaeon Fixed! 🎉 Thank you for guiding me to the right solution. 🙏 The new deployment to https://stefanoltmann.github.io/exif-viewer/ now uses the hover feature. 🙂
c
🎉