3
\$\begingroup\$

In response tomy own question on Stack Overflow, I'm attempting a solution to decouple JavaScript and html. I'd appreciate any comments, proposed refactoring, or criticism.

I have a fiddle of it in usehere

Here's the code:

(function (window, $, undefined) {    "use strict";    var ab = window.ab = window.autoBinder = {},        elements;    ab.exportSymbol = function (publicPath, object) {        var tokens = publicPath.split("."),            target = window,            i;        for (i = 0; i < tokens.length - 1; i++) {            target = target[tokens[i]];        }        target[tokens[tokens.length - 1]] = object;    };    ab.exportProperty = function (owner, publicName, object) {        owner[publicName] = object;    };    ab.extensions = (function () {        return {            datePicker: function (element) {                var params = {                    minDate: 0,                    showButtonPanel: false                },            e = $(element);                if (e.data("mindate") !== undefined) {                    params.minDate = e.data("mindate");                }                if (e.data("showpanel") !== undefined) {                    params.showButtonPanel = e.data("showpanel");                }                e.datepicker(params);            }        };    })();    ab.hookups = (function () {        return {            make: function (value, element) {                if (ab.extensions[value]) {                    ab.extensions[value](element);                }            },            publish: function (value, $element) {                if (!value) {                    return;                }                $element.change(function () {                    $element.trigger(value, $element);                });            },            subscribe: function (value, $element) {                var trigger = $element.data("trigger");                if (trigger === undefined) {                    throw "Found Subscribe without Trigger.";                }                if (!ab.extensions[trigger]) {                    throw "Found Subscribe without Trigger.";                }                $(document).bind(value, function (event, htmlElement) {                    ab.extensions[trigger](event, htmlElement, $element);                });            }        };    })();    ab.exportSymbol("ab.extensions.datePicker", ab.extensions.datePicker);    ab.exportSymbol("ab.hookups.make", ab.hookups.make);    ab.exportSymbol("ab.hookups.publish", ab.hookups.publish);    ab.exportSymbol("ab.hookups.subscribe", ab.hookups.subscribe);    $(window).load(function () {        elements = $("*").filter(function () {            var data = $(this).data(),                p;            if (data === undefined) {                return false;            }            for (p in data) {                if (data.hasOwnProperty(p)) {                    return true;                }            }            return false;        });        elements.each(function () {            var obj = $(this),                data = obj.data(),                p;            for (p in data) {                if (data.hasOwnProperty(p)) {                    if (ab.hookups[p]) {                        ab.hookups[p](data[p], obj);                    }                }            }        });    });} (window, jQuery));// #region Example of Extending extensions    window.ab.extensions.effectiveDateChanged = function (event, triggerElement, subscribedElement) {        var $element = jQuery(triggerElement);        subscribedElement.val("Value set to: " + $element.val());    };window.ab.extensions.dropDownChanged = function(event, triggerElement, subscribedElement) {    var $element = jQuery(triggerElement),        value = $element.val();    if (value === "") {        subscribedElement.attr("disabled", "disabled");        subscribedElement.html("");        return;    }    subscribedElement.removeAttr("disabled");    subscribedElement.html("<option>" + value + "</option>");};// #endregion
askedJul 7, 2011 at 14:02
Jeff Sheldon's user avatar
\$\endgroup\$

1 Answer1

3
\$\begingroup\$

Update here:http://jsfiddle.net/5ej8G/3/ (code is also pasted below)

Main suggestions:

  • your exportSymbol function can be refactored to handle an array of publicPaths and Objects.
  • The subscribe conditions can be consolidated since they throw the same message.
  • check your parameters before using. typeOf checks don't work well with all objects, but there are techniques to have them work with all objects. One from Angus Croll(http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/) is included in the link above.
  • Explicitly state which elements you want your code to act on, maybe by passing in a parameter object. doing a $("*"), on medium to large pages (with lots of dom elements) can be a performance hit.
(function (window, $, undefined) {    "use strict";    var ab = window.ab = window.autoBinder = {},        elements,        toType = function(obj) {      return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()    };    //can handle an array of publicPaths and objects    ab.exportSymbols = function (paramArray) {        var tokens,            target = window,            i,            index,            len,            limit,            exportSymbol;        if(toType(paramArray) !== 'array') {             throw "You must pass an array into this function.";                    }        //Export Symbol now becomes a inner helper function        exportSymbol = function(pubPath, obj) {            tokens = pubPath.split(".");            lastIndex = tokens.Length;            for (i = 0; i < lastIndex ; i++) {                target = target[tokens[i]];            }            target[tokens[lastIndex]] = obj;        };        //validate and run helper function on each object in array        for(index= 0, len=paramArray.length; i < len; i++) {            if(toType(paramArray.publicPath) !== 'string'                || toType(paramArray.publicPath) !== 'object') {                    continue;            }            exportSymbol(paramArray[index].publicPath, paramArray[index].obj);                    }    };    ab.exportProperty = function (owner, publicName, object) {        owner[publicName] = object;    };    ab.extensions = function () {        return {            datePicker: function (element) {                var params = {                    minDate: 0,                    showButtonPanel: false                },            e = $(element);                if (e.data("mindate") !== undefined) {                    params.minDate = e.data("mindate");                }                if (e.data("showpanel") !== undefined) {                    params.showButtonPanel = e.data("showpanel");                }                e.datepicker(params);            }        };    }();    ab.hookups = (function () {        return {            make: function (value, element) {                if (ab.extensions[value]) {                    ab.extensions[value](element);                }            },            publish: function (value, $element) {                if (!value) {                    return;                }                $element.change(function () {                    $element.trigger(value, $element);                });            },            subscribe: function (value, $element) {                var trigger = $element.data("trigger");               //Conditions can be consolidate since they trow the same message                if ((trigger === undefined) || !ab.extensions[trigger]) {                    throw "Found Subscribe without Trigger.";                }                                $(document).bind(value, function (event, htmlElement) {                    ab.extensions[trigger](event, htmlElement, $element);                });            }        };    })();    //can pass in a an array of object instead of mutiple calls    ab.exportSymbols([                     {pubPath : "ab.extensions.datePicker", obj : ab.extensions.datePicker},                     {pubPath : "ab.hookups.make"         , obj : ab.hookups.make},                     {pubPath : "ab.hookups.publish"      , obj : ab.hookups.publish},                     {pubPath : "ab.hookups.subscribe"    , obj : ab.hookups.subscribe}    ]);    $(window).load(function () {        elements = $("*").filter(function () {            var data = $(this).data(),                p;            if (data === undefined) {                return false;            }            for (p in data) {                if (data.hasOwnProperty(p)) {                    return true;                }            }            return false;        });        elements.each(function () {            var obj = $(this),                data = obj.data(),                p;            for (p in data) {                if (data.hasOwnProperty(p)) {                    if (ab.hookups[p]) {                        ab.hookups[p](data[p], obj);                    }                }            }        });    });} (window, jQuery));//  Example Extending extensions    window.ab.extensions.effectiveDateChanged = function (event, triggerElement, subscribedElement) {        var $element = jQuery(triggerElement);        subscribedElement.val("Value set to: " + $element.val());    };window.ab.extensions.dropDownChanged = function(event, triggerElement, subscribedElement) {    var $element = jQuery(triggerElement),        value = $element.val();    if (value === "") {        subscribedElement.attr("disabled", "disabled");        subscribedElement.html("");        return;    }    subscribedElement.removeAttr("disabled");    subscribedElement.html("<option>" + value + "</option>");};
answeredAug 28, 2011 at 12:00
Bless Yahu's user avatar
\$\endgroup\$

You mustlog in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.