Professional Masons only ...

Ok, don't get too excited, I'm talking about Javascript Masonry, not rolled up trousers and funny handshakes.

So, I have a setup involving a number of virtual screens that are all held in the DOM at the same time, typically only one of them is visible at any given time, and each one can have a Masonry object presented on it. Each object in the grid maps to a database object in the back-end that's represented by a unique ID, and updates can come in dynamically for objects, each of which may co-exist on one or more grids.

[This article is mostly for me so I understand what it is I've actually done ...]

Here's what we've implemented, first we set up a unique namespace to contain the code, using jQuery to extend any pre-existing definitions from previous modules;

var NAC = NAC || {};
$.extend(NAC,{
...
});

Now we define the incoming signal types that will indicate updates on any given object;

	SUG_ADD: 25,
	SUG_DEL: 26,

This installs the signal handlers, so if the back-end sends the right signal, it will trigger the routines listed to make the required changes;

	suggest_init: function() {
		console.log("[Initialising Signal handlers :: Suggest]")
		ionman.reg_handler(NAC.SUG_ADD,NAC.suggest_add);
		ionman.reg_handler(NAC.SUG_DEL,NAC.suggest_del);
	}

So at this point we have incoming signals carrying the ID of a changed object. When an object needs to be added to a grid we come here. Each grid will be assigned the class "suggest-list", so performing an each on $('.suggest-list') will iterate over all of our grids - for now I'm not selectively adding, this can come later.

	suggest_add: function(event) {
		function success(data) {
			$('.suggest-list').each(function(){
				var item = jQuery(data.html);
				$(this).append(item).masonry('appended',item,true);
			});
		}
		var options = {template: 'suggest_item',vars: ['Suggestion'], 'suggestion_id': event.id};
		ionman.call('nac.get.j2',options,success);
	},

When we enter 'add' the event object will contain id which is the back-end database identifier. The call routine will request the back-end fill out a template ('suggest___item') with variables from ['Suggestion'] based on the unique data base identifier (suggestion_id) held in event.id.

On completion, success is called, and the HTML required to render the new artifact is held in data.html. So for each DOM object matching ".suggest-list", we're doing a Masonry appended which will add the item to the grid, and re-render the Masonry object.

When we come to delete an object, it looks like this, each object is rendered with a class of ".sg-"+ the unique identifier for the object, so we do an each on matching objects, scan back up the tree with closest to find the enclosing grid, remove the item, and perform a 'layout' on the related grid.

	suggest_del: function(event) {
		$('.sg-'+event.id).each(function(){
			obj = $(this).closest('.masonry-grid');
			$(this).slideUp('slow',function(){
				$(this).remove();
				setTimeout(function(){
					NAC.MasonryLayout(obj[0].id);
				},100);
			});
		});
	},

The hidden magic in MasonryLayout keeps track of Masonry grids by indexing the grid object by the grid's identifier. So when passed the unique identifier for the grid, we can look up the original Masonry object which is needed for a 'layout' call.

The nice part of this style is complete encapsulation. A new module can be added, it can add it's own event handlers, and other code independently of other pre-existing modules. With a little more work I can track this back to the Dashboard, so a once a new module is "included", it should be able to materialize a Dashboard object from scratch, so each Dashboard object should be implemented as an encapsulated stand-alone JS module. It's sort of there now, but ultimately the Dashboard shouldn't need to know anything about the included modules .. bit of work to do on that bit tho' ...