チェックボックスを.htmlで動的に変更し、配列を取得すると値が重複するのですが。。。

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,775

noripi

score 28

複数のチェックボックスを任意の順番に並び替えしたのち、チェックがついているものの値を一括取得したいのですが、チェックがついた状態のものの順番を変更すると一括取得した値が重複してしまいます。
対処方法わかる方おりませんでしょうか。

《追記》
チェックボックスのチェックがない状態で順序を変更後、チェックボックスにチェックを入れる場合は問題ないようです。
チェックボックスにチェックが入ったものを順序変更した場合のみ、チェックが入った値が1つ増えます(重複)します。その後はいくら順序を変更しても重複した値を増えません。

$(function(){
        //表示順序を下に変更
        $("#custom-display-post-widget #item li").on("click", ".down", function() {
            var now_index = $(this).closest("li").index() + 1;
            var next_index = $(this).closest("li").next().index() + 1;
            var now_obj = $(this).closest("li").html();
            var next_obj = $(this).closest("li").next().html();
            $("#custom-display-post-widget #display-setting #item ul li:nth-child("+next_index+")").html(now_obj);
            $("#custom-display-post-widget #display-setting #item ul li:nth-child("+now_index+")").html(next_obj);
            $("#custom-display-post-widget #item li input").removeAttr('checked');//追記
            checkVal();
        });

        //表示順序を上に変更
        $("#custom-display-post-widget #item li").on("click", ".up", function() {
            var now_index = $(this).closest("li").index() + 1;
            var prev_index = $(this).closest("li").prev().index() + 1;
            var now_obj = $(this).closest("li").html();
            var prev_obj = $(this).closest("li").prev().html();
            $("#custom-display-post-widget #display-setting #item ul li:nth-child("+prev_index+")").html(now_obj);
            $("#custom-display-post-widget #display-setting #item ul li:nth-child("+now_index+")").html(prev_obj);
            $("#custom-display-post-widget #item li input").removeAttr('checked');//追記
            checkVal();
        });

        //

        //表示設定を取得
        $("#custom-display-post-widget #item li input").live("change", function() {

            //チェックされていた場合
            if($(this).prop('checked')){
                $(this).attr('checked','checked');
            }

            //チェックされていない場合
            if(!$(this).prop('checked')){
                $(this).removeAttr('checked');
            }

            checkVal();
        });

        function checkVal(){
            var checkBox=[];
            // チェックされた値を取得
            $("#custom-display-post-widget #item li input:checked").each(function(){          
                checkBox.push($(this).val());
            });
            //取得した値を input text にセット
            $("#custom-display-post-widget input.display-post-set").val(checkBox);
        }
    });
<div id="display-setting">
                <p>
                <input id="id_display_order" class="display-post-set" name="display_order" type="text" value="" size="30">
                </p>
                <div id="item">
                <span class="title">アイテム:</span>
                <ul>
                    <li><input class="date display-item" type="checkbox" name="date" value="date">date<span class="order"><span class="up"></span><span class="down"></span></span></li>
                    <li><input class="thumbnail display-item" type="checkbox" name="thumbnail" value="thumbnail">thumbnail<span class="order"><span class="up"></span><span class="down"></span></span></li>
                    <li><input class="title display-item" type="checkbox" name="title" value="title">title<span class="order"><span class="up"></span><span class="down"></span></span></li>
                    <li><input class="excerpt display-item" type="checkbox" name="excerpt" value="excerpt">excerpt<span class="order"><span class="up"></span><span class="down"></span></span></li>
                    <li><input class="category display-item" type="checkbox" name="category" value="category">category<span class="order"><span class="up"></span><span class="down"></span></span></li>
                    <li><input class="link display-item" type="checkbox" name="link" value="link">link<span class="order"><span class="up"></span><span class="down"></span></span></li>
                </ul>
                </div>
            </div>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+3

val関数内でcheck配列を初期化してないのが原因ではないでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/10/18 09:49

    ご回答ありがとうございます。
    早速、配列の初期化と同時に念のため関数名と配列名を変更してみましたが、解決しませんでした。。。
    何か処理のタイミングが原因なんでしょうか。。。

    キャンセル

  • 2016/10/18 11:28

    配列を初期化する位置がおかしいです。
    eachの中で初期化すると、配列の初期化と配列への追加を繰り返すことになりますよね。

    キャンセル

+1

初期化位置がおかしいです。

function checkVal(){
    var checkBox = []; //ADD
    // チェックされた値を取得
    $( "#custom-display-post-widget #item li input:checked" ).each( function() {
        // var checkBox = []; // delete
        checkBox.push( $( this ).val() );
    } );
    //取得した値を input text にセット
    $( "#custom-display-post-widget input.display-post-set" ).val( checkBox );
}

動くサンプル:https://jsfiddle.net/crtbe6v1/1/


また、jQuery().liveはver1.9から廃止されていますので、jQuery().onでコーディングするのが良いと思います。

【jQueryのonをliveの代わりに使う場合の書き方 - 無理しない感じ】
http://hogesuke.hateblo.jp/entry/2014/02/04/101641

【jQueryのclickとbindとliveとdelegateとonの違い - Qiita】
http://qiita.com/smzk/items/5eed5a90c4b32ca8b23a

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/10/18 15:45

    ご回答ありがとうございます。
    初期化位置ですが、こちらは私の投稿追記ミスでした。申し訳ありません。

    liveの廃止は知りませんでした。。。
    教えて頂いたサイトを参考にonへ変更しましたが状況は変わりませんでした。
    orz

    キャンセル

  • 2016/10/18 15:52

    「動くサンプル」は御覧になりましたか?その挙動で問題があれば、問題再現の手順を書いてください。

    キャンセル

  • 2016/10/18 16:03

    すみません。「動くサンプル」上の挙動で問題ないです。
    ですが、本番環境では問題が解決できませんでした。
    もう少し調査してみます。

    キャンセル

check解決した方法

0

理由はよくわかりませんが、JavaScriptコード内の「//追記」部分により問題が解消されました。
他のスクリプトとの競合が原因?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/10/19 13:25

    今更ですがattr、removeAttrでchecked属性を操作いないと正常動作しないとなると、
    DOMが汚染されているのかもしれません。
    通常はpropでcheckedを操作した場合、属性値も書き換わっているはずなのでattrでの操作は必要ないはずです。

    エレメントの移動はhtmlを書き換えるのではなくinsertAfter、insertBefore等を使用されるとよいかもしれません。

    http://cly7796.net/wp/javascript/to-insert-or-move-by-operating-the-dom/

    キャンセル

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

  • ただいまの回答率 90.22%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる