mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-23 02:28:44 +02:00
Advanced search: More criteria UX WIP.
SVN:b1162[5510]
This commit is contained in:
@@ -718,6 +718,7 @@ input.dp-applied {
|
||||
/* Sizing reset */
|
||||
/* Hyperlink reset */
|
||||
/* Input reset */
|
||||
/* List helpers */
|
||||
}
|
||||
.search_form_handler * {
|
||||
box-sizing: border-box;
|
||||
@@ -897,24 +898,6 @@ input.dp-applied {
|
||||
margin-left: 0px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_form_group .sfc_fg_operators .sfc_fg_operator .sfc_opc_multichoices .sfc_opc_mc_filter {
|
||||
position: relative;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_form_group .sfc_fg_operators .sfc_fg_operator .sfc_opc_multichoices .sfc_opc_mc_filter input {
|
||||
width: 100%;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_form_group .sfc_fg_operators .sfc_fg_operator .sfc_opc_multichoices .sfc_opc_mc_filter .sfc_opc_mcf_picto {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
opacity: 0.6;
|
||||
user-select: none;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_form_group .sfc_fg_operators .sfc_fg_operator .sfc_opc_multichoices .sfc_opc_mc_filter .sfc_opc_mc_reset {
|
||||
display: none;
|
||||
}
|
||||
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_form_group .sfc_fg_operators .sfc_fg_operator .sfc_opc_multichoices .sfc_opc_mc_items {
|
||||
max-height: 445px;
|
||||
/* Must be less than .sfc_form_group:max-height - .sfc_opc_mc_toggler:height - .sfc_opc_mc_filter:height */
|
||||
@@ -1049,6 +1032,50 @@ input.dp-applied {
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.search_form_handler .sf_list .sfl_title {
|
||||
font-weight: bold;
|
||||
}
|
||||
.search_form_handler .sf_list .sfl_items {
|
||||
margin: 5px -8px 0px -8px;
|
||||
padding: 0px;
|
||||
}
|
||||
.search_form_handler .sf_list .sfl_items > li {
|
||||
padding: 4px 8px;
|
||||
list-style: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.search_form_handler .sf_list .sfl_items > li:hover {
|
||||
background-color: #fff;
|
||||
}
|
||||
.search_form_handler .sf_list .sfl_items > li > label {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
.search_form_handler .sf_list .sfl_items > li > label > * {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.search_form_handler .sf_list .sfl_items > li > label > input[type="checkbox"] {
|
||||
margin-left: 0px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.search_form_handler .sf_filter {
|
||||
position: relative;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.search_form_handler .sf_filter input {
|
||||
width: 100%;
|
||||
}
|
||||
.search_form_handler .sf_filter .sff_picto {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
opacity: 0.6;
|
||||
user-select: none;
|
||||
}
|
||||
.search_form_handler .sf_filter .sff_reset {
|
||||
display: none;
|
||||
}
|
||||
.sf_results_area .sf_results_placeholder {
|
||||
margin-top: 100px;
|
||||
text-align: center;
|
||||
|
||||
@@ -1004,25 +1004,6 @@ input.dp-applied {
|
||||
}
|
||||
.sfc_opc_mc_toggler{
|
||||
|
||||
}
|
||||
.sfc_opc_mc_filter{
|
||||
position: relative;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
input{
|
||||
width: 100%;
|
||||
}
|
||||
.sfc_opc_mcf_picto{
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
opacity: 0.6;
|
||||
user-select: none;
|
||||
}
|
||||
.sfc_opc_mc_reset{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.sfc_opc_mc_items{
|
||||
max-height: 445px; /* Must be less than .sfc_form_group:max-height - .sfc_opc_mc_toggler:height - .sfc_opc_mc_filter:height */
|
||||
@@ -1223,6 +1204,60 @@ input.dp-applied {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* List helpers */
|
||||
.sf_list{
|
||||
.sfl_title{
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
.sfl_items{
|
||||
margin: 5px -8px 0px -8px;
|
||||
padding: 0px;
|
||||
|
||||
> li{
|
||||
padding: 4px 8px;
|
||||
list-style: none;
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover{
|
||||
background-color: $white;
|
||||
}
|
||||
|
||||
> label{
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
|
||||
> *{
|
||||
vertical-align: middle;
|
||||
}
|
||||
> input[type="checkbox"]{
|
||||
margin-left: 0px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.sf_filter{
|
||||
position: relative;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
input{
|
||||
width: 100%;
|
||||
}
|
||||
.sff_picto{
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
opacity: 0.6;
|
||||
user-select: none;
|
||||
}
|
||||
.sff_reset{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.sf_results_area{
|
||||
.sf_results_placeholder{
|
||||
|
||||
@@ -1386,6 +1386,11 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
// Search form
|
||||
'UI:Search:Toggle' => 'Minimize / Expand',
|
||||
'UI:Search:Criterion:MoreMenu:AddCriteria' => 'Add new criteria',
|
||||
// - Add new criteria button
|
||||
'UI:Search:AddCriteria:List:RecentlyUsed:Title' => 'Recently used',
|
||||
'UI:Search:AddCriteria:List:MostPopular:Title' => 'Most popular',
|
||||
'UI:Search:AddCriteria:List:Others:Title' => 'Others',
|
||||
|
||||
// - Criteria operators
|
||||
// - Default widget
|
||||
'UI:Search:Criteria:Operator:Default:Empty' => 'Is empty',
|
||||
@@ -1438,7 +1443,8 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
'UI:Search:Criteria:Title:Enum:In' => '%1$s: %2$s',
|
||||
'UI:Search:Criteria:Title:Enum:In:Many' => '%1$s: %2$s and %3$s others',
|
||||
'UI:Search:Criteria:Title:Enum:In:All' => '%1$s: Any',
|
||||
// -
|
||||
|
||||
// - Other translations
|
||||
'UI:Search:Value:Filter:Placeholder' => 'Filter...',
|
||||
'UI:Search:Value:Toggler:CheckAllNone' => 'Check all / none',
|
||||
|
||||
|
||||
@@ -95,8 +95,8 @@ $(function()
|
||||
|
||||
// - Filter
|
||||
var sFilterId = 'filter_' + sOpId;
|
||||
var oFilterElem = $('<div class="sfc_opc_mc_filter"></div>')
|
||||
.append('<input type="text" id="' + sFilterId + '" placeholder="' + Dict.S('UI:Search:Value:Filter:Placeholder') + '" /><span class="sfc_opc_mcf_picto sfc_opc_mcf_filter fa fa-filter"></span><span class="sfc_opc_mcf_picto sfc_opc_mcf_reset fa fa-times"></span>')
|
||||
var oFilterElem = $('<div class="sf_filter"></div>')
|
||||
.append('<input type="text" id="' + sFilterId + '" placeholder="' + Dict.S('UI:Search:Value:Filter:Placeholder') + '" /><span class="sff_picto sff_filter fa fa-filter"></span><span class="sff_picto sff_reset fa fa-times"></span>')
|
||||
.appendTo(oOpContentElem);
|
||||
|
||||
// - Allowed values
|
||||
@@ -108,11 +108,12 @@ $(function()
|
||||
// - It is not give by neither the autocomplete or the pre-filled values, so we would need to manually add it in both cases, all operations.
|
||||
if(this.options.field.is_null_allowed === true)
|
||||
{
|
||||
var sItemId = 'value_' + sOpId + '_null';
|
||||
var sValCode = this.options.null_value.code;
|
||||
var sValLabel = this.options.null_value.label;
|
||||
var oValueElem = $('<div class="sfc_opc_mc_item" data-value-code="' + sValCode + '"></div>')
|
||||
.append('<label for="' + sItemId + '"><input type="checkbox" id="' + sItemId + '" value="' + sValCode + '"/>' + sValLabel + '</label>')
|
||||
var oValueElem = $('<div></div>')
|
||||
.addClass('sfc_opc_mc_item')
|
||||
.attr('data-value-code', sValCode)
|
||||
.append('<label><input type="checkbox" value="' + sValCode + '"/>' + sValLabel + '</label>')
|
||||
.appendTo(oAllowedValuesElem);
|
||||
}
|
||||
|
||||
@@ -120,23 +121,20 @@ $(function()
|
||||
if(this.options.field.allowed_values.values !== undefined)
|
||||
{
|
||||
var aSortedValues = this._sortValuesByLabel(this.options.field.allowed_values.values);
|
||||
|
||||
var iValCounter = 0;
|
||||
for(var i in aSortedValues)
|
||||
{
|
||||
var sItemId = 'value_' + sOpId + '_' + iValCounter;
|
||||
var sValCode = aSortedValues[i][0];
|
||||
var sValLabel = aSortedValues[i][1];
|
||||
var oValueElem = $('<div class="sfc_opc_mc_item" data-value-code="' + sValCode + '"></div>')
|
||||
.append('<label for="' + sItemId + '"><input type="checkbox" id="' + sItemId + '" value="' + sValCode + '"/>' + sValLabel + '</label>')
|
||||
var oValueElem = $('<div></div>')
|
||||
.addClass('sfc_opc_mc_item')
|
||||
.attr('data-value-code', sValCode)
|
||||
.append('<label><input type="checkbox" value="' + sValCode + '"/>' + sValLabel + '</label>')
|
||||
.appendTo(oAllowedValuesElem);
|
||||
|
||||
if(this._isSelectedValues(sValCode))
|
||||
{
|
||||
oValueElem.find(':checkbox').prop('checked', true);
|
||||
}
|
||||
|
||||
iValCounter++;
|
||||
}
|
||||
}
|
||||
oAllowedValuesElem.appendTo(oOpContentElem);
|
||||
@@ -162,8 +160,8 @@ $(function()
|
||||
if(sFilter === '')
|
||||
{
|
||||
oOpContentElem.find('.sfc_opc_mc_item').show();
|
||||
oFilterElem.find('.sfc_opc_mcf_filter').show();
|
||||
oFilterElem.find('.sfc_opc_mcf_reset').hide();
|
||||
oFilterElem.find('.sff_filter').show();
|
||||
oFilterElem.find('.sff_reset').hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -181,14 +179,14 @@ $(function()
|
||||
$(this).hide();
|
||||
}
|
||||
});
|
||||
oFilterElem.find('.sfc_opc_mcf_filter').hide();
|
||||
oFilterElem.find('.sfc_opc_mcf_reset').show();
|
||||
oFilterElem.find('.sff_filter').hide();
|
||||
oFilterElem.find('.sff_reset').show();
|
||||
}
|
||||
});
|
||||
oFilterElem.find('.sfc_opc_mcf_filter').on('click', function(){
|
||||
oFilterElem.find('.sff_filter').on('click', function(){
|
||||
oFilterElem.find('input').trigger('focus');
|
||||
});
|
||||
oFilterElem.find('.sfc_opc_mcf_reset').on('click', function(){
|
||||
oFilterElem.find('.sff_reset').on('click', function(){
|
||||
oFilterElem.find('input')
|
||||
.val('')
|
||||
.trigger('focus');
|
||||
|
||||
@@ -11,6 +11,7 @@ $(function()
|
||||
{
|
||||
// Null value
|
||||
'null_value': {
|
||||
'code': 0,
|
||||
'label': Dict.S('UI:UndefinedObject'),
|
||||
}
|
||||
},
|
||||
|
||||
@@ -298,36 +298,57 @@ $(function()
|
||||
var oContentElem = $('<div class="sfm_content"></div>')
|
||||
.appendTo(this.elements.more_criterion);
|
||||
|
||||
// - Add list
|
||||
var oListElem = $('<ul class="sfm_list"></ul>')
|
||||
// - Filter
|
||||
var oFilterElem = $('<div class="sf_filter"></div>')
|
||||
.append('<input type="text" placeholder="' + Dict.S('UI:Search:Value:Filter:Placeholder') + '" /><span class="sff_picto sff_filter fa fa-filter"></span><span class="sff_picto sff_reset fa fa-times"></span>')
|
||||
.appendTo(oContentElem);
|
||||
// - Add fields
|
||||
// TODO: Find a widget to handle dropdown menu
|
||||
// - From "search" zlist
|
||||
|
||||
// - Add fields from zlist list
|
||||
var oZlistElem = $('<div></div>')
|
||||
.addClass('sf_list')
|
||||
.addClass('sf_list_zlist')
|
||||
.appendTo(oContentElem);
|
||||
|
||||
$('<div class="sfl_title"></div>')
|
||||
.text(Dict.S('UI:Search:AddCriteria:List:MostPopular:Title'))
|
||||
.appendTo(oZlistElem);
|
||||
|
||||
var oZListItemsElem = $('<ul class="sfl_items"></ul>')
|
||||
.appendTo(oZlistElem);
|
||||
|
||||
for(var sFieldRef in this.options.search.fields.zlist)
|
||||
{
|
||||
var oField = this.options.search.fields.zlist[sFieldRef];
|
||||
var oFieldElem = $('<li></li>')
|
||||
.addClass('sfm_field')
|
||||
.attr('data-field-ref', sFieldRef)
|
||||
.text(oField.label);
|
||||
oListElem.append(oFieldElem);
|
||||
.append('<label><input type="checkbox" value="' + sFieldRef + '" />' + oField.label + '</label>')
|
||||
.appendTo(oZListItemsElem);
|
||||
}
|
||||
|
||||
// - Others
|
||||
// - Add fields remaining
|
||||
if(this.options.search.fields.others !== undefined)
|
||||
{
|
||||
oListElem.append('<li>==================</li>');
|
||||
oListElem.append('<li>|| TODO: Better separation ||</li>');
|
||||
oListElem.append('<li>==================</li>');
|
||||
var oOthersElem = $('<div></div>')
|
||||
.addClass('sf_list')
|
||||
.addClass('sf_list_others')
|
||||
.appendTo(oContentElem);
|
||||
|
||||
$('<div class="sfl_title"></div>')
|
||||
.text(Dict.S('UI:Search:AddCriteria:List:Others:Title'))
|
||||
.appendTo(oOthersElem);
|
||||
|
||||
var oOthersItemsElem = $('<ul class="sfl_items"></ul>')
|
||||
.appendTo(oOthersElem);
|
||||
|
||||
for(var sFieldRef in this.options.search.fields.others)
|
||||
{
|
||||
var oField = this.options.search.fields.others[sFieldRef];
|
||||
var oFieldElem = $('<li></li>')
|
||||
.addClass('sfm_field')
|
||||
.attr('data-field-ref', sFieldRef)
|
||||
.text(oField.label);
|
||||
oListElem.append(oFieldElem);
|
||||
.append('<label><input type="checkbox" value="' + sFieldRef + '" />' + oField.label + '</label>')
|
||||
.appendTo(oOthersItemsElem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,10 +368,11 @@ $(function()
|
||||
}
|
||||
else
|
||||
{
|
||||
//if using the datetimepicker, do not close anything
|
||||
// TODO: Try to put this back in the date widget as it introduced a non necessary coupling.
|
||||
// If using the datetimepicker, do not close anything
|
||||
if (oEventTargetElem.closest('#ui-datepicker-div, .ui-datepicker-prev, .ui-datepicker-next').length > 0 )
|
||||
{
|
||||
//no closing in this case
|
||||
// No closing in this case
|
||||
}
|
||||
// //if the context is not document, then we have encountered a bug : the css ::after elements do have a context on click and thus, we cannot check if they are inside a #ui-datepicker-div
|
||||
// else if (typeof oEventTargetElem.context != 'undefined' && $(oEventTargetElem.context).is('.ui-icon'))
|
||||
@@ -377,6 +399,47 @@ $(function()
|
||||
|
||||
me._toggleMoreCriterion();
|
||||
});
|
||||
// - Filter
|
||||
// Note: "keyup" event is use instead of "keydown", otherwise, the inpu value would not be set yet.
|
||||
oFilterElem.find('input').on('keyup focus', function(oEvent){
|
||||
// TODO: Move on values with up and down arrow keys; select with space or enter.
|
||||
|
||||
var sFilter = $(this).val();
|
||||
|
||||
if(sFilter === '')
|
||||
{
|
||||
oContentElem.find('.sfl_items > li').show();
|
||||
oFilterElem.find('.sff_filter').show();
|
||||
oFilterElem.find('.sff_reset').hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
oContentElem.find('.sfl_items > li').each(function(){
|
||||
var oRegExp = new RegExp(sFilter, 'ig');
|
||||
var sValue = $(this).find('input').val();
|
||||
var sLabel = $(this).text();
|
||||
|
||||
if( (sValue.match(oRegExp) !== null) || (sLabel.match(oRegExp) !== null) )
|
||||
{
|
||||
$(this).show();
|
||||
}
|
||||
else
|
||||
{
|
||||
$(this).hide();
|
||||
}
|
||||
});
|
||||
oFilterElem.find('.sff_filter').hide();
|
||||
oFilterElem.find('.sff_reset').show();
|
||||
}
|
||||
});
|
||||
oFilterElem.find('.sff_filter').on('click', function(){
|
||||
oFilterElem.find('input').trigger('focus');
|
||||
});
|
||||
oFilterElem.find('.sff_reset').on('click', function(){
|
||||
oFilterElem.find('input')
|
||||
.val('')
|
||||
.trigger('focus');
|
||||
});
|
||||
// - Add criteria
|
||||
this.elements.more_criterion.find('.sfm_field').on('click', function(oEvent){
|
||||
// Prevent anchor
|
||||
|
||||
Reference in New Issue
Block a user