2015-10-16 146 views
1

我想用JavaScript做一個簡單的語法高亮顯示,但我總是會遇到同樣的問題。該程序的工作原理如下:當用戶輸入(不帶shift鍵)時,程序將用另一個關鍵字var用紅色代替關鍵字var(這仍然非常基本)。問題在於,無論何時按下回車鍵,文本都會突出顯示,但光標會返回到第一行的第一個單詞。你如何看待我可以防止這種情況發生?使用JavaScript語法高亮顯示

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

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); 
    } 
} 
+0

也許光標的移動,因爲現有的內容由語法高亮顯示的內容被完全取代,所以光標位置是沒有意義的,並恢復爲默認的位置? – Ryan

+0

你可以發佈JSfiddle或代碼片段嗎? –

+0

是的,但我該如何解決這個問題?,我的意思是說,當我點擊輸入時,替換的文本應該在第一行(或任何行)和下一行的光標? – Noctisdark

回答

2

移動光標到一個contenteditable元件的端部可以根據在所述this answer方法來完成。該方法使用window.getSelection() method來查找光標位置。

我對代碼做了一些更改。

  1. 增加了test check,看看正則表達式甚至與內容相匹配,以避免調用replace和每設置editor.innerHTML輸入擊鍵的原代碼一樣。
  2. 添加了對cursorManager.setEndOfContenteditable方法的調用(根據上面提及的答案),將光標重置爲replace操作後的編輯器末尾。

這裏是更新的代碼。

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); 
    } 
} 

這裏是一個工作示例。

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>

+0

謝謝,謝謝你謝謝!!,你救了我的命,我從來沒有想過這可以完成!謝謝 – Noctisdark