threepenny-gui icon indicating copy to clipboard operation
threepenny-gui copied to clipboard

Conveniently loading JavaScript libraries

Open duplode opened this issue 10 years ago • 2 comments

Hello again! It's been a while, but I finally got back to playing with Threepenny. My latest experiment involved bindings to a small subset of jQuery UI. While it works very well, the trickery involved was, ahem, interesting. Quoting one of my commit messages:

Experimenting with bindings to JQuery UI's Autocomplete widget.

The key complication arises from the fact that we need to have the library fully loaded by the time we call autocompleteInit on the text box. As of Threepenny 0.4.0.2, following usual JavaScript practice by chaining the initialisation steps with callbacks is not feasible, at least as far as I can see. Using the load event of the script element does not work either, as JQuery (which handles element appendage behind the scenes) will evaluate the script and eliminate the DOM element. The next best option, then, is to load the script via a synchronous request. The JavaScript code for doing so was wrapped with callFunction to keep it blocking.

It should be mentioned that the easiest way to load something like JQuery UI would probably be through tpCustomHTML. That, however, would be rather opaque and inflexible.

See also http://stackoverflow.com/a/2880147/2751851 , from which the sync request snippet was mostly taken.

How sane do you think this approach is, and how long is it likely to survive given the evolution of the API? Also, I noticed that improvements to the FFI are being prepared for 0.5, including support for exporting Haskell callbacks. Will they be applicable to this scenario - for instance, by loading a library with jQuery's getScript while passing the rest of the Haskell initialization as a callback?

duplode avatar Feb 20 '14 08:02 duplode

I have to admit that I don't quite understand the details of the issue. It seems to be about code in a <script> which is required to be loaded before a <div class="autocomplete"> elements can be added?

For the moment, the recommended solution for including external JS libraries is to write a custom HTML file and use the tpCustomHTML configuration option. (Unfortunately, issue #60 makes custom HTML less useful than it should be at the moment.)

However, I'm happy to add an addScriptElement function similar to the existing addStyleSheet at some point.

More generally, in every GUI framework, there is always the tension between creating elements programmatically or loading them from a configuration file (a custom HTML file). I'd like to support both, but the implementation is currently very sloppy.

HeinrichApfelmus avatar Feb 21 '14 14:02 HeinrichApfelmus

I have to admit that I don't quite understand the details of the issue. It seems to be about code in a ><script> which is required to be loaded before a <div class="autocomplete"> elements can be > >added?

Yup, in essence that's it. A jQuery Autocomplete widget is initialized with $('#some-element').autocomplete(), which is trivially translated to Threepenny FFI calls to something like element someElement # autocompleteInit; however, that only works if the jQuery UI script was loaded by the time autocompleteInit is called. Any addScriptElement function would ideally be work around that issue, through either synchronous loading or Haskell-to-JS callbacks.

As for the tension you mention, it also appears in another level when we consider how to setup a JavaScript bindings library. On the one hand, it would be good to make life easier for the library user by avoiding the need to use tpCustomHTML and the addition of a data dependency to client code - in particular, one that core Threepenny will rely on. On the other hand, bundling any sizable JavaScript library in a cabal package would likely be very inconvenient, to the point it would become easier for everyone involved to just let users package the JavaScript however they feel best and use tpCustomHTML for configuration.

duplode avatar Feb 21 '14 19:02 duplode