--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sphinx_django/static/#comments.js# Wed Oct 27 13:59:11 2010 +0530
@@ -0,0 +1,587 @@
+/*
+ * Java Script/JQuery glue for server-side Python code and the comments/fixes
+ * stuff which is being served along with the documentation.
+ *
+ * :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ * Below is a short description of the main functions used to make the tool
+ * work. Internal functions are not listed here.
+ *
+ **
+ *** checking/downloading/printing/adding comments and fixes ****************
+ **
+ *
+ * load_comments(id) -> check if database file with comments for paragraph 'id'
+ * exists on the server; if yes, invoke comments_found()
+ * function; if not, invoke no_comments() function.
+ *
+ * load_fixes(id) -> check if database file with fixes for paragraph 'id'
+ * exists on the server; if yes, invoke fixes_found()
+ * function; if not, invoke no_fixes() function.
+ *
+ * no_comments(id) -> insert a link ('No comments') to the post form after
+ * the paragraph 'id'.
+ *
+ * no_fixes(id) -> insert a link ('No fixes') to the post form after the
+ * 'No comments' string.
+ *
+ * comments_found(id) -> download the comments database file for paragraph 'id'
+ * and print it under the paragraph.
+ *
+ * fixes_found(id) -> download the fixes database file for paragraph 'id'
+ * and print it under the paragraph.
+ *
+ * print_comments(id, data) -> print comments collected in an array 'data'
+ * under the paragraph 'id'.
+ * 'data' is an array of objects; every object
+ * has properties like 'name', 'score', 'comment'.
+ * This function also prints a link at the end
+ * of paragraph with a number of comments hidden
+ * (i.e. "3 Comments").
+ *
+ * print_fixes(id, data) -> print fixes collected in an array 'data' under
+ * the paragraph 'id'.
+ * The description for print_comments() applies.
+ *
+ * add_new_comment(id) -> ajaxify a comment post form for paragraph 'id'
+ * and reload comments (with load_comments() function).
+ * This function also validates the form and resets
+ * it on successful submit.
+ *
+ **
+ *** displaying/hiding areas *************************************************
+ **
+ *
+ * show_hide_comments(id) -> hide fixes area, show comments area and make sure
+ * that the main comments/fixes area is shown
+ *
+ * show_hide_fixes(id) -> hide comments area, show fixes area and make sure
+ * that the main comments/fixes area is shown
+ *
+ * show_hide_submitFixFields(id) -> show/hide additional fields in the post
+ * form for fixes view (when 'I would like
+ * to submit a patch' checkbox is 'true')
+ * and fill them with data if needed
+ *
+ *
+ **
+ *** rating comments/fixes ***************************************************
+ **
+ *
+ * comments_up_down(id, comment_no, up_down, db)
+ * -> send a GET request to the server with three parameters:
+ * - id: paragraph id,
+ * - comment_no: a number of a comment to score,
+ * - up_down: two values possible: 'up' or 'down'
+ * depending on what kind of action should
+ * be taken ('up' means score+=1, and down
+ * means score-=1).
+ *
+ **
+ *** sorting comments/fixes ************************************************
+ **
+ *
+ * sort_comments(id, by, db) -> sort comments for paragraph 'id' by 'by' argument
+ * (two values for 'by' are possible at the moment:
+ * 'score' and 'date'). The sorting order changes
+ * automatically from increasing to decreasing with
+ * every sort.
+ *
+ *
+ **
+ *** threading ************************************************************
+ **
+ *
+ * new_thread(id) -> make a particular comment a new thread before submitting
+ * it
+ *
+ * reply_to(id, comment_no) -> make a comment a reply to comment 'comment_no'
+ *
+ **
+ *** developer's actions ***************************************************
+ **
+ *
+ * delete_comment(db, id, comment_no) -> delete entry from database 'db'
+ * located in 'id' file under
+ * 'comment_no' index
+ *
+ * commit_fix(node, id, fix_no) -> commit a fix located in 'id' file under
+ * 'fix_no' index to the repository
+ *
+ **
+ *** general-use functions ************************************************
+ **
+ *
+ * empty_comments(id) -> empty the comments area
+ *
+ * empty_fixes(id) -> empty the fixes area
+ *
+ * is_developer() -> returns true when developer rights should be granted
+ * and false when the rights should not be granted.
+ * At jQuery level it's only about displaying some
+ * additional/developer-only-options. Real authorization
+ * is going on on webapp (appserver.py) level.
+ */
+
+comments_path = "/comments/";
+fixes_path = "/fixes/";
+_db = undefined;
+
+// *** checking/downloading/printing/adding comments ************************
+
+function load_generic(what, id, error_func, success_func) {
+ // if the div was filled with the comments before, empty it before appending
+ if(_db == 'comments') {
+ empty_comments(id);
+ } else {
+ empty_fixes(id);
+ }
+
+ // 'what' -> 'comments_path' or 'fixes_path' variables;
+ var c_path = location.protocol + "//" + location.host + what + id;
+ $.ajax({ url: c_path,
+ type: 'HEAD',
+ error: function() { error_func(id) },
+ success: function() { success_func(id)}
+ });
+}
+
+function load_comments(id) {
+ return load_generic(comments_path, id, no_comments, comments_found)
+}
+
+function load_fixes(id) {
+ return load_generic(fixes_path, id, no_fixes, fixes_found)
+}
+
+function get_load_cf(db) {
+ if(db == 'comments' || db == comments_path) {
+ return load_comments;
+ }
+ return load_fixes;
+}
+
+//////////////////////
+
+function not_found_generic(what, id) {
+ // 'what' -> 'comment' or 'fix' strings
+ plural = what=='comment'?'comments':'fixes';
+ $("a[name*=" + what + "_" + id + "]").replaceWith(
+ '<a name="' + what + '_' + id + '" href="#' + id + '" '
+ + 'onclick="show_hide_' + plural + '(\'' + id + '\')" '
+ + 'id="' + id + '">No ' + plural + '</a>'
+ + '<a name="' + id + '"></a>');
+}
+
+function no_comments(id) {
+ not_found_generic('comment', id);
+}
+
+function no_fixes(id) {
+ not_found_generic('fix', id);
+}
+
+//////////////////////////////
+
+function found_generic(what, id, print_func) {
+ var c_path = location.protocol + "//" + location.host + what + id + "?id=" + id;
+ $.getJSON(c_path, function(data) {
+ print_func(id, data);
+ });
+}
+
+function comments_found(id) {
+ found_generic(comments_path, id, print_comments);
+}
+
+function fixes_found(id) {
+ found_generic(fixes_path, id, print_fixes);
+}
+
+///////////////////////////////
+
+function print_generic(what, id, data) {
+ var c_flag = (what == 'comments') ? true : false;
+ var singular = (what == 'comments') ? 'comment' : 'fix';
+ var isdev = is_developer();
+ var node = $('div[class=submitFixFields_' + id + ']').attr('value');
+
+ if(what == 'comments') {
+ empty_comments(id);
+ } else {
+ empty_fixes(id);
+ }
+
+ // A 'factory' function which generates '+' and '-' buttons for every comment.
+ // 'what' is a kind of database (db for comments or for fixes)
+ // 'id' is a paragraph id.
+ // 'comment_no' is a place of a comment in the list of comments for given
+ // paragraph.
+ // 'up_down' is passed to POST method. It should be 'up' or 'down'.
+ // 'sign' is what's displayed on the button, by default it's '+' or '-'.
+ function rate_comment_up_down_button(what, id, comment_no, up_down, sign) {
+ return ' <a href="#' + id + '" onclick="comments_up_down(\'' + id + '\', \'' + comment_no + '\', \'' + up_down + '\', \'' + what + '\')"><b>' + sign + '</b></a> '
+ }
+
+ // in fixes view - show proposed diff
+ function proposed_fix(c_flag, paragraph) {
+ if(!c_flag) {
+ return '<tr>'
+ + '<td>'
+ + 'Fix: ' + paragraph
+ + '</td>'
+ + '</tr>'
+ + "<tr><td> </td></tr>"
+ }
+ return '';
+ }
+
+ // for every comment/fix generate a 'Reply' button
+ function link_reply_to(id, comment_no) {
+ return 'Comment no.: ' + data[i].comment_no
+ + ' (<a href="#" onclick="reply_to(\'' + id + '\', \'' + comment_no + '\')">reply</a>).'
+ }
+
+ /* <developer's actions> */
+ function delete_comment_button(db, id, comment_no) {
+ return '<a href="#" onclick="delete_comment(\'' + db + '\', \'' + id + '\', \'' + comment_no + '\')">delete</a>'
+ }
+
+ function commit_button(node, id, fix_no) {
+ return '<a href="#" onclick="commit_fix(\'' + node + '\', \'' + id + '\', \''
+ + fix_no + '\')">commit</a>'
+ }
+
+ function developers_actions(what, id, data, i) {
+ return '<tr>'
+ + '<td>'
+ + 'Admin actions: '
+ + delete_comment_button(what, id, data[i].comment_no)
+ + ', '
+ + commit_button(node, id, data[i].comment_no)
+ + '.'
+ + '</td>'
+ + '</tr>'
+ }
+ /* </developer's actions> */
+
+ // add the comments for paragraph
+ for(i=0; i<data.length; i++) {
+ // 'data[i]['date'] * 1000' to convert from milliseconds to seconds
+ var commentDate = new Date(data[i]['date']*1000);
+
+ $('div[class*=' + what + '_for_' + id + ']').append(
+ "<table name='" + id + "' width='" + data[i].width + "%' align=center "
+ + "style='background-color: #f1ffc5; border: solid 1px lightblue;'>"
+ + "<tr>"
+ + "<td>"
+ + "Name: <a href='" + data[i].url + "'>" + data[i].name + "</a>. "
+ + "(" + get_date(commentDate) + ")"
+ + '</td>'
+ + '</tr>'
+ + '<tr>'
+ + '<td>'
+ + ' Score: <span class="score"><b>' + data[i].score + '</b></span>'
+ + rate_comment_up_down_button(what, id, data[i].comment_no, 'up', '+')
+ + rate_comment_up_down_button(what, id, data[i].comment_no, 'down', '-')
+ + '. '
+ + link_reply_to(id, data[i].comment_no)
+ + '</td>'
+ + '</tr>'
+ + (isdev ? developers_actions(what, id, data, i) : '')
+ + '<tr><td> </td></tr>'
+ + proposed_fix(c_flag, data[i].paragraph_diff)
+ + "<tr>"
+ + "<td>"
+ + 'Comment: ' + data[i].comment
+ + "</td>"
+ + "</tr>"
+ + "</table><br>");
+ }
+
+ // add a button for showing/hiding the comments and post form
+ $("a[name*=" + singular + "_" + id + "]").replaceWith(
+ '<a name="' + singular + '_' + id
+ + '" href="#' + id + '"' +
+ 'onclick="show_hide_' + what + '(\'' +
+ id + '\')" '
+ + 'id="' + id + '">'
+ + data.length + ' ' + what + '</a>'
+ + '<a name="' + id + '"></a>');
+
+ if(what == 'comments') {
+ hide_fixes(id);
+ show_comments(id);
+ } else {
+ hide_comments(id);
+ show_fixes(id);
+ }
+}
+
+
+function print_comments(id, data) {
+ print_generic('comments', id, data);
+}
+
+function print_fixes(id, data) {
+ print_generic('fixes', id, data);
+}
+
+/////////////////////////////
+
+function add_new_comment(id) {
+ function validate(formData, jqForm, options) {
+ var form = jqForm[0];
+ if(!form.name.value) {
+ alert("Please provide your name");
+ return false;
+ } else if(!form.comment.value) {
+ alert("Please provide your comment");
+ return false;
+ } else if(form.submitFix.checked && !form.licence.checked) {
+ alert("You have to agree to publish your fix on our licence!");
+ return false;
+ }
+
+ if(form.submitFix.checked) {
+ _db = 'fixes';
+ } else {
+ _db = 'comments';
+ }
+ }
+
+ function form_reset() {
+ $('#commentForm_' + id).resetForm()
+ new_thread(id);
+ if(_db == 'comments') {
+ load_comments(id);
+ } else {
+ load_fixes(id);
+ }
+ }
+
+ // bind 'commentForm' and provide a simple callback function
+ $('#commentForm_' + id).ajaxForm({
+ beforeSubmit: validate,
+ success: form_reset
+ });
+}
+
+//////////////////////////////
+
+function hide_main_div(id) {
+ $('div.x' + id).css('display', 'none');
+}
+
+function show_main_div(id) {
+ $('div.x' + id).css('display', 'block');
+}
+
+function hide_submitFixFields(id) {
+ $('div.submitFixFields_' + id).css('display', 'none');
+}
+
+function show_submitFixFields(id) {
+ node = $('div[class=submitFixFields_' + id + ']').attr('value');
+ fill_paragraph_from_repo(node, id);
+ $('input[name=submitFix]').attr('checked', true);
+ $('div.submitFixFields_' + id).css('display', 'block');
+ _db = 'fixes';
+
+}
+
+function hide_comments(id) {
+ $('input[name=submitFix]').attr('checked', false);
+ $('div.comments_for_' + id).css('display', 'none');
+}
+
+function hide_fixes(id) {
+ $('div.fixes_for_' + id).css('display', 'none');
+ hide_submitFixFields(id);
+}
+
+function show_comments(id) {
+ $('input[name=submitFix]').attr('checked', false);
+ $('div.comments_for_' + id).css('display', 'block');
+ _db = 'comments';
+}
+
+function show_fixes(id) {
+ $('div.fixes_for_' + id).css('display', 'block');
+ show_submitFixFields(id);
+}
+
+function mainDivIsHidden(id) {
+ return $('div.x' + id).is(':hidden');
+}
+
+function show_menu_hide(what, id) {
+ function sort_comments_by_button(what, id, by) {
+ return '<a href="#" onclick="sort_comments(\'' + id + '\', \'' + by + '\', \'' + what + '\')">' + by + '</a>'
+ }
+
+ sort_hide_menu = '<table style="background: #d9fff0; border: #008f57 1px solid;" width="100%"><tr><td>'
+ + '<a name="hide_main_div_'
+ + id
+ + '" href="#" onclick="hide_main_div(\''
+ + id
+ +'\')">Hide</a>'
+ + '</td><td>'
+ + ' Sort by: '
+ + sort_comments_by_button(what, id, 'date')
+ + ', '
+ + sort_comments_by_button(what, id, 'score')
+ + ', '
+ + sort_comments_by_button(what, id, 'thread')
+ + '.'
+ + '</td></tr></table><br>'
+
+ $('div[class=hide_menu_' + id + ']').replaceWith(sort_hide_menu);
+}
+
+function show_hide_comments(id) {
+ show_menu_hide('comments', id);
+ hide_fixes(id);
+ show_comments(id);
+
+ if(mainDivIsHidden(id)) {
+ show_main_div(id);
+ }
+}
+
+function show_hide_fixes(id) {
+ show_menu_hide('fixes', id);
+ hide_comments(id);
+ show_fixes(id);
+
+ if(mainDivIsHidden(id)) {
+ show_main_div(id);
+ }
+}
+
+function show_hide_submitFixFields(id) {
+ // show or hide more form fields when 'i would like to submit a fix' is true
+ var fixes_area_hidden = $('div.submitFixFields_'+id).is(':hidden');
+ if(fixes_area_hidden) {
+ show_submitFixFields(id);
+ } else {
+ hide_submitFixFields(id);
+ }
+}
+
+function fill_paragraph_from_repo(node, id) {
+ var p_path = location.protocol + "//" + location.host
+ + "/get_paragraph?node=" + node + "&id=" + id;
+ $.getJSON(p_path, function(data) {
+ $('textarea[name=paragraph_' + id + ']').replaceWith(
+ '<textarea name="paragraph_' + id + '" rows=10 cols=70>' + data + '</textarea>');
+ $('textarea[name=paragraph_orig_' + id + ']').replaceWith(
+ '<textarea name="paragraph_orig_' + id + '" style="display: none;">' + data + '</textarea>');
+
+ });
+
+}
+
+// *** rating comments ******************************************************
+
+function comments_up_down(id, comment_no, up_down, db) {
+ // request for a 'score' change
+ load_func = get_load_cf(db);
+ var rate_path = location.protocol + "//" + location.host + "/rate_comment";
+ $.ajax({ url: rate_path,
+ type: 'GET',
+ data: "id=" + id + "&comment_no=" + comment_no + "&up_down=" + up_down + "&db=" + db,
+ success: function() { load_func(id)}
+ });
+}
+
+// *** developer actions ****************************************************
+
+function delete_comment(db, id, comment_no) {
+ load_func = get_load_cf(db);
+ var rate_path = location.protocol + "//" + location.host + "/delete_comment";
+ $.ajax({ url: rate_path,
+ type: 'GET',
+ data: "id=" + id + "&cno=" + comment_no + "&db=" + db,
+ success: function() { load_func(id)}
+ });
+}
+
+function commit_fix(node, id, fix_no) {
+ var c_path = location.protocol + "//" + location.host + "/commit_fix";
+ $.ajax({ url: c_path,
+ type: 'GET',
+ data: "node=" + node + "&id=" + id + "&fix_no=" + fix_no,
+ success: function() { load_func(id)}
+ });
+}
+
+// *** sorting comments *****************************************************
+
+function sort_comments(id, by, db) {
+ // request for a sort of comments, display json data structure ('data')
+ var c_path = location.protocol + "//" + location.host
+ + "/sort_comments?id=" + id + "&by=" + by + "&db=" + db;
+ $.getJSON(c_path, function(data) {
+ if(db=='comments') {
+ print_comments(id, data);
+ } else {
+ print_fixes(id, data);
+ }
+ });
+}
+
+// *** general-use functions ***********************************************
+
+function empty_comments(id) {
+ $('div[class=comments_for_' + id + ']').replaceWith('<div class="comments_for_' + id + '" style=\"display: none;\"> </div>');
+}
+
+function empty_fixes(id) {
+ $('div[class=fixes_for_' + id + ']').replaceWith('<div class="fixes_for_' + id + '" style=\"display: none;\"> </div>');
+}
+
+function is_developer() {
+ var isdev_path = location.protocol + "//" + location.host + "/isdeveloper";
+ http = new XMLHttpRequest();
+ http.open('HEAD', isdev_path, false);
+ http.send(null);
+ return http.status!=404;
+}
+
+function get_date(d) {
+ var month=["January", "February", "March", "April",
+ "May", "June", "July", "August",
+ "September", "October", "November", "December"];
+ var t_date = d.getDate(); // Returns the day of the month
+ var t_mon = d.getMonth(); // Returns the month as a digit
+ var t_year = d.getFullYear(); // Returns 4 digit year
+ var t_hour = d.getHours(); // Returns hours
+ var t_min = d.getMinutes(); // Returns minutes
+ var t_sec = d.getSeconds(); // Returns seocnds
+ return t_hour + ':'
+ + (t_min < 10 ? '0' : '') + t_min
+ + ', ' + month[t_mon] + ' ' + t_date + ' ' + t_year
+}
+
+// *** threading **********************************************************
+
+function reply_to(id, comment_no) {
+ $('span[name=replyto_' + id + ']').replaceWith('<span name="replyto_' + id + '">' + comment_no + '</span>');
+ $('textarea[name=replyto_' + id + ']').replaceWith('<textarea name="replyto_' + id + '" style="display: none;">' + comment_no + '</textarea>');
+}
+
+function new_thread(id) {
+ $('span[name=replyto_' + id + ']').replaceWith('<span name="replyto_' + id + '">new thread</span>');
+ $('textarea[name=replyto_' + id + ']').replaceWith('<textarea name="replyto_' + id + '" style="display: none;"></textarea>');
+}
+
+$(document).ready(function() {
+ // load the comments for each paragraph when the DOM is ready
+ $("span[name*=paragraph]").each(function() {
+ var id = $(this).attr('value');
+ load_comments(id);
+ load_fixes(id);
+ });
+});