From fd215812087d7e3ceb8c31d754a5cda7bb7e8e9b Mon Sep 17 00:00:00 2001
From: Emily O'Leary <lotusecho@ThinkLotus>
Date: Sun, 24 Mar 2013 21:42:42 -0400
Subject: [PATCH 1/4] Added comment preview functionality to user pages. It
 works by passing the comment's value as a JSON string
 to a new handler that lives at /ajax/comment/preview.
 The query string is decoded, unquoted, and has its
 leading and trailing quotes removed to match the input
 that cleaned_markdown_conversion expects.

It does this in real time with a 500ms lag by using a timer. Initially I tried the onChange handler but you need to lose focus for that to process. The javascript timer is only invoked if the add comment button is pressed. A request is only sent if the comment box is not empty and the current value is not the same as the last value.
---
 mediagoblin/static/js/comment_show.js               |   12 ++++++++++++
 .../templates/mediagoblin/user_pages/media.html     |    2 ++
 mediagoblin/user_pages/forms.py                     |    2 +-
 mediagoblin/user_pages/routing.py                   |    4 ++++
 mediagoblin/user_pages/views.py                     |   19 ++++++++++++++++++-
 5 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/mediagoblin/static/js/comment_show.js b/mediagoblin/static/js/comment_show.js
index c5ccee6..cb69fcc 100644
--- a/mediagoblin/static/js/comment_show.js
+++ b/mediagoblin/static/js/comment_show.js
@@ -15,12 +15,24 @@
  * You should have received a copy of the GNU Affero General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+var content="";
 
