diff --git a/README.rst b/README.rst index e6cdbf7..b3ba345 100644 --- a/README.rst +++ b/README.rst @@ -172,6 +172,24 @@ The templates and admin interface adapt themselves automatically to show the threaded comments. +Javascript Controls +------------------- + +You are able to control various output settings via javascript. + +1. is_reversed: Will use prepend instead of append to insert the ajax created comment + + +Insert the following code, that does not wait for document.ready + +``` + +``` + Contributing ------------ diff --git a/fluent_comments/admin.py b/fluent_comments/admin.py index 9460d5d..547f667 100644 --- a/fluent_comments/admin.py +++ b/fluent_comments/admin.py @@ -55,8 +55,11 @@ class FluentCommentsAdmin(CommentsAdminBase): def object_link(self, comment): object = comment.content_object - title = unicode(object) - return u'{1}'.format(escape(object.get_absolute_url()), escape(title)) + if object is not None and hasattr(object, 'get_absolute_url'): + title = unicode(object) + return u'{1}'.format(escape(object.get_absolute_url()), escape(title)) + else: + return u'{1}'.format('#', 'Comment Content_Object does not exist') object_link.short_description = _("Page") object_link.allow_tags = True diff --git a/fluent_comments/models.py b/fluent_comments/models.py index 38fad31..95c19e4 100644 --- a/fluent_comments/models.py +++ b/fluent_comments/models.py @@ -34,8 +34,8 @@ def on_comment_posted(sender, comment, request, **kwargs): 'content_object': content_object } - message = render(request, "comments/comment_notification_email.txt", context) - send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, recipient_list, fail_silently=True) + message = unicode(render(request, "comments/comment_notification_email.txt", context)) + send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, recipient_list, fail_silently=False) def get_comments_for_model(content_object, include_moderated=False): diff --git a/fluent_comments/static/fluent_comments/js/ajaxcomments.js b/fluent_comments/static/fluent_comments/js/ajaxcomments.js index 12def5a..f9e1e56 100644 --- a/fluent_comments/static/fluent_comments/js/ajaxcomments.js +++ b/fluent_comments/static/fluent_comments/js/ajaxcomments.js @@ -7,9 +7,14 @@ var COMMENT_SCROLL_TOP_OFFSET = 40; var PREVIEW_SCROLL_TOP_OFFSET = 20; - $.fn.ready(function() { + + var COMMENT_CONTROLS = (window.COMMENT_CONTROLS !== undefined) ? window.COMMENT_CONTROLS : { + 'is_reversed': false, + 'scroll_to_comment': true, + }; + var commentform = $('form.js-comments-form'); if( commentform.length > 0 ) { @@ -93,7 +98,7 @@ function scrollToElement( $element, speed, offset ) { - if( $element.length ) + if( $element.length && COMMENT_CONTROLS.scroll_to_comment === true ) $(scrollElement).animate( {scrollTop: $element.offset().top - (offset || 0) }, speed || 1000 ); } @@ -222,22 +227,26 @@ function addComment(data) { // data contains the server-side response. - var html = data['html'] + var html = $(data['html']) // create the domElement and thus fire appropriate events var parent_id = data['parent_id']; var $new_comment; + + // define the action by which the comment is inserted at the top of the list or the bottom + var insert_action = (COMMENT_CONTROLS.is_reversed === true) ? 'prepend' : 'append' ; + if(parent_id) { var $parentLi = $("#c" + parseInt(parent_id)).parent('li.comment-wrapper'); var $commentUl = $parentLi.children('ul'); if( $commentUl.length == 0 ) $commentUl = $parentLi.append('').children('ul.comment-list-wrapper'); - $commentUl.append('
  • ' + html + '
  • '); + $commentUl[insert_action]('
  • ' + html.prop('outerHTML') + '
  • '); } else { var $comments = getCommentsDiv(); - $comments.append(html).removeClass('empty'); + $comments[insert_action](html.prop('outerHTML')).removeClass('empty'); } return $("#c" + parseInt(data.comment_id)); diff --git a/fluent_comments/templatetags/fluent_comments_tags.py b/fluent_comments/templatetags/fluent_comments_tags.py index 8251ea8..1fd8eaf 100644 --- a/fluent_comments/templatetags/fluent_comments_tags.py +++ b/fluent_comments/templatetags/fluent_comments_tags.py @@ -1,11 +1,13 @@ from django.conf import settings from django.template import Library from django.core import context_processors -from django.template.loader import get_template +from django.template.loader import get_template, render_to_string +from django.contrib.comments.templatetags.comments import RenderCommentListNode from fluent_comments import appsettings from fluent_comments.models import get_comments_for_model from fluent_comments.moderation import comments_are_open, comments_are_moderated + register = Library() @register.inclusion_tag("fluent_comments/templatetags/ajax_comment_tags.html", takes_context=True) @@ -56,3 +58,45 @@ def fluent_comments_list(context): context['USE_THREADEDCOMMENTS'] = appsettings.USE_THREADEDCOMMENTS return template.render(context) + + +class RenderCommentListReversedNode(RenderCommentListNode): + """Render the comment list directly in reverse """ + + def render(self, context): + ctype, object_pk = self.get_target_ctype_pk(context) + if object_pk: + template_search_list = [ + "comments/%s/%s/list.html" % (ctype.app_label, ctype.model), + "comments/%s/list.html" % ctype.app_label, + "comments/list.html" + ] + qs = self.get_query_set(context).prefetch_related('user').order_by('-id') + context.push() + liststr = render_to_string(template_search_list, { + "comment_list" : self.get_context_value_from_queryset(context, qs) + }, context) + context.pop() + return liststr + else: + return '' + +@register.tag +def render_comment_list_reversed(parser, token): + """ + Render the comment list (as returned by ``{% get_comment_list %}``) + through the ``comments/list.html`` template + + but in reverse order + + Syntax:: + + {% render_comment_list_reversed for [object] %} + {% render_comment_list_reversed for [app].[model] [object_id] %} + + Example usage:: + + {% render_comment_list_reversed for event %} + + """ + return RenderCommentListReversedNode.handle_token(parser, token) \ No newline at end of file