web staff : grid infini scroll continued
authorBill Erickson <berick@esilibrary.com>
Mon, 31 Mar 2014 19:39:09 +0000 (15:39 -0400)
committerBill Erickson <berick@esilibrary.com>
Mon, 31 Mar 2014 19:39:09 +0000 (15:39 -0400)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/templates/staff/parts/t_autogrid.tt2
Open-ILS/src/templates/staff/test/t_autogrid2.tt2
Open-ILS/web/js/ui/default/staff/services/grid.js

index d3b732f..db9b271 100644 (file)
 
 </style>
 
-<div ng-show="list.items.length == 0" 
-  class="alert alert-info">[% l('No Items To Display') %]</div>
-
 <!-- Grid -->
-<div class="eg-grid" ng-show="list.items.length > 0"
+<div class="eg-grid"
   ng-class="{'eg-grid-as-conf' : showGridConf, 'eg-grid-scroll' : isScroll}">
 
   <!-- import embedded eg-grid-field defs via no-op transclude -->
         <!--
         ng-repeat="item in list.items"
         -->
+
+    <div ng-show="list.items.length == 0" 
+      class="alert alert-info">[% l('No Items To Display') %]</div>
+
     <div class="eg-grid-row" 
-        ng-scroll="item in egGridData"
+        id="eg-grid-row-{{$index + 1}}"
+        ng-show="list.items.length > 0"
+        ng-scroll="item in gridDataManager"
         ng-class="{'eg-grid-row-selected' : itemIsSelected(item)}">
       <div class="eg-grid-cell eg-grid-cell-stock" style="flex:{{indexFlex}}"
         ng-click="handleRowClick($event, item)">
-        {{$index + 1 + list.pageOffset}}
+        {{$index + gridDataManager.offset}}
       </div>
       <div class="eg-grid-cell eg-grid-cell-stock" style="flex:{{selectorFlex}}">
         <!-- ng-click=handleRowClick here has unintended 
index 7d53a5d..42ea19c 100644 (file)
@@ -5,4 +5,7 @@
   is-scroll="true"
   sort="testGridSort"
   query="testGridQuery"
