Bootstrap sequence for portable web applications

Roonaan
CERTIFIED EXPERT
Published:
Having worked on larger scale sites, we found out that you are bound to look at more scalable solutions to integrating widgets, code snippets or complete applications and mesh them into functional sites, in any given composition.

To share some of our best practices, possibly the most important thing we changed is to eliminate all body onloads and instead rely on a different loading design, which is extremely friendly when your application is to be included by many webpages.

Because it scales both in case of server-side rendering as well as cases of lazy loading content, we are pleased to share a simplified version of the approach as a best practices with Experts Exchange.

So lets start with some code and take, for example, a simple AJAX driven search application.

<html>
                        <head>
                          <script type="text/javascript" src="jquery-1.6.2.min.js"></script>
                        </head>
                        <body>
                          <div class="my-search-app">
                             <form action="/search">
                               <input type="text" name="q" /><input type="submit" value="search" />
                             </form>
                             <div class="my-search-results"></div>
                             <script type="text/javascript" src="my-search-app.js"></script>
                           </div>
                        </body>
                      </html>

Open in new window


In any other, non-portable, application the most sensible JQuery logic to add in my-search-app.js would be:

// Closure
                      (function(window, document, $) {
                      
                        $(document).ready(function() {
                           // Capture search form submit and transfor into AJAX request
                           $('form').submit(function() {
                             // AJAX Logic and stuff
                             fnResults = function(data) {
                                $('.my-search-results').html('Results ... ');
                             }
                           });
                        });
                      
                      // End of closure
                      })(window, document, jQuery);

Open in new window


This portable approach is more complex but we'll explain later on.

(function(window, document, $) {
                      
                        // Generic bootstrap function for each
                        // instance of my-search-app
                        function init(node) {
                           
                           // Prevent duplicated execution of
                           // the bootstrapping logic
                           if (node.isInitialized) {
                              return;
                           }
                           node.isInitialized = true;
                      
                           // Store reference to the JQuery wrapped node.
                           var $node = $(node);
                      
                           // Capture search form submit and transfor into AJAX request
                           $node.find('form').submit(function() {
                             // AJAX Logic and stuff
                             fnResults = function(data) {
                                $node.find('.my-search-results').html('Results ... ');
                             }
                           });
                        }
                      
                        // When this code executes, trigger the
                        // bootstrapping if all instances
                        $(document).ready(function() {
                           $('.my-search-app').each(init);
                        });
                      
                      })(window, document, jQuery);

Open in new window


The most important change one notices is that we use the classname of the outer div element to look up the functional scope of the search application and in further code only execute changes within the scope of that application root node. This is the core principle of portable applications and sometimes called the Isolation Ground Rule: Don't change things outside your application scope, even though javascript and browsers allow you to do so.

So nothing exiting just jet, so let's continue. From this point onwards I can include the code anywhere in other pages and it will work as expected, even when we include it multiple times:

<body>
                         <div id="my-header-wrapper">
                            <div id="my-search-box">
                               <div class="my-search-app">
                                  <form action="/search">
                                     <input type="text" name="q" /><input type="submit" value="search" />
                                  </form>
                                  <div class="my-search-results"></div>
                               </div>
                             </div>
                         </div>
                      
                        <div id="my-full-page-search">
                          <div class="my-search-app">
                            <form action="/search">
                              <input type="text" name="q" /><input type="submit" value="search" />
                            </form>
                            <div class="my-search-results"></div>
                          </div>
                        </div>
                      
                        <script type="text/javascript" src="my-search-app.js"></script>
                      </body>

Open in new window


The power of this loading sequence however is shown when you start lazy loading the applications:

<body>
                        <div id="my-search-form"></div>
                      
                        .. more html ..
                      
                        <script type="text/javascript">
                        // Lazy load the search box application
                        $(document).ready(function() {
                           $('#my-search-form').load('my-search-box.html');
                        });
                        </script>
                      </body>

Open in new window


When you scale this up to the size of enterprise applications the design pattern holds and some additional patterns are added:

<body>
                        <div class="my-lazy-app" data-src="my-search-box.html"></div>
                        <div class="my-lazy-app" data-src="login-app.html"></div>
                        <div class="my-lazy-app" data-src="contextual-navigation.html"></div>
                        <div class="my-lazy-app" data-src="user-profile.html"></div>
                        <div class="my-lazy-app" data-src="social-buttons.html"></div>
                        <script type="text/javascript">
                         $(document).ready(function() {
                           // Load all applications based on their 
                           // declarative application src.
                           $('.my-lazy-app').each(function() {
                              $(this).load($(this).data('src'));
                           });
                         });
                        </script>
                      </body>

Open in new window


If you add to the mix that some of the applications, themselves include sub-applications, you can see the increasing benefit to software reuse that is delivered by this design.

In reality the code is far more complex, including cancellable loading events, plugin points and in general a more complete application lifecycle. But as a best practice this is the minimum baseline we used for our increasing number of applications. As indication that this approach works in reality, let's add that in the latest project we currently number 36 applications that have different compositions running throughout the clients legacy site; it's new internet site; it's intranet site; and ramping up to social networks such as Facebook apps.
3
5,551 Views
Roonaan
CERTIFIED EXPERT

Comments (1)

CERTIFIED EXPERT
Top Expert 2006

Author

Commented:
Thanks, I can see the total, but was wondering if there was a breakdown somewhere.

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.