]>
Commit | Line | Data |
---|---|---|
2bfeaf6f JF |
1 | /* XXX: this message is ultra-lame */ |
2 | var _assert = function (expr, value) { | |
ad554f10 | 3 | if (!expr) { |
2bfeaf6f JF |
4 | var message = "_assert(" + value + ")"; |
5 | console.log(message); | |
ad554f10 JF |
6 | throw message; |
7 | } | |
8 | } | |
2bfeaf6f | 9 | |
ad554f10 JF |
10 | // Compatibility {{{ |
11 | if (typeof Array.prototype.push != "function") | |
12 | Array.prototype.push = function (value) { | |
13 | this[this.length] = value; | |
14 | }; | |
15 | // }}} | |
16 | ||
17 | var $ = function (arg, doc) { | |
18 | if (this.magic_ != $.prototype.magic_) | |
19 | return new $(arg); | |
20 | ||
2bfeaf6f JF |
21 | if (arg == null) |
22 | arg = []; | |
23 | ||
ad554f10 JF |
24 | var type = $.type(arg); |
25 | ||
26 | if (type == "function") | |
27 | $.ready(arg); | |
28 | else if (type == "string") { | |
2bfeaf6f | 29 | if (typeof doc == 'undefined') |
ad554f10 | 30 | doc = document; |
0235116c | 31 | if (arg.charAt(0) == '#') { |
2bfeaf6f JF |
32 | /* XXX: this is somewhat incorrect-a-porter */ |
33 | var element = doc.getElementById(arg.substring(1)); | |
34 | return $(element == null ? [] : [element]); | |
35 | } else if (arg.charAt(0) == '.') | |
36 | return $(doc.getElementsByClassName(arg.substring(1))); | |
37 | else | |
ad554f10 | 38 | return $([doc]).descendants(arg); |
2bfeaf6f JF |
39 | } else if (typeof arg.length != 'undefined') { |
40 | _assert(typeof doc == 'undefined', "non-query with document to $"); | |
41 | this.set(arg); | |
ad554f10 | 42 | return this; |
2bfeaf6f | 43 | } else _assert(false, "unknown argument to $: " + typeof arg); |
ad554f10 JF |
44 | }; |
45 | ||
f464053e JF |
46 | $.xml = function (value) { |
47 | return value | |
48 | .replace(/&/, "&") | |
49 | .replace(/</, "<") | |
50 | .replace(/>/, ">") | |
51 | .replace(/"/, """) | |
52 | .replace(/'/, "'") | |
53 | ; | |
54 | } | |
55 | ||
ad554f10 JF |
56 | $.type = function (value) { |
57 | var type = typeof value; | |
58 | ||
2bfeaf6f JF |
59 | if ((type == "function" || type == "object") && value.toString != null) { |
60 | var string = value.toString(); | |
61 | if (string.substring(0, 8) == "[object ") | |
62 | return string.substring(8, string.length - 1); | |
63 | } | |
64 | ||
65 | return type; | |
ad554f10 JF |
66 | }; |
67 | ||
68 | (function () { | |
69 | var ready_ = null; | |
70 | ||
71 | $.ready = function (_function) { | |
72 | if (ready_ == null) { | |
73 | ready_ = []; | |
74 | ||
75 | document.addEventListener("DOMContentLoaded", function () { | |
76 | for (var i = 0; i != ready_.length; ++i) | |
77 | ready_[i](); | |
78 | }, false); | |
79 | } | |
80 | ||
81 | ready_.push(_function); | |
82 | }; | |
83 | })(); | |
84 | ||
85 | /* XXX: verify arg3 overflow */ | |
86 | $.each = function (values, _function, arg0, arg1, arg2) { | |
87 | for (var i = 0, e = values.length; i != e; ++i) | |
88 | _function(values[i], arg0, arg1, arg2); | |
89 | }; | |
90 | ||
91 | /* XXX: verify arg3 overflow */ | |
92 | $.map = function (values, _function, arg0, arg1, arg2) { | |
93 | var mapped = []; | |
94 | for (var i = 0, e = values.length; i != e; ++i) | |
95 | mapped.push(_function(values[i], arg0, arg1, arg2)); | |
96 | return mapped; | |
97 | }; | |
98 | ||
99 | $.array = function (values) { | |
100 | if (values.constructor == Array) | |
101 | return values; | |
2bfeaf6f | 102 | _assert(typeof values.length != 'undefined', "$.array on underlying non-array"); |
ad554f10 JF |
103 | var array = []; |
104 | for (var i = 0; i != values.length; ++i) | |
105 | array.push(values[i]); | |
106 | return array; | |
107 | }; | |
108 | ||
109 | $.document = function (node) { | |
110 | for (;;) { | |
111 | var parent = node.parentNode; | |
112 | if (parent == null) | |
113 | return node; | |
114 | node = parent; | |
115 | } | |
116 | }; | |
117 | ||
2bfeaf6f JF |
118 | $.reclass = function (_class) { |
119 | return new RegExp('(\\s|^)' + _class + '(\\s|$)'); | |
120 | }; | |
121 | ||
ad554f10 JF |
122 | $.prototype = { |
123 | magic_: 2041085062, | |
124 | ||
125 | add: function (nodes) { | |
2bfeaf6f JF |
126 | Array.prototype.push.apply(this, $.array(nodes)); |
127 | }, | |
128 | ||
129 | at: function (name, value) { | |
130 | if (typeof value == 'undefined') | |
131 | return $.map(this, function (node) { | |
132 | return node.getAttribute(name); | |
133 | }); | |
134 | else if (value == null) | |
135 | $.each(this, function (node) { | |
136 | node.removeAttribute(); | |
137 | }); | |
138 | else | |
139 | $.each(this, function (node) { | |
140 | node.setAttribute(name, value); | |
141 | }); | |
ad554f10 JF |
142 | }, |
143 | ||
144 | set: function (nodes) { | |
145 | this.length = 0; | |
146 | this.add(nodes); | |
147 | }, | |
148 | ||
2bfeaf6f JF |
149 | /* XXX: verify arg3 overflow */ |
150 | each: function (_function, arg0, arg1, arg2) { | |
151 | $.each(this, function (node) { | |
152 | _function($([node]), arg0, arg1, arg2); | |
153 | }); | |
154 | }, | |
155 | ||
ad554f10 JF |
156 | css: function (name, value) { |
157 | $.each(this, function (node) { | |
158 | node.style[name] = value; | |
159 | }); | |
160 | }, | |
161 | ||
2bfeaf6f JF |
162 | addClass: function (_class) { |
163 | $.each(this, function (node) { | |
164 | if (!$([node]).hasClass(_class)[0]) | |
165 | node.className += " " + _class; | |
166 | }); | |
167 | }, | |
168 | ||
169 | blur: function () { | |
170 | $.each(this, function (node) { | |
171 | node.blur(); | |
172 | }); | |
173 | }, | |
174 | ||
175 | focus: function () { | |
176 | $.each(this, function (node) { | |
177 | node.focus(); | |
178 | }); | |
179 | }, | |
180 | ||
181 | removeClass: function (_class) { | |
182 | $.each(this, function (node) { | |
183 | node.className = node.className.replace($.reclass(_class), ' '); | |
184 | }); | |
185 | }, | |
186 | ||
187 | hasClass: function (_class) { | |
188 | return $.map(this, function (node) { | |
189 | return node.className.match($.reclass(_class)); | |
190 | }); | |
191 | }, | |
192 | ||
ad554f10 | 193 | append: function (html) { |
2bfeaf6f | 194 | $.each(this, function (node) { |
ad554f10 JF |
195 | var doc = $.document(node); |
196 | ||
197 | // XXX: implement wrapper system | |
198 | var div = doc.createElement("div"); | |
199 | div.innerHTML = html; | |
200 | ||
201 | while (div.childNodes.length != 0) { | |
202 | var child = div.childNodes[0]; | |
203 | node.appendChild(child); | |
204 | } | |
205 | }); | |
206 | }, | |
207 | ||
208 | descendants: function (expression) { | |
209 | var descendants = $([]); | |
210 | ||
211 | $.each(this, function (node) { | |
2bfeaf6f JF |
212 | var nodes = node.getElementsByTagName(expression); |
213 | descendants.add(nodes); | |
ad554f10 JF |
214 | }); |
215 | ||
216 | return descendants; | |
217 | }, | |
218 | ||
219 | remove: function () { | |
220 | $.each(this, function (node) { | |
221 | node.parentNode.removeChild(node); | |
222 | }); | |
ad554f10 JF |
223 | } |
224 | }; | |
225 | ||
226 | $.scroll = function (x, y) { | |
227 | window.scrollTo(x, y); | |
228 | }; | |
229 | ||
230 | // XXX: document.all? | |
231 | $.all = function (doc) { | |
2bfeaf6f | 232 | if (typeof doc == 'undefined') |
ad554f10 JF |
233 | doc = document; |
234 | return $(doc.getElementsByTagName("*")); | |
235 | }; | |
236 | ||
237 | $.inject = function (a, b) { | |
238 | if ($.type(a) == "string") { | |
239 | $.prototype[a] = function (value) { | |
2bfeaf6f | 240 | if (typeof value == 'undefined') |
ad554f10 JF |
241 | return $.map(this, function (node) { |
242 | return b.get(node); | |
243 | }); | |
244 | else | |
245 | $.each(this, function (node, value) { | |
246 | b.set(node, value); | |
247 | }, value); | |
248 | }; | |
249 | } else for (var name in a) | |
250 | $.inject(name, a[name]); | |
251 | }; | |
252 | ||
253 | $.inject({ | |
2bfeaf6f JF |
254 | _default: { |
255 | get: function (node) { | |
256 | return node.style.defaultValue; | |
257 | }, | |
258 | set: function (node, value) { | |
259 | node.style.defaultValue = value; | |
260 | } | |
261 | }, | |
262 | ||
853d14d3 JF |
263 | display: { |
264 | get: function (node) { | |
265 | return node.style.display; | |
266 | }, | |
267 | set: function (node, value) { | |
268 | node.style.display = value; | |
269 | } | |
270 | }, | |
271 | ||
ad554f10 JF |
272 | html: { |
273 | get: function (node) { | |
274 | return node.innerHTML; | |
275 | }, | |
276 | set: function (node, value) { | |
277 | node.innerHTML = value; | |
278 | } | |
279 | }, | |
280 | ||
281 | href: { | |
282 | get: function (node) { | |
283 | return node.href; | |
284 | }, | |
285 | set: function (node, value) { | |
286 | node.href = value; | |
287 | } | |
288 | }, | |
289 | ||
2bfeaf6f | 290 | name: { |
f464053e | 291 | get: function (node) { |
2bfeaf6f | 292 | return node.name; |
f464053e JF |
293 | }, |
294 | set: function (node, value) { | |
2bfeaf6f JF |
295 | node.name = value; |
296 | } | |
297 | }, | |
298 | ||
299 | parent: { | |
300 | get: function (node) { | |
301 | return node.parentNode; | |
f464053e JF |
302 | } |
303 | }, | |
304 | ||
0235116c JF |
305 | src: { |
306 | get: function (node) { | |
307 | return node.src; | |
308 | }, | |
309 | set: function (node, value) { | |
310 | node.src = value; | |
311 | } | |
312 | }, | |
313 | ||
2bfeaf6f JF |
314 | type: { |
315 | get: function (node) { | |
316 | return node.localName; | |
317 | } | |
318 | }, | |
319 | ||
ad554f10 JF |
320 | value: { |
321 | get: function (node) { | |
322 | return node.value; | |
323 | }, | |
324 | set: function (node, value) { | |
2bfeaf6f JF |
325 | // XXX: do I really need this? |
326 | if (true || node.localName != "select") | |
327 | node.value = value; | |
328 | else { | |
329 | var options = node.options; | |
330 | for (var i = 0, e = options.length; i != e; ++i) | |
331 | if (options[i].value == value) { | |
332 | if (node.selectedIndex != i) | |
333 | node.selectedIndex = i; | |
334 | break; | |
335 | } | |
336 | } | |
337 | } | |
338 | }, | |
339 | ||
340 | width: { | |
341 | get: function (node) { | |
342 | return node.offsetWidth; | |
ad554f10 JF |
343 | } |
344 | } | |
345 | }); | |
346 | ||
2bfeaf6f JF |
347 | // Query String Parsing {{{ |
348 | $.query = function () { | |
349 | var args = {}; | |
350 | ||
351 | var search = location.search; | |
352 | if (search != null) { | |
353 | _assert(search[0] == "?", "query string without ?"); | |
354 | ||
355 | var values = search.substring(1).split("&"); | |
356 | for (var index in values) { | |
357 | var value = values[index] | |
358 | var equal = value.indexOf("="); | |
359 | var name; | |
360 | ||
361 | if (equal == -1) { | |
362 | name = value; | |
363 | value = null; | |
364 | } else { | |
365 | name = value.substring(0, equal); | |
366 | value = value.substring(equal + 1); | |
367 | value = decodeURIComponent(value); | |
368 | } | |
369 | ||
370 | name = decodeURIComponent(name); | |
371 | if (typeof args[name] == "undefined") | |
372 | args[name] = []; | |
373 | if (value != null) | |
374 | args[name].push(value); | |
375 | } | |
376 | } | |
377 | ||
378 | return args; | |
379 | }; | |
380 | // }}} | |
ad554f10 JF |
381 | // Event Registration {{{ |
382 | // XXX: unable to remove registration | |
383 | $.prototype.event = function (event, _function) { | |
384 | $.each(this, function (node) { | |
385 | // XXX: smooth over this pointer ugliness | |
386 | if (node.addEventListener) | |
387 | node.addEventListener(event, _function, false); | |
388 | else if (node.attachEvent) | |
389 | node.attachEvent("on" + event, _function); | |
390 | else | |
391 | // XXX: multiple registration SNAFU | |
392 | node["on" + event] = _function; | |
393 | }); | |
394 | }; | |
395 | ||
396 | $.each([ | |
397 | "click", "load", "submit" | |
398 | ], function (event) { | |
399 | $.prototype[event] = function (_function) { | |
2bfeaf6f JF |
400 | if (typeof _function == 'undefined') |
401 | _assert(false, "undefined function to $.[event]"); | |
ad554f10 JF |
402 | else |
403 | this.event(event, _function); | |
404 | }; | |
405 | }); | |
406 | // }}} | |
407 | // Timed Animation {{{ | |
408 | $.interpolate = function (duration, event) { | |
409 | var start = new Date(); | |
410 | ||
411 | var next = function () { | |
412 | setTimeout(update, 0); | |
413 | }; | |
414 | ||
415 | var update = function () { | |
416 | var time = new Date() - start; | |
417 | ||
418 | if (time >= duration) | |
419 | event(1); | |
420 | else { | |
421 | event(time / duration); | |
422 | next(); | |
423 | } | |
424 | }; | |
425 | ||
426 | next(); | |
427 | }; | |
428 | // }}} | |
429 | // AJAX Requests {{{ | |
430 | // XXX: abstract and implement other cases | |
431 | $.xhr = function (url, method, headers, data, events) { | |
432 | var xhr = new XMLHttpRequest(); | |
433 | xhr.open(method, url, true); | |
434 | ||
435 | for (var name in headers) | |
436 | xhr.setRequestHeader(name.replace(/_/, "-"), headers[name]); | |
437 | ||
438 | if (events == null) | |
439 | events = {}; | |
440 | ||
441 | xhr.onreadystatechange = function () { | |
442 | if (xhr.readyState == 4) | |
443 | if (events.complete != null) | |
444 | events.complete(xhr.responseText); | |
445 | }; | |
446 | ||
447 | xhr.send(data); | |
448 | }; | |
449 | ||
450 | $.call = function (url, post, onsuccess) { | |
451 | var events = {}; | |
452 | ||
453 | if (onsuccess != null) | |
454 | events.complete = function (text) { | |
455 | onsuccess(eval(text)); | |
456 | }; | |
457 | ||
458 | if (post == null) | |
459 | $.xhr(url, "POST", null, null, events); | |
460 | else | |
461 | $.xhr(url, "POST", { | |
462 | Content_Type: "application/json" | |
463 | }, $.json(post), events); | |
464 | }; | |
465 | // }}} | |
466 | // WWW Form URL Encoder {{{ | |
467 | $.form = function (parameters) { | |
468 | var data = ""; | |
469 | ||
470 | var ampersand = false; | |
471 | for (var name in parameters) { | |
472 | if (!ampersand) | |
473 | ampersand = true; | |
474 | else | |
475 | data += "&"; | |
476 | ||
477 | var value = parameters[name]; | |
478 | ||
479 | data += escape(name); | |
480 | data += "="; | |
481 | data += escape(value); | |
482 | } | |
483 | ||
484 | return data; | |
485 | }; | |
486 | // }}} | |
487 | // JSON Serializer {{{ | |
488 | $.json = function (value) { | |
489 | if (value == null) | |
490 | return "null"; | |
491 | ||
492 | var type = $.type(value); | |
493 | ||
494 | if (type == "number") | |
495 | return value; | |
496 | else if (type == "string") | |
497 | return "\"" + value | |
498 | .replace(/\\/, "\\\\") | |
499 | .replace(/\t/, "\\t") | |
500 | .replace(/\r/, "\\r") | |
501 | .replace(/\n/, "\\n") | |
502 | .replace(/"/, "\\\"") | |
503 | + "\""; | |
504 | else if (value.constructor == Array) { | |
505 | var json = "["; | |
506 | var comma = false; | |
507 | ||
508 | for (var i = 0; i != value.length; ++i) { | |
509 | if (!comma) | |
510 | comma = true; | |
511 | else | |
512 | json += ","; | |
513 | ||
514 | json += $.json(value[i]); | |
515 | } | |
516 | ||
517 | return json + "]"; | |
518 | } else if ( | |
519 | value.constructor == Object && | |
520 | value.toString() == "[object Object]" | |
521 | ) { | |
522 | var json = "{"; | |
523 | var comma = false; | |
524 | ||
525 | for (var name in value) { | |
526 | if (!comma) | |
527 | comma = true; | |
528 | else | |
529 | json += ","; | |
530 | ||
531 | json += name + ":" + $.json(value[name]); | |
532 | } | |
533 | return json + "}"; | |
534 | } else { | |
535 | return value; | |
536 | } | |
537 | }; | |
538 | // }}} |