Canvas & HTML 5 Sample Junk

by Jon Davis 27. September 2012 15:48

Poking around with HTML 5 canvas again, refreshing my knowledge of the basics. Here's where I'm dumping links to my own tinkerings for my own reference. I'll update this with more list items later as I come up with them.

  1. Don't have a seizure. http://jsfiddle.net/8RYtu/22/
    HTML5 canvas arc, line, audio, custom web font rendered in canvas, non-fixed (dynamic) render loop with fps meter, window-scale, being obnoxious
  2. Pass-through pointer events http://jsfiddle.net/MtGT8/1/
    Demonstrates how the canvas element, which would normally intercept mouse events, does not do so here, and instead allows the mouse event to propagate to the elements behind it. Huge potential but does not work in Internet Explorer.
  3. Geolocation sample. http://jsfiddle.net/nmu3x/4/ 
    Nothing to do with canvas here. Get over it.
  4. ECMAScript 5 Javascript property getter/setter. http://jsfiddle.net/9QpnW/8/
    Like C#, Javascript now supports assigning functions to property getters/setters. See how I store a value privately (in a closure) and do bad by returning a modified value.

Automatically Declaring Namespaces in Javascript (namespaces.js)

by Jon Davis 25. September 2012 18:24

Namespaces in Javascript are a pattern many untrained or undisciplined developers may fail to do, but they are an essential strategy in retaining maintainability and avoiding collisions in Javascript source.

Part of the problem with namespaces is that if you have a complex client-side solution with several Javascript objects scattered across several files but they all pertain to the same overall solution, you may end up with very long, nested namespaces like this:

var ad = AcmeCorporation.Foo.Bar.WidgetFactory.createWidget('advertisement');

I personally am not opposed to long namespaces, so long as they can be shortened with aliases when their length gets in the way.

var wf = AcmeCorporation.Foo.Bar.WidgetFactory;
var ad = wf.createWidget('advertisement');

The problem I have run into, however, is that when I have multiple .js files in my project and I am not 100% sure of their load order, I may run into errors. For example:

// acme.WidgetFactory.js
AcmeCorporation.Foo.Bar.WidgetFactory = {
createWidget: function(e) {
return new otherProvider.Widget(e);
}
};

This may throw an error immediately because even though I’m declaring the WidgetFactory namespace, I am not certain that these namespaces have been defined:

  • AcmeCorporation
  • AcmeCorporation.Foo
  • AcmeCorporation.Foo.Bar

So again if any of those are missing, the code in my acme.WidgetFactory.js file will fail.

So then I clutter it with code that looks like this:

// acme.WidgetFactory.js
if (!window['AcmeCorporation']) window['AcmeCorporation'] = {};
if (!AcmeCorporation.Foo) AcmeCorporation.Foo = {};
if (!AcmeCorporation.Foo.Bar) AcmeCorporation.Foo.Bar = {};
AcmeCorporation.Foo.Bar.WidgetFactory = {
createWidget: function(e) {
return new otherProvider.Widget(e);
}
};

This is frankly not very clean. It adds a lot of overhead to my productivity just to get started writing code.

So today, to compliment my using.js solution (which dynamically loads scripts), I have cobbled together a very simple script that dynamically defines a namespace in a single line of code:

// acme.WidgetFactory.js
namespace('AcmeCorporation.Foo.Bar');
AcmeCorporation.Foo.Bar.WidgetFactory = {
createWidget : function(e) {
return new otherProvider.Widget(e);
}
};
/* or, alternatively ..
namespace('AcmeCorporation.Foo.Bar.WidgetFactory');
AcmeCorporation.Foo.Bar.WidgetFactory.createWidget = function(e) {
return new otherProvider.Widget(e);
};
*/

As you can see, a function called “namespace” splits the dot-notation and creates the nested objects on the global namespace to allow for the nested namespace to resolve correctly.

Note that this will not overwrite or clobber an existing namespace, it will only ensure that the namespace exists.

a = {};
a.b = {};
a.b.c = 'dog';
namespace('a.b.c');
alert(a.b.c); // alerts with "dog"

Where you will still need to be careful is if you are not sure of load order then your namespace names all the way up the dot-notation tree should be namespaces alone and never be defined objects, or else assigning the defined objects manually may clobber nested namespaces and nested objects.

namespace('a.b.c');
a.b.c.d = 'dog';
a.b.c.e = 'bird';
// in another script ..
a.b = { 
c : {
d : 'cat'
}
};
// in consuming script / page
alert(a.b.c); // alerts [object]
alert(a.b.c.d); // alerts 'cat'
alert(a.b.c.e); // alerts 'undefined'

Here’s the download if you want it as a script file [EDIT: the linked resource has since been modified and has grown significantly], and here is its [original] content:

