]> git.wh0rd.org - tt-rss.git/blame - js/FeedTree.js
fix af_zz_vidmute for new chrome breaking muting via setAttribute
[tt-rss.git] / js / FeedTree.js
CommitLineData
a3e2f1a9 1define(["dojo/_base/declare", "dojo/dom-construct", "dijit/Tree", "dijit/Menu"], function (declare, domConstruct) {
452e75cc 2
d39a2f80
AD
3 return declare("fox.FeedTree", dijit.Tree, {
4 _onKeyPress: function(/* Event */ e) {
5 return; // Stop dijit.Tree from interpreting keystrokes
6 },
7 _createTreeNode: function(args) {
8 var tnode = new dijit._TreeNode(args);
05f224a3 9
6887a0f5
AK
10 var icon = dojo.doc.createElement('img');
11 if (args.item.icon && args.item.icon[0]) {
12 icon.src = args.item.icon[0];
13 } else {
14 icon.src = 'images/blank_icon.gif';
15 }
16 icon.className = 'tinyFeedIcon';
17 domConstruct.place(icon, tnode.iconNode, 'only');
997429c2 18
d39a2f80
AD
19 var id = args.item.id[0];
20 var bare_id = parseInt(id.substr(id.indexOf(':')+1));
9fe80bcd 21
d39a2f80
AD
22 if (bare_id < _label_base_index) {
23 var span = dojo.doc.createElement('span');
24 var fg_color = args.item.fg_color[0];
25 var bg_color = args.item.bg_color[0];
9fe80bcd 26
d39a2f80
AD
27 span.innerHTML = "&alpha;";
28 span.className = 'labelColorIndicator';
29 span.setStyle({
30 color: fg_color,
31 backgroundColor: bg_color});
9fe80bcd 32
6887a0f5 33 domConstruct.place(span, tnode.iconNode, 'only');
d39a2f80 34 }
997429c2 35
d39a2f80
AD
36 if (id.match("FEED:")) {
37 var menu = new dijit.Menu();
38 menu.row_id = bare_id;
e3d2c029 39
10afc7c6 40 menu.addChild(new dijit.MenuItem({
d39a2f80 41 label: __("Mark as read"),
10afc7c6 42 onClick: function() {
d39a2f80 43 catchupFeed(this.getParent().row_id);
10afc7c6
AD
44 }}));
45
d39a2f80
AD
46 if (bare_id > 0) {
47 menu.addChild(new dijit.MenuItem({
48 label: __("Edit feed"),
49 onClick: function() {
50 editFeed(this.getParent().row_id, false);
51 }}));
52
53 /* menu.addChild(new dijit.MenuItem({
54 label: __("Update feed"),
55 onClick: function() {
56 heduleFeedUpdate(this.getParent().row_id, false);
57 }})); */
58 }
59
60 menu.bindDomNode(tnode.domNode);
61 tnode._menu = menu;
62 }
63
64 if (id.match("CAT:") && bare_id >= 0) {
65 var menu = new dijit.Menu();
66 menu.row_id = bare_id;
67
acfee412 68 menu.addChild(new dijit.MenuItem({
f04b12d8 69 label: __("Mark as read"),
acfee412 70 onClick: function() {
f04b12d8 71 catchupFeed(this.getParent().row_id, true);
acfee412
AD
72 }}));
73
d39a2f80 74 menu.addChild(new dijit.MenuItem({
f04b12d8 75 label: __("(Un)collapse"),
10afc7c6 76 onClick: function() {
f04b12d8 77 dijit.byId("feedTree").collapseCat(this.getParent().row_id);
d39a2f80
AD
78 }}));
79
80 menu.bindDomNode(tnode.domNode);
81 tnode._menu = menu;
10afc7c6 82 }
997429c2 83
d39a2f80
AD
84 if (id.match("CAT:")) {
85 loading = dojo.doc.createElement('img');
86 loading.className = 'loadingNode';
87 loading.src = 'images/blank_icon.gif';
9f539be3 88 domConstruct.place(loading, tnode.labelNode, 'after');
d39a2f80
AD
89 tnode.loadingNode = loading;
90 }
c594eca0 91
d39a2f80
AD
92 if (id.match("CAT:") && bare_id == -1) {
93 var menu = new dijit.Menu();
94 menu.row_id = bare_id;
c594eca0 95
d39a2f80
AD
96 menu.addChild(new dijit.MenuItem({
97 label: __("Mark all feeds as read"),
98 onClick: function() {
99 catchupAllFeeds();
100 }}));
101
102 menu.bindDomNode(tnode.domNode);
103 tnode._menu = menu;
8d4b5b46 104 }
d39a2f80
AD
105
106 ctr = dojo.doc.createElement('span');
107 ctr.className = 'counterNode';
108 ctr.innerHTML = args.item.unread > 0 ? args.item.unread : args.item.auxcounter;
109
110 //args.item.unread > 0 ? ctr.addClassName("unread") : ctr.removeClassName("unread");
111
112 args.item.unread > 0 || args.item.auxcounter > 0 ? Element.show(ctr) : Element.hide(ctr);
113
114 args.item.unread == 0 && args.item.auxcounter > 0 ? ctr.addClassName("aux") : ctr.removeClassName("aux");
115
9f539be3 116 domConstruct.place(ctr, tnode.rowNode, 'first');
d39a2f80
AD
117 tnode.counterNode = ctr;
118
119 //tnode.labelNode.innerHTML = args.label;
120 return tnode;
121 },
122 postCreate: function() {
123 this.connect(this.model, "onChange", "updateCounter");
124 this.connect(this, "_expandNode", function() {
125 this.hideRead(getInitParam("hide_read_feeds"), getInitParam("hide_read_shows_special"));
126 });
127
128 this.inherited(arguments);
129 },
130 updateCounter: function (item) {
131 var tree = this;
132
133 //console.log("updateCounter: " + item.id[0] + " " + item.unread + " " + tree);
134
135 var node = tree._itemNodesMap[item.id];
136
137 if (node) {
138 node = node[0];
139
140 if (node.counterNode) {
141 ctr = node.counterNode;
142 ctr.innerHTML = item.unread > 0 ? item.unread : item.auxcounter;
143 item.unread > 0 || item.auxcounter > 0 ?
70c5b2bf
AD
144 item.unread > 0 ?
145 Effect.Appear(ctr, {duration : 0.3,
146 queue: { position: 'end', scope: 'CAPPEAR-' + item.id, limit: 1 }}) :
147 Element.show(ctr) :
d39a2f80
AD
148 Element.hide(ctr);
149
150 item.unread == 0 && item.auxcounter > 0 ? ctr.addClassName("aux") : ctr.removeClassName("aux");
151
2196b517
AD
152 }
153 }
d39a2f80
AD
154
155 },
156 getTooltip: function (item) {
157 if (item.updated)
158 return item.updated;
159 else
160 return "";
161 },
162 getIconClass: function (item, opened) {
163 return (!item || this.model.mayHaveChildren(item)) ? (opened ? "dijitFolderOpened" : "dijitFolderClosed") : "feedIcon";
164 },
165 getLabelClass: function (item, opened) {
166 return (item.unread == 0) ? "dijitTreeLabel" : "dijitTreeLabel Unread";
167 },
168 getRowClass: function (item, opened) {
169 var rc = (!item.error || item.error == '') ? "dijitTreeRow" :
170 "dijitTreeRow Error";
171
172 if (item.unread > 0) rc += " Unread";
f6269d1b 173 if (item.updates_disabled > 0) rc += " UpdatesDisabled";
d39a2f80
AD
174
175 return rc;
176 },
177 getLabel: function(item) {
178 var name = String(item.name);
179
180 /* Horrible */
181 name = name.replace(/&quot;/g, "\"");
182 name = name.replace(/&amp;/g, "&");
183 name = name.replace(/&mdash;/g, "-");
184 name = name.replace(/&lt;/g, "<");
185 name = name.replace(/&gt;/g, ">");
186
187 /* var label;
188
189 if (item.unread > 0) {
190 label = name + " (" + item.unread + ")";
191 } else {
192 label = name;
193 } */
194
195 return name;
196 },
197 expandParentNodes: function(feed, is_cat, list) {
198 try {
199 for (var i = 0; i < list.length; i++) {
200 var id = String(list[i].id);
201 var item = this._itemNodesMap[id];
202
203 if (item) {
204 item = item[0];
205 this._expandNode(item);
2196b517
AD
206 }
207 }
d39a2f80 208 } catch (e) {
1bfe1d7b 209 exception_error(e);
d39a2f80
AD
210 }
211 },
212 findNodeParentsAndExpandThem: function(feed, is_cat, root, parents) {
213 // expands all parents of specified feed to properly mark it as active
214 // my fav thing about frameworks is doing everything myself
215 try {
216 var test_id = is_cat ? 'CAT:' + feed : 'FEED:' + feed;
217
218 if (!root) {
219 if (!this.model || !this.model.store) return false;
2196b517 220
d39a2f80
AD
221 var items = this.model.store._arrayOfTopLevelItems;
222
223 for (var i = 0; i < items.length; i++) {
224 if (String(items[i].id) == test_id) {
2196b517
AD
225 this.expandParentNodes(feed, is_cat, parents);
226 } else {
d39a2f80 227 this.findNodeParentsAndExpandThem(feed, is_cat, items[i], []);
2196b517
AD
228 }
229 }
230 } else {
d39a2f80
AD
231 if (root.items) {
232 parents.push(root);
233
234 for (var i = 0; i < root.items.length; i++) {
235 if (String(root.items[i].id) == test_id) {
236 this.expandParentNodes(feed, is_cat, parents);
237 } else {
238 this.findNodeParentsAndExpandThem(feed, is_cat, root.items[i], parents.slice(0));
239 }
240 }
241 } else {
242 if (String(root.id) == test_id) {
243 this.expandParentNodes(feed, is_cat, parents.slice(0));
244 }
2196b517
AD
245 }
246 }
d39a2f80 247 } catch (e) {
1bfe1d7b 248 exception_error(e);
2196b517 249 }
d39a2f80
AD
250 },
251 selectFeed: function(feed, is_cat) {
252 this.findNodeParentsAndExpandThem(feed, is_cat, false, false);
452e75cc 253
d39a2f80
AD
254 if (is_cat)
255 treeNode = this._itemNodesMap['CAT:' + feed];
256 else
257 treeNode = this._itemNodesMap['FEED:' + feed];
258
259 if (treeNode) {
260 treeNode = treeNode[0];
261 if (!is_cat) this._expandNode(treeNode);
262 this.set("selectedNodes", [treeNode]);
fa1be041 263 this.focusNode(treeNode);
7590f039
AD
264
265 // focus headlines to route key events there
266 setTimeout(function() {
267 $("headlines-frame").focus();
268 }, 0);
d39a2f80
AD
269 }
270 },
271 setFeedIcon: function(feed, is_cat, src) {
272 if (is_cat)
273 treeNode = this._itemNodesMap['CAT:' + feed];
274 else
275 treeNode = this._itemNodesMap['FEED:' + feed];
452e75cc 276
d39a2f80
AD
277 if (treeNode) {
278 treeNode = treeNode[0];
6887a0f5
AK
279 var icon = dojo.doc.createElement('img');
280 icon.src = src;
281 icon.className = 'tinyFeedIcon';
282 domConstruct.place(icon, treeNode.iconNode, 'only');
d39a2f80
AD
283 return true;
284 }
285 return false;
286 },
287 setFeedExpandoIcon: function(feed, is_cat, src) {
288 if (is_cat)
289 treeNode = this._itemNodesMap['CAT:' + feed];
290 else
291 treeNode = this._itemNodesMap['FEED:' + feed];
452e75cc 292
d39a2f80
AD
293 if (treeNode) {
294 treeNode = treeNode[0];
295 if (treeNode.loadingNode) {
296 treeNode.loadingNode.src = src;
297 return true;
298 } else {
6887a0f5
AK
299 var icon = dojo.doc.createElement('img');
300 icon.src = src;
b7d63a58 301 icon.className = 'loadingExpando';
6887a0f5 302 domConstruct.place(icon, treeNode.expandoNode, 'only');
d39a2f80
AD
303 return true;
304 }
305 }
452e75cc 306
d39a2f80
AD
307 return false;
308 },
309 hasCats: function() {
310 return this.model.hasCats();
311 },
312 hideReadCat: function (cat, hide, show_special) {
313 if (this.hasCats()) {
314 var tree = this;
315
316 if (cat && cat.items) {
317 var cat_unread = tree.hideReadFeeds(cat.items, hide, show_special);
318
319 var id = String(cat.id);
320 var node = tree._itemNodesMap[id];
321 var bare_id = parseInt(id.substr(id.indexOf(":")+1));
322
323 if (node) {
324 var check_unread = tree.model.getFeedUnread(bare_id, true);
325
326 if (hide && cat_unread == 0 && check_unread == 0 && (id != "CAT:-1" || !show_special)) {
327 Effect.Fade(node[0].rowNode, {duration : 0.3,
328 queue: { position: 'end', scope: 'FFADE-' + id, limit: 1 }});
329 } else {
330 Element.show(node[0].rowNode);
331 ++cat_unread;
332 }
05f224a3 333 }
452e75cc 334 }
5712a2fe 335 }
d39a2f80
AD
336 },
337 hideRead: function (hide, show_special) {
338 if (this.hasCats()) {
339
340 var tree = this;
341 var cats = this.model.store._arrayOfTopLevelItems;
5712a2fe 342
d39a2f80
AD
343 cats.each(function(cat) {
344 tree.hideReadCat(cat, hide, show_special);
345 });
346
347 } else {
348 this.hideReadFeeds(this.model.store._arrayOfTopLevelItems, hide,
349 show_special);
350 }
351 },
352 hideReadFeeds: function (items, hide, show_special) {
5712a2fe 353 var tree = this;
d39a2f80 354 var cat_unread = 0;
5712a2fe 355
d39a2f80
AD
356 items.each(function(feed) {
357 var id = String(feed.id);
05f224a3 358
d39a2f80
AD
359 // it's a subcategory
360 if (feed.items) {
361 tree.hideReadCat(feed, hide, show_special);
362 } else { // it's a feed
363 var bare_id = parseInt(feed.bare_id);;
364
365 var unread = feed.unread[0];
366 var has_error = feed.error[0] != '';
367 var node = tree._itemNodesMap[id];
368
369 if (node) {
370 if (hide && unread == 0 && !has_error && (bare_id > 0 || bare_id < _label_base_index || !show_special)) {
371 Effect.Fade(node[0].rowNode, {duration : 0.3,
372 queue: { position: 'end', scope: 'FFADE-' + id, limit: 1 }});
373 } else {
374 Element.show(node[0].rowNode);
375 ++cat_unread;
376 }
6cdc4576 377 }
05f224a3 378 }
d39a2f80 379 });
452e75cc 380
d39a2f80
AD
381 return cat_unread;
382 },
383 collapseCat: function(id) {
384 if (!this.model.hasCats()) return;
7613280a 385
d39a2f80 386 var tree = this;
7613280a 387
d39a2f80
AD
388 var node = tree._itemNodesMap['CAT:' + id][0];
389 var item = tree.model.store._itemsByIdentity['CAT:' + id];
7613280a 390
d39a2f80
AD
391 if (node && item) {
392 if (!node.isExpanded)
393 tree._expandNode(node);
394 else
395 tree._collapseNode(node);
7613280a 396
d39a2f80
AD
397 }
398 },
399 getVisibleUnreadFeeds: function() {
400 var items = this.model.store._arrayOfAllItems;
401 var rv = [];
452e75cc 402
d39a2f80
AD
403 for (var i = 0; i < items.length; i++) {
404 var id = String(items[i].id);
405 var box = this._itemNodesMap[id];
452e75cc 406
d39a2f80
AD
407 if (box) {
408 var row = box[0].rowNode;
409 var cat = false;
452e75cc 410
d39a2f80
AD
411 try {
412 cat = box[0].rowNode.parentNode.parentNode;
413 } catch (e) { }
452e75cc 414
d39a2f80
AD
415 if (row) {
416 if (Element.visible(row) && (!cat || Element.visible(cat))) {
417 var feed_id = String(items[i].bare_id);
418 var is_cat = !id.match('FEED:');
419 var unread = this.model.getFeedUnread(feed_id, is_cat);
452e75cc 420
d39a2f80
AD
421 if (unread > 0)
422 rv.push([feed_id, is_cat]);
452e75cc 423
d39a2f80 424 }
452e75cc
AD
425 }
426 }
427 }
d39a2f80
AD
428
429 return rv;
430 },
431 getNextFeed: function (feed, is_cat) {
432 if (is_cat) {
433 treeItem = this.model.store._itemsByIdentity['CAT:' + feed];
434 } else {
435 treeItem = this.model.store._itemsByIdentity['FEED:' + feed];
436 }
437
438 items = this.model.store._arrayOfAllItems;
439 var item = items[0];
440
441 for (var i = 0; i < items.length; i++) {
442 if (items[i] == treeItem) {
443
444 for (var j = i+1; j < items.length; j++) {
445 var id = String(items[j].id);
446 var box = this._itemNodesMap[id];
447
448 if (box) {
449 var row = box[0].rowNode;
450 var cat = box[0].rowNode.parentNode.parentNode;
451
452 if (Element.visible(cat) && Element.visible(row)) {
453 item = items[j];
454 break;
455 }
d026d372
AD
456 }
457 }
d39a2f80 458 break;
d026d372 459 }
d026d372 460 }
d026d372 461
d39a2f80
AD
462 if (item) {
463 return [this.model.store.getValue(item, 'bare_id'),
464 !this.model.store.getValue(item, 'id').match('FEED:')];
465 } else {
466 return false;
467 }
468 },
469 getPreviousFeed: function (feed, is_cat) {
470 if (is_cat) {
471 treeItem = this.model.store._itemsByIdentity['CAT:' + feed];
472 } else {
473 treeItem = this.model.store._itemsByIdentity['FEED:' + feed];
474 }
475
476 items = this.model.store._arrayOfAllItems;
477 var item = items[0] == treeItem ? items[items.length-1] : items[0];
478
479 for (var i = 0; i < items.length; i++) {
480 if (items[i] == treeItem) {
481
482 for (var j = i-1; j > 0; j--) {
483 var id = String(items[j].id);
484 var box = this._itemNodesMap[id];
485
486 if (box) {
487 var row = box[0].rowNode;
488 var cat = box[0].rowNode.parentNode.parentNode;
489
490 if (Element.visible(cat) && Element.visible(row)) {
491 item = items[j];
492 break;
493 }
d026d372 494 }
c2b2869c 495
d39a2f80
AD
496 }
497 break;
d026d372 498 }
d026d372 499 }
d026d372 500
d39a2f80
AD
501 if (item) {
502 return [this.model.store.getValue(item, 'bare_id'),
503 !this.model.store.getValue(item, 'id').match('FEED:')];
504 } else {
505 return false;
506 }
d026d372 507
d39a2f80
AD
508 },
509 getFeedCategory: function(feed) {
510 try {
511 return this.getNodesByItem(this.model.store.
6c8e8fbd 512 _itemsByIdentity["FEED:" + feed])[0].
d39a2f80 513 getParent().item.bare_id[0];
d026d372 514
d39a2f80
AD
515 } catch (e) {
516 return false;
517 }
518 },
519 });
05f224a3 520});
d39a2f80 521