From 1de8ae4c3303d16b4a0ee1d11db4f27e00cb9d29 Mon Sep 17 00:00:00 2001 From: Denis Flaven Date: Sun, 16 May 2010 16:47:16 +0000 Subject: [PATCH] - Added validation of the fields based on a regexp pattern - Fields that depend on another field (in the same form) get refreshed when one of the fields they depend on is changed - Updated the wizard to group all the mandatory fields on the first page, since having inter-dependent fields on one page is now supported SVN:trunk[412] --- application/cmdbabstract.class.inc.php | 52 ++++++--- application/uiwizard.class.inc.php | 61 ++++++----- application/wizardhelper.class.inc.php | 11 +- css/light-grey.css | 3 + images/validation_error.png | Bin 0 -> 1469 bytes images/validation_ok.png | Bin 0 -> 623 bytes js/forms-json-utils.js | 141 ++++++++++++++++--------- js/wizardhelper.js | 54 ++++------ pages/UI.php | 32 +++++- pages/ajax.render.php | 2 +- 10 files changed, 227 insertions(+), 129 deletions(-) create mode 100644 images/validation_error.png create mode 100644 images/validation_ok.png diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 91abac45a..a1bd816de 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -828,25 +828,29 @@ abstract class cmdbAbstractObject extends CMDBObject if (!$oAttDef->IsExternalField()) { $aCSSClasses = array(); + $bMandatory = 0; if ( (!$oAttDef->IsNullAllowed()) || ($iFlags & OPT_ATT_MANDATORY)) { $aCSSClasses[] = 'mandatory'; + $bMandatory = 1; } $sCSSClasses = self::GetCSSClasses($aCSSClasses); + $sValidationField = ""; switch($oAttDef->GetEditClass()) { case 'Date': + case 'DateTime': $aCSSClasses[] = 'date-pick'; $sCSSClasses = self::GetCSSClasses($aCSSClasses); - $sHTMLValue = ""; + $sHTMLValue = "$sValidationField"; break; case 'Password': - $sHTMLValue = ""; + $sHTMLValue = "$sValidationField"; break; case 'Text': - $sHTMLValue = ""; + $sHTMLValue = "$sValidationField"; break; case 'List': @@ -884,7 +888,7 @@ abstract class cmdbAbstractObject extends CMDBObject { // too many choices, use an autocomplete // The input for the auto complete - $sHTMLValue = ""; + $sHTMLValue = "$sValidationField"; // another hidden input to store & pass the object's Id $sHTMLValue .= "\n"; $oPage->add_ready_script("\$('#label_$iInputId').autocomplete('./ajax.render.php', { scroll:true, minChars:3, onItemSelect:selectItem, onFindValue:findValue, formatItem:formatItem, autoFill:true, keyHolder:'#$iInputId', extraParams:{operation:'autocomplete', sclass:'$sClass',attCode:'".$sAttCode."'}});"); @@ -906,15 +910,22 @@ abstract class cmdbAbstractObject extends CMDBObject $sSelected = ($value == $key) ? ' selected' : ''; $sHTMLValue .= "\n"; } - $sHTMLValue .= "\n"; + $sHTMLValue .= "$sValidationField\n"; } } else { - $sHTMLValue = ""; + $sHTMLValue = "$sValidationField"; } break; } + $sPattern = addslashes($oAttDef->GetValidationPattern()); //'^([0-9]+)$'; + $oPage->add_ready_script("$('#$iInputId').bind('validate blur', function(evt, sFormId) { return ValidateField('$iInputId', '$sPattern', $bMandatory, sFormId) } );"); // Bind to a custom event: validate + $aDependencies = MetaModel::GetDependentAttributes($sClass, $sAttCode); // List of attributes that depend on the current one + if (count($aDependencies) > 0) + { + $oPage->add_ready_script("$('#$iInputId').bind('change', function(evt, sFormId) { return UpdateDependentFields(['".implode("','", $aDependencies)."']) } );"); // Bind to a custom event: validate + } } return $sHTMLValue; } @@ -923,12 +934,14 @@ abstract class cmdbAbstractObject extends CMDBObject { static $iFormId = 0; $iFormId++; + $sClass = get_class($this); $oAppContext = new ApplicationContext(); - $sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this)); + $sStateAttCode = MetaModel::GetStateAttributeCode($sClass); $iKey = $this->GetKey(); $aDetails = array(); - $oPage->add("
\n"); - foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef) + $aFieldsMap = array(); + $oPage->add("\n"); + foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef) { if ($oAttDef->IsWritable()) { @@ -957,7 +970,10 @@ abstract class cmdbAbstractObject extends CMDBObject $sValue = $this->Get($sAttCode); $sDisplayValue = $this->GetEditValue($sAttCode); $aArgs = array('this' => $this); - $sHTMLValue = self::GetFormElementForField($oPage, get_class($this), $sAttCode, $oAttDef, $sValue, $sDisplayValue, '', '', $iFlags, $aArgs); + $sInputId = $iFormId.'_'.$sAttCode; + $sHTMLValue = "".self::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $sValue, $sDisplayValue, $sInputId, '', $iFlags, $aArgs); + $aFieldsMap[$sAttCode] = $sInputId; + } $aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sHTMLValue); } @@ -966,7 +982,7 @@ abstract class cmdbAbstractObject extends CMDBObject } $oPage->details($aDetails); $oPage->add("\n"); - $oPage->add("\n"); + $oPage->add("\n"); $oPage->add("\n"); $oPage->add("\n"); foreach($aExtraParams as $sName => $value) @@ -977,6 +993,18 @@ abstract class cmdbAbstractObject extends CMDBObject $oPage->add("    \n"); $oPage->add("\n"); $oPage->add("\n"); + + $iFieldsCount = count($aFieldsMap); + $sJsonFieldsMap = json_encode($aFieldsMap); + + $oPage->add_script( +<<add("
\n"); + $oPage->add("\n"); $aStates = MetaModel::EnumStates($sClass); if ($oObjectToClone == null) { diff --git a/application/uiwizard.class.inc.php b/application/uiwizard.class.inc.php index 7285373b4..f1bf81256 100644 --- a/application/uiwizard.class.inc.php +++ b/application/uiwizard.class.inc.php @@ -61,8 +61,8 @@ class UIWizard $sFieldFlag = (($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE)) || (!$oAttDef->IsNullAllowed()) )? ' *' : ''; $oDefaultValuesSet = $oAttDef->GetDefaultValue(/* $oObject->ToArgs() */); // @@@ TO DO: get the object's current value if the object exists $sHTMLValue = cmdbAbstractObject::GetFormElementForField($this->m_oPage, $this->m_sClass, $sAttCode, $oAttDef, $oDefaultValuesSet, '', "att_$iMaxInputId", '', $iOptions, $aArgs); - $aFieldsMap[$iMaxInputId] = $sAttCode; - $aDetails[] = array('label' => $oAttDef->GetLabel().$sFieldFlag, 'value' => "
$sHTMLValue
"); + $aFieldsMap["att_$iMaxInputId"] = $sAttCode; + $aDetails[] = array('label' => $oAttDef->GetLabel().$sFieldFlag, 'value' => "$sHTMLValue"); if ($oAttDef->GetValuesDef() != null) { $sJSHandlerCode .= "\toWizardHelper.RequestAllowedValues('$sAttCode');\n"; @@ -128,6 +128,7 @@ $sJSHandlerCode $this->m_oPage->add("
\n"); $this->m_oPage->add("
\n"); $this->m_oPage->add($oAppContext->GetForForm()); + $this->m_oPage->add(""); $this->m_oPage->add("m_sClass)."\" />\n"); $this->m_oPage->add("\n"); $this->m_oPage->add("
\n"); @@ -201,35 +202,45 @@ $sJSHandlerCode } // Now use the dependencies between the fields to order them - while(count($aFields) > 0) + // Start from the order of the 'details' + $aList = MetaModel::GetZListItems($this->m_sClass, 'details'); + $index = 0; + $aOrder = array(); + foreach($aFields as $sAttCode => $void) { - $aCurrentStep = array(); - foreach($aFields as $sAttCode => $aDependencies) + $aOrder[$sAttCode] = 999; // At the end of the list... + } + foreach($aList as $sAttCode) + { + if (array_key_exists($sAttCode, $aFields)) { - // All fields with no remaining dependencies can be entered at this - // step of the wizard - if (count($aDependencies) == 0) + $aOrder[$sAttCode] = $index; + } + $index++; + } + foreach($aFields as $sAttCode => $aDependencies) + { + // All fields with no remaining dependencies can be entered at this + // step of the wizard + if (count($aDependencies) > 0) + { + $iMaxPos = 0; + // Remove this field from the dependencies of the other fields + foreach($aDependencies as $sDependentAttCode => $void) { - $aCurrentStep[] = $sAttCode; - $aFieldsDone[$sAttCode] = ''; - unset($aFields[$sAttCode]); - // Remove this field from the dependencies of the other fields - foreach($aFields as $sUpdatedCode => $aDummy) - { - // remove the dependency - unset($aFields[$sUpdatedCode][$sAttCode]); - } + // position the current field after the ones it depends on + $iMaxPos = max($iMaxPos, 1+$aOrder[$sDependentAttCode]); } } - if (count($aCurrentStep) == 0) - { - // This step of the wizard would contain NO field ! - echo "Error: Circular reference in the dependencies between the fields."; - print_r($aFields); - break; - } - $aWizardSteps['mandatory'][] = $aCurrentStep; } + asort($aOrder); + $aCurrentStep = array(); + foreach($aOrder as $sAttCode => $rank) + { + $aCurrentStep[] = $sAttCode; + $aFieldsDone[$sAttCode] = ''; + } + $aWizardSteps['mandatory'][] = $aCurrentStep; // Now computes the steps to fill the optional fields diff --git a/application/wizardhelper.class.inc.php b/application/wizardhelper.class.inc.php index 656b74589..b6eb2927b 100644 --- a/application/wizardhelper.class.inc.php +++ b/application/wizardhelper.class.inc.php @@ -16,9 +16,8 @@ class WizardHelper public function GetTargetObject($bReadUploadedFiles = false) { $oObj = MetaModel::NewObject($this->m_aData['m_sClass']); - foreach($this->m_aData['m_aCurrentValues'] as $iIndex => $value) + foreach($this->m_aData['m_oCurrentValues'] as $sAttCode => $value) { - $sAttCode = array_search($iIndex, $this->m_aData['m_oFieldsMap']); // Because this is stored in a Javascript array, unused indexes // are filled with null values if ( ($sAttCode !== false) && ($value !== null)) @@ -104,7 +103,6 @@ class WizardHelper // Protect against a request for a non existing field if (isset($this->m_aData['m_oFieldsMap'][$sAttCode])) { - $iIndex = $this->m_aData['m_oFieldsMap'][$sAttCode]; $oAttDef = MetaModel::GetAttributeDef($this->m_aData['m_sClass'], $sAttCode); if ($oAttDef->GetEditClass() == 'List') { @@ -124,13 +122,13 @@ class WizardHelper } $aData[] = $aRow; } - $this->m_aData['m_aDefaultValue'][$iIndex] = json_encode($aData); + $this->m_aData['m_oDefaultValue'][$sAttCode] = json_encode($aData); } else { // Normal handling for all other scalar attributes - $this->m_aData['m_aDefaultValue'][$iIndex] = $value; + $this->m_aData['m_oDefaultValue'][$sAttCode] = $value; } } } @@ -145,8 +143,7 @@ class WizardHelper // Protect against a request for a non existing field if (isset($this->m_aData['m_oFieldsMap'][$sAttCode])) { - $iIndex = $this->m_aData['m_oFieldsMap'][$sAttCode]; - $this->m_aData['m_aAllowedValues'][$iIndex] = $sHtml; + $this->m_aData['m_oAllowedValues'][$sAttCode] = $sHtml; } } diff --git a/css/light-grey.css b/css/light-grey.css index e48fa60fc..c1b8e1b9a 100644 --- a/css/light-grey.css +++ b/css/light-grey.css @@ -478,6 +478,9 @@ div.wizStep span { padding: 5px; } +.wizContainer table tr td { + background: transparent; +} .alignRight { text-align: right; padding: 3px; diff --git a/images/validation_error.png b/images/validation_error.png new file mode 100644 index 0000000000000000000000000000000000000000..3dd3b55dbe0ebec6e35cec8eaeba62038acfeb10 GIT binary patch literal 1469 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ za0`Jj+tIX_n~5oC^DMQ#CujeSKy zVsdtBi9%9pdS;%jl7fPQl0s&Rtx~wDuYqrYb81GWM^#a3aFt(3a#eP+Wr~u$9hXgo z6;N|-YDuC(MQ%=Bu~mhw64*>DAR8pCucQE0Qj%?}1aWkPZ-9bxeo?A|iJqZuvVpOQ zf{B@)k-3qjxtWeaaAJvqS7M%mk-37AfdP;(vNANZGBE@?1`L$!xPY`xQA(Oskc%7C zP9V=#DWjyMz)D}gyu4hm+*mKaC|%#s($Z4jz)0W7NEfI=x41H|B(Xv_uUHvk2+SOp z)Z*l#%mQ$5fy_-z$}cUkRZ;?31P4&hB^JOf$}5Hj9xxd7D-sLz4fPE4;U)t$+5iQu zz!8yO6q28xV}~WqY(P3u6d`Oy=udS?EJ?KkhKGf&fswAEd5D3Lm9d$XiD?v)euyG8 z?Y{XbnQ4_s+KqLMOhODTtqcsTOpKt~krY9-+vtM=0x4j?p$_sBnz#ai082@RhgU&q zQ4Tm-Qj+ykb5e6t^Gb?=VP=RLW+};5Y57IDi6wTKxryni`UQFEHu?xbyzYaz8kj7A z$xbP0l+XkK D*?Od} literal 0 HcmV?d00001 diff --git a/images/validation_ok.png b/images/validation_ok.png new file mode 100644 index 0000000000000000000000000000000000000000..a674561c15e90081b90197db179f20beab470875 GIT binary patch literal 623 zcmV-#0+9WQP)%FK}+}fcW$p+nfK2to%YT-oi(#rwO+8G<_39y@Ed#$ zgSE2t)!CZUdlvi)EC!dDS(!Enxq&Ky8*DKsxwZo(CC4{sq!)JChxXFWmo-*%Ra17R z!t%^gWiF6nGAeZRzkSG~smJd_Nt(ngonX6cuDzafUaG$?_8Pr zMMFi6-XHshoJ^(Hd5>ZDm@5>afm?i4M=L4KH!L>hZOufNnu;hYyCwpj`^8PV6DJQH z?y0LN*GCdz{8EU%sV+um?W3zfj?lp}fSPKS(l iCurrentStep) { // Check the values when moving forward - if (CheckMandatoryFields('wizStep'+iCurrentStep)) + if (CheckFields('wizStep'+iCurrentStep)) { oCurrentStep.style.display = 'none'; ActivateStep(iNextStep); @@ -85,70 +85,115 @@ function ActivateStep(iTargetStep) } oNextStep.style.display = ''; G_iCurrentStep = iTargetStep; - $('#wizStep'+(iTargetStep)).block({ message: null }); + //$('#wizStep'+(iTargetStep)).block({ message: null }); } -function AjaxGetValuesDef(oObj, sClass, sAttCode, iFieldId) -{ - var oJSON = document.getElementById(sJsonFieldId); - $.get('ajax.render.php?class=' + sClass + '&json_obj=' + oJSON.value + '&att_code=' + sAttCode, - { operation: "allowed_values" }, - function(data){ - //$('#field_'+iFieldId).html(data); - } - ); -} +//function AjaxGetValuesDef(oObj, sClass, sAttCode, iFieldId) +//{ +// var oJSON = document.getElementById(sJsonFieldId); +// $.get('ajax.render.php?class=' + sClass + '&json_obj=' + oJSON.value + '&att_code=' + sAttCode, +// { operation: "allowed_values" }, +// function(data){ +// //$('#field_'+iFieldId).html(data); +// } +// ); +//} +// +//function AjaxGetDefaultValue(oObj, sClass, sAttCode, iFieldId) +//{ +// // Asynchronously call the server to provide a default value if the field is +// // empty +// if (oObj['m_aCurrValues'][sAttCode] == '') +// { +// var oJSON = document.getElementById(sJsonFieldId); +// $.get('ajax.render.php?class=' + sClass + '&json_obj=' + oJSON.value + '&att_code=' + sAttCode, +// { operation: "default_value" }, +// function(json_data){ +// var oObj = ReloadObjectFromServer(json_data); +// UpdateFieldFromObject(iFieldId, aFieldsMap, oObj) +// } +// ); +// } +//} -function AjaxGetDefaultValue(oObj, sClass, sAttCode, iFieldId) -{ - // Asynchronously call the server to provide a default value if the field is - // empty - if (oObj['m_aCurrValues'][sAttCode] == '') - { - var oJSON = document.getElementById(sJsonFieldId); - $.get('ajax.render.php?class=' + sClass + '&json_obj=' + oJSON.value + '&att_code=' + sAttCode, - { operation: "default_value" }, - function(json_data){ - var oObj = ReloadObjectFromServer(json_data); - UpdateFieldFromObject(iFieldId, aFieldsMap, oObj) - } - ); - } -} +// Store the result of the form validation... there may be several forms per page, beware +var oFormErrors = { err_form0: 0 }; -function CheckMandatoryFields(sFormId) +function CheckFields(sFormId) { $('#'+sFormId+' :submit').attr('disable', 'disabled'); $('#'+sFormId+' :button[type=submit]').attr('disable', 'disabled'); firstErrorId = ''; - var iErrorsCount = 0; - $('#'+sFormId+' :input.mandatory').each( function() { - if (( this.value == '') || (this.value == 0)) - { - this.style.backgroundColor = '#fcc'; - iErrorsCount++; - if (iErrorsCount == 1) - { - firstErrorId = this.id; - } - } - else - { - this.style.backgroundColor = '#fff'; - } + // The two 'fields' below will be updated when the 'validate' event is processed + oFormErrors['err_'+sFormId] = 0; // Number of errors encountered when validating the form + oFormErrors['input_'+sFormId] = null; // First 'input' with an error, to set the focus to it + $('#'+sFormId+' :input').each( function() + { + validateEventResult = $(this).trigger('validate', sFormId); } ); - if(iErrorsCount > 0) + if(oFormErrors['err_'+sFormId] > 0) { alert('Please fill-in all mandatory fields before continuing.'); $('#'+sFormId+' :submit').attr('disable', ''); $('#'+sFormId+' :button[type=submit]').attr('disable', ''); - if (firstErrorId != '') + if (oFormErrors['input_'+sFormId] != null) { - $('#'+firstErrorId).focus(); + $('#'+oFormErrors['input_'+sFormId]).focus(); } } - return(iErrorsCount == 0); + return (oFormErrors['err_'+sFormId] == 0); // If no error, submit the form +} + +function ValidateField(sFieldId, sPattern, bMandatory, sFormId) +{ + var bValid = true; + var currentVal = $('#'+sFieldId).val(); + if (bMandatory && ((currentVal == '') || (currentVal == 0))) + { + bValid = false; + } + else if (sPattern != '') + { + re = new RegExp(sPattern); + //console.log('Validating field: '+sFieldId + ' current value: '+currentVal + ' pattern: '+sPattern ); + bValid = re.test(currentVal); + } + if (bValid) + { + // Visual feedback + $('#v_'+sFieldId).html(''); + } + else + { + // Report the error... + oFormErrors['err_'+sFormId]++; + if (oFormErrors['input_'+sFormId] == null) + { + // Let's remember the first input with an error, so that we can put back the focus on it later + oFormErrors['input_'+sFormId] = sFieldId; + } + // Visual feedback + $('#v_'+sFieldId).html(''); + } + //console.log('Form: '+sFormId+' Validating field: '+sFieldId + ' current value: '+currentVal+' pattern: '+sPattern+' result: '+bValid ); + return bValid; +} + +function UpdateDependentFields(aFieldNames) +{ + //console.log('UpdateDependentFields:'); + //console.log(aFieldNames); + index = 0; + oWizardHelper.ResetQuery(); + oWizardHelper.UpdateWizard(); + while(index < aFieldNames.length ) + { + sAttCode = aFieldNames[index]; + oWizardHelper.RequestAllowedValues(sAttCode); + index++; + } + oWizardHelper.AjaxQueryServer(); } diff --git a/js/wizardhelper.js b/js/wizardhelper.js index 9e8831ee9..94937816a 100644 --- a/js/wizardhelper.js +++ b/js/wizardhelper.js @@ -3,11 +3,11 @@ function WizardHelper(sClass) { this.m_oData = { 'm_sClass' : '', 'm_oFieldsMap': {}, - 'm_aCurrentValues': [], + 'm_oCurrentValues': {}, 'm_aDefaultValueRequested': [], 'm_aAllowedValuesRequested': [], - 'm_aDefaultValue': [], - 'm_aAllowedValues': [], + 'm_oDefaultValue': {}, + 'm_oAllowedValues': {}, 'm_iFieldsCount' : 0 }; this.m_oData.m_sClass = sClass; @@ -16,7 +16,6 @@ function WizardHelper(sClass) this.SetFieldsMap = function (oFieldsMap) { this.m_oData.m_oFieldsMap = oFieldsMap; - } this.SetFieldsCount = function (count) @@ -28,7 +27,6 @@ function WizardHelper(sClass) this.RequestDefaultValue = function (sFieldName) { currentValue = this.UpdateCurrentValue(sFieldName); - sFieldId = this.m_oData.m_oFieldsMap[sFieldName]; if (currentValue == null) { this.m_oData.m_aDefaultValueRequested.push(sFieldName); @@ -40,7 +38,7 @@ function WizardHelper(sClass) } this.SetCurrentValue = function (sFieldName, currentValue) { - this.m_oData.m_aCurrentValues[this.m_oData.m_oFieldsMap[sFieldName]] = currentValue; + this.m_oData.m_oCurrentValues[sFieldName] = currentValue; } this.ToJSON = function () @@ -57,44 +55,40 @@ function WizardHelper(sClass) this.ResetQuery = function () { this.m_oData.m_aDefaultValueRequested = []; - this.m_oData.m_aDefaultValue = []; + this.m_oData.m_oDefaultValue = {}; this.m_oData.m_aAllowedValuesRequested = []; - this.m_oData.m_aAllowedValues = []; + this.m_oData.m_oAllowedValues = {}; } this.UpdateFields = function () { //console.log('** UpdateFields **'); - //console.log(this.m_oData); - for(i=0; i< this.m_oData.m_aAllowedValuesRequested.length; i++) + // Set the full HTML for the input field + for(i=0; iGetName(); $sClassLabel = MetaModel::GetName(get_class($oObj)); $oObj->DBDeleteTracked($oMyChange); - $oP->add("

".Dict::Format('UI:Delete:_Name_Class_Deleted')."

\n"); + $oP->add("

".Dict::Format('UI:Delete:_Name_Class_Deleted', $sName, $sClassLabel)."

\n"); } } else @@ -995,6 +995,12 @@ try $aTransition = $aTransitions[$sStimulus]; $sTargetState = $aTransition['target_state']; $aTargetStates = MetaModel::EnumStates($sClass); + $oP->add_linked_script("../js/json.js"); + $oP->add_linked_script("../js/forms-json-utils.js"); + $oP->add_linked_script("../js/wizardhelper.js"); + $oP->add_linked_script("../js/wizard.utils.js"); + $oP->add_linked_script("../js/linkswidget.js"); + $oP->add_linked_script("../js/jquery.blockUI.js"); $oP->add("
\n"); $oP->add("

$sActionLabel - {$oObj->GetName()}

\n"); $oP->add("
\n"); @@ -1006,6 +1012,8 @@ try $oP->add("
\n"); $oP->add("
\n"); $aDetails = array(); + $iFieldIndex = 0; + $aFieldsMap = array(); foreach($aExpectedAttributes as $sAttCode => $iExpectCode) { // Prompt for an attribute if @@ -1017,8 +1025,10 @@ try $aAttributesDef = MetaModel::ListAttributeDefs($sClass); $oAttDef = $aAttributesDef[$sAttCode]; $aArgs = array('this' => $oObj); - $sHTMLValue = cmdbAbstractObject::GetFormElementForField($oP, $sClass, $sAttCode, $oAttDef, $oObj->Get($sAttCode), $oObj->GetEditValue($sAttCode), '', '', $iExpectCode, $aArgs); - $aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sHTMLValue); + $sHTMLValue = cmdbAbstractObject::GetFormElementForField($oP, $sClass, $sAttCode, $oAttDef, $oObj->Get($sAttCode), $oObj->GetEditValue($sAttCode), 'att_'.$iFieldIndex, '', $iExpectCode, $aArgs); + $aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => "$sHTMLValue"); + $aFieldsMap[$sAttCode] = 'att_'.$iFieldIndex; + $iFieldIndex++; } } $oP->details($aDetails); @@ -1033,6 +1043,18 @@ try $oP->add("
\n"); $oP->add("
\n"); $oP->add("\n"); + + $iFieldsCount = count($aFieldsMap); + $sJsonFieldsMap = json_encode($aFieldsMap); + + $oP->add_script( +<<add("
\n"); $oP->add("

$sActionLabel - {$oObj->GetName()}

\n"); $oP->add("

$sActionDetails

\n"); - $oP->p(Dict::Format('UI:Apply_Stimulus_On_Object_In_State_ToTarget_State', $sACtionLabel, $oObj->GetName(), $oObj->GetStateLabel(), $sTargetState)); + $oP->p(Dict::Format('UI:Apply_Stimulus_On_Object_In_State_ToTarget_State', $sActionLabel, $oObj->GetName(), $oObj->GetStateLabel(), $sTargetState)); $oP->add("
\n"); $aTargetState = $aTargetStates[$sTargetState]; $aExpectedAttributes = $aTargetState['attribute_list']; @@ -1101,7 +1123,7 @@ try $oMyChange->Set("userinfo", $sUserString); $iChangeId = $oMyChange->DBInsert(); $oObj->DBUpdateTracked($oMyChange); - $oP->p(Dict::Format('UI:Class_Object_Updated'), get_class($oObj), $oObj->GetName()); + $oP->p(Dict::Format('UI:Class_Object_Updated', get_class($oObj), $oObj->GetName())); } $oObj->DisplayDetails($oP); } diff --git a/pages/ajax.render.php b/pages/ajax.render.php index 351a326a4..a3d1e8e2d 100644 --- a/pages/ajax.render.php +++ b/pages/ajax.render.php @@ -91,7 +91,7 @@ switch($operation) $value = $oObj->Get($sAttCode); $displayValue = $oObj->GetEditValue($sAttCode); $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); - $sHTMLValue = cmdbAbstractObject::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $value, $displayValue, 'att_'.$sId, '', 0, array('this' => $oObj)); + $sHTMLValue = cmdbAbstractObject::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $value, $displayValue, $sId, '', 0, array('this' => $oObj)); $oWizardHelper->SetAllowedValuesHtml($sAttCode, $sHTMLValue); }