Category Archives: JavaScript

Eliminating Touch Event Lag via CSS

12 Mar 2014

It’s common knowledge that ontouchstart on mobile doesn’t fire immediately because a 300ms pause is implemented in WebKit to determine if the touchstart is the beginning of a double-tap. For that reason, web app developers use the ontouchend event instead because it doesn’t have any built-in delays.

Some people will try to code around the issue by synthesizing a touchend event when touchstart is detected thereby skirting the inherent delay. FastClick is an example of this sort of work-around.

If you find that you need to make a “click-based” application feel more responsive you could try something like the above – or you could just try some CSS. Its possible to eliminate the standard 300ms delay entirely without any JavaScript:

.yourButtonClass, a {
    -ms-touch-action: none; // Deprecated as of IE 11, Microsoft recommends the the standard below
     touch-action: none; // webkit
}

Related to this topic is this dated article at Quirks Mode which I found to of interest (keep in mind its from 2010): The touch action.

The Pub/Sub Pattern and Event Delegation in jQuery

18 Jan 2014

Recently I had a project that was a single-page micro site. Much of the content changed without reloading so it naturally made use of Ajax. There was DOM manipulation and jQuery was used throughout. I knew I would have a buttons and other elements triggering events. I always delegate events and am always looking for ways to improve upon how I’ve done things in the past. With that in mind and my recent foray into patterns that I don’t usually use I decided to use the PubSub pattern with the usual jQuery event registrations to come up with what I think is a clean method of hooking things up. I’d like to take a moment to talk about how I put it all together.

The Pub/Sub Pattern

The Pub/Sub pattern consists of a system where objects Subscribe to a task of some other object. Once subscribed the Publisher notifies each subscriber that the task they are subscribed to has occurred. In this case the subscription object is an array of objects whose properties are themselves arrays of objects populated with function references. As they are arrays its easy to add (“subscribe”) or remove an index of an array (“unsubscribe”) via the array push and slice methods.

When the pattern is applied we essentially look for the subscription object property that matches the event type. Once found we iterate through all of the function references assigned to it.

We of course have to come up with a method of filtering the events instead of blindly calling all of the subscribers to the given event type. My personal approach to validating an event is two-fold, 1) first validate the type of the event, then 2) look for an expected HTML data attribute and branch out from there. This 2-step approach tends to vary depending on what is happening in any given application but is easily adaptable.

There is more to the subject of Pub/Subs but that’s the gist of it. For a great read on patterns try this link.

Event Delegation with the Pub/Sub Pattern

Lay the foundation

So then lets talk about how to apply this in jQuery while delegating events. I’ll start with some basic JavaScript and create our namespace:

;(function(ns){
    // private
    var _subscriptions= {}; // will hold our subscribers

    // public
    ns.init = function(){
        console.log(typeof _subscriptions);
    }
})(this.app = this.app || {})

Our example is namespaced to “app”. To access its public methods you would use “app.methodName”, for example. Next we need a way to init the app and I’ll do so with jQuery’s document.ready.

;(function(ns){
    // private
    var _subscriptions= {};

    // public
    ns.init = function(){
        console.log(typeof _subscriptions);
    }
})(this.app = this.app || {})

$(document).ready(function(){
    app.init();
});

The above prints the word “object” to the console.

OK, lets whip up a quick HTML page – it will have a single div. It will also contain an unordered list.

<div id="box" style="width:100px;height:100px;background-color:#ccc;border:1px solid #000"></div>
<ul>
    <li>Red</li>
    <li>Blue</li>
    <li>Green</li>
    <li>Orange</li>
    <li>Yellow</li>
</ul>

We will be delegating click events on our LI tags, making them function as our “buttons”. I won’t bother styling them as these are quick and dirty examples, you can make them pretty if you like 😉

The Subscriber Function

Next we need to create a subscriber function to populate the _subscriptions object. The _subscriptions object will hold all the functions (function references, known as “subscriptions” in PubSub lingo) that have “subscribed” to a particular event.

;(function(ns){
    // private
    var _subscriptions= {};

    // public

    /* app.subscribe()
     * This function adds subscribers to the _subscribe object */
    ns.subscribe = function(eType,cb){
        if (!_subscriptions.hasOwnProperty(eType)){
            _subscriptions[eType] = [];
        }
        _subscriptions[eType].push(cb);
    }
    ...
})(this.app = this.app || {})
...

