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

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

ただいまの
回答率

90.98%

  • JavaScript

    13877questions

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

  • jQuery

    5835questions

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

動的に要素が生成されるたびにclone内容が変わってしまう

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 254

SugiuraY

score 166

1) 当初のHTMLについて、cloneした要素を動的に要素が変化した後でも常に維持していたいのですが
下記のコードではvar copy_div_element1の内容が  $(document).on('change','#range_2',function(){
のたびに動的に生成された要素の影響で変わってしまいます。
私の理解では

$(function(){
var copy_div_element1=$('#select_inside_amount_1 > div').clone();
はHTMLの構造が変わってもcloneはページの読み込み時に一回しか行われないため、
$(document).on('change','#range_2',function(){で何度構造が変わっても
同じcopy_div_element1をappendしてくれるかと思っていたのですが、可変となってしまいます。
これの原因と解決方法がわかる方いらっしゃいますでしょうか?

$(function(){
    var copy_div_element1=$('#select_inside_amount_1 > div').clone();
//ここでコピー

    $(document).on('change','#range_2',function(){
    $('#select_outside_2').toggleClass('shows');

    var sel_2=$('#select_btn_2').find('div').attr('class');

    if(sel_2=="toggle btn btn-primary"){
                   $('#select_inside_amount_1').show("drop", {"direction": "up"}, 500);
   }else if (sel_2=="toggle btn btn-default off")
                   {
                    console.log(copy_div_element1);
                    $('#select_inside_amount_1').hide("drop", {"direction": "up"}, 500);
                    $('#select_inside_amount_2').hide("drop", {"direction": "up"}, 500);
                    $('#select_inside_amount_1 > div').remove('');
                    $('#select_inside_amount_1').append(copy_div_element1);
            //ここで当初cloneした常に同じ内容をappendしたい
                    $('#select_inside_amount_1 > div > div > div').addClass('item_amount_1');
                    $('.ui.dropdown').dropdown();
                    }

    })
  });

2)全く異なる質問になりますが
下記のように、forを使うことで要素を結合させてたいのですがうまくいきません。
もちろんa1+a2でいけるのですが量が多いため、+=でエラーが出ます、文字列結合では+=は
使用できないのでしょうか、、for文でこのようなことはできますでしょうか?

var a1='<div>あ</div>';
var a2='<div>い</div>';
for(var i=1; i<2; i++){
var concat+='a'+i;
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • jun68ykt

    2018/01/13 22:17

    1)について、もし可能であれば、HTMLと必要であれば CSSも含めて、その JS をjsfiddleに上げて頂けると、回答者にとって「何を実現したくて、何が問題なのか」を把握しやすく、また修正したコードを動かして確認できるので有用な回答を得やすくなると思います。

    キャンセル

回答 2

checkベストアンサー

+4

以下の内容は試していません.


1)
変数copy_div_element1に格納された要素を直接DOMに追加しているため, 編集内容がcopy_div_element1内に保持されてしまっています. $('#select_inside_amount_1').appendに渡すjQueryオブジェクトは事前にcopy_div_element1cloneしたものを設定すべきでしょう.

$(function(){
    var copy_div_element1=$('#select_inside_amount_1 > div').clone();
//ここでコピー

    $(document).on('change','#range_2',function(){
    $('#select_outside_2').toggleClass('shows');

    var sel_2=$('#select_btn_2').find('div').attr('class');

    if(sel_2=="toggle btn btn-primary"){
                   $('#select_inside_amount_1').show("drop", {"direction": "up"}, 500);
   }else if (sel_2=="toggle btn btn-default off")
                   {
                    console.log(copy_div_element1);
                    $('#select_inside_amount_1').hide("drop", {"direction": "up"}, 500);
                    $('#select_inside_amount_2').hide("drop", {"direction": "up"}, 500);
                    $('#select_inside_amount_1 > div').remove('');
                    $('#select_inside_amount_1').append(copy_div_element1.clone());//←
            //ここで当初cloneした常に同じ内容をappendしたい
                    $('#select_inside_amount_1 > div > div > div').addClass('item_amount_1');
                    $('.ui.dropdown').dropdown();
                    }

    })
  });

また、いただいた回答でcase1はか解決はしたのですが、なぜ変数に格納したDOMをさらにcloneすることで解決するのかがどうしても理解ができません。。
例えば当初の
var copy_div_element1='<div class="item"><div>'で変更後が
var copy_div_element1='<div class="item"><div>'の場合、
var copy_div_element1='<div class="item"><div>'が格納されるのはdocumentが読み込まれた時点の一回だけかと思ったので、変数に一旦格納することで、DOMを使い回すことができると思いました。
またcloneしたものをまたcloneしたとしても結局、var copy_div_element1が後者に書き換えられてしまえば、それをcloneしてもそのcloneも書き換えられるのではと思ったのですが、実際には思った通りに動作します。
本件の変数の中身の動きとcloneの動きがどうしても理解できないなため、大変恐縮なのですが、少しだけアドバイスを頂けませんでしょうか?
何卒、よろしくお願い申し上げます。

解説

問題が発現するのは2回目以降のcopy_div_element1appendです. 以下はイベントによって発生しうる処理を展開したものです.

//まずはテンプレートとなるノードの初期状態をDOMからcloneして変数に保管
//本来この内容は触ってはいけない内容である!!!
//NOTE:元々のDOMはこの後編集され破棄される
var copy_div_element1=$('#select_inside_amount_1 > div').clone();//(1)

//ここで#select_inside_amount_1に対して何らかの編集
$('#select_inside_amount_1 > div').remove('');//(2)
$('#select_inside_amount_1').append(copy_div_element1);//(3)

//ここで#select_inside_amount_1に対して何らかの編集
$('#select_inside_amount_1 > div').remove('');//(4)
$('#select_inside_amount_1').append(copy_div_element1);//(5)
  • まずあなたはノード#select_inside_amount_1 > divをcloneし, 変数copy_div_element1に格納しました.このcloneはテンプレートを用意するためのものです.
  • 次にノード#select_inside_amount_1 > divに対する編集内容を削除するため, 当該ノードremove(2)しテンプレートのノードをappend(3)しました.
  • もう一度ノード#select_inside_amount_1 > divに対する編集内容を削除するため, 当該ノードremove(4)しテンプレートのノードをappend(5)しました.

さて, ここであなたは(3)でテンプレートのノードcopy_div_element1を直接DOMに追加してしまいました. もちろんこの内容はユーザーによって中身が書き換えられます. つまりこれ以降copy_div_element1の内容をDOMからremoveしようがDOMにappendしようが初期状態には戻らないことになります.

そのため, DOMにappendするノードとして常にcopy_div_element1からcloneしたものを使わなければならないのです. こうすることでテンプレートの中身を操作させずに済みます.

//まずはテンプレートとなるノードの初期状態をDOMからcloneして変数に保管
//NOTE:元々のDOMはこの後編集され破棄される
var copy_div_element1=$('#select_inside_amount_1 > div').clone();//(1)

//ここで#select_inside_amount_1に対して何らかの編集
$('#select_inside_amount_1 > div').remove('');//(2)
//cloneしているので, (1)の内容が保たれる
$('#select_inside_amount_1').append(copy_div_element1.clone());//(3)

//ここで#select_inside_amount_1に対して何らかの編集
$('#select_inside_amount_1 > div').remove('');//(4)
//cloneしているので, (1)の内容が保たれる
$('#select_inside_amount_1').append(copy_div_element1.clone());//(5)

2)
NOTE:
以下は

forを使うことで要素を結合させてたいのですがうまくいきません。

の部分を見落としていました.
従って jun68ykt さんの回答を参考として下さい.


変数宣言部に+=演算子を記述したことが不味いのであって, 「文字列結合では+=は使用できない」わけではありません. 例えば

var a1='<div>あ</div>';
var a2='<div>い</div>';
var concat = '';
for(var i=1; i<2; i++){
  concat += 'a' + i;
}


とすればよいでしょう.

NOTE:エラーメッセージにはその原因が簡潔に記述されています. 英語とは言え典型的なエラーであれば典型的なメッセージが出力されるため, その内容を読めば何が問題かは自ずと明らかとなります.

NOTE:全く異なる質問を一つにまとめるのは質問の再利用・検索性において問題があります. 質問・ソリューションを探す側のユーザーのことも念頭に入れて下さい.

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/13 23:35 編集

    ご回答ありがとうございます。
    まず、自身の質問が再利用、検索される可能性について配慮が欠けておりました。ご指摘ありがとうございます。そのような質問を何度かしてしまったことがあるため、以後注意してまいります。

    また、いただいた回答でcase1はか解決はしたのですが、なぜ変数に格納したDOMをさらにcloneすることで解決するのかがどうしても理解ができません。。
    例えば当初の
    var copy_div_element1='<div class="item"><div>'で変更後が
    var copy_div_element1='<div class="item active"><div>'の場合、

    var copy_div_element1='<div class="item"><div>'が格納されるのはdocumentが読み込まれた時点の一回だけかと思ったので、変数に一旦格納することで、DOMを使い回すことができると思いました。

    反対に変数が書き換えられてしまうのであれば、
    cloneしたものをまたcloneしたとしても結局、var copy_div_element1が後者に書き換えられてしまえば、それをcloneしてもそのcloneも書き換えられるのではと思ったのですが、実際には思った通りに動作します。
    本件の変数の中身の動きとcloneの動きがどうしても理解できないなため、大変恐縮なのですが、少しだけアドバイスを頂けませんでしょうか?
    何卒、よろしくお願い申し上げます。

    キャンセル

  • 2018/01/14 00:14

    直感的には「原本を複写してそこに落書きをしたとして, 何度もやり直し可能とするのであれば, やり直す都度複写の複写が必要になる」わけです. 言葉でわかりにくければ図にしてみたり, 実際に紙を切ったりして試してみて下さい.

    キャンセル

  • 2018/01/14 01:16 編集

    丁寧なご解説を賜り、本当にありがとうございます。
    おそらく変数の実態をDOMに入れてしまうと編集された内容が保存されてしまうため、これを避けるために実態ではなくcloneを入れてあげることで、本体の変数に影響させないと言うことかと感覚で捉えました。
    と言いながらも、腹落ちしない部分もあるので、少し今からじっくり調べながら考えてみたいと思います。

    というのもDOMではなく通常のどんなコードでも以下のようにどのような変数の利用でも
    元の変数に対して、非破壊的に実行されるため、やはり直感的にん?と思う部分があるからです。
    var n =1;
    document.write(n+1);
    console.log(n);//もちろん2ではなく1を返す
    DocumentObject上は編集されたノードがもしかした破壊的に影響を与えているのかな?という観点でしらべてみます。
    本当に遅い時間までご協力をいただけたことに御礼をさせていただきます。
    よろしくお願い申し上げます。

    キャンセル

  • 2018/01/14 08:31

    var n =1;
    document.write(n+1);
    console.log(n);//もちろん2ではなく1を返す
    ↑変数nに対する操作が行われていないのですから自明です.

    一方例えば配列オブジェクトであれば
    var n = [];
    n[0] = 1;
    console.log(n);
    とすれば変数nに代入操作を行っておらずとも, nが参照している配列の内容は変化しえます.

    オブジェクト型とプリミティブ型の違いについて調査されると良いでしょう

    キャンセル

+1

こんにちは。

2) についてのみの回答になります。

'a1' という文字列から、変数 a1の内容を取得し、
'a2' という文字列から、変数 a2の内容を取得し、
これらを結合したいのであれば、
以下のようにします。

var a1 = '<div>あ</div>';
var a2 = '<div>い</div>';

var concat = '';
for(var i = 1; i <= 2; i ++){
    concat += eval('a' + i);
}

console.log(concat); // => <div>あ</div><div>い</div>

追記

eval は強力な関数ですが、濫用するとプログラムが読みにくくなります。
後で結合することが分かっているなら、配列に入れたほうがよいでしょう。
つまり、

var a = [];

a[0] = '<div>あ</div>';
a[1] = '<div>い</div>';
a[2] = '<div>う</div>';


こうしておいて、普通に

var concat = '';
for ( var i=0; i < a.length; i ++ )
    concat += a[i];


とするか、あるいは、reduce を使って

var concat = a.reduce(
    function(html, div) {
        return(html + div);
    });


という書き方もできます。reduce は慣れるといろいろ便利です。
ちなみに上記のコードは、ES6 だと、

const concat = a.reduce((html, div) => html + div);


とシンプルに書けます。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/13 23:17

    コメントありがとうございます。
    あまりevalの使用は避けるべきと習ったのですが、
    このような方法でもできるというのは大変勉強になりました。
    ありがとうございます。

    キャンセル

  • 2018/01/13 23:21

    > あまりevalの使用は避けるべき

    というのは正しいと思います。なので追記を書きました。参考になれば幸いです。

    キャンセル

  • 2018/01/13 23:56

    コメント、重ねて御礼申し上げます。
    恥ずかしながら、reduceメソッドを初めてしりました。早速調べてみたのですが、配列の扱いについて、いろいろなことができそうですね。実践で試して行ってみたいと思います。
    深謝です!

    キャンセル

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

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

関連した質問

同じタグがついた質問を見る

  • JavaScript

    13877questions

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

  • jQuery

    5835questions

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