Pages

Wednesday, May 25, 2016

Some basic experiments with dojo/_base/lang

Dojo/_base/lang
The important pointers to remember about this package are, this provides following functionalities
Clone – helps clone a node to an other. A literal copy
Delegate – helps create a bounded subclassed object. Changes are reflected to child when parent object is changed, provided, its done in the oops way *(note1:refer note below)
exists getObject setObject
extend mixin partial – extend works with prototype, mixin with properties and partial helps overload functions with ease
hitch – force scope for an object
replace – A huge feature. Lot of varities and customizations are possible. Refer the following html code to understand what it does


*note1
var lang=require("dojo/_base/lang")
var obj = { a:"b", c:"d" };
var thing = lang.delegate(obj);
obj.e='f';
thing; //:is a {a: "b", c: "d", e: "f"}
obj = { a:"b", c:"d" , g:"h"};
thing; //:is still a {a: "b", c: "d", e: "f"} – note g:”h” did not get updated as it was not done in the oops way.

Use the following html file and watch the logs that gets printed. Then run through the code that produced them. This will you understand what does what
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Dojo Lang</title>

<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.3/dojo/dojo.js"
data-dojo-config="async: true"></script>

<script>
//lang.extend & lang.mixin
require([ "dojo/_base/lang", "dojo/json" ], function(lang, json) {
// define a class
var myClass = function() {
this.defaultProp = "default value";
};
myClass.prototype = {};
console.log("the class (unmodified):", json
.stringify(myClass.prototype));

// extend the class
lang.extend(myClass, {
"extendedProp" : "extendedValue"
});
console.log("the class (modified with lang.extend):", json
.stringify(myClass.prototype));

var t = new myClass();
// add new properties to the instance of our class
lang.mixin(t, {
"mixin property" : "myValue"
});
console.log("\nmixin does not bother protoype")
console.log("the instance (modified with lang.mixin):", json
.stringify(t));
});

//lang.getObject()
console.log("\n****lang.getObject()****")
require([ "dojo/_base/lang" ], function(lang) {
// define an object (intentionally global to demonstrate)
foo = {
bar : "lang.getObject() value"
};

console.log("foo.bar=" + lang.getObject("foo.bar"));// returns "some value"

// get the "foo.baz" property, create it if it doesn't exist
console.log(lang.getObject("foo.baz", true)); // returns foo.baz - an empty object {}

// get the "bar" property of the foo object
console.log(lang.getObject("bar", false, foo)); // returns "some value"
});

//lang.partial
//helps create over loaded function
console.log('\n****Overload functions using lang.partial****')
require([ "dojo/_base/lang", "dojo/request" ], function(lang, request) {
var dataLoaded = function(funcName, someFirstParam, data, ioargs) {
if (!funcName || funcName == '')
funcName = 'dataLoaded';
console.log(funcName + "::someFirstParam=" + someFirstParam);
console.log(funcName + "::data=" + data);
console.log(funcName + "::ioargs=" + ioargs);
};

console.log('\ndataLoaded() gives following logs');
dataLoaded();
var partialDataLoaded = lang.partial(dataLoaded, "partialDataLoaded",
"firstValue");
console.log('\npartialDataLoaded() gives following logs');
partialDataLoaded();
console.log('\npartialDataLoaded("myData") gives following logs');
partialDataLoaded("myData");
});

