Skip to main content
IT’S JUST JAVASCRIPT.
   Peter Higgins / @phiggins / #txjs / 2010-06-04
ME.
DOJO.
http://dojotoolkit.org
yay Dojo.


A Library.

5+ years testing, revision, support.

Backwards compatible APIs (to a painful degree)
IN THE END ...
  It’s just a LOT of JavaScript.
IN THE END ...
 It’s just a LOT of modular JavaScript.
IN THE END ...
 It’s just a LOT of optional JavaScript.
JAVASCRIPT IS MAGIC.
MORE THAN JUST TEH DOM
pub/sub, ftw.



ambiguous coupling

cometd
dojo.subscribe("/hello/world", function(){

     console.warn(arguments);
});


dojo.publish("/hello/world", ["foo", "bar"]);


Also availabile for jQuery:
http://higginsforpresident.net/js/static/jq.pubsub.js
OO / CLASSY
dojo.declare("Thing", [inheritance, chain], {

     myProps:"override",

     aMethod:function(){

     
   this.inherited(arguments);

     }
});


new Thing();
`THIS` IS MAGIC.
.CALL / .APPLY
var obj = { b:2 }
var obj2 = {

   b:1,

   foo: function(num){ this.b += num; return this.b; }
}


obj2.foo(1); // 2
obj2.foo.call(obj, 3); // 5
obj2.foo.apply(obj, [3]); // 5
curry, bind, hitch, partial, etc



Scope/context manipulation via apply/call. Simple wrapper.

promotes code re-use / DRY
// partial is to curry ...
var foo = function(direction){

       if(direction){ goleft(); }else{ goright(); }
}
var left = foo.curry(1),
    right = dojo.partial(foo, 0)
    ;


    left(); right();
// as bind is to hitch
var o = {

    handler:function(response){ ... },

    send:function(){

    
      dojo.xhrPost({

    
      
    url:"/the/url",

    
      
    handle: dojo.hitch(this, "method")

    
      })

    }
};
o.send();
ALSO FOR JQUERY ...
  http://higginsforpresident.net/js/static/jq.hitch.js
DUCK PUNCH
   aka: AOP
(function(d){


    var oldonload = d.addOnLoad;

    d.addOnLoad = d.ready = function(fn){

    
 oldonload.call(d, d.partial(fn, d));

    }


    // now you can use `dojo` as whatever first

    // arg to dojo.ready callback is:

    //

    //
 dojo.ready(function(d){

    //
 
 d.require("foo.bar.Baz");

    //
 });

})(dojo);
(function(d){

    var rqr = d.require;

    d.require = function(module){

    
      if(d.isArray(module)){

    
      
   d.forEach(module, rqr, d);

    
      }else{

    
      
   rqr.apply(d, arguments);

    
      }

    
      return d; // mmm chaining.

    }
})(dojo);
// old api:
dojo.require(“foo.Bar”);
// new ducked apis:
dojo.require([“foo.Bar”, “bar.Baz”]);
dojo.require(“bam.Foo”).require(“omg.Really”)
  .require([“oh.Right”, “doit.ThisWayToo”])
  ;
(function(d){
   // replace the old dojo with a function

      var d = dojo;

      dojo = function(a){

      
 if(d.isFunction(a)){

      
 
 d.ready(a);

      
 
 return dojo;

      
 }else{

      
 
 return d.query.apply(d, arguments);

      
 }

      }


      // this is just to bother alex:

      dojo.fn = d.NodeList.prototype;


      // mix dojo back into itself.

      for(var i in d){ dojo[i] = d[i]; }

})(dojo);
dojo(function(){ /* onload */});

dojo("#someId").style({ color:”red” }).onclick(fn);

dojo.style("someId", { color:”red” });

dojo.fn.myRadPlugin = function(){
  return this.forEach(...);
}
Ubiquitous Unicorn.
NATIVE PROTOTYPES
      for fun and profit.
if(!Array.prototype.forEach){

     Array.prototype.forEach = function(cb, thisObj){

     
 thisObj = thisObj || window;

     
 for(var i = 0, l = this.length; i < l; i++){

     
 
 cb.call(thisObj, ar[i], i, ar);

     
 }

     }
}

