git-svn-id: http://code.softwarefreedom.org/svn/stet/trunk@5 55a1384f-cf82-4c22-9380...
[stet:stet.git] / stet.js
1 // Copyright 2005, Software Freedom Law Center, Inc.
2 //
3 // This program is free software: you may copy, modify, or redistribute it
4 // and/or modify it under the terms of the GNU Affero General Public
5 // License as published by the Free Software Foundation, either version 3
6 // of the License, or (at your option) any later version.
7 // This program is distributed in the hope that it will be useful, but
8 // WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
10 // General Public License and/or GNU General Public License for more
11 // details.
12 //
13 // You should have received a copy of the GNU Affero General Public License
14 // and the GNU General Public License along with this program. If not, see
15 // <http://www.gnu.org/licenses/>.
16 //
17
18 // Based on some work from http://www.quirksmode.org/js/selected.html
19 // That work was copyrighted by Peter-Paul Koch.
20 //  His license is:
21 //     You may copy, tweak, rewrite, sell or lease any code example on this site.
22
23 function XpathSel() {
24   var textObj = '';
25   var start = '';
26   var end = '';
27   if (window.getSelection)
28     {
29       textObj = window.getSelection();
30       
31     }
32   else if (document.getSelection)
33     {
34       textObj= document.getSelection();
35     }
36   else if (document.selection)
37     {
38       textObj= document.selection.createRange().text;
39     }
40   else return;
41
42       startNode = textObj.anchorNode.parentNode;
43       startid= startNode.id;
44       start = startNode.nodeName;
45       
46       endnode = textObj.focusNode.parentNode;
47       endid = endnode.id;
48       end = endnode.nodeName;
49   
50
51     for (var oStr='' ; startNode && startNode.nodeName != '#document'; startNode=startNode.parentNode) { 
52       if (startNode.nodeName!='#text') { 
53         oStr = startNode.nodeName 
54         + (startNode.id?('[id='+startNode.id+']'):'')
55         + (oStr?('/'+oStr):'');
56       }
57     }
58         myNoteIfy = createNoteDiv();
59         textString = textObj.toString();
60
61         //      highlightWord(startNode,textString,'','','');
62
63         thisNode = document.getElementById(startid);
64
65         if ((thisNode.previousSibling) && (thisNode.previousSibling.previousSibling) && (thisNode.previousSibling.previousSibling.appendChild)) {
66         thisNode.previousSibling.previousSibling.appendChild(myNoteIfy);
67         }
68         else 
69 if ((thisNode.previousSibling) && (thisNode.previousSibling.appendChild)) {
70         thisNode.previousSibling.appendChild(myNoteIfy);
71         }
72         else {
73         thisNode.appendChild(myNoteIfy);
74         }
75         document.getElementById('DomPath').value = oStr;
76 //      document.getElementById('DomPathTxt').innerHTML = 'xpath: <strong>'+oStr+'</strong>';
77         document.getElementById('Selection').value = textString;
78         document.getElementById('SelectionTxt').innerHTML = 'comment on: <strong>'+textString+'</strong>';
79 //      document.getElementById('NoteText').value = startid;
80         document.getElementById('StartNodeId').value = startid;
81         document.getElementById('EndNodeId').value = endid;
82         document.getElementById('StartNode').value = start;
83         document.getElementById('EndNode').value = end;
84         document.getElementById('NoteUrl').value = location.href;
85         //      document.getElementById('cancel').setAttribute('parent',startid);
86
87
88
89 //    location.href='http://localhost/cgi-bin/stet-submit.pl?url='+escape(location.href)+'&dompath='+oStr+'&selectedtext='+escape(textObj)+'&start='+escape(start)+'&startid='+escape(startid)+'&end='+escape(end)+'&endid='+escape(endid);;
90
91 }
92
93 function submitComment() {
94
95 var form = document.getElementById('noteify');
96  var noteText = form.NoteText.value;
97  form.NoteText.value = "OK, submitting...";
98  form.NoteText.style.background = '#aaa';
99  form.style.background = '#aaa';
100
101 var params = encodeURI('DomPath='+form.DomPath.value+'&amp;Selection='+form.Selection.value+'&amp;NoteText='+noteText+'&amp;StartNode='+form.StartNode.value+'&amp;EndNode='+form.EndNode.value+'&amp;StartNodeId='+form.StartNodeId.value+'&amp;EndNodeId='+form.EndNodeId.value+'&amp;NoteUrl='+location.href);
102
103 var pyparams = encodeURI('custom_note_dom_path='+form.DomPath.value+'&amp;custom_note_selection='+form.Selection.value+'&amp;custom_start_node='+form.StartNode.value+'&amp;custom_end_node='+form.EndNode.value+'&amp;custom_note_start_node_id='+form.StartNodeId.value+'&amp;custom_note_end_node_id='+form.EndNodeId.value+'&amp;custom_note_url='+location.href+'&amp;description='+noteText+'&amp;summary='+form.Selection.value+'&amp;reporter=moglen@columbia.edu&amp;mode=newticket&amp;action=create&amp;status=new&amp;component=component1&amp;severity=normal&amp;submit=create');
104
105
106
107 //oStr = document.getElementById('DomPath').value;
108 //textObj = document.getElementById('Selection').value;
109 //startid = document.getElementById('NoteText').value;
110 //noteSelection = document.getElementById('StartNodeId').value;
111 //endid = document.getElementById('EndNodeId').value;
112 //start = document.getElementById('StartNode').value;
113 //end = document.getElementById('EndNode').value;
114
115 //http://localhost/cgi-bin/stet-submit.pl?DomPath=&Selection=&NoteText=&StartNode=&EndNode=&StartNodeId=&EndNodeId&NoteUrl=
116
117 //var theUrl = 'http://localhost/cgi-bin/stet-submit.pl?NoteUrl='+escape(location.href)+'&DomPath='+oStr+'&Selection='+escape(textObj)+'&StartNode='+escape(start)+'&StartNodeId='+escape(startid)+'&EndNode='+escape(end)+'&EndNodeId='+escape(endid);
118 //dump('would open '+theUrl+"\n");
119 var theUrl = 'http://localhost/cgi-bin/stet-submit.pl'+'?'+params;
120
121 //highlightWord(form.StartNode.value,form.Selection.value,noteText,'');
122 loadXMLDoc(theUrl);
123 //cancelNote("noteify")
124
125 //window.location = 'http://trac.localdomain.org/trac.cgi'+'?'+pyparams;
126 }
127
128 function toggle(myClass) {
129
130 var toggleUs = getElementsByClass(myClass);
131 for (var i=0; i < toggleUs.length; i++) {
132 //      if (toggleUs[i].style.display == 'inline') {
133                 toggleUs[i].style.display='none';
134 //              }
135 //      else if (toggleUs[i].style.display == 'none') {
136 //              toggleUs[i].style.display='inline';
137 //              }
138         }
139 }
140
141 function getElementsByClass(needle)
142 {
143   var         my_array = document.getElementsByTagName('*');
144   var         retvalue = new Array();
145   var        i;
146   var        j;
147
148   for (i = 0, j = 0; i < my_array.length; i++)
149   {
150     var c = " " + my_array[i].className + " ";
151     if (c.indexOf(" " + needle + " ") != -1) {
152       retvalue[j++] = my_array[i];
153     }
154   }
155   return retvalue;
156 }
157
158
159 // help from http://www.xml.com/pub/a/2005/02/09/xml-http-request.html
160
161 var req;
162
163 function loadXMLDoc(url) 
164 {
165     // branch for native XMLHttpRequest object
166     if (window.XMLHttpRequest) {
167         req = new XMLHttpRequest();
168         req.onreadystatechange = processReqChange;
169         //      netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
170         req.open("GET", url, true); // true = asynchronous
171         req.send(null);
172     // branch for IE/Windows ActiveX version
173     } else if (window.ActiveXObject) {
174         req = new ActiveXObject('Microsoft.XMLHTTP');
175         if (req) {
176             req.onreadystatechange = processReqChange;
177             req.open("GET", url, true);
178             req.send();
179         }
180     }
181 }
182
183 function processReqChange() 
184 {
185     // only if req shows "complete"
186     if (req.readyState == 4) {
187         // only if "OK"
188         if (req.status == 200) {
189           cancelNote("noteify");
190 //      dump(req.responseText);
191         response  = req.responseXML.documentElement;
192         //foo_arr = response.getElementsByTagName("annotation");
193 //      dump(req.responseXML+"\n");
194 //      dump(foo_arr + ' ' + foo_arr.length + ' ' + foo_arr.item(1)+"\n");
195
196         selections_arr = response.getElementsByTagName("s");
197 //      dump(selections_arr + ' ' + selections_arr.length + ' ' + selections_arr.item(0)+"\n");
198         startnodes_arr = response.getElementsByTagName("i");
199         annotations_arr = response.getElementsByTagName("n");
200         rtids_arr = response.getElementsByTagName("id");
201         for (i = 0; i < selections_arr.length; i++) {
202 //              dump("n "+i+"="+annotations_arr[i].firstChild.innerHTML+"\n");
203                 startNode = startnodes_arr[i].firstChild.data;
204                 noteSelection = selections_arr[i].firstChild.data;
205                 annoteText = annotations_arr[i];
206 //              if (annotations_arr[i].firstChild.nextSibling) {
207 //              annoteText += annotations_arr[i].firstChild.toString();
208 //              }
209                 
210                 rtid = rtids_arr[i] ? rtids_arr[i].firstChild.data : "";
211
212                 //dump("highlighting "+startNode+' '+noteSelection+' '+annoteText+"\n"); // debug
213                 highlightWord(document.getElementById(startNode),noteSelection,annoteText,rtid);
214
215         //        eval(method + '(\'\', result)');
216         }
217
218     } else {
219       //        dump("There was a problem retrieving the XML data:\n" + req.statusText+"\n"); //debug
220         }
221     }
222     //  else { dump("readyState was "+req.readyState+"\n"); } // debug
223
224 }
225
226
227
228 function postNote(xpath,selection,note) {
229
230
231
232
233 }
234
235 function onNoteifyMouseover() {
236 //this.onblur = onNoteifyBlur;
237
238 }
239
240 function onNoteifyBlur() {
241         noteNode = document.getElementById('noteify');
242 //      dump(noteNode);
243
244 //  window.location = 'http://localhost/cgi-bin/stet-submit.pl?foo=bar';
245 }
246
247 function checkKeyPressed(keyEvent) {
248   if (!document.getElementById("noteify")) {
249           keyEvent = (keyEvent) ? keyEvent : (window.event) ? event : null;
250           if (keyEvent) {
251                 var charCode = (keyEvent.charCode) ? keyEvent.charCode :
252                                            ((keyEvent.keyCode) ? keyEvent.keyCode :
253                                            ((keyEvent.which) ? keyEvent.which : 0));
254                 //dump(charCode);
255                 if (charCode == 99) { XpathSel(); }
256         
257           }
258   }
259 }
260
261 function cancelNote(div) {
262   if (cancelme = document.getElementById(div)) {
263     cancelme.parentNode.removeChild(cancelme);
264   }
265 }
266
267 function createNoteDiv() {
268
269 var noteifyDiv = document.createElement('form');
270 noteifyDiv.setAttribute('action','http://localhost/cgi-bin/stet-submit.pl');
271 noteifyDiv.setAttribute('class','noteify');
272 noteifyDiv.setAttribute('id','noteify');
273 noteifyDiv.setAttribute('name','noteify');
274 // noteifyDiv.style.z-index = '100';
275
276 var DomPathTxt = document.createElement('span');
277 DomPathTxt.setAttribute('id','DomPathTxt');
278 DomPathTxt.setAttribute('name','DomPathTxt');
279
280 var DomPath = document.createElement('input');
281 DomPath.setAttribute('id','DomPath');
282 DomPath.setAttribute('name','DomPath');
283 DomPath.setAttribute('type','hidden');
284
285 var SelectionTxt = document.createElement('span');
286 SelectionTxt.setAttribute('id','SelectionTxt');
287 SelectionTxt.setAttribute('name','SelectionTxt');
288
289 var Selection = document.createElement('input');
290 Selection.setAttribute('id','Selection');
291 Selection.setAttribute('name','Selection');
292 Selection.setAttribute('type','hidden');
293
294 var NoteText = document.createElement('textarea');
295 NoteText.setAttribute('id','NoteText');
296 NoteText.setAttribute('name','NoteText');
297 NoteText.setAttribute('rows','10');
298 NoteText.setAttribute('cols','30');
299
300 var StartNode = document.createElement('input');
301 StartNode.setAttribute('id','StartNode');
302 StartNode.setAttribute('name','StartNode');
303 StartNode.setAttribute('type','hidden');
304
305 var EndNode = document.createElement('input');
306 EndNode.setAttribute('id','EndNode');
307 EndNode.setAttribute('name','EndNode');
308 EndNode.setAttribute('type','hidden');
309
310 var StartNodeId = document.createElement('input');
311 StartNodeId.setAttribute('id','StartNodeId');
312 StartNodeId.setAttribute('name','StartNodeId');
313 StartNodeId.setAttribute('type','hidden');
314
315 var EndNodeId = document.createElement('input');
316 EndNodeId.setAttribute('id','EndNodeId');
317 EndNodeId.setAttribute('name','EndNodeId');
318 EndNodeId.setAttribute('type','hidden');
319
320 var NoteUrl = document.createElement('input');
321 NoteUrl.setAttribute('id','NoteUrl');
322 NoteUrl.setAttribute('name','NoteUrl');
323 NoteUrl.setAttribute('type','hidden');
324
325 var cancel = document.createElement('input');
326 cancel.setAttribute('type','button');
327 cancel.setAttribute('id','cancel');
328 cancel.setAttribute('name','cancel');
329 cancel.setAttribute('value','cancel');
330 cancel.setAttribute('onClick','cancelNote("noteify")');
331
332 var theBR = document.createElement('br');
333
334 var submit = document.createElement('input');
335 submit.setAttribute('type','button');
336 submit.setAttribute('value','submit');
337 //submit.onclick = 'dump("clicked submit")';
338 submit.setAttribute('onClick','submitComment()');
339
340 noteifyDiv.appendChild(DomPathTxt);
341 noteifyDiv.appendChild(DomPath);
342 noteifyDiv.appendChild(theBR);
343 noteifyDiv.appendChild(SelectionTxt);
344 noteifyDiv.appendChild(Selection);
345 noteifyDiv.appendChild(theBR);
346 noteifyDiv.appendChild(NoteText);
347 noteifyDiv.appendChild(StartNode);
348 noteifyDiv.appendChild(EndNode);
349 noteifyDiv.appendChild(StartNodeId);
350 noteifyDiv.appendChild(EndNodeId);
351 noteifyDiv.appendChild(NoteUrl);
352 noteifyDiv.appendChild(submit);
353 noteifyDiv.appendChild(cancel);
354
355 return noteifyDiv;
356
357 }
358
359
360
361 function highlightWord(node,word,tooltip,rtid,altClass) {
362
363 /* this code is basically no longer descended from: */
364 /*                                                 */
365 /* http://www.kryogenix.org/code/browser/searchhi/ */
366 /*                             */
367 /* but it started out that way ... */
368
369   var haveHighlighted = false;
370   //dump("doing highlightword of "+word+"\n");
371   if (node.hasChildNodes) {
372     var iCN;
373     //dump("this node has "+node.childNodes.length+" childNodes\n");
374     for (iCN=0;iCN<node.childNodes.length;iCN++) {
375       //dump("going in to "+node.childNodes[iCN].nodeName+"\nfor "+word+" iCN="+iCN+"\n");
376       highlightWord(node.childNodes[iCN],word,tooltip,rtid);
377     }
378   }
379   if (node.nodeType == 3) { // text node
380     dump("node is "+node.parentNode.id+"\n");
381     if (!haveHighlighted) {
382       //dump("haven't highlighted\n");
383     paragraph = node.parentNode.parentNode;
384     paragraphString = (new XMLSerializer).serializeToString(paragraph);
385     paragraphString.replace(/\s+/g,' ');
386     tempNodeVal = paragraphString;
387     tempWordVal = word;
388     //tempWordVal = tempWordVal.replace(/\W+/g,'[\\W\\s]+(<[^>]+>)?');
389     tempWordVal = tempWordVal.replace(/\W+/g,'[^<]*(<[^>]+>)*');
390
391     var re = new RegExp(tempWordVal, 'mi');
392         //    var re = new RegExp("software", 'mig');
393     //dump("re is "+re+"\n");
394     tooltipString = (new XMLSerializer).serializeToString(tooltip);
395     var ticketLink = rtid ? '<a href="/rt/Ticket/Display.html?id='+rtid+'">[+]</a>' : '[reload for ticket link]';
396     
397     paragraphString = paragraphString.replace(re,'<span class="highlight" id="note.'+rtid+'.'+node.parentNode.id+'">$&<span class="annotation">'+tooltipString+" "+ticketLink+' </span></span>');
398     //     dump("replaced on "+$&+"\n");
399     //dump("pString is now "+paragraphString+"\n");
400     node.parentNode.parentNode.innerHTML = paragraphString;
401     
402     //    haveHighlighted=true;
403     }
404   }
405 }
406
407
408
409
410 window.onload = loadXMLDoc('http://localhost/cgi-bin/rt-test.pl?NoteUrl='+location.href);