Advanced search: WIP POC, integration with endpoint.

SVN:b1162[5412]
This commit is contained in:
Guillaume Lajarige
2018-03-13 10:47:54 +00:00
parent 2038785b09
commit e2174b9ad4
8 changed files with 363 additions and 64 deletions

View File

@@ -9,6 +9,7 @@ $(function()
// default options
options:
{
// Default values for the criteria
ref: '',
operator: '=',
values: [],
@@ -18,9 +19,33 @@ $(function()
field: {
label: '',
},
// Available operators (merged with derived widgets, ordered and then copied to this.operators)
available_operators: {
'=': {
'label': Dict.S('UI:Search:Criteria:Operator:Default:Equals'),
'code': 'equals',
'rank': 10,
},
'empty': {
'label': Dict.S('UI:Search:Criteria:Operator:Default:Empty'),
'code': 'empty',
'rank': 90,
},
'not_empty': {
'label': Dict.S('UI:Search:Criteria:Operator:Default:NotEmpty'),
'code': 'not_empty',
'rank': 100,
},
},
is_modified: false, // TODO: change this on value change and remove oql property value
},
// Operators
operators: {},
// Form handler
handler: null,
// the constructor
@@ -30,33 +55,13 @@ $(function()
this.element.addClass('search_form_criteria');
this._orderOperators();
// Link search form handler
this.handler = this.element.closest('.search_form_handler');
// GetData
this.element.bind('itop.search.criteria.get_data', function(oEvent, oData){
return me._onGetData(oData);
});
// Get/SetCurrentValues callbacks handler
this.element.bind('itop.search.criteria.get_current_values itop.search.criteria.set_current_values', function(oEvent, oData){
oEvent.stopPropagation();
var callback = me.options[oEvent.type+'_callback'];
if(typeof callback === 'string')
{
return me[callback](oEvent, oData);
}
else if(typeof callback === 'function')
{
return callback(me, oEvent, oData);
}
else
{
console.log('search form criteria: callback type must be a function or a existing function name of the widget');
return false;
}
});
// Bind events
this._bindEvents();
this._prepareElement();
},
@@ -85,6 +90,43 @@ $(function()
// Protected methods
// - Order available operators
_orderOperators: function()
{
console.log(this.options.available_operators);
},
// - Bind external events
_bindEvents: function()
{
var me = this;
// Get criteria data
this.element.bind('itop.search.criteria.get_data', function(oEvent, oData){
return me._onGetData(oData);
});
// Get/SetCurrentValues callbacks handler
this.element.bind('itop.search.criteria.get_current_values itop.search.criteria.set_current_values', function(oEvent, oData){
oEvent.stopPropagation();
var callback = me.options[oEvent.type+'_callback'];
if(typeof callback === 'string')
{
return me[callback](oEvent, oData);
}
else if(typeof callback === 'function')
{
return callback(me, oEvent, oData);
}
else
{
console.log('search form criteria: callback type must be a function or a existing function name of the widget');
return false;
}
});
},
_remove: function()
{
this.element.remove();
@@ -93,6 +135,25 @@ $(function()
// Event callbacks
// - Internal events
_onButtonApply: function()
{
this._trace('TODO: Apply button');
this.handler.triggerHandler('itop.search.criteria.value_changed');
},
_onButtonCancel: function()
{
this._trace('TODO: Cancel button');
},
_onButtonMore: function()
{
this.element.find('.sfc_form_group').addClass('advanced');
},
_onButtonLess: function()
{
this.element.find('.sfc_form_group').removeClass('advanced');
},
// - External events
_onGetData: function(oData)
{
var oCriteriaData = {
@@ -113,16 +174,16 @@ $(function()
var me = this;
// Prepare base DOM structure
//this.options.ref+' '+this.options.operator+' '+this.options.values
this.element
.append('<div class="sfc_title"></div>')
.append('<div class="sfc_form_group"></div>')
.append('<div class="sfc_form_group"><div class="sfc_fg_operators"></div><div class="sfc_fg_buttons"></div></div>')
.append('<span class="sfc_toggle"><a class="fa fa-caret-down" href="#"></a></span>');
// Bind events
// - Toggler
this.element.find('.sfc_toggle, .sfc_title').on('click', function(){
me.element.find('.sfc_form_group').toggle();
me.element.find('.sfc_toggle').toggleClass('opened');
});
// Removable / locked decoration
@@ -138,9 +199,64 @@ $(function()
this.element.append('<div class="sfc_locked"><span class="fa fa-lock"></span></div>');
}
// Form group
this._prepareOperators();
this._prepareButtons();
// Fill criteria
// - Title
this._setTitle();
},
// - Prepare the available operators for the criteria
// Meant for overloading.
_prepareOperators: function()
{
for(var sOpIdx in this.options.available_operators)
{
var oOp = this.options.available_operators[sOpIdx];
var sMethod = '_prepare' + this._toCamelCase(oOp.code) + 'Operator';
// Create DOM element from template
var oOpElem = $(this._getOperatorTemplate()).uniqueId();
// Prepare operator's base elements
this._prepareOperator(oOpElem, oOp);
// Prepare operator's specific elements
if(this[sMethod] !== undefined)
{
this[sMethod](oOpElem, oOp);
}
else
{
this._prepareDefaultOperator(oOpElem, oOp);
}
// Append to form group
oOpElem.appendTo(this.element.find('.sfc_fg_operators'));
}
},
// - Prepare the buttons (DOM and events) for a criteria
_prepareButtons: function()
{
var me = this;
// DOM elements
this.element.find('.sfc_fg_buttons')
.append('<button type="button" name="apply" class="sfc_fg_button sfc_fg_apply">' + Dict.S('UI:Button:Apply') + '</button>')
.append('<button type="button" name="cancel" class="sfc_fg_button sfc_fg_cancel">' + Dict.S('UI:Button:Cancel') + '</button>')
.append('<button type="button" name="more" class="sfc_fg_button sfc_fg_more">' + Dict.S('UI:Button:More') + '</button>')
.append('<button type="button" name="less" class="sfc_fg_button sfc_fg_less">' + Dict.S('UI:Button:Less') + '</button>');
// Events
this.element.find('.sfc_fg_button').on('click', function(oEvent){
oEvent.preventDefault();
oEvent.stopPropagation();
var sCallback = '_onButton' + me._toCamelCase($(this).attr('name'));
me[sCallback]();
});
},
// - Set the title element
_setTitle: function(sTitle)
{
@@ -151,7 +267,49 @@ $(function()
}
this.element.find('.sfc_title').text(sTitle);
},
// - Return a HTML template for operators
_getOperatorTemplate: function()
{
return '<div class="sfc_fg_operator"><label><input type="radio" class="sfc_op_radio" name="operator" value="" /><span class="sfc_op_name"></span><span class="sfc_op_content"></span></label></div>';
},
// Operators helpers
_prepareOperator: function(oOpElem, oOp)
{
var sInputId = oOp.code + '_' + oOpElem.attr('id');
// Set label
oOpElem.find('.sfc_op_name').text(oOp.label);
oOpElem.find('> label').attr('for', sInputId);
// Set value
oOpElem.find('.sfc_op_radio').val(oOpElem.id);
oOpElem.find('.sfc_op_radio').attr('id', sInputId);
// Bind events
// - Check radio button on click
oOpElem.on('click', function(){
oOpElem.find('.sfc_op_radio').prop('checked', true);
});
},
_prepareDefaultOperator: function(oOpElem, oOp)
{
var me = this;
// DOM element
var oOpContentElem = $('<input type="text" />');
oOpContentElem.val(this._getValuesAsText());
oOpElem.append(oOpContentElem);
},
_prepareEmptyOperator: function(oOpElem, oOp)
{
// Do nothing as only the label is necessary
},
_prepareNotEmptyOperator: function(oOpElem, oOp)
{
// Do nothing as only the label is necessary
},
// Values helpers
// - Convert values to a standard string
@@ -181,6 +339,21 @@ $(function()
},
// Global helpers
// - Converts a snake_case string to CamelCase
_toCamelCase: function(sString)
{
var aParts = sString.split('_');
for(var i in aParts)
{
aParts[i] = aParts[i].charAt(0).toUpperCase() + aParts[i].substr(1);
}
return aParts.join('');
},
// Debug helpers
// - Show a trace in the javascript console
_trace: function(sMessage, oData)