]>
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 | ||
8944281a JF |
193 | append: function (children) { |
194 | if ($.type(children) == "string") | |
195 | $.each(this, function (node) { | |
196 | var doc = $.document(node); | |
197 | ||
198 | // XXX: implement wrapper system | |
199 | var div = doc.createElement("div"); | |
200 | div.innerHTML = children; | |
201 | ||
202 | while (div.childNodes.length != 0) { | |
203 | var child = div.childNodes[0]; | |
204 | node.appendChild(child); | |
205 | } | |
206 | }); | |
207 | else | |
208 | $.each(this, function (node) { | |
209 | $.each(children, function (child) { | |
210 | node.appendChild(child); | |
211 | }); | |
212 | }); | |
213 | }, | |
214 | ||
215 | xpath: function (expression) { | |
216 | var value = $([]); | |
217 | ||
2bfeaf6f | 218 | $.each(this, function (node) { |
ad554f10 | 219 | var doc = $.document(node); |
8944281a JF |
220 | var results = doc.evaluate(expression, node, null, XPathResult.ANY_TYPE, null); |
221 | var result; | |
222 | while (result = results.iterateNext()) | |
223 | value.add([result]); | |
224 | }); | |
ad554f10 | 225 | |
8944281a JF |
226 | return value; |
227 | }, | |
ad554f10 | 228 | |
8944281a JF |
229 | clone: function (deep) { |
230 | return $($.map(this, function (node) { | |
231 | return node.cloneNode(deep); | |
232 | })); | |
ad554f10 JF |
233 | }, |
234 | ||
235 | descendants: function (expression) { | |
236 | var descendants = $([]); | |
237 | ||
238 | $.each(this, function (node) { | |
2bfeaf6f JF |
239 | var nodes = node.getElementsByTagName(expression); |
240 | descendants.add(nodes); | |
ad554f10 JF |
241 | }); |
242 | ||
243 | return descendants; | |
244 | }, | |
245 | ||
246 | remove: function () { | |
247 | $.each(this, function (node) { | |
248 | node.parentNode.removeChild(node); | |
249 | }); | |
ad554f10 JF |
250 | } |
251 | }; | |
252 | ||
253 | $.scroll = function (x, y) { | |
254 | window.scrollTo(x, y); | |
255 | }; | |
256 | ||
257 | // XXX: document.all? | |
258 | $.all = function (doc) { | |
2bfeaf6f | 259 | if (typeof doc == 'undefined') |
ad554f10 JF |
260 | doc = document; |
261 | return $(doc.getElementsByTagName("*")); | |
262 | }; | |
263 | ||
264 | $.inject = function (a, b) { | |
265 | if ($.type(a) == "string") { | |
266 | $.prototype[a] = function (value) { | |
2bfeaf6f | 267 | if (typeof value == 'undefined') |
ad554f10 JF |
268 | return $.map(this, function (node) { |
269 | return b.get(node); | |
270 | }); | |
271 | else | |
272 | $.each(this, function (node, value) { | |
273 | b.set(node, value); | |
274 | }, value); | |
275 | }; | |
276 | } else for (var name in a) | |
277 | $.inject(name, a[name]); | |
278 | }; | |
279 | ||
280 | $.inject({ | |
2bfeaf6f JF |
281 | _default: { |
282 | get: function (node) { | |
283 | return node.style.defaultValue; | |
284 | }, | |
285 | set: function (node, value) { | |
286 | node.style.defaultValue = value; | |
287 | } | |
288 | }, | |
289 | ||
ad554f10 JF |
290 | html: { |
291 | get: function (node) { | |
292 | return node.innerHTML; | |
293 | }, | |
294 | set: function (node, value) { | |
295 | node.innerHTML = value; | |
296 | } | |
297 | }, | |
298 | ||
299 | href: { | |
300 | get: function (node) { | |
301 | return node.href; | |
302 | }, | |
303 | set: function (node, value) { | |
304 | node.href = value; | |
305 | } | |
306 | }, | |
307 | ||
2bfeaf6f | 308 | name: { |
f464053e | 309 | get: function (node) { |
2bfeaf6f | 310 | return node.name; |
f464053e JF |
311 | }, |
312 | set: function (node, value) { | |
2bfeaf6f JF |
313 | node.name = value; |
314 | } | |
315 | }, | |
316 | ||
317 | parent: { | |
318 | get: function (node) { | |
319 | return node.parentNode; | |
f464053e JF |
320 | } |
321 | }, | |
322 | ||
0235116c JF |
323 | src: { |
324 | get: function (node) { | |
325 | return node.src; | |
326 | }, | |
327 | set: function (node, value) { | |
328 | node.src = value; | |
329 | } | |
330 | }, | |
331 | ||
2bfeaf6f JF |
332 | type: { |
333 | get: function (node) { | |
334 | return node.localName; | |
335 | } | |
336 | }, | |
337 | ||
ad554f10 JF |
338 | value: { |
339 | get: function (node) { | |
340 | return node.value; | |
341 | }, | |
342 | set: function (node, value) { | |
2bfeaf6f JF |
343 | // XXX: do I really need this? |
344 | if (true || node.localName != "select") | |
345 | node.value = value; | |
346 | else { | |
347 | var options = node.options; | |
348 | for (var i = 0, e = options.length; i != e; ++i) | |
349 | if (options[i].value == value) { | |
350 | if (node.selectedIndex != i) | |
351 | node.selectedIndex = i; | |
352 | break; | |
353 | } | |
354 | } | |
355 | } | |
356 | }, | |
357 | ||
358 | width: { | |
359 | get: function (node) { | |
360 | return node.offsetWidth; | |
ad554f10 JF |
361 | } |
362 | } | |
363 | }); | |
364 | ||
2bfeaf6f JF |
365 | // Query String Parsing {{{ |
366 | $.query = function () { | |
367 | var args = {}; | |
368 | ||
369 | var search = location.search; | |
370 | if (search != null) { | |
371 | _assert(search[0] == "?", "query string without ?"); | |
372 | ||
373 | var values = search.substring(1).split("&"); | |
374 | for (var index in values) { | |
375 | var value = values[index] | |
376 | var equal = value.indexOf("="); | |
377 | var name; | |
378 | ||
379 | if (equal == -1) { | |
380 | name = value; | |
381 | value = null; | |
382 | } else { | |
383 | name = value.substring(0, equal); | |
384 | value = value.substring(equal + 1); | |
385 | value = decodeURIComponent(value); | |
386 | } | |
387 | ||
388 | name = decodeURIComponent(name); | |
389 | if (typeof args[name] == "undefined") | |
390 | args[name] = []; | |
391 | if (value != null) | |
392 | args[name].push(value); | |
393 | } | |
394 | } | |
395 | ||
396 | return args; | |
397 | }; | |
398 | // }}} | |
ad554f10 JF |
399 | // Event Registration {{{ |
400 | // XXX: unable to remove registration | |
401 | $.prototype.event = function (event, _function) { | |
402 | $.each(this, function (node) { | |
403 | // XXX: smooth over this pointer ugliness | |
404 | if (node.addEventListener) | |
405 | node.addEventListener(event, _function, false); | |
406 | else if (node.attachEvent) | |
407 | node.attachEvent("on" + event, _function); | |
408 | else | |
409 | // XXX: multiple registration SNAFU | |
410 | node["on" + event] = _function; | |
411 | }); | |
412 | }; | |
413 | ||
414 | $.each([ | |
415 | "click", "load", "submit" | |
416 | ], function (event) { | |
417 | $.prototype[event] = function (_function) { | |
2bfeaf6f JF |
418 | if (typeof _function == 'undefined') |
419 | _assert(false, "undefined function to $.[event]"); | |
ad554f10 JF |
420 | else |
421 | this.event(event, _function); | |
422 | }; | |
423 | }); | |
424 | // }}} | |
425 | // Timed Animation {{{ | |
426 | $.interpolate = function (duration, event) { | |
427 | var start = new Date(); | |
428 | ||
429 | var next = function () { | |
430 | setTimeout(update, 0); | |
431 | }; | |
432 | ||
433 | var update = function () { | |
434 | var time = new Date() - start; | |
435 | ||
436 | if (time >= duration) | |
437 | event(1); | |
438 | else { | |
439 | event(time / duration); | |
440 | next(); | |
441 | } | |
442 | }; | |
443 | ||
444 | next(); | |
445 | }; | |
446 | // }}} | |
447 | // AJAX Requests {{{ | |
448 | // XXX: abstract and implement other cases | |
449 | $.xhr = function (url, method, headers, data, events) { | |
450 | var xhr = new XMLHttpRequest(); | |
451 | xhr.open(method, url, true); | |
452 | ||
453 | for (var name in headers) | |
454 | xhr.setRequestHeader(name.replace(/_/, "-"), headers[name]); | |
455 | ||
456 | if (events == null) | |
457 | events = {}; | |
458 | ||
459 | xhr.onreadystatechange = function () { | |
bde2d79b JF |
460 | if (xhr.readyState == 4) { |
461 | var status = xhr.status; | |
462 | var text = xhr.responseText; | |
463 | if (events.response != null) | |
464 | events.response(status, text); | |
7ec29c77 JF |
465 | if (status == 200) { |
466 | if (events.success != null) | |
bde2d79b | 467 | events.success(text); |
7ec29c77 JF |
468 | } else { |
469 | if (events.failure != null) | |
470 | events.failure(status); | |
471 | } | |
bde2d79b | 472 | } |
ad554f10 JF |
473 | }; |
474 | ||
475 | xhr.send(data); | |
476 | }; | |
477 | ||
478 | $.call = function (url, post, onsuccess) { | |
479 | var events = {}; | |
480 | ||
481 | if (onsuccess != null) | |
482 | events.complete = function (text) { | |
483 | onsuccess(eval(text)); | |
484 | }; | |
485 | ||
486 | if (post == null) | |
487 | $.xhr(url, "POST", null, null, events); | |
488 | else | |
489 | $.xhr(url, "POST", { | |
490 | Content_Type: "application/json" | |
491 | }, $.json(post), events); | |
492 | }; | |
493 | // }}} | |
494 | // WWW Form URL Encoder {{{ | |
495 | $.form = function (parameters) { | |
496 | var data = ""; | |
497 | ||
498 | var ampersand = false; | |
499 | for (var name in parameters) { | |
500 | if (!ampersand) | |
501 | ampersand = true; | |
502 | else | |
503 | data += "&"; | |
504 | ||
505 | var value = parameters[name]; | |
506 | ||
507 | data += escape(name); | |
508 | data += "="; | |
509 | data += escape(value); | |
510 | } | |
511 | ||
512 | return data; | |
513 | }; | |
514 | // }}} | |
515 | // JSON Serializer {{{ | |
516 | $.json = function (value) { | |
517 | if (value == null) | |
518 | return "null"; | |
519 | ||
520 | var type = $.type(value); | |
521 | ||
522 | if (type == "number") | |
523 | return value; | |
524 | else if (type == "string") | |
525 | return "\"" + value | |
526 | .replace(/\\/, "\\\\") | |
527 | .replace(/\t/, "\\t") | |
528 | .replace(/\r/, "\\r") | |
529 | .replace(/\n/, "\\n") | |
530 | .replace(/"/, "\\\"") | |
531 | + "\""; | |
532 | else if (value.constructor == Array) { | |
533 | var json = "["; | |
534 | var comma = false; | |
535 | ||
536 | for (var i = 0; i != value.length; ++i) { | |
537 | if (!comma) | |
538 | comma = true; | |
539 | else | |
540 | json += ","; | |
541 | ||
542 | json += $.json(value[i]); | |
543 | } | |
544 | ||
545 | return json + "]"; | |
546 | } else if ( | |
547 | value.constructor == Object && | |
548 | value.toString() == "[object Object]" | |
549 | ) { | |
550 | var json = "{"; | |
551 | var comma = false; | |
552 | ||
553 | for (var name in value) { | |
554 | if (!comma) | |
555 | comma = true; | |
556 | else | |
557 | json += ","; | |
558 | ||
559 | json += name + ":" + $.json(value[name]); | |
560 | } | |
561 | return json + "}"; | |
562 | } else { | |
563 | return value; | |
564 | } | |
565 | }; | |
566 | // }}} |