/*+*********************************************************************************** * The contents of this file are subject to the vtiger CRM Public License Version 1.0 * ("License"); You may not use this file except in compliance with the License * The Original Code is: vtiger CRM Open Source * The Initial Developer of the Original Code is vtiger. * Portions created by vtiger are Copyright (C) vtiger. * All Rights Reserved. *************************************************************************************/ jQuery.Class("Vtiger_Edit_Js",{ //Event that will triggered when reference field is selected referenceSelectionEvent : 'Vtiger.Reference.Selection', //Event that will triggered when reference field is selected referenceDeSelectionEvent : 'Vtiger.Reference.DeSelection', //Event that will triggered before saving the record recordPreSave : 'Vtiger.Record.PreSave', refrenceMultiSelectionEvent : 'Vtiger.MultiReference.Selection', preReferencePopUpOpenEvent : 'Vtiger.Referece.Popup.Pre', editInstance : false, postReferenceSelectionEvent: 'Vtiger.PostReference.Selection', /** * Function to get Instance by name * @params moduleName:-- Name of the module to create instance */ getInstanceByModuleName : function(moduleName){ if(typeof moduleName == "undefined"){ moduleName = app.getModuleName(); } var parentModule = app.getParentModuleName(); if(parentModule == 'Settings'){ var moduleClassName = parentModule+"_"+moduleName+"_Edit_Js"; if(typeof window[moduleClassName] == 'undefined'){ moduleClassName = moduleName+"_Edit_Js"; } var fallbackClassName = parentModule+"_Vtiger_Edit_Js"; if(typeof window[fallbackClassName] == 'undefined') { fallbackClassName = "Vtiger_Edit_Js"; } } else { moduleClassName = moduleName+"_Edit_Js"; fallbackClassName = "Vtiger_Edit_Js"; } if(typeof window[moduleClassName] != 'undefined'){ var instance = new window[moduleClassName](); }else{ var instance = new window[fallbackClassName](); } return instance; }, getInstance: function(){ if(Vtiger_Edit_Js.editInstance == false){ var instance = Vtiger_Edit_Js.getInstanceByModuleName(); Vtiger_Edit_Js.editInstance = instance; return instance; } return Vtiger_Edit_Js.editInstance; } },{ formElement : false, getForm : function() { if(this.formElement == false){ this.setForm(jQuery('#EditView')); } return this.formElement; }, setForm : function(element){ this.formElement = element; return this; }, getPopUpParams : function(container) { var params = {}; var sourceModule = app.getModuleName(); var popupReferenceModule = jQuery('input[name="popupReferenceModule"]',container).val(); var sourceFieldElement = jQuery('input[class="sourceField"]',container); var sourceField = sourceFieldElement.attr('name'); var sourceRecordElement = jQuery('input[name="record"]'); var sourceRecordId = ''; if(sourceRecordElement.length > 0) { sourceRecordId = sourceRecordElement.val(); } var isMultiple = false; if(sourceFieldElement.data('multiple') == true){ isMultiple = true; } var params = { 'module' : popupReferenceModule, 'src_module' : sourceModule, 'src_field' : sourceField, 'src_record' : sourceRecordId } if(isMultiple) { params.multi_select = true ; } return params; }, openPopUp : function(e){ var thisInstance = this; var parentElem = jQuery(e.target).closest('td'); var params = this.getPopUpParams(parentElem); var isMultiple = false; if(params.multi_select) { isMultiple = true; } var sourceFieldElement = jQuery('input[class="sourceField"]',parentElem); var prePopupOpenEvent = jQuery.Event(Vtiger_Edit_Js.preReferencePopUpOpenEvent); sourceFieldElement.trigger(prePopupOpenEvent); if(prePopupOpenEvent.isDefaultPrevented()) { return ; } var popupInstance =Vtiger_Popup_Js.getInstance(); popupInstance.show(params,function(data){ var responseData = JSON.parse(data); var dataList = new Array(); for(var id in responseData){ var data = { 'name' : responseData[id].name, 'id' : id } dataList.push(data); if(!isMultiple) { thisInstance.setReferenceFieldValue(parentElem, data); } } if(isMultiple) { sourceFieldElement.trigger(Vtiger_Edit_Js.refrenceMultiSelectionEvent,{'data':dataList}); } sourceFieldElement.trigger(Vtiger_Edit_Js.postReferenceSelectionEvent,{'data':responseData}); }); }, setReferenceFieldValue : function(container, params) { var sourceField = container.find('input[class="sourceField"]').attr('name'); var fieldElement = container.find('input[name="'+sourceField+'"]'); var sourceFieldDisplay = sourceField+"_display"; var fieldDisplayElement = container.find('input[name="'+sourceFieldDisplay+'"]'); var popupReferenceModule = container.find('input[name="popupReferenceModule"]').val(); var selectedName = params.name; var id = params.id; fieldElement.val(id) fieldDisplayElement.val(selectedName).attr('readonly',true); fieldElement.trigger(Vtiger_Edit_Js.referenceSelectionEvent, {'source_module' : popupReferenceModule, 'record' : id, 'selectedName' : selectedName}); fieldDisplayElement.validationEngine('closePrompt',fieldDisplayElement); }, proceedRegisterEvents : function(){ if(jQuery('.recordEditView').length > 0){ return true; }else{ return false; } }, referenceModulePopupRegisterEvent : function(container){ var thisInstance = this; container.on("click",'.relatedPopup',function(e){ thisInstance.openPopUp(e); }); container.find('.referenceModulesList').chosen().change(function(e){ var element = jQuery(e.currentTarget); var closestTD = element.closest('td').next(); var popupReferenceModule = element.val(); var referenceModuleElement = jQuery('input[name="popupReferenceModule"]', closestTD); var prevSelectedReferenceModule = referenceModuleElement.val(); referenceModuleElement.val(popupReferenceModule); //If Reference module is changed then we should clear the previous value if(prevSelectedReferenceModule != popupReferenceModule) { closestTD.find('.clearReferenceSelection').trigger('click'); } }); }, getReferencedModuleName : function(parenElement){ return jQuery('input[name="popupReferenceModule"]',parenElement).val(); }, searchModuleNames : function(params) { var aDeferred = jQuery.Deferred(); if(typeof params.module == 'undefined') { params.module = app.getModuleName(); } if(typeof params.action == 'undefined') { params.action = 'BasicAjax'; } AppConnector.request(params).then( function(data){ aDeferred.resolve(data); }, function(error){ //TODO : Handle error aDeferred.reject(); } ) return aDeferred.promise(); }, /** * Function to get reference search params */ getReferenceSearchParams : function(element){ var tdElement = jQuery(element).closest('td'); var params = {}; var searchModule = this.getReferencedModuleName(tdElement); params.search_module = searchModule; return params; }, /** * Function which will handle the reference auto complete event registrations * @params - container - element in which auto complete fields needs to be searched */ registerAutoCompleteFields : function(container) { var thisInstance = this; container.find('input.autoComplete').autocomplete({ 'minLength' : '3', 'source' : function(request, response){ //element will be array of dom elements //here this refers to auto complete instance var inputElement = jQuery(this.element[0]); var searchValue = request.term; var params = thisInstance.getReferenceSearchParams(inputElement); params.search_value = searchValue; thisInstance.searchModuleNames(params).then(function(data){ var reponseDataList = new Array(); var serverDataFormat = data.result if(serverDataFormat.length <= 0) { jQuery(inputElement).val(''); serverDataFormat = new Array({ 'label' : app.vtranslate('JS_NO_RESULTS_FOUND'), 'type' : 'no results' }); } for(var id in serverDataFormat){ var responseData = serverDataFormat[id]; reponseDataList.push(responseData); } response(reponseDataList); }); }, 'select' : function(event, ui ){ var selectedItemData = ui.item; //To stop selection if no results is selected if(typeof selectedItemData.type != 'undefined' && selectedItemData.type=="no results"){ return false; } selectedItemData.name = selectedItemData.value; var element = jQuery(this); var tdElement = element.closest('td'); thisInstance.setReferenceFieldValue(tdElement, selectedItemData); var sourceField = tdElement.find('input[class="sourceField"]').attr('name'); var fieldElement = tdElement.find('input[name="'+sourceField+'"]'); fieldElement.trigger(Vtiger_Edit_Js.postReferenceSelectionEvent,{'data':selectedItemData}); }, 'change' : function(event, ui) { var element = jQuery(this); //if you dont have readonly attribute means the user didnt select the item if(element.attr('readonly')== undefined) { element.closest('td').find('.clearReferenceSelection').trigger('click'); } }, 'open' : function(event,ui) { //To Make the menu come up in the case of quick create jQuery(this).data('autocomplete').menu.element.css('z-index','100001'); } }); }, /** * Function which will register reference field clear event * @params - container - element in which auto complete fields needs to be searched */ registerClearReferenceSelectionEvent : function(container) { container.find('.clearReferenceSelection').on('click', function(e){ var element = jQuery(e.currentTarget); var parentTdElement = element.closest('td'); var fieldNameElement = parentTdElement.find('.sourceField'); var fieldName = fieldNameElement.attr('name'); fieldNameElement.val(''); parentTdElement.find('#'+fieldName+'_display').removeAttr('readonly').val(''); element.trigger(Vtiger_Edit_Js.referenceDeSelectionEvent); e.preventDefault(); }) }, /** * Function which will register event to prevent form submission on pressing on enter * @params - container - element in which auto complete fields needs to be searched */ registerPreventingEnterSubmitEvent : function(container) { container.on('keypress', function(e){ //Stop the submit when enter is pressed in the form var currentElement = jQuery(e.target); if(e.which == 13 && (!currentElement.is('textarea'))) { e. preventDefault(); } }) }, /** * Function which will give you all details of the selected record * @params - an Array of values like {'record' : recordId, 'source_module' : searchModule, 'selectedName' : selectedRecordName} */ getRecordDetails : function(params) { var aDeferred = jQuery.Deferred(); var url = "index.php?module="+app.getModuleName()+"&action=GetData&record="+params['record']+"&source_module="+params['source_module']; AppConnector.request(url).then( function(data){ if(data['success']) { aDeferred.resolve(data); } else { aDeferred.reject(data['message']); } }, function(error){ aDeferred.reject(); } ) return aDeferred.promise(); }, registerTimeFields : function(container) { app.registerEventForTimeFields(container); }, referenceCreateHandler : function(container) { var thisInstance = this; var postQuickCreateSave = function(data) { var params = {}; params.name = data.result._recordLabel; params.id = data.result._recordId; thisInstance.setReferenceFieldValue(container, params); } var referenceModuleName = this.getReferencedModuleName(container); var quickCreateNode = jQuery('#quickCreateModules').find('[data-name="'+ referenceModuleName +'"]'); if(quickCreateNode.length <= 0) { Vtiger_Helper_Js.showPnotify(app.vtranslate('JS_NO_CREATE_OR_NOT_QUICK_CREATE_ENABLED')) } quickCreateNode.trigger('click',{'callbackFunction':postQuickCreateSave}); }, /** * Function which will register event for create of reference record * This will allow users to create reference record from edit view of other record */ registerReferenceCreate : function(container) { var thisInstance = this; container.on('click','.createReferenceRecord', function(e){ var element = jQuery(e.currentTarget); var controlElementTd = element.closest('td'); thisInstance.referenceCreateHandler(controlElementTd); }) }, /** * Function to register the event status change event */ registerEventStatusChangeEvent : function(container){ var followupContainer = container.find('.followUpContainer'); //if default value is set to Held then display follow up container var defaultStatus = container.find('select[name="eventstatus"]').val(); if(defaultStatus == 'Held'){ followupContainer.show(); } container.find('select[name="eventstatus"]').on('change',function(e){ var selectedOption = jQuery(e.currentTarget).val(); if(selectedOption == 'Held'){ followupContainer.show(); } else{ followupContainer.hide(); } }); }, /** * Function which will register basic events which will be used in quick create as well * */ registerBasicEvents : function(container) { this.referenceModulePopupRegisterEvent(container); this.registerAutoCompleteFields(container); this.registerClearReferenceSelectionEvent(container); this.registerPreventingEnterSubmitEvent(container); this.registerTimeFields(container); //Added here instead of register basic event of calendar. because this should be registered all over the places like quick create, edit, list.. this.registerEventStatusChangeEvent(container); this.registerRecordAccessCheckEvent(container); this.registerEventForPicklistDependencySetup(container); }, /** * Function to register event for image delete */ registerEventForImageDelete : function(){ var formElement = this.getForm(); var recordId = formElement.find('input[name="record"]').val(); formElement.find('.imageDelete').on('click',function(e){ var element = jQuery(e.currentTarget); var parentTd = element.closest('td'); var imageUploadElement = parentTd.find('[name="imagename[]"]'); var fieldInfo = imageUploadElement.data('fieldinfo'); var mandatoryStatus = fieldInfo.mandatory; var imageId = element.closest('div').find('img').data().imageId; element.closest('div').remove(); var exisitingImages = parentTd.find('[name="existingImages"]'); if(exisitingImages.length < 1 && mandatoryStatus){ formElement.validationEngine('detach'); imageUploadElement.attr('data-validation-engine','validate[required,funcCall[Vtiger_Base_Validator_Js.invokeValidation]]'); formElement.validationEngine('attach'); } if(formElement.find('[name=imageid]').length != 0) { var imageIdValue = JSON.parse(formElement.find('[name=imageid]').val()); imageIdValue.push(imageId); formElement.find('[name=imageid]').val(JSON.stringify(imageIdValue)); } else { var imageIdJson = []; imageIdJson.push(imageId); formElement.append(''); formElement.append(''); } }); }, triggerDisplayTypeEvent : function() { var widthType = app.cacheGet('widthType', 'narrowWidthType'); if(widthType) { var elements = jQuery('#EditView').find('td'); elements.addClass(widthType); } }, registerSubmitEvent: function() { var editViewForm = this.getForm(); editViewForm.submit(function(e){ //Form should submit only once for multiple clicks also if(typeof editViewForm.data('submit') != "undefined") { return false; } else { var module = jQuery(e.currentTarget).find('[name="module"]').val(); if(editViewForm.validationEngine('validate')) { //Once the form is submiting add data attribute to that form element editViewForm.data('submit', 'true'); //on submit form trigger the recordPreSave event var recordPreSaveEvent = jQuery.Event(Vtiger_Edit_Js.recordPreSave); editViewForm.trigger(recordPreSaveEvent, {'value' : 'edit'}); if(recordPreSaveEvent.isDefaultPrevented()) { //If duplicate record validation fails, form should submit again editViewForm.removeData('submit'); e.preventDefault(); } } else { //If validation fails, form should submit again editViewForm.removeData('submit'); // to avoid hiding of error message under the fixed nav bar app.formAlignmentAfterValidation(editViewForm); } } }); }, /* * Function to check the view permission of a record after save */ registerRecordAccessCheckEvent : function(form) { form.on(Vtiger_Edit_Js.recordPreSave, function(e, data) { var assignedToSelectElement = jQuery('[name="assigned_user_id"]',form); if(assignedToSelectElement.data('recordaccessconfirmation') == true) { return; }else{ if(assignedToSelectElement.data('recordaccessconfirmationprogress') != true) { var recordAccess = assignedToSelectElement.find('option:selected').data('recordaccess'); if(recordAccess == false) { var message = app.vtranslate('JS_NO_VIEW_PERMISSION_AFTER_SAVE'); Vtiger_Helper_Js.showConfirmationBox({'message' : message}).then( function(e) { assignedToSelectElement.data('recordaccessconfirmation',true); assignedToSelectElement.removeData('recordaccessconfirmationprogress'); form.append(''); form.submit(); }, function(error, err){ assignedToSelectElement.removeData('recordaccessconfirmationprogress'); e.preventDefault(); }); assignedToSelectElement.data('recordaccessconfirmationprogress',true); } else { return true; } } } e.preventDefault(); }); }, /** * Function to register event for setting up picklistdependency * for a module if exist on change of picklist value */ registerEventForPicklistDependencySetup : function(container){ var picklistDependcyElemnt = jQuery('[name="picklistDependency"]',container); if(picklistDependcyElemnt.length <= 0) { return; } var picklistDependencyMapping = JSON.parse(picklistDependcyElemnt.val()); var sourcePicklists = Object.keys(picklistDependencyMapping); if(sourcePicklists.length <= 0){ return; } var sourcePickListNames = ""; for(var i=0;i 0){ var ckEditorSourceId = ckEditorSource.attr('id'); var fieldInfo = ckEditorSource.data('fieldinfo'); var isMandatory = fieldInfo.mandatory; var CKEditorInstance = CKEDITOR.instances; var ckEditorValue = jQuery.trim(CKEditorInstance[ckEditorSourceId].document.getBody().getText()); if(isMandatory && (ckEditorValue.length === 0)){ var ckEditorId = 'cke_'+ckEditorSourceId; var message = app.vtranslate('JS_REQUIRED_FIELD'); jQuery('#'+ckEditorId).validationEngine('showPrompt', message , 'error','topLeft',true); return false; }else{ return valid; } } return valid; } return valid } editViewForm.validationEngine(params); this.registerReferenceCreate(editViewForm); //this.triggerDisplayTypeEvent(); } });