Lets look at the app.subscribe method; it requires 2 arguments:

  • eType – this is the type of the event, such as “click”, or “mouseover”. Yes, its a string.
  • cb – short for callback, this is the function that is waiting to be notified that the associated event took place.

As you can tell from looking at the code we are adding properties to _subscribers that correspond to the event names. If that property doesn’t exist (via hasOwnProperty) then we create it and assign it an empty array. The array will hold the functions (callbacks) that will be notified that the event occurred.

The Publisher Function

The publisher “publishes” events to the subscribers when they occur. I personally prefer to use the word “notify” instead of “publisher”, as in “when the event occurs the subscribers are notified”.

Here’s my app.notify function (aka the “Publisher”):

;(function(ns){
    ...
    /* app.notify()
     * This function notifies those subscribers who have subscribed to a specific event */
    ns.notify = function(e){
        e.stopPropagation(); // stop additional events from firing
        if (!$(e.target).attr('data-action')){ // should we do anything at all?
            e.preventDefault();
            return;
        }
        var cbs = _subscriptions[e.type]; // what type of event are we dealing with?
        for (var i=0;i<cbs.length;i++){ // notify all who have subscribed to the event
            cbs[i](e); // pass along the event object to the subscriber
        }
    }
    ...
})(this.app = this.app || {})
...

One important thing to note is that we need a way of validating that something should happen when an event occurs. As I mentioned previously this is a two-step process. The first thing that I personally do is look for the data-action attribute in the event target. “data-action” is my own personal convention, feel free to use whatever makes sense to you. Anyway, if it exists in the event target – regardless of its value – then I know that it is something that one of my subscribers might want to know about.

The second part of validating the event is within each of the subscribers themselves. I’ll describe this in the next section as it is related to our html.

Setting up your HTML

We need to add the data-action attribute to our LI tags so that we can have something to filter our events against else we won’t be able to qualify that the event is something to pay attention to.

<div id="box" style="width:100px;height:100px;background-color:#ccc;border:1px solid #000"></div>
<ul>
    <li data-action="changeDivColor">Red</li>
    <li data-action="changeDivColor">Blue</li>
    &l;li data-action="changeDivColor">Green</li>
    <li data-action="changeDivColor">Orange</li>
    <li data-action="changeDivColor">Yellow</li>
</ul>

Ok, great, however, if we are planning on changing the color of the div then we need to know the color to use. Lets add another attribute and call it data-color.

<div id="box" style="width:100px;height:100px;background-color:#ccc;border:1px solid #000"></div>
<ul>
    <li data-action="changeDivColor" data-color="cd2027">Red</li>
    <li data-action="changeDivColor" data-color="3252d9">Blue</li>
    <li data-action="changeDivColor" data-color="40b645">Green</li>
    <li data-action="changeDivColor" data-color="e79622">Orange</li>
    <li data-action="changeDivColor" data-color="e7e522">Yellow</li>
</ul>

Ok, we’re done here. By virtue of both data-action and data-color we know that a) we should pay attention to events originating from these elements and b) we know what color to use.

Also please note that data-action serves two purposes – yes, if it exists we’ll notify our subscribers, but also, each subscriber will pay attention to the value of data-action. If it isn’t what the subscriber is expecting then it simply returns and stops executing. This is important as you may have any number of subscribers to the same event but any one of them should only continue if the value of data-action jives with what the subscriber’s role in life is.

Speaking of which, lets look at what a subscriber might look like…..

Event Delegation – Creating Subscriptions and the Subscriber

Well, its about time we delegated an event…. lets delegate the click event by adding some jQuery to our app.init function:

;(function(ns){
    ...
    ns.init = function(){
        // delegate the click event
        $('body').on('click','li',app.notify);
    }
...
})(this.app = this.app || {})
...

We’re delegating the click event such that when it occurs it calls app.notify so that all functions subscribed to the “click” can be notified. Yes, its mapped to the list item element.

Of course we have yet to subscribe to anything so lets create a subscription, again, this happens inside of app.init:

