jQueryメモ:親要素だけ消すってどうやるんだろう?
上の図にしたように、子要素を持つ親要素のみを削除したいとき、
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>
とかを一時的に生成した場合、削除する時に使用したりします。
いつもコメントありがとうございます♪
そのプログラムを試してみたところ、.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?
・引数で渡されたものが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ツリー上からもってきてるので複製されたように見える(複製ではないので割り当てられたイベントなどはくっついてこない)
という事ではないでしょうか?(分かりづらい説明ですいません)
なんか最近の日付でtweetされているので一応残しておきます。
contentsメソッドは勉強になりました。