-  auto-fields="true"/>
+  auto-fields="true"></eg-grid>
+
+<br/><br/>
+
index 587532d..c96733f 100644 (file)
@@ -55,9 +55,8 @@ angular.module('egGridMod',
         templateUrl : '/eg/staff/parts/t_autogrid', // TODO: avoid abs url
 
         controller : // TODO: reqs list
-            function($scope, $timeout, $element, egIDL, egAuth, egNet, egList, egGridData) { 
+            function($scope, $timeout, $location, egIDL, egAuth, egNet, egList, egGridData) { 
             var self = this;
-            self.egGridData = egGridData;
 
             // setup function. called at the end of the controller
             this.init = function() {
@@ -78,59 +77,43 @@ angular.module('egGridMod',
                     return;
                 }
 
-                $scope.list = $scope.egList || egList.create();
+                if ($scope.egList) {
+                    $scope.list = $scope.egList;
+                } else {
+                    self.selfManaged = true;
+                    $scope.list = egList.create();
+                }
 
                 if ($scope.autoFields)
                     self.compileAutoFields();
 
                 $scope.list.indexField = $scope.idField;
 
-                self.egGridData.configure({
+                $scope.gridDataManager = egGridData.create({
                     idlClass : $scope.idlClass,
                     query : $scope.query,
-                    list : $scope.list
+                    list : $scope.list,
+                    // TODO: eg_grid_offset assumes one grid per page.
+                    offset : parseInt($location.search().eg_grid_offset)
                 });
             }
 
-            // column-header click quick sort
+            // clicking on a column header performs a quick, single-column
+            // sort.  Sorts on the same column toggle between ascending
+            // and descending sort.
             $scope.sortOn = function(col_name) {
-                if ($scope.sort && $scope.sort.length &&
-                    $scope.sort[0] == col_name) {
+                var sort = $scope.gridDataManager.sort;
+                if (sort && sort.length &&
+                    sort[0] == col_name) {
                     var blob = {};
                     blob[col_name] = 'desc';
-                    $scope.sort = [blob];
+                    sort = [blob];
                 } else {
-                    $scope.sort = [col_name];
+                    sort = [col_name];
                 }
-                egGridData.sort = $scope.sort;
-                egGridData.reset();
-                //$scope.fetchData();
+                $scope.gridDataManager.applySort(sort);
             }
 
-            // maps numeric sort priority to flattener sort blob
-            // e.g. 
-            // name = 1; code = -2; type = 3
-            // compiles to:
-            // [{name : "asc"}, {code : "desc"}, {type : "asc"}]
-            this.compileSort = function() {
-
-                var sortList = $scope.list.allColumns.filter(
-                    function(col) { return Number(col.sortPriority) != 0 }
-                ).sort( 
-                    function(a, b) { 
-                        if (Math.abs(a.sortPriority) < Math.abs(b.sortPriority))
-                            return -1;
-                        return 1;
-                    }
-                );
-
-                $scope.sort = sortList.map(function(col) {
-                    var blob = {};
-                    blob[col.name] = col.sortPriority < 0 ? 'desc' : 'asc';
-                    return blob;
-                });
-            },
-
             $scope.modifyColumnFlex = function(column, val) {
                 column.flex += val;
                 // prevent flex:0;  use hiding instead
@@ -141,11 +124,7 @@ angular.module('egGridMod',
             $scope.toggleGridConf = function() {
                 if ($scope.showGridConf) {
                     $scope.showGridConf = false;
-                    self.compileSort(); 
-
-                    // config done; 
-                    // reload data in case sort priorities changed.
-                    $scope.fetchData();
+                    $scope.gridDataManager.applySort();
                 } else {
                     $scope.showGridConf = true;
                 }
@@ -177,7 +156,7 @@ angular.module('egGridMod',
                 if ($scope.egList) 
                     return $scope.list.fieldValue(item, key);
                 // if we are managing the data, then our data is flat
-                return item[key];
+                return item ? item[key] : '';
             }
 
             /**
@@ -298,39 +277,6 @@ angular.module('egGridMod',
                 return new_field;
             }
 
-            /**
-             * For stock grids, makes a flattened_search call to retrieve
-             * the requested values.
-             * For non-stock grids, calls the external data fetcher
-             */
-            $scope.fetchData = function() {
-
-                // when a list is provided, data management is 
-                // handled externally.
-                if ($scope.egList) return;
-
-                //$scope.list.resetPageData();
-
-                var queryFields = {}
-                angular.forEach($scope.list.allColumns, function(field) {
-                    if ($scope.list.displayColumns[field.name])
-                        queryFields[field.name] = field.path || field.name;
-                });
-
-                egNet.request(
-                    'open-ils.fielder',
-                    'open-ils.fielder.flattened_search',
-                    egAuth.token(), $scope.idlClass, queryFields,
-                    $scope.query,
-                    {   sort : $scope.sort,
-                        limit : self.limit,
-                        offset : self.offset
-                    }
-                ).then(null, null, function(item) {
-                    $scope.list.items.push(item);
-                });
-            }
-
             $scope.handleRowClick = function($event, item) {
                 var index = $scope.list.indexValue(item);
 
@@ -402,11 +348,13 @@ angular.module('egGridMod',
                 $scope.$apply(); // needed
             }
 
+            /*
             $scope.fetchMoreData = function() {
                 console.log('fetchMoreData');
                 self.offset += self.limit;
                 $scope.fetchData();
             }
+            */
 
             this.init();
         }
@@ -436,60 +384,109 @@ angular.module('egGridMod',
     };
 })
 
+/**
+ * Factory service for egGridDataManager instances, which are
+ * responsible for collecting flattened grid data.
+ */
 .factory('egGridData', ['egNet','egAuth',
 
     function(egNet, egAuth) {
-        var service = {};
 
-        service.configure = function(params) {
-            console.log('configure');
-            service.idlClass = params.idlClass;
-            service.query = params.query;
-            service.list = params.list;
-        }
+        // per-grid data manager class
+        function EgGridDataManager(args) {
+            var self = this;
 
-        service.reset = function() {
-            service.list.resetPageData();
-            service._rev = Math.random();
-        }
+            this.idlClass = args.idlClass;
+            this.query = args.query;
+            this.list = args.list;
+            this.offset = args.offset || 0;
+            this.version = 1;
 
-        service.revision = function() {
-            return service._rev;
-        }
+            this.reset = function() {
+                self.list.resetPageData();
+                self.version++;
+            }
 
-        service.get = function(index, count, success) {
-            var queryFields = {}
-            console.log('service.get()');
-            index -= 1; // we like zero-based
-            if (index < 0) return success([]); // hrm??
+            this.revision = function() {
+                return self.version;
+            }
 
-            angular.forEach(service.list.allColumns, function(field) {
-                if (service.list.displayColumns[field.name])
-                    queryFields[field.name] = field.path || field.name;
-            });
+            this.get = function(index, count, success) {
+                index -= 1; // make it zero-based
 
-            egNet.request(
-                'open-ils.fielder',
-                'open-ils.fielder.flattened_search',
-                egAuth.token(), service.idlClass, queryFields,
-                service.query,
-                {   sort : service.sort,
-                    limit : count,
-                    offset : index
-                }
-            ).then( 
-                function() { // oncomplete
-                    console.log(index + ' : ' + count);
-                    success(service.list.items.slice(index, index + count)); 
-                }, 
-                null, // onerror
-                function(item) { // onmessage
-                    service.list.items.push(item);
+                if (self.offset) { index += self.offset }
+                
+                if (index < 0) return success([]);
+
+                console.log('index = ' + index + ' : count = ' + count);
+
+                // we may already have the data
+                var slice = self.list.items.slice(index, index + count);
+                if (slice.length && slice[0]) return success(slice);
+
+                var queryFields = {}
+                angular.forEach(self.list.allColumns, function(field) {
+                    if (self.list.displayColumns[field.name])
+                        queryFields[field.name] = field.path || field.name;
+                });
+
+                var respIndex = index;
+                egNet.request(
+                    'open-ils.fielder',
+                    'open-ils.fielder.flattened_search',
+                    egAuth.token(), self.idlClass, queryFields,
+                    self.query,
+                    {   sort : self.sort,
+                        limit : count,
+                        offset : index
+                    }
+                ).then( 
+                    function() { // oncomplete
+                        success(self.list.items.slice(index, index + count)); 
+                    }, 
+                    null, // onerror
+                    function(item) { // onmessage
+                        self.list.items[respIndex++] = item;
+                    }
+                );
+            }
+
+            this.applySort = function(sortBlob) {
+                self.offset = 0;
+
+                if (sortBlob) {
+                    self.sort = sortBlob;
+
+                } else {
+                    // no sort provided, compile the sort blob
+                    // from the column sort priority values
+
+                    var sortList = self.list.allColumns.filter(
+                        function(col) { return Number(col.sortPriority) != 0 }
+                    ).sort( 
+                        function(a, b) { 
+                            if (Math.abs(a.sortPriority) < Math.abs(b.sortPriority))
+                                return -1;
+                            return 1;
+                        }
+                    );
+
+                    self.sort = sortList.map(function(col) {
+                        var blob = {};
+                        blob[col.name] = col.sortPriority < 0 ? 'desc' : 'asc';
+                        return blob;
+                    });
                 }
-            );
+
+                self.reset();
+            }
         }
 
-        return service;
+        return {
+            create : function(args) {
+                return new EgGridDataManager(args);
+            }
+        };
     }
 ])