1 |
function get_item_link_select(item_id, link_index) |
2 |
{ |
3 |
return document.getElementById('linkSelect' + item_id + '-' + link_index); |
4 |
} |
5 |
|
6 |
function get_item_link(item_id, link_index) |
7 |
{ |
8 |
return document.getElementById('itemLink' + item_id + '-' + link_index); |
9 |
} |
10 |
|
11 |
function link_select(item_id, link) |
12 |
{ |
13 |
var item = document.getElementById('item' + item_id).listItem; |
14 |
|
15 |
if((typeof link == 'string')) { |
16 |
link = link.replace(/(http:\/\/[^\/]+)\/$/, '$1'); |
17 |
// it seems to be necessary to drop the trailing slash, at least for Apple's Safari; except that this breaks the whole thing because it can't match links when they are not the same (i.e. the slash is missing) |
18 |
|
19 |
item.selectLink(link, function() { link_selected(item_id, link); }); |
20 |
return false; |
21 |
} else if(typeof link == 'number') { |
22 |
var link = get_item_link(item_id, link); |
23 |
|
24 |
if(link) { |
25 |
var href = link.href; |
26 |
href = href.replace(/(http:\/\/[^\/]+)\/$/, '$1'); |
27 |
// it seems to be necessary to drop the trailing slash, at least for Apple's Safari; except that this breaks the whole thing because it can't match links when they are not the same (i.e. the slash is missing) |
28 |
|
29 |
item.selectLink(href, function() { link_selected(item_id, href); }); |
30 |
return false; |
31 |
} |
32 |
} |
33 |
|
34 |
return true; |
35 |
} |
36 |
|
37 |
function link_selected(item_id, link) |
38 |
{ |
39 |
var item = document.getElementById('item' + item_id); |
40 |
var ancs = item.getElementsByTagName('A'); |
41 |
|
42 |
for(var a = 0; a < ancs.length; a++) { |
43 |
if(ancs[a].className.match(/\blink-select\b/)) { |
44 |
|
45 |
if(ancs[a].actualHref) { |
46 |
var href = ancs[a].actualHref; |
47 |
href = href.replace(/(http:\/\/[^\/]+)\/$/, '$1'); // it seems to be necessary to drop the trailing slash, at least for Apple's Safari; except that this breaks the whole thing because it can't match links when they are not the same (i.e. the slash is missing) |
48 |
|
49 |
if(href == link) { |
50 |
ancs[a].className = ancs[a].className.replace(/\blink-(un)?selected\b/g, 'link-selected'); |
51 |
|
52 |
} else { |
53 |
ancs[a].className = ancs[a].className.replace(/\blink-(un)?selected\b/g, 'link-unselected'); |
54 |
|
55 |
} |
56 |
} |
57 |
} |
58 |
} |
59 |
} |
60 |
|
61 |
function archive_feed(feed_id) |
62 |
{ |
63 |
var item = document.getElementById('feed'+feed_id).listItem; |
64 |
|
65 |
item.toggleRead(true, function() { archived_feed(feed_id); }); |
66 |
|
67 |
return false; |
68 |
} |
69 |
|
70 |
function archived_feed(feed_id) |
71 |
{ |
72 |
location.reload(); |
73 |
} |
74 |
|
75 |
function toggle_read(item_id) |
76 |
{ |
77 |
var a_priori = false; |
78 |
|
79 |
if(arguments.length >= 3) { |
80 |
if(arguments[2]) { |
81 |
a_priori = 'read'; |
82 |
} else { |
83 |
a_priori = 'unread'; |
84 |
} |
85 |
} |
86 |
|
87 |
var itemNode = document.getElementById('item'+item_id); |
88 |
var item = itemNode.listItem; |
89 |
var anchor = document.getElementById('controlRead'+item_id); |
90 |
anchor.innerHTML = '<span class="big"> </span><span class="small"> </span>' |
91 |
anchor.className = anchor.className + ' processing'; |
92 |
|
93 |
// get the header into view |
94 |
Refeed.App.scrollIntoView(new Refeed.Box(item.getNodeBox().left(), item.getNodeBox().top(), 0, 80)); |
95 |
|
96 |
if(itemNode.className.match(/\bunread/) && (!a_priori || (a_priori && (a_priori == 'read')))) { |
97 |
itemNode.className = itemNode.className.replace(/\b(unread|read-but-visible|read)\b/g, 'read'); |
98 |
item.toggleRead(true, function() { toggled_read(item_id, true); }); |
99 |
|
100 |
return true; /* scroll to next */ |
101 |
|
102 |
} else if(itemNode.className.match(/\bread/) && (!a_priori || (a_priori && (a_priori == 'unread')))) { |
103 |
itemNode.className = itemNode.className.replace(/\b(unread|read-but-visible|read)\b/g, 'unread'); |
104 |
item.toggleRead(false, function() { toggled_read(item_id, false); }); |
105 |
|
106 |
} |
107 |
|
108 |
return false; /* don't scroll */ |
109 |
} |
110 |
|
111 |
function toggled_read(item_id, read) |
112 |
{ |
113 |
var item = document.getElementById('item'+item_id); |
114 |
var anchor = document.getElementById('controlRead'+item_id); |
115 |
|
116 |
anchor.className = anchor.className.replace(/\bprocessing\b/g, ''); |
117 |
|
118 |
if(read) { |
119 |
//item.className = item.className.replace(/\b(unread|read-but-visible|read)\b/g, 'read'); |
120 |
anchor.innerHTML = '<span class="big">A</span><span class="small">archived</span>' |
121 |
anchor.title = 'Mark this item unread'; |
122 |
|
123 |
} else { |
124 |
//item.className = item.className.replace(/\b(unread|read-but-visible|read)\b/g, 'unread'); |
125 |
anchor.innerHTML = '<span class="big">A</span><span class="small">archive</span>' |
126 |
anchor.title = 'Mark this item read'; |
127 |
|
128 |
} |
129 |
} |
130 |
|
131 |
function toggle_published(item_id) |
132 |
{ |
133 |
var itemNode = document.getElementById('item'+item_id); |
134 |
var item = itemNode.listItem; |
135 |
var anchor = document.getElementById('controlPublished'+item_id); |
136 |
|
137 |
anchor.innerHTML = '<span class="big"> </span><span class="small"> </span>' |
138 |
anchor.className = anchor.className + ' processing'; |
139 |
|
140 |
// get the header into view |
141 |
Refeed.App.scrollIntoView(new Refeed.Box(item.getNodeBox().left(), item.getNodeBox().top(), 0, 80)); |
142 |
|
143 |
if(itemNode.className.match(/\bunpublished/)) { |
144 |
item.togglePublished(true, function() { toggled_published(item_id, true); }); |
145 |
|
146 |
} else if(itemNode.className.match(/\bpublished/)) { |
147 |
item.togglePublished(false, function() { toggled_published(item_id, false); }); |
148 |
|
149 |
} else { |
150 |
return true; |
151 |
|
152 |
} |
153 |
|
154 |
return false; |
155 |
} |
156 |
|
157 |
function toggled_published(item_id, published) |
158 |
{ |
159 |
var item = document.getElementById('item'+item_id); |
160 |
var anchor = document.getElementById('controlPublished'+item_id); |
161 |
|
162 |
anchor.className = anchor.className.replace(/\bprocessing\b/g, ''); |
163 |
|
164 |
if(published) { |
165 |
item.className = item.className.replace(/(published|unpublished)/g, 'published'); |
166 |
anchor.innerHTML = '<span class="big">P</span><span class="small">published</span>' |
167 |
anchor.title = 'Mark this item unpublished'; |
168 |
|
169 |
} else { |
170 |
item.className = item.className.replace(/(published|unpublished)/g, 'unpublished'); |
171 |
anchor.innerHTML = '<span class="big">P</span><span class="small">publish</span>' |
172 |
anchor.title = 'Mark this item published'; |
173 |
|
174 |
} |
175 |
} |
176 |
|
177 |
function toggle_kb() |
178 |
{ |
179 |
var useKB = Refeed.App.toggleKB(); |
180 |
var indicator = document.getElementById('kb-indicator'); |
181 |
|
182 |
var onResult = function(result) { |
183 |
if(indicator) { |
184 |
if(useKB) { |
185 |
indicator.innerHTML = 'on'; |
186 |
} else { |
187 |
indicator.innerHTML = 'off'; |
188 |
} |
189 |
} |
190 |
}; |
191 |
|
192 |
var onError = function(result) { |
193 |
if(indicator) { |
194 |
indicator.innerHTML = '?@#$'; |
195 |
} |
196 |
}; |
197 |
|
198 |
indicator.innerHTML = '...'; |
199 |
Refeed.ServerComm.remoteCall('setKeyboardUse', [useKB], onResult, undefined); |
200 |
} |
201 |
|
202 |
function toggle_cheatsheet() |
203 |
{ |
204 |
var sheet = document.getElementById('cheatsheet'); |
205 |
|
206 |
if(sheet) { |
207 |
if(sheet.style.display == 'none') { |
208 |
sheet.style.top = (Refeed.App.getWindowBox().top() + 25 ) + "px"; |
209 |
sheet.style.display = 'block'; |
210 |
} else { |
211 |
sheet.style.display = 'none'; |
212 |
} |
213 |
return false; |
214 |
} |
215 |
} |
216 |
|
217 |
|
218 |
function toggle_focus(focus) |
219 |
{ |
220 |
var body = document.getElementsByTagName('body')[0]; |
221 |
|
222 |
if(focus) { |
223 |
window.has_focus = true; |
224 |
body.className = body.className.replace(/\bbody-(focus|blur)\b/g, 'body-focus'); |
225 |
} else { |
226 |
window.has_focus = false; |
227 |
body.className = body.className.replace(/\bbody-(focus|blur)\b/g, 'body-blur'); |
228 |
|
229 |
} |
230 |
} |
231 |
|
232 |
function added_list_thing(list_item) |
233 |
{ |
234 |
var link_selects = list_item.node.getElementsByTagName('a'); |
235 |
|
236 |
for(var ls = 0; ls < link_selects.length; ls++) { |
237 |
if(link_selects[ls].className.match(/\blink-select\b/) && link_selects[ls].id.match(/^linkSelect(\d+)-(\d+)$/)) { |
238 |
|
239 |
var actualAnchor = document.getElementById('itemLink'+RegExp.$1+'-'+RegExp.$2); |
240 |
|
241 |
if(actualAnchor) { |
242 |
link_selects[ls].itemId = RegExp.$1; |
243 |
link_selects[ls].actualHref = actualAnchor.href; |
244 |
|
245 |
link_selects[ls].onclick = function() { |
246 |
link_select(this.itemId, this.actualHref); |
247 |
return false; |
248 |
}; |
249 |
} |
250 |
} |
251 |
} |
252 |
} |
253 |
|
254 |
function edit_link_select(link) { |
255 |
var link_text = document.getElementById('link_text'); |
256 |
if(link_text) { |
257 |
link_text.value = link; |
258 |
} |
259 |
|
260 |
return true; |
261 |
} |
262 |
|
263 |
function edit_link_edit() { |
264 |
var link_text_radio = document.getElementById('link_text_radio'); |
265 |
if(link_text_radio) { |
266 |
link_text_radio.checked = true; |
267 |
} |
268 |
return false; |
269 |
} |
270 |
|
271 |
function item_editform_link_select(item_id, link) |
272 |
{ |
273 |
var linkField = document.getElementById('selectedLinkField'+item_id); |
274 |
|
275 |
if(linkField) { |
276 |
linkField.value = link; |
277 |
} |
278 |
|
279 |
return true; |
280 |
} |
281 |
|
282 |
function item_editform_link_edit(item_id) { |
283 |
var link_text_radio = document.getElementById('link_text_radio'); |
284 |
if(link_text_radio) { |
285 |
link_text_radio.checked = true; |
286 |
} |
287 |
return false; |
288 |
} |
289 |
|
290 |
/** |
291 |
* Populate an item's body content with results from an HTTP request. |
292 |
* @param int item_id Unique ID of an item |
293 |
* @param string body_source Source of body data - method name to pass to ServerComm.remoteCall() |
294 |
* @param string tab_id DOM ID of associated visual tab |
295 |
* @return boolean false |
296 |
*/ |
297 |
function populate_item_body(item_id, body_source, tab_id) |
298 |
{ |
299 |
var itemNode = document.getElementById('item'+item_id); |
300 |
var item = itemNode.listItem; |
301 |
var itemBody = document.getElementById('itemBody'+item_id); |
302 |
var itemTabs = document.getElementById('itemTabs'+item_id); |
303 |
var itemTab = document.getElementById(tab_id); |
304 |
|
305 |
itemNode.className = itemNode.className + ' processing'; |
306 |
|
307 |
// get the header into view |
308 |
Refeed.App.scrollIntoView(new Refeed.Box(item.getNodeBox().left(), item.getNodeBox().top(), 0, 80)); |
309 |
|
310 |
var onResult = function(html) { |
311 |
if(itemTab) { |
312 |
for(var otherTab = itemTab.parentNode.firstChild; otherTab; otherTab = otherTab.nextSibling) { |
313 |
if(otherTab == itemTab) { |
314 |
otherTab.className = 'on'; |
315 |
} else if(otherTab.tagName == 'A') { |
316 |
otherTab.className = 'off'; |
317 |
} |
318 |
} |
319 |
} |
320 |
itemBody.innerHTML = html; |
321 |
itemNode.className = itemNode.className.replace(/\bprocessing\b/g, ''); |
322 |
// auto focus field if it exists |
323 |
var f = document.getElementById('autoFocus'+item_id); |
324 |
if (f) f.focus(); |
325 |
}; |
326 |
|
327 |
var onError = function(error) { |
328 |
alert(error); |
329 |
itemNode.className = itemNode.className.replace(/\bprocessing\b/g, ''); |
330 |
}; |
331 |
|
332 |
Refeed.ServerComm.remoteCall(body_source, [item.toClassHint()], onResult, onError); |
333 |
return false; |
334 |
} |
335 |
|
336 |
/** |
337 |
* Shorthand access to populate_item_body(), when populating the default item view |
338 |
* @return boolean false |
339 |
*/ |
340 |
function populate_item_body_view(item_id) { return populate_item_body(item_id, 'itemBodyHTML', 'itemTab'+item_id+'View'); } |
341 |
|
342 |
function submit_item_commentform(form, item_id) |
343 |
{ |
344 |
var item = document.getElementById('item'+item_id).listItem; |
345 |
var itemHead = document.getElementById('itemHead'+item_id); |
346 |
|
347 |
var onResult = function() { |
348 |
populate_item_body_view(item_id); |
349 |
}; |
350 |
|
351 |
item.setItemCommentTags(form.elements['comment'].value, form.elements['itemtags'].value.split(/\s+/), onResult, undefined); |
352 |
} |
353 |
|
354 |
function submit_item_editform(form, item_id) |
355 |
{ |
356 |
var item = document.getElementById('item'+item_id).listItem; |
357 |
var itemHead = document.getElementById('itemHead'+item_id); |
358 |
|
359 |
var onResult = function() { |
360 |
populate_item_body_view(item_id); |
361 |
|
362 |
var onSubResult = function(html) { |
363 |
itemHead.innerHTML = html; |
364 |
}; |
365 |
|
366 |
Refeed.ServerComm.remoteCall('itemHeadHTML', [item.toClassHint()], onSubResult, undefined); |
367 |
}; |
368 |
|
369 |
item.setItemTitleContentLink(form.elements['title'].value, form.elements['content'].value, form.elements['link'].value, onResult, undefined); |
370 |
} |
371 |
|
372 |
|
373 |
|
374 |
/** |
375 |
* Populate a feed's body content with results from an HTTP request. |
376 |
* @param int feed_id Unique ID of a feed |
377 |
* @param string body_source Source of body data - method name to pass to ServerComm.remoteCall() |
378 |
* @param string tab_id DOM ID of associated visual tab |
379 |
* @return boolean false |
380 |
*/ |
381 |
function populate_feed_body(feed_id, body_source, tab_id) |
382 |
{ |
383 |
var feed = document.getElementById('feed'+feed_id).listItem; |
384 |
var feedExtra = document.getElementById('feedExtra'+feed_id); |
385 |
var feedTabs = document.getElementById('feedTabs'+feed_id); |
386 |
var feedTab = document.getElementById(tab_id); |
387 |
|
388 |
feedExtra.className = feedExtra.className.replace(/\b(open|closed)\b/g, 'open'); |
389 |
|
390 |
for(var feedExtraCell = feedExtra.firstChild; feedExtraCell; feedExtraCell = feedExtraCell.nextSibling) { |
391 |
if(feedExtraCell.nodeName == 'TD' || feedExtraCell.nodeName == 'P') { |
392 |
break; |
393 |
} |
394 |
} |
395 |
|
396 |
feedExtra.className = feedExtra.className + ' processing'; |
397 |
feedExtraCell.innerHTML = ' '; |
398 |
|
399 |
var onResult = function(html) { |
400 |
if(feedTab) { |
401 |
for(var otherTab = feedTab.parentNode.firstChild; otherTab; otherTab = otherTab.nextSibling) { |
402 |
if(otherTab == feedTab) { |
403 |
otherTab.className = 'on'; |
404 |
} else if(otherTab.tagName == 'A') { |
405 |
otherTab.className = 'off'; |
406 |
} |
407 |
} |
408 |
} |
409 |
feedExtra.className = feedExtra.className.replace(/\bprocessing\b/g, ''); |
410 |
feedExtraCell.innerHTML = '<p class="close"><a class="on" href="#" onclick="depopulate_feed_body('+feed_id+'); return false;">close</a></p>' + html; |
411 |
}; |
412 |
|
413 |
var onError = function(error) { |
414 |
alert(error); |
415 |
feedExtra.className = feedExtra.className.replace(/\bprocessing\b/g, ''); |
416 |
}; |
417 |
|
418 |
Refeed.ServerComm.remoteCall(body_source, [feed.toClassHint()], onResult, onError); |
419 |
return false; |
420 |
} |
421 |
|
422 |
/** |
423 |
* Depopulate a feed's body content, hiding it |
424 |
* @param int feed_id Unique ID of a feed |
425 |
* @return boolean false |
426 |
*/ |
427 |
function depopulate_feed_body(feed_id) |
428 |
{ |
429 |
var feedExtra = document.getElementById('feedExtra'+feed_id); |
430 |
var feedTabs = document.getElementById('feedTabs'+feed_id); |
431 |
|
432 |
feedExtra.className = feedExtra.className.replace(/\b(open|closed)\b/g, 'closed'); |
433 |
|
434 |
for(var otherTab = feedTabs.firstChild; otherTab; otherTab = otherTab.nextSibling) { |
435 |
if(otherTab.tagName == 'A') { |
436 |
otherTab.className = 'off'; |
437 |
} |
438 |
} |
439 |
|
440 |
return false; |
441 |
} |
442 |
|
443 |
function submit_feed_tagsform(form, feed_id) |
444 |
{ |
445 |
var feed = document.getElementById('feed'+feed_id).listItem; |
446 |
var feedExtra = document.getElementById('feedExtra'+feed_id); |
447 |
|
448 |
feedExtra.className = feedExtra.className + ' processing'; |
449 |
|
450 |
var onResult = function() { |
451 |
depopulate_feed_body(feed_id); |
452 |
feedExtra.className = feedExtra.className.replace(/\bprocessing\b/g, ''); |
453 |
}; |
454 |
|
455 |
var onError = function(error) { |
456 |
alert(error); |
457 |
feedExtra.className = feedExtra.className.replace(/\bprocessing\b/g, ''); |
458 |
}; |
459 |
|
460 |
feed.setFeedTags(form.elements['feedtags'].value.split(/\s+/), onResult, onError); |
461 |
} |
462 |
|
463 |
function submit_feed_publishform(form, feed_id) |
464 |
{ |
465 |
var feed = document.getElementById('feed'+feed_id).listItem; |
466 |
var feedExtra = document.getElementById('feedExtra'+feed_id); |
467 |
|
468 |
feedExtra.className = feedExtra.className + ' processing'; |
469 |
|
470 |
var onResult = function() { |
471 |
depopulate_feed_body(feed_id); |
472 |
feedExtra.className = feedExtra.className.replace(/\bprocessing\b/g, ''); |
473 |
}; |
474 |
|
475 |
var onError = function(error) { |
476 |
alert(error); |
477 |
feedExtra.className = feedExtra.className.replace(/\bprocessing\b/g, ''); |
478 |
}; |
479 |
|
480 |
if(form.elements['publish'].value == 'publish') { |
481 |
feed.togglePublished(true, onResult, onError); |
482 |
} else { |
483 |
feed.togglePublished(false, onResult, onError); |
484 |
} |
485 |
} |
486 |
|
487 |
window.onfocus = function() { toggle_focus(true); } |
488 |
window.onblur = function() { toggle_focus(false); } |