function namespace(ns) {
var g = function(){return this}();
ns = ns.split('.');
for(var i=0, n=ns.length; i<n; ++i) {
var x = ns[i];
if (x in g === false) g[x]={}; 
g = g[x];
}
} 

The above is actually written by commenter "steve" (sjakubowsi -AT- hotmail -dot-com). Here is the original solution that I had come up with:

namespace = function(n) {
var s = n.split('.');
var exp = 'var ___v=undefined;try {___v=x} catch(e) {} if (___v===undefined)x={}';
var e = exp.replace(/x/g, s[0]);
eval(e);
for (var i=1; i<s.length; i++) {
var ns = '';
for (var p=0; p<=i; p++) {
if (ns.length > 0) ns += '.';
ns += s[p];
}
e = exp.replace(/x/g, ns);
eval(e);
}
}

Currently rated 4.0 by 2 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Javascript | Pet Projects

Why jQuery Plugins Use String-Referenced Function Invocations

by Jon Davis 25. September 2012 10:52

Some time ago (years ago) I cobbled together a jQuery plug-in or two that at the time I was pretty proud of, but in retrospect I’m pretty embarrassed. One of these plugins was jqDialogForms. The embarrassment was not due to its styling—the point of it was that it could be skinnable, I just didn’t have time to create sample skins—nor was the embarrassment due to the functional conflict with jQuery UI’s dialog component, because I had a specific vision in mind which included modeless parent/child ownership, opening by simple DOM reference or by string, and automatic form serialization to JSON. Were I to do all this again I would probably just extend jQuery UI with syntactical sugar, and move form serialization to another plugin, but all that is a tangent from the purpose of this blog post. My embarassment with jqDialogForms is with the patterns and conventions I chose in contradiction to jQuery’s unique patterns.

Since then I have abandoned (or perhaps neglected) jQuery plugins development, but I still formed casual and sometimes uneducated opinions along the way. One of the patterns that had irked me was jQuery UI’s pattern of how its components’ functions are invoked:

$('#mydiv').accordion( 'disable' );
$('#myauto').autocomplete( 'search' , [value] );
$('#prog').progressbar( 'value' , [value] );

Notice that the actual functions being invoked are identified with a string parameter into another function. I didn’t like this, and I still think it’s ugly. This came across to me as “the jQuery UI” way, and I believed that this contradicted “the jQuery way”, so for years I have been baffled as to how jQuery could have adopted jQuery UI as part of its official suite.

Then recently I came across this, and was baffled even more:

http://docs.jquery.com/Plugins/Authoring

Under no circumstance should a single plugin ever claim more than one namespace in the jQuery.fn object.

(function( $ ){

  $.fn.tooltip = function( options ) { 
    // THIS
  };
  $.fn.tooltipShow = function( ) {
    // IS
  };
  $.fn.tooltipHide = function( ) { 
    // BAD
  };
  $.fn.tooltipUpdate = function( content ) { 
    // !!!  
  };

})( jQuery );

This is a discouraged because it clutters up the $.fn namespace. To remedy this, you should collect all of your plugin’s methods in an object literal and call them by passing the string name of the method to the plugin.

(function( $ ){

  var methods = {
    init : function( options ) { 
      // THIS 
    },
    show : function( ) {
      // IS
    },
    hide : function( ) { 
      // GOOD
    },
    update : function( content ) { 
      // !!! 
    }
  };

  $.fn.tooltip = function( method ) {
    
    // Method calling logic
    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }    
  
  };

})( jQuery );

// calls the init method
$('div').tooltip(); 

// calls the init method
$('div').tooltip({
  foo : 'bar'
});

// calls the hide method
$('div').tooltip('hide'); 
// calls the update method
$('div').tooltip('update', 'This is the new tooltip content!'); 

This type of plugin architecture allows you to encapsulate all of your methods in the plugin's parent closure, and call them by first passing the string name of the method, and then passing any additional parameters you might need for that method. This type of method encapsulation and architecture is a standard in the jQuery plugin community and it used by countless plugins, including the plugins and widgets in jQueryUI.

What baffled me was not their initial reasoning pertaining to namespaces. I completely understand the need to keep plugins’ namespaces in their own bucket. What baffled me was how this was considered a solution. Why not simply use this?

$('#mythingamajig').mySpecialNamespace.mySpecialFeature.doSomething( [options] );

To see about proving that I could make both myself and the “official” jQuery team happy, I cobbled this test together ..

