[geary/bug/728002-webkit2: 101/140] Implement ComposerWebView::insert_link and ::delete_link.



commit e4f50e1c3664f0edfe0f61c5e4592d70bded56a5
Author: Michael James Gratton <mike vee net>
Date:   Thu Jan 19 02:26:42 2017 +1100

    Implement ComposerWebView::insert_link and ::delete_link.
    
    * src/client/composer/composer-web-view.vala (ComposerWebView): Call
      new ComposerPageState methods for ::insert_link and ::delete_link.
    
    * ui/composer-web-view.js (ComposerPageState): Add new ::insertLink
      and ::deleteLink methods, handle linking/unlinking both the
      current selection and the link under the text cursor, if nothing
      is selected.

 src/client/composer/composer-web-view.vala |    4 ++
 ui/composer-web-view.js                    |   67 ++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+), 0 deletions(-)
---
diff --git a/src/client/composer/composer-web-view.vala b/src/client/composer/composer-web-view.vala
index 5546b35..868b883 100644
--- a/src/client/composer/composer-web-view.vala
+++ b/src/client/composer/composer-web-view.vala
@@ -317,12 +317,16 @@ public class ComposerWebView : ClientWebView {
      * will be inserted wrapping the selection.
      */
     public void insert_link(string href) {
+        this.run_javascript.begin(
+            "geary.insertLink(\"%s\");".printf(href), null
+        );
     }
 
     /**
      * Removes any A element at the current text cursor location.
      */
     public void delete_link() {
+        this.run_javascript.begin("geary.deleteLink();", null);
     }
 
     /**
diff --git a/ui/composer-web-view.js b/ui/composer-web-view.js
index 32f2dca..9665631 100644
--- a/ui/composer-web-view.js
+++ b/ui/composer-web-view.js
@@ -114,6 +114,40 @@ ComposerPageState.prototype = {
         document.execCommand("redo", false, null);
         this.checkCommandStack();
     },
+    insertLink: function(href) {
+        if (!window.getSelection().isCollapsed) {
+            // There is currently a selection, so assume the user
+            // knows what they are doing and just linkify it.
+            document.execCommand("createLink", false, href);
+        } else {
+            let selected = SelectionUtil.getCursorElement();
+            if (selected != null && selected.tagName == "A") {
+                // The current cursor element is an A, so select it
+                // since createLink requires a range
+                let selection = SelectionUtil.save();
+                SelectionUtil.selectNode(selected);
+                document.execCommand("createLink", false, href);
+                SelectionUtil.restore(selection);
+            }
+        }
+    },
+    deleteLink: function() {
+        if (!window.getSelection().isCollapsed) {
+            // There is currently a selection, so assume the user
+            // knows what they are doing and just unlink it.
+            document.execCommand("unlink", false, null);
+        } else {
+            let selected = SelectionUtil.getCursorElement();
+            if (selected != null && selected.tagName == "A") {
+                // The current cursor element is an A, so select it
+                // since unlink requires a range
+                let selection = SelectionUtil.save();
+                SelectionUtil.selectNode(selected);
+                document.execCommand("unlink", false, null);
+                SelectionUtil.restore(selection);
+            }
+        }
+    },
     tabOut: function() {
         document.execCommand(
             "inserthtml", false, "<span style='white-space: pre-wrap'>\t</span>"
@@ -365,6 +399,39 @@ let SelectionUtil = {
             node = node.parentNode;
         }
         return node;
+    },
+    /**
+     * Modifies the selection so that it contains the given target node.
+     */
+    selectNode: function(target) {
+        let newRange = new Range();
+        newRange.selectNode(target);
+
+        let selection = window.getSelection();
+        selection.removeAllRanges();
+        selection.addRange(newRange);
+    },
+    /**
+     * Saves the current selection so it can be restored with `restore`.
+     */
+    save: function() {
+        let selection = window.getSelection();
+        var ranges = [];
+        let len = selection.rangeCount;
+        for (let i = 0; i < len; ++i) {
+            ranges.push(selection.getRangeAt(i));
+        }
+        return ranges;
+    },
+    /**
+     * Restores the selection saved with `save`.
+     */
+    restore: function(saved) {
+        let selection = window.getSelection();
+        selection.removeAllRanges();
+        for (let i = 0; i < saved.length; i++) {
+            selection.addRange(saved[i]);
+        }
     }
 };
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]