Thursday, April 26, 2012

"JavaScript Patterns" Sandbox Pattern Correction

More from the JS world; I've been evaluating some ways to simplify the ponderous namespace typing in my javascript framework. It would appear, at this point, that the leading way to do this is by using the Sandbox pattern. As I understand it, the pattern is heavily used by the Yahoo YUI guys. It provides some other interesting capability as well, such as being able to create separate "app domains" as it were, that use different modules based on what you feed the Sandbox constructor. These different sandbox domains can be nested, etc. It's truly a plumbing pattern that seems to have a lot of potential to make your app more flexible and modular, as well as making the code easier to write/read.

 So far, I get it, and I believe it will be useful, but I'm still evaluating.

 I discovered that a reference implementation for the Sandbox pattern is in a book I already have; JavaScript Patterns. However, the reference pattern allows for feeding the desired modules for a given sandbox instance by a list of names, an array, or a '*' (meaning, use all available modules that have been registered with the Sandbox's static "modules" object literal).

 The problem is in the check that looks to see if you used "*".
if ( !modules || modules === '*' ) {
        modules = [ ];
        for ( i in Sandbox.modules ) {
            if ( Sandbox.modules.hasOwnProperty ( i ) ) {
                modules.push ( i );
            }
        }
    }
This causes an error, because the check will never evaluate to true; modules will never be as type "string", because earlier on it's typed as an array. So 'all available modules' will never get added to the Sandbox instance.

 The fix; add 'toString ( )' to the check (it makes sense, you're using absolute equality against '*', which is a string):
if ( !modules || modules.toString ( ) === '*' ) {
        modules = [ ];
        for ( i in Sandbox.modules ) {
            if ( Sandbox.modules.hasOwnProperty ( i ) ) {
                modules.push ( i );
            }
        }
    }
And the check will proceed as intended.

 As always, thanks for visiting.

Thursday, April 19, 2012

"setXMLFromString" Extension for EditableGrid

EditableGrid is a very useful datagrid and chart component. It's written in JS, and after the usual short wrestling match/learning curve to incorporate into my projects, which these days are very data display heavy; lots of charts, tabular data that has to be interactive, I was pleased with the usage and display results.

You can find out more about EditableGrid here:

www.editablegrid.com

However, there is, from what I can see, one major API oversight, and forgive me if it's there but I looked in docs and source and couldn't find it: you can't set the xml from a string or dom object directly. You have to either fake a url call in the loadXML api call, or some other such hacky voodoo.

So I wrote a very simple extension for EditableGrid that allows you to do it straightforwardly.

Create a javascript file, call it, "useXMLString.js". Put it in the extensions directory of your EditableGrid structure.

Put this function in it.



EditableGrid.prototype.setXMLFromString = function ( theXMLString ) {

if ( window.DOMParser )
{
var parser = new DOMParser ( );
this.xmlDoc = parser.parseFromString ( theXMLString, "application/xml" );
}
else
{
this.xmlDoc = new ActiveXObject ( "Microsoft.XMLDOM" ); // IE
this.xmlDoc.async = "false";
this.xmlDoc.loadXML ( theXMLString );
}

this.processXML ( );
this.tableLoaded ( );
}



Not much to see; I add a function to the EditableGrid prototype, use typical "browsers or IE" DOM parsing to turn the string into a DOM object, set the xmlDoc object of EditableGrid to that DOM object, then run the processXML and tableLoaded functions. This is pretty much how the usual EditableGrid.loadXML function works (you can see it in the EditableGrid source), I'm just taking out the need to use a URL.

Save it, and add it to your imports, the way you'd add any other extension to a JS component.

Now, don't call myEditableGrid.loadXML ( url ). Substitute myEditableGrid.setXMLFromString ( theXMLString ).

That's it, works like a charm. Note that you are responsible for making sure your XML string is a valid object.

As always, thanks for visiting.