mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-23 10:38:45 +02:00
- Implementing the creation of objects on the fly when editing an extrernal key... still to be fully tested.
SVN:trunk[955]
This commit is contained in:
@@ -33,6 +33,9 @@ class ajax_page extends WebPage
|
||||
* @var Hash
|
||||
*/
|
||||
protected $m_sReadyScript;
|
||||
protected $m_sCurrentTab;
|
||||
protected $m_sCurrentTabContainer;
|
||||
protected $m_aTabs;
|
||||
|
||||
/**
|
||||
* constructor for the web page
|
||||
@@ -44,8 +47,44 @@ class ajax_page extends WebPage
|
||||
$this->m_sReadyScript = "";
|
||||
$this->add_header("Content-type: text/html; charset=utf-8");
|
||||
$this->add_header("Cache-control: no-cache");
|
||||
$this->m_sCurrentTabContainer = '';
|
||||
$this->m_sCurrentTab = '';
|
||||
$this->m_aTabs = array();
|
||||
}
|
||||
|
||||
public function AddTabContainer($sTabContainer, $sPrefix = '')
|
||||
{
|
||||
$this->m_aTabs[$sTabContainer] = array('content' =>'', 'prefix' => $sPrefix);
|
||||
$this->add("\$Tabs:$sTabContainer\$");
|
||||
}
|
||||
|
||||
public function AddToTab($sTabContainer, $sTabLabel, $sHtml)
|
||||
{
|
||||
if (!isset($this->m_aTabs[$sTabContainer]['content'][$sTabLabel]))
|
||||
{
|
||||
// Set the content of the tab
|
||||
$this->m_aTabs[$sTabContainer]['content'][$sTabLabel] = $sHtml;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Append to the content of the tab
|
||||
$this->m_aTabs[$sTabContainer]['content'][$sTabLabel] .= $sHtml;
|
||||
}
|
||||
}
|
||||
|
||||
public function SetCurrentTabContainer($sTabContainer = '')
|
||||
{
|
||||
$sPreviousTabContainer = $this->m_sCurrentTabContainer;
|
||||
$this->m_sCurrentTabContainer = $sTabContainer;
|
||||
return $sPreviousTabContainer;
|
||||
}
|
||||
|
||||
public function SetCurrentTab($sTabLabel = '')
|
||||
{
|
||||
$sPreviousTab = $this->m_sCurrentTab;
|
||||
$this->m_sCurrentTab = $sTabLabel;
|
||||
return $sPreviousTab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Echoes the content of the whole page
|
||||
@@ -57,15 +96,88 @@ class ajax_page extends WebPage
|
||||
{
|
||||
header($s_header);
|
||||
}
|
||||
|
||||
if (count($this->m_aTabs) > 0)
|
||||
{
|
||||
$this->add_ready_script(
|
||||
<<<EOF
|
||||
// The "tab widgets" to handle.
|
||||
var tabs = $('div[id^=tabbedContent]');
|
||||
|
||||
// This selector will be reused when selecting actual tab widget A elements.
|
||||
var tab_a_selector = 'ul.ui-tabs-nav a';
|
||||
|
||||
// Enable tabs on all tab widgets. The `event` property must be overridden so
|
||||
// that the tabs aren't changed on click, and any custom event name can be
|
||||
// specified. Note that if you define a callback for the 'select' event, it
|
||||
// will be executed for the selected tab whenever the hash changes.
|
||||
tabs.tabs({ event: 'change' });
|
||||
|
||||
// Define our own click handler for the tabs, overriding the default.
|
||||
tabs.find( tab_a_selector ).click(function()
|
||||
{
|
||||
var state = {};
|
||||
|
||||
// Get the id of this tab widget.
|
||||
var id = $(this).closest( 'div[id^=tabbedContent]' ).attr( 'id' );
|
||||
|
||||
// Get the index of this tab.
|
||||
var idx = $(this).parent().prevAll().length;
|
||||
|
||||
// Set the state!
|
||||
state[ id ] = idx;
|
||||
$.bbq.pushState( state );
|
||||
});
|
||||
EOF
|
||||
);
|
||||
}
|
||||
// Render the tabs in the page (if any)
|
||||
foreach($this->m_aTabs as $sTabContainerName => $aTabContainer)
|
||||
{
|
||||
$sTabs = '';
|
||||
$m_aTabs = $aTabContainer['content'];
|
||||
$sPrefix = $aTabContainer['prefix'];
|
||||
$container_index = 0;
|
||||
if (count($m_aTabs) > 0)
|
||||
{
|
||||
$sTabs = "<!-- tabs -->\n<div id=\"tabbedContent_{$sPrefix}{$container_index}\" class=\"light\">\n";
|
||||
$sTabs .= "<ul>\n";
|
||||
// Display the unordered list that will be rendered as the tabs
|
||||
$i = 0;
|
||||
foreach($m_aTabs as $sTabName => $sTabContent)
|
||||
{
|
||||
$sTabs .= "<li><a href=\"#tab_{$sPrefix}$i\" class=\"tab\"><span>".htmlentities($sTabName, ENT_QUOTES, 'UTF-8')."</span></a></li>\n";
|
||||
$i++;
|
||||
}
|
||||
$sTabs .= "</ul>\n";
|
||||
// Now add the content of the tabs themselves
|
||||
$i = 0;
|
||||
foreach($m_aTabs as $sTabName => $sTabContent)
|
||||
{
|
||||
$sTabs .= "<div id=\"tab_{$sPrefix}$i\">".$sTabContent."</div>\n";
|
||||
$i++;
|
||||
}
|
||||
$sTabs .= "</div>\n<!-- end of tabs-->\n";
|
||||
}
|
||||
$this->s_content = str_replace("\$Tabs:$sTabContainerName\$", $sTabs, $this->s_content);
|
||||
$container_index++;
|
||||
}
|
||||
|
||||
$s_captured_output = ob_get_contents();
|
||||
ob_end_clean();
|
||||
echo $this->s_content;
|
||||
echo $this->s_deferred_content;
|
||||
if (count($this->a_scripts) > 0)
|
||||
{
|
||||
echo "<script type=\"text/javascript\">\n";
|
||||
echo implode("\n", $this->a_scripts);
|
||||
echo "\n</script>\n";
|
||||
}
|
||||
if (!empty($this->m_sReadyScript))
|
||||
{
|
||||
echo "<script>\n";
|
||||
echo "<script type=\"text/javascript\">\n";
|
||||
echo $this->m_sReadyScript; // Ready Scripts are output as simple scripts
|
||||
echo "</script>\n";
|
||||
echo "\n</script>\n";
|
||||
}
|
||||
if (trim($s_captured_output) != "")
|
||||
{
|
||||
@@ -82,6 +194,18 @@ class ajax_page extends WebPage
|
||||
public function small_p($sText)
|
||||
{
|
||||
}
|
||||
|
||||
public function add($sHtml)
|
||||
{
|
||||
if (!empty($this->m_sCurrentTabContainer) && !empty($this->m_sCurrentTab))
|
||||
{
|
||||
$this->AddToTab($this->m_sCurrentTabContainer, $this->m_sCurrentTab, $sHtml);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent::add($sHtml);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a script to be executed when the DOM is ready (typical JQuery use)
|
||||
|
||||
@@ -1032,10 +1032,9 @@ EOF
|
||||
{
|
||||
static $iInputId = 0;
|
||||
$sFieldPrefix = '';
|
||||
if (isset($aArgs['prefix']))
|
||||
{
|
||||
$sFieldPrefix = $aArgs['prefix'];
|
||||
}
|
||||
$sFormPrefix = isset($aArgs['formPrefix']) ? $aArgs['formPrefix'] : '';
|
||||
$sFieldPrefix = isset($aArgs['prefix']) ? $sFormPrefix.$aArgs['prefix'] : $sFormPrefix;
|
||||
|
||||
if (isset($aArgs[$sAttCode]) && empty($value))
|
||||
{
|
||||
// default value passed by the context (either the app context of the operation)
|
||||
@@ -1136,7 +1135,7 @@ EOF
|
||||
if (count($aAllowedValues) >= $iMaxComboLength)
|
||||
{
|
||||
// too many choices, use an autocomplete
|
||||
$oWidget = new UIAutoCompleteWidget($sAttCode, $sClass, $oAttDef->GetLabel(), $aAllowedValues, $value, $iId, $sNameSuffix, $sFieldPrefix);
|
||||
$oWidget = new UIAutoCompleteWidget($sAttCode, $sClass, $oAttDef->GetLabel(), $aAllowedValues, $value, $iId, $sNameSuffix, $sFieldPrefix, $sFormPrefix);
|
||||
$sHTMLValue = $oWidget->Display($oPage, $aArgs);
|
||||
|
||||
}
|
||||
@@ -1206,12 +1205,12 @@ 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) } );"); // Bind to a custom event: validate
|
||||
$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
|
||||
}
|
||||
$aDependencies = MetaModel::GetDependentAttributes($sClass, $sAttCode); // List of attributes that depend on the current one
|
||||
if (count($aDependencies) > 0)
|
||||
{
|
||||
$oPage->add_ready_script("$('#$iId').bind('change', function(evt, sFormId) { return UpdateDependentFields(['".implode("','", $aDependencies)."']) } );"); // Bind to a custom event: validate
|
||||
$oPage->add_ready_script("$('#$iId').bind('change', function(evt, sFormId) { return oWizardHelper{$sFormPrefix}.UpdateDependentFields(['".implode("','", $aDependencies)."']) } );\n"); // Bind to a custom event: validate
|
||||
}
|
||||
}
|
||||
return "<div>{$sHTMLValue}</div>";
|
||||
@@ -1219,9 +1218,14 @@ EOF
|
||||
|
||||
public function DisplayModifyForm(WebPage $oPage, $aExtraParams = array())
|
||||
{
|
||||
static $iGlobalFormId = 0;
|
||||
static $iGlobalFormId = 1;
|
||||
$iGlobalFormId++;
|
||||
$this->m_iFormId = $iGlobalFormId;
|
||||
$sPrefix = '';
|
||||
if (isset($aExtraParams['formPrefix']))
|
||||
{
|
||||
$sPrefix = $aExtraParams['formPrefix'];
|
||||
}
|
||||
$this->m_iFormId = $sPrefix.$iGlobalFormId;
|
||||
$sClass = get_class($this);
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
|
||||
@@ -1238,7 +1242,7 @@ EOF
|
||||
}
|
||||
$oPage->add("<form action=\"$sFormAction\" id=\"form_{$this->m_iFormId}\" enctype=\"multipart/form-data\" method=\"post\" onSubmit=\"return CheckFields('form_{$this->m_iFormId}', true)\">\n");
|
||||
|
||||
$oPage->AddTabContainer(OBJECT_PROPERTIES_TAB);
|
||||
$oPage->AddTabContainer(OBJECT_PROPERTIES_TAB, $sPrefix);
|
||||
$oPage->SetCurrentTabContainer(OBJECT_PROPERTIES_TAB);
|
||||
$oPage->SetCurrentTab(Dict::S('UI:PropertiesTab'));
|
||||
// $aDetailsList = $this->FLattenZList(MetaModel::GetZListItems($sClass, 'details'));
|
||||
@@ -1310,7 +1314,7 @@ EOF
|
||||
{
|
||||
$sValue = $this->Get($sAttCode);
|
||||
$sDisplayValue = $this->GetEditValue($sAttCode);
|
||||
$aArgs = array('this' => $this);
|
||||
$aArgs = array('this' => $this, 'formPrefix' => $sPrefix);
|
||||
$sInputId = $this->m_iFormId.'_'.$sAttCode;
|
||||
$sHTMLValue = "<span id=\"field_{$sInputId}\">".self::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $sValue, $sDisplayValue, $sInputId, '', $iFlags, $aArgs).'</span>';
|
||||
$aFieldsMap[$sAttCode] = $sInputId;
|
||||
@@ -1343,8 +1347,10 @@ EOF
|
||||
}
|
||||
|
||||
// Now display the relations, one tab per relation
|
||||
|
||||
$this->DisplayBareRelations($oPage, true); // Edit mode
|
||||
if (!isset($aExtraParams['noRelations']))
|
||||
{
|
||||
$this->DisplayBareRelations($oPage, true); // Edit mode
|
||||
}
|
||||
|
||||
$oPage->SetCurrentTab('');
|
||||
$oPage->add("<input type=\"hidden\" name=\"class\" value=\"$sClass\">\n");
|
||||
@@ -1359,16 +1365,20 @@ EOF
|
||||
// The object already exists in the database, it's modification
|
||||
$oPage->add("<input type=\"hidden\" name=\"id\" value=\"$iKey\">\n");
|
||||
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"apply_modify\">\n");
|
||||
$oPage->add("<button type=\"button\" class=\"action\" onClick=\"BackToDetails('$sClass', $iKey)\"><span>".Dict::S('UI:Button:Cancel')."</span></button> \n");
|
||||
// $oPage->add("<button type=\"button\" id=\"btn_cancel_{$sPrefix}\" class=\"action\" onClick=\"BackToDetails('$sClass', $iKey)\"><span>".Dict::S('UI:Button:Cancel')."</span></button> \n");
|
||||
$oPage->add("<button type=\"button\" class=\"action cancel\"><span>".Dict::S('UI:Button:Cancel')."</span></button> \n");
|
||||
$oPage->add("<button type=\"submit\" class=\"action\"><span>".Dict::S('UI:Button:Apply')."</span></button>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// The object does not exist in the database it's a creation
|
||||
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"apply_new\">\n");
|
||||
$oPage->add("<button type=\"button\" class=\"action\" onClick=\"BackToList('$sClass')\"><span>".Dict::S('UI:Button:Cancel')."</span></button> \n");
|
||||
// $oPage->add("<button type=\"button\" id=\"btn_cancel_{$sPrefix}\" class=\"action\" onClick=\"BackToDetails('$sClass', $iKey)\"><span>".Dict::S('UI:Button:Cancel')."</span></button> \n");
|
||||
$oPage->add("<button type=\"button\" class=\"action cancel\">".Dict::S('UI:Button:Cancel')."</button> \n");
|
||||
$oPage->add("<button type=\"submit\" class=\"action\"><span>".Dict::S('UI:Button:Create')."</span></button>\n");
|
||||
}
|
||||
// Hook the cancel button via jQuery so that it can be unhooked easily as well if needed
|
||||
$oPage->add_ready_script("$('#form_{$this->m_iFormId} button.cancel').click( function() { BackToDetails('$sClass', $iKey)} );");
|
||||
$oPage->add("</form>\n");
|
||||
|
||||
$iFieldsCount = count($aFieldsMap);
|
||||
@@ -1377,15 +1387,16 @@ EOF
|
||||
$oPage->add_script(
|
||||
<<<EOF
|
||||
// Create the object once at the beginning of the page...
|
||||
var oWizardHelper = new WizardHelper('$sClass');
|
||||
oWizardHelper.SetFieldsMap($sJsonFieldsMap);
|
||||
oWizardHelper.SetFieldsCount($iFieldsCount);
|
||||
var oWizardHelper$sPrefix = new WizardHelper('$sClass', '$sPrefix');
|
||||
oWizardHelper$sPrefix.SetFieldsMap($sJsonFieldsMap);
|
||||
oWizardHelper$sPrefix.SetFieldsCount($iFieldsCount);
|
||||
EOF
|
||||
);
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
// Starts the validation when the page is ready
|
||||
CheckFields('form_{$this->m_iFormId}', false);
|
||||
|
||||
EOF
|
||||
);
|
||||
}
|
||||
@@ -1399,9 +1410,12 @@ EOF
|
||||
|
||||
if ($oObjectToClone == null)
|
||||
{
|
||||
$sTargetState = MetaModel::GetDefaultState($sClass);
|
||||
$oObj = MetaModel::NewObject($sClass);
|
||||
$oObj->Set($sStateAttCode, $sTargetState);
|
||||
if (!empty($sStateAttCode))
|
||||
{
|
||||
$sTargetState = MetaModel::GetDefaultState($sClass);
|
||||
$oObj->Set($sStateAttCode, $sTargetState);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1439,7 +1453,7 @@ EOF
|
||||
}
|
||||
}
|
||||
}
|
||||
return $oObj->DisplayModifyForm( $oPage, $aExtraParams = array());
|
||||
return $oObj->DisplayModifyForm( $oPage, $aExtraParams);
|
||||
}
|
||||
|
||||
protected static function ProcessZlist($aList, $aDetails, $sCurrentTab, $sCurrentCol, $sCurrentSet)
|
||||
@@ -1663,5 +1677,100 @@ EOF
|
||||
return $sContextParam;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the object from the POSTed parameters
|
||||
*/
|
||||
function UpdateObject($sFormPrefix = '')
|
||||
{
|
||||
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
|
||||
{
|
||||
if ($oAttDef->IsLinkSet() && $oAttDef->IsIndirect())
|
||||
{
|
||||
$aLinks = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", '');
|
||||
$sLinkedClass = $oAttDef->GetLinkedClass();
|
||||
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
|
||||
$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
|
||||
$oLinkedSet = DBObjectSet::FromScratch($sLinkedClass);
|
||||
if (is_array($aLinks))
|
||||
{
|
||||
foreach($aLinks as $id => $aData)
|
||||
{
|
||||
if (is_numeric($id))
|
||||
{
|
||||
if ($id < 0)
|
||||
{
|
||||
// New link to be created, the opposite of the id (-$id) is the ID of the remote object
|
||||
$oLink = MetaModel::NewObject($sLinkedClass);
|
||||
$oLink->Set($sExtKeyToRemote, -$id);
|
||||
$oLink->Set($sExtKeyToMe, $this->GetKey());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Existing link, potentially to be updated...
|
||||
$oLink = MetaModel::GetObject($sLinkedClass, $id);
|
||||
}
|
||||
// Now populate the attributes
|
||||
foreach($aData as $sName => $value)
|
||||
{
|
||||
if (MetaModel::IsValidAttCode($sLinkedClass, $sName))
|
||||
{
|
||||
$oLinkAttDef = MetaModel::GetAttributeDef($sLinkedClass, $sName);
|
||||
if ($oLinkAttDef->IsWritable())
|
||||
{
|
||||
$oLink->Set($sName, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
$oLinkedSet->AddObject($oLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->Set($sAttCode, $oLinkedSet);
|
||||
}
|
||||
else if ($oAttDef->IsWritable())
|
||||
{
|
||||
$iFlags = $this->GetAttributeFlags($sAttCode);
|
||||
if ($iFlags & (OPT_ATT_HIDDEN | OPT_ATT_READONLY))
|
||||
{
|
||||
// Non-visible, or read-only attribute, do nothing
|
||||
}
|
||||
elseif ($oAttDef->GetEditClass() == 'Document')
|
||||
{
|
||||
// There should be an uploaded file with the named attr_<attCode>
|
||||
$oDocument = utils::ReadPostedDocument("file_{$sFormPrefix}{$sAttCode}");
|
||||
if (!$oDocument->IsEmpty())
|
||||
{
|
||||
// A new file has been uploaded
|
||||
$this->Set($sAttCode, $oDocument);
|
||||
}
|
||||
}
|
||||
elseif ($oAttDef->GetEditClass() == 'One Way Password')
|
||||
{
|
||||
// Check if the password was typed/changed
|
||||
$bChanged = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_changed", false);
|
||||
if ($bChanged)
|
||||
{
|
||||
// The password has been changed or set
|
||||
$rawValue = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null);
|
||||
$this->Set($sAttCode, $rawValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$rawValue = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null);
|
||||
if (!is_null($rawValue))
|
||||
{
|
||||
$aAttributes[$sAttCode] = trim($rawValue);
|
||||
$previousValue = $this->Get($sAttCode);
|
||||
if ($previousValue !== $aAttributes[$sAttCode])
|
||||
{
|
||||
$this->Set($sAttCode, $aAttributes[$sAttCode]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -69,7 +69,7 @@ class UIAutoCompleteWidget
|
||||
protected $iId;
|
||||
protected $sTitle;
|
||||
|
||||
public function __construct($sAttCode, $sClass, $sTitle, $aAllowedValues, $value, $iInputId, $sNameSuffix = '', $sFieldPrefix = '')
|
||||
public function __construct($sAttCode, $sClass, $sTitle, $aAllowedValues, $value, $iInputId, $sNameSuffix = '', $sFieldPrefix = '', $sFormPrefix = '')
|
||||
{
|
||||
self::$iWidgetIndex++;
|
||||
$this->sAttCode = $sAttCode;
|
||||
@@ -82,6 +82,7 @@ class UIAutoCompleteWidget
|
||||
$this->sFieldPrefix = $sFieldPrefix;
|
||||
$this->sTargetClass = $this->oAttDef->GetTargetClass();
|
||||
$this->sTitle = $sTitle;
|
||||
$this->sFormPrefix = $sFormPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,17 +101,25 @@ class UIAutoCompleteWidget
|
||||
{
|
||||
$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(
|
||||
<<<EOF
|
||||
oACWidget_{$this->iId} = new AutocompleteWidget('$this->iId', '$this->sClass', '$this->sAttCode', '$this->sNameSuffix');
|
||||
oACWidget_{$this->iId} = new AutocompleteWidget('$this->iId', '$this->sClass', '$this->sAttCode', '$this->sNameSuffix', oWizardHelper$sFormPrefix);
|
||||
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
|
||||
EOF
|
||||
);
|
||||
$iMinChars = $this->oAttDef->GetMinAutoCompleteChars();
|
||||
|
||||
// the input for the auto-complete
|
||||
$sHTMLValue = "<input count=\"".count($this->aAllowedValues)."\" type=\"text\" id=\"label_$this->iId\" size=\"30\" maxlength=\"$iFieldSize\" value=\"$sDisplayValue\"/> <a class=\"no-arrow\" href=\"javascript:oACWidget_{$this->iId}.Search();\"><img style=\"border:0;vertical-align:middle;\" src=\"../images/mini_search.gif\" /></a> <span id=\"v_{$this->iId}\"></span>";
|
||||
$sHTMLValue = "<input count=\"".count($this->aAllowedValues)."\" type=\"text\" id=\"label_$this->iId\" size=\"30\" maxlength=\"$iFieldSize\" value=\"$sDisplayValue\"/> ";
|
||||
$sHTMLValue .= "<a class=\"no-arrow\" href=\"javascript:oACWidget_{$this->iId}.Search();\"><img style=\"border:0;vertical-align:middle;\" src=\"../images/mini_search.gif\" /></a> ";
|
||||
if ($bCreate)
|
||||
{
|
||||
$sHTMLValue .= "<a class=\"no-arrow\" href=\"javascript:oACWidget_{$this->iId}.CreateObject();\"><img style=\"border:0;vertical-align:middle;\" src=\"../images/mini_add.gif\" /></a> ";
|
||||
}
|
||||
$sHTMLValue .= "<span id=\"v_{$this->iId}\"></span>";
|
||||
|
||||
// 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";
|
||||
@@ -120,7 +129,12 @@ EOF
|
||||
$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
|
||||
}
|
||||
|
||||
return $sHTMLValue;
|
||||
}
|
||||
@@ -143,12 +157,29 @@ EOF
|
||||
$sHTML .= "</form>\n";
|
||||
$sHTML .= '</div></div></div>';
|
||||
|
||||
$oPage->add_ready_script("$('#fs_{$this->iId}').bind('submit.uilinksWizard', oACWidget_{$this->iId}.DoSearchObjects);");
|
||||
$oPage->add_ready_script("$('#fs_{$this->iId}').bind('submit.uiAutocomplete', oACWidget_{$this->iId}.DoSearchObjects);");
|
||||
$oPage->add_ready_script("$('#dc_{$this->iId}').resize(oACWidget_{$this->iId}.UpdateSizes);");
|
||||
|
||||
return $sHTML;
|
||||
}
|
||||
|
||||
|
||||
protected function GetCreationDialog(WebPage $oPage)
|
||||
{
|
||||
$sHTML = '<div id="ac_create_'.$this->iId.'"><div class="wizContainer" style="vertical-align:top;"><div id="dcr_'.$this->iId.'">';
|
||||
|
||||
//$sHTML .= "<form id=\"fcr_{$this->iId}\" OnSubmit=\"return oACWidget_{$this->iId}.DoCreate();\">\n";
|
||||
//cmdbAbstractObject::DisplayCreationForm($oPage, 'Person', null, array());
|
||||
//$sHTML .= "<input type=\"button\" id=\"btn_create_cancel_{$this->iId}\" value=\"".Dict::S('UI:Button:Cancel')."\" onClick=\"$('#ac_create_{$this->iId}').dialog('close');\"> ";
|
||||
//$sHTML .= "<input type=\"button\" id=\"btn_create_ok_{$this->iId}\" value=\"".Dict::S('UI:Button:New')."\" onClick=\"oACWidget_{$this->iId}.DoCreate();\">";
|
||||
//$sHTML .= "</form>\n";
|
||||
$sHTML .= '</div></div></div>';
|
||||
|
||||
//$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)
|
||||
@@ -181,5 +212,42 @@ EOF
|
||||
$oObj = MetaModel::GetObject($this->sTargetClass, $iObjId);
|
||||
return $oObj->GetName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the form to create a new object of the 'target' class
|
||||
*/
|
||||
public function GetObjectCreationForm(WebPage $oPage)
|
||||
{
|
||||
$oPage->add("<h1>".MetaModel::GetClassIcon($this->sTargetClass)." ".Dict::Format('UI:CreationTitle_Class', MetaModel::GetName($this->sTargetClass))."</h1>\n");
|
||||
cmdbAbstractObject::DisplayCreationForm($oPage, $this->sTargetClass, null, array(), array('formPrefix' => $this->iId, 'noRelations' => true));
|
||||
$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);");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the form to create a new object of the 'target' class
|
||||
*/
|
||||
public function DoCreateObject($oPage)
|
||||
{
|
||||
$oObj = MetaModel::NewObject($this->sTargetClass);
|
||||
$oObj->UpdateObject($this->sFormPrefix.$this->iId);
|
||||
$oMyChange = MetaModel::NewObject("CMDBChange");
|
||||
$oMyChange->Set("date", time());
|
||||
if (UserRights::IsImpersonated())
|
||||
{
|
||||
$sUserString = Dict::Format('UI:Archive_User_OnBehalfOf_User', UserRights::GetRealUser(), UserRights::GetUser());
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUserString = UserRights::GetUser();
|
||||
}
|
||||
$oMyChange->Set("userinfo", $sUserString);
|
||||
$iChangeId = $oMyChange->DBInsert();
|
||||
$oObj->DBInsertTracked($oMyChange);
|
||||
|
||||
return array('name' => $oObj->GetName(), 'id' => $oObj->GetKey());
|
||||
|
||||
//return array('name' => 'test', 'id' => '42');
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -227,6 +227,11 @@ class WizardHelper
|
||||
return $this->m_aData['m_sClass'];
|
||||
}
|
||||
|
||||
public function GetFormPrefix()
|
||||
{
|
||||
return $this->m_aData['m_sFormPrefix'];
|
||||
}
|
||||
|
||||
public function GetIdForField($sFieldName)
|
||||
{
|
||||
$sResult = '';
|
||||
|
||||
BIN
images/mini_add.gif
Normal file
BIN
images/mini_add.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 146 B |
@@ -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)
|
||||
function AutocompleteWidget(id, sClass, sAttCode, sSuffix, oWizHelper)
|
||||
{
|
||||
this.id = id;
|
||||
this.sClass = sClass;
|
||||
@@ -21,7 +21,10 @@ function AutocompleteWidget(id, sClass, sAttCode, sSuffix)
|
||||
this.sSuffix = sSuffix;
|
||||
this.emptyHtml = ''; // content to be displayed when the search results are empty (when opening the dialog)
|
||||
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;
|
||||
var me = this;
|
||||
|
||||
this.Init = function()
|
||||
{
|
||||
// make sure that the form is clean
|
||||
@@ -30,6 +33,15 @@ function AutocompleteWidget(id, sClass, sAttCode, sSuffix)
|
||||
$('#'+this.id+'_linksToRemove').val('');
|
||||
}
|
||||
|
||||
this.StopPendingRequest = function()
|
||||
{
|
||||
if (this.ajax_request)
|
||||
{
|
||||
this.ajax_request.Abort();
|
||||
this.ajax_request = null;
|
||||
}
|
||||
}
|
||||
|
||||
this.Search = function()
|
||||
{
|
||||
$('#ac_dlg_'+me.id).dialog('open');
|
||||
@@ -66,8 +78,6 @@ function AutocompleteWidget(id, sClass, sAttCode, sSuffix)
|
||||
}
|
||||
}
|
||||
|
||||
var ajax_request = null;
|
||||
|
||||
this.DoSearchObjects = function(id)
|
||||
{
|
||||
var theMap = { sAttCode: me.sAttCode,
|
||||
@@ -86,8 +96,8 @@ function AutocompleteWidget(id, sClass, sAttCode, sSuffix)
|
||||
}
|
||||
);
|
||||
|
||||
oWizardHelper.UpdateWizard();
|
||||
theMap['json'] = oWizardHelper.ToJSON();
|
||||
me.oWizardHelper.UpdateWizard();
|
||||
theMap['json'] = me.oWizardHelper.ToJSON();
|
||||
|
||||
theMap['sRemoteClass'] = theMap['class']; // swap 'class' (defined in the form) and 'remoteClass'
|
||||
theMap['class'] = me.sClass;
|
||||
@@ -100,14 +110,10 @@ function AutocompleteWidget(id, sClass, sAttCode, sSuffix)
|
||||
|
||||
// Make sure that we cancel any pending request before issuing another
|
||||
// since responses may arrive in arbitrary order
|
||||
if (ajax_request != null)
|
||||
{
|
||||
ajax_request.abort();
|
||||
ajax_request = null;
|
||||
}
|
||||
this.StopPendingRequest();
|
||||
|
||||
// Run the query and display the results
|
||||
ajax_request = $.post( 'ajax.render.php', theMap,
|
||||
this.ajax_request = $.post( 'ajax.render.php', theMap,
|
||||
function(data)
|
||||
{
|
||||
$(sSearchAreaId).html(data);
|
||||
@@ -115,7 +121,7 @@ function AutocompleteWidget(id, sClass, sAttCode, sSuffix)
|
||||
$(sSearchAreaId+' .listResults').tablesorter( { headers: {0: {sorter: false}}, widgets: ['myZebra', 'truncatedList']} ); // sortable and zebra tables
|
||||
$('#fr_'+me.id+' input:radio').click(function() { me.UpdateButtons(); });
|
||||
me.UpdateButtons();
|
||||
ajax_request = null;
|
||||
me.ajax_request = null;
|
||||
},
|
||||
'html'
|
||||
);
|
||||
@@ -140,21 +146,18 @@ function AutocompleteWidget(id, sClass, sAttCode, sSuffix)
|
||||
|
||||
// Make sure that we cancel any pending request before issuing another
|
||||
// since responses may arrive in arbitrary order
|
||||
if (ajax_request != null)
|
||||
{
|
||||
ajax_request.abort();
|
||||
ajax_request = null;
|
||||
}
|
||||
this.StopPendingRequest();
|
||||
|
||||
// Run the query and get the result back directly in JSON
|
||||
ajax_request = $.post( 'ajax.render.php', theMap,
|
||||
this.ajax_request = $.post( 'ajax.render.php', theMap,
|
||||
function(data)
|
||||
{
|
||||
$('#label_'+me.id).val(data.name);
|
||||
$('#label_'+me.id).removeClass('ac_loading');
|
||||
$('#'+me.id).val(iObjectId);
|
||||
$('#'+me.id).trigger('validate');
|
||||
ajax_request = null;
|
||||
$('#label_'+me.id).focus();
|
||||
me.ajax_request = null;
|
||||
},
|
||||
'json'
|
||||
);
|
||||
@@ -174,4 +177,96 @@ function AutocompleteWidget(id, sClass, sAttCode, sSuffix)
|
||||
}
|
||||
$('#label_'+me.id).focus();
|
||||
}
|
||||
|
||||
this.CreateObject = function(oWizHelper)
|
||||
{
|
||||
// Query the server to get the form to create a target object
|
||||
$('#label_'+me.id).addClass('ac_loading');
|
||||
me.oWizardHelper.UpdateWizard();
|
||||
var theMap = { sAttCode: me.sAttCode,
|
||||
iInputId: me.id,
|
||||
sSuffix: me.sSuffix,
|
||||
'class': me.sClass,
|
||||
'json': me.oWizardHelper.ToJSON(),
|
||||
operation: 'objectCreationForm'
|
||||
}
|
||||
|
||||
// Make sure that we cancel any pending request before issuing another
|
||||
// since responses may arrive in arbitrary order
|
||||
this.StopPendingRequest();
|
||||
|
||||
// Run the query and get the result back directly in JSON
|
||||
this.ajax_request = $.post( 'ajax.render.php', theMap,
|
||||
function(data)
|
||||
{
|
||||
$('#dcr_'+me.id).html(data);
|
||||
// Adjust the height of the dialog
|
||||
$('#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(); } );
|
||||
// Modify the action of the cancel button
|
||||
$('#ac_create_'+me.id+' button.cancel').unbind('click').click( me.CloseCreateObject );
|
||||
me.ajax_request = null;
|
||||
},
|
||||
'html'
|
||||
);
|
||||
}
|
||||
|
||||
this.CloseCreateObject = function()
|
||||
{
|
||||
$('#ac_create_'+me.id).dialog( "close" );
|
||||
$('#dcr_'+me.id).html('');
|
||||
}
|
||||
|
||||
this.DoCreateObject = function()
|
||||
{
|
||||
var sFormId = $('#dcr_'+me.id+' form').attr('id');
|
||||
if (CheckFields(sFormId, true))
|
||||
{
|
||||
$('#'+sFormId).block();
|
||||
var theMap = { sAttCode: me.sAttCode,
|
||||
iInputId: me.id,
|
||||
sSuffix: me.sSuffix,
|
||||
'class': me.sClass,
|
||||
'json': me.oWizardHelper.ToJSON()
|
||||
}
|
||||
|
||||
// Gather the values from the form
|
||||
// Gather the parameters from the search form
|
||||
$('#'+sFormId+' :input').each(
|
||||
function(i)
|
||||
{
|
||||
if (this.name != '')
|
||||
{
|
||||
theMap[this.name] = this.value;
|
||||
}
|
||||
}
|
||||
);
|
||||
// Override the 'operation' code
|
||||
theMap['operation'] = 'doCreateObject';
|
||||
theMap['class'] = me.sClass;
|
||||
|
||||
$('#ac_create_'+me.id).dialog('close');
|
||||
|
||||
// Make sure that we cancel any pending request before issuing another
|
||||
// since responses may arrive in arbitrary order
|
||||
this.StopPendingRequest();
|
||||
|
||||
// Run the query and get the result back directly in JSON
|
||||
this.ajax_request = $.post( 'ajax.render.php', theMap,
|
||||
function(data)
|
||||
{
|
||||
$('#label_'+me.id).val(data.name);
|
||||
$('#'+me.id).val(data.id);
|
||||
$('#'+me.id).trigger('validate');
|
||||
$('#label_'+me.id).removeClass('ac_loading');
|
||||
$('#label_'+me.id).focus();
|
||||
me.ajax_request = null;
|
||||
},
|
||||
'json'
|
||||
);
|
||||
}
|
||||
return false; // do NOT submit the form
|
||||
}
|
||||
}
|
||||
@@ -231,6 +231,7 @@ function ValidateCKEditField(sFieldId, sPattern, bMandatory, sFormId, nullValue)
|
||||
setTimeout(function(){ValidateCKEditField(sFieldId, sPattern, bMandatory, sFormId, nullValue);}, 500);
|
||||
}
|
||||
|
||||
/*
|
||||
function UpdateDependentFields(aFieldNames)
|
||||
{
|
||||
//console.log('UpdateDependentFields:');
|
||||
@@ -248,6 +249,7 @@ function UpdateDependentFields(aFieldNames)
|
||||
}
|
||||
oWizardHelper.AjaxQueryServer();
|
||||
}
|
||||
*/
|
||||
|
||||
function ResetPwd(id)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Wizard Helper JavaScript class to communicate with the WizardHelper PHP class
|
||||
function WizardHelper(sClass)
|
||||
function WizardHelper(sClass, sFormPrefix)
|
||||
{
|
||||
this.m_oData = { 'm_sClass' : '',
|
||||
'm_oFieldsMap': {},
|
||||
@@ -8,7 +8,8 @@ function WizardHelper(sClass)
|
||||
'm_aAllowedValuesRequested': [],
|
||||
'm_oDefaultValue': {},
|
||||
'm_oAllowedValues': {},
|
||||
'm_iFieldsCount' : 0
|
||||
'm_iFieldsCount' : 0,
|
||||
'm_sFormPrefix' : sFormPrefix
|
||||
};
|
||||
this.m_oData.m_sClass = sClass;
|
||||
|
||||
@@ -135,4 +136,20 @@ function WizardHelper(sClass)
|
||||
this.m_oData.m_oCurrentValues[sFieldCode] = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
this.UpdateDependentFields = function(aFieldNames)
|
||||
{
|
||||
index = 0;
|
||||
this.ResetQuery();
|
||||
this.UpdateWizard();
|
||||
while(index < aFieldNames.length )
|
||||
{
|
||||
sAttCode = aFieldNames[index];
|
||||
sFieldId = this.GetFieldId(sAttCode);
|
||||
$('#v_'+sFieldId).html('<img src="../images/indicator.gif" />');
|
||||
this.RequestAllowedValues(sAttCode);
|
||||
index++;
|
||||
}
|
||||
this.AjaxQueryServer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,6 @@ switch($operation)
|
||||
$sAttCode = utils::ReadParam('sAttCode', '');
|
||||
$iInputId = utils::ReadParam('iInputId', '');
|
||||
$sSuffix = utils::ReadParam('sSuffix', '');
|
||||
// To do: retrieve the object under construction & use it to filter the allowed values
|
||||
$sJson = utils::ReadParam('json', '');
|
||||
$oWizardHelper = WizardHelper::FromJSON($sJson);
|
||||
$oObj = $oWizardHelper->GetTargetObject();
|
||||
@@ -84,6 +83,36 @@ switch($operation)
|
||||
$oWidget->SearchObjectsToSelect($oPage, $sTargetClass);
|
||||
break;
|
||||
|
||||
// ui.autocompletewidget
|
||||
case 'objectCreationForm':
|
||||
$sTargetClass = utils::ReadParam('sRemoteClass', '');
|
||||
$sAttCode = utils::ReadParam('sAttCode', '');
|
||||
$iInputId = utils::ReadParam('iInputId', '');
|
||||
$sSuffix = utils::ReadParam('sSuffix', '');
|
||||
$sJson = utils::ReadParam('json', '');
|
||||
$oWizardHelper = WizardHelper::FromJSON($sJson);
|
||||
$oObj = $oWizardHelper->GetTargetObject();
|
||||
$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, array('this' => $oObj));
|
||||
$oWidget = new UIAutocompleteWidget($sAttCode, $sClass, '', $aAllowedValues, $oObj->Get($sAttCode), $iInputId, $sSuffix, '');
|
||||
$oWidget->GetObjectCreationForm($oPage);
|
||||
break;
|
||||
|
||||
// ui.autocompletewidget
|
||||
case 'doCreateObject':
|
||||
$sTargetClass = utils::ReadParam('sRemoteClass', '');
|
||||
$sAttCode = utils::ReadParam('sAttCode', '');
|
||||
$iInputId = utils::ReadParam('iInputId', '');
|
||||
$sSuffix = utils::ReadParam('sSuffix', '');
|
||||
$sJson = utils::ReadParam('json', '');
|
||||
$oWizardHelper = WizardHelper::FromJSON($sJson);
|
||||
$oObj = $oWizardHelper->GetTargetObject();
|
||||
$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, array('this' => $oObj));
|
||||
// The iInputId of the autocomplete is the prefix for the form used to create the target object
|
||||
$oWidget = new UIAutocompleteWidget($sAttCode, $sClass, '', $aAllowedValues, null, $iInputId, $sSuffix, $oWizardHelper->GetFormPrefix());
|
||||
$aResult = $oWidget->DoCreateObject($oPage);
|
||||
echo json_encode($aResult);
|
||||
break;
|
||||
|
||||
// ui.autocompletewidget
|
||||
case 'getObjectName':
|
||||
$sTargetClass = utils::ReadParam('sTargetClass', '');
|
||||
@@ -126,6 +155,7 @@ switch($operation)
|
||||
$oWizardHelper->SetDefaultValue($sAttCode, $defaultValue);
|
||||
$oObj->Set($sAttCode, $defaultValue);
|
||||
}
|
||||
$sFormPrefix = $oWizardHelper->GetFormPrefix();
|
||||
foreach($oWizardHelper->GetFieldsForAllowedValues() as $sAttCode)
|
||||
{
|
||||
$sId = $oWizardHelper->GetIdForField($sAttCode);
|
||||
@@ -138,13 +168,13 @@ switch($operation)
|
||||
$displayValue = $oObj->GetEditValue($sAttCode);
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
$iFlags = MetaModel::GetAttributeFlags($sClass, $oObj->GetState(), $sAttCode);
|
||||
$sHTMLValue = cmdbAbstractObject::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $value, $displayValue, $sId, '', $iFlags, array('this' => $oObj));
|
||||
$sHTMLValue = cmdbAbstractObject::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $value, $displayValue, $sId, '', $iFlags, array('this' => $oObj, 'formPrefix' => $sFormPrefix));
|
||||
// Make sure that we immediatly validate the field when we reload it
|
||||
$oPage->add_ready_script("$('#$sId').trigger('validate');");
|
||||
$oWizardHelper->SetAllowedValuesHtml($sAttCode, $sHTMLValue);
|
||||
}
|
||||
}
|
||||
$oPage->add("<script type=\"text/javascript\">\noWizardHelper.m_oData=".$oWizardHelper->ToJSON().";\noWizardHelper.UpdateFields();\n</script>\n");
|
||||
$oPage->add_script("oWizardHelper{$sFormPrefix}.m_oData=".$oWizardHelper->ToJSON().";\noWizardHelper{$sFormPrefix}.UpdateFields();\n");
|
||||
break;
|
||||
|
||||
case 'ajax':
|
||||
|
||||
Reference in New Issue
Block a user