From beee0be8e95fc6be5bc65749572ae4fbc25e682d Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Sun, 14 Nov 2010 01:18:07 -0500 Subject: broken commit. started improving commenting widget in .js --- askbot/middleware/view_log.py | 7 +- askbot/skins/default/media/js/i18n.js | 2 + askbot/skins/default/media/js/post.js | 659 ++++++++++++++++++++----------- askbot/skins/default/templates/base.html | 12 + askbot/urls.py | 25 +- askbot/views/writers.py | 45 +-- 6 files changed, 477 insertions(+), 273 deletions(-) diff --git a/askbot/middleware/view_log.py b/askbot/middleware/view_log.py index 25e9f37f..3dbbd4a8 100644 --- a/askbot/middleware/view_log.py +++ b/askbot/middleware/view_log.py @@ -3,14 +3,13 @@ from django.conf import settings from askbot.views.readers import questions as questions_view from askbot.views.commands import vote from django.views.static import serve -from askbot.views.writers import delete_comment, question_comments, answer_comments +from askbot.views.writers import delete_comment, post_comments, retag_question from askbot.views.readers import revisions #todo: the list is getting bigger and bigger - maybe there is a better way to #trigger reset of sarch state? -IGNORED_VIEWS = (serve, vote, delete_comment, - question_comments, answer_comments, - revisions) +IGNORED_VIEWS = (serve, vote, delete_comment, post_comments, + retag_question, revisions) class ViewLog(object): """must be modified only in this middlware diff --git a/askbot/skins/default/media/js/i18n.js b/askbot/skins/default/media/js/i18n.js index 6f5616b1..22edd5bd 100644 --- a/askbot/skins/default/media/js/i18n.js +++ b/askbot/skins/default/media/js/i18n.js @@ -133,6 +133,8 @@ var i18nEn = { 'title minchars':"please enter at least {0} characters", 'characters':'characters left', 'cannot flag message as offensive twice':'cannot flag message as offensive twice ', + 'edit':'edit', + 'click to edit this comment':'click to edit this comment', }; var i18nFi = { diff --git a/askbot/skins/default/media/js/post.js b/askbot/skins/default/media/js/post.js index d21cc7cd..90680c01 100644 --- a/askbot/skins/default/media/js/post.js +++ b/askbot/skins/default/media/js/post.js @@ -28,8 +28,8 @@ var getUniqueWords = function(value){ return $.unique($.trim(value).split(/\s+/)); }; -function appendLoader(containerSelector) { - $(containerSelector).append('' +
@@ -145,6 +145,7 @@ var CPValidator = function(){
     };
 }();
 
+
 var Vote = function(){
     // All actions are related to a question
     var questionId;
@@ -812,254 +813,470 @@ var questionRetagger = function(){
     };
 }();
 
-var questionComments = createComments('question');
-var answerComments = createComments('answer');
-var commentsFactory = {'question' : questionComments, 'answer' : answerComments};
+inherits = function(childCtor, parentCtor) {
+  /** @constructor taken from google closure */
+    function tempCtor() {};
+    tempCtor.prototype = parentCtor.prototype;
+    childCtor.superClass_ = parentCtor.prototype;
+    childCtor.prototype = new tempCtor();
+    childCtor.prototype.constructor = childCtor;
+};
 
