What’s in an SPA?

Initially nothing. You can start from zero. Or have a landing page with a login, like in this case:

<body>
<div data-role="page" id="login">
<div class="login">
        <label for="user">User</label><input id="user"/>      
        <label for="pwd">Password</label><input id="pwd" type="password" />
   <button>Login</button>
    </div>
</div>
</body>

The header is equally frugal.

<head>
    <meta charset="UTF-8" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-touch-fullscreen" content="yes" />
   <meta name="viewport" content="user-scalable=no, width=device-width">
    <title>SPA</title>

<link rel="stylesheet" href="css/jquery.mobile-1.4.3.min.css" />
<link rel="stylesheet" href="css/base.css" />

<script src="libs/jquery-2.1.1.min.js" type="application/javascript"></script>
<script src="libs/jquery.mobile-1.4.3.min.js" type="application/javascript"></script>
<script src="libs/can.custom.js" type="application/javascript"></script>
<script src="libs/require.js" type="text/javascript"></script>

<scipt>
'use strict';

var objApp;

// a couple of functions that I’ll discuss below in the article

</script>
</head>

I want to have jQueryMobile available from the beginning. Can.js is the basis of my MVC framework, so I have it loaded too. And Require.js, the tool that I’ll be using to load the code only when the user needs it. Forget about loading all of your JavaScript “just in case”.

Now, you don’t really have to do nothing of until the user asks you to, so let’s wait for her to tap on the Login button and then start your app:

$(function () {
    $('#login button').on('click', function(event) {
        event.preventDefault();
        if(!objApp) {
            require(['utils', 'app'],
                    function(utils, app) {
                                objApp = app;
                                login();
                            }
                    );
        } else {
            login();
        }
    });
});

I’m declaring the global objApp just to be a good citizen (and to pass my own strict jshint validations). Once the user decides to login I start loading code. Using Require.js I ask for utils.js and app.js files. You’ll notice that the callback receives two parameters, utils and app and I only use the second one. The reason is simple: in utils.js I have different objects, functions and some native functions overrides. I’m just declaring them as globals. In app.js I have something completely different: a couple of can.js based objects, ModulesHander and Application (what’s in those objects and what they do is irrelevant right now) and this magic block of code:

define(
    function () {
        return new Application();
    }
);

This is the code that will tell to Require.js what is the result of loading app.js: a newly instantiated Application object. And that object is what Require.js passes to my callback: a brand new Application object that I assign to the objApp var. And then I attempt to login().

function login() {
    objApp.authenticate(
                        $('#user').val().trim(),
                        $('#pwd').val().trim(),
                        function (boolOK) {
                          if(boolOK) {
                                objApp.launch();
                            } else {
                                alert(‘Wrong user or password.');
                            }
                        });
}

At this point of execution I know that objApp “contains an Application” so I can just call any of its methods, such as authenticate() to check if the user and password belong to a valid user and retrieve the configuration for that user. Or such as launch(), that is the method that put in action the rendering of any required pages and the loading of needed modules.

Now, your app is ready to go. To continue…?