动态地将文本继续分成单独的<p>段落?

Dav*_*ave 35 html javascript css jquery

下面的小提琴允许将文本粘贴到a中<textarea>并生成相同的段落,动态地<p>由相同数量的字符组成.


发生的问题是; 来自先前动态生成的段落的文本<p>在每个标记内溢出,并且不会正确地继续到下一个动态段落.因此,用户是否可以按Enter键并将该内容向下移动到下一个现有段落中,同时仍然动态且自动地保留现有格式?

如果可以提供一个新的小提琴,我将非常感激,因为我还是新编码.再一次,小提琴可以在这里找到.

更新:是否可以生成段落,用户可以按Enter键,如果可能,将其内容无缝地移动到下面的段落中?并且当按下退格按钮时应用同样的内容,以使内容向上移动到上一段?出现的问题是,当按下回车时,文本似乎由于css中的溢出属性而隐藏文本.


$(function() {
    $("#Go").on('click', function() {
        var theText = $('textarea').val();
        var numberOfCharacters = 300;
        while (theText.length) {
            while (theText.length > numberOfCharacters &&
                theText.charAt(numberOfCharacters) !== ' ') {
                numberOfCharacters++;
            }
            $("#text_land").append("<br><\/br><p>" + theText.substring(
                    0, numberOfCharacters) +
                "<\/p><br><\/br>");
            theText = theText.substring(numberOfCharacters);
            numberOfCharacters = 300;
            $('p').attr('contenteditable', 'true');
            $("p").addClass("text");
        }
    })
})
$('select').on('change', function() {
    var targets = $('#text_land p'),
        property = this.dataset.property;
    targets.css(property, this.value);
}).prop('selectedIndex', 0);
(end);
Run Code Online (Sandbox Code Playgroud)
@media print {
    p {
        page-break-inside: avoid;
    }
}

p {
    position: relative;
}

@media print {
    .no-print,.no-print * {
        display: none !important;
    }
}

