Tags: , , , , | Categories: ASP.Net, C#, Javascript, MVC, Razor Posted by Admin on 6/15/2011 2:24 PM | Comments (2)

Sometimes you just want your javascript to execute after the page is loaded, simply put your <script> block just before your </body> tag and you're done. But if your page is made up of a layout, view and various partial views then this is how to keep those script calls at the end of the page and have them fire in the correct order.

Add these methods to your extension methods class (or create one).

public static MvcHtmlString AddScript(this HtmlHelper htmlHelper, Func<object, HelperResult> script, int executionSequence = int.MaxValue)
{
    Dictionary<int, List<Func<object, HelperResult>>> scripts = new Dictionary<int, List<Func<object, HelperResult>>>();
    if (htmlHelper.ViewContext.HttpContext.Items["_scripts_"] != null)
    {
        scripts = htmlHelper.ViewContext.HttpContext.Items["_scripts_"] as Dictionary<int, List<Func<object, HelperResult>>>;
    }

    if (!scripts.ContainsKey(executionSequence))
    {
        scripts.Add(executionSequence, new List<Func<object, HelperResult>>());
    }

    scripts[executionSequence].Add(script);
    htmlHelper.ViewContext.HttpContext.Items["_scripts_"] = scripts;
    return MvcHtmlString.Empty;
}

public static IHtmlString RenderScripts(this HtmlHelper htmlHelper)
{
    foreach (object key in htmlHelper.ViewContext.HttpContext.Items.Keys)
    {
        if (key.ToString() == "_scripts_")
        {
            var scripts = htmlHelper.ViewContext.HttpContext.Items[key] as Dictionary<int, List<Func<object, HelperResult>>>;
            foreach (var index in scripts.Keys.OrderBy(x => x))
            {
                foreach (var script in scripts[index])
                {
                    var template = script as Func<object, HelperResult>;
                    if (template != null)
                    {
                        htmlHelper.ViewContext.Writer.Write(template(null));
                    }
                }
            }
        }
    }

    return MvcHtmlString.Empty;
}

Call AddScript in your views and partials

<h2 id="indexHeader">Index</h2>
@Html.AddScript(
@<text>
    jQuery('#indexHeader').css('font-size', '18em');
</text>, 1)

Call RenderScripts in your layout.

<body>
    @RenderBody()
    <script>
        @Html.RenderScripts()
    </script>
</body>