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

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

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

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

jQuery

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

Q&A

解決済

3回答

2959閲覧

[全て選択]ボタンクリック時にappendでundefinedが出力される

takepieee

総合スコア686

JavaScript

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

jQuery

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

0グッド

0クリップ

投稿2017/09/07 03:40

編集2017/09/07 05:14

現在アコーディオン内にcheckboxが並び、アコーディオンヘッドに「全て選択」があるフォームを作っています。

html

1<div class="panel"> 2<div class="panel-head"> 3 <h4>路線名</h4> 4 <div class="check-right"> 5 <label><input class="checkall" type="checkbox">全て選択</label> 6 </div> 7</div> 8<div class="panel-body"> 9 <div class="col-md-3"><label><input name="station[]" data-lab="駅1" value="1133401" type="checkbox">駅1</label></div> 10 <div class="col-md-3"><label><input name="station[]" data-lab="駅2" value="1133402" type="checkbox">駅2</label></div> 11 <div class="col-md-3"><label><input name="station[]" data-lab="駅3" value="1133403" type="checkbox">駅3</label></div> 12 <div class="col-md-3"><label><input name="station[]" data-lab="駅4" value="1133404" type="checkbox">駅4</label></div> 13</div> 14 15<div id="choose_station" class="clearfix"> 16 <h4>選択した駅</h4> 17 <p></p> 18</div>

HTMLは上記簡単に書きましたが、少々手抜きもあり・・実際はBootstrapを使ってコーディングしています。

要件として
・普通に駅のチェックボックスをチェックした場合は#choose_station > pに値を入れていく
・全て選択をチェックした場合は.panel-body内のチェックボックスを全てチェックした上でその駅名を#choose_station > pに値を入れていく
・普通に駅のチェックボックスのチェックを外した場合は、その駅だけ#choose_station > pから外す
・全て選択のチェックを外した場合は.panel-body内のチェックボックスを全てオフにし、#choose_station > pの値を削除する
としています。

jacascript

1//通常チェック 2$('.panel-body [type="checkbox"]').on('click',function(){ 3 var labelval = '<span>' + $(this).data('lab') + '</span>'; 4 if($(this).prop('checked')) { 5 $('#choose_station p').append(labelval); 6 } else { 7 var txt = $('#choose_area p').html(); 8 $('#choose_station p').html(txt.replace(labelval,'')); 9 } 10}); 11 12//全て選択 13$('.checkall').on('click',function(){ 14 var items = $(this).parents('.panel').children('.panel-body').find('input[type="checkbox"]'); 15 if($(this).is(':checked')) { 16 $(items).prop('checked', true); 17 for (var i=0; i<$(items).length; i++) { 18 var labelval = '<span>' + $(items).eq(i).data('lab') + '</span>'; 19 if ($('#choose_station p').html().indexOf($(items).eq(i).data('lab')) != -1) { 20 } else { 21 $('#choose_station p').append(labelval); 22 } 23 } 24 } else { 25 $(items).prop('checked', false); 26 for (var i=0; i<$(items).length; i++) { 27 var labelval = '<span>' + $(items).eq(i).data('lab') + '</span>'; 28 if ($('#choose_station p').html().indexOf($(items).eq(i).data('lab')) != -1) { 29 var txt = $('#choose_station p').html(); 30 $('#choose_station p').html(txt.replace(labelval,'')); 31 } 32 } 33 } 34});

この状態で基本うまくいきます。
ただし、アコーディオンを2段階(路線→駅)ではなく3段階(路線会社→路線→駅、panel-body内に同じpanelが存在する感じです)にした場合、「全て選択」をクリックすると
undefiled 駅1 駅2 駅3 駅4
という内容が#choose_station内に表示されます。
コード的に$(items).eq(i).data('lab')を<span>で囲っているのですが、ご丁寧に<span>undefined</span>になっていました。

全て選択をチェックした場合のforループ内にconsole.log($(items).eq(i).data('lab'));を入れると、正常に駅1~駅4が出力されています。
if (typeof $(items).eq(i).data('lab') !== "undefined")
で弾いてもundefinedが入ってきます。

