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

Txjs

  • 1.
    IT’S JUST JAVASCRIPT. Peter Higgins / @phiggins / #txjs / 2010-06-04
  • 2.
  • 3.
  • 4.
    yay Dojo. A Library. 5+years testing, revision, support. Backwards compatible APIs (to a painful degree)
  • 5.
    IN THE END... It’s just a LOT of JavaScript.
  • 6.
    IN THE END... It’s just a LOT of modular JavaScript.
  • 7.
    IN THE END... It’s just a LOT of optional JavaScript.
  • 8.
  • 9.
  • 10.
  • 11.
    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
  • 12.
  • 13.
    dojo.declare("Thing", [inheritance, chain],{ myProps:"override", aMethod:function(){ this.inherited(arguments); } }); new Thing();
  • 14.
  • 15.
  • 16.
    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
  • 17.
    curry, bind, hitch,partial, etc Scope/context manipulation via apply/call. Simple wrapper. promotes code re-use / DRY
  • 18.
    // partial isto curry ... var foo = function(direction){ if(direction){ goleft(); }else{ goright(); } } var left = foo.curry(1), right = dojo.partial(foo, 0) ; left(); right();
  • 19.
    // as bindis to hitch var o = { handler:function(response){ ... }, send:function(){ dojo.xhrPost({ url:"/the/url", handle: dojo.hitch(this, "method") }) } }; o.send();
  • 20.
    ALSO FOR JQUERY... http://higginsforpresident.net/js/static/jq.hitch.js
  • 21.
    DUCK PUNCH aka: AOP
  • 22.
    (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);
  • 23.
    (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);
  • 24.
    // 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”]) ;
  • 25.
    (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);
  • 26.
    dojo(function(){ /* onload*/}); dojo("#someId").style({ color:”red” }).onclick(fn); dojo.style("someId", { color:”red” }); dojo.fn.myRadPlugin = function(){ return this.forEach(...); }
  • 27.
  • 28.
    NATIVE PROTOTYPES for fun and profit.
  • 29.
    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); });
  • 30.
    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); });
  • 31.
  • 32.
    1:1.333333 Mapping toDojo Base Dojo dojo.date dojo.string dojo.Color
  • 33.
    (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);
  • 34.
    LAME MODERN BROWSERS “win”.blink()
  • 35.
    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.
  • 36.
  • 37.
    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]); }
  • 38.
    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); } });
  • 39.
    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 );
  • 40.
  • 41.
    Take Away: JavaScript isfun 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.
  • 42.
    THANKS! clap. or askquestions. or don’t.
  • 43.