1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
/**
* Nextcloud - News
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Bernhard Posselt <dev@bernhard-posselt.com>
* @copyright Bernhard Posselt 2014
*/
app.directive('newsScroll', function ($timeout, ITEM_AUTO_PAGE_SIZE,
MARK_READ_TIMEOUT, SCROLL_TIMEOUT) {
'use strict';
var timer;
// autopaging
var autoPage = function (limit, elem, scope) {
var counter = 0;
var articles = elem.find('.item');
for (var i = articles.length - 1; i >= 0; i -= 1) {
var item = $(articles[i]);
// if the counter is higher than the size it means
// that it didnt break to auto page yet and that
// there are more items, so break
if (counter >= limit) {
break;
}
// this is only reached when the item is not is
// below the top and we didnt hit the factor yet so
// autopage and break
if (item[0].getBoundingClientRect().top < 0) {
scope.$apply(scope.newsScrollAutoPage);
break;
}
counter += 1;
}
};
// mark read
var markRead = function (enabled, elem, scope) {
if (enabled) {
var ids = [];
var articles = elem.querySelectorAll('.item:not(.read)');
articles.forEach(function(article) {
var distTop = article.getBoundingClientRect().top;
var scrollTop = $(document).scrollTop();
if (distTop - scrollTop <= -10) {
ids.push(parseInt(article.dataset.id, 10));
} else {
return false;
}
});
scope.itemIds = ids;
scope.$apply(scope.newsScrollMarkRead);
}
};
return {
restrict: 'A',
scope: {
'newsScroll': '@',
'newsScrollAutoPage': '&',
'newsScrollMarkRead': '&',
'newsScrollEnabledMarkRead': '=',
},
link: function (scope, elem) {
var allowScroll = true;
var scrollHandler = function () {
// allow only one scroll event to trigger every 300ms
if (allowScroll) {
allowScroll = false;
$timeout(function () {
allowScroll = true;
}, SCROLL_TIMEOUT * 1000);
autoPage(ITEM_AUTO_PAGE_SIZE, elem, scope);
// dont stack mark read requests
if (timer) {
$timeout.cancel(timer);
}
// allow user to undo accidental scroll
timer = $timeout(function () {
markRead(scope.newsScrollEnabledMarkRead,
elem[0],
scope);
timer = undefined;
}, MARK_READ_TIMEOUT*1000);
}
};
$(document).on('scroll', scrollHandler);
// remove scroll handler if element is destroyed
scope.$on('$destroy', function () {
$(document).off('scroll', scrollHandler);
});
}
};
});
|