どこでそれが入ってきて何が出力されているのか分からず・・ご質問させていただきました。
console.logでは駅1~駅4を返すのに、appendするとundefinedを返してしまうのか。
$(items).lengthは4なのになぜundefinedを含めて5周しているのか・

何卒ご教授の程お願い致します。

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

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

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

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

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

Lhankor_Mhy

2017/09/07 04:18

ご提示のコードでは再現しませんでしたので、ここに含まれていない部分に原因があるかと思います。不具合の性質上、clickイベントに原因があるのではないかな、と思いました。
takepieee

2017/09/07 04:50

ありがとうございます。実際のhtml系はbootstrapのアコーディオンを使っています。実際上記の階層だと問題はないのですが、panel-body内にpanelがある感じ(その場合内側のpanel内だけに全て選択があるイメージ)ですとうまく動かないのです・・
Lhankor_Mhy

2017/09/07 05:04

とすると、$('.panel-body [type="checkbox"]') は、子アコーディオン内の '.panel-head [type="checkbox"]' も含むのではありませんか? お試しください。
takepieee

2017/09/07 05:10

孫のcollapseにしか全て選択チェックはない状態なので、試しに.parent().parent()で階層指定しましたが、それでも結果は変わりませんでした。なにより疑問なのはconsole.logで正しい結果をループ出来ているのにappendで埋め込んだ途端にundefinedが出力されることですね・・
Lhankor_Mhy

2017/09/07 05:34

いえ、そうではなくて、通常チェックイベントは、子アコーディオン内の '.panel-head [type="checkbox"]'をクリックしたときにも動作するのでは、ということです。ですから試しに、通常チェックイベント内でログをとってみてください、ということです。
Lhankor_Mhy

2017/09/07 05:35

あー、この文脈で言うと「孫アコーディオン内の '.panel-head [type="checkbox"]'」になるんでしょうか?まあとにかくお試しください。
takepieee

2017/09/07 06:01

ご指摘ご指導誠にありがとうございました。無事解決致しました。
guest

回答3

0

ベストアンサー

参考までに

javascript

1$(function(){ 2 $('.checkall').on('change',function(){ 3 var flg=$(this).prop('checked'); 4 $(this).closest('.panel').find('.panel-body input[type="checkbox"]').prop('checked',flg).first().trigger('change'); 5 }); 6 $('.panel .panel-body input[type="checkbox"]').on('change',function(){ 7 var l1=$(this).closest('.panel').find('.panel-body input[type="checkbox"]').length; 8 var l2=$(this).closest('.panel').find('.panel-body input[type="checkbox"]:checked').length; 9 $(this).closest('.panel').find('.checkall').prop('checked',l1==l2); 10 var str=""; 11 $(this).closest('.panel').find('.panel-body input[type="checkbox"]:checked').each(function(){ 12 str+=(str==""?"":" ")+$(this).data('lab'); 13 }); 14 $('#choose_station p').html(str); 15 }); 16}); 17

追記

よくよく考えたら、チェックない数が0ならという考え方の方がラクですね

var flg=$(this).closest('.panel').find('.panel-body').find('input[type="checkbox"]:not(:checked)').length==0; $(this).closest('.panel').find('.checkall').prop('checked',flg);

投稿2017/09/07 05:26

編集2017/09/07 06:00
yambejp

総合スコア114777

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

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

takepieee

2017/09/07 05:55

細かい所までご配慮を頂き、更に簡潔なコードに驚きました。 動きとしては完璧でした。本当にありがとうございました。
yambejp

2017/09/07 06:00

一応ちょっとだけ修正箇所追記しておきました ロジック的にはさほどかわりありません
takepieee

2017/09/07 06:13

ありがとうございます。ただそれだとpanel-body内のチェックがない状態で全選択チェックしたら強制的にチェックが外れそうですが・・
yambejp

2017/09/07 06:18

あれ?そうですか? 修正箇所を明示してなかったのでうまく伝わってないかもしれません var l1=..;var l2=..;$(this).closest... の3行が追記した2行におきかわるイメージです
takepieee

