Click here to Skip to main content
Click here to Skip to main content
Articles » Web Development » Ajax » Libraries » Downloads
 
Add your own
alternative version

ensure - Ensure JavaScripts/HTML/CSS are loaded on-demand when needed

, 9 Jun 2008 CPOL
A tiny JavaScript library that provides a handy function "ensure" which allows you to load JavaScript, HTML, CSS on-demand and then execute your code. ensure ensures that relevant JavaScript and HTML snippets are already in the browser DOM before executing your code that uses them.
<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ OutputCache NoStore="true" Location="None" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Javascript "using" test</title>
    
    <style type="text/css">
        body {
        	background-color: #666600;
	        color: #FFFFFF;
	        font-family: Arial, Helvetica, sans-serif;
	        font-size: 12pt;
	    }
        p { line-height: 150% }
        
        h1 { font-size: 16pt }
        h2 { font-size: 14pt; }
        div.box { float: left; width: 310px; margin: 5px}
        fieldset.testarea { background-color: #4F4F00; border:none; width: 980px; margin-bottom: 20px; padding: 10px; clear:both; display:block; overflow: visible}
        fieldset.testarea em { color:lightgreen; }
        fieldset.testarea a { color:lightblue; }        
        fieldset.testarea h3 { font-size: 1em; height: 2.5em; }
        div.no { font-size: 4em; font-family: Georgia,"Times New Roman",Times,serif; }
        
        p.description
        {
            color: #FFFF99;
            font-size: 0.7em;
            font-weight: bold;
            height: 5em;
            line-height: 120% 
        }
        p.description em { color: lightgreen; font-size: larger; }
        
        code
        {
            font-family: "Courier New", Courier, monospace;
            font-size: 9pt;
            color: #DCDCCC;
            background-color: #414141;
            padding: 4px;
            display: block;
            font-weight: bolder;
            letter-spacing: 1px;
        }
        
        div.example { display:block; background-color: lightyellow; color: black; border: solid 4px black; padding: 10px}
        div.example p { font-size: 10pt }
        p.code { font-size: smallest; font-family: Courier New }
        
        #resultDiv { border: solid 2px black; font-style: italic; background-color: lightgrey }
        
    </style>
    
    <script type="text/javascript" src="Javascripts/jQuery-1.2.3.js"></script>
    <!--<script type="text/javascript" src="Javascripts/MicrosoftAjax.js"></script>-->
    <!--<script type="text/javascript" src="Javascripts/Prototype-1.6.0.js"></script>-->
    <script type="text/javascript" src="Javascripts/ensure.js"></script>
    
    <script type="text/javascript">
    //<![CDATA[[
    var someNullValue = null;
    var someNonNullValue = {};
    var someFalseFunction = function() { return false; }    
    var someTrueFunction = function() { return true; }    
    
    /*
    ensure( {test: someNullValue}, function()
    {
        alert("Works on test:null");
    });
    
    ensure( {test: 'Sys'}, function()
    {
        alert("Works on test:'Sys' when Sys is undefined");
    });
    
    ensure( {test:someFalseFunction}, function()
    {
        alert("Works on test:function(){...} when function returns false");
    });
    
    ensure( {test:someNonNullValue}, function()
    {
        alert("Works on test:non-null value");
    });
    
    ensure( {test:someTrueFunction}, function()
    {
        alert("Works on test:function(){...} when function returns true");
    });
    
    
    // ensure a particular JS object is available, if not download the neessary javascript 
    ensure({
        test:   "SomeJS",
        js:     "Components/SomeJS.js"
        }, 
        function()
        {
            if( typeof SomeJS == "undefined" )
                alert("SomeJS was not loaded successfully");
            else
            {
                SomeJS();
                
                // ensure the JS object is available and callback fires imediately as the necessary
                // javascript is already loaded
                ensure({test:"SomeJS"}, function()
                {
                    if( typeof SomeJS == "undefined" )
                        alert("SomeJS was not loaded successfully");
                    else
                        SomeJS();
                });
            }
        }
    );
    
    ensure({html:"Components/Popup.aspx", css:"Components/Popup.css"},
        function()
        {
            document.getElementById('Popup').style.display = "block";
        });
    
    ensure({
        js:     "Components/BlockUI.js", 
        html:   ["Components/BlockUI.html","Components/Popup.aspx"], 
        css:    "Components/Popup.css"
        }, 
        function()
        {
            BlockUI.show();
            var popup = document.getElementById('Popup');
            if( null == popup ) alert("Popup is not loaded!");
            else popup.style.display = "block";
        });
    */
    
    function showPopup()
    {
        ensure({
            js:     'Components/BlockUI.js', 
            html:   ['Components/BlockUI.html','Components/Popup.aspx'], 
            css:    'Components/Popup.css'
            }, 
            function()
            {
                BlockUI.show();
                var popup = document.getElementById('Popup');
                if( null == popup ) alert('Popup is not loaded!');
                else popup.style.display = 'block';
                
                document.getElementById('example3button').value = "Show me the UI";
            });
    }
    //]]>
    </script>
</head>
<body>
    <form id="UsingTest" runat="server">
	<h1>Javascript &quot;ensure&quot; library</h1>
    <h2>Load HTML, Javascript, CSS on demand before executing code or html snippets</h2>
    
    <fieldset class="testarea">
        <code>ensure( {js:"some.js", html:"some.html", css: "some.css"}, function(){ ...do your work...  } );</code>
        <div class="box">
            <div class="no">1.</div>
            <h3>Ensure Javascript before calling</h3>
            <p class="description">Ensure Javascript libraries or your own functions are avaible 
                before calling them. If they are not available, they will be loaded and then 
                your code will execute.</p>
            
            <div id="example1" class="example">
                <p>The following button loads a Javascript on-demand and calls a function:</p>
                <p class="code">
                &lt;input type="button" value="Click me" onclick="ensure({js:'Components/SomeJS.js'}, function(){ SomeJS(); })" /&gt;
                </p>
                <input id="example1button" type="button" value="Click me" onclick="this.value='Loading...'; ensure({js:'Components/SomeJS.js'}, function(){ SomeJS(); this.value='Click me'; }, this)" />
                
                <p>Some.js defines a function named SomeJS like this:</p>
                <p class="code">function SomeJS() { alert("Hi I am from SomeJS"); }</p>
                <p>The function is available only when the Javascript file is loaded. Clicking on the button will load the 
                javascript and call the function.</p>                
            </div>
        </div>
        
        <div class="box">
            <div class="no">2.</div>
            <h3>Ensure UI loaded before showing/manipulating</h3>
            <p class="description">Load html UI fragments on demand when needed. For example, 
                popup dialog box or some UI block that appears on some user action. Instead of 
                delivering all such UI fragments upfront, you can load them on-demand</p>
            
            <div id="example2" class="example">
                The following button will load a html snippet and CSS on-demand and then show the html inside the dummy DIV below.
                <p class="code">
                &lt;input type="button" value="Load Html, CSS on-demand" onclick="ensure <br />
                ({html:'Components/HtmlSnippet.htm', <br />
                css:'Components/HtmlSnippet.css', <br />
                parent:'resultDiv'}, <br />
                function(){ <br />
                document.getElementById('clickMe').<br />onclick = function() <br />
                { alert('Clicked'); } })"<br /> /&gt;                               
                </p>

                <input id="example2button" type="button" value="Load Html, CSS on-demand" onclick="this.value='Loading...'; ensure({html:'Components/HtmlSnippet.htm',css:'Components/HtmlSnippet.css',parent:'resultDiv'}, function(){ document.getElementById('clickMe').onclick = function() { alert('Clicked');  }; this.value='Load Html, CSS on-demand' }, this)" />
                <p>When you click the button, an html file and a CSS is loaded on-demand and the UI is inserted inside the dummy DIV. Once the UI is loaded, you can write DOM manipulation code that uses the loaded html elements</p>
                <div id="resultDiv">This is a dummy DIV where the content will appear</div>
            </div>
        </div>
        
        <div class="box">
            <div class="no">3.</div>
            <h3>Load application features on de-mand</h3>
            <p class="description">You can load multiple Javascript libraries, CSS, HTML 
                fragment all at once before delivering some feature to user. This allows you to 
                break up a complex application into small manageable components that are loaded 
                only when needed</p>
            
            <div id="example3" class="example">
                <p>Now the season finally, this button will load several Javascripts, HTML and CSS on demand</p>
                <p class="code">
                &lt;input type="button" value="Show me the UI" onclick="showPopup()" /&gt;               
                </p>
                
                <input id="example3button" type="button" value="Show me the UI" onclick="this.value='Loading...'; showPopup()" />               
                
                <p>Here, showPopup() is defined as:</p>
                <code>
    function showPopup()<br />
    {<br />
        ensure({<br />
            js:     'Components/BlockUI.js', <br />
            html:   ['Components/BlockUI.html',<br />
                    'Components/Popup.aspx'], <br />
            css:    'Components/Popup.css'<br />
            }, <br />
            function()<br />
            {<br />
                BlockUI.show();<br />
                var popup = document.getElementById('Popup');<br />
                if( null == popup ) alert('Popup is not loaded!');<br />
                else popup.style.display = 'block';<br />
            });<br />
    }            <br />
                </code>
            </div>
        </div>
    </fieldset>
    
    <fieldset class="testarea">    
        <h3>What is <em>ensure</em></h3>
        <p><em>ensure</em> allows you to load Javascript, HTML and CSS on demand, whenever 
            they are needed. It saves you from writing a gigantic Javascript framework 
            upfront so that you can ensure all functions are available whenever they are called. It 
            also saves you from delivering all possible html on your default page (e.g. default.aspx) hoping 
            that they might some day be 
            needed on some user action. Delivering unnecessary Javascript, html fragments, CSS during initial 
            loading makes initial loading slow. Moreover, browser operations get slower as 
            there are lots of stuff on the browser DOM to deal with. So, <em>ensure</em> 
            saves you from delivering unnecessary javascript, html and CSS upfront instead load 
            them whenever needed, on-demand. Javascripts, html and CSS loaded by <em>ensure</em> remain in the browser and next time when <em>ensure</em> 
            is called with the same Javascript, CSS or HTML, it does not reload them and 
            thus saves from repeated downloads.</p>
        <p>For example, you can use <em>ensure</em> to download Javascript on demand:</p>
        <code>ensure( { js: &quot;Some.js&quot; }, function()<br />
        {<br />
&nbsp;&nbsp;&nbsp; SomeJS(); // The function SomeJS is available in Some.js only<br />
        });</code><p>The above code ensures Some.js is available before 
        executing the code. If the SomeJS.js has already been loaded, it 
        executes the function write away. Otherwise it downloads Some.js, waits 
        until it is properly loaded and only then it executes the function. Thus it 
        saves you from deliverying Some.js upfront when you only need it upon some user 
        action.</p>
        
        <p>Similarly you can wait for some HTML fragment to be available, say a popup 
        dialog box. There&#39;s no need for you to deliver HTML for all possible popup boxes 
        that you will ever show to user on your default web page. You can fetch the HTML whenever you need them.</p>
        <code>ensure( {html: &quot;Popup.html&quot;}, function()<br />
        {<br />
&nbsp;&nbsp;&nbsp; // The element &quot;Popup&quot; is available only in Popup.html<br />
&nbsp;&nbsp;&nbsp; document.getElementById(&quot;Popup&quot;).style.display = &quot;&quot;;&nbsp;&nbsp;&nbsp;
        <br />
        });</code>
&nbsp;<br />
        <p>The above code downloads the html from "Popup.html" and adds it into the body of the 
        document and then fires the function. So, you code can safely use the UI element from that html.</p>
        <p>You can mix match Javascript, html and CSS altogether in one <em>ensure</em> call. 
            For example,</p>
        <p>
        <code>ensure( { js: &quot;popup.js&quot;, html: &quot;popup.html&quot;, 
            css: &quot;popup.css&quot; }, function()<br />
        {<br />
&nbsp;&nbsp;&nbsp; PopupManager.show();<br />
        });</code> </p>
        <p>You can also specify multiple Javascripts, html or CSS files to ensure all of 
            them are made available before executing the code:</p>
        <p>
        <code>ensure( { js: [&quot;blockUI.js&quot;,&quot;popup.js&quot;], html: [&quot;popup.html&quot;, &quot;blockUI.html&quot;], 
            css: [&quot;blockUI.css&quot;, &quot;popup.css&quot;] }, function()<br />
        {<br />
&nbsp;&nbsp;&nbsp; BlockUI.show();<br />
        &nbsp;&nbsp;&nbsp; PopupManager.show();<br />
        });</code> </p>
        
        <p>You might think you are going to end up writing a lot of <em>ensure</em> code all over your 
            Javascript code and result in a larger Javascript file than before. In order to save you 
            javascript size, you can define shorthands for commonly used files:</p>
        
        <code>var JQUERY = { js: &quot;jquery.js&quot; };<br />
                var POPUP = { js: [&quot;blockUI.js&quot;,&quot;popup.js&quot;], html: [&quot;popup.html&quot;, &quot;blockUI.html&quot;], 
            css: [&quot;blockUI.css&quot;, &quot;popup.css&quot;] };<br />
        ...<br />
        ...<br />
        ensure( JQUERY, POPUP, function() {<br />
&nbsp;&nbsp;&nbsp; $(&quot;DeleteConfirmPopupDIV&quot;).show();<br />
        });<br />
        ...<br />
        ...<br />
        ensure( POPUP, function()<br />
        {<br />
&nbsp;&nbsp;&nbsp; $(&quot;SaveConfirmationDIV&quot;).show();<br />
        );</code>
      
        
        <p>While loading html, you can specify a container element where ensure can inject 
            the loaded HTML. For example, you can say load HtmlSnippet.html and then inject 
            the content inside a DIV named &quot;exampleDiv&quot;</p>
        <p><code>ensure( { html: [&quot;popup.html&quot;, &quot;blockUI.html&quot;], parent: &quot;exampleDiv&quot;}, 
            function(){});</code></p>
        <p>You can also specify Javascript and CSS that will be loaded along with the html.&nbsp;</p>
        <h2>Download Code</h2>
        <p>Download latest source code of re</em> from CodePlex: <a href="http://www.codeplex.com/ensure">
            www.codeplex.com/ensure</a></p>
        
    </fieldset>
    
    </form>
</body>
</html>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Omar Al Zabir
Architect BT, UK (ex British Telecom)
United Kingdom United Kingdom

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 9 Jun 2008
Article Copyright 2008 by Omar Al Zabir
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid