Advanced search: UI/UX WIP.

SVN:b1162[5559]
This commit is contained in:
Guillaume Lajarige
2018-03-28 19:38:08 +00:00
parent f3a2a24ee4
commit 14c0733949
8 changed files with 258 additions and 64 deletions

View File

@@ -852,19 +852,24 @@ input.dp-applied {
background-color: #eee;
color: #2d2d2d;
}
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_close, .search_form_handler .sf_criterion_area .search_form_criteria .sfc_toggle {
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_toggle, .search_form_handler .sf_criterion_area .search_form_criteria .sfc_close {
position: absolute;
top: 7px;
color: #e87c1e;
}
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_close {
right: 7px;
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_locked {
position: absolute;
top: 9px;
color: #808080;
}
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_toggle {
display: inline-block;
right: 23px;
transition: all 0.3s ease-in-out;
}
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_close, .search_form_handler .sf_criterion_area .search_form_criteria .sfc_locked {
right: 7px;
}
.search_form_handler .sf_criterion_area .search_form_criteria .sfc_title {
max-width: 240px;
padding-right: 30px;
@@ -997,6 +1002,8 @@ input.dp-applied {
}
.search_form_handler .sf_criterion_area .search_form_criteria.search_form_criteria_raw .sfc_title {
cursor: initial;
padding-right: 20px;
/* Less than regular as there is no toggle icon */
}
.search_form_handler .sf_criterion_area .search_form_criteria.search_form_criteria_raw .sfc_form_group {
display: none;
@@ -1139,19 +1146,47 @@ input.dp-applied {
margin-top: 8px;
margin-bottom: 8px;
}
.search_form_handler .sf_filter input, .search_form_handler .sf_filter button, .search_form_handler .sf_filter .sff_picto {
vertical-align: middle;
height: 22px;
}
.search_form_handler .sf_filter input, .search_form_handler .sf_filter button {
border: 1px solid #ababab;
}
.search_form_handler .sf_filter input {
width: 100%;
}
.search_form_handler .sf_filter .sff_picto {
.search_form_handler .sf_filter button {
width: 23px;
/* Must be equals to .sf_filter > *:height */
background-color: #fff;
color: #ea7d1e;
font-size: 10px;
}
.search_form_handler .sf_filter button:first-of-type {
margin-left: 5px;
}
.search_form_handler .sf_filter button:not(:first-of-type) {
border-left: transparent;
}
.search_form_handler .sf_filter .sff_input_wrapper {
position: relative;
}
.search_form_handler .sf_filter .sff_input_wrapper .sff_picto {
position: absolute;
right: 5px;
top: 5px;
top: 2px;
opacity: 0.6;
user-select: none;
}
.search_form_handler .sf_filter .sff_reset {
.search_form_handler .sf_filter .sff_input_wrapper .sff_reset {
display: none;
}
.search_form_handler .sf_filter.sf_with_buttons input {
width: initial;
/* Reset the 100% */
min-width: 120px;
}
.sf_results_area .sf_results_placeholder {
margin-top: 100px;
text-align: center;

View File

@@ -953,20 +953,26 @@ input.dp-applied {
}
/* Top left corner icons */
.sfc_close,
.sfc_toggle{
.sfc_toggle,
.sfc_close{
position: absolute;
top: 7px;
color: $search-criteria-box-picto-color;
}
.sfc_close{
right: 7px;
.sfc_locked{
position: absolute;
top: 9px;
color: $gray-light;
}
.sfc_toggle{
display: inline-block;
right: 23px;
transition: all 0.3s ease-in-out;
}
.sfc_close,
.sfc_locked{
right: 7px;
}
.sfc_title{
max-width: 240px;
@@ -1142,6 +1148,7 @@ input.dp-applied {
}
.sfc_title{
cursor: initial;
padding-right: 20px; /* Less than regular as there is no toggle icon */
}
.sfc_form_group{
display: none;
@@ -1204,7 +1211,8 @@ input.dp-applied {
}
}
&.search_form_criteria_date_time, &.search_form_criteria_date {
&.search_form_criteria_date_time,
&.search_form_criteria_date {
.sfc_form_group.advanced {
.sfc_fg_operator_between {
margin-bottom: 5px;
@@ -1353,18 +1361,53 @@ input.dp-applied {
margin-top: 8px;
margin-bottom: 8px;
input,
button,
.sff_picto{
vertical-align: middle;
height: 22px;
}
input,
button{
border: 1px solid #ABABAB;
}
input{
width: 100%;
}
.sff_picto{
position: absolute;
right: 5px;
top: 5px;
opacity: 0.6;
user-select: none;
button{
width: 23px; /* Must be equals to .sf_filter > *:height */
background-color: $white;
color: $combodo-orange;
font-size: 10px;
&:first-of-type{
margin-left: 5px;
}
&:not(:first-of-type){
border-left: transparent;
}
}
.sff_reset{
display: none;
.sff_input_wrapper{
position: relative;
.sff_picto{
position: absolute;
right: 5px;
top: 2px;
opacity: 0.6;
user-select: none;
}
.sff_reset{
display: none;
}
}
&.sf_with_buttons{
input{
width: initial; /* Reset the 100% */
min-width: 120px;
}
}
}
}

View File

@@ -1453,6 +1453,7 @@ When associated with a trigger, each action is given an "order" number, specifyi
// - Other translations
'UI:Search:Value:Filter:Placeholder' => 'Filter...',
'UI:Search:Value:Search:Placeholder' => 'Search...',
'UI:Search:Value:Toggler:CheckAllNone' => 'Check all / none',
// - Widget other translations

View File

@@ -595,7 +595,7 @@ $(function()
// Values helpers
// - Check if criteria has allowed values
// - Check if criteria has allowed values either preloaded or through autocomplete
_hasAllowedValues: function()
{
return ( (this.options.field.allowed_values !== undefined) && (this.options.field.allowed_values !== null) );
@@ -615,6 +615,21 @@ $(function()
{
return (this._hasPreloadedAllowedValues()) ? this.options.field.allowed_values.values : {};
},
// - Check if criteria has allowed values that should be loaded through autocomplete
_hasAutocompleteAllowedValues: function()
{
if(this._hasAllowedValues() && (this.options.field.allowed_values.autocomplete === true) )
{
return true;
}
return false;
},
// - Return the allowed values from the autocomplete
_getAutocompleteAllowedValues: function()
{
console.log('TODO: Retrieve allowed values through autocomplete (get needle in the input)');
},
// - Return current values
_getValues: function()
{

View File

@@ -95,12 +95,20 @@ $(function()
// - Filter
var sFilterId = 'filter_' + sOpId;
var sFilterPlaceholder = (this._hasAutocompleteAllowedValues()) ? Dict.S('UI:Search:Value:Search:Placeholder') : Dict.S('UI:Search:Value:Filter:Placeholder');
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>')
.append('<span class="sff_input_wrapper"><input type="text" id="' + sFilterId + '" placeholder="' + sFilterPlaceholder + '" /><span class="sff_picto sff_filter fa fa-filter"></span><span class="sff_picto sff_reset fa fa-times"></span></span>')
.appendTo(oOpContentElem);
// - Allowed values
var oAllowedValuesElem = $('<div class="sfc_opc_mc_items"></div>');
var oAllowedValuesElem = $('<div class="sfc_opc_mc_items"></div>')
.appendTo(oOpContentElem);
// - Static values: Always there no matter the field constraints
var oStaticValuesElem = $('<div class="sfc_opc_mc_items_list sfc_opc_mc_items_static"></div>')
.appendTo(oAllowedValuesElem);
// - Dynamic values: Depends on the field constraints
var oDynamicValuesElem = $('<div class="sfc_opc_mc_items_list sfc_opc_mc_items_dynamic"></div>')
.appendTo(oAllowedValuesElem);
// - Null value if allowed
// Note: null values is NOT put among the allowed values for two reasons:
@@ -114,7 +122,7 @@ $(function()
.addClass('sfc_opc_mc_item')
.attr('data-value-code', sValCode)
.append('<label><input type="checkbox" value="' + sValCode + '"/>' + sValLabel + '</label>')
.appendTo(oAllowedValuesElem);
.appendTo(oStaticValuesElem);
}
// - Regular allowed values
@@ -129,7 +137,7 @@ $(function()
.addClass('sfc_opc_mc_item')
.attr('data-value-code', sValCode)
.append('<label><input type="checkbox" value="'+sValCode+'"/>'+sValLabel+'</label>')
.appendTo(oAllowedValuesElem);
.appendTo(oDynamicValuesElem);
if (this._isSelectedValues(sValCode))
{
@@ -137,7 +145,20 @@ $(function()
}
}
}
oAllowedValuesElem.appendTo(oOpContentElem);
// - Specific to autocomplete mode
if(this._hasAutocompleteAllowedValues())
{
// Remove filter picto from input
oFilterElem.find('.sff_filter').remove();
// Add search dialog button
oFilterElem
.append('<button type="button" class="sff_search_dialog"><span class=" fa fa-search"></span></button>')
.addClass('sf_with_buttons');
// Prepare "selected" values area
}
// Events
// - Check / Uncheck all toggler
@@ -151,7 +172,7 @@ $(function()
});
// - Filter
// Note: "keyup" event is use instead of "keydown", otherwise, the inpu value would not be set yet.
// Note: "keyup" event is use instead of "keydown", otherwise, the input 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.
@@ -204,6 +225,56 @@ $(function()
me._apply();
});
// - Specific to autocomplete mode
// TODO: We NEED to refactor all of this for a better integration. Most might be in the main widget as any widget could use XHR helpers.
if(this._hasAutocompleteAllowedValues())
{
// // Autocomplete
// var oACXHR = null;
// var oACTimeout = null;
// oFilterElem.find('input').off('keyup focus').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 === '')
// {
// oOpContentElem.find('.sfc_opc_mc_item').html('');
// oFilterElem.find('.sff_reset').hide();
// }
// else
// {
// oOpContentElem.find('.sfc_opc_mc_item').html('TOTR: Wait');
// if(oACXHR !== null)
// {
// oACXHR.abort();
// }
// oACXHR = $.post(
// AddAppContext(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php'),
// {
// sTargetClass: me.options.field.class,
// //iInputId: me.id,
// //iObjectId: iObjectId,
// sAttCode: me.options.field.code,
// bSearchMode: true,
// operation: 'getObjectName'
// }
// )
// .done(function(oResponse, sStatus, oXHR){ console.log('ok', oResponse); })
// .fail(function(oResponse, sStatus, oXHR){ console.log('fail', oResponse); })
// .always(function(oResponse, sStatus, oXHR){ console.log('always', oResponse); });
//
// oFilterElem.find('.sff_reset').show();
// }
// });
//
// // Open search dialog
// oFilterElem.find('.sff_search_dialog').on('click', function(){
// // TODO: Open search dialog with right params
// alert('Not implemented yet');
// });
}
oOpElem.find('.sfc_op_content').append(oOpContentElem);
},
_setTitle: function(sTitle)

View File

@@ -9,11 +9,13 @@ $(function()
// default options
options:
{
'endpoint': AddAppContext(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php'),
// Null value
'null_value': {
'code': 0,
'label': Dict.S('UI:UndefinedObject'),
}
},
},
@@ -52,6 +54,5 @@ $(function()
//------------------
// Inherited methods
//------------------
});
});

View File

@@ -48,5 +48,25 @@ $(function()
// Inherited methods
//------------------
// DOM element helpers
prepareInOperator: function(oOpElem, sOpIdx, oOp)
{
var me = this;
this._super();
// DOM elements
// - Add search dialog button
this.element.find('.sf_filter')
.append('<button type="button" class="sff_hierarchy_dialog"><span class=" fa fa-sitemap"></span></button>')
.addClass('sf_with_buttons');
// Events
// - Open hierarchy dialog
this.element.find('.sff_hierarchy_dialog').on('click', function(){
// TODO: Open hierarchy dialog with right params
alert('Not implemented yet');
});
},
});
});

View File

@@ -319,7 +319,7 @@ $(function()
var oFilterElem = $('<div></div>')
.addClass('sf_filter')
.addClass('sfm_filter')
.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>')
.append('<span class="sff_input_wrapper"><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></span>')
.appendTo(oContentElem);
// - Lists container
@@ -618,46 +618,54 @@ $(function()
_addCriteria: function(oData)
{
var sRef = oData.ref;
var sType = (oData.widget !== undefined) ? oData.widget : this._getCriteriaTypeFromFieldRef(sRef);
var sType = sType = (oData.widget !== undefined) ? oData.widget : this._getCriteriaTypeFromFieldRef(sRef);
if(sType !== null)
// Force to raw for non removable criteria
if( (oData.is_removable !== undefined) && (oData.is_removable === false) )
{
// Retrieve widget class
var sWidgetName = this._getCriteriaWidgetNameFromType(sType);
// Add some informations from the field
if(this._hasFieldDefinition(sRef))
{
var oFieldDef = this._getFieldDefinition(sRef);
oData.field = {
label: oFieldDef.label,
class: oFieldDef.class,
class_alias: oFieldDef.class_alias,
code: oFieldDef.code,
widget: oFieldDef.widget,
allowed_values: oFieldDef.allowed_values,
is_null_allowed: oFieldDef.is_null_allowed,
};
}
if ('date' == sType || 'date_time' == sType)
{
oData.datepicker = this.options.datepicker;
}
// Create DOM element
var oCriteriaElem = $('<div></div>')
.addClass('sf_criteria')
//.insertBefore(this.elements.more_criterion);
.appendTo(this.elements.criterion_area);
// Instanciate widget
$.itop[sWidgetName](oData, oCriteriaElem);
sType = 'raw';
}
else
// Protection against bad initialization data
if(sType === null)
{
this._trace('Could not add criteria as we could not retrieve type for ref "' + sRef + '".');
this._trace('Could not add criteria as we could not retrieve type for ref "'+sRef+'".');
return false;
}
// Retrieve widget class
var sWidgetName = this._getCriteriaWidgetNameFromType(sType);
// Add some informations from the field
if(this._hasFieldDefinition(sRef))
{
var oFieldDef = this._getFieldDefinition(sRef);
oData.field = {
label: oFieldDef.label,
class: oFieldDef.class,
class_alias: oFieldDef.class_alias,
code: oFieldDef.code,
widget: oFieldDef.widget,
allowed_values: oFieldDef.allowed_values,
is_null_allowed: oFieldDef.is_null_allowed,
};
}
if ('date' == sType || 'date_time' == sType)
{
oData.datepicker = this.options.datepicker;
}
// Create DOM element
var oCriteriaElem = $('<div></div>')
.addClass('sf_criteria')
//.insertBefore(this.elements.more_criterion);
.appendTo(this.elements.criterion_area);
// Instanciate widget
$.itop[sWidgetName](oData, oCriteriaElem);
return true;
},
// - Find a criteria's type from a field's ref (usually <CLASS_ALIAS>.<ATT_CODE>)
_getCriteriaTypeFromFieldRef: function(sRef)