Defining and Extending JavaScript Modules

After writing a few modules you will find yourself reusing the same parts of code such as:

- initiating a function with a prototype
- getting a reference to the dom element
- merging options with defaults

These are duplicated in each Module Class you write. here is a simple example of code duplication:

Panel.js
function Panel(id, options) {
this.el = document.getElementById(id);
if (!this.options) { this.options = {}; }
for (var item in options) { this.options[item] = options[item]; }
this.init();
}

Panel.prototype = {

init: function() {
this.el.innerHTML = 'options: <pre>'+JSON.stringify(this.options)+'</pre>';
}
}

Item.js
function Item(id, options) {
this.el = document.getElementById(id);
if (!this.options) { this.options = {}; }
for (var item in options) { this.options[item] = options[item]; }
this.init();
}

Item.prototype = {

init: function() {
this.el.innerHTML = 'A new item!';
}
}

Obviously we can improve on these 25 lines of code as these modules share the same init code. So here's a way to improve it using define as a global function name:

Main.js
function define(name, module, unique) {
function Module(id, options) {
this.el = Utils.getEl(id);
if (!this.options) { this.options = {}; }
for (var item in options) { this.options[item] = options[item]; }
this.init();
}
Module.prototype = module;
if (!window[name]) { window[name] = Module; }
}

Panel.js
define('Panel', {
init: function() {
this.el.innerHTML = 'options: <pre>'+JSON.stringify(this.options)+'</pre>';
}
});

Item.js
define('Item', {
init: function() {
this.el.innerHTML = 'A new item!';
}
});

Now it is 22 lines of code and we will save many more for every new module created. The added benefit of this is that we can now update the module base in one place for all modules at once. Here is an example where i've added the ability to define a singleton module that will only exist once ever on a page:

Main.js
function define(name, module, unique) {
if (unique == true) {
if (!window[name]) { window[name] = module; }
}
else {
function Module(id, options) {
this.el = Utils.getEl(id);
if (!this.options) { this.options = {}; }
for (var item in options) { this.options[item] = options[item]; }
this.init();
}
Module.prototype = module;
if (!window[name]) { window[name] = Module; }
}
}

Utils.js
define('Utils', {
elements: {},
getEl: function(id) {
if (this.elements[id]) {
return this.elements[id];
}
else {
this.elements[id] = document.getElementById(id);
return this.elements[id];
}
}
}, true);

So Utils is now defined as a singleton instead of a function with a prototype. But what if we need to extend modules off each other? Well this becomes simpler now as we can save and merge modules within our define function.


var modules = {};

Main.js
modules[name] = module;
if (module.extend) {
module.superclass = modules[module.extend];
module = Utils.extend(Utils.clone(module.superclass), module);
}


First we are saving all module prototypes to a list we can reference by their name. Then if a module contains an extend property we will merge the two modules together and set a property called superclass to reference the parent module at any later date.

The Utils class then is updated with the additional clone and extend functions:

Utils.js

define('Utils', {
elements: {},
getEl: function(id) {
if (this.elements[id]) {
return this.elements[id];
}
else {
this.elements[id] = document.getElementById(id);
return this.elements[id];
}
},
clone: function(o) {
var a = {};
for (var i in o) {
if (o.hasOwnProperty(i)) { a[i] = o[i]; }
}
return a;
},
extend: function(o, o2) {
for (var p in o2) {
try {
if (o2[p].constructor == Object) { o[p] = this.extend(o[p], o2[p]); }
else { o[p] = o2[p]; }
}
catch (e) { o[p] = o2[p]; }
}
return o;
}
}, true);


If you would like to see a real-world example of these modules in action, you can look at the source of my portfolio:
http://kimturley.co.uk/debug.html

http://kimturley.co.uk/js/Main.js
http://kimturley.co.uk/js/modules/Utils.js
http://kimturley.co.uk/js/modules/Events.js
http://kimturley.co.uk/js/modules/Template.js
http://kimturley.co.uk/js/modules/List.js




Manually upgrading to Android 4.2.1

If you are an avid Android user you will find the lack of updates to certain phone models frustrating. Manufacturers such as HTC and Samsung only support updates to supported phones and if you are one of the unlucky ones, you won't see the amazing new features of Android.

I am one of those Desire HD owners, which despite being a top end phone of it's time and fully capable of supporting Android 4, is not ever going to be supported.

Here is how to manually upgrade.

1) First root your phone. The Advance Ace Kit is good for Desire HD
http://tau.shadowchild.nl/aahk

2) Then unlock your phone. Easy-S Off is good for Android 2.2 or lower
http://forum.xda-developers.com/showthread.php?t=855403

3) Visit the xda forums and download a new img rom. I am using AOSP-4.2.1 which works really well!
http://forum.xda-developers.com/showthread.php?t=2003273

4) Download the Rom and the google app zip files to your computer e.g.
Rom: http://downloads.codefi.re/synergy/codefireX-Ace/cfx_ace-4.2-BR4.zip
Apps: http://goo.im/devs/KonstantinKeller/mako/gapps/gapps-4.2-JOP40C-121116.zip

5) Connect your phone via USB cable and mount the SD card as a drive. Copy the two zip files onto the route and name the Rom as update.zip.

6) Reboot your phone in Recovery Mode and first select backup phone. After backing up the phones current files, select wipe data / factory reset

7) Now select apply update.zip and wait for the files to be extracted to your phone. Then hit reboot and do the same again to apply google apps zip file to your phone. Happy days