(function($) {
    
    $.fn.myNamespace = function() {
        var fn = 'default';
        
        var args = $.makeArray(arguments);
        if (args.length > 0 && typeof(args[0]) == 'string' && !(!($.fn.myNamespace[args[0]]))) {
            fn = args[0];
            args = $(args).slice(1);
        }
        $.fn.myNamespace[fn].apply(this, args);
    };
    $.fn.myNamespace.default = function() {
        var s = '\n';
        var i=0;
        $(arguments).each(function() {            
            s += 'arg' + (++i).toString() + '=' + this + '\n';
        });
        alert('Default' + s);
        
    };
    $.fn.myNamespace.alternate = function() {
        var s = '\n';
        var i=0;
        $(arguments).each(function() {            
            s += 'arg' + (++i).toString() + '=' + this + '\n';
        });
        alert('Alternate' + s);
        
    };

    $().myNamespace('asdf', 'xyz');
    $().myNamespace.default('asdf', 'xyz');
    $().myNamespace('default', 'asdf', 'xyz');
    $().myNamespace.alternate('asdf', 'xyz');
    $().myNamespace('alternate', 'asdf', 'xyz');
    
})(jQuery);

Notice the last few lines in there ..

    $().myNamespace('asdf', 'xyz');
    $().myNamespace.default('asdf', 'xyz');
    $().myNamespace('default', 'asdf', 'xyz');
    $().myNamespace.alternate('asdf', 'xyz');
    $().myNamespace('alternate', 'asdf', 'xyz');

When this worked as I hoped I originally set about making this blog post be a “plugin generator plugin” that would make plug-in creation really simple and also enable the above calling convention. But when I got to the some passing tests, adding a few more tests I realized I had failed to notice a critical detail: the this context, and chainability.

In JavaScript, navigating a namespace as with $.fn.myNamespace.something.somethingelse doesn’t execute any code within the dot-notation. Without the execution of functional code, there can be no context for the this context, which should be the jQuery-wrapped selection, and as such there can be no context for the return chainable object. (I realize that it is possible to execute code with modern JavaScript getters and setters but all modern browsers don’t support getters and setters and all commonly used browsers certainly don’t.) This was something that I as a C# developer found easy to forget and overlook, because in C# we take the passing around of context in property getters for granted.

Surprisingly, this technical reasoning for the string-based function identifier for jQuery plug-in function invocations was not mentioned on the jQuery Plugins documentation site, nor was it mentioned in the Pluralsight video-based training I recently perused. It seemed like what Pluralsight’s trainer was saying was, “You can use $().mynamespace.function1()” but that’s obscure! Use a string parameter instead!” And I’m like, “No, it is not obscure! Calling a function by string is obscure because you can’t easily identify it as a function reference distinct from a parameter value!”

The only way to retain the this context while removing the string-based function reference is to invoke it along the way.

$().myNamespace().myFunction('myOption1', true, false);

Notice the parenthesis after .myNamespace. And that is a wholly different convention that few in jQuery-land are used to. But I do think that it is far more readable than ..

$().myNamespace('myFunction', 'myOption1', true, false);

I still like the former, it is more readable, and I remain unsure as to why the latter is the accepted convention over the former, but my guess is that a confused user might try to chain back to jQuery right after .myNamespace() rather than after executing a nested function. And that, I suppose, demonstrates how the former pattern is contrary to jQuery’s chainability design of every().invocation().just().returns().jQuery.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , ,

Javascript

Personal Status Update [September 19, 2012]

by Jon Davis 19. September 2012 12:16

I know, I know, I promised I’d pick up some steam on my blog and then suddenly I got quiet. Here’s the deal .. when I started picking up a bit more steam a couple months ago, I was looking for my next permanent job. Well, I found it. And, I’m kind of floored by its potential, as well as the preexisting knowledge that I’d be surrounded by some amazing people as well as be given high expectations of technical and professional maturity. This is my dream job.

I’ll post more but for now I need to catch up on some Pluralsight training, perhaps (finally) get some Microsoft certifications (MCPD and perhaps at some point even MCM), get a couple project successes behind me, and ultimately prove my worth to my employer. They’re watching. o.O

Oh, by the way, remember using.js? I created it waaay back in 2008 and it was surprisingly popular. Anyway, today I finally moved it over to GitHub. https://github.com/stimpy77/using.js Recent Javascript design patterns training on Pluralsight as a refresher got me motivated to blow the dust off of it and put it in a more publically enjoyable space. Cheers.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:


 

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen

About the author

Jon Davis (aka "stimpy77") has been a programmer, developer, and consultant for web and Windows software solutions professionally since 1997, with experience ranging from OS and hardware support to DHTML programming to IIS/ASP web apps to Java network programming to Visual Basic applications to C# desktop apps.
 
Software in all forms is also his sole hobby, whether playing PC games or tinkering with programming them. "I was playing Defender on the Commodore 64," he reminisces, "when I decided at the age of 12 or so that I want to be a computer programmer when I grow up."

Jon was previously employed as a senior .NET developer at a very well-known Internet services company whom you're more likely than not to have directly done business with. However, this blog and all of jondavis.net have no affiliation with, and are not representative of, his former employer in any way.

Contact Me 


Tag cloud

Calendar

<<  November 2018  >>
MoTuWeThFrSaSu
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

View posts in large calendar