2 * jQuery.query - Query String Modification and Creation for jQuery
3 * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
4 * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
7 * @author Blair Mitchelmore
11 new function(settings
) {
13 var $separator
= settings
.separator
|| '&';
14 var $spaces
= settings
.spaces
=== false ? false : true;
15 var $suffix
= settings
.suffix
=== false ? '' : '[]';
16 var $prefix
= settings
.prefix
=== false ? false : true;
17 var $hash
= $prefix
? settings
.hash
=== true ? "#" : "?" : "";
18 var $numbers
= settings
.numbers
=== false ? false : true;
20 jQuery
.query
= new function() {
21 var is = function(o
, t
) {
22 return o
!= undefined && o
!== null && (!!t
? o
.constructor == t
: true);
24 var parse = function(path
) {
25 var m
, rx
= /\[([^[]*)\]/g, match
= /^([^[]+)(\[.*\])?$/.exec(path
), base
= match
[1], tokens
= [];
26 while (m
= rx
.exec(match
[2])) tokens
.push(m
[1]);
27 return [base
, tokens
];
29 var set = function(target
, tokens
, value
) {
30 var o
, token
= tokens
.shift();
31 if (typeof target
!= 'object') target
= null;
33 if (!target
) target
= [];
34 if (is(target
, Array
)) {
35 target
.push(tokens
.length
== 0 ? value
: set(null, tokens
.slice(0), value
));
36 } else if (is(target
, Object
)) {
38 while (target
[i
++] != null);
39 target
[--i
] = tokens
.length
== 0 ? value
: set(target
[i
], tokens
.slice(0), value
);
42 target
.push(tokens
.length
== 0 ? value
: set(null, tokens
.slice(0), value
));
44 } else if (token
&& token
.match(/^\s*[0-9]+\s*$/)) {
45 var index
= parseInt(token
, 10);
46 if (!target
) target
= [];
47 target
[index
] = tokens
.length
== 0 ? value
: set(target
[index
], tokens
.slice(0), value
);
49 var index
= token
.replace(/^\s*|\s*$/g, "");
50 if (!target
) target
= {};
51 if (is(target
, Array
)) {
53 for (var i
= 0; i
< target
.length
; ++i
) {
58 target
[index
] = tokens
.length
== 0 ? value
: set(target
[index
], tokens
.slice(0), value
);
65 var queryObject = function(a
) {
70 jQuery
.each(a
.get(), function(key
, val
) {
74 jQuery
.each(arguments
, function() {
76 q
= decodeURIComponent(q
);
77 q
= q
.replace(/^[?#]/,''); // remove any leading ? || #
78 q
= q
.replace(/[;&]$/,''); // remove any trailing & || ;
79 if ($spaces
) q
= q
.replace(/[+]/g,' '); // replace +'s with spaces
81 jQuery
.each(q
.split(/[&;]/), function(){
82 var key
= this.split('=')[0];
83 var val
= this.split('=')[1];
88 if (/^[+-]?[0-9]+\.[0-9]*$/.test(val
)) // simple float regex
89 val
= parseFloat(val
);
90 else if (/^[+-]?[0-9]+$/.test(val
)) // simple int regex
91 val
= parseInt(val
, 10);
94 val
= (!val
&& val
!== 0) ? true : val
;
96 if (val
!== false && val
!== true && typeof val
!= 'number')
106 queryObject
.prototype = {
108 has: function(key
, type
) {
109 var value
= this.get(key
);
110 return is(value
, type
);
113 if (!is(key
)) return this.keys
;
114 var parsed
= parse(key
), base
= parsed
[0], tokens
= parsed
[1];
115 var target
= this.keys
[base
];
116 while (target
!= null && tokens
.length
!= 0) {
117 target
= target
[tokens
.shift()];
119 return typeof target
== 'number' ? target
: target
|| "";
122 var target
= this.GET(key
);
123 if (is(target
, Object
))
124 return jQuery
.extend(true, {}, target
);
125 else if (is(target
, Array
))
126 return target
.slice(0);
129 SET: function(key
, val
) {
130 var value
= !is(val
) ? null : val
;
131 var parsed
= parse(key
), base
= parsed
[0], tokens
= parsed
[1];
132 var target
= this.keys
[base
];
133 this.keys
[base
] = set(target
, tokens
.slice(0), value
);
136 set: function(key
, val
) {
137 return this.copy().SET(key
, val
);
139 REMOVE: function(key
) {
140 return this.SET(key
, null).COMPACT();
142 remove: function(key
) {
143 return this.copy().REMOVE(key
);
147 jQuery
.each(self
.keys
, function(key
, value
) {
148 delete self
.keys
[key
];
152 load: function(url
) {
153 var hash
= url
.replace(/^.*?[#](.+?)(?:\?.+)?$/, "$1");
154 var search
= url
.replace(/^.*?[?](.+?)(?:#.+)?$/, "$1");
155 return new queryObject(url
.length
== search
.length
? '' : search
, url
.length
== hash
.length
? '' : hash
);
158 return this.copy().EMPTY();
161 return new queryObject(this);
163 COMPACT: function() {
164 function build(orig
) {
165 var obj
= typeof orig
== "object" ? is(orig
, Array
) ? [] : {} : orig
;
166 if (typeof orig
== 'object') {
167 function add(o
, key
, value
) {
173 jQuery
.each(orig
, function(key
, value
) {
174 if (!is(value
)) return true;
175 add(obj
, key
, build(value
));
180 this.keys
= build(this.keys
);
183 compact: function() {
184 return this.copy().COMPACT();
186 toString: function() {
187 var i
= 0, queryString
= [], chunks
= [], self
= this;
188 var addFields = function(arr
, key
, value
) {
189 if (!is(value
) || value
=== false) return;
190 var o
= [encodeURIComponent(key
)];
191 if (value
!== true) {
193 o
.push(encodeURIComponent(value
));
195 arr
.push(o
.join(""));
197 var build = function(obj
, base
) {
198 var newKey = function(key
) {
199 return !base
|| base
== "" ? [key
].join("") : [base
, "[", key
, "]"].join("");
201 jQuery
.each(obj
, function(key
, value
) {
202 if (typeof value
== 'object')
203 build(value
, newKey(key
));
205 addFields(chunks
, newKey(key
), value
);
211 if (chunks
.length
> 0) queryString
.push($hash
);
212 queryString
.push(chunks
.join($separator
));
214 return queryString
.join("");
218 return new queryObject(location
.search
, location
.hash
);
220 }(jQuery
.query
|| {}); // Pass in jQuery.query as settings object