summaryrefslogtreecommitdiffstats
path: root/js/directive/NewsScroll.js
blob: 126c79b11f989c6dc764ffb8574bf7c8118f55e7 (plain)
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
110
111
112
/**
 * ownCloud - 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', ($timeout) => {
    'use strict';

    // autopaging
    let autoPage = (enabled, limit, callback, elem) => {
        if (enabled) {
            let counter = 0;
            for (let item of reverse(elem.find('.feed_item'))) {
                item = $(item);


                // 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.position().top < 0) {
                    callback();
                    break;
                }

                counter += 1;
            }
        }
    };

    // mark read
    let markRead = (enabled, callback, elem) => {
        if (enabled) {
            let ids = [];

            for (let item of elem.find('.feed_item:not(.read)')) {
                item = $(item);

                if (item.position().top <= -50) {
                    ids.push(parseInt(item.data('id'), 10));
                } else {
                    break;
                }
            }

            callback(ids);
        }
    };

    return {
        restrict: 'A',
        scope: {
            'newsScrollAutoPage': '&',
            'newsScrollMarkRead': '&',
            'newsScrollEnabledMarkRead': '=',
            'newsScrollEnableAutoPage': '=',
            'newsScrollMarkReadTimeout': '@',  // optional, defaults to 1 second
            'newsScrollTimeout': '@',  // optional, defaults to 1 second
            'newsScrollAutoPageWhenLeft': '@'  // optional, defaults to 50
        },
        link: (scope, elem) => {
            let allowScroll = true;

            scope.newsScrollTimeout = scope.newsScrollTimeout || 1;
            scope.newsScrollMarkReadTimeout =
                scope.newsScrollMarkReadTimeout || 1;
            scope.newsScrollAutoPageWhenLeft =
                scope.newsScrollAutoPageWhenLeft || 50;

            let scrollHandler = () => {
                // allow only one scroll event to trigger at once
                if (allowScroll) {
                    allowScroll = false;

                    $timeout(() => {
                        allowScroll = true;
                    }, scope.newsScrollTimeout*1000);

                    autoPage(scope.newsScrollEnableAutoPage,
                             scope.newsScrollAutoPageWhenLeft,
                             scope.newsScrollAutoPage,
                             elem);

                    // allow user to undo accidental scroll
                    $timeout(() => {
                        markRead(scope.newsScrollEnabledMarkRead,
                                 scope.newsScrollMarkRead,
                                 elem);
                    }, scope.newsScrollMarkReadTimeout*1000);
                }

            };

            elem.on('scroll', scrollHandler);

            // remove scroll handler if element is destroyed
            scope.$on('$destroy', () => {
                elem.off('scroll', scrollHandler);
            });
        }
    };
});