diff options
author | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2010-11-15 23:17:34 -0500 |
---|---|---|
committer | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2010-11-15 23:17:34 -0500 |
commit | 9ce190aeb919b675ec9e3a3485018b7e8f7ca1bd (patch) | |
tree | f369de90240920916532488b9697c38c93f573a0 | |
parent | 2889f326334a23196dbf283d4c8e6fdb044df954 (diff) | |
download | askbot-9ce190aeb919b675ec9e3a3485018b7e8f7ca1bd.tar.gz askbot-9ce190aeb919b675ec9e3a3485018b7e8f7ca1bd.tar.bz2 askbot-9ce190aeb919b675ec9e3a3485018b7e8f7ca1bd.zip |
edit comment form shows signs of life
-rw-r--r-- | askbot/skins/default/media/js/post.js | 83 | ||||
-rw-r--r-- | askbot/skins/default/media/js/utils.js | 12 | ||||
-rw-r--r-- | askbot/skins/default/templates/base.html | 1 | ||||
-rw-r--r-- | askbot/skins/default/templates/question.html | 621 | ||||
-rw-r--r-- | askbot/urls.py | 10 | ||||
-rw-r--r-- | askbot/utils/http.py | 34 | ||||
-rw-r--r-- | askbot/views/readers.py | 19 | ||||
-rw-r--r-- | askbot/views/writers.py | 2 |
8 files changed, 443 insertions, 339 deletions
diff --git a/askbot/skins/default/media/js/post.js b/askbot/skins/default/media/js/post.js index acc63d5c..e809886c 100644 --- a/askbot/skins/default/media/js/post.js +++ b/askbot/skins/default/media/js/post.js @@ -891,14 +891,17 @@ var EditCommentForm = function(){ this._comment_widget = null; this._element = null; this._text = ''; + this._id = 'edit-comment-form'; }; inherits(EditCommentForm, WrappedElement); -EditCommentForm.prototype.setComment = function(comment, text){ +EditCommentForm.prototype.getElement = function(){ + EditCommentForm.superClass_.getElement.call(this); + this._textarea.val(this._text); + return this._element; }; EditCommentForm.prototype.attachTo = function(comment){ - var form = editCommentForm.setComment(comment); this._comment = comment; this._comment_widget = comment.getContainerWidget(); this._text = comment.getText(); @@ -906,7 +909,8 @@ EditCommentForm.prototype.attachTo = function(comment){ comment.getElement().hide(); this._comment_widget.hideButton(); this.getElement().show(); - this._textarea.focus(); + this.focus(); + putCursorAtEnd(this._textarea); }; EditCommentForm.prototype.makeCounterUpdater = function(){ @@ -935,13 +939,14 @@ EditCommentForm.prototype.canCancel = function(){ if (this._element === null){ return true; } - if ($.trim(this._textarea.val()) == ''){ + var ctext = $.trim(this._textarea.val()); + if (ctext == this._text){ return true; } else if (this.confirmAbandon()){ return true; } - this._textarea.focus(); + this.focus(); return false; } @@ -978,6 +983,7 @@ EditCommentForm.prototype.createDom = function(){ var div = $('<div></div>'); this._textarea = $('<textarea></textarea>'); + this._textarea.attr('id', this._id); this._element.append(div); @@ -1002,6 +1008,7 @@ EditCommentForm.prototype.createDom = function(){ .focus(update_counter) .keyup(update_counter) .keyup(escape_handler); + this._textarea.val(this._text); setupFormValidation( this._element, @@ -1023,12 +1030,22 @@ EditCommentForm.prototype.disableButtons = function(){ EditCommentForm.prototype.reset = function(){ this._comment = null; + this._text = ''; this._textarea.val(''); }; EditCommentForm.prototype.confirmAbandon = function(){ + this.focus(); + debugger; + this._textarea.addClass('highlight'); + var answer = confirm($.i18n._('confirm abandon comment')); + this._textarea.removeClass('highlight'); + return answer; +}; + +EditCommentForm.prototype.focus = function(){ this._textarea.focus(); - return confirm($.i18n._('confirm abandon comment')); + window.location.hash = this._id; }; EditCommentForm.prototype.save = function(){ @@ -1047,7 +1064,7 @@ EditCommentForm.prototype.save = function(){ this.disableButtons(); - $.ajax({ + /*$.ajax({ type: "POST", url: post_url, dataType: "json", @@ -1068,7 +1085,12 @@ EditCommentForm.prototype.save = function(){ showMessage(this._element, xhr.responseText); this.enableButtons(); } - }); + });*/ +}; + +EditCommentForm.prototype.editComment = function(comment){ + this.detach(); + this.attachTo(comment); }; //a single instance to reuse @@ -1077,7 +1099,7 @@ var editCommentForm = new EditCommentForm(); var Comment = function(widget, data){ WrappedElement.call(this); this._container_widget = widget; - this._data = data; + this._data = data || {}; this._blank = true;//set to false by setContent this._element = null; this._delete_prompt = $.i18n._('delete this comment'); @@ -1110,23 +1132,33 @@ Comment.prototype.decorate = function(element){ this._element.mouseover(function(){edit_link.getElement().show()}); this._element.mouseout(function(){edit_link.getElement().hide()}); } + this._blank = false; }; Comment.prototype.isBlank = function(){ return this._blank; }; +Comment.prototype.hasContent = function(){ + return ('id' in this._data); + //shortcut for 'user_url' 'html' 'user_display_name' 'comment_age' +}; + +Comment.prototype.hasText = function(){ + return ('text' in this._data); +} + Comment.prototype.getContainerWidget = function(){ return this._container_widget; }; Comment.prototype.setContent = function(data){ - this._data = data; + this._data = data || this._data; this._element.html(''); this._element.attr('class', 'comment'); this._element.attr('id', 'comment-' + this._data['id']); - this._element.append(data['text']); + this._element.append(data['html']); this._element.append(' - '); this._user_link = $('<a></a>').attr('class', 'author'); @@ -1173,8 +1205,8 @@ Comment.prototype.dispose = function(){ Comment.prototype.getElement = function(){ Comment.superClass_.getElement.call(this); - if (this._blank && this._data){ - this.setContent(this._data); + if (this.isBlank() && this.hasContent()){ + this.setContent(); if (enableMathJax === true){ MathJax.Hub.Queue(['Typeset', MathJax.Hub]); } @@ -1183,12 +1215,13 @@ Comment.prototype.getElement = function(){ }; Comment.prototype.loadText = function(on_load_handler){ + var me = this; $.ajax({ type: "GET", - url: askbot['urls']['commentGetText'], + url: askbot['urls']['getCommentText'], data: {id: this._data['id']}, success: function(json){ - this._data['text'] = json['text']; + me._data['text'] = json['text']; on_load_handler() } }); @@ -1208,14 +1241,18 @@ Comment.prototype.getEditHandler = function(){ var parent_post_id = this._data['post_id']; var comment = this; return function(){ - comment.loadText( - function(){ - if (editCommentForm.canCancel()){ - editCommentForm.detach(); - editCommentForm.attachTo(comment); - } + if (editCommentForm.canCancel()){ + if (comment.hasText()){ + editCommentForm.editComment(comment); } - ); + else { + comment.loadText( + function(){ + editCommentForm.editComment(comment); + } + ); + } + } }; }; @@ -1343,7 +1380,7 @@ PostCommentsWidget.prototype.reloadAllComments = function(callback){ var post_data = {post_id: this._post_id, post_type: this._post_type}; $.ajax({ type: "GET", - url: askbot['urls']['post_comments'], + url: askbot['urls']['postComments'], data: post_data, success: callback, dataType: "json" diff --git a/askbot/skins/default/media/js/utils.js b/askbot/skins/default/media/js/utils.js index aec04ffd..2b88f49e 100644 --- a/askbot/skins/default/media/js/utils.js +++ b/askbot/skins/default/media/js/utils.js @@ -29,6 +29,18 @@ var setupButtonEventHandlers = function(button, callback){ button.click(callback); }; +var putCursorAtEnd = function(element){ + var el = element.get()[0]; + if (el.setSelectionRange){ + var len = element.val().length * 2; + el.setSelectionRange(len, len); + } + else{ + element.val(element.val()); + } + element.scrollTop = 999999; +}; + var setCheckBoxesIn = function(selector, value){ return $(selector + '> input[type=checkbox]').attr('checked', value); }; diff --git a/askbot/skins/default/templates/base.html b/askbot/skins/default/templates/base.html index 4d23cc60..c8d7ab76 100644 --- a/askbot/skins/default/templates/base.html +++ b/askbot/skins/default/templates/base.html @@ -24,6 +24,7 @@ var askbot = {}; askbot['data'] = {}; askbot['urls'] = {}; + askbot['settings'] = {}; </script> {% block forejs %} {% endblock %} diff --git a/askbot/skins/default/templates/question.html b/askbot/skins/default/templates/question.html index 2af509cd..e9b3f7f1 100644 --- a/askbot/skins/default/templates/question.html +++ b/askbot/skins/default/templates/question.html @@ -16,347 +16,347 @@ </div> <div id="main-body" class=""> <div id="askform"> - <table style="width:100%;" id="question-table" {% if question.deleted %}class="deleted"{%endif%}> - <tr> - <td style="width:30px;vertical-align:top"> - <div class="vote-buttons"> - {% if question_vote %} - <img id="question-img-upvote-{{ question.id }}" class="question-img-upvote" - {% if question_vote.is_upvote() %} - src="{{"/images/vote-arrow-up-on.png"|media}}" - {% else %} - src="{{"/images/vote-arrow-up.png"|media}}" - {% endif %} - alt="{% trans %}i like this post (click again to cancel){% endtrans %}" - title="{% trans %}i like this post (click again to cancel){% endtrans %}" /> - <div id="question-vote-number-{{ question.id }}" class="vote-number" - title="{% trans %}current number of votes{% endtrans %}"> - {{ question.score }} - </div> - <img id="question-img-downvote-{{ question.id }}" class="question-img-downvote" - {% if question_vote.is_downvote() %} - src="{{"/images/vote-arrow-down-on.png"|media}}" - {% else %} - src="{{"/images/vote-arrow-down.png"|media}}" - {% endif %} - alt="{% trans %}i dont like this post (click again to cancel){% endtrans %}" - title="{% trans %}i dont like this post (click again to cancel){% endtrans %}" /> + <table style="width:100%;" id="question-table" {% if question.deleted %}class="deleted"{%endif%}> + <tr> + <td style="width:30px;vertical-align:top"> + <div class="vote-buttons"> + {% if question_vote %} + <img id="question-img-upvote-{{ question.id }}" class="question-img-upvote" + {% if question_vote.is_upvote() %} + src="{{"/images/vote-arrow-up-on.png"|media}}" {% else %} - <img id="question-img-upvote-{{ question.id }}" class="question-img-upvote" - alt="{% trans %}i like this post (click again to cancel){% endtrans %}" src="{{"/images/vote-arrow-up.png"|media}}" - title="{% trans %}i like this post (click again to cancel){% endtrans %}" /> - <div id="question-vote-number-{{ question.id }}" class="vote-number" - title="{% trans %}current number of votes{% endtrans %}"> - {{ question.score }} - </div> - <img id="question-img-downvote-{{ question.id }}" class="question-img-downvote" - src="{{"/images/vote-arrow-down.png"|media}}" - alt="{% trans %}i dont like this post (click again to cancel){% endtrans %}" - title="{% trans %}i dont like this post (click again to cancel){% endtrans %}" /> {% endif %} - {% if favorited %} - <img class="question-img-favorite" src="{{"/images/vote-favorite-on.png"|media}}" - alt="{% trans %}mark this question as favorite (click again to cancel){% endtrans %}" - title="{% trans %}mark this question as favorite (click again to cancel){% endtrans %}" /> - <div id="favorite-number" class="favorite-number my-favorite-number"> - {{ question.favourite_count }} - </div> + alt="{% trans %}i like this post (click again to cancel){% endtrans %}" + title="{% trans %}i like this post (click again to cancel){% endtrans %}" /> + <div id="question-vote-number-{{ question.id }}" class="vote-number" + title="{% trans %}current number of votes{% endtrans %}"> + {{ question.score }} + </div> + <img id="question-img-downvote-{{ question.id }}" class="question-img-downvote" + {% if question_vote.is_downvote() %} + src="{{"/images/vote-arrow-down-on.png"|media}}" {% else %} - <img class="question-img-favorite" src="{{"/images/vote-favorite-off.png"|media}}" - alt="{% trans %}remove favorite mark from this question (click again to restore mark){% endtrans %}" - title="{% trans %}remove favorite mark from this question (click again to restore mark){% endtrans %}" /> - <div id="favorite-number" class="favorite-number"> - {% if question.favourite_count != 0 %}{{ question.favourite_count }}{% endif %} - </div> - {% endif %} - {% if settings.ENABLE_SOCIAL_SHARING %} - <a class="twitter-share" alt="{% trans %}Share this question on twitter{% endtrans %}"></a> - <a class="fb-share" alt="{% trans %}Share this question on facebook{% endtrans %}"></a> + src="{{"/images/vote-arrow-down.png"|media}}" {% endif %} + alt="{% trans %}i dont like this post (click again to cancel){% endtrans %}" + title="{% trans %}i dont like this post (click again to cancel){% endtrans %}" /> + {% else %} + <img id="question-img-upvote-{{ question.id }}" class="question-img-upvote" + alt="{% trans %}i like this post (click again to cancel){% endtrans %}" + src="{{"/images/vote-arrow-up.png"|media}}" + title="{% trans %}i like this post (click again to cancel){% endtrans %}" /> + <div id="question-vote-number-{{ question.id }}" class="vote-number" + title="{% trans %}current number of votes{% endtrans %}"> + {{ question.score }} </div> - </td> - <td> - <div id="item-right"> - <div class="question-body"> - {{question.html}} - </div> - <div id="question-tags" class="post-tags tags"> - {% for tag in question.get_tag_names() %} - <a href="{% url questions %}?tags={{tag|urlencode}}&start_over=true" - class="post-tag" - title="{% trans %}see questions tagged '{{tag}}'{% endtrans %}" rel="tag">{{ tag }}</a> - {% endfor %} - </div> - <div id="question-controls" class="post-controls"> - {% set pipe=joiner('<span class="sep">|</span>') %} - {% if request.user|can_edit_post(question) %}{{ pipe() }} - <a href="{% url edit_question question.id %}">{% trans %}edit{% endtrans %}</a> - {% endif %} - {% if request.user|can_retag_question(question) %}{{ pipe() }} - <a id="retag" href="{% url retag_question question.id %}">{% trans %}retag{% endtrans %}</a> - <script type="text/javascript"> - var retagUrl = "{% url retag_question question.id %}"; - </script> - {% endif %} - {% if question.closed %} - {% if request.user|can_reopen_question(question) %}{{ pipe() }} - <a href="{% url reopen question.id %}">{% trans %}reopen{% endtrans %}</a> - {% endif %} - {% else %} - {% if request.user|can_close_question(question) %}{{ pipe() }} - <a href="{% url close question.id %}">{% trans %}close{% endtrans %}</a> - {% endif %} + <img id="question-img-downvote-{{ question.id }}" class="question-img-downvote" + src="{{"/images/vote-arrow-down.png"|media}}" + alt="{% trans %}i dont like this post (click again to cancel){% endtrans %}" + title="{% trans %}i dont like this post (click again to cancel){% endtrans %}" /> + {% endif %} + {% if favorited %} + <img class="question-img-favorite" src="{{"/images/vote-favorite-on.png"|media}}" + alt="{% trans %}mark this question as favorite (click again to cancel){% endtrans %}" + title="{% trans %}mark this question as favorite (click again to cancel){% endtrans %}" /> + <div id="favorite-number" class="favorite-number my-favorite-number"> + {{ question.favourite_count }} + </div> + {% else %} + <img class="question-img-favorite" src="{{"/images/vote-favorite-off.png"|media}}" + alt="{% trans %}remove favorite mark from this question (click again to restore mark){% endtrans %}" + title="{% trans %}remove favorite mark from this question (click again to restore mark){% endtrans %}" /> + <div id="favorite-number" class="favorite-number"> + {% if question.favourite_count != 0 %}{{ question.favourite_count }}{% endif %} + </div> + {% endif %} + {% if settings.ENABLE_SOCIAL_SHARING %} + <a class="twitter-share" alt="{% trans %}Share this question on twitter{% endtrans %}"></a> + <a class="fb-share" alt="{% trans %}Share this question on facebook{% endtrans %}"></a> + {% endif %} + </div> + </td> + <td> + <div id="item-right"> + <div class="question-body"> + {{question.html}} + </div> + <div id="question-tags" class="post-tags tags"> + {% for tag in question.get_tag_names() %} + <a href="{% url questions %}?tags={{tag|urlencode}}&start_over=true" + class="post-tag" + title="{% trans %}see questions tagged '{{tag}}'{% endtrans %}" rel="tag">{{ tag }}</a> + {% endfor %} + </div> + <div id="question-controls" class="post-controls"> + {% set pipe=joiner('<span class="sep">|</span>') %} + {% if request.user|can_edit_post(question) %}{{ pipe() }} + <a href="{% url edit_question question.id %}">{% trans %}edit{% endtrans %}</a> + {% endif %} + {% if request.user|can_retag_question(question) %}{{ pipe() }} + <a id="retag" href="{% url retag_question question.id %}">{% trans %}retag{% endtrans %}</a> + <script type="text/javascript"> + var retagUrl = "{% url retag_question question.id %}"; + </script> + {% endif %} + {% if question.closed %} + {% if request.user|can_reopen_question(question) %}{{ pipe() }} + <a href="{% url reopen question.id %}">{% trans %}reopen{% endtrans %}</a> {% endif %} - {% if request.user|can_flag_offensive(question) %}{{ pipe() }} - <span id="question-offensive-flag-{{ question.id }}" class="offensive-flag" - title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}"> - <a>{% trans %}flag offensive{% endtrans %}</a> - {% if request.user|can_see_offensive_flags(question) %} - <span class="darkred">{% if question.offensive_flag_count > 0 %}({{ question.offensive_flag_count }}){% endif %}</span> - {% endif %} - </span> + {% else %} + {% if request.user|can_close_question(question) %}{{ pipe() }} + <a href="{% url close question.id %}">{% trans %}close{% endtrans %}</a> {% endif %} - {% if request.user|can_delete_post(question) %}{{ pipe() }} - <a id="question-delete-link-{{question.id}}">{% trans %}delete{% endtrans %}</a> + {% endif %} + {% if request.user|can_flag_offensive(question) %}{{ pipe() }} + <span id="question-offensive-flag-{{ question.id }}" class="offensive-flag" + title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}"> + <a>{% trans %}flag offensive{% endtrans %}</a> + {% if request.user|can_see_offensive_flags(question) %} + <span class="darkred">{% if question.offensive_flag_count > 0 %}({{ question.offensive_flag_count }}){% endif %}</span> {% endif %} - </div> - </div> - <div class="post-update-info-container"> - {{ - macros.post_contributor_info( - question, - "original_author", - question.wiki, - settings.MIN_REP_TO_EDIT_WIKI - ) - }} - {{ - macros.post_contributor_info( - question, - "last_updater", - question.wiki, - settings.MIN_REP_TO_EDIT_WIKI, - ) - }} + </span> + {% endif %} + {% if request.user|can_delete_post(question) %}{{ pipe() }} + <a id="question-delete-link-{{question.id}}">{% trans %}delete{% endtrans %}</a> + {% endif %} </div> - {{ - macros.post_comments_widget( - post = question, - user = request.user, - max_comments = settings.MAX_COMMENTS_TO_SHOW - ) - }} </div> - </td> - </tr> - </table> - {% if question.closed %} - <div class="question-status" style="margin-bottom:15px"> - <h3>{% trans close_reason=question.get_close_reason_display() %}The question has been closed for the following reason "{{ close_reason }}" by{% endtrans %} - <a href="{{ question.closed_by.get_profile_url() }}">{{ question.closed_by.username }}</a> - {% trans closed_at=question.closed_at %}close date {{closed_at}}{% endtrans %}</h3> - </div> - {% endif %} - {% if answers %} - <hr/> - <div class="tabBar"> - <a name="sort-top"></a> - <div class="headUsers"> - {% trans counter=answers|length %} - {{counter}} Answer: - {% pluralize %} - {{counter}} Answers: - {% endtrans %} - </div> - <div class="tabsA"> - <a id="oldest" href="{% url question question.id %}?sort=oldest#sort-top" - title="{% trans %}oldest answers will be shown first{% endtrans %}">{% trans %}oldest answers{% endtrans %}</a> - <a id="latest" href="{% url question question.id %}?sort=latest#sort-top" - title="{% trans %}newest answers will be shown first{% endtrans %}">{% trans %}newest answers{% endtrans %}</a> - <a id="votes" href="{% url question question.id %}?sort=votes#sort-top" - title="{% trans %}most voted answers will be shown first{% endtrans %}">{% trans %}popular answers{% endtrans %}</a> + <div class="post-update-info-container"> + {{ + macros.post_contributor_info( + question, + "original_author", + question.wiki, + settings.MIN_REP_TO_EDIT_WIKI + ) + }} + {{ + macros.post_contributor_info( + question, + "last_updater", + question.wiki, + settings.MIN_REP_TO_EDIT_WIKI, + ) + }} + </div> + {{ + macros.post_comments_widget( + post = question, + user = request.user, + max_comments = settings.MAX_COMMENTS_TO_SHOW + ) + }} </div> + </td> + </tr> + </table> + {% if question.closed %} + <div class="question-status" style="margin-bottom:15px"> + <h3>{% trans close_reason=question.get_close_reason_display() %}The question has been closed for the following reason "{{ close_reason }}" by{% endtrans %} + <a href="{{ question.closed_by.get_profile_url() }}">{{ question.closed_by.username }}</a> + {% trans closed_at=question.closed_at %}close date {{closed_at}}{% endtrans %}</h3> + </div> + {% endif %} + {% if answers %} + <hr/> + <div class="tabBar"> + <a name="sort-top"></a> + <div class="headUsers"> + {% trans counter=answers|length %} + {{counter}} Answer: + {% pluralize %} + {{counter}} Answers: + {% endtrans %} </div> - {{ macros.paginator(paginator_context) }} - - {% for answer in answers %} - <a name="{{ answer.id }}"></a> - <div id="answer-container-{{ answer.id }}" class="answer {% if answer.accepted %}accepted-answer{% endif %} {% if answer.author_id==question.author_id %} answered-by-owner{% endif %} {% if answer.deleted %}deleted{% endif %}"> - <table style="width:100%;"> - <tr> - <td style="width:30px;vertical-align:top"> - <div class="vote-buttons"> - <img id="answer-img-upvote-{{ answer.id }}" class="answer-img-upvote" - {% if user_answer_votes[answer.id] == 1 %} - src="{{"/images/vote-arrow-up-on.png"|media}}" - {% else %} - src="{{"/images/vote-arrow-up.png"|media}}" - {% endif %} - alt="{% trans %}i like this answer (click again to cancel){% endtrans %}" - title="{% trans %}i like this answer (click again to cancel){% endtrans %}"/> - <div id="answer-vote-number-{{ answer.id }}" class="vote-number" title="{% trans %}current number of votes{% endtrans %}"> - {{ answer.score }} - </div> - <img id="answer-img-downvote-{{ answer.id }}" class="answer-img-downvote" - {% if user_answer_votes[answer.id] == -1 %} - src="{{"/images/vote-arrow-down-on.png"|media}}" - {% else %} - src="{{"/images/vote-arrow-down.png"|media}}" - {% endif %} - alt="{% trans %}i dont like this answer (click again to cancel){% endtrans %}" - title="{% trans %}i dont like this answer (click again to cancel){% endtrans %}" /> - {% if request.user == question.author %} + <div class="tabsA"> + <a id="oldest" href="{% url question question.id %}?sort=oldest#sort-top" + title="{% trans %}oldest answers will be shown first{% endtrans %}">{% trans %}oldest answers{% endtrans %}</a> + <a id="latest" href="{% url question question.id %}?sort=latest#sort-top" + title="{% trans %}newest answers will be shown first{% endtrans %}">{% trans %}newest answers{% endtrans %}</a> + <a id="votes" href="{% url question question.id %}?sort=votes#sort-top" + title="{% trans %}most voted answers will be shown first{% endtrans %}">{% trans %}popular answers{% endtrans %}</a> + </div> + </div> + {{ macros.paginator(paginator_context) }} + + {% for answer in answers %} + <a name="{{ answer.id }}"></a> + <div id="answer-container-{{ answer.id }}" class="answer {% if answer.accepted %}accepted-answer{% endif %} {% if answer.author_id==question.author_id %} answered-by-owner{% endif %} {% if answer.deleted %}deleted{% endif %}"> + <table style="width:100%;"> + <tr> + <td style="width:30px;vertical-align:top"> + <div class="vote-buttons"> + <img id="answer-img-upvote-{{ answer.id }}" class="answer-img-upvote" + {% if user_answer_votes[answer.id] == 1 %} + src="{{"/images/vote-arrow-up-on.png"|media}}" + {% else %} + src="{{"/images/vote-arrow-up.png"|media}}" + {% endif %} + alt="{% trans %}i like this answer (click again to cancel){% endtrans %}" + title="{% trans %}i like this answer (click again to cancel){% endtrans %}"/> + <div id="answer-vote-number-{{ answer.id }}" class="vote-number" title="{% trans %}current number of votes{% endtrans %}"> + {{ answer.score }} + </div> + <img id="answer-img-downvote-{{ answer.id }}" class="answer-img-downvote" + {% if user_answer_votes[answer.id] == -1 %} + src="{{"/images/vote-arrow-down-on.png"|media}}" + {% else %} + src="{{"/images/vote-arrow-down.png"|media}}" + {% endif %} + alt="{% trans %}i dont like this answer (click again to cancel){% endtrans %}" + title="{% trans %}i dont like this answer (click again to cancel){% endtrans %}" /> + {% if request.user == question.author %} + <img id="answer-img-accept-{{ answer.id }}" class="answer-img-accept" + {% if answer.accepted %} + src="{{"/images/vote-accepted-on.png"|media}}" + {% else %} + src="{{"/images/vote-accepted.png"|media}}" + {% endif %} + alt="{% trans %}mark this answer as favorite (click again to undo){% endtrans %}" + title="{% trans %}mark this answer as favorite (click again to undo){% endtrans %}" /> + {% else %} + {% if answer.accepted %} <img id="answer-img-accept-{{ answer.id }}" class="answer-img-accept" {% if answer.accepted %} src="{{"/images/vote-accepted-on.png"|media}}" {% else %} - src="{{"/images/vote-accepted.png"|media}}" - {% endif %} - alt="{% trans %}mark this answer as favorite (click again to undo){% endtrans %}" - title="{% trans %}mark this answer as favorite (click again to undo){% endtrans %}" /> - {% else %} - {% if answer.accepted %} - <img id="answer-img-accept-{{ answer.id }}" class="answer-img-accept" - {% if answer.accepted %} - src="{{"/images/vote-accepted-on.png"|media}}" - {% else %} - src="{{"/images/vote-accepted.png"|media}}" - {% endif %} - alt="{% trans question_author=question.author.username %}{{question_author}} has selected this answer as correct{% endtrans %}" - title="{% trans questsion_author=question.author.username%}{{question_author}} has selected this answer as correct{% endtrans %}" + src="{{"/images/vote-accepted.png"|media}}" {% endif %} + alt="{% trans question_author=question.author.username %}{{question_author}} has selected this answer as correct{% endtrans %}" + title="{% trans questsion_author=question.author.username%}{{question_author}} has selected this answer as correct{% endtrans %}" {% endif %} + {% endif %} + </div> + </td> + <td> + <div class="item-right"> + <div class="answer-body"> + {{ answer.html }} </div> - </td> - <td> - <div class="item-right"> - <div class="answer-body"> - {{ answer.html }} - </div> - <div class="answer-controls post-controls"> - {% set pipe=joiner('<span class="sep">|</span>') %} - <span class="linksopt">{{ pipe() }} - <a - href="#{{ answer.id }}" - title="{% trans %}answer permanent link{% endtrans %}"> - {% trans %}permanent link{% endtrans %} - </a> - </span> - {% if request.user|can_edit_post(answer) %}{{ pipe() }} - <span class="action-link"><a href="{% url edit_answer answer.id %}">{% trans %}edit{% endtrans %}</a></span> + <div class="answer-controls post-controls"> + {% set pipe=joiner('<span class="sep">|</span>') %} + <span class="linksopt">{{ pipe() }} + <a + href="#{{ answer.id }}" + title="{% trans %}answer permanent link{% endtrans %}"> + {% trans %}permanent link{% endtrans %} + </a> + </span> + {% if request.user|can_edit_post(answer) %}{{ pipe() }} + <span class="action-link"><a href="{% url edit_answer answer.id %}">{% trans %}edit{% endtrans %}</a></span> + {% endif %} + {% if request.user|can_flag_offensive(answer) %}{{ pipe() }} + <span id="answer-offensive-flag-{{ answer.id }}" class="offensive-flag" + title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}"> + <a>{% trans %}flag offensive{% endtrans %}</a> + {% if request.user|can_see_offensive_flags(answer) %} + <span class="darkred">{% if answer.offensive_flag_count > 0 %}({{ answer.offensive_flag_count }}){% endif %}</span> {% endif %} - {% if request.user|can_flag_offensive(answer) %}{{ pipe() }} - <span id="answer-offensive-flag-{{ answer.id }}" class="offensive-flag" - title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}"> - <a>{% trans %}flag offensive{% endtrans %}</a> - {% if request.user|can_see_offensive_flags(answer) %} - <span class="darkred">{% if answer.offensive_flag_count > 0 %}({{ answer.offensive_flag_count }}){% endif %}</span> - {% endif %} + </span> + {% endif %} + {% if request.user|can_delete_post(answer) %}{{ pipe() }} + {% spaceless %} + <span class="action-link"> + <a id="answer-delete-link-{{answer.id}}"> + {% if answer.deleted %}{% trans %}undelete{% endtrans %}{% else %}{% trans %}delete{% endtrans %}{% endif %}</a> </span> - {% endif %} - {% if request.user|can_delete_post(answer) %}{{ pipe() }} - {% spaceless %} - <span class="action-link"> - <a id="answer-delete-link-{{answer.id}}"> - {% if answer.deleted %}{% trans %}undelete{% endtrans %}{% else %}{% trans %}delete{% endtrans %}{% endif %}</a> - </span> - {% endspaceless %} - {% endif %} - </div> - <div class="post-update-info-container"> - {{ - macros.post_contributor_info( - answer, - "original_author", - answer.wiki, - settings.MIN_REP_TO_EDIT_WIKI - ) - }} - {{ - macros.post_contributor_info( - answer, - "last_updater", - answer.wiki, - settings.MIN_REP_TO_EDIT_WIKI - ) - }} - </div> - {{ - macros.post_comments_widget( - post = answer, - user = request.user, - max_comments = settings.MAX_COMMENTS_TO_SHOW + {% endspaceless %} + {% endif %} + </div> + <div class="post-update-info-container"> + {{ + macros.post_contributor_info( + answer, + "original_author", + answer.wiki, + settings.MIN_REP_TO_EDIT_WIKI + ) + }} + {{ + macros.post_contributor_info( + answer, + "last_updater", + answer.wiki, + settings.MIN_REP_TO_EDIT_WIKI ) - }} + }} </div> - </td> - </tr> - </table> - </div> - {% endfor %} - <div class="paginator-container-left"> - {{ macros.paginator(paginator_context) }} + {{ + macros.post_comments_widget( + post = answer, + user = request.user, + max_comments = settings.MAX_COMMENTS_TO_SHOW + ) + }} + </div> + </td> + </tr> + </table> </div> + {% endfor %} + <div class="paginator-container-left"> + {{ macros.paginator(paginator_context) }} + </div> + {% endif %} + <form id="fmanswer" action="{% url answer question.id %}" method="post"> + {% if request.user.is_authenticated() %} + <p style="padding-left:3px"> + {{ answer.email_notify }} + <label for="question-subscribe-updates"> + {% if request.user.get_q_sel_email_feed_frequency()=='n' %} + {% trans %}Notify me once a day when there are any new answers{% endtrans %} + {% elif request.user.get_q_sel_email_feed_frequency()=='d' %} + {% trans %}Notify me once a day when there are any new answers{% endtrans %} + {% elif request.user.get_q_sel_email_feed_frequency()=='w' %} + {% trans %}Notify me weekly when there are any new answers{% endtrans %} {% endif %} - <form id="fmanswer" action="{% url answer question.id %}" method="post"> - {% if request.user.is_authenticated() %} - <p style="padding-left:3px"> - {{ answer.email_notify }} - <label for="question-subscribe-updates"> - {% if request.user.get_q_sel_email_feed_frequency()=='n' %} - {% trans %}Notify me once a day when there are any new answers{% endtrans %} - {% elif request.user.get_q_sel_email_feed_frequency()=='d' %} - {% trans %}Notify me once a day when there are any new answers{% endtrans %} - {% elif request.user.get_q_sel_email_feed_frequency()=='w' %} - {% trans %}Notify me weekly when there are any new answers{% endtrans %} - {% endif %} - </label> - {% trans profile_url=request.user.get_profile_url() %}You can always adjust frequency of email updates from your {{profile_url}}{% endtrans %} - </p> + </label> + {% trans profile_url=request.user.get_profile_url() %}You can always adjust frequency of email updates from your {{profile_url}}{% endtrans %} + </p> + {% else %} + <p style="padding-left:3px"> + <input class="nomargin" type="checkbox" disabled="disabled" /> + <label>{% trans %}once you sign in you will be able to subscribe for any updates here{% endtrans %}</label> + </p> + {% endif %} + <div style="clear:both"> + </div> + {% if not question.closed %} + <div style="padding:10px 0 0 0;"> + {% spaceless %} + <div class="headNormal"> + {% if answers %} + {% trans %}Your answer{% endtrans %} + {% else %} + {% trans %}Be the first one to answer this question!{% endtrans %} + {% endif %} + </div> + {% endspaceless %} + </div> + {% if not request.user.is_authenticated() %} + <div class="message">{% trans %}you can answer anonymously and then login{% endtrans %}</div> {% else %} - <p style="padding-left:3px"> - <input class="nomargin" type="checkbox" disabled="disabled" /> - <label>{% trans %}once you sign in you will be able to subscribe for any updates here{% endtrans %}</label> + <p class="message"> + {% if request.user==question.author %} + {% trans %}answer your own question only to give an answer{% endtrans %} + {% else %} + {% trans %}please only give an answer, no discussions{% endtrans %} + {% endif %} </p> {% endif %} - <div style="clear:both"> - </div> - {% if not question.closed %} - <div style="padding:10px 0 0 0;"> - {% spaceless %} - <div class="headNormal"> - {% if answers %} - {% trans %}Your answer{% endtrans %} - {% else %} - {% trans %}Be the first one to answer this question!{% endtrans %} - {% endif %} - </div> - {% endspaceless %} - </div> - {% if not request.user.is_authenticated() %} - <div class="message">{% trans %}you can answer anonymously and then login{% endtrans %}</div> + {{macros.edit_post(answer, settings.WIKI_ON)}} + <input type="submit" + {% if user.is_anonymous() %} + value="{% trans %}Login/Signup to Post Your Answer{% endtrans %}" {% else %} - <p class="message"> - {% if request.user==question.author %} - {% trans %}answer your own question only to give an answer{% endtrans %} - {% else %} - {% trans %}please only give an answer, no discussions{% endtrans %} - {% endif %} - </p> - {% endif %} - {{macros.edit_post(answer, settings.WIKI_ON)}} - <input type="submit" - {% if user.is_anonymous() %} - value="{% trans %}Login/Signup to Post Your Answer{% endtrans %}" + {% if user == question.author %} + value="{% trans %}Answer Your Own Question{% endtrans %}" {% else %} - {% if user == question.author %} - value="{% trans %}Answer Your Own Question{% endtrans %}" - {% else %} - value="{% trans %}Answer the question{% endtrans %}" - {% endif %} + value="{% trans %}Answer the question{% endtrans %}" {% endif %} - class="submit after-editor" style="float:left"/> + {% endif %} + class="submit after-editor" style="float:left"/> {% endif %} </form> </div> @@ -413,7 +413,8 @@ var codeFriendlyMarkdown = false; {% endif %} var maxCommentLength = {{settings.MAX_COMMENT_LENGTH}}; - askbot['urls']['post_comments'] = '{% url post_comments %}'; + askbot['urls']['postComments'] = '{% url post_comments %}'; + askbot['urls']['getCommentText'] = '{% url get_comment_text %}'; </script> <script type='text/javascript' src='{{"/js/wmd/showdown.js"|media}}'></script> <script type='text/javascript' src='{{"/js/wmd/wmd.js"|media}}'></script> diff --git a/askbot/urls.py b/askbot/urls.py index 11b63ba1..18d8a7ec 100644 --- a/askbot/urls.py +++ b/askbot/urls.py @@ -116,11 +116,11 @@ urlpatterns = patterns('', app.writers.delete_comment, name='delete_comment' ), - #url( - # r'^comment/get_text/$', - # app.commands.get_comment_text, - # name='comment_get_text' - #), + url( + r'^comment/get_text/$', + app.readers.get_comment_text, + name='get_comment_text' + ), #place general question item in the end of other operations url( r'^%s(?P<id>\d+)/' % _('question/'), diff --git a/askbot/utils/http.py b/askbot/utils/http.py new file mode 100644 index 00000000..a3aea72d --- /dev/null +++ b/askbot/utils/http.py @@ -0,0 +1,34 @@ +"""http utils similar to django's but with more +specific properties +""" +import logging +from django.http import HttpResponse +from django.utils import simplejson + +class JsonResponse(HttpResponse): + """response class that receives a dictionary + and returns it serialized with simplejson + and response type application/json + """ + def __init__(self, *args, **kwargs): + mimetype = kwargs.pop('mimetype', None) + if mimetype: + raise KeyError('JsonResponse does not accept mimetype variable') + kwargs['mimetype'] = 'application/json' + string_data = simplejson.dumps(kwargs.pop('data', '')) + super(JsonResponse, self).__init__(string_data, *args, **kwargs) + +class JsonLoggingErrorResponse(JsonResponse): + """like json response, only with empty content + and status=500, plus logs an error message + """ + def __init__(self, error, *args, **kwargs): + status = kwargs.pop('status', None) + if status: + raise KeyError('JsonLoggingErrorResponse does not accept status') + log_level = kwargs.pop('log_level', 'debug') + assert(log_level in ('debug', 'critical')) + log = getattr(logging, log_level) + log('ajax error ' + unicode(error)) + kwargs['status'] = 500 + super(JsonLoggingErrorResponse, self).__init__(*args, **kwargs) diff --git a/askbot/views/readers.py b/askbot/views/readers.py index 2191dd8b..7e6b1691 100644 --- a/askbot/views/readers.py +++ b/askbot/views/readers.py @@ -37,6 +37,7 @@ from askbot.utils import markup from askbot.utils.forms import get_next_url from askbot.utils.functions import not_a_robot_request from askbot.utils.decorators import profile +from askbot.utils.http import JsonResponse, JsonLoggingErrorResponse from askbot.search.state_manager import SearchState from askbot.templatetags import extra_tags from askbot.templatetags import extra_filters @@ -555,3 +556,21 @@ def revisions(request, id, object_name=None): context = RequestContext(request, data) template = ENV.get_template('revisions.html') return HttpResponse(template.render(context)) + +def get_comment_text(request): + """returns text of a comment by id + via ajax response requires request method get + and request must be ajax + """ + if request.is_ajax(): + if request.method == "GET": + try: + id = int(request.GET['id']) + comment = Comment.objects.get(id = id) + return JsonResponse(data={'text': comment.comment}) + except Exception, e: + return JsonLoggingErrorResponse(e) + else: + return JsonResponse(status=400) + else: + raise Http404() diff --git a/askbot/views/writers.py b/askbot/views/writers.py index 6d304e45..27ba5099 100644 --- a/askbot/views/writers.py +++ b/askbot/views/writers.py @@ -414,7 +414,7 @@ def __generate_comments_json(obj, user):#non-view generates json data for the po json_comments.append({'id' : comment.id, 'object_id': obj.id, 'comment_age': diff_date(comment.added_at), - 'text': comment.html, + 'html': comment.html, 'user_display_name': comment_owner.username, 'user_url': comment_owner.get_profile_url(), 'user_id': comment_owner.id, |