1 /* This file is part of Syj, Copyright (c) 2010 Arnaud Renevier,
2 and is published under the AGPL license. */
4 var CloseBtn = Class.create({
5 initialize: function(elt, options) {
6 var btn, imgsrc, style;
13 if (typeof options !== "object") {
17 style = Object.extend({
24 imgsrc = (options.closeBtnSrc) || "icons/close.png";
25 btn = new Element("input", { type: "image", src: imgsrc, alt: "X"}).setStyle(style);
26 elt.insert({top: btn});
27 btn.observe("click", function(evt) {
29 if (typeof options.callback === "function") {
30 options.callback.call(elt);
37 var Toggler = Class.create({
41 this.element.src = this.options.openIcn;
43 document.fire('toggler:close', this);
47 this.element.src = this.options.closeIcn;
49 document.fire('toggler:open', this);
52 toggle: function(evt) {
53 if (evt && typeof evt.stop === "function") {
56 if (this.target.visible()) {
63 initialize: function(target, options) {
64 this.options = Object.extend({
65 openIcn: 'icons/bullet_arrow_right.png',
66 closeIcn: 'icons/bullet_arrow_down.png'
69 this.target = $(target).hide();
70 this.element = new Element("img").setStyle({ border: 'none', // in firefox, in image inside an anchor has a border
71 verticalAlign: "middle"});
72 this.element.observe('click', this.toggle.bindAsEventListener(this));
74 if (this.options.autoOpen) {
82 var Deck = Class.create({
83 initialize: function(elt, options) {
84 this.element = $(elt);
86 this.setIndex(parseInt(this.element.readAttribute("selectedindex") || 0, 10));
88 setIndex: function(idx) {
89 if (idx === this.index) {
93 var childs = this.element.childElements();
94 if (childs.length === 0) {
98 idx = Math.max(0, idx);
99 idx = Math.min(childs.length - 1, idx);
101 childs.each(function(item, i) {
110 getIndex: function() {
116 highlight: function(element, color, timeout) {
118 if (typeof timeout === "undefined") {
121 current = element.getStyle('backgroundColor');
122 Element.setStyle(element, {'backgroundColor': color});
123 Element.setStyle.delay(timeout, element, {'backgroundColor': current});
128 Ajax.TimedRequest = Class.create(Ajax.Request, {
133 // see http://blog.pothoven.net/2007/12/aborting-ajax-requests-for-prototypejs.html
134 this.transport.onreadystatechange = Prototype.emptyFunction;
135 this.transport.abort();
136 Ajax.activeRequestCount--;
139 initialize: function($super, url, delay, options) {
145 options.onSuccess = options.onSuccess &&
146 options.onSuccess.wrap(function(proceed, transport, json) {
148 window.clearTimeout(this.timeout);
151 if (transport.getStatus() === 0) {
152 this.options.onFailure(transport, json);
154 proceed(transport, json);
158 options.onFailure = options.onFailure &&
159 options.onFailure.wrap(function(proceed, transport, json) {
161 window.clearTimeout(this.timeout);
164 proceed(transport, json);
167 $super(url, options);
170 request: function($super, url) {
171 this.timeout = function() {
172 if (this.options.onFailure) {
173 this.options.onFailure(null);
176 }.bind(this).delay(this.delay);
181 Ajax.Responders.register({
182 // needed for Ajax.TimedRequest.abort to work: see
183 // http://blog.pothoven.net/2007/12/aborting-ajax-requests-for-prototypejs.html
185 onComplete: function() {
186 Ajax.activeRequestCount--;
187 if (Ajax.activeRequestCount < 0) {
188 Ajax.activeRequestCount = 0;
193 // wrapper around Form.request that sets up the submit listener, stops the
194 // submit event, calls presubmit function, calls Form.request and calls a
195 // postsubmit function
196 Element.addMethods('form', {
197 ajaxize : function(form, options) {
200 options = Object.clone(options || {});
202 $(form).observe('submit', function(evt) {
203 evt.stop(); // cancel form submission
205 reqoptions = Object.clone(options);
206 delete(reqoptions.presubmit);
207 delete(reqoptions.postsubmit);
208 delete(reqoptions.delay);
210 if (Object.isFunction(options.presubmit)) {
211 if (options.presubmit(this) === false) {
216 var params = reqoptions.parameters, action = this.readAttribute('action') || '';
218 if (action.blank()) {
219 action = window.location.href;
221 reqoptions.parameters = this.serialize(true);
224 if (Object.isString(params)) {
225 params = params.toQueryParams();
227 Object.extend(reqoptions.parameters, params);
230 if (this.hasAttribute('method') && !reqoptions.method) {
231 reqoptions.method = this.method;
234 if (reqoptions.onFailure) {
235 reqoptions.onFailure = reqoptions.onFailure.wrap(function(proceed, transport, json) {
237 proceed(transport, json);
240 reqoptions.onFailure = function() {
245 if (reqoptions.onSuccess) {
246 reqoptions.onSuccess = reqoptions.onSuccess.wrap(function(proceed, transport, json) {
248 proceed(transport, json);
251 reqoptions.onSuccess = function() {
256 new Ajax.TimedRequest(action, options.delay || 20, reqoptions);
258 if (Object.isFunction(options.postsubmit)) {
259 options.postsubmit(this);
261 Form.getElements(form).each(function(elt) {
268 setfocus: function(form) {
272 error = form.down('.error');
274 tofocus = error.previous('input,textarea');
276 tofocus = form.down('input:not([readonly],[disabled]),textarea:not([readonly][disabled])');
279 if (error && (typeof tofocus.highlight === "function")) {
280 tofocus.highlight('#F08080');
286 checkEmptyElements: function(form, errorMessage) {
288 form.select('.required').each(function(elt) {
289 var id = elt.getAttribute('for'), control = $(id);
293 if (!control.check(function() {
294 return !this.value.strip().empty();
296 results.push(control);
303 Element.addMethods(['input', 'textarea'], {
304 check: function(control, callback, errorMessage) {
305 if (callback.call(control)) {
309 after: new Element("div", {className: 'error'}).update(errorMessage)
314 observe : Element.Methods.observe.wrap(function(proceed, element, eventName, handler) {
315 if (eventName === "contentchange") {
316 proceed(element, 'keyup', function(evt) {
317 if (evt.keyCode === 13) {
320 handler.apply(null, arguments);
322 proceed(element, 'paste', handler);
323 return proceed(element, 'change', handler);
325 return proceed(element, eventName, handler);
328 timedobserve: function(element, callback, delay) {
329 var timeout = null, initialvalue = element.value;
331 if (typeof delay !== "number") {
334 delay = delay * 1000;
336 var canceltimer = function() {
338 clearTimeout(timeout);
342 var resettimer = function() {
344 timeout = setTimeout(triggercallback, delay);
346 var triggercallback = function() {
348 if (initialvalue !== element.value) {
349 initialvalue = element.value;
350 callback.call(element);
354 element.observe('blur', triggercallback).
355 observe('keyup', resettimer).
356 observe('paste', resettimer);
361 Element.addMethods('div', {
362 setMessage: function(div, message, status) {
365 div.setMessageStatus(status);
368 div.addMessage(message);
373 clearMessages: function(div) {
374 var node = div.firstChild, nextNode;
377 nextNode = node.nextSibling;
378 if (node.nodeType === 3 || node.tagName.toLowerCase() === 'br') {
379 div.removeChild(node);
387 addMessage: function(div, message) {
388 var node = (div.ownerDocument || document).createTextNode(message);
390 if ($A(div.childNodes).filter(function(node) {
391 return (node.nodeType === 3 || node.tagName.toLowerCase() === 'br');
393 div.insert(new Element('br'));
396 div.appendChild(node);
400 setMessageStatus: function(div, status) {
401 return div.removeClassName('error').
402 removeClassName('warn').
403 removeClassName('info').
404 removeClassName('success').
405 addClassName(status);