Monday, August 16, 2010

Custom javascript validation scripts in Module Builder

Often when creating edit views in any application there is a need to have complex validation rules. Most of the time more than one field is evaluated to validate the data entered. SugarCrm have a lot of built in support for single field validations but if you want multiple fields in a validations rule or interdependencies between fields you will need to code this yourself.

A way to achieve this would be to generate the initial edit view in module builder and then manually change the generated code file. Depending on the way you implement the code changes and validation this file might no longer be module builder compatible.

This posting will explain how you can modify SugarCrm 5.5.2 code to add support for custom JavaScript in the module builder to validate form.  Error messages will be presented to the user like all other validation error messages.
  1. Go to Admin ->  ModuleBuilder. Open desired package/module/fields.
  2. Add new field (select a suitable field type).
  3. In the field edit screen there are 3 new fields:  JS function name, JS function code and JS Error message.
  4. In JS function name only enter the function name without parentheses like check_dates.
  5. In JS function code enter the full JavaScript function code including the function keyword.
  6. In JS error message enter the custom error message.

Please see the image below

There are some restrictions on what the validation function can do:
  • The function will have only one argument passed as a parameter "form". Using this parameter the custom function can access any field value.
  • The function will a boolean (true/false). If validation passed then true else false.
  • Only use javascript multi line comment in function code /* comment */.
When the validation fails then the defined JS Error message will be shown. This message can be localized from SugarCrm "Labels" screen, if you have my patch for built-in translation support in module builder). It can be localized for each installed language.

Here is a sample validation function:

/* use multiline comment only. form is required in parameter as it will contain the form name for  EditView and sidecreateview*/

function check_start_date(form) { /* declaring and initialising with the html form element for reducing redundancy */
 var startDate = document.forms[form].elements['start_date'];
 var endDate = document.forms[form].elements['end_date']; /* declaring the date var for fields*/
 var startDateVal;
 var endDateVal; /* check field exist and must not be empty */
 if (startDate != '' || enddate != '' || startDate.value.length > 0 || endDate.value.length > 0) {
  startDateVal = Date.parse(startDate.value);
  endDateVal = Date.parse(endDate.value);
  if (startDateVal <= endDateVal) {
   return true;
  } else {
   return false;
  }
 } else {
  return false;
 }
}

This patch/hack is not upgrade safe, which means you cannot just upgrade to a newer official SugarCrm release.

The following lists the changed files:



include/EditView/EditView2.php
(function display to create & assign javascript code)

//HACK: MB support for customcode actions/validation (onblur/onsave)
$tempscript='';
//HACK: MB support for customcode actions/validation (onblur/onsave)
if(isset($this->defs['templateMeta']['javascript'])) {
   if(is_array($this->defs['templateMeta']['javascript'])) {
  $this->th->ss->assign('externalJSFile', 'modules/' . $this->module . '/metadata/editvewdefs.js');
   } else {
  //HACK: MB support for customcode actions/validation (onblur/onsave)
  //$this->th->ss->assign('scriptBlocks', $this->defs['templateMeta']['javascript']);
  $tempscript=$this->defs['templateMeta']['javascript'];
  //HACK: MB support for customcode actions/validation (onblur/onsave)
   }
}

$this->th->ss->assign('id', $this->fieldDefs['id']['value']);
$this->th->ss->assign('offset', $this->offset + 1);
$this->th->ss->assign('APP', $app_strings);
$this->th->ss->assign('MOD', $mod_strings);

//HACK: MB support for customcode actions/validation (onblur/onsave)
foreach($this->fieldDefs as $key => $val){
 if(isset($this->fieldDefs[$key]['validation']['functionName']) && !empty($this->fieldDefs[$key]['validation']['functionName'])){
  if(isset($this->fieldDefs[$key]['customjs'])){
     $tempscript.='{literal}<script type="text/javascript" language="Javascript">'.html_entity_decode($this->fieldDefs[$key]['customjs'],ENT_QUOTES).'</script>{/literal}';
  }
  if(isset($this->fieldDefs[$key]['validation'])&& is_array($this->fieldDefs[$key]['validation'])!=true){
     $this->fieldDefs[$key]['validation'] = unserialize(html_entity_decode($this->fieldDefs[$key]['validation']));
  }
 }
}
$this->th->ss->assign('scriptBlocks', $tempscript);
//HACK: MB support for customcode actions/validation (onblur/onsave)



include/javascript/javascript.php
(function addField modified to add new case for custom function)

//HACK: MB support for customcode actions/validation (onblur/onsave)
case 'customFunction':
 $functionName = $this->sugarbean->field_name_map[$field]['validation']['functionName'];
 if(!empty($functionName)){
  $errorMessage = $this->sugarbean->field_name_map[$field]['validation']['errorMessage'];
  $fieldType = $this->sugarbean->field_name_map[$field]['validation']['type'];
  $required = 'true';
  if(!empty($displayField)){
   $dispField = $displayField;
  }
  else{
   $dispField = $field;
  }
  $this->addToValidateCustomFunction($dispField,$fieldType,$vname,$required,$prefix,$functionName,$errorMessage);                 
 }else{
  if(!empty($displayField)){
   $dispField = $displayField;
  }
  else{
   $dispField = $field;
  }
  $type = (!empty($this->sugarbean->field_name_map[$field]['custom_type']))?$this->sugarbean->field_name_map[$field]['custom_type']:$this->sugarbean->field_name_map[$field]['type'];
  $this->addFieldGeneric($dispField,$type,$vname,$required,$prefix );       
 }
 break;
//HACK: MB support for customcode actions/validation (onblur/onsave)

(new function added in class JavaScript.)

//HACK: MB support for customcode actions/validation (onblur/onsave)
function addToValidateCustomFunction($field, $type, $displayName, $required, $prefix='',$functionName='',$errorMessage=''){
 $this->script .= "addToValidateCustomFunction('".$this->formname."', '".$prefix.$field."', '".$type . "', $required,'".$this->stripEndColon(translate($displayName,$this->sugarbean->module_dir))."' , '$functionName','".$this->stripEndColon(translate($errorMessage,$this->sugarbean->module_dir))."' );\n";
}
//HACK: MB support for customcode actions/validation (onblur/onsave)



include/javascript/sugar_grp1.js
(new global variable & function added to add validation to validation queue.)

//HACK: MB support for customcode actions/validation (onblur/onsave)
var customFunctionName = ''; 
//HACK: MB support for customcode actions/validation (onblur/onsave)

//HACK: MB support for customcode actions/validation (onblur/onsave)

function addToValidateCustomFunction(formname, name, type, required, msg, functionName, errorMessage) {
 required = false;
 if (errorMessage != '') {
  msg = msg + " " + errorMessage;
 }
 addToValidate(formname, name, type, required, msg);
 validate[formname][validate[formname].length - 1][jstypeIndex] = 'customFunction';
 validate[formname][validate[formname].length - 1][customFunctionName] = functionName;
} 
//HACK: MB support for customcode actions/validation (onblur/onsave)

(function validate_form modified and new case added for customfunction. This code will call custom js function.)

//HACK: MB support for customcode actions/validation (onblur/onsave)
case 'customFunction':
 var functionName = validate[formname][i][customFunctionName];

 var fn = functionName + '(\'' + formname + '\')';
 var execstatus = true;
 try {
  execstatus = eval(fn);
 } catch (err) {
  alert(err);
  execstatus = false;
 }
 if (execstatus == false) {
  isError = true;
  add_error_style(formname, validate[formname][i][nameIndex], validate[formname][i][msgIndex]);
 }
 break;
