Skip to content

Commit f005df4

Browse files
authored
Merge pull request #145 from angular-ui/bottomVisible
Bottom Visible
2 parents 7c55ca1 + a3d44e4 commit f005df4

File tree

11 files changed

+1032
-854
lines changed

11 files changed

+1032
-854
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,9 @@ The adapter object is an internal object created for every instance of the scrol
218218
Adapter object implements the following properties:
219219

220220
* `isLoading` - a boolean value (read only) indicating whether there are any pending load requests.
221-
* `topVisible` - a read only reference to the item currently in the topmost visible position.
222-
* `topVisibleElement` - a read only reference to the DOM element currently in the topmost visible position.
223-
* `topVisibleScope` - a read only reference to the scope created for the item currently in the topmost visible position.
221+
* `topVisible`/`bottomVisible` - a read only reference to the item currently in the topmost/bottommost visible position.
222+
* `topVisibleElement`/`bottomVisibleElement` - a read only reference to the DOM element currently in the topmost/bottommost visible position.
223+
* `topVisibleScope`/`bottomVisibleScope` - a read only reference to the scope created for the item currently in the topmost/bottommost visible position.
224224
* `disabled` - setting `disabled` to `true` disables scroller's scroll/resize events handlers. This can be useful if you have multiple scrollers within the same scrollViewport and you want to prevent some of them from responding to the events.
225225

226226
Adapter object implements the following methods
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Bottom visible (Adapter)</title>
6+
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.js"></script>
7+
<script src="../../dist/ui-scroll.js"></script>
8+
<script src="bottomVisibleAdapter.js"></script>
9+
<link rel="stylesheet" href="../css/style.css" type="text/css"/>
10+
</head>
11+
<body ng-app="application" ng-controller="mainController">
12+
13+
<div class="cont cont-global">
14+
15+
<a class="back" href="../index.html">browse other examples</a>
16+
17+
<h1 class="page-header page-header-exapmle">Bottom visible (Adapter)</h1>
18+
19+
<div class="description">
20+
The Adapter implements bottomVisible property which is a reference to the item currently in the very bottom visible position.
21+
22+
<div class="code">
23+
<pre>&lt;li ui-scroll="item in datasource" adapter="adapter"&gt;*{{item}<!---->}*&lt;/li&gt;</pre>
24+
</div>
25+
26+
<div class="code">
27+
<pre>bottom visible: {{adapter.bottomVisible}<!---->}</pre>
28+
</div>
29+
</div>
30+
31+
<div class="info">
32+
<div class="info-item"><span class="info-item-label">bottom visible:</span> {{adapter.bottomVisible}}</div>
33+
</div>
34+
35+
<div class="viewport" id="viewport-listScroller" ui-scroll-viewport>
36+
<div class="item" ui-scroll="item in datasource" adapter="adapter">*{{item}}*</div>
37+
</div>
38+
39+
</div>
40+
41+
</body>
42+
</html>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
angular.module('application', ['ui.scroll'])
2+
.controller('mainController', [
3+
'$scope', '$log', '$timeout', function ($scope, console, $timeout) {
4+
5+
$scope.adapter = {};
6+
7+
$scope.datasource = {};
8+
9+
$scope.datasource.get = function (index, count, success) {
10+
$timeout(function () {
11+
var result = [];
12+
for (var i = index; i <= index + count - 1; i++) {
13+
result.push("item #" + i);
14+
}
15+
success(result);
16+
}, 100);
17+
};
18+
19+
}
20+
]);

demo/chat/chat.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ <h1 class="page-header page-header-exapmle">Chat demo</h1>
2323
<div> - special Server service to emulate the remote</div>
2424
</div>
2525

26-
<br/>
26+
<div class="info">
27+
<div>{{adapter.topVisible.title}} -- top visible item</div>
28+
<div>{{adapter.bottomVisible.title}} -- bottom visible item</div>
29+
</div>
2730

2831
<ul class="chat" ui-scroll-viewport>
2932
<li class="item" ui-scroll="item in datasource" adapter="adapter">

demo/index.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,15 @@ <h1 class="page-header">Scroller Examples</h1>
5555
Top visible
5656
</a>
5757
&nbsp; / &nbsp;
58-
<a href="topVisible/topVisible.html">
58+
<a href="topVisible/topVisibleAdapter.html">
5959
Top visible (Adapter)
6060
</a>
6161
</li>
62+
<li>
63+
<a href="bottomVisible/bottomVisibleAdapter.html">
64+
Bottom visible (Adapter)
65+
</a>
66+
</li>
6267
<li>
6368
<a href="reload100/reload100.html">
6469
Reload datasource to specified index

dist/ui-scroll.js

Lines changed: 32 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/ui-scroll.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/ui-scroll.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/ui-scroll.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/modules/adapter.js

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class Adapter {
7575
}
7676

7777
// these read-only props will be accessible out of ui-scroll via user defined adapter
78-
const publicProps = ['isLoading', 'topVisible', 'topVisibleElement', 'topVisibleScope'];
78+
const publicProps = ['isLoading', 'topVisible', 'topVisibleElement', 'topVisibleScope', 'bottomVisible', 'bottomVisibleElement', 'bottomVisibleScope'];
7979
for (let i = publicProps.length - 1; i >= 0; i--) {
8080
let property, attr = $attr[publicProps[i]];
8181
Object.defineProperty(this, publicProps[i], {
@@ -147,24 +147,37 @@ class Adapter {
147147
}
148148

149149
calculateProperties() {
150-
let item, itemHeight, itemTop, isNewRow, rowTop = null;
151-
let topHeight = 0;
152-
for (let i = 0; i < this.buffer.length; i++) {
153-
item = this.buffer[i];
154-
itemTop = item.element.offset().top;
155-
isNewRow = rowTop !== itemTop;
156-
rowTop = itemTop;
157-
if (isNewRow) {
158-
itemHeight = item.element.outerHeight(true);
159-
}
160-
if (isNewRow && (this.viewport.topDataPos() + topHeight + itemHeight <= this.viewport.topVisiblePos())) {
161-
topHeight += itemHeight;
162-
} else {
163-
if (isNewRow) {
150+
let rowTop = null, topHeight = 0;
151+
let topDone = false, bottomDone = false;
152+
const length = this.buffer.length;
153+
154+
for (let i = 0; i < length; i++) {
155+
const item = this.buffer[i];
156+
const itemTop = item.element.offset().top;
157+
158+
if (rowTop !== itemTop) { // a new row condition
159+
const itemHeight = item.element.outerHeight(true);
160+
const top = this.viewport.topDataPos() + topHeight + itemHeight;
161+
162+
if (!topDone && top > this.viewport.topVisiblePos()) {
163+
topDone = true;
164164
this['topVisible'] = item.item;
165165
this['topVisibleElement'] = item.element;
166166
this['topVisibleScope'] = item.scope;
167167
}
168+
169+
if (!bottomDone && (top >= this.viewport.bottomVisiblePos() || (i === length - 1 && this.isEOF()))) {
170+
bottomDone = true;
171+
this['bottomVisible'] = item.item;
172+
this['bottomVisibleElement'] = item.element;
173+
this['bottomVisibleScope'] = item.scope;
174+
}
175+
topHeight += itemHeight;
176+
}
177+
178+
rowTop = itemTop;
179+
180+
if (topDone && bottomDone) {
168181
break;
169182
}
170183
}

0 commit comments

Comments
 (0)