;(function(ns){
    ...
    ns.init = function(){
        // create a subscription
        app.subscribe('click',app.changeColor);

        // delegate the click event
        $('body').on('click','li',app.notify);
    }
})(this.app = this.app || {})
...

We’re missing the changeColor function so lets create it. Note the “if” statement at the top of the following block of code where we’re checking to see if it’s value is what is expected. If not then we return and don’t proceed any further:

;(function(ns){
    ...
    ns.changeColor= function(e){
        if ($(e.target).attr('data-action') != 'changeDivColor'){
            return;
        }
        $('#box').css('background-color','#' + $(e.target).attr('data-color'));
    }
    ...
})(this.app = this.app || {})
...

Thats it – here’s the example followed by the complete javascript:

;(function(ns){
    // private
    var _subscriptions= {}; // holds our subscriptions

    // public

    /* app.subscribe()
     * This function adds subscribers to the _subscribe object */
    ns.subscribe = function(eType,cb){
        if (!_subscriptions.hasOwnProperty(eType)){
            _subscriptions[eType] = [];
        }
        _subscriptions[eType].push(cb);
    }

    /* app.notify()
     * This function notifies those subscribers who have subscribed to a specific event */
    ns.notify = function(e){
        e.stopPropagation(); // stop additional events from firing
        if (!$(e.target).attr('data-action')){ // should we do anything at all?
            e.preventDefault();
            return;
        }
        var cbs = _subscriptions[e.type]; // what type of event are we dealing with?
        for (var i=0;i<cbs.length;i++){ // notify all who have subscribed to the event
            cbs[i](e); // pass along the event object to the subscriber
        }
    }

    /* app.changeColor()
     * This function was subscribed to "click" events */
    ns.changeColor= function(e){
        if ($(e.target).attr('data-action') != 'changeDivColor'){
            return;
        }
        $('#box').css('background-color','#' + $(e.target).attr('data-color'));
    }

    /* app.init()
     * Init the app - setup event subscriptions and event delegation */
    ns.init = function(){
        // create a subscription
        app.subscribe('click',app.changeColor);

        // delegate the click event
        $('body').on('click','li',app.notify);
    }
})(this.app = this.app || {})

$(document).ready(function(){
    app.init();
});
Implications

With this system in place all you have to do to add another subscriber that should be notified of a click event is add the following line in app.init

app.subscribe('click',app.myNewFunction);

Or, if you want something to react to a different event, such as a change event you would need to do the above **and** associate the event with our notify function.

app.subscribe('change',app.myNewFunction);
$('body').on('change','input',app.notify)

and then subsequent subscriptions to the “change” event would just need to do a regular subscription call:

app.subscribe('change',app.myOtherFunction);

In larger apps I use the above as a sort of switchboard between my models, views and utility objects. I don’t have a chain of function calls where func 1 calls func2 which calls func3, all spread out over a large script or multiple files, etc. Instead, my subscribed functions receive their notifications of the desired event, they inspect the event target to see if it is what it they are expecting (via the data-action attribute) and then different function calls are made (i.e. func1, func2, func3). My subscribers all live in my controller object so there’s no function chain to chase down as I can easily go to my controller and see exactly what functions are called for specific events and “actions” (recall my “data-action” convention).

To illustrate, here’s the same example with a few more buttons and events. View the source to review the code:

Logging the _subscriptions object to the console shows that there are 5 subscribers to the “click” event and 1 subscriber to the “mousemove” event.

