2010-06-09 3 views
14

인터넷에서 사용할 수있는 수많은 WYSIWYG 편집기가 있지만 드래그 앤 드롭 구현의 일부 형식을 구현하는 편집기는 아직 없습니다.contentEditable 요소의 드래그 앤 드롭 콘텐츠

독자적인 편집기를 쉽게 만들 수 있지만 편집 가능한 영역 외부에서 요소 (예 : 토큰)를 드래그하여 편집 가능한 영역 내에서 선택한 위치에 드롭 할 수있게하려고합니다. .

편집 가능한 요소의 특정 위치에 html을 삽입하는 것이 쉽지만 사용자가 편집 가능한 영역의 일부 요소 위로 DIV를 드래그 할 때 캐럿이 있어야하는 위치를 어떻게 결정할 수 있습니까? 내가 설명하려고하는 것을 더 잘 설명하기 위해 다음 시나리오를 참조하십시오.

편집 가능한 영역 (편집 모드에서 IFRAME 또는 true로 설정된의 contentEditable 속성을 가진 DIV 중 하나)가 이미 다음과 같은 텍스트가 포함

"의 친애하는,하시기 바랍니다 참고 ...."

사용자는 편집 가능한 영역 위의 요소 목록에서 토큰을 나타내는 요소를 드래그하여 위에 표시된 것처럼 텍스트의 쉼표 (,) 바로 앞에 캐럿이 나타날 때까지 텍스트 위로 커서를 이동합니다. 사용자가 해당 위치에서 마우스 버튼을 놓으면 HTML이 삽입되어 다음과 같은 결과가 발생할 수 있습니다.

"친애하는 {UserFirstName}, 메모 해주세요 ...".

다른 사람이 이와 비슷한 작업을 한 적이 있는지 또는 적어도 JavaScript를 사용하여이 작업을 수행하는 방법을 알고 있는지는 알 수 없습니다.

도움이 될 것입니다.

답변

6

이 문제를 해결하는 나의 접근 방식 편집 가능한 요소에서 맞춤 드래그 요소 사용 큰 문제는 편집 가능한 요소 위로 마우스를 가져 가면 마우스 커서의 텍스트 오프셋을 확인할 수 없다는 것입니다. 원하는 위치에 캐럿을 설정하기 위해 마우스 클릭을 위조하려고 시도했지만 작동하지 않았습니다. 그랬더라도 드래그하는 동안 캐럿 배치를 시각적으로 볼 수는 없지만 결과 드롭 만 볼 수 있습니다.

텍스트 노드가 아닌 요소에 마우스 오버 이벤트를 바인딩 할 수 있으므로 편집 가능한 요소를 일시적으로 편집 할 수 없도록 설정할 수 있습니다. 모든 요소를 ​​찾아 텍스트의 흐름을 손상시키지 않는 범위의 각 텍스트 노드를 래핑하십시오. 각 범위에는 클래스 이름이 주어져야 다시 찾을 수 있습니다.

랩핑 후 모든 랩된 텍스트 노드를 다시 찾아 각 문자를 다시 찾을 수있는 클래스 이름으로 다른 스팬으로 래핑해야합니다.

이벤트 위임을 사용하면 이벤트를 주 편집 가능 요소에 추가 할 수 있습니다.이 요소는 깜박이는 GIF 이미지를 배경으로 표시 할 각 문자 범위에 스타일을 적용합니다.

또한 위임을 사용하여 각 문자에 마우스 업 이벤트 (드롭 이벤트) 이벤트를 추가해야합니다. 부모 (래핑 된 텍스트 노드) 내에서 문자 범위의 위치 (오프셋)를 사용하여 오프셋을 결정할 수 있습니다. 계산 된 간격 띄우기에 대한 참조를 유지하고 적용 가능한 텍스트 노드에 대한 참조를 유지하면서 줄 바꿈을 실행 취소하는 동안 모든 줄 바꿈을 취소 할 수 있습니다.

