changeset 1099:3f0a7e918c05

Prepare to detach V3 post box from GCalendar.
author Brian Neal <bgneal@gmail.com>
date Mon, 27 Jun 2016 20:11:17 -0500
parents c245caccbbb3
children 541125738f9d
files core/templatetags/core_tags.py gcalendar/static/js/gcalendar.js sg101/static/js/v3/post_box.js sg101/templates/core/v3/post_box.html sg101/templates/core/v3/post_box_modals.html sg101/templates/gcalendar/event.html
diffstat 6 files changed, 473 insertions(+), 463 deletions(-) [+]
line wrap: on
line diff
--- a/core/templatetags/core_tags.py	Mon Jun 27 18:40:59 2016 -0500
+++ b/core/templatetags/core_tags.py	Mon Jun 27 20:11:17 2016 -0500
@@ -238,3 +238,10 @@
     return {
         'slides': slides,
     }
+
+
+@register.inclusion_tag('core/v3/post_box.html')
+def post_box(form_field):
+    return {
+        'form_field': form_field,
+    }
--- a/gcalendar/static/js/gcalendar.js	Mon Jun 27 18:40:59 2016 -0500
+++ b/gcalendar/static/js/gcalendar.js	Mon Jun 27 20:11:17 2016 -0500
@@ -1,46 +1,3 @@
-function editorReplaceText(textArea, i, j, newText) {
-   textArea.value = textArea.value.substring(0, i) + newText +
-      textArea.value.substring(j);
-}
-
-function editorWrapSelection(textArea, wrapText) {
-   if (wrapText.length == 0) return;
-   var i = textArea.selectionStart;
-   var j = textArea.selectionEnd;
-   if (i == j) return;
-   var selection = textArea.value.substring(i, j);
-   var newText = wrapText + selection + wrapText;
-   editorReplaceText(textArea, i, j, newText);
-   textArea.focus();
-   textArea.setSelectionRange(i, j + 2 * wrapText.length);
-}
-
-function editorPrependLines(textArea, s) {
-   if (s.length == 0) return;
-   var i = textArea.selectionStart;
-   var j = textArea.selectionEnd;
-   var newText = s;
-   var selection = textArea.value.substring(i, j);
-   newText += selection.replace(/\n/gm, '\n' + s);
-   editorReplaceText(textArea, i, j, newText);
-}
-
-function editorLink(textArea) {
-   var i = textArea.selectionStart;
-   var j = textArea.selectionEnd;
-   var url = window.prompt("Please enter a URL:", "http://");
-   if (!url) return;
-   var link;
-   if (i == j) {
-      link = '[Link](' + url + ')';
-   } else {
-      var selection = textArea.value.substring(i, j);
-      link = '[' + selection + '](' + url + ')';
-   }
-   editorReplaceText(textArea, i, j, link);
-   textArea.focus();
-}
-
 $(document).ready(function() {
     $('#id_start_date').datepicker({constrainInput: true, 
        dateFormat: 'mm/dd/yy',
@@ -68,178 +25,4 @@
     $('#id_all_day').click(function () {
        $('.all-day-hide').toggle();
     });
-
-   var editorPanel = $('#editor-panel textarea');
-   var previewPanel = $('#editor-preview-panel');
-
-   $('#preview-modal').on('open.zf.reveal', function() {
-      previewPanel.html('');
-      previewPanel.scrollTop(0);
-      // TODO:
-      // Clear preview panel and/or show spinner
-      // If there is any text in editor panel {
-      $.ajax({
-         url: '/comments/markdown/v3/',
-         method: 'POST',
-         data: {'data': editorPanel[0].value},
-         dataType: 'html',
-         success: function(data, textStatus) {
-            previewPanel.html(data);
-         },
-         error: function (xhr, textStatus, ex) {
-            alert('Oops, an error occurred: ' + xhr.statusText + ' - ' +
-                  xhr.responseText);
-         }
-      });
-   });
-
-   // Editor stuff
-   var $postBox;
-   $('.v3-editor').each(function (index) {
-      var $this = $(this);
-      var textArea = $this.find('textarea')[0];
-      $this.find('.editor-bold').click(function () {
-         editorWrapSelection(textArea, '**');
-         return false;
-      });
-      $this.find('.editor-italic').click(function () {
-         editorWrapSelection(textArea, '_');
-         return false;
-      });
-      $this.find('.editor-strike').click(function () {
-         editorWrapSelection(textArea, '---');
-         return false;
-      });
-      $this.find('.editor-link').click(function () {
-         editorLink(textArea);
-         return false;
-      });
-      $this.find('.editor-quote').click(function () {
-         editorPrependLines(textArea, '> ');
-         return false;
-      });
-      $this.find('.editor-code').click(function () {
-         editorPrependLines(textArea, '    ');
-         return false;
-      });
-      $this.find('.editor-bullet').click(function () {
-         editorPrependLines(textArea, '* ');
-         return false;
-      });
-      $this.find('.editor-number').click(function () {
-         editorPrependLines(textArea, '1. ');
-         return false;
-      });
-      $this.find('.editor-hot-link').click(function () {
-         $postBox = $(textArea);
-      });
-      $this.find('.editor-upload').click(function () {
-         $postBox = $(textArea);
-      });
-   });
-
-   var $hotLinkForm = $('#hot-link-form');
-   if ($hotLinkForm.length) {
-      var $hotLinkFormSubmit = $('#hot-link-form-submit');
-      var $hotLinkStatus = $('#hot-link-status');
-
-      $('#hot-link-modal').on('open.zf.reveal', function() {
-         $hotLinkForm.clearForm();
-      });
-      $('#hot-link-modal').on('closed.zf.reveal', function() {
-         $hotLinkStatus.hide();
-      });
-
-      $hotLinkForm.ajaxForm({
-         dataType: 'json',
-         beforeSubmit: function(arr, $form, options) {
-            var url = null;
-            $.each(arr, function(index, val) {
-               if (val.name == 'url') {
-                  url = val.value;
-               }
-            });
-            if (!url) {
-               $hotLinkStatus.removeClass('success').addClass('alert');
-               $hotLinkStatus.html("Please enter a link to an image.");
-               $hotLinkStatus.fadeIn(700);
-               return false;
-            } else {
-               $hotLinkStatus.hide();
-            }
-            $hotLinkFormSubmit.attr('disabled', 'disabled').val('Retrieving...');
-            $hotLinkFormSubmit.addClass('disabled');
-            return true;
-         },
-         success: function(resp, statusText, xhr, $form) {
-            $postBox.val($postBox.val() + '\n![image](' + resp.url + ')');
-            $hotLinkStatus.removeClass('alert').addClass('success');
-            $hotLinkStatus.html("Success! The image code was added to your post.");
-            $hotLinkStatus.fadeIn(700);
-            $hotLinkForm.clearForm();
-         },
-         complete: function(xhr) {
-            $hotLinkFormSubmit.removeAttr('disabled').val('Hot Link');
-            $hotLinkFormSubmit.removeClass('disabled');
-         },
-         error: function(xhr, textStatus, ex) {
-            $hotLinkStatus.removeClass('success').addClass('alert');
-            var resp = $.parseJSON(xhr.responseText);
-            $hotLinkStatus.html("Error: " + ex + ' - ' + resp.error_msg);
-            $hotLinkStatus.fadeIn(700);
-         }
-      });
-   }
-   var $photoForm = $('#photo-upload-form');
-   if ($photoForm.length) {
-      var $photoUploadSubmit = $('#photo-upload-submit');
-      var $photoStatus = $('#photo-status');
-
-      $('#upload-modal').on('open.zf.reveal', function() {
-         $photoForm.clearForm();
-      });
-      $('#upload-modal').on('closed.zf.reveal', function() {
-         $photoStatus.hide();
-      });
-
-      $photoForm.ajaxForm({
-         dataType: 'json',
-         beforeSubmit: function(arr, $form, options) {
-            var fileObj = null;
-            $.each(arr, function(index, val) {
-               if (val.name == 'image_file') {
-                  fileObj = val.value;
-               }
-            });
-            if (!fileObj) {
-               $photoStatus.removeClass('success').addClass('alert');
-               $photoStatus.html("Please choose a file to upload.");
-               $photoStatus.fadeIn(700);
-               return false;
-            } else {
-               $photoStatus.hide();
-            }
-            $photoUploadSubmit.attr('disabled', 'disabled').val('Uploading...');
-            $photoUploadSubmit.addClass('disabled');
-            return true;
-         },
-         success: function(resp, statusText, xhr, $form) {
-            $postBox.val($postBox.val() + '\n![image](' + resp.url + ')');
-            $photoStatus.removeClass('alert').addClass('success');
-            $photoStatus.html("Success! The image code was added to your post.");
-            $photoStatus.fadeIn(700);
-            $photoStatus.clearForm();
-         },
-         complete: function(xhr) {
-            $photoUploadSubmit.removeAttr('disabled').val('Upload photo');
-            $photoUploadSubmit.removeClass('disabled');
-         },
-         error: function(xhr, textStatus, ex) {
-            $photoStatus.removeClass('success').addClass('alert');
-            var resp = $.parseJSON(xhr.responseText);
-            $photoStatus.html("Error: " + ex + ' - ' + resp.error_msg);
-            $photoStatus.fadeIn(700);
-         }
-      });
-   }
 });
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sg101/static/js/v3/post_box.js	Mon Jun 27 20:11:17 2016 -0500
@@ -0,0 +1,218 @@
+function editorReplaceText(textArea, i, j, newText) {
+   textArea.value = textArea.value.substring(0, i) + newText +
+      textArea.value.substring(j);
+}
+
+function editorWrapSelection(textArea, wrapText) {
+   if (wrapText.length == 0) return;
+   var i = textArea.selectionStart;
+   var j = textArea.selectionEnd;
+   if (i == j) return;
+   var selection = textArea.value.substring(i, j);
+   var newText = wrapText + selection + wrapText;
+   editorReplaceText(textArea, i, j, newText);
+   textArea.focus();
+   textArea.setSelectionRange(i, j + 2 * wrapText.length);
+}
+
+function editorPrependLines(textArea, s) {
+   if (s.length == 0) return;
+   var i = textArea.selectionStart;
+   var j = textArea.selectionEnd;
+   var newText = s;
+   var selection = textArea.value.substring(i, j);
+   newText += selection.replace(/\n/gm, '\n' + s);
+   editorReplaceText(textArea, i, j, newText);
+}
+
+function editorLink(textArea) {
+   var i = textArea.selectionStart;
+   var j = textArea.selectionEnd;
+   var url = window.prompt("Please enter a URL:", "http://");
+   if (!url) return;
+   var link;
+   if (i == j) {
+      link = '[Link](' + url + ')';
+   } else {
+      var selection = textArea.value.substring(i, j);
+      link = '[' + selection + '](' + url + ')';
+   }
+   editorReplaceText(textArea, i, j, link);
+   textArea.focus();
+}
+
+$(document).ready(function() {
+   var editorPanel = $('#editor-panel textarea');
+   var previewPanel = $('#editor-preview-panel');
+
+   $('#preview-modal').on('open.zf.reveal', function() {
+      previewPanel.html('');
+      previewPanel.scrollTop(0);
+      // TODO:
+      // Clear preview panel and/or show spinner
+      // If there is any text in editor panel {
+      $.ajax({
+         url: '/comments/markdown/v3/',
+         method: 'POST',
+         data: {'data': editorPanel[0].value},
+         dataType: 'html',
+         success: function(data, textStatus) {
+            previewPanel.html(data);
+         },
+         error: function (xhr, textStatus, ex) {
+            alert('Oops, an error occurred: ' + xhr.statusText + ' - ' +
+                  xhr.responseText);
+         }
+      });
+   });
+
+   // Editor stuff
+   var $postBox;
+   $('.v3-editor').each(function (index) {
+      var $this = $(this);
+      var textArea = $this.find('textarea')[0];
+      $this.find('.editor-bold').click(function () {
+         editorWrapSelection(textArea, '**');
+         return false;
+      });
+      $this.find('.editor-italic').click(function () {
+         editorWrapSelection(textArea, '_');
+         return false;
+      });
+      $this.find('.editor-strike').click(function () {
+         editorWrapSelection(textArea, '---');
+         return false;
+      });
+      $this.find('.editor-link').click(function () {
+         editorLink(textArea);
+         return false;
+      });
+      $this.find('.editor-quote').click(function () {
+         editorPrependLines(textArea, '> ');
+         return false;
+      });
+      $this.find('.editor-code').click(function () {
+         editorPrependLines(textArea, '    ');
+         return false;
+      });
+      $this.find('.editor-bullet').click(function () {
+         editorPrependLines(textArea, '* ');
+         return false;
+      });
+      $this.find('.editor-number').click(function () {
+         editorPrependLines(textArea, '1. ');
+         return false;
+      });
+      $this.find('.editor-hot-link').click(function () {
+         $postBox = $(textArea);
+      });
+      $this.find('.editor-upload').click(function () {
+         $postBox = $(textArea);
+      });
+   });
+
+   var $hotLinkForm = $('#hot-link-form');
+   if ($hotLinkForm.length) {
+      var $hotLinkFormSubmit = $('#hot-link-form-submit');
+      var $hotLinkStatus = $('#hot-link-status');
+
+      $('#hot-link-modal').on('open.zf.reveal', function() {
+         $hotLinkForm.clearForm();
+      });
+      $('#hot-link-modal').on('closed.zf.reveal', function() {
+         $hotLinkStatus.hide();
+      });
+
+      $hotLinkForm.ajaxForm({
+         dataType: 'json',
+         beforeSubmit: function(arr, $form, options) {
+            var url = null;
+            $.each(arr, function(index, val) {
+               if (val.name == 'url') {
+                  url = val.value;
+               }
+            });
+            if (!url) {
+               $hotLinkStatus.removeClass('success').addClass('alert');
+               $hotLinkStatus.html("Please enter a link to an image.");
+               $hotLinkStatus.fadeIn(700);
+               return false;
+            } else {
+               $hotLinkStatus.hide();
+            }
+            $hotLinkFormSubmit.attr('disabled', 'disabled').val('Retrieving...');
+            $hotLinkFormSubmit.addClass('disabled');
+            return true;
+         },
+         success: function(resp, statusText, xhr, $form) {
+            $postBox.val($postBox.val() + '\n![image](' + resp.url + ')');
+            $hotLinkStatus.removeClass('alert').addClass('success');
+            $hotLinkStatus.html("Success! The image code was added to your post.");
+            $hotLinkStatus.fadeIn(700);
+            $hotLinkForm.clearForm();
+         },
+         complete: function(xhr) {
+            $hotLinkFormSubmit.removeAttr('disabled').val('Hot Link');
+            $hotLinkFormSubmit.removeClass('disabled');
+         },
+         error: function(xhr, textStatus, ex) {
+            $hotLinkStatus.removeClass('success').addClass('alert');
+            var resp = $.parseJSON(xhr.responseText);
+            $hotLinkStatus.html("Error: " + ex + ' - ' + resp.error_msg);
+            $hotLinkStatus.fadeIn(700);
+         }
+      });
+   }
+   var $photoForm = $('#photo-upload-form');
+   if ($photoForm.length) {
+      var $photoUploadSubmit = $('#photo-upload-submit');
+      var $photoStatus = $('#photo-status');
+
+      $('#upload-modal').on('open.zf.reveal', function() {
+         $photoForm.clearForm();
+      });
+      $('#upload-modal').on('closed.zf.reveal', function() {
+         $photoStatus.hide();
+      });
+
+      $photoForm.ajaxForm({
+         dataType: 'json',
+         beforeSubmit: function(arr, $form, options) {
+            var fileObj = null;
+            $.each(arr, function(index, val) {
+               if (val.name == 'image_file') {
+                  fileObj = val.value;
+               }
+            });
+            if (!fileObj) {
+               $photoStatus.removeClass('success').addClass('alert');
+               $photoStatus.html("Please choose a file to upload.");
+               $photoStatus.fadeIn(700);
+               return false;
+            } else {
+               $photoStatus.hide();
+            }
+            $photoUploadSubmit.attr('disabled', 'disabled').val('Uploading...');
+            $photoUploadSubmit.addClass('disabled');
+            return true;
+         },
+         success: function(resp, statusText, xhr, $form) {
+            $postBox.val($postBox.val() + '\n![image](' + resp.url + ')');
+            $photoStatus.removeClass('alert').addClass('success');
+            $photoStatus.html("Success! The image code was added to your post.");
+            $photoStatus.fadeIn(700);
+            $photoStatus.clearForm();
+         },
+         complete: function(xhr) {
+            $photoUploadSubmit.removeAttr('disabled').val('Upload photo');
+            $photoUploadSubmit.removeClass('disabled');
+         },
+         error: function(xhr, textStatus, ex) {
+            $photoStatus.removeClass('success').addClass('alert');
+            var resp = $.parseJSON(xhr.responseText);
+            $photoStatus.html("Error: " + ex + ' - ' + resp.error_msg);
+            $photoStatus.fadeIn(700);
+         }
+      });
+   }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sg101/templates/core/v3/post_box.html	Mon Jun 27 20:11:17 2016 -0500
@@ -0,0 +1,27 @@
+{{ form_field.errors }}
+<div class="row">
+   <div class="columns">
+      <label for="{{ form_field.id_for_label }}">{{ form_field.label }}</label>
+      <div class="tabs-panel is-active v3-editor" id="editor-panel">
+         <ul class="menu">
+            <li><a class="editor-bold hide-for-small-only" href="#"><i class="fi-bold size-21" title="Bold"></i></a></li>
+            <li><a class="editor-italic hide-for-small-only" href="#"><i class="fi-italic size-21" title="Italic"></i></a></li>
+            <li><a class="editor-strike hide-for-small-only" href="#"><i class="fi-strikethrough size-21" title="Strike"></i></a></li>
+            <li><a class="editor-link" href="#"><i class="fi-link size-21" title="Link"></i></a></li>
+            <li><a class="editor-quote hide-for-small-only" href="#"><i class="fi-quote size-21" title="Quote"></i></a></li>
+            <li><a class="editor-code hide-for-small-only" href="#"><i class="fi-music size-21" title="Format Tablature"></i></a></li>
+            <li><a class="editor-bullet hide-for-small-only" href="#"><i class="fi-list-bullet size-21" title="Bullet List"></i></a></li>
+            <li><a class="editor-number hide-for-small-only" href="#"><i class="fi-list-number size-21" title="Numbered List"></i></a></li>
+            <li><a class="editor-hot-link" data-open="hot-link-modal">
+               <i class="fi-photo size-21" title="Hot-Link Image"></i></a></li>
+            <li><a class="editor-upload" data-open="upload-modal">
+               <i class="fi-upload size-21" title="Upload Image"></i></a></li>
+            <li><a class="editor-preview" data-open="preview-modal">
+               <i class="fi-eye size-21" title="Preview"></i></a></li>
+            <li><a class="editor-help" data-open="help-modal">
+               <i class="fi-info size-21" title="Help with markup"></i></a></li>
+         </ul>
+         {{ form_field }}
+      </div>
+   </div>
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sg101/templates/core/v3/post_box_modals.html	Mon Jun 27 20:11:17 2016 -0500
@@ -0,0 +1,218 @@
+<div class="small reveal" id="hot-link-modal" data-reveal>
+   <button class="close-button" data-close aria-label="Close modal" type="button">
+      <span aria-hidden="true">&times;</span>
+   </button>
+   <div class="row">
+      <div class="columns">
+         <p class="lead">Hot-Link Image</p>
+      </div>
+   </div>
+   <div class="row">
+      <div class="columns">
+         <p>
+         To add an image already on the Internet to your post, copy &amp; paste the
+         image address to the box below and click "Hot-Link". An image code will be placed
+         in your post after the image is processed.
+         </p>
+      </div>
+   </div>
+   <form id="hot-link-form" action="{% url 'user_photos-hotlink' %}" method="post">{% csrf_token %}
+      <div class="row">
+         <div class="columns">
+            <label>Image Address
+               <input type="url" name="url" placeholder="http://" />
+            </label>
+         </div>
+      </div>
+      <div class="row">
+         <div class="columns">
+            <div id="hot-link-status" class="hidden success callout">
+               Success! An image code was added to your post.
+            </div>
+         </div>
+      </div>
+      <div class="row">
+         <div class="columns text-right">
+            <input type="submit" id="hot-link-form-submit" class="primary button"
+               name="submit" value="Hot-Link" />
+            <button class="secondary button" data-close aria-label="Close modal" type="button">
+               Cancel
+            </button>
+         </div>
+      </div>
+   </form>
+</div>
+
+<div class="reveal" id="upload-modal" data-reveal>
+   <button class="close-button" data-close aria-label="Close modal" type="button">
+      <span aria-hidden="true">&times;</span>
+   </button>
+   <div class="row">
+      <div class="columns">
+         <p class="lead">Upload Image</p>
+      </div>
+   </div>
+   <div class="row">
+      <div class="columns">
+         <p>
+         You can upload an image directly from your computer or device with this
+         form. After the image is uploaded it will be resized and an image code will be
+         placed your post.
+         </p>
+      </div>
+   </div>
+   <form id="photo-upload-form" action="{% url 'user_photos-upload_ajax_v3' %}" method="post"
+      enctype="multipart/form-data">{% csrf_token %}
+      <div class="row">
+         <div class="columns">
+            <input type="file" name="image_file" />
+         </div>
+      </div>
+      <div class="row">
+         <div class="columns">
+            <div id="photo-status" class="hidden success callout">
+               Success! An image code was added to your post.
+            </div>
+         </div>
+      </div>
+      <div class="row">
+         <div class="columns text-right">
+            <input type="submit" id="photo-upload-submit" name="submit" value="Upload"
+               class="primary button" />
+            <button class="secondary button" data-close aria-label="Close modal" type="button">
+               Cancel
+            </button>
+         </div>
+      </div>
+      <div style="width: 80%;margin:auto;"><div id="photo-upload-progress"
+            style="margin:auto;width:100%;"></div></div>
+   </form>
+</div>
+
+<div class="small reveal" id="preview-modal" data-reveal>
+   <button class="close-button" data-close aria-label="Close modal" type="button">
+      <span aria-hidden="true">&times;</span>
+   </button>
+   <div class="row">
+      <div class="columns">
+         <p class="lead">Preview</p>
+      </div>
+   </div>
+   <div class="row">
+      <div class="columns">
+         <div id="editor-preview-panel" class="editor-preview-panel">
+         </div>
+      </div>
+   </div>
+   <div class="row">
+      <div class="columns text-right">
+         <button class="button" data-close aria-label="Close modal" type="button">
+            Close
+         </button>
+      </div>
+   </div>
+</div>
+
+<div class="small reveal modal-scrollable" id="help-modal" data-reveal>
+   <button class="close-button" data-close aria-label="Close modal" type="button">
+      <span aria-hidden="true">&times;</span>
+   </button>
+   <div class="row">
+      <div class="columns">
+         <h4>Help with markup</h4>
+         <p>SurfGuitar101.com uses a variation of the markup language called
+         <a href="http://daringfireball.net/projects/markdown/">Markdown</a>.
+         This is the same markup used by Reddit. Markdown is a light-weight and
+         easy-to-use syntax for styling text on the web. Here is a quick
+         overview of how to use Markdown on SG101.
+         </p>
+      </div>
+   </div>
+   <div class="row medium-unstack">
+      <div class="columns">
+         <h5>Emphasis</h5>
+         <div class="code-callout">*This text will be italic*
+_This will also be italic_
+
+**This text will be bold**
+__This will also be bold__
+
+_You can **combine** these_</div>
+      </div>
+      <div class="columns">
+         <h5>Lists</h5>
+         <div class="code-callout">* Bulleted list item 1
+* Bulleted list item 2
+
+1. Numbered list item 1
+2. Numbered list item 2
+   * You can have sub-lists
+   * if you indent</div>
+      </div>
+   </div>
+   <div class="row medium-unstack">
+      <div class="columns">
+         <h5>Links</h5>
+         <div class="code-callout">https://surfguitar101.com - automatic!
+[SurfGuitar101](https://surfguitar101.com)</div>
+      </div>
+   </div>
+   <div class="row medium-unstack">
+      <div class="columns">
+         <h5>Images</h5>
+         <div class="code-callout">![Image](https://example.com/a.jpg)</div>
+         <p>Note: for security reasons, please use the Hot-Link
+         (<i class="fi-photo"></i>) or Upload (<i class="fi-upload"></i>) buttons to add images
+         to your posts.
+         </p>
+      </div>
+   </div>
+   <div class="row medium-unstack">
+      <div class="columns">
+         <h5>Quoting</h5>
+         <div class="code-callout">Dick Dale said:
+
+&gt; The kids called me King of the Surf Guitar.
+
+This is not part of the quote because of the blank line.
+</div>
+         <div class="warning callout">
+            <i class="fi-info size-21"></i> Be sure to put a blank line above and below your quote.
+         </div>
+      </div>
+   </div>
+   <div class="row medium-unstack">
+      <div class="columns">
+         <h5>Tablature</h5>
+         <p>
+         To display tablature or code, insert at least 4 spaces in front
+         of each line. This is more easily accomplished by selecting all your
+         text and then clicking the <i class="fi-music"></i> button.
+         </p>
+         <div class="code-callout">Here is some tablature:
+
+    |-------------------------------------|
+    |-------------------------------------|
+    |o-----------------------------------o|
+    |o-----------------------------------o|
+    |--0-0---0-2---0---0-2-3-3-2-0---2-0--|
+    |------3-----3-----------------3------|</div>
+      </div>
+   </div>
+   <div class="row medium-unstack">
+      <div class="columns">
+         <h5>Strikethrough</h5>
+         <p>
+         Any words wrapped by 3 dashes (<code>---like this---</code>)
+         will appear crossed out.
+         </p>
+      </div>
+   </div>
+   <div class="row">
+      <div class="columns text-right">
+         <button class="button" data-close aria-label="Close modal" type="button">
+            Close
+         </button>
+      </div>
+   </div>
+</div>
--- a/sg101/templates/gcalendar/event.html	Mon Jun 27 18:40:59 2016 -0500
+++ b/sg101/templates/gcalendar/event.html	Mon Jun 27 20:11:17 2016 -0500
@@ -114,33 +114,7 @@
          </p>
       </div>
    </div>
-   {{ form.description.errors }}
-   <div class="row">
-      <div class="columns">
-         <label for="{{ form.description.id_for_label }}">{{ form.description.label }}</label>
-         <div class="tabs-panel is-active v3-editor" id="editor-panel">
-            <ul class="menu">
-               <li><a class="editor-bold hide-for-small-only" href="#"><i class="fi-bold size-21" title="Bold"></i></a></li>
-               <li><a class="editor-italic hide-for-small-only" href="#"><i class="fi-italic size-21" title="Italic"></i></a></li>
-               <li><a class="editor-strike hide-for-small-only" href="#"><i class="fi-strikethrough size-21" title="Strike"></i></a></li>
-               <li><a class="editor-link" href="#"><i class="fi-link size-21" title="Link"></i></a></li>
-               <li><a class="editor-quote hide-for-small-only" href="#"><i class="fi-quote size-21" title="Quote"></i></a></li>
-               <li><a class="editor-code hide-for-small-only" href="#"><i class="fi-music size-21" title="Format Tablature"></i></a></li>
-               <li><a class="editor-bullet hide-for-small-only" href="#"><i class="fi-list-bullet size-21" title="Bullet List"></i></a></li>
-               <li><a class="editor-number hide-for-small-only" href="#"><i class="fi-list-number size-21" title="Numbered List"></i></a></li>
-               <li><a class="editor-hot-link" data-open="hot-link-modal">
-                  <i class="fi-photo size-21" title="Hot-Link Image"></i></a></li>
-               <li><a class="editor-upload" data-open="upload-modal">
-                  <i class="fi-upload size-21" title="Upload Image"></i></a></li>
-               <li><a class="editor-preview" data-open="preview-modal">
-                  <i class="fi-eye size-21" title="Preview"></i></a></li>
-               <li><a class="editor-help" data-open="help-modal">
-                  <i class="fi-info size-21" title="Help with markup"></i></a></li>
-            </ul>
-            {{ form.description }}
-         </div>
-      </div>
-   </div>
+   {% post_box form.description %}
    {% if form.create_forum_thread %}
       {{ form.create_forum_thread.errors }}
       <div class="row">
@@ -157,230 +131,13 @@
       value="{% if is_new %}Add{% else %}Update{% endif %} Event"
       class="primary button" />
 </form>
-
-<div class="small reveal" id="hot-link-modal" data-reveal>
-   <button class="close-button" data-close aria-label="Close modal" type="button">
-      <span aria-hidden="true">&times;</span>
-   </button>
-   <div class="row">
-      <div class="columns">
-         <p class="lead">Hot-Link Image</p>
-      </div>
-   </div>
-   <div class="row">
-      <div class="columns">
-         <p>
-         To add an image already on the Internet to your post, copy &amp; paste the
-         image address to the box below and click "Hot-Link". An image code will be placed
-         in your post after the image is processed.
-         </p>
-      </div>
-   </div>
-   <form id="hot-link-form" action="{% url 'user_photos-hotlink' %}" method="post">{% csrf_token %}
-      <div class="row">
-         <div class="columns">
-            <label>Image Address
-               <input type="url" name="url" placeholder="http://" />
-            </label>
-         </div>
-      </div>
-      <div class="row">
-         <div class="columns">
-            <div id="hot-link-status" class="hidden success callout">
-               Success! An image code was added to your post.
-            </div>
-         </div>
-      </div>
-      <div class="row">
-         <div class="columns text-right">
-            <input type="submit" id="hot-link-form-submit" class="primary button"
-               name="submit" value="Hot-Link" />
-            <button class="secondary button" data-close aria-label="Close modal" type="button">
-               Cancel
-            </button>
-         </div>
-      </div>
-   </form>
-</div>
-
-<div class="reveal" id="upload-modal" data-reveal>
-   <button class="close-button" data-close aria-label="Close modal" type="button">
-      <span aria-hidden="true">&times;</span>
-   </button>
-   <div class="row">
-      <div class="columns">
-         <p class="lead">Upload Image</p>
-      </div>
-   </div>
-   <div class="row">
-      <div class="columns">
-         <p>
-         You can upload an image directly from your computer or device with this
-         form. After the image is uploaded it will be resized and an image code will be
-         placed your post.
-         </p>
-      </div>
-   </div>
-   <form id="photo-upload-form" action="{% url 'user_photos-upload_ajax_v3' %}" method="post"
-      enctype="multipart/form-data">{% csrf_token %}
-      <div class="row">
-         <div class="columns">
-            <input type="file" name="image_file" />
-         </div>
-      </div>
-      <div class="row">
-         <div class="columns">
-            <div id="photo-status" class="hidden success callout">
-               Success! An image code was added to your post.
-            </div>
-         </div>
-      </div>
-      <div class="row">
-         <div class="columns text-right">
-            <input type="submit" id="photo-upload-submit" name="submit" value="Upload"
-               class="primary button" />
-            <button class="secondary button" data-close aria-label="Close modal" type="button">
-               Cancel
-            </button>
-         </div>
-      </div>
-      <div style="width: 80%;margin:auto;"><div id="photo-upload-progress"
-            style="margin:auto;width:100%;"></div></div>
-   </form>
-</div>
-
-<div class="small reveal" id="preview-modal" data-reveal>
-   <button class="close-button" data-close aria-label="Close modal" type="button">
-      <span aria-hidden="true">&times;</span>
-   </button>
-   <div class="row">
-      <div class="columns">
-         <p class="lead">Preview</p>
-      </div>
-   </div>
-   <div class="row">
-      <div class="columns">
-         <div id="editor-preview-panel" class="editor-preview-panel">
-         </div>
-      </div>
-   </div>
-   <div class="row">
-      <div class="columns text-right">
-         <button class="button" data-close aria-label="Close modal" type="button">
-            Close
-         </button>
-      </div>
-   </div>
-</div>
-
-<div class="small reveal modal-scrollable" id="help-modal" data-reveal>
-   <button class="close-button" data-close aria-label="Close modal" type="button">
-      <span aria-hidden="true">&times;</span>
-   </button>
-   <div class="row">
-      <div class="columns">
-         <h4>Help with markup</h4>
-         <p>SurfGuitar101.com uses a variation of the markup language called
-         <a href="http://daringfireball.net/projects/markdown/">Markdown</a>.
-         This is the same markup used by Reddit. Markdown is a light-weight and
-         easy-to-use syntax for styling text on the web. Here is a quick
-         overview of how to use Markdown on SG101.
-         </p>
-      </div>
-   </div>
-   <div class="row medium-unstack">
-      <div class="columns">
-         <h5>Emphasis</h5>
-         <div class="code-callout">*This text will be italic*
-_This will also be italic_
-
-**This text will be bold**
-__This will also be bold__
-
-_You can **combine** these_</div>
-      </div>
-      <div class="columns">
-         <h5>Lists</h5>
-         <div class="code-callout">* Bulleted list item 1
-* Bulleted list item 2
-
-1. Numbered list item 1
-2. Numbered list item 2
-   * You can have sub-lists
-   * if you indent</div>
-      </div>
-   </div>
-   <div class="row medium-unstack">
-      <div class="columns">
-         <h5>Links</h5>
-         <div class="code-callout">https://surfguitar101.com - automatic!
-[SurfGuitar101](https://surfguitar101.com)</div>
-      </div>
-   </div>
-   <div class="row medium-unstack">
-      <div class="columns">
-         <h5>Images</h5>
-         <div class="code-callout">![Image](https://example.com/a.jpg)</div>
-         <p>Note: for security reasons, please use the Hot-Link
-         (<i class="fi-photo"></i>) or Upload (<i class="fi-upload"></i>) buttons to add images
-         to your posts.
-         </p>
-      </div>
-   </div>
-   <div class="row medium-unstack">
-      <div class="columns">
-         <h5>Quoting</h5>
-         <div class="code-callout">Dick Dale said:
-
-&gt; The kids called me King of the Surf Guitar.
-
-This is not part of the quote because of the blank line.
-</div>
-         <div class="warning callout">
-            <i class="fi-info size-21"></i> Be sure to put a blank line above and below your quote.
-         </div>
-      </div>
-   </div>
-   <div class="row medium-unstack">
-      <div class="columns">
-         <h5>Tablature</h5>
-         <p>
-         To display tablature or code, insert at least 4 spaces in front
-         of each line. This is more easily accomplished by selecting all your
-         text and then clicking the <i class="fi-music"></i> button.
-         </p>
-         <div class="code-callout">Here is some tablature:
-
-    |-------------------------------------|
-    |-------------------------------------|
-    |o-----------------------------------o|
-    |o-----------------------------------o|
-    |--0-0---0-2---0---0-2-3-3-2-0---2-0--|
-    |------3-----3-----------------3------|</div>
-      </div>
-   </div>
-   <div class="row medium-unstack">
-      <div class="columns">
-         <h5>Strikethrough</h5>
-         <p>
-         Any words wrapped by 3 dashes (<code>---like this---</code>)
-         will appear crossed out.
-         </p>
-      </div>
-   </div>
-   <div class="row">
-      <div class="columns text-right">
-         <button class="button" data-close aria-label="Close modal" type="button">
-            Close
-         </button>
-      </div>
-   </div>
-</div>
+{% include 'core/v3/post_box_modals.html' %}
 {% endblock %}
 
 {% block custom_js %}
 {% js_tags 'jquery-ui' %}
 <script src="{% static "js/timezone.js" %}"></script>
 <script src="{% static "js/gcalendar.js" %}"></script>
+<script src="{% static "js/v3/post_box.js" %}"></script>
 <script src="{% static "js/jquery.form.min.js" %}"></script>
 {% endblock %}