Object {click: Array[5], mousemove: Array[1]}
  click: Array[5]
    0: function (e){
    1: function (e){
    2: function (e){
    3: function (e){
    4: function (e){
    length: 5
    __proto__: Array[0]
  mousemove: Array[1]
    0: function (e){
    length: 1
    __proto__: Array[0]
    __proto__: Object

Browsing Filesystems in PhoneGap

24 Dec 2013

I recently came up with an idea for an app that required the ability to browse the device’s filesystem. The first thing that I did was review the PhoneGap API and sure enough everything that I needed was there. So, after an afternoon of tinkering I have my own HTML 5 File Browser – browsing-only at this early stage but it wouldn’t be too much extra effort to be able to delete and move files around.

There is no framework in use here – as you’ll see its just basic JavaScript. Performance is very good with fluid stutter-free scrolling. Even with inserting hundreds of files into my view webkit’s native scrolling function doesn’t skip a beat.

[edit 9/13/2015] Updated this edit with instructions for installing the plugin and verified that the app would build against a target android version of 4.1.1 (API level 16) using PhoneGap 5.2.1 with the file plugin version 0.2.4. Tested on an HTC One M8 Android 5.0.2 and a Dell Venue 7840 running Android 5.1 (and as mentioned in the original text found below, a Galaxy S2/Android 4.0.1).

Here’s what you’re probably looking for: Download the project.

Here’s a screen cap of the app running in the aforementioned HTC One M8 via Chrome’s dev tools – again, PG 5.2.1, Android API level 16, File plugin version 0.2.4:

*** This was originally built when PG 1.9 was the current version and 0.2.4 was current for the file plugin. BUT, people still ask me for the code, so I’m providing it here and showing how to install the old version of the file plugin so you can run it in PG 5.2.1. You should really use the current file plugin but… here you go… ***

To add Android 4.1.1 to your PG project:

phonegap platform add android@4.1.1

To install file plugin version 0.2.4:

  1. Download the 0.2.4 snapshot to your computer (View the plugin’s summary here)
  2. Extract the files
  3. Install the plugin locally via:
    $ phonegap plugin add PATH_TO_PLUGIN

    Where the text “PATH_TO_PLUGIN” is the path to the folder containing the plugin’s “plugin.xml” file. For example, on my computer the complete command was:

    phonegap plugin add c:\projects\file_plugin_old\cordova-plugin-file-8a29d64

(And now, back to the original post….)

Anyway, I’ve been tinkering with this on my Galaxy SII, here are some screen shots:

phonegap_filebrowser_sgs2
phonegap_file_browser_2
phonegap_file_browser_3

As you can see its quite light in the UI department. I googled some icons, dropped them in, then used a little flexbox action to align things and finally styled the unordered list to my liking. No ground-breaking design here, just function over form.

One thing to note about the process described below is that everything is asynchronous. Therefore, there are a number of callbacks for success / failure and the result is a chain of functions. Not too messy though, just something to be aware of.

Ok then…. lets peek under the hood.

Step 1: Request File System

The foundation of all of this is being able to get a reference to the device’s file system.

PhoneGap’s window.requestFileSystem() returns a file system object with this structure:

// This example contains real values relative to my personal phone
{
  name:'persistent',
  root:{
    isFile:false,
    isDirectory:true,
    name:'sdcard0',
    fullPath:'file:///storage/sdcard0',
    filesystem:null
  }
}

Here’s the function that gives us the above:

...
    function beginBrowseForFiles(e){
        // check subscription type
        if (e.target.attributes['data-action'].nodeValue != 'beginBrowseForFiles'){
            return;
        }
		
        if (!e.target.attributes['data-path']){
            window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, requestFileSystemSuccess, null);
        } else {
            // this is used to get subdirectories
            var path = e.target.attributes['data-path'].nodeValue;
            window.resolveLocalFileSystemURI(path, 
                function(filesystem){
		    // we must pass what the PhoneGap API doc examples call an "entry" to the reader
		    // which appears to take the form constructed below.
		    requestFileSystemSuccess({root:filesystem});
		},
		function(err){
		    // Eclipse doesn't let you inspect objects like Chrome does, thus the stringify
		    console.log('### ERR: filesystem.beginBrowseForFiles() -' + (JSON.stringify(err)));
		}
	    );
        }
    }
...

Getting the local filesystem object is easy enough, to understand what happens next just follow the success callback which is explained in Step 2. The interesting thing above is that I re-use this function to drill down into sub directories (note my comments) and that I’m constructing an object that I pass to the success callback in that case – I’m sure there is something that I’ve missed in the API docs, maybe something that does this for me, but I’ve figured out that the next step (creating a reader) needs to have an object that takes the form constructed in the example.

In any event you can see that the success callback for both the first pass and drilling into subdirectories is the same – requestFileSystemSuccess

Step 2: Directory Reader

The requestFileSystemSuccess callback now takes the filesystem object and uses it to create a reader which allows us to get all the entries (files and folders) for the given location. On success we will pass our entry array to a function that will sort them, construct an unordered list and then insert them into the app.

...
  function requestFileSystemSuccess(fileSystem){
    // lets insert the current path into our UI
    document.getElementById('folderName').innerHTML = fileSystem.root.fullPath;
    // save this location for future use
    _currentFileSystem = fileSystem;
    // create a directory reader
    var directoryReader = fileSystem.root.createReader();
    // Get a list of all the entries in the directory
    directoryReader.readEntries(directoryReaderSuccess,fail);
  }
...

Step 3: Compile Entries into something useful

The last thing we want to do is order the entry list. It appears to me to have a random order though maybe it is ordered by creation date – I’ve honestly not spent the time to investigate.

After making sense of things I then loop through the entry array and create my list from each entry object.

While doing that I investigate each entry object to determine if I’m dealing with a file or directory and thus insert the appropriate icon. Entry objects take the following form:

// a sample entry object
{
  isFile:false,
  isDirectory:true,
  name:'backups',
  fullPath:'file:///storage/sdcard0',
  filesystem:null
}

I also am filtering out system/hidden files/folders as determined by anything that has a leading period in its name. As you look at the code sample you will see that I have implemented the ability to toggle this on or off based on user preferences.

...
  function directoryReaderSuccess(entries){
    // again, Eclipse doesn't allow object inspection, thus the stringify
    console.log(JSON.stringify(entries));
    
    // alphabetically sort the entries based on the entry's name
    entries.sort(function(a,b){return (a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1)});
    
    //  start constructing the view
    var list = 'lt;ul>';
    var skip = null;
      for (var i=0;i<entries.length;i++){
        // should we hide "system" files and directories?
	if (app.util.getPref('hideSystem')){
  	  skip = entries[i].name.indexOf('.') == 0;
	}
	if (!skip){
 	  list += '<li><div class="rowTitle" data-action="' + (entries[i].isFile ? 'selectFile' : 'beginBrowseForFiles') + '" \
	       data-type="' + (entries[i].isFile ? 'file':'directory') + '" \
	       data-path="' + entries[i].fullPath + '">' + entries[i].name + '</div>\
	       <div class="alginIconInRow"><img src="images/' + (entries[i].isFile ? 'file':'folder') + '.png"></div>\
	       </li>';
	}
  }
  // insert the list into our container
  document.getElementById('body').innerHTML = list + '</ul>';
}
...

You can get a glimpse of how I drill into subdirectories – each DIV row contains information describing the entry it represents, data-type and data-path. Also note my own personal convention for determining what should happen when anything is tapped – data-action. My pub-sub implementation (not shown here) will loop through and fire all subscriptions to the touchend event. Because of this the subscribers need a way to know if they should run or not and data-action provides a mechanism for that.

The beginBrowseForFiles() function found in Step 1 is fired again when any row is tapped and the file path (via the data-path attribute) is passed along and the whole process starts over again.

Going back – viewing the parent directory

What good is drilling down into a file system if you can’t go back up? Enter the following function, as is evident on success we have what we need to jump to Step 2 which then re-populates our view:

...
  function doDirectoryUp(){
    var path = _currentFileSystem.root.fullPath;
		
    window.resolveLocalFileSystemURI(path,
      function(entry){
	entry.getParent( 
	  function(filesystem){
	    requestFileSystemSuccess({root:filesystem});
	  },
	  function(err){
            // once again Eclipse is not Chrome, so I stringify the objects so I can see them in the console
	    console.log('### ERR: filesystem.directoryUp() getParent -' + (JSON.stringify(err)));
	  }
	);
      },
      function(err){
	console.log('### ERR: filesystem.directoryUp() -' + (JSON.stringify(err)));
      }
    );
  }
...

Conclusion

PhoneGap provides all the tools to find folders and files, its just a matter of putting the pieces together. From here I can do a number of things – as I mentioned delete & move files are on my list as well as reading files. Once I have the first two I’ll put this thing on the app store. After that I’ll continue with my app idea – recall that all this was the first step for something bigger 😉

On a side note in the absence of a framework I did have a brief issue with scrolling where my swipes would naturally cause touchend events to fire. I figured out a little method of dealing with it… I think I’ll save that one for another day…

HTML Strings in JavaScript

10 Dec 2013

Over time as we are exposed to other people’s code and thus their idea’s and techniques we not only learn more about the language but also we learn about new approaches to common challenges. This is just the way of things and we should all be curious as to how people take the approaches they end up taking.

In particular, I’ve noticed several ways to deal with constructing HTML strings and will share them here along with what I think the advantages are and their appropriate applications.

+= operator

This one is simple and is easily the most commonly used approach. We are simply taking the original string and concatenating a new string to to the end.

var pets = 'dog';
    pets += ' and cats';
console.log(pets); // outputs "dog and cats"

Simple and easy to understand and in this case no need to do anything any different. Another example might be to loop through an array of some sort, create a block of HTML and then insert that HTML into a page.

var pets = [{type:'dog',breed:'collie',color:'brown'},
    {type:'dog',breed:'bulldog',color:'brown and white'},
    {type:'cat',breed:'tabby','color:'orange'},
    {type:'cat',breed:'persian','color:'white'}];

var output = '';
    output += '';

for (var i=0;i';
    output += '';
    output += '';
    output += '';
}

output += '
TypeBreedColor
' + pets[i].breed + '' + pets[i].color + '
'; $('#your_container').html(output); // inserts into an element with ID "your_container" console.log(output); // prints the table html to the console

As you can see we’re building a table and populating the table cells with the data from the pets array which is an array of objects. Again, pretty straight forward – with each iteration of the for loop we are constructing a row in our table.

For the sake of this discussion lets make things more complicated and add in additional html that might more closely resemble the type of thing that would happen in real-world applications.

var pets = [{type:'dog',breed:'collie',color:'brown'},
            {type:'dog',breed:'bulldog',color:'brown and white'},
            {type:'cat',breed:'tabby',color:'orange'},
            {type:'cat',breed:'persian',color:'white'}];

var output = '';
    output += '';

for (var i=0;i';
    output += '';
    output += '';
    output += '';
    output += '';
}

    output += '
TypeBreedColor
' + pets[i].type; output += '
Select
' + pets[i].breed; output += '
Select
' + pets[i].color; output += '
Select
'; $('#your_container').html(output); // inserts into an element with ID "your_container" console.log(output); // prints the table html to the console

Now that our code has gotten a little more complicated the issue of readability comes into play – we should strive to make our code easier to read whenever we can. The above is a good example of something that could benefit from a different approach to building a string.

Code formatting with the += operator

Obviously the previous example could benefit from some judicious code indenting for the HTML within the strings themselves. Lets try it:

for (var i=0;i';
    output += '   ' + pets[i].type;
    output += '      
Select
'; output += ' ' + pets[i].breed; output += '
Select
'; output += ' ' + pets[i].color; output += '
Select
'; output += ''; }

We’re now starting to see the structure/relationship between our HTML elements. Lets go a step further and break some of those lines into even more lines of code:

for (var i=0;i';
    output += '   ' + pets[i].type;
    output += '      
Select
'; output += ' '; output += ' ' + pets[i].breed; output += '
Select
'; output += ' '; output += ' ' + pets[i].color; output += '
Select
'; output += ' '; output += ''; }

Now we’re getting somewhere, very readable. Where do we go from here?

+ operator

Well, for starters we can get rid of all the output += statements – in JavaScript less is more. We know that the + operator is a string concatenator so lets use it here:

for (var i=0;i' +
    '   ' + pets[i].type +
    '      
Select
' + ' ' + ' ' + pets[i].breed + '
Select
' + ' ' + ' ' + pets[i].color + '
Select
' + ' ' + ''; }

As you can see we’ve trimmed down the amount of code necessary to construct our string. Note that in line 2 above that I’ve started our string concatenation pattern with the output += ” + which is critical. The rest of the string is put together via the + operator and is helped by the fact that white space in JavaScript is ignored which is why we can have multiple lines the way we do. Also note that I’m properly ending the concatenation routine in line 13 with a semi-colon.

This looks about as good as we can get, right?

Escape New Lines

It turns out we can get even cleaner code by simply escaping the new line character that is inserted when you hit the “enter” key. The backslash “\” in JavaScript is used to escape characters that would otherwise have a special meaning in the language (which results in a string literal) or to insert special characters that have no other method of representation (which are known as escape sequences). For our purposes we want to escape the new line/carriage return which will trick a browser’s parser into thinking that it is dealing with a single long line of code. We do this by placing the escape character at the end of each line.

for (var i=0;i\
       ' + pets[i].type + '\
          
Select
\ \ ' + pets[i].breed + '\
Select
\ \ ' + pets[i].color + '\
Select
\ \ '; }

Using an Array

Here’s an interesting example that uses an array, via an array literal, to house each line of HTML as a unique array element. This approach obviates the need for end-of-line-escaping or the use of a concatenation operator to create a single string across multiple lines. Instead we have a series of strings housed within the array that are concatenated into a single string via the Array join method.

While we are “joining” the array elements (strings) we are also inserting a new line character ( \n ) to “pretty print” our code into the page. True, you could also add the new line character in all of the above examples but that would require you to insert it many times whereas here we do it once. Also, because we are letting the join method do our concatenating our code no longer needs to be cluttered by additional operators or escape characters.

for (var i=0;i',
      '  ' + pets[i].type',
      '     
Select
', ' ', ' ' + pets[i].breed', '
Select
', ' ', ' ' + pets[i].color', '
Select
', ' ', '' ].join('\n'); }

Which one to use?

IMO the first two methods are immediately understandable. The third “escape” method is a small step backwards for readability and can be a little tricky – as can be seen in the example you do have to be aware of where your string starts and ends when inserting dynamic values (for example, line 4 and others).

Often you may find yourself with a large beginning and end block of HTML which the escape method works well for only to have a middle section with many dynamic elements and/or logic (nested for loops come to mind) that is more appropriate for += or + operators since the escape method would quickly work against you.

There are other string-creation strategies of course when using the above examples such as generating your dynamic content first by assigning them to variables and then using any method of concatenation to achieve the final string. Here’s one such approach using the escape method:

for (var i=0;i\
       ' + type + '\
          
Select
\ \ ' + breed + '\
Select
\ \ ' + color + '\
Select
\ \ '; }

This approach is even better yet – its as short / concise as we can get with our example and is easier to maintain.

Your project of course will vary but armed with whats been presented above you should be able to create code that is both readable and efficient.

JSON is a String

26 Nov 2013

I had a developer once tell me that the Sencha Touch project we were working on was “just JSON”. I had not considered that the code we were writing had a resemblance to JSON until that moment. My head being consumed with the project required me to supply a shrug of the shoulders and go back to my work… but later I realized that no, thats not the case at all and IMO it was not only a gross over simplification of what we were doing at the time but also showed a lack of understanding of what JSON is.

JSON is a string. It is also an acronym – JavaScript Object Notation. JSON looks like this:

'{
   "name" : "groupname",
   "type" : "some type",
   "description" : "some description"
}'

As noted above we should be looking at a string and we are by virtue of the surrounding single quotes. When we do an AJAX request that returns JSON we receive something like the above example. It is common practice to then use some library to parse the JSON response into a JavaScript Object. If we don’t then the JSON string is of little use. Therefore many libraries/frameworks, such as jQuery or Sencha Touch, have JSON parsers to convert JSON into a bonafide JavaScript Object.

Modern browsers have parsing built-in natively via two two useful methods: JSON.parse() and JSON.stringify() where the former converts (deserializes) JSON into an object and the later converts (serializes) an object into a JSON-formatted string. The name of that last last method – **stringify()** – should IMO end the discussion of what JSON is (if the official JSON spec didn’t already do that) – JSON is a string. A string with a specific format but a string none-the-less.

Why then does the term JSON get used so liberally? Lets do a JSON.parse() on our JSON example. This is what we get:

{
   name : "groupname",
   type : "some type",
   description : "some description"
}

What we are looking at here is our converted JSON – now a JavaScript object – represented via a JavaScript Object Literal. It *looks* like “JavaScript Object Notation” (JSON) but obviously it is not. Yet the label is applied anyway. The logic appears to be that if it looks like JSON but doesn’t necessary “smell” like JSON it must somehow be JSON despite the fact that “notation” is an inert facsimile of an object whereas a “literal” is literally the object in question.