2014-10-16 3 views
2

"contenteditable"이 true로 설정된 div가 있습니다.입력 된 텍스트를 범위 내에서 contenteditable elememt로 묶을 수 있습니까?

이제 새로 입력 된 텍스트를 하나의 스팬에 래핑하려고합니다. 편집 된 텍스트를 강조 표시 할 수 있습니다. 내가 지금 어디에 있어요 여기

입니다 - http://jsfiddle.net/ug4xr9x0/

HTML

<div contenteditable="true" id="myContent">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi suscipit tincidunt leo, non volutpat lectus sodales non. Phasellus id felis ultrices, egestas enim nec, ornare quam. Ut at posuere felis, vitae sodales risus. Suspendisse velit nibh, facilisis et ante et, vehicula facilisis velit.</div> 

자바 스크립트 이것은 스팬 ARO를 래핑 CSS

.highlight{ 
    background-color:yellow; 
} 

document.getElementById('myContent').addEventListener('keydown',function(evt){ 
    var range = window.getSelection().getRangeAt(0); 
    if(range.startContainer.parentNode.className!=='highlight'){ 
     var newElement = document.createElement('span'); 
     newElement.className = 'highlight'; 
     newElement.innerHTML = String.fromCharCode(evt.which); 
     range.insertNode(newElement); 
     range.setStartAfter(newElement); 
     evt.preventDefault(); 
    } 
}); 

und 문자이지만 캐럿을 스팬으로 이동하지 않으므로 역방향 입력이 발생합니다. keydown이 듣기에 적절한 이벤트인지, 심지어 키 누르기를 차단하고 요소를 삽입하는 것이 올바른지는 확실하지 않습니다. 줄 range.setStartAfter은 캐럿을 따라 움직이기위한 시도 였지만, 캐럿의 유무에 관계없이 동일하게 동작합니다.

나는 또한 선택한 텍스트가 입력이 시작될 때 즉시 삭제되지 않도록하고 싶습니다.

도움을 주시면 감사하겠습니다. 감사.

답변

0

저는 Chrome과 Firefox에서이 문제를 해결할 수있었습니다. "를 keyDown"에 반대 여기에 수정 http://jsfiddle.net/ug4xr9x0/8/

"키를 누를 때"

document.getElementById('myContent').addEventListener('keypress',function(evt){ 
    var range = window.getSelection().getRangeAt(0), 
     modifiers = [0,8]; // List of keys to ignore (0 is arrows & 8 is delete in firefox) 

    if(range.startContainer.parentNode.className!=='highlight' && modifiers.indexOf(evt.which) < 0){ 
     if(!range.collapsed){ 
      range.deleteContents(); 
     } 
     var el = document.createElement('span'); 
     el.appendChild(document.createTextNode('A')); 
     el.className = 'highlight'; 
     range.insertNode(el); 

     var sel = window.getSelection();   
     range.setStartBefore(el.childNodes[0]); 
     range.setEndAfter(el.childNodes[0]); 
     sel.removeAllRanges(); 
     sel.addRange(range); 
    } 
}); 

그리고 바이올린 크롬에서 발사 화살표 키 등, 중지하다, 파이어 폭스는 "evt.which"속성을 무시하는 데 필요한 at 0 & 8.

is는 문자 'A'가 포함 된 텍스트 노드가있는 범위를 삽입합니다. 그런 다음 setStartBefore & setEndAfter를 사용하여 해당 노드를 래핑하고 addRange를 사용하여 창 선택 항목을 업데이트 할 범위를 설정합니다. textnode 'A'가 덮어 쓰기됩니다 (기본값 방지 필요 없음).

나는 이것을 달성하는보다 우아한 방법이있을 것이라고 확신하지만, 저에게는 효과적입니다.

도움 주셔서 감사합니다.

0

onkeydown이 적합하지만 oninput은 더 좋지만 모든 브라우저의 contenteditables에는 실행되지 않습니다. 또한 요소를 추가하려면 inserNode이 적절한 방법입니다. setStartAfter은 사용하신 작업에만 해당되며, range.collapse()으로도 처리 할 수 ​​있습니다.

새로 만든 span의 콘텐츠를 newElement.innerHTML = String.fromCharCode(evt.which);으로 설정하면 문제가 시작됩니다. 삽입 된 텍스트가 반드시 사용자가 입력하려고 한 것은 아닙니다.

이 스 니펫은 코드에서 약간 수정되었지만 사용자가 입력 한 텍스트를 보여줍니다.

document.getElementById('myContent').addEventListener('keydown', function (evt) { 
    var range = window.getSelection().getRangeAt(0), 
     modifiers = [8, 13, 37, 38, 39, 40, 46], // List of keys, which should not prevent the default action 
     newElement, chr; 
    if (range.startContainer.parentNode.className !== 'highlight') { 
     if (modifiers.indexOf(evt.which) < 0) { 
      newElement = document.createElement('span'); 
      newElement.className = 'highlight'; 
      range.deleteContents(); // This deletes the content of the selection 
      chr = evt.key || evt.char; // Gets the entered real character 
      if (chr.length < 2) { // Excludes "modifiers" like SHIFT and CTRL etc. 
       newElement.textContent = chr; 
      } 
      range.insertNode(newElement); 
      range.collapse(); // Collapses the range to end 
      evt.preventDefault(); 
     } 
    } 
}); 

A live demo at jsFiddle.

이 코드에는 단점이있는 것으로 보입니다. 입력 한 모든 문자는 span에 실제로 쓰지 않는 한 새로운 span을 만듭니다.

+0

감사합니다. Teemu, Chrome에서 작동해야한다고 말했어 야합니다. 당신의 바이올린이 크롬에서 작동하지 않았을 때 나는 파이어 폭스에서 이것을보기로 결심했습니다. 내 원래 코드는 크롬보다 firefox에서 다르게 작동하는 것 같습니다. 내 주요 문제는 문자가 Chrome에서 거꾸로 있다는 점입니다. 감사 – Ben