質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

4回答

2705閲覧

【jQuery】prevAllを使って条件付きで取得したい

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

0クリップ

投稿2016/04/18 08:58

javascript

1 2$(this).parent('.news-wrap').prevAll('p').prependTo(this,'.news-wrap'); 3

上記のようなコードを書いております。

HTMLは下記のようになっております。

html

1 2<h3>タイトル</h3> 3<p>テキストテキストテキストテキスト</p> 4<p>テキストテキストテキストテキスト</p> 5<p>テキストテキストテキストテキスト</p> 6<p>テキストテキストテキストテキスト</p> 7<div class="news-wrap"></div> 8 9<table> 10<!-- テーブルの記述があります。 --> 11</table> 12 13<p>テキストテキストテキストテキスト</p> 14<p>テキストテキストテキストテキスト</p> 15<div class="news-wrap"></div> 16

そして理想の結果が下記の通りです。

html

1 2<h3>タイトル</h3> 3 4<div class="news-wrap"> 5<p>テキストテキストテキストテキスト</p> 6<p>テキストテキストテキストテキスト</p> 7<p>テキストテキストテキストテキスト</p> 8<p>テキストテキストテキストテキスト</p> 9</div> 10 11<table> 12<!-- テーブルの記述があります。 --> 13</table> 14 15<div class="news-wrap"> 16<p>テキストテキストテキストテキスト</p> 17<p>テキストテキストテキストテキスト</p> 18</div> 19

.news-wrap の前にあるpタグ群を .news-wrapへ入れたいという意味になります。

しかし、prevだとpタグ一つしか、、 prevAllだと 記事内のすべてのpタグが入ってしまうので希望通りの結果になりません。

prevAllで「pタグ以外のタグが見つかったらストップ」という条件は可能なのでしょうか?
prevAllを使用しないやり方も考えられますでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

こんな時こそ :has() の出番ですが、「0回以上の繰り返し」がないのでスマートにかけないのが難点ですね。
(XPath を使えばエレガントに書けそうですが…)

HTML

1<h3>タイトル</h3> 2<p>text1-1</p> 3<p>text1-2</p> 4<p>text1-3</p> 5<p>text1-4</p> 6<div class="news-wrap"></div> 7 8<table> 9 <tbody> 10 <tr> 11 <td>A1</td> 12 <td>A2</td> 13 <td>A3</td> 14 </tr> 15 </tbody> 16</table> 17 18<p>text2-1</p> 19<p>text2-2</p> 20<div class="news-wrap"></div> 21<script> 22'use strict'; 23jQuery('.news-wrap').each(function (i, news) { 24 news = jQuery(news); 25 news.append(news.prevAll('p:has(+.news-wrap),p:has(+p+.news-wrap),p:has(+p+p+.news-wrap),p:has(+p+p+p+.news-wrap)').reverse()); 26// news.append(news.prevAll('p:has(+:scope),p:has(+p+:scope),p:has(+p+p+:scope),p:has(+p+p+p+:scope)').reverse()); // Selectors Level 4 的には scope: を使うべきだが、jQuery は未対応 27}); 28</script>

上記コードでは p:has(+.news-wrap) のようにセレクタを書いていますが、この書き方は前方にある別の .news-wrap にもマッチします。
前方から処理する関係で不正な一致はしませんが、本質的には p:has(+:scope) であるべきです。


素直に書けば、次のようなコードでしょうか。

JavaScript

1'use strict'; 2jQuery('.news-wrap').each(function (i, news) { 3 var p = [], 4 element = news = jQuery(news); 5 6 while ((element = element.prev('p')) && element.length > 0) { 7 p.push(element); 8 } 9 10 news.append(p.reverse()); 11});

Re: palus さん

投稿2016/04/18 15:30

think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/04/18 15:39

凄いです。 こんなスマートにかけるんですね! whileの使い方がとても勉強になりました。 ありがとうございます!
guest

0

普通に次のようなコードでよいのではないでしょうか(うちではうまくいきました)。

javasctipt

1$(function() { 2 $('.news-wrap').each(function() { 3 $($(this).prevAll('p').get().reverse()).prependTo($(this)); 4 }) 5});

$( ... .get().reverse()) としているのは、.prevAll() で持ってきた p タグの順番が逆順になっていたので、一度 get() でラップ集合から普通の配列に変換し、それを reverse() で逆順にしたうえで $() でまたラップ集合に戻す、というのをやっています。
$('.news-wrap') にたいして each() で次々にアクセスして前に出てくる p タグを自分の配下に入れていくわけですが、次の .news-wrap において prevAllp タグを集めようとしたとき、その前の .news-wrap の前にあった p タグについてはもうすでに .news-wrap の配下に収まっているので、.news-wrap以降のp` タグしか集まらないことになります。

投稿2016/04/18 13:49

unau

総合スコア2468

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

特に理由がないなら無理してjQueryですべて記述するよりもhtmlの記述を変えてしまったほうが手っ取り早いと思います。

<div>タグで囲んでしまえばそれで済みますね。

投稿2016/04/18 13:55

realizerS

総合スコア265

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

javascript

1$('.news-wrap:first').prevAll('p:parent:not(".news-wrap")')

これなら「news-wrap」要素の前にあって親要素が「news-wrap」でない「p」要素を引っ張ってこれるので、

javascript

1$('.news-wrap').each(function(x, e){$(e).prevAll('p:parent:not(".news-wrap")').prependTo($(e));})

のようにしてやればうまくいくんじゃないかと。

投稿2016/04/18 09:59

tkturbo

総合スコア5572

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問