0

これが私のHTML「サンドボックス」です。

<p>1 2 3</p>
<span id="myid">
<span id="mytext">
<p>4 5 6</p>
<p>7 8 9</p>
<p>10 11 12</p>
</span>
</span>
<p>13 14 15</p>

それに応じてpタグを「マージ」したいと思います:(
見やすくするために、変更を加えた場所にマイナス記号を追加しました:)

<p>1 2 3 -
<span id="myid">
<span id="mytext">
- 4 5 6</p>
<p>7 8 9</p>
<p>10 11 12 -
</span>
</span>
- 13 14 15</p>

マイナス記号を追加したすべての場所で、実際にa<p>または</p>タグを削除して2つの段落要素をマージしました(123と456の間、および10 1112と131415の間)-(このマージは123-456および101112-131415のインライン表示を実現します)。

'raw' JavaScriptでこの結果を達成するにはどうすればよいですか(ライブラリではありません)。

注: 私は何かを作成しようとしましたが、80行のコードが必要でした-これを行うためのより良い方法があると確信しています。

編集: Jon Hannaは彼のコメントで、私はそのように正しいHTMLを使用できると述べました(JavaScriptの結果として):

    <p>1 2 3 <span class="myclass mytext">4 5 6</span></p>
<p class="myclass mytext">7 8 9</p>
<p><span class="myclass mytext"10 11 12</span> 13 14 15</p>
4

3 に答える 3

1

などでソースコードを取得しinnerHTML、文字列を操作して文字列を出力する必要があります。

<p>DOM は通常、間違ってinsideを持っているという事実を止めませんが、オブジェクト<span>がないため、必要な出力を表現することは論理的に不可能です。HalfWrittenPElement

故意に規則を破るという要件は、オブジェクト モデルが設計されていることと矛盾するため、文字列をハッキングするしかありません。

編集:

そうは言っても、ブラウザはすべて内部モデルでそれを修正するため、最終的には整形式の (必ずしも有効ではないにしても) HTML になります。仕様ではなく、実装で定義された修正に従っているだけです。

于 2012-08-17T23:05:33.627 に答える
1

私はこれをテストしていませんが、あなたはアイデアを得るでしょう。自分でデバッグとクロスブラウザの微調整を行うことができます;)

すべての<p>タグを見つけて、それらのそれぞれについて、その兄弟が<span><span>およびであるかどうかを確認し<p>ます。次に、<span>s と 2 番目のテキストを<p>最初の の中に入れます<p>

var pTags = document.getElementsByTagName('p');  // get all <p>

for (var i = 0; i < pTags.length; i++) {         // for every one of them
   var a = pTags[i];                             // take the <p> (and call it `a`)

   var b = a.nextElementSibling();               // and the next tag (call it `b`)
   if (b == null) continue;

   var c = b.nextElementSibling();               // and the next tag (call it `c`)
   if (c == null) continue;

   var d = c.nextElementSibling();               // and the next tag (call it `d`)
   if (d == null) continue;

   if (b.tagName.toUpperCase() == 'SPAN' &&      //  if b is <span>
       c.tagName.toUpperCase() == 'SPAN' &&      // and c is <span>
       d.tagName.toUpperCase() == 'P') {         // and d is <p> again

         a.appendChild(b);                       // put b inside a
         a.appendChild(c);                       // put c inside a
         a.appendChild(d.firstChild.nodeValue);  // put text of d inside a
   }
}

nextElementSiblingメソッドはクロスブラウザーではありませんが、型になるまで呼び出すことでエミュレートできnextSiblingますElement

appendChildまた、要素を呼び出すと、最初に元のコンテナーから削除され、その後に追加されることにも注意してください。それが私たちが望むものです。

クイック編集:

他の人が指摘しているように、最初は気付かなかった無効なhtmlがあります。<span>しかし、 s を適切に閉じたいと思ったと思います。

于 2012-08-17T23:05:46.697 に答える
1

(ご容赦ください。あなたの最新の編集の前にこれを書き始めました。ただし、それでも役立つと思います。)

何を達成したいのかわかりませんが、JavaScript を使用して求めていることを正確に達成するのは非常に難しいと言えます。これは主に、HTML が無効になるためです。

まず、HTML が無効になる理由を見ていきましょう。ブラウザーが HTML を解析するとき、 DOM ノードのネストされたツリーを構築します。最初の例は次のように表すことができます。

  • <p>
    • 1 2 3
  • <span id="myid">
    • <span id="mytext">
      • <p>
        • 4 5 6
      • <p>
        • 7 8 9
      • <p>
        • 10 11 12
  • <p>
    • 13 14 15

JavaScript と DOM を使用すると、このツリーをたどって操作できます。さまざまなタグのテキスト ノードを組み合わせて、問題なく<p>1 つの<p>タグに配置できます。しかし、2 番目の例の構造を作成することはできません。単純に DOM ツリーの形をしていないため、DOM を使用してその HTML を作成することはできません。

HTML を操作して 2 番目の例の形にする唯一の方法は、 Jon Hanna が説明してinnerHTMLいるように、. 幸いなことに、ブラウザーは常に無効な HTML を有効な DOM 構造に修正します。悪いニュースは、ブラウザごとにこれが異なるため、最終的にどうなるか分からないことです.

唯一の本当の解決策は、最新の編集で行ったように、HTML 構造を再考することです。

元の問題を解決する方法は、元の HTML がどの程度静的であるかによって異なります。大まかな例を挙げますが、それについては次のように推測します。

  • 常に正確に5 <p>があります
  • の 2 番目から 4 番目まで<p>は常に の内側<span>にあり、1 番目と 5 番目は常に の外側にあります。

これら 2 つの条件が満たされている場合は、次のようなものを使用できます。

var paragraphs = document.getElementsByTagName('p');
var newParagraphs = [];

function createElementWithText(tagname, text, classname) {
    var classname = classname || '';
    var element = document.createElement(tagname);
    element.className = classname;
    element.appendChild(document.createTextNode(text));
    return element;
}

newParagraphs[0] = createElementWithText('p', paragraphs[0].textContent);
newParagraphs[0].appendChild(createElementWithText('span', paragraphs[1].textContent, 'myclass mytext'));

newParagraphs[1] = createElementWithText('p', paragraphs[2].textContent, 'myclass mytext');

newParagraphs[2] = document.createElement('p');
newParagraphs[2].appendChild(createElementWithText('span', paragraphs[3].textContent, 'myclass mytext'));
newParagraphs[2].appendChild(document.createTextNode(paragraphs[4].textContent));

JSFiddle に実例を投稿しました: jsfiddle.net/vSrLJ/

于 2012-08-17T23:51:22.717 に答える