-// site comments
-function createComments(type) {
-    var objectType = type;
-    var jDivInit = function(id) {
-        return $('); +}; +WrappedElement.prototype.getElement = function(){ + if (this._element === null){ + this.createDom(); + } + return this._element; +}; +WrappedElement.prototype.dispose = function(){ + this._element.remove(); +}; - var appendLoaderImg = function(id) { - appendLoader("#comments-container-" + objectType + '-' + id); - }; +var EditLink = function(edit_handler){ + WrappedElement.call(this) + this._edit_handler = edit_handler; +}; +inherits(EditLink, WrappedElement); + +EditLink.prototype.createDom = function(){ + this._element = $(''); + this._element.attr('title', $.i18n._('click to edit this comment')); + this._element.css('display', 'none'); + this._element.html($.i18n._('edit')); + setupButtonEventHandlers(this._element, this._edit_handler); +}; - var canPostComments = function(id) { - var jHidden = $("#can-post-comments-" + objectType + '-' + id); - return jHidden.val().toLowerCase() == "true"; - }; +var DeleteIcon = function(title, delete_handler){ + WrappedElement.call(this); + this._title = title; + this._delete_handler = delete_handler; +}; +inherits(DeleteIcon, WrappedElement); + +DeleteIcon.prototype.decorate = function(element){ + this._element = element; + var img = mediaUrl("media/images/close-small.png"); + var imgHover = mediaUrl("media/images/close-small-hover.png"); + this._element.attr('class', 'delete-icon'); + this._element.attr('src', img); + this._element.attr('title', this._title); + setupButtonEventHandlers(this._element, this._delete_handler); + this._element.mouseover(function(e){ + $(this).attr('src', imgHover); + }); + this._element.mouseout(function(e){ + $(this).attr('src', img); + }); +}; - var renderForm = function(id) { - var formId = "form-comments-" + objectType + "-" + id; - var jDiv = $('#comments-link-' + objectType + "-" + id).parent(); - $(jDiv).css('background','none'); - $(jDiv).css('padding-left',0); - if (canPostComments(id)) { - if (jDiv.find("#" + formId).length === 0) { - var form = '
'; - form += ''; - form += '
'; - form += '
'; - - jDiv.append(form); - - setupFormValidation("#" + formId, - { comment: { required: true, minlength: 10} }, '', - function() { postComment(id, formId); }) - ; - } - } - else { - var divId = "comments-rep-needed-" + objectType + '-' + id; - if (jDiv.find("#" + divId).length === 0) { - jDiv.append( - '

' + - $.i18n._('to comment, need') + ' ' + - repNeededForComments + ' ' + $.i18n._('community karma points') + - '' + - $.i18n._('please see') + 'faq

' - ); - } - } - }; +DeleteIcon.prototype.createDom = function(){ + this.decorate($('')); +}; - var getComments = function(id, jDiv) { - //appendLoaderImg(id); - $.getJSON(scriptUrl + $.i18n._(objectType + "s/") + id + "/" + $.i18n._("comments/"), - function(json) { showComments(id, json); }); - }; - var showComments = function(id, json) { - var jDiv = jDivInit(id); +//constructor for the form +var EditCommentForm = function(){ + WrappedElement.call(this); + this._comment = null; + this._text = ''; + this._element = null; +}; +inherits(EditCommentForm, WrappedElement); - //jDiv = jDiv.find("div.comments"); // this div should contain any fetched comments.. - //jDiv.find("div[id^='comment-" + objectType + "-'" + "]").remove(); // clean previous calls.. - jDiv.children().remove(); - removeLoader(); - if (json && json.length > 0) { - for (var i = 0; i < json.length; i++){ - renderComment(jDiv, json[i]); - } - jDiv.children().show(); - } - if (enableMathJax === true){ - MathJax.Hub.Queue(['Typeset', MathJax.Hub]); - } - }; +EditCommentForm.prototype.setComment = function(comment, text){ + self._comment = comment; + self._text = text || ''; +}; - var renderDeleteCommentIcon = function(post_id, delete_url){ - if (canPostComments(post_id)){ - var html = ''; - var img = mediaUrl("media/images/close-small.png"); - var imgHover = mediaUrl("media/images/close-small-hover.png"); - html += ''; - return html; +EditCommentForm.prototype.makeCounterUpdater = function(){ + //returns event handler + var counter = this._text_counter; + var handler = function(){ + var text_area = $(this); + var length = text_area.val() ? textarea.val().length : 0; + var length1 = maxCommentLength - 100; + if (length1 < 0){ + length1 = Math.round(0.7*maxCommentLength); } - else{ - return ''; + var length2 = maxCommentLength - 30; + if (length2 < 0){ + length2 = Math.round(0.9*maxCommentLength); } + var color = length > length2 ? "#f00" : length > length1 ? "#f60" : "#999"; + counter.html($.i18n._('can write') + ' ' + + (maxCommentLength - length) + ' ' + + $.i18n._('characters')).css("color", color); }; + return handler; +}; - // {"Id":6,"PostId":38589,"CreationDate":"an hour ago","Text":"hello there!","UserDisplayName":"Jarrod Dixon","UserUrl":"/users/3/jarrod-dixon","DeleteUrl":null} - var renderComment = function(jDiv, json) { - var html = ''; +Comment.prototype.setContent = function(data){ + this._data = data; + this._element.html(''); + this._element.attr('class', 'comment').css('display:none'); + this._element.attr('id', 'comment-' + this._data['id']); + + this._element.append(data['text']); + this._element.append(' - '); + + this._user_link = $('').attr('class', 'comment-user'); + this._user_link.attr('href', this._data['user_url']); + this._user_link.html(this._data['user_display_name']); + this._element.append(this._user_link); + + this._element.append(' ('); + this._comment_age = $(''); + this._comment_age.html(this._data['comment_age']); + this._element.append(this._comment_age); + this._element.append(')'); + + if (this._deletable){ + this._delete_icon = new DeleteIcon(this._delete_prompt, this.getDeleteHandler); + this._element.append(this._delete_icon.getElement()); + } + if (this._editable){ + this._edit_link = new EditLink(this.getEditHandler()); + this._element.append(this._edit_link.getElement()); + this._element.mouseover(function(){this._edit_link.getElement().show()}); + this._element.mouseout(function(){this._edit_link.getElement().hide()}); + } + this._blank = false; +}; - jDiv.append(html); - }; +Comment.prototype.dispose = function(){ + this._user_link.remove(); + this._comment_age.remove(); + if (this._delete_icon){ + this._delete_icon.dispose(); + } + if (this._edit_link){ + this._edit_link.dispose(); + } + this._data = null; + Comment.superClass_.dispose.call(this); +}; - var postComment = function(id, formId) { - //appendLoaderImg(id); +Comment.prototype.getElement = function(){ + Comment.superClass_.getElement.call(this); + if (this._blank && this._data){ + this.setContent(this._data); + if (enableMathJax === true){ + MathJax.Hub.Queue(['Typeset', MathJax.Hub]); + } + } + return this._element; +}; - var formSelector = "#" + formId; - var textarea = $(formSelector + " textarea"); +Comment.prototype.loadText = function(on_load_handler){ + $.ajax({ + type: "GET", + url: askbot['urls']['commentGetText'], + data: {id: this._data['id']}, + success: on_load_handler + }); +}; - $.ajax({ - type: "POST", - url: scriptUrl + $.i18n._(objectType + "s/") + id + "/" + $.i18n._("comments/"), - dataType: "json", - data: { comment: textarea.val() }, - success: function(json) { - showComments(id, json); - textarea.val(""); - commentsFactory[objectType].updateTextCounter(textarea); - enableSubmitButton(formSelector); - }, - error: function(xhr, textStatus, errorThrown) { - removeLoader(); - showMessage($(formSelector), xhr.responseText); - enableSubmitButton(formSelector); +Comment.prototype.getEditHandler = function(){ + var comment_id = this._data['id']; + var parent_post_id = this._data['post_id']; + var comment = this; + return function(){ + comment.loadText( + function(text){ + if (editCommentForm.isFree()){ + editCommentForm.setComment(comment, text); + comment.getElement().after(editCommentForm.getElement()); + comment.getElement().hide(); + editCommentForm.activate(); + } + else { + editCommentForm.getElement().focus(); + } } - }); + ); }; +}; - // public methods.. - return { - - init: function() { - // Setup "show comments" clicks.. - $("a[id^='comments-link-" + objectType + "-" + "']").unbind("click").click(function() { - commentsFactory[objectType].show($(this).attr("id").substr(("comments-link-" + objectType + "-").length)); - }); - - var cBox = $("[id^='comments-container-" + objectType + "']"); - cBox.each( function(i){ - var post_id = $(this).attr('id').replace('comments-container-' + objectType + '-', ''); - - $(this).children().each( - function(i){ - var comment_id = $(this).attr('id').replace('comment-',''); - var delete_url = scriptUrl + $.i18n._(objectType + 's/') + post_id + '/' + - $.i18n._('comments/') + comment_id + '/' + $.i18n._('delete/'); - var html = $(this).html(); - var CommentsClass; - if (objectType == 'question'){ - CommentsClass = questionComments; - } - else if (objectType == 'answer') { - CommentsClass = answerComments; - } - var delete_icon = $(this).find('img.delete-icon'); - delete_icon.click(function(){CommentsClass.deleteComment($(this),comment_id,delete_url);}); - delete_icon.unbind('mouseover').bind('mouseover', - function(){ - $(this).attr('src',mediaUrl('media/images/close-small-hover.png')); - } - ); - delete_icon.unbind('mouseout').bind('mouseout', - function(){ - $(this).attr('src',mediaUrl('media/images/close-small.png')); - } - ); - } - ); +Comment.prototype.getDeleteHandler = function(){ + var comment = this; + return function(){ + if (confirm($.i18n._('confirm delete comment'))){ + $(this).hide(); + $.ajax({ + type: 'POST', + url: askbot['urls']['deleteComment'], + data: { comment_id: comment._data['id'] }, + success: function(json, textStatus, xhr) { + comment.dispose(); + }, + error: function(xhr, textStatus, exception) { + $(this).show(); + showMessage(me._delete_icon, xhr.responseText); + }, + dataType: "json" }); - }, + } + }; +}; - show: function(id) { - var jDiv = jDivInit(id); - getComments(id, jDiv); - renderForm(id); - jDiv.show(); +var PostCommentsWidget = function(){ + WrappedElement.call(this); + this._denied = false; +}; +inherits(PostCommentsWidget, WrappedElement); - var link = $('#comments-link-' + objectType + '-' + id); - if (canPostComments(id)) { link.parent().find("textarea").get(0).focus(); } - link.remove(); - }, +var PostCommentsWidget.prototype.decorate = function(element){ + var can_post_input = element.find('[id^="can-post-comments"]') + objectType + '-' + id); + this._user_can_post = (can_post_input.val().toLowerCase() == 'true'); + this._activate_button = element.find('a[id^="comments-link"]'); - hide: function(id) { - var jDiv = jDivInit(id); - var len = jDiv.children("div.comments").children().length; - var anchorText = len === 0 ? $.i18n._('add a comment') : $.i18n._('comments') + ' (' + len + ")"; + if (this.user_can_post == false){ + setupButtonEventHandlers(this._activate_button, this.getDenyHandler()); + } - jDiv.hide(); - jDiv.siblings("a").unbind("click").click(function() { commentsFactory[objectType].show(id); }).html(anchorText); - jDiv.children("div.comments").children().hide(); - }, + this._element = element; + var id = element.attr('id'); + this._post_type = id.split('-')[2]; + setupButtonEventHandlers(this._activate_button, this.getActivateHandler()); + + this._cbox = element.find('[id^="comments-container"]'); + var comments = new Array(); + this._cbox.each(function(index, element)){ + var comment = new Comment(); + comments.push(comment) + comment.decorate(element); + }); + this._comments = comments; +}; - deleteComment: function(jImg, id, deleteUrl) { - if (confirm($.i18n._('confirm delete comment'))) { - jImg.hide(); - $.ajax({ - type: 'POST', - url: deleteUrl, - data: { dataNeeded: "forIIS7" }, - success: function(json, textStatus, xhr) { - var par = jImg.parent(); - par.remove(); - }, - error: function(xhr, textStatus, exception) { - jImg.show(); - showMessage(jImg, xhr.responseText); - }, - dataType: "json" - }); - } - }, +var PostCommentsWidget.prototype.getActivateHandler = function(){ + var me = this; + return function() { + if (editCommentForm.isFree()){ + me.reloadAllComments(function(json){ + me.reRenderComments(json); + var comment = new Comment(); + var form = editCommentForm.setComment(comment); + me._cbox.append(form.getElement()); + me._activate_button.hide(); + editCommentForm.getElement().focus(); + }); + } + else { + editCommentForm.getElement().focus(); + } + }; +}; - updateTextCounter: function(textarea) { - var length = textarea.value ? textarea.value.length : 0; - var length1 = maxCommentLength - 100; - if (length1 < 0){ - length1 = Math.round(0.7*maxCommentLength); - } - var length2 = maxCommentLength - 30; - if (length2 < 0){ - length2 = Math.round(0.9*maxCommentLength); - } - var color = length > length2 ? "#f00" : length > length1 ? "#f60" : "#999"; - var jSpan = $(textarea).siblings("span.text-counter"); - jSpan.html($.i18n._('can write') + ' ' + - (maxCommentLength - length) + ' ' + - $.i18n._('characters')).css("color", color); +var PostCommentsWidget.prototype.getDenyHandler = function(){ + var me = this; + return function(){ + if (me._denied == false){ + var denial = $('

'); + denial.html($.i18n._('to comment, need') + ' ' + + repNeededForComments + ' ' + $.i18n._('community karma points') + + '' + + $.i18n._('please see') + 'faq' + ); + me._cbox.append(denial); } + me._denied = true; }; -} +}; + + +var 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'], + data: post_data, + success: callback, + dataType: "json" + }); +}; + +var PostCommentsWidget.prototype.reRenderComments = function(json){ + $.each(this._comments, function(i, item){ + item.dispose(); + }); + this._comments = new Array(); + $.each(json, function(i, item){ + var comment = new Comment(item); + this._comments.push(comment); + this._element.prepend(comment.getElement()); + }); +}; + var socialSharing = function(){ @@ -1104,9 +1321,11 @@ var socialSharing = function(){ }(); $(document).ready(function() { - questionComments.init(); + $('id^=comments-container-').each(function(index, element){ + var comments = new PostCommentsWidget(); + comments.decorate(element); + }); questionRetagger.init(); - answerComments.init(); socialSharing.init(); }); diff --git a/askbot/skins/default/templates/base.html b/askbot/skins/default/templates/base.html index d9ca2dea..24fbfdcd 100644 --- a/askbot/skins/default/templates/base.html +++ b/askbot/skins/default/templates/base.html @@ -42,6 +42,18 @@ var scriptUrl = '/{{settings.ASKBOT_URL}}' var askbotSkin = '{{settings.ASKBOT_DEFAULT_SKIN}}'; var enableMathJax = {% if settings.ENABLE_MATHJAX %}true{% else %}false{% endif %}; + var askbot = askbot || {}; + askbot['data'] = askbot['data'] || {}; + {% if request.user.is_authenticated() %} + askbot['data']['userIsAuthenticated'] = true; + askbot['data']['userId'] = {{request.user.id}}; + askbot['data']['userIsAdminOrMod'] = {% if + request.user.is_administrator() + or request.user.is_moderator() + %}true{% else %}false{% endif %}; + {% else %} + askbot['data']['userIsAuthenticated'] = false; + {% endif %}