SUMMARY: Bought a javascript book and a jQuery cookbook to get familiar with common programming solutions. Figured out the flow of execution for the javascript-side of the web app. Added dynamic javascript load support, which will allow me to manage the code more easily into a standard MVC split.
I picked up a couple of books from Barnes & Noble last week:
- Pragmatic Guide to Javascript – a highly distilled book about the essence, as far as I can tell, of Javascript programming. I like how it uses multiple javascript library examples for each concept. Targeted toward experienced programmers, so it doesn’t waste a lot of time re-introducing concepts. The tone is reminiscent of talking shop with an experienced programmer, sprinkled with useful insights into the very nature of the javascript.
- jQuery Cookbook – This is a solutions-oriented book, as most cookbooks are, with very specific examples on how to accomplish common programming tasks. It’s precisely what I need.
Last week, I’d written my first fragments of jQuery-flavored Javascript, performing simple toggle operations. This is stuff that happens on the browser. Now it’s time to send some data to the web server.
What Should Happen
There is an entire layer of dynamic object management that I will have to write at some point, but in the meantime I’m just going to focus on getting the javascript to talk to the webserver and update the database.
To keep things simple, I’ll define the task as follows:
- Request the list of current objects from the server
- Draw the objects into the browser
- Handle events as they come through for the UI
- Write changes back to the server
This is pretty standard MVC-style organization. The next step is to start writing the skeleton of this code. I like to use placeholder functions that print out what they are supposed to be doing, then going back and filling them in with working code. It helps reinforce my understanding of the code and the flow of interactive program execution, like a “living outline” of the program.
Where do functions live?
So…where does it make sense to handle step 1? Probably on jQuery.ready(), which fires before the web page has been rendered but after the DOM is completely read.
On the server side, I have a skeleton application class called app.php
. I was about to put stuff here but then I remembered DUH, I need to put this on the JAVASCRIPT side. Each script is loaded in the page template with a call to a function called dseah_pagescript('script.js')
, which loads from my scripts directory in the template folder. The actual script load happens just before the closing body tag. This is the start of javascript execution, the seat of interactivity. The PHP side of things will handle data only, I think.
Where is the execution loop?
Unlike game programming, there isn’t a main loop running in a web app as far as Javascript is concerned. Scripts are intended to run for short bursts, as they block browser updates until they finish running. In that respect, the browser itself is the main controlling loop. Javascript is used to execute in-line with browser code, and also to handle events.
What I need to do is, on initialization, create elements and bind event handlers to them. The list of elements is retrieved from the server, which is used to populate a javascript-side data structure (the “model” in MVC) that is used to create the “view” in the browser. The controller is what ultimately handles the various commands that come in from the UI event handler code.
Looking at Javascript’s classless approach to objects, I’m wondering the best way to define the controller, interpreter, model, and view code in a way that’s maintainable. For me, that means having the major code chunks defined in their own files. According to this Stack Oveflow question, you can asynchronously load and execute scripts, activating on a callback event. The loaded script executes after the current script has finished executing.
What about namespaces? Does everything go into a global namespace? There’s a nifty article series that describes /javascript, so that may be helpful when I get to the point I have to refactor code. I also just read about some odd Javascript features there, such as its use of function as-opposed to block scoping, and the ability to rewrite functions on-the-fly. This moved me to read the wikipedia entry on Javascript to get a better sense of the language’s history. This is a nice overview of the language’s differences from Java (historical tidbit: it has nothing to do with it) and C.
Writing Initialization
Let’s get the javascript part of this loaded! My goals were to:
- Load individual javascript files dynamically, so I can break up the source code into manageable chunks
- Define a main entry point for the Javascript code, when everything is initialized and ready to go
I had to modify the template PHP to pass along the theme’s stylesheet location, because the scripts I’m loading live in the stylesheet directory. This is passed as a javascript variable just before the main template javascript file executes:
// global variables // DS_ScriptURI is set in HTML via PHP template loader for our convenienience // initialize debug logger DBG = new Object(); DBG.enabled = true; DBG.Out = function (msg) { if (DBG.enabled) console.log("[JS] "+msg); } // initialize loader DS_Scripts = new Object(); DS_Scripts.loaded = false; DS_Scripts.scripts = ["second-controller.js","second-model.js"]; DS_Scripts.scriptCount = DS_Scripts.scripts.length; DS_Scripts.ErrorHandler = function(e,request,settings,ex) { DBG.Out("Error loading "+settings.url); DBG.Out(ex); } DS_Scripts.ScriptLoadSuccess = function () { if (DS_Scripts.scriptCount>0) { DS_Scripts.scriptCount--; } if (DS_Scripts.scriptCount==0) { DS_Scripts.loaded = true; JavascriptMain(); } } // load scripts when all of DOM is initialized but not yet rendered jQuery(document).ready( function($) { // load scripts dynamically $(document).ajaxError(DS_Scripts.ErrorHandler); for (n in DS_Scripts.scripts) { var scriptname = DS_ScriptURI + DS_Scripts.scripts[n]; $.getScript(scriptname, DS_Scripts.ScriptLoadSuccess); } // execution continues in JavascriptMain() }); // Main Javascript Entry Point // everything should be initialized on server by now // scripts also should have been all initialized // top level js objects ready to instantiate! function JavascriptMain() { if (DS_Scripts.loaded==false) return; DBG.Out("Load object list from server into Model"); DBG.Out("Create browser elements from Model"); DBG.Out("Render Model to View"); }
I create an object that holds a list of scripts (line 12). When the page’s DOM has been loaded but not-yet rendered, the list of scripts is asynchronously loaded via jquery.getScript(). Every time a script is loaded and parsed, the ScriptLoadSuccess() callback is triggered, which compares the number of calls to the number of scripts in line 12. When the number of success callbacks matches the number of scripts, JavascriptMain()
is called.
So this gives me some flexibility in defining an arbitrary number of scripts to load and execute. This will allow me to put each main object (e.g. models, controller, database connector) in its own file, which will help me keep development cleaner. If I need to speed things up, I can combine it all into a single script later.
The next steps are about writing code to:
- load object list from the server into an internal data structure
- create browser objects from the data structure
- hook event handlers into the objects
- render the data to the browser
Finally, we are into the meat of application development!
0 Comments