diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 7423f2cb1..ee6c4ac04 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -1052,10 +1052,10 @@ EOF if (!$oAttDef->IsExternalField()) { - $sMandatory = 'false'; + $bMandatory = 'false'; if ( (!$oAttDef->IsNullAllowed()) || ($iFlags & OPT_ATT_MANDATORY)) { - $sMandatory = 'true'; + $bMandatory = 'true'; } $sValidationField = ""; $sHelpText = $oAttDef->GetHelpOnEdition(); @@ -1085,7 +1085,7 @@ EOF break; case 'HTML': - $oWidget = new UIHTMLEditorWidget($iId, $sAttCode, $sNameSuffix, $sHelpText, $sValidationField, $value, $sMandatory); + $oWidget = new UIHTMLEditorWidget($iId, $sAttCode, $sNameSuffix, $sHelpText, $sValidationField, $value, $bMandatory); $sHTMLValue = $oWidget->Display($oPage, $aArgs); break; @@ -1128,38 +1128,11 @@ EOF $aEventsList[] ='validate'; $aEventsList[] ='change'; - // #@# todo - add context information (depending on dimensions) $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs); $iFieldSize = $oAttDef->GetMaxSize(); $iMaxComboLength = $oAttDef->GetMaximumComboLength(); - if (count($aAllowedValues) >= $iMaxComboLength) - { - // too many choices, use an autocomplete - $oWidget = new UIAutoCompleteWidget($sAttCode, $sClass, $oAttDef->GetLabel(), $aAllowedValues, $value, $iId, $sNameSuffix, $sFieldPrefix, $sFormPrefix); - $sHTMLValue = $oWidget->Display($oPage, $aArgs); - - } - else - { - // Few choices, use a normal 'select' - // In case there are no valid values, the select will be empty, thus blocking the user from validating the form - $sHTMLValue = " {$sValidationField}\n"; - } + $oWidget = new UIExtKeyWidget($sAttCode, $sClass, $oAttDef->GetLabel(), $aAllowedValues, $value, $iId, $bMandatory, $sNameSuffix, $sFieldPrefix, $sFormPrefix); + $sHTMLValue = $oWidget->Display($oPage, $aArgs); break; case 'String': @@ -1175,7 +1148,7 @@ EOF $sHTMLValue .= "\n"; foreach($aAllowedValues as $key => $display_value) { - if ((count($aAllowedValues) == 1) && ($sMandatory == 'true') ) + if ((count($aAllowedValues) == 1) && ($bMandatory == 'true') ) { // When there is only once choice, select it by default $sSelected = ' selected'; @@ -1205,7 +1178,7 @@ EOF { $sNullValue = "'$sNullValue'"; // Add quotes to turn this into a JS string if it's not a number } - $oPage->add_ready_script("$('#$iId').bind('".implode(' ', $aEventsList)."', function(evt, sFormId) { return ValidateField('$iId', '$sPattern', $sMandatory, sFormId, $sNullValue) } );\n"); // Bind to a custom event: validate + $oPage->add_ready_script("$('#$iId').bind('".implode(' ', $aEventsList)."', function(evt, sFormId) { return ValidateField('$iId', '$sPattern', $bMandatory, sFormId, $sNullValue) } );\n"); // Bind to a custom event: validate } $aDependencies = MetaModel::GetDependentAttributes($sClass, $sAttCode); // List of attributes that depend on the current one if (count($aDependencies) > 0) diff --git a/application/ui.autocompletewidget.class.inc.php b/application/ui.autocompletewidget.class.inc.php index 1d53c373a..ad7bd6644 100644 --- a/application/ui.autocompletewidget.class.inc.php +++ b/application/ui.autocompletewidget.class.inc.php @@ -14,7 +14,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA /** - * Class UIAutoCompleteWidget + * Class UIExtKeyWidget * UI wdiget for displaying and editing external keys when * A simple drop-down list is not enough... * @@ -61,7 +61,7 @@ require_once(APPROOT.'/application/webpage.class.inc.php'); require_once(APPROOT.'/application/displayblock.class.inc.php'); -class UIAutoCompleteWidget +class UIExtKeyWidget { protected static $iWidgetIndex = 0; protected $sAttCode; @@ -69,7 +69,7 @@ class UIAutoCompleteWidget protected $iId; protected $sTitle; - public function __construct($sAttCode, $sClass, $sTitle, $aAllowedValues, $value, $iInputId, $sNameSuffix = '', $sFieldPrefix = '', $sFormPrefix = '') + public function __construct($sAttCode, $sClass, $sTitle, $aAllowedValues, $value, $iInputId, $bMandatory, $sNameSuffix = '', $sFieldPrefix = '', $sFormPrefix = '') { self::$iWidgetIndex++; $this->sAttCode = $sAttCode; @@ -83,6 +83,7 @@ class UIAutoCompleteWidget $this->sTargetClass = $this->oAttDef->GetTargetClass(); $this->sTitle = $sTitle; $this->sFormPrefix = $sFormPrefix; + $this->bMandatory = $bMandatory; } /** @@ -93,50 +94,74 @@ class UIAutoCompleteWidget */ public function Display(WebPage $oPage, $aArgs = array()) { - if ($this->oAttDef->IsNull($this->value)) // Null values are displayed as '' + $bCreate = (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $this->oAttDef->AllowTargetCreation()); + if (count($this->aAllowedValues) < $this->oAttDef->GetMaximumComboLength()) { - $sDisplayValue = ''; + // Few choices, use a normal 'select' + $sSelectMode = 'true'; + // In case there are no valid values, the select will be empty, thus blocking the user from validating the form + $sHTMLValue = "\n"; } else { - $sDisplayValue = $this->GetObjectName($this->value); - } - $bCreate = UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY); - $sMessage = Dict::S('UI:Message:EmptyList:UseSearchForm'); - $sFormPrefix = $this->sFormPrefix; - $oPage->add_ready_script( -<<iId} = new AutocompleteWidget('$this->iId', '$this->sClass', '$this->sAttCode', '$this->sNameSuffix', oWizardHelper$sFormPrefix); - oACWidget_{$this->iId}.emptyHtml = "

$sMessage

"; -EOF -); - $iMinChars = $this->oAttDef->GetMinAutoCompleteChars(); - $iFieldSize = $this->oAttDef->GetMaxSize(); + // Too many choices, use an autocomplete + $sSelectMode = 'false'; + + if ($this->oAttDef->IsNull($this->value)) // Null values are displayed as '' + { + $sDisplayValue = ''; + } + else + { + $sDisplayValue = $this->GetObjectName($this->value); + } + $sMessage = Dict::S('UI:Message:EmptyList:UseSearchForm'); + $sFormPrefix = $this->sFormPrefix; + $iMinChars = $this->oAttDef->GetMinAutoCompleteChars(); + $iFieldSize = $this->oAttDef->GetMaxSize(); + + // the input for the auto-complete + $sHTMLValue = "aAllowedValues)."\" type=\"text\" id=\"label_$this->iId\" size=\"30\" maxlength=\"$iFieldSize\" value=\"$sDisplayValue\"/> "; + $sHTMLValue .= "iId}.Search();\"> "; + + // another hidden input to store & pass the object's Id + $sHTMLValue .= "iId\" name=\"attr_{$this->sFieldPrefix}{$this->sAttCode}{$this->sNameSuffix}\" value=\"$this->value\" />\n"; + + // Scripts to start the autocomplete and bind some events to it + $oPage->add_ready_script("\$('#label_$this->iId').autocomplete('./ajax.render.php', { scroll:true, minChars:{$iMinChars}, formatItem:formatItem, autoFill:false, matchContains:true, keyHolder:'#{$this->iId}', extraParams:{operation:'autocomplete', sclass:'$this->sClass',attCode:'".$this->sAttCode."'}});"); + $oPage->add_ready_script("\$('#label_$this->iId').blur(function() { $(this).search(); } );"); + $oPage->add_ready_script("\$('#label_$this->iId').result( function(event, data, formatted) { OnAutoComplete('$this->iId', event, data, formatted); } );"); + $oPage->add_ready_script("\$('#ac_dlg_$this->iId').dialog({ width: $(window).width()*0.8, height: $(window).height()*0.8, autoOpen: false, modal: true, title: '$this->sTitle', resizeStop: oACWidget_{$this->iId}.UpdateSizes, close: oACWidget_{$this->iId}.OnClose });\n"); + $oPage->add_at_the_end($this->GetSearchDialog($oPage)); // To prevent adding forms inside the main form - // the input for the auto-complete - $sHTMLValue = "aAllowedValues)."\" type=\"text\" id=\"label_$this->iId\" size=\"30\" maxlength=\"$iFieldSize\" value=\"$sDisplayValue\"/> "; - $sHTMLValue .= "iId}.Search();\"> "; + } if ($bCreate) { $sHTMLValue .= "iId}.CreateObject();\"> "; + $oPage->add_at_the_end('
'); } $sHTMLValue .= "iId}\">"; - - // another hidden input to store & pass the object's Id - $sHTMLValue .= "iId\" name=\"attr_{$this->sFieldPrefix}{$this->sAttCode}{$this->sNameSuffix}\" value=\"$this->value\" />\n"; - - // Scripts to start the autocomplete and bind some events to it - $oPage->add_ready_script("\$('#label_$this->iId').autocomplete('./ajax.render.php', { scroll:true, minChars:{$iMinChars}, formatItem:formatItem, autoFill:false, matchContains:true, keyHolder:'#{$this->iId}', extraParams:{operation:'autocomplete', sclass:'$this->sClass',attCode:'".$this->sAttCode."'}});"); - $oPage->add_ready_script("\$('#label_$this->iId').blur(function() { $(this).search(); } );"); - $oPage->add_ready_script("\$('#label_$this->iId').result( function(event, data, formatted) { OnAutoComplete('$this->iId', event, data, formatted); } );"); - $oPage->add_ready_script("\$('#ac_dlg_$this->iId').dialog({ width: $(window).width()*0.8, height: $(window).height()*0.8, autoOpen: false, modal: true, title: '$this->sTitle', resizeStop: oACWidget_{$this->iId}.UpdateSizes, close: oACWidget_{$this->iId}.OnClose });\n"); - $oPage->add_ready_script("\$('#ac_create_$this->iId').dialog({ width: $(window).width()*0.8, height: $(window).height()*0.8, autoOpen: false, modal: true, title: '$this->sTitle'});\n"); - $oPage->add_at_the_end($this->GetSearchDialog($oPage)); // To prevent adding forms inside the main form - if ($bCreate) - { - $oPage->add_at_the_end($this->GetCreationDialog($oPage)); // To prevent adding forms inside the main form - } - + $oPage->add_ready_script( +<<iId} = new ExtKeyWidget('$this->iId', '$this->sClass', '$this->sAttCode', '$this->sNameSuffix', $sSelectMode, oWizardHelper{$this->sFormPrefix}); + oACWidget_{$this->iId}.emptyHtml = "

