Browse Source

Ported Callisto editor's JS to Misago.

Ralfp 12 years ago
parent
commit
c4be939f02

+ 4 - 2
static/sora/css/sora.css

@@ -1000,7 +1000,8 @@ td.lead-cell{color:#555555;font-weight:bold;}
 .posts-list .well-post .post-extra .label-purple{background-color:#7a43b6;}
 .posts-list .well-post .post-extra .label-purple{background-color:#7a43b6;}
 .posts-list .well-post .post-nav{clear:both;margin-left:286px;overflow:auto;padding:8px 16px;padding-bottom:0px;margin-bottom:-8px;}.posts-list .well-post .post-nav .changelog{float:left;opacity:0.5;filter:alpha(opacity=50);color:#999999;}
 .posts-list .well-post .post-nav{clear:both;margin-left:286px;overflow:auto;padding:8px 16px;padding-bottom:0px;margin-bottom:-8px;}.posts-list .well-post .post-nav .changelog{float:left;opacity:0.5;filter:alpha(opacity=50);color:#999999;}
 .posts-list .well-post .post-nav ul{margin:0px;padding:0px;}
 .posts-list .well-post .post-nav ul{margin:0px;padding:0px;}
-.posts-list .well-post .post-nav .nav-pills li{opacity:0.1;filter:alpha(opacity=10);}.posts-list .well-post .post-nav .nav-pills li a{padding:6px 7px;}
+.posts-list .well-post .post-nav .nav-pills li{opacity:0.1;filter:alpha(opacity=10);}.posts-list .well-post .post-nav .nav-pills li form{margin:0px;}
+.posts-list .well-post .post-nav .nav-pills li a{padding:6px 7px;}
 .posts-list .well-post .post-nav .nav-pills li button{padding:3px 7px;}
 .posts-list .well-post .post-nav .nav-pills li button{padding:3px 7px;}
 .posts-list .well-post .post-nav .nav-pills li a,.posts-list .well-post .post-nav .nav-pills li button{background-color:#c9c9c9;border:none;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;margin:0px;color:#ffffff;font-weight:bold;}.posts-list .well-post .post-nav .nav-pills li a:hover,.posts-list .well-post .post-nav .nav-pills li button:hover{background-color:#1ab2ff;}.posts-list .well-post .post-nav .nav-pills li a:hover.danger,.posts-list .well-post .post-nav .nav-pills li button:hover.danger{background-color:#d83a2e;}
 .posts-list .well-post .post-nav .nav-pills li a,.posts-list .well-post .post-nav .nav-pills li button{background-color:#c9c9c9;border:none;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;margin:0px;color:#ffffff;font-weight:bold;}.posts-list .well-post .post-nav .nav-pills li a:hover,.posts-list .well-post .post-nav .nav-pills li button:hover{background-color:#1ab2ff;}.posts-list .well-post .post-nav .nav-pills li a:hover.danger,.posts-list .well-post .post-nav .nav-pills li button:hover.danger{background-color:#d83a2e;}
 .posts-list .well-post .post-nav .nav-pills li i{background-image:url("../img/glyphicons-halflings-white.png");}
 .posts-list .well-post .post-nav .nav-pills li i{background-image:url("../img/glyphicons-halflings-white.png");}
@@ -1020,7 +1021,8 @@ td.lead-cell{color:#555555;font-weight:bold;}
 .editor .editor-error .help-block:last-child{margin-bottom:0px;}
 .editor .editor-error .help-block:last-child{margin-bottom:0px;}
 .editor .editor-input{padding:8px;}.editor .editor-input div{margin-right:14px;}
 .editor .editor-input{padding:8px;}.editor .editor-input div{margin-right:14px;}
 .editor .editor-input textarea{margin:0px;width:100%;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;}
 .editor .editor-input textarea{margin:0px;width:100%;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;}
-.editor .editor-actions{border-top:2px solid #c9c9c9;overflow:auto;padding:8px;}
+.editor .editor-actions{border-top:2px solid #c9c9c9;overflow:auto;padding:8px;}.editor .editor-actions .editor-tools{display:none;overflow:auto;margin:-6px;padding:6px;}.editor .editor-actions .editor-tools li{float:left;list-style:none;margin-right:6px;}.editor .editor-actions .editor-tools li.divider{margin-left:6px;}
+.editor .editor-actions .editor-tools li a{background-color:#eeeeee;border-color:#ffffff;-webkit-box-shadow:0px 0px 3px #999999;-moz-box-shadow:0px 0px 3px #999999;box-shadow:0px 0px 3px #999999;padding:4px 7px;}.editor .editor-actions .editor-tools li a:hover{background-color:#ffffff;}
 .markdown{margin-bottom:-12px;}.markdown h1{font-size:160%;}
 .markdown{margin-bottom:-12px;}.markdown h1{font-size:160%;}
 .markdown h2{font-size:120%;}
 .markdown h2{font-size:120%;}
 .markdown blockquote{background-color:#fcfcfc;border:1px solid #cccccc;border-bottom-width:2px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;display:inline-block;padding:14px 16px;width:90%;margin-left:auto;margin-right:auto;}.markdown blockquote h3{margin:0px;margin-top:-10px;padding:0px;color:#555555;font-size:100%;}
 .markdown blockquote{background-color:#fcfcfc;border:1px solid #cccccc;border-bottom-width:2px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;display:inline-block;padding:14px 16px;width:90%;margin-left:auto;margin-right:auto;}.markdown blockquote h3{margin:0px;margin-top:-10px;padding:0px;color:#555555;font-size:100%;}

+ 28 - 0
static/sora/css/sora/editor.less

@@ -36,5 +36,33 @@
     border-top: 2px solid darken(@bodyBackground, 20%);
     border-top: 2px solid darken(@bodyBackground, 20%);
     overflow: auto;
     overflow: auto;
     padding: 8px;
     padding: 8px;
+    
+    .editor-tools {
+      display: none;
+      overflow: auto;
+      margin: -6px;
+      padding: 6px;
+      
+      li {
+        float: left;
+        list-style: none;
+        margin-right: 6px;
+        
+        &.divider {
+          margin-left: 6px;
+        }
+        
+        a {
+          background-color: @grayLighter;
+          border-color: @white;
+          .box-shadow(0px 0px 3px @grayLight);
+          padding: 4px 7px;
+          
+          &:hover {
+            background-color: @white;
+          }
+        }
+      }
+    }
   }
   }
 }
 }

+ 4 - 0
static/sora/css/sora/threads.less

@@ -240,6 +240,10 @@
       .nav-pills li {
       .nav-pills li {
         .opacity(10);
         .opacity(10);
         
         
+        form {
+          margin: 0px;
+        }
+        
         a {
         a {
           padding: 6px 7px;
           padding: 6px 7px;
         }
         }

+ 119 - 0
static/sora/js/editor.js

@@ -0,0 +1,119 @@
+// Basic editor functions
+function storeCaret(ftext) {    
+    if (ftext.createTextRange) {
+        ftext.caretPos = document.selection.createRange().duplicate();
+    }
+}
+
+function SelectionRange(start, end) {
+    this.start = start;
+    this.end = end;
+}
+
+function getSelection(textId) {
+    ctrl = document.getElementById(textId);
+    if (document.selection) {
+        ctrl.focus();
+        var range = document.selection.createRange();
+        var length = range.text.length;
+        range.moveStart('character', -ctrl.value.length);
+        return new SelectionRange(range.text.length - length, range.text.length);
+    } else if (ctrl.selectionStart || ctrl.selectionStart == '0') {
+        return new SelectionRange(ctrl.selectionStart, ctrl.selectionEnd);
+    }
+}
+
+function setSelection(textId, SelectionRange) {
+    ctrl = document.getElementById(textId);
+    if (ctrl.setSelectionRange) {
+        ctrl.focus();
+        ctrl.setSelectionRange(SelectionRange.start, SelectionRange.end);
+    } else if (ctrl.createTextRange) {
+        var range = ctrl.createTextRange();
+        range.collapse(true);
+        range.moveStart('character', SelectionRange.start);
+        range.moveEnd('character', SelectionRange.end);
+        range.select();
+    }
+}
+
+function _makeWrap(textId, myRange, wrap_start, wrap_end) {
+    var ctrl = document.getElementById(textId);
+    var text = ctrl.value;
+    var startText = text.substring(0, myRange.start) + wrap_start;
+    var middleText = text.substring(myRange.start, myRange.end);
+    var endText = wrap_end + text.substring(myRange.end);
+    ctrl.value = startText + middleText + endText;
+    setSelection(textId, new SelectionRange(startText.length, startText.length + middleText.length));
+}
+
+function makeWrap(textId, wrap_start, wrap_end) {
+    _makeWrap(textId, getSelection(textId), wrap_start, wrap_end);
+}
+
+function _makeReplace(textId, myRange, replacement) {
+    var ctrl = document.getElementById(textId);
+    var text = ctrl.value;
+    var startText = text.substring(0, myRange.start);
+    var middleText = text.substring(myRange.start, myRange.end);
+    var endText = text.substring(myRange.end);
+    ctrl.value = text.substring(0, myRange.start) + replacement + text.substring(myRange.end);
+    setSelection(textId, new SelectionRange(startText.length + middleText.length, startText.length + middleText.length));
+}
+
+function makeReplace(textId, replacement) {
+    _makeReplace(textId, getSelection(textId), replacement);
+}
+
+// Nice editor functionality
+$(function() {
+  $('.editor-tools').fadeIn(600);
+  
+  function get_textarea(obj) {
+      return $(obj).parent().parent().parent().parent().find('textarea');
+  }
+  
+  $('.editor-bold').click(function() {
+      ta = get_textarea(this).attr('id');
+      makeWrap(ta, '**', '**');
+      return false;
+  });
+  
+  $('.editor-emphasis').click(function() {
+      ta = get_textarea(this).attr('id');
+      makeWrap(ta, '_', '_');
+      return false;
+  });
+  
+  $('.editor-link').click(function() {
+      ta = get_textarea(this).attr('id');
+      var link_url = $.trim(prompt(ed_lang_enter_link_url));
+      if (link_url.length > 0) {
+          var link_label = $.trim(prompt(ed_lang_enter_link_label));
+          if (link_label.length > 0) {
+              makeReplace(ta, '[' + link_label + '](' + link_url + ')');
+          } else {
+              makeReplace(ta, '<' + link_url + '>');
+          }
+      }
+      return false;
+  });
+  
+  $('.editor-image').click(function() {
+      ta = get_textarea(this).attr('id');
+      var image_url = $.trim(prompt(ed_lang_enter_image_url));
+      if (image_url.length > 0) {
+          var image_label = $.trim(prompt(ed_lang_enter_image_label));
+          if (image_label.length > 0) {
+              makeReplace(ta, '![' + image_label + '](' + image_url + ')');
+          }
+      }
+      return false;
+  });
+  
+  $('.editor-hr').click(function() {
+      ta = get_textarea(this).attr('id');
+      makeReplace(ta, '- - - - -');
+      return false;
+  });
+});

+ 18 - 2
templates/sora/editor.html

@@ -1,4 +1,4 @@
-{% macro editor(field, submit_button, placeholder=None, rows=4) %}
+{% macro editor(field, submit_button, placeholder=None, rows=4, hide_links=False, hide_images=False, hide_hr=False) %}
 <div class="editor">
 <div class="editor">
   {% if field.errors %}
   {% if field.errors %}
   <div class="editor-error">
   <div class="editor-error">
@@ -13,10 +13,26 @@
     </div>
     </div>
   </div>
   </div>
   <div class="editor-actions">
   <div class="editor-actions">
+    <ul class="editor-tools unstyled pull-left">
+      <li><a href="#" class="tooltip-top btn editor-bold" title="{% trans %}Bold{% endtrans %}"><i class="icon-bold"></i></a></li>
+      <li><a href="#" class="tooltip-top btn editor-emphasis" title="{% trans %}Emphasis{% endtrans %}"><i class="icon-italic"></i></a></li>
+      {% if not hide_links %}<li class="divider"><a href="#" class="tooltip-top btn editor-link" title="{% trans %}Insert Link{% endtrans %}"><i class="icon-share-alt"></i></a></li>{% endif %}
+      {% if not hide_images %}<li{% if hide_links %} class="divider"{% endif %}><a href="#" class="tooltip-top btn editor-image" title="{% trans %}Insert Image{% endtrans %}"><i class="icon-picture"></i></a></li>{% endif %}
+      {% if not hide_hr %}<li class="divider"><a href="#" class="tooltip-top btn editor-hr" title="{% trans %}Insert Horizontal Line{% endtrans %}"><i class="icon-minus"></i></a></li>{% endif %}
+    </ul>
     <button name="save" type="submit" class="btn btn-primary pull-right">{{ submit_button }}</button>
     <button name="save" type="submit" class="btn btn-primary pull-right">{{ submit_button }}</button>
   </div>
   </div>
 </div>
 </div>
 {% endmacro %}
 {% endmacro %}
 
 
-{% macro editor_js() %}
+{% macro js() %}
+  <script type="text/javascript">
+    $(function () {
+        ed_lang_enter_link_url = "{% trans %}Enter link address{% endtrans %}";
+        ed_lang_enter_link_label = "{% trans %}Enter link label (optional){% endtrans %}";
+        ed_lang_enter_image_url = "{% trans %}Enter image address{% endtrans %}";
+        ed_lang_enter_image_label = "{% trans %}Enter image label{% endtrans %}";
+    });
+  </script>
+  <script src="{{ STATIC_URL }}sora/js/editor.js"></script>
 {% endmacro %}
 {% endmacro %}

+ 5 - 0
templates/sora/threads/posting.html

@@ -105,3 +105,8 @@
 {% trans %}Edit Reply{% endtrans %}
 {% trans %}Edit Reply{% endtrans %}
 {%- endif %}
 {%- endif %}
 {%- endmacro %}
 {%- endmacro %}
+
+{% block javascripts %}
+{{ super() }}
+  {{ editor.js() }}
+{% endblock %}

+ 3 - 0
templates/sora/threads/thread.html

@@ -315,4 +315,7 @@
       });
       });
     });
     });
   </script>{% endif %}
   </script>{% endif %}
+  {% if user.is_authenticated() and acl.threads.can_reply(forum, thread) %}
+  {{ editor.js() }}
+  {% endif %}
 {%- endblock %}
 {%- endblock %}

+ 9 - 1
templates/sora/usercp/signature.html

@@ -19,6 +19,14 @@
 {% endif %}
 {% endif %}
 <form action="{% url 'usercp_signature' %}" method="post">
 <form action="{% url 'usercp_signature' %}" method="post">
   <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
   <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
-  {{ editor.editor(form.fields.signature, _('Save Signature')) }}
+  {{ editor.editor(form.fields.signature, _('Save Signature'),
+        hide_links=(not acl.usercp.allow_signature_links()),
+        hide_images=(not acl.usercp.allow_signature_images()),
+        hide_hr=True) }}
 </form>
 </form>
+{% endblock %}
+
+{% block javascripts %}
+{{ super() }}
+  {{ editor.js() }}
 {% endblock %}
 {% endblock %}