Search forms enhancement: when a search criteria is an external (foreign) key, use an autocomplete instead of of drop-down list, when the number of different values is too big, as in other forms.

SVN:trunk[1123]
This commit is contained in:
Denis Flaven
2011-03-09 16:39:58 +00:00
parent 692f7060ea
commit bca713a964
6 changed files with 68 additions and 14 deletions

View File

@@ -106,7 +106,11 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
{
// Assumption: $aData['datasource'] will not be null because the data source id is always set...
$sApplicationURL = $aData['datasource']->GetApplicationUrl($this, $aData['replica']);
$sLink = '';
if (!empty($sApplicationURL))
{
$sLink = "<a href=\"$sApplicationURL\" target=\"_blank\">".$aData['datasource']->GetName()."</a>";
}
if ($aData['replica']->Get('status_dest_creator') == 1)
{
$sTip .= "<p>The object was <b>created</b> by the external data source $sLink</p>";
@@ -1062,6 +1066,18 @@ EOF
$aAllowedValues = MetaModel::GetAllowedValues_flt($sClassName, $sFilterCode, $aExtraParams);
if ($aAllowedValues != null)
{
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sFilterCode);
if ($oAttDef->IsExternalKey())
{
$iFieldSize = $oAttDef->GetMaxSize();
$iMaxComboLength = $oAttDef->GetMaximumComboLength();
$oWidget = new UIExtKeyWidget($sFilterCode, $sClassName, $oAttDef->GetLabel(), $aAllowedValues, $sFilterValue, 'search_'.$sFilterCode, false, '', '', '');
$sHtml .= "<label>".MetaModel::GetFilterLabel($sClassName, $sFilterCode).":</label>&nbsp;";
$sHtml .= $oWidget->Display($oPage, $aExtraParams, true /* bSearchMode */);
}
else
{
//Enum field or external key, display a combo
$sValue = "<select name=\"$sFilterCode\">\n";
$sValue .= "<option value=\"\">".Dict::S('UI:SearchValue:Any')."</option>\n";
@@ -1079,6 +1095,7 @@ EOF
}
$sValue .= "</select>\n";
$sHtml .= "<label>".MetaModel::GetFilterLabel($sClassName, $sFilterCode).":</label>&nbsp;$sValue\n";
}
unset($aExtraParams[$sFilterCode]);
}
else

View File

@@ -92,12 +92,24 @@ class UIExtKeyWidget
* @param Hash $aArgs Extra context arguments
* @return string The HTML fragment to be inserted into the page
*/
public function Display(WebPage $oPage, $aArgs = array())
public function Display(WebPage $oPage, $aArgs = array(), $bSearchMode = false)
{
$bCreate = (!MetaModel::IsAbstract($this->sTargetClass)) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $this->oAttDef->AllowTargetCreation());
$oPage->add_linked_script('../js/extkeywidget.js');
$oPage->add_linked_script('../js/forms-json-utils.js');
$bCreate = (!$bSearchMode) && (!MetaModel::IsAbstract($this->sTargetClass)) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $this->oAttDef->AllowTargetCreation());
$sMessage = Dict::S('UI:Message:EmptyList:UseSearchForm');
$sAttrFieldPrefix = ($bSearchMode) ? '' : 'attr_';
$sHTMLValue = "<span style=\"white-space:nowrap\">"; // no wrap
if($bSearchMode)
{
$sWizHelper = 'null';
}
else
{
$sWizHelper = 'oWizardHelper'.$this->sFormPrefix;
}
if (count($this->aAllowedValues) < $this->oAttDef->GetMaximumComboLength())
{
// Few choices, use a normal 'select'
@@ -106,8 +118,15 @@ class UIExtKeyWidget
$sHelpText = $this->oAttDef->GetHelpOnEdition();
// In case there are no valid values, the select will be empty, thus blocking the user from validating the form
$sHTMLValue = "<select title=\"$sHelpText\" name=\"attr_{$this->sFieldPrefix}{$this->sAttCode}{$this->sNameSuffix}\" id=\"$this->iId\">\n";
$sHTMLValue .= "<option value=\"\">".Dict::S('UI:SelectOne')."</option>\n";
$sHTMLValue = "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$this->sFieldPrefix}{$this->sAttCode}{$this->sNameSuffix}\" id=\"$this->iId\">\n";
if ($bSearchMode)
{
$sHTMLValue .= "<option value=\"\">".Dict::S('UI:SearchValue:Any')."</option>\n";
}
else
{
$sHTMLValue .= "<option value=\"\">".Dict::S('UI:SelectOne')."</option>\n";
}
foreach($this->aAllowedValues as $key => $display_value)
{
if ((count($this->aAllowedValues) == 1) && ($this->bMandatory == 'true') )
@@ -122,9 +141,9 @@ class UIExtKeyWidget
$sHTMLValue .= "<option value=\"$key\"$sSelected>$display_value</option>\n";
}
$sHTMLValue .= "</select>\n";
$oPage->add_ready_script(
$oPage->add_ready_script(
<<<EOF
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sClass}', '{$this->sAttCode}', '{$this->sNameSuffix}', $sSelectMode, oWizardHelper{$this->sFormPrefix});
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sClass}', '{$this->sAttCode}', '{$this->sNameSuffix}', $sSelectMode, $sWizHelper);
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
EOF
@@ -152,12 +171,12 @@ EOF
$sHTMLValue .= "<a class=\"no-arrow\" href=\"javascript:oACWidget_{$this->iId}.Search();\"><img style=\"border:0;vertical-align:middle;\" src=\"../images/mini_search.gif\" /></a>&nbsp;";
// another hidden input to store & pass the object's Id
$sHTMLValue .= "<input type=\"hidden\" id=\"$this->iId\" name=\"attr_{$this->sFieldPrefix}{$this->sAttCode}{$this->sNameSuffix}\" value=\"$this->value\" />\n";
$sHTMLValue .= "<input type=\"hidden\" id=\"$this->iId\" name=\"{$sAttrFieldPrefix}{$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(
<<<EOF
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sClass}', '{$this->sAttCode}', '{$this->sNameSuffix}', $sSelectMode, oWizardHelper{$this->sFormPrefix});
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sClass}', '{$this->sAttCode}', '{$this->sNameSuffix}', $sSelectMode, $sWizHelper);
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
$('#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}'}});
$('#label_$this->iId').blur(function() { $(this).search(); } );

