javascript - library - html5 div editable



contentEditable div에서 텍스트 추출하기 (4)

div를 contentEditable 설정하고 " white-space:pre " white-space:pre 스타일을 지정하여 줄 contentEditable 같은 것을 유지합니다. 사파리, FF 및 IE에서 div는 꽤 많이 보이고 동일하게 작동합니다. 모든 것이 잘됩니다. 내가 원하는 것은이 div에서 텍스트를 추출하는 것입니다.하지만 서식을 잃지 않을 것입니다. 특히 줄 바꿈이 필요합니다.

우리는 text() 함수가 기본적으로 선주문 DFS를 수행하고 DOM의 해당 분기에있는 모든 내용을 하나의 덩어리로 묶는 jQuery를 사용하고 있습니다. 이것은 서식을 잃습니다.

html() 함수를 살펴 보았지만 세 브라우저 모두 내 contentEditable div에서 장면 뒤에 생성되는 실제 HTML과 다른 작업을 수행하는 것으로 보입니다. 이것을 div에 입력한다고 가정합니다.

1
2
3

결과는 다음과 같습니다.

사파리 4 :

1
<div>2</div>
<div>3</div>

Firefox 3.6 :

1
<br _moz_dirty="">
2
<br _moz_dirty="">
3
<br _moz_dirty="">
<br _moz_dirty="" type="_moz">

IE 8 :

<P>1</P><P>2</P><P>3</P>

응. 여기에는 아무런 일관성이 없습니다. 놀라운 점은 MSIE가 가장 정상적으로 보입니다. (자본화 된 P 태그 및 모두)

div는 CSS를 사용하여 동적으로 스타일 (글꼴, 색상, 크기 및 정렬)을 설정하므로 pre 태그 (Google을 사용하여 찾은 일부 페이지에서 언급 한)를 사용할 수 있는지 확실하지 않습니다.

누구든지 어떤 JavaScript 코드 및 / 또는 jQuery 플러그인이나 linebreaks를 유지하는 방식으로 contentEditable div에서 텍스트를 추출하는 것을 알고 있습니까? 내가 할 필요가 없다면 파싱 휠을 재발 명하고 싶지는 않을 것입니다.

업데이트 : jQuery 1.4.2에서 getText 함수를 cribbed하고 공백을 사용하여 추출하기 위해 수정했습니다 (줄 바꿈을 추가하는 한 줄만 chnaged).

function extractTextWithWhitespace( elems ) {
    var ret = "", elem;

    for ( var i = 0; elems[i]; i++ ) {
        elem = elems[i];

        // Get the text from text nodes and CDATA nodes
        if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
            ret += elem.nodeValue + "\n";

        // Traverse everything else, except comment nodes
        } else if ( elem.nodeType !== 8 ) {
            ret += extractTextWithWhitespace2( elem.childNodes );
        }
    }

    return ret;
}

이 함수를 호출하고 출력을 사용하여 jQuery와 같은 XML 노드에 할당합니다.

var extractedText = extractTextWithWhitespace($(this));
var $someXmlNode = $('<someXmlNode/>');
$someXmlNode.text(extractedText);

결과 XML은 결국 AJAX 호출을 통해 서버로 전송됩니다.

이것은 Safari와 Firefox에서 잘 작동합니다.

IE에서는 첫 번째 '\ n'만 유지되는 것으로 보입니다. 더 자세히 살펴보면 jQuery가 텍스트를 이렇게 설정하는 것 같습니다 (jQuery-1.4.2.js의 4004 행).

return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );

createTextNode 에 대해 읽어 보면 IE의 구현이 공백을 매시는 것처럼 보입니다. 이게 사실입니까, 아니면 제가 잘못하고있는 것입니까?

https://src-bin.com


Answer #1

iOS Safari (iOS 7 및 8), Safari 8, Chrome 43 및 OS X의 Firefox 36, Windows의 IE6-11에서 작동하는 솔루션 (밑줄 및 jquery 사용)이 있습니다.

_.reduce($editable.contents(), function(text, node) {
    return text + (node.nodeValue || '\n' +
        (_.isString(node.textContent) ? node.textContent : node.innerHTML));
}, '')

테스트 페이지 참조 : http://brokendisk.com/code/contenteditable.html

진정한 대답은 브라우저에서 제공하는 마크 업에 관심이 없다면 contenteditable 속성을 사용하지 말아야한다는 것입니다. 텍스트 영역은 작업에 적합한 도구입니다.


