連続する要素のみをラップするバージョンのwrapAllはありますか?したがって、この:
<p>foo</p>
<p>foo</p>
<h2>bar</h2>
<p>foo</p>
これに変わります:
<div>
<p>foo</p>
<p>foo</p>
</div>
<h2>bar</h2>
<div>
<p>foo</p>
</div>
これはいつ実行されますか?
$('p').wrapAll2('<div />')
これを行う1つの方法は次のとおりです。
$(function(){
var cWrap=$('<div />');
$('p').each(function(){
var o = $(this).next('p').length;
$(this).replaceWith(cWrap).appendTo(cWrap);
if (!o) cWrap=$('<div />');
});
});
または本格的なプラグインとして:
(function($){
$.fn.wrapAll2 = function(wrapper){
if (!this.length) return this;
var cWrap=$(wrapper),
tag = this.get(0).nodeName.toLowerCase();
return this.each(function(){
var o = $(this).next(tag).length;
$(this).replaceWith(cWrap).appendTo(cWrap);
if (!o) cWrap = $(wrapper);
});
};
})(jQuery);
$(function(){
$('p').wrapAll2('<div />');
});
*同種のコレクション(少なくともすべて同じノードタイプ)で呼び出すことを前提としていることに注意してください
実験的に、jQueryの内部を調べたところ、コレクションの作成に使用されるセレクターが格納されていることがわかりました。[少なくともインスタンス化に関して]、それを念頭に置いて、少なくとも現在のバージョンのjQueryで動作し、任意のセレクターを受け入れる別のバージョンを作成しました。
(function($) {
$.fn.wrapAll2 = function(wrapper) {
if (!this.length) return this;
var wrap = $(wrapper),
sel = this.selector || this.get(0).nodeName.toLowerCase();
return this.each(function() {
var more = $(this).next(sel).length;
console.log(this,more);
$(this).replaceWith(wrap).appendTo(wrap);
if (!more) wrap = $(wrapper);
});
}
})(jQuery);
$(function() {
$('p, span').wrapAll2('<div />');
});
ただし、次のようなものでは機能しません。$('p').add('span').wrapAll2('<div />');
Shadの優れた答えについて説明し、ノードタイプだけでなく、任意のセレクターを使用するコードを作成しました。
(function($){
$.wrapAll2 = function(sel, wrapSel) {
var wrap = $(wrapSel);
$(sel).each(function() {
var more = $(this).next(sel).length;
$(this).replaceWith(wrap).appendTo(wrap);
if (!more) wrap = $(wrapSel);
});
};
})(jQuery);
$(function() {
$.wrapAll2('p', '<div/>');
});
セレクター文字列の代わりにJQueryオブジェクトを渡すことができればいいのですが、これは私の目的には十分に機能します。
これは、任意のjQueryセレクターで機能し、コレクションが変更された場合にも機能する一般的なソリューションです。たとえば、add()またはandSelf()またはnot():を使用します。
(function($){
$.fn.wrapConsecutive = function(wrapper){
if (!this.length) return this;
var thisRun,prev;
this.each(function(){
if (!prev || $(this).prev()[0]!=prev){
if (thisRun) thisRun.wrapAll(wrapper);
thisRun = $();
}
thisRun = thisRun.add(this);
prev = this;
});
if (thisRun) thisRun.wrapAll(wrapper);
return this;
};
})(jQuery);
操作されたコレクションに基づいて動作することを示すデモ:http://jsfiddle.net/wujX6/1/
唯一の注意点は、連続する要素の間にあるテキストノードがラッピングに含まれないことです。したがって、たとえば、$('p').wrapConsecutive('<div/>')このHTMLを呼び出すと次のようになります。
<p>foo</p>
<p>bar</b>
jim
<p>baz</p>
jar
…結果は次のようになります。
<div><p>foo</p><p>bar</b><p>baz</p></div>
jim
jar