$sMessage

"; +EOF +); return $sHTMLValue; } @@ -163,23 +188,6 @@ EOF return $sHTML; } - - protected function GetCreationDialog(WebPage $oPage) - { - $sHTML = '
'; - - //$sHTML .= "
iId}\" OnSubmit=\"return oACWidget_{$this->iId}.DoCreate();\">\n"; - //cmdbAbstractObject::DisplayCreationForm($oPage, 'Person', null, array()); - //$sHTML .= "iId}\" value=\"".Dict::S('UI:Button:Cancel')."\" onClick=\"$('#ac_create_{$this->iId}').dialog('close');\">  "; - //$sHTML .= "iId}\" value=\"".Dict::S('UI:Button:New')."\" onClick=\"oACWidget_{$this->iId}.DoCreate();\">"; - //$sHTML .= "
\n"; - $sHTML .= '
'; - - //$oPage->add_ready_script("$('#dc_{$this->iId}').resize(oACWidget_{$this->iId}.UpdateSizes);"); - - return $sHTML; - } - /** * Search for objects to be selected * @param WebPage $oP The page used for the output (usually an AjaxWebPage) @@ -218,8 +226,11 @@ EOF */ public function GetObjectCreationForm(WebPage $oPage) { + $oPage->add('
'); $oPage->add("

