Simple RSS Reader inspired by Gxxgle Reader
修订版 | 5d6d1591ce2fca6012f8c45c107a283747d3fc83 (tree) |
---|---|
时间 | 2013-07-15 18:21:48 |
作者 | hylom <hylom@hylo...> |
Commiter | hylom |
implement paging...
@@ -4,6 +4,40 @@ | ||
4 | 4 | (function () { |
5 | 5 | // private functions |
6 | 6 | |
7 | + function updatePager(total, skip, count) { | |
8 | + var totalPage = Math.floor((total - 1) / count + 1); | |
9 | + var currentPage = (skip == 0) ? 0 : (skip - 1) / count + 1; | |
10 | + var elem = ''; | |
11 | + | |
12 | + console.log(skip + ',' + count + '/' + total); | |
13 | + console.log(currentPage + '/' + totalPage); | |
14 | + | |
15 | + var paging = $('#page-navigation'); | |
16 | + paging.empty(); | |
17 | + | |
18 | + var pagingFirst = '<li id="paging-first"><a href="#">«</a></li>'; | |
19 | + paging.append(pagingFirst); | |
20 | + | |
21 | + if (currentPage > 0) { | |
22 | + elem = '<li><a href="#">' | |
23 | + + currentPage + '</a></li>'; | |
24 | + paging.append(elem); | |
25 | + } | |
26 | + | |
27 | + elem = '<li class="active"><a href="#">' + (currentPage + 1) | |
28 | + + '</a></li>'; | |
29 | + paging.append(elem); | |
30 | + | |
31 | + if (currentPage != totalPage) { | |
32 | + elem = '<li><a href="#">' | |
33 | + + (currentPage + 2) + '</a></li>'; | |
34 | + paging.append(elem); | |
35 | + } | |
36 | + | |
37 | + var pagingLast = $('<li id="paging-last"><a href="#">»</a></li>'); | |
38 | + paging.append(pagingLast); | |
39 | + } | |
40 | + | |
7 | 41 | function updateContentsPane(data) { |
8 | 42 | var pane = $('#contentsPane'); |
9 | 43 | pane.empty(); |
@@ -22,43 +56,54 @@ | ||
22 | 56 | ; |
23 | 57 | var tableRows = Hogan.compile(tmpl); |
24 | 58 | |
25 | - for (var i = 0; i < data.length; i++) { | |
26 | - var item = data[i]; | |
59 | + var contents = data.contents; | |
60 | + for (var i = 0; i < contents.length; i++) { | |
61 | + var item = contents[i]; | |
27 | 62 | var elem = tableRows.render(item); |
28 | 63 | pane.append(elem); |
29 | 64 | } |
65 | + pane.attr('skip', data.skip); | |
66 | + pane.attr('count', data.count); | |
67 | + updatePager(data.total, data.skip, data.count); | |
68 | + } | |
69 | + | |
70 | + function showFeed(feedId, skip, count) { | |
71 | + skip = skip || 0; | |
72 | + count = count || 20; | |
73 | + feedId = Number(feedId); | |
74 | + if (isNaN(feedId)) { | |
75 | + return | |
76 | + } | |
77 | + var url = '/api/feed/' + feedId + '/contents' | |
78 | + + '?skip=' + skip + '&count=' + count; | |
79 | + $.getJSON(url, updateContentsPane); | |
30 | 80 | } |
31 | 81 | |
32 | - function loadFeed(event) { | |
82 | + // Load feed | |
83 | + $(document).on('click', ".feedItem", function (ev) { | |
33 | 84 | var feedId = $(event.target).attr('feed-id'); |
34 | 85 | var feedTitle = $(event.target).text(); |
35 | 86 | if (feedId !== undefined) { |
36 | - var url = '/api/feed/' + feedId + '/contents'; | |
37 | - $.getJSON(url, updateContentsPane); | |
87 | + showFeed(feedId); | |
38 | 88 | } |
39 | 89 | $('#feedTitle').text(feedTitle); |
40 | 90 | var pane = $('#contentsPane'); |
41 | 91 | pane.empty(); |
42 | 92 | return false; |
43 | - } | |
93 | + }); | |
44 | 94 | |
45 | - function toggleContentBody(event) { | |
95 | + // Toggle feed contents | |
96 | + $(document).on('click', ".contentTitleString", function (ev) { | |
46 | 97 | var contentId = $(event.target).attr('cid'); |
47 | - console.log('click header ' + contentId); | |
48 | 98 | if (contentId !== undefined) { |
49 | 99 | $('#cbody' + contentId).toggle(); |
50 | 100 | } |
51 | 101 | return false; |
52 | - } | |
53 | - | |
54 | - $(document).on('click', ".feedItem", loadFeed); | |
55 | - $(document).on('click', ".contentTitleString", toggleContentBody); | |
102 | + }); | |
56 | 103 | |
104 | + // When page loaded, show 'All Feeds' | |
57 | 105 | $(document).ready(function () { |
58 | - var feedId = 0; | |
59 | - var url = '/api/feed/' + feedId + '/contents'; | |
60 | - $.getJSON(url, updateContentsPane); | |
106 | + showFeed(0); | |
61 | 107 | }); |
62 | -}).apply(); | |
63 | - | |
64 | 108 | |
109 | +}).apply(); |
@@ -87,14 +87,25 @@ exports.feedContent = function (req, res) { | ||
87 | 87 | }; |
88 | 88 | |
89 | 89 | exports.feedContents = function (req, res) { |
90 | +/* | |
91 | + returns json: | |
92 | + { | |
93 | + totalCount: Number, | |
94 | + skip: Number, | |
95 | + itemCount: Number, | |
96 | + contents: [ | |
97 | + ] | |
98 | +*/ | |
90 | 99 | var feedId = req.params.fid; |
91 | 100 | var connection = mysql.createConnection(config.mysql); |
92 | - var skip = req.query.skip || 0; | |
93 | - var count = req.query.count || 20; | |
101 | + var skip = Number(req.query.skip) || 0; | |
102 | + var count = Number(req.query.count) || 20; | |
94 | 103 | |
95 | 104 | if (feedId === '0') { |
96 | 105 | // show all feeds |
97 | 106 | // TODO: if use multiple users, need checking subscribing feeds |
107 | + var sqlCount = 'SELECT COUNT(content_id) FROM feed_contents;'; | |
108 | + var paramsCount = []; | |
98 | 109 | var sql = 'SELECT content_id, feed_id, title, url, body, timestamp' |
99 | 110 | + ' FROM feed_contents' |
100 | 111 | + ' ORDER BY timestamp DESC' |
@@ -102,6 +113,9 @@ exports.feedContents = function (req, res) { | ||
102 | 113 | + ';'; |
103 | 114 | var params = [skip, count]; |
104 | 115 | } else { |
116 | + var sqlCount = 'SELECT COUNT(content_id) FROM feed_contents' | |
117 | + + ' WHERE feed_id = ?;' | |
118 | + var paramsCount = [feedId]; | |
105 | 119 | var sql = 'SELECT content_id, feed_id, title, url, body, timestamp' |
106 | 120 | + ' FROM feed_contents' |
107 | 121 | + ' WHERE feed_id = ?' |
@@ -112,8 +126,7 @@ exports.feedContents = function (req, res) { | ||
112 | 126 | } |
113 | 127 | |
114 | 128 | connection.connect(); |
115 | - connection.query(sql, params, function (err, rows, fields) { | |
116 | - connection.end(); | |
129 | + connection.query(sqlCount, paramsCount, function (err, rows, fields) { | |
117 | 130 | if (err) { |
118 | 131 | logger.debug("query error at index.feedContents: " + util.inspect(err)); |
119 | 132 | res.send(500); |
@@ -123,9 +136,28 @@ exports.feedContents = function (req, res) { | ||
123 | 136 | res.send(404); |
124 | 137 | return; |
125 | 138 | } |
126 | - for (var i = 0; i < rows.length; i++) { | |
127 | - rows[i].formatedTimestamp = formatTimestamp(rows[i].timestamp); | |
128 | - } | |
129 | - res.json(rows); | |
139 | + var totalCount = rows[0]['COUNT(content_id)']; | |
140 | + connection.query(sql, params, function (err, rows, fields) { | |
141 | + connection.end(); | |
142 | + if (err) { | |
143 | + logger.debug("query error at index.feedContents: " + util.inspect(err)); | |
144 | + res.send(500); | |
145 | + return; | |
146 | + } | |
147 | + if (rows.length == 0) { | |
148 | + res.send(404); | |
149 | + return; | |
150 | + } | |
151 | + for (var i = 0; i < rows.length; i++) { | |
152 | + rows[i].formatedTimestamp = formatTimestamp(rows[i].timestamp); | |
153 | + } | |
154 | + var result = { | |
155 | + "total": totalCount, | |
156 | + "skip": skip, | |
157 | + "count": count, | |
158 | + "contents": rows | |
159 | + } | |
160 | + res.json(result); | |
161 | + }); | |
130 | 162 | }); |
131 | 163 | }; |
@@ -15,6 +15,6 @@ block content | ||
15 | 15 | table.table#contentsPane |
16 | 16 | .pagination.pagination-centered |
17 | 17 | ul#page-navigation |
18 | - li.disabled: a(href='#') Prev | |
18 | + li#paging-first.disabled: a(href='#') « | |
19 | 19 | li.active: a(href='#') 1 |
20 | - li.disabled: a(href='#') Next | |
20 | + li#paging-last.disabled: a(href='#') » |