[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/layouts/vlayout/modules/Settings/LayoutEditor/resources/ -> LayoutEditor.js (source)

   1  /*+***********************************************************************************
   2   * The contents of this file are subject to the vtiger CRM Public License Version 1.0
   3   * ("License"); You may not use this file except in compliance with the License
   4   * The Original Code is:  vtiger CRM Open Source
   5   * The Initial Developer of the Original Code is vtiger.
   6   * Portions created by vtiger are Copyright (C) vtiger.
   7   * All Rights Reserved.
   8   *************************************************************************************/
   9  jQuery.Class('Settings_LayoutEditor_Js', {
  10  
  11  }, {
  12      updatedBlockSequence : {},
  13  
  14      reactiveFieldsList : [],
  15  
  16      updatedRelatedList : {'updated' : [], 'deleted' : []},
  17  
  18      removeModulesArray : false,
  19  
  20      inActiveFieldsList : false,
  21  
  22      updatedBlockFieldsList : [],
  23  
  24      updatedBlocksList : [],
  25  
  26      blockNamesList : [],
  27  
  28      /**
  29       * Function to set the removed modules array used in related list
  30       */
  31      setRemovedModulesList : function() {
  32          var thisInstance = this;
  33          var relatedList = jQuery('#relatedTabOrder');
  34          var container = relatedList.find('.relatedTabModulesList');
  35          thisInstance.removeModulesArray = JSON.parse(container.find('.RemovedModulesListArray').val());
  36      },
  37  
  38      /**
  39       * Function to set the inactive fields list used to show the inactive fields
  40       */
  41      setInactiveFieldsList : function() {
  42          var thisInstance = this;
  43          var contents = jQuery('#layoutEditorContainer').find('.contents');
  44          thisInstance.inActiveFieldsList = JSON.parse(contents.find('.inActiveFieldsArray').val());
  45      },
  46  
  47      /**
  48       * Function to regiser the event to make the blocks sortable
  49       */
  50      makeBlocksListSortable : function() {
  51          var thisInstance = this;
  52          var contents = jQuery('#layoutEditorContainer').find('.contents');
  53          var table = contents.find('.blockSortable');
  54          contents.sortable({
  55              'containment' : contents,
  56              'items' : table,
  57              'revert' : true,
  58              'tolerance':'pointer',
  59              'cursor' : 'move',
  60              'update' : function(e, ui) {
  61                  thisInstance.updateBlockSequence();
  62              }
  63          });
  64      },
  65  
  66      /**
  67       * Function which will update block sequence
  68       */
  69      updateBlockSequence : function() {
  70          var thisInstance = this;
  71          var progressIndicatorElement = jQuery.progressIndicator({
  72              'position' : 'html',
  73              'blockInfo' : {
  74                  'enabled' : true
  75              }
  76          });
  77  
  78          var sequence = JSON.stringify(thisInstance.updateBlocksListByOrder());
  79          var params = {};
  80          params['module'] = app.getModuleName();
  81          params['parent'] = app.getParentModuleName();
  82          params['action'] = 'Block';
  83          params['mode'] = 'updateSequenceNumber';
  84          params['sequence'] = sequence;
  85  
  86          AppConnector.request(params).then(
  87              function(data) {
  88                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
  89                  var params = {};
  90                  params['text'] = app.vtranslate('JS_BLOCK_SEQUENCE_UPDATED');
  91                  Settings_Vtiger_Index_Js.showMessage(params);
  92              },
  93              function(error) {
  94                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
  95              }
  96          );
  97      },
  98  
  99      /**
 100       * Function which will arrange the sequence number of blocks
 101       */
 102      updateBlocksListByOrder : function() {
 103          var thisInstance = this;
 104          var contents = jQuery('#layoutEditorContainer').find('.contents');
 105          contents.find('.editFieldsTable').each(function(index,domElement){
 106              var blockTable = jQuery(domElement);
 107              var blockId = blockTable.data('blockId');
 108              var actualBlockSequence = blockTable.data('sequence');
 109              var expectedBlockSequence = (index+1);
 110  
 111              if(expectedBlockSequence != actualBlockSequence) {
 112                  blockTable.data('sequence', expectedBlockSequence);
 113              }
 114              thisInstance.updatedBlockSequence[blockId] = expectedBlockSequence;
 115          });
 116          return thisInstance.updatedBlockSequence;
 117      },
 118  
 119      /**
 120       * Function to regiser the event to make the related modules sortable
 121       */
 122      makeRelatedModuleSortable : function() {
 123          var thisInstance = this;
 124          var relatedModulesContainer = jQuery('#relatedTabOrder');
 125          var modulesList = relatedModulesContainer.find('li.relatedModule');
 126          relatedModulesContainer.sortable({
 127              'containment' : relatedModulesContainer,
 128              'items' : modulesList,
 129              'revert' : true,
 130              'tolerance':'pointer',
 131              'cursor' : 'move',
 132              'update' : function(e, ui) {
 133                  thisInstance.showSaveButton();
 134              }
 135          });
 136      },
 137  
 138      /**
 139       * Function which will enable the save button in realted tabs list
 140       */
 141      showSaveButton : function() {
 142          var relatedList = jQuery('#relatedTabOrder');
 143          var saveButton = relatedList.find('.saveRelatedList');
 144          if(saveButton.attr('disabled') ==  'disabled') {
 145              saveButton.removeAttr('disabled');
 146          }
 147      },
 148  
 149      /**
 150       * Function which will disable the save button in related tabs list
 151       */
 152      disableSaveButton : function() {
 153          var relatedList = jQuery('#relatedTabOrder');
 154          var saveButton = relatedList.find('.saveRelatedList');
 155          saveButton.attr('disabled', 'disabled');
 156      },
 157  
 158      /**
 159       * Function to register all the relatedList Events
 160       */
 161      registerRelatedListEvents : function() {
 162          var thisInstance = this;
 163          var relatedList = jQuery('#relatedTabOrder');
 164          var container = relatedList.find('.relatedTabModulesList');
 165          var allModulesListArray = JSON.parse(container.find('.ModulesListArray').val());
 166          var ulEle = container.find('ul.relatedModulesList');
 167  
 168          var selectEle = container.find('[name="addToList"]');
 169          app.showSelect2ElementView(selectEle, {maximumSelectionSize : 1, closeOnSelect : true, dropdownCss : {'z-index' : 0}});
 170          selectEle.on('change', function() {
 171              var selectedVal = selectEle.val();
 172              var moduleLabel = allModulesListArray[selectedVal];
 173              //remove the element if its already exists
 174              ulEle.find('.module_'+selectedVal[0]).remove();
 175  
 176              //append li element for the selected module
 177              var liEle = container.find('.moduleCopy').clone(true, true);
 178              liEle.data('relationId', selectedVal[0]).find('.moduleLabel').text(moduleLabel);
 179              ulEle.append(liEle.removeClass('hide moduleCopy').addClass('relatedModule module_'+selectedVal[0]));
 180              thisInstance.makeRelatedModuleSortable();
 181  
 182              //remove that selected module from the select element
 183              selectEle.select2('data',[]);
 184              selectEle.find('option[value="'+selectedVal[0]+'"]').remove();
 185  
 186              thisInstance.removeModulesArray.splice(thisInstance.removeModulesArray.indexOf(selectedVal[0]),1);
 187              thisInstance.showSaveButton();
 188          })
 189  
 190          //register the event to click on close the related module
 191          container.find('.close').one('click', function(e) {
 192              var currentTarget = jQuery(e.currentTarget);
 193              thisInstance.showSaveButton();
 194              var liEle = currentTarget.closest('li.relatedModule');
 195              var relationId = liEle.data('relationId');
 196              var moduleLabel = liEle.find('.moduleLabel').text();
 197              liEle.fadeOut('slow').addClass('deleted');
 198              selectEle.append('<option value="'+relationId+'">'+moduleLabel+'</option>');
 199          })
 200  
 201          //register click event for save related  list button
 202          relatedList.on('click', '.saveRelatedList', function(e) {
 203              var currentTarget = jQuery(e.currentTarget);
 204              if(currentTarget.attr('disabled') != 'disabled') {
 205                  thisInstance.disableSaveButton();
 206                  thisInstance.updatedRelatedList['deleted'] = [];
 207                  for(var key in thisInstance.removeModulesArray) {
 208                      thisInstance.updatedRelatedList['deleted'].push(thisInstance.removeModulesArray[key]);
 209                  }
 210                  thisInstance.saveRelatedListInfo();
 211              }
 212          })
 213      },
 214  
 215      /**
 216       * Function to save the updated information in related list
 217       */
 218      saveRelatedListInfo : function() {
 219          var thisInstance = this;
 220          var aDeferred = jQuery.Deferred();
 221          var progressIndicatorElement = jQuery.progressIndicator({
 222              'position' : 'html',
 223              'blockInfo' : {
 224                  'enabled' : true
 225              }
 226          });
 227  
 228          var params = {};
 229          params['module'] = app.getModuleName();
 230          params['parent'] = app.getParentModuleName();
 231          params['action'] = 'Relation';
 232          params['related_info'] = thisInstance.getUpdatedModulesInfo();
 233          params['sourceModule'] = jQuery('#selectedModuleName').val();
 234  
 235          AppConnector.request(params).then(
 236              function(data) {
 237                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
 238                  var params = {};
 239                  params['text'] = app.vtranslate('JS_RELATED_INFO_SAVED');
 240                  Settings_Vtiger_Index_Js.showMessage(params);
 241                  aDeferred.resolve(data);
 242              },
 243              function(error) {
 244                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
 245                  aDeferred.reject(error);
 246              }
 247          );
 248          return aDeferred.promise();
 249      },
 250  
 251      /**
 252       * Function to get the updates happened with the related modules list
 253       */
 254      getUpdatedModulesInfo : function() {
 255          var thisInstance = this;
 256          var relatedList = jQuery('#relatedTabOrder');
 257          var removedModulesList = relatedList.find('li.relatedModule').filter('.deleted');
 258          var updatedModulesList = relatedList.find('li.relatedModule').not('.deleted');
 259          thisInstance.updatedRelatedList['updated'] = [];
 260  
 261          //update deleted related modules list
 262          removedModulesList.each(function(index,domElement) {
 263              var relationId = jQuery(domElement).data('relationId');
 264              thisInstance.updatedRelatedList['deleted'].push(relationId);
 265          });
 266          //update the existing related modules list
 267          updatedModulesList.each(function(index,domElement){
 268              var relationId = jQuery(domElement).data('relationId');
 269              thisInstance.updatedRelatedList['updated'].push(relationId);
 270          });
 271          return thisInstance.updatedRelatedList;
 272      },
 273  
 274      /**
 275       * Function to regiser the event to make the fields sortable
 276       */
 277      makeFieldsListSortable : function() {
 278          var thisInstance = this;
 279          var contents = jQuery('#layoutEditorContainer').find('.contents');
 280          var table = contents.find('.editFieldsTable');
 281          table.find('ul[name=sortable1], ul[name=sortable2]').sortable({
 282              'containment' : '#moduleBlocks',
 283              'revert' : true,
 284              'tolerance':'pointer',
 285              'cursor' : 'move',
 286              'connectWith' : '.connectedSortable',
 287              'update' : function(e, ui) {
 288                  var currentField = ui['item'];
 289                  thisInstance.showSaveFieldSequenceButton();
 290                  thisInstance.createUpdatedBlocksList(currentField);
 291                  // rearrange the older block fields
 292                  if(ui.sender) {
 293                      var olderBlock = ui.sender.closest('.editFieldsTable');
 294                      thisInstance.reArrangeBlockFields(olderBlock);
 295                  }
 296              }
 297          });
 298      },
 299  
 300      /**
 301       * Function to show the save button of fieldSequence
 302       */
 303      showSaveFieldSequenceButton : function() {
 304          var thisInstance = this;
 305          var layout = jQuery('#detailViewLayout');
 306          var saveButton = layout.find('.saveFieldSequence');
 307          if(app.isHidden(saveButton)) {
 308              thisInstance.updatedBlocksList = [];
 309              thisInstance.updatedBlockFieldsList = [];
 310              saveButton.removeClass('hide');
 311              var params = {};
 312              params['text'] = app.vtranslate('JS_SAVE_THE_CHANGES_TO_UPDATE_FIELD_SEQUENCE');
 313              Settings_Vtiger_Index_Js.showMessage(params);
 314          }
 315      },
 316  
 317      /**
 318       * Function which will hide the saveFieldSequence button
 319       */
 320      hideSaveFieldSequenceButton : function() {
 321          var layout = jQuery('#detailViewLayout');
 322          var saveButton = layout.find('.saveFieldSequence');
 323          saveButton.addClass('hide');
 324      },
 325  
 326      /**
 327       * Function to create the blocks list which are updated while sorting
 328       */
 329      createUpdatedBlocksList : function(currentField) {
 330          var thisInstance = this;
 331          var block = currentField.closest('.editFieldsTable');
 332          var updatedBlockId = block.data('blockId');
 333          if(jQuery.inArray(updatedBlockId, thisInstance.updatedBlocksList) == -1) {
 334              thisInstance.updatedBlocksList.push(updatedBlockId);
 335          }
 336          thisInstance.reArrangeBlockFields(block);
 337      },
 338  
 339      /**
 340       * Function that rearranges fields in the block when the fields are moved
 341       * @param <jQuery object> block
 342       */
 343      reArrangeBlockFields : function(block) {
 344          // 1.get the containers, 2.compare the length, 3.if uneven then move the last element
 345          var leftSideContainer = block.find('ul[name=sortable1]');
 346          var rightSideContainer = block.find('ul[name=sortable2]');
 347          if(leftSideContainer.children().length < rightSideContainer.children().length) {
 348              var lastElementInRightContainer = rightSideContainer.children(':last');
 349              leftSideContainer.append(lastElementInRightContainer);
 350          } else if(leftSideContainer.children().length > rightSideContainer.children().length+1) {    //greater than 1
 351              var lastElementInLeftContainer = leftSideContainer.children(':last');
 352              rightSideContainer.append(lastElementInLeftContainer);
 353          }
 354      },
 355      /**
 356       * Function to create the list of updated blocks with all the fields and their sequences
 357       */
 358      createUpdatedBlockFieldsList : function() {
 359          var thisInstance = this;
 360          var contents = jQuery('#layoutEditorContainer').find('.contents');
 361  
 362          for(var index in  thisInstance.updatedBlocksList) {
 363              var updatedBlockId = thisInstance.updatedBlocksList[index];
 364              var updatedBlock = contents.find('.block_'+updatedBlockId);
 365              var firstBlockSortFields = updatedBlock.find('ul[name=sortable1]');
 366              var editFields = firstBlockSortFields.find('.editFields');
 367              var expectedFieldSequence = 1;
 368              editFields.each(function(i,domElement){
 369                  var fieldEle = jQuery(domElement);
 370                  var fieldId = fieldEle.data('fieldId');
 371                  thisInstance.updatedBlockFieldsList.push({'fieldid' : fieldId,'sequence' : expectedFieldSequence, 'block' : updatedBlockId});
 372                  expectedFieldSequence = expectedFieldSequence+2;
 373              });
 374              var secondBlockSortFields = updatedBlock.find('ul[name=sortable2]');
 375              var secondEditFields = secondBlockSortFields.find('.editFields');
 376              var sequenceValue = 2;
 377              secondEditFields.each(function(i,domElement){
 378                  var fieldEle = jQuery(domElement);
 379                  var fieldId = fieldEle.data('fieldId');
 380                  thisInstance.updatedBlockFieldsList.push({'fieldid' : fieldId,'sequence' : sequenceValue, 'block' : updatedBlockId});
 381                  sequenceValue = sequenceValue+2;
 382              });
 383          }
 384      },
 385  
 386      /**
 387       * Function to register click event for save button of fields sequence
 388       */
 389      registerFieldSequenceSaveClick : function() {
 390          var thisInstance = this;
 391          var layout = jQuery('#detailViewLayout');
 392          layout.on('click', '.saveFieldSequence', function() {
 393              thisInstance.hideSaveFieldSequenceButton();
 394              thisInstance.createUpdatedBlockFieldsList();
 395              thisInstance.updateFieldSequence();
 396          });
 397      },
 398  
 399      /**
 400       * Function will save the field sequences
 401       */
 402      updateFieldSequence : function() {
 403          var thisInstance = this;
 404          var progressIndicatorElement = jQuery.progressIndicator({
 405              'position' : 'html',
 406              'blockInfo' : {
 407                  'enabled' : true
 408              }
 409          });
 410          var params = {};
 411          params['module'] = app.getModuleName();
 412          params['parent'] = app.getParentModuleName();
 413          params['action'] = 'Field';
 414          params['mode'] = 'move';
 415          params['updatedFields'] = thisInstance.updatedBlockFieldsList;
 416  
 417          AppConnector.request(params).then(
 418              function(data) {
 419                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
 420                  window.location.reload();
 421                  var params = {};
 422                  params['text'] = app.vtranslate('JS_FIELD_SEQUENCE_UPDATED');
 423                  Settings_Vtiger_Index_Js.showMessage(params);
 424              },
 425              function(error) {
 426                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
 427              }
 428          );
 429      },
 430  
 431      /**
 432       * Function to register click evnet add custom field button
 433       */
 434      registerAddCustomFieldEvent : function() {
 435          var thisInstance = this;
 436          var contents = jQuery('#layoutEditorContainer').find('.contents');
 437          contents.find('.addCustomField').click(function(e) {
 438              var blockId = jQuery(e.currentTarget).closest('.editFieldsTable').data('blockId');
 439              var addFieldContainer = contents.find('.createFieldModal').clone(true, true);
 440              addFieldContainer.removeClass('hide');
 441  
 442              var callBackFunction = function(data) {
 443                  //register all select2 Elements
 444                  app.showSelect2ElementView(data.find('select'));
 445  
 446                  var form = data.find('.createCustomFieldForm');
 447                  form.attr('id', 'createFieldForm');
 448                  var select2params = {tags: [],tokenSeparators: [","]}
 449                  app.showSelect2ElementView(form.find('[name="pickListValues"]'), select2params);
 450  
 451                  thisInstance.registerFieldTypeChangeEvent(form);
 452  
 453                  var params = app.getvalidationEngineOptions(true);
 454                  params.onValidationComplete = function(form, valid){
 455                      if(valid) {
 456                          var fieldTypeValue = jQuery('[name="fieldType"]',form).val();
 457                          if(fieldTypeValue == 'Picklist' || fieldTypeValue == 'MultiSelectCombo') {
 458                              var pickListValueElement = jQuery('#picklistUi',form);
 459                              var pickLisValues = pickListValueElement.val();
 460                              var pickListValuesArray = pickLisValues.split(',');
 461                              var pickListValuesArraySize = pickListValuesArray.length;
 462                              var specialChars = /["]/ ;
 463                              for(var i=0;i<pickListValuesArray.length;i++) {
 464                                  if (specialChars.test(pickListValuesArray[i])) {
 465                                      var select2Element = app.getSelect2ElementFromSelect(pickListValueElement);
 466                                      var message = app.vtranslate('JS_SPECIAL_CHARACTERS')+' " '+app.vtranslate('JS_NOT_ALLOWED');
 467                                      select2Element.validationEngine('showPrompt', message , 'error','bottomLeft',true);
 468                                      return false;
 469                                  }
 470                              }
 471                              var lowerCasedpickListValuesArray = jQuery.map(pickListValuesArray, function(item, index) {
 472                                                                      return item.toLowerCase();
 473                                                                  });
 474                              var uniqueLowerCasedpickListValuesArray = jQuery.unique(lowerCasedpickListValuesArray);
 475                              var uniqueLowerCasedpickListValuesArraySize = uniqueLowerCasedpickListValuesArray.length;
 476                              var arrayDiffSize = pickListValuesArraySize-uniqueLowerCasedpickListValuesArraySize;
 477                              if(arrayDiffSize > 0) {
 478                                  var select2Element = app.getSelect2ElementFromSelect(pickListValueElement);
 479                                  var message = app.vtranslate('JS_DUPLICATES_VALUES_FOUND');
 480                                  select2Element.validationEngine('showPrompt', message , 'error','bottomLeft',true);
 481                                  return false;
 482                              }
 483  
 484                          }
 485                          var saveButton = form.find(':submit');
 486                          saveButton.attr('disabled', 'disabled');
 487                          thisInstance.addCustomField(blockId, form).then(
 488                              function(data) {
 489                                  var result = data['result'];
 490                                  var params = {};
 491                                  if(data['success']) {
 492                                      app.hideModalWindow();
 493                                      params['text'] = app.vtranslate('JS_CUSTOM_FIELD_ADDED');
 494                                      Settings_Vtiger_Index_Js.showMessage(params);
 495                                      thisInstance.showCustomField(result);
 496                                  } else {
 497                                      var message = data['error']['message'];
 498                                      form.find('[name="fieldLabel"]').validationEngine('showPrompt', message , 'error','topLeft',true);
 499                                      saveButton.removeAttr('disabled');
 500                                  }
 501                              }
 502                          );
 503                      }
 504                      //To prevent form submit
 505                      return false;
 506                  }
 507                  form.validationEngine(params);
 508              }
 509  
 510              app.showModalWindow(addFieldContainer,function(data) {
 511                  if(typeof callBackFunction == 'function') {
 512                      callBackFunction(data);
 513                  }
 514              }, {'width':'1000px'});
 515          });
 516      },
 517  
 518      /**
 519       * Function to create the array of block names list
 520       */
 521      setBlocksListArray : function(form) {
 522          var thisInstance = this;
 523          thisInstance.blockNamesList = [];
 524          var blocksListSelect = form.find('[name="beforeBlockId"]');
 525          blocksListSelect.find('option').each(function(index, ele) {
 526              var option = jQuery(ele);
 527              var label = option.data('label');
 528              thisInstance.blockNamesList.push(label);
 529          })
 530      },
 531  
 532      /**
 533       * Function to save the custom field details
 534       */
 535      addCustomField : function(blockId, form) {
 536          var thisInstance = this;
 537          var modalHeader = form.closest('#globalmodal').find('.modal-header h3');
 538          var aDeferred = jQuery.Deferred();
 539  
 540          modalHeader.progressIndicator({smallLoadingImage : true, imageContainerCss : {display : 'inline', 'margin-left' : '18%',position : 'absolute'}});
 541  
 542          var params = form.serializeFormData();
 543          params['module'] = app.getModuleName();
 544          params['parent'] = app.getParentModuleName();
 545          params['action'] = 'Field';
 546          params['mode'] = 'add';
 547          params['blockid'] = blockId;
 548          params['sourceModule'] = jQuery('#selectedModuleName').val();
 549  
 550          AppConnector.request(params).then(
 551              function(data) {
 552                  modalHeader.progressIndicator({'mode' : 'hide'});
 553                  aDeferred.resolve(data);
 554              },
 555              function(error) {
 556                  modalHeader.progressIndicator({'mode' : 'hide'});
 557                  aDeferred.reject(error);
 558              }
 559          );
 560          return aDeferred.promise();
 561      },
 562  
 563      /**
 564       * Function to register change event for fieldType while adding custom field
 565       */
 566      registerFieldTypeChangeEvent : function(form) {
 567          var thisInstance = this;
 568          var lengthInput = form.find('[name="fieldLength"]');
 569  
 570          //special validators while adding new field
 571          var lengthValidator = [{'name' : 'DecimalMaxLength'}];
 572          var maxLengthValidator = [{'name' : 'MaxLength'}];
 573          var decimalValidator = [{'name' : 'FloatingDigits'}];
 574  
 575          //By default add the max length validator
 576          lengthInput.data('validator', maxLengthValidator);
 577  
 578          //register the change event for field types
 579          form.find('[name="fieldType"]').on('change', function(e) {
 580              var currentTarget = jQuery(e.currentTarget);
 581              var lengthInput = form.find('[name="fieldLength"]');
 582              var selectedOption = currentTarget.find('option:selected');
 583  
 584              //hide all the elements like length, decimal,picklist
 585              form.find('.supportedType').addClass('hide');
 586  
 587              if(selectedOption.data('lengthsupported')) {
 588                  form.find('.lengthsupported').removeClass('hide');
 589                  lengthInput.data('validator', maxLengthValidator);
 590              }
 591  
 592              if(selectedOption.data('decimalsupported')) {
 593                  var decimalFieldUi = form.find('.decimalsupported');
 594                  decimalFieldUi.removeClass('hide');
 595  
 596                  var decimalInput = decimalFieldUi.find('[name="decimal"]');
 597                  var maxFloatingDigits = selectedOption.data('maxfloatingdigits');
 598  
 599                  if(typeof maxFloatingDigits != "undefined") {
 600                      decimalInput.data('validator', decimalValidator);
 601                      lengthInput.data('validator', lengthValidator);
 602                  }
 603  
 604                  if(selectedOption.data('decimalreadonly')) {
 605                      decimalInput.val(maxFloatingDigits).attr('readonly', true);
 606                  } else {
 607                      decimalInput.removeAttr('readonly').val('');
 608                  }
 609              }
 610  
 611              if(selectedOption.data('predefinedvalueexists')) {
 612                  var pickListUi = form.find('.preDefinedValueExists');
 613                  pickListUi.removeClass('hide');
 614              }
 615              if(selectedOption.data('picklistoption')) {
 616                  var pickListOption = form.find('.picklistOption');
 617                  pickListOption.removeClass('hide');
 618              }
 619          })
 620      },
 621  
 622      /**
 623       * Function to add new custom field ui to the list
 624       */
 625      showCustomField : function(result) {
 626          var thisInstance = this;
 627          var contents = jQuery('#layoutEditorContainer').find('.contents');
 628          var relatedBlock = contents.find('.block_'+result['blockid']);
 629          var fieldCopy = contents.find('.newCustomFieldCopy').clone(true, true);
 630          var fieldContainer = fieldCopy.find('div.marginLeftZero.border1px');
 631          fieldContainer.addClass('opacity editFields').attr('data-field-id', result['id']).attr('data-block-id', result['blockid']);
 632          fieldContainer.find('.deleteCustomField, .saveFieldDetails').attr('data-field-id', result['id']);
 633          fieldContainer.find('.fieldLabel').html(result['label']);
 634          if(!result['customField']){
 635              fieldContainer.find('.deleteCustomField').remove();
 636          }
 637          var block = relatedBlock.find('.blockFieldsList');
 638          var sortable1 = block.find('ul[name=sortable1]');
 639          var length1 = sortable1.children().length;
 640          var sortable2 = block.find('ul[name=sortable2]');
 641          var length2 = sortable2.children().length;
 642          // Deciding where to add the new field
 643          if(length1 > length2) {
 644              sortable2.append(fieldCopy.removeClass('hide newCustomFieldCopy'));
 645          } else {
 646              sortable1.append(fieldCopy.removeClass('hide newCustomFieldCopy'));
 647          }
 648          var form = fieldCopy.find('form.fieldDetailsForm');
 649          thisInstance.setFieldDetails(result, form);
 650          thisInstance.makeFieldsListSortable();
 651      },
 652  
 653      /**
 654       * Function to set the field info for edit field actions
 655       */
 656      setFieldDetails : function(result, form) {
 657          var thisInstance = this;
 658          //add field label to the field details
 659          form.find('.modal-header').html(jQuery('<strong>'+result['label']+'</strong><div class="pull-right"><a href="javascript:void(0)" class="cancel">X</a></div>'));
 660  
 661          var defaultValueUi = form.find('.defaultValueUi');
 662          if(result['mandatory']) {
 663              form.find('[name="mandatory"]').filter(':checkbox').attr('checked', true);
 664          }
 665          if(result['presence']) {
 666              form.find('[name="presence"]').filter(':checkbox').attr('checked', true);
 667          }
 668          if(result['quickcreate']) {
 669              form.find('[name="quickcreate"]').filter(':checkbox').attr('checked', true);
 670          }
 671          if(result['isQuickCreateDisabled']) {
 672              form.find('[name="quickcreate"]').filter(':checkbox').attr('readonly', 'readonly').addClass('optionDisabled');
 673          }
 674          if(result['isSummaryField']) {
 675              form.find('[name="summaryfield"]').filter(':checkbox').attr('checked', true);
 676          }
 677          if(result['isSummaryFieldDisabled']) {
 678              form.find('[name="summaryfield"]').filter(':checkbox').attr('readonly', 'readonly').addClass('optionDisabled');
 679          }
 680          if(result['masseditable']) {
 681              form.find('[name="masseditable"]').filter(':checkbox').attr('checked', true);
 682          }
 683          if(result['isMassEditDisabled']) {
 684              form.find('[name="masseditable"]').filter(':checkbox').attr('readonly', 'readonly').addClass('optionDisabled');
 685          }
 686          if(result['isDefaultValueDisabled']) {
 687              form.find('[name="defaultvalue"]').filter(':checkbox').attr('readonly', 'readonly').addClass('optionDisabled');
 688          }
 689          if(result['defaultvalue']) {
 690              form.find('[name="defaultvalue"]').filter(':checkbox').attr('checked', true);
 691              defaultValueUi.removeClass('zeroOpacity');
 692          } else {
 693              defaultValueUi.addClass('zeroOpacity');
 694          }
 695          //based on the field model it will give the respective ui for the field
 696          var fieldModel = Vtiger_Field_Js.getInstance(result);
 697          var fieldUi = fieldModel.getUiTypeSpecificHtml();
 698          defaultValueUi.html(fieldUi);
 699          defaultValueUi.find('.chzn-select').removeClass('chzn-select');
 700  
 701          //Handled Time field UI
 702          var timeField = defaultValueUi.find('.timepicker-default');
 703          timeField.removeClass('timePicker timepicker-default');
 704          timeField.attr('data-toregister','time');
 705  
 706          //Handled date field UI
 707          var dateField = defaultValueUi.find('.dateField')
 708          dateField.removeClass('dateField');
 709          dateField.attr('data-toregister','date');
 710  
 711          defaultValueUi.find('[data-validation-engine]').attr('data-validation-engine','validate[required,funcCall[Vtiger_Base_Validator_Js.invokeValidation]]');
 712          defaultValueUi.find('[name*='+result['name']+']').attr('name', 'fieldDefaultValue');
 713          defaultValueUi.find('[name="fieldDefaultValue"]').attr('disabled','disabled');
 714          defaultValueUi.find('input').addClass('input-medium');
 715          defaultValueUi.find('.select2').addClass('row-fluid');
 716      },
 717  
 718      /**
 719       * Function to register click event for add custom block button
 720       */
 721      registerAddCustomBlockEvent : function() {
 722          var thisInstance = this;
 723          var contents = jQuery('#layoutEditorContainer').find('.contents');
 724          contents.find('.addCustomBlock').click(function(e) {
 725              var addBlockContainer = contents.find('.addBlockModal').clone(true, true);
 726  
 727              var callBackFunction = function(data) {
 728                  data.find('.addBlockModal').removeClass('hide');
 729                  //register all select2 Elements
 730                  app.showSelect2ElementView(data.find('select'));
 731  
 732                  var form = data.find('.addCustomBlockForm');
 733                  thisInstance.setBlocksListArray(form);
 734                  var fieldLabel = form.find('[name="label"]');
 735                  var params = app.validationEngineOptions;
 736                  params.onValidationComplete = function(form, valid){
 737                      if(valid) {
 738                          var formData = form.serializeFormData();
 739                          if(jQuery.inArray(formData['label'], thisInstance.blockNamesList) == -1) {
 740                              thisInstance.saveBlockDetails(form).then(
 741                                  function(data) {
 742                                      var params = {};
 743                                      if(data['success']) {
 744                                          var result = data['result'];
 745                                          thisInstance.displayNewCustomBlock(result);
 746                                          thisInstance.updateNewSequenceForBlocks(result['sequenceList']);
 747                                          thisInstance.appendNewBlockToBlocksList(result, form);
 748                                          thisInstance.makeFieldsListSortable();
 749  
 750                                          params['text'] = app.vtranslate('JS_CUSTOM_BLOCK_ADDED');
 751                                      } else {
 752                                          params['text'] = data['error']['message'];
 753                                          params['type'] = 'error';
 754                                      }
 755                                      Settings_Vtiger_Index_Js.showMessage(params);
 756                                  }
 757                              );
 758                              app.hideModalWindow();
 759                              return valid;
 760                          } else {
 761                              var result = app.vtranslate('JS_BLOCK_NAME_EXISTS');
 762                              fieldLabel.validationEngine('showPrompt', result , 'error','topLeft',true);
 763                              e.preventDefault();
 764                              return;
 765                          }
 766                      }
 767                  }
 768                  form.validationEngine(params);
 769  
 770                  form.submit(function(e) {
 771                      e.preventDefault();
 772                  })
 773              }
 774              app.showModalWindow(addBlockContainer,function(data) {
 775                  if(typeof callBackFunction == 'function') {
 776                      callBackFunction(data);
 777                  }
 778              }, {'width':'1000px'});
 779          });
 780      },
 781  
 782      /**
 783       * Function to save the new custom block details
 784       */
 785      saveBlockDetails : function(form) {
 786          var thisInstance = this;
 787          var aDeferred = jQuery.Deferred();
 788          var progressIndicatorElement = jQuery.progressIndicator({
 789              'position' : 'html',
 790              'blockInfo' : {
 791                  'enabled' : true
 792              }
 793          });
 794          var params = form.serializeFormData();
 795          params['module'] = app.getModuleName();
 796          params['parent'] = app.getParentModuleName();
 797          params['sourceModule'] = jQuery('#selectedModuleName').val();
 798          params['action'] = 'Block';
 799          params['mode'] = 'save';
 800  
 801          AppConnector.request(params).then(
 802              function(data) {
 803                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
 804                  aDeferred.resolve(data);
 805              },
 806              function(error) {
 807                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
 808                  aDeferred.reject(error);
 809              }
 810          );
 811          return aDeferred.promise();
 812      },
 813  
 814      /**
 815       * Function used to display the new custom block ui after save
 816       */
 817      displayNewCustomBlock : function(result) {
 818          var thisInstance = this;
 819          var contents = jQuery('#layoutEditorContainer').find('.contents');
 820          var beforeBlockId = result['beforeBlockId'];
 821          var beforeBlock = contents.find('.block_'+beforeBlockId);
 822  
 823          var newBlockCloneCopy = contents.find('.newCustomBlockCopy').clone(true, true);
 824          newBlockCloneCopy.data('blockId', result['id']).find('.blockLabel').append(jQuery('<strong>'+result['label']+'</strong>'));
 825          newBlockCloneCopy.find('.blockVisibility').data('blockId', result['id']);
 826          if(result['isAddCustomFieldEnabled']) {
 827              newBlockCloneCopy.find('.addCustomField').removeClass('hide');
 828          }
 829          beforeBlock.after(newBlockCloneCopy.removeClass('hide newCustomBlockCopy').addClass('editFieldsTable block_'+result['id']));
 830  
 831          newBlockCloneCopy.find('.blockFieldsList').sortable({'connectWith' : '.blockFieldsList'});
 832      },
 833  
 834      /**
 835       * Function to update the sequence for all blocks after adding new Block
 836       */
 837      updateNewSequenceForBlocks : function(sequenceList) {
 838          var contents = jQuery('#layoutEditorContainer').find('.contents');
 839          jQuery.each(sequenceList, function(blockId, sequence) {
 840              contents.find('.block_'+blockId).data('sequence', sequence);
 841          });
 842      },
 843  
 844      /**
 845       * Function to update the block list with the new block label in the clone container
 846       */
 847      appendNewBlockToBlocksList : function(result, form) {
 848          var contents = jQuery('#layoutEditorContainer').find('.contents');
 849          var hiddenAddBlockModel = contents.find('.addBlockModal');
 850          var blocksListSelect = hiddenAddBlockModel.find('[name="beforeBlockId"]');
 851          var option = jQuery("<option>",{
 852                            value: result['id'],
 853                            text: result['label']
 854                      })
 855          blocksListSelect.append(option.attr('data-label', result['label']));
 856      },
 857  
 858      /**
 859       * Function to update the block list to remove the deleted custom block label in the clone container
 860       */
 861      removeBlockFromBlocksList : function(blockId) {
 862          var contents = jQuery('#layoutEditorContainer').find('.contents');
 863          var hiddenAddBlockModel = contents.find('.addBlockModal');
 864          var blocksListSelect = hiddenAddBlockModel.find('[name="beforeBlockId"]');
 865          blocksListSelect.find('option[value="'+blockId+'"]').remove();
 866      },
 867  
 868      /**
 869       * Function to register the change event for block visibility
 870       */
 871      registerBlockVisibilityEvent : function() {
 872          var thisInstance = this;
 873          var contents = jQuery('#layoutEditorContainer').find('.contents');
 874          contents.on('click', 'li.blockVisibility', function(e) {
 875              var currentTarget = jQuery(e.currentTarget);
 876              var oldDisplayStatus = currentTarget.data('visible');
 877              if(oldDisplayStatus == '0') {
 878                  currentTarget.find('.icon-ok').removeClass('hide');
 879                  currentTarget.data('visible', '1');
 880              } else {
 881                  currentTarget.find('.icon-ok').addClass('hide');
 882                  currentTarget.data('visible', '0');
 883              }
 884              thisInstance.updateBlockStatus(currentTarget);
 885          })
 886      },
 887  
 888      /**
 889       * Function to save the changed visibility for the block
 890       */
 891      updateBlockStatus : function(currentTarget) {
 892          var thisInstance = this;
 893          var blockStatus = currentTarget.data('visible');
 894          var progressIndicatorElement = jQuery.progressIndicator({
 895              'position' : 'html',
 896              'blockInfo' : {
 897                  'enabled' : true
 898              }
 899          });
 900          var params = {};
 901          params['module'] = app.getModuleName();
 902          params['parent'] = app.getParentModuleName();
 903          params['sourceModule'] = jQuery('#selectedModuleName').val();
 904          params['action'] = 'Block';
 905          params['mode'] = 'save';
 906          params['blockid'] = currentTarget.data('blockId');
 907          params['display_status'] = blockStatus;
 908  
 909          AppConnector.request(params).then(
 910              function(data) {
 911                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
 912                  var params = {};
 913                  if(blockStatus == '1') {
 914                      params['text'] = app.vtranslate('JS_BLOCK_VISIBILITY_SHOW');
 915                  } else {
 916                      params['text'] = app.vtranslate('JS_BLOCK_VISIBILITY_HIDE');
 917                  }
 918                  Settings_Vtiger_Index_Js.showMessage(params);
 919              },
 920              function(error) {
 921                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
 922              }
 923          );
 924      },
 925  
 926      /**
 927       * Function to register the click event for inactive fields list
 928       */
 929      registerInactiveFieldsEvent : function() {
 930          var thisInstance = this;
 931          var contents = jQuery('#layoutEditorContainer').find('.contents');
 932          contents.on('click', 'li.inActiveFields', function(e) {
 933              var currentTarget = jQuery(e.currentTarget);
 934              var currentBlock = currentTarget.closest('.editFieldsTable');
 935              var blockId = currentBlock.data('blockId');
 936              //If there are no hidden fields, show pnotify
 937              if(jQuery.isEmptyObject(thisInstance.inActiveFieldsList[blockId])) {
 938                  var params = {};
 939                  params['text'] = app.vtranslate('JS_NO_HIDDEN_FIELDS_EXISTS');
 940                  params['type'] = 'error';
 941                  Settings_Vtiger_Index_Js.showMessage(params);
 942              } else {
 943                  var inActiveFieldsContainer = contents.find('.inactiveFieldsModal').clone(true, true);
 944  
 945                  var callBackFunction = function(data) {
 946                      data.find('.inactiveFieldsModal').removeClass('hide');
 947                      thisInstance.reactiveFieldsList = [];
 948                      var form = data.find('.inactiveFieldsForm');
 949                      thisInstance.showHiddenFields(blockId, form);
 950                      //register click event for reactivate button in the inactive fields modal
 951                      data.find('[name="reactivateButton"]').click(function(e) {
 952                          thisInstance.createReactivateFieldslist(blockId, form);
 953                          thisInstance.reActivateHiddenFields(currentBlock);
 954                          app.hideModalWindow();
 955                      });
 956                  }
 957  
 958                  app.showModalWindow(inActiveFieldsContainer,function(data) {
 959                      if(typeof callBackFunction == 'function') {
 960                          callBackFunction(data);
 961                      }
 962                  }, {'width':'1000px'});
 963              }
 964          });
 965  
 966      },
 967  
 968      /**
 969       * Function to show the list of inactive fields in the modal
 970       */
 971      showHiddenFields : function(blockId, form) {
 972          var thisInstance = this;
 973          jQuery.each(thisInstance.inActiveFieldsList[blockId], function(key, value) {
 974              var inActiveField = jQuery('<div class="span4 marginLeftZero padding-bottom1per"><label class="checkbox">\n\
 975                                      <input type="checkbox" class="inActiveField" value="'+key+'" />&nbsp;'+value+'</label></div>');
 976              form.find('.inActiveList').append(inActiveField);
 977          });
 978      },
 979  
 980      /**
 981       * Function to create the list of reactivate fields list
 982       */
 983      createReactivateFieldslist : function(blockId, form) {
 984          var thisInstance = this;
 985          form.find('.inActiveField').each(function(index,domElement){
 986              var element = jQuery(domElement);
 987              var fieldId = element.val();
 988              if(element.is(':checked')) {
 989                  delete thisInstance.inActiveFieldsList[blockId][fieldId];
 990                  thisInstance.reactiveFieldsList.push(fieldId);
 991              }
 992          });
 993      },
 994  
 995      /**
 996       * Function to unHide the selected fields in the inactive fields modal
 997       */
 998      reActivateHiddenFields : function(currentBlock) {
 999          var thisInstance = this;
1000          var progressIndicatorElement = jQuery.progressIndicator({
1001              'position' : 'html',
1002              'blockInfo' : {
1003                  'enabled' : true
1004              }
1005          });
1006          var params = {};
1007          params['module'] = app.getModuleName();
1008          params['parent'] = app.getParentModuleName();
1009          params['action'] = 'Field';
1010          params['mode'] = 'unHide';
1011          params['blockId'] = currentBlock.data('blockId');
1012          params['fieldIdList'] = JSON.stringify(thisInstance.reactiveFieldsList);
1013  
1014          AppConnector.request(params).then(
1015              function(data) {
1016                  for(var index in data.result) {
1017                      thisInstance.showCustomField(data.result[index]);
1018                  }
1019                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
1020                  var params = {};
1021                  params['text'] = app.vtranslate('JS_SELECTED_FIELDS_REACTIVATED');
1022                  Settings_Vtiger_Index_Js.showMessage(params);
1023              },
1024              function(error) {
1025                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
1026              }
1027          );
1028      },
1029      /**
1030       * Function to register the click event for delete custom block
1031       */
1032      registerDeleteCustomBlockEvent : function() {
1033          var thisInstance = this;
1034          var contents = jQuery('#layoutEditorContainer').find('.contents');
1035          var table = contents.find('.editFieldsTable');
1036          contents.on('click', 'li.deleteCustomBlock', function(e) {
1037              var currentTarget = jQuery(e.currentTarget);
1038              var table = currentTarget.closest('div.editFieldsTable');
1039              var blockId = table.data('blockId');
1040  
1041              var message = app.vtranslate('JS_LBL_ARE_YOU_SURE_YOU_WANT_TO_DELETE');
1042              Vtiger_Helper_Js.showConfirmationBox({'message' : message}).then(
1043                  function(e) {
1044                      thisInstance.deleteCustomBlock(blockId);
1045                  },
1046                  function(error, err){
1047  
1048                  }
1049              );
1050          });
1051      },
1052  
1053      /**
1054       * Function to delete the custom block
1055       */
1056      deleteCustomBlock : function(blockId) {
1057          var thisInstance = this;
1058          var progressIndicatorElement = jQuery.progressIndicator({
1059              'position' : 'html',
1060              'blockInfo' : {
1061                  'enabled' : true
1062              }
1063          });
1064  
1065          var params = {};
1066          params['module'] = app.getModuleName();
1067          params['parent'] = app.getParentModuleName();
1068          params['action'] = 'Block';
1069          params['mode'] = 'delete';
1070          params['blockid'] = blockId;
1071  
1072          AppConnector.request(params).then(
1073              function(data) {
1074                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
1075                  var params = {};
1076                  if(data['success']) {
1077                      thisInstance.removeDeletedBlock(blockId);
1078                      thisInstance.removeBlockFromBlocksList(blockId);
1079                      params['text'] = app.vtranslate('JS_CUSTOM_BLOCK_DELETED');
1080                  } else {
1081                      params['text'] = data['error']['message'];
1082                      params['type'] = 'error';
1083                  }
1084                  Settings_Vtiger_Index_Js.showMessage(params);
1085              },
1086              function(error) {
1087                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
1088              }
1089          );
1090      },
1091  
1092      /**
1093       * Function to remove the deleted custom block from the ui
1094       */
1095      removeDeletedBlock : function(blockId) {
1096          var contents = jQuery('#layoutEditorContainer').find('.contents');
1097          var deletedTable = contents.find('.block_'+blockId);
1098          deletedTable.fadeOut('slow').remove();
1099      },
1100  
1101      /**
1102       * Function to register the click event for delete custom field
1103       */
1104      registerDeleteCustomFieldEvent : function(contents) {
1105          var thisInstance = this;
1106          if(typeof contents == 'undefined') {
1107              contents = jQuery('#layoutEditorContainer').find('.contents');
1108          }
1109          contents.find('a.deleteCustomField').click(function(e) {
1110              var currentTarget = jQuery(e.currentTarget);
1111              var fieldId = currentTarget.data('fieldId');
1112              var message = app.vtranslate('JS_LBL_ARE_YOU_SURE_YOU_WANT_TO_DELETE');
1113              Vtiger_Helper_Js.showConfirmationBox({'message' : message}).then(
1114                  function(e) {
1115                      thisInstance.deleteCustomField(fieldId).then(
1116                          function(data) {
1117                              var field = currentTarget.closest('div.editFields');
1118                              var blockId = field.data('blockId');
1119                              field.parent().fadeOut('slow').remove();
1120                              var block = jQuery('#block_'+blockId);
1121                              thisInstance.reArrangeBlockFields(block);
1122                              var params = {};
1123                              params['text'] = app.vtranslate('JS_CUSTOM_FIELD_DELETED');
1124                              Settings_Vtiger_Index_Js.showMessage(params);
1125                          },function(error, err) {
1126  
1127                          }
1128                      );
1129                  },
1130                  function(error, err){
1131  
1132                  }
1133              );
1134          });
1135      },
1136  
1137      /**
1138       * Function to delete the custom field
1139       */
1140      deleteCustomField : function(fieldId) {
1141          var thisInstance = this;
1142          var aDeferred = jQuery.Deferred();
1143          var progressIndicatorElement = jQuery.progressIndicator({
1144              'position' : 'html',
1145              'blockInfo' : {
1146                  'enabled' : true
1147              }
1148          });
1149  
1150          var params = {};
1151          params['module'] = app.getModuleName();
1152          params['parent'] = app.getParentModuleName();
1153          params['action'] = 'Field';
1154          params['mode'] = 'delete';
1155          params['fieldid'] = fieldId;
1156  
1157          AppConnector.request(params).then(
1158              function(data) {
1159                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
1160                  aDeferred.resolve(data);
1161              },
1162              function(error) {
1163                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
1164                  aDeferred.reject();
1165              }
1166          );
1167          return aDeferred.promise();
1168      },
1169  
1170  
1171      /**
1172       * Function to register the click event for save button after edit field details
1173       */
1174      registerSaveFieldDetailsEvent : function(form) {
1175          var thisInstance = this;
1176          var submitButtton = form.find('.saveFieldDetails');
1177          var fieldId = submitButtton.data('fieldId');
1178          var block = submitButtton.closest('.editFieldsTable');
1179          var blockId = block.data('blockId');
1180          //close the drop down
1181          submitButtton.closest('.btn-group').removeClass('open');
1182          //adding class opacity to fieldRow - to give opacity to the actions of the fields
1183          var fieldRow = submitButtton.closest('.editFields');
1184          fieldRow.addClass('opacity');
1185  
1186          thisInstance.saveFieldDetails(submitButtton).then(
1187              function(data) {
1188                  var result = data['result'];
1189                  var fieldLabel = fieldRow.find('.fieldLabel');
1190                  if(result['presence'] == '1') {
1191                      fieldRow.parent().fadeOut('slow').remove();
1192  
1193                      if(jQuery.isEmptyObject(thisInstance.inActiveFieldsList[blockId])) {
1194                          if(thisInstance.inActiveFieldsList.length == '0') {
1195                              thisInstance.inActiveFieldsList = {};
1196                          }
1197                          thisInstance.inActiveFieldsList[blockId] = {};
1198                          thisInstance.inActiveFieldsList[blockId][fieldId] = result['label'];
1199                      } else {
1200                          thisInstance.inActiveFieldsList[blockId][fieldId] = result['label'];
1201                      }
1202                      thisInstance.reArrangeBlockFields(block);
1203                  }
1204                  if(result['mandatory']) {
1205                      if(fieldLabel.find('.redColor').length == '0') {
1206                          fieldRow.find('.fieldLabel').append(jQuery('<span class="redColor">*</span>'));
1207                      }
1208                  } else {
1209                      fieldRow.find('.fieldLabel').find('.redColor').remove();
1210                  }
1211  
1212                  //updating the hidden container with saved values.
1213                  var dropDownMenu = form.closest('.dropdown-menu');
1214                  app.destroyChosenElement(form);
1215                  var selectElemet = form.find('.defaultValueUi ').find('select');
1216                  var selectedvalue = selectElemet.val();
1217                  selectElemet.removeAttr('disabled');
1218                  selectElemet.find('option').removeAttr('selected');
1219                  if(selectedvalue != null ){
1220                      if(typeof(selectElemet.attr('multiple')) == 'undefined'){
1221                          var encodedSelectedValue = selectedvalue.replace(/"/g, '\\"');
1222                          selectElemet.find('[value="'+encodedSelectedValue+'"]').attr('selected','selected');
1223                      } else {
1224                          for (var i = 0; i < selectedvalue.length; i++) {
1225                              var encodedSelectedValue = selectedvalue[i].replace(/"/g, '\\"');
1226                              selectElemet.find('[value="'+encodedSelectedValue+'"]').attr('selected','selected');
1227                          }
1228                      }
1229                  }
1230                  //handled registration of time field
1231                  var timeFieldElement = form.find('[data-toregister="time"]');
1232                  if(timeFieldElement.length > 0){
1233                      app.destroyTimeFields(timeFieldElement);
1234                  }
1235                  var basicContents = form.closest('.editFields').find('.basicFieldOperations');
1236                  basicContents.html(form);
1237                  dropDownMenu.remove();
1238              },
1239              function(error, err) {
1240  
1241              }
1242              );
1243      },
1244  
1245      /**
1246       * Function to save all the field details which are changed
1247       */
1248      saveFieldDetails : function(currentTarget) {
1249          var thisInstance = this;
1250          var aDeferred = jQuery.Deferred();
1251          var form = currentTarget.closest('form.fieldDetailsForm');
1252          var fieldId = currentTarget.data('fieldId');
1253                  var defaultValueField = form.find('[name=fieldDefaultValue]');
1254                  var defaultValue = defaultValueField.val();
1255          var progressIndicatorElement = jQuery.progressIndicator({
1256              'position' : 'html',
1257              'blockInfo' : {
1258                  'enabled' : true
1259              }
1260          });
1261  
1262          var params = form.serializeFormData();
1263          params['module'] = app.getModuleName();
1264          params['parent'] = app.getParentModuleName();
1265          params['action'] = 'Field';
1266          params['mode'] = 'save';
1267          params['fieldid'] = fieldId;
1268          params['sourceModule'] = jQuery('#selectedModuleName').val();
1269  
1270          AppConnector.request(params).then(
1271              function(data) {
1272                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
1273                  var params = {};
1274                  params['text'] = app.vtranslate('JS_FIELD_DETAILS_SAVED');
1275                  Settings_Vtiger_Index_Js.showMessage(params);
1276                                  if(defaultValueField.prop("tagName") == 'TEXTAREA') {
1277                                          defaultValueField.text(defaultValue);
1278                                  }
1279                  aDeferred.resolve(data);
1280              },
1281              function(error) {
1282                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
1283                  aDeferred.reject();
1284              }
1285          );
1286          return aDeferred.promise();
1287      },
1288  
1289      /**
1290       * Function to register the cahnge event for mandatory & default checkboxes in edit field details
1291       */
1292      registerFieldDetailsChange : function(contents) {
1293          if(typeof contents == 'undefined') {
1294              contents = jQuery('#layoutEditorContainer').find('.contents');
1295          }
1296          contents.on('change', '[name="mandatory"]', function(e) {
1297              var currentTarget = jQuery(e.currentTarget);
1298              if(currentTarget.attr('readonly') != 'readonly') {
1299                  var form = currentTarget.closest('.fieldDetailsForm');
1300                  var quickcreateEle = form.find('[name="quickcreate"]').filter(':checkbox').not('.optionDisabled');
1301                  var presenceEle = form.find('[name="presence"]').filter(':checkbox').not('.optionDisabled');
1302                  if(currentTarget.is(':checked')) {
1303                      quickcreateEle.attr('checked', true).attr('readonly', 'readonly');
1304                      presenceEle.attr('checked', true).attr('readonly', 'readonly');
1305                  } else {
1306                      quickcreateEle.removeAttr('readonly');
1307                      presenceEle.removeAttr('readonly');
1308                  }
1309              }
1310          })
1311  
1312          contents.on('change', '[name="defaultvalue"]', function(e) {
1313              var currentTarget = jQuery(e.currentTarget);
1314              var defaultValueUi = currentTarget.closest('span').find('.defaultValueUi');
1315              var defaultField = defaultValueUi.find('[name="fieldDefaultValue"]');
1316              if(currentTarget.is(':checked')) {
1317                  defaultValueUi.removeClass('zeroOpacity');
1318                  defaultField.removeAttr('disabled');
1319                  if(defaultField.is('select')){
1320                      defaultField.trigger("liszt:updated");
1321                  }
1322              } else {
1323                  defaultField.attr('disabled', 'disabled');
1324              //    defaultField.val('');
1325                  defaultValueUi.addClass('zeroOpacity');
1326              }
1327          })
1328  
1329      },
1330  
1331      /**
1332       * Function to register the click event for related modules list tab
1333       */
1334      relatedModulesTabClickEvent : function() {
1335          var thisInstance = this;
1336          var contents = jQuery('#layoutEditorContainer').find('.contents');
1337          var relatedContainer = contents.find('#relatedTabOrder');
1338          var relatedTab = contents.find('.relatedListTab');
1339          relatedTab.click(function() {
1340              if(relatedContainer.find('.relatedTabModulesList').length > 0) {
1341  
1342              } else {
1343                  thisInstance.showRelatedTabModulesList(relatedContainer);
1344              }
1345          });
1346      },
1347  
1348      /**
1349       * Function to show the related tab modules list in the tab
1350       */
1351      showRelatedTabModulesList : function(relatedContainer) {
1352          var thisInstance = this;
1353          var params = {};
1354          params['module'] = app.getModuleName();
1355          params['parent'] = app.getParentModuleName();
1356          params['sourceModule'] = jQuery('#selectedModuleName').val();
1357          params['view'] = 'Index';
1358          params['mode'] = 'showRelatedListLayout';
1359  
1360          AppConnector.request(params).then(
1361              function(data) {
1362                  relatedContainer.html(data);
1363                  if(jQuery(data).find('.relatedListContainer').length > 0) {
1364                      thisInstance.makeRelatedModuleSortable();
1365                      thisInstance.registerRelatedListEvents();
1366                      thisInstance.setRemovedModulesList();
1367                  }
1368              },
1369              function(error) {
1370              }
1371          );
1372      },
1373  
1374      /**
1375       * Function to get the respective module layout editor through pjax
1376       */
1377      getModuleLayoutEditor : function(selectedModule) {
1378          var thisInstance = this;
1379          var aDeferred = jQuery.Deferred();
1380          var progressIndicatorElement = jQuery.progressIndicator({
1381              'position' : 'html',
1382              'blockInfo' : {
1383                  'enabled' : true
1384              }
1385          });
1386  
1387          var params = {};
1388          params['module'] = app.getModuleName();
1389          params['parent'] = app.getParentModuleName();
1390          params['view'] = 'Index';
1391          params['sourceModule'] = selectedModule;
1392  
1393          AppConnector.requestPjax(params).then(
1394              function(data) {
1395                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
1396                  aDeferred.resolve(data);
1397              },
1398              function(error) {
1399                  progressIndicatorElement.progressIndicator({'mode' : 'hide'});
1400                  aDeferred.reject();
1401              }
1402          );
1403          return aDeferred.promise();
1404      },
1405  
1406      /**
1407       * Function to register the change event for layout editor modules list
1408       */
1409      registerModulesChangeEvent : function() {
1410          var thisInstance = this;
1411          var container = jQuery('#layoutEditorContainer');
1412          var contentsDiv = container.closest('.contentsDiv');
1413  
1414          app.showSelect2ElementView(container.find('[name="layoutEditorModules"]'), {dropdownCss : {'z-index' : 0}});
1415  
1416          container.on('change', '[name="layoutEditorModules"]', function(e) {
1417              var currentTarget = jQuery(e.currentTarget);
1418              var selectedModule = currentTarget.val();
1419              thisInstance.getModuleLayoutEditor(selectedModule).then(
1420                  function(data) {
1421                      contentsDiv.html(data);
1422                      thisInstance.registerEvents();
1423                  }
1424              );
1425          });
1426  
1427      },
1428  
1429      /**
1430       * Function to register click event for drop-downs in fields list
1431       */
1432      avoidDropDownClick : function(dropDownContainer) {
1433          dropDownContainer.find('.dropdown-menu').click(function(e) {
1434              e.stopPropagation();
1435          });
1436      },
1437          
1438      registerEditFieldDetailsClick : function(contents) {
1439          var thisInstance = this;
1440          if(typeof contents == 'undefined') {
1441              contents = jQuery('#layoutEditorContainer').find('.contents');
1442          }
1443          contents.find('.editFieldDetails').click(function(e) {
1444              var currentTarget = jQuery(e.currentTarget);
1445              var fieldRow = currentTarget.closest('div.editFields');
1446              fieldRow.removeClass('opacity');
1447              var basicDropDown = fieldRow.find('.basicFieldOperations');
1448              var dropDownContainer = currentTarget.closest('.btn-group');
1449              dropDownContainer.find('.dropdown-menu').remove();
1450              var dropDown = basicDropDown.clone().removeClass('basicFieldOperations hide').addClass('dropdown-menu');
1451              dropDownContainer.append(dropDown);
1452              var dropDownMenu  = dropDownContainer.find('.dropdown-menu');
1453              var params = app.getvalidationEngineOptions(true);
1454              params.binded = false,
1455              params.onValidationComplete = function(form,valid){
1456                  if(valid) {
1457                      thisInstance.registerSaveFieldDetailsEvent(form);
1458                  }
1459                  return false;
1460              }
1461              dropDownMenu.find('form').validationEngine(params);
1462              var defaultValueUiContainer = basicDropDown.find('.defaultValueUi');
1463  
1464  
1465              //handled registration of chosen for select element
1466              var selectElements = defaultValueUiContainer.find('select');
1467              if(selectElements.length > 0) {
1468                  dropDownMenu.find('select').addClass('chzn-select');
1469                  app.changeSelectElementView(dropDownMenu);
1470              }
1471  
1472              //handled registration of time field
1473              var timeFieldElement = defaultValueUiContainer.find('[data-toregister="time"]');
1474              if(timeFieldElement.length > 0){
1475                  dropDownMenu.find('[data-toregister="time"]').addClass('timepicker-default timePicker');
1476                  app.registerEventForTimeFields(dropDownMenu);
1477              }
1478  
1479              //handled registration for date fields
1480               var dateField = defaultValueUiContainer.find('[data-toregister="date"]');
1481               if(dateField.length > 0) {
1482                   dropDownMenu.find('[data-toregister="date"]').addClass('dateField');
1483                   app.registerEventForDatePickerFields(dropDownMenu);
1484               }
1485              thisInstance.avoidDropDownClick(dropDownContainer);
1486  
1487              dropDownMenu.on('change', ':checkbox', function(e) {
1488                  var currentTarget = jQuery(e.currentTarget);
1489                  if(currentTarget.attr('readonly') == 'readonly') {
1490                      var status = jQuery(e.currentTarget).is(':checked');
1491                      if(!status){
1492                          jQuery(e.currentTarget).attr('checked','checked')
1493                      }else{
1494                          jQuery(e.currentTarget).removeAttr('checked');
1495                      }
1496                      e.preventDefault();
1497                  }
1498              });
1499  
1500              //added for drop down position change
1501              var offset = currentTarget.offset(),
1502                  height = currentTarget.outerHeight(),
1503                  dropHeight = dropDown.outerHeight(),
1504                  viewportBottom = $(window).scrollTop() + document.documentElement.clientHeight,
1505                  dropTop = offset.top + height,
1506                  enoughRoomBelow = dropTop + dropHeight <= viewportBottom;
1507                 if(!enoughRoomBelow) {
1508                     dropDown.addClass('bottom-up');
1509                 } else {
1510                     dropDown.removeClass('bottom-up');
1511                 }
1512  
1513              var callbackFunction = function() {
1514                  fieldRow.addClass('opacity');
1515                  dropDown.remove();
1516                  jQuery('body').off('click.dropdown.data-api.layouteditor');
1517              }
1518              thisInstance.addClickOutSideEvent(dropDown, callbackFunction);
1519              
1520              jQuery('.cancel').click(function(){
1521                  callbackFunction();
1522              });
1523              jQuery('body').on('click.dropdown.data-api.layouteditor',function(e){
1524                  var target = jQuery(e.target);
1525                  //user clicked on time picker
1526                  if(target.closest('.ui-timepicker-list').length > 0) {
1527                      e.stopPropagation();
1528                  }
1529              })
1530          });
1531      },
1532  
1533      /**
1534       * Function to register all the events for blocks
1535       */
1536      registerBlockEvents : function() {
1537          var thisInstance = this;
1538          thisInstance.makeBlocksListSortable();
1539          thisInstance.registerAddCustomFieldEvent();
1540          thisInstance.registerBlockVisibilityEvent();
1541          thisInstance.registerInactiveFieldsEvent();
1542          thisInstance.registerDeleteCustomBlockEvent();
1543      },
1544  
1545      /**
1546       * Function to register all the events for fields
1547       */
1548      registerFieldEvents : function(contents) {
1549          var thisInstance = this;
1550          if(typeof contents == 'undefined') {
1551              contents = jQuery('#layoutEditorContainer').find('.contents');
1552          }
1553          app.registerEventForDatePickerFields(contents);
1554          app.registerEventForTimeFields(contents);
1555          app.changeSelectElementView(contents);
1556  
1557          thisInstance.makeFieldsListSortable();
1558          thisInstance.registerDeleteCustomFieldEvent(contents);
1559          thisInstance.registerFieldDetailsChange(contents);
1560          thisInstance.registerEditFieldDetailsClick(contents);
1561  
1562          contents.find(':checkbox').change(function(e) {
1563              var currentTarget = jQuery(e.currentTarget);
1564              if(currentTarget.attr('readonly') == 'readonly') {
1565                  var status = jQuery(e.currentTarget).is(':checked');
1566                  if(!status){
1567                      jQuery(e.currentTarget).attr('checked','checked')
1568                  }else{
1569                      jQuery(e.currentTarget).removeAttr('checked');
1570                  }
1571                  e.preventDefault();
1572              }
1573          });
1574      },
1575  
1576      /*
1577       * Function to add clickoutside event on the element - By using outside events plugin
1578       * @params element---On which element you want to apply the click outside event
1579       * @params callbackFunction---This function will contain the actions triggered after clickoutside event
1580       */
1581      addClickOutSideEvent : function(element, callbackFunction) {
1582          element.one('clickoutside',callbackFunction);
1583      },
1584      
1585      /**
1586       * register events for layout editor
1587       */
1588      registerEvents : function() {
1589          var thisInstance = this;
1590  
1591          thisInstance.registerBlockEvents();
1592          thisInstance.registerFieldEvents();
1593          thisInstance.setInactiveFieldsList();
1594          thisInstance.registerAddCustomBlockEvent();
1595          thisInstance.registerFieldSequenceSaveClick();
1596  
1597          thisInstance.relatedModulesTabClickEvent();
1598          thisInstance.registerModulesChangeEvent();
1599      }
1600  
1601  });
1602  
1603  jQuery(document).ready(function() {
1604      var instance = new Settings_LayoutEditor_Js();
1605      instance.registerEvents();
1606  })
1607  
1608  Vtiger_WholeNumberGreaterThanZero_Validator_Js("Vtiger_FloatingDigits_Validator_Js",{
1609      
1610      /**
1611       *Function which invokes field validation
1612       *@param accepts field element as parameter
1613       * @return error if validation fails true on success
1614       */
1615      invokeValidation: function(field, rules, i, options){
1616          var rangeInstance = new Vtiger_FloatingDigits_Validator_Js();
1617          rangeInstance.setElement(field);
1618          var response = rangeInstance.validate();
1619          if(response != true){
1620              return rangeInstance.getError();
1621          }
1622      }
1623      
1624  },{
1625      /**
1626       * Function to validate the decimals length
1627       * @return true if validation is successfull
1628       * @return false if validation error occurs
1629       */
1630      validate: function(){
1631          var response = this._super();
1632          if(response != true){
1633              return response;
1634          }else{
1635              var fieldValue = this.getFieldValue();
1636              if (fieldValue < 2 || fieldValue > 5) {
1637                  var errorInfo = app.vtranslate('JS_PLEASE_ENTER_NUMBER_IN_RANGE_2TO5');
1638                  this.setError(errorInfo);
1639                  return false;
1640              }
1641              
1642              var specialChars = /^[+]/ ;
1643              if (specialChars.test(fieldValue)) {
1644                  var error = app.vtranslate('JS_CONTAINS_ILLEGAL_CHARACTERS');
1645                  this.setError(error);
1646                  return false;
1647              }
1648              return true;
1649          }
1650      }
1651  });
1652  
1653  Vtiger_WholeNumberGreaterThanZero_Validator_Js("Vtiger_DecimalMaxLength_Validator_Js",{
1654      
1655      /**
1656       *Function which invokes field validation
1657       *@param accepts field element as parameter
1658       * @return error if validation fails true on success
1659       */
1660      invokeValidation: function(field, rules, i, options){
1661          var rangeInstance = new Vtiger_DecimalMaxLength_Validator_Js();
1662          rangeInstance.setElement(field);
1663          var response = rangeInstance.validate();
1664          if(response != true){
1665              return rangeInstance.getError();
1666          }
1667      }
1668      
1669  },{
1670      /**
1671       * Function to validate the fieldLength
1672       * @return true if validation is successfull
1673       * @return false if validation error occurs
1674       */
1675      validate: function(){
1676          var response = this._super();
1677          if(response != true){
1678              return response;
1679          }else{
1680              var fieldValue = this.getFieldValue();
1681              var decimalFieldValue = jQuery('#createFieldForm').find('[name="decimal"]').val();
1682              var fieldLength = parseInt(64)-parseInt(decimalFieldValue);
1683              if (fieldValue > fieldLength && !(fieldLength < 0) && fieldLength >= 59) {
1684                  var errorInfo = app.vtranslate('JS_LENGTH_SHOULD_BE_LESS_THAN_EQUAL_TO')+' '+fieldLength;
1685                  this.setError(errorInfo);
1686                  return false;
1687              }
1688              
1689              var specialChars = /^[+]/ ;
1690              if (specialChars.test(fieldValue)) {
1691                  var error = app.vtranslate('JS_CONTAINS_ILLEGAL_CHARACTERS');
1692                  this.setError(error);
1693                  return false;
1694              }
1695              return true;
1696          }
1697      }
1698  });
1699  
1700  Vtiger_WholeNumberGreaterThanZero_Validator_Js("Vtiger_MaxLength_Validator_Js",{
1701      
1702      /**
1703       *Function which invokes field validation
1704       *@param accepts field element as parameter
1705       * @return error if validation fails true on success
1706       */
1707      invokeValidation: function(field, rules, i, options){
1708          var rangeInstance = new Vtiger_DecimalMaxLength_Validator_Js();
1709          rangeInstance.setElement(field);
1710          var response = rangeInstance.validate();
1711          if(response != true){
1712              return rangeInstance.getError();
1713          }
1714      }
1715      
1716  },{
1717      /**
1718       * Function to validate the fieldLength
1719       * @return true if validation is successfull
1720       * @return false if validation error occurs
1721       */
1722      validate: function(){
1723          var response = this._super();
1724          if(response != true){
1725              return response;
1726          }else{
1727              var fieldValue = this.getFieldValue();
1728              if (fieldValue > 255) {
1729                  var errorInfo = app.vtranslate('JS_LENGTH_SHOULD_BE_LESS_THAN_EQUAL_TO')+' 255';
1730                  this.setError(errorInfo);
1731                  return false;
1732              }
1733              
1734              var specialChars = /^[+]/ ;
1735              if (specialChars.test(fieldValue)) {
1736                  var error = app.vtranslate('JS_CONTAINS_ILLEGAL_CHARACTERS');
1737                  this.setError(error);
1738                  return false;
1739              }
1740              return true;
1741          }
1742      }
1743  });
1744  
1745  Vtiger_Base_Validator_Js("Vtiger_FieldLabel_Validator_Js",{
1746      
1747      /**
1748       *Function which invokes field validation
1749       *@param accepts field element as parameter
1750       * @return error if validation fails true on success
1751       */
1752      invokeValidation: function(field, rules, i, options){
1753          var instance = new Vtiger_FieldLabel_Validator_Js();
1754          instance.setElement(field);
1755          var response = instance.validate();
1756          if(response != true){
1757              return instance.getError();
1758          }
1759      }
1760      
1761  },{
1762      /**
1763       * Function to validate the field label
1764       * @return true if validation is successfull
1765       * @return false if validation error occurs
1766       */
1767      validate: function(){
1768          var fieldValue = this.getFieldValue();
1769          return this.validateValue(fieldValue);
1770      },
1771      
1772      validateValue : function(fieldValue){
1773          var specialChars = /[&\<\>\:\'\"\,\_]/ ;
1774  
1775          if (specialChars.test(fieldValue)) {
1776              var errorInfo = app.vtranslate('JS_SPECIAL_CHARACTERS')+" & < > ' \" : , _ "+app.vtranslate('JS_NOT_ALLOWED');
1777              this.setError(errorInfo);
1778              return false;
1779          } 
1780          return true;
1781      }
1782  });
1783  
1784  Vtiger_Base_Validator_Js("Vtiger_PicklistFieldValues_Validator_Js",{
1785      
1786      /**
1787       *Function which invokes field validation
1788       *@param accepts field element as parameter
1789       * @return error if validation fails true on success
1790       */
1791      invokeValidation: function(field, rules, i, options){
1792          var instance = new Vtiger_PicklistFieldValues_Validator_Js();
1793          instance.setElement(field);
1794          var response = instance.validate();
1795          if(response != true){
1796              return instance.getError();
1797          }
1798      }
1799      
1800  },{
1801      /**
1802       * Function to validate the field label
1803       * @return true if validation is successfull
1804       * @return false if validation error occurs
1805       */
1806      validate: function(){
1807          var fieldValue = this.getFieldValue();
1808          return this.validateValue(fieldValue);
1809      },
1810      
1811      validateValue : function(fieldValue){
1812          var specialChars = /(\<|\>)/gi ;
1813          if (specialChars.test(fieldValue)) {
1814              var errorInfo = app.vtranslate('JS_SPECIAL_CHARACTERS')+" < >"+app.vtranslate('JS_NOT_ALLOWED');
1815              this.setError(errorInfo);
1816              return false;
1817          } 
1818          return true;
1819      }
1820  });


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1