andrewdavey / knapsack

Project moved to https://github.com/andrewdavey/cassette
MIT License
24 stars 3 forks source link

Option for header and footer scripts #5

Closed bkaid closed 4 years ago

bkaid commented 13 years ago

One idea I had is adding a location parameter or a string code so that you can call @Html.ReferenceScript("top", "~/myscript.js") and then in your header call @Html.RenderScripts("top") and in your footer call @Html.RenderScripts("bottom"). This way you could push all async loading scripts to the top and blocking scripts to the bottom. I can fork and submit a pull if you think this is a good way to handle it.

andrewdavey commented 13 years ago

Thanks for taking a look at Knapsack. You raise an interesting issue. I'm trying to work out the best API for this multiple module "blocks" feature. It seems that a module always needs to appear in the same location, top or bottom. So having to specify this on every constituent script reference may get frustrating. Perhaps this could be a configuration setting instead?

bkaid commented 13 years ago

You are right - there are really only top or bottom scripts. But for a given page I may want some up top and some at the bottom so I'm not sure if a configuration setting would work. Maybe Html.ReferenceAsyncScript("script.js") and Html.ReferenceScript("script.js") and Html.RenderScripts() and Html.RenderAsyncScripts()

andrewdavey commented 13 years ago

Out of interest, what scripts do you put in the <head> of your pages? When does the location requirement change? I seem to always put scripts at the bottom of pages.

bkaid commented 13 years ago

Maybe you are right that this isn't actually needed. The only scripts I put in the are async inline scripts like those required to asynchronously load google analytics or the facebook javascript sdk. I guess what I am looking for that at first I thought Knapsack could also help with is a way for partial views to include async loading scripts for scripts like the Facebook sdk that aren't needed on every view.

andrewdavey commented 13 years ago

I'm still figuring out how Knapsack can and should be used :) So don't let me discourage you! The more ideas the better. Registering scripts from a partial view is exactly one of the use cases I had in mind.

Can you clarify what you mean by async loading? Are you referring to script tags in the body with a defer attribute?

bkaid commented 13 years ago

If my particular view or partial view requires Facebook functionality, I need to add this code to my the end of my section:

Same with pages that I want google analytics.

andrewdavey commented 13 years ago

There's an interesting problem with referencing things that need to be in <head> from a partial view. If partial view has been executed after the <head> has been rendered then any references it makes are missed. This is especially annoying for CSS references, since they must go in the head.

However, after quick test it seems that @Html.Partial("test") called from a content view page actually works! But the same partial, called from a Layout (or a layout-null view page, I assume) does not work. A possible solution is to buffer the entire page output so we can still insert into head after the fact. I'll have a play with the code...

Regarding, your FB/Google analytics snippet do you need a way to embed the script rather than link to it? I can think of other use cases for this ability as well e.g. passing view data into JavaScript globals.

andrewdavey commented 13 years ago

Latest code (and nuget package) has support for script locations. Locations have to be defined at the module level, using web.config. For example:

    <scripts>
        <add path="scripts/base" location="head"/>
        <add path="scripts/lib" location="head"/>
        <add path="scripts/util" location="head"/>
        <add path="scripts/social" location="body"/>
    </scripts>
</knapsack>

Then in the layout:

    @Html.RenderScripts("head")
</head>
<body>
    ...
    @Html.RenderScripts("body")
</body>

Knapsack is now buffering the HTML output (using Response.Filter) so it can insert things into the <head> even from a partial view reference.