GridColumnPicker mult-column support selectors
authorBill Erickson <berick@esilibrary.com>
Wed, 28 Mar 2012 15:51:19 +0000 (11:51 -0400)
committerBill Erickson <berick@esilibrary.com>
Wed, 28 Mar 2012 15:51:19 +0000 (11:51 -0400)
Adds a number spinner to each sortable column in the grid column picker.
A Sort Priority of '0' means no sorting is applied, a priority of 1 is
highest priority, 2 is second, etc.

Adds support for an onSortchange handler, which is passed the list of
fields to sort in order.

Adds support for an onLoad handler, which is called after the initial
retrieval of the user persist settings.  This is important for the
initial grid load, which may need to wait until after the sort columns
are known (to avoid re-fetching on the initial load).

Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/web/js/dojo/openils/widget/GridColumnPicker.js

index 7e0dcea..0959e58 100644 (file)
@@ -20,6 +20,7 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
 
     dojo.require('dijit.Dialog');
     dojo.require('dijit.form.Button');
+    dojo.require('dijit.form.NumberSpinner');
     dojo.require('openils.User');
     dojo.require('openils.Event');
     dojo.require('openils.Util');
@@ -31,6 +32,7 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
         USER_PERSIST_SETTING : 'ui.grid_columns',
 
         constructor : function (authtoken, persistKey, grid, structure) {
+            var _this = this;
             this.grid = grid;
             this.persistKey = this.USER_PERSIST_SETTING+'.'+persistKey;
             this.authtoken = authtoken || openils.User.authtoken;
@@ -40,7 +42,15 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
             this.dialog = this.buildDialog();
             this.dialogTable = this.dialog.containerNode.getElementsByTagName('tbody')[0];
 
-            var _this = this;
+            // replace: called after any sort changes
+            this.onSortChange = function(list) {console.log('onSortChange()')}
+            // replace:  called after user settings are first retrieved
+            this.onLoad = function(opts) {console.log('onLoad()')};
+
+            // internal onload handler
+            this.loaded = false;
+            this._onLoad = function(opts) {_this.loaded = true; _this.onLoad(opts)};
+
             this.grid.onHeaderContextMenu = function(e) { 
                 _this.build();
                 _this.dialog.show(); 
@@ -49,7 +59,7 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
         },
 
         // determine the visible sorting from the 
-        // view and update structure cells to match
+        // view and update our list of cells to match
         refreshCells : function() {
             var cells = this.cells;
             this.cells = [];
@@ -90,17 +100,27 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
 
             var dialog = new dijit.Dialog({title : 'Column Picker'});
             var table = dojo.create('table', {'class':'oils-generic-table', innerHTML : 
-                "<thead><tr><th width='33%'>Column</th><th width='33%'>Display</th><th width='33%'>Auto Width</th></tr></thead>" +
-                "<tbody><tr><td><div name='cancel_button'></div></td><td><div name='save_button'></div></td></tr></tbody></table>" });
+                "<table><thead><tr><th width='30%'>Column</th><th width='23%'>Display</th>" +
+                "<th width='23%'>Auto Width</th><th width='23%'>Sort Priority</th></tr></thead>" +
+                "<tbody />"});
 
-            dialog.containerNode.appendChild(table);
+            var tDiv = dojo.create('div', {style : 'height:400px; overflow-y:auto'});
+            tDiv.appendChild(table);
+
+            var bDiv = dojo.create('div', {style : 'text-align:right; width:100%;',
+                innerHTML : "<span name='cancel_button'></span><span name='save_button'></span>"});
+            
+            var wrapper = dojo.create('div');
+            wrapper.appendChild(tDiv);
+            wrapper.appendChild(bDiv);
+            dialog.containerNode.appendChild(wrapper);
 
             var button = new dijit.form.Button({label:'Save'}, 
-                dojo.query('[name=save_button]', table)[0]);
+                dojo.query('[name=save_button]', bDiv)[0]);
             button.onClick = function() { dialog.hide(); self.update(true); };
 
             button = new dijit.form.Button({label:'Cancel'}, 
-                dojo.query('[name=cancel_button]', table)[0]);
+                dojo.query('[name=cancel_button]', bDiv)[0]);
             button.onClick = function() { dialog.hide(); };
 
             return dialog;
@@ -126,21 +146,21 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
                 var cell = this.cells[i];
                 tr = document.createElement('tr');
                 tr.setAttribute('picker', 'picker');
+                td0 = document.createElement('td');
                 td1 = document.createElement('td');
                 td2 = document.createElement('td');
                 td3 = document.createElement('td');
 
                 ipt = document.createElement('input');
                 ipt.setAttribute('type', 'checkbox');
-                ipt.setAttribute('checked', 'checked');
-                ipt.setAttribute('ident', cell.field+''+cell.name);
                 ipt.setAttribute('name', 'selector');
 
                 ipt2 = document.createElement('input');
                 ipt2.setAttribute('type', 'checkbox');
-                ipt2.setAttribute('ident', cell.field+''+cell.name);
                 ipt2.setAttribute('name', 'width');
 
+                ipt3 = document.createElement('input');
+
                 if (cell.nonSelectable) {
                     ipt.setAttribute('checked', 'checked');
                     ipt.setAttribute('disabled', true);
@@ -156,16 +176,28 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
                     }
                 }
 
