]>
git.wh0rd.org - tt-rss.git/blob - js/FeedTree.js
1 define(["dojo/_base/declare", "dojo/dom-construct", "dijit/Tree", "dijit/Menu"], function (declare
, domConstruct
) {
3 return declare("fox.FeedTree", dijit
.Tree
, {
4 _onKeyPress: function(/* Event */ e
) {
5 return; // Stop dijit.Tree from interpreting keystrokes
7 _createTreeNode: function(args
) {
8 var tnode
= new dijit
._TreeNode(args
);
10 var icon
= dojo
.doc
.createElement('img');
11 if (args
.item
.icon
&& args
.item
.icon
[0]) {
12 icon
.src
= args
.item
.icon
[0];
14 icon
.src
= 'images/blank_icon.gif';
16 icon
.className
= 'tinyFeedIcon';
17 domConstruct
.place(icon
, tnode
.iconNode
, 'only');
19 var id
= args
.item
.id
[0];
20 var bare_id
= parseInt(id
.substr(id
.indexOf(':')+1));
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];
27 span
.innerHTML
= "α";
28 span
.className
= 'labelColorIndicator';
31 backgroundColor
: bg_color
});
33 domConstruct
.place(span
, tnode
.iconNode
, 'only');
36 if (id
.match("FEED:")) {
37 var menu
= new dijit
.Menu();
38 menu
.row_id
= bare_id
;
40 menu
.addChild(new dijit
.MenuItem({
41 label
: __("Mark as read"),
43 catchupFeed(this.getParent().row_id
);
47 menu
.addChild(new dijit
.MenuItem({
48 label
: __("Edit feed"),
50 editFeed(this.getParent().row_id
, false);
53 /* menu.addChild(new dijit.MenuItem({
54 label: __("Update feed"),
56 heduleFeedUpdate(this.getParent().row_id, false);
60 menu
.bindDomNode(tnode
.domNode
);
64 if (id
.match("CAT:") && bare_id
>= 0) {
65 var menu
= new dijit
.Menu();
66 menu
.row_id
= bare_id
;
68 menu
.addChild(new dijit
.MenuItem({
69 label
: __("Mark as read"),
71 catchupFeed(this.getParent().row_id
, true);
74 menu
.addChild(new dijit
.MenuItem({
75 label
: __("(Un)collapse"),
77 dijit
.byId("feedTree").collapseCat(this.getParent().row_id
);
80 menu
.bindDomNode(tnode
.domNode
);
84 if (id
.match("CAT:")) {
85 loading
= dojo
.doc
.createElement('img');
86 loading
.className
= 'loadingNode';
87 loading
.src
= 'images/blank_icon.gif';
88 domConstruct
.place(loading
, tnode
.labelNode
, 'after');
89 tnode
.loadingNode
= loading
;
92 if (id
.match("CAT:") && bare_id
== -1) {
93 var menu
= new dijit
.Menu();
94 menu
.row_id
= bare_id
;
96 menu
.addChild(new dijit
.MenuItem({
97 label
: __("Mark all feeds as read"),
102 menu
.bindDomNode(tnode
.domNode
);
106 ctr
= dojo
.doc
.createElement('span');
107 ctr
.className
= 'counterNode';
108 ctr
.innerHTML
= args
.item
.unread
> 0 ? args
.item
.unread
: args
.item
.auxcounter
;
110 //args.item.unread > 0 ? ctr.addClassName("unread") : ctr.removeClassName("unread");
112 args
.item
.unread
> 0 || args
.item
.auxcounter
> 0 ? Element
.show(ctr
) : Element
.hide(ctr
);
114 args
.item
.unread
== 0 && args
.item
.auxcounter
> 0 ? ctr
.addClassName("aux") : ctr
.removeClassName("aux");
116 domConstruct
.place(ctr
, tnode
.rowNode
, 'first');
117 tnode
.counterNode
= ctr
;
119 //tnode.labelNode.innerHTML = args.label;
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"));
128 this.inherited(arguments
);
130 updateCounter: function (item
) {
133 //console.log("updateCounter: " + item.id[0] + " " + item.unread + " " + tree);
135 var node
= tree
._itemNodesMap
[item
.id
];
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 ?
145 Effect
.Appear(ctr
, {duration
: 0.3,
146 queue
: { position
: 'end', scope
: 'CAPPEAR-' + item
.id
, limit
: 1 }}) :
150 item
.unread
== 0 && item
.auxcounter
> 0 ? ctr
.addClassName("aux") : ctr
.removeClassName("aux");
156 getTooltip: function (item
) {
162 getIconClass: function (item
, opened
) {
163 return (!item
|| this.model
.mayHaveChildren(item
)) ? (opened
? "dijitFolderOpened" : "dijitFolderClosed") : "feedIcon";
165 getLabelClass: function (item
, opened
) {
166 return (item
.unread
== 0) ? "dijitTreeLabel" : "dijitTreeLabel Unread";
168 getRowClass: function (item
, opened
) {
169 var rc
= (!item
.error
|| item
.error
== '') ? "dijitTreeRow" :
170 "dijitTreeRow Error";
172 if (item
.unread
> 0) rc
+= " Unread";
173 if (item
.updates_disabled
> 0) rc
+= " UpdatesDisabled";
177 getLabel: function(item
) {
178 var name
= String(item
.name
);
181 name
= name
.replace(/"/g, "\"");
182 name
= name
.replace(/&/g, "&");
183 name
= name
.replace(/—/g, "-");
184 name
= name
.replace(/</g, "<");
185 name
= name
.replace(/>/g, ">");
189 if (item.unread > 0) {
190 label = name + " (" + item.unread + ")";
197 expandParentNodes: function(feed
, is_cat
, list
) {
199 for (var i
= 0; i
< list
.length
; i
++) {
200 var id
= String(list
[i
].id
);
201 var item
= this._itemNodesMap
[id
];
205 this._expandNode(item
);
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
216 var test_id
= is_cat
? 'CAT:' + feed
: 'FEED:' + feed
;
219 if (!this.model
|| !this.model
.store
) return false;
221 var items
= this.model
.store
._arrayOfTopLevelItems
;
223 for (var i
= 0; i
< items
.length
; i
++) {
224 if (String(items
[i
].id
) == test_id
) {
225 this.expandParentNodes(feed
, is_cat
, parents
);
227 this.findNodeParentsAndExpandThem(feed
, is_cat
, items
[i
], []);
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
);
238 this.findNodeParentsAndExpandThem(feed
, is_cat
, root
.items
[i
], parents
.slice(0));
242 if (String(root
.id
) == test_id
) {
243 this.expandParentNodes(feed
, is_cat
, parents
.slice(0));
251 selectFeed: function(feed
, is_cat
) {
252 this.findNodeParentsAndExpandThem(feed
, is_cat
, false, false);
255 treeNode
= this._itemNodesMap
['CAT:' + feed
];
257 treeNode
= this._itemNodesMap
['FEED:' + feed
];
260 treeNode
= treeNode
[0];
261 if (!is_cat
) this._expandNode(treeNode
);
262 this.set("selectedNodes", [treeNode
]);
263 this.focusNode(treeNode
);
265 // focus headlines to route key events there
266 setTimeout(function() {
267 $("headlines-frame").focus();
271 setFeedIcon: function(feed
, is_cat
, src
) {
273 treeNode
= this._itemNodesMap
['CAT:' + feed
];
275 treeNode
= this._itemNodesMap
['FEED:' + feed
];
278 treeNode
= treeNode
[0];
279 var icon
= dojo
.doc
.createElement('img');
281 icon
.className
= 'tinyFeedIcon';
282 domConstruct
.place(icon
, treeNode
.iconNode
, 'only');
287 setFeedExpandoIcon: function(feed
, is_cat
, src
) {
289 treeNode
= this._itemNodesMap
['CAT:' + feed
];
291 treeNode
= this._itemNodesMap
['FEED:' + feed
];
294 treeNode
= treeNode
[0];
295 if (treeNode
.loadingNode
) {
296 treeNode
.loadingNode
.src
= src
;
299 var icon
= dojo
.doc
.createElement('img');
301 icon
.className
= 'loadingExpando';
302 domConstruct
.place(icon
, treeNode
.expandoNode
, 'only');
309 hasCats: function() {
310 return this.model
.hasCats();
312 hideReadCat: function (cat
, hide
, show_special
) {
313 if (this.hasCats()) {
316 if (cat
&& cat
.items
) {
317 var cat_unread
= tree
.hideReadFeeds(cat
.items
, hide
, show_special
);
319 var id
= String(cat
.id
);
320 var node
= tree
._itemNodesMap
[id
];
321 var bare_id
= parseInt(id
.substr(id
.indexOf(":")+1));
324 var check_unread
= tree
.model
.getFeedUnread(bare_id
, true);
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 }});
330 Element
.show(node
[0].rowNode
);
337 hideRead: function (hide
, show_special
) {
338 if (this.hasCats()) {
341 var cats
= this.model
.store
._arrayOfTopLevelItems
;
343 cats
.each(function(cat
) {
344 tree
.hideReadCat(cat
, hide
, show_special
);
348 this.hideReadFeeds(this.model
.store
._arrayOfTopLevelItems
, hide
,
352 hideReadFeeds: function (items
, hide
, show_special
) {
356 items
.each(function(feed
) {
357 var id
= String(feed
.id
);
359 // it's a subcategory
361 tree
.hideReadCat(feed
, hide
, show_special
);
362 } else { // it's a feed
363 var bare_id
= parseInt(feed
.bare_id
);;
365 var unread
= feed
.unread
[0];
366 var has_error
= feed
.error
[0] != '';
367 var node
= tree
._itemNodesMap
[id
];
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 }});
374 Element
.show(node
[0].rowNode
);
383 collapseCat: function(id
) {
384 if (!this.model
.hasCats()) return;
388 var node
= tree
._itemNodesMap
['CAT:' + id
][0];
389 var item
= tree
.model
.store
._itemsByIdentity
['CAT:' + id
];
392 if (!node
.isExpanded
)
393 tree
._expandNode(node
);
395 tree
._collapseNode(node
);
399 getVisibleUnreadFeeds: function() {
400 var items
= this.model
.store
._arrayOfAllItems
;
403 for (var i
= 0; i
< items
.length
; i
++) {
404 var id
= String(items
[i
].id
);
405 var box
= this._itemNodesMap
[id
];
408 var row
= box
[0].rowNode
;
412 cat
= box
[0].rowNode
.parentNode
.parentNode
;
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
);
422 rv
.push([feed_id
, is_cat
]);
431 getNextFeed: function (feed
, is_cat
) {
433 treeItem
= this.model
.store
._itemsByIdentity
['CAT:' + feed
];
435 treeItem
= this.model
.store
._itemsByIdentity
['FEED:' + feed
];
438 items
= this.model
.store
._arrayOfAllItems
;
441 for (var i
= 0; i
< items
.length
; i
++) {
442 if (items
[i
] == treeItem
) {
444 for (var j
= i
+1; j
< items
.length
; j
++) {
445 var id
= String(items
[j
].id
);
446 var box
= this._itemNodesMap
[id
];
449 var row
= box
[0].rowNode
;
450 var cat
= box
[0].rowNode
.parentNode
.parentNode
;
452 if (Element
.visible(cat
) && Element
.visible(row
)) {
463 return [this.model
.store
.getValue(item
, 'bare_id'),
464 !this.model
.store
.getValue(item
, 'id').match('FEED:')];
469 getPreviousFeed: function (feed
, is_cat
) {
471 treeItem
= this.model
.store
._itemsByIdentity
['CAT:' + feed
];
473 treeItem
= this.model
.store
._itemsByIdentity
['FEED:' + feed
];
476 items
= this.model
.store
._arrayOfAllItems
;
477 var item
= items
[0] == treeItem
? items
[items
.length
-1] : items
[0];
479 for (var i
= 0; i
< items
.length
; i
++) {
480 if (items
[i
] == treeItem
) {
482 for (var j
= i
-1; j
> 0; j
--) {
483 var id
= String(items
[j
].id
);
484 var box
= this._itemNodesMap
[id
];
487 var row
= box
[0].rowNode
;
488 var cat
= box
[0].rowNode
.parentNode
.parentNode
;
490 if (Element
.visible(cat
) && Element
.visible(row
)) {
502 return [this.model
.store
.getValue(item
, 'bare_id'),
503 !this.model
.store
.getValue(item
, 'id').match('FEED:')];
509 getFeedCategory: function(feed
) {
511 return this.getNodesByItem(this.model
.store
.
512 _itemsByIdentity
["FEED:" + feed
])[0].
513 getParent().item
.bare_id
[0];