diff options
Diffstat (limited to 'includes/js/dojox/lang')
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 + } + }); +})(); + +} |