xpodev / seamless

A Python package for creating and manipulating HTML components. It is working similar to React.js, but in Python.
https://seamless.readthedocs.io
MIT License
11 stars 1 forks source link

Seamless JS script inline not working #37

Closed binyamin555 closed 2 months ago

binyamin555 commented 2 months ago

Seamless version 0.8.0 (latest on PyPI).

I'm trying to derive the Page class like this:

from pathlib import Path

from seamless.components import Page
from seamless.html import Script

HERE = Path(__file__).parent.resolve()

with open(HERE / "seamless.js") as sjs:
  SEAMLESS_JS = sjs.read()

class MyPage(Page):
  def head(self):
    yield from super().head()
    yield Script()(SEAMLESS_JS)

When using the MyPage class, server side callbacks (such as Button(on_click=)) don't work. However, if I pass the script with src and with defer, everything works fine:

yield Script(src=str("/seamless.js"), defer=True)

But this requires that I either have a StaticFiles middleware or have a dedicated route just for /seamless.js.

I suspect it's because the seamless JS script transforms seamless elements right when it's loaded rather than waiting for the entire page to load.

Therefore, I think it might be a good idea to put in the JS script that it'll only transform the seamless elements after the entire document is loaded.

neriyaco commented 2 months ago

Since you put the script in the head element, the code will run before the content is loaded. The Seamless instance should be created after the content is loaded. You can either put the script in the bottom of the body or you can create the instance after the DOMContentLoaded is fired.

binyamin555 commented 2 months ago

Okay, I found a few solutions.

One is to have the script inline and add another script that only creates the Seamless instance after the document finished loading.

<script>
// Seamless index.js content here
</script>

<script>
document.addEventListener("DOMContentLoaded", () => {
  new Seamless.default();
});
</script>

Another option is to use the latest version from jsdelivr with defer.

<script
  src="https://cdn.jsdelivr.net/npm/@python-seamless/core/umd/index.js"
  defer>
</script>