/* * @copyright Copyright (C) 2010-2024 Combodo SAS * @license http://opensource.org/licenses/AGPL-3.0 */ /* * Plugin to change the behaviour of enter and backspace buttons * if the inputText is null when iti push on enter, the field is put to null * when we push on backspace, it clean the input text, in order to autocmplete * */ Selectize.define('custom_itop', function(aOptions) { var KEY_BACKSPACE = 8; var KEY_RETURN = 13; var self = this; aOptions.text = aOptions.text || function (aOptions) { return aOptions[this.settings.labelField]; }; self.onKeyDown = (function () { var original = self.onKeyDown; return function (e) { var iIndex; switch (e.keyCode) { case KEY_BACKSPACE: if (this.$control_input.val() === '' && !this.$activeItems.length) { iIndex = this.caretPos-1; if (iIndex >= 0 && iIndex < this.items.length) { let sPreviousValue = this.options[this.items[iIndex]].search_label; this.clear(true); e.preventDefault(); this.setTextboxValue(sPreviousValue.slice(0, -1)); return; } } case KEY_RETURN: if (self.isOpen) { //case nothing selected ->delete selection if (!self.$activeOption || (self.currentResults.query === '' && !this.$control_input.val() === '')) { self.deleteSelection(e); self.setValue(""); return; } } } return original.apply(this, arguments); }; })(); self.open = (function () { let original = self.open; return function () { ManageScroll(self); original.apply(self); } })(); self.close = (function () { let original = self.close; return function () { StopManageScroll(self); original.apply(self); } })(); ManageScroll = function (self) { let id = self.$input[0].id; if (self.$input.scrollParent()[0].tagName != 'HTML') { self.$input.scrollParent().on(['scroll.'+id, 'resize.'+id].join(" "), function () { setTimeout(function () { ManageScrollInElement(self); }, 50); }); if (self.$input.scrollParent().scrollParent()[0].tagName != 'HTML') { self.$input.scrollParent().scrollParent().on(['scroll.'+id, 'resize.'+id].join(" "), function () { setTimeout(function () { ManageScrollInElement(self); }, 50); }); } } }; StopManageScroll = function (self) { let id = self.$input[0].id; if (self.$input.scrollParent()[0].tagName != 'HTML') { self.$input.scrollParent().off('scroll.'+id); self.$input.scrollParent().off('resize.'+id); if (self.$input.scrollParent().scrollParent()[0].tagName != 'HTML') { self.$input.scrollParent().scrollParent().off('scroll.'+id); self.$input.scrollParent().scrollParent().off('resize.'+id); } } }; ManageScrollInElement = function (self) { if (self.isOpen) { if (self.$input.closest('.ibo-panel') != 'undefined' && self.$input.closest('.ibo-panel').find('.ibo-panel--header').first().outerHeight()+self.$input.closest('.ibo-panel').find('.ibo-panel--header').first().offset().top > self.$control_input.offset().top) { //field is not visible self.close(); } else { self.positionDropdown.apply(self, arguments); } } }; }); function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper, sAttCode, bSearchMode, bDoSearch, sFormAttCode) { this.id = id; this.sOriginalTargetClass = sTargetClass; this.sTargetClass = sTargetClass; this.sFilter = sFilter; this.sTitle = sTitle; this.sAttCode = sAttCode; 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; 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 this.bDoSearch = bDoSearch; // false if the search is not launched this.sFormAttCode = sFormAttCode; var me = this; this.Init = function () { // make sure that the form is clean $('#'+this.id+'_btnRemove').prop('disabled', true); $('#'+this.id+'_linksToRemove').val(''); } this.AddSelectize = function (options, initValue) { let $select = $('#'+me.id).selectize({ plugins:['custom_itop', 'selectize-plugin-a11y'], render: { item: function (item) { if (item.obsolescence_flag == 1) { val = ''+item.label; } else { val = item.label; } return $("
');
} else {
$('#label_'+me.id).addClass('ac_dlg_loading');
}
let sPromiseId = 'ajax_promise_'+me.id;
let theMap = {
sAttCode: me.sAttCode,
iInputId: me.id,
sTitle: me.sTitle,
sAttCode: me.sAttCode,
sTargetClass: me.sTargetClass,
sFilter: me.sFilter,
bSearchMode: me.bSearchMode,
operation: 'objectSearchForm',
ajax_promise_id: sPromiseId
};
if (me.oWizardHelper == null) {
theMap['json'] = '';
} else {
// Not inside a "search form", updating a real object
me.oWizardHelper.UpdateWizard();
theMap['json'] = me.oWizardHelper.ToJSON();
}
// 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) {
$('#ac_dlg_'+me.id).html(data);
window[sPromiseId].then(function () {
$('#ac_dlg_'+me.id).dialog('open');
me.UpdateSizes();
me.UpdateButtons();
me.ajax_request = null;
$('#count_'+me.id+'_results').on('change', function () {
me.UpdateButtons();
});
if (me.bDoSearch) {
me.DoSearchObjects();
}
});
},
'html'
);
};
/**
* Update the dialog size to fit into the screen
* @constructor
*/
this.UpdateSizes = function () {
var dlg = $('#ac_dlg_'+me.id);
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 = $('#dr_'+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', ''));
}
}
width = dlg.innerWidth()-oPadding['right']-oPadding['left']-22; // 5 (margin-left) + 5 (padding-left) + 5 (padding-right) + 5 (margin-right) + 2 for rounding !
height = dlg.innerHeight()-oPadding['top']-oPadding['bottom']-22;
form_height = searchForm.outerHeight();
results.height(height-form_height-40); // Leave some space for the buttons
};
this.UpdateButtons = function () {
var okBtn = $('#btn_ok_'+me.id+'_results');
if ($('#count_'+me.id+'_results').val() > 0) {
okBtn.prop('disabled', false);
} else {
okBtn.prop('disabled', true);
}
};
this.DoSearchObjects = function (id) {
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;
}
}
});
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.operation = 'searchObjectsToSelect'; // Override what is defined in the form itself
theMap.sAttCode = me.sAttCode,
sSearchAreaId = '#dr_'+me.id;
$(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;
me.UpdateSizes();
},
'html'
);
return false; // Don't submit the form, stay in the current page !
};
this.DoOk = function () {
var iObjectId = window['oSelectedItems'+me.id+'_results'][0];
$('#ac_dlg_'+this.id).dialog('close');
$('#label_'+this.id).addClass('ac_dlg_loading');
// Query the server again to get the display name of the selected object
var theMap = {
sTargetClass: me.sTargetClass,
iInputId: me.id,
iObjectId: iObjectId,
sAttCode: me.sAttCode,
sFormAttCode: me.sFormAttCode,
bSearchMode: me.bSearchMode,
operation: 'getObjectName'
};
// 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 JSON
me.ajax_request = $.post(AddAppContext(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php'), theMap,
function (data) {
var oTemp = $('
');
} else {
$('#label_'+me.id).addClass('ac_dlg_loading');
}
me.oWizardHelper.UpdateWizard();
var sPromiseId = 'ajax_promise_'+me.id;
var theMap = {
sTargetClass: me.sTargetClass,
iInputId: me.id,
sAttCode: me.sAttCode,
'json': me.oWizardHelper.ToJSON(),
operation: 'objectCreationForm',
ajax_promise_id: sPromiseId,
bTargetClassSelected: bTargetClassSelected
};
// 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
var sLocalTargetClass = me.sTargetClass; // Remember the target class since it will be reset when closing the dialog
// Handle transaction id
const sRootFormTransactionId = me.GetRootTransactionId();
me.ajax_request = $.post(AddAppContext(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php'), theMap,
function (data) {
$('#ajax_'+me.id).html(data);
window[sPromiseId].then(function () {
$('#ac_create_'+me.id).dialog('open');
$('#ac_create_'+me.id).dialog("option", "close", me.OnCloseCreateObject);
// Modify the action of the cancel button
$('#ac_create_'+me.id+' button.cancel').off('click').on('click', me.CloseCreateObject);
me.ajax_request = null;
me.sTargetClass = sLocalTargetClass;
// Adjust the dialog's size to fit into the screen
if ($('#ac_create_'+me.id).width() > ($(window).width()-40)) {
$('#ac_create_'+me.id).width($(window).width()-40);
}
if ($('#ac_create_'+me.id).height() > ($(window).height()-70)) {
$('#ac_create_'+me.id).height($(window).height()-70);
}
// Add root_transaction_id
$('#ac_create_'+me.id+' form').append(``)
});
},
'html'
);
};
this.CloseCreateObject = function () {
$('#ac_create_'+me.id).dialog("close");
};
this.OnCloseCreateObject = function () {
if (me.bSelectMode) {
$('#fstatus_'+me.id).html('');
} else {
$('#label_'+me.id).removeClass('ac_dlg_loading');
}
$('#label_'+me.id).focus();
$('#ac_create_'+me.id).dialog("destroy");
$('#ac_create_'+me.id).remove();
$('#ajax_'+me.id).html('');
// Resetting target class to its original value
// (If not done, closing the dialog and trying to create a object again
// will force it be of the same class as the previous call)
me.sTargetClass = me.sOriginalTargetClass;
};
this.DoCreateObject = function () {
var sFormId = $('#dcr_'+me.id+' form').attr('id');
if (CheckFields(sFormId, true)) {
$('#'+sFormId).block();
var theMap = {
sTargetClass: me.sTargetClass,
iInputId: me.id,
sAttCode: me.sAttCode,
'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 != '') {
if ($(this).hasClass('htmlEditor')) {
var sId = $(this).attr('id');
CombodoCKEditorHandler.DeleteInstance(sId);
if ($('#'+sId).data('timeout_validate') != undefined) {
clearInterval($('#'+sId).data('timeout_validate'));
}
}
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
me.StopPendingRequest();
// Run the query and get the result back directly in JSON
me.ajax_request = $.post(AddAppContext(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php'), theMap,
function (data) {
$('#fstatus_'+me.id).html('');
if (data.id == 0) {
$('#label_'+me.id).removeClass('ac_dlg_loading');
CombodoModal.OpenErrorModal(data.error);
} else if (me.bSelectMode) {
// Add the newly created object to the drop-down list and select it
/*$('', { value : data.id }).html(data.name).appendTo('#'+me.id);
$('#'+me.id+' option[value="'+data.id+'"]').attr('selected', 'selected');
$('#'+me.id).focus();*/
var select = $('#'+me.id)[0].selectize;
select.addOption({label: data.name, value: data.id});
select.setValue(data.id);
} else {
// Put the value corresponding to the newly created object in the autocomplete
var oTemp = $('
');
} else {
$('#label_'+me.id).addClass('ac_dlg_loading');
}
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'] = me.sTargetClass;
theMap.operation = 'displayHierarchy';
// 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) {
$('#ac_tree_'+me.id).html(data);
var maxHeight = $(window).height()-110;
$('#tree_'+me.id).css({maxHeight: maxHeight});
},
'html'
);
};
this.OnHKResize = function (event, ui) {
var dh = ui.size.height-ui.originalSize.height;
if (dh != 0) {
var dlg_content = $('#dlg_tree_'+me.id+' .wizContainer');
var h = dlg_content.height();
dlg_content.height(h+dh);
var tree = $('#tree_'+me.id);
var h = tree.height();
tree.height(h+dh-1);
}
};
this.OnHKClose = function () {
if (me.bSelectMode) {
$('#fstatus_'+me.id).html('');
} else {
$('#label_'+me.id).removeClass('ac_dlg_loading');
}
$('#label_'+me.id).focus();
$('#dlg_tree_'+me.id).dialog("destroy");
$('#dlg_tree_'+me.id).remove();
};
this.DoHKOk = function () {
iObjectId = $('#tree_'+me.id+' input[name=selectObject]:checked').val();
$('#dlg_tree_'+me.id).dialog('close');
// Query the server again to get the display name of the selected object
var theMap = {
sTargetClass: me.sTargetClass,
iInputId: me.id,
iObjectId: iObjectId,
sAttCode: me.sAttCode,
bSearchMode: me.bSearchMode,
operation: 'getObjectName'
};
// Make sure that we cancel any pending request before issuing another
// since responses may arrive in arbitrary order
me.StopPendingRequest();
if ($('#label_'+me.id).size() == 0) {
var prevValue = $('#'+me.id)[0].selectize.getValue();
$('#'+me.id)[0].selectize.setValue(iObjectId);
} else {
// Run the query and get the result back directly in JSON
me.ajax_request = $.post(AddAppContext(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php'), theMap,
function (data) {
var oTemp = $('