-/* This file is part of Syj, Copyright (c) 2010 Arnaud Renevier,
+/* This file is part of Syj, Copyright (c) 2010-2011 Arnaud Renevier,
and is published under the AGPL license. */
+"use strict";
+
var CloseBtn = Class.create({
initialize: function(elt, options) {
var btn, imgsrc, style;
return;
}
+ if (typeof options !== "object") {
+ options = {};
+ }
+
style = Object.extend({
- float: "right",
+ 'float': "right",
margin: "2px",
fontWeight: "bold",
padding: "0px"
- }, typeof options === "object" ? options.style: {});
+ }, options.style);
- imgsrc = (options && options.closeBtnSrc) || "icons/close.png";
+ imgsrc = (options.closeBtnSrc) || "icons/close.png";
btn = new Element("input", { type: "image", src: imgsrc, alt: "X"}).setStyle(style);
elt.insert({top: btn});
btn.observe("click", function(evt) {
evt.stop();
+ if (evt.detail === 0) { // it's not a real click, possibly a submit event
+ return;
+ }
if (typeof options.callback === "function") {
options.callback.call(elt);
}
- elt.hide();
+ if (typeof elt.clearMessages === "function") {
+ elt.clearMessages();
+ } else {
+ elt.hide();
+ }
});
}
});
var Toggler = Class.create({
- initialize: function(target, options) {
- options = Object.extend({}, options);
- target = $(target).hide();
+ options: {},
- var openIcn = options.openIcn || 'icons/bullet_arrow_right.png',
- closeIcn = options.closeIcn || 'icons/bullet_arrow_down.png';
+ close: function() {
+ this.element.src = this.options.openIcn;
+ this.target.hide();
+ document.fire('toggler:close', this);
+ },
- this.element = new Element("img", { src: openIcn })
- .setStyle({ border: 'none', // in firefox, in image inside an anchor has a border
- verticalAlign: "middle"});
+ open: function() {
+ this.element.src = this.options.closeIcn;
+ this.target.show();
+ document.fire('toggler:open', this);
+ },
- this.element.observe('click', function(evt) {
- if (target.visible()) {
- evt.target.src = openIcn;
- target.hide();
- } else {
- evt.target.src = closeIcn;
- target.show();
- }
+ toggle: function(evt) {
+ if (evt && typeof evt.stop === "function") {
evt.stop();
- });
+ }
+ if (this.target.visible()) {
+ this.close();
+ } else {
+ this.open();
+ }
+ },
- if (options.initialShow) {
- target.show();
- this.element.src = closeIcn;
+ initialize: function(target, options) {
+ this.options = Object.extend({
+ openIcn: 'icons/bullet_arrow_right.png',
+ closeIcn: 'icons/bullet_arrow_down.png'
+ }, options);
+
+ this.target = $(target).hide();
+ this.element = new Element("img").setStyle({ border: 'none', // in firefox, in image inside an anchor has a border
+ verticalAlign: "middle"});
+ this.element.observe('click', this.toggle.bindAsEventListener(this));
+
+ if (this.options.autoOpen) {
+ this.open();
+ } else {
+ this.close();
}
}
});
Element.setStyle(element, {'backgroundColor': color});
Element.setStyle.delay(timeout, element, {'backgroundColor': current});
return element;
+ },
+ text: function(element, content) {
+ if (typeof content === "undefined") { // getter
+ if (element.nodeType === 8) {
+ return "";
+ } else if (element.nodeType === 3 || element.nodeType === 4) {
+ return element.nodeValue;
+ } else {
+ return $A(element.childNodes).inject("", function(acc, el) {
+ return acc + Element.text(el);
+ });
+ }
+ } else { // setter
+ var node = document.createTextNode(content);
+ element.update().appendChild(node);
+ return element;
+ }
}
});
// wrapper around Form.request that sets up the submit listener, stops the
// submit event, calls presubmit function, calls Form.request and calls a
-// postsubmit function
+// postsubmit function. If form has some visible and activated file inputs,
+// execute presubmit, but do not send the file with ajax.
Element.addMethods('form', {
ajaxize : function(form, options) {
var reqoptions;
options = Object.clone(options || {});
$(form).observe('submit', function(evt) {
- evt.stop(); // cancel form submission
reqoptions = Object.clone(options);
delete(reqoptions.presubmit);
if (Object.isFunction(options.presubmit)) {
if (options.presubmit(this) === false) {
+ evt.stop(); // cancel form submission
return;
}
}
+ // get list of input file not disabled, and not hidden
+ if (this.getInputs('file').find(function(elt) {
+ if (elt.disabled) {
+ return false;
+ }
+ while (elt && $(elt).identify() !== this.identify()) {
+ if (!elt.visible()) {
+ return false;
+ }
+ elt = elt.parentNode;
+ }
+ return true;
+ }.bind(this))) {
+ // form has some file inputs. Do not manage on our own.
+ return;
+ }
+
+ evt.stop(); // cancel form submission
+
var params = reqoptions.parameters, action = this.readAttribute('action') || '';
if (action.blank()) {
reqoptions.method = this.method;
}
+ if (reqoptions.onFailure) {
+ reqoptions.onFailure = reqoptions.onFailure.wrap(function(proceed, transport, json) {
+ form.enable();
+ proceed(transport, json);
+ });
+ } else {
+ reqoptions.onFailure = function() {
+ form.enable();
+ };
+ }
+
+ if (reqoptions.onSuccess) {
+ reqoptions.onSuccess = reqoptions.onSuccess.wrap(function(proceed, transport, json) {
+ form.enable();
+ proceed(transport, json);
+ });
+ } else {
+ reqoptions.onSuccess = function() {
+ form.enable();
+ };
+ }
+
new Ajax.TimedRequest(action, options.delay || 20, reqoptions);
if (Object.isFunction(options.postsubmit)) {
options.postsubmit(this);
}
+ Form.getElements(form).each(function(elt) {
+ elt.blur();
+ elt.disable();
+ });
});
},
}
handler.apply(null, arguments);
});
- proceed(element, 'paste', handler);
+ proceed(element, 'paste', handler.defer.bind(handler));
return proceed(element, 'change', handler);
}
return proceed(element, eventName, handler);
}
});
-Element.addMethods('div', {
- setMessage: function(div, message, status) {
- div.clearMessages();
- if (status) {
- div.setMessageStatus(status);
+Element.addMethods('div', (function() {
+ var supportsTransition = false, endTransitionEventName = null;
+
+ if (window.addEventListener) { // fails badly in ie: prevents page from loading
+ var div = $(document.createElement('div'));
+ var timeout = null;
+
+ var cleanup = function() {
+ if (timeout) {
+ window.clearTimeout(timeout);
+ timeout = null;
+ div.stopObserving('webkitTransitionEnd');
+ div.stopObserving('transitionend');
+ div.stopObserving('oTransitionend');
+ Element.remove.defer(div);
+ }
}
- if (message) {
- div.addMessage(message);
+
+ var handler = function(e) {
+ supportsTransition = true;
+ endTransitionEventName = e.type;
+ cleanup();
}
- return div;
- },
+ div.observe('webkitTransitionEnd', handler).observe('transitionend', handler) .observe('oTransitionend', handler);
+ div.setStyle({'transitionProperty': 'opacity',
+ 'MozTransitionProperty': 'opacity',
+ 'WebkitTransitionProperty': 'opacity',
+ 'OTransitionProperty': 'opacity',
+ 'transitionDuration': '1ms',
+ 'MozTransitionDuration': '1ms',
+ 'WebkitTransitionDuration': '1ms',
+ 'OTransitionDuration': '1ms'});
+ $(document.documentElement).insert(div);
+ Element.setOpacity.defer(div, 0);
+ window.setTimeout(cleanup, 100);
+ }
- clearMessages: function(div) {
+ function removeMessages(div) {
var node = div.firstChild, nextNode;
while (node) {
nextNode = node.nextSibling;
- if (node.nodeType === 3 || node.tagName.toLowerCase() === 'br') {
+ if (node.nodeType === 3 || node.tagName.toLowerCase() === 'br' || node.textContent || node.innerText) {
div.removeChild(node);
}
node = nextNode;
}
+ return div;
+ };
+
+ function hasOpacityTransition(div) {
+ return ([div.getStyle('transition-property'),
+ div.getStyle('-moz-transition-property'),
+ div.getStyle('-webkit-transition-property'),
+ div.getStyle('-o-transition-property')
+ ].join(' ').split(' ').indexOf('opacity') !== -1);
+ }
+
+ function hide(div) {
+ div = $(div);
+ if (supportsTransition && hasOpacityTransition(div)) {
+ div.observe(endTransitionEventName, function() {
+ div.stopObserving(endTransitionEventName);
+ div.hide();
+ });
+ div.setOpacity(0);
+ } else {
+ div.hide();
+ }
+ }
+ function show(div) {
+ div = $(div);
+ div.show();
+ // we need to set opacity to 0 before calling hasOpacityTransition
+ // otherwise we trigger mozilla #601190
+ div.setOpacity(0);
+ if (supportsTransition && hasOpacityTransition(div)) {
+ // display = '' then opacity = 1;
+ Element.setOpacity.defer(div, 1);
+ } else {
+ div.setOpacity(1);
+ }
+ }
+
+ function clearMessages(div) {
+ if (div.visible()) {
+ hide(div);
+ }
return div;
- },
+ }
- addMessage: function(div, message) {
+ function setMessage(div, message, status) {
+ removeMessages(div);
+ if (status) {
+ div.setMessageStatus(status);
+ }
+ if (message) {
+ div.addMessage(message);
+ }
+ return div;
+ }
+
+ function addMessage(div, message) {
var node = (div.ownerDocument || document).createTextNode(message);
if ($A(div.childNodes).filter(function(node) {
- return (node.nodeType === 3 || node.tagName.toLowerCase() === 'br');
+ return (node.nodeType === 3 || node.tagName.toLowerCase() === 'br' || node.textContent || node.innerText);
}).length) {
div.insert(new Element('br'));
}
div.appendChild(node);
- return div.show();
- },
+ if (!div.visible()) {
+ show(div);
+ }
+ return div;
+ }
- setMessageStatus: function(div, status) {
- return div.removeClassName('error').
- removeClassName('warn').
- removeClassName('info').
- removeClassName('success').
- addClassName(status);
+ function setMessageStatus(div, status) {
+ $A(["error", "warn", "info", "success", "optional"]).each(function(clname) {
+ div.removeClassName(clname);
+ });
+ if (typeof status === "string") {
+ div.addClassName(status);
+ } else {
+ $A(status).each(function(clname) {
+ div.addClassName(clname);
+ });
+ }
+ return div;
}
-});
+
+ return {
+ setMessage: setMessage,
+ clearMessages: clearMessages,
+ addMessage: addMessage,
+ setMessageStatus: setMessageStatus
+ };
+
+})());