Skip to content

Instantly share code, notes, and snippets.

@mcmire
Created January 20, 2009 18:58
Show Gist options
  • Save mcmire/49602 to your computer and use it in GitHub Desktop.
Save mcmire/49602 to your computer and use it in GitHub Desktop.
Extending Prototype to retain order of form data when sending an Ajax request
Object.extend(Object, {
clone: function(object) {
return object.clone ? object.clone() : Object.extend({ }, object);
},
toQueryString: function(object) {
return object.toQueryString ? object.toQueryString() : $H(object).toQueryString()
}
});
var PseudoHash = Class.create(Hash, (function() {
function toQueryPair(key, value) {
if (Object.isUndefined(value)) return key;
return key + '=' + encodeURIComponent(String.interpret(value));
}
return {
initialize: function(object) {
this._object = object ? (object.toArray ? object.toArray() : object) : [];
},
_each: function(iterator) {
for (var i=0, len=this._object.length; i<len; i++) {
var pair = this._object[i]; // do we need to clone this?
if (!Object.isArray(pair)) pair = [ pair.key, pair.value ];
pair.key = pair[0];
pair.value = pair[1];
iterator(pair);
}
},
set: function(key, value) {
this.unset(key);
return this._object.push({ key: key, value: value });
},
get: function(key) {
var pair = this._object.find(function(pair) { pair.key == key });
return pair ? pair.value : null;
},
unset: function(key) {
var value = this.get(key);
this._object = this._object.reject(function(pair) { pair.key == key });
return value;
},
update: function(object) {
return new PseudoHash(object).inject(this, function(result, pair) {
result.set(pair.key, pair.value);
return result;
});
},
toHash: function() {
return this.inject({}, function(h, pair) {
h[pair.key] = pair.value;
return h;
});
},
toQueryString: function() {
return this.map(function(pair) {
var key = encodeURIComponent(pair.key), values = pair.value;
if (values && typeof values == 'object') {
if (Object.isArray(values))
return values.map(toQueryPair.curry(key)).join('&');
}
return toQueryPair(key, values);
}).join('&');
},
inspect: function() {
return '#<PseudoHash:{' + this.map(function(pair) {
return pair.map(Object.inspect).join(': ');
}).join(', ') + '}>';
},
clone: function() {
return new PseudoHash(this);
}
}
})());
String.prototype.toQueryParams = function(separator) {
var match = this.strip().match(/([^?#]*)(#.*)?$/);
if (!match) return { };
return match[1].split(separator || '&').inject((new PseudoHash), function(hash, pair) {
if ((pair = pair.split('='))[0]) {
var key = decodeURIComponent(pair.shift());
var value = pair.length > 1 ? pair.join('=') : pair[0];
if (value != undefined) value = decodeURIComponent(value);
var v;
if (v = hash.get(key)) {
// a key is already present; construct an array of values
if (!Object.isArray(v)) { v = [v]; hash.set(key, v) }
v.push(value);
}
else hash.set(key, value);
}
return hash;
});
};
Form.serializeElements = function(elements, options) {
if (typeof options != 'object') options = { hash: !!options };
else if (Object.isUndefined(options.hash)) options.hash = true;
var key, value, submitted = false, submit = options.submit;
var data = elements.inject((new PseudoHash), function(result, element) {
if (!element.disabled && element.name) {
key = element.name; value = $(element).getValue();
if (
value != null &&
(
element.type != 'submit' ||
(!submitted && submit !== false && (!submit || key == submit) && (submitted = true))
)
)
{
var v;
if (v = result.get(key)) {
// a key is already present; construct an array of values
if (!Object.isArray(v)) { v = [v]; result.set(key, v) }
v.push(value);
}
else result.set(key, value);
}
}
return result;
});
if (options.hash) {
return data.toHash();
} else {
return data.toQueryString();
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment