2 Last Modified: 29/01/07 14:16:09
5 A very small library with a lot of functionality
7 4mir Salihefendic (http://amix.dk) - amix@amix.dk
9 Copyright (c) 2006 Amir Salihefendic. All rights reserved.
10 Copyright (c) 2005 Bob Ippolito. All rights reserved.
11 http://www.opensource.org/licenses/mit-license.php
15 http://orangoo.com/AmiNation/AJS
27 ajaxErrorHandler: null,
30 // General accessor functions
32 getQueryArgument: function(var_name) {
33 var query = window.location.search.substring(1);
34 var vars = query.split("&");
35 for (var i=0;i<vars.length;i++) {
36 var pair = vars[i].split("=");
37 if (pair[0] == var_name) {
45 return (navigator.userAgent.toLowerCase().indexOf("msie") != -1 && navigator.userAgent.toLowerCase().indexOf("opera") == -1);
47 isNetscape7: function() {
48 return (navigator.userAgent.toLowerCase().indexOf("netscape") != -1 && navigator.userAgent.toLowerCase().indexOf("7.") != -1);
50 isSafari: function() {
51 return (navigator.userAgent.toLowerCase().indexOf("khtml") != -1);
54 return (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
56 isMozilla: function() {
57 return (navigator.userAgent.toLowerCase().indexOf("gecko") != -1 && navigator.productSub >= 20030210);
65 createArray: function(v) {
66 if(AJS.isArray(v) && !AJS.isString(v))
74 forceArray: function(args) {
76 AJS.map(args, function(elm) {
82 join: function(delim, list) {
84 return list.join(delim);
87 var r = list[0] || '';
88 AJS.map(list, function(elm) {
95 isIn: function(elm, list) {
96 var i = AJS.getIndex(elm, list);
103 getIndex: function(elm, list/*optional*/, eval_fn) {
104 for(var i=0; i < list.length; i++)
105 if(eval_fn && eval_fn(list[i]) || elm == list[i])
110 getFirst: function(list) {
117 getLast: function(list) {
119 return list[list.length-1];
124 update: function(l1, l2) {
130 flattenList: function(list) {
132 var _flatten = function(r, l) {
133 AJS.map(l, function(o) {
135 else if (AJS.isArray(o))
147 // Functional programming
149 map: function(list, fn,/*optional*/ start_index, end_index) {
150 var i = 0, l = list.length;
156 fn.apply(null, [list[i], i]);
159 rmap: function(list, fn) {
160 var i = list.length-1, l = 0;
162 fn.apply(null, [list[i], i]);
165 filter: function(list, fn, /*optional*/ start_index, end_index) {
167 AJS.map(list, function(elm) {
170 }, start_index, end_index);
174 partial: function(fn) {
175 var args = AJS.forceArray(arguments);
176 return AJS.$b(fn, null, args.slice(1, args.length).reverse(), false, true);
184 getElement: function(id) {
185 if(AJS.isString(id) || AJS.isNumber(id))
186 return document.getElementById(id);
192 getElements: function(/*id1, id2, id3*/) {
193 var args = AJS.forceArray(arguments);
194 var elements = new Array();
195 for (var i = 0; i < args.length; i++) {
196 var element = AJS.getElement(args[i]);
197 elements.push(element);
202 //Shortcut: AJS.$bytc
203 getElementsByTagAndClassName: function(tag_name, class_name, /*optional*/ parent) {
204 var class_elements = [];
205 if(!AJS.isDefined(parent))
207 if(!AJS.isDefined(tag_name))
210 var els = parent.getElementsByTagName(tag_name);
211 var els_len = els.length;
212 var pattern = new RegExp("(^|\\s)" + class_name + "(\\s|$)");
214 for (i = 0, j = 0; i < els_len; i++) {
215 if ( pattern.test(els[i].className) || class_name == null ) {
216 class_elements[j] = els[i];
220 return class_elements;
223 _nodeWalk: function(elm, tag_name, class_name, fn_next_elm) {
224 var p = fn_next_elm(elm);
227 if(tag_name && class_name) {
228 checkFn = function(p) {
229 return AJS.nodeName(p) == tag_name && AJS.hasClass(p, class_name);
233 checkFn = function(p) { return AJS.nodeName(p) == tag_name; }
236 checkFn = function(p) { return AJS.hasClass(p, class_name); }
247 getParentBytc: function(elm, tag_name, class_name) {
248 return AJS._nodeWalk(elm, tag_name, class_name, function(m) { return m.parentNode; });
251 getPreviousSiblingBytc: function(elm, tag_name, class_name) {
252 return AJS._nodeWalk(elm, tag_name, class_name, function(m) { return m.previousSibling; });
255 getNextSiblingBytc: function(elm, tag_name, class_name) {
256 return AJS._nodeWalk(elm, tag_name, class_name, function(m) { return m.nextSibling; });
260 getFormElement: function(form, name) {
263 AJS.map(form.elements, function(elm) {
264 if(elm.name && elm.name == name)
270 formContents: function(form) {
271 var form = AJS.$(form);
273 var fn = function(elms) {
274 AJS.map(elms, function(e) {
276 r[e.name] = e.value || '';
279 fn(AJS.$bytc('input', null, form));
280 fn(AJS.$bytc('textarea', null, form));
284 getBody: function() {
285 return AJS.$bytc('body')[0]
288 nodeName: function(elm) {
289 return elm.nodeName.toLowerCase();
292 hasParent: function(elm, parent_to_consider, max_look_up) {
293 if(elm == parent_to_consider)
297 return AJS.hasParent(elm.parentNode, parent_to_consider, max_look_up-1);
300 isElementHidden: function(elm) {
301 return elm.style.visibility == "hidden";
305 documentInsert: function(elm) {
306 if(typeof(elm) == 'string')
307 elm = AJS.HTML2DOM(elm);
308 document.write('<span id="dummy_holder"></span>');
309 AJS.swapDOM(AJS.$('dummy_holder'), elm);
312 cloner: function(element) {
314 return element.cloneNode(true);
318 appendToTop: function(elm/*, elms...*/) {
319 var args = AJS.forceArray(arguments).slice(1);
320 if(args.length >= 1) {
321 var first_child = elm.firstChild;
324 var t_elm = args.shift();
326 AJS.insertBefore(t_elm, first_child);
332 AJS.ACN.apply(null, arguments);
339 appendChildNodes: function(elm/*, elms...*/) {
340 if(arguments.length >= 2) {
341 AJS.map(arguments, function(n) {
352 replaceChildNodes: function(elm/*, elms...*/) {
354 while ((child = elm.firstChild))
355 elm.removeChild(child);
356 if (arguments.length < 2)
359 return AJS.appendChildNodes.apply(null, arguments);
363 insertAfter: function(elm, reference_elm) {
364 reference_elm.parentNode.insertBefore(elm, reference_elm.nextSibling);
368 insertBefore: function(elm, reference_elm) {
369 reference_elm.parentNode.insertBefore(elm, reference_elm);
373 showElement: function(/*elms...*/) {
374 var args = AJS.forceArray(arguments);
375 AJS.map(args, function(elm) { elm.style.display = ''});
378 hideElement: function(elm) {
379 var args = AJS.forceArray(arguments);
380 AJS.map(args, function(elm) { elm.style.display = 'none'});
383 swapDOM: function(dest, src) {
384 dest = AJS.getElement(dest);
385 var parent = dest.parentNode;
387 src = AJS.getElement(src);
388 parent.replaceChild(src, dest);
390 parent.removeChild(dest);
395 removeElement: function(/*elm1, elm2...*/) {
396 var args = AJS.forceArray(arguments);
397 AJS.map(args, function(elm) { AJS.swapDOM(elm, null); });
400 createDOM: function(name, attrs) {
402 elm = document.createElement(name);
404 if(AJS.isDict(attrs[i])) {
408 elm.style.cssText = attr;
409 else if(k == "class" || k == 'className')
410 elm.className = attr;
412 elm.setAttribute(k, attr);
421 AJS.map(attrs, function(n) {
423 if(AJS.isString(n) || AJS.isNumber(n))
431 _createDomShortcuts: function() {
433 "ul", "li", "td", "tr", "th",
434 "tbody", "table", "input", "span", "b",
435 "a", "div", "img", "button", "h1",
436 "h2", "h3", "br", "textarea", "form",
437 "p", "select", "option", "iframe", "script",
438 "center", "dl", "dt", "dd", "small",
441 var extends_ajs = function(elm) {
442 var c_dom = "return AJS.createDOM.apply(null, ['" + elm + "', arguments]);";
443 var c_fun_dom = 'function() { ' + c_dom + ' }';
444 eval("AJS." + elm.toUpperCase() + "=" + c_fun_dom);
446 AJS.map(elms, extends_ajs);
447 AJS.TN = function(text) { return document.createTextNode(text) };
450 getCssDim: function(dim) {
451 if(AJS.isString(dim))
456 getCssProperty: function(elm, prop) {
460 y = elm.currentStyle[prop];
461 else if (window.getComputedStyle)
462 y = document.defaultView.getComputedStyle(elm,null).getPropertyValue(prop);
466 setStyle: function(/*elm1, elm2..., property, new_value*/) {
467 var args = AJS.forceArray(arguments);
468 var new_val = args.pop();
469 var property = args.pop();
470 AJS.map(args, function(elm) {
471 elm.style[property] = AJS.getCssDim(new_val);
475 setWidth: function(/*elm1, elm2..., width*/) {
476 var args = AJS.forceArray(arguments);
477 args.splice(args.length-1, 0, 'width');
478 AJS.setStyle.apply(null, args);
480 setHeight: function(/*elm1, elm2..., height*/) {
481 var args = AJS.forceArray(arguments);
482 args.splice(args.length-1, 0, 'height');
483 AJS.setStyle.apply(null, args);
485 setLeft: function(/*elm1, elm2..., left*/) {
486 var args = AJS.forceArray(arguments);
487 args.splice(args.length-1, 0, 'left');
488 AJS.setStyle.apply(null, args);
490 setTop: function(/*elm1, elm2..., top*/) {
491 var args = AJS.forceArray(arguments);
492 args.splice(args.length-1, 0, 'top');
493 AJS.setStyle.apply(null, args);
495 setClass: function(/*elm1, elm2..., className*/) {
496 var args = AJS.forceArray(arguments);
498 AJS.map(args, function(elm) { elm.className = c});
500 addClass: function(/*elm1, elm2..., className*/) {
501 var args = AJS.forceArray(arguments);
502 var cls = args.pop();
503 var add_class = function(o) {
504 if(!new RegExp("(^|\\s)" + cls + "(\\s|$)").test(o.className))
505 o.className += (o.className ? " " : "") + cls;
507 AJS.map(args, function(elm) { add_class(elm); });
509 hasClass: function(elm, cls) {
512 return elm.className == cls ||
513 elm.className.search(new RegExp(" " + cls)) != -1
515 removeClass: function(/*elm1, elm2..., className*/) {
516 var args = AJS.forceArray(arguments);
517 var cls = args.pop();
518 var rm_class = function(o) {
519 o.className = o.className.replace(new RegExp("\\s?" + cls, 'g'), "");
521 AJS.map(args, function(elm) { rm_class(elm); });
524 setHTML: function(elm, html) {
525 elm.innerHTML = html;
529 RND: function(tmpl, ns, scope) {
530 scope = scope || window;
531 var fn = function(w, g) {
534 for(var i=1; i < g.length; i++)
535 cnt = scope[g[i]](cnt);
538 if(cnt == 0 || cnt == -1)
542 return tmpl.replace(/%\(([A-Za-z0-9_|.]*)\)/g, fn);
545 HTML2DOM: function(html,/*optional*/ first_child) {
549 return d.childNodes[0];
554 preloadImages: function(/*img_src1, ..., img_srcN*/) {
555 AJS.AEV(window, 'load', AJS.$p(function(args) {
556 AJS.map(args, function(src) {
557 var pic = new Image();
567 setOpacity: function(elm, p) {
568 elm.style.opacity = p;
569 elm.style.filter = "alpha(opacity="+ p*100 +")";
576 getXMLHttpRequest: function() {
578 function () { return new XMLHttpRequest(); },
579 function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
580 function () { return new ActiveXObject('Microsoft.XMLHTTP'); },
581 function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); },
582 function () { throw "Browser does not support XMLHttpRequest"; }
584 for (var i = 0; i < try_these.length; i++) {
585 var func = try_these[i];
593 getRequest: function(url, data, type) {
596 var req = AJS.getXMLHttpRequest();
598 if(url.indexOf("http://") == -1) {
599 if(AJS.BASE_URL != '') {
600 if(AJS.BASE_URL.lastIndexOf('/') != AJS.BASE_URL.length-1)
602 url = AJS.BASE_URL + url;
605 url = window.location + url;
608 req.open(type, url, true);
610 req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
611 return AJS._sendXMLHttpRequest(req);
614 _sendXMLHttpRequest: function(req, data) {
615 var d = new AJSDeferred(req);
617 var onreadystatechange = function () {
618 if (req.readyState == 4) {
624 if(status == 200 || status == 304 || req.responseText == null) {
628 if(AJS.ajaxErrorHandler)
629 AJS.ajaxErrorHandler(req.responseText, req);
635 req.onreadystatechange = onreadystatechange;
639 _reprString: function(o) {
640 return ('"' + o.replace(/(["\\])/g, '\\$1') + '"'
641 ).replace(/[\f]/g, "\\f"
642 ).replace(/[\b]/g, "\\b"
643 ).replace(/[\n]/g, "\\n"
644 ).replace(/[\t]/g, "\\t"
645 ).replace(/[\r]/g, "\\r");
648 serializeJSON: function(o) {
649 var objtype = typeof(o);
650 if (objtype == "undefined") {
652 } else if (objtype == "number" || objtype == "boolean") {
654 } else if (o === null) {
657 if (objtype == "string") {
658 return AJS._reprString(o);
660 var me = arguments.callee;
661 if (objtype != "function" && typeof(o.length) == "number") {
663 for (var i = 0; i < o.length; i++) {
665 if (typeof(val) != "string") {
670 return "[" + res.join(",") + "]";
672 // it's a function with no adapter, bad
673 if (objtype == "function")
678 if (typeof(k) == "number") {
679 useKey = '"' + k + '"';
680 } else if (typeof(k) == "string") {
681 useKey = AJS._reprString(k);
683 // skip non-string or number keys
687 if (typeof(val) != "string") {
688 // skip non-serializable values
691 res.push(useKey + ":" + val);
693 return "{" + res.join(",") + "}";
696 loadJSONDoc: function(url) {
697 var d = AJS.getRequest(url);
698 var eval_req = function(data, req) {
699 var text = req.responseText;
703 return AJS.evalTxt(text);
705 d.addCallback(eval_req);
709 evalTxt: function(txt) {
711 return eval('('+ txt + ')');
718 evalScriptTags: function(html) {
719 var script_data = html.match(/<script.*?>((\n|\r|.)*?)<\/script>/g);
720 if(script_data != null) {
721 for(var i=0; i < script_data.length; i++) {
722 var script_only = script_data[i].replace(/<script.*?>/g, "");
723 script_only = script_only.replace(/<\/script>/g, "");
729 queryArguments: function(data) {
732 post_data.push(k + "=" + AJS.urlencode(data[k]));
733 return post_data.join("&");
740 getMousePos: function(e) {
743 if (!e) var e = window.event;
744 if (e.pageX || e.pageY)
749 else if (e.clientX || e.clientY)
751 posx = e.clientX + document.body.scrollLeft;
752 posy = e.clientY + document.body.scrollTop;
754 return {x: posx, y: posy};
757 getScrollTop: function() {
758 //From: http://www.quirksmode.org/js/doctypes.html
760 if (document.documentElement && document.documentElement.scrollTop)
761 t = document.documentElement.scrollTop;
762 else if (document.body)
763 t = document.body.scrollTop;
767 absolutePosition: function(elm) {
768 var posObj = {'x': elm.offsetLeft, 'y': elm.offsetTop};
769 if(elm.offsetParent) {
770 var temp_pos = AJS.absolutePosition(elm.offsetParent);
771 posObj.x += temp_pos.x;
772 posObj.y += temp_pos.y;
775 if (AJS.isSafari() && elm.style.position == 'absolute' ) {
776 posObj.x -= document.body.offsetLeft;
777 posObj.y -= document.body.offsetTop;
782 getWindowSize: function(doc) {
783 doc = doc || document;
785 if (self.innerHeight) {
786 win_w = self.innerWidth;
787 win_h = self.innerHeight;
788 } else if (doc.documentElement && doc.documentElement.clientHeight) {
789 win_w = doc.documentElement.clientWidth;
790 win_h = doc.documentElement.clientHeight;
791 } else if (doc.body) {
792 win_w = doc.body.clientWidth;
793 win_h = doc.body.clientHeight;
795 return {'w': win_w, 'h': win_h};
798 isOverlapping: function(elm1, elm2) {
799 var pos_elm1 = AJS.absolutePosition(elm1);
800 var pos_elm2 = AJS.absolutePosition(elm2);
802 var top1 = pos_elm1.y;
803 var left1 = pos_elm1.x;
804 var right1 = left1 + elm1.offsetWidth;
805 var bottom1 = top1 + elm1.offsetHeight;
806 var top2 = pos_elm2.y;
807 var left2 = pos_elm2.x;
808 var right2 = left2 + elm2.offsetWidth;
809 var bottom2 = top2 + elm2.offsetHeight;
810 var getSign = function(v) {
811 if(v > 0) return "+";
812 else if(v < 0) return "-";
816 if ((getSign(top1 - bottom2) != getSign(bottom1 - top2)) &&
817 (getSign(left1 - right2) != getSign(right1 - left2)))
826 getEventElm: function(e) {
827 if(e && !e.type && !e.keyCode)
830 if (!e) var e = window.event;
831 if (e.target) targ = e.target;
832 else if (e.srcElement) targ = e.srcElement;
833 if (targ.nodeType == 3) // defeat Safari bug
834 targ = targ.parentNode;
838 _getRealScope: function(fn, /*optional*/ extra_args, dont_send_event, rev_extra_args) {
840 extra_args = AJS.$A(extra_args);
845 //Append all the orginal arguments + extra_args
851 AJS.map(arguments, function(arg) { args.push(arg) }, i);
852 args = args.concat(extra_args);
854 args = args.reverse();
855 return fn.apply(scope, args);
859 _unloadListeners: function() {
861 AJS.map(AJS.listeners, function(elm, type, fn) { AJS.REV(elm, type, fn) });
865 setEventKey: function(e) {
866 e.key = e.keyCode ? e.keyCode : e.charCode;
869 e.ctrl = window.event.ctrlKey;
870 e.shift = window.event.shiftKey;
874 e.shift = e.shiftKey;
893 addEventListener: function(elm, type, fn, /*optional*/listen_once, cancle_bubble) {
895 cancle_bubble = false;
897 var elms = AJS.$A(elm);
898 AJS.map(elms, function(elmz) {
900 fn = AJS._listenOnce(elmz, type, fn);
902 //Hack since it does not work in all browsers
903 if(AJS.isIn(type, ['submit', 'load', 'scroll', 'resize'])) {
904 var old = elm['on' + type];
905 elm['on' + type] = function() {
908 return old(arguments);
911 return fn(arguments);
917 if(AJS.isIn(type, ['keypress', 'keydown', 'keyup', 'click'])) {
921 return old_fn.apply(null, arguments);
925 if (elmz.attachEvent) {
926 //FIXME: We ignore cancle_bubble for IE... could be a problem?
927 elmz.attachEvent("on" + type, fn);
929 else if(elmz.addEventListener)
930 elmz.addEventListener(type, fn, cancle_bubble);
932 AJS.listeners = AJS.$A(AJS.listeners);
933 AJS.listeners.push([elmz, type, fn]);
938 removeEventListener: function(elm, type, fn, /*optional*/cancle_bubble) {
940 cancle_bubble = false;
941 if(elm.removeEventListener) {
942 elm.removeEventListener(type, fn, cancle_bubble);
944 elm.removeEventListener(type, fn, !cancle_bubble);
946 else if(elm.detachEvent)
947 elm.detachEvent("on" + type, fn);
951 bind: function(fn, scope, /*optional*/ extra_args, dont_send_event, rev_extra_args) {
953 return AJS._getRealScope(fn, extra_args, dont_send_event, rev_extra_args);
956 bindMethods: function(self) {
957 for (var k in self) {
959 if (typeof(func) == 'function') {
960 self[k] = AJS.$b(func, self);
965 _listenOnce: function(elm, type, fn) {
966 var r_fn = function() {
967 AJS.removeEventListener(elm, type, r_fn);
973 callLater: function(fn, interval) {
974 var fn_no_send = function() {
977 window.setTimeout(fn_no_send, interval);
980 preventDefault: function(e) {
982 window.event.returnValue = false;
991 dragAble: function(elm, /*optional*/ handler, args) {
994 if(!AJS.isDefined(args['move_x']))
995 args['move_x'] = true;
996 if(!AJS.isDefined(args['move_y']))
997 args['move_y'] = true;
998 if(!AJS.isDefined(args['moveable']))
999 args['moveable'] = false;
1000 if(!AJS.isDefined(args['hide_on_move']))
1001 args['hide_on_move'] = true;
1002 if(!AJS.isDefined(args['on_mouse_up']))
1003 args['on_mouse_up'] = null;
1004 if(!AJS.isDefined(args['cursor']))
1005 args['cursor'] = 'move';
1006 if(!AJS.isDefined(args['max_move']))
1007 args['max_move'] = {'top': null, 'left': null};
1014 handler = AJS.$(handler);
1015 var old_cursor = handler.style.cursor;
1016 handler.style.cursor = args['cursor'];
1017 elm.style.position = 'relative';
1019 AJS.addClass(handler, '_ajs_handler');
1020 handler._args = args;
1022 AJS.AEV(handler, 'mousedown', AJS._dragStart);
1025 _dragStart: function(e) {
1026 var handler = AJS.getEventElm(e);
1027 if(!AJS.hasClass(handler, '_ajs_handler')) {
1028 handler = AJS.getParentBytc(handler, null, '_ajs_handler');
1031 AJS._dragInit(e, handler._elm, handler._args);
1034 dropZone: function(elm, args) {
1036 var item = {elm: elm};
1037 AJS.update(item, args);
1038 AJS._drop_zones.push(item);
1041 removeDragAble: function(elm) {
1042 AJS.REV(elm, 'mousedown', AJS._dragStart);
1043 elm.style.cursor = '';
1046 removeDropZone: function(elm) {
1047 var i = AJS.getIndex(elm, AJS._drop_zones, function(item) {
1048 if(item.elm == elm) return true;
1051 AJS._drop_zones.splice(i, 1);
1055 _dragInit: function(e, click_elm, args) {
1056 AJS.drag_obj = new Object();
1057 AJS.drag_obj.args = args;
1059 AJS.drag_obj.click_elm = click_elm;
1060 AJS.drag_obj.mouse_pos = AJS.getMousePos(e);
1061 AJS.drag_obj.click_elm_pos = AJS.absolutePosition(click_elm);
1063 AJS.AEV(document, 'mousemove', AJS._dragMove, false, true);
1064 AJS.AEV(document, 'mouseup', AJS._dragStop, false, true);
1067 window.event.cancelBubble = true;
1068 AJS.preventDefault(e);
1071 _initDragElm: function(elm) {
1072 if(AJS.drag_elm && AJS.drag_elm.style.display == 'none')
1073 AJS.removeElement(AJS.drag_elm);
1076 AJS.drag_elm = AJS.DIV();
1077 var d = AJS.drag_elm;
1078 AJS.insertBefore(d, AJS.getBody().firstChild);
1079 AJS.setHTML(d, elm.innerHTML);
1081 d.className = elm.className;
1082 d.style.cssText = elm.style.cssText;
1084 d.style.position = 'absolute';
1085 d.style.zIndex = 10000;
1087 var t = AJS.absolutePosition(elm);
1089 AJS.setLeft(d, t.x);
1091 if(AJS.drag_obj.args.on_init) {
1092 AJS.drag_obj.args.on_init(elm);
1097 _dragMove: function(e) {
1098 var drag_obj = AJS.drag_obj;
1099 var click_elm = drag_obj.click_elm;
1101 AJS._initDragElm(click_elm);
1102 var drag_elm = AJS.drag_elm;
1104 if(drag_obj.args['hide_on_move'])
1105 click_elm.style.visibility = 'hidden';
1107 var cur_pos = AJS.getMousePos(e);
1109 var mouse_pos = drag_obj.mouse_pos;
1111 var click_elm_pos = drag_obj.click_elm_pos;
1113 AJS.map(AJS._drop_zones, function(d_z) {
1114 if(AJS.isOverlapping(d_z['elm'], drag_elm)) {
1115 if(d_z['elm'] != drag_elm) {
1116 var on_hover = d_z['on_hover'];
1118 on_hover(d_z['elm'], click_elm, drag_elm);
1123 if(drag_obj.args['on_drag'])
1124 drag_obj.args['on_drag'](click_elm, e);
1126 var max_move_top = drag_obj.args['max_move']['top'];
1127 var max_move_left = drag_obj.args['max_move']['left'];
1129 if(drag_obj.args['move_x']) {
1130 p = cur_pos.x - (mouse_pos.x - click_elm_pos.x);
1131 if(max_move_left == null || max_move_left <= p)
1132 AJS.setLeft(elm, p);
1135 if(drag_obj.args['move_y']) {
1136 p = cur_pos.y - (mouse_pos.y - click_elm_pos.y);
1137 if(max_move_top == null || max_move_top <= p)
1141 window.event.cancelBubble = true;
1142 window.event.returnValue = false;
1148 _dragStop: function(e) {
1149 var drag_obj = AJS.drag_obj;
1150 var drag_elm = AJS.drag_elm;
1151 var click_elm = drag_obj.click_elm;
1153 AJS.REV(document, "mousemove", AJS._dragMove, true);
1154 AJS.REV(document, "mouseup", AJS._dragStop, true);
1156 var dropped = false;
1157 AJS.map(AJS._drop_zones, function(d_z) {
1158 if(AJS.isOverlapping(d_z['elm'], click_elm)) {
1159 if(d_z['elm'] != click_elm) {
1160 var on_drop = d_z['on_drop'];
1163 on_drop(d_z['elm'], click_elm);
1169 if(drag_obj.args['moveable']) {
1170 var t = parseInt(click_elm.style.top) || 0;
1171 var l = parseInt(click_elm.style.left) || 0;
1172 var drag_elm_xy = AJS.absolutePosition(drag_elm);
1173 var click_elm_xy = AJS.absolutePosition(click_elm);
1174 AJS.setTop(click_elm, t + drag_elm_xy.y - click_elm_xy.y);
1175 AJS.setLeft(click_elm, l + drag_elm_xy.x - click_elm_xy.x);
1178 if(!dropped && drag_obj.args['on_mouse_up'])
1179 drag_obj.args['on_mouse_up'](click_elm, e);
1181 if(drag_obj.args['hide_on_move'])
1182 drag_obj.click_elm.style.visibility = 'visible';
1184 if(drag_obj.args.on_end) {
1185 drag_obj.args.on_end(click_elm);
1188 AJS._dragObj = null;
1190 AJS.hideElement(drag_elm);
1191 AJS.drag_elm = null;
1198 keys: function(obj) {
1200 for (var prop in obj) {
1206 values: function(obj) {
1208 for (var prop in obj) {
1209 rval.push(obj[prop]);
1214 urlencode: function(str) {
1215 return encodeURIComponent(str.toString());
1218 isDefined: function(o) {
1219 return (o != "undefined" && o != null)
1222 isArray: function(obj) {
1223 return obj instanceof Array;
1226 isString: function(obj) {
1227 return (typeof obj == 'string');
1230 isNumber: function(obj) {
1231 return (typeof obj == 'number');
1234 isObject: function(obj) {
1235 return (typeof obj == 'object');
1238 isFunction: function(obj) {
1239 return (typeof obj == 'function');
1242 isDict: function(o) {
1243 var str_repr = String(o);
1244 return str_repr.indexOf(" Object") != -1;
1247 exportToGlobalScope: function() {
1249 eval(e + " = AJS." + e);
1256 var div = AJS.DIV({'style': 'color: green'});
1257 AJS.ACN(AJS.getBody(), AJS.setHTML(div, ''+o));
1263 AJS.Class = function(members) {
1264 var fn = function() {
1265 if(arguments[0] != 'no_init') {
1266 return this.init.apply(this, arguments);
1269 fn.prototype = members;
1270 AJS.update(fn, AJS.Class.prototype);
1273 AJS.Class.prototype = {
1274 extend: function(members) {
1275 var parent = new this('no_init');
1277 var prev = parent[k];
1278 var cur = members[k];
1279 if (prev && prev != cur && typeof cur == 'function') {
1280 cur = this._parentize(cur, prev);
1284 return new AJS.Class(parent);
1287 implement: function(members) {
1288 AJS.update(this.prototype, members);
1291 _parentize: function(cur, prev) {
1294 return cur.apply(this, arguments);
1300 AJS.$ = AJS.getElement;
1301 AJS.$$ = AJS.getElements;
1302 AJS.$f = AJS.getFormElement;
1304 AJS.$p = AJS.partial;
1305 AJS.$FA = AJS.forceArray;
1306 AJS.$A = AJS.createArray;
1307 AJS.DI = AJS.documentInsert;
1308 AJS.ACN = AJS.appendChildNodes;
1309 AJS.RCN = AJS.replaceChildNodes;
1310 AJS.AEV = AJS.addEventListener;
1311 AJS.REV = AJS.removeEventListener;
1312 AJS.$bytc = AJS.getElementsByTagAndClassName;
1314 AJSDeferred = function(req) {
1315 this.callbacks = [];
1319 AJSDeferred.prototype = {
1320 excCallbackSeq: function(req, list) {
1321 var data = req.responseText;
1322 while (list.length > 0) {
1323 var fn = list.pop();
1324 var new_data = fn(data, req);
1330 callback: function () {
1331 this.excCallbackSeq(this.req, this.callbacks);
1334 errback: function() {
1335 if(this.errbacks.length == 0)
1336 alert("Error encountered:\n" + this.req.responseText);
1338 this.excCallbackSeq(this.req, this.errbacks);
1341 addErrback: function(fn) {
1342 this.errbacks.unshift(fn);
1345 addCallback: function(fn) {
1346 this.callbacks.unshift(fn);
1349 addCallbacks: function(fn1, fn2) {
1350 this.addCallback(fn1);
1351 this.addErrback(fn2);
1354 sendReq: function(data) {
1355 if(AJS.isObject(data)) {
1356 this.req.send(AJS.queryArguments(data));
1358 else if(AJS.isDefined(data))
1359 this.req.send(data);
1366 //Prevent memory-leaks
1367 AJS.addEventListener(window, 'unload', AJS._unloadListeners);
1368 AJS._createDomShortcuts()
1371 script_loaded = true;