Remove link in a contenteditable element

Viewed 51

I'm currently working on a simple project and I'm using contenteditable so that users can format the text. I managed to create for users to add a hyperlink in the text selecting part of text and clicking on the "Create Link" Button which will allow them to add the link.

Problem : I want to create a way to remove the link by clicking on the "Remove Link" Button also a way to modify the link if added. How can I archive this?

A perfect example is Gmail when you Compose a new email you are able to add link to remove it also to edit it.

Here is my current Project for reference: Stackblitz

My index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Link App</title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <link rel="stylesheet" href="styles.css" />
    <script type="text/javascript" src="script.js"></script>
  </head>
  <body>
    <button onclick="createLink()">Create Link</button>
    <button onclick="removeLink()">Remove Link</button>
    <hr />
    <div contenteditable="true" class="text-box">
      <h4>Select some of this content and click the link button</h4>
      Quisque velit nisi, pretium ut lacinia in, elementum id enim. Proin eget
      tortor risus. Curabitur aliquet quam id dui posuere blandit. Proin eget
      tortor risus. Vestibulum ac diam sit amet quam vehicula elementum sed sit
      amet dui. Vivamus magna justo, lacinia eget consectetur sed, convallis at
      tellus. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Proin
      eget tortor risus. Curabitur non nulla sit amet nisl tempus convallis quis
      ac lectus. Vivamus magna justo, lacinia eget consectetur sed, convallis at
      tellus.
    </div>
    <hr />
  </body>
</html>

My script.js

function saveSelection() {
  if (window.getSelection) {
    sel = window.getSelection();
    if (sel.getRangeAt && sel.rangeCount) {
      var ranges = [];
      for (var i = 0, len = sel.rangeCount; i < len; ++i) {
        ranges.push(sel.getRangeAt(i));
      }
      return ranges;
    }
  } else if (document.selection && document.selection.createRange) {
    return document.selection.createRange();
  }
  return null;
}

function restoreSelection(savedSel) {
  if (savedSel) {
    if (window.getSelection) {
      sel = window.getSelection();
      sel.removeAllRanges();
      for (var i = 0, len = savedSel.length; i < len; ++i) {
        sel.addRange(savedSel[i]);
      }
    } else if (document.selection && savedSel.select) {
      savedSel.select();
    }
  }
}

function formatDoc(sCmd, sValue) {
  document.execCommand(sCmd, false, sValue);
}

function createLink() {
  var savedSel = saveSelection();
  var sLnk = prompt('Write the URL here', 'http://');
  if (sLnk && sLnk != '' && sLnk != 'http://') {
    formatDoc('createlink', sLnk);
  }
  restoreSelection(savedSel);
}
1 Answers

Here is a basic version of the removeLink() function you would need.

If you check the window.getSelection() return value, you can see a number of properties available, and so for this I chose the ["baseNode"]["parentElement"] (though it should be noted that anchorNode also seems to contain the same properties and vales as baseNode so perhaps someone else can explain the difference).

function saveSelection() {
  if (window.getSelection) {
    sel = window.getSelection();
    if (sel.getRangeAt && sel.rangeCount) {
      var ranges = [];
      for (var i = 0, len = sel.rangeCount; i < len; ++i) {
        ranges.push(sel.getRangeAt(i));
      }
      return ranges;
    }
  } else if (document.selection && document.selection.createRange) {
    return document.selection.createRange();
  }
  return null;
}

function restoreSelection(savedSel) {
  if (savedSel) {
    if (window.getSelection) {
      sel = window.getSelection();
      sel.removeAllRanges();
      for (var i = 0, len = savedSel.length; i < len; ++i) {
        sel.addRange(savedSel[i]);
      }
    } else if (document.selection && savedSel.select) {
      savedSel.select();
    }
  }
}

function formatDoc(sCmd, sValue) {
  document.execCommand(sCmd, false, sValue);
}

function createLink() {
  var savedSel = saveSelection();
  var sLnk = prompt('Write the URL here', 'http://');
  if (sLnk && sLnk != '' && sLnk != 'http://') {
    formatDoc('createlink', sLnk);
  }
  restoreSelection(savedSel);
}

function removeLink() {
  let p = window.getSelection()["baseNode"]["parentElement"];
  if(p.tagName == "A") {
    p.replaceWith(p.textContent);
  } else {
    console.log("Not a link");
  }
}

function editLink() {
  let p = window.getSelection()["baseNode"]["parentElement"];
  if(p.tagName == "A") {
    let url = prompt("Write the URL here", p.href);
    p.href = url;
  } else {
    console.log("Not a link");
  }
}
* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: system-ui, sans-serif;
  color: black;
  background-color: white;
}

.intLink {
  cursor: pointer;
}

.text-box:focus {
  outline: 0;
}
    <button onclick="createLink()">Create Link</button>
    <button onclick="removeLink()">Remove Link</button>
    <button onclick="editLink()">Edit Link</button>
    <hr />
    <div contenteditable="true" class="text-box">
      <h4>Select some of this content and click the link button</h4>
      Quisque velit nisi, pretium ut lacinia in, elementum id enim. Proin eget
      tortor risus. Curabitur aliquet quam id dui posuere blandit. Proin eget
      tortor risus. Vestibulum ac diam sit amet quam vehicula elementum sed sit
      amet dui. Vivamus magna justo, lacinia eget consectetur sed, convallis at
      tellus. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Proin
      eget tortor risus. Curabitur non nulla sit amet nisl tempus convallis quis
      ac lectus. Vivamus magna justo, lacinia eget consectetur sed, convallis at
      tellus.
    </div>
    <hr />

EDIT: Instead of entirely removing the newly added <a> tag via .remove(), I am using .replaceWith(), which allows me to swap the element out for only its text value.

I also added in an editLink() function which pulls the href attribute of the link and allows you to update that value.

Related