]> dev.renevier.net Git - syj.git/blob - public/js/utils.js
assemble all utils scripts in a utils.js file
[syj.git] / public / js / utils.js
1 /*  This file is part of Syj, Copyright (c) 2010 Arnaud Renevier,
2     and is published under the AGPL license. */
3
4 var CloseBtn = Class.create({
5     initialize: function(elt, options) {
6         var btn, imgsrc, style;
7
8         elt = $(elt);
9         if (!elt) {
10             return;
11         }
12
13         style = Object.extend({
14             float: "right",
15             margin: "2px",
16             fontWeight: "bold",
17             padding: "0px"
18         }, typeof options === "object" ? options.style: {});
19
20         imgsrc = (options && options.closeBtnSrc) || "icons/close.png";
21         btn = new Element("input", { type: "image", src: imgsrc, alt: "X"}).setStyle(style);
22         elt.insert({top: btn});
23         btn.observe("click", function(evt) {
24             elt.hide();
25         });
26     }
27 });
28
29 var Deck = Class.create({
30     initialize: function(elt, options) {
31         this.element = $(elt);
32         this.index = null;
33         this.setIndex(parseInt(this.element.readAttribute("selectedindex") || 0, 10));
34     },
35     setIndex: function(idx) {
36         if (idx === this.index) {
37             return;
38         }
39
40         var childs = this.element.childElements();
41         if (childs.length === 0) {
42             this.index = -1;
43             return;
44         }
45         idx = Math.max(0, idx);
46         idx = Math.min(childs.length - 1, idx);
47
48         childs.each(function(item, i) {
49             if (idx === i) {
50                 item.show();
51             } else {
52                 item.hide();
53             }
54         });
55         this.index = idx;
56     },
57     getIndex: function() {
58         return this.index;
59     }
60 });
61
62 Element.addMethods({
63     highlight: function(element, color, timeout) {
64         var current;
65         if (typeof timeout === "undefined") {
66             timeout = 0.3;
67         }
68         current = element.getStyle('backgroundColor');
69         Element.setStyle(element, {'backgroundColor': color});
70         Element.setStyle.delay(timeout, element, {'backgroundColor': current});
71         return element;
72     }
73 });
74
75 // wrapper around Form.request that sets up the submit listener, stops the
76 // submit event, calls presubmit function, calls Form.request and calls a
77 // postsubmit function
78 Element.addMethods('form', {
79     ajaxize : function(form, options) {
80         var reqoptions, timeout;
81
82         options = Object.clone(options);
83         reqoptions = Object.clone(options);
84         timeout = null;
85
86         function onSuccess(transport, json) {
87             if (timeout) {
88                 window.clearTimeout(timeout);
89                 timeout = null;
90             }
91             if (transport.getStatus() === 0) {
92                 options.onFailure(transport, json);
93             } else {
94                 options.onSuccess(transport, json);
95             }
96         }
97
98         function onFailure(transport, json) {
99             if (timeout) {
100                 window.clearTimeout(timeout);
101                 timeout = null;
102             }
103             options.onFailure(transport, json);
104         }
105
106         delete(reqoptions.presubmit);
107         delete(reqoptions.postsubmit);
108
109         $(form).observe('submit', function(evt) {
110             var req;
111
112             evt.stop(); // cancel form submission
113             if (Object.isFunction(options.presubmit)) {
114                 if (options.presubmit(this) === false) {
115                     return;
116                 }
117             }
118             req = this.request(Object.extend(reqoptions, {
119                 onSuccess: onSuccess,
120                 onFailure: onFailure
121             }));
122             timeout = (function() {
123                 options.onFailure(null);
124                 req.abort();
125             }).delay(options.timeout || 20);
126             if (Object.isFunction(options.postsubmit)) {
127                 options.postsubmit(this);
128             }
129         });
130     },
131
132     focus: function(form) {
133         var tofocus, error;
134
135         tofocus = null;
136         error = form.down('.error');
137         if (error) {
138             tofocus = error.previous('input,textarea');
139         } else {
140             tofocus = form.down('input:not([readonly],[disabled]),textarea:not([readonly][disabled])');
141         }
142         if (tofocus) {
143             if (error && (typeof tofocus.highlight === "function")) {
144                 tofocus.highlight('#F08080');
145             }
146             tofocus.focus();
147             tofocus.select();
148         }
149     },
150
151     checkEmptyElements: function(form, errorMessage) {
152         var results = [];
153         form.select('.required').each(function(elt) {
154             var id = elt.getAttribute('for'), control = $(id);
155             if (!control) {
156                 return;
157             }
158             if (!control.check(function() {
159                     return !this.value.strip().empty();
160                 }, errorMessage)) {
161                 results.push(control);
162             }
163         });
164         return results;
165     }
166 });
167
168 Element.addMethods(['input', 'textarea'], {
169     check: function(control, callback, errorMessage) {
170         if (callback.call(control)) {
171             return true;
172         }
173         control.insert({
174             after: new Element("div", {className: 'error'}).update(errorMessage)
175         });
176         return false;
177     }
178 });
179
180 Element.addMethods('div', {
181     setMessage: function(div, message, status) {
182         div.clearMessages();
183         if (status) {
184             div.setMessageStatus(status);
185         }
186         if (message) {
187             div.addMessage(message);
188         }
189         return div;
190     },
191
192     clearMessages: function(div) {
193         var node = div.firstChild, nextNode;
194
195         while (node) {
196             nextNode = node.nextSibling;
197             if (node.nodeType === 3 || node.tagName.toLowerCase() === 'br') {
198                 div.removeChild(node);
199             }
200                 node = nextNode;
201         }
202
203         return div;
204     },
205
206     addMessage: function(div, message) {
207         var node = (div.ownerDocument || document).createTextNode(message);
208         if (!div.empty()) {
209             div.insert(new Element('br'));
210         }
211         div.appendChild(node);
212         return div.show();
213     },
214
215     setMessageStatus: function(div, status) {
216         return div.removeClassName('error').
217                 removeClassName('warn').
218                 removeClassName('info').
219                 removeClassName('success').
220                 addClassName(status);
221     }
222 });