Upgraded phpmyadmin to 4.0.4 (All Languages) - No modifications yet
[openemr.git] / phpmyadmin / doc / html / _static / websupport.js
blobe9bd1b851c62bf625a2cac10d8da09526c440373
1 /*
2  * websupport.js
3  * ~~~~~~~~~~~~~
4  *
5  * sphinx.websupport utilties for all documentation.
6  *
7  * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
8  * :license: BSD, see LICENSE for details.
9  *
10  */
12 (function($) {
13   $.fn.autogrow = function() {
14     return this.each(function() {
15     var textarea = this;
17     $.fn.autogrow.resize(textarea);
19     $(textarea)
20       .focus(function() {
21         textarea.interval = setInterval(function() {
22           $.fn.autogrow.resize(textarea);
23         }, 500);
24       })
25       .blur(function() {
26         clearInterval(textarea.interval);
27       });
28     });
29   };
31   $.fn.autogrow.resize = function(textarea) {
32     var lineHeight = parseInt($(textarea).css('line-height'), 10);
33     var lines = textarea.value.split('\n');
34     var columns = textarea.cols;
35     var lineCount = 0;
36     $.each(lines, function() {
37       lineCount += Math.ceil(this.length / columns) || 1;
38     });
39     var height = lineHeight * (lineCount + 1);
40     $(textarea).css('height', height);
41   };
42 })(jQuery);
44 (function($) {
45   var comp, by;
47   function init() {
48     initEvents();
49     initComparator();
50   }
52   function initEvents() {
53     $('a.comment-close').live("click", function(event) {
54       event.preventDefault();
55       hide($(this).attr('id').substring(2));
56     });
57     $('a.vote').live("click", function(event) {
58       event.preventDefault();
59       handleVote($(this));
60     });
61     $('a.reply').live("click", function(event) {
62       event.preventDefault();
63       openReply($(this).attr('id').substring(2));
64     });
65     $('a.close-reply').live("click", function(event) {
66       event.preventDefault();
67       closeReply($(this).attr('id').substring(2));
68     });
69     $('a.sort-option').live("click", function(event) {
70       event.preventDefault();
71       handleReSort($(this));
72     });
73     $('a.show-proposal').live("click", function(event) {
74       event.preventDefault();
75       showProposal($(this).attr('id').substring(2));
76     });
77     $('a.hide-proposal').live("click", function(event) {
78       event.preventDefault();
79       hideProposal($(this).attr('id').substring(2));
80     });
81     $('a.show-propose-change').live("click", function(event) {
82       event.preventDefault();
83       showProposeChange($(this).attr('id').substring(2));
84     });
85     $('a.hide-propose-change').live("click", function(event) {
86       event.preventDefault();
87       hideProposeChange($(this).attr('id').substring(2));
88     });
89     $('a.accept-comment').live("click", function(event) {
90       event.preventDefault();
91       acceptComment($(this).attr('id').substring(2));
92     });
93     $('a.delete-comment').live("click", function(event) {
94       event.preventDefault();
95       deleteComment($(this).attr('id').substring(2));
96     });
97     $('a.comment-markup').live("click", function(event) {
98       event.preventDefault();
99       toggleCommentMarkupBox($(this).attr('id').substring(2));
100     });
101   }
103   /**
104    * Set comp, which is a comparator function used for sorting and
105    * inserting comments into the list.
106    */
107   function setComparator() {
108     // If the first three letters are "asc", sort in ascending order
109     // and remove the prefix.
110     if (by.substring(0,3) == 'asc') {
111       var i = by.substring(3);
112       comp = function(a, b) { return a[i] - b[i]; };
113     } else {
114       // Otherwise sort in descending order.
115       comp = function(a, b) { return b[by] - a[by]; };
116     }
118     // Reset link styles and format the selected sort option.
119     $('a.sel').attr('href', '#').removeClass('sel');
120     $('a.by' + by).removeAttr('href').addClass('sel');
121   }
123   /**
124    * Create a comp function. If the user has preferences stored in
125    * the sortBy cookie, use those, otherwise use the default.
126    */
127   function initComparator() {
128     by = 'rating'; // Default to sort by rating.
129     // If the sortBy cookie is set, use that instead.
130     if (document.cookie.length > 0) {
131       var start = document.cookie.indexOf('sortBy=');
132       if (start != -1) {
133         start = start + 7;
134         var end = document.cookie.indexOf(";", start);
135         if (end == -1) {
136           end = document.cookie.length;
137           by = unescape(document.cookie.substring(start, end));
138         }
139       }
140     }
141     setComparator();
142   }
144   /**
145    * Show a comment div.
146    */
147   function show(id) {
148     $('#ao' + id).hide();
149     $('#ah' + id).show();
150     var context = $.extend({id: id}, opts);
151     var popup = $(renderTemplate(popupTemplate, context)).hide();
152     popup.find('textarea[name="proposal"]').hide();
153     popup.find('a.by' + by).addClass('sel');
154     var form = popup.find('#cf' + id);
155     form.submit(function(event) {
156       event.preventDefault();
157       addComment(form);
158     });
159     $('#s' + id).after(popup);
160     popup.slideDown('fast', function() {
161       getComments(id);
162     });
163   }
165   /**
166    * Hide a comment div.
167    */
168   function hide(id) {
169     $('#ah' + id).hide();
170     $('#ao' + id).show();
171     var div = $('#sc' + id);
172     div.slideUp('fast', function() {
173       div.remove();
174     });
175   }
177   /**
178    * Perform an ajax request to get comments for a node
179    * and insert the comments into the comments tree.
180    */
181   function getComments(id) {
182     $.ajax({
183      type: 'GET',
184      url: opts.getCommentsURL,
185      data: {node: id},
186      success: function(data, textStatus, request) {
187        var ul = $('#cl' + id);
188        var speed = 100;
189        $('#cf' + id)
190          .find('textarea[name="proposal"]')
191          .data('source', data.source);
193        if (data.comments.length === 0) {
194          ul.html('<li>No comments yet.</li>');
195          ul.data('empty', true);
196        } else {
197          // If there are comments, sort them and put them in the list.
198          var comments = sortComments(data.comments);
199          speed = data.comments.length * 100;
200          appendComments(comments, ul);
201          ul.data('empty', false);
202        }
203        $('#cn' + id).slideUp(speed + 200);
204        ul.slideDown(speed);
205      },
206      error: function(request, textStatus, error) {
207        showError('Oops, there was a problem retrieving the comments.');
208      },
209      dataType: 'json'
210     });
211   }
213   /**
214    * Add a comment via ajax and insert the comment into the comment tree.
215    */
216   function addComment(form) {
217     var node_id = form.find('input[name="node"]').val();
218     var parent_id = form.find('input[name="parent"]').val();
219     var text = form.find('textarea[name="comment"]').val();
220     var proposal = form.find('textarea[name="proposal"]').val();
222     if (text == '') {
223       showError('Please enter a comment.');
224       return;
225     }
227     // Disable the form that is being submitted.
228     form.find('textarea,input').attr('disabled', 'disabled');
230     // Send the comment to the server.
231     $.ajax({
232       type: "POST",
233       url: opts.addCommentURL,
234       dataType: 'json',
235       data: {
236         node: node_id,
237         parent: parent_id,
238         text: text,
239         proposal: proposal
240       },
241       success: function(data, textStatus, error) {
242         // Reset the form.
243         if (node_id) {
244           hideProposeChange(node_id);
245         }
246         form.find('textarea')
247           .val('')
248           .add(form.find('input'))
249           .removeAttr('disabled');
250         var ul = $('#cl' + (node_id || parent_id));
251         if (ul.data('empty')) {
252           $(ul).empty();
253           ul.data('empty', false);
254         }
255         insertComment(data.comment);
256         var ao = $('#ao' + node_id);
257         ao.find('img').attr({'src': opts.commentBrightImage});
258         if (node_id) {
259           // if this was a "root" comment, remove the commenting box
260           // (the user can get it back by reopening the comment popup)
261           $('#ca' + node_id).slideUp();
262         }
263       },
264       error: function(request, textStatus, error) {
265         form.find('textarea,input').removeAttr('disabled');
266         showError('Oops, there was a problem adding the comment.');
267       }
268     });
269   }
271   /**
272    * Recursively append comments to the main comment list and children
273    * lists, creating the comment tree.
274    */
275   function appendComments(comments, ul) {
276     $.each(comments, function() {
277       var div = createCommentDiv(this);
278       ul.append($(document.createElement('li')).html(div));
279       appendComments(this.children, div.find('ul.comment-children'));
280       // To avoid stagnating data, don't store the comments children in data.
281       this.children = null;
282       div.data('comment', this);
283     });
284   }
286   /**
287    * After adding a new comment, it must be inserted in the correct
288    * location in the comment tree.
289    */
290   function insertComment(comment) {
291     var div = createCommentDiv(comment);
293     // To avoid stagnating data, don't store the comments children in data.
294     comment.children = null;
295     div.data('comment', comment);
297     var ul = $('#cl' + (comment.node || comment.parent));
298     var siblings = getChildren(ul);
300     var li = $(document.createElement('li'));
301     li.hide();
303     // Determine where in the parents children list to insert this comment.
304     for(i=0; i < siblings.length; i++) {
305       if (comp(comment, siblings[i]) <= 0) {
306         $('#cd' + siblings[i].id)
307           .parent()
308           .before(li.html(div));
309         li.slideDown('fast');
310         return;
311       }
312     }
314     // If we get here, this comment rates lower than all the others,
315     // or it is the only comment in the list.
316     ul.append(li.html(div));
317     li.slideDown('fast');
318   }
320   function acceptComment(id) {
321     $.ajax({
322       type: 'POST',
323       url: opts.acceptCommentURL,
324       data: {id: id},
325       success: function(data, textStatus, request) {
326         $('#cm' + id).fadeOut('fast');
327         $('#cd' + id).removeClass('moderate');
328       },
329       error: function(request, textStatus, error) {
330         showError('Oops, there was a problem accepting the comment.');
331       }
332     });
333   }
335   function deleteComment(id) {
336     $.ajax({
337       type: 'POST',
338       url: opts.deleteCommentURL,
339       data: {id: id},
340       success: function(data, textStatus, request) {
341         var div = $('#cd' + id);
342         if (data == 'delete') {
343           // Moderator mode: remove the comment and all children immediately
344           div.slideUp('fast', function() {
345             div.remove();
346           });
347           return;
348         }
349         // User mode: only mark the comment as deleted
350         div
351           .find('span.user-id:first')
352           .text('[deleted]').end()
353           .find('div.comment-text:first')
354           .text('[deleted]').end()
355           .find('#cm' + id + ', #dc' + id + ', #ac' + id + ', #rc' + id +
356                 ', #sp' + id + ', #hp' + id + ', #cr' + id + ', #rl' + id)
357           .remove();
358         var comment = div.data('comment');
359         comment.username = '[deleted]';
360         comment.text = '[deleted]';
361         div.data('comment', comment);
362       },
363       error: function(request, textStatus, error) {
364         showError('Oops, there was a problem deleting the comment.');
365       }
366     });
367   }
369   function showProposal(id) {
370     $('#sp' + id).hide();
371     $('#hp' + id).show();
372     $('#pr' + id).slideDown('fast');
373   }
375   function hideProposal(id) {
376     $('#hp' + id).hide();
377     $('#sp' + id).show();
378     $('#pr' + id).slideUp('fast');
379   }
381   function showProposeChange(id) {
382     $('#pc' + id).hide();
383     $('#hc' + id).show();
384     var textarea = $('#pt' + id);
385     textarea.val(textarea.data('source'));
386     $.fn.autogrow.resize(textarea[0]);
387     textarea.slideDown('fast');
388   }
390   function hideProposeChange(id) {
391     $('#hc' + id).hide();
392     $('#pc' + id).show();
393     var textarea = $('#pt' + id);
394     textarea.val('').removeAttr('disabled');
395     textarea.slideUp('fast');
396   }
398   function toggleCommentMarkupBox(id) {
399     $('#mb' + id).toggle();
400   }
402   /** Handle when the user clicks on a sort by link. */
403   function handleReSort(link) {
404     var classes = link.attr('class').split(/\s+/);
405     for (var i=0; i<classes.length; i++) {
406       if (classes[i] != 'sort-option') {
407         by = classes[i].substring(2);
408       }
409     }
410     setComparator();
411     // Save/update the sortBy cookie.
412     var expiration = new Date();
413     expiration.setDate(expiration.getDate() + 365);
414     document.cookie= 'sortBy=' + escape(by) +
415                      ';expires=' + expiration.toUTCString();
416     $('ul.comment-ul').each(function(index, ul) {
417       var comments = getChildren($(ul), true);
418       comments = sortComments(comments);
419       appendComments(comments, $(ul).empty());
420     });
421   }
423   /**
424    * Function to process a vote when a user clicks an arrow.
425    */
426   function handleVote(link) {
427     if (!opts.voting) {
428       showError("You'll need to login to vote.");
429       return;
430     }
432     var id = link.attr('id');
433     if (!id) {
434       // Didn't click on one of the voting arrows.
435       return;
436     }
437     // If it is an unvote, the new vote value is 0,
438     // Otherwise it's 1 for an upvote, or -1 for a downvote.
439     var value = 0;
440     if (id.charAt(1) != 'u') {
441       value = id.charAt(0) == 'u' ? 1 : -1;
442     }
443     // The data to be sent to the server.
444     var d = {
445       comment_id: id.substring(2),
446       value: value
447     };
449     // Swap the vote and unvote links.
450     link.hide();
451     $('#' + id.charAt(0) + (id.charAt(1) == 'u' ? 'v' : 'u') + d.comment_id)
452       .show();
454     // The div the comment is displayed in.
455     var div = $('div#cd' + d.comment_id);
456     var data = div.data('comment');
458     // If this is not an unvote, and the other vote arrow has
459     // already been pressed, unpress it.
460     if ((d.value !== 0) && (data.vote === d.value * -1)) {
461       $('#' + (d.value == 1 ? 'd' : 'u') + 'u' + d.comment_id).hide();
462       $('#' + (d.value == 1 ? 'd' : 'u') + 'v' + d.comment_id).show();
463     }
465     // Update the comments rating in the local data.
466     data.rating += (data.vote === 0) ? d.value : (d.value - data.vote);
467     data.vote = d.value;
468     div.data('comment', data);
470     // Change the rating text.
471     div.find('.rating:first')
472       .text(data.rating + ' point' + (data.rating == 1 ? '' : 's'));
474     // Send the vote information to the server.
475     $.ajax({
476       type: "POST",
477       url: opts.processVoteURL,
478       data: d,
479       error: function(request, textStatus, error) {
480         showError('Oops, there was a problem casting that vote.');
481       }
482     });
483   }
485   /**
486    * Open a reply form used to reply to an existing comment.
487    */
488   function openReply(id) {
489     // Swap out the reply link for the hide link
490     $('#rl' + id).hide();
491     $('#cr' + id).show();
493     // Add the reply li to the children ul.
494     var div = $(renderTemplate(replyTemplate, {id: id})).hide();
495     $('#cl' + id)
496       .prepend(div)
497       // Setup the submit handler for the reply form.
498       .find('#rf' + id)
499       .submit(function(event) {
500         event.preventDefault();
501         addComment($('#rf' + id));
502         closeReply(id);
503       })
504       .find('input[type=button]')
505       .click(function() {
506         closeReply(id);
507       });
508     div.slideDown('fast', function() {
509       $('#rf' + id).find('textarea').focus();
510     });
511   }
513   /**
514    * Close the reply form opened with openReply.
515    */
516   function closeReply(id) {
517     // Remove the reply div from the DOM.
518     $('#rd' + id).slideUp('fast', function() {
519       $(this).remove();
520     });
522     // Swap out the hide link for the reply link
523     $('#cr' + id).hide();
524     $('#rl' + id).show();
525   }
527   /**
528    * Recursively sort a tree of comments using the comp comparator.
529    */
530   function sortComments(comments) {
531     comments.sort(comp);
532     $.each(comments, function() {
533       this.children = sortComments(this.children);
534     });
535     return comments;
536   }
538   /**
539    * Get the children comments from a ul. If recursive is true,
540    * recursively include childrens' children.
541    */
542   function getChildren(ul, recursive) {
543     var children = [];
544     ul.children().children("[id^='cd']")
545       .each(function() {
546         var comment = $(this).data('comment');
547         if (recursive)
548           comment.children = getChildren($(this).find('#cl' + comment.id), true);
549         children.push(comment);
550       });
551     return children;
552   }
554   /** Create a div to display a comment in. */
555   function createCommentDiv(comment) {
556     if (!comment.displayed && !opts.moderator) {
557       return $('<div class="moderate">Thank you!  Your comment will show up '
558                + 'once it is has been approved by a moderator.</div>');
559     }
560     // Prettify the comment rating.
561     comment.pretty_rating = comment.rating + ' point' +
562       (comment.rating == 1 ? '' : 's');
563     // Make a class (for displaying not yet moderated comments differently)
564     comment.css_class = comment.displayed ? '' : ' moderate';
565     // Create a div for this comment.
566     var context = $.extend({}, opts, comment);
567     var div = $(renderTemplate(commentTemplate, context));
569     // If the user has voted on this comment, highlight the correct arrow.
570     if (comment.vote) {
571       var direction = (comment.vote == 1) ? 'u' : 'd';
572       div.find('#' + direction + 'v' + comment.id).hide();
573       div.find('#' + direction + 'u' + comment.id).show();
574     }
576     if (opts.moderator || comment.text != '[deleted]') {
577       div.find('a.reply').show();
578       if (comment.proposal_diff)
579         div.find('#sp' + comment.id).show();
580       if (opts.moderator && !comment.displayed)
581         div.find('#cm' + comment.id).show();
582       if (opts.moderator || (opts.username == comment.username))
583         div.find('#dc' + comment.id).show();
584     }
585     return div;
586   }
588   /**
589    * A simple template renderer. Placeholders such as <%id%> are replaced
590    * by context['id'] with items being escaped. Placeholders such as <#id#>
591    * are not escaped.
592    */
593   function renderTemplate(template, context) {
594     var esc = $(document.createElement('div'));
596     function handle(ph, escape) {
597       var cur = context;
598       $.each(ph.split('.'), function() {
599         cur = cur[this];
600       });
601       return escape ? esc.text(cur || "").html() : cur;
602     }
604     return template.replace(/<([%#])([\w\.]*)\1>/g, function() {
605       return handle(arguments[2], arguments[1] == '%' ? true : false);
606     });
607   }
609   /** Flash an error message briefly. */
610   function showError(message) {
611     $(document.createElement('div')).attr({'class': 'popup-error'})
612       .append($(document.createElement('div'))
613                .attr({'class': 'error-message'}).text(message))
614       .appendTo('body')
615       .fadeIn("slow")
616       .delay(2000)
617       .fadeOut("slow");
618   }
620   /** Add a link the user uses to open the comments popup. */
621   $.fn.comment = function() {
622     return this.each(function() {
623       var id = $(this).attr('id').substring(1);
624       var count = COMMENT_METADATA[id];
625       var title = count + ' comment' + (count == 1 ? '' : 's');
626       var image = count > 0 ? opts.commentBrightImage : opts.commentImage;
627       var addcls = count == 0 ? ' nocomment' : '';
628       $(this)
629         .append(
630           $(document.createElement('a')).attr({
631             href: '#',
632             'class': 'sphinx-comment-open' + addcls,
633             id: 'ao' + id
634           })
635             .append($(document.createElement('img')).attr({
636               src: image,
637               alt: 'comment',
638               title: title
639             }))
640             .click(function(event) {
641               event.preventDefault();
642               show($(this).attr('id').substring(2));
643             })
644         )
645         .append(
646           $(document.createElement('a')).attr({
647             href: '#',
648             'class': 'sphinx-comment-close hidden',
649             id: 'ah' + id
650           })
651             .append($(document.createElement('img')).attr({
652               src: opts.closeCommentImage,
653               alt: 'close',
654               title: 'close'
655             }))
656             .click(function(event) {
657               event.preventDefault();
658               hide($(this).attr('id').substring(2));
659             })
660         );
661     });
662   };
664   var opts = {
665     processVoteURL: '/_process_vote',
666     addCommentURL: '/_add_comment',
667     getCommentsURL: '/_get_comments',
668     acceptCommentURL: '/_accept_comment',
669     deleteCommentURL: '/_delete_comment',
670     commentImage: '/static/_static/comment.png',
671     closeCommentImage: '/static/_static/comment-close.png',
672     loadingImage: '/static/_static/ajax-loader.gif',
673     commentBrightImage: '/static/_static/comment-bright.png',
674     upArrow: '/static/_static/up.png',
675     downArrow: '/static/_static/down.png',
676     upArrowPressed: '/static/_static/up-pressed.png',
677     downArrowPressed: '/static/_static/down-pressed.png',
678     voting: false,
679     moderator: false
680   };
682   if (typeof COMMENT_OPTIONS != "undefined") {
683     opts = jQuery.extend(opts, COMMENT_OPTIONS);
684   }
686   var popupTemplate = '\
687     <div class="sphinx-comments" id="sc<%id%>">\
688       <p class="sort-options">\
689         Sort by:\
690         <a href="#" class="sort-option byrating">best rated</a>\
691         <a href="#" class="sort-option byascage">newest</a>\
692         <a href="#" class="sort-option byage">oldest</a>\
693       </p>\
694       <div class="comment-header">Comments</div>\
695       <div class="comment-loading" id="cn<%id%>">\
696         loading comments... <img src="<%loadingImage%>" alt="" /></div>\
697       <ul id="cl<%id%>" class="comment-ul"></ul>\
698       <div id="ca<%id%>">\
699       <p class="add-a-comment">Add a comment\
700         (<a href="#" class="comment-markup" id="ab<%id%>">markup</a>):</p>\
701       <div class="comment-markup-box" id="mb<%id%>">\
702         reStructured text markup: <i>*emph*</i>, <b>**strong**</b>, \
703         <tt>``code``</tt>, \
704         code blocks: <tt>::</tt> and an indented block after blank line</div>\
705       <form method="post" id="cf<%id%>" class="comment-form" action="">\
706         <textarea name="comment" cols="80"></textarea>\
707         <p class="propose-button">\
708           <a href="#" id="pc<%id%>" class="show-propose-change">\
709             Propose a change &#9657;\
710           </a>\
711           <a href="#" id="hc<%id%>" class="hide-propose-change">\
712             Propose a change &#9663;\
713           </a>\
714         </p>\
715         <textarea name="proposal" id="pt<%id%>" cols="80"\
716                   spellcheck="false"></textarea>\
717         <input type="submit" value="Add comment" />\
718         <input type="hidden" name="node" value="<%id%>" />\
719         <input type="hidden" name="parent" value="" />\
720       </form>\
721       </div>\
722     </div>';
724   var commentTemplate = '\
725     <div id="cd<%id%>" class="sphinx-comment<%css_class%>">\
726       <div class="vote">\
727         <div class="arrow">\
728           <a href="#" id="uv<%id%>" class="vote" title="vote up">\
729             <img src="<%upArrow%>" />\
730           </a>\
731           <a href="#" id="uu<%id%>" class="un vote" title="vote up">\
732             <img src="<%upArrowPressed%>" />\
733           </a>\
734         </div>\
735         <div class="arrow">\
736           <a href="#" id="dv<%id%>" class="vote" title="vote down">\
737             <img src="<%downArrow%>" id="da<%id%>" />\
738           </a>\
739           <a href="#" id="du<%id%>" class="un vote" title="vote down">\
740             <img src="<%downArrowPressed%>" />\
741           </a>\
742         </div>\
743       </div>\
744       <div class="comment-content">\
745         <p class="tagline comment">\
746           <span class="user-id"><%username%></span>\
747           <span class="rating"><%pretty_rating%></span>\
748           <span class="delta"><%time.delta%></span>\
749         </p>\
750         <div class="comment-text comment"><#text#></div>\
751         <p class="comment-opts comment">\
752           <a href="#" class="reply hidden" id="rl<%id%>">reply &#9657;</a>\
753           <a href="#" class="close-reply" id="cr<%id%>">reply &#9663;</a>\
754           <a href="#" id="sp<%id%>" class="show-proposal">proposal &#9657;</a>\
755           <a href="#" id="hp<%id%>" class="hide-proposal">proposal &#9663;</a>\
756           <a href="#" id="dc<%id%>" class="delete-comment hidden">delete</a>\
757           <span id="cm<%id%>" class="moderation hidden">\
758             <a href="#" id="ac<%id%>" class="accept-comment">accept</a>\
759           </span>\
760         </p>\
761         <pre class="proposal" id="pr<%id%>">\
762 <#proposal_diff#>\
763         </pre>\
764           <ul class="comment-children" id="cl<%id%>"></ul>\
765         </div>\
766         <div class="clearleft"></div>\
767       </div>\
768     </div>';
770   var replyTemplate = '\
771     <li>\
772       <div class="reply-div" id="rd<%id%>">\
773         <form id="rf<%id%>">\
774           <textarea name="comment" cols="80"></textarea>\
775           <input type="submit" value="Add reply" />\
776           <input type="button" value="Cancel" />\
777           <input type="hidden" name="parent" value="<%id%>" />\
778           <input type="hidden" name="node" value="" />\
779         </form>\
780       </div>\
781     </li>';
783   $(document).ready(function() {
784     init();
785   });
786 })(jQuery);
788 $(document).ready(function() {
789   // add comment anchors for all paragraphs that are commentable
790   $('.sphinx-has-comment').comment();
792   // highlight search words in search results
793   $("div.context").each(function() {
794     var params = $.getQueryParameters();
795     var terms = (params.q) ? params.q[0].split(/\s+/) : [];
796     var result = $(this);
797     $.each(terms, function() {
798       result.highlightText(this.toLowerCase(), 'highlighted');
799     });
800   });
802   // directly open comment window if requested
803   var anchor = document.location.hash;
804   if (anchor.substring(0, 9) == '#comment-') {
805     $('#ao' + anchor.substring(9)).click();
806     document.location.hash = '#s' + anchor.substring(9);
807   }