//HACK: MB support for customcode actions/validation (onblur/onsave)



modules/DynamicFields/templates/Fields/Forms/coreTop.tpl
(the following code will add 3 new property in EditField window in module builder. (smarty template))

{* HACK: MB support for customcode actions/validation (onblur/onsave)*}
<tr>
 <td class='mbLBL'>{$MOD.COLUMN_TITLE_CUSTOMJS_NAME_TEXT}</td>
 <td>{if $hideLevel < 5 && $MB == 1}
  <input type="text" name="validation" value="{$vardef.validation.functionName}">
  {else}
  <input type="hidden" name="validation" value="{$vardef.validation.functionName}">{$vardef.validation.functionName}
  {/if}
 </td>
</tr>
<tr>
 <td class='mbLBL'>{$MOD.COLUMN_TITLE_CUSTOMJS_TEXT}</td>
 <td>{if $hideLevel < 5 && $MB == 1}
  <textarea name="customjs">{$vardef.customjs}</textarea>
  {else}
  <input type="hidden" name="customjs" value="{$vardef.customjs}">{$vardef.customjs}
  {/if}
 </td>
</tr>
<tr>
 <td class='mbLBL'>{$MOD.COLUMN_TITLE_CUSTOMJS_ERROR_TEXT}</td>
 <td>{if $hideLevel < 5 && $MB == 1}
  <input type="text" name="customerrormsg" value="{$vardef.validation.errorMessage}">
  {else}
  <input type="hidden" name="customerrormsg" value="{$vardef.validation.errorMessage}">{$vardef.validation.errorMessage}
  {/if}
 </td>
</tr>
{* HACK: MB support for customcode actions/validation (onblur/onsave) *}



modules/EditCustomFields/language/en_us.lang.php
(labels for 3 new property in MB EditField screen)

// HACK: MB support for customcode actions/validation (onblur/onsave)
$mod_strings['COLUMN_TITLE_CUSTOMJS_NAME_TEXT']='JS Function Name:';
$mod_strings['COLUMN_TITLE_CUSTOMJS_TEXT']='JS Function Code:';
$mod_strings['COLUMN_TITLE_CUSTOMJS_ERROR_TEXT']='JS Error Message:';
//HACK: MB support for customcode actions/validation (onblur/onsave)



modules/EditCustomFields/vardefs.php
(2 new field in EditCustomFields vardefs)

//HACK: MB support for customcode actions/validation (onblur/onsave)
$dictionary['FieldsMetaData']['fields']['customjs']=array('name' =>'customjs','type' =>'text','default'=>'');
$dictionary['FieldsMetaData']['fields']['validation']=array('name' =>'validation','type' =>'text','default'=>'');
//HACK: MB support for customcode actions/validation (onblur/onsave)



modules/ModuleBuilder/controller.php
(function action_SaveField is modified to set custom js function and function name in vardefs. It will also set custom error message to language file.)

//HACK :MB support for customcode actions/validation (onblur/onsave)
if(isset($_REQUEST['validation']) && isset($_REQUEST['customjs']) && mb_strlen(trim($_REQUEST['validation']))>0 && mb_strlen(trim($_REQUEST['customjs']))>0){
 $module->mbvardefs->vardef['fields'][$_REQUEST['name']]['validation']=array('type' => 'customFunction','functionName'=>$_REQUEST['validation'],'errorMessage'=>'LBL_'.mb_strtoupper($_REQUEST['name']).'_JS_ERR_MSG');
 $module->mbvardefs->vardef['fields'][$_REQUEST['name']]['customjs']=$_REQUEST['customjs'];
}
//HACK: MB support for customcode actions/validation (onblur/onsave)
$module->mbvardefs->save () ;
// get the module again to refresh the labels we might have saved with the $field->save (e.g., for address fields)
$module = & $mb->getPackageModule ( $_REQUEST [ 'view_package' ], $_REQUEST [ 'view_module' ] ) ;
if (isset ( $_REQUEST [ 'label' ] ) && isset ( $_REQUEST [ 'labelValue' ] ))
 $module->setLabel ( $GLOBALS [ 'current_language' ], $_REQUEST [ 'label' ], $_REQUEST [ 'labelValue' ] ) ;
//HACK: MB support for customcode actions/validation (onblur/onsave)
if(isset($_REQUEST['validation']) && isset($_REQUEST['customjs']) && mb_strlen(trim($_REQUEST['validation']))>0 && mb_strlen(trim($_REQUEST['customjs']))>0){
 $module->setLabel($GLOBALS['current_language'],'LBL_'.mb_strtoupper($_REQUEST['name']).'_JS_ERR_MSG',$_REQUEST['customerrormsg']);   }            
//HACK: MB support for customcode actions/validation (onblur/onsave)



modules/ModuleBuilder/views/view.modulefield.php
(custom validation error is retrieved from language file & set in $vardef['validation']['errorMessage'] so it can be shown on EditField screen.)

//HACK: MB support for customcode actions/validation (onblur/onsave)
if(isset($vardef['validation']['errorMessage']) && !empty($vardef['validation']['errorMessage']))
 $vardef['validation']['errorMessage'] = $module->getLabel($GLOBALS['current_language'],$vardef['validation']['errorMessage']);
//HACK: MB support for customcode actions/validation (onblur/onsave)



(the following SQL statement will add 2 new field in fields_meta_data table in the sugarcrm database)

ALTER TABLE fields_meta_data
add column customjs text  NULL ,
add column validation text  NULL

Changes in the vardefs.php & language files generated by module builder when using this hack are not upgrade safe.


And here is the SVN patch/diff file


