summaryrefslogtreecommitdiffstats
path: root/js/directive/NewsScroll.js
blob: 5972cce672ef87254f011421d25d3e4ab66f02bc (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
/**
 * 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';

    return {
        restrict: 'A',
        scope: {
            'newsScrollAutoPage': '&',
            'newsScrollMarkRead': '&',
            'newsScrollDisabledMarkRead': '=',
            'newsScrollDisabledAutoPage': '=',
            'newsScrollMarkReadTimeout': '@',  // optional, defaults to 1 second
            'newsScrollTimeout': '@',  // optional, defaults to 1 second
            'newsScrollAutoPageWhenLeft': '@',  // optional, defaults to 50
            'newsScrollItemsSelector': '@'  // optional, defaults to .items
        },
        link: (scope, elem) => {
            let scrolling = false;

            scope.newsScrollTimeout = scope.newsScrollTimeout || 1;
            scope.newsScrollMarkReadTimeout =
                scope.newsScrollMarkReadTimeout || 1;
            scope.newsScrollAutoPageWhenLeft =
                scope.newsScrollAutoPageWhenLeft || 50;
            scope.newsScrollItemsSelector =
                scope.newsScrollItemsSelector || '.items';


            elem.on('scroll', () => {

                // only allow one scrolling event to trigger
                if (!scrolling) {
                    scrolling = true;

                    $timeout(() => {
                        scrolling = false;
                    }, scope.newsScrollTimeout*1000);


                    let items = $(scope.newsScrollItemsSelector);

                    // autopaging
                    if (!scope.newsScrollDisabledAutoPage) {
                        let counter = 0;
                        for (let item of reverse(items.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 >= scope.newsScrollAutoPageWhenLeft) {
                                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) {
                                scope.newsScrollAutoPage();
                                break;
                            }

                            counter += 1;
                        }
                    }

                    // mark read
                    let markRead = () => {
                        if (!scope.newsScrollDisabledMarkRead) {
                            let ids = [];
                            let unread = items.find('.feed_item:not(.read)');

                            for (let item of unread) {
                                item = $(item);

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

                            scope.newsScrollMarkRead(ids);
                        }
                    };

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

            });

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