/[refeed]/trunk/style/dom.js
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/style/dom.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (show annotations)
Wed Jul 5 01:03:22 2006 UTC (17 years, 10 months ago) by dpavlin
File MIME type: application/javascript
File size: 16102 byte(s)
- auto-focus of field after update from server if it has ID auto-focus-{item_id}
- added vi-like keybinding for next/previous post
- archive key (a) now moves automatically to next item
- added t key (like tag) to add tags

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">&nbsp;</span><span class="small">&nbsp;</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">&nbsp;</span><span class="small">&nbsp;</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 = '&nbsp;';
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); }

  ViewVC Help
Powered by ViewVC 1.1.26