diff --git a/js/search/search_form_criteria.js b/js/search/search_form_criteria.js new file mode 100644 index 000000000..27d5e0a87 --- /dev/null +++ b/js/search/search_form_criteria.js @@ -0,0 +1,155 @@ +//iTop Search form criteria +; +$(function() +{ + // the widget definition, where 'itop' is the namespace, + // 'search_form_criteria' the widget name + $.widget( 'itop.search_form_criteria', + { + // default options + options: + { + handled_classes: [], + get_current_value_callback: 'getCurrentValue', + set_current_value_callback: function(me, oEvent, oData){ console.log('Search form criteria: set_current_value_callback must be overloaded, this is the default callback.'); }, + + ref: "", + operator: "=", + values: [], + oql: "", + is_removable: true, + }, + + // the constructor + _create: function() + { + var me = this; + + this.element + .addClass('search_form_criteria'); + + // Get/SetCurrentValue callbacks handler + this.element + .bind('get_current_value set_current_value', 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; + } + }); + + this._prepareElement(); + }, + // called when created, and later when changing options + _refresh: function() + { + + }, + // events bound via _bind are removed automatically + // revert other modifications here + _destroy: function() + { + this.element + .removeClass('search_form_criteria'); + }, + // _setOptions is called with a hash of all options that are changing + // always refresh when changing options + _setOptions: function() + { + this._superApply(arguments); + }, + // _setOption is called for each individual option that is changing + _setOption: function( key, value ) + { + this._super( key, value ); + }, + + + getCurrentValue: function() + { + // TODO + // var value = null; + // + // this.element.find(':input').each(function(iIndex, oElem){ + // if($(oElem).is(':hidden') || $(oElem).is(':text') || $(oElem).is(':password') || $(oElem).is('textarea')) + // { + // value = $(oElem).val(); + // } + // else if($(oElem).is('select')) + // { + // if($(oElem).is('select[multiple]')) + // { + // value = []; + // $(oElem).find('option:selected').each(function(){ + // value.push($(this).val()); + // }); + // } + // else + // { + // value = $(oElem).val(); + // } + // } + // else if($(oElem).is(':checkbox') || $(oElem).is(':radio')) + // { + // if(value === null) + // { + // value = []; + // } + // if($(oElem).is(':checked')) + // { + // value.push($(oElem).val()); + // } + // } + // else + // { + // console.log('Form field : Input type not handle yet.'); + // } + // }); + // + // return value; + }, + + + // Prepare DOM element + _prepareElement: function() + { + // Prepare base DOM structure + //this.options.ref+' '+this.options.operator+' '+this.options.values + this.element + .append('
') + .append('
') + .append('
'); + + // Removable / locked decoration + if(this.options.is_removable === true) + { + this.element.append('
'); + } + else + { + this.element.append('
'); + } + + // Fill + }, + + + // Debug helper + showOptions: function() + { + return this.options; + } + }); +}); diff --git a/js/search/search_form_handler.js b/js/search/search_form_handler.js new file mode 100644 index 000000000..d8e2c65aa --- /dev/null +++ b/js/search/search_form_handler.js @@ -0,0 +1,251 @@ +//iTop Search form handler +; +$(function() +{ + // the widget definition, where 'itop' is the namespace, + // 'search_form_handler' the widget name + $.widget( 'itop.search_form_handler', + { + // default options + options: + { + "criterion_outer_selector": null, + "result_list_outer_selector": null, + "submit_button_selector": null, + "hide_initial_criterion": false, // What is that? + "endpoint": null, + "search": { + "base_oql": "", + "criterion": [ + // Structure + // { + // "or": [ + // { + // "and": [ + // { + // "ref": "alias.code", + // "operator": "contains", + // "values": [ + // { + // "value": "foo", + // "label": "bar", + // } + // ], + // "is_removable": true, + // "oql": "", + // }, + // ] + // }, + // ] + // }, + ], + "fields": [ + // Structure + // "alias.code": { + // "class_alias": "", + // "class": "", + // "code": "", + // "label": "", + // "type": "", + // "allowed_values": {...}, + // }, + ], + }, + }, + + // jQuery elements + elements: + { + criterion_area: null, + }, + + // the constructor + _create: function() + { + var me = this; + + this.element + .addClass('search_form_handler'); + + // Binding events + // this.element.bind('update_fields', function(oEvent, oData){ + // me._onUpdateFields(oEvent, oData); + // }); + + // Binding buttons + if(this.options.submit_button_selector !== null) + { + this.options.submit_button_selector.off('click').on('click', function(oEvent){ me._onSubmitClick(oEvent); }); + } + // if(this.options.cancel_btn_selector !== null) + // { + // this.options.cancel_btn_selector.off('click').on('click', function(oEvent){ me._onCancelClick(oEvent); }); + // } + + // Prepare criterion area + this._prepareCriterionArea(); + }, + + // called when created, and later when changing options + _refresh: function() + { + + }, + // events bound via _bind are removed automatically + // revert other modifications here + _destroy: function() + { + this.element + .removeClass('search_form_handler'); + }, + // _setOptions is called with a hash of all options that are changing + // always refresh when changing options + _setOptions: function() + { + this._superApply(arguments); + }, + // _setOption is called for each individual option that is changing + _setOption: function( key, value ) + { + this._super( key, value ); + }, + + + getCurrentValues: function() + { + // TODO + // return this.options.field_set.triggerHandler('get_current_values'); + }, + + // - Prepare criterion area + _prepareCriterionArea: function() + { + // Build area element + if(this.options.criterion_outer_selector !== null && $(this.options.criterion_outer_selector).length > 0) + { + this.elements.criterion_area = $(this.options.criterion_outer_selector); + } + else + { + var oCriterionAreaElem = $('
').appendTo(this.element); + this.elements.criterion_area = oCriterionAreaElem; + } + this.elements.criterion_area.addClass('sf_criterion_area'); + + // Clean area + this.elements.criterion_area.html(''); + + // Fill area with existing criterion + for(var i in this.options.search.criterion) + { + console.log(i, this.options.search.criterion[i]); + } + }, + + + // Criteria handlers + // - Add a criteria to the form + _addCriteria: function(oData) + { + var sRef = oData.ref + var sType = this._getCriteriaTypeFromFieldRef(sRef); + + if(sType !== null) + { + var sWidgetClass = 'search_form_criteria' + ((sType === 'raw') ? '' : '_' + sType); + oCriteriaElem = $('
') + .addClass('sf_criteria') + .appendTo(this.elements.criterion_area) + .search_form_criteria(oData); + } + else + { + this._trace('Could not add criteria as we could not retrieve type for ref "' + sRef + '".'); + } + }, + // - Find a criteria's type from a field's ref (usually .) + _getCriteriaTypeFromFieldRef: function(sRef) + { + var sType = null; + + if(this.options.search.fields[sRef] !== undefined) + { + sType = this.options.search.fields[sRef].type; + } + + return sType; + }, + + + // Button handlers + _onSubmitClick: function(oEvent) + { + // TODO + }, + _onCancelClick: function(oEvent) + { + // TODO + }, + + + // Update handlers + // - Called on form update successes + _onUpdateSuccess: function(oData, sFormPath) + { + // TODO + // if(oData.form.updated_fields !== undefined) + // { + // this.element.find('[data-form-path="' + sFormPath + '"]').trigger('update_form', {updated_fields: oData.form.updated_fields}); + // } + }, + // - Called on form update failures + _onUpdateFailure: function(oData, sFormPath) + { + // TODO + }, + // - Called after form updates + _onUpdateAlways: function(oData, sFormPath) + { + // TODO + // // Check all touched AFTER ajax is complete, otherwise the renderer will redraw the field in the mean time. + // this.element.find('[data-form-path="' + sFormPath + '"]').trigger('validate'); + // this._enableFormAfterLoading(); + }, + + + // Helpers + // - Show loader + _disableFormBeforeLoading: function() + { + // TODO + }, + // - Remove loader + _enableFormAfterLoading: function() + { + // TODO + }, + + + // Debug helpers + // - Show a trace in the javascript console + _trace: function(sMessage, oData) + { + if(window.console) + { + if(oData !== undefined) + { + console.log('Search form handler: ' + sMessage, oData); + } + else + { + console.log('Search form handler: ' + sMessage); + } + } + }, + // - Show current options + showOptions: function() + { + this._trace('Options', this.options, this.toto); + } + }); +});