범위 객체 & 브라우저의 선택 객체를 사용하여 계산 된 오프셋을 사용하여 해당 텍스트 노드에 선택을 설정하고 새롭게 설정된 선택 (캐럿 위치)에 필요한 HTML을 주입 할 수 있습니다.

editElement.find(".text-node").each(function() 
{ 
    var textnode = $(this), text = textnode.text(), result = []; 

    for (var i = 0; i < text.length; i++) result.push(text.substr(i, 1)); 

    textnode.html("<span class=\"char\">" 
     + result.join("</span><span class=\"char\">") + "</span>"); 
}); 

는 포장을 취소하려면 :

editElement.find("*:not(.text-node)").contents().filter(function(){ 
    return this.nodeType != 1; 
}).wrap("<span class=\"text-node\"/>"); 

각 텍스트 노드를 찾으려면 각 문자 사용을 포장 : 여기

이 textnodes를 찾을 수 jQuery를 사용하여 조각을 다음과 그들을 포장 :

editElement.find(".text-node").each(function() 
{ 
    this.parentNode.replaceChild(document.createTextNode($(this).text()), this); 
}); 

희망이 방법은 가진 자와 유사한 과제를하는 데 도움이

+1

위에서 언급 한 것처럼 문자 범위에 위임 된 mouseup 이벤트를 적용 할 필요는 없지만 실제로 drappable 이벤트의 원래 이벤트 속성을 사용하여 드래그 가능 항목이 문자 범위에서 삭제되었는지 여부를 확인할 수 있습니다. 그냥 FYI .... – Raybiez

1

현재 HTML5 API가 개발 중입니다. 이지만 불행히도 IE는이를 지원하지 않습니다. 편집 : 분명히 IE는 실제로 드래그 앤 드롭을 지원하지만, 작동 방식에 익숙하지 않습니다. "IE 드래그 앤 드롭"Googling을 시도하십시오.

이 사이트에서 찾고 시도해보십시오

+0

내 동료가 해결 방법을 찾았습니다. 나는 그에게 질문을 던졌습니다. 곧 해결책을 게시 할 것입니다. – Raybiez

+0

아아, 그의 해결책은 실제로 적용 할 수 없습니다. 사냥이 다시 시작됩니다 ... grrr – Raybiez

+0

@ Raybiez 아마도 당신은 작동하지 않는 해결책을 추가하기 위해 질문을 편집 할 수 있습니까? 또한이 질문을 첫 페이지로 밀어 넣는 부작용이 있습니다. – Na7coldwater

2

나는 당신이 무슨 말을하는지 이해한다면, 이것은 단지 기본적인 드래그 앤 드롭 일뿐입니다. 아래 해결책은 FIREFOX에 대한 최선의 해결책에 가깝습니다. 나는 IE를위한 다른 기능이 있다고 확신한다. 도움이 필요하면 http://www.html5rocks.com/en/tutorials/dnd/basics/으로 이동하십시오.

끌어 놓을 개체의 "draggable"특성을 설정하고 개체의 "ondragstart"메서드를 "dragStartHandler"또는 함수 호출시 설정합니다.

// You can set this to 'text/plain' if you don't want to insert HTML content 
var internalDNDType = 'text/html'; 

function dragStartHandler(event) { 
    // This is whatever html data you want to insert. 
    var textContent = "<b>"+userFirstName+"</b>"; 

    event.dataTransfer.setData(internalDNDType, textContent); 
    event.dataTransfer.effectAllowed = 'copy'; 
} 

function dragEnterHandler(event) 
{ 
    event.preventDefault(); 
    return false; 
} 

function dragOverHandler(event) 
{ 
    event.preventDefault(); 
    return false; 
} 

function dropHandler(event) { 
    event.preventDefault(); 
    event.stopPropogation(); 
    return false; 
} 
+0

응답 주셔서 감사합니다, 그러나 이것은 HTML5에 의존하고, 응용 프로그램은 오래된 브라우저를 지원해야했습니다. 레거시 브라우저 지원이없는 새로운 업데이트 된 응용 프로그램의 경우이 방법이 가장 적합합니다. – Raybiez