Index: include/EditView/EditView2.php
===================================================================
--- include/EditView/EditView2.php (revision 1)
+++ include/EditView/EditView2.php (working copy)
@@ -433,13 +433,17 @@
      */
     function display($showTitle = true, $ajaxSave = false) {
         global $mod_strings, $sugar_config, $app_strings, $app_list_strings, $theme, $current_user;
-
-
+  //HACK : MB support for customcode actions/validation (onblur/onsave)
+        $tempscript='';
+  //HACK : MB support for customcode actions/validation (onblur/onsave)
         if(isset($this->defs['templateMeta']['javascript'])) {
            if(is_array($this->defs['templateMeta']['javascript'])) {
              $this->th->ss->assign('externalJSFile', 'modules/' . $this->module . '/metadata/editvewdefs.js');
            } else {
-             $this->th->ss->assign('scriptBlocks', $this->defs['templateMeta']['javascript']);
+             //HACK : MB support for customcode actions/validation (onblur/onsave)
+             //$this->th->ss->assign('scriptBlocks', $this->defs['templateMeta']['javascript']);
+             $tempscript=$this->defs['templateMeta']['javascript'];
+             //HACK : MB support for customcode actions/validation (onblur/onsave)
            }
         }
 
@@ -447,6 +451,21 @@
         $this->th->ss->assign('offset', $this->offset + 1);
         $this->th->ss->assign('APP', $app_strings);
         $this->th->ss->assign('MOD', $mod_strings);
+
+  //HACK : MB support for customcode actions/validation (onblur/onsave)
+  foreach($this->fieldDefs as $key => $val){
+            if(isset($this->fieldDefs[$key]['validation']['functionName']) && !empty($this->fieldDefs[$key]['validation']['functionName'])){
+    if(isset($this->fieldDefs[$key]['customjs'])){
+                $tempscript.='{literal}<script type="text/javascript" language="Javascript">'.html_entity_decode($this->fieldDefs[$key]['customjs'],ENT_QUOTES).'</script>{/literal}';
+             }
+             if(isset($this->fieldDefs[$key]['validation'])&& is_array($this->fieldDefs[$key]['validation'])!=true){
+                $this->fieldDefs[$key]['validation'] = unserialize(html_entity_decode($this->fieldDefs[$key]['validation']));
+             }
+   }
+  }
+  $this->th->ss->assign('scriptBlocks', $tempscript);
+  //HACK : MB support for customcode actions/validation (onblur/onsave)
+
         $this->th->ss->assign('fields', $this->fieldDefs);
         $this->th->ss->assign('sectionPanels', $this->sectionPanels);
         $this->th->ss->assign('returnModule', $this->returnModule);
Index: include/javascript/javascript.php
===================================================================
--- include/javascript/javascript.php (revision 1)
+++ include/javascript/javascript.php (working copy)
@@ -124,6 +124,33 @@
       $this->addFieldDateBeforeAllowBlank($dispField,$this->sugarbean->field_name_map[$field]['type'],$vname,$required,$prefix, $compareTo );
       else $this->addFieldDateBefore($dispField,$this->sugarbean->field_name_map[$field]['type'],$vname,$required,$prefix, $compareTo );
       break;
+
+     //HACK : MB support for customcode actions/validation (onblur/onsave)
+     case 'customFunction':
+      $functionName = $this->sugarbean->field_name_map[$field]['validation']['functionName'];
+      if(!empty($functionName)){
+       $errorMessage = $this->sugarbean->field_name_map[$field]['validation']['errorMessage'];
+       $fieldType = $this->sugarbean->field_name_map[$field]['validation']['type'];
+       $required = 'true';
+       if(!empty($displayField)){
+        $dispField = $displayField;
+       }
+       else{
+        $dispField = $field;
+       }
+       $this->addToValidateCustomFunction($dispField,$fieldType,$vname,$required,$prefix,$functionName,$errorMessage);                 
+      }else{
+       if(!empty($displayField)){
+        $dispField = $displayField;
+       }
+       else{
+        $dispField = $field;
+       }
+       $type = (!empty($this->sugarbean->field_name_map[$field]['custom_type']))?$this->sugarbean->field_name_map[$field]['custom_type']:$this->sugarbean->field_name_map[$field]['type'];
+       $this->addFieldGeneric($dispField,$type,$vname,$required,$prefix );       
+      }
+      break;
+     //HACK : MB support for customcode actions/validation (onblur/onsave)
      default: 
       if(!empty($displayField)){
        $dispField = $displayField;
@@ -208,7 +235,11 @@
   $arr = $json->encode($arr);
   $this->script .= "addToValidateIsInArray('{$this->formname}', '{$name}', '{$type}', {$req}, '".$this->stripEndColon(translate($displayName,$this->sugarbean->module_dir))."', '{$arr}', '{$operator}');\n";
     }
-
+    //HACK : MB support for customcode actions/validation (onblur/onsave)
+ function addToValidateCustomFunction($field, $type, $displayName, $required, $prefix='',$functionName='',$errorMessage=''){
+  $this->script .= "addToValidateCustomFunction('".$this->formname."', '".$prefix.$field."', '".$type . "', $required,'".$this->stripEndColon(translate($displayName,$this->sugarbean->module_dir))."' , '$functionName','".$this->stripEndColon(translate($errorMessage,$this->sugarbean->module_dir))."' );\n";
+ }
+ //HACK : MB support for customcode actions/validation (onblur/onsave)
  function addAllFields($prefix,$skip_fields=null, $translate = false){
   if (!isset($skip_fields))
   {
Index: include/javascript/sugar_grp1.js
===================================================================
--- include/javascript/sugar_grp1.js (revision 1)
+++ include/javascript/sugar_grp1.js (working copy)
@@ -32,6 +32,24 @@
  * technical reasons, the Appropriate Legal Notices must display the words
  * "Powered by SugarCRM".
  ********************************************************************************/
+ 
+/*HACK : MB support for customcode actions/validation (onblur/onsave)*/
+var customFunctionName = ''; 
+/*HACK : MB support for customcode actions/validation (onblur/onsave)*/
+
+/*HACK : MB support for customcode actions/validation (onblur/onsave)*/
+
+function addToValidateCustomFunction(formname, name, type, required, msg, functionName, errorMessage) {
+ required = false;
+ if (errorMessage != '') {
+  msg = msg + " " + errorMessage;
+ }
+ addToValidate(formname, name, type, required, msg);
+ validate[formname][validate[formname].length - 1][jstypeIndex] = 'customFunction';
+ validate[formname][validate[formname].length - 1][customFunctionName] = functionName;
+} 
+/*HACK : MB support for customcode actions/validation (onblur/onsave)*/
+
 if(typeof(SUGAR)=="undefined")SUGAR={};if(typeof(SUGAR.themes)=="undefined")SUGAR.themes={};SUGAR.sugarHome={};SUGAR.subpanelUtils={};SUGAR.ajaxStatusClass={};SUGAR.tabChooser={};SUGAR.util={};SUGAR.savedViews={};SUGAR.dashlets={};SUGAR.unifiedSearchAdvanced={};SUGAR.searchForm={};SUGAR.language={};SUGAR.Studio={};SUGAR.contextMenu={};var dtCh="-";var minYear=1900;var maxYear=2100;var nameIndex=0;var typeIndex=1;var requiredIndex=2;var msgIndex=3;var jstypeIndex=5;var minIndex=10;var maxIndex=11;var altMsgIndex=15;var compareToIndex=7;var arrIndex=12;var operatorIndex=13;var allowblank=8;var validate=new Array();var maxHours=24;var requiredTxt='Missing Required Field:'
 var invalidTxt='Invalid Value:'
 var secondsSinceLoad=0;var inputsWithErrors=new Array();var lastSubmitTime=0;var alertList=new Array();var oldStartsWith='';function isSupportedIE(){var userAgent=navigator.userAgent.toLowerCase();if(userAgent.indexOf("msie")!=-1&&userAgent.indexOf("mac")==-1&&userAgent.indexOf("opera")==-1){var version=navigator.appVersion.match(/MSIE (.\..)/)[1];if(version>=5.5){return true;}else{return false;}}}
@@ -161,53 +179,356 @@
 function hex2dec(hex){return(parseInt(hex,16));}
 var hexDigit=new Array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F");function dec2hex(dec){return(hexDigit[dec>>4]+hexDigit[dec&15]);}
 function fade_error_style(normalStyle,percent){errorStyle='c60c30';var r1=hex2dec(errorStyle.slice(0,2));var g1=hex2dec(errorStyle.slice(2,4));var b1=hex2dec(errorStyle.slice(4,6));var r2=hex2dec(normalStyle.slice(0,2));var g2=hex2dec(normalStyle.slice(2,4));var b2=hex2dec(normalStyle.slice(4,6));var pc=percent/100;r=Math.floor(r1+(pc*(r2-r1))+.5);g=Math.floor(g1+(pc*(g2-g1))+.5);b=Math.floor(b1+(pc*(b2-b1))+.5);for(var wp=0;wp<inputsWithErrors.length;wp++){inputsWithErrors[wp].style.backgroundColor="#"+dec2hex(r)+dec2hex(g)+dec2hex(b);}}
-function validate_form(formname,startsWith){requiredTxt=SUGAR.language.get('app_strings','ERR_MISSING_REQUIRED_FIELDS');invalidTxt=SUGAR.language.get('app_strings','ERR_INVALID_VALUE');if(typeof(formname)=='undefined')
-{return false;}
-if(typeof(validate[formname])=='undefined')
-{return true;}
-var form=document.forms[formname];var isError=false;var errorMsg="";var _date=new Date();if(_date.getTime()<(lastSubmitTime+2000)&&startsWith==oldStartsWith){return false;}
-lastSubmitTime=_date.getTime();oldStartsWith=startsWith;clear_all_errors();inputsWithErrors=new Array();for(var i=0;i<validate[formname].length;i++){if(validate[formname][i][nameIndex].indexOf(startsWith)==0){if(typeof form[validate[formname][i][nameIndex]]!='undefined'){var bail=false;if(validate[formname][i][requiredIndex]&&validate[formname][i][typeIndex]!='bool'){if(typeof form[validate[formname][i][nameIndex]]=='undefined'||trim(form[validate[formname][i][nameIndex]].value)==""){add_error_style(formname,validate[formname][i][nameIndex],requiredTxt+' '+validate[formname][i][msgIndex]);isError=true;}}
-if(!bail){switch(validate[formname][i][typeIndex]){case'email':if(!isValidEmail(trim(form[validate[formname][i][nameIndex]].value))){isError=true;add_error_style(formname,validate[formname][i][nameIndex],invalidTxt+" "+validate[formname][i][msgIndex]);}
-break;case'time':if(!isTime(trim(form[validate[formname][i][nameIndex]].value))){isError=true;add_error_style(formname,validate[formname][i][nameIndex],invalidTxt+" "+validate[formname][i][msgIndex]);}break;case'date':if(!isDate(trim(form[validate[formname][i][nameIndex]].value))){isError=true;add_error_style(formname,validate[formname][i][nameIndex],invalidTxt+" "+validate[formname][i][msgIndex]);}break;case'alpha':break;case'DBName':if(!isDBName(trim(form[validate[formname][i][nameIndex]].value))){isError=true;add_error_style(formname,validate[formname][i][nameIndex],invalidTxt+" "+validate[formname][i][msgIndex]);}
-break;case'alphanumeric':break;case'int':if(!isInteger(trim(form[validate[formname][i][nameIndex]].value))){isError=true;add_error_style(formname,validate[formname][i][nameIndex],invalidTxt+" "+validate[formname][i][msgIndex]);}
-break;case'currency':case'float':if(!isFloat(trim(form[validate[formname][i][nameIndex]].value))){isError=true;add_error_style(formname,validate[formname][i][nameIndex],invalidTxt+" "+validate[formname][i][msgIndex]);}
-break;case'teamset_mass':div_element_id=formname+'_'+form[validate[formname][i][nameIndex]].name+'_operation_div';input_elements=YAHOO.util.Selector.query('input',document.getElementById(div_element_id));primary_field_id='';validation_passed=false;replace_selected=false;for(t in input_elements){if(input_elements[t].type&&input_elements[t].type=='radio'&&input_elements[t].checked==true&&input_elements[t].value=='replace'){radio_elements=YAHOO.util.Selector.query('input[type=radio]',document.getElementById(formname+'_team_name_table'));for(x in radio_elements){if(radio_elements[x].name!='team_name_type'){primary_field_id='team_name_collection_'+radio_elements[x].value;if(radio_elements[x].checked){replace_selected=true;if(trim(document.forms[formname].elements[primary_field_id].value)!=''){validation_passed=true;break;}}else if(trim(document.forms[formname].elements[primary_field_id].value)!=''){replace_selected=true;}}}}}
-if(replace_selected&&!validation_passed){add_error_style(formname,primary_field_id,SUGAR.language.get('app_strings','ERR_NO_PRIMARY_TEAM_SPECIFIED'));isError=true;}
-break;case'teamset':table_element_id=formname+'_'+form[validate[formname][i][nameIndex]].name+'_table';if(document.getElementById(table_element_id)){input_elements=YAHOO.util.Selector.query('input[type=radio]',document.getElementById(table_element_id));has_primary=false;primary_field_id=form[validate[formname][i][nameIndex]].name+'_collection_0';for(t in input_elements){primary_field_id=form[validate[formname][i][nameIndex]].name+'_collection_'+input_elements[t].value;if(input_elements[t].type&&input_elements[t].type=='radio'&&input_elements[t].checked==true){if(document.forms[formname].elements[primary_field_id].value!=''){has_primary=true;}
-break;}}
-if(!has_primary){isError=true;field_id=form[validate[formname][i][nameIndex]].name+'_collection_'+input_elements[0].value;add_error_style(formname,field_id,SUGAR.language.get('app_strings','ERR_NO_PRIMARY_TEAM_SPECIFIED'));}}
-break;case'error':isError=true;add_error_style(formname,validate[formname][i][nameIndex],validate[formname][i][msgIndex]);break;}
-if(typeof validate[formname][i][jstypeIndex]!='undefined'){switch(validate[formname][i][jstypeIndex]){case'range':if(!inRange(trim(form[validate[formname][i][nameIndex]].value),validate[formname][i][minIndex],validate[formname][i][maxIndex])){isError=true;var lbl_validate_range=SUGAR.language.get('app_strings','LBL_VALIDATE_RANGE');add_error_style(formname,validate[formname][i][nameIndex],validate[formname][i][msgIndex]+" value "+form[validate[formname][i][nameIndex]].value+" "+lbl_validate_range+" ("+validate[formname][i][minIndex]+" - "+validate[formname][i][maxIndex]+") ");}
-break;case'isbefore':compareTo=form[validate[formname][i][compareToIndex]];if(typeof compareTo!='undefined'){if(trim(compareTo.value)!=''||(validate[formname][i][allowblank]!='true')){date2=trim(compareTo.value);date1=trim(form[validate[formname][i][nameIndex]].value);if(trim(date1).length!=0&&!isBefore(date1,date2)){isError=true;add_error_style(formname,validate[formname][i][nameIndex],validate[formname][i][msgIndex]+"("+date1+") "+SUGAR.language.get('app_strings','MSG_IS_NOT_BEFORE')+' '+date2);}}}
-break;case'less':value=parseInt(trim(form[validate[formname][i][nameIndex]].value));maximum=parseInt(validate[formname][i][maxIndex]);if(typeof maximum!='undefined'){if(value>maximum){isError=true;add_error_style(formname,validate[formname][i][nameIndex],validate[formname][i][msgIndex]+" "+SUGAR.language.get('app_strings','MSG_IS_MORE_THAN')+' '+validate[formname][i][altMsgIndex]);}}
-break;case'more':value=parseInt(trim(form[validate[formname][i][nameIndex]].value));minimum=parseInt(validate[formname][i][minIndex]);if(typeof minimum!='undefined'){if(value<minimum){isError=true;add_error_style(formname,validate[formname][i][nameIndex],validate[formname][i][msgIndex]+" "+SUGAR.language.get('app_strings','MSG_SHOULD_BE')+' '+minimum+' '+SUGAR.language.get('app_strings','MSG_OR_GREATER'));}}
-break;case'binarydep':compareTo=form[validate[formname][i][compareToIndex]];if(typeof compareTo!='undefined'){item1=trim(form[validate[formname][i][nameIndex]].value);item2=trim(compareTo.value);if(!bothExist(item1,item2)){isError=true;add_error_style(formname,validate[formname][i][nameIndex],validate[formname][i][msgIndex]);}}
-break;case'comparison':compareTo=form[validate[formname][i][compareToIndex]];if(typeof compareTo!='undefined'){item1=trim(form[validate[formname][i][nameIndex]].value);item2=trim(compareTo.value);if(!bothExist(item1,item2)||item1!=item2){isError=true;add_error_style(formname,validate[formname][i][nameIndex],validate[formname][i][msgIndex]);}}
-break;case'in_array':arr=eval(validate[formname][i][arrIndex]);operator=validate[formname][i][operatorIndex];item1=trim(form[validate[formname][i][nameIndex]].value);if(operator.charAt(0)=='u'){item1=item1.toUpperCase();operator=operator.substring(1);}else if(operator.charAt(0)=='l'){item1=item1.toLowerCase();operator=operator.substring(1);}
-for(j=0;j<arr.length;j++){val=arr[j];if((operator=="=="&&val==item1)||(operator=="!="&&val!=item1)){isError=true;add_error_style(formname,validate[formname][i][nameIndex],invalidTxt+" "+validate[formname][i][msgIndex]);}}
-break;case'verified':if(trim(form[validate[formname][i][nameIndex]].value)=='false'){isError=true;}
-break;}}}}}}
-if(formsWithFieldLogic){var invalidLogic=false;if(formsWithFieldLogic.min&&formsWithFieldLogic.max&&formsWithFieldLogic._default){var showErrorsOn={min:{value:'min',show:false,obj:formsWithFieldLogic.min.value},max:{value:'max',show:false,obj:formsWithFieldLogic.max.value},_default:{value:'default',show:false,obj:formsWithFieldLogic._default.value},len:{value:'len',show:false,obj:parseInt(formsWithFieldLogic.len.value)}};var min=(formsWithFieldLogic.min.value!='')?parseInt(formsWithFieldLogic.min.value):'undef';var max=(formsWithFieldLogic.max.value!='')?parseInt(formsWithFieldLogic.max.value):'undef';var _default=(formsWithFieldLogic._default.value!='')?parseInt(formsWithFieldLogic._default.value):'undef';for(var i in showErrorsOn){if(showErrorsOn[i].value!='len'&&showErrorsOn[i].obj.length>showErrorsOn.len.obj){invalidLogic=true;showErrorsOn[i].show=true;showErrorsOn.len.show=true;}}
-if(min!='undef'&&max!='undef'&&_default!='undef'){if(!inRange(_default,min,max)){invalidLogic=true;showErrorsOn.min.show=true;showErrorsOn.max.show=true;showErrorsOn._default.show=true;}}
-if(min!='undef'&&max!='undef'&&min>max){invalidLogic=true;showErrorsOn.min.show=true;showErrorsOn.max.show=true;}
-if(min!='undef'&&_default!='undef'&&_default<min){invalidLogic=true;showErrorsOn.min.show=true;showErrorsOn._default.show=true;}
-if(max!='undef'&&_default!='undef'&&_default>max){invalidLogic=true;showErrorsOn.max.show=true;showErrorsOn._default.show=true;}
-if(invalidLogic){isError=true;for(var error in showErrorsOn)
-if(showErrorsOn[error].show)
-add_error_style(formname,showErrorsOn[error].value,formsWithFieldLogic.msg);}
-else if(!isError)
-formsWithFieldLogic=null;}}
-if(formWithPrecision){if(!isValidPrecision(formWithPrecision.float.value,formWithPrecision.precision.value)){isError=true;add_error_style(formname,'default',SUGAR.language.get('app_strings','ERR_COMPATIBLE_PRECISION_VALUE'));}else if(!isError){isError=false;}}
-if(isError==true){var nw,ne,sw,se;if(self.pageYOffset)
-{nwX=self.pageXOffset;seX=self.innerWidth;nwY=self.pageYOffset;seY=self.innerHeight;}
-else if(document.documentElement&&document.documentElement.scrollTop)
-{nwX=document.documentElement.scrollLeft;seX=document.documentElement.clientWidth;nwY=document.documentElement.scrollTop;seY=document.documentElement.clientHeight;}
-else if(document.body)
-{nwX=document.body.scrollLeft;seX=document.body.clientWidth;nwY=document.body.scrollTop;seY=document.body.clientHeight;}
-var inView=true;for(var wp=0;wp<inputsWithErrors.length;wp++){var elementCoor=findElementPos(inputsWithErrors[wp]);if(!(elementCoor.x>=nwX&&elementCoor.y>=nwY&&elementCoor.x<=seX&&elementCoor.y<=seY)){inView=false;scrollToTop=elementCoor.y-75;scrollToLeft=elementCoor.x-75;}
-else{break;}}
-if(!inView)window.scrollTo(scrollToTop,scrollToLeft);return false;}
-return true;}
+function validate_form(formname, startsWith) {
+ requiredTxt = SUGAR.language.get('app_strings', 'ERR_MISSING_REQUIRED_FIELDS');
+ invalidTxt = SUGAR.language.get('app_strings', 'ERR_INVALID_VALUE');
+ if (typeof(formname) == 'undefined') {
+  return false;
+ }
+ if (typeof(validate[formname]) == 'undefined') {
+  return true;
+ }
+ var form = document.forms[formname];
+ var isError = false;
+ var errorMsg = "";
+ var _date = new Date();
+ if (_date.getTime() < (lastSubmitTime + 2000) && startsWith == oldStartsWith) {
+  return false;
+ }
+ lastSubmitTime = _date.getTime();
+ oldStartsWith = startsWith;
+ clear_all_errors();
+ inputsWithErrors = new Array();
+ for (var i = 0; i < validate[formname].length; i++) {
+  if (validate[formname][i][nameIndex].indexOf(startsWith) == 0) {
+   if (typeof form[validate[formname][i][nameIndex]] != 'undefined') {
+    var bail = false;
+    if (validate[formname][i][requiredIndex] && validate[formname][i][typeIndex] != 'bool') {
+     if (typeof form[validate[formname][i][nameIndex]] == 'undefined' || trim(form[validate[formname][i][nameIndex]].value) == "") {
+      add_error_style(formname, validate[formname][i][nameIndex], requiredTxt + ' ' + validate[formname][i][msgIndex]);
+      isError = true;
+     }
+    }
+    if (!bail) {
+     switch (validate[formname][i][typeIndex]) {
+     case 'email':
+      if (!isValidEmail(trim(form[validate[formname][i][nameIndex]].value))) {
+       isError = true;
+       add_error_style(formname, validate[formname][i][nameIndex], invalidTxt + " " + validate[formname][i][msgIndex]);
+      }
+      break;
+     case 'time':
+      if (!isTime(trim(form[validate[formname][i][nameIndex]].value))) {
+       isError = true;
+       add_error_style(formname, validate[formname][i][nameIndex], invalidTxt + " " + validate[formname][i][msgIndex]);
+      }
+      break;
+     case 'date':
+      if (!isDate(trim(form[validate[formname][i][nameIndex]].value))) {
+       isError = true;
+       add_error_style(formname, validate[formname][i][nameIndex], invalidTxt + " " + validate[formname][i][msgIndex]);
+      }
+      break;
+     case 'alpha':
+      break;
+     case 'DBName':
+      if (!isDBName(trim(form[validate[formname][i][nameIndex]].value))) {
+       isError = true;
+       add_error_style(formname, validate[formname][i][nameIndex], invalidTxt + " " + validate[formname][i][msgIndex]);
+      }
+      break;
+     case 'alphanumeric':
+      break;
+     case 'int':
+      if (!isInteger(trim(form[validate[formname][i][nameIndex]].value))) {
+       isError = true;
+       add_error_style(formname, validate[formname][i][nameIndex], invalidTxt + " " + validate[formname][i][msgIndex]);
+      }
+      break;
+     case 'currency':
+     case 'float':
+      if (!isFloat(trim(form[validate[formname][i][nameIndex]].value))) {
+       isError = true;
+       add_error_style(formname, validate[formname][i][nameIndex], invalidTxt + " " + validate[formname][i][msgIndex]);
+      }
+      break;
+     case 'teamset_mass':
+      div_element_id = formname + '_' + form[validate[formname][i][nameIndex]].name + '_operation_div';
+      input_elements = YAHOO.util.Selector.query('input', document.getElementById(div_element_id));
+      primary_field_id = '';
+      validation_passed = false;
+      replace_selected = false;
+      for (t in input_elements) {
+       if (input_elements[t].type && input_elements[t].type == 'radio' && input_elements[t].checked == true && input_elements[t].value == 'replace') {
+        radio_elements = YAHOO.util.Selector.query('input[type=radio]', document.getElementById(formname + '_team_name_table'));
+        for (x in radio_elements) {
+         if (radio_elements[x].name != 'team_name_type') {
+          primary_field_id = 'team_name_collection_' + radio_elements[x].value;
+          if (radio_elements[x].checked) {
+           replace_selected = true;
+           if (trim(document.forms[formname].elements[primary_field_id].value) != '') {
+            validation_passed = true;
+            break;
+           }
+          } else if (trim(document.forms[formname].elements[primary_field_id].value) != '') {
+           replace_selected = true;
+          }
+         }
+        }
+       }
+      }
+      if (replace_selected && !validation_passed) {
+       add_error_style(formname, primary_field_id, SUGAR.language.get('app_strings', 'ERR_NO_PRIMARY_TEAM_SPECIFIED'));
+       isError = true;
+      }
+      break;
+     case 'teamset':
+      table_element_id = formname + '_' + form[validate[formname][i][nameIndex]].name + '_table';
+      if (document.getElementById(table_element_id)) {
+       input_elements = YAHOO.util.Selector.query('input[type=radio]', document.getElementById(table_element_id));
+       has_primary = false;
+       primary_field_id = form[validate[formname][i][nameIndex]].name + '_collection_0';
+       for (t in input_elements) {
+        primary_field_id = form[validate[formname][i][nameIndex]].name + '_collection_' + input_elements[t].value;
+        if (input_elements[t].type && input_elements[t].type == 'radio' && input_elements[t].checked == true) {
+         if (document.forms[formname].elements[primary_field_id].value != '') {
+          has_primary = true;
+         }
+         break;
+        }
+       }
+       if (!has_primary) {
+        isError = true;
+        field_id = form[validate[formname][i][nameIndex]].name + '_collection_' + input_elements[0].value;
+        add_error_style(formname, field_id, SUGAR.language.get('app_strings', 'ERR_NO_PRIMARY_TEAM_SPECIFIED'));
+       }
+      }
+      break;
+     case 'error':
+      isError = true;
+      add_error_style(formname, validate[formname][i][nameIndex], validate[formname][i][msgIndex]);
+      break;
+     }
+     if (typeof validate[formname][i][jstypeIndex] != 'undefined') {
+      switch (validate[formname][i][jstypeIndex]) {
+      case 'range':
+       if (!inRange(trim(form[validate[formname][i][nameIndex]].value), validate[formname][i][minIndex], validate[formname][i][maxIndex])) {
+        isError = true;
+        var lbl_validate_range = SUGAR.language.get('app_strings', 'LBL_VALIDATE_RANGE');
+        add_error_style(formname, validate[formname][i][nameIndex], validate[formname][i][msgIndex] + " value " + form[validate[formname][i][nameIndex]].value + " " + lbl_validate_range + " (" + validate[formname][i][minIndex] + " - " + validate[formname][i][maxIndex] + ") ");
+       }
+       break;
+      case 'isbefore':
+       compareTo = form[validate[formname][i][compareToIndex]];
+       if (typeof compareTo != 'undefined') {
+        if (trim(compareTo.value) != '' || (validate[formname][i][allowblank] != 'true')) {
+         date2 = trim(compareTo.value);
+         date1 = trim(form[validate[formname][i][nameIndex]].value);
+         if (trim(date1).length != 0 && !isBefore(date1, date2)) {
+          isError = true;
+          add_error_style(formname, validate[formname][i][nameIndex], validate[formname][i][msgIndex] + "(" + date1 + ") " + SUGAR.language.get('app_strings', 'MSG_IS_NOT_BEFORE') + ' ' + date2);
+         }
+        }
+       }
+       break;
+      case 'less':
+       value = parseInt(trim(form[validate[formname][i][nameIndex]].value));
+       maximum = parseInt(validate[formname][i][maxIndex]);
+       if (typeof maximum != 'undefined') {
+        if (value > maximum) {
+         isError = true;
+         add_error_style(formname, validate[formname][i][nameIndex], validate[formname][i][msgIndex] + " " + SUGAR.language.get('app_strings', 'MSG_IS_MORE_THAN') + ' ' + validate[formname][i][altMsgIndex]);
+        }
+       }
+       break;
+      case 'more':
+       value = parseInt(trim(form[validate[formname][i][nameIndex]].value));
+       minimum = parseInt(validate[formname][i][minIndex]);
+       if (typeof minimum != 'undefined') {
+        if (value < minimum) {
+         isError = true;
+         add_error_style(formname, validate[formname][i][nameIndex], validate[formname][i][msgIndex] + " " + SUGAR.language.get('app_strings', 'MSG_SHOULD_BE') + ' ' + minimum + ' ' + SUGAR.language.get('app_strings', 'MSG_OR_GREATER'));
+        }
+       }
+       break;
+      case 'binarydep':
+       compareTo = form[validate[formname][i][compareToIndex]];
+       if (typeof compareTo != 'undefined') {
+        item1 = trim(form[validate[formname][i][nameIndex]].value);
+        item2 = trim(compareTo.value);
+        if (!bothExist(item1, item2)) {
+         isError = true;
+         add_error_style(formname, validate[formname][i][nameIndex], validate[formname][i][msgIndex]);
+        }
+       }
+       break;
+      case 'comparison':
+       compareTo = form[validate[formname][i][compareToIndex]];
+       if (typeof compareTo != 'undefined') {
+        item1 = trim(form[validate[formname][i][nameIndex]].value);
+        item2 = trim(compareTo.value);
+        if (!bothExist(item1, item2) || item1 != item2) {
+         isError = true;
+         add_error_style(formname, validate[formname][i][nameIndex], validate[formname][i][msgIndex]);
+        }
+       }
+       break;
+      case 'in_array':
+       arr = eval(validate[formname][i][arrIndex]);
+       operator = validate[formname][i][operatorIndex];
+       item1 = trim(form[validate[formname][i][nameIndex]].value);
+       if (operator.charAt(0) == 'u') {
+        item1 = item1.toUpperCase();
+        operator = operator.substring(1);
+       } else if (operator.charAt(0) == 'l') {
+        item1 = item1.toLowerCase();
+        operator = operator.substring(1);
+       }
+       for (j = 0; j < arr.length; j++) {
+        val = arr[j];
+        if ((operator == "==" && val == item1) || (operator == "!=" && val != item1)) {
+         isError = true;
+         add_error_style(formname, validate[formname][i][nameIndex], invalidTxt + " " + validate[formname][i][msgIndex]);
+        }
+       }
+       break;
+      case 'verified':
+       if (trim(form[validate[formname][i][nameIndex]].value) == 'false') {
+        isError = true;
+       }
+       break;
+       //HACK : MB support for customcode actions/validation (onblur/onsave)
+      case 'customFunction':
+       var functionName = validate[formname][i][customFunctionName];
+
+       var fn = functionName + '(\'' + formname + '\')';
+       var execstatus = true;
+       try {
+        execstatus = eval(fn);
+       } catch (err) {
+        alert(err);
+        execstatus = false;
+       }
+       if (execstatus == false) {
+        isError = true;
+        add_error_style(formname, validate[formname][i][nameIndex], validate[formname][i][msgIndex]);
+       }
+       break;
+       //HACK : MB support for customcode actions/validation (onblur/onsave)      
+      }
+     }
+    }
+   }
+  }
+ }
+ if (formsWithFieldLogic) {
+  var invalidLogic = false;
+  if (formsWithFieldLogic.min && formsWithFieldLogic.max && formsWithFieldLogic._default) {
+   var showErrorsOn = {
+    min: {
+     value: 'min',
+     show: false,
+     obj: formsWithFieldLogic.min.value
+    }, max: {
+     value: 'max',
+     show: false,
+     obj: formsWithFieldLogic.max.value
+    }, _default: {
+     value: 'default',
+     show: false,
+     obj: formsWithFieldLogic._default.value
+    }, len: {
+     value: 'len',
+     show: false,
+     obj: parseInt(formsWithFieldLogic.len.value)
+    }
+   };
+   var min = (formsWithFieldLogic.min.value != '') ? parseInt(formsWithFieldLogic.min.value) : 'undef';
+   var max = (formsWithFieldLogic.max.value != '') ? parseInt(formsWithFieldLogic.max.value) : 'undef';
+   var _default = (formsWithFieldLogic._default.value != '') ? parseInt(formsWithFieldLogic._default.value) : 'undef';
+   for (var i in showErrorsOn) {
+    if (showErrorsOn[i].value != 'len' && showErrorsOn[i].obj.length > showErrorsOn.len.obj) {
+     invalidLogic = true;
+     showErrorsOn[i].show = true;
+     showErrorsOn.len.show = true;
+    }
+   }
+   if (min != 'undef' && max != 'undef' && _default != 'undef') {
+    if (!inRange(_default, min, max)) {
+     invalidLogic = true;
+     showErrorsOn.min.show = true;
+     showErrorsOn.max.show = true;
+     showErrorsOn._default.show = true;
+    }
+   }
+   if (min != 'undef' && max != 'undef' && min > max) {
+    invalidLogic = true;
+    showErrorsOn.min.show = true;
+    showErrorsOn.max.show = true;
+   }
+   if (min != 'undef' && _default != 'undef' && _default < min) {
+    invalidLogic = true;
+    showErrorsOn.min.show = true;
+    showErrorsOn._default.show = true;
+   }
+   if (max != 'undef' && _default != 'undef' && _default > max) {
+    invalidLogic = true;
+    showErrorsOn.max.show = true;
+    showErrorsOn._default.show = true;
+   }
+   if (invalidLogic) {
+    isError = true;
+    for (var error in showErrorsOn)
+    if (showErrorsOn[error].show) add_error_style(formname, showErrorsOn[error].value, formsWithFieldLogic.msg);
+   }
+   else if (!isError) formsWithFieldLogic = null;
+  }
+ }
+ if (formWithPrecision) {
+  if (!isValidPrecision(formWithPrecision.float.value, formWithPrecision.precision.value)) {
+   isError = true;
+   add_error_style(formname, 'default', SUGAR.language.get('app_strings', 'ERR_COMPATIBLE_PRECISION_VALUE'));
+  } else if (!isError) {
+   isError = false;
+  }
+ }
+ if (isError == true) {
+  var nw, ne, sw, se;
+  if (self.pageYOffset) {
+   nwX = self.pageXOffset;
+   seX = self.innerWidth;
+   nwY = self.pageYOffset;
+   seY = self.innerHeight;
+  }
+  else if (document.documentElement && document.documentElement.scrollTop) {
+   nwX = document.documentElement.scrollLeft;
+   seX = document.documentElement.clientWidth;
+   nwY = document.documentElement.scrollTop;
+   seY = document.documentElement.clientHeight;
+  }
+  else if (document.body) {
+   nwX = document.body.scrollLeft;
+   seX = document.body.clientWidth;
+   nwY = document.body.scrollTop;
+   seY = document.body.clientHeight;
+  }
+  var inView = true;
+  for (var wp = 0; wp < inputsWithErrors.length; wp++) {
+   var elementCoor = findElementPos(inputsWithErrors[wp]);
+   if (!(elementCoor.x >= nwX && elementCoor.y >= nwY && elementCoor.x <= seX && elementCoor.y <= seY)) {
+    inView = false;
+    scrollToTop = elementCoor.y - 75;
+    scrollToLeft = elementCoor.x - 75;
+   }
+   else {
+    break;
+   }
+  }
+  if (!inView) window.scrollTo(scrollToTop, scrollToLeft);
+  return false;
+ }
+ return true;
+}
 var marked_row=new Array;function setPointer(theRow,theRowNum,theAction,theDefaultColor,thePointerColor,theMarkColor){var theCells=null;if((thePointerColor==''&&theMarkColor=='')||typeof(theRow.style)=='undefined'){return false;}
 if(typeof(document.getElementsByTagName)!='undefined'){theCells=theRow.getElementsByTagName('td');}
 else if(typeof(theRow.cells)!='undefined'){theCells=theRow.cells;}
Index: modules/DynamicFields/templates/Fields/Forms/coreTop.tpl
===================================================================
--- modules/DynamicFields/templates/Fields/Forms/coreTop.tpl (revision 1)
+++ modules/DynamicFields/templates/Fields/Forms/coreTop.tpl (working copy)
@@ -83,7 +83,37 @@
  <td class='mbLBL'>{$MOD.COLUMN_TITLE_HELP_TEXT}:</td><td>{if $hideLevel < 5 }<input type="text" name="help" value="{$vardef.help}">{else}<input type="hidden" name="help" value="{$vardef.help}">{$vardef.help}{/if}
  </td>
 </tr>
+{* HACK: MB support for customcode actions/validation (onblur/onsave) -- MB support for customcode actions/validation (onblur/onsave)*}
 <tr>
+ <td class='mbLBL'>{$MOD.COLUMN_TITLE_CUSTOMJS_NAME_TEXT}</td>
+ <td>{if $hideLevel < 5 && $MB == 1}
+  <input type="text" name="validation" value="{$vardef.validation.functionName}">
+  {else}
+  <input type="hidden" name="validation" value="{$vardef.validation.functionName}">{$vardef.validation.functionName}
+  {/if}
+ </td>
+</tr>
+<tr>
+ <td class='mbLBL'>{$MOD.COLUMN_TITLE_CUSTOMJS_TEXT}</td>
+ <td>{if $hideLevel < 5 && $MB == 1}
+  <textarea name="customjs">{$vardef.customjs}</textarea>
+  {else}
+  <input type="hidden" name="customjs" value="{$vardef.customjs}">{$vardef.customjs}
+  {/if}
+ </td>
+</tr>
+<tr>
+ <td class='mbLBL'>{$MOD.COLUMN_TITLE_CUSTOMJS_ERROR_TEXT}</td>
+ <td>{if $hideLevel < 5 && $MB == 1}
+  <input type="text" name="customerrormsg" value="{$vardef.validation.errorMessage}">
+  {else}
+  <input type="hidden" name="customerrormsg" value="{$vardef.validation.errorMessage}">{$vardef.validation.errorMessage}
+  {/if}
+ </td>
+</tr>
+{* HACK:  MB support for customcode actions/validation (onblur/onsave) *}
+
+<tr>
     <td class='mbLBL'>{$MOD.COLUMN_TITLE_COMMENT_TEXT}:</td><td>{if $hideLevel < 5 }<input type="text" name="comments" value="{$vardef.comments}">{else}<input type="hidden" name="comment" value="{$vardef.comment}">{$vardef.comment}{/if}
     </td>
 </tr>
Index: modules/EditCustomFields/language/en_us.lang.php
===================================================================
--- modules/EditCustomFields/language/en_us.lang.php (revision 1)
+++ modules/EditCustomFields/language/en_us.lang.php (working copy)
@@ -92,4 +92,10 @@
  'LBL_DEPENDENT_TRIGGER'=>'Trigger',
  'LBL_BTN_EDIT_VISIBILITY'=>'Edit Visibility',
 );
+
+// HACK: MB support for customcode actions/validation (onblur/onsave) -- MB support for customcode actions/validation (onblur/onsave)
+$mod_strings['COLUMN_TITLE_CUSTOMJS_NAME_TEXT']='JS Function Name:';
+$mod_strings['COLUMN_TITLE_CUSTOMJS_TEXT']='JS Function Code:';
+$mod_strings['COLUMN_TITLE_CUSTOMJS_ERROR_TEXT']='JS Error Message:';
+//HACK: MB support for customcode actions/validation (onblur/onsave)
 ?>
Index: modules/EditCustomFields/vardefs.php
===================================================================
--- modules/EditCustomFields/vardefs.php (revision 1)
+++ modules/EditCustomFields/vardefs.php (working copy)
@@ -66,4 +66,9 @@
   array('name' => 'idx_meta_cm_del', 'type' => 'index', 'fields' => array('custom_module', 'deleted')),
  ),
 );
+
+//HACK : MB support for customcode actions/validation (onblur/onsave)
+$dictionary['FieldsMetaData']['fields']['customjs']=array('name' =>'customjs','type' =>'text','default'=>'');
+$dictionary['FieldsMetaData']['fields']['validation']=array('name' =>'validation','type' =>'text','default'=>'');
+//HACK : MB support for customcode actions/validation (onblur/onsave)
 ?>
Index: modules/ModuleBuilder/controller.php
===================================================================
--- modules/ModuleBuilder/controller.php (revision 1)
+++ modules/ModuleBuilder/controller.php (working copy)
@@ -332,11 +332,21 @@
             $mb = new ModuleBuilder ( ) ;
             $module = & $mb->getPackageModule ( $_REQUEST [ 'view_package' ], $_REQUEST [ 'view_module' ] ) ;
             $field->save ( $module ) ;
+   //HACK : MB support for customcode actions/validation (onblur/onsave)
+   if(isset($_REQUEST['validation']) && isset($_REQUEST['customjs']) && mb_strlen(trim($_REQUEST['validation']))>0 && mb_strlen(trim($_REQUEST['customjs']))>0){
+    $module->mbvardefs->vardef['fields'][$_REQUEST['name']]['validation']=array('type' => 'customFunction','functionName'=>$_REQUEST['validation'],'errorMessage'=>'LBL_'.mb_strtoupper($_REQUEST['name']).'_JS_ERR_MSG');
+    $module->mbvardefs->vardef['fields'][$_REQUEST['name']]['customjs']=$_REQUEST['customjs'];
+   }
+   //HACK : MB support for customcode actions/validation (onblur/onsave) 
             $module->mbvardefs->save () ;
             // get the module again to refresh the labels we might have saved with the $field->save (e.g., for address fields)
             $module = & $mb->getPackageModule ( $_REQUEST [ 'view_package' ], $_REQUEST [ 'view_module' ] ) ;
             if (isset ( $_REQUEST [ 'label' ] ) && isset ( $_REQUEST [ 'labelValue' ] ))
                 $module->setLabel ( $GLOBALS [ 'current_language' ], $_REQUEST [ 'label' ], $_REQUEST [ 'labelValue' ] ) ;
+         //HACK : MB support for customcode actions/validation (onblur/onsave)
+   if(isset($_REQUEST['validation']) && isset($_REQUEST['customjs']) && mb_strlen(trim($_REQUEST['validation']))>0 && mb_strlen(trim($_REQUEST['customjs']))>0){
+    $module->setLabel($GLOBALS['current_language'],'LBL_'.mb_strtoupper($_REQUEST['name']).'_JS_ERR_MSG',$_REQUEST['customerrormsg']);   }            
+            //HACK : MB support for customcode actions/validation (onblur/onsave)   
             $module->save();
         }
         $this->view = 'modulefields' ;
