add link/unlink to quick edit
authorFrédéric Péters <fpeters@0d.be>
Thu, 4 Jun 2020 14:59:15 +0000 (16:59 +0200)
committerFrédéric Péters <fpeters@0d.be>
Thu, 4 Jun 2020 14:59:15 +0000 (16:59 +0200)
chloro/phyll/static/css/style.scss
chloro/phyll/static/js/chloro.js

index 50b7bf0..e3fb0af 100644 (file)
@@ -185,6 +185,18 @@ footer {
 
 #style-popup {
        background: white;
+       input {
+               display: none;
+               padding: 3px;
+               border: 1px inset #ccc;
+               background: white;
+               width: 0px;
+               transition: width ease 2s;
+               &.shown {
+                       display: inline-block;
+                       width: 400px;
+               }
+       }
        button {
                padding: 0;
                height: 2em;
@@ -196,5 +208,9 @@ footer {
                &:hover {
                        background: #ccc;
                }
+               &[data-action=createLink] {
+                       color: blue;
+                       text-decoration: underline;
+               }
        }
 }
index 78930c3..c997bc7 100644 (file)
@@ -37,8 +37,47 @@ $(function() {
       action = 'insertHTML';
       param = $('<code></code>', {text: window.getSelection().toString()})[0].outerHTML;
     }
+    if (action == 'createLink') {
+      var sel = window.getSelection();
+      var $input = $('input[name=link-target]');
+      $input[0]._range = sel.getRangeAt(0);
+      if (sel.anchorNode instanceof Element) {
+        var elem = sel.anchorNode.childNodes[sel.anchorOffset];
+        if (elem.tagName == 'A') {
+          $input.val(elem.href);
+        }
+      }
+      $input.addClass('shown');
+      $input.focus();
+      return;
+    }
     document.execCommand(action, false, param);
   }
+  function validate_link(ev) {
+    var charCode = typeof ev.which == "number" ? ev.which : ev.keyCode;
+    if (ev.key == "Enter") {
+      var $input = $(this);
+      var range = this._range;
+      var url = $input.val();
+      $input.removeClass('shown');
+      var sel = window.getSelection();
+      sel.addRange(this._range);
+      if (url) {
+        document.execCommand('createLink', false, url);
+      } else {
+        document.execCommand('unlink', false, null);
+      }
+      sel.empty();
+      $input.val('');
+    }
+  }
+  function focusout_link(ev) {
+    var $input = $(this);
+    $input.removeClass('shown');
+    var range = this._range;
+    var sel = window.getSelection();
+    sel.addRange(this._range);
+  }
 
   function show_style_popup(sel) {
     if (style_popup === null) {
@@ -47,18 +86,24 @@ $(function() {
                       '<button data-action="bold"><b>b</b></button>' +
                       '<button data-action="code">#</button>' +
                       '<button data-action="removeFormat">×</button>' +
+                      '<button data-action="createLink">a</button>' +
+                      '<input name="link-target"/>' +
                       '</div>');
       style_popup.hide();
-      style_popup.insertAfter($('div[contenteditable]'));
+      style_popup.insertAfter($('.actions'));
       style_popup.find('button').on('click', update_style);
+      style_popup.find('[name=link-target]').on('keypress', validate_link).on('focusout', focusout_link);
     }
     style_popup.css('position', 'absolute');
     var pos = sel.getRangeAt(0).getClientRects()[0];
-    style_popup.css('top', pos.top + window.scrollY - $('main').offset().top - 33);
-    style_popup.css('left', pos.left + window.scrollX - $('main').offset().left);
+    style_popup.css('top', pos.top + window.scrollY - 33);
+    style_popup.css('left', pos.left + window.scrollX);
     style_popup.show();
   };
   $(document).on('selectionchange', function(event) {
+    if ($('input[name=link-target].shown').length) {
+      return;
+    }
     var sel = window.getSelection();
     if ($(sel.anchorNode).parents('div[contenteditable]').length && sel.toString()) {
       show_style_popup(sel);