mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-20 07:42:17 +02:00
Improved autocomplete field display
This commit is contained in:
204
pages/audit.php
204
pages/audit.php
@@ -162,8 +162,8 @@ function MakeSelectField($oPage, string $sLabel, string $sFieldName, string $sOq
|
||||
$iMaxComboLength = MetaModel::GetConfig()->Get('max_combo_length');
|
||||
|
||||
$bIsAutocomplete = $oAllowedValues->CountExceeds($iMaxComboLength);
|
||||
$sWrapperCssClass = $bIsAutocomplete ? 'ibo-input-select-autocomplete-wrapper' : 'ibo-input-select-wrapper';
|
||||
$sHTMLValue = "<div class=\"field_input_zone\">";
|
||||
$sWrapperCssClass = $bIsAutocomplete ? 'field_input_extkey ibo-input-wrapper ibo-input-select-wrapper--with-buttons ibo-input-select-autocomplete-wrapper' : 'ibo-input-select-wrapper';
|
||||
$sHTMLValue = "<div class=\"field_input_zone $sWrapperCssClass\">";
|
||||
|
||||
// We just need to compare the number of entries with MaxComboLength, so no need to get the real count.
|
||||
if (!$bIsAutocomplete) {
|
||||
@@ -263,210 +263,34 @@ JS
|
||||
// another hidden input to store & pass the object's Id
|
||||
$sHTMLValue .= "<input type=\"hidden\" id=\"$sFieldName\" name=\"{$sFieldName}\" value=\"".utils::HtmlEntities($sCurrentValue)."\" />\n";
|
||||
|
||||
// Scripts to start the autocomplete and bind some events to it
|
||||
$sMessage = Dict::S('UI:Message:EmptyList:UseSearchForm');
|
||||
$oPage->add_ready_script(
|
||||
<<<JS
|
||||
|
||||
var hasFocus = 0;
|
||||
var cache = {};
|
||||
$('#label_$sFieldName').data('selected_value', $('#label_$sFieldName').val());
|
||||
$('#label_$sFieldName').attr('title', $('#label_$sFieldName').val());
|
||||
$('#label_$sFieldName').autocomplete({
|
||||
source: function (request, response) {
|
||||
term = request.term.toLowerCase().latinise().replace(/[\u0300-\u036f]/g, "");
|
||||
|
||||
if (term in cache) {
|
||||
response(cache[term]);
|
||||
return;
|
||||
}
|
||||
if (term.indexOf(this.previous) >= 0 && cache[this.previous] != null && cache[this.previous].length < 120) {
|
||||
//we have already all the possibility in cache
|
||||
var data = [];
|
||||
$.each(cache[this.previous], function (key, value) {
|
||||
if (value.label.toLowerCase().latinise().replace(/[\u0300-\u036f]/g, "").indexOf(term) >= 0) {
|
||||
data.push(value);
|
||||
}
|
||||
});
|
||||
cache[term] = data;
|
||||
response(data);
|
||||
} else {
|
||||
$.post({
|
||||
url: GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
|
||||
dataType: "json",
|
||||
data: {
|
||||
q: request.term,
|
||||
operation: 'ac_extkey',
|
||||
sTargetClass: '$sClass',
|
||||
sFilter: '$sOql',
|
||||
bSearchMode: true,
|
||||
sOutputFormat: 'json',
|
||||
json: function () {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
success: function (data) {
|
||||
cache[term] = data;
|
||||
response(data);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
autoFocus: true,
|
||||
minLength: $iMinChars,
|
||||
focus: function (event, ui) {
|
||||
return false;
|
||||
},
|
||||
select: function (event, ui) {
|
||||
$('#$sFieldName').val(ui.item.value);
|
||||
let labelValue = $('<div>').html(ui.item.label).text();
|
||||
$('#label_$sFieldName').val(labelValue);
|
||||
$('#label_$sFieldName').data('selected_value', labelValue);
|
||||
$('#label_$sFieldName').attr('title',labelValue);
|
||||
return false;
|
||||
},
|
||||
open: function (event, ui) {
|
||||
// dialog tries to move above every .ui-front with _moveToTop(), we want to be above our parent dialog
|
||||
var dialog = $(this).closest('.ui-dialog');
|
||||
if (dialog.length > 0) {
|
||||
$('.ui-autocomplete.ui-front').css('z-index', parseInt(dialog.css("z-index"))+1);
|
||||
}
|
||||
// UpdateDropdownPosition = function (oControlElem, oDropdownElem) {
|
||||
// First fix width to ensure it's not too long
|
||||
const fControlWidth = $(this).outerWidth();
|
||||
$('.ui-autocomplete.selectize-dropdown:visible').css('width', fControlWidth);
|
||||
|
||||
// Then, fix height / position to ensure it's within the viewport
|
||||
const fWindowHeight = window.innerHeight;
|
||||
|
||||
const fControlTopY = $(this).offset().top;
|
||||
const fControlHeight = $(this).outerHeight();
|
||||
|
||||
const fDropdownTopY = $('.ui-autocomplete.selectize-dropdown:visible').offset().top;
|
||||
// This one is "let" as it might be updated if necessary
|
||||
let fDropdownHeight = $('.ui-autocomplete.selectize-dropdown:visible').outerHeight();
|
||||
const fDropdownBottomY = fDropdownTopY + fDropdownHeight;
|
||||
|
||||
if (fDropdownBottomY > fWindowHeight) {
|
||||
// Set dropdown max-height to 1/3 of the screen, this way we are sure the dropdown will fit in either the top / bottom half of the screen
|
||||
$('.ui-autocomplete.selectize-dropdown:visible').css('max-height', '30vh');
|
||||
fDropdownHeight = $('.ui-autocomplete.selectize-dropdown:visible').outerHeight();
|
||||
|
||||
// Position dropdown above input if not enough space on the bottom part of the screen
|
||||
if ((fDropdownTopY / fWindowHeight) > 0.6) {
|
||||
$('.ui-autocomplete.selectize-dropdown:visible').css('top', fDropdownTopY - fDropdownHeight - fControlHeight);
|
||||
}
|
||||
}
|
||||
// this.ManageScroll = function () {
|
||||
if ($('#label_$sFieldName').scrollParent()[0].tagName != 'HTML') {
|
||||
$('#label_$sFieldName').scrollParent().on(['scroll.$sFieldName', 'resize.$sFieldName'].join(" "), function () {
|
||||
setTimeout(function () {
|
||||
me.ManageScrollInElement();
|
||||
}, 50);
|
||||
});
|
||||
if ($('#label_$sFieldName').scrollParent().scrollParent()[0].tagName != 'HTML') {
|
||||
$('#label_$sFieldName').scrollParent().scrollParent().on(['scroll.$sFieldName', 'resize.$sFieldName'].join(" "), function () {
|
||||
setTimeout(function () {
|
||||
me.ManageScrollInElement();
|
||||
}, 50);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
close: function (event, ui) {
|
||||
if ($('#label_$sFieldName').scrollParent()[0].tagName != 'HTML') {
|
||||
$('#label_$sFieldName').scrollParent().off('scroll.$sFieldName');
|
||||
$('#label_$sFieldName').scrollParent().off('resize.$sFieldName');
|
||||
if ($('#label_$sFieldName').scrollParent().scrollParent()[0].tagName != 'HTML') {
|
||||
$('#label_$sFieldName').scrollParent().scrollParent().off('scroll.$sFieldName');
|
||||
$('#label_$sFieldName').scrollParent().scrollParent().off('resize.$sFieldName');
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.autocomplete("instance")._renderItem = function (ul, item) {
|
||||
$(ul).addClass('selectize-dropdown');
|
||||
let term = this.term.replace("/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi", "\\$1");
|
||||
let val = '';
|
||||
if (item.initials != undefined) {
|
||||
if (item.picture_url != undefined) {
|
||||
val = '<span class="ibo-input-select--autocomplete-item-image" style="background-image: url('+item.picture_url+');">'+item.initials+'</span>';
|
||||
} else {
|
||||
val = '<span class="ibo-input-select--autocomplete-item-image");">'+item.initials+'</span>';
|
||||
}
|
||||
}
|
||||
val = val+'<div class="ibo-input-select--autocomplete-item-txt" title="'+item.label+'">';
|
||||
if (item.obsolescence_flag == '1') {
|
||||
val = val+' <span class="object-ref-icon text_decoration"><span class="fas fa-eye-slash object-obsolete fa-1x fa-fw"></span></span>';
|
||||
}
|
||||
let labelValue = item.label.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)("+term+")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
|
||||
val = val+labelValue;
|
||||
if (item.additional_field != undefined) {
|
||||
val = val+'<br><i>'+item.additional_field+'</i>';
|
||||
}
|
||||
val = val+'</div>';
|
||||
return $("<li>")
|
||||
.append("<div data-selectable=\"\" class=\"ibo-input-select--autocomplete-item\">"+val+"</div>")
|
||||
.appendTo(ul);
|
||||
};
|
||||
|
||||
$('#label_$sFieldName').on('focus', function () {
|
||||
// track whether the field has focus, we shouldn't process any
|
||||
// results if the field no longer has focus
|
||||
hasFocus++;
|
||||
}).on('blur', function () {
|
||||
hasFocus = 0;
|
||||
if ($('#label_$sFieldName').val().length == 0) {
|
||||
$('#$sFieldName').val('');
|
||||
$('#label_$sFieldName').val('');
|
||||
$('#label_$sFieldName').data('selected_value', '');
|
||||
} else {
|
||||
$('#label_$sFieldName').val($('#label_$sFieldName').data('selected_value'));
|
||||
}
|
||||
}).on('click',
|
||||
function () {
|
||||
hasFocus++;
|
||||
$('#label_$sFieldName').autocomplete("search");
|
||||
}).on('keyup',function () {
|
||||
if ($('#label_$sFieldName').val().length == 0) {
|
||||
if (!$('#label_$sFieldName').parent().find('.ibo-input-select--action-button--clear').hasClass('ibo-is-hidden')) {
|
||||
$('#label_$sFieldName').parent().find('.ibo-input-select--action-button--clear').addClass('ibo-is-hidden');
|
||||
}
|
||||
} else {
|
||||
if ($('#label_$sFieldName').parent().find('.ibo-input-select--action-button--clear').hasClass('ibo-is-hidden')) {
|
||||
$('#label_$sFieldName').parent().find('.ibo-input-select--action-button--clear').removeClass('ibo-is-hidden');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var iPaddingRight = $('#$sFieldName').parent().find('.ibo-input-select--action-buttons')[0].childElementCount * 20+15;
|
||||
$('#$sFieldName').parent().find('.ibo-input-select').css('padding-right', iPaddingRight);
|
||||
|
||||
|
||||
|
||||
<<<EOF
|
||||
oACWidget_{$sFieldName} = new ExtKeyWidget('$sFieldName', '$sClass', '$sOql', '$sLabel', false, null, '{$sFieldName}', true, false);
|
||||
oACWidget_{$sFieldName}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
|
||||
oACWidget_{$sFieldName}.AddAutocomplete($iMinChars, '');
|
||||
if ($('#ac_dlg_{$sFieldName}').length == 0)
|
||||
{
|
||||
$('body').append('<div id="ac_dlg_{$sFieldName}"></div>');
|
||||
}
|
||||
JS
|
||||
EOF
|
||||
);
|
||||
$sHTMLValue .= "<div class=\"ibo-input-select--action-buttons\">";
|
||||
$sHTMLValue .= "<a href=\"#\" class=\"ibo-input-select--action-button ibo-input-select--action-button--clear ibo-is-hidden\" id=\"mini_clear_{$sFieldName}\" onClick=\"$('#$sFieldName').val('');$('#label_$sFieldName').val(''); $('#label_$sFieldName').data('selected_value', '');\" data-tooltip-content='".Dict::S('UI:Button:Clear')."'><i class=\"fas fa-times\"></i></a>";
|
||||
}
|
||||
/* if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false) {
|
||||
$sHTMLValue .= "<a href=\"#\" class=\"ibo-input-select--action-button ibo-input-select--action-button--hierarchy\" id=\"mini_tree_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\" data-tooltip-content='".Dict::S('UI:Button:SearchInHierarchy')."'><i class=\"fas fa-sitemap\"></i></a>";
|
||||
$sHTMLValue .= "<a href=\"#\" class=\"ibo-input-select--action-button ibo-input-select--action-button--search\" id=\"mini_search_{$sFieldName}\" onClick=\"oACWidget_{$sFieldName}.Search();\" data-tooltip-content='".Dict::S('UI:Button:Search')."'><i class=\"fas fa-search\"></i></a>";
|
||||
if (MetaModel::IsHierarchicalClass($sClass) !== false) {
|
||||
$sHTMLValue .= "<a href=\"#\" class=\"ibo-input-select--action-button ibo-input-select--action-button--hierarchy\" id=\"mini_tree_{$sFieldName}\" onClick=\"oACWidget_{$sFieldName}.HKDisplay();\" data-tooltip-content='".Dict::S('UI:Button:SearchInHierarchy')."'><i class=\"fas fa-sitemap\"></i></a>";
|
||||
$oPage->add_ready_script(
|
||||
<<<JS
|
||||
if ($('#ac_tree_{$sFieldName}').length == 0)
|
||||
{
|
||||
$('body').append('<div id="ac_tree_{$sFieldName}"></div>');
|
||||
}
|
||||
JS
|
||||
JS
|
||||
);
|
||||
}
|
||||
if ($oAllowedValues->CountExceeds($iMaxComboLength)) {
|
||||
$sHTMLValue .= " <a href=\"#\" class=\"ibo-input-select--action-button ibo-input-select--action-button--search\" id=\"mini_search_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.Search();\" data-tooltip-content='".Dict::S('UI:Button:Search')."'><i class=\"fas fa-search\"></i></a>";
|
||||
}*/
|
||||
}
|
||||
|
||||
$sHTMLValue .= "</div>";
|
||||
$sHTMLValue .= "</div>";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user