GridColumnPicker support column ordering, cleanup
authorBill Erickson <berick@esilibrary.com>
Tue, 27 Mar 2012 13:38:20 +0000 (09:38 -0400)
committerBill Erickson <berick@esilibrary.com>
Tue, 27 Mar 2012 15:52:41 +0000 (11:52 -0400)
This adds support for detecting and saving state information for
re-ordered grid columns.  Also, with each instantiation of the column
picker dialog (via control-click), the dialog is re-rendered to match
the order of columns in the grid in case they have moved.

ColumnPicker now produces a useful console message when the user setting
required for persistance does not exist.

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

index f9f858e..0aa8ffc 100644 (file)
@@ -31,26 +31,58 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
         USER_PERSIST_SETTING : 'ui.grid_columns',
 
         constructor : function (authtoken, persistPrefix, grid, structure) {
-            this.dialog = this.buildDialog();
             this.grid = grid;
-            this.structure = structure;
-            if(!structure) 
-                this.structure = this.grid.attr('structure');
-            this.dialogTable = this.dialog.containerNode.getElementsByTagName('tbody')[0];
-            this.baseCellList = this.structure[0].cells[0].slice();
-            this.build();
-            this.authtoken = authtoken;
-            this.savedColums = null;
             this.persistPrefix = persistPrefix;
-            this.setting = null;
+            this.authtoken = authtoken || openils.User.authtoken;
+            this.structure = structure || this.grid.structure;
+            this.cells = this.structure[0].cells[0].slice();
 
-            var self = this;
+            this.dialog = this.buildDialog();
+            this.dialogTable = this.dialog.containerNode.getElementsByTagName('tbody')[0];
+
+            var _this = this;
             this.grid.onHeaderContextMenu = function(e) { 
-                self.dialog.show(); 
+                _this.build();
+                _this.dialog.show(); 
                 dojo.stopEvent(e);
             };
         },
 