Index: modules/ModuleBuilder/views/view.modulefield.php
===================================================================
--- modules/ModuleBuilder/views/view.modulefield.php (revision 1)
+++ modules/ModuleBuilder/views/view.modulefield.php (working copy)
@@ -186,6 +186,12 @@
             $fv->ss->assign('module', $module);
             $fv->ss->assign('package', $package);
             $fv->ss->assign('MB','1');
+            //HACK : MB support for customcode actions/validation (onblur/onsave)
+            if(isset($vardef['validation']['errorMessage']) && !empty($vardef['validation']['errorMessage']))
+    //HACK :Upgrade sugarbase to SugarCRM 5.5
+             $vardef['validation']['errorMessage'] = $module->getLabel($GLOBALS['current_language'],$vardef['validation']['errorMessage']);
+    //HACK :Upgrade sugarbase to SugarCRM 5.5
+   //HACK : MB support for customcode actions/validation (onblur/onsave)
 
             if(isset($vardef['vname']))
                 $fv->ss->assign('lbl_value', htmlentities($module->getLabel('en_us',$vardef['vname']), ENT_QUOTES, 'UTF-8'));


1 comment:

Unknown said...

Good morning. I tried to make changes to suitecrm but the spaces to write the custom js code in the studio do not appear. Can you help me? thank you