简体   繁体   中英

Prevent editable div's behavior when typing certain characters

I have the following code taken from Pranav C Balan 's answer to my previous question :

 var div = document.getElementById('div'); div.addEventListener('input', function() { var pos = getCaretCharacterOffsetWithin(this); // get all red subtring and wrap it with span this.innerHTML = this.innerText.replace(/red/g, '<span style="color:red">$&</span>') setCaretPosition(this, pos); }) // following code is copied from following question // https://stackoverflow.com/questions/26139475/restore-cursor-position-after-changing-contenteditable function getCaretCharacterOffsetWithin(element) { var caretOffset = 0; var doc = element.ownerDocument || element.document; var win = doc.defaultView || doc.parentWindow; var sel; if (typeof win.getSelection != "undefined") { sel = win.getSelection(); if (sel.rangeCount > 0) { var range = win.getSelection().getRangeAt(0); var preCaretRange = range.cloneRange(); preCaretRange.selectNodeContents(element); preCaretRange.setEnd(range.endContainer, range.endOffset); caretOffset = preCaretRange.toString().length; } } else if ((sel = doc.selection) && sel.type != "Control") { var textRange = sel.createRange(); var preCaretTextRange = doc.body.createTextRange(); preCaretTextRange.moveToElementText(element); preCaretTextRange.setEndPoint("EndToEnd", textRange); caretOffset = preCaretTextRange.text.length; } return caretOffset; } function setCaretPosition(element, offset) { var range = document.createRange(); var sel = window.getSelection(); //select appropriate node var currentNode = null; var previousNode = null; for (var i = 0; i < element.childNodes.length; i++) { //save previous node previousNode = currentNode; //get current node currentNode = element.childNodes[i]; //if we get span or something else then we should get child node while (currentNode.childNodes.length > 0) { currentNode = currentNode.childNodes[0]; } //calc offset in current node if (previousNode != null) { offset -= previousNode.length; } //check whether current node has enough length if (offset <= currentNode.length) { break; } } //move caret to specified offset if (currentNode != null) { range.setStart(currentNode, offset); range.collapse(true); sel.removeAllRanges(); sel.addRange(range); } } 
 <span contenteditable="true" id="div" style="width:100%;display:block">sss</span> 

It has a editable <div> where the user can input and it automatically colors the word red as red just like some code editors color key words like HTML tags, strings, functions, etc.
Type "red" and you will understand what I mean.

The issue I'm having is, when I type "<", it deletes all the characters in front of it unless it finds a ">" where it will stop. Another error happens if you type "&#1" (or any other number instead of 1 really).

Any ideia on how to prevent this behavior?

You're running into this problem because you're expecting the user to be able to input HTML-like entities such as <xyz... or &#123; but don't want to parse that input as HTML , but at the same time, you're yourself putting html elements in the same div and you want that to be parsed as HTML . So there are two ways you can go about this:

  1. Keep the input and presentation separate. So user can input anything, which you'll sanitize and display in an output box.

  2. Or... change the addEventListener function:

     div.addEventListener('input', function() { var pos = getCaretCharacterOffsetWithin(this); var userString = sanitizeHTML(this.innerText); // get all red subtring and wrap it with span this.innerHTML = userString.replace(/red/g, '<span style="color:red">$&</span>') setCaretPosition(this, pos); }) 

This would work in most scenarios, but it'd break (badly) if you're expecting user to input HTML too, for example <span class="red" style="color: red">red</span> would become horribly mutilated. Other than that, you're good to go. Get sanitizeHTML from here: https://github.com/punkave/sanitize-html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM