/[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

Annotation of /trunk/style/dom.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (hide annotations)
Wed Jul 5 01:03:22 2006 UTC (17 years, 11 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 dpavlin 2 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 dpavlin 4 // auto focus field if it exists
324     var f = document.getElementById('auto-focus-'+item_id);
325     if (f) f.focus();
326 dpavlin 2 };
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