mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-18 06:48:50 +02:00
N°9229 - Modernize search foreign keys code with built in JS tools (#847)
* N°9229 - Modernize search foreign keys code with built in JS tools * N°9229 - Allow modals to have button id specified * N°9229 - Remove the modal instead of only destroying it * N°9229 - Remove dead code * Update js/searchformforeignkeys.js * Add robustness to modals button id
This commit is contained in:
@@ -27,6 +27,9 @@ require_once(APPROOT.'/application/displayblock.class.inc.php');
|
||||
|
||||
class UISearchFormForeignKeys
|
||||
{
|
||||
private $m_sRemoteClass;
|
||||
private $m_iInputId;
|
||||
|
||||
public function __construct($sTargetClass, $iInputId = null)
|
||||
{
|
||||
$this->m_sRemoteClass = $sTargetClass;
|
||||
@@ -40,7 +43,7 @@ class UISearchFormForeignKeys
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function ShowModalSearchForeignKeys($oPage, $sTitle)
|
||||
public function ShowModalSearchForeignKeys($oPage)
|
||||
{
|
||||
|
||||
$oFilter = new DBObjectSearch($this->m_sRemoteClass);
|
||||
@@ -60,8 +63,6 @@ class UISearchFormForeignKeys
|
||||
]
|
||||
));
|
||||
$sEmptyList = Dict::S('UI:Message:EmptyList:UseSearchForm');
|
||||
$sCancel = Dict::S('UI:Button:Cancel');
|
||||
$sAdd = Dict::S('UI:Button:Add');
|
||||
|
||||
$oPage->add(
|
||||
<<<HTML
|
||||
@@ -73,39 +74,6 @@ class UISearchFormForeignKeys
|
||||
</form>
|
||||
HTML
|
||||
);
|
||||
|
||||
$oPage->add_ready_script(
|
||||
<<<JS
|
||||
$('#dlg_{$this->m_iInputId}').dialog({
|
||||
width: $(window).width()*0.8,
|
||||
height: $(window).height()*0.8,
|
||||
autoOpen: false,
|
||||
modal: true,
|
||||
resizeStop: oForeignKeysWidget{$this->m_iInputId}.UpdateSizes,
|
||||
buttons: [
|
||||
{
|
||||
text: Dict.S('UI:Button:Cancel'),
|
||||
class: "cancel ibo-is-alternative ibo-is-neutral",
|
||||
click: function() {
|
||||
$('#dlg_{$this->m_iInputId}').dialog('close');
|
||||
}
|
||||
},
|
||||
{
|
||||
text: Dict.S('UI:Button:Add'),
|
||||
id: 'btn_ok_{$this->m_iInputId}',
|
||||
class: "ok ibo-is-regular ibo-is-primary",
|
||||
click: function() {
|
||||
oForeignKeysWidget{$this->m_iInputId}.DoAddObjects(this.id);
|
||||
}
|
||||
},
|
||||
],
|
||||
|
||||
});
|
||||
$('#dlg_{$this->m_iInputId}').dialog('option', {title:'$sTitle'});
|
||||
$('#SearchFormToAdd_{$this->m_iInputId} form').on('submit.uilinksWizard', oForeignKeysWidget{$this->m_iInputId}.SearchObjectsToAdd);
|
||||
$('#SearchFormToAdd_{$this->m_iInputId}').on('resize', oForeignKeysWidget{$this->m_iInputId}.UpdateSizes);
|
||||
JS
|
||||
);
|
||||
}
|
||||
|
||||
public function GetFullListForeignKeysFromSelection($oPage, $oFullSetFilter)
|
||||
@@ -119,31 +87,4 @@ JS
|
||||
IssueLog::Error($e->getMessage()."\nDebug trace:\n".$e->getTraceAsString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for objects to be linked to the current object (i.e "remote" objects)
|
||||
*
|
||||
* @param WebPage $oP The page used for the output (usually an AjaxWebPage)
|
||||
* @param string $sRemoteClass Name of the "remote" class to perform the search on, must be a derived class of m_sRemoteClass
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function ListResultsSearchForeignKeys(WebPage $oP, $sRemoteClass = '')
|
||||
{
|
||||
if ($sRemoteClass != '') {
|
||||
// assert(MetaModel::IsParentClass($this->m_sRemoteClass, $sRemoteClass));
|
||||
$oFilter = new DBObjectSearch($sRemoteClass);
|
||||
} else {
|
||||
// No remote class specified use the one defined in the linkedset
|
||||
$oFilter = new DBObjectSearch($this->m_sRemoteClass);
|
||||
}
|
||||
|
||||
$oBlock = new DisplayBlock($oFilter, 'list', false);
|
||||
$oBlock->Display(
|
||||
$oP,
|
||||
"ResultsToAdd_{$this->m_iInputId}",
|
||||
['menu' => false, 'cssCount' => "#count_{$this->m_iInputId}", 'selection_mode' => true, 'table_id' => "add_{$this->m_iInputId}"]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -332,6 +332,12 @@ CombodoModal._ConvertButtonDefinition = function (aButtonsDefinitions) {
|
||||
class: typeof(element.classes) !== 'undefined' ? element.classes.join(' ') : '',
|
||||
click: element.callback_on_click
|
||||
}
|
||||
|
||||
// id is optional, and we don't want to set it if not defined
|
||||
if (typeof element.id !== 'undefined' && element.id !== null) {
|
||||
aButton.id = element.id;
|
||||
}
|
||||
|
||||
aConverted.push(aButton);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -35,116 +35,63 @@ function SearchFormForeignKeys(id, sTargetClass, sAttCode, oSearchWidgetElmt, sF
|
||||
this.sAttCode = sAttCode;
|
||||
this.oSearchWidgetElmt = oSearchWidgetElmt;
|
||||
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.ajax_request = null;
|
||||
// this.bSelectMode = bSelectMode; // true if the edited field is a SELECT, false if it's an autocomplete
|
||||
// this.bSearchMode = bSearchMode; // true if selecting a value in the context of a search form
|
||||
var me = this;
|
||||
|
||||
this.Init = function()
|
||||
{
|
||||
// make sure that the form is clean
|
||||
$('#linkedset_'+this.id+' .selection').each( function() { this.checked = false; });
|
||||
$('#'+this.id+'_btnRemove').prop('disabled', false);
|
||||
|
||||
$('<div id="dlg_'+me.id+'"></div>').appendTo(document.body);
|
||||
|
||||
// me.trace(dialog);
|
||||
|
||||
//TODO : check and remove all unneded code bellow this line!!
|
||||
|
||||
$('#'+this.id+'_linksToRemove').val('');
|
||||
|
||||
$('#linkedset_'+me.id).on('remove', function() {
|
||||
// prevent having the dlg div twice
|
||||
$('#dlg_'+me.id).remove();
|
||||
});
|
||||
|
||||
$('#'+this.iInputId).closest('form').on('submit', function() {
|
||||
return me.OnFormSubmit();
|
||||
});
|
||||
};
|
||||
|
||||
this.StopPendingRequest = function()
|
||||
{
|
||||
if (me.ajax_request)
|
||||
{
|
||||
me.ajax_request.abort();
|
||||
me.ajax_request = null;
|
||||
}
|
||||
};
|
||||
|
||||
this.ShowModalSearchForeignKeys = function()
|
||||
{
|
||||
// // Query the server to get the form to search for target objects
|
||||
// if (me.bSelectMode)
|
||||
// {
|
||||
// $('#fstatus_'+me.id).html('<img src="../images/indicator.gif" />');
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// $('#label_'+me.id).addClass('dlg_loading');
|
||||
// }
|
||||
$('#label_'+me.id).addClass('dlg_loading');
|
||||
var theMap = {
|
||||
sAttCode: me.sAttCode,
|
||||
iInputId: me.id,
|
||||
sTitle: me.sTitle,
|
||||
sTargetClass: me.sTargetClass,
|
||||
// bSearchMode: me.bSearchMode,
|
||||
operation: 'ShowModalSearchForeignKeys'
|
||||
};
|
||||
const oModalParams = {
|
||||
content: {
|
||||
endpoint: AddAppContext(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php'),
|
||||
data: {
|
||||
sAttCode: me.sAttCode,
|
||||
iInputId: me.id,
|
||||
sTargetClass: me.sTargetClass,
|
||||
operation: 'ShowModalSearchForeignKeys'
|
||||
},
|
||||
},
|
||||
title: me.sTitle,
|
||||
id: 'dlg_'+me.id,
|
||||
size: 'lg',
|
||||
buttons: [
|
||||
{
|
||||
text: Dict.S('UI:Button:Cancel'),
|
||||
callback_on_click: function() {
|
||||
$(this).dialog("close");
|
||||
},
|
||||
classes: ['cancel', 'ibo-is-alternative', 'ibo-is-neutral'],
|
||||
},
|
||||
{
|
||||
text: Dict.S('UI:Button:Add'),
|
||||
id: "btn_ok_"+me.id,
|
||||
classes: ['ok', 'ibo-is-regular', 'ibo-is-primary'],
|
||||
callback_on_click: function() {
|
||||
me.DoAddObjects();
|
||||
}
|
||||
}
|
||||
],
|
||||
callback_on_content_loaded: function(oModalContentElement){
|
||||
// Update initial buttons state
|
||||
me.UpdateButtons();
|
||||
},
|
||||
|
||||
extra_options: {
|
||||
callback_on_modal_close: function () {
|
||||
$(this).remove(); // destroy then remove dialog object
|
||||
}
|
||||
}
|
||||
}
|
||||
const oModal = CombodoModal.OpenModal(oModalParams);
|
||||
|
||||
|
||||
// Make sure that we cancel any pending request before issuing another
|
||||
// since responses may arrive in arbitrary order
|
||||
me.StopPendingRequest();
|
||||
|
||||
// Run the query and get the result back directly in HTML
|
||||
me.ajax_request = $.post( AddAppContext(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php'), theMap,
|
||||
function(data)
|
||||
{
|
||||
// $('#dlg_'+me.id).html(data);
|
||||
$('#dlg_'+me.id).empty().append($(data)); // $(data).filter(':not(script)'));
|
||||
$('#dlg_'+me.id).dialog('open');
|
||||
me.UpdateSizes();
|
||||
me.UpdateButtons();
|
||||
me.ajax_request = null;
|
||||
me.ListResultsSearchForeignKeys();
|
||||
},
|
||||
'html'
|
||||
);
|
||||
};
|
||||
|
||||
this.UpdateSizes = function()
|
||||
{
|
||||
var dlg = $('#dlg_'+me.id);
|
||||
// Adjust the dialog's size to fit into the screen
|
||||
if (dlg.width() > ($(window).width()-40))
|
||||
{
|
||||
dlg.width($(window).width()-40);
|
||||
}
|
||||
if (dlg.height() > ($(window).height()-70))
|
||||
{
|
||||
dlg.height($(window).height()-70);
|
||||
}
|
||||
var searchForm = dlg.find('div.display_block:first'); // Top search form, enclosing display_block
|
||||
var results = $('#SearchResultsToAdd_'+me.id);
|
||||
var oPadding = {};
|
||||
var aKeys = ['top', 'right', 'bottom', 'left'];
|
||||
for(k in aKeys)
|
||||
{
|
||||
oPadding[aKeys[k]] = 0;
|
||||
if (dlg.css('padding-'+aKeys[k]))
|
||||
{
|
||||
oPadding[aKeys[k]] = parseInt(dlg.css('padding-'+aKeys[k]).replace('px', ''));
|
||||
}
|
||||
}
|
||||
//var width = dlg.innerWidth() - oPadding['right'] - oPadding['left'] - 22; // 5 (margin-left) + 5 (padding-left) + 5 (padding-right) + 5 (margin-right) + 2 for rounding !
|
||||
var height = dlg.innerHeight()-oPadding['top']-oPadding['bottom']-22;
|
||||
var form_height = searchForm.outerHeight();
|
||||
results.height(height - form_height - 40); // Leave some space for the buttons
|
||||
// Bind events
|
||||
oModal.on('change', '#count_'+me.id, function(){
|
||||
me.UpdateButtons();
|
||||
});
|
||||
};
|
||||
|
||||
this.UpdateButtons = function()
|
||||
@@ -160,63 +107,6 @@ function SearchFormForeignKeys(id, sTargetClass, sAttCode, oSearchWidgetElmt, sF
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {boolean}
|
||||
*/
|
||||
this.ListResultsSearchForeignKeys = function ()
|
||||
{
|
||||
var theMap = {
|
||||
sTargetClass: me.sTargetClass,
|
||||
iInputId: me.id,
|
||||
sFilter: me.sfilter,
|
||||
// bSearchMode: me.bSearchMode
|
||||
};
|
||||
|
||||
// Gather the parameters from the search form
|
||||
$('#fs_'+me.id+' :input').each( function() {
|
||||
if (this.name !== '')
|
||||
{
|
||||
var val = $(this).val(); // supports multiselect as well
|
||||
if (val !== null)
|
||||
{
|
||||
theMap[this.name] = val;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
theMap['sRemoteClass'] = theMap['class']; // swap 'class' (defined in the form) and 'remoteClass'
|
||||
theMap.operation = 'ListResultsSearchForeignKeys'; // Override what is defined in the form itself
|
||||
theMap.sAttCode = me.sAttCode;
|
||||
var sSearchAreaId = '#SearchResultsToAdd_'+me.id;
|
||||
//$(sSearchAreaId).html('<div style="text-align:center;width:100%;height:24px;vertical-align:middle;"><img src="../images/indicator.gif" /></div>');
|
||||
$(sSearchAreaId).block();
|
||||
me.UpdateButtons();
|
||||
|
||||
// Make sure that we cancel any pending request before issuing another
|
||||
// since responses may arrive in arbitrary order
|
||||
me.StopPendingRequest();
|
||||
|
||||
// Run the query and display the results
|
||||
me.ajax_request = $.post(AddAppContext(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php'), theMap,
|
||||
function(data)
|
||||
{
|
||||
$(sSearchAreaId).html(data);
|
||||
$('#fr_'+me.id+' input:radio').on('click', function() { me.UpdateButtons(); });
|
||||
me.UpdateButtons();
|
||||
me.ajax_request = null;
|
||||
$('#count_'+me.id).on('change', function(){
|
||||
me.UpdateButtons();
|
||||
});
|
||||
me.UpdateSizes();
|
||||
},
|
||||
'html'
|
||||
);
|
||||
|
||||
return false; // Don't submit the form, stay in the current page !
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {boolean}
|
||||
*/
|
||||
@@ -286,56 +176,4 @@ function SearchFormForeignKeys(id, sTargetClass, sAttCode, oSearchWidgetElmt, sF
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
// Workaround for a ui.jquery limitation: if the content of
|
||||
// the dialog contains many INPUTs, closing and opening the
|
||||
// dialog is very slow. So empty it each time.
|
||||
this.OnClose = function()
|
||||
{
|
||||
me.StopPendingRequest();
|
||||
// called by the dialog, so in the context 'this' points to the jQueryObject
|
||||
if (me.emptyOnClose)
|
||||
{
|
||||
$('#SearchResultsToAdd_'+me.id).html(me.emptyHtml);
|
||||
}
|
||||
$('#label_'+me.id).removeClass('dlg_loading');
|
||||
$('#label_'+me.id).focus();
|
||||
me.ajax_request = null;
|
||||
};
|
||||
|
||||
this.DoSelectObjectClass = function()
|
||||
{
|
||||
// Retrieving selected value
|
||||
var oSelectedClass = $('#ac_create_'+me.id+' select');
|
||||
if(oSelectedClass.length !== 1) return;
|
||||
|
||||
// Setting new target class
|
||||
me.sTargetClass = oSelectedClass.val();
|
||||
|
||||
// Opening real creation form
|
||||
$('#ac_create_'+me.id).dialog('close');
|
||||
me.CreateObject();
|
||||
};
|
||||
|
||||
this.Update = function()
|
||||
{
|
||||
if ($('#'+me.id).prop('disabled'))
|
||||
{
|
||||
$('#v_'+me.id).html('');
|
||||
$('#label_'+me.id).prop('disabled', true);
|
||||
$('#label_'+me.id).css({'background': 'transparent'});
|
||||
$('#mini_add_'+me.id).hide();
|
||||
$('#mini_tree_'+me.id).hide();
|
||||
$('#mini_search_'+me.id).hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#label_'+me.id).prop('disabled', false);
|
||||
$('#label_'+me.id).css({'background': '#fff url(../images/ac-background.gif) no-repeat right'});
|
||||
$('#mini_add_'+me.id).show();
|
||||
$('#mini_tree_'+me.id).show();
|
||||
$('#mini_search_'+me.id).show();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -173,10 +173,9 @@ try {
|
||||
case 'ShowModalSearchForeignKeys':
|
||||
$oPage->SetContentType('text/html');
|
||||
$iInputId = utils::ReadParam('iInputId', '');
|
||||
$sTitle = utils::ReadParam('sTitle', '', false, 'raw_data');
|
||||
$sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class');
|
||||
$oWidget = new UISearchFormForeignKeys($sTargetClass, $iInputId);
|
||||
$oWidget->ShowModalSearchForeignKeys($oPage, $sTitle);
|
||||
$oWidget->ShowModalSearchForeignKeys($oPage);
|
||||
break;
|
||||
|
||||
// ui.searchformforeignkeys
|
||||
@@ -187,16 +186,6 @@ try {
|
||||
$oWidget->GetFullListForeignKeysFromSelection($oPage, $oFullSetFilter);
|
||||
break;
|
||||
|
||||
// ui.searchformforeignkeys
|
||||
case 'ListResultsSearchForeignKeys':
|
||||
$oPage->SetContentType('text/html');
|
||||
$sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class');
|
||||
$iInputId = utils::ReadParam('iInputId', '');
|
||||
$sRemoteClass = utils::ReadParam('sRemoteClass', '', false, 'class');
|
||||
$oWidget = new UISearchFormForeignKeys($sTargetClass, $iInputId);
|
||||
$oWidget->ListResultsSearchForeignKeys($oPage, $sRemoteClass);
|
||||
break;
|
||||
|
||||
// ui.linkswidget
|
||||
case 'addObjects':
|
||||
$oPage->SetContentType('text/html');
|
||||
|
||||
Reference in New Issue
Block a user