Answer #2

니코가 현상금을 때렸을 때까지 지금까지이 질문을 잊어 버렸습니다.

필자는 필자가 필요로했던 함수를 작성하고 기존 jQuery 코드베이스에서 함수를 크립하여 필요한대로 작동하도록 수정하여 문제를 해결했습니다.

Safari (WebKit), IE, Firefox 및 Opera에서이 기능을 테스트했습니다. contentEditable 전체가 비표준이므로 다른 브라우저를 확인하는 것을 신경 쓰지 않았습니다. contentEditable을 구현하는 방법을 변경하면 브라우저를 업데이트하면이 함수가 중단 될 수도 있습니다. 따라서 프로그래머는 조심하십시오.

function extractTextWithWhitespace(elems)
{
    var lineBreakNodeName = "BR"; // Use <br> as a default
    if ($.browser.webkit)
    {
        lineBreakNodeName = "DIV";
    }
    else if ($.browser.msie)
    {
        lineBreakNodeName = "P";
    }
    else if ($.browser.mozilla)
    {
        lineBreakNodeName = "BR";
    }
    else if ($.browser.opera)
    {
        lineBreakNodeName = "P";
    }
    var extractedText = extractTextWithWhitespaceWorker(elems, lineBreakNodeName);

    return extractedText;
}

// Cribbed from jQuery 1.4.2 (getText) and modified to retain whitespace
function extractTextWithWhitespaceWorker(elems, lineBreakNodeName)
{
    var ret = "";
    var elem;

    for (var i = 0; elems[i]; i++)
    {
        elem = elems[i];

        if (elem.nodeType === 3     // text node
            || elem.nodeType === 4) // CDATA node
        {
            ret += elem.nodeValue;
        }

        if (elem.nodeName === lineBreakNodeName)
        {
            ret += "\n";
        }

        if (elem.nodeType !== 8) // comment node
        {
            ret += extractTextWithWhitespace(elem.childNodes, lineBreakNodeName);
        }
    }

    return ret;
}

Answer #3

오늘 Firefox에서 이것을 발견했습니다.

white-space가 "pre"로 설정되어있는 contenteditable div를이 함수에 전달합니다.이 함수는 예리하게 작동합니다.

얼마나 많은 노드가 있는지를 보여주는 라인을 추가하고 라인 프리가 손상되지 않았 음을 증명하기 위해 출력을 다른 PRE에 넣는 버튼을 추가했습니다.

기본적으로 다음과 같이 말합니다.

For each child node of the DIV,
   if it contains the 'data' property,
      add the data value to the output
   otherwise
      add an LF (or a CRLF for Windows)
}
and return the result.

문제가 있습니다. LF를 입력하는 대신 원본 텍스트의 줄 끝에서 Enter 키를 누르면 "Â"가 입력됩니다. 다시 Enter 키를 누르면 LF가 처음에는 입력되지 않습니다. 그리고 "Â"(공백 같이 보입니다)를 지워야합니다. Go figure - 나는 버그라고 생각합니다.

이것은 IE8에서는 발생하지 않습니다. (textContent를 innerText로 바꾼다) 다른 버그가있다. Enter 키를 누르면 Firefox에서와 같이 노드가 2 노드로 나뉘지만 각 노드의 "data"속성은 "undefined"가됩니다.

눈을 맞추는 것보다 훨씬 더 많은 일이 여기에있을 것이라는 점을 확신합니다. 문제에 대한 모든 의견이 밝혀 질 것입니다.

<!DOCTYPE html>
<html>
<HEAD>
<SCRIPT type="text/javascript">
    function htmlToText(elem) {
        var outText="";
        for(var x=0; x<elem.childNodes.length; x++){
            if(elem.childNodes[x].data){
                outText+=elem.childNodes[x].data;
            }else{
                outText+="\n";
            }
        }
        alert(elem.childNodes.length + " Nodes: \r\n\r\n" + outText);
        return(outText);
    }
</SCRIPT>
</HEAD>
<body>

<div style="white-space:pre;" contenteditable=true id=test>Text in a pre element
is displayed in a fixed-width
font, and it preserves
both      spaces and
line breaks
</DIV>
<INPUT type=button value="submit" onclick="document.getElementById('test2').textContent=htmlToText(document.getElementById('test'))">
<PRE id=test2>
</PRE>
</body>
</html>





contenteditable