root / doc / build / html / _static / websupport.js @ 6de88ee1
History | View | Annotate | Download (24.7 kB)
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 |
*/
|
11 |
|
12 |
(function($) { |
13 |
$.fn.autogrow = function() { |
14 |
return this.each(function() { |
15 |
var textarea = this; |
16 |
|
17 |
$.fn.autogrow.resize(textarea);
|
18 |
|
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 |
}; |
30 |
|
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); |
43 |
|
44 |
(function($) { |
45 |
var comp, by;
|
46 |
|
47 |
function init() { |
48 |
initEvents(); |
49 |
initComparator(); |
50 |
} |
51 |
|
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 |
} |
102 |
|
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 |
} |
117 |
|
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 |
} |
122 |
|
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 |
} |
143 |
|
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 |
} |
164 |
|
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 |
} |
176 |
|
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);
|
192 |
|
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 |
} |
212 |
|
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(); |
221 |
|
222 |
if (text == '') { |
223 |
showError('Please enter a comment.');
|
224 |
return;
|
225 |
} |
226 |
|
227 |
// Disable the form that is being submitted.
|
228 |
form.find('textarea,input').attr('disabled', 'disabled'); |
229 |
|
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 |
} |
270 |
|
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 |
} |
285 |
|
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);
|
292 |
|
293 |
// To avoid stagnating data, don't store the comments children in data.
|
294 |
comment.children = null;
|
295 |
div.data('comment', comment);
|
296 |
|
297 |
var ul = $('#cl' + (comment.node || comment.parent)); |
298 |
var siblings = getChildren(ul);
|
299 |
|
300 |
var li = $(document.createElement('li')); |
301 |
li.hide(); |
302 |
|
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 |
} |
313 |
|
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 |
} |
319 |
|
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 |
} |
334 |
|
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 |
} |
368 |
|
369 |
function showProposal(id) { |
370 |
$('#sp' + id).hide(); |
371 |
$('#hp' + id).show(); |
372 |
$('#pr' + id).slideDown('fast'); |
373 |
} |
374 |
|
375 |
function hideProposal(id) { |
376 |
$('#hp' + id).hide(); |
377 |
$('#sp' + id).show(); |
378 |
$('#pr' + id).slideUp('fast'); |
379 |
} |
380 |
|
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 |
} |
389 |
|
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 |
} |
397 |
|
398 |
function toggleCommentMarkupBox(id) { |
399 |
$('#mb' + id).toggle(); |
400 |
} |
401 |
|
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 |
} |
422 |
|
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 |
} |
431 |
|
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 |
}; |
448 |
|
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(); |
453 |
|
454 |
// The div the comment is displayed in.
|
455 |
var div = $('div#cd' + d.comment_id); |
456 |
var data = div.data('comment'); |
457 |
|
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 |
} |
464 |
|
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);
|
469 |
|
470 |
// Change the rating text.
|
471 |
div.find('.rating:first')
|
472 |
.text(data.rating + ' point' + (data.rating == 1 ? '' : 's')); |
473 |
|
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 |
} |
484 |
|
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(); |
492 |
|
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 |
} |
512 |
|
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 |
}); |
521 |
|
522 |
// Swap out the hide link for the reply link
|
523 |
$('#cr' + id).hide(); |
524 |
$('#rl' + id).show(); |
525 |
} |
526 |
|
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 |
} |
537 |
|
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 |
} |
553 |
|
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)); |
568 |
|
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 |
} |
575 |
|
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 |
} |
587 |
|
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')); |
595 |
|
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 |
} |
603 |
|
604 |
return template.replace(/<([%#])([\w\.]*)\1>/g, function() { |
605 |
return handle(arguments[2], arguments[1] == '%' ? true : false); |
606 |
}); |
607 |
} |
608 |
|
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 |
} |
619 |
|
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 |
}; |
663 |
|
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 |
}; |
681 |
|
682 |
if (typeof COMMENT_OPTIONS != "undefined") { |
683 |
opts = jQuery.extend(opts, COMMENT_OPTIONS); |
684 |
} |
685 |
|
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 ▹\
|
710 |
</a>\
|
711 |
<a href="#" id="hc<%id%>" class="hide-propose-change">\
|
712 |
Propose a change ▿\
|
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>';
|
723 |
|
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 ▹</a>\
|
753 |
<a href="#" class="close-reply" id="cr<%id%>">reply ▿</a>\
|
754 |
<a href="#" id="sp<%id%>" class="show-proposal">proposal ▹</a>\
|
755 |
<a href="#" id="hp<%id%>" class="hide-proposal">proposal ▿</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>';
|
769 |
|
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>';
|
782 |
|
783 |
$(document).ready(function() { |
784 |
init(); |
785 |
}); |
786 |
})(jQuery); |
787 |
|
788 |
$(document).ready(function() { |
789 |
// add comment anchors for all paragraphs that are commentable
|
790 |
$('.sphinx-has-comment').comment(); |
791 |
|
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 |
}); |
801 |
|
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 |
} |
808 |
}); |