[1,2,3].forEach(function(num){ alert(num); });
if(!Array.prototype.forEach){

    Array.prototype.forEach = function(cb){

    
    for(var i = 0, l = this.length; i < l; i++){

    
    
    cb.call(ar[i], i, ar);

    
    }

    }
}
[1,2,3].forEach(function(){ alert(this); });
DOJOTYPE!
http://code.google.com/p/dojotype
1:1.333333 Mapping to Dojo
Base Dojo

dojo.date

dojo.string

dojo.Color
(function(d){


    var c = new d.Color(),

    
 setup = function(meth){

    
 
 if(!this[meth]){

    
 
 
 this[meth] = function(){

    
 
 
 
 c.setColor(this);

    
 
 
 
 return c[meth].apply(c, arguments);

    
 
 
 };

    
 
 }

    
 }

    ;


    d.forEach(["toRgb", "toRgba", "toHex"], setup, String.prototype);

    d.forEach(["toCss"], setup, Array.prototype);

       // [255,255,255].toCss(); // returns #000000
       // “#000000”.toRgb(); // returns [255,255,255]

})(dojo);
LAME MODERN BROWSERS
        “win”.blink()
es3ex-String!
          http://code.google.com/p/dojotype/source/browse/trunk/es3ex-String.js




.anchor(), .link(), .fontsize, .fontcolor

  node.innerHTML = “click here”.link(“http://google.com”);

blink(), sup(), small(), et al.
new Date()


i18n

formatting

comparison

addition
var dd = d.date, dp = Date.prototype,

   
     map = {

   
     
     "daysInMonth": [dd, "daysInMonth"],

   
     
     "isLeapYear": [dd, "isLeapYear"],

   
     
     "timezone": [dd, "getTimezoneName"],

   
     
     "compare": [dd, "compare"],

   
     
     "add": [dd, "add"],

   
     
     "difference": [dd, "difference"],

   
     
     "format": [dd.locale, "format"],

   
     
     "isWeekend": [dd.locale, "isWeekend"]

   
     }

   ;


   // setup all the above direct mappings

   var setup = function(pn, fn){

   
      if(!dp[pn]){

   
      
       var fullfn = fn[0][fn[1]];

   
      
       dp[pn] = function(){

   
      
       
      return fullfn.apply(fn[0], d._prep(this, arguments));

   
      
       };

   
      }

   };


   for(var i in map){ setup(i, map[i]); }
d._clobber(Date.prototype, {

   
     json: function(){

   
     
       // summary: Serializes a Date object as an ISO String. Helps

   
     
       // when serializing a JSON string from an object containing

   
     
       // Date objects.

   
     
       return d.date.stamp.toISOString(this, { selector: 'date' });

   
     }

   });


   d._clobber(String.prototype, {

   
     toDate: function(options){

   
     
     // summary: Convert this string into a Date object, provided it is formatted properly.

   
     
     return dojo.date.locale.parse(this, options);

   
     }

   });
var maff = Math, np = Number.prototype;

   d.forEach(

   
     [

   
     
      // a list of straight-up-shit-that-could-be-on-Number

   
     
      // that would just call Math.something(this)

   
     
      "abs", "acos", "asin", "atan", "atan2", "ceil", "cos", "exp", "floor", "log",

   
     
      "max", "min", "pow", /* "random", "round", */ "sin", "sqrt", "tan"

   
     ],

   
     function(meth){

   
     
      // setup the function in place if it doesn't exist

   
     
      // for some reason

   
     
      if(!this[meth] && maff[meth]){

   
     
      
        this[meth] = function(param){

   
     
      
        
      // if we have at least one extra param, take the whole thing:

   
     
      
        
      return maff[meth].apply(maff, param ? d._prep(this, arguments) : [this]);

   
     
      
        };

   
     
      }

   
     },

   
     np // context

   );
JUST JAVASCRIPT.
       Still.
Take Away:

JavaScript is fun and flexible.

The DOM is the culprit. and evil.

Because you can do something, doesn’t mean you should.

  Don’t let that stop you.

Embrace the language as a whole.
THANKS!
clap. or ask questions. or don’t.
@PHIGGINS
 http://higginsforpresident.net