+        // determine the visible sorting from the 
+        // view and update structure cells to match
+        refreshCells : function() {
+            var cells = this.cells;
+            this.cells = [];
+            var _this = this;
+
+            dojo.forEach(
+                 _this.grid.views.views[0].structure.cells[0],
+                 function(vCell) {
+                    for (var i = 0; i < cells.length; i++) {
+                        if (cells[i].field == vCell.field) {
+                            cells[i]._visible = true;
+                            _this.cells.push(cells[i]);
+                            break;
+                        }
+                    }
+                }
+            );
+
+            // Depending on how the grid structure is built, there may be
+            // cells in the structure that are not yet in the view.  Push
+            // any remaining cells onto the end.
+            dojo.forEach(
+                cells,
+                function(cell) {
+                    existing = _this.cells.filter(function(s){return s.field == cell.field})[0]
+                    if (!existing) {
+                        cell._visible = false;
+                        _this.cells.push(cell);
+                    }
+                }
+            );
+        },
+
         buildDialog : function() {
             var self = this;
             
@@ -63,10 +95,12 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
 
             dialog.containerNode.appendChild(table);
 
-            var button = new dijit.form.Button({label:'Save'}, dojo.query('[name=save_button]', table)[0]);
+            var button = new dijit.form.Button({label:'Save'}, 
+                dojo.query('[name=save_button]', table)[0]);
             button.onClick = function() { dialog.hide(); self.update(true); };
 
-            button = new dijit.form.Button({label:'Cancel'}, dojo.query('[name=cancel_button]', table)[0]);
+            button = new dijit.form.Button({label:'Cancel'}, 
+                dojo.query('[name=cancel_button]', table)[0]);
             button.onClick = function() { dialog.hide(); };
 
             return dialog;
@@ -74,8 +108,7 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
 
         // builds the column-picker dialog table
         build : function() {
-            var  cells = this._selectableCellList();
-            var str = '';
+            this.refreshCells();
             var rows = dojo.query('tr', this.dialogTable);
 
             for(var i = 0; i < rows.length; i++) {
@@ -88,9 +121,9 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
             if(rows.length > 0)
                 lastChild = rows[rows.length-1];
 
-            for(var i = 0; i < cells.length; i++) {
+            for(var i = 0; i < this.cells.length; i++) {
                 // setting table.innerHTML breaks stuff, so do it the hard way
-                var cell = cells[i];
+                var cell = this.cells[i];
                 tr = document.createElement('tr');
                 tr.setAttribute('picker', 'picker');
                 td1 = document.createElement('td');
@@ -108,10 +141,15 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
                 ipt2.setAttribute('ident', cell.field+''+cell.name);
                 ipt2.setAttribute('name', 'width');
 
-                if(this.setting) {
-                    // set the UI based on the loaded settings
-                    if(this._arrayHas(this.setting.columns, cell.field)) {
-                        if(this._arrayHas(this.setting.auto, cell.field))
+                if (cell.nonSelectable) {
+                    ipt.setAttribute('checked', 'checked');
+                    ipt.setAttribute('disabled', true);
+                    ipt2.setAttribute('disabled', true);
+
+                } else {
+                    if (cell._visible) {
+                        ipt.setAttribute('checked', 'checked');
+                        if (cell.width == 'auto') 
                             ipt2.setAttribute('checked', 'checked');
                     } else {
                         ipt.removeAttribute('checked');
@@ -133,114 +171,123 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
 
         // update the grid based on the items selected in the picker dialog
         update : function(persist) {
-            var newCellList = [];
             var rows = dojo.query('[picker=picker]', this.dialogTable);
-
-            for(var j = 0; j < this.baseCellList.length; j++) {
-                var cell = this.baseCellList[j];
-                if(cell.selectableColumn) {
-                    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];
-                        if(selector.checked && selector.getAttribute('ident') == cell.field+''+cell.name) {
-                            if(width.checked) {
-                                cell.width = 'auto';
-                            } else {
-                                if(cell.width == 'auto')
-                                    delete cell.width;
-                            }
-                            newCellList.push(cell);
-                        }
+            var _this = this;
+            displayCells = [];
+
+            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
+
+                if (selector.checked) {
+                    cell._visible = true;
+                    if (width.checked) {
+                        cell.width = 'auto';
+                    } else if(cell.width == 'auto') {
+                        delete cell.width;
                     }
-                } else { // if it's not selectable, always show it
-                    newCellList.push(cell); 
+                    displayCells.push(cell);
+                } else {
+                    cell._visible = false;
+                    delete cell.width;
                 }
             }
 
-            this.structure[0].cells[0] = newCellList;
+            this.structure[0].cells[0] = displayCells;
             this.grid.setStructure(this.structure);
             this.grid.update();
 
-            if(persist) this.persist();
-        },
-
-        _selectableCellList : function() {
-            var cellList = this.structure[0].cells[0];
-            var cells = [];
-            for(var i = 0; i < cellList.length; i++) {
-                var cell = cellList[i];
-                if(!cell.nonSelectable) cell.selectableColumn = true;
-                if(cell.selectableColumn) 
-                    cells.push({name:cell.name, field:cell.field}); 
-            }
-            return cells;
+            if(persist) 
+                this.persist(true);
         },
 
         // save me as a user setting
-        persist : function() {
-            var cells = this.structure[0].cells[0];
+        persist : function(noRefresh) {
             var list = [];
             var autos = [];
-            for(var i = 0; i < cells.length; i++) {
-                var cell = cells[i];
-                if(cell.selectableColumn) {
+            if (!noRefresh) this.refreshCells();
+
+            for(var i = 0; i < this.cells.length; i++) {
+                var cell = this.cells[i];
+                if (cell._visible) {
                     list.push(cell.field);
                     if(cell.width == 'auto')
                         autos.push(cell.field);
-                }
+                } 
             }
+
             var setting = {};
-            setting[this.USER_PERSIST_SETTING+'.'+this.persistPrefix] = {'columns':list, 'auto':autos};
+            var setName = this.USER_PERSIST_SETTING+'.'+this.persistPrefix;
+            setting[setName] = {'columns':list, 'auto':autos};
+
             fieldmapper.standardRequest(
                 ['open-ils.actor', 'open-ils.actor.patron.settings.update'],
                 {   async: true,
                     params: [this.authtoken, null, setting],
                     oncomplete: function(r) {
                         var stat = openils.Util.readResponse(r);
+                    },
+                    onmethoderror : function() {},
+                    onerror : function() { 
+                        console.log("No user setting '" + setName + "' configured.  Cannot persist") 
                     }
                 }
             );
         }, 
 
-        _arrayHas : function(arr, val) {
-            for(var i = 0; arr && i < arr.length; i++) {
-                if(arr[i] == val)
-                    return true;
-            }
-            return false;
-        },
-
         _loadColsFromSetting : function(setting) {
+            var _this = this;
             this.setting = setting;
-            var newCellList = [];
-            for(var j = 0; j < this.baseCellList.length; j++) {
-                var cell = this.baseCellList[j];
-                if(cell.selectableColumn) {
-                    if(this._arrayHas(setting.columns, cell.field)) {
-                        newCellList.push(cell);
-                        if(this._arrayHas(setting.auto, cell.field)) {
+            var displayCells = [];
+
+            dojo.forEach(setting.columns,
+                function(col) {
+                    var cell = _this.cells.filter(function(c){return c.field == col})[0];
+                    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;
                         }
+                    } else {
+                        console.log('Unknown setting column '+col+'.  Ignoring...');
                     }
-                }  else { // if it's not selectable, always show it
-                    newCellList.push(cell); 
                 }
-            }
+            );
+            
+            // 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)
+                    cell._visible = false;
+            });
 
-            this.build();
-            this.structure[0].cells[0] = newCellList;
+            this.structure[0].cells[0] = displayCells;
             this.grid.setStructure(this.structure);
             this.grid.update();
         },
 
         load : function() {
+            var _this = this;
+
+            // if load is called before the user has logged in,
+            // queue the loading up for after authentication.
+            if (!this.authtoken) {
+                var _this = this;
+                openils.Util.addOnLoad(function() {
+                    _this.authtoken = openils.User.authtoken;
+                    _this.load()
+                }); 
+                return;
+            }
+
             if(this.setting)
                 return this._loadColsFromSetting(this.setting);
-            var picker = this;
+
             fieldmapper.standardRequest(
                 ['open-ils.actor', 'open-ils.actor.patron.settings.retrieve'],
                 {   async: true,
@@ -248,11 +295,10 @@ if(!dojo._hasResource["openils.widget.GridColumnPicker"]) {
                     oncomplete: function(r) {
                         var set = openils.Util.readResponse(r);
                         if(set) {
-                            picker._loadColsFromSetting(set);
+                            _this._loadColsFromSetting(set);
                         } else {
-                            picker.build();
-                            picker.grid.setStructure(picker.structure);
-                            picker.grid.update();
+                            _this.grid.setStructure(_this.structure);
+                            _this.grid.update();
                         }
                     }
                 }