dojo.require('openils.Util');
/* This is not the dijit per se. Search further in this file for
- * "dojo.declare" for the dijit. */
- function PCrudFilterRowTable() {
+ * "dojo.declare" for the beginning of the dijit. */
+ function PCrudFilterRowManager() {
var self = this;
this._init = function(container, field_store, fm_class) {
}, this.container
);
+ var tr = dojo.create(
+ "tr", {
+ "id": "pcrudfilterdialog-empty",
+ "className": "hidden"
+ }, this.table
+ );
+
+ dojo.create(
+ "td", {
+ "colspan": 4,
+ "innerHTML": "Add rows to filter results, or just click Apply to see unfiltered results." /* XXX i18n */
+ }, tr
+ );
+
this.add_row();
};
+ this._compile_second_pass = function(first_pass) {
+ var and = [];
+ var result = {"-and": and};
+
+ for (var field in first_pass) {
+ var list = first_pass[field];
+ if (list.length == 1) {
+ var obj = {};
+ obj[field] = list.pop();
+ and.push(obj);
+ } else {
+ var or = list.map(
+ function(expr) {
+ var obj = {}; obj[field] = expr; return obj;
+ }
+ );
+ and.push({"-or": or});
+ }
+ }
+
+ return result;
+ };
+
this.add_row = function() {
+ this.hide_empty_placeholder();
var row_id = this.row_index++;
this.rows[row_id] = new PCrudFilterRow(this, row_id);
};
this.remove_row = function(row_id) {
this.rows[row_id].destroy();
delete this.rows[row_id];
+
+ if (openils.Util.objectProperties(this.rows).length < 1)
+ this.show_empty_placeholder();
+ };
+
+ this.hide_empty_placeholder = function() {
+ openils.Util.hide("pcrudfilterdialog-empty");
+ };
+
+ this.show_empty_placeholder = function() {
+ openils.Util.show("pcrudfilterdialog-empty");
};
this.compile = function() {
- var filter = {};
+ /* We'll prepare a first-pass data structure that looks like:
+ * {
+ * field1: [{"op": "one value"}],
+ * field2: [{"op": "a value"}, {"op": "b value"}],
+ * field3: [{"op": "first value"}, {"op": ["range start", "range end"]}]
+ * }
+ *
+ * which will be passed to _compile_second_pass() to yield an
+ * actual filter suitable for pcrud (with -and and -or in all the
+ * right places) so the above example would come out like:
+ *
+ * { "-and": [
+ * {"field1": {"op": "one value"}},
+ * {"-or": [ {"field2": {"op": "a value"}}, {"field2": {"op": "b value"}} ] },
+ * {"-or": [
+ * {"field3": {"op": "first value"}},
+ * {"field3": {"op": ["range start", "range end"]}}
+ * ] }
+ * ] }
+ */
+ var first_pass = {};
+
for (var row_id in this.rows) {
var row = this.rows[row_id];
var value = row.compile();
if (typeof(value) != "undefined" &&
typeof(field) != "undefined") {
- filter[field] = value;
+
+ if (!first_pass[field])
+ first_pass[field] = [];
+ first_pass[field].push(value);
}
}
/* Don't return an empty filter: pcrud can't use that. */
- if (openils.Util.objectProperties(filter).length < 1)
- filter[fieldmapper[this.fm_class].Identifier] = {"!=": null};
-
- dump(js2JSON(filter) + "\n"); // LFW XXX
- return filter;
+ if (openils.Util.objectProperties(first_pass).length < 1) {
+ var result = {};
+ result[fieldmapper[this.fm_class].Identifier] = {"!=": null};
+ return result;
+ } else {
+ return this._compile_second_pass(first_pass);
+ }
};
this._init.apply(this, arguments);
function PCrudFilterRow() {
var self = this;
- this._init = function(filter_row_table, row_id) {
- this.filter_row_table = filter_row_table;
+ this._init = function(filter_row_manager, row_id) {
+ this.filter_row_manager = filter_row_manager;
this.row_id = row_id;
this._build();
};
this._build = function() {
- this.tr = dojo.create("tr", {}, this.filter_row_table.table);
+ this.tr = dojo.create("tr", {}, this.filter_row_manager.table);
this._create_field_selector();
this._create_operator_selector();
this.field_selector = new dijit.form.FilteringSelect(
{
"labelAttr": "label",
+ "scrollOnFocus": false,
"onChange": function(value) {
self.update_selected_field(value);
},
- "store": this.filter_row_table.field_store
+ "store": this.filter_row_manager.field_store
}, dojo.create("span", {}, td)
);
};
"innerHTML": "X",
"href": "#",
"onclick": function() {
- self.filter_row_table.remove_row(self.row_id);
+ self.filter_row_manager.remove_row(self.row_id);
}
}, td
);
this._clear_value_slot = function() {
if (this.value_widget)
- this.value_widget.destroy();
+ this.value_widget.widget.destroy();
dojo.empty(this.value_slot);
};
this._clear_value_slot();
this.value_widget = new openils.widget.AutoFieldWidget({
- "fmClass": this.filter_row_table.fm_class,
+ "fmClass": this.filter_row_manager.fm_class,
"fmField": value,
- "parentNode": dojo.create("div", {}, this.value_slot)
+ "parentNode": dojo.create("div", {}, this.value_slot),
+ "dijitArgs": {"scrollOnFocus": false}
});
this.value_widget.build();
constructor : function(args) {
for(var k in args)
this[k] = args[k];
- this.title = this.title || "Filter Rows"; /* XXX i18n */
+ this.title = this.title || "Filter Results"; /* XXX i18n */
this.widgetIndex = 0;
this.widgetCache = {};
},
}
});
- this.filter_row_table = new PCrudFilterRowTable(
+ this.filter_row_manager = new PCrudFilterRowManager(
dojo.create("div", {}, this.domNode),
this.fieldStore, this.fmClass
);
new dijit.form.Button(
{
"label": "Add Row", /* XXX i18n */
+ "scrollOnFocus": false, /* almost always better */
"onClick": function() {
- self.filter_row_table.add_row();
+ self.filter_row_manager.add_row();
}
}, dojo.create("span", {}, button_holder)
);
new dijit.form.Button(
{
"label": "Apply", /* XXX i18n */
+ "scrollOnFocus": false,
"onClick": function() {
if (self.onApply)
- self.onApply(self.filter_row_table.compile());
+ self.onApply(self.filter_row_manager.compile());
self.hide();
}
}, dojo.create("span", {}, button_holder)
new dijit.form.Button(
{
"label": "Cancel", /* XXX i18n */
+ "scrollOnFocus": false,
"onClick": function() {
if (self.onCancel)
self.onCancel();