133 lines
3.2 KiB
JavaScript
133 lines
3.2 KiB
JavaScript
var Hash = function(object) {
|
|
if (object instanceof Hash) this.merge(object);
|
|
else Object.extend(this, object || { });
|
|
};
|
|
|
|
Object.extend(Hash, {
|
|
toQueryString: function(obj) {
|
|
var parts = [];
|
|
parts.add = arguments.callee.addPair;
|
|
|
|
this.prototype._each.call(obj, function(pair) {
|
|
if (!pair.key) return;
|
|
var value = pair.value;
|
|
|
|
if (value && typeof value == 'object') {
|
|
if (Object.isArray(value)) value.each(function(value) {
|
|
parts.add(pair.key, value);
|
|
});
|
|
return;
|
|
}
|
|
parts.add(pair.key, value);
|
|
});
|
|
|
|
return parts.join('&');
|
|
},
|
|
|
|
toJSON: function(object) {
|
|
var results = [];
|
|
this.prototype._each.call(object, function(pair) {
|
|
var value = Object.toJSON(pair.value);
|
|
if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value);
|
|
});
|
|
return '{' + results.join(', ') + '}';
|
|
}
|
|
});
|
|
|
|
Hash.toQueryString.addPair = function(key, value, prefix) {
|
|
key = encodeURIComponent(key);
|
|
if (value === undefined) this.push(key);
|
|
else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value)));
|
|
};
|
|
|
|
Object.extend(Hash.prototype, Enumerable);
|
|
Object.extend(Hash.prototype, {
|
|
_each: function(iterator) {
|
|
for (var key in this) {
|
|
var value = this[key];
|
|
if (value && value == Hash.prototype[key]) continue;
|
|
|
|
var pair = [key, value];
|
|
pair.key = key;
|
|
pair.value = value;
|
|
iterator(pair);
|
|
}
|
|
},
|
|
|
|
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(hash) {
|
|
return $H(hash).inject(this, function(mergedHash, pair) {
|
|
mergedHash[pair.key] = pair.value;
|
|
return mergedHash;
|
|
});
|
|
},
|
|
|
|
remove: function() {
|
|
var result;
|
|
for(var i = 0, length = arguments.length; i < length; i++) {
|
|
var value = this[arguments[i]];
|
|
if (value !== undefined){
|
|
if (result === undefined) result = value;
|
|
else {
|
|
if (!Object.isArray(result)) result = [result];
|
|
result.push(value);
|
|
}
|
|
}
|
|
delete this[arguments[i]];
|
|
}
|
|
return result;
|
|
},
|
|
|
|
toQueryString: function() {
|
|
return Hash.toQueryString(this);
|
|
},
|
|
|
|
inspect: function() {
|
|
return '#<Hash:{' + this.map(function(pair) {
|
|
return pair.map(Object.inspect).join(': ');
|
|
}).join(', ') + '}>';
|
|
},
|
|
|
|
toJSON: function() {
|
|
return Hash.toJSON(this);
|
|
}
|
|
});
|
|
|
|
function $H(object) {
|
|
if (object instanceof Hash) return object;
|
|
return new Hash(object);
|
|
};
|
|
|
|
// Safari iterates over shadowed properties
|
|
if (function() {
|
|
var i = 0, Test = function(value) { this.key = value };
|
|
Test.prototype.key = 'foo';
|
|
for (var property in new Test('bar')) i++;
|
|
return i > 1;
|
|
}()) Hash.prototype._each = function(iterator) {
|
|
var cache = [];
|
|
for (var key in this) {
|
|
var value = this[key];
|
|
if ((value && value == Hash.prototype[key]) || cache.include(key)) continue;
|
|
cache.push(key);
|
|
var pair = [key, value];
|
|
pair.key = key;
|
|
pair.value = value;
|
|
iterator(pair);
|
|
}
|
|
};
|