Since writing your own UI elements from scratch is for chumps, I’ve been using jQuery to construct our new booking systems. Lots of shiny there, all the better to Web-2.0 your social media with, my dear.
*{vomits a little in his mouth}*
I have a sortable list where each li element has an attribute storing object data. An AJAX lookup supplies the data from a 3rd party source, and there can be 1..n li elements. Calling serialize on that list allows me to get the ids of the list objects in their currently sorted order:
>>> $("#waypoints").sortable("serialize")
"waypoints[]=5&waypoints[]=8"
That’s OK, but I want to access the json data, not the ids. I could put that data in a javascript array and then simply re-order it (or post the ids and the data separately and use the controller to order them), and I also could gouge my eyeballs out with a rusty spoon. Thankfully, according to the docs, I can pass a hash to serialize specifying which attribute to return:
>>> $("#waypoints").sortable("serialize" {attribute: "json_data"})
"{"des_id":"a","des_name":"r","fleet[]=id":"5"}& "{"des_id":"a","des_name":"r","fleet[]=id":"8"}
…Well that’s not what we what. That’s weird, and what the fuck is going on with that inserted []? Hmm, perhaps the key parameter is being clobbered and needs to be set as well (thus specifying what the first part should be):
>>> $("#waypoints").sortable("serialize" {attribute: "json_data", key: "waypoints"})
"waypoints[]=id":"5"}&waypoints=name":"8" }"
Nope, still fucked. And weirdly escaped now, also. I could use expression to create my own parsing regex, but I also could gouge my eyes out with a rusty spoon. Into the source code, then, to see what the hell’s going on.
serialize is defined on line 3365 of my copy of jquery-ui.js, and has this snippet:
3365 3366 3367 3368
| $(items).each(function() {
var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
}); |
Ah. That explains why I was getting that inserted [] in the last part of each value, and also why I wasn’t getting the full thing when I changed the key. When I don’t pass an expression in, it chunks up the value by discarding the first group, and using the second. In this case, everything up to the last underscore is discarded and the key used is everything before the last underscore, with a [] appended.
When I supplied a key, it simply discarded the entire first matched group and returned the second.
So now I can solve my problem. To parse an attribute containing underscores (or – or =) with serialize, I simply need to provide the attribute name, the key and a catchall expression, say, (.+):
>>> $("#waypoints").sortable("serialize" {attribute: "json_data", key: "waypoints", expression: "(.+)"})
"waypoints[]={"des_id":"a","des_name":"r","fleet_id":"5"}& "{"des_id":"a","des_name":"r","fleet_id":"8"}"