2017/09/07 06:21

ああ、申し訳ありません。文体的に最初の.checkallのonchangeかと思っていました。 それはそうですね・・
guest

0

僕も再現性がなかったので書き直しました。

考え方は

  • ひとつひとつの状態を取るのではなくて、何か動作をするたびに全体時の状態を取得して反映
  • チェックボックスは押した段階でstatusが変わるので、反映の関数を呼ぶだけ

html

1<input type="checkbox" id="jsCheckAll"/>全部 2<input type="checkbox" class="jsCheck" data-name="駅1"/>駅1 3<input type="checkbox" class="jsCheck" data-name="駅2"/>駅2 4<input type="checkbox" class="jsCheck" data-name="駅3"/>駅3 5<input type="checkbox" class="jsCheck" data-name="駅4"/>駅4 6<input type="checkbox" class="jsCheck" data-name="駅5"/>駅5 7<input type="checkbox" class="jsCheck" data-name="駅5"/>駅5 8 9<div id="jsShowArea"></div>

js

1var $checkAll = $('#jsCheckAll'); 2var $checkboxes = $('.jsCheck'); 3var $jsShowArea = $('#jsShowArea'); 4 5// チェックボックス全体からチェック済みだけを取得して書き出す 6var showCheckedStations = function(){ 7 var chosenTexts = [] 8 $checkboxes.each(function(){ 9 if($(this).prop('checked')){ 10 chosenTexts.push($(this).attr('data-name')) 11 } 12 }) 13 $jsShowArea.text(chosenTexts.join(',')) 14 console.log(chosenTexts) 15} 16 17// 全選択をクリックしたら、全選択の状態をすべてに反映する 18$('#jsCheckAll').on('change', function(){ 19 var isAllChecked = $(this).prop('checked'); 20 $checkboxes.each(function(){ 21 $(this).prop('checked', isAllChecked) 22 }) 23 showCheckedStations() 24}) 25 26// ひとつひとつのチェックボックスを押すと、状態は既に変わっているので反映するだけ 27$checkboxes.on('change', function(){ 28 showCheckedStations() 29})

サンプルもどうぞ! 上記コードの動くやつ

また、直接関係はありませんが、undefinedの比較は以下では通らないかと。

js

1if (typeof $(items).eq(i).data('lab') !== "undefined")

なので以下のように修正した方がいいと思います!

js

1if (typeof $(items).eq(i).data('lab') != "undefined") 2// or 3if (typeof $(items).eq(i).data('lab') !== undefined) 4 5// さらに厳格にすると 6if (typeof $(items).eq(i).data('lab') !== void 0)

よろしければどうぞ!

投稿2017/09/07 05:20

編集2017/09/07 05:21
MasakazuFukami

総合スコア1869

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

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

takepieee

2017/09/07 05:45

ありがとうございます。$jsShowArea.text(chosenTexts.join(','));で出力した場合うまく動きました。 console.logでも正常に値を取得して配列化しています。 そこで上記の部分だけ私が書いたようにforで回した所、同じようにundefinedが出ました・・appendでしょうか、問題は。 typeの比較文ありがとうございます。本当ですね。クオートで囲ってました。
guest

0

再現しないコードなので気になった点を。

$(this).parents('.panel')

複数取っていますが、closest('.panel')ではだめでしょうか?

.find('input[type="checkbox"]')

必ずdata-lab属性が必要であれば、ここで.find('input[type="checkbox"][data-lab]')としておいたほうがいいかもしれません。
ないものが見つかればundefinedになります。

html()で取得した文字列と比較(indexOfやreplace)しているのが気になります。想定しているものがそのまま取れるとは限りません。

投稿2017/09/07 04:28

x_x

総合スコア13749

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

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

takepieee

2017/09/07 05:00

指定方法についてご指摘を頂きありがとうございます。 先に駅をチェック→その後全て選択をクリック、の対策として「一致したデータがあったら追加しない」為にindexOfで一致確認をしました。逆にチェックを外した場合は一致した文字列を削除するためにreplaceを使いました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問