rumkin / pill

Add dynamic content loading to static sites with only 1 KiB of JS
https://rumkin.github.io/pill/
MIT License
383 stars 18 forks source link

Script tags aren't evaluating #5

Closed tamb closed 4 years ago

tamb commented 5 years ago

I'm trying to split out separate webpack files and load them within the content div. The browser is evaluating style tags fine, but not script tags.

I'm using http-server and checking my logs. There's no log of even a 404 on the external js file.

I get loading static html. But how can I load other js files?

tamb commented 5 years ago

I was able to find a good loading script on SO: https://stackoverflow.com/questions/950087/how-do-i-include-a-javascript-file-in-another-javascript-file#answer-54986702

Then I used your onReady hook to fire a CustomEvent pill-loaded

I listened for this event and parsed the location.pathname. I run a switch statement on the pathname and use the function mentioned in that SO answer dynamicallyLoadScript to load in the bundle I need. Seems like a lot of work. But it works. I bet I could chunk it out with webpack and use a CustomEvent again to do dynamic imports...

I would recommend a method like this in your documentation. I would also clarify the line:

Each document of the site should surround #content element with the same HTML.

This makes it sound like each html page has to be the same. But that's not true. It's for the sake of keeping navigation.

I love this library btw. It's much easier to handle than turbolinks!

tamb commented 5 years ago

Would recommend creating documentation to handle this case.

rumkin commented 5 years ago

@tamb Thanks, for the issue. I will think how to handle this to make scripts work out of the box. Not sure if this should be digging out from documentation.

tamb commented 5 years ago

@rumkin I definitely think it should be added to the documentation. I also would consider offering solutions like described above. There's probably no need to add this functionality to the library. But developers should be made aware of this.

ioalex commented 4 years ago

@tamb Would you happen to have an example of your code? I'm in a similar situation and your code would really help me figure this out. Sorry, I know it's been a while, so you don't have it that's cool!

tamb commented 4 years ago

The StackOverflow above address the issue well.
The idea is that the markup thar pill is fetching contains a script tag. The browser will not parse that script. I believe for security reasons. A way around this would be to use the SO answer above and in your fetched HTML probably have the script src in a data- attribute. Then you use the onReady hooks and find that attribute and dynamically add the script

From my understanding this should work.

ioalex commented 4 years ago

Appreciate it @tamb. I'll give it a go!

tamb commented 4 years ago

Appreciate it @tamb. I'll give it a go!

My understanding is that there will be plugins for this library in the future. There should be one made to resolve this.

ioalex commented 4 years ago

@tamb That would be really nice

ioalex commented 4 years ago

@rumkin In the corner case section of the README, you mention that "You should place all scripts on top of your page or run JS manually." Do you mean I should place all scripts in the head section of the HTML file?

rumkin commented 4 years ago

@ioalex You could place scripts into head element or in the end of the body (for example next to the content element). And to turn custom logic on and off with onMounting and onUnmounting hooks.

Like this:

<!DOCTYPE html>
<html>
  <head></head>
  <body>
    <div id="content"></div>
    <!-- common scripts -->
    <script src="/scripts/pill.js" />
    <script src="/scripts/site.js" />
    <script>
       pill('#content', {
          onMounting(page, url, element) {
            // Init page, for example bind event listeners, start timers, etc.
            Site.initPage(url, element)
          },
          onUnmounting(page, url, element) {
            // Uninitialise page, for example remove event listeners, stop timers, etc.
            Site.destroyPage(url, element)
          },
       })
    </script>
</html>

Where Site is your custom behaviour from /scripts/site.js script.