Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Include script once and only once in a custom Editor

So I'm trying to create a custom editor so that for a DataType of "Duration" a textbox appears with a masked format of HH:MM:SS.

I've created a very simple piece of code so far

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line", type = "duration" })

<script>
    $(document).ready(function () {
        $("#@Html.NameFor(c => c)").mask("00:00:00");
    });
</script>

This is in my ~/Views/Shared/EditorTemplates/Duration.cshtml file. However it requires an additional javascript to be loaded (maskedInput.js).

Is there any razor includes I can use here so that I can include the maskedInput.js file once and only once in a page load. I realise I could add it to the parent page the editor will be on (but that would require knowing every page where this editor is used). I could add it to the master layout view but this would mean overhead for the pages that don't use this editor.

So I suppose in summary all I'm asking is :- "Is there a way to include a javascript file once and only once from a EditorTemplate".

like image 665
John Mitchell Avatar asked Jun 28 '13 13:06

John Mitchell


People also ask

Can I write script in partial view?

A Note About Script Binding for Partial ViewsJavaScript functions can be bound to elements on the partial view; the partial view is rendered at the same time as the parent view. This happens when loading the partial view with a @Html. Action helper method, as in this section from Edit.

Should I put all my JavaScript in one file?

You should put your JS code in a separate file because this makes it easier to test and develop. The question of how you serve the code is a different matter. Serving the HTML and the JS separately has the advantage that a client can cache the JS.

How many script elements are permitted on a page?

The number of script tags loaded increases the more the user navigates through the application. Is there a limit imposed by HTML on how many script tags can appear in the head of a document? no, there's no real limits to html, but anything more than a few (say 10, max) script tags is getting into ludicrous territory.

Does the order of script tags matter?

Script tags are executed in the order they appear It also means scripts which appear later on the page can depend on things scripts which appear earlier have done. Elements on the page won't render until all the script tags preceding them have loaded and executed.


1 Answers

I wrote a nuget package exactly for this purpose and wrote the blog post that YD1m has referred to.

To use the package, first thing you need to do is add a call to Html.RenderScripts() somewhere in your layout so that all of the script file references and blocks added using the helpers during the rendering of a Razor view are outputted in the response. The typical place to put this call is after the core scripts in your top level layout. Here's an example layout:

<!DOCTYPE html>
<html lang="en"> 
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title>@ViewBag.Title</title>
        <meta name="viewport" content="width=device-width">
    </head>
    <body>       
        @RenderBody()           
        <script src="~/Scripts/jquery-2.0.2.js"></script>
        @* Call just after the core scripts in the top level layout *@
        @Html.RenderScripts()    
    </body>
</html>

If you're using the Microsoft ASP.NET Web Optimization framework, you can use the overload of Html.RenderScripts() to use the Scripts.Render() method as the function for generating scripts:

@Html.RenderScripts(Scripts.Render)

With that done, now all you need to do in your editor template is use the helpers in the nuget package to add a reference to the script and add your code block

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line", type = "duration" })

@using (Html.BeginScriptContext())
{
    Html.AddScriptFile("~/Scripts/maskedInput.js");
    Html.AddScriptBlock(
        @<script>
            $(document).ready(function () {
                $("#@Html.NameFor(c => c)").mask("00:00:00");
            });
        </script>);
}

The referenced script file will only be added once to the page and all of the script blocks will be written out at the end of Html.RenderScripts() call.

Using the helpers, you can add script files and script blocks in Views, Partial Views and Editor/Display Templates. Note that the current version (1.1.0.0) will not render out scripts using the helpers when called via AJAX but this is something that I'm looking to add in the next version.

like image 56
Russ Cam Avatar answered Nov 05 '22 10:11

Russ Cam