/public/javascripts/dojo/util/buildscripts/jslib/packer/base2.js

http://enginey.googlecode.com/ · JavaScript · 972 lines · 692 code · 137 blank · 143 comment · 177 complexity · 27e955754bed263c91f3bfc293430da3 MD5 · raw file

  1. // timestamp: Tue, 24 Apr 2007 09:57:15
  2. /*
  3. base2.js - copyright 2007, Dean Edwards
  4. http://www.opensource.org/licenses/mit-license
  5. */
  6. var base2 = {};
  7. // You know, writing a javascript library is awfully time consuming.
  8. new function(_) { //////////////////// BEGIN: CLOSURE ////////////////////
  9. // =========================================================================
  10. // base2/Base.js
  11. // =========================================================================
  12. // version 1.1
  13. var Base = function() {
  14. // call this method from any other method to invoke that method's ancestor
  15. };
  16. Base.prototype = {
  17. extend: function(source) {
  18. if (arguments.length > 1) { // extending with a name/value pair
  19. var ancestor = this[source];
  20. var value = arguments[1];
  21. if (typeof value == "function" && ancestor && /\bbase\b/.test(value)) {
  22. var method = value;
  23. value = function() { // override
  24. var previous = this.base;
  25. this.base = ancestor;
  26. var returnValue = method.apply(this, arguments);
  27. this.base = previous;
  28. return returnValue;
  29. };
  30. value.method = method;
  31. value.ancestor = ancestor;
  32. }
  33. this[source] = value;
  34. } else if (source) { // extending with an object literal
  35. var extend = Base.prototype.extend;
  36. if (Base._prototyping) {
  37. var key, i = 0, members = ["constructor", "toString", "valueOf"];
  38. while (key = members[i++]) if (source[key] != Object.prototype[key]) {
  39. extend.call(this, key, source[key]);
  40. }
  41. } else if (typeof this != "function") {
  42. // if the object has a customised extend() method then use it
  43. extend = this.extend || extend;
  44. }
  45. // copy each of the source object's properties to this object
  46. for (key in source) if (!Object.prototype[key]) {
  47. extend.call(this, key, source[key]);
  48. }
  49. }
  50. return this;
  51. },
  52. base: Base
  53. };
  54. Base.extend = function(_instance, _static) { // subclass
  55. var extend = Base.prototype.extend;
  56. // build the prototype
  57. Base._prototyping = true;
  58. var proto = new this;
  59. extend.call(proto, _instance);
  60. delete Base._prototyping;
  61. // create the wrapper for the constructor function
  62. var constructor = proto.constructor;
  63. var klass = proto.constructor = function() {
  64. if (!Base._prototyping) {
  65. if (this._constructing || this.constructor == klass) { // instantiation
  66. this._constructing = true;
  67. constructor.apply(this, arguments);
  68. delete this._constructing;
  69. } else { // casting
  70. var object = arguments[0];
  71. if (object != null) {
  72. (object.extend || extend).call(object, proto);
  73. }
  74. return object;
  75. }
  76. }
  77. };
  78. // build the class interface
  79. for (var i in Base) klass[i] = this[i];
  80. klass.ancestor = this;
  81. klass.base = Base.base;
  82. klass.prototype = proto;
  83. klass.toString = this.toString;
  84. extend.call(klass, _static);
  85. // class initialisation
  86. if (typeof klass.init == "function") klass.init();
  87. return klass;
  88. };
  89. // initialise
  90. Base = Base.extend({
  91. constructor: function() {
  92. this.extend(arguments[0]);
  93. }
  94. }, {
  95. ancestor: Object,
  96. base: Base,
  97. implement: function(_interface) {
  98. if (typeof _interface == "function") {
  99. // if it's a function, call it
  100. _interface(this.prototype);
  101. } else {
  102. // add the interface using the extend() method
  103. this.prototype.extend(_interface);
  104. }
  105. return this;
  106. }
  107. });
  108. // =========================================================================
  109. // lang/main.js
  110. // =========================================================================
  111. var Legacy = typeof $Legacy == "undefined" ? {} : $Legacy;
  112. var K = function(k) {return k};
  113. var assert = function(condition, message, Err) {
  114. if (!condition) {
  115. throw new (Err || Error)(message || "Assertion failed.");
  116. }
  117. };
  118. var assertType = function(object, type, message) {
  119. if (type) {
  120. var condition = typeof type == "function" ? instanceOf(object, type) : typeof object == type;
  121. assert(condition, message || "Invalid type.", TypeError);
  122. }
  123. };
  124. var format = function(string) {
  125. // replace %n with arguments[n]
  126. // e.g. format("%1 %2%3 %2a %1%3", "she", "se", "lls");
  127. // ==> "she sells sea shells"
  128. // only supports nine replacements: %1 - %9
  129. var args = arguments;
  130. return String(string).replace(/%([1-9])/g, function(match, index) {
  131. return index < args.length ? args[index] : match;
  132. });
  133. };
  134. var $instanceOf = Legacy.instanceOf || new Function("o,k", "return o instanceof k");
  135. var instanceOf = function(object, klass) {
  136. assertType(klass, "function", "Invalid 'instanceOf' operand.");
  137. if ($instanceOf(object, klass)) return true;
  138. // handle exceptions where the target object originates from another frame
  139. // this is handy for JSON parsing (amongst other things)
  140. if (object != null) switch (klass) {
  141. case Object:
  142. return true;
  143. case Number:
  144. case Boolean:
  145. case Function:
  146. case String:
  147. return typeof object == typeof klass.prototype.valueOf();
  148. case Array:
  149. // this is the only troublesome one
  150. return !!(object.join && object.splice && !arguments.callee(object, Function));
  151. case Date:
  152. return !!object.getTimezoneOffset;
  153. case RegExp:
  154. return String(object.constructor.prototype) == String(new RegExp);
  155. }
  156. return false;
  157. };
  158. var match = function(string, expression) {
  159. // same as String.match() except that this function will return an empty
  160. // array if there is no match
  161. return String(string).match(expression) || [];
  162. };
  163. var RESCAPE = /([\/()[\]{}|*+-.,^$?\\])/g;
  164. var rescape = function(string) {
  165. // make a string safe for creating a RegExp
  166. return String(string).replace(RESCAPE, "\\$1");
  167. };
  168. var $slice = Array.prototype.slice;
  169. var slice = function(object) {
  170. // slice an array-like object
  171. return $slice.apply(object, $slice.call(arguments, 1));
  172. };
  173. var TRIM = /^\s+|\s+$/g;
  174. var trim = function(string) {
  175. return String(string).replace(TRIM, "");
  176. };
  177. // =========================================================================
  178. // lang/extend.js
  179. // =========================================================================
  180. var base = function(object, args) {
  181. // invoke the base method with all supplied arguments
  182. return object.base.apply(object, args);
  183. };
  184. var extend = function(object) {
  185. assert(object != Object.prototype, "Object.prototype is verboten!");
  186. return Base.prototype.extend.apply(object, slice(arguments, 1));
  187. };
  188. // =========================================================================
  189. // lang/assignID.js
  190. // =========================================================================
  191. var $ID = 1;
  192. var assignID = function(object) {
  193. // assign a unique id
  194. if (!object.base2ID) object.base2ID = "b2_" + $ID++;
  195. return object.base2ID;
  196. };
  197. // =========================================================================
  198. // lang/forEach.js
  199. // =========================================================================
  200. if (typeof StopIteration == "undefined") {
  201. StopIteration = new Error("StopIteration");
  202. }
  203. var forEach = function(object, block, context) {
  204. if (object == null) return;
  205. if (typeof object == "function") {
  206. // functions are a special case
  207. var fn = Function;
  208. } else if (typeof object.forEach == "function" && object.forEach != arguments.callee) {
  209. // the object implements a custom forEach method
  210. object.forEach(block, context);
  211. return;
  212. } else if (typeof object.length == "number") {
  213. // the object is array-like
  214. forEach.Array(object, block, context);
  215. return;
  216. }
  217. forEach.Function(fn || Object, object, block, context);
  218. };
  219. // these are the two core enumeration methods. all other forEach methods
  220. // eventually call one of these two.
  221. forEach.Array = function(array, block, context) {
  222. var i, length = array.length; // preserve
  223. if (typeof array == "string") {
  224. for (i = 0; i < length; i++) {
  225. block.call(context, array.charAt(i), i, array);
  226. }
  227. } else {
  228. for (i = 0; i < length; i++) {
  229. block.call(context, array[i], i, array);
  230. }
  231. }
  232. };
  233. forEach.Function = Legacy.forEach || function(fn, object, block, context) {
  234. // enumerate an object and compare its keys with fn's prototype
  235. for (var key in object) {
  236. if (fn.prototype[key] === undefined) {
  237. block.call(context, object[key], key, object);
  238. }
  239. }
  240. };
  241. // =========================================================================
  242. // base2/Base/forEach.js
  243. // =========================================================================
  244. Base.forEach = function(object, block, context) {
  245. forEach.Function(this, object, block, context);
  246. };
  247. // =========================================================================
  248. // base2/../Function.js
  249. // =========================================================================
  250. // some browsers don't define this
  251. Function.prototype.prototype = {};
  252. // =========================================================================
  253. // base2/../String.js
  254. // =========================================================================
  255. // fix String.replace (Safari/IE5.0)
  256. if ("".replace(/^/, String)) {
  257. extend(String.prototype, "replace", function(expression, replacement) {
  258. if (typeof replacement == "function") { // Safari doesn't like functions
  259. if (instanceOf(expression, RegExp)) {
  260. var regexp = expression;
  261. var global = regexp.global;
  262. if (global == null) global = /(g|gi)$/.test(regexp);
  263. // we have to convert global RexpExps for exec() to work consistently
  264. if (global) regexp = new RegExp(regexp.source); // non-global
  265. } else {
  266. regexp = new RegExp(rescape(expression));
  267. }
  268. var match, string = this, result = "";
  269. while (string && (match = regexp.exec(string))) {
  270. result += string.slice(0, match.index) + replacement.apply(this, match);
  271. string = string.slice(match.index + match[0].length);
  272. if (!global) break;
  273. }
  274. return result + string;
  275. } else {
  276. return base(this, arguments);
  277. }
  278. });
  279. }
  280. // =========================================================================
  281. // base2/Abstract.js
  282. // =========================================================================
  283. var Abstract = Base.extend({
  284. constructor: function() {
  285. throw new TypeError("Class cannot be instantiated.");
  286. }
  287. });
  288. // =========================================================================
  289. // base2/Module.js
  290. // =========================================================================
  291. // based on ruby's Module class and Mozilla's Array generics:
  292. // http://www.ruby-doc.org/core/classes/Module.html
  293. // http://developer.mozilla.org/en/docs/New_in_JavaScript_1.6#Array_and_String_generics
  294. // A Module is used as the basis for creating interfaces that can be
  295. // applied to other classes. *All* properties and methods are static.
  296. // When a module is used as a mixin, methods defined on what would normally be
  297. // the instance interface become instance methods of the target object.
  298. // Modules cannot be instantiated. Static properties and methods are inherited.
  299. var Module = Abstract.extend(null, {
  300. extend: function(_interface, _static) {
  301. // extend a module to create a new module
  302. var module = this.base();
  303. // inherit static methods
  304. forEach (this, function(property, name) {
  305. if (!Module[name] && name != "init") {
  306. extend(module, name, property);
  307. }
  308. });
  309. // implement module (instance AND static) methods
  310. module.implement(_interface);
  311. // implement static properties and methods
  312. extend(module, _static);
  313. // Make the submarine noises Larry!
  314. if (typeof module.init == "function") module.init();
  315. return module;
  316. },
  317. implement: function(_interface) {
  318. // implement an interface on BOTH the instance and static interfaces
  319. var module = this;
  320. if (typeof _interface == "function") {
  321. module.base(_interface);
  322. forEach (_interface, function(property, name) {
  323. if (!Module[name] && name != "init") {
  324. extend(module, name, property);
  325. }
  326. });
  327. } else {
  328. // create the instance interface
  329. Base.forEach (extend({}, _interface), function(property, name) {
  330. // instance methods call the equivalent static method
  331. if (typeof property == "function") {
  332. property = function() {
  333. base; // force inheritance
  334. return module[name].apply(module, [this].concat(slice(arguments)));
  335. };
  336. }
  337. if (!Module[name]) extend(this, name, property);
  338. }, module.prototype);
  339. // add the static interface
  340. extend(module, _interface);
  341. }
  342. return module;
  343. }
  344. });
  345. // =========================================================================
  346. // base2/Enumerable.js
  347. // =========================================================================
  348. var Enumerable = Module.extend({
  349. every: function(object, test, context) {
  350. var result = true;
  351. try {
  352. this.forEach (object, function(value, key) {
  353. result = test.call(context, value, key, object);
  354. if (!result) throw StopIteration;
  355. });
  356. } catch (error) {
  357. if (error != StopIteration) throw error;
  358. }
  359. return !!result; // cast to boolean
  360. },
  361. filter: function(object, test, context) {
  362. return this.reduce(object, new Array2, function(result, value, key) {
  363. if (test.call(context, value, key, object)) {
  364. result[result.length] = value;
  365. }
  366. return result;
  367. });
  368. },
  369. invoke: function(object, method) {
  370. // apply a method to each item in the enumerated object
  371. var args = slice(arguments, 2);
  372. return this.map(object, (typeof method == "function") ? function(item) {
  373. if (item != null) return method.apply(item, args);
  374. } : function(item) {
  375. if (item != null) return item[method].apply(item, args);
  376. });
  377. },
  378. map: function(object, block, context) {
  379. var result = new Array2;
  380. this.forEach (object, function(value, key) {
  381. result[result.length] = block.call(context, value, key, object);
  382. });
  383. return result;
  384. },
  385. pluck: function(object, key) {
  386. return this.map(object, function(item) {
  387. if (item != null) return item[key];
  388. });
  389. },
  390. reduce: function(object, result, block, context) {
  391. this.forEach (object, function(value, key) {
  392. result = block.call(context, result, value, key, object);
  393. });
  394. return result;
  395. },
  396. some: function(object, test, context) {
  397. return !this.every(object, function(value, key) {
  398. return !test.call(context, value, key, object);
  399. });
  400. }
  401. }, {
  402. forEach: forEach
  403. });
  404. // =========================================================================
  405. // base2/Array2.js
  406. // =========================================================================
  407. // The IArray module implements all Array methods.
  408. // This module is not public but its methods are accessible through the Array2 object (below).
  409. var IArray = Module.extend({
  410. combine: function(keys, values) {
  411. // combine two arrays to make a hash
  412. if (!values) values = keys;
  413. return this.reduce(keys, {}, function(object, key, index) {
  414. object[key] = values[index];
  415. return object;
  416. });
  417. },
  418. copy: function(array) {
  419. return this.concat(array);
  420. },
  421. contains: function(array, item) {
  422. return this.indexOf(array, item) != -1;
  423. },
  424. forEach: forEach.Array,
  425. indexOf: function(array, item, fromIndex) {
  426. var length = array.length;
  427. if (fromIndex == null) {
  428. fromIndex = 0;
  429. } else if (fromIndex < 0) {
  430. fromIndex = Math.max(0, length + fromIndex);
  431. }
  432. for (var i = fromIndex; i < length; i++) {
  433. if (array[i] === item) return i;
  434. }
  435. return -1;
  436. },
  437. insertAt: function(array, item, index) {
  438. this.splice(array, index, 0, item);
  439. return item;
  440. },
  441. insertBefore: function(array, item, before) {
  442. var index = this.indexOf(array, before);
  443. if (index == -1) this.push(array, item);
  444. else this.splice(array, index, 0, item);
  445. return item;
  446. },
  447. lastIndexOf: function(array, item, fromIndex) {
  448. var length = array.length;
  449. if (fromIndex == null) {
  450. fromIndex = length - 1;
  451. } else if (from < 0) {
  452. fromIndex = Math.max(0, length + fromIndex);
  453. }
  454. for (var i = fromIndex; i >= 0; i--) {
  455. if (array[i] === item) return i;
  456. }
  457. return -1;
  458. },
  459. remove: function(array, item) {
  460. var index = this.indexOf(array, item);
  461. if (index != -1) this.removeAt(array, index);
  462. return item;
  463. },
  464. removeAt: function(array, index) {
  465. var item = array[index];
  466. this.splice(array, index, 1);
  467. return item;
  468. }
  469. });
  470. IArray.prototype.forEach = function(block, context) {
  471. forEach.Array(this, block, context);
  472. };
  473. IArray.implement(Enumerable);
  474. forEach ("concat,join,pop,push,reverse,shift,slice,sort,splice,unshift".split(","), function(name) {
  475. IArray[name] = function(array) {
  476. return Array.prototype[name].apply(array, slice(arguments, 1));
  477. };
  478. });
  479. // create a faux constructor that augments the built-in Array object
  480. var Array2 = function() {
  481. return IArray(this.constructor == IArray ? Array.apply(null, arguments) : arguments[0]);
  482. };
  483. // expose IArray.prototype so that it can be extended
  484. Array2.prototype = IArray.prototype;
  485. forEach (IArray, function(method, name, proto) {
  486. if (Array[name]) {
  487. IArray[name] = Array[name];
  488. delete IArray.prototype[name];
  489. }
  490. Array2[name] = IArray[name];
  491. });
  492. // =========================================================================
  493. // base2/Hash.js
  494. // =========================================================================
  495. var HASH = "#" + Number(new Date);
  496. var KEYS = HASH + "keys";
  497. var VALUES = HASH + "values";
  498. var Hash = Base.extend({
  499. constructor: function(values) {
  500. this[KEYS] = new Array2;
  501. this[VALUES] = {};
  502. this.merge(values);
  503. },
  504. copy: function() {
  505. var copy = new this.constructor(this);
  506. Base.forEach (this, function(property, name) {
  507. if (typeof property != "function" && name.charAt(0) != "#") {
  508. copy[name] = property;
  509. }
  510. });
  511. return copy;
  512. },
  513. // ancient browsers throw an error when we use "in" as an operator
  514. // so we must create the function dynamically
  515. exists: Legacy.exists || new Function("k", format("return('%1'+k)in this['%2']", HASH, VALUES)),
  516. fetch: function(key) {
  517. return this[VALUES][HASH + key];
  518. },
  519. forEach: function(block, context) {
  520. forEach (this[KEYS], function(key) {
  521. block.call(context, this.fetch(key), key, this);
  522. }, this);
  523. },
  524. keys: function(index, length) {
  525. var keys = this[KEYS] || new Array2;
  526. switch (arguments.length) {
  527. case 0: return keys.copy();
  528. case 1: return keys[index];
  529. default: return keys.slice(index, length);
  530. }
  531. },
  532. merge: function(values) {
  533. forEach (arguments, function(values) {
  534. forEach (values, function(value, key) {
  535. this.store(key, value);
  536. }, this);
  537. }, this);
  538. return this;
  539. },
  540. remove: function(key) {
  541. var value = this.fetch(key);
  542. this[KEYS].remove(String(key));
  543. delete this[VALUES][HASH + key];
  544. return value;
  545. },
  546. store: function(key, value) {
  547. if (arguments.length == 1) value = key;
  548. // only store the key for a new entry
  549. if (!this.exists(key)) {
  550. this[KEYS].push(String(key));
  551. }
  552. // create the new entry (or overwrite the old entry)
  553. this[VALUES][HASH + key] = value;
  554. return value;
  555. },
  556. toString: function() {
  557. return String(this[KEYS]);
  558. },
  559. union: function(values) {
  560. return this.merge.apply(this.copy(), arguments);
  561. },
  562. values: function(index, length) {
  563. var values = this.map(K);
  564. switch (arguments.length) {
  565. case 0: return values;
  566. case 1: return values[index];
  567. default: return values.slice(index, length);
  568. }
  569. }
  570. });
  571. Hash.implement(Enumerable);
  572. // =========================================================================
  573. // base2/Collection.js
  574. // =========================================================================
  575. // A Hash that is more array-like (accessible by index).
  576. // Collection classes have a special (optional) property: Item
  577. // The Item property points to a constructor function.
  578. // Members of the collection must be an instance of Item.
  579. // e.g.
  580. // var Dates = Collection.extend(); // create a collection class
  581. // Dates.Item = Date; // only JavaScript Date objects allowed as members
  582. // var appointments = new Dates(); // instantiate the class
  583. // appointments.add(appointmentId, new Date); // add a date
  584. // appointments.add(appointmentId, "tomorrow"); // ERROR!
  585. // The static create() method is responsible for all construction of collection items.
  586. // Instance methods that add new items (add, store, insertAt, replaceAt) pass *all* of their arguments
  587. // to the static create() method. If you want to modify the way collection items are
  588. // created then you only need to override this method for custom collections.
  589. var Collection = Hash.extend({
  590. add: function(key, item) {
  591. // Duplicates not allowed using add().
  592. // - but you can still overwrite entries using store()
  593. assert(!this.exists(key), "Duplicate key.");
  594. return this.store.apply(this, arguments);
  595. },
  596. count: function() {
  597. return this[KEYS].length;
  598. },
  599. indexOf: function(key) {
  600. return this[KEYS].indexOf(String(key));
  601. },
  602. insertAt: function(index, key, item) {
  603. assert(!this.exists(key), "Duplicate key.");
  604. this[KEYS].insertAt(index, String(key));
  605. return this.store.apply(this, slice(arguments, 1));
  606. },
  607. item: function(index) {
  608. return this.fetch(this[KEYS][index]);
  609. },
  610. removeAt: function(index) {
  611. return this.remove(this[KEYS][index]);
  612. },
  613. reverse: function() {
  614. this[KEYS].reverse();
  615. return this;
  616. },
  617. sort: function(compare) {
  618. if (compare) {
  619. var self = this;
  620. this[KEYS].sort(function(key1, key2) {
  621. return compare(self.fetch(key1), self.fetch(key2), key1, key2);
  622. });
  623. } else this[KEYS].sort();
  624. return this;
  625. },
  626. store: function(key, item) {
  627. if (arguments.length == 1) item = key;
  628. item = this.constructor.create.apply(this.constructor, arguments);
  629. return this.base(key, item);
  630. },
  631. storeAt: function(index, item) {
  632. //-dean: get rid of this?
  633. assert(index < this.count(), "Index out of bounds.");
  634. arguments[0] = this[KEYS][index];
  635. return this.store.apply(this, arguments);
  636. }
  637. }, {
  638. Item: null, // if specified, all members of the Collection must be instances of Item
  639. create: function(key, item) {
  640. if (this.Item && !instanceOf(item, this.Item)) {
  641. item = new this.Item(key, item);
  642. }
  643. return item;
  644. },
  645. extend: function(_instance, _static) {
  646. var klass = this.base(_instance);
  647. klass.create = this.create;
  648. extend(klass, _static);
  649. if (!klass.Item) {
  650. klass.Item = this.Item;
  651. } else if (typeof klass.Item != "function") {
  652. klass.Item = (this.Item || Base).extend(klass.Item);
  653. }
  654. if (typeof klass.init == "function") klass.init();
  655. return klass;
  656. }
  657. });
  658. // =========================================================================
  659. // base2/RegGrp.js
  660. // =========================================================================
  661. var RegGrp = Collection.extend({
  662. constructor: function(values, flags) {
  663. this.base(values);
  664. if (typeof flags == "string") {
  665. this.global = /g/.test(flags);
  666. this.ignoreCase = /i/.test(flags);
  667. }
  668. },
  669. global: true, // global is the default setting
  670. ignoreCase: false,
  671. exec: function(string, replacement) {
  672. if (arguments.length == 1) {
  673. var keys = this[KEYS];
  674. var values = this[VALUES];
  675. replacement = function(match) {
  676. if (!match) return "";
  677. var offset = 1, i = 0;
  678. // loop through the values
  679. while (match = values[HASH + keys[i++]]) {
  680. // do we have a result?
  681. if (arguments[offset]) {
  682. var replacement = match.replacement;
  683. switch (typeof replacement) {
  684. case "function":
  685. return replacement.apply(null, slice(arguments, offset));
  686. case "number":
  687. return arguments[offset + replacement];
  688. default:
  689. return replacement;
  690. }
  691. // no? then skip over references to sub-expressions
  692. } else offset += match.length + 1;
  693. }
  694. };
  695. }
  696. var flags = (this.global ? "g" : "") + (this.ignoreCase ? "i" : "");
  697. return String(string).replace(new RegExp(this, flags), replacement);
  698. },
  699. test: function(string) {
  700. return this.exec(string) != string;
  701. },
  702. toString: function() {
  703. var length = 0;
  704. return "(" + this.map(function(item) {
  705. // fix back references
  706. var expression = String(item).replace(/\\(\d+)/g, function($, index) {
  707. return "\\" + (1 + Number(index) + length);
  708. });
  709. length += item.length + 1;
  710. return expression;
  711. }).join(")|(") + ")";
  712. }
  713. }, {
  714. IGNORE: "$0",
  715. init: function() {
  716. forEach ("add,exists,fetch,remove,store".split(","), function(name) {
  717. extend(this, name, function(expression) {
  718. if (instanceOf(expression, RegExp)) {
  719. expression = expression.source;
  720. }
  721. return base(this, arguments);
  722. });
  723. }, this.prototype);
  724. }
  725. });
  726. // =========================================================================
  727. // base2/RegGrp/Item.js
  728. // =========================================================================
  729. RegGrp.Item = Base.extend({
  730. constructor: function(expression, replacement) {
  731. var ESCAPE = /\\./g;
  732. var STRING = /(['"])\1\+(.*)\+\1\1$/;
  733. expression = instanceOf(expression, RegExp) ? expression.source : String(expression);
  734. if (typeof replacement == "number") replacement = String(replacement);
  735. else if (replacement == null) replacement = "";
  736. // count the number of sub-expressions
  737. // - add one because each pattern is itself a sub-expression
  738. this.length = match(expression.replace(ESCAPE, "").replace(/\[[^\]]+\]/g, ""), /\(/g).length;
  739. // does the pattern use sub-expressions?
  740. if (typeof replacement == "string" && /\$(\d+)/.test(replacement)) {
  741. // a simple lookup? (e.g. "$2")
  742. if (/^\$\d+$/.test(replacement)) {
  743. // store the index (used for fast retrieval of matched strings)
  744. replacement = parseInt(replacement.slice(1));
  745. } else { // a complicated lookup (e.g. "Hello $2 $1")
  746. // build a function to do the lookup
  747. var i = this.length + 1;
  748. var Q = /'/.test(replacement.replace(ESCAPE, "")) ? '"' : "'";
  749. replacement = replacement.replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\$(\d+)/g, Q +
  750. "+(arguments[$1]||" + Q+Q + ")+" + Q);
  751. replacement = new Function("return " + Q + replacement.replace(STRING, "$1") + Q);
  752. }
  753. }
  754. this.replacement = replacement;
  755. this.toString = function() {
  756. return expression || "";
  757. };
  758. },
  759. length: 0,
  760. replacement: ""
  761. });
  762. // =========================================================================
  763. // base2/Namespace.js
  764. // =========================================================================
  765. var Namespace = Base.extend({
  766. constructor: function(_private, _public) {
  767. this.extend(_public);
  768. this.toString = function() {
  769. return format("[base2.%1]", this.name);
  770. };
  771. // initialise
  772. if (typeof this.init == "function") this.init();
  773. if (this.name != "base2") {
  774. this.namespace = format("var %1=base2.%1;", this.name);
  775. }
  776. var namespace = "var base=" + base + ";";
  777. var imports = ("base2,lang," + this.imports).split(",");
  778. _private.imports = Enumerable.reduce(imports, namespace, function(namespace, name) {
  779. if (base2[name]) namespace += base2[name].namespace;
  780. return namespace;
  781. });
  782. var namespace = format("base2.%1=%1;", this.name);
  783. var exports = this.exports.split(",");
  784. _private.exports = Enumerable.reduce(exports, namespace, function(namespace, name) {
  785. if (name) {
  786. this.namespace += format("var %2=%1.%2;", this.name, name);
  787. namespace += format("if(!%1.%2)%1.%2=%2;base2.%2=%1.%2;", this.name, name);
  788. }
  789. return namespace;
  790. }, this);
  791. if (this.name != "base2") {
  792. base2.namespace += format("var %1=base2.%1;", this.name);
  793. }
  794. },
  795. exports: "",
  796. imports: "",
  797. namespace: "",
  798. name: ""
  799. });
  800. base2 = new Namespace(this, {
  801. name: "base2",
  802. version: "0.8 (alpha)",
  803. exports: "Base,Abstract,Module,Enumerable,Array2,Hash,Collection,RegGrp,Namespace"
  804. });
  805. base2.toString = function() {
  806. return "[base2]";
  807. };
  808. eval(this.exports);
  809. // =========================================================================
  810. // base2/lang/namespace.js
  811. // =========================================================================
  812. var lang = new Namespace(this, {
  813. name: "lang",
  814. version: base2.version,
  815. exports: "K,assert,assertType,assignID,instanceOf,extend,format,forEach,match,rescape,slice,trim",
  816. init: function() {
  817. this.extend = extend;
  818. // add the Enumerable methods to the lang object
  819. forEach (Enumerable.prototype, function(method, name) {
  820. if (!Module[name]) {
  821. this[name] = function() {
  822. return Enumerable[name].apply(Enumerable, arguments);
  823. };
  824. this.exports += "," + name;
  825. }
  826. }, this);
  827. }
  828. });
  829. eval(this.exports);
  830. base2.namespace += lang.namespace;
  831. }; //////////////////// END: CLOSURE /////////////////////////////////////