summaryrefslogtreecommitdiffstats
path: root/js/directive/NewsScroll.js
blob: 26e799da60925ca013b84483230c629d19cf8a52 (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
113
114
/**
 * 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', function ($timeout) {
    'use strict';

    // autopaging
    var autoPage = function (enabled, limit, elem, scope) {
        if (enabled) {
            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.position().top < 0) {
                    scope.$apply(scope.newsScrollAutoPage);
                    break;
                }

                counter += 1;
            }
        }
    };

    // mark read
    var markRead = function (enabled, elem, scope) {
        if (enabled) {
            var ids = [];
            var articles = elem.find('.item:not(.read)');

            articles.each(function(index, article) {
                var item = $(article);

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

            scope.itemIds = ids;
            scope.$apply(scope.newsScrollMarkRead);
        }
    };

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

            var scrollTimeout = scope.newsScrollTimeout || 1;
            var markReadTimeout = scope.newsScrollMarkReadTimeout || 1;
            var autoPageLimit = scope.newsScrollAutoPageWhenLeft || 50;

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

                    $timeout(function () {
                        allowScroll = true;
                    }, scrollTimeout*1000);

                    autoPage(scope.newsScrollEnabledAutoPage,
                             autoPageLimit,
                             elem,
                             scope);

                    // allow user to undo accidental scroll
                    $timeout(function () {
                        markRead(scope.newsScrollEnabledMarkRead,
                                 elem,
                                 scope);
                    }, markReadTimeout*1000);
                }

            };

            elem.on('scroll', scrollHandler);

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