+function previewComment(){
+	if ($('#comment_content').val() && (content != $('#comment_content').val())) {
+		content = $('#comment_content').val();
+		$.getJSON($('#previewURL').val(),JSON.stringify($('#comment_content').val()),
+		function(data){
+			$('#comment_preview').replaceWith("<div id=comment_preview><h3>Comment Preview</h3><br />" + decodeURIComponent(data) + 
+			"<hr style='border: 1px solid #333;' /></div>");
+		});
+	}
+}
 $(document).ready(function(){
   $('#form_comment').hide();
   $('#button_addcomment').click(function(){
     $(this).fadeOut('fast');
     $('#form_comment').slideDown(function(){
+	setInterval("previewComment()",500);
         $('#comment_content').focus();
     });
   });
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html
index b77c12b..28573d3 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media.html
@@ -102,7 +102,9 @@
             <input type="submit" value="{% trans %}Add this comment{% endtrans %}" class="button_action" />
               {{ csrf_token }}
           </div>
+          <input type="hidden" value="{{ request.urlgen('mediagoblin.user_pages.media_preview_comment') }}" id="previewURL" />
         </form>
+	<div id="comment_preview"></div>
       {% endif %}
       <ul style="list-style:none">
       {% for comment in comments %}
diff --git a/mediagoblin/user_pages/forms.py b/mediagoblin/user_pages/forms.py
index e9746a6..fe6fccf 100644
--- a/mediagoblin/user_pages/forms.py
+++ b/mediagoblin/user_pages/forms.py
@@ -23,7 +23,7 @@ class MediaCommentForm(wtforms.Form):
         _('Comment'),
         [wtforms.validators.Required()],
         description=_(u'You can use '
-                      u'<a href="http://daringfireball.net/projects/markdown/basics">'
+                      u'<a href="http://daringfireball.net/projects/markdown/basics" target=new>'
                       u'Markdown</a> for formatting.'))
 
 class ConfirmDeleteForm(wtforms.Form):
diff --git a/mediagoblin/user_pages/routing.py b/mediagoblin/user_pages/routing.py
index 9cb665b..b1dde39 100644
--- a/mediagoblin/user_pages/routing.py
+++ b/mediagoblin/user_pages/routing.py
@@ -32,6 +32,10 @@ add_route('mediagoblin.user_pages.media_post_comment',
           '/u/<string:user>/m/<int:media_id>/comment/add/',
           'mediagoblin.user_pages.views:media_post_comment')
 
+add_route('mediagoblin.user_pages.media_preview_comment',
+          '/ajax/comment/preview/',
+          'mediagoblin.user_pages.views:media_preview_comment')
+
 add_route('mediagoblin.user_pages.user_gallery',
           '/u/<string:user>/gallery/',
           'mediagoblin.user_pages.views:user_gallery')
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index c611daa..c50d801 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -16,22 +16,26 @@
 
 import logging
 import datetime
+import json
+import urllib
 
 from mediagoblin import messages, mg_globals
 from mediagoblin.db.models import (MediaEntry, MediaTag, Collection,
                                    CollectionItem, User)
 from mediagoblin.tools.response import render_to_response, render_404, redirect
+from mediagoblin.tools.text import cleaned_markdown_conversion
 from mediagoblin.tools.translate import pass_to_ugettext as _
 from mediagoblin.tools.pagination import Pagination
 from mediagoblin.user_pages import forms as user_forms
 from mediagoblin.user_pages.lib import send_comment_email
-
+from mediagoblin.meddleware.csrf import render_csrf_form_token
 from mediagoblin.decorators import (uses_pagination, get_user_media_entry,
     get_media_entry_by_id,
     require_active_login, user_may_delete_media, user_may_alter_collection,
     get_user_collection, get_user_collection_item, active_user_from_url)
 
 from werkzeug.contrib.atom import AtomFeed
+from werkzeug.wrappers import Response
 
 
 _log = logging.getLogger(__name__)
@@ -157,6 +161,7 @@ def media_post_comment(request, media):
     comment = request.db.MediaComment()
     comment.media_entry = media.id
     comment.author = request.user.id
+    print request.form['comment_content']
     comment.content = unicode(request.form['comment_content'])
 
     if not comment.content.strip():
@@ -180,6 +185,18 @@ def media_post_comment(request, media):
     return redirect(request, location=media.url_for_self(request.urlgen))
 
 
+
+def media_preview_comment(request):
+
+    comment = unicode(urllib.unquote(request.query_string).decode('string_escape'))
+    if comment.startswith('"') and comment.endswith('"'):
+        comment = comment[1:-1]
+    print comment
+    #decoderRing = json.JSONDecoder()
+   #comment = decoderRing.decode(request.query_string)
+	
+    return Response(json.dumps(cleaned_markdown_conversion(comment)))
+
 @get_media_entry_by_id
 @require_active_login
 def media_collect(request, media):
-- 
1.7.10.4


From 1e2720a25acc7408ab6eb0d498fc389a1fc73e6b Mon Sep 17 00:00:00 2001
From: Emily O'Leary <lotusecho@ThinkLotus>
Date: Sun, 24 Mar 2013 22:16:12 -0400
Subject: [PATCH 2/4] Added i18n to my javascript changes as per trac #417

---
 mediagoblin/static/js/comment_show.js |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mediagoblin/static/js/comment_show.js b/mediagoblin/static/js/comment_show.js
index cb69fcc..35183be 100644
--- a/mediagoblin/static/js/comment_show.js
+++ b/mediagoblin/static/js/comment_show.js
@@ -22,7 +22,7 @@ function previewComment(){
 		content = $('#comment_content').val();
 		$.getJSON($('#previewURL').val(),JSON.stringify($('#comment_content').val()),
 		function(data){
-			$('#comment_preview').replaceWith("<div id=comment_preview><h3>Comment Preview</h3><br />" + decodeURIComponent(data) + 
+			$('#comment_preview').replaceWith("<div id=comment_preview><h3>{% trans -%}Comment Preview{%- endtrans %}</h3><br />" + decodeURIComponent(data) + 
 			"<hr style='border: 1px solid #333;' /></div>");
 		});
 	}
-- 
1.7.10.4


From 53576b3f233c83bc54b7ec0d6791141ed89ec026 Mon Sep 17 00:00:00 2001
From: Emily O'Leary <lotusecho@ThinkLotus>
Date: Mon, 25 Mar 2013 14:13:09 -0400
Subject: [PATCH 3/4] Changed the target of the markdown links for opening in
 a new tab as suggested by joar.

---
 mediagoblin/user_pages/forms.py |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mediagoblin/user_pages/forms.py b/mediagoblin/user_pages/forms.py
index fe6fccf..7c04c9d 100644
--- a/mediagoblin/user_pages/forms.py
+++ b/mediagoblin/user_pages/forms.py
@@ -23,7 +23,7 @@ class MediaCommentForm(wtforms.Form):
         _('Comment'),
         [wtforms.validators.Required()],
         description=_(u'You can use '
-                      u'<a href="http://daringfireball.net/projects/markdown/basics" target=new>'
+                      u'<a href="http://daringfireball.net/projects/markdown/basics" target="_blank">'
                       u'Markdown</a> for formatting.'))
 
 class ConfirmDeleteForm(wtforms.Form):
@@ -47,5 +47,5 @@ class MediaCollectForm(wtforms.Form):
     collection_description = wtforms.TextAreaField(
         _('Description of this collection'),
         description=_("""You can use
-                      <a href="http://daringfireball.net/projects/markdown/basics">
+                      <a href="http://daringfireball.net/projects/markdown/basics" target="_blank">
                       Markdown</a> for formatting."""))
-- 
1.7.10.4


From d1b23937078582864f842b075f24c8263e513c59 Mon Sep 17 00:00:00 2001
From: Emily O'Leary <Emma.C.Echo@gmail.com>
Date: Tue, 6 Aug 2013 18:22:51 -0400
Subject: [PATCH 4/4] Changed how the comment was encoded/read. Fixed CSRF +
 Post with comment preview. Merged with latest master

---
 mediagoblin/static/js/comment_show.js               |   19 ++++++++++---------
 .../templates/mediagoblin/user_pages/media.html     |    1 +
 mediagoblin/user_pages/views.py                     |   12 ++++--------
 3 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/mediagoblin/static/js/comment_show.js b/mediagoblin/static/js/comment_show.js
index 35183be..42a2181 100644
--- a/mediagoblin/static/js/comment_show.js
+++ b/mediagoblin/static/js/comment_show.js
@@ -18,21 +18,22 @@
 var content="";
 
 function previewComment(){
-	if ($('#comment_content').val() && (content != $('#comment_content').val())) {
-		content = $('#comment_content').val();
-		$.getJSON($('#previewURL').val(),JSON.stringify($('#comment_content').val()),
-		function(data){
-			$('#comment_preview').replaceWith("<div id=comment_preview><h3>{% trans -%}Comment Preview{%- endtrans %}</h3><br />" + decodeURIComponent(data) + 
-			"<hr style='border: 1px solid #333;' /></div>");
-		});
-	}
+    if ($('#comment_content').val() && (content != $('#comment_content').val())) {
+        content = $('#comment_content').val();
+        $.post($('#previewURL').val(),$('#form_comment').serialize(),
+        function(data){
+            preview = JSON.parse(data)
+            $('#comment_preview').replaceWith("<div id=comment_preview><h3>" + $('#previewText').val() +"</h3><br />" + preview.content + 
+            "<hr style='border: 1px solid #333;' /></div>");
+        });
+    }
 }
 $(document).ready(function(){
   $('#form_comment').hide();
   $('#button_addcomment').click(function(){
     $(this).fadeOut('fast');
     $('#form_comment').slideDown(function(){
-	setInterval("previewComment()",500);
+    setInterval("previewComment()",500);
         $('#comment_content').focus();
     });
   });
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html
index 39a5eec..3acd835 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media.html
@@ -108,6 +108,7 @@
               {{ csrf_token }}
           </div>
           <input type="hidden" value="{{ request.urlgen('mediagoblin.user_pages.media_preview_comment') }}" id="previewURL" />
+          <input type="hidden" value="{% trans %}Comment Preview{% endtrans %}" id="previewText"/>
         </form>
 	<div id="comment_preview"></div>
       {% endif %}
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index 66d8fc5..a087851 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -198,15 +198,11 @@ def media_post_comment(request, media):
 
 
 def media_preview_comment(request):
+    """Runs a comment through markdown so it can be previewed."""
+    comment = unicode(request.form['comment_content'])
+    cleancomment = { "content":cleaned_markdown_conversion(comment)}
 
-    comment = unicode(urllib.unquote(request.query_string).decode('string_escape'))
-    if comment.startswith('"') and comment.endswith('"'):
-        comment = comment[1:-1]
-    print comment
-    #decoderRing = json.JSONDecoder()
-   #comment = decoderRing.decode(request.query_string)
-	
-    return Response(json.dumps(cleaned_markdown_conversion(comment)))
+    return Response(json.dumps(cleancomment))
 
 @get_media_entry_by_id
 @require_active_login
-- 
1.7.10.4

