少し時間がかかりますので、よくお読みください。関数の流れに関する一般的な考え方を示すために、重要な部分に注釈を付けました。
function paragraphify(parent) {
var i, str, p, workspace = document.createElement('div'), nodes = parent.childNodes;
p = document.createElement('p');
workspace.appendChild(p);
// Filter nodes out of parent and into the workspace.
while(nodes.length > 0) {
// Get the first child node of the parent element.
node = nodes[0];
// Divs and paragraphs need not be processed; skip them.
if(node.nodeName === 'P' || node.nodeName === 'DIV') {
workspace.insertBefore(node, p);
continue;
}
// Drop the node into the paragraph.
p.appendChild(node);
// Skip non-text nodes.
if(node.nodeName !== '#text') { continue; }
// We need to parse the text of the node for newlines.
str = node.nodeValue;
for(i = 0; i < str.length; i += 1) {
if(str[i] === '\n') {
// If text contains a newline ...
if(i < (str.length - 1)) {
// ... and there's enough space to split it, then split it.
parent.insertBefore(document.createTextNode(str.substr(i+1)), nodes[0]);
node.nodeValue = str.substr(0, i+1);
}
// Create a new paragraph for holding elements, and add it to the workspace.
p = document.createElement('p');
workspace.appendChild(p);
// Break here to return to the node-processing loop.
// If the text was split on a newline, then that will be the next node to be processed.
break;
}
}
}
// Pull the nodes back out of the workspace and into the parent element.
nodes = workspace.children;
while(nodes.length > 0) {
node = nodes[0];
// Skip empty paragraphs.
if(node.nodeName === 'P' && node.textContent.replace(/\s/g, '').length === 0) {
workspace.removeChild(node);
}
else {
parent.appendChild(node);
}
}
}
この関数は、例で指定したとおりに機能します。Paragraphify
引数の子ノードparent
、スキップ<div>
、<p>
要素を繰り返し処理します。これらはフォーマットする必要がないためです。段落ノードを作成し、親のノードを一度に1つずつ移動して、テキストノード内で改行文字に遭遇すると、テキストノードを適切に分割します。
これは、親要素が空になるまで処理されます。その後、ワークスペース要素は親に戻されます。これは、アクティブに反復しているコレクションの操作が煩雑になる可能性があるため、処理をはるかに簡単にするために行われました。
これは親の直接の子供よりも下がらないことを警告する必要がありますが、この必要がある場合は、私に知らせてください。基本的に、この関数はこの変換を実行しません。
<span>Hello
world</span>
... の中へ ...
<p><span>Hello</span></p>
<p><span>world</span></p>
それでも、これは基本的なJavascriptを使用したHTMLでの行処理に必要な基本機能の良い例です。
jsFiddleデモンストレーション