summaryrefslogtreecommitdiffstatshomepage
path: root/includes/js/dojox/lang
diff options
context:
space:
mode:
Diffstat (limited to 'includes/js/dojox/lang')
-rw-r--r--includes/js/dojox/lang/LICENSE21
-rw-r--r--includes/js/dojox/lang/README37
-rw-r--r--includes/js/dojox/lang/functional.js9
-rw-r--r--includes/js/dojox/lang/functional/array.js113
-rw-r--r--includes/js/dojox/lang/functional/curry.js96
-rw-r--r--includes/js/dojox/lang/functional/fold.js87
-rw-r--r--includes/js/dojox/lang/functional/lambda.js110
-rw-r--r--includes/js/dojox/lang/functional/listcomp.js54
-rw-r--r--includes/js/dojox/lang/functional/object.js48
-rw-r--r--includes/js/dojox/lang/functional/reversed.js79
-rw-r--r--includes/js/dojox/lang/functional/scan.js84
-rw-r--r--includes/js/dojox/lang/functional/sequence.js38
-rw-r--r--includes/js/dojox/lang/functional/zip.js45
-rw-r--r--includes/js/dojox/lang/tests/array.js84
-rw-r--r--includes/js/dojox/lang/tests/curry.js31
-rw-r--r--includes/js/dojox/lang/tests/fold.js64
-rw-r--r--includes/js/dojox/lang/tests/fun_perf.html176
-rw-r--r--includes/js/dojox/lang/tests/lambda.js24
-rw-r--r--includes/js/dojox/lang/tests/listcomp.js28
-rw-r--r--includes/js/dojox/lang/tests/main.js17
-rw-r--r--includes/js/dojox/lang/tests/misc.js31
-rw-r--r--includes/js/dojox/lang/tests/runTests.html9
-rw-r--r--includes/js/dojox/lang/utils.js54
23 files changed, 1339 insertions, 0 deletions
diff --git a/includes/js/dojox/lang/LICENSE b/includes/js/dojox/lang/LICENSE
new file mode 100644
index 0000000..d84a6aa
--- /dev/null
+++ b/includes/js/dojox/lang/LICENSE
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2007 Oliver Steele
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/includes/js/dojox/lang/README b/includes/js/dojox/lang/README
new file mode 100644
index 0000000..753b943
--- /dev/null
+++ b/includes/js/dojox/lang/README
@@ -0,0 +1,37 @@
+-------------------------------------------------------------------------------
+dojox.lang
+-------------------------------------------------------------------------------
+Version 0.991
+Release date: 07/30/2007
+-------------------------------------------------------------------------------
+Project state:
+[beta]
+-------------------------------------------------------------------------------
+Credits
+ Eugene Lazutkin (eugene.lazutkin@gmail.com)
+-------------------------------------------------------------------------------
+Project description
+
+Implementation of common functional operations, and provisions
+Later we can add other JS language-related helpers.
+-------------------------------------------------------------------------------
+Dependencies:
+
+None.
+-------------------------------------------------------------------------------
+Documentation
+
+-------------------------------------------------------------------------------
+Installation instructions
+
+Grab the following from the Dojo SVN Repository:
+http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/lang/*
+
+Install into the following directory structure:
+/dojox/lang/
+
+...which should be at the same level as your Dojo checkout.
+-------------------------------------------------------------------------------
+Additional Notes
+
+See tests and the source for more details.
diff --git a/includes/js/dojox/lang/functional.js b/includes/js/dojox/lang/functional.js
new file mode 100644
index 0000000..e75ad00
--- /dev/null
+++ b/includes/js/dojox/lang/functional.js
@@ -0,0 +1,9 @@
+if(!dojo._hasResource["dojox.lang.functional"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.functional"] = true;
+dojo.provide("dojox.lang.functional");
+
+dojo.require("dojox.lang.functional.lambda");
+dojo.require("dojox.lang.functional.array");
+dojo.require("dojox.lang.functional.object");
+
+}
diff --git a/includes/js/dojox/lang/functional/array.js b/includes/js/dojox/lang/functional/array.js
new file mode 100644
index 0000000..45c2613
--- /dev/null
+++ b/includes/js/dojox/lang/functional/array.js
@@ -0,0 +1,113 @@
+if(!dojo._hasResource["dojox.lang.functional.array"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.functional.array"] = true;
+dojo.provide("dojox.lang.functional.array");
+
+dojo.require("dojox.lang.functional.lambda");
+
+// This module adds high-level functions and related constructs:
+// - array-processing functions similar to standard JS functions
+
+// Notes:
+// - this module provides JS standard methods similar to high-level functions in dojo/_base/array.js:
+// forEach, map, filter, every, some
+
+// Defined methods:
+// - take any valid lambda argument as the functional argument
+// - operate on dense arrays
+// - take a string as the array argument
+// - take an iterator objects as the array argument
+
+(function(){
+ var d = dojo, df = dojox.lang.functional;
+
+ d.mixin(df, {
+ // JS 1.6 standard array functions, which can take a lambda as a parameter.
+ // Consider using dojo._base.array functions, if you don't need the lambda support.
+ filter: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+ // summary: creates a new array with all elements that pass the test
+ // implemented by the provided function.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ var t = [], v;
+ if(d.isArray(a)){
+ for(var i = 0, n = a.length; i < n; ++i){
+ v = a[i];
+ if(f.call(o, v, i, a)){ t.push(v); }
+ }
+ }else{
+ for(var i = 0; a.hasNext();){
+ v = a.next();
+ if(f.call(o, v, i++)){ t.push(v); }
+ }
+ }
+ return t; // Array
+ },
+ forEach: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+ // summary: executes a provided function once per array element.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ if(d.isArray(a)){
+ for(var i = 0, n = a.length; i < n; f.call(o, a[i], i, a), ++i);
+ }else{
+ for(var i = 0; a.hasNext(); f.call(o, a.next(), i++));
+ }
+ },
+ map: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+ // summary: creates a new array with the results of calling
+ // a provided function on every element in this array.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ var t, n;
+ if(d.isArray(a)){
+ t = new Array(n = a.length);
+ for(var i = 0; i < n; t[i] = f.call(o, a[i], i, a), ++i);
+ }else{
+ t = [];
+ for(var i = 0; a.hasNext(); t.push(f.call(o, a.next(), i++)));
+ }
+ return t; // Array
+ },
+ every: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+ // summary: tests whether all elements in the array pass the test
+ // implemented by the provided function.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ if(d.isArray(a)){
+ for(var i = 0, n = a.length; i < n; ++i){
+ if(!f.call(o, a[i], i, a)){
+ return false; // Boolean
+ }
+ }
+ }else{
+ for(var i = 0; a.hasNext();){
+ if(!f.call(o, a.next(), i++)){
+ return false; // Boolean
+ }
+ }
+ }
+ return true; // Boolean
+ },
+ some: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+ // summary: tests whether some element in the array passes the test
+ // implemented by the provided function.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ if(d.isArray(a)){
+ for(var i = 0, n = a.length; i < n; ++i){
+ if(f.call(o, a[i], i, a)){
+ return true; // Boolean
+ }
+ }
+ }else{
+ for(var i = 0; a.hasNext();){
+ if(f.call(o, a.next(), i++)){
+ return true; // Boolean
+ }
+ }
+ }
+ return false; // Boolean
+ }
+ });
+})();
+
+}
diff --git a/includes/js/dojox/lang/functional/curry.js b/includes/js/dojox/lang/functional/curry.js
new file mode 100644
index 0000000..7c795ec
--- /dev/null
+++ b/includes/js/dojox/lang/functional/curry.js
@@ -0,0 +1,96 @@
+if(!dojo._hasResource["dojox.lang.functional.curry"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.functional.curry"] = true;
+dojo.provide("dojox.lang.functional.curry");
+
+dojo.require("dojox.lang.functional.lambda");
+
+// This module adds high-level functions and related constructs:
+// - currying and partial functions
+// - argument pre-processing: mixer and flip
+
+// Acknoledgements:
+// - partial() is based on work by Oliver Steele
+// (http://osteele.com/sources/javascript/functional/functional.js)
+// which was published under MIT License
+
+// Defined methods:
+// - take any valid lambda argument as the functional argument
+
+(function(){
+ var df = dojox.lang.functional;
+
+ var currying = function(/*Object*/ info){
+ return function(){ // Function
+ if(arguments.length + info.args.length < info.arity){
+ return currying({func: info.func, arity: info.arity,
+ args: Array.prototype.concat.apply(info.args, arguments)});
+ }
+ return info.func.apply(this, Array.prototype.concat.apply(info.args, arguments));
+ };
+ };
+
+ dojo.mixin(df, {
+ // currying and partial functions
+ curry: function(/*Function|String|Array*/ f, /*Number?*/ arity){
+ // summary: curries a function until the arity is satisfied, at
+ // which point it returns the calculated value.
+ f = df.lambda(f);
+ arity = typeof arity == "number" ? arity : f.length;
+ return currying({func: f, arity: arity, args: []}); // Function
+ },
+ arg: {}, // marker for missing arguments
+ partial: function(/*Function|String|Array*/ f){
+ // summary: creates a function where some arguments are bound, and
+ // some arguments (marked as dojox.lang.functional.arg) are will be
+ // accepted by the final function in the order they are encountered.
+ // description: This method is used to produce partially bound
+ // functions. If you want to change the order of arguments, use
+ // dojox.lang.functional.mixer() or dojox.lang.functional.flip().
+ var a = arguments, args = new Array(a.length - 1), p = [];
+ f = df.lambda(f);
+ for(var i = 1; i < a.length; ++i){
+ var t = a[i];
+ args[i - 1] = t;
+ if(t == df.arg){
+ p.push(i - 1);
+ }
+ }
+ return function(){ // Function
+ var t = Array.prototype.slice.call(args, 0); // clone the array
+ for(var i = 0; i < p.length; ++i){
+ t[p[i]] = arguments[i];
+ }
+ return f.apply(this, t);
+ };
+ },
+ // argument pre-processing
+ mixer: function(/*Function|String|Array*/ f, /*Array*/ mix){
+ // summary: changes the order of arguments using an array of
+ // numbers mix --- i-th argument comes from mix[i]-th place
+ // of supplied arguments.
+ f = df.lambda(f);
+ return function(){ // Function
+ var t = new Array(mix.length);
+ for(var i = 0; i < mix.length; ++i){
+ t[i] = arguments[mix[i]];
+ }
+ return f.apply(this, t);
+ };
+ },
+ flip: function(/*Function|String|Array*/ f){
+ // summary: changes the order of arguments by reversing their
+ // order.
+ f = df.lambda(f);
+ return function(){ // Function
+ // reverse arguments
+ var a = arguments, l = a.length - 1, t = new Array(l + 1), i;
+ for(i = 0; i <= l; ++i){
+ t[l - i] = a[i];
+ }
+ return f.apply(this, t);
+ };
+ }
+ });
+})();
+
+}
diff --git a/includes/js/dojox/lang/functional/fold.js b/includes/js/dojox/lang/functional/fold.js
new file mode 100644
index 0000000..90a9a3d
--- /dev/null
+++ b/includes/js/dojox/lang/functional/fold.js
@@ -0,0 +1,87 @@
+if(!dojo._hasResource["dojox.lang.functional.fold"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.functional.fold"] = true;
+dojo.provide("dojox.lang.functional.fold");
+
+dojo.require("dojox.lang.functional.lambda");
+
+// This module adds high-level functions and related constructs:
+// - "fold" family of functions
+
+// Notes:
+// - missing high-level functions are provided with the compatible API:
+// foldl, foldl1, foldr, foldr1
+// - missing JS standard functions are provided with the compatible API:
+// reduce, reduceRight
+
+// Defined methods:
+// - take any valid lambda argument as the functional argument
+// - operate on dense arrays
+// - take a string as the array argument
+// - take an iterator objects as the array argument (only foldl, foldl1, and reduce)
+
+(function(){
+ var d = dojo, df = dojox.lang.functional;
+
+ d.mixin(df, {
+ // classic reduce-class functions
+ foldl: function(/*Array|String|Object*/ a, /*Function*/ f, /*Object*/ z, /*Object?*/ o){
+ // summary: repeatedly applies a binary function to an array from left
+ // to right using a seed value as a starting point; returns the final
+ // value.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ if(d.isArray(a)){
+ for(var i = 0, n = a.length; i < n; z = f.call(o, z, a[i], i, a), ++i);
+ }else{
+ for(var i = 0; a.hasNext(); z = f.call(o, z, a.next(), i++));
+ }
+ return z; // Object
+ },
+ foldl1: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+ // summary: repeatedly applies a binary function to an array from left
+ // to right; returns the final value.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ var z;
+ if(d.isArray(a)){
+ z = a[0];
+ for(var i = 1, n = a.length; i < n; z = f.call(o, z, a[i], i, a), ++i);
+ }else if(a.hasNext()){
+ z = a.next();
+ for(var i = 1; a.hasNext(); z = f.call(o, z, a.next(), i++));
+ }
+ return z; // Object
+ },
+ foldr: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
+ // summary: repeatedly applies a binary function to an array from right
+ // to left using a seed value as a starting point; returns the final
+ // value.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ for(var i = a.length; i > 0; --i, z = f.call(o, z, a[i], i, a));
+ return z; // Object
+ },
+ foldr1: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+ // summary: repeatedly applies a binary function to an array from right
+ // to left; returns the final value.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ var n = a.length, z = a[n - 1];
+ for(var i = n - 1; i > 0; --i, z = f.call(o, z, a[i], i, a));
+ return z; // Object
+ },
+ // JS 1.8 standard array functions, which can take a lambda as a parameter.
+ reduce: function(/*Array|String|Object*/ a, /*Function*/ f, /*Object?*/ z){
+ // summary: apply a function simultaneously against two values of the array
+ // (from left-to-right) as to reduce it to a single value.
+ return arguments.length < 3 ? df.foldl1(a, f) : df.foldl(a, f, z); // Object
+ },
+ reduceRight: function(/*Array|String*/ a, /*Function*/ f, /*Object?*/ z){
+ // summary: apply a function simultaneously against two values of the array
+ // (from right-to-left) as to reduce it to a single value.
+ return arguments.length < 3 ? df.foldr1(a, f) : df.foldr(a, f, z); // Object
+ }
+ });
+})();
+
+}
diff --git a/includes/js/dojox/lang/functional/lambda.js b/includes/js/dojox/lang/functional/lambda.js
new file mode 100644
index 0000000..60be9f3
--- /dev/null
+++ b/includes/js/dojox/lang/functional/lambda.js
@@ -0,0 +1,110 @@
+if(!dojo._hasResource["dojox.lang.functional.lambda"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.functional.lambda"] = true;
+dojo.provide("dojox.lang.functional.lambda");
+
+// This module adds high-level functions and related constructs:
+// - anonymous functions built from the string
+
+// Acknoledgements:
+// - lambda() is based on work by Oliver Steele
+// (http://osteele.com/sources/javascript/functional/functional.js)
+// which was published under MIT License
+
+// Notes:
+// - lambda() produces functions, which after the compilation step are
+// as fast as regular JS functions (at least theoretically).
+
+// Lambda input values:
+// - returns functions unchanged
+// - converts strings to functions
+// - converts arrays to a functional composition
+
+(function(){
+ var df = dojox.lang.functional;
+
+ // split() is augmented on IE6 to ensure the uniform behavior
+ var split = "ab".split(/a*/).length > 1 ? String.prototype.split :
+ function(sep){
+ var r = this.split.call(this, sep),
+ m = sep.exec(this);
+ if(m && m.index == 0){ r.unshift(""); }
+ return r;
+ };
+
+ var lambda = function(/*String*/ s){
+ var args = [], sects = split.call(s, /\s*->\s*/m);
+ if(sects.length > 1){
+ while(sects.length){
+ s = sects.pop();
+ args = sects.pop().split(/\s*,\s*|\s+/m);
+ if(sects.length){ sects.push("(function(" + args + "){return (" + s + ")})"); }
+ }
+ }else if(s.match(/\b_\b/)){
+ args = ["_"];
+ }else{
+ var l = s.match(/^\s*(?:[+*\/%&|\^\.=<>]|!=)/m),
+ r = s.match(/[+\-*\/%&|\^\.=<>!]\s*$/m);
+ if(l || r){
+ if(l){
+ args.push("$1");
+ s = "$1" + s;
+ }
+ if(r){
+ args.push("$2");
+ s = s + "$2";
+ }
+ }else{
+ // the point of the long regex below is to exclude all well-known
+ // lower-case words from the list of potential arguments
+ var vars = s.
+ replace(/(?:\b[A-Z]|\.[a-zA-Z_$])[a-zA-Z_$\d]*|[a-zA-Z_$][a-zA-Z_$\d]*:|this|true|false|null|undefined|typeof|instanceof|in|delete|new|void|arguments|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|escape|eval|isFinite|isNaN|parseFloat|parseInt|unescape|dojo|dijit|dojox|window|document|'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/g, "").
+ match(/([a-z_$][a-z_$\d]*)/gi) || [];
+ var t = {};
+ dojo.forEach(vars, function(v){
+ if(!(v in t)){
+ args.push(v);
+ t[v] = 1;
+ }
+ });
+ }
+ }
+ return {args: args, body: "return (" + s + ");"}; // Object
+ };
+
+ var compose = function(/*Array*/ a){
+ return a.length ?
+ function(){
+ var i = a.length - 1, x = df.lambda(a[i]).apply(this, arguments);
+ for(--i; i >= 0; --i){ x = df.lambda(a[i]).call(this, x); }
+ return x;
+ }
+ :
+ // identity
+ function(x){ return x; };
+ };
+
+ dojo.mixin(df, {
+ // lambda
+ buildLambda: function(/*String*/ s){
+ // summary: builds a function from a snippet, returns a string,
+ // which represents the function.
+ // description: This method returns a textual representation of a function
+ // built from the snippet. It is meant to be evaled in the proper context,
+ // so local variables can be pulled from the environment.
+ s = lambda(s);
+ return "function(" + s.args.join(",") + "){" + s.body + "}"; // String
+ },
+ lambda: function(/*Function|String|Array*/ s){
+ // summary: builds a function from a snippet, or array (composing), returns
+ // a function object; functions are passed through unmodified.
+ // description: This method is used to normalize a functional representation
+ // (a text snippet, an array, or a function) to a function object.
+ if(typeof s == "function"){ return s; }
+ if(s instanceof Array){ return compose(s); }
+ s = lambda(s);
+ return new Function(s.args, s.body); // Function
+ }
+ });
+})();
+
+}
diff --git a/includes/js/dojox/lang/functional/listcomp.js b/includes/js/dojox/lang/functional/listcomp.js
new file mode 100644
index 0000000..adb4883
--- /dev/null
+++ b/includes/js/dojox/lang/functional/listcomp.js
@@ -0,0 +1,54 @@
+if(!dojo._hasResource["dojox.lang.functional.listcomp"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.functional.listcomp"] = true;
+dojo.provide("dojox.lang.functional.listcomp");
+
+// This module adds high-level functions and related constructs:
+// - list comprehensions similar to JavaScript 1.7
+
+// Notes:
+// - listcomp() produces functions, which after the compilation step are
+// as fast as regular JS functions (at least theoretically).
+
+(function(){
+ var g_re = /\bfor\b|\bif\b/gm;
+
+ var listcomp = function(/*String*/ s){
+ var frag = s.split(g_re), act = s.match(g_re),
+ head = ["var r = [];"], tail = [];
+ for(var i = 0; i < act.length;){
+ var a = act[i], f = frag[++i];
+ if(a == "for" && !/^\s*\(\s*(;|var)/.test(f)){
+ f = f.replace(/^\s*\(/, "(var ");
+ }
+ head.push(a, f, "{");
+ tail.push("}");
+ }
+ return head.join("") + "r.push(" + frag[0] + ");" + tail.join("") + "return r;"; // String
+ };
+
+ dojo.mixin(dojox.lang.functional, {
+ buildListcomp: function(/*String*/ s){
+ // summary: builds a function from a text snippet, which represents a valid
+ // JS 1.7 list comprehension, returns a string, which represents the function.
+ // description: This method returns a textual representation of a function
+ // built from the list comprehension text snippet (conformant to JS 1.7).
+ // It is meant to be evaled in the proper context, so local variable can be
+ // pulled from the environment.
+ return "function(){" + listcomp(s) + "}"; // String
+ },
+ compileListcomp: function(/*String*/ s){
+ // summary: builds a function from a text snippet, which represents a valid
+ // JS 1.7 list comprehension, returns a function object.
+ // description: This method returns a function built from the list
+ // comprehension text snippet (conformant to JS 1.7). It is meant to be
+ // reused several times.
+ return new Function([], listcomp(s)); // Function
+ },
+ listcomp: function(/*String*/ s){
+ // summary: executes the list comprehension building an array.
+ return (new Function([], listcomp(s)))(); // Array
+ }
+ });
+})();
+
+}
diff --git a/includes/js/dojox/lang/functional/object.js b/includes/js/dojox/lang/functional/object.js
new file mode 100644
index 0000000..52b6272
--- /dev/null
+++ b/includes/js/dojox/lang/functional/object.js
@@ -0,0 +1,48 @@
+if(!dojo._hasResource["dojox.lang.functional.object"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.functional.object"] = true;
+dojo.provide("dojox.lang.functional.object");
+
+dojo.require("dojox.lang.functional.lambda");
+
+// This module adds high-level functions and related constructs:
+// - object/dictionary helpers
+
+// Defined methods:
+// - take any valid lambda argument as the functional argument
+
+(function(){
+ var d = dojo, df = dojox.lang.functional, empty = {};
+
+ d.mixin(df, {
+ // object helpers
+ forIn: function(/*Object*/ obj, /*Function|String|Array*/ f, /*Object?*/ o){
+ // summary: iterates over all object members skipping members, which
+ // are present in the empty object (IE and/or 3rd-party libraries).
+ o = o || d.global; f = df.lambda(f);
+ for(var i in obj){
+ if(i in empty){ continue; }
+ f.call(o, obj[i], i, obj);
+ }
+ },
+ keys: function(/*Object*/ obj){
+ // summary: returns an array of all keys in the object
+ var t = [];
+ for(var i in obj){
+ if(i in empty){ continue; }
+ t.push(i);
+ }
+ return t; // Array
+ },
+ values: function(/*Object*/ obj){
+ // summary: returns an array of all values in the object
+ var t = [];
+ for(var i in obj){
+ if(i in empty){ continue; }
+ t.push(obj[i]);
+ }
+ return t; // Array
+ }
+ });
+})();
+
+}
diff --git a/includes/js/dojox/lang/functional/reversed.js b/includes/js/dojox/lang/functional/reversed.js
new file mode 100644
index 0000000..4375948
--- /dev/null
+++ b/includes/js/dojox/lang/functional/reversed.js
@@ -0,0 +1,79 @@
+if(!dojo._hasResource["dojox.lang.functional.reversed"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.functional.reversed"] = true;
+dojo.provide("dojox.lang.functional.reversed");
+
+dojo.require("dojox.lang.functional.lambda");
+
+// This module adds high-level functions and related constructs:
+// - reversed versions of array-processing functions similar to standard JS functions
+
+// Notes:
+// - this module provides reversed versions of standard array-processing functions:
+// forEachRev, mapRev, filterRev
+
+// Defined methods:
+// - take any valid lambda argument as the functional argument
+// - operate on dense arrays
+// - take a string as the array argument
+
+(function(){
+ var d = dojo, df = dojox.lang.functional;
+
+ d.mixin(df, {
+ // JS 1.6 standard array functions, which can take a lambda as a parameter.
+ // Consider using dojo._base.array functions, if you don't need the lambda support.
+ filterRev: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+ // summary: creates a new array with all elements that pass the test
+ // implemented by the provided function.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ var t = [], v;
+ for(var i = a.length - 1; i >= 0; --i){
+ v = a[i];
+ if(f.call(o, v, i, a)){ t.push(v); }
+ }
+ return t; // Array
+ },
+ forEachRev: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+ // summary: executes a provided function once per array element.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ for(var i = a.length - 1; i >= 0; f.call(o, a[i], i, a), --i);
+ },
+ mapRev: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+ // summary: creates a new array with the results of calling
+ // a provided function on every element in this array.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ var n = a.length, t = new Array(n);
+ for(var i = n - 1, j = 0; i >= 0; t[j++] = f.call(o, a[i], i, a), --i);
+ return t; // Array
+ },
+ everyRev: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+ // summary: tests whether all elements in the array pass the test
+ // implemented by the provided function.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ for(var i = a.length - 1; i >= 0; --i){
+ if(!f.call(o, a[i], i, a)){
+ return false; // Boolean
+ }
+ }
+ return true; // Boolean
+ },
+ someRev: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+ // summary: tests whether some element in the array passes the test
+ // implemented by the provided function.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ for(var i = a.length - 1; i >= 0; --i){
+ if(f.call(o, a[i], i, a)){
+ return true; // Boolean
+ }
+ }
+ return false; // Boolean
+ }
+ });
+})();
+
+}
diff --git a/includes/js/dojox/lang/functional/scan.js b/includes/js/dojox/lang/functional/scan.js
new file mode 100644
index 0000000..65a3ef2
--- /dev/null
+++ b/includes/js/dojox/lang/functional/scan.js
@@ -0,0 +1,84 @@
+if(!dojo._hasResource["dojox.lang.functional.scan"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.functional.scan"] = true;
+dojo.provide("dojox.lang.functional.scan");
+
+dojo.require("dojox.lang.functional.lambda");
+
+// This module adds high-level functions and related constructs:
+// - "scan" family of functions
+
+// Notes:
+// - missing high-level functions are provided with the compatible API:
+// scanl, scanl1, scanr, scanr1
+
+// Defined methods:
+// - take any valid lambda argument as the functional argument
+// - operate on dense arrays
+// - take a string as the array argument
+// - take an iterator objects as the array argument (only scanl, and scanl1)
+
+(function(){
+ var d = dojo, df = dojox.lang.functional;
+
+ d.mixin(df, {
+ // classic reduce-class functions
+ scanl: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
+ // summary: repeatedly applies a binary function to an array from left
+ // to right using a seed value as a starting point; returns an array
+ // of values produced by foldl() at that point.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ var t, n;
+ if(d.isArray(a)){
+ t = new Array((n = a.length) + 1);
+ t[0] = z;
+ for(var i = 0; i < n; z = f.call(o, z, a[i], i, a), t[++i] = z);
+ }else{
+ t = [z];
+ for(var i = 0; a.hasNext(); t.push(z = f.call(o, z, a.next(), i++)));
+ }
+ return t; // Array
+ },
+ scanl1: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+ // summary: repeatedly applies a binary function to an array from left
+ // to right; returns an array of values produced by foldl1() at that
+ // point.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ var t, n, z;
+ if(d.isArray(a)){
+ t = new Array(n = a.length);
+ t[0] = z = a[0];
+ for(var i = 1; i < n; t[i] = z = f.call(o, z, a[i], i, a), ++i);
+ }else if(a.hasNext()){
+ t = [z = a.next()];
+ for(var i = 1; a.hasNext(); t.push(z = f.call(o, z, a.next(), i++)));
+ }
+ return t; // Array
+ },
+ scanr: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
+ // summary: repeatedly applies a binary function to an array from right
+ // to left using a seed value as a starting point; returns an array
+ // of values produced by foldr() at that point.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ var n = a.length, t = new Array(n + 1);
+ t[n] = z;
+ for(var i = n; i > 0; --i, z = f.call(o, z, a[i], i, a), t[i] = z);
+ return t; // Array
+ },
+ scanr1: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+ // summary: repeatedly applies a binary function to an array from right
+ // to left; returns an array of values produced by foldr1() at that
+ // point.
+ if(typeof a == "string"){ a = a.split(""); }
+ o = o || d.global; f = df.lambda(f);
+ var n = a.length, t = new Array(n), z = a[n - 1];
+ t[n - 1] = z;
+ for(var i = n - 1; i > 0; --i, z = f.call(o, z, a[i], i, a), t[i] = z);
+ return t; // Array
+ }
+ });
+})();
+
+}
diff --git a/includes/js/dojox/lang/functional/sequence.js b/includes/js/dojox/lang/functional/sequence.js
new file mode 100644
index 0000000..c5aaa1c
--- /dev/null
+++ b/includes/js/dojox/lang/functional/sequence.js
@@ -0,0 +1,38 @@
+if(!dojo._hasResource["dojox.lang.functional.sequence"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.functional.sequence"] = true;
+dojo.provide("dojox.lang.functional.sequence");
+
+dojo.require("dojox.lang.functional.lambda");
+
+// This module adds high-level functions and related constructs:
+// - sequence generators
+
+// Defined methods:
+// - take any valid lambda argument as the functional argument
+
+(function(){
+ var d = dojo, df = dojox.lang.functional;
+
+ d.mixin(df, {
+ // sequence generators
+ repeat: function(/*Number*/ n, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
+ // summary: builds an array by repeatedly applying a unary function N times
+ // with a seed value Z.
+ o = o || d.global; f = df.lambda(f);
+ var t = new Array(n);
+ t[0] = z;
+ for(var i = 1; i < n; t[i] = z = f.call(o, z), ++i);
+ return t; // Array
+ },
+ until: function(/*Function|String|Array*/ pr, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
+ // summary: builds an array by repeatedly applying a unary function with
+ // a seed value Z until the predicate is satisfied.
+ o = o || d.global; f = df.lambda(f); pr = df.lambda(pr);
+ var t = [];
+ for(; !pr.call(o, z); t.push(z), z = f.call(o, z));
+ return t; // Array
+ }
+ });
+})();
+
+}
diff --git a/includes/js/dojox/lang/functional/zip.js b/includes/js/dojox/lang/functional/zip.js
new file mode 100644
index 0000000..523f400
--- /dev/null
+++ b/includes/js/dojox/lang/functional/zip.js
@@ -0,0 +1,45 @@
+if(!dojo._hasResource["dojox.lang.functional.zip"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.functional.zip"] = true;
+dojo.provide("dojox.lang.functional.zip");
+
+// This module adds high-level functions and related constructs:
+// - zip combiners
+
+// Defined methods:
+// - operate on dense arrays
+
+(function(){
+ var df = dojox.lang.functional;
+
+ dojo.mixin(df, {
+ // combiners
+ zip: function(){
+ // summary: returns an array of arrays, where the i-th array
+ // contains the i-th element from each of the argument arrays.
+ // description: This is the venerable zip combiner (for example,
+ // see Python documentation for general details). The returned
+ // array is truncated to match the length of the shortest input
+ // array.
+ var n = arguments[0].length, m = arguments.length, i;
+ for(i = 1; i < m; n = Math.min(n, arguments[i++].length));
+ var t = new Array(n), j;
+ for(i = 0; i < n; ++i){
+ var p = new Array(m);
+ for(j = 0; j < m; p[j] = arguments[j][i], ++j);
+ t[i] = p;
+ }
+ return t; // Array
+ },
+ unzip: function(/*Array*/ a){
+ // summary: similar to dojox.lang.functional.zip(), but takes
+ // a single array of arrays as the input.
+ // description: This function is similar to dojox.lang.functional.zip()
+ // and can be used to unzip objects packed by
+ // dojox.lang.functional.zip(). It is here mostly to provide
+ // a short-cut for the different method signature.
+ return df.zip.apply(null, a); // Array
+ }
+ });
+})();
+
+}
diff --git a/includes/js/dojox/lang/tests/array.js b/includes/js/dojox/lang/tests/array.js
new file mode 100644
index 0000000..292210c
--- /dev/null
+++ b/includes/js/dojox/lang/tests/array.js
@@ -0,0 +1,84 @@
+if(!dojo._hasResource["dojox.lang.tests.array"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.tests.array"] = true;
+dojo.provide("dojox.lang.tests.array");
+
+dojo.require("dojox.lang.functional");
+dojo.require("dojox.lang.functional.fold");
+dojo.require("dojox.lang.functional.reversed");
+
+(function(){
+ var df = dojox.lang.functional, v, isOdd = "%2";
+
+ var revArrayIter = function(array){
+ this.array = array;
+ this.position = array.length - 1;
+ };
+ dojo.extend(revArrayIter, {
+ hasNext: df.lambda("this.position >= 0"),
+ next: df.lambda("this.array[this.position--]")
+ });
+
+ tests.register("dojox.lang.tests.array", [
+ function testFilter1(t){ t.assertEqual(df.filter([1, 2, 3], isOdd), [1, 3]); },
+ function testFilter2(t){ t.assertEqual(df.filter([1, 2, 3], "%2==0"), [2]); },
+ function testFilterIter(t){
+ var iter = new revArrayIter([1, 2, 3]);
+ t.assertEqual(df.filter(iter, isOdd), [3, 1]);
+ },
+ function testFilterRev(t){
+ var iter = new revArrayIter([1, 2, 3]);
+ t.assertEqual(df.filter(iter, isOdd), df.filterRev([1, 2, 3], isOdd));
+ },
+
+ function testForEach(t){
+ t.assertEqual((v = [], df.forEach([1, 2, 3], function(x){ v.push(x); }), v), [1, 2, 3]);
+ },
+ function testForEachIter(t){
+ var iter = new revArrayIter([1, 2, 3]);
+ t.assertEqual((v = [], df.forEach(iter, function(x){ v.push(x); }), v), [3, 2, 1]);
+ },
+ function testForEachRev(t){
+ t.assertEqual((v = [], df.forEachRev([1, 2, 3], function(x){ v.push(x); }), v), [3, 2, 1]);
+ },
+
+ function testMap(t){ t.assertEqual(df.map([1, 2, 3], "+3"), [4, 5, 6]); },
+ function testMapIter(t){
+ var iter = new revArrayIter([1, 2, 3]);
+ t.assertEqual(df.map(iter, "+3"), [6, 5, 4]);
+ },
+ function testMapRev(t){
+ var iter = new revArrayIter([1, 2, 3]);
+ t.assertEqual(df.map(iter, "+3"), df.mapRev([1, 2, 3], "+3"));
+ },
+
+ function testEvery1(t){ t.assertFalse(df.every([1, 2, 3], isOdd)); },
+ function testEvery2(t){ t.assertTrue(df.every([1, 3, 5], isOdd)); },
+ function testEveryIter(t){
+ var iter = new revArrayIter([1, 3, 5]);
+ t.assertTrue(df.every(iter, isOdd));
+ },
+ function testEveryRev1(t){ t.assertFalse(df.everyRev([1, 2, 3], isOdd)); },
+ function testEveryRev2(t){ t.assertTrue(df.everyRev([1, 3, 5], isOdd)); },
+
+ function testSome1(t){ t.assertFalse(df.some([2, 4, 6], isOdd)); },
+ function testSome2(t){ t.assertTrue(df.some([1, 2, 3], isOdd)); },
+ function testSomeIter(t){
+ var iter = new revArrayIter([1, 2, 3]);
+ t.assertTrue(df.some(iter, isOdd));
+ },
+ function testSomeRev1(t){ t.assertFalse(df.someRev([2, 4, 6], isOdd)); },
+ function testSomeRev2(t){ t.assertTrue(df.someRev([1, 2, 3], isOdd)); },
+
+ function testReduce1(t){ t.assertEqual(df.reduce([4, 2, 1], "x-y"), 1); },
+ function testReduce2(t){ t.assertEqual(df.reduce([4, 2, 1], "x-y", 8), 1); },
+ function testReduceIter(t){
+ var iter = new revArrayIter([1, 2, 4]);
+ t.assertEqual(df.reduce(iter, "x-y"), 1);
+ },
+
+ function testReduceRight1(t){ t.assertEqual(df.reduceRight([4, 2, 1], "x-y"), -5); },
+ function testReduceRight2(t){ t.assertEqual(df.reduceRight([4, 2, 1], "x-y", 8), 1); }
+ ]);
+})();
+
+}
diff --git a/includes/js/dojox/lang/tests/curry.js b/includes/js/dojox/lang/tests/curry.js
new file mode 100644
index 0000000..cb6fa6a
--- /dev/null
+++ b/includes/js/dojox/lang/tests/curry.js
@@ -0,0 +1,31 @@
+if(!dojo._hasResource["dojox.lang.tests.curry"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.tests.curry"] = true;
+dojo.provide("dojox.lang.tests.curry");
+
+dojo.require("dojox.lang.functional.curry");
+
+(function(){
+ var df = dojox.lang.functional, add5 = df.curry("+")(5), sub3 = df.curry("_-3"), fun = df.lambda("100*a + 10*b + c");
+ tests.register("dojox.lang.tests.curry", [
+ function testCurry1(t){ t.assertEqual(df.curry("+")(1, 2), 3); },
+ function testCurry2(t){ t.assertEqual(df.curry("+")(1)(2), 3); },
+ function testCurry3(t){ t.assertEqual(df.curry("+")(1, 2, 3), 3); },
+ function testCurry4(t){ t.assertEqual(add5(1), 6); },
+ function testCurry5(t){ t.assertEqual(add5(3), 8); },
+ function testCurry6(t){ t.assertEqual(add5(5), 10); },
+ function testCurry7(t){ t.assertEqual(sub3(1), -2); },
+ function testCurry8(t){ t.assertEqual(sub3(3), 0); },
+ function testCurry9(t){ t.assertEqual(sub3(5), 2); },
+
+ function testPartial1(t){ t.assertEqual(df.partial(fun, 1, 2, 3)(), 123); },
+ function testPartial2(t){ t.assertEqual(df.partial(fun, 1, 2, df.arg)(3), 123); },
+ function testPartial3(t){ t.assertEqual(df.partial(fun, 1, df.arg, 3)(2), 123); },
+ function testPartial4(t){ t.assertEqual(df.partial(fun, 1, df.arg, df.arg)(2, 3), 123); },
+ function testPartial5(t){ t.assertEqual(df.partial(fun, df.arg, 2, 3)(1), 123); },
+ function testPartial6(t){ t.assertEqual(df.partial(fun, df.arg, 2, df.arg)(1, 3), 123); },
+ function testPartial7(t){ t.assertEqual(df.partial(fun, df.arg, df.arg, 3)(1, 2), 123); },
+ function testPartial8(t){ t.assertEqual(df.partial(fun, df.arg, df.arg, df.arg)(1, 2, 3), 123); }
+ ]);
+})();
+
+}
diff --git a/includes/js/dojox/lang/tests/fold.js b/includes/js/dojox/lang/tests/fold.js
new file mode 100644
index 0000000..e766c62
--- /dev/null
+++ b/includes/js/dojox/lang/tests/fold.js
@@ -0,0 +1,64 @@
+if(!dojo._hasResource["dojox.lang.tests.fold"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.tests.fold"] = true;
+dojo.provide("dojox.lang.tests.fold");
+
+dojo.require("dojox.lang.functional.fold");
+dojo.require("dojox.lang.functional.scan");
+dojo.require("dojox.lang.functional.curry");
+
+(function(){
+ var df = dojox.lang.functional, a = df.arg;
+
+ var revArrayIter = function(array){
+ this.array = array;
+ this.position = array.length - 1;
+ };
+ dojo.extend(revArrayIter, {
+ hasNext: df.lambda("this.position >= 0"),
+ next: df.lambda("this.array[this.position--]")
+ });
+
+ tests.register("dojox.lang.tests.fold", [
+ function testFoldl1(t){ t.assertEqual(df.foldl([1, 2, 3], "+", 0), 6); },
+ function testFoldl2(t){ t.assertEqual(df.foldl1([1, 2, 3], "*"), 6); },
+ function testFoldl3(t){ t.assertEqual(df.foldl1([1, 2, 3], "/"), 1/6); },
+ function testFoldl4(t){ t.assertEqual(df.foldl1([1, 2, 3], df.partial(Math.max, a, a)), 3); },
+ function testFoldl5(t){ t.assertEqual(df.foldl1([1, 2, 3], df.partial(Math.min, a, a)), 1); },
+
+ function testFoldlIter(t){
+ var iter = new revArrayIter([1, 2, 3]);
+ t.assertEqual(df.foldl(iter, "+", 0), 6);
+ },
+ function testFoldl1Iter(t){
+ var iter = new revArrayIter([1, 2, 3]);
+ t.assertEqual(df.foldl1(iter, "/"), 3/2);
+ },
+
+ function testFoldr1(t){ t.assertEqual(df.foldr([1, 2, 3], "+", 0), 6); },
+ function testFoldr2(t){ t.assertEqual(df.foldr1([1, 2, 3], "*"), 6); },
+ function testFoldr3(t){ t.assertEqual(df.foldr1([1, 2, 3], "/"), 3/2); },
+ function testFoldr4(t){ t.assertEqual(df.foldr1([1, 2, 3], df.partial(Math.max, a, a)), 3); },
+ function testFoldr5(t){ t.assertEqual(df.foldr1([1, 2, 3], df.partial(Math.min, a, a)), 1); },
+
+ function testScanl1(t){ t.assertEqual(df.scanl([1, 2, 3], "+", 0), [0, 1, 3, 6]); },
+ function testScanl2(t){ t.assertEqual(df.scanl1([1, 2, 3], "*"), [1, 2, 6]); },
+ function testScanl3(t){ t.assertEqual(df.scanl1([1, 2, 3], df.partial(Math.max, a, a)), [1, 2, 3]); },
+ function testScanl4(t){ t.assertEqual(df.scanl1([1, 2, 3], df.partial(Math.min, a, a)), [1, 1, 1]); },
+
+ function testScanlIter(t){
+ var iter = new revArrayIter([1, 2, 3]);
+ t.assertEqual(df.scanl(iter, "+", 0), [0, 3, 5, 6]);
+ },
+ function testScanl1Iter(t){
+ var iter = new revArrayIter([1, 2, 3]);
+ t.assertEqual(df.scanl1(iter, "*"), [3, 6, 6]);
+ },
+
+ function testScanr1(t){ t.assertEqual(df.scanr([1, 2, 3], "+", 0), [6, 5, 3, 0]); },
+ function testScanr2(t){ t.assertEqual(df.scanr1([1, 2, 3], "*"), [6, 6, 3]); },
+ function testScanr3(t){ t.assertEqual(df.scanr1([1, 2, 3], df.partial(Math.max, a, a)), [3, 3, 3]); },
+ function testScanr4(t){ t.assertEqual(df.scanr1([1, 2, 3], df.partial(Math.min, a, a)), [1, 2, 3]); }
+ ]);
+})();
+
+}
diff --git a/includes/js/dojox/lang/tests/fun_perf.html b/includes/js/dojox/lang/tests/fun_perf.html
new file mode 100644
index 0000000..9d19a60
--- /dev/null
+++ b/includes/js/dojox/lang/tests/fun_perf.html
@@ -0,0 +1,176 @@
+<html>
+ <head>
+ <title>clocking fun</title>
+ <style type="text/css">
+ @import "../../../dojo/resources/dojo.css";
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true"></script>
+ <script type="text/javascript" src="../functional.js"></script>
+ <script type="text/javascript" src="../functional/sequence.js"></script>
+ <script type="text/javascript" src="../functional/fold.js"></script>
+ <script type="text/javascript">
+ dojo.addOnLoad(function(){
+ var LEN = 2000, ITER = 200, b, e, tests = {},
+ df = dojox.lang.functional,
+ sample = df.repeat(LEN, "+1", 0),
+ add = df.lambda("+"),
+ isOdd = df.lambda("%2");
+
+ var clock = function(body){
+ var b = new Date();
+ body();
+ var e = new Date();
+ return e.getTime() - b.getTime(); // in ms
+ };
+
+ var log = function(name, body){
+ b = new Date();
+ var ms = clock(body);
+ e = new Date();
+ console.log(name + ":", ms);
+ };
+
+ // filter
+ tests["raw filter"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ var t = [];
+ for(var j = 0; j < sample.length; ++j){
+ if(isOdd(sample[j])){ t.push(sample[j]); }
+ }
+ }
+ };
+ tests["dojo.filter"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ dojo.filter(sample, isOdd);
+ }
+ };
+ tests["df.filter"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ df.filter(sample, isOdd);
+ }
+ };
+ if(sample.filter){
+ tests["Array.prototype.filter"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ sample.filter(isOdd);
+ }
+ };
+ }
+
+ // map
+ tests["raw map"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ var t = [];
+ for(var j = 0; j < sample.length; ++j){
+ t.push(isOdd(sample[j]));
+ }
+ }
+ };
+ tests["dojo.map"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ dojo.map(sample, isOdd);
+ }
+ };
+ tests["df.map"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ df.map(sample, isOdd);
+ }
+ };
+ if(sample.map){
+ tests["Array.prototype.map"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ sample.map(isOdd);
+ }
+ };
+ }
+
+ // forEach
+ tests["raw forEach"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ for(var j = 0; j < sample.length; ++j){
+ isOdd(sample[j]);
+ }
+ }
+ };
+ tests["dojo.forEach"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ dojo.forEach(sample, isOdd);
+ }
+ };
+ tests["df.forEach"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ df.forEach(sample, isOdd);
+ }
+ };
+ if(sample.forEach){
+ tests["Array.prototype.forEach"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ sample.forEach(isOdd);
+ }
+ };
+ }
+
+ // reduce
+ tests["raw reduce"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ var z = 0;
+ for(var j = 0; j < sample.length; ++j){
+ z = add(z, sample[j]);
+ }
+ }
+ };
+ tests["df.reduce"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ df.reduce(sample, add, 0);
+ }
+ };
+ if(sample.reduce){
+ tests["Array.prototype.reduce"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ sample.reduce(add, 0);
+ }
+ };
+ }
+
+ // reduceRight
+ tests["raw reduceRight"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ var z = 0;
+ for(var j = sample.length - 1; j >= 0; --j){
+ z = add(z, sample[j]);
+ }
+ }
+ };
+ tests["df.reduceRight"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ df.reduceRight(sample, add, 0);
+ }
+ };
+ if(sample.reduceRight){
+ tests["Array.prototype.reduceRight"] = function(){
+ for(var i = 0; i < ITER; ++i){
+ sample.reduceRight(add, 0);
+ }
+ };
+ }
+
+ var keys = df.keys(tests), i = 0;
+
+ var doTest = function(){
+ log(keys[i], tests[keys[i]]);
+ ++i;
+ if(i < keys.length){
+ setTimeout(doTest, 1);
+ }else{
+ console.log("that's all");
+ }
+ };
+
+ setTimeout(doTest, 1);
+ });
+ </script>
+ </head>
+ <body>
+ <p>This test is meant to run with Firebug.</p>
+ </body>
+</html>
diff --git a/includes/js/dojox/lang/tests/lambda.js b/includes/js/dojox/lang/tests/lambda.js
new file mode 100644
index 0000000..7e5e7ed
--- /dev/null
+++ b/includes/js/dojox/lang/tests/lambda.js
@@ -0,0 +1,24 @@
+if(!dojo._hasResource["dojox.lang.tests.lambda"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.tests.lambda"] = true;
+dojo.provide("dojox.lang.tests.lambda");
+
+dojo.require("dojox.lang.functional");
+dojo.require("dojox.lang.functional.sequence");
+
+(function(){
+ var df = dojox.lang.functional;
+ tests.register("dojox.lang.tests.lambda", [
+ function testLambda1(t){ t.assertEqual(df.repeat(3, "3*", 1), [1, 3, 9]); },
+ function testLambda2(t){ t.assertEqual(df.repeat(3, "*3", 1), [1, 3, 9]); },
+ function testLambda3(t){ t.assertEqual(df.repeat(3, "_*3", 1), [1, 3, 9]); },
+ function testLambda4(t){ t.assertEqual(df.repeat(3, "3*_", 1), [1, 3, 9]); },
+ function testLambda5(t){ t.assertEqual(df.repeat(3, "n->n*3", 1), [1, 3, 9]); },
+ function testLambda6(t){ t.assertEqual(df.repeat(3, "n*3", 1), [1, 3, 9]); },
+ function testLambda7(t){ t.assertEqual(df.repeat(3, "3*m", 1), [1, 3, 9]); },
+ function testLambda8(t){ t.assertEqual(df.repeat(3, "->1", 1), [1, 1, 1]); },
+ function testLambda9(t){ t.assertEqual(df.repeat(3, function(n){ return n * 3; }, 1), [1, 3, 9]); },
+ function testLambda10(t){ t.assertEqual(df.repeat(3, ["_-1", ["*3"]], 1), [1, 2, 5]); }
+ ]);
+})();
+
+}
diff --git a/includes/js/dojox/lang/tests/listcomp.js b/includes/js/dojox/lang/tests/listcomp.js
new file mode 100644
index 0000000..45cd8ab
--- /dev/null
+++ b/includes/js/dojox/lang/tests/listcomp.js
@@ -0,0 +1,28 @@
+if(!dojo._hasResource["dojox.lang.tests.listcomp"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.tests.listcomp"] = true;
+dojo.provide("dojox.lang.tests.listcomp");
+
+dojo.require("dojox.lang.functional.listcomp");
+dojo.require("dojox.lang.functional.sequence");
+
+(function(){
+ var df = dojox.lang.functional;
+ tests.register("dojox.lang.tests.listcomp", [
+ function testIterator1(t){ t.assertEqual(df.repeat(3, function(n){ return n + 1; }, 0), [0, 1, 2]); },
+ function testIterator2(t){ t.assertEqual(df.repeat(3, function(n){ return n * 3; }, 1), [1, 3, 9]); },
+ function testIterator3(t){ t.assertEqual(df.until(function(n){ return n > 10; }, function(n){ return n * 3; }, 1), [1, 3, 9]); },
+
+ function testListcomp1(t){ t.assertEqual(df.listcomp("i for(var i=0; i<3; ++i)"), [0, 1, 2]); },
+ function testListcomp2(t){ t.assertEqual(df.listcomp("i*j for(var i=0; i<3; ++i) for(var j=0; j<3; ++j)"), [0, 0, 0, 0, 1, 2, 0, 2, 4]); },
+ function testListcomp3(t){ t.assertEqual(df.listcomp("i*j for(var i=0; i<3; ++i) if(i%2==1) for(var j=0; j<3; ++j)"), [0, 1, 2]); },
+ function testListcomp4(t){ t.assertEqual(df.listcomp("i+j for(var i=0; i<3; ++i) for(var j=0; j<3; ++j)"), [0, 1, 2, 1, 2, 3, 2, 3, 4]); },
+ function testListcomp5(t){ t.assertEqual(df.listcomp("i+j for(var i=0; i<3; ++i) if(i%2==1) for(var j=0; j<3; ++j)"), [1, 2, 3]); },
+ function testListcomp6(t){ t.assertEqual(df.listcomp("i for(i=0; i<3; ++i)"), [0, 1, 2]); },
+ function testListcomp7(t){ t.assertEqual(df.listcomp("i*j for(i=0; i<3; ++i) for(j=0; j<3; ++j)"), [0, 0, 0, 0, 1, 2, 0, 2, 4]); },
+ function testListcomp8(t){ t.assertEqual(df.listcomp("i*j for(i=0; i<3; ++i) if(i%2==1) for(j=0; j<3; ++j)"), [0, 1, 2]); },
+ function testListcomp9(t){ t.assertEqual(df.listcomp("i+j for(i=0; i<3; ++i) for(j=0; j<3; ++j)"), [0, 1, 2, 1, 2, 3, 2, 3, 4]); },
+ function testListcomp10(t){ t.assertEqual(df.listcomp("i+j for(i=0; i<3; ++i) if(i%2==1) for(j=0; j<3; ++j)"), [1, 2, 3]); }
+ ]);
+})();
+
+}
diff --git a/includes/js/dojox/lang/tests/main.js b/includes/js/dojox/lang/tests/main.js
new file mode 100644
index 0000000..1f0d7ab
--- /dev/null
+++ b/includes/js/dojox/lang/tests/main.js
@@ -0,0 +1,17 @@
+if(!dojo._hasResource["dojox.lang.tests.main"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.tests.main"] = true;
+dojo.provide("dojox.lang.tests.main");
+
+try{
+ // functional block
+ dojo.require("dojox.lang.tests.listcomp");
+ dojo.require("dojox.lang.tests.lambda");
+ dojo.require("dojox.lang.tests.fold");
+ dojo.require("dojox.lang.tests.curry");
+ dojo.require("dojox.lang.tests.misc");
+ dojo.require("dojox.lang.tests.array");
+}catch(e){
+ doh.debug(e);
+}
+
+}
diff --git a/includes/js/dojox/lang/tests/misc.js b/includes/js/dojox/lang/tests/misc.js
new file mode 100644
index 0000000..f17ea8c
--- /dev/null
+++ b/includes/js/dojox/lang/tests/misc.js
@@ -0,0 +1,31 @@
+if(!dojo._hasResource["dojox.lang.tests.misc"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.tests.misc"] = true;
+dojo.provide("dojox.lang.tests.misc");
+
+dojo.require("dojox.lang.functional.object");
+dojo.require("dojox.lang.functional.zip");
+
+(function(){
+ var df = dojox.lang.functional, fun = df.lambda("100*a + 10*b + c"), result = [];
+ df.forIn({a: 1, b: 2}, function(v, i){ result.push("[" + i + "] = " + v); });
+
+ tests.register("dojox.lang.tests.misc", [
+ function testZip1(t){ t.assertEqual(df.zip([1, 2, 3], [4, 5, 6]), [[1, 4], [2, 5], [3, 6]]); },
+ function testZip2(t){ t.assertEqual(df.zip([1, 2], [3, 4], [5, 6]), [[1, 3, 5], [2, 4, 6]]); },
+
+ function testUnzip1(t){ t.assertEqual(df.unzip([[1, 4], [2, 5], [3, 6]]), [[1, 2, 3], [4, 5, 6]]); },
+ function testUnzip2(t){ t.assertEqual(df.unzip([[1, 3, 5], [2, 4, 6]]), [[1, 2], [3, 4], [5, 6]]); },
+
+ function testMixer(t){ t.assertEqual(df.mixer(fun, [1, 2, 0])(3, 1, 2), 123); },
+ function testFlip(t){ t.assertEqual(df.flip(fun)(3, 2, 1), 123); },
+
+ function testCompose1(t){ t.assertEqual(df.lambda(["+5", "*3"])(8), 8 * 3 + 5); },
+ function testCompose2(t){ t.assertEqual(df.lambda(["+5", "*3"].reverse())(8), (8 + 5) * 3); },
+
+ function testForIn(t){ t.assertEqual(result.sort().join(", "), "[a] = 1, [b] = 2"); },
+ function testKeys(t){ t.assertEqual(df.keys({a: 1, b: 2, c: 3}), ["a", "b", "c"]); },
+ function testValues(t){ t.assertEqual(df.values({a: 1, b: 2, c: 3}), [1, 2, 3]); }
+ ]);
+})();
+
+}
diff --git a/includes/js/dojox/lang/tests/runTests.html b/includes/js/dojox/lang/tests/runTests.html
new file mode 100644
index 0000000..32fdfdb
--- /dev/null
+++ b/includes/js/dojox/lang/tests/runTests.html
@@ -0,0 +1,9 @@
+<html>
+ <head>
+ <title>DojoX Functional Unit Test Runner</title>
+ <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.lang.tests.main" />
+ </head>
+ <body>
+ <p>Redirecting to D.O.H runner.</p>
+ </body>
+</html>
diff --git a/includes/js/dojox/lang/utils.js b/includes/js/dojox/lang/utils.js
new file mode 100644
index 0000000..b7926c6
--- /dev/null
+++ b/includes/js/dojox/lang/utils.js
@@ -0,0 +1,54 @@
+if(!dojo._hasResource["dojox.lang.utils"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.lang.utils"] = true;
+dojo.provide("dojox.lang.utils");
+
+(function(){
+ var empty = {}, du = dojox.lang.utils;
+
+ dojo.mixin(dojox.lang.utils, {
+ coerceType: function(target, source){
+ switch(typeof target){
+ case "number": return Number(eval("(" + source + ")"));
+ case "string": return String(source);
+ case "boolean": return Boolean(eval("(" + source + ")"));
+ }
+ return eval("(" + source + ")");
+ },
+
+ updateWithObject: function(target, source, conv){
+ // summary: updates an existing object in place with properties from an "source" object.
+ // target: Object: the "target" object to be updated
+ // source: Object: the "source" object, whose properties will be used to source the existed object.
+ // conv: Boolean?: force conversion to the original type
+ if(!source){ return target; }
+ for(var x in target){
+ if(x in source && !(x in empty)){
+ var t = target[x];
+ if(t && typeof t == "object"){
+ du.updateObject(t, source[x]);
+ }else{
+ target[x] = conv ? du.coerceType(t, source[x]) : dojo.clone(source[x]);
+ }
+ }
+ }
+ return target; // Object
+ },
+
+ updateWithPattern: function(target, source, pattern, conv){
+ // summary: updates an existing object in place with properties from an "source" object.
+ // target: Object: the "target" object to be updated
+ // source: Object: the "source" object, whose properties will be used to source the existed object.
+ // pattern: Array: an array of properties to be copied
+ // conv: Boolean?: force conversion to the original type
+ if(!source || !pattern){ return target; }
+ for(var x in pattern){
+ if(x in source && !(x in empty)){
+ target[x] = conv ? du.coerceType(pattern[x], source[x]) : dojo.clone(source[x]);
+ }
+ }
+ return target; // Object
+ }
+ });
+})();
+
+}