diff --git a/README.md b/README.md index 6fcdaebe..524d609f 100644 --- a/README.md +++ b/README.md @@ -475,6 +475,9 @@ Pull Rerquest should include source code (./scr) changes, may include tests (./t ## Change log +### v1.7.4 + * Fixed jqLite/jQuery confrontation. + ### v1.7.3 * Fixed some html-attributes and Adapter.reload argument parsing. diff --git a/bower.json b/bower.json index 011c229d..e3d7c603 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "angular-ui-scroll", "description": "AngularJS infinite scrolling module", - "version": "1.7.3", + "version": "1.7.4", "main": "./dist/ui-scroll.js", "homepage": "https://github.com/angular-ui/ui-scroll.git", "license": "MIT", diff --git a/demo/adapterSync/server.js b/demo/adapterSync/server.js index 2d2ce191..23bb6395 100644 --- a/demo/adapterSync/server.js +++ b/demo/adapterSync/server.js @@ -1,161 +1,161 @@ -angular.module('server', []).factory('Server', - ['$timeout', '$q', function ($timeout, $q) { - - var ServerFactory = { - - firstIndex: 1, - - lastIndex: 40, - - delay: 100, - - data: [], - - absIndex: 1, - - generateId: function () { - var d = '-'; - function S4() { - return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); - } - return (S4() + S4() + d + S4() + d + S4() + d + S4() + d + S4() + S4() + S4()); - }, - - generateItem: function (index) { - return { - index: index, - id: this.generateId(), - content: 'Item #' + this.absIndex++ - } - }, - - init: function () { - for (var i = this.firstIndex; i <= this.lastIndex; i++) { - this.data.push(this.generateItem(i)); - } - }, - - getItem: function (index) { - for (var i = this.data.length - 1; i >= 0; i--) { - if (this.data[i].index === index) { - return this.data[i]; - } - } - }, - - returnDeferredResult: function (result) { - var deferred = $q.defer(); - $timeout(function () { - deferred.resolve(result); - }, this.delay); - return deferred.promise; - }, - - request: function (index, count) { - var start = index; - var end = index + count - 1; - var item, result = { - items: [] - }; - if (start <= end) { - for (var i = start; i <= end; i++) { - if (item = this.getItem(i)) { - result.items.push(item); - } - } - } - return this.returnDeferredResult(result); - }, - - prependItem: function (params) { - var newItem = this.generateItem(--this.firstIndex); - newItem.content += params; - this.data.unshift(newItem); - return this.returnDeferredResult(newItem); - }, - - appendItem: function (params) { - var newItem = this.generateItem(++this.lastIndex); - newItem.content += params; - this.data.push(newItem); - return this.returnDeferredResult(newItem); - }, - - removeFirst: function () { - var firstItem = this.data.find(i => i.index === this.firstIndex); - if(!firstItem) { - return $q.reject(); - } - return this.removeItemById(firstItem.id); - }, - - removeLast: function () { - var lastItem = this.data.find(i => i.index === this.lastIndex); - if(!lastItem) { - return $q.reject(); - } - return this.removeItemById(lastItem.id); - }, - - removeItemById: function (itemId) { - var length = this.data.length; - for (var i = 0; i < length; i++) { - if (this.data[i].id === itemId) { - var indexRemoved = this.data[i].index; - if(indexRemoved > this.firstIndex) { - for (var j = i; j < length; j++) { - this.data[j].index--; - } - } - this.data.splice(i, 1); - this.setIndices(); - return this.returnDeferredResult(indexRemoved); - } - } - return this.returnDeferredResult(false); - }, - - insertAfterIndex: function (index, params) { - if(index < this.firstIndex || index > this.lastIndex) { - return this.returnDeferredResult(null); - } - var length = this.data.length, item; - for (var i = 0; i < length; i++) { - if (this.data[i].index === index) { - for (var j = i + 1; j < length; j++) { - this.data[j].index++; - } - item = this.generateItem(index + 1); - item.content += params; - this.data.splice(i + 1, 0, item); - this.setIndices(); - return this.returnDeferredResult(item); - } - } - return this.returnDeferredResult(null); - }, - - setIndices: function () { - if(!this.data.length) { - this.firstIndex = 1; - this.lastIndex = 1; - return; - } - this.firstIndex = this.data[0].index; - this.lastIndex = this.data[0].index; - for (var i = this.data.length - 1; i >= 0; i--) { - if(this.data[i].index > this.lastIndex) { - this.lastIndex = this.data[i].index; - } - if(this.data[i].index < this.firstIndex) { - this.firstIndex = this.data[i].index; - } - } - } - }; - - ServerFactory.init(); - - return ServerFactory; - } -]); +angular.module('server', []).factory('Server', + ['$timeout', '$q', function ($timeout, $q) { + + var ServerFactory = { + + firstIndex: 1, + + lastIndex: 40, + + delay: 100, + + data: [], + + absIndex: 1, + + generateId: function () { + var d = '-'; + function S4() { + return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); + } + return (S4() + S4() + d + S4() + d + S4() + d + S4() + d + S4() + S4() + S4()); + }, + + generateItem: function (index) { + return { + index: index, + id: this.generateId(), + content: 'Item #' + this.absIndex++ + } + }, + + init: function () { + for (var i = this.firstIndex; i <= this.lastIndex; i++) { + this.data.push(this.generateItem(i)); + } + }, + + getItem: function (index) { + for (var i = this.data.length - 1; i >= 0; i--) { + if (this.data[i].index === index) { + return this.data[i]; + } + } + }, + + returnDeferredResult: function (result) { + var deferred = $q.defer(); + $timeout(function () { + deferred.resolve(result); + }, this.delay); + return deferred.promise; + }, + + request: function (index, count) { + var start = index; + var end = index + count - 1; + var item, result = { + items: [] + }; + if (start <= end) { + for (var i = start; i <= end; i++) { + if (item = this.getItem(i)) { + result.items.push(item); + } + } + } + return this.returnDeferredResult(result); + }, + + prependItem: function (params) { + var newItem = this.generateItem(--this.firstIndex); + newItem.content += params; + this.data.unshift(newItem); + return this.returnDeferredResult(newItem); + }, + + appendItem: function (params) { + var newItem = this.generateItem(++this.lastIndex); + newItem.content += params; + this.data.push(newItem); + return this.returnDeferredResult(newItem); + }, + + removeFirst: function () { + var firstItem = this.data.find(i => i.index === this.firstIndex); + if(!firstItem) { + return $q.reject(); + } + return this.removeItemById(firstItem.id); + }, + + removeLast: function () { + var lastItem = this.data.find(i => i.index === this.lastIndex); + if(!lastItem) { + return $q.reject(); + } + return this.removeItemById(lastItem.id); + }, + + removeItemById: function (itemId) { + var length = this.data.length; + for (var i = 0; i < length; i++) { + if (this.data[i].id === itemId) { + var indexRemoved = this.data[i].index; + if(indexRemoved > this.firstIndex) { + for (var j = i; j < length; j++) { + this.data[j].index--; + } + } + this.data.splice(i, 1); + this.setIndices(); + return this.returnDeferredResult(indexRemoved); + } + } + return this.returnDeferredResult(false); + }, + + insertAfterIndex: function (index, params) { + if(index < this.firstIndex || index > this.lastIndex) { + return this.returnDeferredResult(null); + } + var length = this.data.length, item; + for (var i = 0; i < length; i++) { + if (this.data[i].index === index) { + for (var j = i + 1; j < length; j++) { + this.data[j].index++; + } + item = this.generateItem(index + 1); + item.content += params; + this.data.splice(i + 1, 0, item); + this.setIndices(); + return this.returnDeferredResult(item); + } + } + return this.returnDeferredResult(null); + }, + + setIndices: function () { + if(!this.data.length) { + this.firstIndex = 1; + this.lastIndex = 1; + return; + } + this.firstIndex = this.data[0].index; + this.lastIndex = this.data[0].index; + for (var i = this.data.length - 1; i >= 0; i--) { + if(this.data[i].index > this.lastIndex) { + this.lastIndex = this.data[i].index; + } + if(this.data[i].index < this.firstIndex) { + this.firstIndex = this.data[i].index; + } + } + } + }; + + ServerFactory.init(); + + return ServerFactory; + } +]); diff --git a/demo/append/server.js b/demo/append/server.js index 51a90a86..649171ad 100644 --- a/demo/append/server.js +++ b/demo/append/server.js @@ -1,86 +1,86 @@ -angular.module('server', []).factory('Server', - ['$timeout', '$q', function($timeout, $q) { - - var ServerFactory = { - - max: 50, - - first: 1, - - delay: 100, - - data: [], - - prependedData: [], - - appendedData: [], - - generateItem: function(number) { - return { - number: number, - content: 'Item #' + number - } - }, - - init: function() { - for (var i = this.first - 1; i <= this.max; i++) { - this.data.push(this.generateItem(i)); - } - }, - - getItem: function(index) { - if (index < this.first) { - return this.prependedData[(-1) * index]; - } else if (index > this.max) { - return this.appendedData[index - this.max - 1]; - } else { - return this.data[index]; - } - }, - - request: function(index, count) { - var self = this; - var deferred = $q.defer(); - - var start = index; - var end = index + count - 1; - - $timeout(function() { - var item, result = { - items: [] - }; - if (start <= end) { - for (var i = start; i <= end; i++) { - if (item = self.getItem(i)) { - result.items.push(item); - } - } - } - deferred.resolve(result); - }, self.delay); - - return deferred.promise; - }, - - prependItem: function(params) { - var prependedDataIndex = this.first - this.prependedData.length - 1; - var newItem = this.generateItem(prependedDataIndex); - newItem.content += params; - this.prependedData.push(newItem); - return newItem; - }, - - appendItem: function(params) { - var appendedDataIndex = this.max + this.appendedData.length + 1; - var newItem = this.generateItem(appendedDataIndex); - newItem.content += params; - this.appendedData.push(newItem); - return newItem; - } - }; - - ServerFactory.init(); - - return ServerFactory; - } -]); +angular.module('server', []).factory('Server', + ['$timeout', '$q', function($timeout, $q) { + + var ServerFactory = { + + max: 50, + + first: 1, + + delay: 100, + + data: [], + + prependedData: [], + + appendedData: [], + + generateItem: function(number) { + return { + number: number, + content: 'Item #' + number + } + }, + + init: function() { + for (var i = this.first - 1; i <= this.max; i++) { + this.data.push(this.generateItem(i)); + } + }, + + getItem: function(index) { + if (index < this.first) { + return this.prependedData[(-1) * index]; + } else if (index > this.max) { + return this.appendedData[index - this.max - 1]; + } else { + return this.data[index]; + } + }, + + request: function(index, count) { + var self = this; + var deferred = $q.defer(); + + var start = index; + var end = index + count - 1; + + $timeout(function() { + var item, result = { + items: [] + }; + if (start <= end) { + for (var i = start; i <= end; i++) { + if (item = self.getItem(i)) { + result.items.push(item); + } + } + } + deferred.resolve(result); + }, self.delay); + + return deferred.promise; + }, + + prependItem: function(params) { + var prependedDataIndex = this.first - this.prependedData.length - 1; + var newItem = this.generateItem(prependedDataIndex); + newItem.content += params; + this.prependedData.push(newItem); + return newItem; + }, + + appendItem: function(params) { + var appendedDataIndex = this.max + this.appendedData.length + 1; + var newItem = this.generateItem(appendedDataIndex); + newItem.content += params; + this.appendedData.push(newItem); + return newItem; + } + }; + + ServerFactory.init(); + + return ServerFactory; + } +]); diff --git a/demo/disabled/disabled.html b/demo/disabled/disabled.html index c9b4a3b4..2b41caa4 100644 --- a/demo/disabled/disabled.html +++ b/demo/disabled/disabled.html @@ -1,44 +1,44 @@ - - - - - Disabling - - - - - - - -
- - browse other examples - -

Disabled attribute

- -
- There is an property "disabled" on the ui-scroll adapter which allows to ignore user scroll/resize events: - -
-
<div ui-scroll="item in datasource" adapter="myAdapter">{{item}}</div>
-
- Here we have two-way binding, so just set the property in appropriate time: -
-
$scope.myAdapter.disabled = true;
-
- Since "disabled" is true no user scroll is being processed by ui-scroll engine. - -
- -
- User scroll processing is {{myAdapter.disabled ? "disabled" : "enabled"}} now
- -
- -
-
{{item}}
-
- -
- + + + + + Disabling + + + + + + + +
+ + browse other examples + +

Disabled attribute

+ +
+ There is an property "disabled" on the ui-scroll adapter which allows to ignore user scroll/resize events: + +
+
<div ui-scroll="item in datasource" adapter="myAdapter">{{item}}</div>
+
+ Here we have two-way binding, so just set the property in appropriate time: +
+
$scope.myAdapter.disabled = true;
+
+ Since "disabled" is true no user scroll is being processed by ui-scroll engine. + +
+ +
+ User scroll processing is {{myAdapter.disabled ? "disabled" : "enabled"}} now
+ +
+ +
+
{{item}}
+
+ +
+ \ No newline at end of file diff --git a/demo/disabled/disabled.js b/demo/disabled/disabled.js index 30219f1a..7c873bc8 100644 --- a/demo/disabled/disabled.js +++ b/demo/disabled/disabled.js @@ -1,18 +1,18 @@ -angular.module('application', ['ui.scroll']) - .controller('mainController', [ - '$scope', '$log', '$timeout', function ($scope, console, $timeout) { - var datasource = {}; - - datasource.get = function (index, count, success) { - $timeout(function () { - var result = []; - for (var i = index; i <= index + count - 1; i++) { - result.push("item #" + i); - } - success(result); - }, 100); - }; - - $scope.datasource = datasource; - } - ]); +angular.module('application', ['ui.scroll']) + .controller('mainController', [ + '$scope', '$log', '$timeout', function ($scope, console, $timeout) { + var datasource = {}; + + datasource.get = function (index, count, success) { + $timeout(function () { + var result = []; + for (var i = index; i <= index + count - 1; i++) { + result.push("item #" + i); + } + success(result); + }, 100); + }; + + $scope.datasource = datasource; + } + ]); diff --git a/demo/fixedRowHeight/fixedRowHeight.html b/demo/fixedRowHeight/fixedRowHeight.html new file mode 100644 index 00000000..827cc167 --- /dev/null +++ b/demo/fixedRowHeight/fixedRowHeight.html @@ -0,0 +1,64 @@ + + + + + + Fixed Row Height + + + + + + + + +
+ + browse other examples + +

Fixed Row Height

+ +
+

+ If the height of all the viewport rows is known and not going to be changed, + it might be passed as "row-height" attribute. + This reduces inner calculations and browser reflows, + which leads to a performance increase. +

+
+ +
+ performance decrease coefficient (0 - fastest) +
+ +
+
+
+ + {{item.text}} + + + + {{getSum(item)}} + {{getMul(item)}} + {{getText(item)}} + + +
+ {{item.text}} + + + + {{getSum(item)}} + {{getMul(item)}} + {{getText(item)}} +
+
+ +
+
+
+ + + + \ No newline at end of file diff --git a/demo/fixedRowHeight/fixedRowHeight.js b/demo/fixedRowHeight/fixedRowHeight.js new file mode 100644 index 00000000..93185574 --- /dev/null +++ b/demo/fixedRowHeight/fixedRowHeight.js @@ -0,0 +1,74 @@ +angular.module('application', ['ui.scroll']) + + .controller('MainCtrl', ($scope) => { + $scope.hello = 'Hello Main Controller!'; + + let min = -150, max = 200, delay = 0, inputs = 10; + + const getInput = index => { + const result = []; + for (let i = 0; i < inputs; i++) { + result.push({ value: ((index % 2 === 0 ? -1 : 1) * (i + 1)).toString() }); + } + return result; + } + + const data = []; + for (let i = min; i <= max; i++) { + height = 50 + (i + 1); + data.push({ + index: i, + text: 'item #' + i, + input: getInput(i) + }); + } + + $scope.datasource = { + get: (index, count, success) => { + console.log('Getting ' + count + ' items started from ' + index + '...'); + setTimeout(() => { + const result = []; + const start = Math.max(min, index); + const end = Math.min(index + count - 1, max); + if (start <= end) { + for (let i = start; i <= end; i++) { + const _item = data.find(item => item.index === i); + if (_item) { + result.push(_item); + } + } + } + console.log('Got ' + result.length + ' items [' + start + '..' + end + ']'); + success(result); + }, delay); + } + }; + + $scope.getSum = item => + item.input.reduce((a, i) => a + Number(i.value), 0); + + $scope.getMul = item => + item.input.reduce((a, i) => a * Number(i.value), 1); + + $scope.getText = item => { + const num = $scope.getMul(item).toString(); + const result = []; + for (let i = 0; i < item.text.length; i++) { + result.push(item.text[i]); + result.push(i < num.length ? num[i] : 'x'); + } + return result.join(''); + } + + const perfSlowCountDefault = 2; + $scope.perfSlowCount = perfSlowCountDefault; + $scope.perfSlowCountList = []; + $scope.$watch('perfSlowCount', () => { + let size = Number($scope.perfSlowCount); + if (isNaN(size)) { + size = perfSlowCountDefault; + } + $scope.perfSlowCountList = (new Array(size)).fill(0); + }) + + }); diff --git a/demo/grid-dnd-widths/grid-dnd-widths.html b/demo/grid-dnd-widths/grid-dnd-widths.html index 06f05182..678a0bb1 100644 --- a/demo/grid-dnd-widths/grid-dnd-widths.html +++ b/demo/grid-dnd-widths/grid-dnd-widths.html @@ -1,55 +1,55 @@ - - - - - Grid dnd widths - - - - - - - - -
- - browse other examples - -

Grid drag and drop widths

- -
- To manipulate grid columns widths .css method on gridAdapter column is available: -
-
-$scope.adapter.gridAdapter.columns[0].css('width', '200px');
-
- You also can set any css property this way. -
- - - - - - - - - - - - - - -
- num - - text
{{item.col1}}{{item.col2}}
- -
- + + + + + Grid dnd widths + + + + + + + + +
+ + browse other examples + +

Grid drag and drop widths

+ +
+ To manipulate grid columns widths .css method on gridAdapter column is available: +
+
+$scope.adapter.gridAdapter.columns[0].css('width', '200px');
+
+ You also can set any css property this way. +
+ + + + + + + + + + + + + + +
+ num + + text
{{item.col1}}{{item.col2}}
+ +
+ \ No newline at end of file diff --git a/demo/grid-dnd-widths/grid-dnd-widths.js b/demo/grid-dnd-widths/grid-dnd-widths.js index 9404aeca..629bcd84 100644 --- a/demo/grid-dnd-widths/grid-dnd-widths.js +++ b/demo/grid-dnd-widths/grid-dnd-widths.js @@ -1,57 +1,57 @@ -angular.module('application', ['ui.scroll', 'ui.scroll.grid']) - .controller('gridController', [ - '$scope', '$log', '$timeout', function ($scope, console, $timeout) { - var datasource = {}; - - datasource.get = function (index, count, success) { - $timeout(function () { - var result = []; - for (var i = index; i <= index + count - 1; i++) { - result.push({ - col1: i, - col2: 'item #' + i - }); - } - success(result); - }, 100); - }; - - $scope.datasource = datasource; - - var splitter = angular.element(document.getElementById('splitter')); - var startX = 0; - var right = 0; - var startDrag = false; - - $scope.dragStart = function (evt) { - if(startDrag) { - return false; - } - splitter.addClass('active'); - startDrag = true; - startX = right + evt.clientX; - }; - - $scope.dragOver = function (evt) { - if(!startDrag) { - return false; - } - - right = startX - evt.clientX; - $scope.adapter.gridAdapter.columns[1].css('width', (200 + right) + 'px'); - $scope.adapter.gridAdapter.columns[0].css('width', (80 - right) + 'px'); - splitter.css('right', '0'); - - return false; - }; - - $scope.dragDrop = function (evt) { - startDrag = false; - splitter.removeClass('active'); - } - - - } - ]); - - +angular.module('application', ['ui.scroll', 'ui.scroll.grid']) + .controller('gridController', [ + '$scope', '$log', '$timeout', function ($scope, console, $timeout) { + var datasource = {}; + + datasource.get = function (index, count, success) { + $timeout(function () { + var result = []; + for (var i = index; i <= index + count - 1; i++) { + result.push({ + col1: i, + col2: 'item #' + i + }); + } + success(result); + }, 100); + }; + + $scope.datasource = datasource; + + var splitter = angular.element(document.getElementById('splitter')); + var startX = 0; + var right = 0; + var startDrag = false; + + $scope.dragStart = function (evt) { + if(startDrag) { + return false; + } + splitter.addClass('active'); + startDrag = true; + startX = right + evt.clientX; + }; + + $scope.dragOver = function (evt) { + if(!startDrag) { + return false; + } + + right = startX - evt.clientX; + $scope.adapter.gridAdapter.columns[1].css('width', (200 + right) + 'px'); + $scope.adapter.gridAdapter.columns[0].css('width', (80 - right) + 'px'); + splitter.css('right', '0'); + + return false; + }; + + $scope.dragDrop = function (evt) { + startDrag = false; + splitter.removeClass('active'); + } + + + } + ]); + + diff --git a/demo/grid-dnd-widths/grid.css b/demo/grid-dnd-widths/grid.css index 1fe6cc7b..f5d16e11 100644 --- a/demo/grid-dnd-widths/grid.css +++ b/demo/grid-dnd-widths/grid.css @@ -1,40 +1,40 @@ -.grid { - height: 300px; -} - -.grid tbody { - width: 300px; - } - -.col1 { - width: 80px; -} - -td.col1 { - font-style: italic; -} - -.col2 { - width: 200px; -} - -.splitter{ - cursor: e-resize; - float: right; - border: 2px solid black; - height: 20px; - position: relative; - right: 0; -} - -td, th { - border: 0 dashed #999; - border-left-width: 1px; -} -th { - border-bottom-width: 1px; -} - -.active { - border: 2px solid red; +.grid { + height: 300px; +} + +.grid tbody { + width: 300px; + } + +.col1 { + width: 80px; +} + +td.col1 { + font-style: italic; +} + +.col2 { + width: 200px; +} + +.splitter{ + cursor: e-resize; + float: right; + border: 2px solid black; + height: 20px; + position: relative; + right: 0; +} + +td, th { + border: 0 dashed #999; + border-left-width: 1px; +} +th { + border-bottom-width: 1px; +} + +.active { + border: 2px solid red; } \ No newline at end of file diff --git a/demo/index.html b/demo/index.html index d2c32b7c..7db6cb35 100644 --- a/demo/index.html +++ b/demo/index.html @@ -16,6 +16,11 @@

Scroller Examples

Datasource as service +
  • + + Datasource as service with a fixed rowHeight + +
  • Datasource on scope (not as service) @@ -64,6 +69,11 @@

    Scroller Examples

    Bottom visible (Adapter)
  • +
  • + + Fixed row height (higher perfromance) + +
  • Reload datasource to specified index diff --git a/demo/insideComponent/insideComponent.html b/demo/insideComponent/insideComponent.html index 01dc6c92..37cdebf4 100644 --- a/demo/insideComponent/insideComponent.html +++ b/demo/insideComponent/insideComponent.html @@ -1,32 +1,32 @@ - - - - - Inside Angular 1.5+ component - - - - - - - -
    - - browse other examples - -

    Scroller inside Angular 1.5+ Component

    - -
    - This sample demonstrates encapsulation of the ui-scroll directive inside some custom component (Angular 1.5+). - - To demonstrate the work of the Adapter, click on any row. The text of the item should change after click. - - The controller of this Component is implemented as ES6 class. Note that this demo might not work in old browsers which don't support ES6 classes. -
    - - - -
    - - - + + + + + Inside Angular 1.5+ component + + + + + + + +
    + + browse other examples + +

    Scroller inside Angular 1.5+ Component

    + +
    + This sample demonstrates encapsulation of the ui-scroll directive inside some custom component (Angular 1.5+). + + To demonstrate the work of the Adapter, click on any row. The text of the item should change after click. + + The controller of this Component is implemented as ES6 class. Note that this demo might not work in old browsers which don't support ES6 classes. +
    + + + +
    + + + diff --git a/demo/insideComponent/insideComponent.js b/demo/insideComponent/insideComponent.js index 24c7ce6b..41a59005 100644 --- a/demo/insideComponent/insideComponent.js +++ b/demo/insideComponent/insideComponent.js @@ -1,45 +1,45 @@ -(function (angular) { - - class Ctrl { - constructor($timeout, $scope) { - this.timeout = $timeout; - this.show = true; - this.$scope = $scope; - } - - get(index, count, success) { - this.timeout(function () { - var result = []; - for (var i = index; i <= index + count - 1; i++) { - result.push({ - id: i, - name: "item #" + i - }); - } - success(result); - }, 100); - } - - update(id) { - return this.scrollAdapter.applyUpdates(function (item) { - if (item.id === id) { - item.name += " *"; - } - }); - } - } - - angular - .module('application', ['ui.scroll']) - .component('myComponent', { - controllerAs: 'ctrl', - template: - '
    ' + - '
    ' + - '
    {{item.name}}
    ' + - '
    ' + - '
    ', - controller: Ctrl - }); - -})(angular); +(function (angular) { + + class Ctrl { + constructor($timeout, $scope) { + this.timeout = $timeout; + this.show = true; + this.$scope = $scope; + } + + get(index, count, success) { + this.timeout(function () { + var result = []; + for (var i = index; i <= index + count - 1; i++) { + result.push({ + id: i, + name: "item #" + i + }); + } + success(result); + }, 100); + } + + update(id) { + return this.scrollAdapter.applyUpdates(function (item) { + if (item.id === id) { + item.name += " *"; + } + }); + } + } + + angular + .module('application', ['ui.scroll']) + .component('myComponent', { + controllerAs: 'ctrl', + template: + '
    ' + + '
    ' + + '
    {{item.name}}
    ' + + '
    ' + + '
    ', + controller: Ctrl + }); + +})(angular); diff --git a/demo/jquery/jquery.html b/demo/jquery/jquery.html new file mode 100644 index 00000000..390b9360 --- /dev/null +++ b/demo/jquery/jquery.html @@ -0,0 +1,37 @@ + + + + + jQuery + + + + + + + + +
    + + browse other examples + +

    jQuery

    + +
    + In case the Angular App works with jQuery, the ui-scroll should use jQuery. + Otherwise, the ui-scroll should use jqLiteExtras. +
    + +
    + jQuery version is {{jqueryVersion}} + jQuery is not loaded +
    + +
    +
    {{item}}
    +
    + +
    + + + \ No newline at end of file diff --git a/demo/jquery/jquery.js b/demo/jquery/jquery.js new file mode 100644 index 00000000..de5167d2 --- /dev/null +++ b/demo/jquery/jquery.js @@ -0,0 +1,21 @@ +angular.module('application', ['ui.scroll']) + .controller('mainController', [ + '$scope', '$log', '$timeout', function ($scope, console, $timeout) { + var datasource = {}; + + datasource.get = function (index, count, success) { + $timeout(function () { + var result = []; + for (var i = index; i <= index + count - 1; i++) { + result.push("item #" + i); + } + success(result); + }, 100); + }; + + $scope.datasource = datasource; + + $scope.jqueryVersion = window.jQuery && angular.element.fn && angular.element.fn.jquery; + + } + ]); diff --git a/demo/outOfBuffer/outOfBuffer.html b/demo/outOfBuffer/outOfBuffer.html index 3c639946..4fe1f3bf 100644 --- a/demo/outOfBuffer/outOfBuffer.html +++ b/demo/outOfBuffer/outOfBuffer.html @@ -1,49 +1,49 @@ - - - - - Adapter sync - - - - - - - - -
    - -
    - - - - - -
    - -
    - -
      -
    • -
      - {{$index}}: {{item.content}} ({{item.id}}) - [x] -
      -
    • -
    - -
    - + + + + + Adapter sync + + + + + + + + +
    + +
    + + + + + +
    + +
    + +
      +
    • +
      + {{$index}}: {{item.content}} ({{item.id}}) + [x] +
      +
    • +
    + +
    + \ No newline at end of file diff --git a/demo/outOfBuffer/outOfBuffer.js b/demo/outOfBuffer/outOfBuffer.js index bc932b22..0b946a01 100644 --- a/demo/outOfBuffer/outOfBuffer.js +++ b/demo/outOfBuffer/outOfBuffer.js @@ -1,217 +1,217 @@ -var app = angular.module('application', ['ui.scroll']); - -app.factory('Server', [ - '$timeout', '$q', function ($timeout, $q) { - - var ServerFactory = { - - firstIndex: 1, - - lastIndex: 40, - - delay: 100, - - data: [], - - absIndex: 1, - - generateId: function () { - var d = '-'; - function S4() { - return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); - } - return (S4() + S4() + d + S4() + d + S4() + d + S4() + d + S4() + S4() + S4()); - }, - - generateItem: function (index) { - return { - index: index, - id: this.generateId(), - content: 'Item #' + this.absIndex++ - } - }, - - init: function () { - for (var i = this.firstIndex; i <= this.lastIndex; i++) { - this.data.push(this.generateItem(i)); - } - }, - - getItem: function (index) { - for (var i = this.data.length - 1; i >= 0; i--) { - if (this.data[i].index === index) { - return this.data[i]; - } - } - }, - - returnDeferredResult: function (result) { - var deferred = $q.defer(); - $timeout(function () { - deferred.resolve(result); - }, this.delay); - return deferred.promise; - }, - - request: function (index, count) { - var start = index; - var end = index + count - 1; - var item, result = { - items: [] - }; - if (start <= end) { - for (var i = start; i <= end; i++) { - if (item = this.getItem(i)) { - result.items.push(item); - } - } - } - return this.returnDeferredResult(result); - }, - - prependItem: function (params) { - var newItem = this.generateItem(--this.firstIndex); - newItem.content += params; - this.data.unshift(newItem); - return this.returnDeferredResult(newItem); - }, - - appendItem: function (params) { - var newItem = this.generateItem(++this.lastIndex); - newItem.content += params; - this.data.push(newItem); - return this.returnDeferredResult(newItem); - }, - - removeFirst: function () { - var firstItem = this.data.find(i => i.index === this.firstIndex); - if(!firstItem) { - return; - } - return this.removeItemById(firstItem.id); - }, - - removeLast: function () { - var lastItem = this.data.find(i => i.index === this.lastIndex); - if(!lastItem) { - return; - } - return this.removeItemById(lastItem.id); - }, - - removeItemById: function (itemId) { - var length = this.data.length; - for (var i = 0; i < length; i++) { - if (this.data[i].id === itemId) { - var indexRemoved = this.data[i].index; - this.data.splice(i, 1); - this.setIndices(); - return this.returnDeferredResult(indexRemoved); - } - } - return this.returnDeferredResult(false); - }, - - setIndices: function() { - if(!this.data.length) { - this.firstIndex = 1; - this.lastIndex = 1; - return; - } - this.firstIndex = this.data[0].index; - this.lastIndex = this.data[0].index; - for (var i = this.data.length - 1; i >= 0; i--) { - if(this.data[i].index > this.lastIndex) { - this.lastIndex = this.data[i].index; - } - if(this.data[i].index < this.firstIndex) { - this.firstIndex = this.data[i].index; - } - } - } - }; - - ServerFactory.init(); - - return ServerFactory; - - } -]); - - -app.controller('mainController', [ - '$scope', 'Server', function ($scope, Server) { - - var ctrl = this; - - ctrl.datasource = { - get: function (index, count, success) { - console.log('request by index = ' + index + ', count = ' + count); - Server.request(index, count).then(function (result) { - if (result.items) { - console.log('resolved ' + result.items.length + ' items'); - } - success(result.items); - }); - } - }; - - $scope.$watch('adapter', (prev, next) => { - console.log('The adapter has been initialized'); - }); - - ctrl.prepend = function () { - Server.prependItem(' ***').then(function (newItem) { - if (ctrl.adapter.isBOF()) { - ctrl.adapter.prepend([newItem]); - } - }); - }; - - ctrl.append = function () { - Server.appendItem(' ***').then(function (newItem) { - if (ctrl.adapter.isEOF()) { - ctrl.adapter.append([newItem]); - } - }); - }; - - // todo dhilt : need to implement it properly - ctrl.removeAll = function () { - ctrl.adapter.applyUpdates(function (item) { - if (item.id) { - Server.removeItemById(item.id); - return []; - } - }); - }; - - ctrl.remove = function (itemRemove) { - Server.removeItemById(itemRemove.id).then(function (result) { - if (result !== false) { - ctrl.adapter.applyUpdates(function (item) { - if (item.id === itemRemove.id) { - return []; - } - }); - } - }); - }; - - ctrl.removeFirst = function () { - Server.removeFirst().then(function (indexRemoved) { - if (indexRemoved !== false) { - ctrl.adapter.applyUpdates(indexRemoved, []); - } - }); - }; - - ctrl.removeLast = function () { - Server.removeLast().then(function (indexRemoved) { - if (indexRemoved !== false) { - ctrl.adapter.applyUpdates(indexRemoved, []); - } - }); - }; - } -]); +var app = angular.module('application', ['ui.scroll']); + +app.factory('Server', [ + '$timeout', '$q', function ($timeout, $q) { + + var ServerFactory = { + + firstIndex: 1, + + lastIndex: 40, + + delay: 100, + + data: [], + + absIndex: 1, + + generateId: function () { + var d = '-'; + function S4() { + return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); + } + return (S4() + S4() + d + S4() + d + S4() + d + S4() + d + S4() + S4() + S4()); + }, + + generateItem: function (index) { + return { + index: index, + id: this.generateId(), + content: 'Item #' + this.absIndex++ + } + }, + + init: function () { + for (var i = this.firstIndex; i <= this.lastIndex; i++) { + this.data.push(this.generateItem(i)); + } + }, + + getItem: function (index) { + for (var i = this.data.length - 1; i >= 0; i--) { + if (this.data[i].index === index) { + return this.data[i]; + } + } + }, + + returnDeferredResult: function (result) { + var deferred = $q.defer(); + $timeout(function () { + deferred.resolve(result); + }, this.delay); + return deferred.promise; + }, + + request: function (index, count) { + var start = index; + var end = index + count - 1; + var item, result = { + items: [] + }; + if (start <= end) { + for (var i = start; i <= end; i++) { + if (item = this.getItem(i)) { + result.items.push(item); + } + } + } + return this.returnDeferredResult(result); + }, + + prependItem: function (params) { + var newItem = this.generateItem(--this.firstIndex); + newItem.content += params; + this.data.unshift(newItem); + return this.returnDeferredResult(newItem); + }, + + appendItem: function (params) { + var newItem = this.generateItem(++this.lastIndex); + newItem.content += params; + this.data.push(newItem); + return this.returnDeferredResult(newItem); + }, + + removeFirst: function () { + var firstItem = this.data.find(i => i.index === this.firstIndex); + if(!firstItem) { + return; + } + return this.removeItemById(firstItem.id); + }, + + removeLast: function () { + var lastItem = this.data.find(i => i.index === this.lastIndex); + if(!lastItem) { + return; + } + return this.removeItemById(lastItem.id); + }, + + removeItemById: function (itemId) { + var length = this.data.length; + for (var i = 0; i < length; i++) { + if (this.data[i].id === itemId) { + var indexRemoved = this.data[i].index; + this.data.splice(i, 1); + this.setIndices(); + return this.returnDeferredResult(indexRemoved); + } + } + return this.returnDeferredResult(false); + }, + + setIndices: function() { + if(!this.data.length) { + this.firstIndex = 1; + this.lastIndex = 1; + return; + } + this.firstIndex = this.data[0].index; + this.lastIndex = this.data[0].index; + for (var i = this.data.length - 1; i >= 0; i--) { + if(this.data[i].index > this.lastIndex) { + this.lastIndex = this.data[i].index; + } + if(this.data[i].index < this.firstIndex) { + this.firstIndex = this.data[i].index; + } + } + } + }; + + ServerFactory.init(); + + return ServerFactory; + + } +]); + + +app.controller('mainController', [ + '$scope', 'Server', function ($scope, Server) { + + var ctrl = this; + + ctrl.datasource = { + get: function (index, count, success) { + console.log('request by index = ' + index + ', count = ' + count); + Server.request(index, count).then(function (result) { + if (result.items) { + console.log('resolved ' + result.items.length + ' items'); + } + success(result.items); + }); + } + }; + + $scope.$watch('adapter', (prev, next) => { + console.log('The adapter has been initialized'); + }); + + ctrl.prepend = function () { + Server.prependItem(' ***').then(function (newItem) { + if (ctrl.adapter.isBOF()) { + ctrl.adapter.prepend([newItem]); + } + }); + }; + + ctrl.append = function () { + Server.appendItem(' ***').then(function (newItem) { + if (ctrl.adapter.isEOF()) { + ctrl.adapter.append([newItem]); + } + }); + }; + + // todo dhilt : need to implement it properly + ctrl.removeAll = function () { + ctrl.adapter.applyUpdates(function (item) { + if (item.id) { + Server.removeItemById(item.id); + return []; + } + }); + }; + + ctrl.remove = function (itemRemove) { + Server.removeItemById(itemRemove.id).then(function (result) { + if (result !== false) { + ctrl.adapter.applyUpdates(function (item) { + if (item.id === itemRemove.id) { + return []; + } + }); + } + }); + }; + + ctrl.removeFirst = function () { + Server.removeFirst().then(function (indexRemoved) { + if (indexRemoved !== false) { + ctrl.adapter.applyUpdates(indexRemoved, []); + } + }); + }; + + ctrl.removeLast = function () { + Server.removeLast().then(function (indexRemoved) { + if (indexRemoved !== false) { + ctrl.adapter.applyUpdates(indexRemoved, []); + } + }); + }; + } +]); diff --git a/demo/remote/remote.html b/demo/remote/remote.html index d589fb11..2b3f0079 100644 --- a/demo/remote/remote.html +++ b/demo/remote/remote.html @@ -1,34 +1,34 @@ - - - - - - Remote server emulation - - - - - - - -
    - browse other examples -

    Remote server emulation

    -
    - This demo implements Remote server emulation factory, so the datasource get method looks like -
    -
    -datasource.get = function(index, count, success) {
    -  Server.request(index, count).then(success);
    -};
    -
    -
    -
    -
    - {{item.content}} -
    -
    -
    - - + + + + + + Remote server emulation + + + + + + + +
    + browse other examples +

    Remote server emulation

    +
    + This demo implements Remote server emulation factory, so the datasource get method looks like +
    +
    +datasource.get = function(index, count, success) {
    +  Server.request(index, count).then(success);
    +};
    +
    +
    +
    +
    + {{item.content}} +
    +
    +
    + + \ No newline at end of file diff --git a/demo/remote/remote.js b/demo/remote/remote.js index acf218c1..5114b0c2 100644 --- a/demo/remote/remote.js +++ b/demo/remote/remote.js @@ -1,69 +1,69 @@ -angular.module('application', ['ui.scroll']) - - .factory('Server', function($timeout, $q) { - return { - - default: { - first: 0, - max: 99, - delay: 100 - }, - - data: [], - - init: function(settings = {}) { - this.first = settings.hasOwnProperty('first') ? settings.first : this.default.first; - this.max = settings.hasOwnProperty('max') ? settings.max : this.default.max; - this.delay = settings.hasOwnProperty('delay') ? settings.delay : this.default.delay; - for (var i = this.first; i <= this.max; i++) { - this.data[i] = { - index: i, - content: 'Item #' + i - }; - } - }, - - request: function(index, count) { - var self = this; - var deferred = $q.defer(); - - var start = index; - var end = index + count - 1; - - $timeout(function() { - var item, result = []; - if (start <= end) { - for (var i = start; i <= end; i++) { - if (item = self.data[i]) { - result.push(item); - } - } - } - deferred.resolve(result); - }, self.delay); - - return deferred.promise; - } - }; - }) - - .controller('mainController', function($scope, Server) { - - $scope.firstIndex = 1; - - Server.init({ - first: $scope.firstIndex, - max: 100, - delay: 40 - }); - - $scope.datasource = { - get: function(index, count, success) { - console.log('requested index = ' + index + ', count = ' + count); - Server.request(index, count).then(function(result) { - console.log('resolved ' + result.length + ' items'); - success(result); - }); - } - }; +angular.module('application', ['ui.scroll']) + + .factory('Server', function($timeout, $q) { + return { + + default: { + first: 0, + max: 99, + delay: 100 + }, + + data: [], + + init: function(settings = {}) { + this.first = settings.hasOwnProperty('first') ? settings.first : this.default.first; + this.max = settings.hasOwnProperty('max') ? settings.max : this.default.max; + this.delay = settings.hasOwnProperty('delay') ? settings.delay : this.default.delay; + for (var i = this.first; i <= this.max; i++) { + this.data[i] = { + index: i, + content: 'Item #' + i + }; + } + }, + + request: function(index, count) { + var self = this; + var deferred = $q.defer(); + + var start = index; + var end = index + count - 1; + + $timeout(function() { + var item, result = []; + if (start <= end) { + for (var i = start; i <= end; i++) { + if (item = self.data[i]) { + result.push(item); + } + } + } + deferred.resolve(result); + }, self.delay); + + return deferred.promise; + } + }; + }) + + .controller('mainController', function($scope, Server) { + + $scope.firstIndex = 1; + + Server.init({ + first: $scope.firstIndex, + max: 100, + delay: 40 + }); + + $scope.datasource = { + get: function(index, count, success) { + console.log('requested index = ' + index + ', count = ' + count); + Server.request(index, count).then(function(result) { + console.log('resolved ' + result.length + ' items'); + success(result); + }); + } + }; }); \ No newline at end of file diff --git a/demo/serviceDatasourceRowHeight/serviceDatasource.html b/demo/serviceDatasourceRowHeight/serviceDatasource.html new file mode 100644 index 00000000..e7cab253 --- /dev/null +++ b/demo/serviceDatasourceRowHeight/serviceDatasource.html @@ -0,0 +1,41 @@ + + + + + Datasource as service + + + + + + + +
    + + browse other examples + +

    Datasource as service with fixed row height

    + +
    +

    This sample shows the optimizations provided by a fixed row height, in particular when scrolling + fast through a large list of items as it uses the scrollTo() method for a direct jump.

    + +

    To see the optimization in action, scroll down to item #500, and then scroll back to top using the scrollbar + or by pressing 'Home' or 'cmd+ArrowUp' on your keyboard.

    + + The page is identical to the standard Datasource as service + demo, with the fixed row-height attribute set for the directive: +
    +
    <li ui-scroll="item in datasource" row-height="26">{{item}}</li>
    +
    + +
    + +
    +
    {{item}}
    +
    + +
    + + + \ No newline at end of file diff --git a/demo/serviceDatasourceRowHeight/serviceDatasource.js b/demo/serviceDatasourceRowHeight/serviceDatasource.js new file mode 100644 index 00000000..b8eab711 --- /dev/null +++ b/demo/serviceDatasourceRowHeight/serviceDatasource.js @@ -0,0 +1,19 @@ +angular.module('application', ['ui.scroll']) + .factory('datasource', ['$log', '$timeout', + function (console, $timeout) { + + var get = function (index, count, success) { + $timeout(function () { + var result = []; + for (var i = index; i <= index + count - 1; i++) { + result.push("item #" + i); + } + success(result); + }, 100); + }; + + return { + get: get + }; + } + ]); diff --git a/demo/userIndexes/userIndexes.html b/demo/userIndexes/userIndexes.html index f6dcdfdc..0d62dfcf 100644 --- a/demo/userIndexes/userIndexes.html +++ b/demo/userIndexes/userIndexes.html @@ -1,57 +1,57 @@ - - - - - User min and max indexes - - - - - - - - -
    - - browse other examples - -

    Set user min and max indexes

    - -
    - Here we provide an ability of external min and max indexes setting to let the viewport know how many items do we have. -
    -
    <li ui-scroll="item in datasource">{{item}}</li>
    -
    - Then you can play with minIndex and maxIndex properties which are being accessible on your datasource after the ui-scroll directive is linked: -
    -
    -datasource.minIndex = -100;
    -datasource.maxIndex = 100;
    -
    - Such setting does not not lead to data fetching but the scroll bar params do match datasource size defined this way. -
    - -
    - - minIndex value to set -
    - - maxIndex value to set -
    - -
    - -
    -
    {{item}}
    -
    - -
    - - + + + + + User min and max indexes + + + + + + + + +
    + + browse other examples + +

    Set user min and max indexes

    + +
    + Here we provide an ability of external min and max indexes setting to let the viewport know how many items do we have. +
    +
    <li ui-scroll="item in datasource">{{item}}</li>
    +
    + Then you can play with minIndex and maxIndex properties which are being accessible on your datasource after the ui-scroll directive is linked: +
    +
    +datasource.minIndex = -100;
    +datasource.maxIndex = 100;
    +
    + Such setting does not not lead to data fetching but the scroll bar params do match datasource size defined this way. +
    + +
    + + minIndex value to set +
    + + maxIndex value to set +
    + +
    + +
    +
    {{item}}
    +
    + +
    + + \ No newline at end of file diff --git a/demo/userIndexes/userIndexes.js b/demo/userIndexes/userIndexes.js index 7a1e5720..93f35c68 100644 --- a/demo/userIndexes/userIndexes.js +++ b/demo/userIndexes/userIndexes.js @@ -1,42 +1,42 @@ -angular.module('application', ['ui.scroll']) - .controller('mainController', [ - '$scope', '$log', '$timeout', function ($scope, console, $timeout) { - var datasource = {}; - - datasource.get = function (index, count, success) { - $timeout(function () { - var result = []; - for (var i = index; i <= index + count - 1; i++) { - result.push("item #" + i); - } - success(result); - }, 100); - }; - - $scope.datasource = datasource; - $scope.adapter = {}; - - $scope.setUserMinIndex = function () { - var userMinIndex = parseInt($scope.userMinIndex, 10); - if(!isNaN(userMinIndex)) - $scope.datasource.minIndex = userMinIndex; - }; - - $scope.setUserMaxIndex = function () { - var userMaxIndex = parseInt($scope.userMaxIndex, 10); - if(!isNaN(userMaxIndex)) - $scope.datasource.maxIndex = userMaxIndex; - }; - - $scope.setUserIndexes = function () { - $scope.setUserMinIndex(); - $scope.setUserMaxIndex(); - }; - - $scope.delay = false; - $timeout(function() { - $scope.delay = true; - }, 500); - - } +angular.module('application', ['ui.scroll']) + .controller('mainController', [ + '$scope', '$log', '$timeout', function ($scope, console, $timeout) { + var datasource = {}; + + datasource.get = function (index, count, success) { + $timeout(function () { + var result = []; + for (var i = index; i <= index + count - 1; i++) { + result.push("item #" + i); + } + success(result); + }, 100); + }; + + $scope.datasource = datasource; + $scope.adapter = {}; + + $scope.setUserMinIndex = function () { + var userMinIndex = parseInt($scope.userMinIndex, 10); + if(!isNaN(userMinIndex)) + $scope.datasource.minIndex = userMinIndex; + }; + + $scope.setUserMaxIndex = function () { + var userMaxIndex = parseInt($scope.userMaxIndex, 10); + if(!isNaN(userMaxIndex)) + $scope.datasource.maxIndex = userMaxIndex; + }; + + $scope.setUserIndexes = function () { + $scope.setUserMinIndex(); + $scope.setUserMaxIndex(); + }; + + $scope.delay = false; + $timeout(function() { + $scope.delay = true; + }, 500); + + } ]); \ No newline at end of file diff --git a/dist/ui-scroll-grid.js b/dist/ui-scroll-grid.js index f69f8807..0199247b 100644 --- a/dist/ui-scroll-grid.js +++ b/dist/ui-scroll-grid.js @@ -1,7 +1,7 @@ /*! * angular-ui-scroll * https://github.com/angular-ui/ui-scroll - * Version: 1.7.3 -- 2019-05-27T16:57:07.461Z + * Version: 1.7.4 -- 2019-08-26T15:34:13.140Z * License: MIT */ /******/ (function(modules) { // webpackBootstrap diff --git a/dist/ui-scroll-jqlite.js b/dist/ui-scroll-jqlite.js index c542a1a4..7fae71e5 100644 --- a/dist/ui-scroll-jqlite.js +++ b/dist/ui-scroll-jqlite.js @@ -1,12 +1,12 @@ -/*! - * angular-ui-scroll - * https://github.com/angular-ui/ui-scroll.git - * This module is deprecated since 1.6.0 and will be removed in future versions! - * License: MIT - */ -(function () { - 'use strict'; - - angular.module('ui.scroll.jqlite', []); - +/*! + * angular-ui-scroll + * https://github.com/angular-ui/ui-scroll.git + * This module is deprecated since 1.6.0 and will be removed in future versions! + * License: MIT + */ +(function () { + 'use strict'; + + angular.module('ui.scroll.jqlite', []); + })(); \ No newline at end of file diff --git a/dist/ui-scroll-jqlite.min.js b/dist/ui-scroll-jqlite.min.js index c542a1a4..7fae71e5 100644 --- a/dist/ui-scroll-jqlite.min.js +++ b/dist/ui-scroll-jqlite.min.js @@ -1,12 +1,12 @@ -/*! - * angular-ui-scroll - * https://github.com/angular-ui/ui-scroll.git - * This module is deprecated since 1.6.0 and will be removed in future versions! - * License: MIT - */ -(function () { - 'use strict'; - - angular.module('ui.scroll.jqlite', []); - +/*! + * angular-ui-scroll + * https://github.com/angular-ui/ui-scroll.git + * This module is deprecated since 1.6.0 and will be removed in future versions! + * License: MIT + */ +(function () { + 'use strict'; + + angular.module('ui.scroll.jqlite', []); + })(); \ No newline at end of file diff --git a/dist/ui-scroll.js b/dist/ui-scroll.js index 6a791810..8133dc1b 100644 --- a/dist/ui-scroll.js +++ b/dist/ui-scroll.js @@ -1,7 +1,7 @@ /*! * angular-ui-scroll * https://github.com/angular-ui/ui-scroll - * Version: 1.7.3 -- 2019-05-27T16:57:07.461Z + * Version: 1.7.4 -- 2019-08-26T15:34:13.140Z * License: MIT */ /******/ (function(modules) { // webpackBootstrap @@ -113,15 +113,15 @@ function _defineProperties(target, props) { for (var i = 0; i < props.length; i+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } -/*! - globals: angular, window - List of used element methods available in JQuery but not in JQuery Lite - element.before(elem) - element.height() - element.outerHeight(true) - element.height(value) = only for Top/Bottom padding elements - element.scrollTop() - element.scrollTop(value) +/*! + globals: angular, window + List of used element methods available in JQuery but not in JQuery Lite + element.before(elem) + element.height() + element.outerHeight(true) + element.height(value) = only for Top/Bottom padding elements + element.scrollTop() + element.scrollTop(value) */ var jqLiteExtras_JQLiteExtras = /*#__PURE__*/ @@ -342,8 +342,8 @@ function () { return getWidthHeight(this[0], 'width', option ? 'outerfull' : 'outer'); }, - /* - The offset setter method is not implemented + /* + The offset setter method is not implemented */ offset: function offset(value) { var docElem, win; @@ -509,7 +509,7 @@ function () { // CONCATENATED MODULE: ./src/modules/buffer.js -function ScrollBuffer(elementRoutines, bufferSize, startIndex) { +function ScrollBuffer(elementRoutines, bufferSize, startIndex, rowHeight) { var buffer = Object.create(Array.prototype); angular.extend(buffer, { size: bufferSize, @@ -519,11 +519,23 @@ function ScrollBuffer(elementRoutines, bufferSize, startIndex) { buffer.bof = false; buffer.first = startIndex; buffer.next = startIndex; - buffer.minIndex = startIndex; + buffer.minIndex = startIndex; // Calculated when data is effectively accessed + buffer.maxIndex = startIndex; - buffer.minIndexUser = null; + buffer.minIndexUser = null; // as set by the user (datasource) + buffer.maxIndexUser = null; }, + // PHIL: set the new index to be displayed without resettng the sroll and the calculated min/max + // Note that this actually make sense with a fixed rowHeight when the scroll value can be calculated + // for a # of rows + resetStartIndex: function resetStartIndex(startIndex) { + buffer.remove(0, buffer.length); + buffer.eof = buffer.eof && startIndex == buffer.maxIndex; + buffer.bof = buffer.bof && startIndex == buffer.minIndex; + buffer.first = startIndex; + buffer.next = startIndex; + }, append: function append(items) { items.forEach(function (item) { ++buffer.next; @@ -539,11 +551,11 @@ function ScrollBuffer(elementRoutines, bufferSize, startIndex) { buffer.minIndex = buffer.bof ? buffer.minIndex = buffer.first : Math.min(buffer.first, buffer.minIndex); }, - /** - * inserts wrapped element in the buffer - * the first argument is either operation keyword (see below) or a number for operation 'insert' - * for insert the number is the index for the buffer element the new one have to be inserted after - * operations: 'append', 'prepend', 'insert', 'remove', 'update', 'none' + /** + * inserts wrapped element in the buffer + * the first argument is either operation keyword (see below) or a number for operation 'insert' + * for insert the number is the index for the buffer element the new one have to be inserted after + * operations: 'append', 'prepend', 'insert', 'remove', 'update', 'none' */ insert: function insert(operation, item, isTop) { var wrapper = { @@ -601,8 +613,9 @@ function ScrollBuffer(elementRoutines, bufferSize, startIndex) { } if (!buffer.length) { - buffer.first = 1; - buffer.next = 1; + buffer.first = buffer.minIndex % 1 ? buffer.minIndex : startIndex; + buffer.next = buffer.first; + buffer.eof = buffer.eof && buffer.first == buffer.maxIndex; } return elementRoutines.removeElementAnimated(arg1); @@ -653,10 +666,33 @@ function ScrollBuffer(elementRoutines, bufferSize, startIndex) { if (wrapper.element[0].offsetParent) { // element style is not display:none top = Math.min(top, wrapper.element.offset().top); - bottom = Math.max(bottom, wrapper.element.offset().top + wrapper.element.outerHeight(true)); + bottom = Math.max(bottom, wrapper.element.offset().top + (rowHeight || wrapper.element.outerHeight(true))); } }); return Math.max(0, bottom - top); + }, + getItems: function getItems() { + return buffer.filter(function (item) { + return item.op === 'none'; + }); + }, + getFirstItem: function getFirstItem() { + var list = buffer.getItems(); + + if (!list.length) { + return null; + } + + return list[0].item; + }, + getLastItem: function getLastItem() { + var list = buffer.getItems(); + + if (!list.length) { + return null; + } + + return list[list.length - 1].item; } }); buffer.reset(startIndex); @@ -764,21 +800,30 @@ function generateElement(template) { } return element; -} +} // +// Padding represents the dummy element added to both the top and the bottom of the scrolling container +// It holds the element, as well as a cache for the items (rows) height. In case of a fixed rowHeight, the +// cache is not used and thus is not created. +// + var Padding = /*#__PURE__*/ function () { - function Padding(template) { + function Padding(template, useCache) { padding_classCallCheck(this, Padding); this.element = generateElement(template); - this.cache = new Cache(); + + if (useCache) { + this.cache = new Cache(); + } } padding_createClass(Padding, [{ key: "height", value: function height() { + // When called with a parameter, this sets the height of the padding return this.element.height.apply(this.element, arguments); } }]); @@ -789,7 +834,7 @@ function () { /* harmony default export */ var modules_padding = (Padding); // CONCATENATED MODULE: ./src/modules/viewport.js -function Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding) { +function Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding, rowHeight) { var topPadding = null; var bottomPadding = null; var viewport = viewportController && viewportController.viewport ? viewportController.viewport : angular.element(window); @@ -803,15 +848,41 @@ function Viewport(elementRoutines, buffer, element, viewportController, $rootSco function bufferPadding() { return viewport.outerHeight() * padding; // some extra space to initiate preload - } + } // + // Viewport measurements + // + // +----------------+ 0 + // | top | + // | padding | + // +----------------+ topDataPos() [=topPadding.height] + // | not visible | + // | items | + // +----------------+ topVisiblePos() [=viewport.scrollTop] + // | | + // | visible | + // | items | + // | | + // +----------------+ bottomVisiblePos() [=viewport.scrollTop+viewport.height] + // | not visible | + // | items | + // +----------------+ bottomDataPos() [=scrollHeight-bottomPadding.height] + // | bottom | + // | padding | + // +----------------+ scrollHeight + // + // bufferPadding is some extra space we have top & bottom to allow infinite scrolling + // bufferPadding = viewport.outerHeight() * padding + // + // bottomVisiblePos() - topVisiblePos() == viewport.outerHeight() + angular.extend(viewport, { getScope: function getScope() { return scope; }, createPaddingElements: function createPaddingElements(template) { - topPadding = new modules_padding(template); - bottomPadding = new modules_padding(template); + topPadding = new modules_padding(template, !rowHeight); + bottomPadding = new modules_padding(template, !rowHeight); element.before(topPadding.element); element.after(bottomPadding.element); topPadding.height(0); @@ -854,20 +925,25 @@ function Viewport(elementRoutines, buffer, element, viewportController, $rootSco clipBottom: function clipBottom() { // clip the invisible items off the bottom var overage = 0; - var overageHeight = 0; - var itemHeight = 0; var emptySpaceHeight = viewport.bottomDataPos() - viewport.bottomVisiblePos() - bufferPadding(); - for (var i = buffer.length - 1; i >= 0; i--) { - itemHeight = buffer[i].element.outerHeight(true); + if (rowHeight) { + overage = Math.min(buffer.length, Math.floor(emptySpaceHeight / rowHeight)); + } else { + var itemHeight = 0; + var overageHeight = 0; - if (overageHeight + itemHeight > emptySpaceHeight) { - break; - } + for (var i = buffer.length - 1; i >= 0; i--) { + itemHeight = buffer[i].element.outerHeight(true); + + if (overageHeight + itemHeight > emptySpaceHeight) { + break; + } - bottomPadding.cache.add(buffer[i]); - overageHeight += itemHeight; - overage++; + bottomPadding.cache.add(buffer[i]); + overageHeight += itemHeight; + overage++; + } } if (overage > 0) { @@ -884,19 +960,25 @@ function Viewport(elementRoutines, buffer, element, viewportController, $rootSco // clip the invisible items off the top var overage = 0; var overageHeight = 0; - var itemHeight = 0; var emptySpaceHeight = viewport.topVisiblePos() - viewport.topDataPos() - bufferPadding(); - for (var i = 0; i < buffer.length; i++) { - itemHeight = buffer[i].element.outerHeight(true); + if (rowHeight) { + overage = Math.min(buffer.length, Math.floor(emptySpaceHeight / rowHeight)); + overageHeight = overage * rowHeight; + } else { + var itemHeight = 0; - if (overageHeight + itemHeight > emptySpaceHeight) { - break; - } + for (var i = 0; i < buffer.length; i++) { + itemHeight = buffer[i].element.outerHeight(true); - topPadding.cache.add(buffer[i]); - overageHeight += itemHeight; - overage++; + if (overageHeight + itemHeight > emptySpaceHeight) { + break; + } + + topPadding.cache.add(buffer[i]); + overageHeight += itemHeight; + overage++; + } } if (overage > 0) { @@ -908,7 +990,36 @@ function Viewport(elementRoutines, buffer, element, viewportController, $rootSco buffer.first += overage; } }, + // PHIL: remove all the entries in the buffer without changing the scrollbar, nor the scroll position + // and update the padding accordingly + // It is designed to work with non fixed rowHeight, although it will need more tests in this area... + scrollTo: function scrollTo(first) { + if (rowHeight) { + var min = buffer.getAbsMinIndex(); + var max = buffer.getAbsMaxIndex(); + first = Math.min(Math.max(first, min), max); // Adjust the paddings before removing the elements to avoid touching the scroll top position + + topPadding.height((first - min) * rowHeight); + bottomPadding.height((max + 1 - first) * rowHeight); + buffer.resetStartIndex(first); + } else { + buffer.resetStartIndex(first); + viewport.adjustPaddings(); + } + }, adjustPaddings: function adjustPaddings() { + if (rowHeight) { + var min = buffer.getAbsMinIndex(); + var max = buffer.getAbsMaxIndex(); + topPadding.height((buffer.first - min) * rowHeight); // PHIL: next points to the next possible item, while max is the index of the last one. + // In order to make them compatible, we should add one to max + // Also, it looks like buffer is not changing maxIndex when an element is inserted/appended + // Not sure if this can have a consequence or not.... + + bottomPadding.height((max + 1 - buffer.next) * rowHeight); + return; + } + if (!buffer.length) { return; } // precise heights calculation based on items that are in buffer or that were in buffer once @@ -970,15 +1081,26 @@ function Viewport(elementRoutines, buffer, element, viewportController, $rootSco }, resetTopPadding: function resetTopPadding() { topPadding.height(0); - topPadding.cache.clear(); + + if (topPadding.cache) { + topPadding.cache.clear(); + } }, resetBottomPadding: function resetBottomPadding() { bottomPadding.height(0); - bottomPadding.cache.clear(); + + if (bottomPadding.cache) { + bottomPadding.cache.clear(); + } }, removeCacheItem: function removeCacheItem(item, isTop) { - topPadding.cache.remove(item, isTop); - bottomPadding.cache.remove(item, isTop); + if (topPadding.cache) { + topPadding.cache.remove(item, isTop); + } + + if (bottomPadding.cache) { + bottomPadding.cache.remove(item, isTop); + } }, removeItem: function removeItem(item) { this.removeCacheItem(item); @@ -1070,6 +1192,21 @@ function () { for (var _i = publicProps.length - 1; _i >= 0; _i--) { _loop(_i); + } // read-only immediately calculated public properties + + + var publicPropsImmediate = ['bufferFirst', 'bufferLast', 'bufferLength']; + + var _loop2 = function _loop2(_i2) { + Object.defineProperty(_this.publicContext, publicPropsImmediate[_i2], { + get: function get() { + return _this[publicPropsImmediate[_i2]]; + } + }); + }; + + for (var _i2 = publicPropsImmediate.length - 1; _i2 >= 0; _i2--) { + _loop2(_i2); } // non-read-only public property @@ -1120,29 +1257,33 @@ function () { } }, { key: "applyUpdates", - value: function applyUpdates(arg1, arg2) { + value: function applyUpdates(arg1, arg2, arg3) { if (typeof arg1 === 'function') { - this.applyUpdatesFunc(arg1); + this.applyUpdatesFunc(arg1, arg2); + if (arg2 && arg2.noAdjust) return; } else { - this.applyUpdatesIndex(arg1, arg2); + this.applyUpdatesIndex(arg1, arg2, arg3); + if (arg3 && arg3.noAdjust) return; } this.doAdjust(); } }, { key: "applyUpdatesFunc", - value: function applyUpdatesFunc(cb) { + value: function applyUpdatesFunc(cb, options) { var _this2 = this; this.buffer.slice(0).forEach(function (wrapper) { // we need to do it on the buffer clone, because buffer content // may change as we iterate through - _this2.applyUpdate(wrapper, cb(wrapper.item, wrapper.scope, wrapper.element)); + _this2.applyUpdate(wrapper, cb(wrapper.item, wrapper.scope, wrapper.element), options); }); } }, { key: "applyUpdatesIndex", value: function applyUpdatesIndex(index, newItems) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + if (index % 1 !== 0) { throw new Error('applyUpdates - ' + index + ' is not a valid index (should be an integer)'); } @@ -1151,13 +1292,13 @@ function () { if (_index >= 0 && _index < this.buffer.length) { - this.applyUpdate(this.buffer[_index], newItems); + this.applyUpdate(this.buffer[_index], newItems, options); } // out-of-buffer case: deletion may affect Paddings else if (index >= this.buffer.getAbsMinIndex() && index <= this.buffer.getAbsMaxIndex()) { if (angular.isArray(newItems) && !newItems.length) { - this.viewport.removeCacheItem(index, index === this.buffer.minIndex); + this.viewport.removeCacheItem(index, !options.immutableTop && index === this.buffer.minIndex); - if (index === this.buffer.getAbsMinIndex()) { + if (!options.immutableTop && index === this.buffer.getAbsMinIndex()) { this.buffer.incrementMinIndex(); } else { this.buffer.decrementMaxIndex(); @@ -1170,6 +1311,8 @@ function () { value: function applyUpdate(wrapper, newItems) { var _this3 = this; + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + if (!angular.isArray(newItems)) { return; } @@ -1181,7 +1324,7 @@ function () { })) { wrapper.op = 'remove'; - if (position === 0 && !newItems.length) { + if (!options.immutableTop && position === 0 && !newItems.length) { wrapper._op = 'isTop'; // to catch "first" edge case on remove } } @@ -1191,7 +1334,7 @@ function () { position--; } else { // 3 parameter (isTop) is to catch "first" edge case on insert - _this3.buffer.insert(position + 1, newItem, position === -1); + _this3.buffer.insert(position + 1, newItem, !options.immutableTop && position === -1); } }); } @@ -1237,6 +1380,21 @@ function () { } } } + }, { + key: "bufferLength", + get: function get() { + return this.buffer.getItems().length; + } + }, { + key: "bufferFirst", + get: function get() { + return this.buffer.getFirstItem(); + } + }, { + key: "bufferLast", + get: function get() { + return this.buffer.getLastItem(); + } }]); return Adapter; @@ -1250,7 +1408,8 @@ function () { angular.module('ui.scroll', []).constant('JQLiteExtras', jqLiteExtras_JQLiteExtras).run(['JQLiteExtras', function (JQLiteExtras) { - !window.jQuery ? new JQLiteExtras().registerFor(angular.element) : null; + var elt = angular.element; + !(window.jQuery && elt.fn && elt.fn.jquery) ? new JQLiteExtras().registerFor(elt) : null; ElementRoutines.addCSSRules(); }]).directive('uiScrollViewport', function () { return { @@ -1299,31 +1458,52 @@ angular.module('ui.scroll', []).constant('JQLiteExtras', jqLiteExtras_JQLiteExtr return parseNumber(result, defaultValue, isFloat); } - var BUFFER_MIN = 3; - var BUFFER_DEFAULT = 10; - var PADDING_MIN = 0.3; - var PADDING_DEFAULT = 0.5; - var START_INDEX_DEFAULT = 1; - var MAX_VIEWPORT_DELAY = 500; - var VIEWPORT_POLLING_INTERVAL = 50; + var BUFFER_MIN = 3; // Minimum size of the data source request + + var BUFFER_DEFAULT = 10; // Default datasource request size + + var PADDING_MIN = 0.3; // Mininum # of rows in the padding area + + var PADDING_DEFAULT = 0.5; // Default # of rows in the padding area + + var START_INDEX_DEFAULT = 1; // Default start index when requestng the first data block + + var MAX_VIEWPORT_DELAY = 500; // Max time wait (ms) to get the viewport with an height>0 + + var VIEWPORT_POLLING_INTERVAL = 50; // Interval used to check the initial viewport height + var datasource = null; - var itemName = match[1]; - var datasourceName = match[2]; - var viewportController = controllers[0]; + var itemName = match[1]; // Name of the index variable to publish + + var datasourceName = match[2]; // Name of the datasource to request the rows from + + var viewportController = controllers[0]; // ViewportController, as specified in the require option (http://websystique.com/angularjs/angularjs-custom-directives-controllers-require-option-guide/) + var bufferSize = Math.max(BUFFER_MIN, parseNumericAttr($attr.bufferSize, BUFFER_DEFAULT)); var padding = Math.max(PADDING_MIN, parseNumericAttr($attr.padding, PADDING_DEFAULT, true)); - var startIndex = parseNumericAttr($attr.startIndex, START_INDEX_DEFAULT); + var startIndex = parseNumericAttr($attr.startIndex, START_INDEX_DEFAULT); // PHIL: Provide a fixed row height + // + + var rowHeight = parseNumericAttr($attr.rowHeight, null, false); // PHIL: Read the visibility watch option, true by default + + var allowVisibilityWatch = $attr.allowVisibilityWatch !== 'false'; // Revision IDs + // + var ridActual = 0; // current data revision id var pending = []; var elementRoutines = new ElementRoutines($injector, $q); - var buffer = new ScrollBuffer(elementRoutines, bufferSize, startIndex); - var viewport = new Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding); + var buffer = new ScrollBuffer(elementRoutines, bufferSize, startIndex, rowHeight); + var viewport = new Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding, rowHeight); var adapter = new modules_adapter($scope, $parse, $attr, viewport, buffer, doAdjust, reload); if (viewportController) { viewportController.adapter = adapter; - } + } // Currently, we only debounce the scroll events when a fixed rowHeight is provided + // as the unit tests will have to be adapted to support this feature + + + var scPreviousScrollTop = -1; var isDatasourceValid = function isDatasourceValid() { return Object.prototype.toString.call(datasource) === '[object Object]' && typeof datasource.get === 'function'; @@ -1473,7 +1653,12 @@ angular.module('ui.scroll', []).constant('JQLiteExtras', jqLiteExtras_JQLiteExtr function bindEvents() { viewport.bind('resize', resizeAndScrollHandler); - viewport.bind('scroll', resizeAndScrollHandler); + viewport.bind('scroll', resizeAndScrollHandler); // If a scroll event happened while the handler was not bounded, emit the scroll + + if (isPendingScroll()) { + // Do it immediately + _resizeAndScrollHandler(); + } } function unbindEvents() { @@ -1482,6 +1667,7 @@ angular.module('ui.scroll', []).constant('JQLiteExtras', jqLiteExtras_JQLiteExtr } function reload() { + unbindEvents(); viewport.resetTopPadding(); viewport.resetBottomPadding(); @@ -1490,13 +1676,21 @@ angular.module('ui.scroll', []).constant('JQLiteExtras', jqLiteExtras_JQLiteExtr } buffer.reset(startIndex); + scPreviousScrollTop = -1; // Avoid isScrollPending() to be true + persistDatasourceIndex(datasource, 'minIndex'); persistDatasourceIndex(datasource, 'maxIndex'); doAdjust(); } + function scrollTo(first) { + unbindEvents(); + viewport.scrollTo(first); + doAdjust(); + } + function isElementVisible(wrapper) { - return wrapper.element.height() && wrapper.element[0].offsetParent; + return (rowHeight || wrapper.element.height()) && wrapper.element[0].offsetParent; } function visibilityWatcher(wrapper) { @@ -1519,13 +1713,15 @@ angular.module('ui.scroll', []).constant('JQLiteExtras', jqLiteExtras_JQLiteExtr function insertWrapperContent(wrapper, insertAfter) { createElement(wrapper, insertAfter, viewport.insertElement); - if (!isElementVisible(wrapper)) { + if (allowVisibilityWatch && !isElementVisible(wrapper)) { wrapper.unregisterVisibilityWatcher = wrapper.scope.$watch(function () { return visibilityWatcher(wrapper); }); } - elementRoutines.hideElement(wrapper); // hide inserted elements before data binding + if (allowVisibilityWatch) { + elementRoutines.hideElement(wrapper); // hide inserted elements before data binding + } } function createElement(wrapper, insertAfter, insertElement) { @@ -1599,7 +1795,9 @@ angular.module('ui.scroll', []).constant('JQLiteExtras', jqLiteExtras_JQLiteExtr inserted: inserted, animated: promises }; - } + } // Adjust the viewport paddings + // + function updatePaddings(rid, updates) { // schedule another doAdjust after animation completion @@ -1614,6 +1812,17 @@ angular.module('ui.scroll', []).constant('JQLiteExtras', jqLiteExtras_JQLiteExtr } function enqueueFetch(rid, updates) { + // If there is a scroll pending, we don't enqueue the fetch as the scroll might be an absolute scroll + // So we don't need to load top or bottom + // This happens when there is a scroll frenzi, and the $digest is slow enough, so it stacks the calls without + // giving a chance to the scroll event to be emitted and processed. + // We also do that if it leads to an absolute scroll + if (isPendingScroll() && calculateAbsoluteScroll() !== undefined) { + // Looks like the event is swallowed on some browsers (FF) on some scroll configuration + resizeAndScrollHandler(); + return; + } + if (viewport.shouldLoadBottom()) { if (!updates || buffer.effectiveHeight(updates.inserted) > 0) { // this means that at least one item appended in the last batch has height > 0 @@ -1637,14 +1846,23 @@ angular.module('ui.scroll', []).constant('JQLiteExtras', jqLiteExtras_JQLiteExtr function processUpdates() { var updates = updateDOM(); // We need the item bindings to be processed before we can do adjustments + // If there are no changes and the row-height is static, then ignore it! + + var changes = updates.animated.length + updates.inserted.length + updates.prepended.length + updates.removed.length; + + if (changes || !rowHeight) { + !$scope.$$phase && !$rootScope.$$phase && $scope.$digest(); + } + + if (allowVisibilityWatch) { + updates.inserted.forEach(function (w) { + return elementRoutines.showElement(w); + }); + updates.prepended.forEach(function (w) { + return elementRoutines.showElement(w); + }); + } - !$scope.$$phase && !$rootScope.$$phase && $scope.$digest(); - updates.inserted.forEach(function (w) { - return elementRoutines.showElement(w); - }); - updates.prepended.forEach(function (w) { - return elementRoutines.showElement(w); - }); return updates; } @@ -1739,19 +1957,79 @@ angular.module('ui.scroll', []).constant('JQLiteExtras', jqLiteExtras_JQLiteExtr } } + function isPendingScroll() { + if (rowHeight) { + // Maybe the scroll changed but the event has *not* yet being dispatched + // because of the $digest running and taking to long + var sc = viewport.scrollTop(); + + if (sc != scPreviousScrollTop && scPreviousScrollTop >= 0) { + return true; + } + } + + return false; + } // Deboucing the scroll events avois intermediate $digest when scrolling fast + + + var scTimer; + function resizeAndScrollHandler() { + if (rowHeight) { + if (scTimer) clearTimeout(scTimer); + scTimer = setTimeout(_resizeAndScrollHandler, 50); + } else { + _resizeAndScrollHandler(); + } + } + + function _resizeAndScrollHandler() { if (!$rootScope.$$phase && !adapter.isLoading && !adapter.disabled) { + // Absolute positioning currently only works when a fixed rowHeight is provided + // We might isolate the averegaRowHeight calculation in the viewport to provide an estimate + // and provide a reasonable behavior with variable height as well + if (rowHeight) { + var newFirst = calculateAbsoluteScroll(); + + if (newFirst !== undefined) { + scrollTo(newFirst); + return; + } + } + enqueueFetch(ridActual); if (pending.length) { unbindEvents(); } else { adapter.calculateProperties(); - !$scope.$$phase && $scope.$digest(); + + if (!rowHeight) { + // The digest is forced to calculate the height, which is not necessary when the height is knowm + !$scope.$$phase && $scope.$digest(); + } } } } + function calculateAbsoluteScroll() { + if (rowHeight) { + scPreviousScrollTop = viewport.scrollTop(); + var newFirst = Math.floor(viewport.scrollTop() / rowHeight) + buffer.getAbsMinIndex(); + newFirst = Math.max(buffer.getAbsMinIndex(), Math.min(buffer.getAbsMaxIndex(), newFirst)); // Bound the scroll + + if (newFirst < buffer.first - bufferSize) { + return newFirst; + } + + if (newFirst > buffer.next + bufferSize) { + return newFirst; + } + } + + return undefined; + } + function wheelHandler(event) { if (!adapter.disabled) { var scrollTop = viewport[0].scrollTop; diff --git a/dist/ui-scroll.js.map b/dist/ui-scroll.js.map index ee87c1d0..526bc9b9 100644 --- a/dist/ui-scroll.js.map +++ b/dist/ui-scroll.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/modules/jqLiteExtras.js","webpack:///./src/modules/elementRoutines.js","webpack:///./src/modules/buffer.js","webpack:///./src/modules/padding.js","webpack:///./src/modules/viewport.js","webpack:///./src/modules/adapter.js","webpack:///./src/ui-scroll.js"],"names":["JQLiteExtras","element","convertToPx","css","getStyle","isWindow","angular","prototype","name","value","self","elem","nodeType","style","call","obj","document","location","alert","setInterval","scrollTo","direction","top","left","method","prop","preserve","isValueDefined","documentElement","window","getComputedStyle","parseFloat","currentStyle","result","rs","rsLeft","core_pnum","source","rnumnonpx","RegExp","test","runtimeStyle","pixelLeft","getMeasurements","measure","base","borderA","borderB","computedMarginA","computedMarginB","computedStyle","dirA","dirB","marginA","marginB","paddingA","paddingB","height","width","padding","border","margin","offsetWidth","offsetHeight","getWidthHeight","measurements","outer","outerfull","forEach","before","newElem","children","i","j","parent","ref","contents","prepend","length","after","Error","outerHTML","isNumber","outerHeight","option","outerWidth","offset","docElem","win","box","doc","ownerDocument","arguments","undefined","getBoundingClientRect","defaultView","parentWindow","pageYOffset","scrollTop","clientTop","pageXOffset","scrollLeft","clientLeft","key","hideClassToken","ElementRoutines","selector","rules","sheet","styleSheets","index","cssRules","err","insertRule","addRule","$injector","$q","$animate","has","get","isAngularVersionLessThen1_3","version","major","minor","wrapper","addClass","removeClass","newElement","previousElement","remove","scope","$destroy","insertElement","deferred","defer","enter","resolve","promise","removeElement","leave","then","ScrollBuffer","elementRoutines","bufferSize","startIndex","buffer","Object","create","Array","extend","size","reset","eof","bof","first","next","minIndex","maxIndex","minIndexUser","maxIndexUser","append","items","item","insert","Math","max","reverse","min","operation","isTop","op","splice","push","unshift","arg1","arg2","indexOf","_op","getAbsMinIndex","incrementMinIndex","decrementMaxIndex","removeElementAnimated","getAbsMaxIndex","effectiveHeight","elements","Number","MAX_VALUE","bottom","NEGATIVE_INFINITY","offsetParent","CacheProto","$index","sort","a","b","argument","_isTop","Cache","instance","apply","setPrototypeOf","getOwnPropertyNames","methodName","generateElement","template","Node","ELEMENT_NODE","tagName","toLowerCase","table","find","Padding","cache","Viewport","viewportController","$rootScope","topPadding","bottomPadding","viewport","container","bufferPadding","getScope","createPaddingElements","applyContainerStyle","bottomDataPos","scrollHeight","topDataPos","bottomVisiblePos","topVisiblePos","e","sibling","insertElementAnimated","shouldLoadBottom","clipBottom","overage","overageHeight","itemHeight","emptySpaceHeight","add","adjustPaddings","shouldLoadTop","clipTop","visibleItemsHeight","reduce","summ","topPaddingHeight","topCount","bottomPaddingHeight","bottomCount","totalHeight","averageItemHeight","adjustTopPadding","adjustBottomPadding","topPaddingHeightAdd","bottomPaddingHeightAdd","onAfterMinIndexSet","topPaddingHeightOld","diff","onAfterPrepend","updates","prepended","paddingHeight","resetTopPadding","clear","resetBottomPadding","removeCacheItem","removeItem","Adapter","$scope","$parse","$attr","doAdjust","reload","isLoading","disabled","viewportScope","startScope","$parent","publicContext","assignAdapter","adapter","generatePublicContext","adapterAttr","replace","adapterOnScope","assign","error","message","publicMethods","bind","publicProps","property","attr","defineProperty","set","newItems","applyUpdatesFunc","applyUpdatesIndex","cb","slice","applyUpdate","_index","isArray","position","some","newItem","rowTop","topHeight","topDone","bottomDone","itemTop","isEOF","module","constant","run","jQuery","registerFor","addCSSRules","directive","restrict","controller","child","console","$timeout","$interval","require","transclude","priority","terminal","link","controllers","linker","match","uiScroll","parseNumber","defaultValue","isFloat","floor","isNaN","parseNumericAttr","BUFFER_MIN","BUFFER_DEFAULT","PADDING_MIN","PADDING_DEFAULT","START_INDEX_DEFAULT","MAX_VIEWPORT_DELAY","VIEWPORT_POLLING_INTERVAL","datasource","itemName","datasourceName","ridActual","pending","isDatasourceValid","toString","onRenderHandlers","onRenderHandlersRunner","handler","persistDatasourceIndex","propName","getter","filter","id","defineDatasourceIndex","propUserName","descriptor","getOwnPropertyDescriptor","fetchNext","success","count","fetchPrevious","initialize","tryCount","timer","cancel","clone","$on","unbindEvents","unbind","wheelHandler","isInvalid","rid","$$destroyed","bindEvents","resizeAndScrollHandler","isElementVisible","visibilityWatcher","unregisterVisibilityWatcher","insertWrapperContent","insertAfter","createElement","$watch","hideElement","promises","transform","tdInitializer","uiScrollTdInitializer","linking","onLink","updateDOM","toBePrepended","toBeRemoved","inserted","concat","removed","animated","updatePaddings","all","enqueueFetch","loading","fetch","processUpdates","$$phase","$digest","w","showElement","calculateProperties","doAdjustAfterFetch","shift","event","yMax","clientHeight","preventDefault"],"mappings":"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","file":"ui-scroll.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n","/*!\r\n globals: angular, window\r\n List of used element methods available in JQuery but not in JQuery Lite\r\n element.before(elem)\r\n element.height()\r\n element.outerHeight(true)\r\n element.height(value) = only for Top/Bottom padding elements\r\n element.scrollTop()\r\n element.scrollTop(value)\r\n */\r\n\r\nexport default class JQLiteExtras {\r\n\r\n registerFor(element) {\r\n let convertToPx, css, getStyle, isWindow;\r\n // angular implementation blows up if elem is the window\r\n css = angular.element.prototype.css;\r\n\r\n element.prototype.css = function (name, value) {\r\n let self = this;\r\n let elem = self[0];\r\n if (!(!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style)) {\r\n return css.call(self, name, value);\r\n }\r\n };\r\n\r\n // as defined in angularjs v1.0.5\r\n isWindow = (obj) => obj && obj.document && obj.location && obj.alert && obj.setInterval;\r\n\r\n function scrollTo(self, direction, value) {\r\n let elem = self[0];\r\n let [method, prop, preserve] = {\r\n top: [\r\n 'scrollTop',\r\n 'pageYOffset',\r\n 'scrollLeft'\r\n ],\r\n left: [\r\n 'scrollLeft',\r\n 'pageXOffset',\r\n 'scrollTop'\r\n ]\r\n }[direction];\r\n\r\n const isValueDefined = typeof value !== 'undefined';\r\n if (isWindow(elem)) {\r\n if (isValueDefined) {\r\n return elem.scrollTo(self[preserve].call(self), value);\r\n }\r\n return (prop in elem) ? elem[prop] : elem.document.documentElement[method];\r\n } else {\r\n if (isValueDefined) {\r\n elem[method] = value;\r\n }\r\n return elem[method];\r\n }\r\n }\r\n\r\n if (window.getComputedStyle) {\r\n getStyle = (elem) => window.getComputedStyle(elem, null);\r\n convertToPx = (elem, value) => parseFloat(value);\r\n } else {\r\n getStyle = (elem) => elem.currentStyle;\r\n convertToPx = (elem, value) => {\r\n let left, result, rs, rsLeft, style;\r\n let core_pnum = /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source;\r\n let rnumnonpx = new RegExp('^(' + core_pnum + ')(?!px)[a-z%]+$', 'i');\r\n\r\n if (!rnumnonpx.test(value)) {\r\n return parseFloat(value);\r\n }\r\n\r\n // ported from JQuery\r\n style = elem.style;\r\n left = style.left;\r\n rs = elem.runtimeStyle;\r\n rsLeft = rs && rs.left;\r\n if (rs) {\r\n rs.left = style.left;\r\n }\r\n // put in the new values to get a computed style out\r\n style.left = value;\r\n result = style.pixelLeft;\r\n style.left = left;\r\n if (rsLeft) {\r\n rs.left = rsLeft;\r\n }\r\n return result;\r\n };\r\n }\r\n\r\n function getMeasurements(elem, measure) {\r\n let base, borderA, borderB, computedMarginA, computedMarginB, computedStyle, dirA, dirB, marginA, marginB, paddingA, paddingB;\r\n\r\n if (isWindow(elem)) {\r\n base = document.documentElement[{height: 'clientHeight', width: 'clientWidth'}[measure]];\r\n\r\n return {\r\n base: base,\r\n padding: 0,\r\n border: 0,\r\n margin: 0\r\n };\r\n }\r\n\r\n // Start with offset property\r\n [\r\n base,\r\n dirA,\r\n dirB\r\n ] = {\r\n width: [\r\n elem.offsetWidth,\r\n 'Left',\r\n 'Right'\r\n ],\r\n height: [\r\n elem.offsetHeight,\r\n 'Top',\r\n 'Bottom'\r\n ]\r\n }[measure];\r\n\r\n computedStyle = getStyle(elem);\r\n paddingA = convertToPx(elem, computedStyle['padding' + dirA]) || 0;\r\n paddingB = convertToPx(elem, computedStyle['padding' + dirB]) || 0;\r\n borderA = convertToPx(elem, computedStyle['border' + dirA + 'Width']) || 0;\r\n borderB = convertToPx(elem, computedStyle['border' + dirB + 'Width']) || 0;\r\n computedMarginA = computedStyle['margin' + dirA];\r\n computedMarginB = computedStyle['margin' + dirB];\r\n\r\n // I do not care for width for now, so this hack is irrelevant\r\n // if ( !supportsPercentMargin )\r\n // computedMarginA = hackPercentMargin( elem, computedStyle, computedMarginA )\r\n // computedMarginB = hackPercentMargin( elem, computedStyle, computedMarginB )\r\n marginA = convertToPx(elem, computedMarginA) || 0;\r\n marginB = convertToPx(elem, computedMarginB) || 0;\r\n\r\n return {\r\n base: base,\r\n padding: paddingA + paddingB,\r\n border: borderA + borderB,\r\n margin: marginA + marginB\r\n };\r\n }\r\n\r\n function getWidthHeight(elem, direction, measure) {\r\n let computedStyle, result;\r\n\r\n let measurements = getMeasurements(elem, direction);\r\n\r\n if (measurements.base > 0) {\r\n return {\r\n base: measurements.base - measurements.padding - measurements.border,\r\n outer: measurements.base,\r\n outerfull: measurements.base + measurements.margin\r\n }[measure];\r\n }\r\n\r\n // Fall back to computed then uncomputed css if necessary\r\n computedStyle = getStyle(elem);\r\n result = computedStyle[direction];\r\n\r\n if (result < 0 || result === null) {\r\n result = elem.style[direction] || 0;\r\n }\r\n\r\n // Normalize \"\", auto, and prepare for extra\r\n result = parseFloat(result) || 0;\r\n\r\n return {\r\n base: result - measurements.padding - measurements.border,\r\n outer: result,\r\n outerfull: result + measurements.padding + measurements.border + measurements.margin\r\n }[measure];\r\n }\r\n\r\n // define missing methods\r\n return angular.forEach({\r\n before(newElem) {\r\n var children, elem, i, j, parent, ref, self;\r\n self = this;\r\n elem = self[0];\r\n parent = self.parent();\r\n children = parent.contents();\r\n if (children[0] === elem) {\r\n return parent.prepend(newElem);\r\n } else {\r\n for (i = j = 1, ref = children.length - 1; 1 <= ref ? j <= ref : j >= ref; i = 1 <= ref ? ++j : --j) {\r\n if (children[i] === elem) {\r\n angular.element(children[i - 1]).after(newElem);\r\n return;\r\n }\r\n }\r\n throw new Error('invalid DOM structure ' + elem.outerHTML);\r\n }\r\n },\r\n height (value){\r\n var self;\r\n self = this;\r\n if (typeof value !== 'undefined') {\r\n if (angular.isNumber(value)) {\r\n value = value + 'px';\r\n }\r\n return css.call(self, 'height', value);\r\n } else {\r\n return getWidthHeight(this[0], 'height', 'base');\r\n }\r\n },\r\n outerHeight(option) {\r\n return getWidthHeight(this[0], 'height', option ? 'outerfull' : 'outer');\r\n },\r\n outerWidth(option) {\r\n return getWidthHeight(this[0], 'width', option ? 'outerfull' : 'outer');\r\n },\r\n\r\n /*\r\n The offset setter method is not implemented\r\n */\r\n offset(value) {\r\n let docElem, win;\r\n let self = this;\r\n let box = {\r\n top: 0,\r\n left: 0\r\n };\r\n let elem = self[0];\r\n let doc = elem && elem.ownerDocument;\r\n\r\n if (arguments.length) {\r\n if (value === undefined) {\r\n return self;\r\n }\r\n // TODO: implement setter\r\n throw new Error('offset setter method is not implemented');\r\n }\r\n\r\n if (!doc) {\r\n return;\r\n }\r\n\r\n docElem = doc.documentElement;\r\n\r\n // TODO: Make sure it's not a disconnected DOM node\r\n\r\n if (elem.getBoundingClientRect != null) {\r\n box = elem.getBoundingClientRect();\r\n }\r\n\r\n win = doc.defaultView || doc.parentWindow;\r\n\r\n return {\r\n top: box.top + (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0),\r\n left: box.left + (win.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)\r\n };\r\n },\r\n scrollTop(value) {\r\n return scrollTo(this, 'top', value);\r\n },\r\n scrollLeft(value) {\r\n return scrollTo(this, 'left', value);\r\n }\r\n }, (value, key) => {\r\n if (!element.prototype[key]) {\r\n return element.prototype[key] = value;\r\n }\r\n });\r\n }\r\n\r\n}\r\n","const hideClassToken = 'ng-ui-scroll-hide';\r\n\r\nexport default class ElementRoutines {\r\n\r\n static addCSSRules() {\r\n const selector = '.' + hideClassToken;\r\n const rules = 'display: none';\r\n const sheet = document.styleSheets[0];\r\n let index;\r\n try {\r\n index = sheet.cssRules.length;\r\n } catch (err) {\r\n index = 0;\r\n }\r\n if('insertRule' in sheet) {\r\n sheet.insertRule(selector + '{' + rules + '}', index);\r\n }\r\n else if('addRule' in sheet) {\r\n sheet.addRule(selector, rules, index);\r\n }\r\n }\r\n\r\n constructor($injector, $q) {\r\n this.$animate = ($injector.has && $injector.has('$animate')) ? $injector.get('$animate') : null;\r\n this.isAngularVersionLessThen1_3 = angular.version.major === 1 && angular.version.minor < 3;\r\n this.$q = $q;\r\n }\r\n\r\n hideElement(wrapper) {\r\n wrapper.element.addClass(hideClassToken);\r\n }\r\n\r\n showElement(wrapper) {\r\n wrapper.element.removeClass(hideClassToken);\r\n }\r\n\r\n insertElement(newElement, previousElement) {\r\n previousElement.after(newElement);\r\n return [];\r\n }\r\n\r\n removeElement(wrapper) {\r\n wrapper.element.remove();\r\n wrapper.scope.$destroy();\r\n return [];\r\n }\r\n\r\n insertElementAnimated(newElement, previousElement) {\r\n if (!this.$animate) {\r\n return this.insertElement(newElement, previousElement);\r\n }\r\n\r\n if (this.isAngularVersionLessThen1_3) {\r\n const deferred = this.$q.defer();\r\n // no need for parent - previous element is never null\r\n this.$animate.enter(newElement, null, previousElement, () => deferred.resolve());\r\n\r\n return [deferred.promise];\r\n }\r\n\r\n // no need for parent - previous element is never null\r\n return [this.$animate.enter(newElement, null, previousElement)];\r\n }\r\n\r\n removeElementAnimated(wrapper) {\r\n if (!this.$animate) {\r\n return this.removeElement(wrapper);\r\n }\r\n\r\n if (this.isAngularVersionLessThen1_3) {\r\n const deferred = this.$q.defer();\r\n this.$animate.leave(wrapper.element, () => {\r\n wrapper.scope.$destroy();\r\n return deferred.resolve();\r\n });\r\n\r\n return [deferred.promise];\r\n }\r\n\r\n return [(this.$animate.leave(wrapper.element)).then(() => wrapper.scope.$destroy())];\r\n }\r\n}","export default function ScrollBuffer(elementRoutines, bufferSize, startIndex) {\r\n const buffer = Object.create(Array.prototype);\r\n\r\n angular.extend(buffer, {\r\n size: bufferSize,\r\n\r\n reset(startIndex) {\r\n buffer.remove(0, buffer.length);\r\n buffer.eof = false;\r\n buffer.bof = false;\r\n buffer.first = startIndex;\r\n buffer.next = startIndex;\r\n buffer.minIndex = startIndex;\r\n buffer.maxIndex = startIndex;\r\n buffer.minIndexUser = null;\r\n buffer.maxIndexUser = null;\r\n },\r\n\r\n append(items) {\r\n items.forEach((item) => {\r\n ++buffer.next;\r\n buffer.insert('append', item);\r\n });\r\n buffer.maxIndex = buffer.eof ? buffer.next - 1 : Math.max(buffer.next - 1, buffer.maxIndex);\r\n },\r\n\r\n prepend(items) {\r\n items.reverse().forEach((item) => {\r\n --buffer.first;\r\n buffer.insert('prepend', item);\r\n });\r\n buffer.minIndex = buffer.bof ? buffer.minIndex = buffer.first : Math.min(buffer.first, buffer.minIndex);\r\n },\r\n\r\n /**\r\n * inserts wrapped element in the buffer\r\n * the first argument is either operation keyword (see below) or a number for operation 'insert'\r\n * for insert the number is the index for the buffer element the new one have to be inserted after\r\n * operations: 'append', 'prepend', 'insert', 'remove', 'update', 'none'\r\n */\r\n insert(operation, item, isTop) {\r\n const wrapper = {\r\n item: item\r\n };\r\n\r\n if (operation % 1 === 0) {// it is an insert\r\n wrapper.op = 'insert';\r\n buffer.splice(operation, 0, wrapper);\r\n if(isTop) {\r\n buffer.first--;\r\n }\r\n else {\r\n buffer.next++;\r\n }\r\n } else {\r\n wrapper.op = operation;\r\n switch (operation) {\r\n case 'append':\r\n buffer.push(wrapper);\r\n break;\r\n case 'prepend':\r\n buffer.unshift(wrapper);\r\n break;\r\n }\r\n }\r\n },\r\n\r\n // removes elements from buffer\r\n remove(arg1, arg2) {\r\n if (angular.isNumber(arg1)) {\r\n // removes items from arg1 (including) through arg2 (excluding)\r\n for (let i = arg1; i < arg2; i++) {\r\n elementRoutines.removeElement(buffer[i]);\r\n }\r\n return buffer.splice(arg1, arg2 - arg1);\r\n }\r\n // removes single item(wrapper) from the buffer\r\n buffer.splice(buffer.indexOf(arg1), 1);\r\n if(arg1._op === 'isTop' && buffer.first === this.getAbsMinIndex()) {\r\n this.incrementMinIndex();\r\n }\r\n else {\r\n this.decrementMaxIndex();\r\n }\r\n if(arg1._op === 'isTop') {\r\n buffer.first++;\r\n }\r\n else {\r\n buffer.next--;\r\n }\r\n if(!buffer.length) {\r\n buffer.first = 1;\r\n buffer.next = 1;\r\n }\r\n\r\n return elementRoutines.removeElementAnimated(arg1);\r\n },\r\n\r\n incrementMinIndex() {\r\n if(buffer.minIndexUser !== null) {\r\n if(buffer.minIndex > buffer.minIndexUser) {\r\n buffer.minIndexUser++;\r\n return;\r\n }\r\n if(buffer.minIndex === buffer.minIndexUser) {\r\n buffer.minIndexUser++;\r\n }\r\n }\r\n buffer.minIndex++;\r\n },\r\n\r\n decrementMaxIndex() {\r\n if(buffer.maxIndexUser !== null && buffer.maxIndex <= buffer.maxIndexUser) {\r\n buffer.maxIndexUser--;\r\n }\r\n buffer.maxIndex--;\r\n },\r\n\r\n getAbsMinIndex() {\r\n if(buffer.minIndexUser !== null) {\r\n return Math.min(buffer.minIndexUser, buffer.minIndex);\r\n }\r\n return buffer.minIndex;\r\n },\r\n\r\n getAbsMaxIndex() {\r\n if(buffer.maxIndexUser !== null) {\r\n return Math.max(buffer.maxIndexUser, buffer.maxIndex);\r\n }\r\n return buffer.maxIndex;\r\n },\r\n\r\n effectiveHeight(elements) {\r\n if (!elements.length) {\r\n return 0;\r\n }\r\n let top = Number.MAX_VALUE;\r\n let bottom = Number.NEGATIVE_INFINITY;\r\n elements.forEach((wrapper) => {\r\n if (wrapper.element[0].offsetParent) {\r\n // element style is not display:none\r\n top = Math.min(top, wrapper.element.offset().top);\r\n bottom = Math.max(bottom, wrapper.element.offset().top + wrapper.element.outerHeight(true));\r\n }\r\n });\r\n return Math.max(0, bottom - top);\r\n }\r\n\r\n });\r\n\r\n buffer.reset(startIndex);\r\n\r\n return buffer;\r\n}\r\n","// Can't just extend the Array, due to Babel does not support built-in classes extending\r\n// This solution was taken from https://stackoverflow.com/questions/46897414/es6-class-extends-array-workaround-for-es5-babel-transpile\r\nclass CacheProto {\r\n add(item) {\r\n for (let i = this.length - 1; i >= 0; i--) {\r\n if (this[i].index === item.scope.$index) {\r\n this[i].height = item.element.outerHeight();\r\n return;\r\n }\r\n }\r\n this.push({\r\n index: item.scope.$index,\r\n height: item.element.outerHeight()\r\n });\r\n this.sort((a, b) => ((a.index < b.index) ? -1 : ((a.index > b.index) ? 1 : 0)));\r\n }\r\n\r\n remove(argument, _isTop) {\r\n const index = argument % 1 === 0 ? argument : argument.scope.$index;\r\n const isTop = argument % 1 === 0 ? _isTop : argument._op === 'isTop';\r\n for (let i = this.length - 1; i >= 0; i--) {\r\n if (this[i].index === index) {\r\n this.splice(i, 1);\r\n break;\r\n }\r\n }\r\n if(!isTop) {\r\n for (let i = this.length - 1; i >= 0; i--) {\r\n if (this[i].index > index) {\r\n this[i].index--;\r\n }\r\n }\r\n }\r\n }\r\n\r\n clear() {\r\n this.length = 0;\r\n }\r\n}\r\n\r\nfunction Cache() {\r\n const instance = [];\r\n instance.push.apply(instance, arguments);\r\n Object.setPrototypeOf(instance, Cache.prototype);\r\n return instance;\r\n}\r\nCache.prototype = Object.create(Array.prototype);\r\nObject.getOwnPropertyNames(CacheProto.prototype).forEach(methodName =>\r\n Cache.prototype[methodName] = CacheProto.prototype[methodName]\r\n);\r\n\r\nfunction generateElement(template) {\r\n if(template.nodeType !== Node.ELEMENT_NODE) {\r\n throw new Error('ui-scroll directive requires an Element node for templating the view');\r\n }\r\n let element;\r\n switch (template.tagName.toLowerCase()) {\r\n case 'dl':\r\n throw new Error(`ui-scroll directive does not support <${template.tagName}> as a repeating tag: ${template.outerHTML}`);\r\n case 'tr':\r\n let table = angular.element('
    ');\r\n element = table.find('tr');\r\n break;\r\n case 'li':\r\n element = angular.element('
  • ');\r\n break;\r\n default:\r\n element = angular.element('
    ');\r\n }\r\n return element;\r\n}\r\n\r\nclass Padding {\r\n constructor(template) {\r\n this.element = generateElement(template);\r\n this.cache = new Cache();\r\n }\r\n\r\n height() {\r\n return this.element.height.apply(this.element, arguments);\r\n }\r\n}\r\n\r\nexport default Padding;","import Padding from './padding';\r\n\r\nexport default function Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding) {\r\n let topPadding = null;\r\n let bottomPadding = null;\r\n const viewport = viewportController && viewportController.viewport ? viewportController.viewport : angular.element(window);\r\n const container = viewportController && viewportController.container ? viewportController.container : undefined;\r\n const scope = viewportController && viewportController.scope ? viewportController.scope : $rootScope;\r\n\r\n viewport.css({\r\n 'overflow-anchor': 'none',\r\n 'overflow-y': 'auto',\r\n 'display': 'block'\r\n });\r\n\r\n function bufferPadding() {\r\n return viewport.outerHeight() * padding; // some extra space to initiate preload\r\n }\r\n\r\n angular.extend(viewport, {\r\n getScope() {\r\n return scope;\r\n },\r\n\r\n createPaddingElements(template) {\r\n topPadding = new Padding(template);\r\n bottomPadding = new Padding(template);\r\n element.before(topPadding.element);\r\n element.after(bottomPadding.element);\r\n topPadding.height(0);\r\n bottomPadding.height(0);\r\n },\r\n\r\n applyContainerStyle() {\r\n if (!container) {\r\n return true;\r\n }\r\n if(container !== viewport) {\r\n viewport.css('height', window.getComputedStyle(container[0]).height);\r\n }\r\n return viewport.height() > 0;\r\n },\r\n\r\n bottomDataPos() {\r\n let scrollHeight = viewport[0].scrollHeight;\r\n scrollHeight = scrollHeight != null ? scrollHeight : viewport[0].document.documentElement.scrollHeight;\r\n return scrollHeight - bottomPadding.height();\r\n },\r\n\r\n topDataPos() {\r\n return topPadding.height();\r\n },\r\n\r\n bottomVisiblePos() {\r\n return viewport.scrollTop() + viewport.outerHeight();\r\n },\r\n\r\n topVisiblePos() {\r\n return viewport.scrollTop();\r\n },\r\n\r\n insertElement(e, sibling) {\r\n return elementRoutines.insertElement(e, sibling || topPadding.element);\r\n },\r\n\r\n insertElementAnimated(e, sibling) {\r\n return elementRoutines.insertElementAnimated(e, sibling || topPadding.element);\r\n },\r\n\r\n shouldLoadBottom() {\r\n return !buffer.eof && viewport.bottomDataPos() < viewport.bottomVisiblePos() + bufferPadding();\r\n },\r\n\r\n clipBottom() {\r\n // clip the invisible items off the bottom\r\n let overage = 0;\r\n let overageHeight = 0;\r\n let itemHeight = 0;\r\n let emptySpaceHeight = viewport.bottomDataPos() - viewport.bottomVisiblePos() - bufferPadding();\r\n\r\n for (let i = buffer.length - 1; i >= 0; i--) {\r\n itemHeight = buffer[i].element.outerHeight(true);\r\n if (overageHeight + itemHeight > emptySpaceHeight) {\r\n break;\r\n }\r\n bottomPadding.cache.add(buffer[i]);\r\n overageHeight += itemHeight;\r\n overage++;\r\n }\r\n\r\n if (overage > 0) {\r\n buffer.eof = false;\r\n buffer.remove(buffer.length - overage, buffer.length);\r\n buffer.next -= overage;\r\n viewport.adjustPaddings();\r\n }\r\n },\r\n\r\n shouldLoadTop() {\r\n return !buffer.bof && (viewport.topDataPos() > viewport.topVisiblePos() - bufferPadding());\r\n },\r\n\r\n clipTop() {\r\n // clip the invisible items off the top\r\n let overage = 0;\r\n let overageHeight = 0;\r\n let itemHeight = 0;\r\n let emptySpaceHeight = viewport.topVisiblePos() - viewport.topDataPos() - bufferPadding();\r\n\r\n for (let i = 0; i < buffer.length; i++) {\r\n itemHeight = buffer[i].element.outerHeight(true);\r\n if (overageHeight + itemHeight > emptySpaceHeight) {\r\n break;\r\n }\r\n topPadding.cache.add(buffer[i]);\r\n overageHeight += itemHeight;\r\n overage++;\r\n }\r\n\r\n if (overage > 0) {\r\n // we need to adjust top padding element before items are removed from top\r\n // to avoid strange behaviour of scroll bar during remove top items when we are at the very bottom\r\n topPadding.height(topPadding.height() + overageHeight);\r\n buffer.bof = false;\r\n buffer.remove(0, overage);\r\n buffer.first += overage;\r\n }\r\n },\r\n\r\n adjustPaddings() {\r\n if (!buffer.length) {\r\n return;\r\n }\r\n\r\n // precise heights calculation based on items that are in buffer or that were in buffer once\r\n const visibleItemsHeight = buffer.reduce((summ, item) => summ + item.element.outerHeight(true), 0);\r\n\r\n let topPaddingHeight = 0, topCount = 0;\r\n topPadding.cache.forEach(item => {\r\n if(item.index < buffer.first) {\r\n topPaddingHeight += item.height;\r\n topCount++;\r\n }\r\n });\r\n\r\n let bottomPaddingHeight = 0, bottomCount = 0;\r\n bottomPadding.cache.forEach(item => {\r\n if(item.index >= buffer.next) {\r\n bottomPaddingHeight += item.height;\r\n bottomCount++;\r\n }\r\n });\r\n\r\n const totalHeight = visibleItemsHeight + topPaddingHeight + bottomPaddingHeight;\r\n const averageItemHeight = totalHeight / (topCount + bottomCount + buffer.length);\r\n\r\n // average heights calculation, items that have never been reached\r\n let adjustTopPadding = buffer.minIndexUser !== null && buffer.minIndex > buffer.minIndexUser;\r\n let adjustBottomPadding = buffer.maxIndexUser !== null && buffer.maxIndex < buffer.maxIndexUser;\r\n let topPaddingHeightAdd = adjustTopPadding ? (buffer.minIndex - buffer.minIndexUser) * averageItemHeight : 0;\r\n let bottomPaddingHeightAdd = adjustBottomPadding ? (buffer.maxIndexUser - buffer.maxIndex) * averageItemHeight : 0;\r\n\r\n // paddings combine adjustment\r\n topPadding.height(topPaddingHeight + topPaddingHeightAdd);\r\n bottomPadding.height(bottomPaddingHeight + bottomPaddingHeightAdd);\r\n },\r\n\r\n onAfterMinIndexSet(topPaddingHeightOld) {\r\n // additional scrollTop adjustment in case of datasource.minIndex external set\r\n if (buffer.minIndexUser !== null && buffer.minIndex > buffer.minIndexUser) {\r\n let diff = topPadding.height() - topPaddingHeightOld;\r\n viewport.scrollTop(viewport.scrollTop() + diff);\r\n while((diff -= viewport.scrollTop()) > 0) {\r\n bottomPadding.height(bottomPadding.height() + diff);\r\n viewport.scrollTop(viewport.scrollTop() + diff);\r\n }\r\n }\r\n },\r\n\r\n onAfterPrepend(updates) {\r\n if (!updates.prepended.length)\r\n return;\r\n const height = buffer.effectiveHeight(updates.prepended);\r\n const paddingHeight = topPadding.height() - height;\r\n if (paddingHeight >= 0) {\r\n topPadding.height(paddingHeight);\r\n }\r\n else {\r\n topPadding.height(0);\r\n viewport.scrollTop(viewport.scrollTop() - paddingHeight);\r\n }\r\n },\r\n\r\n resetTopPadding() {\r\n topPadding.height(0);\r\n topPadding.cache.clear();\r\n },\r\n\r\n resetBottomPadding() {\r\n bottomPadding.height(0);\r\n bottomPadding.cache.clear();\r\n },\r\n\r\n removeCacheItem(item, isTop) {\r\n topPadding.cache.remove(item, isTop);\r\n bottomPadding.cache.remove(item, isTop);\r\n },\r\n\r\n removeItem(item) {\r\n this.removeCacheItem(item);\r\n return buffer.remove(item);\r\n }\r\n });\r\n\r\n return viewport;\r\n}\r\n","class Adapter {\r\n\r\n constructor($scope, $parse, $attr, viewport, buffer, doAdjust, reload) {\r\n this.$parse = $parse;\r\n this.$attr = $attr;\r\n this.viewport = viewport;\r\n this.buffer = buffer;\r\n\r\n this.doAdjust = doAdjust;\r\n this.reload = reload;\r\n\r\n this.isLoading = false;\r\n this.disabled = false;\r\n\r\n const viewportScope = viewport.getScope();\r\n this.startScope = viewportScope.$parent ? viewportScope : $scope;\r\n\r\n this.publicContext = {};\r\n this.assignAdapter($attr.adapter);\r\n this.generatePublicContext();\r\n }\r\n\r\n assignAdapter(adapterAttr) {\r\n if (!adapterAttr || !(adapterAttr = adapterAttr.replace(/^\\s+|\\s+$/gm, ''))) {\r\n return;\r\n }\r\n let adapterOnScope;\r\n\r\n try {\r\n this.$parse(adapterAttr).assign(this.startScope, {});\r\n adapterOnScope = this.$parse(adapterAttr)(this.startScope);\r\n }\r\n catch (error) {\r\n error.message = `Angular ui-scroll Adapter assignment exception.\\n` +\r\n `Can't parse \"${adapterAttr}\" expression.\\n` +\r\n error.message;\r\n throw error;\r\n }\r\n\r\n angular.extend(adapterOnScope, this.publicContext);\r\n this.publicContext = adapterOnScope;\r\n }\r\n\r\n generatePublicContext() {\r\n // these methods will be accessible out of ui-scroll via user defined adapter\r\n const publicMethods = ['reload', 'applyUpdates', 'append', 'prepend', 'isBOF', 'isEOF', 'isEmpty'];\r\n for (let i = publicMethods.length - 1; i >= 0; i--) {\r\n this.publicContext[publicMethods[i]] = this[publicMethods[i]].bind(this);\r\n }\r\n\r\n // these read-only props will be accessible out of ui-scroll via user defined adapter\r\n const publicProps = ['isLoading', 'topVisible', 'topVisibleElement', 'topVisibleScope', 'bottomVisible', 'bottomVisibleElement', 'bottomVisibleScope'];\r\n for (let i = publicProps.length - 1; i >= 0; i--) {\r\n let property, attr = this.$attr[publicProps[i]];\r\n Object.defineProperty(this, publicProps[i], {\r\n get: () => property,\r\n set: (value) => {\r\n property = value;\r\n this.publicContext[publicProps[i]] = value;\r\n if (attr) {\r\n this.$parse(attr).assign(this.startScope, value);\r\n }\r\n }\r\n });\r\n }\r\n\r\n // non-read-only public property\r\n Object.defineProperty(this.publicContext, 'disabled', {\r\n get: () => this.disabled,\r\n set: (value) => (!(this.disabled = value)) ? this.doAdjust() : null\r\n });\r\n }\r\n\r\n loading(value) {\r\n this.isLoading = value;\r\n }\r\n\r\n isBOF() {\r\n return this.buffer.bof;\r\n }\r\n\r\n isEOF() {\r\n return this.buffer.eof;\r\n }\r\n\r\n isEmpty() {\r\n return !this.buffer.length;\r\n }\r\n\r\n append(newItems) {\r\n this.buffer.append(newItems);\r\n this.doAdjust();\r\n this.viewport.clipTop();\r\n this.viewport.clipBottom();\r\n }\r\n\r\n prepend(newItems) {\r\n this.buffer.prepend(newItems);\r\n this.doAdjust();\r\n this.viewport.clipTop();\r\n this.viewport.clipBottom();\r\n }\r\n\r\n applyUpdates(arg1, arg2) {\r\n if (typeof arg1 === 'function') {\r\n this.applyUpdatesFunc(arg1);\r\n } else {\r\n this.applyUpdatesIndex(arg1, arg2);\r\n }\r\n this.doAdjust();\r\n }\r\n\r\n applyUpdatesFunc(cb) {\r\n this.buffer.slice(0).forEach((wrapper) => {\r\n // we need to do it on the buffer clone, because buffer content\r\n // may change as we iterate through\r\n this.applyUpdate(wrapper, cb(wrapper.item, wrapper.scope, wrapper.element));\r\n });\r\n }\r\n\r\n applyUpdatesIndex(index, newItems) {\r\n if (index % 1 !== 0) {\r\n throw new Error('applyUpdates - ' + index + ' is not a valid index (should be an integer)');\r\n }\r\n const _index = index - this.buffer.first;\r\n\r\n // apply updates only within buffer\r\n if (_index >= 0 && _index < this.buffer.length) {\r\n this.applyUpdate(this.buffer[_index], newItems);\r\n }\r\n // out-of-buffer case: deletion may affect Paddings\r\n else if(index >= this.buffer.getAbsMinIndex() && index <= this.buffer.getAbsMaxIndex()) {\r\n if(angular.isArray(newItems) && !newItems.length) {\r\n this.viewport.removeCacheItem(index, index === this.buffer.minIndex);\r\n if(index === this.buffer.getAbsMinIndex()) {\r\n this.buffer.incrementMinIndex();\r\n }\r\n else {\r\n this.buffer.decrementMaxIndex();\r\n }\r\n }\r\n }\r\n }\r\n\r\n applyUpdate(wrapper, newItems) {\r\n if (!angular.isArray(newItems)) {\r\n return;\r\n }\r\n let position = this.buffer.indexOf(wrapper);\r\n if (!newItems.reverse().some(newItem => newItem === wrapper.item)) {\r\n wrapper.op = 'remove';\r\n if(position === 0 && !newItems.length) {\r\n wrapper._op = 'isTop'; // to catch \"first\" edge case on remove\r\n }\r\n }\r\n newItems.forEach((newItem) => {\r\n if (newItem === wrapper.item) {\r\n position--;\r\n } else {\r\n // 3 parameter (isTop) is to catch \"first\" edge case on insert\r\n this.buffer.insert(position + 1, newItem, position === -1);\r\n }\r\n });\r\n }\r\n\r\n calculateProperties() {\r\n let rowTop = null, topHeight = 0;\r\n let topDone = false, bottomDone = false;\r\n const length = this.buffer.length;\r\n\r\n for (let i = 0; i < length; i++) {\r\n const item = this.buffer[i];\r\n const itemTop = item.element.offset().top;\r\n\r\n if (rowTop !== itemTop) { // a new row condition\r\n const itemHeight = item.element.outerHeight(true);\r\n const top = this.viewport.topDataPos() + topHeight + itemHeight;\r\n\r\n if (!topDone && top > this.viewport.topVisiblePos()) {\r\n topDone = true;\r\n this['topVisible'] = item.item;\r\n this['topVisibleElement'] = item.element;\r\n this['topVisibleScope'] = item.scope;\r\n }\r\n if (!bottomDone && (top >= this.viewport.bottomVisiblePos() || (i === length - 1 && this.isEOF()))) {\r\n bottomDone = true;\r\n this['bottomVisible'] = item.item;\r\n this['bottomVisibleElement'] = item.element;\r\n this['bottomVisibleScope'] = item.scope;\r\n }\r\n topHeight += itemHeight;\r\n }\r\n rowTop = itemTop;\r\n\r\n if (topDone && bottomDone) {\r\n break;\r\n }\r\n }\r\n }\r\n\r\n}\r\n\r\nexport default Adapter;\r\n","import JQLiteExtras from './modules/jqLiteExtras';\nimport ElementRoutines from './modules/elementRoutines.js';\nimport ScrollBuffer from './modules/buffer.js';\nimport Viewport from './modules/viewport.js';\nimport Adapter from './modules/adapter.js';\n\nangular.module('ui.scroll', [])\n\n .constant('JQLiteExtras', JQLiteExtras)\n .run(['JQLiteExtras', (JQLiteExtras) => {\n !window.jQuery ? (new JQLiteExtras()).registerFor(angular.element) : null;\n ElementRoutines.addCSSRules();\n }])\n\n .directive('uiScrollViewport', function () {\n return {\n restrict: 'A',\n controller: [\n '$scope',\n '$element',\n function (scope, element) {\n this.container = element;\n this.viewport = element;\n this.scope = scope;\n\n angular.forEach(element.children(), child => {\n if (child.tagName.toLowerCase() === 'tbody') {\n this.viewport = angular.element(child);\n }\n });\n\n return this;\n }\n ]\n };\n })\n\n .directive('uiScroll', [\n '$log',\n '$injector',\n '$rootScope',\n '$timeout',\n '$interval',\n '$q',\n '$parse',\n function (console, $injector, $rootScope, $timeout, $interval, $q, $parse) {\n\n return {\n require: ['?^uiScrollViewport'],\n restrict: 'A',\n transclude: 'element',\n priority: 1000,\n terminal: true,\n link: link\n };\n\n function link($scope, element, $attr, controllers, linker) {\n const match = $attr.uiScroll.match(/^\\s*(\\w+)\\s+in\\s+([(\\w|\\$)\\.]+)\\s*$/);\n if (!match) {\n throw new Error('Expected uiScroll in form of \\'_item_ in _datasource_\\' but got \\'' + $attr.uiScroll + '\\'');\n }\n\n function parseNumber(value, defaultValue, isFloat) {\n if (!isFloat) {\n value = value === null ? defaultValue : Math.floor(value);\n }\n return isNaN(value) ? defaultValue : value;\n }\n\n function parseNumericAttr(value, defaultValue, isFloat) {\n const result = $parse(value)($scope);\n return parseNumber(result, defaultValue, isFloat);\n }\n\n const BUFFER_MIN = 3;\n const BUFFER_DEFAULT = 10;\n const PADDING_MIN = 0.3;\n const PADDING_DEFAULT = 0.5;\n const START_INDEX_DEFAULT = 1;\n const MAX_VIEWPORT_DELAY = 500;\n const VIEWPORT_POLLING_INTERVAL = 50;\n\n let datasource = null;\n const itemName = match[1];\n const datasourceName = match[2];\n const viewportController = controllers[0];\n const bufferSize = Math.max(BUFFER_MIN, parseNumericAttr($attr.bufferSize, BUFFER_DEFAULT));\n const padding = Math.max(PADDING_MIN, parseNumericAttr($attr.padding, PADDING_DEFAULT, true));\n let startIndex = parseNumericAttr($attr.startIndex, START_INDEX_DEFAULT);\n let ridActual = 0; // current data revision id\n let pending = [];\n\n const elementRoutines = new ElementRoutines($injector, $q);\n const buffer = new ScrollBuffer(elementRoutines, bufferSize, startIndex);\n const viewport = new Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding);\n const adapter = new Adapter($scope, $parse, $attr, viewport, buffer, doAdjust, reload);\n\n if (viewportController) {\n viewportController.adapter = adapter;\n }\n\n const isDatasourceValid = () =>\n Object.prototype.toString.call(datasource) === '[object Object]' && typeof datasource.get === 'function';\n\n datasource = $parse(datasourceName)($scope); // try to get datasource on scope\n if (!isDatasourceValid()) {\n datasource = $injector.get(datasourceName); // try to inject datasource as service\n if (!isDatasourceValid()) {\n throw new Error(datasourceName + ' is not a valid datasource');\n }\n }\n\n let onRenderHandlers = [];\n function onRenderHandlersRunner() {\n onRenderHandlers.forEach(handler => handler.run());\n onRenderHandlers = [];\n }\n function persistDatasourceIndex(datasource, propName) {\n let getter;\n // need to postpone min/maxIndexUser processing if the view is empty\n if(angular.isNumber(datasource[propName])) {\n getter = datasource[propName];\n if(angular.isNumber(getter)) {\n onRenderHandlers = onRenderHandlers.filter(handler => handler.id !== propName);\n onRenderHandlers.push({\n id: propName,\n run: () => datasource[propName] = getter\n });\n }\n }\n }\n\n function defineDatasourceIndex(datasource, propName, propUserName) {\n const descriptor = Object.getOwnPropertyDescriptor(datasource, propName);\n if (descriptor && (descriptor.set || descriptor.get)) {\n return;\n }\n let getter;\n persistDatasourceIndex(datasource, propName);\n Object.defineProperty(datasource, propName, {\n set: (value) => {\n getter = value;\n if(pending.length && !buffer.length) {\n persistDatasourceIndex(datasource, propName);\n return;\n }\n buffer[propUserName] = value;\n const topPaddingHeightOld = viewport.topDataPos();\n viewport.adjustPaddings();\n if (propName === 'minIndex') {\n viewport.onAfterMinIndexSet(topPaddingHeightOld);\n }\n },\n get: () => getter\n });\n }\n\n defineDatasourceIndex(datasource, 'minIndex', 'minIndexUser');\n defineDatasourceIndex(datasource, 'maxIndex', 'maxIndexUser');\n\n const fetchNext = (datasource.get.length !== 2) ?\n (success) => datasource.get(buffer.next, bufferSize, success) :\n (success) => {\n datasource.get({\n index: buffer.next,\n append: buffer.length ? buffer[buffer.length - 1].item : void 0,\n count: bufferSize\n }, success);\n };\n\n const fetchPrevious = (datasource.get.length !== 2) ?\n (success) => datasource.get(buffer.first - bufferSize, bufferSize, success) :\n (success) => {\n datasource.get({\n index: buffer.first - bufferSize,\n prepend: buffer.length ? buffer[0].item : void 0,\n count: bufferSize\n }, success);\n };\n\n const initialize = () => {\n let tryCount = 0;\n if(!viewport.applyContainerStyle()) {\n const timer = $interval(() => {\n tryCount++;\n if(viewport.applyContainerStyle()) {\n $interval.cancel(timer);\n doAdjust();\n }\n if(tryCount * VIEWPORT_POLLING_INTERVAL >= MAX_VIEWPORT_DELAY) {\n $interval.cancel(timer);\n throw Error(`ui-scroll directive requires a viewport with non-zero height in ${MAX_VIEWPORT_DELAY}ms`);\n }\n }, VIEWPORT_POLLING_INTERVAL);\n }\n else {\n doAdjust();\n }\n };\n\n /**\n * Build padding elements\n *\n * Calling linker is the only way I found to get access to the tag name of the template\n * to prevent the directive scope from pollution a new scope is created and destroyed\n * right after the builder creation is completed\n */\n linker((clone, scope) => {\n viewport.createPaddingElements(clone[0]);\n // we do not include the clone in the DOM. It means that the nested directives will not\n // be able to reach the parent directives, but in this case it is intentional because we\n // created the clone to access the template tag name\n scope.$destroy();\n clone.remove();\n });\n\n $scope.$on('$destroy', () => {\n unbindEvents();\n viewport.unbind('mousewheel', wheelHandler);\n });\n\n viewport.bind('mousewheel', wheelHandler);\n\n initialize();\n\n /* Private function definitions */\n\n function isInvalid(rid) {\n return (rid && rid !== ridActual) || $scope.$$destroyed;\n }\n\n function bindEvents() {\n viewport.bind('resize', resizeAndScrollHandler);\n viewport.bind('scroll', resizeAndScrollHandler);\n }\n\n function unbindEvents() {\n viewport.unbind('resize', resizeAndScrollHandler);\n viewport.unbind('scroll', resizeAndScrollHandler);\n }\n\n function reload() {\n viewport.resetTopPadding();\n viewport.resetBottomPadding();\n if (arguments.length) {\n startIndex = parseNumber(arguments[0], START_INDEX_DEFAULT, false);\n }\n buffer.reset(startIndex);\n persistDatasourceIndex(datasource, 'minIndex');\n persistDatasourceIndex(datasource, 'maxIndex');\n doAdjust();\n }\n\n function isElementVisible(wrapper) {\n return wrapper.element.height() && wrapper.element[0].offsetParent;\n }\n\n function visibilityWatcher(wrapper) {\n if (isElementVisible(wrapper)) {\n buffer.forEach((item) => {\n if (typeof item.unregisterVisibilityWatcher === 'function') {\n item.unregisterVisibilityWatcher();\n delete item.unregisterVisibilityWatcher;\n }\n });\n if (!pending.length) {\n $timeout(() => doAdjust());\n }\n }\n }\n\n function insertWrapperContent(wrapper, insertAfter) {\n createElement(wrapper, insertAfter, viewport.insertElement);\n if (!isElementVisible(wrapper)) {\n wrapper.unregisterVisibilityWatcher = wrapper.scope.$watch(() => visibilityWatcher(wrapper));\n }\n elementRoutines.hideElement(wrapper); // hide inserted elements before data binding\n }\n\n function createElement(wrapper, insertAfter, insertElement) {\n let promises = null;\n const sibling = (insertAfter > 0) ? buffer[insertAfter - 1].element : undefined;\n linker((clone, scope) => {\n promises = insertElement(clone, sibling);\n wrapper.element = clone;\n wrapper.scope = scope;\n scope[itemName] = wrapper.item;\n });\n // ui-scroll-grid apply\n if (adapter.transform) {\n const tdInitializer = wrapper.scope.uiScrollTdInitializer;\n if (tdInitializer && tdInitializer.linking) {\n adapter.transform(wrapper.scope, wrapper.element);\n } else {\n wrapper.scope.uiScrollTdInitializer = {\n onLink: () => adapter.transform(wrapper.scope, wrapper.element),\n scope: wrapper.scope\n };\n }\n }\n return promises;\n }\n\n function updateDOM() {\n let promises = [];\n const toBePrepended = [];\n const toBeRemoved = [];\n const inserted = [];\n\n buffer.forEach((wrapper, i) => {\n switch (wrapper.op) {\n case 'prepend':\n toBePrepended.unshift(wrapper);\n break;\n case 'append':\n insertWrapperContent(wrapper, i);\n wrapper.op = 'none';\n inserted.push(wrapper);\n break;\n case 'insert':\n promises = promises.concat(createElement(wrapper, i, viewport.insertElementAnimated));\n wrapper.op = 'none';\n inserted.push(wrapper);\n break;\n case 'remove':\n toBeRemoved.push(wrapper);\n }\n });\n\n toBeRemoved.forEach((wrapper) => promises = promises.concat(viewport.removeItem(wrapper)));\n\n if (toBePrepended.length)\n toBePrepended.forEach((wrapper) => {\n insertWrapperContent(wrapper);\n wrapper.op = 'none';\n });\n\n buffer.forEach((item, i) => item.scope.$index = buffer.first + i);\n\n return {\n prepended: toBePrepended,\n removed: toBeRemoved,\n inserted: inserted,\n animated: promises\n };\n\n }\n\n function updatePaddings(rid, updates) {\n // schedule another doAdjust after animation completion\n if (updates.animated.length) {\n $q.all(updates.animated).then(() => {\n viewport.adjustPaddings();\n doAdjust(rid);\n });\n } else {\n viewport.adjustPaddings();\n }\n }\n\n function enqueueFetch(rid, updates) {\n if (viewport.shouldLoadBottom()) {\n if (!updates || buffer.effectiveHeight(updates.inserted) > 0) {\n // this means that at least one item appended in the last batch has height > 0\n if (pending.push(true) === 1) {\n adapter.loading(true);\n fetch(rid);\n }\n }\n } else if (viewport.shouldLoadTop()) {\n if ((!updates || buffer.effectiveHeight(updates.prepended) > 0) || pending[0]) {\n // this means that at least one item appended in the last batch has height > 0\n // pending[0] = true means that previous fetch was appending. We need to force at least one prepend\n // BTW there will always be at least 1 element in the pending array because bottom is fetched first\n if (pending.push(false) === 1) {\n adapter.loading(true);\n fetch(rid);\n }\n }\n }\n }\n\n function processUpdates() {\n const updates = updateDOM();\n\n // We need the item bindings to be processed before we can do adjustments\n !$scope.$$phase && !$rootScope.$$phase && $scope.$digest();\n\n updates.inserted.forEach(w => elementRoutines.showElement(w));\n updates.prepended.forEach(w => elementRoutines.showElement(w));\n return updates;\n }\n\n function doAdjust(rid) {\n if (!rid) { // dismiss pending requests\n pending = [];\n rid = ++ridActual;\n }\n\n const updates = processUpdates();\n\n if (isInvalid(rid)) {\n return;\n }\n\n updatePaddings(rid, updates);\n enqueueFetch(rid);\n\n if (!pending.length) {\n adapter.calculateProperties();\n }\n }\n\n function doAdjustAfterFetch(rid) {\n const updates = processUpdates();\n\n viewport.onAfterPrepend(updates);\n\n if (isInvalid(rid)) {\n return;\n }\n\n updatePaddings(rid, updates);\n onRenderHandlersRunner();\n enqueueFetch(rid, updates);\n pending.shift();\n\n if (pending.length)\n fetch(rid);\n else {\n adapter.loading(false);\n bindEvents();\n adapter.calculateProperties();\n }\n }\n\n function fetch(rid) {\n if (pending[0]) {// scrolling down\n if (buffer.length && !viewport.shouldLoadBottom()) {\n doAdjustAfterFetch(rid);\n } else {\n fetchNext((result) => {\n if (isInvalid(rid)) {\n return;\n }\n\n if (result.length < bufferSize) {\n buffer.eof = true;\n }\n\n if (result.length > 0) {\n viewport.clipTop();\n buffer.append(result);\n }\n\n doAdjustAfterFetch(rid);\n });\n }\n } else { // scrolling up\n if (buffer.length && !viewport.shouldLoadTop()) {\n doAdjustAfterFetch(rid);\n } else {\n fetchPrevious((result) => {\n if (isInvalid(rid)) {\n return;\n }\n\n if (result.length < bufferSize) {\n buffer.bof = true;\n // log 'bof is reached'\n }\n\n if (result.length > 0) {\n if (buffer.length) {\n viewport.clipBottom();\n }\n buffer.prepend(result);\n }\n\n doAdjustAfterFetch(rid);\n });\n }\n }\n }\n\n function resizeAndScrollHandler() {\n if (!$rootScope.$$phase && !adapter.isLoading && !adapter.disabled) {\n\n enqueueFetch(ridActual);\n\n if (pending.length) {\n unbindEvents();\n } else {\n adapter.calculateProperties();\n !$scope.$$phase && $scope.$digest();\n }\n }\n }\n\n function wheelHandler(event) {\n if (!adapter.disabled) {\n const scrollTop = viewport[0].scrollTop;\n const yMax = viewport[0].scrollHeight - viewport[0].clientHeight;\n\n if ((scrollTop === 0 && !buffer.bof) || (scrollTop === yMax && !buffer.eof)) {\n event.preventDefault();\n }\n }\n }\n }\n\n }\n ]);\n"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/modules/jqLiteExtras.js","webpack:///./src/modules/elementRoutines.js","webpack:///./src/modules/buffer.js","webpack:///./src/modules/padding.js","webpack:///./src/modules/viewport.js","webpack:///./src/modules/adapter.js","webpack:///./src/ui-scroll.js"],"names":["JQLiteExtras","element","convertToPx","css","getStyle","isWindow","angular","prototype","name","value","self","elem","nodeType","style","call","obj","document","location","alert","setInterval","scrollTo","direction","top","left","method","prop","preserve","isValueDefined","documentElement","window","getComputedStyle","parseFloat","currentStyle","result","rs","rsLeft","core_pnum","source","rnumnonpx","RegExp","test","runtimeStyle","pixelLeft","getMeasurements","measure","base","borderA","borderB","computedMarginA","computedMarginB","computedStyle","dirA","dirB","marginA","marginB","paddingA","paddingB","height","width","padding","border","margin","offsetWidth","offsetHeight","getWidthHeight","measurements","outer","outerfull","forEach","before","newElem","children","i","j","parent","ref","contents","prepend","length","after","Error","outerHTML","isNumber","outerHeight","option","outerWidth","offset","docElem","win","box","doc","ownerDocument","arguments","undefined","getBoundingClientRect","defaultView","parentWindow","pageYOffset","scrollTop","clientTop","pageXOffset","scrollLeft","clientLeft","key","hideClassToken","ElementRoutines","selector","rules","sheet","styleSheets","index","cssRules","err","insertRule","addRule","$injector","$q","$animate","has","get","isAngularVersionLessThen1_3","version","major","minor","wrapper","addClass","removeClass","newElement","previousElement","remove","scope","$destroy","insertElement","deferred","defer","enter","resolve","promise","removeElement","leave","then","ScrollBuffer","elementRoutines","bufferSize","startIndex","rowHeight","buffer","Object","create","Array","extend","size","reset","eof","bof","first","next","minIndex","maxIndex","minIndexUser","maxIndexUser","resetStartIndex","append","items","item","insert","Math","max","reverse","min","operation","isTop","op","splice","push","unshift","arg1","arg2","indexOf","_op","getAbsMinIndex","incrementMinIndex","decrementMaxIndex","removeElementAnimated","getAbsMaxIndex","effectiveHeight","elements","Number","MAX_VALUE","bottom","NEGATIVE_INFINITY","offsetParent","getItems","filter","getFirstItem","list","getLastItem","CacheProto","$index","sort","a","b","argument","_isTop","Cache","instance","apply","setPrototypeOf","getOwnPropertyNames","methodName","generateElement","template","Node","ELEMENT_NODE","tagName","toLowerCase","table","find","Padding","useCache","cache","Viewport","viewportController","$rootScope","topPadding","bottomPadding","viewport","container","bufferPadding","getScope","createPaddingElements","applyContainerStyle","bottomDataPos","scrollHeight","topDataPos","bottomVisiblePos","topVisiblePos","e","sibling","insertElementAnimated","shouldLoadBottom","clipBottom","overage","emptySpaceHeight","floor","itemHeight","overageHeight","add","adjustPaddings","shouldLoadTop","clipTop","visibleItemsHeight","reduce","summ","topPaddingHeight","topCount","bottomPaddingHeight","bottomCount","totalHeight","averageItemHeight","adjustTopPadding","adjustBottomPadding","topPaddingHeightAdd","bottomPaddingHeightAdd","onAfterMinIndexSet","topPaddingHeightOld","diff","onAfterPrepend","updates","prepended","paddingHeight","resetTopPadding","clear","resetBottomPadding","removeCacheItem","removeItem","Adapter","$scope","$parse","$attr","doAdjust","reload","isLoading","disabled","viewportScope","startScope","$parent","publicContext","assignAdapter","adapter","generatePublicContext","adapterAttr","replace","adapterOnScope","assign","error","message","publicMethods","bind","publicProps","property","attr","defineProperty","set","publicPropsImmediate","newItems","arg3","applyUpdatesFunc","noAdjust","applyUpdatesIndex","cb","options","slice","applyUpdate","_index","isArray","immutableTop","position","some","newItem","rowTop","topHeight","topDone","bottomDone","itemTop","isEOF","module","constant","run","elt","jQuery","fn","jquery","registerFor","addCSSRules","directive","restrict","controller","child","console","$timeout","$interval","require","transclude","priority","terminal","link","controllers","linker","match","uiScroll","parseNumber","defaultValue","isFloat","isNaN","parseNumericAttr","BUFFER_MIN","BUFFER_DEFAULT","PADDING_MIN","PADDING_DEFAULT","START_INDEX_DEFAULT","MAX_VIEWPORT_DELAY","VIEWPORT_POLLING_INTERVAL","datasource","itemName","datasourceName","allowVisibilityWatch","ridActual","pending","scPreviousScrollTop","isDatasourceValid","toString","onRenderHandlers","onRenderHandlersRunner","handler","persistDatasourceIndex","propName","getter","id","defineDatasourceIndex","propUserName","descriptor","getOwnPropertyDescriptor","fetchNext","success","count","fetchPrevious","initialize","tryCount","timer","cancel","clone","$on","unbindEvents","unbind","wheelHandler","isInvalid","rid","$$destroyed","bindEvents","resizeAndScrollHandler","isPendingScroll","_resizeAndScrollHandler","isElementVisible","visibilityWatcher","unregisterVisibilityWatcher","insertWrapperContent","insertAfter","createElement","$watch","hideElement","promises","transform","tdInitializer","uiScrollTdInitializer","linking","onLink","updateDOM","toBePrepended","toBeRemoved","inserted","concat","removed","animated","updatePaddings","all","enqueueFetch","calculateAbsoluteScroll","loading","fetch","processUpdates","changes","$$phase","$digest","w","showElement","calculateProperties","doAdjustAfterFetch","shift","sc","scTimer","clearTimeout","setTimeout","newFirst","event","yMax","clientHeight","preventDefault"],"mappings":"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","file":"ui-scroll.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n","/*!\n globals: angular, window\n List of used element methods available in JQuery but not in JQuery Lite\n element.before(elem)\n element.height()\n element.outerHeight(true)\n element.height(value) = only for Top/Bottom padding elements\n element.scrollTop()\n element.scrollTop(value)\n */\n\nexport default class JQLiteExtras {\n\n registerFor(element) {\n let convertToPx, css, getStyle, isWindow;\n // angular implementation blows up if elem is the window\n css = angular.element.prototype.css;\n\n element.prototype.css = function (name, value) {\n let self = this;\n let elem = self[0];\n if (!(!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style)) {\n return css.call(self, name, value);\n }\n };\n\n // as defined in angularjs v1.0.5\n isWindow = (obj) => obj && obj.document && obj.location && obj.alert && obj.setInterval;\n\n function scrollTo(self, direction, value) {\n let elem = self[0];\n let [method, prop, preserve] = {\n top: [\n 'scrollTop',\n 'pageYOffset',\n 'scrollLeft'\n ],\n left: [\n 'scrollLeft',\n 'pageXOffset',\n 'scrollTop'\n ]\n }[direction];\n\n const isValueDefined = typeof value !== 'undefined';\n if (isWindow(elem)) {\n if (isValueDefined) {\n return elem.scrollTo(self[preserve].call(self), value);\n }\n return (prop in elem) ? elem[prop] : elem.document.documentElement[method];\n } else {\n if (isValueDefined) {\n elem[method] = value;\n }\n return elem[method];\n }\n }\n\n if (window.getComputedStyle) {\n getStyle = (elem) => window.getComputedStyle(elem, null);\n convertToPx = (elem, value) => parseFloat(value);\n } else {\n getStyle = (elem) => elem.currentStyle;\n convertToPx = (elem, value) => {\n let left, result, rs, rsLeft, style;\n let core_pnum = /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source;\n let rnumnonpx = new RegExp('^(' + core_pnum + ')(?!px)[a-z%]+$', 'i');\n\n if (!rnumnonpx.test(value)) {\n return parseFloat(value);\n }\n\n // ported from JQuery\n style = elem.style;\n left = style.left;\n rs = elem.runtimeStyle;\n rsLeft = rs && rs.left;\n if (rs) {\n rs.left = style.left;\n }\n // put in the new values to get a computed style out\n style.left = value;\n result = style.pixelLeft;\n style.left = left;\n if (rsLeft) {\n rs.left = rsLeft;\n }\n return result;\n };\n }\n\n function getMeasurements(elem, measure) {\n let base, borderA, borderB, computedMarginA, computedMarginB, computedStyle, dirA, dirB, marginA, marginB, paddingA, paddingB;\n\n if (isWindow(elem)) {\n base = document.documentElement[{height: 'clientHeight', width: 'clientWidth'}[measure]];\n\n return {\n base: base,\n padding: 0,\n border: 0,\n margin: 0\n };\n }\n\n // Start with offset property\n [\n base,\n dirA,\n dirB\n ] = {\n width: [\n elem.offsetWidth,\n 'Left',\n 'Right'\n ],\n height: [\n elem.offsetHeight,\n 'Top',\n 'Bottom'\n ]\n }[measure];\n\n computedStyle = getStyle(elem);\n paddingA = convertToPx(elem, computedStyle['padding' + dirA]) || 0;\n paddingB = convertToPx(elem, computedStyle['padding' + dirB]) || 0;\n borderA = convertToPx(elem, computedStyle['border' + dirA + 'Width']) || 0;\n borderB = convertToPx(elem, computedStyle['border' + dirB + 'Width']) || 0;\n computedMarginA = computedStyle['margin' + dirA];\n computedMarginB = computedStyle['margin' + dirB];\n\n // I do not care for width for now, so this hack is irrelevant\n // if ( !supportsPercentMargin )\n // computedMarginA = hackPercentMargin( elem, computedStyle, computedMarginA )\n // computedMarginB = hackPercentMargin( elem, computedStyle, computedMarginB )\n marginA = convertToPx(elem, computedMarginA) || 0;\n marginB = convertToPx(elem, computedMarginB) || 0;\n\n return {\n base: base,\n padding: paddingA + paddingB,\n border: borderA + borderB,\n margin: marginA + marginB\n };\n }\n\n function getWidthHeight(elem, direction, measure) {\n let computedStyle, result;\n\n let measurements = getMeasurements(elem, direction);\n\n if (measurements.base > 0) {\n return {\n base: measurements.base - measurements.padding - measurements.border,\n outer: measurements.base,\n outerfull: measurements.base + measurements.margin\n }[measure];\n }\n\n // Fall back to computed then uncomputed css if necessary\n computedStyle = getStyle(elem);\n result = computedStyle[direction];\n\n if (result < 0 || result === null) {\n result = elem.style[direction] || 0;\n }\n\n // Normalize \"\", auto, and prepare for extra\n result = parseFloat(result) || 0;\n\n return {\n base: result - measurements.padding - measurements.border,\n outer: result,\n outerfull: result + measurements.padding + measurements.border + measurements.margin\n }[measure];\n }\n\n // define missing methods\n return angular.forEach({\n before(newElem) {\n var children, elem, i, j, parent, ref, self;\n self = this;\n elem = self[0];\n parent = self.parent();\n children = parent.contents();\n if (children[0] === elem) {\n return parent.prepend(newElem);\n } else {\n for (i = j = 1, ref = children.length - 1; 1 <= ref ? j <= ref : j >= ref; i = 1 <= ref ? ++j : --j) {\n if (children[i] === elem) {\n angular.element(children[i - 1]).after(newElem);\n return;\n }\n }\n throw new Error('invalid DOM structure ' + elem.outerHTML);\n }\n },\n height (value){\n var self;\n self = this;\n if (typeof value !== 'undefined') {\n if (angular.isNumber(value)) {\n value = value + 'px';\n }\n return css.call(self, 'height', value);\n } else {\n return getWidthHeight(this[0], 'height', 'base');\n }\n },\n outerHeight(option) {\n return getWidthHeight(this[0], 'height', option ? 'outerfull' : 'outer');\n },\n outerWidth(option) {\n return getWidthHeight(this[0], 'width', option ? 'outerfull' : 'outer');\n },\n\n /*\n The offset setter method is not implemented\n */\n offset(value) {\n let docElem, win;\n let self = this;\n let box = {\n top: 0,\n left: 0\n };\n let elem = self[0];\n let doc = elem && elem.ownerDocument;\n\n if (arguments.length) {\n if (value === undefined) {\n return self;\n }\n // TODO: implement setter\n throw new Error('offset setter method is not implemented');\n }\n\n if (!doc) {\n return;\n }\n\n docElem = doc.documentElement;\n\n // TODO: Make sure it's not a disconnected DOM node\n\n if (elem.getBoundingClientRect != null) {\n box = elem.getBoundingClientRect();\n }\n\n win = doc.defaultView || doc.parentWindow;\n\n return {\n top: box.top + (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0),\n left: box.left + (win.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)\n };\n },\n scrollTop(value) {\n return scrollTo(this, 'top', value);\n },\n scrollLeft(value) {\n return scrollTo(this, 'left', value);\n }\n }, (value, key) => {\n if (!element.prototype[key]) {\n return element.prototype[key] = value;\n }\n });\n }\n\n}\n","const hideClassToken = 'ng-ui-scroll-hide';\n\nexport default class ElementRoutines {\n\n static addCSSRules() {\n const selector = '.' + hideClassToken;\n const rules = 'display: none';\n const sheet = document.styleSheets[0];\n let index;\n try {\n index = sheet.cssRules.length;\n } catch (err) {\n index = 0;\n }\n if('insertRule' in sheet) {\n sheet.insertRule(selector + '{' + rules + '}', index);\n }\n else if('addRule' in sheet) {\n sheet.addRule(selector, rules, index);\n }\n }\n\n constructor($injector, $q) {\n this.$animate = ($injector.has && $injector.has('$animate')) ? $injector.get('$animate') : null;\n this.isAngularVersionLessThen1_3 = angular.version.major === 1 && angular.version.minor < 3;\n this.$q = $q;\n }\n\n hideElement(wrapper) {\n wrapper.element.addClass(hideClassToken);\n }\n\n showElement(wrapper) {\n wrapper.element.removeClass(hideClassToken);\n }\n\n insertElement(newElement, previousElement) {\n previousElement.after(newElement);\n return [];\n }\n\n removeElement(wrapper) {\n wrapper.element.remove();\n wrapper.scope.$destroy();\n return [];\n }\n\n insertElementAnimated(newElement, previousElement) {\n if (!this.$animate) {\n return this.insertElement(newElement, previousElement);\n }\n\n if (this.isAngularVersionLessThen1_3) {\n const deferred = this.$q.defer();\n // no need for parent - previous element is never null\n this.$animate.enter(newElement, null, previousElement, () => deferred.resolve());\n\n return [deferred.promise];\n }\n\n // no need for parent - previous element is never null\n return [this.$animate.enter(newElement, null, previousElement)];\n }\n\n removeElementAnimated(wrapper) {\n if (!this.$animate) {\n return this.removeElement(wrapper);\n }\n\n if (this.isAngularVersionLessThen1_3) {\n const deferred = this.$q.defer();\n this.$animate.leave(wrapper.element, () => {\n wrapper.scope.$destroy();\n return deferred.resolve();\n });\n\n return [deferred.promise];\n }\n\n return [(this.$animate.leave(wrapper.element)).then(() => wrapper.scope.$destroy())];\n }\n}","export default function ScrollBuffer(elementRoutines, bufferSize, startIndex, rowHeight) {\n const buffer = Object.create(Array.prototype);\n\n angular.extend(buffer, {\n size: bufferSize,\n\n reset(startIndex) {\n buffer.remove(0, buffer.length);\n buffer.eof = false;\n buffer.bof = false;\n buffer.first = startIndex;\n buffer.next = startIndex;\n buffer.minIndex = startIndex; // Calculated when data is effectively accessed\n buffer.maxIndex = startIndex;\n buffer.minIndexUser = null; // as set by the user (datasource)\n buffer.maxIndexUser = null;\n },\n \n // PHIL: set the new index to be displayed without resettng the sroll and the calculated min/max\n // Note that this actually make sense with a fixed rowHeight when the scroll value can be calculated\n // for a # of rows\n resetStartIndex: function resetStartIndex(startIndex) {\n buffer.remove(0, buffer.length);\n buffer.eof = buffer.eof && startIndex==buffer.maxIndex;\n buffer.bof = buffer.bof && startIndex==buffer.minIndex;\n buffer.first = startIndex;\n buffer.next = startIndex;\n },\n\n append(items) {\n items.forEach((item) => {\n ++buffer.next;\n buffer.insert('append', item);\n });\n buffer.maxIndex = buffer.eof ? buffer.next - 1 : Math.max(buffer.next - 1, buffer.maxIndex);\n },\n\n prepend(items) {\n items.reverse().forEach((item) => {\n --buffer.first;\n buffer.insert('prepend', item);\n });\n buffer.minIndex = buffer.bof ? buffer.minIndex = buffer.first : Math.min(buffer.first, buffer.minIndex);\n },\n\n /**\n * inserts wrapped element in the buffer\n * the first argument is either operation keyword (see below) or a number for operation 'insert'\n * for insert the number is the index for the buffer element the new one have to be inserted after\n * operations: 'append', 'prepend', 'insert', 'remove', 'update', 'none'\n */\n insert(operation, item, isTop) {\n const wrapper = {\n item: item\n };\n\n if (operation % 1 === 0) {// it is an insert\n wrapper.op = 'insert';\n buffer.splice(operation, 0, wrapper);\n if(isTop) {\n buffer.first--;\n }\n else {\n buffer.next++;\n }\n } else {\n wrapper.op = operation;\n switch (operation) {\n case 'append':\n buffer.push(wrapper);\n break;\n case 'prepend':\n buffer.unshift(wrapper);\n break;\n }\n }\n },\n\n // removes elements from buffer\n remove(arg1, arg2) {\n if (angular.isNumber(arg1)) {\n // removes items from arg1 (including) through arg2 (excluding)\n for (let i = arg1; i < arg2; i++) {\n elementRoutines.removeElement(buffer[i]);\n }\n return buffer.splice(arg1, arg2 - arg1);\n }\n // removes single item(wrapper) from the buffer\n buffer.splice(buffer.indexOf(arg1), 1);\n if(arg1._op === 'isTop' && buffer.first === this.getAbsMinIndex()) {\n this.incrementMinIndex();\n }\n else {\n this.decrementMaxIndex();\n }\n if(arg1._op === 'isTop') {\n buffer.first++;\n }\n else {\n buffer.next--;\n }\n if(!buffer.length) {\n buffer.first = buffer.minIndex%1 ? buffer.minIndex : startIndex;\n buffer.next = buffer.first;\n buffer.eof = buffer.eof && buffer.first==buffer.maxIndex;\n }\n\n return elementRoutines.removeElementAnimated(arg1);\n },\n\n incrementMinIndex() {\n if(buffer.minIndexUser !== null) {\n if(buffer.minIndex > buffer.minIndexUser) {\n buffer.minIndexUser++;\n return;\n }\n if(buffer.minIndex === buffer.minIndexUser) {\n buffer.minIndexUser++;\n }\n }\n buffer.minIndex++;\n },\n\n decrementMaxIndex() {\n if(buffer.maxIndexUser !== null && buffer.maxIndex <= buffer.maxIndexUser) {\n buffer.maxIndexUser--;\n }\n buffer.maxIndex--;\n },\n\n getAbsMinIndex() {\n if(buffer.minIndexUser !== null) {\n return Math.min(buffer.minIndexUser, buffer.minIndex);\n }\n return buffer.minIndex;\n },\n\n getAbsMaxIndex() {\n if(buffer.maxIndexUser !== null) {\n return Math.max(buffer.maxIndexUser, buffer.maxIndex);\n }\n return buffer.maxIndex;\n },\n\n effectiveHeight(elements) {\n if (!elements.length) {\n return 0;\n }\n let top = Number.MAX_VALUE;\n let bottom = Number.NEGATIVE_INFINITY;\n elements.forEach((wrapper) => {\n if (wrapper.element[0].offsetParent) {\n // element style is not display:none\n top = Math.min(top, wrapper.element.offset().top);\n bottom = Math.max(bottom, wrapper.element.offset().top + (rowHeight || wrapper.element.outerHeight(true)));\n }\n });\n return Math.max(0, bottom - top);\n },\n\n getItems() {\n return buffer.filter(item => item.op === 'none');\n },\n\n getFirstItem() {\n const list = buffer.getItems();\n if (!list.length) {\n return null;\n }\n return list[0].item;\n },\n\n getLastItem() {\n const list = buffer.getItems();\n if (!list.length) {\n return null;\n }\n return list[list.length - 1].item;\n }\n\n });\n\n buffer.reset(startIndex);\n\n return buffer;\n}\n","// Can't just extend the Array, due to Babel does not support built-in classes extending\n// This solution was taken from https://stackoverflow.com/questions/46897414/es6-class-extends-array-workaround-for-es5-babel-transpile\nclass CacheProto {\n add(item) {\n for (let i = this.length - 1; i >= 0; i--) {\n if (this[i].index === item.scope.$index) {\n this[i].height = item.element.outerHeight();\n return;\n }\n }\n this.push({\n index: item.scope.$index,\n height: item.element.outerHeight()\n });\n this.sort((a, b) => ((a.index < b.index) ? -1 : ((a.index > b.index) ? 1 : 0)));\n }\n\n remove(argument, _isTop) {\n const index = argument % 1 === 0 ? argument : argument.scope.$index;\n const isTop = argument % 1 === 0 ? _isTop : argument._op === 'isTop';\n for (let i = this.length - 1; i >= 0; i--) {\n if (this[i].index === index) {\n this.splice(i, 1);\n break;\n }\n }\n if(!isTop) {\n for (let i = this.length - 1; i >= 0; i--) {\n if (this[i].index > index) {\n this[i].index--;\n }\n }\n }\n }\n\n clear() {\n this.length = 0;\n }\n}\n\nfunction Cache() {\n const instance = [];\n instance.push.apply(instance, arguments);\n Object.setPrototypeOf(instance, Cache.prototype);\n return instance;\n}\nCache.prototype = Object.create(Array.prototype);\nObject.getOwnPropertyNames(CacheProto.prototype).forEach(methodName =>\n Cache.prototype[methodName] = CacheProto.prototype[methodName]\n);\n\nfunction generateElement(template) {\n if(template.nodeType !== Node.ELEMENT_NODE) {\n throw new Error('ui-scroll directive requires an Element node for templating the view');\n }\n let element;\n switch (template.tagName.toLowerCase()) {\n case 'dl':\n throw new Error(`ui-scroll directive does not support <${template.tagName}> as a repeating tag: ${template.outerHTML}`);\n case 'tr':\n let table = angular.element('
    ');\n element = table.find('tr');\n break;\n case 'li':\n element = angular.element('
  • ');\n break;\n default:\n element = angular.element('
    ');\n }\n return element;\n}\n\n//\n// Padding represents the dummy element added to both the top and the bottom of the scrolling container\n// It holds the element, as well as a cache for the items (rows) height. In case of a fixed rowHeight, the \n// cache is not used and thus is not created.\n//\nclass Padding {\n constructor(template,useCache) {\n this.element = generateElement(template);\n if(useCache) {\n this.cache = new Cache();\n }\n }\n\n height() {\n // When called with a parameter, this sets the height of the padding\n return this.element.height.apply(this.element, arguments);\n }\n}\n\nexport default Padding;","import Padding from './padding';\n\nexport default function Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding, rowHeight) {\n let topPadding = null;\n let bottomPadding = null;\n const viewport = viewportController && viewportController.viewport ? viewportController.viewport : angular.element(window);\n const container = viewportController && viewportController.container ? viewportController.container : undefined;\n const scope = viewportController && viewportController.scope ? viewportController.scope : $rootScope;\n\n viewport.css({\n 'overflow-anchor': 'none',\n 'overflow-y': 'auto',\n 'display': 'block'\n });\n\n function bufferPadding() {\n return viewport.outerHeight() * padding; // some extra space to initiate preload\n }\n\n // \n // Viewport measurements\n //\n // +----------------+ 0\n // | top |\n // | padding |\n // +----------------+ topDataPos() [=topPadding.height]\n // | not visible |\n // | items |\n // +----------------+ topVisiblePos() [=viewport.scrollTop]\n // | |\n // | visible |\n // | items |\n // | |\n // +----------------+ bottomVisiblePos() [=viewport.scrollTop+viewport.height]\n // | not visible |\n // | items |\n // +----------------+ bottomDataPos() [=scrollHeight-bottomPadding.height]\n // | bottom |\n // | padding |\n // +----------------+ scrollHeight \n //\n // bufferPadding is some extra space we have top & bottom to allow infinite scrolling\n // bufferPadding = viewport.outerHeight() * padding\n //\n // bottomVisiblePos() - topVisiblePos() == viewport.outerHeight()\n \n\n angular.extend(viewport, {\n getScope() {\n return scope;\n },\n\n createPaddingElements(template) {\n topPadding = new Padding(template,!rowHeight);\n bottomPadding = new Padding(template,!rowHeight);\n element.before(topPadding.element);\n element.after(bottomPadding.element);\n topPadding.height(0);\n bottomPadding.height(0);\n },\n\n applyContainerStyle() {\n if (!container) {\n return true;\n }\n if(container !== viewport) {\n viewport.css('height', window.getComputedStyle(container[0]).height);\n }\n return viewport.height() > 0;\n },\n\n bottomDataPos() {\n let scrollHeight = viewport[0].scrollHeight;\n scrollHeight = scrollHeight != null ? scrollHeight : viewport[0].document.documentElement.scrollHeight;\n return scrollHeight - bottomPadding.height();\n },\n\n topDataPos() {\n return topPadding.height();\n },\n\n bottomVisiblePos() {\n return viewport.scrollTop() + viewport.outerHeight();\n },\n\n topVisiblePos() {\n return viewport.scrollTop();\n },\n\n insertElement(e, sibling) {\n return elementRoutines.insertElement(e, sibling || topPadding.element);\n },\n\n insertElementAnimated(e, sibling) {\n return elementRoutines.insertElementAnimated(e, sibling || topPadding.element);\n },\n\n shouldLoadBottom() {\n return !buffer.eof && viewport.bottomDataPos() < viewport.bottomVisiblePos() + bufferPadding();\n },\n\n clipBottom() {\n // clip the invisible items off the bottom\n let overage = 0;\n let emptySpaceHeight = viewport.bottomDataPos() - viewport.bottomVisiblePos() - bufferPadding();\n if(rowHeight) {\n overage = Math.min(buffer.length,Math.floor(emptySpaceHeight/rowHeight));\n } else {\n let itemHeight = 0;\n let overageHeight = 0;\n\n for (let i = buffer.length - 1; i >= 0; i--) {\n itemHeight = buffer[i].element.outerHeight(true);\n if (overageHeight + itemHeight > emptySpaceHeight) {\n break;\n }\n bottomPadding.cache.add(buffer[i]);\n overageHeight += itemHeight;\n overage++;\n }\n }\n\n if (overage > 0) {\n buffer.eof = false;\n buffer.remove(buffer.length - overage, buffer.length);\n buffer.next -= overage;\n viewport.adjustPaddings();\n }\n },\n\n shouldLoadTop() {\n return !buffer.bof && (viewport.topDataPos() > viewport.topVisiblePos() - bufferPadding());\n },\n\n clipTop() {\n // clip the invisible items off the top\n let overage = 0;\n let overageHeight = 0;\n let emptySpaceHeight = viewport.topVisiblePos() - viewport.topDataPos() - bufferPadding();\n if(rowHeight) {\n overage = Math.min(buffer.length,Math.floor(emptySpaceHeight/rowHeight));\n overageHeight = overage * rowHeight;\n } else {\n let itemHeight = 0;\n\n for (let i = 0; i < buffer.length; i++) {\n itemHeight = buffer[i].element.outerHeight(true);\n if (overageHeight + itemHeight > emptySpaceHeight) {\n break;\n }\n topPadding.cache.add(buffer[i]);\n overageHeight += itemHeight;\n overage++;\n }\n }\n\n if (overage > 0) {\n // we need to adjust top padding element before items are removed from top\n // to avoid strange behaviour of scroll bar during remove top items when we are at the very bottom\n topPadding.height(topPadding.height() + overageHeight);\n buffer.bof = false;\n buffer.remove(0, overage);\n buffer.first += overage;\n }\n },\n\n // PHIL: remove all the entries in the buffer without changing the scrollbar, nor the scroll position\n // and update the padding accordingly\n // It is designed to work with non fixed rowHeight, although it will need more tests in this area...\n scrollTo(first) {\n if(rowHeight) {\n const min = buffer.getAbsMinIndex(); \n const max = buffer.getAbsMaxIndex();\n first = Math.min(Math.max(first, min),max);\n // Adjust the paddings before removing the elements to avoid touching the scroll top position\n topPadding.height((first-min)*rowHeight);\n bottomPadding.height(((max+1)-first)*rowHeight);\n buffer.resetStartIndex(first);\n } else {\n buffer.resetStartIndex(first);\n viewport.adjustPaddings();\n } \n },\n \n adjustPaddings() {\n if(rowHeight) {\n const min = buffer.getAbsMinIndex(); \n const max = buffer.getAbsMaxIndex();\n topPadding.height((buffer.first-min)*rowHeight);\n // PHIL: next points to the next possible item, while max is the index of the last one.\n // In order to make them compatible, we should add one to max\n // Also, it looks like buffer is not changing maxIndex when an element is inserted/appended\n // Not sure if this can have a consequence or not....\n bottomPadding.height(((max+1)-buffer.next)*rowHeight);\n return;\n }\n\n if (!buffer.length) {\n return;\n }\n\n // precise heights calculation based on items that are in buffer or that were in buffer once\n const visibleItemsHeight = buffer.reduce((summ, item) => summ + item.element.outerHeight(true), 0);\n let topPaddingHeight = 0, topCount = 0;\n topPadding.cache.forEach(item => {\n if(item.index < buffer.first) {\n topPaddingHeight += item.height;\n topCount++;\n }\n });\n \n let bottomPaddingHeight = 0, bottomCount = 0;\n bottomPadding.cache.forEach(item => {\n if(item.index >= buffer.next) {\n bottomPaddingHeight += item.height;\n bottomCount++;\n }\n });\n \n const totalHeight = visibleItemsHeight + topPaddingHeight + bottomPaddingHeight;\n const averageItemHeight = totalHeight / (topCount + bottomCount + buffer.length); \n\n // average heights calculation, items that have never been reached\n let adjustTopPadding = buffer.minIndexUser !== null && buffer.minIndex > buffer.minIndexUser;\n let adjustBottomPadding = buffer.maxIndexUser !== null && buffer.maxIndex < buffer.maxIndexUser;\n let topPaddingHeightAdd = adjustTopPadding ? (buffer.minIndex - buffer.minIndexUser) * averageItemHeight : 0;\n let bottomPaddingHeightAdd = adjustBottomPadding ? (buffer.maxIndexUser - buffer.maxIndex) * averageItemHeight : 0;\n\n // paddings combine adjustment\n topPadding.height(topPaddingHeight + topPaddingHeightAdd);\n bottomPadding.height(bottomPaddingHeight + bottomPaddingHeightAdd);\n },\n\n onAfterMinIndexSet(topPaddingHeightOld) {\n // additional scrollTop adjustment in case of datasource.minIndex external set\n if (buffer.minIndexUser !== null && buffer.minIndex > buffer.minIndexUser) {\n let diff = topPadding.height() - topPaddingHeightOld;\n viewport.scrollTop(viewport.scrollTop() + diff);\n while((diff -= viewport.scrollTop()) > 0) {\n bottomPadding.height(bottomPadding.height() + diff);\n viewport.scrollTop(viewport.scrollTop() + diff);\n }\n }\n },\n\n onAfterPrepend(updates) {\n if (!updates.prepended.length)\n return;\n const height = buffer.effectiveHeight(updates.prepended);\n const paddingHeight = topPadding.height() - height;\n if (paddingHeight >= 0) {\n topPadding.height(paddingHeight);\n }\n else {\n topPadding.height(0);\n viewport.scrollTop(viewport.scrollTop() - paddingHeight);\n }\n },\n\n resetTopPadding() {\n topPadding.height(0);\n if(topPadding.cache) {\n topPadding.cache.clear();\n }\n },\n\n resetBottomPadding() {\n bottomPadding.height(0);\n if(bottomPadding.cache) {\n bottomPadding.cache.clear();\n }\n },\n\n removeCacheItem(item, isTop) {\n if(topPadding.cache) {\n topPadding.cache.remove(item, isTop);\n }\n if(bottomPadding.cache) {\n bottomPadding.cache.remove(item, isTop);\n }\n },\n\n removeItem(item) {\n this.removeCacheItem(item);\n return buffer.remove(item);\n }\n });\n\n return viewport;\n}\n","class Adapter {\n\n constructor($scope, $parse, $attr, viewport, buffer, doAdjust, reload) {\n this.$parse = $parse;\n this.$attr = $attr;\n this.viewport = viewport;\n this.buffer = buffer;\n\n this.doAdjust = doAdjust;\n this.reload = reload;\n\n this.isLoading = false;\n this.disabled = false;\n\n const viewportScope = viewport.getScope();\n this.startScope = viewportScope.$parent ? viewportScope : $scope;\n\n this.publicContext = {};\n this.assignAdapter($attr.adapter);\n this.generatePublicContext();\n }\n\n assignAdapter(adapterAttr) {\n if (!adapterAttr || !(adapterAttr = adapterAttr.replace(/^\\s+|\\s+$/gm, ''))) {\n return;\n }\n let adapterOnScope;\n\n try {\n this.$parse(adapterAttr).assign(this.startScope, {});\n adapterOnScope = this.$parse(adapterAttr)(this.startScope);\n }\n catch (error) {\n error.message = `Angular ui-scroll Adapter assignment exception.\\n` +\n `Can't parse \"${adapterAttr}\" expression.\\n` +\n error.message;\n throw error;\n }\n\n angular.extend(adapterOnScope, this.publicContext);\n this.publicContext = adapterOnScope;\n }\n\n generatePublicContext() {\n // these methods will be accessible out of ui-scroll via user defined adapter\n const publicMethods = ['reload', 'applyUpdates', 'append', 'prepend', 'isBOF', 'isEOF', 'isEmpty'];\n for (let i = publicMethods.length - 1; i >= 0; i--) {\n this.publicContext[publicMethods[i]] = this[publicMethods[i]].bind(this);\n }\n\n // these read-only props will be accessible out of ui-scroll via user defined adapter\n const publicProps = ['isLoading', 'topVisible', 'topVisibleElement', 'topVisibleScope', 'bottomVisible', 'bottomVisibleElement', 'bottomVisibleScope'];\n for (let i = publicProps.length - 1; i >= 0; i--) {\n let property, attr = this.$attr[publicProps[i]];\n Object.defineProperty(this, publicProps[i], {\n get: () => property,\n set: (value) => {\n property = value;\n this.publicContext[publicProps[i]] = value;\n if (attr) {\n this.$parse(attr).assign(this.startScope, value);\n }\n }\n });\n }\n\n // read-only immediately calculated public properties\n const publicPropsImmediate = ['bufferFirst', 'bufferLast', 'bufferLength'];\n for (let i = publicPropsImmediate.length - 1; i >= 0; i--) {\n Object.defineProperty(this.publicContext, publicPropsImmediate[i], {\n get: () => this[publicPropsImmediate[i]]\n });\n }\n\n // non-read-only public property\n Object.defineProperty(this.publicContext, 'disabled', {\n get: () => this.disabled,\n set: (value) => (!(this.disabled = value)) ? this.doAdjust() : null\n });\n }\n\n loading(value) {\n this.isLoading = value;\n }\n\n isBOF() {\n return this.buffer.bof;\n }\n\n isEOF() {\n return this.buffer.eof;\n }\n\n isEmpty() {\n return !this.buffer.length;\n }\n\n get bufferLength() {\n return this.buffer.getItems().length;\n }\n\n get bufferFirst() {\n return this.buffer.getFirstItem();\n }\n\n get bufferLast() {\n return this.buffer.getLastItem();\n }\n\n append(newItems) {\n this.buffer.append(newItems);\n this.doAdjust();\n this.viewport.clipTop();\n this.viewport.clipBottom();\n }\n\n prepend(newItems) {\n this.buffer.prepend(newItems);\n this.doAdjust();\n this.viewport.clipTop();\n this.viewport.clipBottom();\n }\n\n applyUpdates(arg1, arg2, arg3) {\n if (typeof arg1 === 'function') {\n this.applyUpdatesFunc(arg1, arg2);\n if(arg2 && arg2.noAdjust) return;\n } else {\n this.applyUpdatesIndex(arg1, arg2, arg3);\n if(arg3 && arg3.noAdjust) return;\n }\n this.doAdjust();\n }\n\n applyUpdatesFunc(cb, options) {\n this.buffer.slice(0).forEach((wrapper) => {\n // we need to do it on the buffer clone, because buffer content\n // may change as we iterate through\n this.applyUpdate(wrapper, cb(wrapper.item, wrapper.scope, wrapper.element), options);\n });\n }\n\n applyUpdatesIndex(index, newItems, options = {}) {\n if (index % 1 !== 0) {\n throw new Error('applyUpdates - ' + index + ' is not a valid index (should be an integer)');\n }\n const _index = index - this.buffer.first;\n\n // apply updates only within buffer\n if (_index >= 0 && _index < this.buffer.length) {\n this.applyUpdate(this.buffer[_index], newItems, options);\n }\n // out-of-buffer case: deletion may affect Paddings\n else if(index >= this.buffer.getAbsMinIndex() && index <= this.buffer.getAbsMaxIndex()) {\n if(angular.isArray(newItems) && !newItems.length) {\n this.viewport.removeCacheItem(index, !options.immutableTop && index === this.buffer.minIndex);\n if (!options.immutableTop && index === this.buffer.getAbsMinIndex()) {\n this.buffer.incrementMinIndex();\n }\n else {\n this.buffer.decrementMaxIndex();\n }\n }\n }\n }\n\n applyUpdate(wrapper, newItems, options = {}) {\n if (!angular.isArray(newItems)) {\n return;\n }\n let position = this.buffer.indexOf(wrapper);\n if (!newItems.reverse().some(newItem => newItem === wrapper.item)) {\n wrapper.op = 'remove';\n if (!options.immutableTop && position === 0 && !newItems.length) {\n wrapper._op = 'isTop'; // to catch \"first\" edge case on remove\n }\n }\n newItems.forEach((newItem) => {\n if (newItem === wrapper.item) {\n position--;\n } else {\n // 3 parameter (isTop) is to catch \"first\" edge case on insert\n this.buffer.insert(position + 1, newItem, !options.immutableTop && position === -1);\n }\n });\n }\n\n calculateProperties() {\n let rowTop = null, topHeight = 0;\n let topDone = false, bottomDone = false;\n const length = this.buffer.length;\n\n for (let i = 0; i < length; i++) {\n const item = this.buffer[i];\n const itemTop = item.element.offset().top;\n\n if (rowTop !== itemTop) { // a new row condition\n const itemHeight = item.element.outerHeight(true);\n const top = this.viewport.topDataPos() + topHeight + itemHeight;\n\n if (!topDone && top > this.viewport.topVisiblePos()) {\n topDone = true;\n this['topVisible'] = item.item;\n this['topVisibleElement'] = item.element;\n this['topVisibleScope'] = item.scope;\n }\n if (!bottomDone && (top >= this.viewport.bottomVisiblePos() || (i === length - 1 && this.isEOF()))) {\n bottomDone = true;\n this['bottomVisible'] = item.item;\n this['bottomVisibleElement'] = item.element;\n this['bottomVisibleScope'] = item.scope;\n }\n topHeight += itemHeight;\n }\n rowTop = itemTop;\n\n if (topDone && bottomDone) {\n break;\n }\n }\n }\n\n}\n\nexport default Adapter;\n","import JQLiteExtras from './modules/jqLiteExtras';\nimport ElementRoutines from './modules/elementRoutines.js';\nimport ScrollBuffer from './modules/buffer.js';\nimport Viewport from './modules/viewport.js';\nimport Adapter from './modules/adapter.js';\n\nangular.module('ui.scroll', [])\n\n .constant('JQLiteExtras', JQLiteExtras)\n .run(['JQLiteExtras', (JQLiteExtras) => {\n const elt = angular.element;\n !(window.jQuery && elt.fn && elt.fn.jquery) ? (new JQLiteExtras()).registerFor(elt) : null;\n ElementRoutines.addCSSRules();\n }])\n\n .directive('uiScrollViewport', function () {\n return {\n restrict: 'A',\n controller: [\n '$scope',\n '$element',\n function (scope, element) {\n this.container = element;\n this.viewport = element;\n this.scope = scope;\n\n angular.forEach(element.children(), child => {\n if (child.tagName.toLowerCase() === 'tbody') {\n this.viewport = angular.element(child);\n }\n });\n\n return this;\n }\n ]\n };\n })\n\n .directive('uiScroll', [\n '$log',\n '$injector',\n '$rootScope',\n '$timeout',\n '$interval',\n '$q',\n '$parse',\n function (console, $injector, $rootScope, $timeout, $interval, $q, $parse) {\n\n return {\n require: ['?^uiScrollViewport'],\n restrict: 'A',\n transclude: 'element',\n priority: 1000,\n terminal: true,\n link: link\n };\n\n function link($scope, element, $attr, controllers, linker) {\n const match = $attr.uiScroll.match(/^\\s*(\\w+)\\s+in\\s+([(\\w|\\$)\\.]+)\\s*$/);\n if (!match) {\n throw new Error('Expected uiScroll in form of \\'_item_ in _datasource_\\' but got \\'' + $attr.uiScroll + '\\'');\n }\n\n function parseNumber(value, defaultValue, isFloat) {\n if (!isFloat) {\n value = value === null ? defaultValue : Math.floor(value);\n }\n return isNaN(value) ? defaultValue : value;\n }\n\n function parseNumericAttr(value, defaultValue, isFloat) {\n const result = $parse(value)($scope);\n return parseNumber(result, defaultValue, isFloat);\n }\n\n const BUFFER_MIN = 3; // Minimum size of the data source request\n const BUFFER_DEFAULT = 10; // Default datasource request size\n const PADDING_MIN = 0.3; // Mininum # of rows in the padding area\n const PADDING_DEFAULT = 0.5; // Default # of rows in the padding area\n const START_INDEX_DEFAULT = 1; // Default start index when requestng the first data block\n const MAX_VIEWPORT_DELAY = 500; // Max time wait (ms) to get the viewport with an height>0\n const VIEWPORT_POLLING_INTERVAL = 50; // Interval used to check the initial viewport height\n\n let datasource = null;\n const itemName = match[1]; // Name of the index variable to publish\n const datasourceName = match[2]; // Name of the datasource to request the rows from\n const viewportController = controllers[0]; // ViewportController, as specified in the require option (http://websystique.com/angularjs/angularjs-custom-directives-controllers-require-option-guide/)\n const bufferSize = Math.max(BUFFER_MIN, parseNumericAttr($attr.bufferSize, BUFFER_DEFAULT)); \n const padding = Math.max(PADDING_MIN, parseNumericAttr($attr.padding, PADDING_DEFAULT, true));\n let startIndex = parseNumericAttr($attr.startIndex, START_INDEX_DEFAULT);\n\n // PHIL: Provide a fixed row height\n // \n const rowHeight = parseNumericAttr($attr.rowHeight, null, false);\n\n // PHIL: Read the visibility watch option, true by default\n const allowVisibilityWatch = $attr.allowVisibilityWatch!=='false';\n\n // Revision IDs\n // \n let ridActual = 0; // current data revision id\n let pending = [];\n\n const elementRoutines = new ElementRoutines($injector, $q);\n const buffer = new ScrollBuffer(elementRoutines, bufferSize, startIndex, rowHeight);\n const viewport = new Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding, rowHeight);\n const adapter = new Adapter($scope, $parse, $attr, viewport, buffer, doAdjust, reload);\n\n if (viewportController) {\n viewportController.adapter = adapter;\n }\n\n // Currently, we only debounce the scroll events when a fixed rowHeight is provided\n // as the unit tests will have to be adapted to support this feature\n let scPreviousScrollTop=-1;\n\n const isDatasourceValid = () =>\n Object.prototype.toString.call(datasource) === '[object Object]' && typeof datasource.get === 'function';\n\n datasource = $parse(datasourceName)($scope); // try to get datasource on scope\n if (!isDatasourceValid()) {\n datasource = $injector.get(datasourceName); // try to inject datasource as service\n if (!isDatasourceValid()) {\n throw new Error(datasourceName + ' is not a valid datasource');\n }\n }\n\n let onRenderHandlers = [];\n function onRenderHandlersRunner() {\n onRenderHandlers.forEach(handler => handler.run());\n onRenderHandlers = [];\n }\n function persistDatasourceIndex(datasource, propName) {\n let getter;\n // need to postpone min/maxIndexUser processing if the view is empty\n if(angular.isNumber(datasource[propName])) {\n getter = datasource[propName];\n if(angular.isNumber(getter)) {\n onRenderHandlers = onRenderHandlers.filter(handler => handler.id !== propName);\n onRenderHandlers.push({\n id: propName,\n run: () => datasource[propName] = getter\n });\n }\n }\n }\n\n function defineDatasourceIndex(datasource, propName, propUserName) {\n const descriptor = Object.getOwnPropertyDescriptor(datasource, propName);\n if (descriptor && (descriptor.set || descriptor.get)) {\n return;\n }\n let getter;\n persistDatasourceIndex(datasource, propName);\n Object.defineProperty(datasource, propName, {\n set: (value) => {\n getter = value;\n if(pending.length && !buffer.length) {\n persistDatasourceIndex(datasource, propName);\n return;\n }\n buffer[propUserName] = value;\n const topPaddingHeightOld = viewport.topDataPos();\n viewport.adjustPaddings();\n if (propName === 'minIndex') {\n viewport.onAfterMinIndexSet(topPaddingHeightOld);\n }\n },\n get: () => getter\n });\n }\n\n defineDatasourceIndex(datasource, 'minIndex', 'minIndexUser');\n defineDatasourceIndex(datasource, 'maxIndex', 'maxIndexUser');\n\n const fetchNext = (datasource.get.length !== 2) ?\n (success) => datasource.get(buffer.next, bufferSize, success) :\n (success) => {\n datasource.get({\n index: buffer.next,\n append: buffer.length ? buffer[buffer.length - 1].item : void 0,\n count: bufferSize\n }, success);\n };\n\n const fetchPrevious = (datasource.get.length !== 2) ?\n (success) => datasource.get(buffer.first - bufferSize, bufferSize, success) :\n (success) => {\n datasource.get({\n index: buffer.first - bufferSize,\n prepend: buffer.length ? buffer[0].item : void 0,\n count: bufferSize\n }, success);\n };\n\n const initialize = () => {\n let tryCount = 0;\n if(!viewport.applyContainerStyle()) {\n const timer = $interval(() => {\n tryCount++;\n if(viewport.applyContainerStyle()) {\n $interval.cancel(timer);\n doAdjust();\n }\n if(tryCount * VIEWPORT_POLLING_INTERVAL >= MAX_VIEWPORT_DELAY) {\n $interval.cancel(timer);\n throw Error(`ui-scroll directive requires a viewport with non-zero height in ${MAX_VIEWPORT_DELAY}ms`);\n }\n }, VIEWPORT_POLLING_INTERVAL);\n }\n else {\n doAdjust();\n }\n };\n\n /**\n * Build padding elements\n *\n * Calling linker is the only way I found to get access to the tag name of the template\n * to prevent the directive scope from pollution a new scope is created and destroyed\n * right after the builder creation is completed\n */\n linker((clone, scope) => {\n viewport.createPaddingElements(clone[0]);\n // we do not include the clone in the DOM. It means that the nested directives will not\n // be able to reach the parent directives, but in this case it is intentional because we\n // created the clone to access the template tag name\n scope.$destroy();\n clone.remove();\n });\n\n $scope.$on('$destroy', () => {\n unbindEvents();\n viewport.unbind('mousewheel', wheelHandler);\n });\n\n viewport.bind('mousewheel', wheelHandler);\n\n initialize();\n\n /* Private function definitions */\n\n function isInvalid(rid) {\n return (rid && rid !== ridActual) || $scope.$$destroyed;\n }\n\n function bindEvents() {\n viewport.bind('resize', resizeAndScrollHandler);\n viewport.bind('scroll', resizeAndScrollHandler);\n // If a scroll event happened while the handler was not bounded, emit the scroll\n if(isPendingScroll()) {\n // Do it immediately\n _resizeAndScrollHandler();\n }\n }\n\n function unbindEvents() {\n viewport.unbind('resize', resizeAndScrollHandler);\n viewport.unbind('scroll', resizeAndScrollHandler);\n }\n\n function reload() {\n unbindEvents();\n viewport.resetTopPadding();\n viewport.resetBottomPadding();\n if (arguments.length) {\n startIndex = parseNumber(arguments[0], START_INDEX_DEFAULT, false);\n }\n buffer.reset(startIndex);\n scPreviousScrollTop = -1; // Avoid isScrollPending() to be true\n persistDatasourceIndex(datasource, 'minIndex');\n persistDatasourceIndex(datasource, 'maxIndex');\n doAdjust();\n }\n\n function scrollTo(first) {\n unbindEvents();\n viewport.scrollTo(first);\n doAdjust();\n }\n\n function isElementVisible(wrapper) {\n return (rowHeight || wrapper.element.height()) && wrapper.element[0].offsetParent;\n }\n\n function visibilityWatcher(wrapper) {\n if (isElementVisible(wrapper)) {\n buffer.forEach((item) => {\n if (typeof item.unregisterVisibilityWatcher === 'function') {\n item.unregisterVisibilityWatcher();\n delete item.unregisterVisibilityWatcher;\n }\n });\n if (!pending.length) {\n $timeout(() => doAdjust());\n }\n }\n }\n\n function insertWrapperContent(wrapper, insertAfter) {\n createElement(wrapper, insertAfter, viewport.insertElement);\n if (allowVisibilityWatch && !isElementVisible(wrapper)) {\n wrapper.unregisterVisibilityWatcher = wrapper.scope.$watch(() => visibilityWatcher(wrapper));\n }\n if (allowVisibilityWatch) {\n elementRoutines.hideElement(wrapper); // hide inserted elements before data binding\n }\n }\n\n function createElement(wrapper, insertAfter, insertElement) {\n let promises = null;\n const sibling = (insertAfter > 0) ? buffer[insertAfter - 1].element : undefined;\n linker((clone, scope) => {\n promises = insertElement(clone, sibling);\n wrapper.element = clone;\n wrapper.scope = scope;\n scope[itemName] = wrapper.item;\n });\n // ui-scroll-grid apply\n if (adapter.transform) {\n const tdInitializer = wrapper.scope.uiScrollTdInitializer;\n if (tdInitializer && tdInitializer.linking) {\n adapter.transform(wrapper.scope, wrapper.element);\n } else {\n wrapper.scope.uiScrollTdInitializer = {\n onLink: () => adapter.transform(wrapper.scope, wrapper.element),\n scope: wrapper.scope\n };\n }\n }\n return promises;\n }\n\n function updateDOM() {\n let promises = [];\n const toBePrepended = [];\n const toBeRemoved = [];\n const inserted = [];\n\n buffer.forEach((wrapper, i) => {\n switch (wrapper.op) {\n case 'prepend':\n toBePrepended.unshift(wrapper);\n break;\n case 'append':\n insertWrapperContent(wrapper, i);\n wrapper.op = 'none';\n inserted.push(wrapper);\n break;\n case 'insert':\n promises = promises.concat(createElement(wrapper, i, viewport.insertElementAnimated));\n wrapper.op = 'none';\n inserted.push(wrapper);\n break;\n case 'remove':\n toBeRemoved.push(wrapper);\n }\n });\n\n toBeRemoved.forEach((wrapper) => promises = promises.concat(viewport.removeItem(wrapper)));\n\n if (toBePrepended.length)\n toBePrepended.forEach((wrapper) => {\n insertWrapperContent(wrapper);\n wrapper.op = 'none';\n });\n\n buffer.forEach((item, i) => item.scope.$index = buffer.first + i);\n\n return {\n prepended: toBePrepended,\n removed: toBeRemoved,\n inserted: inserted,\n animated: promises\n };\n\n }\n\n // Adjust the viewport paddings\n // \n function updatePaddings(rid, updates) {\n // schedule another doAdjust after animation completion\n if (updates.animated.length) {\n $q.all(updates.animated).then(() => {\n viewport.adjustPaddings();\n doAdjust(rid);\n });\n } else {\n viewport.adjustPaddings();\n }\n }\n\n function enqueueFetch(rid, updates) {\n // If there is a scroll pending, we don't enqueue the fetch as the scroll might be an absolute scroll\n // So we don't need to load top or bottom\n // This happens when there is a scroll frenzi, and the $digest is slow enough, so it stacks the calls without\n // giving a chance to the scroll event to be emitted and processed.\n // We also do that if it leads to an absolute scroll\n if(isPendingScroll() && calculateAbsoluteScroll()!==undefined) {\n // Looks like the event is swallowed on some browsers (FF) on some scroll configuration\n resizeAndScrollHandler();\n return;\n }\n\n if (viewport.shouldLoadBottom()) {\n if (!updates || buffer.effectiveHeight(updates.inserted) > 0) {\n // this means that at least one item appended in the last batch has height > 0\n if (pending.push(true) === 1) {\n adapter.loading(true);\n fetch(rid);\n }\n }\n } else if (viewport.shouldLoadTop()) {\n if ((!updates || buffer.effectiveHeight(updates.prepended) > 0) || pending[0]) {\n // this means that at least one item appended in the last batch has height > 0\n // pending[0] = true means that previous fetch was appending. We need to force at least one prepend\n // BTW there will always be at least 1 element in the pending array because bottom is fetched first\n if (pending.push(false) === 1) {\n adapter.loading(true);\n fetch(rid);\n }\n }\n }\n }\n\n function processUpdates() {\n const updates = updateDOM();\n\n // We need the item bindings to be processed before we can do adjustments\n // If there are no changes and the row-height is static, then ignore it!\n const changes = updates.animated.length+updates.inserted.length+updates.prepended.length+updates.removed.length;\n if(changes || !rowHeight) {\n !$scope.$$phase && !$rootScope.$$phase && $scope.$digest();\n }\n\n if (allowVisibilityWatch) {\n updates.inserted.forEach(w => elementRoutines.showElement(w));\n updates.prepended.forEach(w => elementRoutines.showElement(w));\n }\n\n return updates;\n }\n\n function doAdjust(rid) {\n if (!rid) { // dismiss pending requests\n pending = [];\n rid = ++ridActual;\n }\n\n const updates = processUpdates();\n\n if (isInvalid(rid)) {\n return;\n }\n\n updatePaddings(rid, updates);\n enqueueFetch(rid);\n\n if (!pending.length) {\n adapter.calculateProperties();\n }\n }\n\n function doAdjustAfterFetch(rid) {\n const updates = processUpdates();\n\n viewport.onAfterPrepend(updates);\n\n if (isInvalid(rid)) {\n return;\n }\n\n updatePaddings(rid, updates);\n onRenderHandlersRunner();\n enqueueFetch(rid, updates);\n pending.shift();\n\n if (pending.length)\n fetch(rid);\n else {\n adapter.loading(false);\n bindEvents();\n adapter.calculateProperties();\n }\n }\n\n function fetch(rid) {\n if (pending[0]) {// scrolling down\n if (buffer.length && !viewport.shouldLoadBottom()) {\n doAdjustAfterFetch(rid);\n } else {\n fetchNext((result) => {\n if (isInvalid(rid)) {\n return;\n }\n\n if (result.length < bufferSize) {\n buffer.eof = true;\n }\n\n if (result.length > 0) {\n viewport.clipTop();\n buffer.append(result);\n }\n\n doAdjustAfterFetch(rid);\n });\n }\n } else { // scrolling up\n if (buffer.length && !viewport.shouldLoadTop()) {\n doAdjustAfterFetch(rid);\n } else {\n fetchPrevious((result) => {\n if (isInvalid(rid)) {\n return;\n }\n\n if (result.length < bufferSize) {\n buffer.bof = true;\n // log 'bof is reached'\n }\n\n if (result.length > 0) {\n if (buffer.length) {\n viewport.clipBottom();\n }\n buffer.prepend(result);\n }\n\n doAdjustAfterFetch(rid);\n });\n }\n }\n }\n\n function isPendingScroll() {\n if(rowHeight) {\n // Maybe the scroll changed but the event has *not* yet being dispatched\n // because of the $digest running and taking to long\n var sc = viewport.scrollTop();\n if(sc!=scPreviousScrollTop && scPreviousScrollTop>=0) {\n return true;\n }\n }\n return false;\n }\n\n // Deboucing the scroll events avois intermediate $digest when scrolling fast\n let scTimer;\n function resizeAndScrollHandler() {\n if (rowHeight) {\n if (scTimer) clearTimeout(scTimer);\n scTimer = setTimeout(_resizeAndScrollHandler, 50);\n } else {\n _resizeAndScrollHandler();\n }\n }\n\n function _resizeAndScrollHandler() {\n if (!$rootScope.$$phase && !adapter.isLoading && !adapter.disabled) {\n // Absolute positioning currently only works when a fixed rowHeight is provided\n // We might isolate the averegaRowHeight calculation in the viewport to provide an estimate\n // and provide a reasonable behavior with variable height as well\n if(rowHeight) {\n const newFirst = calculateAbsoluteScroll();\n if(newFirst!==undefined) {\n scrollTo(newFirst);\n return;\n }\n }\n\n enqueueFetch(ridActual);\n\n if (pending.length) {\n unbindEvents();\n } else {\n adapter.calculateProperties();\n if(!rowHeight) {\n // The digest is forced to calculate the height, which is not necessary when the height is knowm\n !$scope.$$phase && $scope.$digest();\n }\n }\n }\n }\n\n function calculateAbsoluteScroll() {\n if(rowHeight) {\n scPreviousScrollTop = viewport.scrollTop();\n let newFirst = Math.floor(viewport.scrollTop() / rowHeight) + buffer.getAbsMinIndex();\n newFirst = Math.max(buffer.getAbsMinIndex(), Math.min(buffer.getAbsMaxIndex(),newFirst)); // Bound the scroll\n if (newFirstbuffer.next+bufferSize) {\n return newFirst;\n } \n }\n return undefined;\n }\n\n function wheelHandler(event) {\n if (!adapter.disabled) {\n const scrollTop = viewport[0].scrollTop;\n const yMax = viewport[0].scrollHeight - viewport[0].clientHeight;\n\n if ((scrollTop === 0 && !buffer.bof) || (scrollTop === yMax && !buffer.eof)) {\n event.preventDefault();\n }\n }\n }\n }\n\n }\n ]);\n"],"sourceRoot":""} \ No newline at end of file diff --git a/dist/ui-scroll.min.js b/dist/ui-scroll.min.js index b6b5d46e..483f5356 100644 --- a/dist/ui-scroll.min.js +++ b/dist/ui-scroll.min.js @@ -1,2 +1,2 @@ -!function(n){var r={};function i(e){if(r[e])return r[e].exports;var t=r[e]={i:e,l:!1,exports:{}};return n[e].call(t.exports,t,t.exports,i),t.l=!0,t.exports}i.m=n,i.c=r,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)i.d(n,r,function(e){return t[e]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=1)}([,function(e,t,n){"use strict";function g(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=[],r=!0,i=!1,o=void 0;try{for(var a,s=e[Symbol.iterator]();!(r=(a=s.next()).done)&&(n.push(a.value),!t||n.length!==t);r=!0);}catch(e){i=!0,o=e}finally{try{r||null==s.return||s.return()}finally{if(i)throw o}}return n}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function i(e,t){for(var n=0;ni.minIndexUser)return void i.minIndexUser++;i.minIndex===i.minIndexUser&&i.minIndexUser++}i.minIndex++},decrementMaxIndex:function(){null!==i.maxIndexUser&&i.maxIndex<=i.maxIndexUser&&i.maxIndexUser--,i.maxIndex--},getAbsMinIndex:function(){return null!==i.minIndexUser?Math.min(i.minIndexUser,i.minIndex):i.minIndex},getAbsMaxIndex:function(){return null!==i.maxIndexUser?Math.max(i.maxIndexUser,i.maxIndex):i.maxIndex},effectiveHeight:function(e){if(!e.length)return 0;var t=Number.MAX_VALUE,n=Number.NEGATIVE_INFINITY;return e.forEach(function(e){e.element[0].offsetParent&&(t=Math.min(t,e.element.offset().top),n=Math.max(n,e.element.offset().top+e.element.outerHeight(!0)))}),Math.max(0,n-t)}}),i.reset(t),i}function u(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function l(e,t){for(var n=0;nt.index?1:0})}},{key:"remove",value:function(e,t){for(var n=e%1==0?e:e.scope.$index,r=e%1==0?t:"isTop"===e._op,i=this.length-1;0<=i;i--)if(this[i].index===n){this.splice(i,1);break}if(!r)for(var o=this.length-1;0<=o;o--)this[o].index>n&&this[o].index--}},{key:"clear",value:function(){this.length=0}}]),e}();function d(){var e=[];return e.push.apply(e,arguments),Object.setPrototypeOf(e,d.prototype),e}d.prototype=Object.create(Array.prototype),Object.getOwnPropertyNames(f.prototype).forEach(function(e){return d.prototype[e]=f.prototype[e]});var h=function(){function t(e){u(this,t),this.element=function(e){if(e.nodeType!==Node.ELEMENT_NODE)throw new Error("ui-scroll directive requires an Element node for templating the view");var t;switch(e.tagName.toLowerCase()){case"dl":throw new Error("ui-scroll directive does not support <".concat(e.tagName,"> as a repeating tag: ").concat(e.outerHTML));case"tr":t=angular.element("
    ").find("tr");break;case"li":t=angular.element("
  • ");break;default:t=angular.element("
    ")}return t}(e),this.cache=new d}return c(t,[{key:"height",value:function(){return this.element.height.apply(this.element,arguments)}}]),t}();function X(n,c,t,e,r,i){var f=null,d=null,o=e&&e.viewport?e.viewport:angular.element(window),a=e&&e.container?e.container:void 0,s=e&&e.scope?e.scope:r;function u(){return o.outerHeight()*i}return o.css({"overflow-anchor":"none","overflow-y":"auto",display:"block"}),angular.extend(o,{getScope:function(){return s},createPaddingElements:function(e){f=new h(e),d=new h(e),t.before(f.element),t.after(d.element),f.height(0),d.height(0)},applyContainerStyle:function(){return!a||(a!==o&&o.css("height",window.getComputedStyle(a[0]).height),0o.topVisiblePos()-u()},clipTop:function(){for(var e=0,t=0,n=0,r=o.topVisiblePos()-o.topDataPos()-u(),i=0;i=c.next&&(r+=e.height,i++)});var o=(e+t+r)/(n+i+c.length),a=null!==c.minIndexUser&&c.minIndex>c.minIndexUser,s=null!==c.maxIndexUser&&c.maxIndexc.minIndexUser){var t=f.height()-e;for(o.scrollTop(o.scrollTop()+t);0<(t-=o.scrollTop());)d.height(d.height()+t),o.scrollTop(o.scrollTop()+t)}},onAfterPrepend:function(e){if(e.prepended.length){var t=c.effectiveHeight(e.prepended),n=f.height()-t;0<=n?f.height(n):(f.height(0),o.scrollTop(o.scrollTop()-n))}},resetTopPadding:function(){f.height(0),f.cache.clear()},resetBottomPadding:function(){d.height(0),d.cache.clear()},removeCacheItem:function(e,t){f.cache.remove(e,t),d.cache.remove(e,t)},removeItem:function(e){return this.removeCacheItem(e),c.remove(e)}}),o}function p(e,t){for(var n=0;n=this.buffer.getAbsMinIndex()&&e<=this.buffer.getAbsMaxIndex()&&angular.isArray(t)&&!t.length&&(this.viewport.removeCacheItem(e,e===this.buffer.minIndex),e===this.buffer.getAbsMinIndex()?this.buffer.incrementMinIndex():this.buffer.decrementMaxIndex())}},{key:"applyUpdate",value:function(t,e){var n=this;if(angular.isArray(e)){var r=this.buffer.indexOf(t);e.reverse().some(function(e){return e===t.item})||(t.op="remove",0!==r||e.length||(t._op="isTop")),e.forEach(function(e){e===t.item?r--:n.buffer.insert(r+1,e,-1===r)})}}},{key:"calculateProperties",value:function(){for(var e=null,t=0,n=!1,r=!1,i=this.buffer.length,o=0;othis.viewport.topVisiblePos()&&(n=!0,this.topVisible=a.item,this.topVisibleElement=a.element,this.topVisibleScope=a.scope),!r&&(l>=this.viewport.bottomVisiblePos()||o===i-1&&this.isEOF())&&(r=!0,this.bottomVisible=a.item,this.bottomVisibleElement=a.element,this.bottomVisibleScope=a.scope),t+=u}if(e=s,n&&r)break}}}])&&p(e.prototype,t),n&&p(e,n),u}();angular.module("ui.scroll",[]).constant("JQLiteExtras",r).run(["JQLiteExtras",function(e){!window.jQuery&&(new e).registerFor(angular.element),q.addCSSRules()}]).directive("uiScrollViewport",function(){return{restrict:"A",controller:["$scope","$element",function(e,t){var n=this;return this.container=t,this.viewport=t,this.scope=e,angular.forEach(t.children(),function(e){"tbody"===e.tagName.toLowerCase()&&(n.viewport=angular.element(e))}),this}]}}).directive("uiScroll",["$log","$injector","$rootScope","$timeout","$interval","$q","$parse",function(e,B,D,F,R,W,z){return{require:["?^uiScrollViewport"],restrict:"A",transclude:"element",priority:1e3,terminal:!0,link:function(i,e,t,n,a){var r=t.uiScroll.match(/^\s*(\w+)\s+in\s+([(\w|\$)\.]+)\s*$/);if(!r)throw new Error("Expected uiScroll in form of '_item_ in _datasource_' but got '"+t.uiScroll+"'");function o(e,t,n){return n||(e=null===e?t:Math.floor(e)),isNaN(e)?t:e}function s(e,t,n){var r=z(e)(i);return o(r,t,n)}var u=null,l=r[1],c=r[2],f=n[0],d=Math.max(3,s(t.bufferSize,10)),h=Math.max(.3,s(t.padding,.5,!0)),p=s(t.startIndex,1),m=0,g=[],v=new q(B,W),b=new Q(v,d,p),x=new X(v,b,e,f,D,h),y=new Y(i,z,t,x,b,C,function(){x.resetTopPadding(),x.resetBottomPadding(),arguments.length&&(p=o(arguments[0],1,!1));b.reset(p),E(u,"minIndex"),E(u,"maxIndex"),C()});f&&(f.adapter=y);var w=function(){return"[object Object]"===Object.prototype.toString.call(u)&&"function"==typeof u.get};if(u=z(c)(i),!w()&&(u=B.get(c),!w()))throw new Error(c+" is not a valid datasource");var I=[];function E(e,t){var n;angular.isNumber(e[t])&&(n=e[t],angular.isNumber(n)&&(I=I.filter(function(e){return e.id!==t})).push({id:t,run:function(){return e[t]=n}}))}function $(n,r,i){var o,e=Object.getOwnPropertyDescriptor(n,r);e&&(e.set||e.get)||(E(n,r),Object.defineProperty(n,r,{set:function(e){if(o=e,!g.length||b.length){b[i]=e;var t=x.topDataPos();x.adjustPaddings(),"minIndex"===r&&x.onAfterMinIndexSet(t)}else E(n,r)},get:function(){return o}}))}$(u,"minIndex","minIndexUser"),$(u,"maxIndex","maxIndexUser");var P=2!==u.get.length?function(e){return u.get(b.next,d,e)}:function(e){u.get({index:b.next,append:b.length?b[b.length-1].item:void 0,count:d},e)},T=2!==u.get.length?function(e){return u.get(b.first-d,d,e)}:function(e){u.get({index:b.first-d,prepend:b.length?b[0].item:void 0,count:d},e)};function S(e){return e&&e!==m||i.$$destroyed}function k(){x.unbind("resize",_),x.unbind("scroll",_)}function A(e){return e.element.height()&&e.element[0].offsetParent}function O(e,t){j(e,t,x.insertElement),A(e)||(e.unregisterVisibilityWatcher=e.scope.$watch(function(){A(e)&&(b.forEach(function(e){"function"==typeof e.unregisterVisibilityWatcher&&(e.unregisterVisibilityWatcher(),delete e.unregisterVisibilityWatcher)}),g.length||F(function(){return C()}))})),v.hideElement(e)}function j(n,e,r){var i=null,o=0a.minIndexUser)return void a.minIndexUser++;a.minIndex===a.minIndexUser&&a.minIndexUser++}a.minIndex++},decrementMaxIndex:function(){null!==a.maxIndexUser&&a.maxIndex<=a.maxIndexUser&&a.maxIndexUser--,a.maxIndex--},getAbsMinIndex:function(){return null!==a.minIndexUser?Math.min(a.minIndexUser,a.minIndex):a.minIndex},getAbsMaxIndex:function(){return null!==a.maxIndexUser?Math.max(a.maxIndexUser,a.maxIndex):a.maxIndex},effectiveHeight:function(e){if(!e.length)return 0;var t=Number.MAX_VALUE,n=Number.NEGATIVE_INFINITY;return e.forEach(function(e){e.element[0].offsetParent&&(t=Math.min(t,e.element.offset().top),n=Math.max(n,e.element.offset().top+(o||e.element.outerHeight(!0))))}),Math.max(0,n-t)},getItems:function(){return a.filter(function(e){return"none"===e.op})},getFirstItem:function(){var e=a.getItems();return e.length?e[0].item:null},getLastItem:function(){var e=a.getItems();return e.length?e[e.length-1].item:null}}),a.reset(i),a}function s(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function l(e,t){for(var n=0;nt.index?1:0})}},{key:"remove",value:function(e,t){for(var n=e%1==0?e:e.scope.$index,r=e%1==0?t:"isTop"===e._op,i=this.length-1;0<=i;i--)if(this[i].index===n){this.splice(i,1);break}if(!r)for(var o=this.length-1;0<=o;o--)this[o].index>n&&this[o].index--}},{key:"clear",value:function(){this.length=0}}]),e}();function d(){var e=[];return e.push.apply(e,arguments),Object.setPrototypeOf(e,d.prototype),e}d.prototype=Object.create(Array.prototype),Object.getOwnPropertyNames(c.prototype).forEach(function(e){return d.prototype[e]=c.prototype[e]});var v=function(){function n(e,t){s(this,n),this.element=function(e){if(e.nodeType!==Node.ELEMENT_NODE)throw new Error("ui-scroll directive requires an Element node for templating the view");var t;switch(e.tagName.toLowerCase()){case"dl":throw new Error("ui-scroll directive does not support <".concat(e.tagName,"> as a repeating tag: ").concat(e.outerHTML));case"tr":t=angular.element("
    ").find("tr");break;case"li":t=angular.element("
  • ");break;default:t=angular.element("
    ")}return t}(e),t&&(this.cache=new d)}return f(n,[{key:"height",value:function(){return this.element.height.apply(this.element,arguments)}}]),n}();function te(n,d,t,e,r,i,h){var p=null,m=null,o=e&&e.viewport?e.viewport:angular.element(window),a=e&&e.container?e.container:void 0,u=e&&e.scope?e.scope:r;function s(){return o.outerHeight()*i}return o.css({"overflow-anchor":"none","overflow-y":"auto",display:"block"}),angular.extend(o,{getScope:function(){return u},createPaddingElements:function(e){p=new v(e,!h),m=new v(e,!h),t.before(p.element),t.after(m.element),p.height(0),m.height(0)},applyContainerStyle:function(){return!a||(a!==o&&o.css("height",window.getComputedStyle(a[0]).height),0o.topVisiblePos()-s()},clipTop:function(){var e=0,t=0,n=o.topVisiblePos()-o.topDataPos()-s();if(h)t=(e=Math.min(d.length,Math.floor(n/h)))*h;else for(var r=0,i=0;i=d.next&&(o+=e.height,a++)});var u=(n+r+o)/(i+a+d.length),s=null!==d.minIndexUser&&d.minIndex>d.minIndexUser,l=null!==d.maxIndexUser&&d.maxIndexd.minIndexUser){var t=p.height()-e;for(o.scrollTop(o.scrollTop()+t);0<(t-=o.scrollTop());)m.height(m.height()+t),o.scrollTop(o.scrollTop()+t)}},onAfterPrepend:function(e){if(e.prepended.length){var t=d.effectiveHeight(e.prepended),n=p.height()-t;0<=n?p.height(n):(p.height(0),o.scrollTop(o.scrollTop()-n))}},resetTopPadding:function(){p.height(0),p.cache&&p.cache.clear()},resetBottomPadding:function(){m.height(0),m.cache&&m.cache.clear()},removeCacheItem:function(e,t){p.cache&&p.cache.remove(e,t),m.cache&&m.cache.remove(e,t)},removeItem:function(e){return this.removeCacheItem(e),d.remove(e)}}),o}function h(e,t){for(var n=0;n=this.buffer.getAbsMinIndex()&&e<=this.buffer.getAbsMaxIndex()&&angular.isArray(t)&&!t.length&&(this.viewport.removeCacheItem(e,!n.immutableTop&&e===this.buffer.minIndex),n.immutableTop||e!==this.buffer.getAbsMinIndex()?this.buffer.decrementMaxIndex():this.buffer.incrementMinIndex())}},{key:"applyUpdate",value:function(t,e){var n=this,r=2this.viewport.topVisiblePos()&&(n=!0,this.topVisible=a.item,this.topVisibleElement=a.element,this.topVisibleScope=a.scope),!r&&(l>=this.viewport.bottomVisiblePos()||o===i-1&&this.isEOF())&&(r=!0,this.bottomVisible=a.item,this.bottomVisibleElement=a.element,this.bottomVisibleScope=a.scope),t+=s}if(e=u,n&&r)break}}},{key:"bufferLength",get:function(){return this.buffer.getItems().length}},{key:"bufferFirst",get:function(){return this.buffer.getFirstItem()}},{key:"bufferLast",get:function(){return this.buffer.getLastItem()}}])&&h(e.prototype,t),n&&h(e,n),s}();angular.module("ui.scroll",[]).constant("JQLiteExtras",r).run(["JQLiteExtras",function(e){var t=angular.element;!(window.jQuery&&t.fn&&t.fn.jquery)&&(new e).registerFor(t),Z.addCSSRules()}]).directive("uiScrollViewport",function(){return{restrict:"A",controller:["$scope","$element",function(e,t){var n=this;return this.container=t,this.viewport=t,this.scope=e,angular.forEach(t.children(),function(e){"tbody"===e.tagName.toLowerCase()&&(n.viewport=angular.element(e))}),this}]}}).directive("uiScroll",["$log","$injector","$rootScope","$timeout","$interval","$q","$parse",function(e,Q,X,Y,J,G,K){return{require:["?^uiScrollViewport"],restrict:"A",transclude:"element",priority:1e3,terminal:!0,link:function(i,e,t,n,a){var r=t.uiScroll.match(/^\s*(\w+)\s+in\s+([(\w|\$)\.]+)\s*$/);if(!r)throw new Error("Expected uiScroll in form of '_item_ in _datasource_' but got '"+t.uiScroll+"'");function o(e,t,n){return n||(e=null===e?t:Math.floor(e)),isNaN(e)?t:e}function u(e,t,n){var r=K(e)(i);return o(r,t,n)}var s=null,l=r[1],f=r[2],c=n[0],d=Math.max(3,u(t.bufferSize,10)),h=Math.max(.3,u(t.padding,.5,!0)),p=u(t.startIndex,1),m=u(t.rowHeight,null,!1),g="false"!==t.allowVisibilityWatch,v=0,b=[],x=new Z(Q,G),y=new ee(x,d,p,m),I=new te(x,y,e,c,X,h,m),w=new ne(i,K,t,I,y,N,function(){O(),I.resetTopPadding(),I.resetBottomPadding(),arguments.length&&(p=o(arguments[0],1,!1));y.reset(p),E=-1,P(s,"minIndex"),P(s,"maxIndex"),N()});c&&(c.adapter=w);var E=-1,T=function(){return"[object Object]"===Object.prototype.toString.call(s)&&"function"==typeof s.get};if(s=K(f)(i),!T()&&(s=Q.get(f),!T()))throw new Error(f+" is not a valid datasource");var $=[];function P(e,t){var n;angular.isNumber(e[t])&&(n=e[t],angular.isNumber(n)&&($=$.filter(function(e){return e.id!==t})).push({id:t,run:function(){return e[t]=n}}))}function M(n,r,i){var o,e=Object.getOwnPropertyDescriptor(n,r);e&&(e.set||e.get)||(P(n,r),Object.defineProperty(n,r,{set:function(e){if(o=e,!b.length||y.length){y[i]=e;var t=I.topDataPos();I.adjustPaddings(),"minIndex"===r&&I.onAfterMinIndexSet(t)}else P(n,r)},get:function(){return o}}))}M(s,"minIndex","minIndexUser"),M(s,"maxIndex","maxIndexUser");var A,S=2!==s.get.length?function(e){return s.get(y.next,d,e)}:function(e){s.get({index:y.next,append:y.length?y[y.length-1].item:void 0,count:d},e)},k=2!==s.get.length?function(e){return s.get(y.first-d,d,e)}:function(e){s.get({index:y.first-d,prepend:y.length?y[0].item:void 0,count:d},e)};function j(e){return e&&e!==v||i.$$destroyed}function O(){I.unbind("resize",R),I.unbind("scroll",R)}function L(e){return(m||e.element.height())&&e.element[0].offsetParent}function U(e,t){V(e,t,I.insertElement),g&&!L(e)&&(e.unregisterVisibilityWatcher=e.scope.$watch(function(){L(e)&&(y.forEach(function(e){"function"==typeof e.unregisterVisibilityWatcher&&(e.unregisterVisibilityWatcher(),delete e.unregisterVisibilityWatcher)}),b.length||Y(function(){return N()}))})),g&&x.hideElement(e)}function V(n,e,r){var i=null,o=0y.next+d)return e}}function z(e){if(!w.disabled){var t=I[0].scrollTop,n=I[0].scrollHeight-I[0].clientHeight;(0===t&&!y.bof||t===n&&!y.eof)&&e.preventDefault()}}a(function(e,t){I.createPaddingElements(e[0]),t.$destroy(),e.remove()}),i.$on("$destroy",function(){O(),I.unbind("mousewheel",z)}),I.bind("mousewheel",z),function(){var e=0;if(I.applyContainerStyle())N();else var t=J(function(){if(e++,I.applyContainerStyle()&&(J.cancel(t),N()),500<=50*e)throw J.cancel(t),Error("ui-scroll directive requires a viewport with non-zero height in ".concat(500,"ms"))},50)}()}}}])}]); //# sourceMappingURL=ui-scroll.min.js.map \ No newline at end of file diff --git a/dist/ui-scroll.min.js.map b/dist/ui-scroll.min.js.map index 821f66bf..5c9174da 100644 --- a/dist/ui-scroll.min.js.map +++ b/dist/ui-scroll.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/modules/jqLiteExtras.js","webpack:///./src/modules/elementRoutines.js","webpack:///./src/modules/buffer.js","webpack:///./src/modules/padding.js","webpack:///./src/modules/viewport.js","webpack:///./src/modules/adapter.js","webpack:///./src/ui-scroll.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","JQLiteExtras","element","convertToPx","css","getStyle","isWindow","scrollTo","self","direction","elem","_top$left$direction","_slicedToArray","top","left","method","prop","preserve","isValueDefined","document","documentElement","getWidthHeight","measure","result","measurements","base","borderA","borderB","computedMarginA","computedMarginB","computedStyle","dirA","dirB","paddingA","paddingB","height","width","padding","border","margin","_width$height$measure","offsetWidth","offsetHeight","getMeasurements","outer","outerfull","style","parseFloat","angular","this","nodeType","obj","location","alert","setInterval","window","getComputedStyle","currentStyle","rs","rsLeft","RegExp","source","test","runtimeStyle","pixelLeft","forEach","before","newElem","children","j","parent","ref","contents","prepend","length","after","Error","outerHTML","isNumber","outerHeight","option","outerWidth","offset","docElem","win","box","doc","ownerDocument","arguments","undefined","getBoundingClientRect","defaultView","parentWindow","pageYOffset","scrollTop","clientTop","pageXOffset","scrollLeft","clientLeft","hideClassToken","ElementRoutines","$injector","$q","elementRoutines_classCallCheck","$animate","has","isAngularVersionLessThen1_3","version","major","minor","index","selector","rules","sheet","styleSheets","cssRules","err","insertRule","addRule","wrapper","addClass","removeClass","newElement","previousElement","remove","scope","$destroy","insertElement","deferred","defer","enter","resolve","promise","removeElement","leave","then","ScrollBuffer","elementRoutines","bufferSize","startIndex","buffer","Array","extend","size","reset","eof","bof","first","next","minIndex","maxIndex","minIndexUser","maxIndexUser","append","items","item","insert","Math","max","reverse","min","operation","isTop","op","splice","push","unshift","arg1","arg2","indexOf","_op","getAbsMinIndex","incrementMinIndex","decrementMaxIndex","removeElementAnimated","getAbsMaxIndex","effectiveHeight","elements","Number","MAX_VALUE","bottom","NEGATIVE_INFINITY","offsetParent","CacheProto","$index","sort","a","b","argument","_isTop","Cache","instance","apply","setPrototypeOf","getOwnPropertyNames","methodName","Padding","template","padding_classCallCheck","Node","ELEMENT_NODE","tagName","toLowerCase","concat","find","generateElement","cache","Viewport","viewportController","$rootScope","topPadding","bottomPadding","viewport","container","bufferPadding","overflow-anchor","overflow-y","display","getScope","createPaddingElements","applyContainerStyle","bottomDataPos","scrollHeight","topDataPos","bottomVisiblePos","topVisiblePos","e","sibling","insertElementAnimated","shouldLoadBottom","clipBottom","overage","overageHeight","itemHeight","emptySpaceHeight","add","adjustPaddings","shouldLoadTop","clipTop","visibleItemsHeight","reduce","summ","topPaddingHeight","topCount","bottomPaddingHeight","bottomCount","averageItemHeight","adjustTopPadding","adjustBottomPadding","topPaddingHeightAdd","bottomPaddingHeightAdd","onAfterMinIndexSet","topPaddingHeightOld","diff","onAfterPrepend","updates","prepended","paddingHeight","resetTopPadding","clear","resetBottomPadding","removeCacheItem","removeItem","Adapter","$scope","$parse","$attr","doAdjust","reload","adapter_classCallCheck","isLoading","disabled","viewportScope","startScope","$parent","publicContext","assignAdapter","adapter","generatePublicContext","adapterAttr","replace","adapterOnScope","assign","error","message","_this","publicMethods","publicProps","_loop","attr","set","newItems","applyUpdatesFunc","applyUpdatesIndex","cb","_this2","slice","applyUpdate","_index","isArray","_this3","position","some","newItem","rowTop","topHeight","topDone","bottomDone","itemTop","isEOF","constant","run","jQuery","registerFor","addCSSRules","directive","restrict","controller","child","console","$timeout","$interval","require","transclude","priority","terminal","link","controllers","linker","match","uiScroll","parseNumber","defaultValue","isFloat","floor","isNaN","parseNumericAttr","datasource","itemName","datasourceName","ridActual","pending","persistDatasourceIndex","isDatasourceValid","toString","onRenderHandlers","propName","filter","handler","id","defineDatasourceIndex","propUserName","descriptor","getOwnPropertyDescriptor","fetchNext","success","count","fetchPrevious","isInvalid","rid","$$destroyed","unbindEvents","unbind","resizeAndScrollHandler","isElementVisible","insertWrapperContent","insertAfter","createElement","unregisterVisibilityWatcher","$watch","hideElement","promises","clone","transform","tdInitializer","uiScrollTdInitializer","linking","onLink","updatePaddings","animated","all","enqueueFetch","inserted","loading","fetch","processUpdates","toBePrepended","toBeRemoved","removed","updateDOM","$$phase","$digest","w","showElement","calculateProperties","doAdjustAfterFetch","shift","wheelHandler","event","yMax","clientHeight","preventDefault","$on","tryCount","timer","cancel","initialize"],"mappings":"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","file":"ui-scroll.min.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n","/*!\r\n globals: angular, window\r\n List of used element methods available in JQuery but not in JQuery Lite\r\n element.before(elem)\r\n element.height()\r\n element.outerHeight(true)\r\n element.height(value) = only for Top/Bottom padding elements\r\n element.scrollTop()\r\n element.scrollTop(value)\r\n */\r\n\r\nexport default class JQLiteExtras {\r\n\r\n registerFor(element) {\r\n let convertToPx, css, getStyle, isWindow;\r\n // angular implementation blows up if elem is the window\r\n css = angular.element.prototype.css;\r\n\r\n element.prototype.css = function (name, value) {\r\n let self = this;\r\n let elem = self[0];\r\n if (!(!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style)) {\r\n return css.call(self, name, value);\r\n }\r\n };\r\n\r\n // as defined in angularjs v1.0.5\r\n isWindow = (obj) => obj && obj.document && obj.location && obj.alert && obj.setInterval;\r\n\r\n function scrollTo(self, direction, value) {\r\n let elem = self[0];\r\n let [method, prop, preserve] = {\r\n top: [\r\n 'scrollTop',\r\n 'pageYOffset',\r\n 'scrollLeft'\r\n ],\r\n left: [\r\n 'scrollLeft',\r\n 'pageXOffset',\r\n 'scrollTop'\r\n ]\r\n }[direction];\r\n\r\n const isValueDefined = typeof value !== 'undefined';\r\n if (isWindow(elem)) {\r\n if (isValueDefined) {\r\n return elem.scrollTo(self[preserve].call(self), value);\r\n }\r\n return (prop in elem) ? elem[prop] : elem.document.documentElement[method];\r\n } else {\r\n if (isValueDefined) {\r\n elem[method] = value;\r\n }\r\n return elem[method];\r\n }\r\n }\r\n\r\n if (window.getComputedStyle) {\r\n getStyle = (elem) => window.getComputedStyle(elem, null);\r\n convertToPx = (elem, value) => parseFloat(value);\r\n } else {\r\n getStyle = (elem) => elem.currentStyle;\r\n convertToPx = (elem, value) => {\r\n let left, result, rs, rsLeft, style;\r\n let core_pnum = /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source;\r\n let rnumnonpx = new RegExp('^(' + core_pnum + ')(?!px)[a-z%]+$', 'i');\r\n\r\n if (!rnumnonpx.test(value)) {\r\n return parseFloat(value);\r\n }\r\n\r\n // ported from JQuery\r\n style = elem.style;\r\n left = style.left;\r\n rs = elem.runtimeStyle;\r\n rsLeft = rs && rs.left;\r\n if (rs) {\r\n rs.left = style.left;\r\n }\r\n // put in the new values to get a computed style out\r\n style.left = value;\r\n result = style.pixelLeft;\r\n style.left = left;\r\n if (rsLeft) {\r\n rs.left = rsLeft;\r\n }\r\n return result;\r\n };\r\n }\r\n\r\n function getMeasurements(elem, measure) {\r\n let base, borderA, borderB, computedMarginA, computedMarginB, computedStyle, dirA, dirB, marginA, marginB, paddingA, paddingB;\r\n\r\n if (isWindow(elem)) {\r\n base = document.documentElement[{height: 'clientHeight', width: 'clientWidth'}[measure]];\r\n\r\n return {\r\n base: base,\r\n padding: 0,\r\n border: 0,\r\n margin: 0\r\n };\r\n }\r\n\r\n // Start with offset property\r\n [\r\n base,\r\n dirA,\r\n dirB\r\n ] = {\r\n width: [\r\n elem.offsetWidth,\r\n 'Left',\r\n 'Right'\r\n ],\r\n height: [\r\n elem.offsetHeight,\r\n 'Top',\r\n 'Bottom'\r\n ]\r\n }[measure];\r\n\r\n computedStyle = getStyle(elem);\r\n paddingA = convertToPx(elem, computedStyle['padding' + dirA]) || 0;\r\n paddingB = convertToPx(elem, computedStyle['padding' + dirB]) || 0;\r\n borderA = convertToPx(elem, computedStyle['border' + dirA + 'Width']) || 0;\r\n borderB = convertToPx(elem, computedStyle['border' + dirB + 'Width']) || 0;\r\n computedMarginA = computedStyle['margin' + dirA];\r\n computedMarginB = computedStyle['margin' + dirB];\r\n\r\n // I do not care for width for now, so this hack is irrelevant\r\n // if ( !supportsPercentMargin )\r\n // computedMarginA = hackPercentMargin( elem, computedStyle, computedMarginA )\r\n // computedMarginB = hackPercentMargin( elem, computedStyle, computedMarginB )\r\n marginA = convertToPx(elem, computedMarginA) || 0;\r\n marginB = convertToPx(elem, computedMarginB) || 0;\r\n\r\n return {\r\n base: base,\r\n padding: paddingA + paddingB,\r\n border: borderA + borderB,\r\n margin: marginA + marginB\r\n };\r\n }\r\n\r\n function getWidthHeight(elem, direction, measure) {\r\n let computedStyle, result;\r\n\r\n let measurements = getMeasurements(elem, direction);\r\n\r\n if (measurements.base > 0) {\r\n return {\r\n base: measurements.base - measurements.padding - measurements.border,\r\n outer: measurements.base,\r\n outerfull: measurements.base + measurements.margin\r\n }[measure];\r\n }\r\n\r\n // Fall back to computed then uncomputed css if necessary\r\n computedStyle = getStyle(elem);\r\n result = computedStyle[direction];\r\n\r\n if (result < 0 || result === null) {\r\n result = elem.style[direction] || 0;\r\n }\r\n\r\n // Normalize \"\", auto, and prepare for extra\r\n result = parseFloat(result) || 0;\r\n\r\n return {\r\n base: result - measurements.padding - measurements.border,\r\n outer: result,\r\n outerfull: result + measurements.padding + measurements.border + measurements.margin\r\n }[measure];\r\n }\r\n\r\n // define missing methods\r\n return angular.forEach({\r\n before(newElem) {\r\n var children, elem, i, j, parent, ref, self;\r\n self = this;\r\n elem = self[0];\r\n parent = self.parent();\r\n children = parent.contents();\r\n if (children[0] === elem) {\r\n return parent.prepend(newElem);\r\n } else {\r\n for (i = j = 1, ref = children.length - 1; 1 <= ref ? j <= ref : j >= ref; i = 1 <= ref ? ++j : --j) {\r\n if (children[i] === elem) {\r\n angular.element(children[i - 1]).after(newElem);\r\n return;\r\n }\r\n }\r\n throw new Error('invalid DOM structure ' + elem.outerHTML);\r\n }\r\n },\r\n height (value){\r\n var self;\r\n self = this;\r\n if (typeof value !== 'undefined') {\r\n if (angular.isNumber(value)) {\r\n value = value + 'px';\r\n }\r\n return css.call(self, 'height', value);\r\n } else {\r\n return getWidthHeight(this[0], 'height', 'base');\r\n }\r\n },\r\n outerHeight(option) {\r\n return getWidthHeight(this[0], 'height', option ? 'outerfull' : 'outer');\r\n },\r\n outerWidth(option) {\r\n return getWidthHeight(this[0], 'width', option ? 'outerfull' : 'outer');\r\n },\r\n\r\n /*\r\n The offset setter method is not implemented\r\n */\r\n offset(value) {\r\n let docElem, win;\r\n let self = this;\r\n let box = {\r\n top: 0,\r\n left: 0\r\n };\r\n let elem = self[0];\r\n let doc = elem && elem.ownerDocument;\r\n\r\n if (arguments.length) {\r\n if (value === undefined) {\r\n return self;\r\n }\r\n // TODO: implement setter\r\n throw new Error('offset setter method is not implemented');\r\n }\r\n\r\n if (!doc) {\r\n return;\r\n }\r\n\r\n docElem = doc.documentElement;\r\n\r\n // TODO: Make sure it's not a disconnected DOM node\r\n\r\n if (elem.getBoundingClientRect != null) {\r\n box = elem.getBoundingClientRect();\r\n }\r\n\r\n win = doc.defaultView || doc.parentWindow;\r\n\r\n return {\r\n top: box.top + (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0),\r\n left: box.left + (win.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)\r\n };\r\n },\r\n scrollTop(value) {\r\n return scrollTo(this, 'top', value);\r\n },\r\n scrollLeft(value) {\r\n return scrollTo(this, 'left', value);\r\n }\r\n }, (value, key) => {\r\n if (!element.prototype[key]) {\r\n return element.prototype[key] = value;\r\n }\r\n });\r\n }\r\n\r\n}\r\n","const hideClassToken = 'ng-ui-scroll-hide';\r\n\r\nexport default class ElementRoutines {\r\n\r\n static addCSSRules() {\r\n const selector = '.' + hideClassToken;\r\n const rules = 'display: none';\r\n const sheet = document.styleSheets[0];\r\n let index;\r\n try {\r\n index = sheet.cssRules.length;\r\n } catch (err) {\r\n index = 0;\r\n }\r\n if('insertRule' in sheet) {\r\n sheet.insertRule(selector + '{' + rules + '}', index);\r\n }\r\n else if('addRule' in sheet) {\r\n sheet.addRule(selector, rules, index);\r\n }\r\n }\r\n\r\n constructor($injector, $q) {\r\n this.$animate = ($injector.has && $injector.has('$animate')) ? $injector.get('$animate') : null;\r\n this.isAngularVersionLessThen1_3 = angular.version.major === 1 && angular.version.minor < 3;\r\n this.$q = $q;\r\n }\r\n\r\n hideElement(wrapper) {\r\n wrapper.element.addClass(hideClassToken);\r\n }\r\n\r\n showElement(wrapper) {\r\n wrapper.element.removeClass(hideClassToken);\r\n }\r\n\r\n insertElement(newElement, previousElement) {\r\n previousElement.after(newElement);\r\n return [];\r\n }\r\n\r\n removeElement(wrapper) {\r\n wrapper.element.remove();\r\n wrapper.scope.$destroy();\r\n return [];\r\n }\r\n\r\n insertElementAnimated(newElement, previousElement) {\r\n if (!this.$animate) {\r\n return this.insertElement(newElement, previousElement);\r\n }\r\n\r\n if (this.isAngularVersionLessThen1_3) {\r\n const deferred = this.$q.defer();\r\n // no need for parent - previous element is never null\r\n this.$animate.enter(newElement, null, previousElement, () => deferred.resolve());\r\n\r\n return [deferred.promise];\r\n }\r\n\r\n // no need for parent - previous element is never null\r\n return [this.$animate.enter(newElement, null, previousElement)];\r\n }\r\n\r\n removeElementAnimated(wrapper) {\r\n if (!this.$animate) {\r\n return this.removeElement(wrapper);\r\n }\r\n\r\n if (this.isAngularVersionLessThen1_3) {\r\n const deferred = this.$q.defer();\r\n this.$animate.leave(wrapper.element, () => {\r\n wrapper.scope.$destroy();\r\n return deferred.resolve();\r\n });\r\n\r\n return [deferred.promise];\r\n }\r\n\r\n return [(this.$animate.leave(wrapper.element)).then(() => wrapper.scope.$destroy())];\r\n }\r\n}","export default function ScrollBuffer(elementRoutines, bufferSize, startIndex) {\r\n const buffer = Object.create(Array.prototype);\r\n\r\n angular.extend(buffer, {\r\n size: bufferSize,\r\n\r\n reset(startIndex) {\r\n buffer.remove(0, buffer.length);\r\n buffer.eof = false;\r\n buffer.bof = false;\r\n buffer.first = startIndex;\r\n buffer.next = startIndex;\r\n buffer.minIndex = startIndex;\r\n buffer.maxIndex = startIndex;\r\n buffer.minIndexUser = null;\r\n buffer.maxIndexUser = null;\r\n },\r\n\r\n append(items) {\r\n items.forEach((item) => {\r\n ++buffer.next;\r\n buffer.insert('append', item);\r\n });\r\n buffer.maxIndex = buffer.eof ? buffer.next - 1 : Math.max(buffer.next - 1, buffer.maxIndex);\r\n },\r\n\r\n prepend(items) {\r\n items.reverse().forEach((item) => {\r\n --buffer.first;\r\n buffer.insert('prepend', item);\r\n });\r\n buffer.minIndex = buffer.bof ? buffer.minIndex = buffer.first : Math.min(buffer.first, buffer.minIndex);\r\n },\r\n\r\n /**\r\n * inserts wrapped element in the buffer\r\n * the first argument is either operation keyword (see below) or a number for operation 'insert'\r\n * for insert the number is the index for the buffer element the new one have to be inserted after\r\n * operations: 'append', 'prepend', 'insert', 'remove', 'update', 'none'\r\n */\r\n insert(operation, item, isTop) {\r\n const wrapper = {\r\n item: item\r\n };\r\n\r\n if (operation % 1 === 0) {// it is an insert\r\n wrapper.op = 'insert';\r\n buffer.splice(operation, 0, wrapper);\r\n if(isTop) {\r\n buffer.first--;\r\n }\r\n else {\r\n buffer.next++;\r\n }\r\n } else {\r\n wrapper.op = operation;\r\n switch (operation) {\r\n case 'append':\r\n buffer.push(wrapper);\r\n break;\r\n case 'prepend':\r\n buffer.unshift(wrapper);\r\n break;\r\n }\r\n }\r\n },\r\n\r\n // removes elements from buffer\r\n remove(arg1, arg2) {\r\n if (angular.isNumber(arg1)) {\r\n // removes items from arg1 (including) through arg2 (excluding)\r\n for (let i = arg1; i < arg2; i++) {\r\n elementRoutines.removeElement(buffer[i]);\r\n }\r\n return buffer.splice(arg1, arg2 - arg1);\r\n }\r\n // removes single item(wrapper) from the buffer\r\n buffer.splice(buffer.indexOf(arg1), 1);\r\n if(arg1._op === 'isTop' && buffer.first === this.getAbsMinIndex()) {\r\n this.incrementMinIndex();\r\n }\r\n else {\r\n this.decrementMaxIndex();\r\n }\r\n if(arg1._op === 'isTop') {\r\n buffer.first++;\r\n }\r\n else {\r\n buffer.next--;\r\n }\r\n if(!buffer.length) {\r\n buffer.first = 1;\r\n buffer.next = 1;\r\n }\r\n\r\n return elementRoutines.removeElementAnimated(arg1);\r\n },\r\n\r\n incrementMinIndex() {\r\n if(buffer.minIndexUser !== null) {\r\n if(buffer.minIndex > buffer.minIndexUser) {\r\n buffer.minIndexUser++;\r\n return;\r\n }\r\n if(buffer.minIndex === buffer.minIndexUser) {\r\n buffer.minIndexUser++;\r\n }\r\n }\r\n buffer.minIndex++;\r\n },\r\n\r\n decrementMaxIndex() {\r\n if(buffer.maxIndexUser !== null && buffer.maxIndex <= buffer.maxIndexUser) {\r\n buffer.maxIndexUser--;\r\n }\r\n buffer.maxIndex--;\r\n },\r\n\r\n getAbsMinIndex() {\r\n if(buffer.minIndexUser !== null) {\r\n return Math.min(buffer.minIndexUser, buffer.minIndex);\r\n }\r\n return buffer.minIndex;\r\n },\r\n\r\n getAbsMaxIndex() {\r\n if(buffer.maxIndexUser !== null) {\r\n return Math.max(buffer.maxIndexUser, buffer.maxIndex);\r\n }\r\n return buffer.maxIndex;\r\n },\r\n\r\n effectiveHeight(elements) {\r\n if (!elements.length) {\r\n return 0;\r\n }\r\n let top = Number.MAX_VALUE;\r\n let bottom = Number.NEGATIVE_INFINITY;\r\n elements.forEach((wrapper) => {\r\n if (wrapper.element[0].offsetParent) {\r\n // element style is not display:none\r\n top = Math.min(top, wrapper.element.offset().top);\r\n bottom = Math.max(bottom, wrapper.element.offset().top + wrapper.element.outerHeight(true));\r\n }\r\n });\r\n return Math.max(0, bottom - top);\r\n }\r\n\r\n });\r\n\r\n buffer.reset(startIndex);\r\n\r\n return buffer;\r\n}\r\n","// Can't just extend the Array, due to Babel does not support built-in classes extending\r\n// This solution was taken from https://stackoverflow.com/questions/46897414/es6-class-extends-array-workaround-for-es5-babel-transpile\r\nclass CacheProto {\r\n add(item) {\r\n for (let i = this.length - 1; i >= 0; i--) {\r\n if (this[i].index === item.scope.$index) {\r\n this[i].height = item.element.outerHeight();\r\n return;\r\n }\r\n }\r\n this.push({\r\n index: item.scope.$index,\r\n height: item.element.outerHeight()\r\n });\r\n this.sort((a, b) => ((a.index < b.index) ? -1 : ((a.index > b.index) ? 1 : 0)));\r\n }\r\n\r\n remove(argument, _isTop) {\r\n const index = argument % 1 === 0 ? argument : argument.scope.$index;\r\n const isTop = argument % 1 === 0 ? _isTop : argument._op === 'isTop';\r\n for (let i = this.length - 1; i >= 0; i--) {\r\n if (this[i].index === index) {\r\n this.splice(i, 1);\r\n break;\r\n }\r\n }\r\n if(!isTop) {\r\n for (let i = this.length - 1; i >= 0; i--) {\r\n if (this[i].index > index) {\r\n this[i].index--;\r\n }\r\n }\r\n }\r\n }\r\n\r\n clear() {\r\n this.length = 0;\r\n }\r\n}\r\n\r\nfunction Cache() {\r\n const instance = [];\r\n instance.push.apply(instance, arguments);\r\n Object.setPrototypeOf(instance, Cache.prototype);\r\n return instance;\r\n}\r\nCache.prototype = Object.create(Array.prototype);\r\nObject.getOwnPropertyNames(CacheProto.prototype).forEach(methodName =>\r\n Cache.prototype[methodName] = CacheProto.prototype[methodName]\r\n);\r\n\r\nfunction generateElement(template) {\r\n if(template.nodeType !== Node.ELEMENT_NODE) {\r\n throw new Error('ui-scroll directive requires an Element node for templating the view');\r\n }\r\n let element;\r\n switch (template.tagName.toLowerCase()) {\r\n case 'dl':\r\n throw new Error(`ui-scroll directive does not support <${template.tagName}> as a repeating tag: ${template.outerHTML}`);\r\n case 'tr':\r\n let table = angular.element('
    ');\r\n element = table.find('tr');\r\n break;\r\n case 'li':\r\n element = angular.element('
  • ');\r\n break;\r\n default:\r\n element = angular.element('
    ');\r\n }\r\n return element;\r\n}\r\n\r\nclass Padding {\r\n constructor(template) {\r\n this.element = generateElement(template);\r\n this.cache = new Cache();\r\n }\r\n\r\n height() {\r\n return this.element.height.apply(this.element, arguments);\r\n }\r\n}\r\n\r\nexport default Padding;","import Padding from './padding';\r\n\r\nexport default function Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding) {\r\n let topPadding = null;\r\n let bottomPadding = null;\r\n const viewport = viewportController && viewportController.viewport ? viewportController.viewport : angular.element(window);\r\n const container = viewportController && viewportController.container ? viewportController.container : undefined;\r\n const scope = viewportController && viewportController.scope ? viewportController.scope : $rootScope;\r\n\r\n viewport.css({\r\n 'overflow-anchor': 'none',\r\n 'overflow-y': 'auto',\r\n 'display': 'block'\r\n });\r\n\r\n function bufferPadding() {\r\n return viewport.outerHeight() * padding; // some extra space to initiate preload\r\n }\r\n\r\n angular.extend(viewport, {\r\n getScope() {\r\n return scope;\r\n },\r\n\r\n createPaddingElements(template) {\r\n topPadding = new Padding(template);\r\n bottomPadding = new Padding(template);\r\n element.before(topPadding.element);\r\n element.after(bottomPadding.element);\r\n topPadding.height(0);\r\n bottomPadding.height(0);\r\n },\r\n\r\n applyContainerStyle() {\r\n if (!container) {\r\n return true;\r\n }\r\n if(container !== viewport) {\r\n viewport.css('height', window.getComputedStyle(container[0]).height);\r\n }\r\n return viewport.height() > 0;\r\n },\r\n\r\n bottomDataPos() {\r\n let scrollHeight = viewport[0].scrollHeight;\r\n scrollHeight = scrollHeight != null ? scrollHeight : viewport[0].document.documentElement.scrollHeight;\r\n return scrollHeight - bottomPadding.height();\r\n },\r\n\r\n topDataPos() {\r\n return topPadding.height();\r\n },\r\n\r\n bottomVisiblePos() {\r\n return viewport.scrollTop() + viewport.outerHeight();\r\n },\r\n\r\n topVisiblePos() {\r\n return viewport.scrollTop();\r\n },\r\n\r\n insertElement(e, sibling) {\r\n return elementRoutines.insertElement(e, sibling || topPadding.element);\r\n },\r\n\r\n insertElementAnimated(e, sibling) {\r\n return elementRoutines.insertElementAnimated(e, sibling || topPadding.element);\r\n },\r\n\r\n shouldLoadBottom() {\r\n return !buffer.eof && viewport.bottomDataPos() < viewport.bottomVisiblePos() + bufferPadding();\r\n },\r\n\r\n clipBottom() {\r\n // clip the invisible items off the bottom\r\n let overage = 0;\r\n let overageHeight = 0;\r\n let itemHeight = 0;\r\n let emptySpaceHeight = viewport.bottomDataPos() - viewport.bottomVisiblePos() - bufferPadding();\r\n\r\n for (let i = buffer.length - 1; i >= 0; i--) {\r\n itemHeight = buffer[i].element.outerHeight(true);\r\n if (overageHeight + itemHeight > emptySpaceHeight) {\r\n break;\r\n }\r\n bottomPadding.cache.add(buffer[i]);\r\n overageHeight += itemHeight;\r\n overage++;\r\n }\r\n\r\n if (overage > 0) {\r\n buffer.eof = false;\r\n buffer.remove(buffer.length - overage, buffer.length);\r\n buffer.next -= overage;\r\n viewport.adjustPaddings();\r\n }\r\n },\r\n\r\n shouldLoadTop() {\r\n return !buffer.bof && (viewport.topDataPos() > viewport.topVisiblePos() - bufferPadding());\r\n },\r\n\r\n clipTop() {\r\n // clip the invisible items off the top\r\n let overage = 0;\r\n let overageHeight = 0;\r\n let itemHeight = 0;\r\n let emptySpaceHeight = viewport.topVisiblePos() - viewport.topDataPos() - bufferPadding();\r\n\r\n for (let i = 0; i < buffer.length; i++) {\r\n itemHeight = buffer[i].element.outerHeight(true);\r\n if (overageHeight + itemHeight > emptySpaceHeight) {\r\n break;\r\n }\r\n topPadding.cache.add(buffer[i]);\r\n overageHeight += itemHeight;\r\n overage++;\r\n }\r\n\r\n if (overage > 0) {\r\n // we need to adjust top padding element before items are removed from top\r\n // to avoid strange behaviour of scroll bar during remove top items when we are at the very bottom\r\n topPadding.height(topPadding.height() + overageHeight);\r\n buffer.bof = false;\r\n buffer.remove(0, overage);\r\n buffer.first += overage;\r\n }\r\n },\r\n\r\n adjustPaddings() {\r\n if (!buffer.length) {\r\n return;\r\n }\r\n\r\n // precise heights calculation based on items that are in buffer or that were in buffer once\r\n const visibleItemsHeight = buffer.reduce((summ, item) => summ + item.element.outerHeight(true), 0);\r\n\r\n let topPaddingHeight = 0, topCount = 0;\r\n topPadding.cache.forEach(item => {\r\n if(item.index < buffer.first) {\r\n topPaddingHeight += item.height;\r\n topCount++;\r\n }\r\n });\r\n\r\n let bottomPaddingHeight = 0, bottomCount = 0;\r\n bottomPadding.cache.forEach(item => {\r\n if(item.index >= buffer.next) {\r\n bottomPaddingHeight += item.height;\r\n bottomCount++;\r\n }\r\n });\r\n\r\n const totalHeight = visibleItemsHeight + topPaddingHeight + bottomPaddingHeight;\r\n const averageItemHeight = totalHeight / (topCount + bottomCount + buffer.length);\r\n\r\n // average heights calculation, items that have never been reached\r\n let adjustTopPadding = buffer.minIndexUser !== null && buffer.minIndex > buffer.minIndexUser;\r\n let adjustBottomPadding = buffer.maxIndexUser !== null && buffer.maxIndex < buffer.maxIndexUser;\r\n let topPaddingHeightAdd = adjustTopPadding ? (buffer.minIndex - buffer.minIndexUser) * averageItemHeight : 0;\r\n let bottomPaddingHeightAdd = adjustBottomPadding ? (buffer.maxIndexUser - buffer.maxIndex) * averageItemHeight : 0;\r\n\r\n // paddings combine adjustment\r\n topPadding.height(topPaddingHeight + topPaddingHeightAdd);\r\n bottomPadding.height(bottomPaddingHeight + bottomPaddingHeightAdd);\r\n },\r\n\r\n onAfterMinIndexSet(topPaddingHeightOld) {\r\n // additional scrollTop adjustment in case of datasource.minIndex external set\r\n if (buffer.minIndexUser !== null && buffer.minIndex > buffer.minIndexUser) {\r\n let diff = topPadding.height() - topPaddingHeightOld;\r\n viewport.scrollTop(viewport.scrollTop() + diff);\r\n while((diff -= viewport.scrollTop()) > 0) {\r\n bottomPadding.height(bottomPadding.height() + diff);\r\n viewport.scrollTop(viewport.scrollTop() + diff);\r\n }\r\n }\r\n },\r\n\r\n onAfterPrepend(updates) {\r\n if (!updates.prepended.length)\r\n return;\r\n const height = buffer.effectiveHeight(updates.prepended);\r\n const paddingHeight = topPadding.height() - height;\r\n if (paddingHeight >= 0) {\r\n topPadding.height(paddingHeight);\r\n }\r\n else {\r\n topPadding.height(0);\r\n viewport.scrollTop(viewport.scrollTop() - paddingHeight);\r\n }\r\n },\r\n\r\n resetTopPadding() {\r\n topPadding.height(0);\r\n topPadding.cache.clear();\r\n },\r\n\r\n resetBottomPadding() {\r\n bottomPadding.height(0);\r\n bottomPadding.cache.clear();\r\n },\r\n\r\n removeCacheItem(item, isTop) {\r\n topPadding.cache.remove(item, isTop);\r\n bottomPadding.cache.remove(item, isTop);\r\n },\r\n\r\n removeItem(item) {\r\n this.removeCacheItem(item);\r\n return buffer.remove(item);\r\n }\r\n });\r\n\r\n return viewport;\r\n}\r\n","class Adapter {\r\n\r\n constructor($scope, $parse, $attr, viewport, buffer, doAdjust, reload) {\r\n this.$parse = $parse;\r\n this.$attr = $attr;\r\n this.viewport = viewport;\r\n this.buffer = buffer;\r\n\r\n this.doAdjust = doAdjust;\r\n this.reload = reload;\r\n\r\n this.isLoading = false;\r\n this.disabled = false;\r\n\r\n const viewportScope = viewport.getScope();\r\n this.startScope = viewportScope.$parent ? viewportScope : $scope;\r\n\r\n this.publicContext = {};\r\n this.assignAdapter($attr.adapter);\r\n this.generatePublicContext();\r\n }\r\n\r\n assignAdapter(adapterAttr) {\r\n if (!adapterAttr || !(adapterAttr = adapterAttr.replace(/^\\s+|\\s+$/gm, ''))) {\r\n return;\r\n }\r\n let adapterOnScope;\r\n\r\n try {\r\n this.$parse(adapterAttr).assign(this.startScope, {});\r\n adapterOnScope = this.$parse(adapterAttr)(this.startScope);\r\n }\r\n catch (error) {\r\n error.message = `Angular ui-scroll Adapter assignment exception.\\n` +\r\n `Can't parse \"${adapterAttr}\" expression.\\n` +\r\n error.message;\r\n throw error;\r\n }\r\n\r\n angular.extend(adapterOnScope, this.publicContext);\r\n this.publicContext = adapterOnScope;\r\n }\r\n\r\n generatePublicContext() {\r\n // these methods will be accessible out of ui-scroll via user defined adapter\r\n const publicMethods = ['reload', 'applyUpdates', 'append', 'prepend', 'isBOF', 'isEOF', 'isEmpty'];\r\n for (let i = publicMethods.length - 1; i >= 0; i--) {\r\n this.publicContext[publicMethods[i]] = this[publicMethods[i]].bind(this);\r\n }\r\n\r\n // these read-only props will be accessible out of ui-scroll via user defined adapter\r\n const publicProps = ['isLoading', 'topVisible', 'topVisibleElement', 'topVisibleScope', 'bottomVisible', 'bottomVisibleElement', 'bottomVisibleScope'];\r\n for (let i = publicProps.length - 1; i >= 0; i--) {\r\n let property, attr = this.$attr[publicProps[i]];\r\n Object.defineProperty(this, publicProps[i], {\r\n get: () => property,\r\n set: (value) => {\r\n property = value;\r\n this.publicContext[publicProps[i]] = value;\r\n if (attr) {\r\n this.$parse(attr).assign(this.startScope, value);\r\n }\r\n }\r\n });\r\n }\r\n\r\n // non-read-only public property\r\n Object.defineProperty(this.publicContext, 'disabled', {\r\n get: () => this.disabled,\r\n set: (value) => (!(this.disabled = value)) ? this.doAdjust() : null\r\n });\r\n }\r\n\r\n loading(value) {\r\n this.isLoading = value;\r\n }\r\n\r\n isBOF() {\r\n return this.buffer.bof;\r\n }\r\n\r\n isEOF() {\r\n return this.buffer.eof;\r\n }\r\n\r\n isEmpty() {\r\n return !this.buffer.length;\r\n }\r\n\r\n append(newItems) {\r\n this.buffer.append(newItems);\r\n this.doAdjust();\r\n this.viewport.clipTop();\r\n this.viewport.clipBottom();\r\n }\r\n\r\n prepend(newItems) {\r\n this.buffer.prepend(newItems);\r\n this.doAdjust();\r\n this.viewport.clipTop();\r\n this.viewport.clipBottom();\r\n }\r\n\r\n applyUpdates(arg1, arg2) {\r\n if (typeof arg1 === 'function') {\r\n this.applyUpdatesFunc(arg1);\r\n } else {\r\n this.applyUpdatesIndex(arg1, arg2);\r\n }\r\n this.doAdjust();\r\n }\r\n\r\n applyUpdatesFunc(cb) {\r\n this.buffer.slice(0).forEach((wrapper) => {\r\n // we need to do it on the buffer clone, because buffer content\r\n // may change as we iterate through\r\n this.applyUpdate(wrapper, cb(wrapper.item, wrapper.scope, wrapper.element));\r\n });\r\n }\r\n\r\n applyUpdatesIndex(index, newItems) {\r\n if (index % 1 !== 0) {\r\n throw new Error('applyUpdates - ' + index + ' is not a valid index (should be an integer)');\r\n }\r\n const _index = index - this.buffer.first;\r\n\r\n // apply updates only within buffer\r\n if (_index >= 0 && _index < this.buffer.length) {\r\n this.applyUpdate(this.buffer[_index], newItems);\r\n }\r\n // out-of-buffer case: deletion may affect Paddings\r\n else if(index >= this.buffer.getAbsMinIndex() && index <= this.buffer.getAbsMaxIndex()) {\r\n if(angular.isArray(newItems) && !newItems.length) {\r\n this.viewport.removeCacheItem(index, index === this.buffer.minIndex);\r\n if(index === this.buffer.getAbsMinIndex()) {\r\n this.buffer.incrementMinIndex();\r\n }\r\n else {\r\n this.buffer.decrementMaxIndex();\r\n }\r\n }\r\n }\r\n }\r\n\r\n applyUpdate(wrapper, newItems) {\r\n if (!angular.isArray(newItems)) {\r\n return;\r\n }\r\n let position = this.buffer.indexOf(wrapper);\r\n if (!newItems.reverse().some(newItem => newItem === wrapper.item)) {\r\n wrapper.op = 'remove';\r\n if(position === 0 && !newItems.length) {\r\n wrapper._op = 'isTop'; // to catch \"first\" edge case on remove\r\n }\r\n }\r\n newItems.forEach((newItem) => {\r\n if (newItem === wrapper.item) {\r\n position--;\r\n } else {\r\n // 3 parameter (isTop) is to catch \"first\" edge case on insert\r\n this.buffer.insert(position + 1, newItem, position === -1);\r\n }\r\n });\r\n }\r\n\r\n calculateProperties() {\r\n let rowTop = null, topHeight = 0;\r\n let topDone = false, bottomDone = false;\r\n const length = this.buffer.length;\r\n\r\n for (let i = 0; i < length; i++) {\r\n const item = this.buffer[i];\r\n const itemTop = item.element.offset().top;\r\n\r\n if (rowTop !== itemTop) { // a new row condition\r\n const itemHeight = item.element.outerHeight(true);\r\n const top = this.viewport.topDataPos() + topHeight + itemHeight;\r\n\r\n if (!topDone && top > this.viewport.topVisiblePos()) {\r\n topDone = true;\r\n this['topVisible'] = item.item;\r\n this['topVisibleElement'] = item.element;\r\n this['topVisibleScope'] = item.scope;\r\n }\r\n if (!bottomDone && (top >= this.viewport.bottomVisiblePos() || (i === length - 1 && this.isEOF()))) {\r\n bottomDone = true;\r\n this['bottomVisible'] = item.item;\r\n this['bottomVisibleElement'] = item.element;\r\n this['bottomVisibleScope'] = item.scope;\r\n }\r\n topHeight += itemHeight;\r\n }\r\n rowTop = itemTop;\r\n\r\n if (topDone && bottomDone) {\r\n break;\r\n }\r\n }\r\n }\r\n\r\n}\r\n\r\nexport default Adapter;\r\n","import JQLiteExtras from './modules/jqLiteExtras';\nimport ElementRoutines from './modules/elementRoutines.js';\nimport ScrollBuffer from './modules/buffer.js';\nimport Viewport from './modules/viewport.js';\nimport Adapter from './modules/adapter.js';\n\nangular.module('ui.scroll', [])\n\n .constant('JQLiteExtras', JQLiteExtras)\n .run(['JQLiteExtras', (JQLiteExtras) => {\n !window.jQuery ? (new JQLiteExtras()).registerFor(angular.element) : null;\n ElementRoutines.addCSSRules();\n }])\n\n .directive('uiScrollViewport', function () {\n return {\n restrict: 'A',\n controller: [\n '$scope',\n '$element',\n function (scope, element) {\n this.container = element;\n this.viewport = element;\n this.scope = scope;\n\n angular.forEach(element.children(), child => {\n if (child.tagName.toLowerCase() === 'tbody') {\n this.viewport = angular.element(child);\n }\n });\n\n return this;\n }\n ]\n };\n })\n\n .directive('uiScroll', [\n '$log',\n '$injector',\n '$rootScope',\n '$timeout',\n '$interval',\n '$q',\n '$parse',\n function (console, $injector, $rootScope, $timeout, $interval, $q, $parse) {\n\n return {\n require: ['?^uiScrollViewport'],\n restrict: 'A',\n transclude: 'element',\n priority: 1000,\n terminal: true,\n link: link\n };\n\n function link($scope, element, $attr, controllers, linker) {\n const match = $attr.uiScroll.match(/^\\s*(\\w+)\\s+in\\s+([(\\w|\\$)\\.]+)\\s*$/);\n if (!match) {\n throw new Error('Expected uiScroll in form of \\'_item_ in _datasource_\\' but got \\'' + $attr.uiScroll + '\\'');\n }\n\n function parseNumber(value, defaultValue, isFloat) {\n if (!isFloat) {\n value = value === null ? defaultValue : Math.floor(value);\n }\n return isNaN(value) ? defaultValue : value;\n }\n\n function parseNumericAttr(value, defaultValue, isFloat) {\n const result = $parse(value)($scope);\n return parseNumber(result, defaultValue, isFloat);\n }\n\n const BUFFER_MIN = 3;\n const BUFFER_DEFAULT = 10;\n const PADDING_MIN = 0.3;\n const PADDING_DEFAULT = 0.5;\n const START_INDEX_DEFAULT = 1;\n const MAX_VIEWPORT_DELAY = 500;\n const VIEWPORT_POLLING_INTERVAL = 50;\n\n let datasource = null;\n const itemName = match[1];\n const datasourceName = match[2];\n const viewportController = controllers[0];\n const bufferSize = Math.max(BUFFER_MIN, parseNumericAttr($attr.bufferSize, BUFFER_DEFAULT));\n const padding = Math.max(PADDING_MIN, parseNumericAttr($attr.padding, PADDING_DEFAULT, true));\n let startIndex = parseNumericAttr($attr.startIndex, START_INDEX_DEFAULT);\n let ridActual = 0; // current data revision id\n let pending = [];\n\n const elementRoutines = new ElementRoutines($injector, $q);\n const buffer = new ScrollBuffer(elementRoutines, bufferSize, startIndex);\n const viewport = new Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding);\n const adapter = new Adapter($scope, $parse, $attr, viewport, buffer, doAdjust, reload);\n\n if (viewportController) {\n viewportController.adapter = adapter;\n }\n\n const isDatasourceValid = () =>\n Object.prototype.toString.call(datasource) === '[object Object]' && typeof datasource.get === 'function';\n\n datasource = $parse(datasourceName)($scope); // try to get datasource on scope\n if (!isDatasourceValid()) {\n datasource = $injector.get(datasourceName); // try to inject datasource as service\n if (!isDatasourceValid()) {\n throw new Error(datasourceName + ' is not a valid datasource');\n }\n }\n\n let onRenderHandlers = [];\n function onRenderHandlersRunner() {\n onRenderHandlers.forEach(handler => handler.run());\n onRenderHandlers = [];\n }\n function persistDatasourceIndex(datasource, propName) {\n let getter;\n // need to postpone min/maxIndexUser processing if the view is empty\n if(angular.isNumber(datasource[propName])) {\n getter = datasource[propName];\n if(angular.isNumber(getter)) {\n onRenderHandlers = onRenderHandlers.filter(handler => handler.id !== propName);\n onRenderHandlers.push({\n id: propName,\n run: () => datasource[propName] = getter\n });\n }\n }\n }\n\n function defineDatasourceIndex(datasource, propName, propUserName) {\n const descriptor = Object.getOwnPropertyDescriptor(datasource, propName);\n if (descriptor && (descriptor.set || descriptor.get)) {\n return;\n }\n let getter;\n persistDatasourceIndex(datasource, propName);\n Object.defineProperty(datasource, propName, {\n set: (value) => {\n getter = value;\n if(pending.length && !buffer.length) {\n persistDatasourceIndex(datasource, propName);\n return;\n }\n buffer[propUserName] = value;\n const topPaddingHeightOld = viewport.topDataPos();\n viewport.adjustPaddings();\n if (propName === 'minIndex') {\n viewport.onAfterMinIndexSet(topPaddingHeightOld);\n }\n },\n get: () => getter\n });\n }\n\n defineDatasourceIndex(datasource, 'minIndex', 'minIndexUser');\n defineDatasourceIndex(datasource, 'maxIndex', 'maxIndexUser');\n\n const fetchNext = (datasource.get.length !== 2) ?\n (success) => datasource.get(buffer.next, bufferSize, success) :\n (success) => {\n datasource.get({\n index: buffer.next,\n append: buffer.length ? buffer[buffer.length - 1].item : void 0,\n count: bufferSize\n }, success);\n };\n\n const fetchPrevious = (datasource.get.length !== 2) ?\n (success) => datasource.get(buffer.first - bufferSize, bufferSize, success) :\n (success) => {\n datasource.get({\n index: buffer.first - bufferSize,\n prepend: buffer.length ? buffer[0].item : void 0,\n count: bufferSize\n }, success);\n };\n\n const initialize = () => {\n let tryCount = 0;\n if(!viewport.applyContainerStyle()) {\n const timer = $interval(() => {\n tryCount++;\n if(viewport.applyContainerStyle()) {\n $interval.cancel(timer);\n doAdjust();\n }\n if(tryCount * VIEWPORT_POLLING_INTERVAL >= MAX_VIEWPORT_DELAY) {\n $interval.cancel(timer);\n throw Error(`ui-scroll directive requires a viewport with non-zero height in ${MAX_VIEWPORT_DELAY}ms`);\n }\n }, VIEWPORT_POLLING_INTERVAL);\n }\n else {\n doAdjust();\n }\n };\n\n /**\n * Build padding elements\n *\n * Calling linker is the only way I found to get access to the tag name of the template\n * to prevent the directive scope from pollution a new scope is created and destroyed\n * right after the builder creation is completed\n */\n linker((clone, scope) => {\n viewport.createPaddingElements(clone[0]);\n // we do not include the clone in the DOM. It means that the nested directives will not\n // be able to reach the parent directives, but in this case it is intentional because we\n // created the clone to access the template tag name\n scope.$destroy();\n clone.remove();\n });\n\n $scope.$on('$destroy', () => {\n unbindEvents();\n viewport.unbind('mousewheel', wheelHandler);\n });\n\n viewport.bind('mousewheel', wheelHandler);\n\n initialize();\n\n /* Private function definitions */\n\n function isInvalid(rid) {\n return (rid && rid !== ridActual) || $scope.$$destroyed;\n }\n\n function bindEvents() {\n viewport.bind('resize', resizeAndScrollHandler);\n viewport.bind('scroll', resizeAndScrollHandler);\n }\n\n function unbindEvents() {\n viewport.unbind('resize', resizeAndScrollHandler);\n viewport.unbind('scroll', resizeAndScrollHandler);\n }\n\n function reload() {\n viewport.resetTopPadding();\n viewport.resetBottomPadding();\n if (arguments.length) {\n startIndex = parseNumber(arguments[0], START_INDEX_DEFAULT, false);\n }\n buffer.reset(startIndex);\n persistDatasourceIndex(datasource, 'minIndex');\n persistDatasourceIndex(datasource, 'maxIndex');\n doAdjust();\n }\n\n function isElementVisible(wrapper) {\n return wrapper.element.height() && wrapper.element[0].offsetParent;\n }\n\n function visibilityWatcher(wrapper) {\n if (isElementVisible(wrapper)) {\n buffer.forEach((item) => {\n if (typeof item.unregisterVisibilityWatcher === 'function') {\n item.unregisterVisibilityWatcher();\n delete item.unregisterVisibilityWatcher;\n }\n });\n if (!pending.length) {\n $timeout(() => doAdjust());\n }\n }\n }\n\n function insertWrapperContent(wrapper, insertAfter) {\n createElement(wrapper, insertAfter, viewport.insertElement);\n if (!isElementVisible(wrapper)) {\n wrapper.unregisterVisibilityWatcher = wrapper.scope.$watch(() => visibilityWatcher(wrapper));\n }\n elementRoutines.hideElement(wrapper); // hide inserted elements before data binding\n }\n\n function createElement(wrapper, insertAfter, insertElement) {\n let promises = null;\n const sibling = (insertAfter > 0) ? buffer[insertAfter - 1].element : undefined;\n linker((clone, scope) => {\n promises = insertElement(clone, sibling);\n wrapper.element = clone;\n wrapper.scope = scope;\n scope[itemName] = wrapper.item;\n });\n // ui-scroll-grid apply\n if (adapter.transform) {\n const tdInitializer = wrapper.scope.uiScrollTdInitializer;\n if (tdInitializer && tdInitializer.linking) {\n adapter.transform(wrapper.scope, wrapper.element);\n } else {\n wrapper.scope.uiScrollTdInitializer = {\n onLink: () => adapter.transform(wrapper.scope, wrapper.element),\n scope: wrapper.scope\n };\n }\n }\n return promises;\n }\n\n function updateDOM() {\n let promises = [];\n const toBePrepended = [];\n const toBeRemoved = [];\n const inserted = [];\n\n buffer.forEach((wrapper, i) => {\n switch (wrapper.op) {\n case 'prepend':\n toBePrepended.unshift(wrapper);\n break;\n case 'append':\n insertWrapperContent(wrapper, i);\n wrapper.op = 'none';\n inserted.push(wrapper);\n break;\n case 'insert':\n promises = promises.concat(createElement(wrapper, i, viewport.insertElementAnimated));\n wrapper.op = 'none';\n inserted.push(wrapper);\n break;\n case 'remove':\n toBeRemoved.push(wrapper);\n }\n });\n\n toBeRemoved.forEach((wrapper) => promises = promises.concat(viewport.removeItem(wrapper)));\n\n if (toBePrepended.length)\n toBePrepended.forEach((wrapper) => {\n insertWrapperContent(wrapper);\n wrapper.op = 'none';\n });\n\n buffer.forEach((item, i) => item.scope.$index = buffer.first + i);\n\n return {\n prepended: toBePrepended,\n removed: toBeRemoved,\n inserted: inserted,\n animated: promises\n };\n\n }\n\n function updatePaddings(rid, updates) {\n // schedule another doAdjust after animation completion\n if (updates.animated.length) {\n $q.all(updates.animated).then(() => {\n viewport.adjustPaddings();\n doAdjust(rid);\n });\n } else {\n viewport.adjustPaddings();\n }\n }\n\n function enqueueFetch(rid, updates) {\n if (viewport.shouldLoadBottom()) {\n if (!updates || buffer.effectiveHeight(updates.inserted) > 0) {\n // this means that at least one item appended in the last batch has height > 0\n if (pending.push(true) === 1) {\n adapter.loading(true);\n fetch(rid);\n }\n }\n } else if (viewport.shouldLoadTop()) {\n if ((!updates || buffer.effectiveHeight(updates.prepended) > 0) || pending[0]) {\n // this means that at least one item appended in the last batch has height > 0\n // pending[0] = true means that previous fetch was appending. We need to force at least one prepend\n // BTW there will always be at least 1 element in the pending array because bottom is fetched first\n if (pending.push(false) === 1) {\n adapter.loading(true);\n fetch(rid);\n }\n }\n }\n }\n\n function processUpdates() {\n const updates = updateDOM();\n\n // We need the item bindings to be processed before we can do adjustments\n !$scope.$$phase && !$rootScope.$$phase && $scope.$digest();\n\n updates.inserted.forEach(w => elementRoutines.showElement(w));\n updates.prepended.forEach(w => elementRoutines.showElement(w));\n return updates;\n }\n\n function doAdjust(rid) {\n if (!rid) { // dismiss pending requests\n pending = [];\n rid = ++ridActual;\n }\n\n const updates = processUpdates();\n\n if (isInvalid(rid)) {\n return;\n }\n\n updatePaddings(rid, updates);\n enqueueFetch(rid);\n\n if (!pending.length) {\n adapter.calculateProperties();\n }\n }\n\n function doAdjustAfterFetch(rid) {\n const updates = processUpdates();\n\n viewport.onAfterPrepend(updates);\n\n if (isInvalid(rid)) {\n return;\n }\n\n updatePaddings(rid, updates);\n onRenderHandlersRunner();\n enqueueFetch(rid, updates);\n pending.shift();\n\n if (pending.length)\n fetch(rid);\n else {\n adapter.loading(false);\n bindEvents();\n adapter.calculateProperties();\n }\n }\n\n function fetch(rid) {\n if (pending[0]) {// scrolling down\n if (buffer.length && !viewport.shouldLoadBottom()) {\n doAdjustAfterFetch(rid);\n } else {\n fetchNext((result) => {\n if (isInvalid(rid)) {\n return;\n }\n\n if (result.length < bufferSize) {\n buffer.eof = true;\n }\n\n if (result.length > 0) {\n viewport.clipTop();\n buffer.append(result);\n }\n\n doAdjustAfterFetch(rid);\n });\n }\n } else { // scrolling up\n if (buffer.length && !viewport.shouldLoadTop()) {\n doAdjustAfterFetch(rid);\n } else {\n fetchPrevious((result) => {\n if (isInvalid(rid)) {\n return;\n }\n\n if (result.length < bufferSize) {\n buffer.bof = true;\n // log 'bof is reached'\n }\n\n if (result.length > 0) {\n if (buffer.length) {\n viewport.clipBottom();\n }\n buffer.prepend(result);\n }\n\n doAdjustAfterFetch(rid);\n });\n }\n }\n }\n\n function resizeAndScrollHandler() {\n if (!$rootScope.$$phase && !adapter.isLoading && !adapter.disabled) {\n\n enqueueFetch(ridActual);\n\n if (pending.length) {\n unbindEvents();\n } else {\n adapter.calculateProperties();\n !$scope.$$phase && $scope.$digest();\n }\n }\n }\n\n function wheelHandler(event) {\n if (!adapter.disabled) {\n const scrollTop = viewport[0].scrollTop;\n const yMax = viewport[0].scrollHeight - viewport[0].clientHeight;\n\n if ((scrollTop === 0 && !buffer.bof) || (scrollTop === yMax && !buffer.eof)) {\n event.preventDefault();\n }\n }\n }\n }\n\n }\n ]);\n"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/modules/jqLiteExtras.js","webpack:///./src/modules/elementRoutines.js","webpack:///./src/modules/buffer.js","webpack:///./src/modules/padding.js","webpack:///./src/modules/viewport.js","webpack:///./src/modules/adapter.js","webpack:///./src/ui-scroll.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","JQLiteExtras","element","convertToPx","css","getStyle","isWindow","scrollTo","self","direction","elem","_top$left$direction","_slicedToArray","top","left","method","prop","preserve","isValueDefined","document","documentElement","getWidthHeight","measure","result","measurements","base","borderA","borderB","computedMarginA","computedMarginB","computedStyle","dirA","dirB","paddingA","paddingB","height","width","padding","border","margin","_width$height$measure","offsetWidth","offsetHeight","getMeasurements","outer","outerfull","style","parseFloat","angular","this","nodeType","obj","location","alert","setInterval","window","getComputedStyle","currentStyle","rs","rsLeft","RegExp","source","test","runtimeStyle","pixelLeft","forEach","before","newElem","children","j","parent","ref","contents","prepend","length","after","Error","outerHTML","isNumber","outerHeight","option","outerWidth","offset","docElem","win","box","doc","ownerDocument","arguments","undefined","getBoundingClientRect","defaultView","parentWindow","pageYOffset","scrollTop","clientTop","pageXOffset","scrollLeft","clientLeft","hideClassToken","ElementRoutines","$injector","$q","elementRoutines_classCallCheck","$animate","has","isAngularVersionLessThen1_3","version","major","minor","index","selector","rules","sheet","styleSheets","cssRules","err","insertRule","addRule","wrapper","addClass","removeClass","newElement","previousElement","remove","scope","$destroy","insertElement","deferred","defer","enter","resolve","promise","removeElement","leave","then","ScrollBuffer","elementRoutines","bufferSize","startIndex","rowHeight","buffer","Array","extend","size","reset","eof","bof","first","next","minIndex","maxIndex","minIndexUser","maxIndexUser","resetStartIndex","append","items","item","insert","Math","max","reverse","min","operation","isTop","op","splice","push","unshift","arg1","arg2","indexOf","_op","getAbsMinIndex","incrementMinIndex","decrementMaxIndex","removeElementAnimated","getAbsMaxIndex","effectiveHeight","elements","Number","MAX_VALUE","bottom","NEGATIVE_INFINITY","offsetParent","getItems","filter","getFirstItem","list","getLastItem","CacheProto","$index","sort","a","b","argument","_isTop","Cache","instance","apply","setPrototypeOf","getOwnPropertyNames","methodName","Padding","template","useCache","padding_classCallCheck","Node","ELEMENT_NODE","tagName","toLowerCase","concat","find","generateElement","cache","Viewport","viewportController","$rootScope","topPadding","bottomPadding","viewport","container","bufferPadding","overflow-anchor","overflow-y","display","getScope","createPaddingElements","applyContainerStyle","bottomDataPos","scrollHeight","topDataPos","bottomVisiblePos","topVisiblePos","e","sibling","insertElementAnimated","shouldLoadBottom","clipBottom","overage","emptySpaceHeight","floor","itemHeight","overageHeight","add","adjustPaddings","shouldLoadTop","clipTop","visibleItemsHeight","reduce","summ","topPaddingHeight","topCount","bottomPaddingHeight","bottomCount","averageItemHeight","adjustTopPadding","adjustBottomPadding","topPaddingHeightAdd","bottomPaddingHeightAdd","onAfterMinIndexSet","topPaddingHeightOld","diff","onAfterPrepend","updates","prepended","paddingHeight","resetTopPadding","clear","resetBottomPadding","removeCacheItem","removeItem","Adapter","$scope","$parse","$attr","doAdjust","reload","adapter_classCallCheck","isLoading","disabled","viewportScope","startScope","$parent","publicContext","assignAdapter","adapter","generatePublicContext","adapterAttr","replace","adapterOnScope","assign","error","message","_this","publicMethods","publicProps","_loop","attr","set","publicPropsImmediate","_loop2","newItems","arg3","applyUpdatesFunc","noAdjust","applyUpdatesIndex","cb","options","_this2","slice","applyUpdate","_index","isArray","immutableTop","_this3","position","some","newItem","rowTop","topHeight","topDone","bottomDone","itemTop","isEOF","constant","run","elt","jQuery","fn","jquery","registerFor","addCSSRules","directive","restrict","controller","child","console","$timeout","$interval","require","transclude","priority","terminal","link","controllers","linker","match","uiScroll","parseNumber","defaultValue","isFloat","isNaN","parseNumericAttr","datasource","itemName","datasourceName","allowVisibilityWatch","ridActual","pending","unbindEvents","scPreviousScrollTop","persistDatasourceIndex","isDatasourceValid","toString","onRenderHandlers","propName","handler","id","defineDatasourceIndex","propUserName","descriptor","getOwnPropertyDescriptor","scTimer","fetchNext","success","count","fetchPrevious","isInvalid","rid","$$destroyed","unbind","resizeAndScrollHandler","isElementVisible","insertWrapperContent","insertAfter","createElement","unregisterVisibilityWatcher","$watch","hideElement","promises","clone","transform","tdInitializer","uiScrollTdInitializer","linking","onLink","updatePaddings","animated","all","enqueueFetch","isPendingScroll","calculateAbsoluteScroll","inserted","loading","fetch","processUpdates","toBePrepended","toBeRemoved","removed","updateDOM","changes","$$phase","$digest","w","showElement","calculateProperties","doAdjustAfterFetch","shift","_resizeAndScrollHandler","sc","clearTimeout","setTimeout","newFirst","wheelHandler","event","yMax","clientHeight","preventDefault","$on","tryCount","timer","cancel","initialize"],"mappings":"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","file":"ui-scroll.min.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n","/*!\n globals: angular, window\n List of used element methods available in JQuery but not in JQuery Lite\n element.before(elem)\n element.height()\n element.outerHeight(true)\n element.height(value) = only for Top/Bottom padding elements\n element.scrollTop()\n element.scrollTop(value)\n */\n\nexport default class JQLiteExtras {\n\n registerFor(element) {\n let convertToPx, css, getStyle, isWindow;\n // angular implementation blows up if elem is the window\n css = angular.element.prototype.css;\n\n element.prototype.css = function (name, value) {\n let self = this;\n let elem = self[0];\n if (!(!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style)) {\n return css.call(self, name, value);\n }\n };\n\n // as defined in angularjs v1.0.5\n isWindow = (obj) => obj && obj.document && obj.location && obj.alert && obj.setInterval;\n\n function scrollTo(self, direction, value) {\n let elem = self[0];\n let [method, prop, preserve] = {\n top: [\n 'scrollTop',\n 'pageYOffset',\n 'scrollLeft'\n ],\n left: [\n 'scrollLeft',\n 'pageXOffset',\n 'scrollTop'\n ]\n }[direction];\n\n const isValueDefined = typeof value !== 'undefined';\n if (isWindow(elem)) {\n if (isValueDefined) {\n return elem.scrollTo(self[preserve].call(self), value);\n }\n return (prop in elem) ? elem[prop] : elem.document.documentElement[method];\n } else {\n if (isValueDefined) {\n elem[method] = value;\n }\n return elem[method];\n }\n }\n\n if (window.getComputedStyle) {\n getStyle = (elem) => window.getComputedStyle(elem, null);\n convertToPx = (elem, value) => parseFloat(value);\n } else {\n getStyle = (elem) => elem.currentStyle;\n convertToPx = (elem, value) => {\n let left, result, rs, rsLeft, style;\n let core_pnum = /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source;\n let rnumnonpx = new RegExp('^(' + core_pnum + ')(?!px)[a-z%]+$', 'i');\n\n if (!rnumnonpx.test(value)) {\n return parseFloat(value);\n }\n\n // ported from JQuery\n style = elem.style;\n left = style.left;\n rs = elem.runtimeStyle;\n rsLeft = rs && rs.left;\n if (rs) {\n rs.left = style.left;\n }\n // put in the new values to get a computed style out\n style.left = value;\n result = style.pixelLeft;\n style.left = left;\n if (rsLeft) {\n rs.left = rsLeft;\n }\n return result;\n };\n }\n\n function getMeasurements(elem, measure) {\n let base, borderA, borderB, computedMarginA, computedMarginB, computedStyle, dirA, dirB, marginA, marginB, paddingA, paddingB;\n\n if (isWindow(elem)) {\n base = document.documentElement[{height: 'clientHeight', width: 'clientWidth'}[measure]];\n\n return {\n base: base,\n padding: 0,\n border: 0,\n margin: 0\n };\n }\n\n // Start with offset property\n [\n base,\n dirA,\n dirB\n ] = {\n width: [\n elem.offsetWidth,\n 'Left',\n 'Right'\n ],\n height: [\n elem.offsetHeight,\n 'Top',\n 'Bottom'\n ]\n }[measure];\n\n computedStyle = getStyle(elem);\n paddingA = convertToPx(elem, computedStyle['padding' + dirA]) || 0;\n paddingB = convertToPx(elem, computedStyle['padding' + dirB]) || 0;\n borderA = convertToPx(elem, computedStyle['border' + dirA + 'Width']) || 0;\n borderB = convertToPx(elem, computedStyle['border' + dirB + 'Width']) || 0;\n computedMarginA = computedStyle['margin' + dirA];\n computedMarginB = computedStyle['margin' + dirB];\n\n // I do not care for width for now, so this hack is irrelevant\n // if ( !supportsPercentMargin )\n // computedMarginA = hackPercentMargin( elem, computedStyle, computedMarginA )\n // computedMarginB = hackPercentMargin( elem, computedStyle, computedMarginB )\n marginA = convertToPx(elem, computedMarginA) || 0;\n marginB = convertToPx(elem, computedMarginB) || 0;\n\n return {\n base: base,\n padding: paddingA + paddingB,\n border: borderA + borderB,\n margin: marginA + marginB\n };\n }\n\n function getWidthHeight(elem, direction, measure) {\n let computedStyle, result;\n\n let measurements = getMeasurements(elem, direction);\n\n if (measurements.base > 0) {\n return {\n base: measurements.base - measurements.padding - measurements.border,\n outer: measurements.base,\n outerfull: measurements.base + measurements.margin\n }[measure];\n }\n\n // Fall back to computed then uncomputed css if necessary\n computedStyle = getStyle(elem);\n result = computedStyle[direction];\n\n if (result < 0 || result === null) {\n result = elem.style[direction] || 0;\n }\n\n // Normalize \"\", auto, and prepare for extra\n result = parseFloat(result) || 0;\n\n return {\n base: result - measurements.padding - measurements.border,\n outer: result,\n outerfull: result + measurements.padding + measurements.border + measurements.margin\n }[measure];\n }\n\n // define missing methods\n return angular.forEach({\n before(newElem) {\n var children, elem, i, j, parent, ref, self;\n self = this;\n elem = self[0];\n parent = self.parent();\n children = parent.contents();\n if (children[0] === elem) {\n return parent.prepend(newElem);\n } else {\n for (i = j = 1, ref = children.length - 1; 1 <= ref ? j <= ref : j >= ref; i = 1 <= ref ? ++j : --j) {\n if (children[i] === elem) {\n angular.element(children[i - 1]).after(newElem);\n return;\n }\n }\n throw new Error('invalid DOM structure ' + elem.outerHTML);\n }\n },\n height (value){\n var self;\n self = this;\n if (typeof value !== 'undefined') {\n if (angular.isNumber(value)) {\n value = value + 'px';\n }\n return css.call(self, 'height', value);\n } else {\n return getWidthHeight(this[0], 'height', 'base');\n }\n },\n outerHeight(option) {\n return getWidthHeight(this[0], 'height', option ? 'outerfull' : 'outer');\n },\n outerWidth(option) {\n return getWidthHeight(this[0], 'width', option ? 'outerfull' : 'outer');\n },\n\n /*\n The offset setter method is not implemented\n */\n offset(value) {\n let docElem, win;\n let self = this;\n let box = {\n top: 0,\n left: 0\n };\n let elem = self[0];\n let doc = elem && elem.ownerDocument;\n\n if (arguments.length) {\n if (value === undefined) {\n return self;\n }\n // TODO: implement setter\n throw new Error('offset setter method is not implemented');\n }\n\n if (!doc) {\n return;\n }\n\n docElem = doc.documentElement;\n\n // TODO: Make sure it's not a disconnected DOM node\n\n if (elem.getBoundingClientRect != null) {\n box = elem.getBoundingClientRect();\n }\n\n win = doc.defaultView || doc.parentWindow;\n\n return {\n top: box.top + (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0),\n left: box.left + (win.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)\n };\n },\n scrollTop(value) {\n return scrollTo(this, 'top', value);\n },\n scrollLeft(value) {\n return scrollTo(this, 'left', value);\n }\n }, (value, key) => {\n if (!element.prototype[key]) {\n return element.prototype[key] = value;\n }\n });\n }\n\n}\n","const hideClassToken = 'ng-ui-scroll-hide';\n\nexport default class ElementRoutines {\n\n static addCSSRules() {\n const selector = '.' + hideClassToken;\n const rules = 'display: none';\n const sheet = document.styleSheets[0];\n let index;\n try {\n index = sheet.cssRules.length;\n } catch (err) {\n index = 0;\n }\n if('insertRule' in sheet) {\n sheet.insertRule(selector + '{' + rules + '}', index);\n }\n else if('addRule' in sheet) {\n sheet.addRule(selector, rules, index);\n }\n }\n\n constructor($injector, $q) {\n this.$animate = ($injector.has && $injector.has('$animate')) ? $injector.get('$animate') : null;\n this.isAngularVersionLessThen1_3 = angular.version.major === 1 && angular.version.minor < 3;\n this.$q = $q;\n }\n\n hideElement(wrapper) {\n wrapper.element.addClass(hideClassToken);\n }\n\n showElement(wrapper) {\n wrapper.element.removeClass(hideClassToken);\n }\n\n insertElement(newElement, previousElement) {\n previousElement.after(newElement);\n return [];\n }\n\n removeElement(wrapper) {\n wrapper.element.remove();\n wrapper.scope.$destroy();\n return [];\n }\n\n insertElementAnimated(newElement, previousElement) {\n if (!this.$animate) {\n return this.insertElement(newElement, previousElement);\n }\n\n if (this.isAngularVersionLessThen1_3) {\n const deferred = this.$q.defer();\n // no need for parent - previous element is never null\n this.$animate.enter(newElement, null, previousElement, () => deferred.resolve());\n\n return [deferred.promise];\n }\n\n // no need for parent - previous element is never null\n return [this.$animate.enter(newElement, null, previousElement)];\n }\n\n removeElementAnimated(wrapper) {\n if (!this.$animate) {\n return this.removeElement(wrapper);\n }\n\n if (this.isAngularVersionLessThen1_3) {\n const deferred = this.$q.defer();\n this.$animate.leave(wrapper.element, () => {\n wrapper.scope.$destroy();\n return deferred.resolve();\n });\n\n return [deferred.promise];\n }\n\n return [(this.$animate.leave(wrapper.element)).then(() => wrapper.scope.$destroy())];\n }\n}","export default function ScrollBuffer(elementRoutines, bufferSize, startIndex, rowHeight) {\n const buffer = Object.create(Array.prototype);\n\n angular.extend(buffer, {\n size: bufferSize,\n\n reset(startIndex) {\n buffer.remove(0, buffer.length);\n buffer.eof = false;\n buffer.bof = false;\n buffer.first = startIndex;\n buffer.next = startIndex;\n buffer.minIndex = startIndex; // Calculated when data is effectively accessed\n buffer.maxIndex = startIndex;\n buffer.minIndexUser = null; // as set by the user (datasource)\n buffer.maxIndexUser = null;\n },\n \n // PHIL: set the new index to be displayed without resettng the sroll and the calculated min/max\n // Note that this actually make sense with a fixed rowHeight when the scroll value can be calculated\n // for a # of rows\n resetStartIndex: function resetStartIndex(startIndex) {\n buffer.remove(0, buffer.length);\n buffer.eof = buffer.eof && startIndex==buffer.maxIndex;\n buffer.bof = buffer.bof && startIndex==buffer.minIndex;\n buffer.first = startIndex;\n buffer.next = startIndex;\n },\n\n append(items) {\n items.forEach((item) => {\n ++buffer.next;\n buffer.insert('append', item);\n });\n buffer.maxIndex = buffer.eof ? buffer.next - 1 : Math.max(buffer.next - 1, buffer.maxIndex);\n },\n\n prepend(items) {\n items.reverse().forEach((item) => {\n --buffer.first;\n buffer.insert('prepend', item);\n });\n buffer.minIndex = buffer.bof ? buffer.minIndex = buffer.first : Math.min(buffer.first, buffer.minIndex);\n },\n\n /**\n * inserts wrapped element in the buffer\n * the first argument is either operation keyword (see below) or a number for operation 'insert'\n * for insert the number is the index for the buffer element the new one have to be inserted after\n * operations: 'append', 'prepend', 'insert', 'remove', 'update', 'none'\n */\n insert(operation, item, isTop) {\n const wrapper = {\n item: item\n };\n\n if (operation % 1 === 0) {// it is an insert\n wrapper.op = 'insert';\n buffer.splice(operation, 0, wrapper);\n if(isTop) {\n buffer.first--;\n }\n else {\n buffer.next++;\n }\n } else {\n wrapper.op = operation;\n switch (operation) {\n case 'append':\n buffer.push(wrapper);\n break;\n case 'prepend':\n buffer.unshift(wrapper);\n break;\n }\n }\n },\n\n // removes elements from buffer\n remove(arg1, arg2) {\n if (angular.isNumber(arg1)) {\n // removes items from arg1 (including) through arg2 (excluding)\n for (let i = arg1; i < arg2; i++) {\n elementRoutines.removeElement(buffer[i]);\n }\n return buffer.splice(arg1, arg2 - arg1);\n }\n // removes single item(wrapper) from the buffer\n buffer.splice(buffer.indexOf(arg1), 1);\n if(arg1._op === 'isTop' && buffer.first === this.getAbsMinIndex()) {\n this.incrementMinIndex();\n }\n else {\n this.decrementMaxIndex();\n }\n if(arg1._op === 'isTop') {\n buffer.first++;\n }\n else {\n buffer.next--;\n }\n if(!buffer.length) {\n buffer.first = buffer.minIndex%1 ? buffer.minIndex : startIndex;\n buffer.next = buffer.first;\n buffer.eof = buffer.eof && buffer.first==buffer.maxIndex;\n }\n\n return elementRoutines.removeElementAnimated(arg1);\n },\n\n incrementMinIndex() {\n if(buffer.minIndexUser !== null) {\n if(buffer.minIndex > buffer.minIndexUser) {\n buffer.minIndexUser++;\n return;\n }\n if(buffer.minIndex === buffer.minIndexUser) {\n buffer.minIndexUser++;\n }\n }\n buffer.minIndex++;\n },\n\n decrementMaxIndex() {\n if(buffer.maxIndexUser !== null && buffer.maxIndex <= buffer.maxIndexUser) {\n buffer.maxIndexUser--;\n }\n buffer.maxIndex--;\n },\n\n getAbsMinIndex() {\n if(buffer.minIndexUser !== null) {\n return Math.min(buffer.minIndexUser, buffer.minIndex);\n }\n return buffer.minIndex;\n },\n\n getAbsMaxIndex() {\n if(buffer.maxIndexUser !== null) {\n return Math.max(buffer.maxIndexUser, buffer.maxIndex);\n }\n return buffer.maxIndex;\n },\n\n effectiveHeight(elements) {\n if (!elements.length) {\n return 0;\n }\n let top = Number.MAX_VALUE;\n let bottom = Number.NEGATIVE_INFINITY;\n elements.forEach((wrapper) => {\n if (wrapper.element[0].offsetParent) {\n // element style is not display:none\n top = Math.min(top, wrapper.element.offset().top);\n bottom = Math.max(bottom, wrapper.element.offset().top + (rowHeight || wrapper.element.outerHeight(true)));\n }\n });\n return Math.max(0, bottom - top);\n },\n\n getItems() {\n return buffer.filter(item => item.op === 'none');\n },\n\n getFirstItem() {\n const list = buffer.getItems();\n if (!list.length) {\n return null;\n }\n return list[0].item;\n },\n\n getLastItem() {\n const list = buffer.getItems();\n if (!list.length) {\n return null;\n }\n return list[list.length - 1].item;\n }\n\n });\n\n buffer.reset(startIndex);\n\n return buffer;\n}\n","// Can't just extend the Array, due to Babel does not support built-in classes extending\n// This solution was taken from https://stackoverflow.com/questions/46897414/es6-class-extends-array-workaround-for-es5-babel-transpile\nclass CacheProto {\n add(item) {\n for (let i = this.length - 1; i >= 0; i--) {\n if (this[i].index === item.scope.$index) {\n this[i].height = item.element.outerHeight();\n return;\n }\n }\n this.push({\n index: item.scope.$index,\n height: item.element.outerHeight()\n });\n this.sort((a, b) => ((a.index < b.index) ? -1 : ((a.index > b.index) ? 1 : 0)));\n }\n\n remove(argument, _isTop) {\n const index = argument % 1 === 0 ? argument : argument.scope.$index;\n const isTop = argument % 1 === 0 ? _isTop : argument._op === 'isTop';\n for (let i = this.length - 1; i >= 0; i--) {\n if (this[i].index === index) {\n this.splice(i, 1);\n break;\n }\n }\n if(!isTop) {\n for (let i = this.length - 1; i >= 0; i--) {\n if (this[i].index > index) {\n this[i].index--;\n }\n }\n }\n }\n\n clear() {\n this.length = 0;\n }\n}\n\nfunction Cache() {\n const instance = [];\n instance.push.apply(instance, arguments);\n Object.setPrototypeOf(instance, Cache.prototype);\n return instance;\n}\nCache.prototype = Object.create(Array.prototype);\nObject.getOwnPropertyNames(CacheProto.prototype).forEach(methodName =>\n Cache.prototype[methodName] = CacheProto.prototype[methodName]\n);\n\nfunction generateElement(template) {\n if(template.nodeType !== Node.ELEMENT_NODE) {\n throw new Error('ui-scroll directive requires an Element node for templating the view');\n }\n let element;\n switch (template.tagName.toLowerCase()) {\n case 'dl':\n throw new Error(`ui-scroll directive does not support <${template.tagName}> as a repeating tag: ${template.outerHTML}`);\n case 'tr':\n let table = angular.element('
    ');\n element = table.find('tr');\n break;\n case 'li':\n element = angular.element('
  • ');\n break;\n default:\n element = angular.element('
    ');\n }\n return element;\n}\n\n//\n// Padding represents the dummy element added to both the top and the bottom of the scrolling container\n// It holds the element, as well as a cache for the items (rows) height. In case of a fixed rowHeight, the \n// cache is not used and thus is not created.\n//\nclass Padding {\n constructor(template,useCache) {\n this.element = generateElement(template);\n if(useCache) {\n this.cache = new Cache();\n }\n }\n\n height() {\n // When called with a parameter, this sets the height of the padding\n return this.element.height.apply(this.element, arguments);\n }\n}\n\nexport default Padding;","import Padding from './padding';\n\nexport default function Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding, rowHeight) {\n let topPadding = null;\n let bottomPadding = null;\n const viewport = viewportController && viewportController.viewport ? viewportController.viewport : angular.element(window);\n const container = viewportController && viewportController.container ? viewportController.container : undefined;\n const scope = viewportController && viewportController.scope ? viewportController.scope : $rootScope;\n\n viewport.css({\n 'overflow-anchor': 'none',\n 'overflow-y': 'auto',\n 'display': 'block'\n });\n\n function bufferPadding() {\n return viewport.outerHeight() * padding; // some extra space to initiate preload\n }\n\n // \n // Viewport measurements\n //\n // +----------------+ 0\n // | top |\n // | padding |\n // +----------------+ topDataPos() [=topPadding.height]\n // | not visible |\n // | items |\n // +----------------+ topVisiblePos() [=viewport.scrollTop]\n // | |\n // | visible |\n // | items |\n // | |\n // +----------------+ bottomVisiblePos() [=viewport.scrollTop+viewport.height]\n // | not visible |\n // | items |\n // +----------------+ bottomDataPos() [=scrollHeight-bottomPadding.height]\n // | bottom |\n // | padding |\n // +----------------+ scrollHeight \n //\n // bufferPadding is some extra space we have top & bottom to allow infinite scrolling\n // bufferPadding = viewport.outerHeight() * padding\n //\n // bottomVisiblePos() - topVisiblePos() == viewport.outerHeight()\n \n\n angular.extend(viewport, {\n getScope() {\n return scope;\n },\n\n createPaddingElements(template) {\n topPadding = new Padding(template,!rowHeight);\n bottomPadding = new Padding(template,!rowHeight);\n element.before(topPadding.element);\n element.after(bottomPadding.element);\n topPadding.height(0);\n bottomPadding.height(0);\n },\n\n applyContainerStyle() {\n if (!container) {\n return true;\n }\n if(container !== viewport) {\n viewport.css('height', window.getComputedStyle(container[0]).height);\n }\n return viewport.height() > 0;\n },\n\n bottomDataPos() {\n let scrollHeight = viewport[0].scrollHeight;\n scrollHeight = scrollHeight != null ? scrollHeight : viewport[0].document.documentElement.scrollHeight;\n return scrollHeight - bottomPadding.height();\n },\n\n topDataPos() {\n return topPadding.height();\n },\n\n bottomVisiblePos() {\n return viewport.scrollTop() + viewport.outerHeight();\n },\n\n topVisiblePos() {\n return viewport.scrollTop();\n },\n\n insertElement(e, sibling) {\n return elementRoutines.insertElement(e, sibling || topPadding.element);\n },\n\n insertElementAnimated(e, sibling) {\n return elementRoutines.insertElementAnimated(e, sibling || topPadding.element);\n },\n\n shouldLoadBottom() {\n return !buffer.eof && viewport.bottomDataPos() < viewport.bottomVisiblePos() + bufferPadding();\n },\n\n clipBottom() {\n // clip the invisible items off the bottom\n let overage = 0;\n let emptySpaceHeight = viewport.bottomDataPos() - viewport.bottomVisiblePos() - bufferPadding();\n if(rowHeight) {\n overage = Math.min(buffer.length,Math.floor(emptySpaceHeight/rowHeight));\n } else {\n let itemHeight = 0;\n let overageHeight = 0;\n\n for (let i = buffer.length - 1; i >= 0; i--) {\n itemHeight = buffer[i].element.outerHeight(true);\n if (overageHeight + itemHeight > emptySpaceHeight) {\n break;\n }\n bottomPadding.cache.add(buffer[i]);\n overageHeight += itemHeight;\n overage++;\n }\n }\n\n if (overage > 0) {\n buffer.eof = false;\n buffer.remove(buffer.length - overage, buffer.length);\n buffer.next -= overage;\n viewport.adjustPaddings();\n }\n },\n\n shouldLoadTop() {\n return !buffer.bof && (viewport.topDataPos() > viewport.topVisiblePos() - bufferPadding());\n },\n\n clipTop() {\n // clip the invisible items off the top\n let overage = 0;\n let overageHeight = 0;\n let emptySpaceHeight = viewport.topVisiblePos() - viewport.topDataPos() - bufferPadding();\n if(rowHeight) {\n overage = Math.min(buffer.length,Math.floor(emptySpaceHeight/rowHeight));\n overageHeight = overage * rowHeight;\n } else {\n let itemHeight = 0;\n\n for (let i = 0; i < buffer.length; i++) {\n itemHeight = buffer[i].element.outerHeight(true);\n if (overageHeight + itemHeight > emptySpaceHeight) {\n break;\n }\n topPadding.cache.add(buffer[i]);\n overageHeight += itemHeight;\n overage++;\n }\n }\n\n if (overage > 0) {\n // we need to adjust top padding element before items are removed from top\n // to avoid strange behaviour of scroll bar during remove top items when we are at the very bottom\n topPadding.height(topPadding.height() + overageHeight);\n buffer.bof = false;\n buffer.remove(0, overage);\n buffer.first += overage;\n }\n },\n\n // PHIL: remove all the entries in the buffer without changing the scrollbar, nor the scroll position\n // and update the padding accordingly\n // It is designed to work with non fixed rowHeight, although it will need more tests in this area...\n scrollTo(first) {\n if(rowHeight) {\n const min = buffer.getAbsMinIndex(); \n const max = buffer.getAbsMaxIndex();\n first = Math.min(Math.max(first, min),max);\n // Adjust the paddings before removing the elements to avoid touching the scroll top position\n topPadding.height((first-min)*rowHeight);\n bottomPadding.height(((max+1)-first)*rowHeight);\n buffer.resetStartIndex(first);\n } else {\n buffer.resetStartIndex(first);\n viewport.adjustPaddings();\n } \n },\n \n adjustPaddings() {\n if(rowHeight) {\n const min = buffer.getAbsMinIndex(); \n const max = buffer.getAbsMaxIndex();\n topPadding.height((buffer.first-min)*rowHeight);\n // PHIL: next points to the next possible item, while max is the index of the last one.\n // In order to make them compatible, we should add one to max\n // Also, it looks like buffer is not changing maxIndex when an element is inserted/appended\n // Not sure if this can have a consequence or not....\n bottomPadding.height(((max+1)-buffer.next)*rowHeight);\n return;\n }\n\n if (!buffer.length) {\n return;\n }\n\n // precise heights calculation based on items that are in buffer or that were in buffer once\n const visibleItemsHeight = buffer.reduce((summ, item) => summ + item.element.outerHeight(true), 0);\n let topPaddingHeight = 0, topCount = 0;\n topPadding.cache.forEach(item => {\n if(item.index < buffer.first) {\n topPaddingHeight += item.height;\n topCount++;\n }\n });\n \n let bottomPaddingHeight = 0, bottomCount = 0;\n bottomPadding.cache.forEach(item => {\n if(item.index >= buffer.next) {\n bottomPaddingHeight += item.height;\n bottomCount++;\n }\n });\n \n const totalHeight = visibleItemsHeight + topPaddingHeight + bottomPaddingHeight;\n const averageItemHeight = totalHeight / (topCount + bottomCount + buffer.length); \n\n // average heights calculation, items that have never been reached\n let adjustTopPadding = buffer.minIndexUser !== null && buffer.minIndex > buffer.minIndexUser;\n let adjustBottomPadding = buffer.maxIndexUser !== null && buffer.maxIndex < buffer.maxIndexUser;\n let topPaddingHeightAdd = adjustTopPadding ? (buffer.minIndex - buffer.minIndexUser) * averageItemHeight : 0;\n let bottomPaddingHeightAdd = adjustBottomPadding ? (buffer.maxIndexUser - buffer.maxIndex) * averageItemHeight : 0;\n\n // paddings combine adjustment\n topPadding.height(topPaddingHeight + topPaddingHeightAdd);\n bottomPadding.height(bottomPaddingHeight + bottomPaddingHeightAdd);\n },\n\n onAfterMinIndexSet(topPaddingHeightOld) {\n // additional scrollTop adjustment in case of datasource.minIndex external set\n if (buffer.minIndexUser !== null && buffer.minIndex > buffer.minIndexUser) {\n let diff = topPadding.height() - topPaddingHeightOld;\n viewport.scrollTop(viewport.scrollTop() + diff);\n while((diff -= viewport.scrollTop()) > 0) {\n bottomPadding.height(bottomPadding.height() + diff);\n viewport.scrollTop(viewport.scrollTop() + diff);\n }\n }\n },\n\n onAfterPrepend(updates) {\n if (!updates.prepended.length)\n return;\n const height = buffer.effectiveHeight(updates.prepended);\n const paddingHeight = topPadding.height() - height;\n if (paddingHeight >= 0) {\n topPadding.height(paddingHeight);\n }\n else {\n topPadding.height(0);\n viewport.scrollTop(viewport.scrollTop() - paddingHeight);\n }\n },\n\n resetTopPadding() {\n topPadding.height(0);\n if(topPadding.cache) {\n topPadding.cache.clear();\n }\n },\n\n resetBottomPadding() {\n bottomPadding.height(0);\n if(bottomPadding.cache) {\n bottomPadding.cache.clear();\n }\n },\n\n removeCacheItem(item, isTop) {\n if(topPadding.cache) {\n topPadding.cache.remove(item, isTop);\n }\n if(bottomPadding.cache) {\n bottomPadding.cache.remove(item, isTop);\n }\n },\n\n removeItem(item) {\n this.removeCacheItem(item);\n return buffer.remove(item);\n }\n });\n\n return viewport;\n}\n","class Adapter {\n\n constructor($scope, $parse, $attr, viewport, buffer, doAdjust, reload) {\n this.$parse = $parse;\n this.$attr = $attr;\n this.viewport = viewport;\n this.buffer = buffer;\n\n this.doAdjust = doAdjust;\n this.reload = reload;\n\n this.isLoading = false;\n this.disabled = false;\n\n const viewportScope = viewport.getScope();\n this.startScope = viewportScope.$parent ? viewportScope : $scope;\n\n this.publicContext = {};\n this.assignAdapter($attr.adapter);\n this.generatePublicContext();\n }\n\n assignAdapter(adapterAttr) {\n if (!adapterAttr || !(adapterAttr = adapterAttr.replace(/^\\s+|\\s+$/gm, ''))) {\n return;\n }\n let adapterOnScope;\n\n try {\n this.$parse(adapterAttr).assign(this.startScope, {});\n adapterOnScope = this.$parse(adapterAttr)(this.startScope);\n }\n catch (error) {\n error.message = `Angular ui-scroll Adapter assignment exception.\\n` +\n `Can't parse \"${adapterAttr}\" expression.\\n` +\n error.message;\n throw error;\n }\n\n angular.extend(adapterOnScope, this.publicContext);\n this.publicContext = adapterOnScope;\n }\n\n generatePublicContext() {\n // these methods will be accessible out of ui-scroll via user defined adapter\n const publicMethods = ['reload', 'applyUpdates', 'append', 'prepend', 'isBOF', 'isEOF', 'isEmpty'];\n for (let i = publicMethods.length - 1; i >= 0; i--) {\n this.publicContext[publicMethods[i]] = this[publicMethods[i]].bind(this);\n }\n\n // these read-only props will be accessible out of ui-scroll via user defined adapter\n const publicProps = ['isLoading', 'topVisible', 'topVisibleElement', 'topVisibleScope', 'bottomVisible', 'bottomVisibleElement', 'bottomVisibleScope'];\n for (let i = publicProps.length - 1; i >= 0; i--) {\n let property, attr = this.$attr[publicProps[i]];\n Object.defineProperty(this, publicProps[i], {\n get: () => property,\n set: (value) => {\n property = value;\n this.publicContext[publicProps[i]] = value;\n if (attr) {\n this.$parse(attr).assign(this.startScope, value);\n }\n }\n });\n }\n\n // read-only immediately calculated public properties\n const publicPropsImmediate = ['bufferFirst', 'bufferLast', 'bufferLength'];\n for (let i = publicPropsImmediate.length - 1; i >= 0; i--) {\n Object.defineProperty(this.publicContext, publicPropsImmediate[i], {\n get: () => this[publicPropsImmediate[i]]\n });\n }\n\n // non-read-only public property\n Object.defineProperty(this.publicContext, 'disabled', {\n get: () => this.disabled,\n set: (value) => (!(this.disabled = value)) ? this.doAdjust() : null\n });\n }\n\n loading(value) {\n this.isLoading = value;\n }\n\n isBOF() {\n return this.buffer.bof;\n }\n\n isEOF() {\n return this.buffer.eof;\n }\n\n isEmpty() {\n return !this.buffer.length;\n }\n\n get bufferLength() {\n return this.buffer.getItems().length;\n }\n\n get bufferFirst() {\n return this.buffer.getFirstItem();\n }\n\n get bufferLast() {\n return this.buffer.getLastItem();\n }\n\n append(newItems) {\n this.buffer.append(newItems);\n this.doAdjust();\n this.viewport.clipTop();\n this.viewport.clipBottom();\n }\n\n prepend(newItems) {\n this.buffer.prepend(newItems);\n this.doAdjust();\n this.viewport.clipTop();\n this.viewport.clipBottom();\n }\n\n applyUpdates(arg1, arg2, arg3) {\n if (typeof arg1 === 'function') {\n this.applyUpdatesFunc(arg1, arg2);\n if(arg2 && arg2.noAdjust) return;\n } else {\n this.applyUpdatesIndex(arg1, arg2, arg3);\n if(arg3 && arg3.noAdjust) return;\n }\n this.doAdjust();\n }\n\n applyUpdatesFunc(cb, options) {\n this.buffer.slice(0).forEach((wrapper) => {\n // we need to do it on the buffer clone, because buffer content\n // may change as we iterate through\n this.applyUpdate(wrapper, cb(wrapper.item, wrapper.scope, wrapper.element), options);\n });\n }\n\n applyUpdatesIndex(index, newItems, options = {}) {\n if (index % 1 !== 0) {\n throw new Error('applyUpdates - ' + index + ' is not a valid index (should be an integer)');\n }\n const _index = index - this.buffer.first;\n\n // apply updates only within buffer\n if (_index >= 0 && _index < this.buffer.length) {\n this.applyUpdate(this.buffer[_index], newItems, options);\n }\n // out-of-buffer case: deletion may affect Paddings\n else if(index >= this.buffer.getAbsMinIndex() && index <= this.buffer.getAbsMaxIndex()) {\n if(angular.isArray(newItems) && !newItems.length) {\n this.viewport.removeCacheItem(index, !options.immutableTop && index === this.buffer.minIndex);\n if (!options.immutableTop && index === this.buffer.getAbsMinIndex()) {\n this.buffer.incrementMinIndex();\n }\n else {\n this.buffer.decrementMaxIndex();\n }\n }\n }\n }\n\n applyUpdate(wrapper, newItems, options = {}) {\n if (!angular.isArray(newItems)) {\n return;\n }\n let position = this.buffer.indexOf(wrapper);\n if (!newItems.reverse().some(newItem => newItem === wrapper.item)) {\n wrapper.op = 'remove';\n if (!options.immutableTop && position === 0 && !newItems.length) {\n wrapper._op = 'isTop'; // to catch \"first\" edge case on remove\n }\n }\n newItems.forEach((newItem) => {\n if (newItem === wrapper.item) {\n position--;\n } else {\n // 3 parameter (isTop) is to catch \"first\" edge case on insert\n this.buffer.insert(position + 1, newItem, !options.immutableTop && position === -1);\n }\n });\n }\n\n calculateProperties() {\n let rowTop = null, topHeight = 0;\n let topDone = false, bottomDone = false;\n const length = this.buffer.length;\n\n for (let i = 0; i < length; i++) {\n const item = this.buffer[i];\n const itemTop = item.element.offset().top;\n\n if (rowTop !== itemTop) { // a new row condition\n const itemHeight = item.element.outerHeight(true);\n const top = this.viewport.topDataPos() + topHeight + itemHeight;\n\n if (!topDone && top > this.viewport.topVisiblePos()) {\n topDone = true;\n this['topVisible'] = item.item;\n this['topVisibleElement'] = item.element;\n this['topVisibleScope'] = item.scope;\n }\n if (!bottomDone && (top >= this.viewport.bottomVisiblePos() || (i === length - 1 && this.isEOF()))) {\n bottomDone = true;\n this['bottomVisible'] = item.item;\n this['bottomVisibleElement'] = item.element;\n this['bottomVisibleScope'] = item.scope;\n }\n topHeight += itemHeight;\n }\n rowTop = itemTop;\n\n if (topDone && bottomDone) {\n break;\n }\n }\n }\n\n}\n\nexport default Adapter;\n","import JQLiteExtras from './modules/jqLiteExtras';\nimport ElementRoutines from './modules/elementRoutines.js';\nimport ScrollBuffer from './modules/buffer.js';\nimport Viewport from './modules/viewport.js';\nimport Adapter from './modules/adapter.js';\n\nangular.module('ui.scroll', [])\n\n .constant('JQLiteExtras', JQLiteExtras)\n .run(['JQLiteExtras', (JQLiteExtras) => {\n const elt = angular.element;\n !(window.jQuery && elt.fn && elt.fn.jquery) ? (new JQLiteExtras()).registerFor(elt) : null;\n ElementRoutines.addCSSRules();\n }])\n\n .directive('uiScrollViewport', function () {\n return {\n restrict: 'A',\n controller: [\n '$scope',\n '$element',\n function (scope, element) {\n this.container = element;\n this.viewport = element;\n this.scope = scope;\n\n angular.forEach(element.children(), child => {\n if (child.tagName.toLowerCase() === 'tbody') {\n this.viewport = angular.element(child);\n }\n });\n\n return this;\n }\n ]\n };\n })\n\n .directive('uiScroll', [\n '$log',\n '$injector',\n '$rootScope',\n '$timeout',\n '$interval',\n '$q',\n '$parse',\n function (console, $injector, $rootScope, $timeout, $interval, $q, $parse) {\n\n return {\n require: ['?^uiScrollViewport'],\n restrict: 'A',\n transclude: 'element',\n priority: 1000,\n terminal: true,\n link: link\n };\n\n function link($scope, element, $attr, controllers, linker) {\n const match = $attr.uiScroll.match(/^\\s*(\\w+)\\s+in\\s+([(\\w|\\$)\\.]+)\\s*$/);\n if (!match) {\n throw new Error('Expected uiScroll in form of \\'_item_ in _datasource_\\' but got \\'' + $attr.uiScroll + '\\'');\n }\n\n function parseNumber(value, defaultValue, isFloat) {\n if (!isFloat) {\n value = value === null ? defaultValue : Math.floor(value);\n }\n return isNaN(value) ? defaultValue : value;\n }\n\n function parseNumericAttr(value, defaultValue, isFloat) {\n const result = $parse(value)($scope);\n return parseNumber(result, defaultValue, isFloat);\n }\n\n const BUFFER_MIN = 3; // Minimum size of the data source request\n const BUFFER_DEFAULT = 10; // Default datasource request size\n const PADDING_MIN = 0.3; // Mininum # of rows in the padding area\n const PADDING_DEFAULT = 0.5; // Default # of rows in the padding area\n const START_INDEX_DEFAULT = 1; // Default start index when requestng the first data block\n const MAX_VIEWPORT_DELAY = 500; // Max time wait (ms) to get the viewport with an height>0\n const VIEWPORT_POLLING_INTERVAL = 50; // Interval used to check the initial viewport height\n\n let datasource = null;\n const itemName = match[1]; // Name of the index variable to publish\n const datasourceName = match[2]; // Name of the datasource to request the rows from\n const viewportController = controllers[0]; // ViewportController, as specified in the require option (http://websystique.com/angularjs/angularjs-custom-directives-controllers-require-option-guide/)\n const bufferSize = Math.max(BUFFER_MIN, parseNumericAttr($attr.bufferSize, BUFFER_DEFAULT)); \n const padding = Math.max(PADDING_MIN, parseNumericAttr($attr.padding, PADDING_DEFAULT, true));\n let startIndex = parseNumericAttr($attr.startIndex, START_INDEX_DEFAULT);\n\n // PHIL: Provide a fixed row height\n // \n const rowHeight = parseNumericAttr($attr.rowHeight, null, false);\n\n // PHIL: Read the visibility watch option, true by default\n const allowVisibilityWatch = $attr.allowVisibilityWatch!=='false';\n\n // Revision IDs\n // \n let ridActual = 0; // current data revision id\n let pending = [];\n\n const elementRoutines = new ElementRoutines($injector, $q);\n const buffer = new ScrollBuffer(elementRoutines, bufferSize, startIndex, rowHeight);\n const viewport = new Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding, rowHeight);\n const adapter = new Adapter($scope, $parse, $attr, viewport, buffer, doAdjust, reload);\n\n if (viewportController) {\n viewportController.adapter = adapter;\n }\n\n // Currently, we only debounce the scroll events when a fixed rowHeight is provided\n // as the unit tests will have to be adapted to support this feature\n let scPreviousScrollTop=-1;\n\n const isDatasourceValid = () =>\n Object.prototype.toString.call(datasource) === '[object Object]' && typeof datasource.get === 'function';\n\n datasource = $parse(datasourceName)($scope); // try to get datasource on scope\n if (!isDatasourceValid()) {\n datasource = $injector.get(datasourceName); // try to inject datasource as service\n if (!isDatasourceValid()) {\n throw new Error(datasourceName + ' is not a valid datasource');\n }\n }\n\n let onRenderHandlers = [];\n function onRenderHandlersRunner() {\n onRenderHandlers.forEach(handler => handler.run());\n onRenderHandlers = [];\n }\n function persistDatasourceIndex(datasource, propName) {\n let getter;\n // need to postpone min/maxIndexUser processing if the view is empty\n if(angular.isNumber(datasource[propName])) {\n getter = datasource[propName];\n if(angular.isNumber(getter)) {\n onRenderHandlers = onRenderHandlers.filter(handler => handler.id !== propName);\n onRenderHandlers.push({\n id: propName,\n run: () => datasource[propName] = getter\n });\n }\n }\n }\n\n function defineDatasourceIndex(datasource, propName, propUserName) {\n const descriptor = Object.getOwnPropertyDescriptor(datasource, propName);\n if (descriptor && (descriptor.set || descriptor.get)) {\n return;\n }\n let getter;\n persistDatasourceIndex(datasource, propName);\n Object.defineProperty(datasource, propName, {\n set: (value) => {\n getter = value;\n if(pending.length && !buffer.length) {\n persistDatasourceIndex(datasource, propName);\n return;\n }\n buffer[propUserName] = value;\n const topPaddingHeightOld = viewport.topDataPos();\n viewport.adjustPaddings();\n if (propName === 'minIndex') {\n viewport.onAfterMinIndexSet(topPaddingHeightOld);\n }\n },\n get: () => getter\n });\n }\n\n defineDatasourceIndex(datasource, 'minIndex', 'minIndexUser');\n defineDatasourceIndex(datasource, 'maxIndex', 'maxIndexUser');\n\n const fetchNext = (datasource.get.length !== 2) ?\n (success) => datasource.get(buffer.next, bufferSize, success) :\n (success) => {\n datasource.get({\n index: buffer.next,\n append: buffer.length ? buffer[buffer.length - 1].item : void 0,\n count: bufferSize\n }, success);\n };\n\n const fetchPrevious = (datasource.get.length !== 2) ?\n (success) => datasource.get(buffer.first - bufferSize, bufferSize, success) :\n (success) => {\n datasource.get({\n index: buffer.first - bufferSize,\n prepend: buffer.length ? buffer[0].item : void 0,\n count: bufferSize\n }, success);\n };\n\n const initialize = () => {\n let tryCount = 0;\n if(!viewport.applyContainerStyle()) {\n const timer = $interval(() => {\n tryCount++;\n if(viewport.applyContainerStyle()) {\n $interval.cancel(timer);\n doAdjust();\n }\n if(tryCount * VIEWPORT_POLLING_INTERVAL >= MAX_VIEWPORT_DELAY) {\n $interval.cancel(timer);\n throw Error(`ui-scroll directive requires a viewport with non-zero height in ${MAX_VIEWPORT_DELAY}ms`);\n }\n }, VIEWPORT_POLLING_INTERVAL);\n }\n else {\n doAdjust();\n }\n };\n\n /**\n * Build padding elements\n *\n * Calling linker is the only way I found to get access to the tag name of the template\n * to prevent the directive scope from pollution a new scope is created and destroyed\n * right after the builder creation is completed\n */\n linker((clone, scope) => {\n viewport.createPaddingElements(clone[0]);\n // we do not include the clone in the DOM. It means that the nested directives will not\n // be able to reach the parent directives, but in this case it is intentional because we\n // created the clone to access the template tag name\n scope.$destroy();\n clone.remove();\n });\n\n $scope.$on('$destroy', () => {\n unbindEvents();\n viewport.unbind('mousewheel', wheelHandler);\n });\n\n viewport.bind('mousewheel', wheelHandler);\n\n initialize();\n\n /* Private function definitions */\n\n function isInvalid(rid) {\n return (rid && rid !== ridActual) || $scope.$$destroyed;\n }\n\n function bindEvents() {\n viewport.bind('resize', resizeAndScrollHandler);\n viewport.bind('scroll', resizeAndScrollHandler);\n // If a scroll event happened while the handler was not bounded, emit the scroll\n if(isPendingScroll()) {\n // Do it immediately\n _resizeAndScrollHandler();\n }\n }\n\n function unbindEvents() {\n viewport.unbind('resize', resizeAndScrollHandler);\n viewport.unbind('scroll', resizeAndScrollHandler);\n }\n\n function reload() {\n unbindEvents();\n viewport.resetTopPadding();\n viewport.resetBottomPadding();\n if (arguments.length) {\n startIndex = parseNumber(arguments[0], START_INDEX_DEFAULT, false);\n }\n buffer.reset(startIndex);\n scPreviousScrollTop = -1; // Avoid isScrollPending() to be true\n persistDatasourceIndex(datasource, 'minIndex');\n persistDatasourceIndex(datasource, 'maxIndex');\n doAdjust();\n }\n\n function scrollTo(first) {\n unbindEvents();\n viewport.scrollTo(first);\n doAdjust();\n }\n\n function isElementVisible(wrapper) {\n return (rowHeight || wrapper.element.height()) && wrapper.element[0].offsetParent;\n }\n\n function visibilityWatcher(wrapper) {\n if (isElementVisible(wrapper)) {\n buffer.forEach((item) => {\n if (typeof item.unregisterVisibilityWatcher === 'function') {\n item.unregisterVisibilityWatcher();\n delete item.unregisterVisibilityWatcher;\n }\n });\n if (!pending.length) {\n $timeout(() => doAdjust());\n }\n }\n }\n\n function insertWrapperContent(wrapper, insertAfter) {\n createElement(wrapper, insertAfter, viewport.insertElement);\n if (allowVisibilityWatch && !isElementVisible(wrapper)) {\n wrapper.unregisterVisibilityWatcher = wrapper.scope.$watch(() => visibilityWatcher(wrapper));\n }\n if (allowVisibilityWatch) {\n elementRoutines.hideElement(wrapper); // hide inserted elements before data binding\n }\n }\n\n function createElement(wrapper, insertAfter, insertElement) {\n let promises = null;\n const sibling = (insertAfter > 0) ? buffer[insertAfter - 1].element : undefined;\n linker((clone, scope) => {\n promises = insertElement(clone, sibling);\n wrapper.element = clone;\n wrapper.scope = scope;\n scope[itemName] = wrapper.item;\n });\n // ui-scroll-grid apply\n if (adapter.transform) {\n const tdInitializer = wrapper.scope.uiScrollTdInitializer;\n if (tdInitializer && tdInitializer.linking) {\n adapter.transform(wrapper.scope, wrapper.element);\n } else {\n wrapper.scope.uiScrollTdInitializer = {\n onLink: () => adapter.transform(wrapper.scope, wrapper.element),\n scope: wrapper.scope\n };\n }\n }\n return promises;\n }\n\n function updateDOM() {\n let promises = [];\n const toBePrepended = [];\n const toBeRemoved = [];\n const inserted = [];\n\n buffer.forEach((wrapper, i) => {\n switch (wrapper.op) {\n case 'prepend':\n toBePrepended.unshift(wrapper);\n break;\n case 'append':\n insertWrapperContent(wrapper, i);\n wrapper.op = 'none';\n inserted.push(wrapper);\n break;\n case 'insert':\n promises = promises.concat(createElement(wrapper, i, viewport.insertElementAnimated));\n wrapper.op = 'none';\n inserted.push(wrapper);\n break;\n case 'remove':\n toBeRemoved.push(wrapper);\n }\n });\n\n toBeRemoved.forEach((wrapper) => promises = promises.concat(viewport.removeItem(wrapper)));\n\n if (toBePrepended.length)\n toBePrepended.forEach((wrapper) => {\n insertWrapperContent(wrapper);\n wrapper.op = 'none';\n });\n\n buffer.forEach((item, i) => item.scope.$index = buffer.first + i);\n\n return {\n prepended: toBePrepended,\n removed: toBeRemoved,\n inserted: inserted,\n animated: promises\n };\n\n }\n\n // Adjust the viewport paddings\n // \n function updatePaddings(rid, updates) {\n // schedule another doAdjust after animation completion\n if (updates.animated.length) {\n $q.all(updates.animated).then(() => {\n viewport.adjustPaddings();\n doAdjust(rid);\n });\n } else {\n viewport.adjustPaddings();\n }\n }\n\n function enqueueFetch(rid, updates) {\n // If there is a scroll pending, we don't enqueue the fetch as the scroll might be an absolute scroll\n // So we don't need to load top or bottom\n // This happens when there is a scroll frenzi, and the $digest is slow enough, so it stacks the calls without\n // giving a chance to the scroll event to be emitted and processed.\n // We also do that if it leads to an absolute scroll\n if(isPendingScroll() && calculateAbsoluteScroll()!==undefined) {\n // Looks like the event is swallowed on some browsers (FF) on some scroll configuration\n resizeAndScrollHandler();\n return;\n }\n\n if (viewport.shouldLoadBottom()) {\n if (!updates || buffer.effectiveHeight(updates.inserted) > 0) {\n // this means that at least one item appended in the last batch has height > 0\n if (pending.push(true) === 1) {\n adapter.loading(true);\n fetch(rid);\n }\n }\n } else if (viewport.shouldLoadTop()) {\n if ((!updates || buffer.effectiveHeight(updates.prepended) > 0) || pending[0]) {\n // this means that at least one item appended in the last batch has height > 0\n // pending[0] = true means that previous fetch was appending. We need to force at least one prepend\n // BTW there will always be at least 1 element in the pending array because bottom is fetched first\n if (pending.push(false) === 1) {\n adapter.loading(true);\n fetch(rid);\n }\n }\n }\n }\n\n function processUpdates() {\n const updates = updateDOM();\n\n // We need the item bindings to be processed before we can do adjustments\n // If there are no changes and the row-height is static, then ignore it!\n const changes = updates.animated.length+updates.inserted.length+updates.prepended.length+updates.removed.length;\n if(changes || !rowHeight) {\n !$scope.$$phase && !$rootScope.$$phase && $scope.$digest();\n }\n\n if (allowVisibilityWatch) {\n updates.inserted.forEach(w => elementRoutines.showElement(w));\n updates.prepended.forEach(w => elementRoutines.showElement(w));\n }\n\n return updates;\n }\n\n function doAdjust(rid) {\n if (!rid) { // dismiss pending requests\n pending = [];\n rid = ++ridActual;\n }\n\n const updates = processUpdates();\n\n if (isInvalid(rid)) {\n return;\n }\n\n updatePaddings(rid, updates);\n enqueueFetch(rid);\n\n if (!pending.length) {\n adapter.calculateProperties();\n }\n }\n\n function doAdjustAfterFetch(rid) {\n const updates = processUpdates();\n\n viewport.onAfterPrepend(updates);\n\n if (isInvalid(rid)) {\n return;\n }\n\n updatePaddings(rid, updates);\n onRenderHandlersRunner();\n enqueueFetch(rid, updates);\n pending.shift();\n\n if (pending.length)\n fetch(rid);\n else {\n adapter.loading(false);\n bindEvents();\n adapter.calculateProperties();\n }\n }\n\n function fetch(rid) {\n if (pending[0]) {// scrolling down\n if (buffer.length && !viewport.shouldLoadBottom()) {\n doAdjustAfterFetch(rid);\n } else {\n fetchNext((result) => {\n if (isInvalid(rid)) {\n return;\n }\n\n if (result.length < bufferSize) {\n buffer.eof = true;\n }\n\n if (result.length > 0) {\n viewport.clipTop();\n buffer.append(result);\n }\n\n doAdjustAfterFetch(rid);\n });\n }\n } else { // scrolling up\n if (buffer.length && !viewport.shouldLoadTop()) {\n doAdjustAfterFetch(rid);\n } else {\n fetchPrevious((result) => {\n if (isInvalid(rid)) {\n return;\n }\n\n if (result.length < bufferSize) {\n buffer.bof = true;\n // log 'bof is reached'\n }\n\n if (result.length > 0) {\n if (buffer.length) {\n viewport.clipBottom();\n }\n buffer.prepend(result);\n }\n\n doAdjustAfterFetch(rid);\n });\n }\n }\n }\n\n function isPendingScroll() {\n if(rowHeight) {\n // Maybe the scroll changed but the event has *not* yet being dispatched\n // because of the $digest running and taking to long\n var sc = viewport.scrollTop();\n if(sc!=scPreviousScrollTop && scPreviousScrollTop>=0) {\n return true;\n }\n }\n return false;\n }\n\n // Deboucing the scroll events avois intermediate $digest when scrolling fast\n let scTimer;\n function resizeAndScrollHandler() {\n if (rowHeight) {\n if (scTimer) clearTimeout(scTimer);\n scTimer = setTimeout(_resizeAndScrollHandler, 50);\n } else {\n _resizeAndScrollHandler();\n }\n }\n\n function _resizeAndScrollHandler() {\n if (!$rootScope.$$phase && !adapter.isLoading && !adapter.disabled) {\n // Absolute positioning currently only works when a fixed rowHeight is provided\n // We might isolate the averegaRowHeight calculation in the viewport to provide an estimate\n // and provide a reasonable behavior with variable height as well\n if(rowHeight) {\n const newFirst = calculateAbsoluteScroll();\n if(newFirst!==undefined) {\n scrollTo(newFirst);\n return;\n }\n }\n\n enqueueFetch(ridActual);\n\n if (pending.length) {\n unbindEvents();\n } else {\n adapter.calculateProperties();\n if(!rowHeight) {\n // The digest is forced to calculate the height, which is not necessary when the height is knowm\n !$scope.$$phase && $scope.$digest();\n }\n }\n }\n }\n\n function calculateAbsoluteScroll() {\n if(rowHeight) {\n scPreviousScrollTop = viewport.scrollTop();\n let newFirst = Math.floor(viewport.scrollTop() / rowHeight) + buffer.getAbsMinIndex();\n newFirst = Math.max(buffer.getAbsMinIndex(), Math.min(buffer.getAbsMaxIndex(),newFirst)); // Bound the scroll\n if (newFirstbuffer.next+bufferSize) {\n return newFirst;\n } \n }\n return undefined;\n }\n\n function wheelHandler(event) {\n if (!adapter.disabled) {\n const scrollTop = viewport[0].scrollTop;\n const yMax = viewport[0].scrollHeight - viewport[0].clientHeight;\n\n if ((scrollTop === 0 && !buffer.bof) || (scrollTop === yMax && !buffer.eof)) {\n event.preventDefault();\n }\n }\n }\n }\n\n }\n ]);\n"],"sourceRoot":""} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 5cac9765..d7cda5ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "angular-ui-scroll", - "version": "1.7.3", + "version": "1.7.4", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -3288,8 +3288,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -3313,15 +3312,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3338,22 +3335,19 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -3484,8 +3478,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -3499,7 +3492,6 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3516,7 +3508,6 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -3525,15 +3516,13 @@ "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3554,7 +3543,6 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -3643,8 +3631,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -3658,7 +3645,6 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -3754,8 +3740,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -3797,7 +3782,6 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3819,7 +3803,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3868,15 +3851,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true, - "optional": true + "dev": true } } }, diff --git a/package.json b/package.json index 90f7b02e..fa219e3a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-ui-scroll", "description": "AngularJS infinite scrolling module", - "version": "1.7.3", + "version": "1.7.4", "src": "./src/", "public": "./dist/", "main": "./dist/ui-scroll.js", @@ -26,6 +26,7 @@ "hint-test": "jshint --verbose test", "hint-src": "jshint --verbose src", "build": "npm run hint-src && npm run prod-build && npm run hint-test && npm run prod-test", + "build-dev": "npm run hint-src && npm run prod-build", "dev": "npm-run-all --parallel dev-server dev-test", "test": "npm run dev-test", "start": "npm run dev-server" diff --git a/src/modules/adapter.js b/src/modules/adapter.js index 09e8767a..d37115f8 100644 --- a/src/modules/adapter.js +++ b/src/modules/adapter.js @@ -1,203 +1,225 @@ -class Adapter { - - constructor($scope, $parse, $attr, viewport, buffer, doAdjust, reload) { - this.$parse = $parse; - this.$attr = $attr; - this.viewport = viewport; - this.buffer = buffer; - - this.doAdjust = doAdjust; - this.reload = reload; - - this.isLoading = false; - this.disabled = false; - - const viewportScope = viewport.getScope(); - this.startScope = viewportScope.$parent ? viewportScope : $scope; - - this.publicContext = {}; - this.assignAdapter($attr.adapter); - this.generatePublicContext(); - } - - assignAdapter(adapterAttr) { - if (!adapterAttr || !(adapterAttr = adapterAttr.replace(/^\s+|\s+$/gm, ''))) { - return; - } - let adapterOnScope; - - try { - this.$parse(adapterAttr).assign(this.startScope, {}); - adapterOnScope = this.$parse(adapterAttr)(this.startScope); - } - catch (error) { - error.message = `Angular ui-scroll Adapter assignment exception.\n` + - `Can't parse "${adapterAttr}" expression.\n` + - error.message; - throw error; - } - - angular.extend(adapterOnScope, this.publicContext); - this.publicContext = adapterOnScope; - } - - generatePublicContext() { - // these methods will be accessible out of ui-scroll via user defined adapter - const publicMethods = ['reload', 'applyUpdates', 'append', 'prepend', 'isBOF', 'isEOF', 'isEmpty']; - for (let i = publicMethods.length - 1; i >= 0; i--) { - this.publicContext[publicMethods[i]] = this[publicMethods[i]].bind(this); - } - - // these read-only props will be accessible out of ui-scroll via user defined adapter - const publicProps = ['isLoading', 'topVisible', 'topVisibleElement', 'topVisibleScope', 'bottomVisible', 'bottomVisibleElement', 'bottomVisibleScope']; - for (let i = publicProps.length - 1; i >= 0; i--) { - let property, attr = this.$attr[publicProps[i]]; - Object.defineProperty(this, publicProps[i], { - get: () => property, - set: (value) => { - property = value; - this.publicContext[publicProps[i]] = value; - if (attr) { - this.$parse(attr).assign(this.startScope, value); - } - } - }); - } - - // non-read-only public property - Object.defineProperty(this.publicContext, 'disabled', { - get: () => this.disabled, - set: (value) => (!(this.disabled = value)) ? this.doAdjust() : null - }); - } - - loading(value) { - this.isLoading = value; - } - - isBOF() { - return this.buffer.bof; - } - - isEOF() { - return this.buffer.eof; - } - - isEmpty() { - return !this.buffer.length; - } - - append(newItems) { - this.buffer.append(newItems); - this.doAdjust(); - this.viewport.clipTop(); - this.viewport.clipBottom(); - } - - prepend(newItems) { - this.buffer.prepend(newItems); - this.doAdjust(); - this.viewport.clipTop(); - this.viewport.clipBottom(); - } - - applyUpdates(arg1, arg2) { - if (typeof arg1 === 'function') { - this.applyUpdatesFunc(arg1); - } else { - this.applyUpdatesIndex(arg1, arg2); - } - this.doAdjust(); - } - - applyUpdatesFunc(cb) { - this.buffer.slice(0).forEach((wrapper) => { - // we need to do it on the buffer clone, because buffer content - // may change as we iterate through - this.applyUpdate(wrapper, cb(wrapper.item, wrapper.scope, wrapper.element)); - }); - } - - applyUpdatesIndex(index, newItems) { - if (index % 1 !== 0) { - throw new Error('applyUpdates - ' + index + ' is not a valid index (should be an integer)'); - } - const _index = index - this.buffer.first; - - // apply updates only within buffer - if (_index >= 0 && _index < this.buffer.length) { - this.applyUpdate(this.buffer[_index], newItems); - } - // out-of-buffer case: deletion may affect Paddings - else if(index >= this.buffer.getAbsMinIndex() && index <= this.buffer.getAbsMaxIndex()) { - if(angular.isArray(newItems) && !newItems.length) { - this.viewport.removeCacheItem(index, index === this.buffer.minIndex); - if(index === this.buffer.getAbsMinIndex()) { - this.buffer.incrementMinIndex(); - } - else { - this.buffer.decrementMaxIndex(); - } - } - } - } - - applyUpdate(wrapper, newItems) { - if (!angular.isArray(newItems)) { - return; - } - let position = this.buffer.indexOf(wrapper); - if (!newItems.reverse().some(newItem => newItem === wrapper.item)) { - wrapper.op = 'remove'; - if(position === 0 && !newItems.length) { - wrapper._op = 'isTop'; // to catch "first" edge case on remove - } - } - newItems.forEach((newItem) => { - if (newItem === wrapper.item) { - position--; - } else { - // 3 parameter (isTop) is to catch "first" edge case on insert - this.buffer.insert(position + 1, newItem, position === -1); - } - }); - } - - calculateProperties() { - let rowTop = null, topHeight = 0; - let topDone = false, bottomDone = false; - const length = this.buffer.length; - - for (let i = 0; i < length; i++) { - const item = this.buffer[i]; - const itemTop = item.element.offset().top; - - if (rowTop !== itemTop) { // a new row condition - const itemHeight = item.element.outerHeight(true); - const top = this.viewport.topDataPos() + topHeight + itemHeight; - - if (!topDone && top > this.viewport.topVisiblePos()) { - topDone = true; - this['topVisible'] = item.item; - this['topVisibleElement'] = item.element; - this['topVisibleScope'] = item.scope; - } - if (!bottomDone && (top >= this.viewport.bottomVisiblePos() || (i === length - 1 && this.isEOF()))) { - bottomDone = true; - this['bottomVisible'] = item.item; - this['bottomVisibleElement'] = item.element; - this['bottomVisibleScope'] = item.scope; - } - topHeight += itemHeight; - } - rowTop = itemTop; - - if (topDone && bottomDone) { - break; - } - } - } - -} - -export default Adapter; +class Adapter { + + constructor($scope, $parse, $attr, viewport, buffer, doAdjust, reload) { + this.$parse = $parse; + this.$attr = $attr; + this.viewport = viewport; + this.buffer = buffer; + + this.doAdjust = doAdjust; + this.reload = reload; + + this.isLoading = false; + this.disabled = false; + + const viewportScope = viewport.getScope(); + this.startScope = viewportScope.$parent ? viewportScope : $scope; + + this.publicContext = {}; + this.assignAdapter($attr.adapter); + this.generatePublicContext(); + } + + assignAdapter(adapterAttr) { + if (!adapterAttr || !(adapterAttr = adapterAttr.replace(/^\s+|\s+$/gm, ''))) { + return; + } + let adapterOnScope; + + try { + this.$parse(adapterAttr).assign(this.startScope, {}); + adapterOnScope = this.$parse(adapterAttr)(this.startScope); + } + catch (error) { + error.message = `Angular ui-scroll Adapter assignment exception.\n` + + `Can't parse "${adapterAttr}" expression.\n` + + error.message; + throw error; + } + + angular.extend(adapterOnScope, this.publicContext); + this.publicContext = adapterOnScope; + } + + generatePublicContext() { + // these methods will be accessible out of ui-scroll via user defined adapter + const publicMethods = ['reload', 'applyUpdates', 'append', 'prepend', 'isBOF', 'isEOF', 'isEmpty']; + for (let i = publicMethods.length - 1; i >= 0; i--) { + this.publicContext[publicMethods[i]] = this[publicMethods[i]].bind(this); + } + + // these read-only props will be accessible out of ui-scroll via user defined adapter + const publicProps = ['isLoading', 'topVisible', 'topVisibleElement', 'topVisibleScope', 'bottomVisible', 'bottomVisibleElement', 'bottomVisibleScope']; + for (let i = publicProps.length - 1; i >= 0; i--) { + let property, attr = this.$attr[publicProps[i]]; + Object.defineProperty(this, publicProps[i], { + get: () => property, + set: (value) => { + property = value; + this.publicContext[publicProps[i]] = value; + if (attr) { + this.$parse(attr).assign(this.startScope, value); + } + } + }); + } + + // read-only immediately calculated public properties + const publicPropsImmediate = ['bufferFirst', 'bufferLast', 'bufferLength']; + for (let i = publicPropsImmediate.length - 1; i >= 0; i--) { + Object.defineProperty(this.publicContext, publicPropsImmediate[i], { + get: () => this[publicPropsImmediate[i]] + }); + } + + // non-read-only public property + Object.defineProperty(this.publicContext, 'disabled', { + get: () => this.disabled, + set: (value) => (!(this.disabled = value)) ? this.doAdjust() : null + }); + } + + loading(value) { + this.isLoading = value; + } + + isBOF() { + return this.buffer.bof; + } + + isEOF() { + return this.buffer.eof; + } + + isEmpty() { + return !this.buffer.length; + } + + get bufferLength() { + return this.buffer.getItems().length; + } + + get bufferFirst() { + return this.buffer.getFirstItem(); + } + + get bufferLast() { + return this.buffer.getLastItem(); + } + + append(newItems) { + this.buffer.append(newItems); + this.doAdjust(); + this.viewport.clipTop(); + this.viewport.clipBottom(); + } + + prepend(newItems) { + this.buffer.prepend(newItems); + this.doAdjust(); + this.viewport.clipTop(); + this.viewport.clipBottom(); + } + + applyUpdates(arg1, arg2, arg3) { + if (typeof arg1 === 'function') { + this.applyUpdatesFunc(arg1, arg2); + if(arg2 && arg2.noAdjust) return; + } else { + this.applyUpdatesIndex(arg1, arg2, arg3); + if(arg3 && arg3.noAdjust) return; + } + this.doAdjust(); + } + + applyUpdatesFunc(cb, options) { + this.buffer.slice(0).forEach((wrapper) => { + // we need to do it on the buffer clone, because buffer content + // may change as we iterate through + this.applyUpdate(wrapper, cb(wrapper.item, wrapper.scope, wrapper.element), options); + }); + } + + applyUpdatesIndex(index, newItems, options = {}) { + if (index % 1 !== 0) { + throw new Error('applyUpdates - ' + index + ' is not a valid index (should be an integer)'); + } + const _index = index - this.buffer.first; + + // apply updates only within buffer + if (_index >= 0 && _index < this.buffer.length) { + this.applyUpdate(this.buffer[_index], newItems, options); + } + // out-of-buffer case: deletion may affect Paddings + else if(index >= this.buffer.getAbsMinIndex() && index <= this.buffer.getAbsMaxIndex()) { + if(angular.isArray(newItems) && !newItems.length) { + this.viewport.removeCacheItem(index, !options.immutableTop && index === this.buffer.minIndex); + if (!options.immutableTop && index === this.buffer.getAbsMinIndex()) { + this.buffer.incrementMinIndex(); + } + else { + this.buffer.decrementMaxIndex(); + } + } + } + } + + applyUpdate(wrapper, newItems, options = {}) { + if (!angular.isArray(newItems)) { + return; + } + let position = this.buffer.indexOf(wrapper); + if (!newItems.reverse().some(newItem => newItem === wrapper.item)) { + wrapper.op = 'remove'; + if (!options.immutableTop && position === 0 && !newItems.length) { + wrapper._op = 'isTop'; // to catch "first" edge case on remove + } + } + newItems.forEach((newItem) => { + if (newItem === wrapper.item) { + position--; + } else { + // 3 parameter (isTop) is to catch "first" edge case on insert + this.buffer.insert(position + 1, newItem, !options.immutableTop && position === -1); + } + }); + } + + calculateProperties() { + let rowTop = null, topHeight = 0; + let topDone = false, bottomDone = false; + const length = this.buffer.length; + + for (let i = 0; i < length; i++) { + const item = this.buffer[i]; + const itemTop = item.element.offset().top; + + if (rowTop !== itemTop) { // a new row condition + const itemHeight = item.element.outerHeight(true); + const top = this.viewport.topDataPos() + topHeight + itemHeight; + + if (!topDone && top > this.viewport.topVisiblePos()) { + topDone = true; + this['topVisible'] = item.item; + this['topVisibleElement'] = item.element; + this['topVisibleScope'] = item.scope; + } + if (!bottomDone && (top >= this.viewport.bottomVisiblePos() || (i === length - 1 && this.isEOF()))) { + bottomDone = true; + this['bottomVisible'] = item.item; + this['bottomVisibleElement'] = item.element; + this['bottomVisibleScope'] = item.scope; + } + topHeight += itemHeight; + } + rowTop = itemTop; + + if (topDone && bottomDone) { + break; + } + } + } + +} + +export default Adapter; diff --git a/src/modules/buffer.js b/src/modules/buffer.js index 866afe17..71c7b875 100644 --- a/src/modules/buffer.js +++ b/src/modules/buffer.js @@ -1,154 +1,186 @@ -export default function ScrollBuffer(elementRoutines, bufferSize, startIndex) { - const buffer = Object.create(Array.prototype); - - angular.extend(buffer, { - size: bufferSize, - - reset(startIndex) { - buffer.remove(0, buffer.length); - buffer.eof = false; - buffer.bof = false; - buffer.first = startIndex; - buffer.next = startIndex; - buffer.minIndex = startIndex; - buffer.maxIndex = startIndex; - buffer.minIndexUser = null; - buffer.maxIndexUser = null; - }, - - append(items) { - items.forEach((item) => { - ++buffer.next; - buffer.insert('append', item); - }); - buffer.maxIndex = buffer.eof ? buffer.next - 1 : Math.max(buffer.next - 1, buffer.maxIndex); - }, - - prepend(items) { - items.reverse().forEach((item) => { - --buffer.first; - buffer.insert('prepend', item); - }); - buffer.minIndex = buffer.bof ? buffer.minIndex = buffer.first : Math.min(buffer.first, buffer.minIndex); - }, - - /** - * inserts wrapped element in the buffer - * the first argument is either operation keyword (see below) or a number for operation 'insert' - * for insert the number is the index for the buffer element the new one have to be inserted after - * operations: 'append', 'prepend', 'insert', 'remove', 'update', 'none' - */ - insert(operation, item, isTop) { - const wrapper = { - item: item - }; - - if (operation % 1 === 0) {// it is an insert - wrapper.op = 'insert'; - buffer.splice(operation, 0, wrapper); - if(isTop) { - buffer.first--; - } - else { - buffer.next++; - } - } else { - wrapper.op = operation; - switch (operation) { - case 'append': - buffer.push(wrapper); - break; - case 'prepend': - buffer.unshift(wrapper); - break; - } - } - }, - - // removes elements from buffer - remove(arg1, arg2) { - if (angular.isNumber(arg1)) { - // removes items from arg1 (including) through arg2 (excluding) - for (let i = arg1; i < arg2; i++) { - elementRoutines.removeElement(buffer[i]); - } - return buffer.splice(arg1, arg2 - arg1); - } - // removes single item(wrapper) from the buffer - buffer.splice(buffer.indexOf(arg1), 1); - if(arg1._op === 'isTop' && buffer.first === this.getAbsMinIndex()) { - this.incrementMinIndex(); - } - else { - this.decrementMaxIndex(); - } - if(arg1._op === 'isTop') { - buffer.first++; - } - else { - buffer.next--; - } - if(!buffer.length) { - buffer.first = 1; - buffer.next = 1; - } - - return elementRoutines.removeElementAnimated(arg1); - }, - - incrementMinIndex() { - if(buffer.minIndexUser !== null) { - if(buffer.minIndex > buffer.minIndexUser) { - buffer.minIndexUser++; - return; - } - if(buffer.minIndex === buffer.minIndexUser) { - buffer.minIndexUser++; - } - } - buffer.minIndex++; - }, - - decrementMaxIndex() { - if(buffer.maxIndexUser !== null && buffer.maxIndex <= buffer.maxIndexUser) { - buffer.maxIndexUser--; - } - buffer.maxIndex--; - }, - - getAbsMinIndex() { - if(buffer.minIndexUser !== null) { - return Math.min(buffer.minIndexUser, buffer.minIndex); - } - return buffer.minIndex; - }, - - getAbsMaxIndex() { - if(buffer.maxIndexUser !== null) { - return Math.max(buffer.maxIndexUser, buffer.maxIndex); - } - return buffer.maxIndex; - }, - - effectiveHeight(elements) { - if (!elements.length) { - return 0; - } - let top = Number.MAX_VALUE; - let bottom = Number.NEGATIVE_INFINITY; - elements.forEach((wrapper) => { - if (wrapper.element[0].offsetParent) { - // element style is not display:none - top = Math.min(top, wrapper.element.offset().top); - bottom = Math.max(bottom, wrapper.element.offset().top + wrapper.element.outerHeight(true)); - } - }); - return Math.max(0, bottom - top); - } - - }); - - buffer.reset(startIndex); - - return buffer; -} +export default function ScrollBuffer(elementRoutines, bufferSize, startIndex, rowHeight) { + const buffer = Object.create(Array.prototype); + + angular.extend(buffer, { + size: bufferSize, + + reset(startIndex) { + buffer.remove(0, buffer.length); + buffer.eof = false; + buffer.bof = false; + buffer.first = startIndex; + buffer.next = startIndex; + buffer.minIndex = startIndex; // Calculated when data is effectively accessed + buffer.maxIndex = startIndex; + buffer.minIndexUser = null; // as set by the user (datasource) + buffer.maxIndexUser = null; + }, + + // PHIL: set the new index to be displayed without resettng the sroll and the calculated min/max + // Note that this actually make sense with a fixed rowHeight when the scroll value can be calculated + // for a # of rows + resetStartIndex: function resetStartIndex(startIndex) { + buffer.remove(0, buffer.length); + buffer.eof = buffer.eof && startIndex==buffer.maxIndex; + buffer.bof = buffer.bof && startIndex==buffer.minIndex; + buffer.first = startIndex; + buffer.next = startIndex; + }, + + append(items) { + items.forEach((item) => { + ++buffer.next; + buffer.insert('append', item); + }); + buffer.maxIndex = buffer.eof ? buffer.next - 1 : Math.max(buffer.next - 1, buffer.maxIndex); + }, + + prepend(items) { + items.reverse().forEach((item) => { + --buffer.first; + buffer.insert('prepend', item); + }); + buffer.minIndex = buffer.bof ? buffer.minIndex = buffer.first : Math.min(buffer.first, buffer.minIndex); + }, + + /** + * inserts wrapped element in the buffer + * the first argument is either operation keyword (see below) or a number for operation 'insert' + * for insert the number is the index for the buffer element the new one have to be inserted after + * operations: 'append', 'prepend', 'insert', 'remove', 'update', 'none' + */ + insert(operation, item, isTop) { + const wrapper = { + item: item + }; + + if (operation % 1 === 0) {// it is an insert + wrapper.op = 'insert'; + buffer.splice(operation, 0, wrapper); + if(isTop) { + buffer.first--; + } + else { + buffer.next++; + } + } else { + wrapper.op = operation; + switch (operation) { + case 'append': + buffer.push(wrapper); + break; + case 'prepend': + buffer.unshift(wrapper); + break; + } + } + }, + + // removes elements from buffer + remove(arg1, arg2) { + if (angular.isNumber(arg1)) { + // removes items from arg1 (including) through arg2 (excluding) + for (let i = arg1; i < arg2; i++) { + elementRoutines.removeElement(buffer[i]); + } + return buffer.splice(arg1, arg2 - arg1); + } + // removes single item(wrapper) from the buffer + buffer.splice(buffer.indexOf(arg1), 1); + if(arg1._op === 'isTop' && buffer.first === this.getAbsMinIndex()) { + this.incrementMinIndex(); + } + else { + this.decrementMaxIndex(); + } + if(arg1._op === 'isTop') { + buffer.first++; + } + else { + buffer.next--; + } + if(!buffer.length) { + buffer.first = buffer.minIndex%1 ? buffer.minIndex : startIndex; + buffer.next = buffer.first; + buffer.eof = buffer.eof && buffer.first==buffer.maxIndex; + } + + return elementRoutines.removeElementAnimated(arg1); + }, + + incrementMinIndex() { + if(buffer.minIndexUser !== null) { + if(buffer.minIndex > buffer.minIndexUser) { + buffer.minIndexUser++; + return; + } + if(buffer.minIndex === buffer.minIndexUser) { + buffer.minIndexUser++; + } + } + buffer.minIndex++; + }, + + decrementMaxIndex() { + if(buffer.maxIndexUser !== null && buffer.maxIndex <= buffer.maxIndexUser) { + buffer.maxIndexUser--; + } + buffer.maxIndex--; + }, + + getAbsMinIndex() { + if(buffer.minIndexUser !== null) { + return Math.min(buffer.minIndexUser, buffer.minIndex); + } + return buffer.minIndex; + }, + + getAbsMaxIndex() { + if(buffer.maxIndexUser !== null) { + return Math.max(buffer.maxIndexUser, buffer.maxIndex); + } + return buffer.maxIndex; + }, + + effectiveHeight(elements) { + if (!elements.length) { + return 0; + } + let top = Number.MAX_VALUE; + let bottom = Number.NEGATIVE_INFINITY; + elements.forEach((wrapper) => { + if (wrapper.element[0].offsetParent) { + // element style is not display:none + top = Math.min(top, wrapper.element.offset().top); + bottom = Math.max(bottom, wrapper.element.offset().top + (rowHeight || wrapper.element.outerHeight(true))); + } + }); + return Math.max(0, bottom - top); + }, + + getItems() { + return buffer.filter(item => item.op === 'none'); + }, + + getFirstItem() { + const list = buffer.getItems(); + if (!list.length) { + return null; + } + return list[0].item; + }, + + getLastItem() { + const list = buffer.getItems(); + if (!list.length) { + return null; + } + return list[list.length - 1].item; + } + + }); + + buffer.reset(startIndex); + + return buffer; +} diff --git a/src/modules/elementRoutines.js b/src/modules/elementRoutines.js index b4c7dda5..a9c877f6 100644 --- a/src/modules/elementRoutines.js +++ b/src/modules/elementRoutines.js @@ -1,82 +1,82 @@ -const hideClassToken = 'ng-ui-scroll-hide'; - -export default class ElementRoutines { - - static addCSSRules() { - const selector = '.' + hideClassToken; - const rules = 'display: none'; - const sheet = document.styleSheets[0]; - let index; - try { - index = sheet.cssRules.length; - } catch (err) { - index = 0; - } - if('insertRule' in sheet) { - sheet.insertRule(selector + '{' + rules + '}', index); - } - else if('addRule' in sheet) { - sheet.addRule(selector, rules, index); - } - } - - constructor($injector, $q) { - this.$animate = ($injector.has && $injector.has('$animate')) ? $injector.get('$animate') : null; - this.isAngularVersionLessThen1_3 = angular.version.major === 1 && angular.version.minor < 3; - this.$q = $q; - } - - hideElement(wrapper) { - wrapper.element.addClass(hideClassToken); - } - - showElement(wrapper) { - wrapper.element.removeClass(hideClassToken); - } - - insertElement(newElement, previousElement) { - previousElement.after(newElement); - return []; - } - - removeElement(wrapper) { - wrapper.element.remove(); - wrapper.scope.$destroy(); - return []; - } - - insertElementAnimated(newElement, previousElement) { - if (!this.$animate) { - return this.insertElement(newElement, previousElement); - } - - if (this.isAngularVersionLessThen1_3) { - const deferred = this.$q.defer(); - // no need for parent - previous element is never null - this.$animate.enter(newElement, null, previousElement, () => deferred.resolve()); - - return [deferred.promise]; - } - - // no need for parent - previous element is never null - return [this.$animate.enter(newElement, null, previousElement)]; - } - - removeElementAnimated(wrapper) { - if (!this.$animate) { - return this.removeElement(wrapper); - } - - if (this.isAngularVersionLessThen1_3) { - const deferred = this.$q.defer(); - this.$animate.leave(wrapper.element, () => { - wrapper.scope.$destroy(); - return deferred.resolve(); - }); - - return [deferred.promise]; - } - - return [(this.$animate.leave(wrapper.element)).then(() => wrapper.scope.$destroy())]; - } +const hideClassToken = 'ng-ui-scroll-hide'; + +export default class ElementRoutines { + + static addCSSRules() { + const selector = '.' + hideClassToken; + const rules = 'display: none'; + const sheet = document.styleSheets[0]; + let index; + try { + index = sheet.cssRules.length; + } catch (err) { + index = 0; + } + if('insertRule' in sheet) { + sheet.insertRule(selector + '{' + rules + '}', index); + } + else if('addRule' in sheet) { + sheet.addRule(selector, rules, index); + } + } + + constructor($injector, $q) { + this.$animate = ($injector.has && $injector.has('$animate')) ? $injector.get('$animate') : null; + this.isAngularVersionLessThen1_3 = angular.version.major === 1 && angular.version.minor < 3; + this.$q = $q; + } + + hideElement(wrapper) { + wrapper.element.addClass(hideClassToken); + } + + showElement(wrapper) { + wrapper.element.removeClass(hideClassToken); + } + + insertElement(newElement, previousElement) { + previousElement.after(newElement); + return []; + } + + removeElement(wrapper) { + wrapper.element.remove(); + wrapper.scope.$destroy(); + return []; + } + + insertElementAnimated(newElement, previousElement) { + if (!this.$animate) { + return this.insertElement(newElement, previousElement); + } + + if (this.isAngularVersionLessThen1_3) { + const deferred = this.$q.defer(); + // no need for parent - previous element is never null + this.$animate.enter(newElement, null, previousElement, () => deferred.resolve()); + + return [deferred.promise]; + } + + // no need for parent - previous element is never null + return [this.$animate.enter(newElement, null, previousElement)]; + } + + removeElementAnimated(wrapper) { + if (!this.$animate) { + return this.removeElement(wrapper); + } + + if (this.isAngularVersionLessThen1_3) { + const deferred = this.$q.defer(); + this.$animate.leave(wrapper.element, () => { + wrapper.scope.$destroy(); + return deferred.resolve(); + }); + + return [deferred.promise]; + } + + return [(this.$animate.leave(wrapper.element)).then(() => wrapper.scope.$destroy())]; + } } \ No newline at end of file diff --git a/src/modules/jqLiteExtras.js b/src/modules/jqLiteExtras.js index e730f2ec..bba9b7f7 100644 --- a/src/modules/jqLiteExtras.js +++ b/src/modules/jqLiteExtras.js @@ -1,270 +1,270 @@ -/*! - globals: angular, window - List of used element methods available in JQuery but not in JQuery Lite - element.before(elem) - element.height() - element.outerHeight(true) - element.height(value) = only for Top/Bottom padding elements - element.scrollTop() - element.scrollTop(value) - */ - -export default class JQLiteExtras { - - registerFor(element) { - let convertToPx, css, getStyle, isWindow; - // angular implementation blows up if elem is the window - css = angular.element.prototype.css; - - element.prototype.css = function (name, value) { - let self = this; - let elem = self[0]; - if (!(!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style)) { - return css.call(self, name, value); - } - }; - - // as defined in angularjs v1.0.5 - isWindow = (obj) => obj && obj.document && obj.location && obj.alert && obj.setInterval; - - function scrollTo(self, direction, value) { - let elem = self[0]; - let [method, prop, preserve] = { - top: [ - 'scrollTop', - 'pageYOffset', - 'scrollLeft' - ], - left: [ - 'scrollLeft', - 'pageXOffset', - 'scrollTop' - ] - }[direction]; - - const isValueDefined = typeof value !== 'undefined'; - if (isWindow(elem)) { - if (isValueDefined) { - return elem.scrollTo(self[preserve].call(self), value); - } - return (prop in elem) ? elem[prop] : elem.document.documentElement[method]; - } else { - if (isValueDefined) { - elem[method] = value; - } - return elem[method]; - } - } - - if (window.getComputedStyle) { - getStyle = (elem) => window.getComputedStyle(elem, null); - convertToPx = (elem, value) => parseFloat(value); - } else { - getStyle = (elem) => elem.currentStyle; - convertToPx = (elem, value) => { - let left, result, rs, rsLeft, style; - let core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source; - let rnumnonpx = new RegExp('^(' + core_pnum + ')(?!px)[a-z%]+$', 'i'); - - if (!rnumnonpx.test(value)) { - return parseFloat(value); - } - - // ported from JQuery - style = elem.style; - left = style.left; - rs = elem.runtimeStyle; - rsLeft = rs && rs.left; - if (rs) { - rs.left = style.left; - } - // put in the new values to get a computed style out - style.left = value; - result = style.pixelLeft; - style.left = left; - if (rsLeft) { - rs.left = rsLeft; - } - return result; - }; - } - - function getMeasurements(elem, measure) { - let base, borderA, borderB, computedMarginA, computedMarginB, computedStyle, dirA, dirB, marginA, marginB, paddingA, paddingB; - - if (isWindow(elem)) { - base = document.documentElement[{height: 'clientHeight', width: 'clientWidth'}[measure]]; - - return { - base: base, - padding: 0, - border: 0, - margin: 0 - }; - } - - // Start with offset property - [ - base, - dirA, - dirB - ] = { - width: [ - elem.offsetWidth, - 'Left', - 'Right' - ], - height: [ - elem.offsetHeight, - 'Top', - 'Bottom' - ] - }[measure]; - - computedStyle = getStyle(elem); - paddingA = convertToPx(elem, computedStyle['padding' + dirA]) || 0; - paddingB = convertToPx(elem, computedStyle['padding' + dirB]) || 0; - borderA = convertToPx(elem, computedStyle['border' + dirA + 'Width']) || 0; - borderB = convertToPx(elem, computedStyle['border' + dirB + 'Width']) || 0; - computedMarginA = computedStyle['margin' + dirA]; - computedMarginB = computedStyle['margin' + dirB]; - - // I do not care for width for now, so this hack is irrelevant - // if ( !supportsPercentMargin ) - // computedMarginA = hackPercentMargin( elem, computedStyle, computedMarginA ) - // computedMarginB = hackPercentMargin( elem, computedStyle, computedMarginB ) - marginA = convertToPx(elem, computedMarginA) || 0; - marginB = convertToPx(elem, computedMarginB) || 0; - - return { - base: base, - padding: paddingA + paddingB, - border: borderA + borderB, - margin: marginA + marginB - }; - } - - function getWidthHeight(elem, direction, measure) { - let computedStyle, result; - - let measurements = getMeasurements(elem, direction); - - if (measurements.base > 0) { - return { - base: measurements.base - measurements.padding - measurements.border, - outer: measurements.base, - outerfull: measurements.base + measurements.margin - }[measure]; - } - - // Fall back to computed then uncomputed css if necessary - computedStyle = getStyle(elem); - result = computedStyle[direction]; - - if (result < 0 || result === null) { - result = elem.style[direction] || 0; - } - - // Normalize "", auto, and prepare for extra - result = parseFloat(result) || 0; - - return { - base: result - measurements.padding - measurements.border, - outer: result, - outerfull: result + measurements.padding + measurements.border + measurements.margin - }[measure]; - } - - // define missing methods - return angular.forEach({ - before(newElem) { - var children, elem, i, j, parent, ref, self; - self = this; - elem = self[0]; - parent = self.parent(); - children = parent.contents(); - if (children[0] === elem) { - return parent.prepend(newElem); - } else { - for (i = j = 1, ref = children.length - 1; 1 <= ref ? j <= ref : j >= ref; i = 1 <= ref ? ++j : --j) { - if (children[i] === elem) { - angular.element(children[i - 1]).after(newElem); - return; - } - } - throw new Error('invalid DOM structure ' + elem.outerHTML); - } - }, - height (value){ - var self; - self = this; - if (typeof value !== 'undefined') { - if (angular.isNumber(value)) { - value = value + 'px'; - } - return css.call(self, 'height', value); - } else { - return getWidthHeight(this[0], 'height', 'base'); - } - }, - outerHeight(option) { - return getWidthHeight(this[0], 'height', option ? 'outerfull' : 'outer'); - }, - outerWidth(option) { - return getWidthHeight(this[0], 'width', option ? 'outerfull' : 'outer'); - }, - - /* - The offset setter method is not implemented - */ - offset(value) { - let docElem, win; - let self = this; - let box = { - top: 0, - left: 0 - }; - let elem = self[0]; - let doc = elem && elem.ownerDocument; - - if (arguments.length) { - if (value === undefined) { - return self; - } - // TODO: implement setter - throw new Error('offset setter method is not implemented'); - } - - if (!doc) { - return; - } - - docElem = doc.documentElement; - - // TODO: Make sure it's not a disconnected DOM node - - if (elem.getBoundingClientRect != null) { - box = elem.getBoundingClientRect(); - } - - win = doc.defaultView || doc.parentWindow; - - return { - top: box.top + (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0), - left: box.left + (win.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0) - }; - }, - scrollTop(value) { - return scrollTo(this, 'top', value); - }, - scrollLeft(value) { - return scrollTo(this, 'left', value); - } - }, (value, key) => { - if (!element.prototype[key]) { - return element.prototype[key] = value; - } - }); - } - -} +/*! + globals: angular, window + List of used element methods available in JQuery but not in JQuery Lite + element.before(elem) + element.height() + element.outerHeight(true) + element.height(value) = only for Top/Bottom padding elements + element.scrollTop() + element.scrollTop(value) + */ + +export default class JQLiteExtras { + + registerFor(element) { + let convertToPx, css, getStyle, isWindow; + // angular implementation blows up if elem is the window + css = angular.element.prototype.css; + + element.prototype.css = function (name, value) { + let self = this; + let elem = self[0]; + if (!(!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style)) { + return css.call(self, name, value); + } + }; + + // as defined in angularjs v1.0.5 + isWindow = (obj) => obj && obj.document && obj.location && obj.alert && obj.setInterval; + + function scrollTo(self, direction, value) { + let elem = self[0]; + let [method, prop, preserve] = { + top: [ + 'scrollTop', + 'pageYOffset', + 'scrollLeft' + ], + left: [ + 'scrollLeft', + 'pageXOffset', + 'scrollTop' + ] + }[direction]; + + const isValueDefined = typeof value !== 'undefined'; + if (isWindow(elem)) { + if (isValueDefined) { + return elem.scrollTo(self[preserve].call(self), value); + } + return (prop in elem) ? elem[prop] : elem.document.documentElement[method]; + } else { + if (isValueDefined) { + elem[method] = value; + } + return elem[method]; + } + } + + if (window.getComputedStyle) { + getStyle = (elem) => window.getComputedStyle(elem, null); + convertToPx = (elem, value) => parseFloat(value); + } else { + getStyle = (elem) => elem.currentStyle; + convertToPx = (elem, value) => { + let left, result, rs, rsLeft, style; + let core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source; + let rnumnonpx = new RegExp('^(' + core_pnum + ')(?!px)[a-z%]+$', 'i'); + + if (!rnumnonpx.test(value)) { + return parseFloat(value); + } + + // ported from JQuery + style = elem.style; + left = style.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; + if (rs) { + rs.left = style.left; + } + // put in the new values to get a computed style out + style.left = value; + result = style.pixelLeft; + style.left = left; + if (rsLeft) { + rs.left = rsLeft; + } + return result; + }; + } + + function getMeasurements(elem, measure) { + let base, borderA, borderB, computedMarginA, computedMarginB, computedStyle, dirA, dirB, marginA, marginB, paddingA, paddingB; + + if (isWindow(elem)) { + base = document.documentElement[{height: 'clientHeight', width: 'clientWidth'}[measure]]; + + return { + base: base, + padding: 0, + border: 0, + margin: 0 + }; + } + + // Start with offset property + [ + base, + dirA, + dirB + ] = { + width: [ + elem.offsetWidth, + 'Left', + 'Right' + ], + height: [ + elem.offsetHeight, + 'Top', + 'Bottom' + ] + }[measure]; + + computedStyle = getStyle(elem); + paddingA = convertToPx(elem, computedStyle['padding' + dirA]) || 0; + paddingB = convertToPx(elem, computedStyle['padding' + dirB]) || 0; + borderA = convertToPx(elem, computedStyle['border' + dirA + 'Width']) || 0; + borderB = convertToPx(elem, computedStyle['border' + dirB + 'Width']) || 0; + computedMarginA = computedStyle['margin' + dirA]; + computedMarginB = computedStyle['margin' + dirB]; + + // I do not care for width for now, so this hack is irrelevant + // if ( !supportsPercentMargin ) + // computedMarginA = hackPercentMargin( elem, computedStyle, computedMarginA ) + // computedMarginB = hackPercentMargin( elem, computedStyle, computedMarginB ) + marginA = convertToPx(elem, computedMarginA) || 0; + marginB = convertToPx(elem, computedMarginB) || 0; + + return { + base: base, + padding: paddingA + paddingB, + border: borderA + borderB, + margin: marginA + marginB + }; + } + + function getWidthHeight(elem, direction, measure) { + let computedStyle, result; + + let measurements = getMeasurements(elem, direction); + + if (measurements.base > 0) { + return { + base: measurements.base - measurements.padding - measurements.border, + outer: measurements.base, + outerfull: measurements.base + measurements.margin + }[measure]; + } + + // Fall back to computed then uncomputed css if necessary + computedStyle = getStyle(elem); + result = computedStyle[direction]; + + if (result < 0 || result === null) { + result = elem.style[direction] || 0; + } + + // Normalize "", auto, and prepare for extra + result = parseFloat(result) || 0; + + return { + base: result - measurements.padding - measurements.border, + outer: result, + outerfull: result + measurements.padding + measurements.border + measurements.margin + }[measure]; + } + + // define missing methods + return angular.forEach({ + before(newElem) { + var children, elem, i, j, parent, ref, self; + self = this; + elem = self[0]; + parent = self.parent(); + children = parent.contents(); + if (children[0] === elem) { + return parent.prepend(newElem); + } else { + for (i = j = 1, ref = children.length - 1; 1 <= ref ? j <= ref : j >= ref; i = 1 <= ref ? ++j : --j) { + if (children[i] === elem) { + angular.element(children[i - 1]).after(newElem); + return; + } + } + throw new Error('invalid DOM structure ' + elem.outerHTML); + } + }, + height (value){ + var self; + self = this; + if (typeof value !== 'undefined') { + if (angular.isNumber(value)) { + value = value + 'px'; + } + return css.call(self, 'height', value); + } else { + return getWidthHeight(this[0], 'height', 'base'); + } + }, + outerHeight(option) { + return getWidthHeight(this[0], 'height', option ? 'outerfull' : 'outer'); + }, + outerWidth(option) { + return getWidthHeight(this[0], 'width', option ? 'outerfull' : 'outer'); + }, + + /* + The offset setter method is not implemented + */ + offset(value) { + let docElem, win; + let self = this; + let box = { + top: 0, + left: 0 + }; + let elem = self[0]; + let doc = elem && elem.ownerDocument; + + if (arguments.length) { + if (value === undefined) { + return self; + } + // TODO: implement setter + throw new Error('offset setter method is not implemented'); + } + + if (!doc) { + return; + } + + docElem = doc.documentElement; + + // TODO: Make sure it's not a disconnected DOM node + + if (elem.getBoundingClientRect != null) { + box = elem.getBoundingClientRect(); + } + + win = doc.defaultView || doc.parentWindow; + + return { + top: box.top + (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0), + left: box.left + (win.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0) + }; + }, + scrollTop(value) { + return scrollTo(this, 'top', value); + }, + scrollLeft(value) { + return scrollTo(this, 'left', value); + } + }, (value, key) => { + if (!element.prototype[key]) { + return element.prototype[key] = value; + } + }); + } + +} diff --git a/src/modules/padding.js b/src/modules/padding.js index ce66e22d..6b9766dd 100644 --- a/src/modules/padding.js +++ b/src/modules/padding.js @@ -1,84 +1,92 @@ -// Can't just extend the Array, due to Babel does not support built-in classes extending -// This solution was taken from https://stackoverflow.com/questions/46897414/es6-class-extends-array-workaround-for-es5-babel-transpile -class CacheProto { - add(item) { - for (let i = this.length - 1; i >= 0; i--) { - if (this[i].index === item.scope.$index) { - this[i].height = item.element.outerHeight(); - return; - } - } - this.push({ - index: item.scope.$index, - height: item.element.outerHeight() - }); - this.sort((a, b) => ((a.index < b.index) ? -1 : ((a.index > b.index) ? 1 : 0))); - } - - remove(argument, _isTop) { - const index = argument % 1 === 0 ? argument : argument.scope.$index; - const isTop = argument % 1 === 0 ? _isTop : argument._op === 'isTop'; - for (let i = this.length - 1; i >= 0; i--) { - if (this[i].index === index) { - this.splice(i, 1); - break; - } - } - if(!isTop) { - for (let i = this.length - 1; i >= 0; i--) { - if (this[i].index > index) { - this[i].index--; - } - } - } - } - - clear() { - this.length = 0; - } -} - -function Cache() { - const instance = []; - instance.push.apply(instance, arguments); - Object.setPrototypeOf(instance, Cache.prototype); - return instance; -} -Cache.prototype = Object.create(Array.prototype); -Object.getOwnPropertyNames(CacheProto.prototype).forEach(methodName => - Cache.prototype[methodName] = CacheProto.prototype[methodName] -); - -function generateElement(template) { - if(template.nodeType !== Node.ELEMENT_NODE) { - throw new Error('ui-scroll directive requires an Element node for templating the view'); - } - let element; - switch (template.tagName.toLowerCase()) { - case 'dl': - throw new Error(`ui-scroll directive does not support <${template.tagName}> as a repeating tag: ${template.outerHTML}`); - case 'tr': - let table = angular.element('
    '); - element = table.find('tr'); - break; - case 'li': - element = angular.element('
  • '); - break; - default: - element = angular.element('
    '); - } - return element; -} - -class Padding { - constructor(template) { - this.element = generateElement(template); - this.cache = new Cache(); - } - - height() { - return this.element.height.apply(this.element, arguments); - } -} - +// Can't just extend the Array, due to Babel does not support built-in classes extending +// This solution was taken from https://stackoverflow.com/questions/46897414/es6-class-extends-array-workaround-for-es5-babel-transpile +class CacheProto { + add(item) { + for (let i = this.length - 1; i >= 0; i--) { + if (this[i].index === item.scope.$index) { + this[i].height = item.element.outerHeight(); + return; + } + } + this.push({ + index: item.scope.$index, + height: item.element.outerHeight() + }); + this.sort((a, b) => ((a.index < b.index) ? -1 : ((a.index > b.index) ? 1 : 0))); + } + + remove(argument, _isTop) { + const index = argument % 1 === 0 ? argument : argument.scope.$index; + const isTop = argument % 1 === 0 ? _isTop : argument._op === 'isTop'; + for (let i = this.length - 1; i >= 0; i--) { + if (this[i].index === index) { + this.splice(i, 1); + break; + } + } + if(!isTop) { + for (let i = this.length - 1; i >= 0; i--) { + if (this[i].index > index) { + this[i].index--; + } + } + } + } + + clear() { + this.length = 0; + } +} + +function Cache() { + const instance = []; + instance.push.apply(instance, arguments); + Object.setPrototypeOf(instance, Cache.prototype); + return instance; +} +Cache.prototype = Object.create(Array.prototype); +Object.getOwnPropertyNames(CacheProto.prototype).forEach(methodName => + Cache.prototype[methodName] = CacheProto.prototype[methodName] +); + +function generateElement(template) { + if(template.nodeType !== Node.ELEMENT_NODE) { + throw new Error('ui-scroll directive requires an Element node for templating the view'); + } + let element; + switch (template.tagName.toLowerCase()) { + case 'dl': + throw new Error(`ui-scroll directive does not support <${template.tagName}> as a repeating tag: ${template.outerHTML}`); + case 'tr': + let table = angular.element('
    '); + element = table.find('tr'); + break; + case 'li': + element = angular.element('
  • '); + break; + default: + element = angular.element('
    '); + } + return element; +} + +// +// Padding represents the dummy element added to both the top and the bottom of the scrolling container +// It holds the element, as well as a cache for the items (rows) height. In case of a fixed rowHeight, the +// cache is not used and thus is not created. +// +class Padding { + constructor(template,useCache) { + this.element = generateElement(template); + if(useCache) { + this.cache = new Cache(); + } + } + + height() { + // When called with a parameter, this sets the height of the padding + return this.element.height.apply(this.element, arguments); + } +} + export default Padding; \ No newline at end of file diff --git a/src/modules/viewport.js b/src/modules/viewport.js index 4f64acb9..c6744e41 100644 --- a/src/modules/viewport.js +++ b/src/modules/viewport.js @@ -1,216 +1,290 @@ -import Padding from './padding'; - -export default function Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding) { - let topPadding = null; - let bottomPadding = null; - const viewport = viewportController && viewportController.viewport ? viewportController.viewport : angular.element(window); - const container = viewportController && viewportController.container ? viewportController.container : undefined; - const scope = viewportController && viewportController.scope ? viewportController.scope : $rootScope; - - viewport.css({ - 'overflow-anchor': 'none', - 'overflow-y': 'auto', - 'display': 'block' - }); - - function bufferPadding() { - return viewport.outerHeight() * padding; // some extra space to initiate preload - } - - angular.extend(viewport, { - getScope() { - return scope; - }, - - createPaddingElements(template) { - topPadding = new Padding(template); - bottomPadding = new Padding(template); - element.before(topPadding.element); - element.after(bottomPadding.element); - topPadding.height(0); - bottomPadding.height(0); - }, - - applyContainerStyle() { - if (!container) { - return true; - } - if(container !== viewport) { - viewport.css('height', window.getComputedStyle(container[0]).height); - } - return viewport.height() > 0; - }, - - bottomDataPos() { - let scrollHeight = viewport[0].scrollHeight; - scrollHeight = scrollHeight != null ? scrollHeight : viewport[0].document.documentElement.scrollHeight; - return scrollHeight - bottomPadding.height(); - }, - - topDataPos() { - return topPadding.height(); - }, - - bottomVisiblePos() { - return viewport.scrollTop() + viewport.outerHeight(); - }, - - topVisiblePos() { - return viewport.scrollTop(); - }, - - insertElement(e, sibling) { - return elementRoutines.insertElement(e, sibling || topPadding.element); - }, - - insertElementAnimated(e, sibling) { - return elementRoutines.insertElementAnimated(e, sibling || topPadding.element); - }, - - shouldLoadBottom() { - return !buffer.eof && viewport.bottomDataPos() < viewport.bottomVisiblePos() + bufferPadding(); - }, - - clipBottom() { - // clip the invisible items off the bottom - let overage = 0; - let overageHeight = 0; - let itemHeight = 0; - let emptySpaceHeight = viewport.bottomDataPos() - viewport.bottomVisiblePos() - bufferPadding(); - - for (let i = buffer.length - 1; i >= 0; i--) { - itemHeight = buffer[i].element.outerHeight(true); - if (overageHeight + itemHeight > emptySpaceHeight) { - break; - } - bottomPadding.cache.add(buffer[i]); - overageHeight += itemHeight; - overage++; - } - - if (overage > 0) { - buffer.eof = false; - buffer.remove(buffer.length - overage, buffer.length); - buffer.next -= overage; - viewport.adjustPaddings(); - } - }, - - shouldLoadTop() { - return !buffer.bof && (viewport.topDataPos() > viewport.topVisiblePos() - bufferPadding()); - }, - - clipTop() { - // clip the invisible items off the top - let overage = 0; - let overageHeight = 0; - let itemHeight = 0; - let emptySpaceHeight = viewport.topVisiblePos() - viewport.topDataPos() - bufferPadding(); - - for (let i = 0; i < buffer.length; i++) { - itemHeight = buffer[i].element.outerHeight(true); - if (overageHeight + itemHeight > emptySpaceHeight) { - break; - } - topPadding.cache.add(buffer[i]); - overageHeight += itemHeight; - overage++; - } - - if (overage > 0) { - // we need to adjust top padding element before items are removed from top - // to avoid strange behaviour of scroll bar during remove top items when we are at the very bottom - topPadding.height(topPadding.height() + overageHeight); - buffer.bof = false; - buffer.remove(0, overage); - buffer.first += overage; - } - }, - - adjustPaddings() { - if (!buffer.length) { - return; - } - - // precise heights calculation based on items that are in buffer or that were in buffer once - const visibleItemsHeight = buffer.reduce((summ, item) => summ + item.element.outerHeight(true), 0); - - let topPaddingHeight = 0, topCount = 0; - topPadding.cache.forEach(item => { - if(item.index < buffer.first) { - topPaddingHeight += item.height; - topCount++; - } - }); - - let bottomPaddingHeight = 0, bottomCount = 0; - bottomPadding.cache.forEach(item => { - if(item.index >= buffer.next) { - bottomPaddingHeight += item.height; - bottomCount++; - } - }); - - const totalHeight = visibleItemsHeight + topPaddingHeight + bottomPaddingHeight; - const averageItemHeight = totalHeight / (topCount + bottomCount + buffer.length); - - // average heights calculation, items that have never been reached - let adjustTopPadding = buffer.minIndexUser !== null && buffer.minIndex > buffer.minIndexUser; - let adjustBottomPadding = buffer.maxIndexUser !== null && buffer.maxIndex < buffer.maxIndexUser; - let topPaddingHeightAdd = adjustTopPadding ? (buffer.minIndex - buffer.minIndexUser) * averageItemHeight : 0; - let bottomPaddingHeightAdd = adjustBottomPadding ? (buffer.maxIndexUser - buffer.maxIndex) * averageItemHeight : 0; - - // paddings combine adjustment - topPadding.height(topPaddingHeight + topPaddingHeightAdd); - bottomPadding.height(bottomPaddingHeight + bottomPaddingHeightAdd); - }, - - onAfterMinIndexSet(topPaddingHeightOld) { - // additional scrollTop adjustment in case of datasource.minIndex external set - if (buffer.minIndexUser !== null && buffer.minIndex > buffer.minIndexUser) { - let diff = topPadding.height() - topPaddingHeightOld; - viewport.scrollTop(viewport.scrollTop() + diff); - while((diff -= viewport.scrollTop()) > 0) { - bottomPadding.height(bottomPadding.height() + diff); - viewport.scrollTop(viewport.scrollTop() + diff); - } - } - }, - - onAfterPrepend(updates) { - if (!updates.prepended.length) - return; - const height = buffer.effectiveHeight(updates.prepended); - const paddingHeight = topPadding.height() - height; - if (paddingHeight >= 0) { - topPadding.height(paddingHeight); - } - else { - topPadding.height(0); - viewport.scrollTop(viewport.scrollTop() - paddingHeight); - } - }, - - resetTopPadding() { - topPadding.height(0); - topPadding.cache.clear(); - }, - - resetBottomPadding() { - bottomPadding.height(0); - bottomPadding.cache.clear(); - }, - - removeCacheItem(item, isTop) { - topPadding.cache.remove(item, isTop); - bottomPadding.cache.remove(item, isTop); - }, - - removeItem(item) { - this.removeCacheItem(item); - return buffer.remove(item); - } - }); - - return viewport; -} +import Padding from './padding'; + +export default function Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding, rowHeight) { + let topPadding = null; + let bottomPadding = null; + const viewport = viewportController && viewportController.viewport ? viewportController.viewport : angular.element(window); + const container = viewportController && viewportController.container ? viewportController.container : undefined; + const scope = viewportController && viewportController.scope ? viewportController.scope : $rootScope; + + viewport.css({ + 'overflow-anchor': 'none', + 'overflow-y': 'auto', + 'display': 'block' + }); + + function bufferPadding() { + return viewport.outerHeight() * padding; // some extra space to initiate preload + } + + // + // Viewport measurements + // + // +----------------+ 0 + // | top | + // | padding | + // +----------------+ topDataPos() [=topPadding.height] + // | not visible | + // | items | + // +----------------+ topVisiblePos() [=viewport.scrollTop] + // | | + // | visible | + // | items | + // | | + // +----------------+ bottomVisiblePos() [=viewport.scrollTop+viewport.height] + // | not visible | + // | items | + // +----------------+ bottomDataPos() [=scrollHeight-bottomPadding.height] + // | bottom | + // | padding | + // +----------------+ scrollHeight + // + // bufferPadding is some extra space we have top & bottom to allow infinite scrolling + // bufferPadding = viewport.outerHeight() * padding + // + // bottomVisiblePos() - topVisiblePos() == viewport.outerHeight() + + + angular.extend(viewport, { + getScope() { + return scope; + }, + + createPaddingElements(template) { + topPadding = new Padding(template,!rowHeight); + bottomPadding = new Padding(template,!rowHeight); + element.before(topPadding.element); + element.after(bottomPadding.element); + topPadding.height(0); + bottomPadding.height(0); + }, + + applyContainerStyle() { + if (!container) { + return true; + } + if(container !== viewport) { + viewport.css('height', window.getComputedStyle(container[0]).height); + } + return viewport.height() > 0; + }, + + bottomDataPos() { + let scrollHeight = viewport[0].scrollHeight; + scrollHeight = scrollHeight != null ? scrollHeight : viewport[0].document.documentElement.scrollHeight; + return scrollHeight - bottomPadding.height(); + }, + + topDataPos() { + return topPadding.height(); + }, + + bottomVisiblePos() { + return viewport.scrollTop() + viewport.outerHeight(); + }, + + topVisiblePos() { + return viewport.scrollTop(); + }, + + insertElement(e, sibling) { + return elementRoutines.insertElement(e, sibling || topPadding.element); + }, + + insertElementAnimated(e, sibling) { + return elementRoutines.insertElementAnimated(e, sibling || topPadding.element); + }, + + shouldLoadBottom() { + return !buffer.eof && viewport.bottomDataPos() < viewport.bottomVisiblePos() + bufferPadding(); + }, + + clipBottom() { + // clip the invisible items off the bottom + let overage = 0; + let emptySpaceHeight = viewport.bottomDataPos() - viewport.bottomVisiblePos() - bufferPadding(); + if(rowHeight) { + overage = Math.min(buffer.length,Math.floor(emptySpaceHeight/rowHeight)); + } else { + let itemHeight = 0; + let overageHeight = 0; + + for (let i = buffer.length - 1; i >= 0; i--) { + itemHeight = buffer[i].element.outerHeight(true); + if (overageHeight + itemHeight > emptySpaceHeight) { + break; + } + bottomPadding.cache.add(buffer[i]); + overageHeight += itemHeight; + overage++; + } + } + + if (overage > 0) { + buffer.eof = false; + buffer.remove(buffer.length - overage, buffer.length); + buffer.next -= overage; + viewport.adjustPaddings(); + } + }, + + shouldLoadTop() { + return !buffer.bof && (viewport.topDataPos() > viewport.topVisiblePos() - bufferPadding()); + }, + + clipTop() { + // clip the invisible items off the top + let overage = 0; + let overageHeight = 0; + let emptySpaceHeight = viewport.topVisiblePos() - viewport.topDataPos() - bufferPadding(); + if(rowHeight) { + overage = Math.min(buffer.length,Math.floor(emptySpaceHeight/rowHeight)); + overageHeight = overage * rowHeight; + } else { + let itemHeight = 0; + + for (let i = 0; i < buffer.length; i++) { + itemHeight = buffer[i].element.outerHeight(true); + if (overageHeight + itemHeight > emptySpaceHeight) { + break; + } + topPadding.cache.add(buffer[i]); + overageHeight += itemHeight; + overage++; + } + } + + if (overage > 0) { + // we need to adjust top padding element before items are removed from top + // to avoid strange behaviour of scroll bar during remove top items when we are at the very bottom + topPadding.height(topPadding.height() + overageHeight); + buffer.bof = false; + buffer.remove(0, overage); + buffer.first += overage; + } + }, + + // PHIL: remove all the entries in the buffer without changing the scrollbar, nor the scroll position + // and update the padding accordingly + // It is designed to work with non fixed rowHeight, although it will need more tests in this area... + scrollTo(first) { + if(rowHeight) { + const min = buffer.getAbsMinIndex(); + const max = buffer.getAbsMaxIndex(); + first = Math.min(Math.max(first, min),max); + // Adjust the paddings before removing the elements to avoid touching the scroll top position + topPadding.height((first-min)*rowHeight); + bottomPadding.height(((max+1)-first)*rowHeight); + buffer.resetStartIndex(first); + } else { + buffer.resetStartIndex(first); + viewport.adjustPaddings(); + } + }, + + adjustPaddings() { + if(rowHeight) { + const min = buffer.getAbsMinIndex(); + const max = buffer.getAbsMaxIndex(); + topPadding.height((buffer.first-min)*rowHeight); + // PHIL: next points to the next possible item, while max is the index of the last one. + // In order to make them compatible, we should add one to max + // Also, it looks like buffer is not changing maxIndex when an element is inserted/appended + // Not sure if this can have a consequence or not.... + bottomPadding.height(((max+1)-buffer.next)*rowHeight); + return; + } + + if (!buffer.length) { + return; + } + + // precise heights calculation based on items that are in buffer or that were in buffer once + const visibleItemsHeight = buffer.reduce((summ, item) => summ + item.element.outerHeight(true), 0); + let topPaddingHeight = 0, topCount = 0; + topPadding.cache.forEach(item => { + if(item.index < buffer.first) { + topPaddingHeight += item.height; + topCount++; + } + }); + + let bottomPaddingHeight = 0, bottomCount = 0; + bottomPadding.cache.forEach(item => { + if(item.index >= buffer.next) { + bottomPaddingHeight += item.height; + bottomCount++; + } + }); + + const totalHeight = visibleItemsHeight + topPaddingHeight + bottomPaddingHeight; + const averageItemHeight = totalHeight / (topCount + bottomCount + buffer.length); + + // average heights calculation, items that have never been reached + let adjustTopPadding = buffer.minIndexUser !== null && buffer.minIndex > buffer.minIndexUser; + let adjustBottomPadding = buffer.maxIndexUser !== null && buffer.maxIndex < buffer.maxIndexUser; + let topPaddingHeightAdd = adjustTopPadding ? (buffer.minIndex - buffer.minIndexUser) * averageItemHeight : 0; + let bottomPaddingHeightAdd = adjustBottomPadding ? (buffer.maxIndexUser - buffer.maxIndex) * averageItemHeight : 0; + + // paddings combine adjustment + topPadding.height(topPaddingHeight + topPaddingHeightAdd); + bottomPadding.height(bottomPaddingHeight + bottomPaddingHeightAdd); + }, + + onAfterMinIndexSet(topPaddingHeightOld) { + // additional scrollTop adjustment in case of datasource.minIndex external set + if (buffer.minIndexUser !== null && buffer.minIndex > buffer.minIndexUser) { + let diff = topPadding.height() - topPaddingHeightOld; + viewport.scrollTop(viewport.scrollTop() + diff); + while((diff -= viewport.scrollTop()) > 0) { + bottomPadding.height(bottomPadding.height() + diff); + viewport.scrollTop(viewport.scrollTop() + diff); + } + } + }, + + onAfterPrepend(updates) { + if (!updates.prepended.length) + return; + const height = buffer.effectiveHeight(updates.prepended); + const paddingHeight = topPadding.height() - height; + if (paddingHeight >= 0) { + topPadding.height(paddingHeight); + } + else { + topPadding.height(0); + viewport.scrollTop(viewport.scrollTop() - paddingHeight); + } + }, + + resetTopPadding() { + topPadding.height(0); + if(topPadding.cache) { + topPadding.cache.clear(); + } + }, + + resetBottomPadding() { + bottomPadding.height(0); + if(bottomPadding.cache) { + bottomPadding.cache.clear(); + } + }, + + removeCacheItem(item, isTop) { + if(topPadding.cache) { + topPadding.cache.remove(item, isTop); + } + if(bottomPadding.cache) { + bottomPadding.cache.remove(item, isTop); + } + }, + + removeItem(item) { + this.removeCacheItem(item); + return buffer.remove(item); + } + }); + + return viewport; +} diff --git a/src/ui-scroll-jqlite.js b/src/ui-scroll-jqlite.js index c542a1a4..7fae71e5 100644 --- a/src/ui-scroll-jqlite.js +++ b/src/ui-scroll-jqlite.js @@ -1,12 +1,12 @@ -/*! - * angular-ui-scroll - * https://github.com/angular-ui/ui-scroll.git - * This module is deprecated since 1.6.0 and will be removed in future versions! - * License: MIT - */ -(function () { - 'use strict'; - - angular.module('ui.scroll.jqlite', []); - +/*! + * angular-ui-scroll + * https://github.com/angular-ui/ui-scroll.git + * This module is deprecated since 1.6.0 and will be removed in future versions! + * License: MIT + */ +(function () { + 'use strict'; + + angular.module('ui.scroll.jqlite', []); + })(); \ No newline at end of file diff --git a/src/ui-scroll.js b/src/ui-scroll.js index edb83dea..73284808 100644 --- a/src/ui-scroll.js +++ b/src/ui-scroll.js @@ -8,7 +8,8 @@ angular.module('ui.scroll', []) .constant('JQLiteExtras', JQLiteExtras) .run(['JQLiteExtras', (JQLiteExtras) => { - !window.jQuery ? (new JQLiteExtras()).registerFor(angular.element) : null; + const elt = angular.element; + !(window.jQuery && elt.fn && elt.fn.jquery) ? (new JQLiteExtras()).registerFor(elt) : null; ElementRoutines.addCSSRules(); }]) @@ -72,33 +73,47 @@ angular.module('ui.scroll', []) return parseNumber(result, defaultValue, isFloat); } - const BUFFER_MIN = 3; - const BUFFER_DEFAULT = 10; - const PADDING_MIN = 0.3; - const PADDING_DEFAULT = 0.5; - const START_INDEX_DEFAULT = 1; - const MAX_VIEWPORT_DELAY = 500; - const VIEWPORT_POLLING_INTERVAL = 50; + const BUFFER_MIN = 3; // Minimum size of the data source request + const BUFFER_DEFAULT = 10; // Default datasource request size + const PADDING_MIN = 0.3; // Mininum # of rows in the padding area + const PADDING_DEFAULT = 0.5; // Default # of rows in the padding area + const START_INDEX_DEFAULT = 1; // Default start index when requestng the first data block + const MAX_VIEWPORT_DELAY = 500; // Max time wait (ms) to get the viewport with an height>0 + const VIEWPORT_POLLING_INTERVAL = 50; // Interval used to check the initial viewport height let datasource = null; - const itemName = match[1]; - const datasourceName = match[2]; - const viewportController = controllers[0]; - const bufferSize = Math.max(BUFFER_MIN, parseNumericAttr($attr.bufferSize, BUFFER_DEFAULT)); + const itemName = match[1]; // Name of the index variable to publish + const datasourceName = match[2]; // Name of the datasource to request the rows from + const viewportController = controllers[0]; // ViewportController, as specified in the require option (http://websystique.com/angularjs/angularjs-custom-directives-controllers-require-option-guide/) + const bufferSize = Math.max(BUFFER_MIN, parseNumericAttr($attr.bufferSize, BUFFER_DEFAULT)); const padding = Math.max(PADDING_MIN, parseNumericAttr($attr.padding, PADDING_DEFAULT, true)); let startIndex = parseNumericAttr($attr.startIndex, START_INDEX_DEFAULT); + + // PHIL: Provide a fixed row height + // + const rowHeight = parseNumericAttr($attr.rowHeight, null, false); + + // PHIL: Read the visibility watch option, true by default + const allowVisibilityWatch = $attr.allowVisibilityWatch!=='false'; + + // Revision IDs + // let ridActual = 0; // current data revision id let pending = []; const elementRoutines = new ElementRoutines($injector, $q); - const buffer = new ScrollBuffer(elementRoutines, bufferSize, startIndex); - const viewport = new Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding); + const buffer = new ScrollBuffer(elementRoutines, bufferSize, startIndex, rowHeight); + const viewport = new Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding, rowHeight); const adapter = new Adapter($scope, $parse, $attr, viewport, buffer, doAdjust, reload); if (viewportController) { viewportController.adapter = adapter; } + // Currently, we only debounce the scroll events when a fixed rowHeight is provided + // as the unit tests will have to be adapted to support this feature + let scPreviousScrollTop=-1; + const isDatasourceValid = () => Object.prototype.toString.call(datasource) === '[object Object]' && typeof datasource.get === 'function'; @@ -232,6 +247,11 @@ angular.module('ui.scroll', []) function bindEvents() { viewport.bind('resize', resizeAndScrollHandler); viewport.bind('scroll', resizeAndScrollHandler); + // If a scroll event happened while the handler was not bounded, emit the scroll + if(isPendingScroll()) { + // Do it immediately + _resizeAndScrollHandler(); + } } function unbindEvents() { @@ -240,19 +260,27 @@ angular.module('ui.scroll', []) } function reload() { + unbindEvents(); viewport.resetTopPadding(); viewport.resetBottomPadding(); if (arguments.length) { startIndex = parseNumber(arguments[0], START_INDEX_DEFAULT, false); } buffer.reset(startIndex); + scPreviousScrollTop = -1; // Avoid isScrollPending() to be true persistDatasourceIndex(datasource, 'minIndex'); persistDatasourceIndex(datasource, 'maxIndex'); doAdjust(); } + function scrollTo(first) { + unbindEvents(); + viewport.scrollTo(first); + doAdjust(); + } + function isElementVisible(wrapper) { - return wrapper.element.height() && wrapper.element[0].offsetParent; + return (rowHeight || wrapper.element.height()) && wrapper.element[0].offsetParent; } function visibilityWatcher(wrapper) { @@ -271,10 +299,12 @@ angular.module('ui.scroll', []) function insertWrapperContent(wrapper, insertAfter) { createElement(wrapper, insertAfter, viewport.insertElement); - if (!isElementVisible(wrapper)) { + if (allowVisibilityWatch && !isElementVisible(wrapper)) { wrapper.unregisterVisibilityWatcher = wrapper.scope.$watch(() => visibilityWatcher(wrapper)); } - elementRoutines.hideElement(wrapper); // hide inserted elements before data binding + if (allowVisibilityWatch) { + elementRoutines.hideElement(wrapper); // hide inserted elements before data binding + } } function createElement(wrapper, insertAfter, insertElement) { @@ -346,6 +376,8 @@ angular.module('ui.scroll', []) } + // Adjust the viewport paddings + // function updatePaddings(rid, updates) { // schedule another doAdjust after animation completion if (updates.animated.length) { @@ -359,6 +391,17 @@ angular.module('ui.scroll', []) } function enqueueFetch(rid, updates) { + // If there is a scroll pending, we don't enqueue the fetch as the scroll might be an absolute scroll + // So we don't need to load top or bottom + // This happens when there is a scroll frenzi, and the $digest is slow enough, so it stacks the calls without + // giving a chance to the scroll event to be emitted and processed. + // We also do that if it leads to an absolute scroll + if(isPendingScroll() && calculateAbsoluteScroll()!==undefined) { + // Looks like the event is swallowed on some browsers (FF) on some scroll configuration + resizeAndScrollHandler(); + return; + } + if (viewport.shouldLoadBottom()) { if (!updates || buffer.effectiveHeight(updates.inserted) > 0) { // this means that at least one item appended in the last batch has height > 0 @@ -384,10 +427,17 @@ angular.module('ui.scroll', []) const updates = updateDOM(); // We need the item bindings to be processed before we can do adjustments - !$scope.$$phase && !$rootScope.$$phase && $scope.$digest(); + // If there are no changes and the row-height is static, then ignore it! + const changes = updates.animated.length+updates.inserted.length+updates.prepended.length+updates.removed.length; + if(changes || !rowHeight) { + !$scope.$$phase && !$rootScope.$$phase && $scope.$digest(); + } + + if (allowVisibilityWatch) { + updates.inserted.forEach(w => elementRoutines.showElement(w)); + updates.prepended.forEach(w => elementRoutines.showElement(w)); + } - updates.inserted.forEach(w => elementRoutines.showElement(w)); - updates.prepended.forEach(w => elementRoutines.showElement(w)); return updates; } @@ -483,8 +533,41 @@ angular.module('ui.scroll', []) } } + function isPendingScroll() { + if(rowHeight) { + // Maybe the scroll changed but the event has *not* yet being dispatched + // because of the $digest running and taking to long + var sc = viewport.scrollTop(); + if(sc!=scPreviousScrollTop && scPreviousScrollTop>=0) { + return true; + } + } + return false; + } + + // Deboucing the scroll events avois intermediate $digest when scrolling fast + let scTimer; function resizeAndScrollHandler() { + if (rowHeight) { + if (scTimer) clearTimeout(scTimer); + scTimer = setTimeout(_resizeAndScrollHandler, 50); + } else { + _resizeAndScrollHandler(); + } + } + + function _resizeAndScrollHandler() { if (!$rootScope.$$phase && !adapter.isLoading && !adapter.disabled) { + // Absolute positioning currently only works when a fixed rowHeight is provided + // We might isolate the averegaRowHeight calculation in the viewport to provide an estimate + // and provide a reasonable behavior with variable height as well + if(rowHeight) { + const newFirst = calculateAbsoluteScroll(); + if(newFirst!==undefined) { + scrollTo(newFirst); + return; + } + } enqueueFetch(ridActual); @@ -492,11 +575,29 @@ angular.module('ui.scroll', []) unbindEvents(); } else { adapter.calculateProperties(); - !$scope.$$phase && $scope.$digest(); + if(!rowHeight) { + // The digest is forced to calculate the height, which is not necessary when the height is knowm + !$scope.$$phase && $scope.$digest(); + } } } } + function calculateAbsoluteScroll() { + if(rowHeight) { + scPreviousScrollTop = viewport.scrollTop(); + let newFirst = Math.floor(viewport.scrollTop() / rowHeight) + buffer.getAbsMinIndex(); + newFirst = Math.max(buffer.getAbsMinIndex(), Math.min(buffer.getAbsMaxIndex(),newFirst)); // Bound the scroll + if (newFirstbuffer.next+bufferSize) { + return newFirst; + } + } + return undefined; + } + function wheelHandler(event) { if (!adapter.disabled) { const scrollTop = viewport[0].scrollTop; diff --git a/test/PaddingsSpec.js b/test/PaddingsSpec.js index df80b4b1..362d881b 100644 --- a/test/PaddingsSpec.js +++ b/test/PaddingsSpec.js @@ -1,404 +1,404 @@ -describe('uiScroll Paddings spec.', () => { - 'use strict'; - - let datasource; - beforeEach(module('ui.scroll')); - beforeEach(module('ui.scroll.test.datasources')); - beforeEach( - inject(function(myResponsiveDatasource) { - datasource = myResponsiveDatasource; - }) - ); - - const itemsCount = 30; - const itemHeight = 100; - const viewportHeight = 500; - const MAX = 3; // maximum scrolling interations to reach out the EOF/BOF - - const scrollSettings = { - datasource: 'myResponsiveDatasource', - adapter: 'adapter', - itemHeight: itemHeight, - viewportHeight: viewportHeight - }; - - function appendTitle(outside, indices) { - return (outside ? ' outside' : ' inside') + ' the buffer' + (indices ? ' when min/max indices are set': ''); - } - - function setUserIndices() { - datasource.minIndex = datasource.min; - datasource.maxIndex = datasource.max; - } - - function scrollBottom(viewport, count = 1) { - for (var i = 0; i < count; i++) { - viewport.scrollTop(99999); - viewport.trigger('scroll'); - } - } - - function scrollTop(viewport, count = 1) { - for (var i = 0; i < count; i++) { - viewport.scrollTop(0); - viewport.trigger('scroll'); - } - } - - function removeItem(datasource, index) { - if(index >= datasource.min && index <= datasource.max) { - const indexRemoved = datasource.data.indexOf(datasource.data[index - datasource.min]); - if(indexRemoved > -1) { - datasource.data.splice(indexRemoved, 1); - if(index === datasource.min) { - datasource.min++; - } - else { - datasource.max--; - } - } - } - } - - function insertItems(datasource, index, items = []) { - if(index >= datasource.min && index <= datasource.max && items.length) { - const indexToInsert = datasource.data.indexOf(datasource.data[index - datasource.min]); - if(indexToInsert > -1) { - datasource.data.splice(indexToInsert, 0, items); - datasource.max += items.length; - } - } - } - - function checkRow(viewport, row, content, tail = false) { - var children = viewport.children(); - if(tail) { - row = children.length - 1 - row; - } - const rowElement = children[row]; - expect(rowElement.innerHTML).toBe(content); - } - - function checkRowBack(viewport, row, content) { - checkRow(viewport, row, content, true); - } - - it('\nshould set up properly', () => { - runTest(scrollSettings, - () => { - expect(datasource.min).toBe(1); - expect(datasource.max).toBe(itemsCount); - } - ); - }); - - describe('Removing items via indexed-based applyUpdates\n', () => { - - [true, false].forEach(outside => - [true, false].forEach(userIndices => - it('should remove last row' + appendTitle(outside, userIndices), () => - runTest(scrollSettings, - (viewport, scope) => { - userIndices && setUserIndices(); - - scrollBottom(viewport, MAX); - outside && scrollTop(viewport); - const initialBottomHeight = Helper.getBottomPadding(viewport); - - removeItem(datasource, datasource.max); - scope.adapter.applyUpdates(itemsCount, []); - outside && expect(Helper.getBottomPadding(viewport)).toBe(initialBottomHeight - itemHeight); - - !outside && scrollTop(viewport); - scrollBottom(viewport, MAX); - expect(viewport.scrollTop()).toBe(itemsCount * itemHeight - viewportHeight - itemHeight); - checkRowBack(viewport, 1, (itemsCount - 1) + ': item' + (itemsCount - 1)); - } - ) - ) - ) - ); - - [true, false].forEach(outside => - [true, false].forEach(userIndices => - it('should remove last row and then the next after last' + appendTitle(outside, userIndices), () => - runTest(scrollSettings, - (viewport, scope) => { - userIndices && setUserIndices(); - - scrollBottom(viewport, MAX); - outside && scrollTop(viewport); - - const initialBottomHeight = Helper.getBottomPadding(viewport); - removeItem(datasource, datasource.max); - scope.adapter.applyUpdates(itemsCount, []); - removeItem(datasource, datasource.max); - scope.adapter.applyUpdates(itemsCount - 1, []); - outside && expect(Helper.getBottomPadding(viewport)).toBe(initialBottomHeight - itemHeight * 2); - - !outside && scrollTop(viewport); - scrollBottom(viewport, MAX); - expect(viewport.scrollTop()).toBe(itemsCount * itemHeight - viewportHeight - itemHeight * 2); - checkRowBack(viewport, 1, (itemsCount - 2) + ': item' + (itemsCount - 2)); - } - ) - ) - ) - ); - - [true, false].forEach(outside => - [true, false].forEach(userIndices => - it('should remove pre-last row' + appendTitle(outside, userIndices), () => - runTest(scrollSettings, - (viewport, scope) => { - userIndices && setUserIndices(); - - scrollBottom(viewport, MAX); - outside && scrollTop(viewport); - - const initialBottomHeight = Helper.getBottomPadding(viewport); - removeItem(datasource, datasource.max - 1); - scope.adapter.applyUpdates(itemsCount - 1, []); - outside && expect(Helper.getBottomPadding(viewport)).toBe(initialBottomHeight - itemHeight); - - !outside && scrollTop(viewport); - scrollBottom(viewport, MAX); - expect(viewport.scrollTop()).toBe(itemsCount * itemHeight - viewportHeight - itemHeight); - checkRowBack(viewport, 1, (itemsCount - 1) + ': item' + itemsCount); - checkRowBack(viewport, 2, (itemsCount - 2) + ': item' + (itemsCount - 2)); - } - ) - ) - ) - ); - - [true, false].forEach(outside => - [true, false].forEach(userIndices => - it('should remove first row' + appendTitle(outside, userIndices), () => - runTest(scrollSettings, - (viewport, scope) => { - userIndices && setUserIndices(); - - outside && scrollBottom(viewport, MAX); - - const initialTopHeight = Helper.getTopPadding(viewport); - removeItem(datasource, datasource.min); - scope.adapter.applyUpdates(1, []); - outside && expect(Helper.getTopPadding(viewport)).toBe(initialTopHeight - itemHeight); - - !outside && scrollBottom(viewport, MAX); - expect(Helper.getBottomPadding(viewport)).toBe(0); - - scrollTop(viewport); - expect(Helper.getTopPadding(viewport)).toBe(0); - checkRow(viewport, 1, '2: item2'); - } - ) - ) - ) - ); - - [true, false].forEach(outside => - [true, false].forEach(userIndices => - it('should remove first row and then the next after first' + appendTitle(outside, userIndices), () => - runTest(scrollSettings, - (viewport, scope) => { - userIndices && setUserIndices(); - - outside && scrollBottom(viewport, MAX); - - const initialTopHeight = Helper.getTopPadding(viewport); - removeItem(datasource, datasource.min); - scope.adapter.applyUpdates(1, []); - removeItem(datasource, datasource.min); - scope.adapter.applyUpdates(2, []); - outside && expect(Helper.getTopPadding(viewport)).toBe(initialTopHeight - itemHeight * 2); - - !outside && scrollBottom(viewport, MAX); - expect(Helper.getBottomPadding(viewport)).toBe(0); - - scrollTop(viewport); - expect(Helper.getTopPadding(viewport)).toBe(0); - checkRow(viewport, 1, '3: item3'); - } - ) - ) - ) - ); - - [true, false].forEach(outside => - [true, false].forEach(userIndices => - it('should remove second row' + appendTitle(outside, userIndices), () => - runTest(scrollSettings, - (viewport, scope) => { - userIndices && setUserIndices(); - - outside && scrollBottom(viewport, MAX); - - const initialTopHeight = Helper.getTopPadding(viewport); - removeItem(datasource, datasource.min + 1); - scope.adapter.applyUpdates(2, []); - outside && expect(Helper.getTopPadding(viewport)).toBe(initialTopHeight - itemHeight * 1); - - !outside && scrollBottom(viewport, MAX); - expect(Helper.getBottomPadding(viewport)).toBe(0); - - scrollTop(viewport); - expect(Helper.getTopPadding(viewport)).toBe(0); - checkRow(viewport, 1, '1: item1'); - checkRow(viewport, 2, '2: item3'); - } - ) - ) - ) - ); - }); - - describe('Appending inside the buffer\n', () => { - - it('should append 3 rows via index-based applyUpdates', () => { - runTest(Object.assign({}, scrollSettings, { startIndex: 28 }), - (viewport, scope) => { - const newItems = [ - 'item' + (datasource.max + 1), - 'item' + (datasource.max + 2), - 'item' + (datasource.max + 3) - ]; - const oldMax = datasource.max; - const _scrollTop = viewport.scrollTop(); - - insertItems(datasource, datasource.max, newItems); - scope.adapter.applyUpdates(oldMax, ['item' + oldMax, ...newItems]); - - scrollBottom(viewport); - expect(viewport.scrollTop()).toBe(_scrollTop + newItems.length * itemHeight); - - checkRowBack(viewport, 1, (datasource.max - 0) + ': ' + newItems[2]); - checkRowBack(viewport, 2, (datasource.max - 1) + ': ' + newItems[1]); - checkRowBack(viewport, 3, (datasource.max - 2) + ': ' + newItems[0]); - checkRowBack(viewport, 4, oldMax + ': item' + oldMax); - } - ); - }); - - it('should append 3 rows via index-based applyUpdates when min/max indices are set', () => { - runTest(Object.assign({}, scrollSettings, { startIndex: 28 }), - (viewport, scope) => { - const newItems = [ - 'item' + (datasource.max + 1), - 'item' + (datasource.max + 2), - 'item' + (datasource.max + 3) - ]; - const oldMax = datasource.max; - - datasource.minIndex = datasource.min; - datasource.maxIndex = datasource.max; - const _scrollTop = viewport.scrollTop(); - - insertItems(datasource, datasource.max, newItems); - scope.adapter.applyUpdates(oldMax, ['item' + oldMax, ...newItems]); - - scrollBottom(viewport); - expect(viewport.scrollTop()).toBe(_scrollTop + newItems.length * itemHeight); - - checkRowBack(viewport, 1, (datasource.max - 0) + ': ' + newItems[2]); - checkRowBack(viewport, 2, (datasource.max - 1) + ': ' + newItems[1]); - checkRowBack(viewport, 3, (datasource.max - 2) + ': ' + newItems[0]); - checkRowBack(viewport, 4, oldMax + ': item' + oldMax); - } - ); - }); - }); - - - describe('Removing items via indexed-based applyUpdates when neither BOF nor EOF are reached\n', () => { - const _scrollSettings = Object.assign({}, scrollSettings, { startIndex: 12 }); - - [true, false].forEach(userIndices => - it('should remove first buffered row' + appendTitle(true, userIndices), () => - runTest(_scrollSettings, - (viewport, scope) => { - userIndices && setUserIndices(); - - removeItem(datasource, 2); - scope.adapter.applyUpdates(2, []); - - scrollBottom(viewport, MAX); - expect(Helper.getBottomPadding(viewport)).toBe(0); - checkRowBack(viewport, 1, (itemsCount - 1) + ': item' + itemsCount); - - scrollTop(viewport); - expect(Helper.getTopPadding(viewport)).toBe(0); - checkRow(viewport, 1, '1: item1'); - checkRow(viewport, 2, '2: item3'); - } - ) - ) - ); - - [true, false].forEach(userIndices => - it('should remove last buffered row' + appendTitle(true, userIndices), () => - runTest(_scrollSettings, - (viewport, scope) => { - userIndices && setUserIndices(); - - removeItem(datasource, 19); - scope.adapter.applyUpdates(19, []); - - scrollBottom(viewport); - expect(Helper.getBottomPadding(viewport)).toBe(0); - checkRowBack(viewport, 1, (itemsCount - 1) + ': item' + itemsCount); - - scrollTop(viewport); - expect(Helper.getTopPadding(viewport)).toBe(0); - } - ) - ) - ); - - [true, false].forEach(userIndices => - it('should remove absolute first row' + appendTitle(true, userIndices), () => - runTest(_scrollSettings, - (viewport, scope) => { - userIndices && setUserIndices(); - - removeItem(datasource, 1); - scope.adapter.applyUpdates(1, []); - - scrollBottom(viewport, MAX); - expect(Helper.getBottomPadding(viewport)).toBe(0); - checkRowBack(viewport, 1, itemsCount + ': item' + itemsCount); - - scrollTop(viewport); - expect(Helper.getTopPadding(viewport)).toBe(0); - checkRow(viewport, 1, '2: item2'); - checkRow(viewport, 2, '3: item3'); - } - ) - ) - ); - - [true, false].forEach(userIndices => - it('should remove absolute last row' + appendTitle(true, userIndices), () => - runTest(_scrollSettings, - (viewport, scope) => { - userIndices && setUserIndices(); - - removeItem(datasource, itemsCount); - scope.adapter.applyUpdates(itemsCount, []); - - scrollBottom(viewport, MAX); - expect(Helper.getBottomPadding(viewport)).toBe(0); - checkRowBack(viewport, 1, (itemsCount - 1) + ': item' + (itemsCount - 1)); - - scrollTop(viewport); - expect(Helper.getTopPadding(viewport)).toBe(0); - checkRow(viewport, 1, '1: item1'); - checkRow(viewport, 2, '2: item2'); - } - ) - ) - ); - }); - -}); +describe('uiScroll Paddings spec.', () => { + 'use strict'; + + let datasource; + beforeEach(module('ui.scroll')); + beforeEach(module('ui.scroll.test.datasources')); + beforeEach( + inject(function(myResponsiveDatasource) { + datasource = myResponsiveDatasource; + }) + ); + + const itemsCount = 30; + const itemHeight = 100; + const viewportHeight = 500; + const MAX = 3; // maximum scrolling interations to reach out the EOF/BOF + + const scrollSettings = { + datasource: 'myResponsiveDatasource', + adapter: 'adapter', + itemHeight: itemHeight, + viewportHeight: viewportHeight + }; + + function appendTitle(outside, indices) { + return (outside ? ' outside' : ' inside') + ' the buffer' + (indices ? ' when min/max indices are set': ''); + } + + function setUserIndices() { + datasource.minIndex = datasource.min; + datasource.maxIndex = datasource.max; + } + + function scrollBottom(viewport, count = 1) { + for (var i = 0; i < count; i++) { + viewport.scrollTop(99999); + viewport.trigger('scroll'); + } + } + + function scrollTop(viewport, count = 1) { + for (var i = 0; i < count; i++) { + viewport.scrollTop(0); + viewport.trigger('scroll'); + } + } + + function removeItem(datasource, index) { + if(index >= datasource.min && index <= datasource.max) { + const indexRemoved = datasource.data.indexOf(datasource.data[index - datasource.min]); + if(indexRemoved > -1) { + datasource.data.splice(indexRemoved, 1); + if(index === datasource.min) { + datasource.min++; + } + else { + datasource.max--; + } + } + } + } + + function insertItems(datasource, index, items = []) { + if(index >= datasource.min && index <= datasource.max && items.length) { + const indexToInsert = datasource.data.indexOf(datasource.data[index - datasource.min]); + if(indexToInsert > -1) { + datasource.data.splice(indexToInsert, 0, items); + datasource.max += items.length; + } + } + } + + function checkRow(viewport, row, content, tail = false) { + var children = viewport.children(); + if(tail) { + row = children.length - 1 - row; + } + const rowElement = children[row]; + expect(rowElement.innerHTML).toBe(content); + } + + function checkRowBack(viewport, row, content) { + checkRow(viewport, row, content, true); + } + + it('\nshould set up properly', () => { + runTest(scrollSettings, + () => { + expect(datasource.min).toBe(1); + expect(datasource.max).toBe(itemsCount); + } + ); + }); + + describe('Removing items via indexed-based applyUpdates\n', () => { + + [true, false].forEach(outside => + [true, false].forEach(userIndices => + it('should remove last row' + appendTitle(outside, userIndices), () => + runTest(scrollSettings, + (viewport, scope) => { + userIndices && setUserIndices(); + + scrollBottom(viewport, MAX); + outside && scrollTop(viewport); + const initialBottomHeight = Helper.getBottomPadding(viewport); + + removeItem(datasource, datasource.max); + scope.adapter.applyUpdates(itemsCount, []); + outside && expect(Helper.getBottomPadding(viewport)).toBe(initialBottomHeight - itemHeight); + + !outside && scrollTop(viewport); + scrollBottom(viewport, MAX); + expect(viewport.scrollTop()).toBe(itemsCount * itemHeight - viewportHeight - itemHeight); + checkRowBack(viewport, 1, (itemsCount - 1) + ': item' + (itemsCount - 1)); + } + ) + ) + ) + ); + + [true, false].forEach(outside => + [true, false].forEach(userIndices => + it('should remove last row and then the next after last' + appendTitle(outside, userIndices), () => + runTest(scrollSettings, + (viewport, scope) => { + userIndices && setUserIndices(); + + scrollBottom(viewport, MAX); + outside && scrollTop(viewport); + + const initialBottomHeight = Helper.getBottomPadding(viewport); + removeItem(datasource, datasource.max); + scope.adapter.applyUpdates(itemsCount, []); + removeItem(datasource, datasource.max); + scope.adapter.applyUpdates(itemsCount - 1, []); + outside && expect(Helper.getBottomPadding(viewport)).toBe(initialBottomHeight - itemHeight * 2); + + !outside && scrollTop(viewport); + scrollBottom(viewport, MAX); + expect(viewport.scrollTop()).toBe(itemsCount * itemHeight - viewportHeight - itemHeight * 2); + checkRowBack(viewport, 1, (itemsCount - 2) + ': item' + (itemsCount - 2)); + } + ) + ) + ) + ); + + [true, false].forEach(outside => + [true, false].forEach(userIndices => + it('should remove pre-last row' + appendTitle(outside, userIndices), () => + runTest(scrollSettings, + (viewport, scope) => { + userIndices && setUserIndices(); + + scrollBottom(viewport, MAX); + outside && scrollTop(viewport); + + const initialBottomHeight = Helper.getBottomPadding(viewport); + removeItem(datasource, datasource.max - 1); + scope.adapter.applyUpdates(itemsCount - 1, []); + outside && expect(Helper.getBottomPadding(viewport)).toBe(initialBottomHeight - itemHeight); + + !outside && scrollTop(viewport); + scrollBottom(viewport, MAX); + expect(viewport.scrollTop()).toBe(itemsCount * itemHeight - viewportHeight - itemHeight); + checkRowBack(viewport, 1, (itemsCount - 1) + ': item' + itemsCount); + checkRowBack(viewport, 2, (itemsCount - 2) + ': item' + (itemsCount - 2)); + } + ) + ) + ) + ); + + [true, false].forEach(outside => + [true, false].forEach(userIndices => + it('should remove first row' + appendTitle(outside, userIndices), () => + runTest(scrollSettings, + (viewport, scope) => { + userIndices && setUserIndices(); + + outside && scrollBottom(viewport, MAX); + + const initialTopHeight = Helper.getTopPadding(viewport); + removeItem(datasource, datasource.min); + scope.adapter.applyUpdates(1, []); + outside && expect(Helper.getTopPadding(viewport)).toBe(initialTopHeight - itemHeight); + + !outside && scrollBottom(viewport, MAX); + expect(Helper.getBottomPadding(viewport)).toBe(0); + + scrollTop(viewport); + expect(Helper.getTopPadding(viewport)).toBe(0); + checkRow(viewport, 1, '2: item2'); + } + ) + ) + ) + ); + + [true, false].forEach(outside => + [true, false].forEach(userIndices => + it('should remove first row and then the next after first' + appendTitle(outside, userIndices), () => + runTest(scrollSettings, + (viewport, scope) => { + userIndices && setUserIndices(); + + outside && scrollBottom(viewport, MAX); + + const initialTopHeight = Helper.getTopPadding(viewport); + removeItem(datasource, datasource.min); + scope.adapter.applyUpdates(1, []); + removeItem(datasource, datasource.min); + scope.adapter.applyUpdates(2, []); + outside && expect(Helper.getTopPadding(viewport)).toBe(initialTopHeight - itemHeight * 2); + + !outside && scrollBottom(viewport, MAX); + expect(Helper.getBottomPadding(viewport)).toBe(0); + + scrollTop(viewport); + expect(Helper.getTopPadding(viewport)).toBe(0); + checkRow(viewport, 1, '3: item3'); + } + ) + ) + ) + ); + + [true, false].forEach(outside => + [true, false].forEach(userIndices => + it('should remove second row' + appendTitle(outside, userIndices), () => + runTest(scrollSettings, + (viewport, scope) => { + userIndices && setUserIndices(); + + outside && scrollBottom(viewport, MAX); + + const initialTopHeight = Helper.getTopPadding(viewport); + removeItem(datasource, datasource.min + 1); + scope.adapter.applyUpdates(2, []); + outside && expect(Helper.getTopPadding(viewport)).toBe(initialTopHeight - itemHeight * 1); + + !outside && scrollBottom(viewport, MAX); + expect(Helper.getBottomPadding(viewport)).toBe(0); + + scrollTop(viewport); + expect(Helper.getTopPadding(viewport)).toBe(0); + checkRow(viewport, 1, '1: item1'); + checkRow(viewport, 2, '2: item3'); + } + ) + ) + ) + ); + }); + + describe('Appending inside the buffer\n', () => { + + it('should append 3 rows via index-based applyUpdates', () => { + runTest(Object.assign({}, scrollSettings, { startIndex: 28 }), + (viewport, scope) => { + const newItems = [ + 'item' + (datasource.max + 1), + 'item' + (datasource.max + 2), + 'item' + (datasource.max + 3) + ]; + const oldMax = datasource.max; + const _scrollTop = viewport.scrollTop(); + + insertItems(datasource, datasource.max, newItems); + scope.adapter.applyUpdates(oldMax, ['item' + oldMax, ...newItems]); + + scrollBottom(viewport); + expect(viewport.scrollTop()).toBe(_scrollTop + newItems.length * itemHeight); + + checkRowBack(viewport, 1, (datasource.max - 0) + ': ' + newItems[2]); + checkRowBack(viewport, 2, (datasource.max - 1) + ': ' + newItems[1]); + checkRowBack(viewport, 3, (datasource.max - 2) + ': ' + newItems[0]); + checkRowBack(viewport, 4, oldMax + ': item' + oldMax); + } + ); + }); + + it('should append 3 rows via index-based applyUpdates when min/max indices are set', () => { + runTest(Object.assign({}, scrollSettings, { startIndex: 28 }), + (viewport, scope) => { + const newItems = [ + 'item' + (datasource.max + 1), + 'item' + (datasource.max + 2), + 'item' + (datasource.max + 3) + ]; + const oldMax = datasource.max; + + datasource.minIndex = datasource.min; + datasource.maxIndex = datasource.max; + const _scrollTop = viewport.scrollTop(); + + insertItems(datasource, datasource.max, newItems); + scope.adapter.applyUpdates(oldMax, ['item' + oldMax, ...newItems]); + + scrollBottom(viewport); + expect(viewport.scrollTop()).toBe(_scrollTop + newItems.length * itemHeight); + + checkRowBack(viewport, 1, (datasource.max - 0) + ': ' + newItems[2]); + checkRowBack(viewport, 2, (datasource.max - 1) + ': ' + newItems[1]); + checkRowBack(viewport, 3, (datasource.max - 2) + ': ' + newItems[0]); + checkRowBack(viewport, 4, oldMax + ': item' + oldMax); + } + ); + }); + }); + + + describe('Removing items via indexed-based applyUpdates when neither BOF nor EOF are reached\n', () => { + const _scrollSettings = Object.assign({}, scrollSettings, { startIndex: 12 }); + + [true, false].forEach(userIndices => + it('should remove first buffered row' + appendTitle(true, userIndices), () => + runTest(_scrollSettings, + (viewport, scope) => { + userIndices && setUserIndices(); + + removeItem(datasource, 2); + scope.adapter.applyUpdates(2, []); + + scrollBottom(viewport, MAX); + expect(Helper.getBottomPadding(viewport)).toBe(0); + checkRowBack(viewport, 1, (itemsCount - 1) + ': item' + itemsCount); + + scrollTop(viewport); + expect(Helper.getTopPadding(viewport)).toBe(0); + checkRow(viewport, 1, '1: item1'); + checkRow(viewport, 2, '2: item3'); + } + ) + ) + ); + + [true, false].forEach(userIndices => + it('should remove last buffered row' + appendTitle(true, userIndices), () => + runTest(_scrollSettings, + (viewport, scope) => { + userIndices && setUserIndices(); + + removeItem(datasource, 19); + scope.adapter.applyUpdates(19, []); + + scrollBottom(viewport); + expect(Helper.getBottomPadding(viewport)).toBe(0); + checkRowBack(viewport, 1, (itemsCount - 1) + ': item' + itemsCount); + + scrollTop(viewport); + expect(Helper.getTopPadding(viewport)).toBe(0); + } + ) + ) + ); + + [true, false].forEach(userIndices => + it('should remove absolute first row' + appendTitle(true, userIndices), () => + runTest(_scrollSettings, + (viewport, scope) => { + userIndices && setUserIndices(); + + removeItem(datasource, 1); + scope.adapter.applyUpdates(1, []); + + scrollBottom(viewport, MAX); + expect(Helper.getBottomPadding(viewport)).toBe(0); + checkRowBack(viewport, 1, itemsCount + ': item' + itemsCount); + + scrollTop(viewport); + expect(Helper.getTopPadding(viewport)).toBe(0); + checkRow(viewport, 1, '2: item2'); + checkRow(viewport, 2, '3: item3'); + } + ) + ) + ); + + [true, false].forEach(userIndices => + it('should remove absolute last row' + appendTitle(true, userIndices), () => + runTest(_scrollSettings, + (viewport, scope) => { + userIndices && setUserIndices(); + + removeItem(datasource, itemsCount); + scope.adapter.applyUpdates(itemsCount, []); + + scrollBottom(viewport, MAX); + expect(Helper.getBottomPadding(viewport)).toBe(0); + checkRowBack(viewport, 1, (itemsCount - 1) + ': item' + (itemsCount - 1)); + + scrollTop(viewport); + expect(Helper.getTopPadding(viewport)).toBe(0); + checkRow(viewport, 1, '1: item1'); + checkRow(viewport, 2, '2: item2'); + } + ) + ) + ); + }); + +}); diff --git a/test/config/karma.conf.files.js b/test/config/karma.conf.files.js index 3570fb61..905af763 100644 --- a/test/config/karma.conf.files.js +++ b/test/config/karma.conf.files.js @@ -1,31 +1,31 @@ -const files = [ - 'https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js', - 'https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.js', - 'https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular-mocks.js', - '../misc/test.css', - '../misc/datasources.js', - '../misc/scaffolding*.js', - '../misc/helpers.js', - { - pattern: '../*Spec.js', - watched: false, - served: true, - included: true - } -]; - -module.exports.development = [ - ...files, - '../../src/ui-scroll.js', - '../../src/ui-scroll-grid.js' -]; - -module.exports.production = [ - ...files, - '../../dist/ui-scroll.min.js', - '../../dist/ui-scroll-grid.min.js', - { - pattern: '../../dist/*.js.map', - included: false - } -]; +const files = [ + 'https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js', + 'https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.js', + 'https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular-mocks.js', + '../misc/test.css', + '../misc/datasources.js', + '../misc/scaffolding*.js', + '../misc/helpers.js', + { + pattern: '../*Spec.js', + watched: false, + served: true, + included: true + } +]; + +module.exports.development = [ + ...files, + '../../src/ui-scroll.js', + '../../src/ui-scroll-grid.js' +]; + +module.exports.production = [ + ...files, + '../../dist/ui-scroll.min.js', + '../../dist/ui-scroll-grid.min.js', + { + pattern: '../../dist/*.js.map', + included: false + } +]; diff --git a/test/misc/scaffoldingGrid.js b/test/misc/scaffoldingGrid.js index 5f9a3408..04475533 100644 --- a/test/misc/scaffoldingGrid.js +++ b/test/misc/scaffoldingGrid.js @@ -1,68 +1,68 @@ -/* exported runGridTest */ - -function createGridHtml (settings) { - 'use strict'; - var viewportStyle = ' style="height:' + (settings.viewportHeight || 200) + 'px"'; - var columns = ['col0', 'col1', 'col2', 'col3']; - - var html = - '' + - '' + - ''; - columns.forEach(col => { html += - ''; - }); html += - '' + - '' + - '' + - ''; - if(settings.rowTemplate) { - html += settings.rowTemplate; - } else { - columns.forEach(col => { html += - ''; - }); - } html += - '' + - '' + - '
    ' + col + '
    {{item.' + col + '}}
    '; - return html; -} - -function finalize(scroller, options, scope, $timeout) { - 'use strict'; - options = options || {}; - scroller.remove(); - - if (typeof options.cleanupTest === 'function') { - options.cleanupTest(scroller, scope, $timeout); - } -} - -function runGridTest(scrollSettings, run, options) { - 'use strict'; - options = options || {}; - inject(function($rootScope, $compile, $window, $timeout) { - var scroller = angular.element(createGridHtml(scrollSettings)); - var scope = $rootScope.$new(); - - angular.element(document).find('body').append(scroller); - var head = angular.element(scroller.children()[0]); - var body = angular.element(scroller.children()[1]); - - if (options.scope) { - angular.extend(scope, options.scope); - } - - $compile(scroller)(scope); - - scope.$apply(); - $timeout.flush(); - - try { - run(head, body, scope, $timeout); - } finally { - finalize(scroller, options, scope, $timeout); - } - }); +/* exported runGridTest */ + +function createGridHtml (settings) { + 'use strict'; + var viewportStyle = ' style="height:' + (settings.viewportHeight || 200) + 'px"'; + var columns = ['col0', 'col1', 'col2', 'col3']; + + var html = + '' + + '' + + ''; + columns.forEach(col => { html += + ''; + }); html += + '' + + '' + + '' + + ''; + if(settings.rowTemplate) { + html += settings.rowTemplate; + } else { + columns.forEach(col => { html += + ''; + }); + } html += + '' + + '' + + '
    ' + col + '
    {{item.' + col + '}}
    '; + return html; +} + +function finalize(scroller, options, scope, $timeout) { + 'use strict'; + options = options || {}; + scroller.remove(); + + if (typeof options.cleanupTest === 'function') { + options.cleanupTest(scroller, scope, $timeout); + } +} + +function runGridTest(scrollSettings, run, options) { + 'use strict'; + options = options || {}; + inject(function($rootScope, $compile, $window, $timeout) { + var scroller = angular.element(createGridHtml(scrollSettings)); + var scope = $rootScope.$new(); + + angular.element(document).find('body').append(scroller); + var head = angular.element(scroller.children()[0]); + var body = angular.element(scroller.children()[1]); + + if (options.scope) { + angular.extend(scope, options.scope); + } + + $compile(scroller)(scope); + + scope.$apply(); + $timeout.flush(); + + try { + run(head, body, scope, $timeout); + } finally { + finalize(scroller, options, scope, $timeout); + } + }); } \ No newline at end of file diff --git a/test/misc/test.css b/test/misc/test.css index d7af5c04..70657749 100644 --- a/test/misc/test.css +++ b/test/misc/test.css @@ -1,6 +1,6 @@ -.grid { width: 250px; } -.col0 { width: 40px; } -.col1 { width: 80px; } -.col2 { width: 40px; } -.col3 { width: 50px; } +.grid { width: 250px; } +.col0 { width: 40px; } +.col1 { width: 80px; } +.col2 { width: 40px; } +.col3 { width: 50px; } .item:nth-child(odd) { background-color: #e6e6e6; } \ No newline at end of file