# Javascript widget patterns and merging configurations

I'm volunteering some time to work on an open-data project, which I've started a repo out here for:

The general idea is you'll paste in script tags the same way Google maps does to any third-party site to call the JavaScript.

I'm trying to prevent global namespace abuses (both-ways), and make configuration very simple and straight-forward.

Right now, the plugin configuration looks like (this is before my re-write):

<script type="text/javascript">
var Config = { height: 500, width: 500 };
document.write(unescape("%3Cscript src='http://example.com/somecode.js' type='text/javascript'%3E%3C/script%3E"));
</script>


I've got a few problems with this, first of all, it's using document.write and hopes that script-tags execute in the way I want them to. I'm scared this will break the page, I'd rather use DOM append child methods.

The other problem here is you can't configure this in-site simply without introducing a global variable.

I'd like to do something where I can call such as:

<script type="text/javascript">
/*document.createelement script tag... make the
src equal to the javascript, pass config data by function parameter?*/);
</script>


So my code is mostly a huge closure, and I try to contain the whole thing inside of there.

(function(conf){
/*things happen*/
})({
"conf": "data",
"etc":"etc"
});


In the code I've linked up above I've made a function confMerge that attempts to do a recursive deep exclusive replace on the defaults being over-ridden by the configure data. I'm somewhat concerned it's over-kill in a few areas, and may break in others. My other concern is that I can't alter behavior based on type (for instance, google maps API can take a string as a center parameter, but I provide two numbers, my configure style can't deal with that.)

I've got a few rules, and that's that this needs to be ie6 friendly, I can't play with the prototype to shim ES5 styles, and I can't blow up someone elses website with my plugin, and it needs to be able to work without letting an average website with globals all-over-the-place blow up my widget.

Thoughts?

There's nothing stopping you putting a closure in around the script part so you don't have global variables - all except closures cause memory leaks in IE6 - in fact, Google Analytic does it.

The switch statement does look a bit over-kill in confMerge. I'm not sure typeof will return 'xml'. Most often, all you have to do is options[i] = conf[i] || defaults[i];, basically. With objects and arrays you just recurse down. I've done this numerous times, so as far as I can see, nothing to worry about.

I don't see why you cannot support strings. You can always build a validator for that specific property.

Update: I think I realise my mistake. I assumed that copyMerge did a shallow copy. The way you do it, you enforce the structure of the defaults. I still believe, however, that validation is best solution, but what you should do is a shallow copy, so when you see an object or array you just reference it, rather than calling copyMerge.

Then to validate the data, I feel that creating validation functions for all the properties is the best way. Thus you can handle the property center and make sure if it's a string, or an object with the two properties 1 and 0. If it must be an array you can it by using Object.prototype.toString.apply( obj ) === "[object Array]".

You can put the validation functions in copyMerge by creating an object funcs with the same name as the properties, so object["center"] or in copyMerge, object[ i ] where i === "center". Another way is to have a copyMerge go the copying and have a validator function to validate the data.

• The XML is there because that's a possibility in the spec, so I figure'd I account for it somehow. I'm sure I could support strings, my issue is what's an elegant way to actually do that? If my defaults are an array, and I get a string, I don't want to code a one-off setting, I want to design a solution for other things. – Incognito Sep 11 '11 at 23:02
• I have added more information. A question that cropped up for me is, why do you do a deep copy? – NebulaFox Sep 12 '11 at 10:40