简体   繁体   English

JavaScript语法高亮

[英]Syntax highlight with JavaScript

I'm trying to make a simple syntax highlighter with JavaScript, but I always end up having the same problem. 我试图用JavaScript制作一个简单的语法荧光笔,但最终总是遇到相同的问题。 The program works as follows: as the user types enter (without the shift key) the program will replace the keyword var with another one with red color (this is still so basic). 该程序的工作方式如下:当用户输入时(不带Shift键),程序将用另一个红色的关键字替换var(这仍然很基本)。 The problem is that whenever you press enter, the text gets highlighted but the cursor returns to the first word of the first line. 问题在于,每当您按Enter键时,文本都会突出显示,但是光标会返回到第一行的第一个单词。 How do you think I can prevent this from happening? 您认为我如何防止这种情况发生?

<div class="container">
    <pre class="text"><code contenteditable="true" id="format">
    </code></pre>
</div>

JS JS

var editor = document.getElementById('format');
var npatt = / *var +/igm
editor.addEventListener('keyup', highlight);

function highlight(e){
    var content = editor.innerHTML;
    if(e.which === 13 && e.shiftKey===false){
        editor.innerHTML = content.replace(npatt, '<span style="color:red">var</span>&nbsp;');
        console.log(editor.innerHTML);
    }
}

Moving the cursor to the end of a contenteditable element can be done according to the method in this answer . 可以根据此答案中的方法将光标移动到contenteditable元素的末尾。 That approach uses the window.getSelection() method to find the cursor position. 该方法使用window.getSelection()方法查找光标位置。

I made a few changes to your code. 我对您的代码做了一些更改。

  1. Added a test check to see if the regular expression even matches the content to avoid calling replace and setting editor.innerHTML on every Enter keystroke as the original code did. 添加了一个test检查,以查看正则表达式是否与内容匹配,从而避免像原始代码一样在每个Enter键上调用replaceeditor.innerHTML
  2. Added a call to the cursorManager.setEndOfContenteditable method (from the answer referenced above) to reset the cursor to the end of the editor after the replace operation. 添加了对cursorManager.setEndOfContenteditable方法的调用(来自上面引用的答案),以在replace操作之后将游标重置到编辑器的末尾。

Here is the updated code. 这是更新的代码。

var editor = document.getElementById('format');
var npatt = / *var +/igm;

editor.addEventListener('keyup', highlight);

function highlight(e){
    var content = editor.innerHTML;

    if(e.which === 13 && e.shiftKey === false && npatt.test(content)) {
        editor.innerHTML = content.replace(npatt, '<span style="color:red">var</span>&nbsp;');
        cursorManager.setEndOfContenteditable(editor);
    }
}

And here is a working example. 这是一个有效的示例。

 var editor = document.getElementById('format'); var npatt = / *var +/igm; editor.addEventListener('keyup', highlight); function highlight(e){ var content = editor.innerHTML; if(e.which === 13 && e.shiftKey === false && npatt.test(content)) { editor.innerHTML = content.replace(npatt, '<span style="color:red">var</span>&nbsp;'); cursorManager.setEndOfContenteditable(editor); } } //Code to set the cursor position modified from this answer: https://stackoverflow.com/a/19588665/830125 //Namespace management idea from http://enterprisejquery.com/2010/10/how-good-c-habits-can-encourage-bad-javascript-habits-part-1/ (function( cursorManager ) { //From: http://www.w3.org/TR/html-markup/syntax.html#syntax-elements var voidNodeTags = ['AREA', 'BASE', 'BR', 'COL', 'EMBED', 'HR', 'IMG', 'INPUT', 'KEYGEN', 'LINK', 'MENUITEM', 'META', 'PARAM', 'SOURCE', 'TRACK', 'WBR', 'BASEFONT', 'BGSOUND', 'FRAME', 'ISINDEX']; //From: https://stackoverflow.com/questions/237104/array-containsobj-in-javascript Array.prototype.contains = function(obj) { var i = this.length; while (i--) { if (this[i] === obj) { return true; } } return false; } //Basic idea from: https://stackoverflow.com/questions/19790442/test-if-an-element-can-contain-text function canContainText(node) { if(node.nodeType == 1) { //is an element node return !voidNodeTags.contains(node.nodeName); } else { //is not an element node return false; } }; function getLastChildElement(el){ var lc = el.lastChild; while(lc && lc.nodeType != 1) { if(lc.previousSibling) lc = lc.previousSibling; else break; } return lc; } //Based on Nico Burns's answer cursorManager.setEndOfContenteditable = function(contentEditableElement) { var range,selection; if(document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+ { range = document.createRange();//Create a range (a range is a like the selection but invisible) range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start selection = window.getSelection();//get the selection object (allows you to change selection) selection.removeAllRanges();//remove any selections already made selection.addRange(range);//make the range you have just created the visible selection } else if(document.selection)//IE 8 and lower { range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible) range.moveToElementText(contentEditableElement);//Select the entire contents of the element with the range range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start range.select();//Select the range (make it the visible selection } } }( window.cursorManager = window.cursorManager || {})); 
 <div class="container"> <pre class="text"><code contenteditable="true" id="format"> </code></pre> </div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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