diff -r f5e18f8ed036 -r de4a2ed2f34b sphinx_django/static/comments.js --- /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( + 'No ' + plural + '' + + ''); +} + +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 ' ' + sign + ' ' + } + + // in fixes view - show proposed diff + function proposed_fix(c_flag, paragraph) { + if(!c_flag) { + return '' + + '' + + 'Fix: ' + paragraph + + '' + + '' + + " " + } + return ''; + } + + // for every comment/fix generate a 'Reply' button + function link_reply_to(id, comment_no) { + return 'Comment no.: ' + data[i].comment_no + + ' (reply).' + } + + /* */ + function delete_comment_button(db, id, comment_no) { + return 'delete' + } + + function commit_button(node, id, fix_no) { + return 'commit' + } + + function developers_actions(what, id, data, i) { + return '' + + '' + + 'Admin actions: ' + + delete_comment_button(what, id, data[i].comment_no) + + ', ' + + commit_button(node, id, data[i].comment_no) + + '.' + + '' + + '' + } + /* */ + + // add the comments for paragraph + for(i=0; i" + + "" + + "" + + "Name: " + data[i].name + ". " + + "(" + get_date(commentDate) + ")" + + '' + + '' + + '' + + '' + + ' Score: ' + data[i].score + '' + + 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) + + '' + + '' + + (isdev ? developers_actions(what, id, data, i) : '') + + ' ' + + proposed_fix(c_flag, data[i].paragraph_diff) + + "" + + "" + + 'Comment: ' + data[i].comment + + "" + + "" + + "
"); + } + + // add a button for showing/hiding the comments and post form + $("a[name*=" + singular + "_" + id + "]").replaceWith( + '' + + data.length + ' ' + what + '' + + ''); + + 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 '' + by + '' + } + + sort_hide_menu = '
' + + 'Hide' + + '' + + ' Sort by: ' + + sort_comments_by_button(what, id, 'date') + + ', ' + + sort_comments_by_button(what, id, 'score') + + ', ' + + sort_comments_by_button(what, id, 'thread') + + '.' + + '

' + + $('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_orig_' + id + ']').replaceWith( + ''); + + }); + +} + +// *** 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('
'); +} + +function empty_fixes(id) { + $('div[class=fixes_for_' + id + ']').replaceWith('
'); +} + +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('' + comment_no + ''); + $('textarea[name=replyto_' + id + ']').replaceWith(''); +} + +function new_thread(id) { + $('span[name=replyto_' + id + ']').replaceWith('new thread'); + $('textarea[name=replyto_' + id + ']').replaceWith(''); +} + +$(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); + }); +});