-// timestamp: Tue, 01 May 2007 19:13:00\r
-/*\r
- base2.js - copyright 2007, Dean Edwards\r
- http://www.opensource.org/licenses/mit-license\r
-*/\r
-\r
-var base2 = {};\r
-\r
-// You know, writing a javascript library is awfully time consuming.\r
-\r
-new function(_) { //////////////////// BEGIN: CLOSURE ////////////////////\r
-\r
-// =========================================================================\r
-// base2/Base.js\r
-// =========================================================================\r
-\r
-// version 1.1\r
-\r
-var Base = function() {\r
- // call this method from any other method to invoke that method's ancestor\r
-};\r
-\r
-Base.prototype = { \r
- extend: function(source) {\r
- if (arguments.length > 1) { // extending with a name/value pair\r
- var ancestor = this[source];\r
- var value = arguments[1];\r
- if (typeof value == "function" && ancestor && /\bbase\b/.test(value)) {\r
- var method = value; \r
- value = function() { // override\r
- var previous = this.base;\r
- this.base = ancestor;\r
- var returnValue = method.apply(this, arguments);\r
- this.base = previous;\r
- return returnValue;\r
- };\r
- value.method = method;\r
- value.ancestor = ancestor;\r
- }\r
- this[source] = value;\r
- } else if (source) { // extending with an object literal\r
- var extend = Base.prototype.extend;\r
- if (Base._prototyping) {\r
- var key, i = 0, members = ["constructor", "toString", "valueOf"];\r
- while (key = members[i++]) if (source[key] != Object.prototype[key]) {\r
- extend.call(this, key, source[key]);\r
- }\r
- } else if (typeof this != "function") {\r
- // if the object has a customised extend() method then use it\r
- extend = this.extend || extend;\r
- } \r
- // copy each of the source object's properties to this object\r
- for (key in source) if (!Object.prototype[key]) {\r
- extend.call(this, key, source[key]);\r
- }\r
- }\r
- return this;\r
- },\r
-\r
- base: Base\r
-};\r
-\r
-Base.extend = function(_instance, _static) { // subclass\r
- var extend = Base.prototype.extend;\r
- \r
- // build the prototype\r
- Base._prototyping = true;\r
- var proto = new this;\r
- extend.call(proto, _instance);\r
- delete Base._prototyping;\r
- \r
- // create the wrapper for the constructor function\r
- var constructor = proto.constructor;\r
- var klass = proto.constructor = function() {\r
- if (!Base._prototyping) {\r
- if (this._constructing || this.constructor == klass) { // instantiation\r
- this._constructing = true;\r
- constructor.apply(this, arguments);\r
- delete this._constructing;\r
- } else { // casting\r
- var object = arguments[0];\r
- if (object != null) {\r
- (object.extend || extend).call(object, proto);\r
- }\r
- return object;\r
- }\r
- }\r
- };\r
- \r
- // build the class interface\r
- for (var i in Base) klass[i] = this[i];\r
- klass.ancestor = this;\r
- klass.base = Base.base;\r
- klass.prototype = proto;\r
- klass.toString = this.toString;\r
- extend.call(klass, _static);\r
- // class initialisation\r
- if (typeof klass.init == "function") klass.init();\r
- return klass;\r
-};\r
-\r
-// initialise\r
-Base = Base.extend({\r
- constructor: function() {\r
- this.extend(arguments[0]);\r
- }\r
-}, {\r
- ancestor: Object,\r
- base: Base,\r
- \r
- implement: function(_interface) {\r
- if (typeof _interface == "function") {\r
- // if it's a function, call it\r
- _interface(this.prototype);\r
- } else {\r
- // add the interface using the extend() method\r
- this.prototype.extend(_interface);\r
- }\r
- return this;\r
- }\r
-});\r
-\r
-// =========================================================================\r
-// lang/main.js\r
-// =========================================================================\r
-\r
-var Legacy = typeof $Legacy == "undefined" ? {} : $Legacy;\r
-\r
-var K = function(k) {return k};\r
-\r
-var assert = function(condition, message, Err) {\r
- if (!condition) {\r
- throw new (Err || Error)(message || "Assertion failed.");\r
- }\r
-};\r
-\r
-var assertType = function(object, type, message) {\r
- if (type) {\r
- var condition = typeof type == "function" ? instanceOf(object, type) : typeof object == type;\r
- assert(condition, message || "Invalid type.", TypeError);\r
- }\r
-};\r
-\r
-var copy = function(object) {\r
- var fn = new Function;\r
- fn.prototype = object;\r
- return new fn;\r
-};\r
-\r
-var format = function(string) {\r
- // replace %n with arguments[n]\r
- // e.g. format("%1 %2%3 %2a %1%3", "she", "se", "lls");\r
- // ==> "she sells sea shells"\r
- // only supports nine replacements: %1 - %9\r
- var args = arguments;\r
- return String(string).replace(/%([1-9])/g, function(match, index) {\r
- return index < args.length ? args[index] : match;\r
- });\r
-};\r
-\r
-var $instanceOf = Legacy.instanceOf || new Function("o,k", "return o instanceof k");\r
-var instanceOf = function(object, klass) {\r
- assertType(klass, "function", "Invalid 'instanceOf' operand.");\r
- if ($instanceOf(object, klass)) return true;\r
- // handle exceptions where the target object originates from another frame\r
- // this is handy for JSON parsing (amongst other things)\r
- if (object != null) switch (klass) {\r
- case Object:\r
- return true;\r
- case Number:\r
- case Boolean:\r
- case Function:\r
- case String:\r
- return typeof object == typeof klass.prototype.valueOf();\r
- case Array:\r
- // this is the only troublesome one\r
- return !!(object.join && object.splice && !arguments.callee(object, Function));\r
- case Date:\r
- return !!object.getTimezoneOffset;\r
- case RegExp:\r
- return String(object.constructor.prototype) == String(new RegExp);\r
- }\r
- return false;\r
-};\r
- \r
-var match = function(string, expression) {\r
- // same as String.match() except that this function will return an empty \r
- // array if there is no match\r
- return String(string).match(expression) || [];\r
-};\r
-\r
-var RESCAPE = /([\/()[\]{}|*+-.,^$?\\])/g;\r
-var rescape = function(string) {\r
- // make a string safe for creating a RegExp\r
- return String(string).replace(RESCAPE, "\\$1");\r
-};\r
-\r
-var $slice = Array.prototype.slice;\r
-var slice = function(object) {\r
- // slice an array-like object\r
- return $slice.apply(object, $slice.call(arguments, 1));\r
-};\r
-\r
-var TRIM = /^\s+|\s+$/g;\r
-var trim = function(string) {\r
- return String(string).replace(TRIM, ""); \r
-};\r
-\r
-// =========================================================================\r
-// lang/extend.js\r
-// =========================================================================\r
-\r
-var base = function(object, args) {\r
- // invoke the base method with all supplied arguments\r
- return object.base.apply(object, args);\r
-};\r
-\r
-var extend = function(object) {\r
- assert(object != Object.prototype, "Object.prototype is verboten!");\r
- return Base.prototype.extend.apply(object, slice(arguments, 1));\r
-};\r
-\r
-// =========================================================================\r
-// lang/assignID.js\r
-// =========================================================================\r
-\r
-var $ID = 1;\r
-var assignID = function(object) {\r
- // assign a unique id\r
- if (!object.base2ID) object.base2ID = "b2_" + $ID++;\r
- return object.base2ID;\r
-};\r
-\r
-// =========================================================================\r
-// lang/forEach.js\r
-// =========================================================================\r
-\r
-if (typeof StopIteration == "undefined") {\r
- StopIteration = new Error("StopIteration");\r
-}\r
-\r
-var forEach = function(object, block, context) {\r
- if (object == null) return;\r
- if (typeof object == "function") {\r
- // functions are a special case\r
- var fn = Function;\r
- } else if (typeof object.forEach == "function" && object.forEach != arguments.callee) {\r
- // the object implements a custom forEach method\r
- object.forEach(block, context);\r
- return;\r
- } else if (typeof object.length == "number") {\r
- // the object is array-like\r
- forEach.Array(object, block, context);\r
- return;\r
- }\r
- forEach.Function(fn || Object, object, block, context);\r
-};\r
-\r
-// these are the two core enumeration methods. all other forEach methods\r
-// eventually call one of these two.\r
-\r
-forEach.Array = function(array, block, context) {\r
- var i, length = array.length; // preserve\r
- if (typeof array == "string") {\r
- for (i = 0; i < length; i++) {\r
- block.call(context, array.charAt(i), i, array);\r
- }\r
- } else {\r
- for (i = 0; i < length; i++) {\r
- block.call(context, array[i], i, array);\r
- }\r
- }\r
-};\r
-\r
-forEach.Function = Legacy.forEach || function(fn, object, block, context) {\r
- // enumerate an object and compare its keys with fn's prototype\r
- for (var key in object) {\r
- if (fn.prototype[key] === undefined) {\r
- block.call(context, object[key], key, object);\r
- }\r
- }\r
-};\r
-\r
-// =========================================================================\r
-// base2/Base/forEach.js\r
-// =========================================================================\r
-\r
-Base.forEach = function(object, block, context) {\r
- forEach.Function(this, object, block, context);\r
-};\r
-\r
-// =========================================================================\r
-// base2/../Function.js\r
-// =========================================================================\r
-\r
-// some browsers don't define this\r
-\r
-Function.prototype.prototype = {};\r
-\r
-\r
-// =========================================================================\r
-// base2/../String.js\r
-// =========================================================================\r
-\r
-// fix String.replace (Safari/IE5.0)\r
-\r
-if ("".replace(/^/, String)) {\r
- extend(String.prototype, "replace", function(expression, replacement) {\r
- if (typeof replacement == "function") { // Safari doesn't like functions\r
- if (instanceOf(expression, RegExp)) {\r
- var regexp = expression;\r
- var global = regexp.global;\r
- if (global == null) global = /(g|gi)$/.test(regexp);\r
- // we have to convert global RexpExps for exec() to work consistently\r
- if (global) regexp = new RegExp(regexp.source); // non-global\r
- } else {\r
- regexp = new RegExp(rescape(expression));\r
- }\r
- var match, string = this, result = "";\r
- while (string && (match = regexp.exec(string))) {\r
- result += string.slice(0, match.index) + replacement.apply(this, match);\r
- string = string.slice(match.index + match[0].length);\r
- if (!global) break;\r
- }\r
- return result + string;\r
- } else {\r
- return base(this, arguments);\r
- }\r
- });\r
-}\r
-\r
-// =========================================================================\r
-// base2/Abstract.js\r
-// =========================================================================\r
-\r
-var Abstract = Base.extend({\r
- constructor: function() {\r
- throw new TypeError("Class cannot be instantiated.");\r
- }\r
-});\r
-\r
-// =========================================================================\r
-// base2/Module.js\r
-// =========================================================================\r
-\r
-// based on ruby's Module class and Mozilla's Array generics:\r
-// http://www.ruby-doc.org/core/classes/Module.html\r
-// http://developer.mozilla.org/en/docs/New_in_JavaScript_1.6#Array_and_String_generics\r
-\r
-// A Module is used as the basis for creating interfaces that can be\r
-// applied to other classes. *All* properties and methods are static.\r
-// When a module is used as a mixin, methods defined on what would normally be\r
-// the instance interface become instance methods of the target object.\r
-\r
-// Modules cannot be instantiated. Static properties and methods are inherited.\r
-\r
-var Module = Abstract.extend(null, {\r
- extend: function(_interface, _static) {\r
- // extend a module to create a new module\r
- var module = this.base();\r
- // inherit static methods\r
- forEach (this, function(property, name) {\r
- if (!Module[name] && name != "init") {\r
- extend(module, name, property);\r
- }\r
- });\r
- // implement module (instance AND static) methods\r
- module.implement(_interface);\r
- // implement static properties and methods\r
- extend(module, _static);\r
- // Make the submarine noises Larry!\r
- if (typeof module.init == "function") module.init();\r
- return module;\r
- },\r
- \r
- implement: function(_interface) {\r
- // implement an interface on BOTH the instance and static interfaces\r
- var module = this;\r
- if (typeof _interface == "function") {\r
- module.base(_interface);\r
- forEach (_interface, function(property, name) {\r
- if (!Module[name] && name != "init") {\r
- extend(module, name, property);\r
- }\r
- });\r
- } else {\r
- // create the instance interface\r
- Base.forEach (extend({}, _interface), function(property, name) {\r
- // instance methods call the equivalent static method\r
- if (typeof property == "function") {\r
- property = function() {\r
- base; // force inheritance\r
- return module[name].apply(module, [this].concat(slice(arguments)));\r
- };\r
- }\r
- if (!Module[name]) extend(this, name, property);\r
- }, module.prototype);\r
- // add the static interface\r
- extend(module, _interface);\r
- }\r
- return module;\r
- }\r
-});\r
-\r
-\r
-// =========================================================================\r
-// base2/Enumerable.js\r
-// =========================================================================\r
-\r
-var Enumerable = Module.extend({\r
- every: function(object, test, context) {\r
- var result = true;\r
- try {\r
- this.forEach (object, function(value, key) {\r
- result = test.call(context, value, key, object);\r
- if (!result) throw StopIteration;\r
- });\r
- } catch (error) {\r
- if (error != StopIteration) throw error;\r
- }\r
- return !!result; // cast to boolean\r
- },\r
- \r
- filter: function(object, test, context) {\r
- return this.reduce(object, function(result, value, key) {\r
- if (test.call(context, value, key, object)) {\r
- result[result.length] = value;\r
- }\r
- return result;\r
- }, new Array2);\r
- },\r
-\r
- invoke: function(object, method) {\r
- // apply a method to each item in the enumerated object\r
- var args = slice(arguments, 2);\r
- return this.map(object, (typeof method == "function") ? function(item) {\r
- if (item != null) return method.apply(item, args);\r
- } : function(item) {\r
- if (item != null) return item[method].apply(item, args);\r
- });\r
- },\r
- \r
- map: function(object, block, context) {\r
- var result = new Array2;\r
- this.forEach (object, function(value, key) {\r
- result[result.length] = block.call(context, value, key, object);\r
- });\r
- return result;\r
- },\r
- \r
- pluck: function(object, key) {\r
- return this.map(object, function(item) {\r
- if (item != null) return item[key];\r
- });\r
- },\r
- \r
- reduce: function(object, block, result, context) {\r
- this.forEach (object, function(value, key) {\r
- result = block.call(context, result, value, key, object);\r
- });\r
- return result;\r
- },\r
- \r
- some: function(object, test, context) {\r
- return !this.every(object, function(value, key) {\r
- return !test.call(context, value, key, object);\r
- });\r
- }\r
-}, {\r
- forEach: forEach\r
-});\r
-\r
-// =========================================================================\r
-// base2/Array2.js\r
-// =========================================================================\r
-\r
-// The IArray module implements all Array methods.\r
-// This module is not public but its methods are accessible through the Array2 object (below). \r
-\r
-var IArray = Module.extend({\r
- combine: function(keys, values) {\r
- // combine two arrays to make a hash\r
- if (!values) values = keys;\r
- return this.reduce(keys, function(object, key, index) {\r
- object[key] = values[index];\r
- return object;\r
- }, {});\r
- },\r
- \r
- copy: function(array) {\r
- return this.concat(array);\r
- },\r
- \r
- contains: function(array, item) {\r
- return this.indexOf(array, item) != -1;\r
- },\r
- \r
- forEach: forEach.Array,\r
- \r
- indexOf: function(array, item, fromIndex) {\r
- var length = array.length;\r
- if (fromIndex == null) {\r
- fromIndex = 0;\r
- } else if (fromIndex < 0) {\r
- fromIndex = Math.max(0, length + fromIndex);\r
- }\r
- for (var i = fromIndex; i < length; i++) {\r
- if (array[i] === item) return i;\r
- }\r
- return -1;\r
- },\r
- \r
- insertAt: function(array, item, index) {\r
- this.splice(array, index, 0, item);\r
- return item;\r
- },\r
- \r
- insertBefore: function(array, item, before) {\r
- var index = this.indexOf(array, before);\r
- if (index == -1) this.push(array, item);\r
- else this.splice(array, index, 0, item);\r
- return item;\r
- },\r
- \r
- lastIndexOf: function(array, item, fromIndex) {\r
- var length = array.length;\r
- if (fromIndex == null) {\r
- fromIndex = length - 1;\r
- } else if (from < 0) {\r
- fromIndex = Math.max(0, length + fromIndex);\r
- }\r
- for (var i = fromIndex; i >= 0; i--) {\r
- if (array[i] === item) return i;\r
- }\r
- return -1;\r
- },\r
- \r
- remove: function(array, item) {\r
- var index = this.indexOf(array, item);\r
- if (index != -1) this.removeAt(array, index);\r
- return item;\r
- },\r
- \r
- removeAt: function(array, index) {\r
- var item = array[index];\r
- this.splice(array, index, 1);\r
- return item;\r
- }\r
-});\r
-\r
-IArray.prototype.forEach = function(block, context) {\r
- forEach.Array(this, block, context);\r
-};\r
-\r
-IArray.implement(Enumerable);\r
-\r
-forEach ("concat,join,pop,push,reverse,shift,slice,sort,splice,unshift".split(","), function(name) {\r
- IArray[name] = function(array) {\r
- return Array.prototype[name].apply(array, slice(arguments, 1));\r
- };\r
-});\r
-\r
-// create a faux constructor that augments the built-in Array object\r
-var Array2 = function() {\r
- return IArray(this.constructor == IArray ? Array.apply(null, arguments) : arguments[0]);\r
-};\r
-// expose IArray.prototype so that it can be extended\r
-Array2.prototype = IArray.prototype;\r
-\r
-forEach (IArray, function(method, name, proto) {\r
- if (Array[name]) {\r
- IArray[name] = Array[name];\r
- delete IArray.prototype[name];\r
- }\r
- Array2[name] = IArray[name];\r
-});\r
-\r
-// =========================================================================\r
-// base2/Hash.js\r
-// =========================================================================\r
-\r
-var HASH = "#" + Number(new Date);\r
-var KEYS = HASH + "keys";\r
-var VALUES = HASH + "values";\r
-\r
-var Hash = Base.extend({\r
- constructor: function(values) {\r
- this[KEYS] = new Array2;\r
- this[VALUES] = {};\r
- this.merge(values);\r
- },\r
-\r
- copy: function() {\r
- var copy = new this.constructor(this);\r
- Base.forEach (this, function(property, name) {\r
- if (typeof property != "function" && name.charAt(0) != "#") {\r
- copy[name] = property;\r
- }\r
- });\r
- return copy;\r
- },\r
-\r
- // ancient browsers throw an error when we use "in" as an operator \r
- // so we must create the function dynamically\r
- exists: Legacy.exists || new Function("k", format("return('%1'+k)in this['%2']", HASH, VALUES)),\r
-\r
- fetch: function(key) {\r
- return this[VALUES][HASH + key];\r
- },\r
-\r
- forEach: function(block, context) {\r
- forEach (this[KEYS], function(key) {\r
- block.call(context, this.fetch(key), key, this);\r
- }, this);\r
- },\r
-\r
- keys: function(index, length) {\r
- var keys = this[KEYS] || new Array2;\r
- switch (arguments.length) {\r
- case 0: return keys.copy();\r
- case 1: return keys[index];\r
- default: return keys.slice(index, length);\r
- }\r
- },\r
-\r
- merge: function(values) {\r
- forEach (arguments, function(values) {\r
- forEach (values, function(value, key) {\r
- this.store(key, value);\r
- }, this);\r
- }, this);\r
- return this;\r
- },\r
-\r
- remove: function(key) {\r
- var value = this.fetch(key);\r
- this[KEYS].remove(String(key));\r
- delete this[VALUES][HASH + key];\r
- return value;\r
- },\r
-\r
- store: function(key, value) {\r
- if (arguments.length == 1) value = key;\r
- // only store the key for a new entry\r
- if (!this.exists(key)) {\r
- this[KEYS].push(String(key));\r
- }\r
- // create the new entry (or overwrite the old entry)\r
- this[VALUES][HASH + key] = value;\r
- return value;\r
- },\r
-\r
- toString: function() {\r
- return String(this[KEYS]);\r
- },\r
-\r
- union: function(values) {\r
- return this.merge.apply(this.copy(), arguments);\r
- },\r
-\r
- values: function(index, length) {\r
- var values = this.map(K);\r
- switch (arguments.length) {\r
- case 0: return values;\r
- case 1: return values[index];\r
- default: return values.slice(index, length);\r
- }\r
- }\r
-});\r
-\r
-Hash.implement(Enumerable);\r
-\r
-// =========================================================================\r
-// base2/Collection.js\r
-// =========================================================================\r
-\r
-// A Hash that is more array-like (accessible by index).\r
-\r
-// Collection classes have a special (optional) property: Item\r
-// The Item property points to a constructor function.\r
-// Members of the collection must be an instance of Item.\r
-// e.g.\r
-// var Dates = Collection.extend(); // create a collection class\r
-// Dates.Item = Date; // only JavaScript Date objects allowed as members\r
-// var appointments = new Dates(); // instantiate the class\r
-// appointments.add(appointmentId, new Date); // add a date\r
-// appointments.add(appointmentId, "tomorrow"); // ERROR!\r
-\r
-// The static create() method is responsible for all construction of collection items.\r
-// Instance methods that add new items (add, store, insertAt, replaceAt) pass *all* of their arguments\r
-// to the static create() method. If you want to modify the way collection items are \r
-// created then you only need to override this method for custom collections.\r
-\r
-var Collection = Hash.extend({\r
- add: function(key, item) {\r
- // Duplicates not allowed using add().\r
- // - but you can still overwrite entries using store()\r
- assert(!this.exists(key), "Duplicate key.");\r
- return this.store.apply(this, arguments);\r
- },\r
-\r
- count: function() {\r
- return this[KEYS].length;\r
- },\r
-\r
- indexOf: function(key) {\r
- return this[KEYS].indexOf(String(key));\r
- },\r
-\r
- insertAt: function(index, key, item) {\r
- assert(!this.exists(key), "Duplicate key.");\r
- this[KEYS].insertAt(index, String(key));\r
- return this.store.apply(this, slice(arguments, 1));\r
- },\r
-\r
- item: function(index) {\r
- return this.fetch(this[KEYS][index]);\r
- },\r
-\r
- removeAt: function(index) {\r
- return this.remove(this[KEYS][index]);\r
- },\r
-\r
- reverse: function() {\r
- this[KEYS].reverse();\r
- return this;\r
- },\r
-\r
- sort: function(compare) {\r
- if (compare) {\r
- var self = this;\r
- this[KEYS].sort(function(key1, key2) {\r
- return compare(self.fetch(key1), self.fetch(key2), key1, key2);\r
- });\r
- } else this[KEYS].sort();\r
- return this;\r
- },\r
-\r
- store: function(key, item) {\r
- if (arguments.length == 1) item = key;\r
- item = this.constructor.create.apply(this.constructor, arguments);\r
- return this.base(key, item);\r
- },\r
-\r
- storeAt: function(index, item) {\r
- //-dean: get rid of this?\r
- assert(index < this.count(), "Index out of bounds.");\r
- arguments[0] = this[KEYS][index];\r
- return this.store.apply(this, arguments);\r
- }\r
-}, {\r
- Item: null, // if specified, all members of the Collection must be instances of Item\r
- \r
- create: function(key, item) {\r
- if (this.Item && !instanceOf(item, this.Item)) {\r
- item = new this.Item(key, item);\r
- }\r
- return item;\r
- },\r
- \r
- extend: function(_instance, _static) {\r
- var klass = this.base(_instance);\r
- klass.create = this.create;\r
- extend(klass, _static);\r
- if (!klass.Item) {\r
- klass.Item = this.Item;\r
- } else if (typeof klass.Item != "function") {\r
- klass.Item = (this.Item || Base).extend(klass.Item);\r
- }\r
- if (typeof klass.init == "function") klass.init();\r
- return klass;\r
- }\r
-});\r
-\r
-// =========================================================================\r
-// base2/RegGrp.js\r
-// =========================================================================\r
-\r
-var RegGrp = Collection.extend({\r
- constructor: function(values, flags) {\r
- this.base(values);\r
- if (typeof flags == "string") {\r
- this.global = /g/.test(flags);\r
- this.ignoreCase = /i/.test(flags);\r
- }\r
- },\r
-\r
- global: true, // global is the default setting\r
- ignoreCase: false,\r
-\r
- exec: function(string, replacement) {\r
- if (arguments.length == 1) {\r
- var keys = this[KEYS];\r
- var values = this[VALUES];\r
- replacement = function(match) {\r
- if (!match) return "";\r
- var offset = 1, i = 0;\r
- // loop through the values\r
- while (match = values[HASH + keys[i++]]) {\r
- // do we have a result?\r
- if (arguments[offset]) {\r
- var replacement = match.replacement;\r
- switch (typeof replacement) {\r
- case "function":\r
- return replacement.apply(null, slice(arguments, offset));\r
- case "number":\r
- return arguments[offset + replacement];\r
- default:\r
- return replacement;\r
- }\r
- // no? then skip over references to sub-expressions\r
- } else offset += match.length + 1;\r
- }\r
- };\r
- }\r
- var flags = (this.global ? "g" : "") + (this.ignoreCase ? "i" : "");\r
- return String(string).replace(new RegExp(this, flags), replacement);\r
- },\r
-\r
- test: function(string) {\r
- return this.exec(string) != string;\r
- },\r
- \r
- toString: function() {\r
- var length = 0;\r
- return "(" + this.map(function(item) {\r
- // fix back references\r
- var expression = String(item).replace(/\\(\d+)/g, function($, index) {\r
- return "\\" + (1 + Number(index) + length);\r
- });\r
- length += item.length + 1;\r
- return expression;\r
- }).join(")|(") + ")";\r
- }\r
-}, {\r
- IGNORE: "$0",\r
- \r
- init: function() {\r
- forEach ("add,exists,fetch,remove,store".split(","), function(name) {\r
- extend(this, name, function(expression) {\r
- if (instanceOf(expression, RegExp)) {\r
- expression = expression.source;\r
- }\r
- return base(this, arguments);\r
- });\r
- }, this.prototype);\r
- }\r
-});\r
-\r
-// =========================================================================\r
-// base2/RegGrp/Item.js\r
-// =========================================================================\r
-\r
-RegGrp.Item = Base.extend({\r
- constructor: function(expression, replacement) {\r
- var ESCAPE = /\\./g;\r
- var STRING = /(['"])\1\+(.*)\+\1\1$/;\r
- \r
- expression = instanceOf(expression, RegExp) ? expression.source : String(expression);\r
- \r
- if (typeof replacement == "number") replacement = String(replacement);\r
- else if (replacement == null) replacement = "";\r
- \r
- // count the number of sub-expressions\r
- // - add one because each pattern is itself a sub-expression\r
- this.length = match(expression.replace(ESCAPE, "").replace(/\[[^\]]+\]/g, ""), /\(/g).length;\r
- \r
- // does the pattern use sub-expressions?\r
- if (typeof replacement == "string" && /\$(\d+)/.test(replacement)) {\r
- // a simple lookup? (e.g. "$2")\r
- if (/^\$\d+$/.test(replacement)) {\r
- // store the index (used for fast retrieval of matched strings)\r
- replacement = parseInt(replacement.slice(1));\r
- } else { // a complicated lookup (e.g. "Hello $2 $1")\r
- // build a function to do the lookup\r
- var i = this.length + 1;\r
- var Q = /'/.test(replacement.replace(ESCAPE, "")) ? '"' : "'";\r
- replacement = replacement.replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\$(\d+)/g, Q +\r
- "+(arguments[$1]||" + Q+Q + ")+" + Q);\r
- replacement = new Function("return " + Q + replacement.replace(STRING, "$1") + Q);\r
- }\r
- }\r
- this.replacement = replacement;\r
- this.toString = function() {\r
- return expression || "";\r
- };\r
- },\r
- \r
- length: 0,\r
- replacement: ""\r
-});\r
-\r
-// =========================================================================\r
-// base2/Namespace.js\r
-// =========================================================================\r
-\r
-var Namespace = Base.extend({\r
- constructor: function(_private, _public) {\r
- this.extend(_public);\r
- this.toString = function() {\r
- return format("[base2.%1]", this.name);\r
- };\r
- \r
- // initialise\r
- if (typeof this.init == "function") this.init();\r
- \r
- if (this.name != "base2") {\r
- this.namespace = format("var %1=base2.%1;", this.name);\r
- }\r
- \r
- var namespace = "var base=" + base + ";";\r
- var imports = ("base2,lang," + this.imports).split(",");\r
- _private.imports = Enumerable.reduce(imports, function(namespace, name) {\r
- if (base2[name]) namespace += base2[name].namespace;\r
- return namespace;\r
- }, namespace);\r
- \r
- var namespace = format("base2.%1=%1;", this.name);\r
- var exports = this.exports.split(",");\r
- _private.exports = Enumerable.reduce(exports, function(namespace, name) {\r
- if (name) {\r
- this.namespace += format("var %2=%1.%2;", this.name, name);\r
- namespace += format("if(!%1.%2)%1.%2=%2;base2.%2=%1.%2;", this.name, name);\r
- }\r
- return namespace;\r
- }, namespace, this);\r
- \r
- if (this.name != "base2") {\r
- base2.namespace += format("var %1=base2.%1;", this.name);\r
- }\r
- },\r
-\r
- exports: "",\r
- imports: "",\r
- namespace: "",\r
- name: ""\r
-});\r
-\r
-base2 = new Namespace(this, {\r
- name: "base2",\r
- version: "0.8 (alpha)",\r
- exports: "Base,Abstract,Module,Enumerable,Array2,Hash,Collection,RegGrp,Namespace"\r
-});\r
-\r
-base2.toString = function() {\r
- return "[base2]";\r
-};\r
-\r
-eval(this.exports);\r
-\r
-// =========================================================================\r
-// base2/lang/namespace.js\r
-// =========================================================================\r
-\r
-var lang = new Namespace(this, {\r
- name: "lang",\r
- version: base2.version,\r
- exports: "K,assert,assertType,assignID,copy,instanceOf,extend,format,forEach,match,rescape,slice,trim",\r
- \r
- init: function() {\r
- this.extend = extend;\r
- // add the Enumerable methods to the lang object\r
- forEach (Enumerable.prototype, function(method, name) {\r
- if (!Module[name]) {\r
- this[name] = function() {\r
- return Enumerable[name].apply(Enumerable, arguments);\r
- };\r
- this.exports += "," + name;\r
- }\r
- }, this);\r
- }\r
-});\r
-\r
-eval(this.exports);\r
-\r
-base2.namespace += lang.namespace;\r
-\r
-}; //////////////////// END: CLOSURE /////////////////////////////////////\r