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