Twitter Meta:
@kvangork
#OOJS
Object-Oriented Javascript
order from chaos (we hope)
function bfIsAlphaNumeric( cfield )
{
cfield.value = TRIM2(cfield.value);
for ( i = 0 ; i < cfield.value.length ; i++)
{
var n = cfield.value.substr(i,1);
if ( n != 'a' && n != 'b' && n != 'c' && n != 'd'
&& n != 'e' && n != 'f' && n != 'g' && n != 'h'
//...
&& n != '8' && n != '9'
&& n != '_' && n != '@' && n != '-‐' && n != '.' )
{
window.alert("Only Alphanumeric are allowed.\nPlease re-‐enter the value.");
cfield.value = '';
cfield.focus();
}
cfield.value = cfield.value.toUpperCase();
}
return;
}
everything is an
Object
even functions
http://www.flickr.com/photos/sanchtv/4192677571
every
Object
has a
Prototype
http://www.flickr.com/photos/macwalsh/4403701509
Tools
//Helper function. Copy all properties of props into obj
function mixin (obj, props) {
if(obj && props && typeof props == 'object') {
for(var property in props) {
obj[property] = props[property];
}
}
}
Tools
//Pseudo-‐Classical Extension Function
//Preserves: inheritance
// superclass
function extend (superclass, overrides) {
//...complicated, dragon-‐filled, etc...
//get the well-‐commented code from http://gist.github.com/339766
//Returns new class, descended from superclass, with overrides applied.
}
Basic Container Class
var Container = function(){
this.items = []; //empty array to hold items
};
Container.prototype.addItem = function(item) {
this.items.push(item);
}
Container.prototype.getCount = function() {
return this.items.length;
}
var Container = function(){
this.items = []; //empty array to hold items
};
Container.prototype.addItem = function(item) {
this.items.push(item);
}
Container.prototype.getCount = function() {
return this.items.length;
}
var LimitedContainer = extend(Container, {
constructor: function(maxItems) {
LimitedContainer.superclass.constructor.call(this);
this.maxItems = maxItems;
},
addItem: function(item) {
if(this.getCount() < this.maxItems) {
LimitedContainer.superclass.addItem.call(this, item);
}
}
});
var Container = function(){
this.items = []; //empty array to hold items
};
Container.prototype.addItem = function(item) {
this.items.push(item);
}
Container.prototype.getCount = function() {
return this.items.length;
}
var LimitedContainer = extend(Container, {
constructor: function(maxItems) {
LimitedContainer.superclass.constructor.call(this);
this.maxItems = maxItems;
},
addItem: function(item) {
if(this.getCount() < this.maxItems) {
LimitedContainer.superclass.addItem.call(this, item);
}
}
});
http://www.flickr.com/photos/thomasroche/2481517741
Bearded Men of the 21st Century (1939)
Config Objects
function LimitedContainer (maxItems) {
this.maxItems = maxItems;
}
new LimitedContainer(3);
Config Objects
function LimitedContainer(config) {
mixin(this, config); //who knows what you'll need
this.maxItems = config.maxItems || 3;
}
new LimitedContainer({maxItems: 3});
Model View
Example
Model View
var DS = {};
//Empty constructor, this is just a stub
DS.QueryControllerView = extend(Object, {
//No constructor required, use Object's default
//Required Delegate methods:
QueryCompleted: function (resultSet) {
alert("Your query finished with " + resultSet.features.length + " features returned.");
},
QueryFailed: function (error) {
alert("Sorry, your query failed. Here are its last words: " + error);
}
});
DS.QueryController = extend(Object, {
constructor: function (config) {
//copy all config parameters
mixin(this, config);
//verify required parameter presence and types
if (!(this.view instanceof DS.QueryControllerView)) throw("Incorrect view...");
if (!this.serviceURL) throw("Missing Service URL.");
this.queryTask = new esri.tasks.QueryTask(this.serviceURL);
},
initiateQuery: function (geometry) {
if (!geometry instanceof esri.geometry.Geometry) throw("Invalid geometry parameter...");
var query = new esri.tasks.Query();
query.geometry = geometry;
query.returnGeometry = true;
this.runningQuery = this.queryTask.execute(query, this.callback, this.errback);
},
view = new DS.QueryControllerView();
controller = new DS.QueryController({
view: view,
serviceURL: "http://sampleserver1.arcg...mographics/ESRI_Census_USA/MapServer/3"
});
//set up click event handler
dojo.connect(map, "onClick", function(evt) {
controller.initiateQuery(evt.mapPoint);
});
Demo
DS.QueryControllerMapView = extend(DS.QueryControllerView, {
constructor: function(config) {
mixin(this, config);
if (!(this.map instanceof esri.Map)) throw("Incorrect map parameter...");
},
QueryCompleted: function(resultSet) {
if(resultSet.features.length) {
this.map.graphics.clear();
var mySymbol = new esri.symbol.SimpleFillSymbol(...255,0,0.25]));
var feature = resultSet.features[0];
feature.setSymbol(mySymbol);
this.map.graphics.add(feature);
}
}
});
view = new DS.QueryControllerMapView({map: map});
controller = new DS.QueryController({
view: view,
serviceURL: "http://sampleserver1.arcg...mographics/ESRI_Census_USA/MapServer/3"
});
//set up click event handler
dojo.connect(map, "onClick", function(evt) {
controller.initiateQuery(evt.mapPoint);
});
Demo
Resources
Object-Oriented Javascript by Stoyan Stefanov
YUI Theater, especially Douglas Crockford’s videos
Read Library Source Code - Dojo, jQuery, YUI
Download this deck and code at http://prng.vangorkom.org
You should follow me on Twitter: @kvangork