From f46a3c2430a6dee93bc66854473078cc42d7a69d Mon Sep 17 00:00:00 2001 From: Tobie Langel Date: Sun, 28 Sep 2008 18:57:01 +0200 Subject: [PATCH 1/4] Reorganizing array.js source code. --- src/array.js | 193 ++++++++++++++++++++++++++++----------------------- 1 file changed, 108 insertions(+), 85 deletions(-) diff --git a/src/array.js b/src/array.js index 8c0cc11..9b3ef3e 100644 --- a/src/array.js +++ b/src/array.js @@ -21,86 +21,93 @@ if (Prototype.Browser.WebKit) { }; } +function $w(string) { + if (!Object.isString(string)) return []; + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + Array.from = $A; -Object.extend(Array.prototype, Enumerable); - -if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; - -Object.extend(Array.prototype, { - _each: function(iterator) { +(function() { + var arrayProto = Array.prototype, + slice = arrayProto.slice; + + function each(iterator) { for (var i = 0, length = this.length; i < length; i++) iterator(this[i]); - }, - - clear: function() { + } + + function clear() { this.length = 0; return this; - }, - - first: function() { + } + + function first() { return this[0]; - }, - - last: function() { + } + + function last() { return this[this.length - 1]; - }, - - compact: function() { + } + + function compact() { return this.select(function(value) { return value != null; }); - }, - - flatten: function() { + } + + function flatten() { return this.inject([], function(array, value) { - return array.concat(Object.isArray(value) ? - value.flatten() : [value]); + if (Object.isArray(value)) + return array.concat(value.flatten()); + array.push(value); + return array; }); - }, - - without: function() { - var values = $A(arguments); + } + + function without() { + var values = slice.call(arguments, 0); return this.select(function(value) { return !values.include(value); }); - }, - - reverse: function(inline) { + } + + function reverse(inline) { return (inline !== false ? this : this.toArray())._reverse(); - }, - - reduce: function() { + } + + function reduce() { return this.length > 1 ? this : this[0]; - }, - - uniq: function(sorted) { + } + + function uniq(sorted) { return this.inject([], function(array, value, index) { if (0 == index || (sorted ? array.last() != value : !array.include(value))) array.push(value); return array; }); - }, - - intersect: function(array) { + } + + function intersect(array) { return this.uniq().findAll(function(item) { return array.detect(function(value) { return item === value }); }); - }, - - clone: function() { - return [].concat(this); - }, - - size: function() { + } + + function clone() { + return slice.call(this, 0); + } + + function size() { return this.length; - }, - - inspect: function() { + } + + function inspect() { return '[' + this.map(Object.inspect).join(', ') + ']'; - }, - - toJSON: function() { + } + + function toJSON() { var results = []; this.each(function(object) { var value = Object.toJSON(object); @@ -108,37 +115,23 @@ Object.extend(Array.prototype, { }); return '[' + results.join(', ') + ']'; } -}); - -// use native browser JS 1.6 implementation if available -if (Object.isFunction(Array.prototype.forEach)) - Array.prototype._each = Array.prototype.forEach; - -if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { - i || (i = 0); - var length = this.length; - if (i < 0) i = length + i; - for (; i < length; i++) - if (this[i] === item) return i; - return -1; -}; - -if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { - i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; - var n = this.slice(0, i).reverse().indexOf(item); - return (n < 0) ? n : i - n - 1; -}; - -Array.prototype.toArray = Array.prototype.clone; - -function $w(string) { - if (!Object.isString(string)) return []; - string = string.strip(); - return string ? string.split(/\s+/) : []; -} - -if (Prototype.Browser.Opera){ - Array.prototype.concat = function() { + + function indexOf(item, i) { + i || (i = 0); + var length = this.length; + if (i < 0) i = length + i; + for (; i < length; i++) + if (this[i] === item) return i; + return -1; + } + + function lastIndexOf(item, i) { + i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; + var n = this.slice(0, i).reverse().indexOf(item); + return (n < 0) ? n : i - n - 1; + } + + function concat() { var array = []; for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); for (var i = 0, length = arguments.length; i < length; i++) { @@ -150,5 +143,35 @@ if (Prototype.Browser.Opera){ } } return array; - }; -} + } + + Object.extend(arrayProto, Enumerable); + + if (!arrayProto._reverse) + arrayProto._reverse = arrayProto.reverse; + + var _each = 'forEach' in arrayProto ? arrayProto.forEach : each; + Object.extend(arrayProto, { + _each: _each, + clear: clear, + first: first, + last: last, + compact: compact, + flatten: flatten, + without: without, + reverse: reverse, + reduce: reduce, + uniq: uniq, + intersect: intersect, + clone: clone, + toArray: clone, + size: size, + inspect: inspect, + toJSON: toJSON + }); + + // use native browser JS 1.6 implementation if available + if (!'indexOf' in arrayProto) arrayProto.indexOf = indexOf; + if (!'lastIndexOf' in arrayProto) arrayProto.lastIndexOf = lastIndexOf; + if (!'concat' in arrayProto) arrayProto.concat = concat; +})(); From f5d8a093f2cc25b5094327b80407bf9f8725e634 Mon Sep 17 00:00:00 2001 From: Tobie Langel Date: Sun, 28 Sep 2008 19:14:17 +0200 Subject: [PATCH 2/4] More clean-up to array.js. --- src/array.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/array.js b/src/array.js index 9b3ef3e..0976ea9 100644 --- a/src/array.js +++ b/src/array.js @@ -31,13 +31,15 @@ Array.from = $A; (function() { var arrayProto = Array.prototype, - slice = arrayProto.slice; + slice = arrayProto.slice, + _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available function each(iterator) { for (var i = 0, length = this.length; i < length; i++) iterator(this[i]); } - + if (!_each) _each = each; + function clear() { this.length = 0; return this; @@ -150,7 +152,6 @@ Array.from = $A; if (!arrayProto._reverse) arrayProto._reverse = arrayProto.reverse; - var _each = 'forEach' in arrayProto ? arrayProto.forEach : each; Object.extend(arrayProto, { _each: _each, clear: clear, From b7e817927e4a688210075447c0276457a0bec839 Mon Sep 17 00:00:00 2001 From: Tobie Langel Date: Sun, 28 Sep 2008 19:25:03 +0200 Subject: [PATCH 3/4] Reorganize enumerable.js. --- src/enumerable.js | 134 +++++++++++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 56 deletions(-) diff --git a/src/enumerable.js b/src/enumerable.js index d6cbc54..b2155e0 100644 --- a/src/enumerable.js +++ b/src/enumerable.js @@ -1,7 +1,7 @@ var $break = { }; -var Enumerable = { - each: function(iterator, context) { +var Enumerable = (function() { + function each(iterator, context) { var index = 0; try { this._each(function(value) { @@ -11,17 +11,17 @@ var Enumerable = { if (e != $break) throw e; } return this; - }, + } - eachSlice: function(number, iterator, context) { + function eachSlice(number, iterator, context) { var index = -number, slices = [], array = this.toArray(); if (number < 1) return array; while ((index += number) < array.length) slices.push(array.slice(index, index+number)); return slices.collect(iterator, context); - }, + } - all: function(iterator, context) { + function all(iterator, context) { iterator = iterator || Prototype.K; var result = true; this.each(function(value, index) { @@ -29,9 +29,9 @@ var Enumerable = { if (!result) throw $break; }); return result; - }, + } - any: function(iterator, context) { + function any(iterator, context) { iterator = iterator || Prototype.K; var result = false; this.each(function(value, index) { @@ -39,18 +39,18 @@ var Enumerable = { throw $break; }); return result; - }, + } - collect: function(iterator, context) { + function collect(iterator, context) { iterator = iterator || Prototype.K; var results = []; this.each(function(value, index) { results.push(iterator.call(context, value, index)); }); return results; - }, + } - detect: function(iterator, context) { + function detect(iterator, context) { var result; this.each(function(value, index) { if (iterator.call(context, value, index)) { @@ -59,18 +59,18 @@ var Enumerable = { } }); return result; - }, + } - findAll: function(iterator, context) { + function findAll(iterator, context) { var results = []; this.each(function(value, index) { if (iterator.call(context, value, index)) results.push(value); }); return results; - }, + } - grep: function(filter, iterator, context) { + function grep(filter, iterator, context) { iterator = iterator || Prototype.K; var results = []; @@ -82,9 +82,9 @@ var Enumerable = { results.push(iterator.call(context, value, index)); }); return results; - }, + } - include: function(object) { + function include(object) { if (Object.isFunction(this.indexOf)) if (this.indexOf(object) != -1) return true; @@ -96,31 +96,31 @@ var Enumerable = { } }); return found; - }, + } - inGroupsOf: function(number, fillWith) { + function inGroupsOf(number, fillWith) { fillWith = Object.isUndefined(fillWith) ? null : fillWith; return this.eachSlice(number, function(slice) { while(slice.length < number) slice.push(fillWith); return slice; }); - }, + } - inject: function(memo, iterator, context) { + function inject(memo, iterator, context) { this.each(function(value, index) { memo = iterator.call(context, memo, value, index); }); return memo; - }, + } - invoke: function(method) { + function invoke(method) { var args = $A(arguments).slice(1); return this.map(function(value) { return value[method].apply(value, args); }); - }, + } - max: function(iterator, context) { + function max(iterator, context) { iterator = iterator || Prototype.K; var result; this.each(function(value, index) { @@ -129,9 +129,9 @@ var Enumerable = { result = value; }); return result; - }, + } - min: function(iterator, context) { + function min(iterator, context) { iterator = iterator || Prototype.K; var result; this.each(function(value, index) { @@ -140,9 +140,9 @@ var Enumerable = { result = value; }); return result; - }, + } - partition: function(iterator, context) { + function partition(iterator, context) { iterator = iterator || Prototype.K; var trues = [], falses = []; this.each(function(value, index) { @@ -150,26 +150,26 @@ var Enumerable = { trues : falses).push(value); }); return [trues, falses]; - }, + } - pluck: function(property) { + function pluck(property) { var results = []; this.each(function(value) { results.push(value[property]); }); return results; - }, + } - reject: function(iterator, context) { + function reject(iterator, context) { var results = []; this.each(function(value, index) { if (!iterator.call(context, value, index)) results.push(value); }); return results; - }, + } - sortBy: function(iterator, context) { + function sortBy(iterator, context) { return this.map(function(value, index) { return { value: value, @@ -179,13 +179,13 @@ var Enumerable = { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); - }, + } - toArray: function() { + function toArray() { return this.map(); - }, + } - zip: function() { + function zip() { var iterator = Prototype.K, args = $A(arguments); if (Object.isFunction(args.last())) iterator = args.pop(); @@ -194,24 +194,46 @@ var Enumerable = { return this.map(function(value, index) { return iterator(collections.pluck(index)); }); - }, + } - size: function() { + function size() { return this.toArray().length; - }, + } - inspect: function() { + function inspect() { return '#'; } -}; - -Object.extend(Enumerable, { - map: Enumerable.collect, - find: Enumerable.detect, - select: Enumerable.findAll, - filter: Enumerable.findAll, - member: Enumerable.include, - entries: Enumerable.toArray, - every: Enumerable.all, - some: Enumerable.any -}); + + return { + each: each, + eachSlice: eachSlice, + all: all, + every: all, + any: any, + some: any, + collect: collect, + map: collect, + detect: detect, + findAll: findAll, + select: findAll, + filter: findAll, + grep: grep, + include: include, + member: include, + inGroupsOf: inGroupsOf, + inject: inject, + invoke: invoke, + max: max, + min: min, + partition: partition, + pluck: pluck, + reject: reject, + sortBy: sortBy, + toArray: toArray, + entries: toArray, + zip: zip, + size: size, + inspect: inspect, + find: detect + }; +})(); From a94c420a34a43dbfd13f7cf820e01cd9f389cd08 Mon Sep 17 00:00:00 2001 From: Tobie Langel Date: Sun, 28 Sep 2008 19:41:53 +0200 Subject: [PATCH 4/4] Reorganize hash.js. --- src/hash.js | 187 ++++++++++++++++++++++++++++------------------------ 1 file changed, 101 insertions(+), 86 deletions(-) diff --git a/src/hash.js b/src/hash.js index ed96637..928a236 100644 --- a/src/hash.js +++ b/src/hash.js @@ -3,99 +3,114 @@ function $H(object) { }; var Hash = Class.create(Enumerable, (function() { + function initialize(object) { + this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); + } + + function _each(iterator) { + for (var key in this._object) { + var value = this._object[key], pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + } + + function set(key, value) { + return this._object[key] = value; + } + + function get(key) { + // simulating poorly supported hasOwnProperty + if (this._object[key] !== Object.prototype[key]) + return this._object[key]; + } + + function unset(key) { + var value = this._object[key]; + delete this._object[key]; + return value; + } + + function toObject() { + return Object.clone(this._object); + } + + function keys() { + return this.pluck('key'); + } + + function values() { + return this.pluck('value'); + } + + function index(value) { + var match = this.detect(function(pair) { + return pair.value === value; + }); + return match && match.key; + } + + function merge(object) { + return this.clone().update(object); + } + + function update(object) { + return new Hash(object).inject(this, function(result, pair) { + result.set(pair.key, pair.value); + return result; + }); + } function toQueryPair(key, value) { if (Object.isUndefined(value)) return key; return key + '=' + encodeURIComponent(String.interpret(value)); } - return { - initialize: function(object) { - this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); - }, - - _each: function(iterator) { - for (var key in this._object) { - var value = this._object[key], pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, - - set: function(key, value) { - return this._object[key] = value; - }, - - get: function(key) { - // simulating poorly supported hasOwnProperty - if (this._object[key] !== Object.prototype[key]) - return this._object[key]; - }, - - unset: function(key) { - var value = this._object[key]; - delete this._object[key]; - return value; - }, - - toObject: function() { - return Object.clone(this._object); - }, - - keys: function() { - return this.pluck('key'); - }, - - values: function() { - return this.pluck('value'); - }, - - index: function(value) { - var match = this.detect(function(pair) { - return pair.value === value; - }); - return match && match.key; - }, - - merge: function(object) { - return this.clone().update(object); - }, - - update: function(object) { - return new Hash(object).inject(this, function(result, pair) { - result.set(pair.key, pair.value); - return result; - }); - }, - - toQueryString: function() { - return this.inject([], function(results, pair) { - var key = encodeURIComponent(pair.key), values = pair.value; - - if (values && typeof values == 'object') { - if (Object.isArray(values)) - return results.concat(values.map(toQueryPair.curry(key))); - } else results.push(toQueryPair(key, values)); - return results; - }).join('&'); - }, - - inspect: function() { - return '#'; - }, - - toJSON: function() { - return Object.toJSON(this.toObject()); - }, - - clone: function() { - return new Hash(this); - } + function toQueryString() { + return this.inject([], function(results, pair) { + var key = encodeURIComponent(pair.key), values = pair.value; + + if (values && typeof values == 'object') { + if (Object.isArray(values)) + return results.concat(values.map(toQueryPair.curry(key))); + } else results.push(toQueryPair(key, values)); + return results; + }).join('&'); } + + function inspect() { + return '#'; + } + + function toJSON() { + return Object.toJSON(this.toObject()); + } + + function clone() { + return new Hash(this); + } + + return { + initialize: initialize, + _each: _each, + set: set, + get: get, + unset: unset, + toObject: toObject, + toTemplateReplacements: toObject, + keys: keys, + values: values, + index: index, + merge: merge, + update: update, + toQueryString: toQueryString, + inspect: inspect, + toJSON: toJSON, + clone: clone + }; })()); -Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; Hash.from = $H;