console.log('\n****lang.Replace()****');
require(
[ "dojo/_base/lang", "dojo/dom", "dojo/_base/array",
"dojo/domReady!" ],
function(lang, dom, array) {

replacedString = lang.replace(
"Hello, {name.first} {name.last} AKA {nick}!", {
name : {
first : "Karthikeyan",
middle : "X",
last : "Alagirisamy"
},
nick : "AK"
});
console.log('replacedString=' + replacedString);
replacedString = lang.replace("Hello, {0} {2} AKA {3}!", [
"Karthikeyan", "X", "Alagirisamy", "Manda" ]);
console.log('replacedString=' + replacedString);

console.log('\n*** replace with a function');

// helper function for complex replace
function sum(a) {
var t = 0;
array.forEach(a, function(x) {
t += x;
});
return t;
}

var complexReplace = lang
.replace(
"{count} items averaging {avg} per item ranging from {min} to {max} with a total sum of {sum}.",
lang.hitch(
{
payments : [ 11, 16, 12, 24, 99,
46, 8, 82 ]
}, function(_, key) {
switch (key) {
case "count":
return this.payments.length;
case "min":
return Math.min.apply(Math,
this.payments);
case "max":
return Math.max.apply(Math,
this.payments);
case "sum":
return sum(this.payments);
case "avg":
return sum(this.payments)
/ this.payments.length;
}
}));

console.log("complexReplace = " + complexReplace);

console.log("\n***Replace using custom patterns");
var customReplace = lang
.replace("Hello, %[0] %[2] AKA %[3]!", [ "Robert", "X",
"Cringely", "Bob" ], /\%\[([^\]]+)\]/g);
console.log("customReplace=" + customReplace);

console.log("\n***Escaping Substitutions");
function safeReplace(tmpl, dict) {
// convert dict to a function, if needed
var fn = lang.isFunction(dict) ? dict : function(_, name) {
return lang.getObject(name, false, dict);
};

// perform the substitution
return lang.replace(tmpl, function(_, name) {
if (name.charAt(0) == '!') {
// no escaping
return fn(_, name.slice(1));
}
// escape
return fn(_, name).replace(/&/g, "&")
.replace(/</g, "<").replace(/>/g, ">").replace(
/"/g, '"');
});
}

// we don't want to break the Code Glass widget here
var bad = "{script}alert('Let\' break stuff!');{/script}";

// let's reconstitute the original bad string
bad = bad.replace(/\{/g, "<").replace(/\}/g, ">");

// now the replacement
var escapedSubstitution = safeReplace("<div>{0}</div", [ bad ]);
console.log('escapedSubstitution=' + escapedSubstitution);

console.log('\n****Formatting Substitutions');
function format(tmpl, dict, formatters) {
// convert dict to a function, if needed
var fn = lang.isFunction(dict) ? dict : function(_, name) {
return lang.getObject(name, false, dict);
};

// perform the substitution
return lang.replace(tmpl,
function(_, name) {
var parts = name.split(":"), value = fn(_,
parts[0]);
if (parts.length > 1) {
value = formatters[parts[1]](value, parts
.slice(2));
}
return value;
});
}

// simple numeric formatters
var customFormatters = {
f : function(value, opts) {
// return formatted as a fixed number
var precision = opts && opts.length && opts[0];
return Number(value).toFixed(precision);
},
e : function(value, opts) {
// return formatted as an exponential number
var precision = opts && opts.length && opts[0];
return Number(value).toExponential(precision);
}
};

// that is how we use it:
var output1 = format(
"pi = {pi}<br>pi:f = {pi:f}<br>pi:f:5 = {pi:f:5}", {
pi : Math.PI,
big : 1234567890
}, customFormatters);

var formatingSubEx1 = format(
"pi = {pi}<br>pi:f = {pi:f}<br>pi:f:5 = {pi:f:5}", {
pi : Math.PI,
big : 1234567890
}, customFormatters);

var formatingSubEx2 = format(
"big = {big}<br>big:e = {big:e}<br>big:e:5 = {big:e:5}",
{
pi : Math.PI,
big : 1234567890
}, customFormatters);

console.log("formatingSubEx1=" + formatingSubEx1);
console.log("formatingSubEx2=" + formatingSubEx2);

console.log('\n******lang.setObject************');
var obj={};
lang.setObject("parent.child.prop", "some value", obj);
console.log("obj.parent.child.prop=" + obj.parent.child.prop);

console.log('\n**********lang.trim**********');
function show(str) {
console.log("|" + lang.trim(str) + "|");
}
show("   one");
show("two ");
show("   three ");
show("\tfour\r\n");
show("\f\n\r\t\vF I V E\f\n\r\t\v");

/*
isString() Checks if the parameter is a String
isArray() Checks if the parameter is an Array
isFunction() Checks if the parameter is a Function
isObject() Checks if the parameter is a Object
isArrayLike() Checks if the parameter is like an Array
isAlien() Checks if the parameter is a built-in function
*/
});
</script>

</head>
<body>http://pc301227.xts.com:8090/DojoCracker/index.html
</body>
</html>



Console shall produce the following output
the class (unmodified): {}
dojo_base_lang.html:25 the class (modified with lang.extend): {"extendedProp":"extendedValue"}
dojo_base_lang.html:33
mixin does not bother protoype
dojo_base_lang.html:34 the instance (modified with lang.mixin): {"defaultProp":"default value","mixin property":"myValue"}
dojo_base_lang.html:39
****lang.getObject()****
dojo_base_lang.html:46 foo.bar=lang.getObject() value
dojo_base_lang.html:49 Object {}
dojo_base_lang.html:52 lang.getObject() value
dojo_base_lang.html:57
****Overload functions using lang.partial****
dojo_base_lang.html:67
dataLoaded() gives following logs
dojo_base_lang.html:62 dataLoaded::someFirstParam=undefined
dojo_base_lang.html:63 dataLoaded::data=undefined
dojo_base_lang.html:64 dataLoaded::ioargs=undefined
dojo_base_lang.html:71
partialDataLoaded() gives following logs
dojo_base_lang.html:62 partialDataLoaded::someFirstParam=firstValue
dojo_base_lang.html:63 partialDataLoaded::data=undefined
dojo_base_lang.html:64 partialDataLoaded::ioargs=undefined
dojo_base_lang.html:73
partialDataLoaded("myData") gives following logs
dojo_base_lang.html:62 partialDataLoaded::someFirstParam=firstValue
dojo_base_lang.html:63 partialDataLoaded::data=myData
dojo_base_lang.html:64 partialDataLoaded::ioargs=undefined
dojo_base_lang.html:77
****lang.Replace()****
dojo_base_lang.html:92 replacedString=Hello, Karthikeyan Alagirisamy AKA AK!
dojo_base_lang.html:95 replacedString=Hello, Karthikeyan Alagirisamy AKA Manda!
dojo_base_lang.html:97
*** replace with a function
dojo_base_lang.html:133 complexReplace = 8 items averaging 37.25 per item ranging from 8 to 99 with a total sum of 298.
dojo_base_lang.html:135
***Replace using custom patterns
dojo_base_lang.html:139 customReplace=Hello, Robert Cringely AKA Bob!
dojo_base_lang.html:141
***Escaping Substitutions
dojo_base_lang.html:169 escapedSubstitution=<div><script>alert('Let' break stuff!');</script></div
dojo_base_lang.html:171
****Formatting Substitutions
dojo_base_lang.html:225 formatingSubEx1=pi = 3.141592653589793<br>pi:f = 3<br>pi:f:5 = 3.14159
dojo_base_lang.html:226 formatingSubEx2=big = 1234567890<br>big:e = 1e+9<br>big:e:5 = 1.23457e+9
dojo_base_lang.html:228
******lang.setObject************
dojo_base_lang.html:231 obj.parent.child.prop=some value
dojo_base_lang.html:233
**********lang.trim**********
dojo_base_lang.html:235 |one|
dojo_base_lang.html:235 |two|
dojo_base_lang.html:235 |three|
dojo_base_lang.html:235 |four|
dojo_base_lang.html:235 |F I V E|