View File

@@ -125,7 +125,7 @@ class Config
'show_in_conf_sample' => true,
),
'max_combo_length' => array(
'type' => 'int',
'type' => 'integer',
'description' => 'The maximum number of elements in a drop-down list. If more then an autocomplete will be used',
'default' => 50,
'value' => 50,
@@ -133,7 +133,7 @@ class Config
'show_in_conf_sample' => false,
),
'min_autocomplete_chars' => array(
'type' => 'int',
'type' => 'integer',
'description' => 'The minimum number of characters to type in order to trigger the "autocomplete" behavior',
'default' => 3,
'value' => 3,

View File

@@ -160,7 +160,7 @@ p a:hover, td a:hover {
background: url(../images/mini-arrow-orange.gif) no-repeat left;
}
td a.no-arrow, td a.no-arrow:visited {
td a.no-arrow, td a.no-arrow:visited, .SearchDrawer a.no-arrow, .SearchDrawer a.no-arrow:visited {
text-decoration:none;
color:#000000;
padding-left:0px;

View File

@@ -97,8 +97,16 @@ function ExtKeyWidget(id, sClass, sAttCode, sSuffix, bSelectMode, oWizHelper)
}
);
me.oWizardHelper.UpdateWizard();
theMap['json'] = me.oWizardHelper.ToJSON();
if (me.oWizardHelper == null)
{
theMap['json'] = '';
}
else
{
// Not inside a "search form", updating a real object
me.oWizardHelper.UpdateWizard();
theMap['json'] = me.oWizardHelper.ToJSON();
}
theMap['sRemoteClass'] = theMap['class']; // swap 'class' (defined in the form) and 'remoteClass'
theMap['class'] = me.sClass;

View File

@@ -79,10 +79,20 @@ try
$iInputId = utils::ReadParam('iInputId', '');
$sSuffix = utils::ReadParam('sSuffix', '');
$sJson = utils::ReadParam('json', '');
if (!empty($sJson))
{
$oWizardHelper = WizardHelper::FromJSON($sJson);
$oObj = $oWizardHelper->GetTargetObject();
$currentValue = $oObj->Get($sAttCode);
}
else
{
// Search form: no current object
$oObj = null;
$currentValue = 'eviV bulgroZ';
}
$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, array('this' => $oObj));
$oWidget = new UIExtKeyWidget($sAttCode, $sClass, '', $aAllowedValues, $oObj->Get($sAttCode), $iInputId, false, $sSuffix, '');
$oWidget = new UIExtKeyWidget($sAttCode, $sClass, '', $aAllowedValues, $currentValue, $iInputId, false, $sSuffix, '');
$oWidget->SearchObjectsToSelect($oPage, $sTargetClass);
break;