Mercurial > repos > yating-l > hac
comparison doc/_build/html/_static/websupport.js @ 0:0bca8a6364a7 draft default tip
planemo upload for repository https://github.com/Yating-L/hubarchivecreator-test commit 48b59e91e2dcc2e97735ee35d587960cbfbce932-dirty
| author | yating-l |
|---|---|
| date | Wed, 21 Dec 2016 17:21:18 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:0bca8a6364a7 |
|---|---|
| 1 /* | |
| 2 * websupport.js | |
| 3 * ~~~~~~~~~~~~~ | |
| 4 * | |
| 5 * sphinx.websupport utilities for all documentation. | |
| 6 * | |
| 7 * :copyright: Copyright 2007-2016 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 $(document).on("click", 'a.comment-close', function(event) { | |
| 54 event.preventDefault(); | |
| 55 hide($(this).attr('id').substring(2)); | |
| 56 }); | |
| 57 $(document).on("click", 'a.vote', function(event) { | |
| 58 event.preventDefault(); | |
| 59 handleVote($(this)); | |
| 60 }); | |
| 61 $(document).on("click", 'a.reply', function(event) { | |
| 62 event.preventDefault(); | |
| 63 openReply($(this).attr('id').substring(2)); | |
| 64 }); | |
| 65 $(document).on("click", 'a.close-reply', function(event) { | |
| 66 event.preventDefault(); | |
| 67 closeReply($(this).attr('id').substring(2)); | |
| 68 }); | |
| 69 $(document).on("click", 'a.sort-option', function(event) { | |
| 70 event.preventDefault(); | |
| 71 handleReSort($(this)); | |
| 72 }); | |
| 73 $(document).on("click", 'a.show-proposal', function(event) { | |
| 74 event.preventDefault(); | |
| 75 showProposal($(this).attr('id').substring(2)); | |
| 76 }); | |
| 77 $(document).on("click", 'a.hide-proposal', function(event) { | |
| 78 event.preventDefault(); | |
| 79 hideProposal($(this).attr('id').substring(2)); | |
| 80 }); | |
| 81 $(document).on("click", 'a.show-propose-change', function(event) { | |
| 82 event.preventDefault(); | |
| 83 showProposeChange($(this).attr('id').substring(2)); | |
| 84 }); | |
| 85 $(document).on("click", 'a.hide-propose-change', function(event) { | |
| 86 event.preventDefault(); | |
| 87 hideProposeChange($(this).attr('id').substring(2)); | |
| 88 }); | |
| 89 $(document).on("click", 'a.accept-comment', function(event) { | |
| 90 event.preventDefault(); | |
| 91 acceptComment($(this).attr('id').substring(2)); | |
| 92 }); | |
| 93 $(document).on("click", 'a.delete-comment', function(event) { | |
| 94 event.preventDefault(); | |
| 95 deleteComment($(this).attr('id').substring(2)); | |
| 96 }); | |
| 97 $(document).on("click", 'a.comment-markup', 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 <code>``code``</code>, \ | |
| 704 code blocks: <code>::</code> 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 }); |
