THE HAM MEDIA BLOG

jQueryメモ:親要素だけ消すってどうやるんだろう?

Clip to Evernote このエントリーをはてなブックマークに追加
カテゴリ:
jQuery
タグ:
jquery
javascript

親要素だけ消すってどうやるんだろう?

上の図にしたように、子要素を持つ親要素のみを削除したいとき、
jQueryを使って表現するにはどうしたらいいんだろう?
なんてのを悩んで結局できなかった。

とりあえずためしたものをメモエントリーとして書いておく。

2009/02/18修正

できなかった例

一応使用HTML

■HTML

<a href="#damy"><span>ダミーテキスト</span></a>

これにJavaScriptを適応させて、
リンクが外れていたら成功になる。

失敗だと、上のようなままか、もしくは中身が消失する。

当然remove()は中まで消える

■スクリプト

$(function(){
  $('a[href*="damy"]').remove();
});

ちなみに、$('a[@href*="damy"]')の部分はa要素のリンク先のURLで
「damy」の文字を含んでいるリンクを対象とするという指定です。

■プレビュー

.remove()は、指定した要素自体とその子要素をすべて削除するので、
中身もろとも消えてしまうことになる。

replaceWithも同じか

■スクリプト

$(function(){
  $('a[href*="damy"]').replaceWith($(this).html());
});

■プレビュー

これも中身ごと消失。うーむ。
指定のしかたがよくなさそう。

replaceWithの使い方かな?

上記の例だと、要素に直接.replaceWith()をつけてみたけど、
どうもこれだと挙動がおかしい。next()をはずしてhtml()をtext()にしたところ、
全体の文字情報が表示されてしまった。
つまり指定がよくなさそう。
なので、一つずつに適応するようにeachを使ってみる。

■スクリプト

$(function(){
  $('a[href*="damy"]').each(function(){
  	$(this).replaceWith($(this).html());
  });
});

■プレビュー

おっ、消えた!!

親要素だけ消すってどうやるんだろう?

eachを使うようにしないとだめなようだ。
これは応用がききそうなので、覚えておくようにしよう。

◎ 余談

実はこのエントリーを書くまではeachなんて使うこと浮かばずストップ。
ひらめきが足りずに、できないまま悩んでいた。
で、text()なんてのを試したときに、ページ全体のテキストが出てきて
それでひらめいた!いろいろためしてみるもんですね。

この記事へのコメント
毎度どうもです。
innerHTMLでリプレースする方法だと、子・子孫要素に割り当てたイベントなどが消失してしまうので、以下のように子・子孫要素を一旦よけといてから削除するようにしています。

$.removeSelf = function(o){
return o.each(function(idx){
var t=o.eq(idx)
t.after(t.contents())
t.remove()
})
}
$.fn.removeSelf = function(){
return $.removeSelf(this)
}

$('div.tempContainer').removeSelf()

wrapInnerなどで
<div style="position:relative"></div>
とかを一時的に生成した場合、削除する時に使用したりします。
Posted by cyokodog at 2008年11月13日
>cyokodogさん
いつもコメントありがとうございます♪
そのプログラムを試してみたところ、.contents()の動作に驚きました。
remove()を考えずに一部抜粋して考えた時、例えばHTMLが
<div class="hoge"><a href="#"><span>ダミー</span></a></div>
で、スクリプトが
$('.hoge a').each(function(){
$(this).after('テキスト');
});
だとすると、その出力は
<div class="hoge"><a href="#"><span>ダミー</span></a>テキスト</div>
という動作で、これには何も疑問がないのですが、ところが、
$('.hoge a').each(function(){
$(this).after($(this).contents());
});
とすると、この出力結果が、最初僕は
<div class="hoge"><a href="#"><span>ダミー</span></a><span>ダミー</span></div>
と、after()によって中身がコピーされるのかなと思っていましたが、
<div class="hoge"><a href="#"></a><span>ダミー</span></div>
という出力でした。
なるほど、つまり.after($(this).contents())は、thisの中身の移動になるのですね。

えっと、contents()自体が抜きだしになっているのですよね?

・・・と、認識してしまったのですがこれであっていますでしょうか(;^_^A?
Posted by ハム at 2008年11月13日
うーん…jQueryのソースを見た訳ではないので、間違ったことを言ってしまうかもしれませんが、私の解釈としてはafterメソッドの役割は、引数で渡されたオブジェクトを後方に配置するのみで

・引数で渡されたものがDOMツリー上に存在してるオブジェクトなら、結果的にオブジェクトの移動となる

ex1)xxx.after($('#aaa'))
ex2)xxx.after($('#aaa').contents())

contentsメソッドは、DOMツリー上のオブジェクトを掴むものなので、その処理結果をafterに引き渡すということは、結果的に移動になるかと…


・引数で渡されたものがDOMツリー上に存在しないオブジェクトなら、結果的にオブジェクトの追加となる

ex1)xxx.after('div')
ex2)xxx.after('<div/>')
ex3)xxx.after($j('<div/>'))
ex4)xxx.after($j('#aaa').html())

ex1の場合は単なるテキストと解釈され、divというテキスト(ノード)が後方に追加される
ex2も文字列を引数で受け取ってるが、文字列の内容がhtmlのタグを表してるのでelement(ノード)が後方に追加される
ex3は事前にオブジェクト化ものをelement(ノード)として追加してるが、結果的にはex2と同じになる
ex4はhtmlメソッドの処理結果(つまりDOMツリー上に存在するelementのinnerHTML(=text))を渡してるので、ex1やex2と同じパターンになるが、DOMツリー上からもってきてるので複製されたように見える(複製ではないので割り当てられたイベントなどはくっついてこない)

という事ではないでしょうか?(分かりづらい説明ですいません)
Posted by cyokodog at 2008年11月14日
ちょうどjQueryで同様のことを考えていたので、大変助かりました!ありがとうございます。
Posted by ひだか屋 at 2009年10月19日
今はunwrapメソッドがありますね(jQuery1.4以降のようです)。
なんか最近の日付でtweetされているので一応残しておきます。

contentsメソッドは勉強になりました。
Posted by なっしんぐ at 2011年12月05日
コメントを書く
お名前: [必須入力]

メールアドレス: [必須入力]

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック

トップに戻る

×

この広告は90日以上新しい記事の投稿がないブログに表示されております。