p {
    border-style: solid;
    color: #000;
    display: block;
    text-align: justify;
    border-width: 5px;
    font-size: 19px;
    overflow: hidden;
    height: 300px;
    width: 460px;
    word-wrap: break-word;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


 <div align="center">
        <h4 align="center"><u>Paste text in the field below to divide text into
        paragraphs.</u></h4><br>
        <br>
        <textarea placeholder="Type text here, then press the button below." cols="50" id="textarea1" rows="10">
</textarea><br>
        <br>
        <button id="Go">Divide Text into Paragraphs!</button>
    </div>
    <hr>
    <h2 align="center">Divided Text Will Appear Below:</h2>
    <div>
        <div align="center" id="text_land" style="font-family: monospace">
        </div>
    </div>
Run Code Online (Sandbox Code Playgroud)

Abh*_*lks 6

用户可以按Enter键并将该内容向下移动到下一个现有段落中,同时仍然动态地自动保留现有格式

如果我理解正确,你想要的是,一旦文本被分成段落,然后用户将一些文本添加到其中一个并按下Enter,那么剩下的文本应该流入下一段分配溢出文本,就像完成一样早.

类似地,当用户BackSpace在段落的开头按下时,文本再次返回到前一段中,溢出的文本与先前所做的一样分配到其他段落中.

作为一种算法,你需要的是这样的:

  1. 将初始文本划分为相等的块,并分配到p根据需要动态创建s的段落中.
  2. 听取keyup有关这些p元素的事件
  3. 按键是Enter,
    • 3.1从Enter按下的位置提取剩余文本
    • 3.2从下面所有段落中提取文本,前面加上上面提取的溢出文本
    • 3.3删除下一个所有段落并分发组合文本,就像我们在步骤1中所做的那样
  4. 按键是BackSpace,
    • 4.1检查它是否在段落的开头,如果有前一段
    • 4.2提取段落的文本并附加下一段所有段落的文本
    • 4.3删除包括当前段落在内的所有段落,并将提取的文本附加到前一段.
    • 4.4像在步骤1中一样分发组合文本

使用这种粗略的算法,您可以开始编码,看起来像这样:

注1:这是所有JavaScript,没有jQuery.
注2:这过于简化,您需要进一步优化和计算所有边缘情况.

缓存必需元素并绑定事件处理程序:

var btn = document.getElementById('go'), 
    textarea = document.getElementById('textarea1'), 
    content = document.getElementById('content');

btn.addEventListener('click', initialDistribute);
content.addEventListener('keyup', handleKey);
Run Code Online (Sandbox Code Playgroud)

textarea如果有的话,从删除现有段落中分发初始文本:

function initialDistribute() {
    var text = textarea.value;
    while (content.hasChildNodes()) { content.removeChild(content.lastChild); }
    rearrange(text);
}
Run Code Online (Sandbox Code Playgroud)

通过动态创建所需数量的段落来重新排列/分发文本的逻辑:

function rearrange(text) {
    var chunks = text.match(/.{1,100}/g) || [];
    chunks.forEach(function(str, idx) {
        para = document.createElement('P');
        para.setAttribute('contenteditable', true);
        para.textContent = str;
        content.appendChild(para);
    });
}
Run Code Online (Sandbox Code Playgroud)

注3:本例中我使用了100个字符来分割文本.此外,这不会处理空格,并将分隔两者之间的单词.您需要在代码中执行此操作.(#见下面的编辑)

陷阱Enter(键码13)和BackSpace(键码8)键的事件处理程序.另外,看看元素是否是一个p元素:

function handleKey(e) {
    var para = e.target, position, 
        key, fragment, overflow, remainingText;
    key = e.which || e.keyCode || 0;
    if (para.tagName != 'P') { return; }
    if (key != 13 && key != 8) { return; }
    ...
Run Code Online (Sandbox Code Playgroud)

获取光标位置以确定是否BackSpace在段落的开头按下了:

position = window.getSelection().getRangeAt(0).startOffset;    
Run Code Online (Sandbox Code Playgroud)

如果Enter被按下,提取当前段落的最后一个孩子后的文本(CONTENTEDITABLE会产生divEnter按下),删除节点,在前面加上它来在此之后的所有段落的剩余的文本,并删除其余的段落.

if (key == 13) {
    fragment = para.lastChild; overflow = fragment.textContent;
    fragment.parentNode.removeChild(fragment); 
    remainingText = overflow + removeSiblings(para, false);
    rearrange(remainingText);
}
Run Code Online (Sandbox Code Playgroud)

如果BackSpace按下,检查是否有前一段并且光标位于开头.如果是,则在删除所有后续段落(包括当前段落)时提取剩余文本:

if (key == 8 && para.previousElementSibling && position == 0) {
    fragment = para.previousElementSibling;
    remainingText = removeSiblings(fragment, true);
    rearrange(remainingText);
}
Run Code Online (Sandbox Code Playgroud)

逻辑从后续段落中提取文本并删除它们:

function removeSiblings(elem, includeCurrent) {
    var text = '', next;
    if (includeCurrent && !elem.previousElementSibling) { 
        parent = elem.parentNode; text = parent.textContent;
        while (parent.hasChildNodes()) { parent.removeChild(parent.lastChild); }
    } else {
        elem = includeCurrent ? elem.previousElementSibling : elem;
        while (next = elem.nextSibling) { 
            text += next.textContent; elem.parentNode.removeChild(next);
        }
    }
    return text;
}
Run Code Online (Sandbox Code Playgroud)

把它们放在一起,这是一个工作片段:

片段:

var btn = document.getElementById('go'), 
	textarea = document.getElementById('textarea1'), 
	content = document.getElementById('content'), 
    chunkSize = 100;
    
btn.addEventListener('click', initialDistribute);
content.addEventListener('keyup', handleKey);

function initialDistribute() {
    var text = textarea.value;
    while (content.hasChildNodes()) {
        content.removeChild(content.lastChild);
    }
    rearrange(text);
}

function rearrange(text) {
    var	chunks = splitText(text, false);
    chunks.forEach(function(str, idx) {
        para = document.createElement('P');
        para.setAttribute('contenteditable', true);
        para.textContent = str;
        content.appendChild(para);
    });
}

function handleKey(e) {
    var para = e.target, position, 
        key, fragment, overflow, remainingText;
    key = e.which || e.keyCode || 0;
    if (para.tagName != 'P') { return; }
    if (key != 13 && key != 8) { return; }
		position = window.getSelection().getRangeAt(0).startOffset;    
    if (key == 13) {
        fragment = para.lastChild;
        overflow = fragment.textContent;
        fragment.parentNode.removeChild(fragment); 
        remainingText = overflow + removeSiblings(para, false);
        rearrange(remainingText);
    }
    if (key == 8 && para.previousElementSibling && position == 0) {
        fragment = para.previousElementSibling;
        remainingText = removeSiblings(fragment, true);
        rearrange(remainingText);
    }
}

function removeSiblings(elem, includeCurrent) {
    var text = '', next;
    if (includeCurrent && !elem.previousElementSibling) { 
        parent = elem.parentNode; 
		text = parent.textContent;
        while (parent.hasChildNodes()) {
            parent.removeChild(parent.lastChild);
        }
    } else {
        elem = includeCurrent ? elem.previousElementSibling : elem;
        while (next = elem.nextSibling) { 
            text += next.textContent;
            elem.parentNode.removeChild(next);
        }
    }
    return text;
}

function splitText(text, useRegex) {
	var chunks = [], i, textSize, boundary = 0;
    if (useRegex) { 
        var regex = new RegExp('.{1,' + chunkSize + '}\\b', 'g');
        chunks = text.match(regex) || [];
    } else {
		for (i = 0, textSize = text.length; i < textSize; i = boundary) {
			boundary = i + chunkSize;
			if (boundary <= textSize && text.charAt(boundary) == ' ') {
				chunks.push(text.substring(i, boundary));
			} else {
				while (boundary <= textSize && text.charAt(boundary) != ' ') { boundary++; }
				chunks.push(text.substring(i, boundary));
			}
		}
	}
	return chunks;
}
Run Code Online (Sandbox Code Playgroud)
* { box-sizing: border-box; padding: 0; margin: 0; }
body { font-family: monospace; font-size: 1em; }
h3 { margin: 1.2em 0; }
div { margin: 1.2em; }
textarea { width: 100%; }
button { padding: 0.5em; }
p { padding: 1.2em 0.5em; margin: 1.4em 0; border: 1px dashed #aaa; }
Run Code Online (Sandbox Code Playgroud)
<div>
  <h3>Paste text in the field below to divide text into
        paragraphs..</h3>
  <textarea placeholder="Type text here, then press the button below." id="textarea1" rows="5" ></textarea><br/><br/>
  <button id="go">Divide Text into Paragraphs</button>
</div>
<hr>
<div>
  <h3>Divided Text Will Appear Below:</h3>
  <div id="content"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

还有一个小提琴供你玩:

小提琴:https://jsfiddle.net/abhitalks/jwnnn5oy/


编辑1:

修复了在字边界处打破的正则表达式.还添加了相同的非正则表达式程序代码(在Op的原始代码行上),以演示如何将其他代码段纳入其中并将其集成到其中的Op.

注4:关于Op的使用jQuery的评论,它与手头的问题无关.jQuery只不过是JavaScript,对于他们来说,将片段片段合并到更大的代码库中应该是微不足道的.

更改集:添加功能splitText.


编辑2:

根据您的评论,如果您希望在用户键入时自动进行重新分发...那么您需要计算该段落中文本的长度,看看是否超过了您的块大小.如果是,则从该段开始重新分配.对退格做反向.

我最初发布的解决方案是为了满足您的要求,当用户按下任何文本之间进行输入以断开并将其分发到后续段落时.我不建议自动将其作为用户类型执行,因为更改对用户来说太过于刺耳.

摘录2:

var btn = document.getElementById('go'), 
	textarea = document.getElementById('textarea1'), 
	content = document.getElementById('content'), 
    chunkSize = 100;
    
btn.addEventListener('click', initialDistribute);
content.addEventListener('keyup', handleKey);

function initialDistribute() {
    var text = textarea.value;
    while (content.hasChildNodes()) {
        content.removeChild(content.lastChild);
    }
    rearrange(text);
}

function rearrange(text) {
    var	chunks = splitText(text, false);
    chunks.forEach(function(str, idx) {
        para = document.createElement('P');
        para.setAttribute('contenteditable', true);
        para.textContent = str;
        content.appendChild(para);
    });
}

function handleKey(e) {
    var para = e.target, position, 
        key, fragment, overflow, remainingText;
    key = e.which || e.keyCode || 0;
    if (para.tagName != 'P') { return; }
    if (key != 13 && key != 8) { redistributeAuto(para); return; }
		position = window.getSelection().getRangeAt(0).startOffset;    
    if (key == 13) {
        fragment = para.lastChild;
        overflow = fragment.textContent;
        fragment.parentNode.removeChild(fragment); 
        remainingText = overflow + removeSiblings(para, false);
        rearrange(remainingText);
    }
    if (key == 8 && para.previousElementSibling && position == 0) {
        fragment = para.previousElementSibling;
        remainingText = removeSiblings(fragment, true);
        rearrange(remainingText);
    }
}

function redistributeAuto(para) {
	var text = para.textContent, fullText;
	if (text.length > chunkSize) {
		fullText = removeSiblings(para, true);
	}
	rearrange(fullText);
}

function removeSiblings(elem, includeCurrent) {
    var text = '', next;
    if (includeCurrent && !elem.previousElementSibling) { 
        parent = elem.parentNode; 
		text = parent.textContent;
        while (parent.hasChildNodes()) {
            parent.removeChild(parent.lastChild);
        }
    } else {
        elem = includeCurrent ? elem.previousElementSibling : elem;
        while (next = elem.nextSibling) { 
            text += next.textContent;
            elem.parentNode.removeChild(next);
        }
    }
    return text;
}

function splitText(text, useRegex) {
	var chunks = [], i, textSize, boundary = 0;
    if (useRegex) { 
        var regex = new RegExp('.{1,' + chunkSize + '}\\b', 'g');
        chunks = text.match(regex) || [];
    } else {
		for (i = 0, textSize = text.length; i < textSize; i = boundary) {
			boundary = i + chunkSize;
			if (boundary <= textSize && text.charAt(boundary) == ' ') {
				chunks.push(text.substring(i, boundary));
			} else {
				while (boundary <= textSize && text.charAt(boundary) != ' ') { boundary++; }
				chunks.push(text.substring(i, boundary));
			}
		}
	}
	return chunks;
}
Run Code Online (Sandbox Code Playgroud)
* { box-sizing: border-box; padding: 0; margin: 0; }
body { font-family: monospace; font-size: 1em; }
h3 { margin: 1.2em 0; }
div { margin: 1.2em; }
textarea { width: 100%; }
button { padding: 0.5em; }
p { padding: 1.2em 0.5em; margin: 1.4em 0; border: 1px dashed #aaa; }
Run Code Online (Sandbox Code Playgroud)
<div>
  <h3>Paste text in the field below to divide text into
        paragraphs..</h3>
  <textarea placeholder="Type text here, then press the button below." id="textarea1" rows="5" ></textarea><br/><br/>
  <button id="go">Divide Text into Paragraphs</button>
</div>
<hr>
<div>
  <h3>Divided Text Will Appear Below:</h3>
  <div id="content"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

小提琴2:https://jsfiddle.net/abhitalks/hvhr4ds8/

注意5:在小提琴中首先按Enter键以打断其间的一些文本,这样您就可以看到在键入时如何重新分配.另外,请注意,由于不会破坏单词的逻辑,在重新分发之前需要多一些字符.

更改集:添加功能redistributeAuto.