-                td1.appendChild(document.createTextNode(cell.name));
-                td2.appendChild(ipt);
-                td3.appendChild(ipt2);
+                td0.appendChild(document.createTextNode(cell.name));
+                td1.appendChild(ipt);
+                td2.appendChild(ipt2);
+                td3.appendChild(ipt3);
+                tr.appendChild(td0);
                 tr.appendChild(td1);
                 tr.appendChild(td2);
                 tr.appendChild(td3);
+
                 if(lastChild)
                     this.dialogTable.insertBefore(tr, lastChild);
                 else
                     this.dialogTable.appendChild(tr);
+
+                // this must be added after its parent node is inserted into the DOM.
+                var ns = new dijit.form.NumberSpinner(
+                    {   constraints : {min : 0, places : 0}, 
+                        value : cell._sort || 0,
+                        style : 'width:4em',
+                        name : 'sort'
+                    }, ipt3
+                );
             }
         },
 
@@ -173,13 +205,20 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
         update : function(persist) {
             var rows = dojo.query('[picker=picker]', this.dialogTable);
             var _this = this;
-            displayCells = [];
+            var displayCells = [];
+            var sortUpdated = false;
 
             for (var i = 0; i < rows.length; i++) {
                 var row = rows[i];
                 var selector = dojo.query('[name=selector]', row)[0];
                 var width = dojo.query('[name=width]', row)[0];
-                var cell = this.cells[i]; // should match
+                var sort = dojo.query('[name=sort]', row)[0];
+                var cell = this.cells[i]; // index should match dialog
+
+                if (cell._sort != sort.value) {
+                    sortUpdated = true;
+                    cell._sort = sort.value;
+                }
 
                 if (selector.checked) {
                     cell._visible = true;
@@ -189,6 +228,7 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
                         delete cell.width;
                     }
                     displayCells.push(cell);
+
                 } else {
                     cell._visible = false;
                     delete cell.width;
@@ -199,14 +239,30 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
             this.grid.setStructure(this.structure);
             this.grid.update();
 
-            if(persist) 
-                this.persist(true);
+            if (sortUpdated && this.onSortChange) 
+                this.onSortChange(this.buildSortList());
+
+            if (persist) this.persist(true);
+        },
+
+        // extract cells that have sorting applied, order lowest to highest
+        buildSortList : function() {
+            var sortList = this.cells.filter(
+                function(cella) { return cella._sort > 0 }
+            ).sort( 
+                function(a, b) { 
+                    if (a._sort < b._sort) return -1; 
+                    return 1; 
+                }
+            );
+            return sortList.map(function(f){return f.field});
         },
 
         // save me as a user setting
         persist : function(noRefresh) {
             var list = [];
             var autos = [];
+            var sort = [];
             if (!noRefresh) this.refreshCells();
 
             for(var i = 0; i < this.cells.length; i++) {
@@ -216,10 +272,16 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
                     if(cell.width == 'auto')
                         autos.push(cell.field);
                 } 
+                if (cell._sort > 0)
+                    sort.push(cell.field);
             }
 
             var setting = {};
-            setting[this.persistKey] = {'columns':list, 'auto':autos};
+            setting[this.persistKey] = {
+                'columns' : list, 
+                'auto' : autos,
+                'sort' : sort
+            };
 
             var _this = this;
             fieldmapper.standardRequest(
@@ -237,10 +299,13 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
             );
         }, 
 
-        _loadColsFromSetting : function(setting) {
+        loadColsFromSetting : function(setting) {
             var _this = this;
             this.setting = setting;
             var displayCells = [];
+            
+            // new component, existing settings may not have this
+            if (!setting.sort) setting.sort = [];
 
             dojo.forEach(setting.columns,
                 function(col) {
@@ -248,12 +313,15 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
                     if (cell) {
                         cell._visible = true;
                         displayCells.push(cell);
+
                         if(setting.auto.indexOf(cell.field) > -1) {
                             cell.width = 'auto';
                         } else {
                             if(cell.width == 'auto')
                                 delete cell.width;
                         }
+                        cell._sort = setting.sort.indexOf(cell.field) + 1;
+
                     } else {
                         console.log('Unknown setting column '+col+'.  Ignoring...');
                     }
@@ -262,8 +330,10 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
             
             // any cells not in the setting must be marked as non-visible
             dojo.forEach(this.cells, function(cell) { 
-                if (setting.columns.indexOf(cell.field) == -1)
+                if (setting.columns.indexOf(cell.field) == -1) {
                     cell._visible = false;
+                    cell._sort = 0;
+                }
             });
 
             this.structure[0].cells[0] = displayCells;
@@ -280,13 +350,16 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
                 var _this = this;
                 openils.Util.addOnLoad(function() {
                     _this.authtoken = openils.User.authtoken;
-                    _this.load()
+                    _this.load();
                 }); 
                 return;
             }
 
-            if(this.setting)
-                return this._loadColsFromSetting(this.setting);
+            if(this.setting) {
+                this.loadColsFromSetting(this.setting);
+                this._onLoad({sortFields : this.buildSortList()});
+                return;
+            }
 
             fieldmapper.standardRequest(
                 ['open-ils.actor', 'open-ils.actor.patron.settings.retrieve'],
@@ -295,11 +368,12 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
                     oncomplete: function(r) {
                         var set = openils.Util.readResponse(r);
                         if(set) {
-                            _this._loadColsFromSetting(set);
+                            _this.loadColsFromSetting(set);
                         } else {
                             _this.grid.setStructure(_this.structure);
                             _this.grid.update();
                         }
+                        _this._onLoad({sortFields : _this.buildSortList()});
                     }
                 }
             );