Is there a recommended way to forward context to squint?
Like how in Sci you have the option to add namespaces via the context: (sci/eval-string "(inc x)" {:namespaces {'user {'x 2}}})
tell me what exactly you are trying to do
I might have an idea but I'm not totally sure what you mean
I'm playing again with this idea of https://jsfiddle.net/jeroenvandijk/ygrnpx8h/8/, but it doesn't seem to work anymore. I was forwarding vars via the javascript env
This fiddle still worked: https://jsfiddle.net/jeroenvandijk/ygrnpx8h/8/ Are you suggesting something broke?
No i'm using it from a module now, that's the only difference I can think of
But the way I reference variables from the js context might not be the best way. I'm a bit surprised by the results I get (mostly nil references)
repro? still not sure what you're trying to do
the only way to bring in stuff into a module is with import or access global values using globalThis
In squint you access global values using js/whatever or js/globalThis.whatever
I'm loading the above module via [:script {:type "module" :src "/squint-script.js"}] and it mostly seems to work, but for instance _closest is not known anymore
I can try putting it in the fiddle again. Maybe I'm just misunderstanding how js modules work
I'm trying to have something like [:a {:on {:click '(-> el (htmx/addClass "is-active"))}}]
if you want _closest to be globally available you need to export it
and then import it from another module
or stick it on the global Object, like globalThis._closest = closest
I wonder if the modules are a good fit for element event handlers. But I'll try something with export. Thanks!
Ok I found a workaround for imports. eval doesn't support import so I did something like mentioned here https://2ality.com/2019/10/eval-via-import.html
you can use the :repl true option to get JS output that you can eval in an async function
see how that works in the squint playground: https://squint-cljs.github.io/squint/
but if import() works fine and you don't need the return value, I guess that works too. the playground uses both things, depending on whether the REPL toggle is set or not
Thanks. I will check what happens with :repl
also pass context "return" and then you can wrap the stuff in a
(async function() { ... here })()
it will then be async, not sure if that's a problemYeah I switched from 'expr' to 'return' before. I am now trying all three values, but I don't see a difference yet. Before I did, so I must do something wrong
I'll cleanup what I have first
This is what works for me now.
• It don't use eval anymore, but an import hack (https://2ality.com/2019/10/eval-via-import.html). Not sure if it can work otherwise without global references.
• I'm using querySelectorAll, because I chose to go for on instead of on:click and so I don't need document.evaluate anymore. Also document.evaluate doesn't seem to like the dynamic import as it was complaining about the document that it was iterating over being changed.
I'm guessing this code is not very suitable for production environments as the dynamic imports for every event handler feel a bit heavy. But for dev envs it could work (I'm guessing). In production it could be compiled in a couple of different ways.
why is dynamic import heavy?
I'm just guessing that I could have some overhead, but I have no idea really. I'll test it a bit now
btw it seems you have to :context keys in the options map?
two I mean
yeah just saw that. I cleaned this up. Although javascript doesn't seem to care much
context: repl doesn't work. it's repl: true
I think with repl: true and context: return you could still do the async handlers and you don't need to use elide-imports
i will check
as a bonus, even top level await will then work in your handlers :)
repl: true, context: return and no ellide imports. I get the following. Maybe I am misunderstanding what you have in mind. I could wrap it in an async block, but I don't think it would make a difference
perhaps you're using an ancient squint version?
possible 🙈 I'll check
also please show the invocation of compileString as code
yes very old version I see sorry
0.2.28 🙈
could be worse ;)
This is a working demo https://jsfiddle.net/jeroenvandijk/dbqjm90y/10/
I'm not sure why the event seems to fire twice here
I don't know how to make the scenario you proposed work yet
Ah it was fired because I had the javascript in two places. That is fixed now
Thanks for your help. I might experiment more and give some updates :)
there is still an old version of squint string.js in that fiddle
ah indeed. I wasn't using the string namespace yet. I fixed it
I think I can't see the change unless you re-publish it
saved 😅
can you give me the url? somehow I don't see the change
ah /16 vs /10
ah yeah, missed that
here is the REPL-based version with a working string example: https://jsfiddle.net/borkdude/zbdyf2v7/7/
which uses eval
Nice! Thanks, looks better
I'm adding
var extraImports = `
globalThis.user = globalThis.user || {};
var htmx = await import('');
globalThis.user.htmx = htmx;
Above ${compiled.javascript}} to make it work with htmx. I think the import() syntax is slightly different than the static import . It doesn't give me the htmx var I need yet. I'm assuming this can be fixed and I just need to look into the how this works exactlysimilar to how I did it for str
Cool, yes that generates this code for me. I think there is something particular with htmx as only one of the three ways seem to work (not this one I guess)
https://stackoverflow.com/questions/70619055/how-to-import-htmx-variable/70622085#70622085 The first one worked in my previous approach, but in this dynamic approach it doesn't know htmx
Actually only
import "";
worked. Because it doesn't have a default exportI really have no idea what I'm doing, maybe time to read up on these modules a bit 😬
Ok found the issue with htmx, I need to wait for the ready event before I can use anything of the htmx module 😅 Then I am able to use your solution
awesome
I use something like this to do this
import ''
var htmx2;
function ready(fn) {
if (document.readyState !== "loading") {
setTimeout(fn);
} else {
document.addEventListener("DOMContentLoaded", fn);
}
}
ready(function() {
htmx2 = htmx;
}) I guess this is because htmx does stuff asynchronously after it's loaded?
perhaps htmx itself has a callback that is called after it did its stuff?
yeah i suspected something like this after looking at the source code and having a vague memory https://github.com/bigskysoftware/htmx/blob/0b6769a257ac1bf50f3f7228f8a5be5964970f7e/src/htmx.js#L3824-L3832
I kept getting an empty module otherwise. I had no idea why, but now i know
> perhaps htmx itself has a callback that is called after it did its stuff? Yeah could be. I didn't find any hints yet. Didn't find many examples of using it as an javascript API either
I see htmx has an onLoad callback but I'm not sure what it's for. but you have a working solution anyway so that's good
yeah exactly, it is good enough for now
Btw, are you considering adding :refer :all to squint? I'm sort of doing something like this manually now by building a context module and adding all exports to the globalThis.user
no :)
Ok np, happy to do it myself here hehe
refer all doesn't exist in CLJS and also not in JS
ah yeah makes sense
also it messes with static analysis, clj-kondo doesn't like refer all at all
yeah true I understand
I'm playing with my own user namespace now. I can write things like this:
[:button {:on {:click '(log (confirm "hi"))}} "click me"]
Not sure yet what I think of it, but I like it's concisenessI think it makes sense for little snippets like this yes
why not [:button {:click ...}]?
or :on-click
I guess :click and :on-click would not conflict with the native :onclick so it is possible. I have no strong reasons yet. Maybe in the future supporting other events and then you only have to search for the on attribute and not for all the different kind of events. But yeah, could definitely change this
right
Also maybe having multiple events on one element. Not sure if there are use cases for this
Still not sure what exactly is going on with the htmx module. I'm ignoring it for now