pcrudfilterdialog features and autogrid feature:
authorLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Fri, 6 Jan 2012 22:37:35 +0000 (17:37 -0500)
committerLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Fri, 6 Jan 2012 22:37:35 +0000 (17:37 -0500)
    pcrudfilterdialog: reusable fields (or-ed together within general and)
    pcrudfilterdialog: empty case
    autogrid: keep using same filter, don't recreate new every time

Signed-off-by: Lebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Open-ILS/web/js/dojo/openils/widget/AutoGrid.js
Open-ILS/web/js/dojo/openils/widget/PCrudFilterDialog.js

index ab42a00..7ceb628 100644 (file)
@@ -119,13 +119,15 @@ if(!dojo._hasResource['openils.widget.AutoGrid']) {
                                 style : 'padding-right:6px;',
                                 href : 'javascript:void(0);', 
                                 onclick : function() { 
-                                    var dialog = new openils.widget.PCrudFilterDialog({fmClass:self.fmClass})
-                                    dialog.onApply = function(filter) {
-                                        self.resetStore();
-                                        self.loadAll(self.cachedQueryOpts, filter);
-                                    };
-                                    dialog.startup();
-                                    dialog.show();
+                                    if (!self.filterDialog) {
+                                        self.filterDialog = new openils.widget.PCrudFilterDialog({fmClass:self.fmClass})
+                                        self.filterDialog.onApply = function(filter) {
+                                            self.resetStore();
+                                            self.loadAll(self.cachedQueryOpts, filter);
+                                        };
+                                        self.filterDialog.startup();
+                                    }
+                                    self.filterDialog.show();
                                 }
                             }),
                             this.paginator.domNode
index 90d7449..bb6b7ea 100644 (file)
@@ -8,8 +8,8 @@ if(!dojo._hasResource['openils.widget.PCrudFilterDialog']) {
     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) {
@@ -30,10 +30,48 @@ if(!dojo._hasResource['openils.widget.PCrudFilterDialog']) {
                 }, 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);
         };
@@ -41,10 +79,42 @@ if(!dojo._hasResource['openils.widget.PCrudFilterDialog']) {
         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();
@@ -52,16 +122,21 @@ if(!dojo._hasResource['openils.widget.PCrudFilterDialog']) {
 
                 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);
@@ -70,15 +145,15 @@ if(!dojo._hasResource['openils.widget.PCrudFilterDialog']) {
     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();
@@ -91,10 +166,11 @@ if(!dojo._hasResource['openils.widget.PCrudFilterDialog']) {
             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)
             );
         };
@@ -114,7 +190,7 @@ if(!dojo._hasResource['openils.widget.PCrudFilterDialog']) {
                     "innerHTML": "X",
                     "href": "#",
                     "onclick": function() {
-                        self.filter_row_table.remove_row(self.row_id);
+                        self.filter_row_manager.remove_row(self.row_id);
                     }
                 }, td
             );
@@ -122,7 +198,7 @@ if(!dojo._hasResource['openils.widget.PCrudFilterDialog']) {
 
         this._clear_value_slot = function() {
             if (this.value_widget)
-                this.value_widget.destroy();
+                this.value_widget.widget.destroy();
 
             dojo.empty(this.value_slot);
         };
@@ -135,9 +211,10 @@ if(!dojo._hasResource['openils.widget.PCrudFilterDialog']) {
             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();
@@ -176,7 +253,7 @@ if(!dojo._hasResource['openils.widget.PCrudFilterDialog']) {
             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 = {};
             },
@@ -203,7 +280,7 @@ if(!dojo._hasResource['openils.widget.PCrudFilterDialog']) {
                     }
                 });
 
-                this.filter_row_table = new PCrudFilterRowTable(
+                this.filter_row_manager = new PCrudFilterRowManager(
                     dojo.create("div", {}, this.domNode),
                     this.fieldStore, this.fmClass
                 );
@@ -217,8 +294,9 @@ if(!dojo._hasResource['openils.widget.PCrudFilterDialog']) {
                 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)
                 );
@@ -226,9 +304,10 @@ if(!dojo._hasResource['openils.widget.PCrudFilterDialog']) {
                 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)
@@ -237,6 +316,7 @@ if(!dojo._hasResource['openils.widget.PCrudFilterDialog']) {
                 new dijit.form.Button(
                     {
                         "label": "Cancel", /* XXX i18n */
+                        "scrollOnFocus": false,
                         "onClick": function() {
                             if (self.onCancel)
                             self.onCancel();