ldapsaisie/src/includes/js/LSform.js
Benjamin Renard b42093cf45 Improve handling Ajax mode
- LSurlRequest: add ajax property to check if Ajax mode is enabled
- LSurl: handle_request() now handle Ajax mode detection
- LSsession :: setApiMode now trigger LSsession :: setAjaxDisplay()
- Fix LStemplate::fatal_error() to correctly handle Ajax mode
- LSform: fix reporting failure on Ajax submit
2021-11-16 13:59:17 +01:00

547 lines
16 KiB
JavaScript

var LSform = new Class({
initialize: function(){
this._modules=[];
this._fields=[];
this._elements=[];
this.listeners = new Hash({
init: new Hash(),
submit: new Hash()
});
this.listeners_answers = new Hash();
// On non-ajax submit form, store confirmation status;
this.submit_confirmed = false;
if ($type($('LSform_idform'))) {
this.objecttype = $('LSform_objecttype').value;
this.objectdn = $('LSform_objectdn').value;
this.idform = $('LSform_idform').value;
}
this.submitting = false;
this.initializeLSform();
this.initializeLSformLayout();
},
initializeLSform: function(el) {
this.params={};
if (this.idform) {
if (typeof(el) == 'undefined') {
el = document;
}
el.getElements('ul.LSform').each(function(ul) {
this._elements[ul.id] = new LSformElement(this,ul.id,ul);
}, this);
this.params=varLSdefault.LSjsConfig['LSform_'+this.idform];
if (!$type(this.params)) {
this.params={};
}
this._ajaxSubmit=this.params.ajaxSubmit;
LSdebug('LSform('+this.idform+'): ajaxSubmit='+this._ajaxSubmit);
this.warnBox = new LSinfosBox({
name: 'LSformWarnBox',
fxDuration: 600,
closeBtn: 1,
autoClose: 0
});
if ($type(this.params.warnings)) {
this.warnTxt = '<ul>';
this.params.warnings.each(function(w) {
this.warnTxt +='<li>'+w+'</li>';
},this);
this.warnTxt += '</ul>';
this.warnBox.display(this.warnTxt);
}
LSdebug(this.params);
this.listAvailableDataEntryForm=$('LSform_listAvailableDataEntryForm');
if ($type(this.listAvailableDataEntryForm)) {
this.listAvailableDataEntryForm.addEvent('change',this.onListAvailableDataEntryFormChange.bind(this));
}
}
LSforms = $$('form.LSform');
if ($type(LSforms[0])) {
this.LSform = LSforms[0];
this.LSform.addEvent('submit',this.onSubmit.bindWithEvent(this));
}
this.fireEvent.bind(this)('init');
},
initializeLSformLayout: function(el) {
$$('.LSform_layout').each(function(el) {
el.addClass('LSform_layout_active');
},this);
var LIs = $$('li.LSform_layout');
LIs.each(function(li) {
var Layout = this.getLayout(li);
if ($type(Layout)) {
if ($type(Layout.getElement('dt.LSform-errors'))) {
LSdebug('add');
li.addClass('LSform_layout_errors');
}
else {
if (!$type(Layout.getElement('dt'))) {
li.destroy();
Layout.destroy();
}
}
}
// Remove corresponding anchor to avoid scrolling on tab change
$$('a[name='+this.getLayoutNameFromBtn(li)+']').dispose();
li.getFirst('a').addEvent('click',this.onTabBtnClick.bindWithEvent(this,li));
},this);
if (LIs.length != 0) {
var defaut_on_first = true;
this._currentTab = 'default_value';
if (window.location.hash) {
var li = $('LSform_layout_btn_'+window.location.hash.substr(1));
if (li) {
defaut_on_first = false;
li.getFirst('a').fireEvent('click');
// Scroll on top of the page
window.scroll(0, 0);
}
}
if (defaut_on_first) {
document.getElement('li.LSform_layout').getFirst('a').fireEvent('click');
}
}
var checkUrl = new RegExp('^object/[^/]+/(create|[^/]+(%3D|=)[^/]+(/modify)?)$');
document.getElements('a.LSview-actions').each(function(a) {
if (checkUrl.exec(a.get('href'))) {
a.addEvent('click',this.onActionBtnClick.bindWithEvent(this,a));
}
},this);
},
onActionBtnClick: function(event,a) {
if (!location.hash) {
return true;
}
if ($type(event)) {
event = new Event(event);
event.stop();
}
var href=a.href;
var checkExistingHash=new RegExp('^([^#]+)#[^#]+$');
var cur = checkExistingHash.exec(href);
if (cur) {
href=cur[1]+location.hash;
}
else {
href=href+location.hash;
}
window.location=href;
},
getLayoutBtn: function(div) {
var getName = new RegExp('LSform_layout_div_(.*)');
var name = getName.exec(div.id);
if (!name) {
return;
}
return $('LSform_layout_btn_'+name[1]);
},
getLayoutNameFromBtn: function(btn) {
var getName = new RegExp('LSform_layout_btn_(.*)');
var name = getName.exec(btn.id);
if (!name) {
return;
}
return name[1];
},
getLayout: function(btn) {
var name = this.getLayoutNameFromBtn(btn);
if (!name) {
return;
}
return $('LSform_layout_div_'+name);
},
onTabBtnClick: function(event,li) {
if ($type(event)) {
event = new Event(event);
event.stop();
if ($type(event.target.blur)) {
event.target.blur();
}
}
if (this._currentTab!=li) {
if (this._currentTab!='default_value') {
this._currentTab.removeClass('LSform_layout_current');
var oldDiv = this.getLayout(this._currentTab);
if ($type(oldDiv)) {
oldDiv.removeClass('LSform_layout_current');
}
}
this._currentTab = li;
li.addClass('LSform_layout_current');
var a=li.getElement('a');
if ($type(a)) {
var layout_name = this.getLayoutNameFromBtn(li);
if (layout_name) {
location.hash='#'+layout_name;
}
}
var div = this.getLayout(li);
if ($type(div)) {
div.addClass('LSform_layout_current');
// Focus
var ul = div.getElement('ul.LSform');
if ($type(ul)) {
var el = ul.getElement('input');
if (!$type(el)) {
el = ul.getElement('textarea');
}
if (!$type(el)) {
el = ul.getElement('select');
}
if ($type(el)) {
if(el.type!='hidden') {
el.focus();
}
}
}
}
}
},
addModule: function(name,obj) {
this._modules[name]=obj;
},
initializeModule: function(fieldType,li) {
if ($type(this._modules[fieldType])) {
try {
this._modules[fieldType].reinitialize(li);
}
catch(e) {
LSdebug('No reinitialize for ' + fieldType);
}
}
},
addField: function(name,obj) {
this._fields[name]=obj;
},
clearFieldValue: function(name) {
if ($type(this._fields[name]) && $type(this._fields[name].clearValue)) {
this._fields[name].clearValue();
}
},
getValue: function(fieldName) {
var retVal = Array();
var inputs = this.getInput(fieldName);
inputs.each(function(el){
if (el.value!="") {
retVal.include(el.value);
}
},this);
return retVal;
},
getInput: function(fieldName) {
var retVal = Array();
var ul = $(fieldName);
if ($type(ul)) {
var elements = ul.getElements('input');
elements.combine(ul.getElements('textarea'));
elements.combine(ul.getElements('select'));
var getName = new RegExp('([a-zA-Z0-9]*)(\[.*\])?');
elements.each(function(el){
var name = getName.exec(el.name);
LSdebug(name);
if (name) {
if (name[1]==fieldName) {
retVal.include(el);
}
}
},this);
}
return retVal;
},
onSubmit: function(event) {
if (this.submit_confirmed) {
// On non-ajax form, leave form submitting if already confirmed
LSdebug('onSubmit(): form submission already confirmed, do not stop submit event');
return true;
}
// Stop form submitting event
event = new Event(event);
event.stop();
// Check if form is already submitting
if (this.submitting) {
// Form is already submitting: stop
LSdebug('onSubmit(): form already submitting...');
return;
}
this.submitting = true;
LSdebug(this.LSform);
this.LSform.addClass('submitting');
// Fire
LSdebug('onSubmit(): fire submit event');
this.fireEvent.bind(this)('submit', this.onSubmitConfirm.bind(this));
},
onSubmitConfirm: function (confirmed, event) {
LSdebug("onSubmitConfirm("+confirmed+")");
if (!confirmed) {
this.submitting = false;
this.LSform.removeClass('submitting');
return;
}
// Check file upload to disable ajax submission in this case
this.checkUploadFileDefined();
if (this._ajaxSubmit) {
LSdebug("onSubmitConfirm(): AJAX submission enabled");
this.LSformAjaxInput = new Element('input');
this.LSformAjaxInput.setProperties ({
type: 'hidden',
name: 'ajax',
value: '1'
});
this.LSformAjaxInput.injectInside(this.LSform);
this.LSform.set('send',{
data: this.LSform,
onSuccess: this.onAjaxSubmitSuccess.bind(this),
onFailure: this.onAjaxSubmitFailure.bind(this),
url: this.LSform.get('action'),
imgload: varLSdefault.loadingImgDisplay($('LSform_title'),'inside')
});
this.LSform.send();
}
else {
LSdebug("onSubmitConfirm(): AJAX submission disabled");
if($type(this.LSformAjaxInput)) {
this.LSformAjaxInput.dispose();
}
this.submit_confirmed = true;
LSdebug("onSubmitConfirm("+confirmed+"): non-AJAX form, submit form again with submit_confirmed flag == TRUE.");
this.LSform.submit();
}
},
checkUploadFileDefined: function() {
this.LSform.getElements('input[type=file]').each(function(ipt) {
if (ipt.files.length!=0) {
LSdebug("checkUploadFileDefined(): input[type=file] detected, disable AJAX submit.");
this._ajaxSubmit=0;
}
}, this);
},
onAjaxSubmitComplete: function(data) {
if (!this.submitting) return;
this.submitting = false;
this.LSform.removeClass('submitting');
// Handle common Ajax return checks
varLSdefault.checkAjaxReturn(data);
},
onAjaxSubmitSuccess: function(responseText, responseXML) {
if (!this.submitting) return;
var data = JSON.decode(responseText);
this.onAjaxSubmitComplete(data);
// Handle LSform errors
this.resetErrors();
if (data && $type(data.LSformErrors) == 'object') {
data.LSformErrors = new Hash(data.LSformErrors);
data.LSformErrors.each(this.addError, this);
}
},
onAjaxSubmitFailure: function(xhr) {
if (!this.submitting) return;
var data;
if (xhr.response) {
data = JSON.decode(xhr.response);
}
else {
varLSdefault.LSerror.displayOrAdd(this.param.onFailureMessage);
}
this.onAjaxSubmitComplete(data);
},
resetErrors: function() {
$$('dd.LSform-errors').each(function(dd) {
dd.destroy();
});
$$('dt.LSform-errors').each(function(dt) {
dt.removeClass('LSform-errors');
});
$$('li.LSform_layout_errors').each(function(li) {
li.removeClass('LSform_layout_errors');
});
},
addError: function(errors,name) {
var ul = $(name);
if ($type(ul)) {
if ($type(errors) != 'array')
errors = new Array(errors);
var ctx = new Object();
ctx.injectAfter = ul.getParent();
errors.each(function(txt){
var dd = new Element('dd');
dd.addClass('LSform');
dd.addClass('LSform-errors');
dd.set('html',txt);
dd.injectAfter(this.injectAfter);
this.injectAfter = dd;
}, ctx);
var dt = ul.getParent('dd.LSform').getPrevious('dt');
if ($type(dt)) {
dt.addClass('LSform-errors');
}
var layout = ul.getParent('div.LSform_layout_active');
if ($type(layout)) {
var li = this.getLayoutBtn(layout);
if($type(li)) {
li.addClass('LSform_layout_errors');
}
}
}
else {
this.tmp=name+" :</br><ul>";
errors = new Array(errors);
errors.each(function(error){
this.tmp += "<li>"+error+"</li>";
},this);
this.tmp +="</ul>";
this.warnBox.display(this.tmp);
}
},
onListAvailableDataEntryFormChange: function() {
var url=window.location.pathname+"?LSobject="+this.objecttype
if (this.listAvailableDataEntryForm.value!="") {
url+="&LSform_dataEntryForm="+this.listAvailableDataEntryForm.value;
}
document.location=url;
},
addEvent: function(event,fnct,fnct_name) {
if ($type(this.listeners[event])) {
if ($type(fnct)=="function") {
if ($type(fnct_name)!="string") {
fnct_name = generate_uuid();
}
else if (this.listeners[event].has(fnct_name)) {
fnct_name = fnct_name+"_"+generate_uuid();
}
this.listeners[event].set(fnct_name, fnct);
}
}
},
fireEvent: function(event, callback) {
LSdebug('LSform :: fireEvent('+event+')');
if (this.listeners.has(event)) {
// If no listener configured, considered as confirmed and run callback
if ($type(callback) == "function" && this.listeners[event].getLength() == 0) {
callback(true, event);
return;
}
// Reset listeners answers state
this.listeners_answers[event] = new Hash();
// Run listeners callback
this.listeners[event].each(function(fnct, listener_uuid) {
var result;
try {
fnct(
this,
function() {
LSdebug('Listener '+listener_uuid+' confirmed');
this.eventListenerCallback.bind(this)(event, listener_uuid, true, callback);
}.bind(this),
function() {
LSdebug('Listener '+listener_uuid+' cancel');
this.eventListenerCallback.bind(this)(event, listener_uuid, false, callback);
}.bind(this)
);
}
catch(e) {
LSdebug('LSform :: fireEvent('+event+') :: exception occured running listener '+listener_uuid+' => considered as not-confirmed.');
LSdebug(e);
result = false;
}
},this);
}
},
eventListenerCallback: function(event, listener_uuid, listener_answer, final_callback) {
// Check event & listener_uuid
if (!this.listeners.has(event) || !this.listeners[event].has(listener_uuid))
return;
// Set listener answers
this.listeners_answers[event].set(listener_uuid, listener_answer);
LSdebug('LSform :: eventListenerCallback('+event+', '+listener_uuid+', '+listener_answer+')');
// Check all listeners have answered
if (this.listeners_answers[event].getLength() != this.listeners[event].getLength())
return;
// Run final callback
this.onFinalEventListenerCallback.bind(this)(event, final_callback);
},
onFinalEventListenerCallback: function(event, final_callback) {
LSdebug('LSform :: onFinalEventListenerCallback('+event+')');
if ($type(final_callback) != "function") {
LSdebug('LSform :: onFinalEventListenerCallback('+event+') : final_callback is not a function, stop.');
return;
}
// Combine all listeners answers
var final_result = true;
this.listeners[event].each(function(fnct, listener_uuid) {
if (!this.listeners_answers[event].has(listener_uuid) || !this.listeners_answers[event][listener_uuid]) {
final_result = false;
}
}, this);
// Run final callback
LSdebug('LSform :: onFinalEventListenerCallback('+event+'): run final_callback with final result = '+final_result);
final_callback(final_result, event);
},
});
window.addEvent(window.ie ? 'load' : 'domready', function() {
varLSform = new LSform();
});