".MetaModel::GetClassIcon($this->sTargetClass)." ".Dict::Format('UI:CreationTitle_Class', MetaModel::GetName($this->sTargetClass))."

\n"); cmdbAbstractObject::DisplayCreationForm($oPage, $this->sTargetClass, null, array(), array('formPrefix' => $this->iId, 'noRelations' => true)); + $oPage->add('
'); + $oPage->add_ready_script("\$('#ac_create_$this->iId').dialog({ width: $(window).width()*0.8, height: 'auto', autoOpen: false, modal: true, title: '$this->sTitle'});\n"); $oPage->add_ready_script("$('#dcr_{$this->iId} form').removeAttr('onsubmit');"); $oPage->add_ready_script("$('#dcr_{$this->iId} form').bind('submit.uilinksWizard', oACWidget_{$this->iId}.DoCreateObject);"); } diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index c4a9e6458..81febee9b 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -1747,6 +1747,12 @@ class AttributeExternalKey extends AttributeDBFieldVoid { return $this->GetOptional('min_autocomplete_chars', utils::GetConfig()->Get('min_autocomplete_chars')); } + + public function AllowTargetCreation() + { + return $this->GetOptional('allow_target_creation', utils::GetConfig()->Get('allow_target_creation')); + } + } /** diff --git a/core/config.class.inc.php b/core/config.class.inc.php index aa85e2edb..6ec467d7e 100644 --- a/core/config.class.inc.php +++ b/core/config.class.inc.php @@ -135,6 +135,14 @@ class Config 'source_of_value' => '', 'show_in_conf_sample' => false, ), + 'allow_target_creation' => array( + 'type' => 'bool', + 'description' => 'Displays the + button on external keys to create target objects', + 'default' => true, + 'value' => true, + 'source_of_value' => '', + 'show_in_conf_sample' => false, + ), 'database_read_only' => array( 'type' => 'bool', 'description' => 'Freeze the data for administration purposes - administrators can still do anything... in appearance!', diff --git a/js/autocompletewidget.js b/js/autocompletewidget.js index 93377dd00..048627fd7 100644 --- a/js/autocompletewidget.js +++ b/js/autocompletewidget.js @@ -13,7 +13,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -function AutocompleteWidget(id, sClass, sAttCode, sSuffix, oWizHelper) +function ExtKeyWidget(id, sClass, sAttCode, sSuffix, bSelectMode, oWizHelper) { this.id = id; this.sClass = sClass; @@ -23,6 +23,7 @@ function AutocompleteWidget(id, sClass, sAttCode, sSuffix, oWizHelper) this.emptyOnClose = true; // Workaround for the JQuery dialog being very slow when opening and closing if the content contains many INPUT tags this.oWizardHelper = oWizHelper; this.ajax_request = null; + this.bSelectMode = bSelectMode; // true if the edited field is a SELECT, false if it's an autocomplete var me = this; this.Init = function() @@ -194,16 +195,13 @@ function AutocompleteWidget(id, sClass, sAttCode, sSuffix, oWizHelper) // since responses may arrive in arbitrary order me.StopPendingRequest(); - // Run the query and get the result back directly in JSON + // Run the query and get the result back directly in HTML me.ajax_request = $.post( 'ajax.render.php', theMap, function(data) { - $('#dcr_'+me.id).html(data); - // Adjust the height of the dialog + $('#ajax_'+me.id).html(data); $('#ac_create_'+me.id).dialog('open'); - var h = $('#ac_create_'+me.id+' .wizContainer').outerHeight(); - $('#ac_create_'+me.id).dialog( "option", "height", h+55 ); // space for dialog title and padding... - $('#ac_create_'+me.id).dialog( "option", "close", function() { $('#label_'+me.id).removeClass('ac_loading'); $('#label_'+me.id).focus(); } ); + $('#ac_create_'+me.id).dialog( "option", "close", me.OnCloseCreateObject ); // Modify the action of the cancel button $('#ac_create_'+me.id+' button.cancel').unbind('click').click( me.CloseCreateObject ); me.ajax_request = null; @@ -215,7 +213,15 @@ function AutocompleteWidget(id, sClass, sAttCode, sSuffix, oWizHelper) this.CloseCreateObject = function() { $('#ac_create_'+me.id).dialog( "close" ); - $('#dcr_'+me.id).html(''); + } + + this.OnCloseCreateObject = function() + { + $('#label_'+me.id).removeClass('ac_loading'); + $('#label_'+me.id).focus(); + $('#ac_create_'+me.id).dialog("destroy"); + $('#ac_create_'+me.id).remove(); + $('#ajax_'+me.id).html(''); } this.DoCreateObject = function() @@ -256,11 +262,22 @@ function AutocompleteWidget(id, sClass, sAttCode, sSuffix, oWizHelper) me.ajax_request = $.post( 'ajax.render.php', theMap, function(data) { - $('#label_'+me.id).val(data.name); - $('#'+me.id).val(data.id); + if (me.bSelectMode) + { + // Add the newly created object to the drop-down list and select it + $('