🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
イベントハンドラ

マウスのクリックなどの特定の事象(イベント)が発生した時に実行される処理のことをイベントハンドラと呼びます。

JavaScript

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

Q&A

解決済

1回答

3198閲覧

javascript 同じイベント処理をもつ要素の複製を繰り返したいです

oasis

総合スコア2

イベントハンドラ

マウスのクリックなどの特定の事象(イベント)が発生した時に実行される処理のことをイベントハンドラと呼びます。

JavaScript

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

0グッド

0クリップ

投稿2020/12/20 09:04

編集2020/12/22 15:33

前提・実現したいこと

javascriptで
マウスドラックを用いた家具の配置2Dシミレーション(枠内を指定したフローリング)を実装したいと思っています

発生している問題・エラーメッセージ

同じ家具をフローリングに出力する追加機能を持つボタンを作成している時に

既存の本棚に対して同じイベント処理(枠内のマウスドラック)を
追加した本棚をclone.Nodeも用いて出力することができましたが
(2つまでの出力は成功)

(3つ目を試みると)
もう一度
追加ボタンを押すと本棚は出力されるのですが、
イベント処理(枠内マウスドラック)が追加されず適用されずにドラックができません。

エラーメッセージ

該当のソースコード

javascript ライブラリを使用Jqueryは使用していません ソースコード HTML <div class="menu-card-inner"> <img class="menu-image" src="./images/0fb8a39d38f69ae68fa57ed1edf7b9ec.jpg" alt="家具1"> <h3 class="menu-title">本棚<br> 4800円</h3> <button class ="btn" onclick="document.getElementById('contents1').style.visibility = 'visible';">クリック</button> <button class ="btn" onclick=cloneElement()>追加</button>                     //この追加機能を直したいです <button class ="btn" id="addbuton" onclick=remove()>削除</button> </div> </div> <div class="menu-card"> <div class="menu-card-inner"> <img class="menu-image" src="./images/trend_20150716131537.jpg" alt="家具1"> <h3 class="menu-title">テレビ<br> 27000円</h3> <button class ="btn" onclick="document.getElementById('contents2').style.visibility = 'visible';">クリック</button> <button class ="btn" onclick="cloneElement1();stopclone()">追加</button> </div> </div> <div class="menu-card"> <div class="menu-card-inner"> <img class="menu-image" src="./images/1b71e2b924b8a56374648cb8efdc1958.jpg" alt="家具1"> <h3 class="menu-title">机<br> 3000円 </h3> <button class ="btn" onclick="document.getElementById('contents3').style.visibility = 'visible';">クリック</button> <button class ="btn" onclick=cloneElement2()>追加</button> </div> </div> <div class="menu-card"> <div class="menu-card-inner"> <img class="menu-image" src="./images/471429001.jpg" alt="レモネード"> <h3 class="menu-title">食器棚<br> 8000円</h3> <button class ="btn" onclick="document.getElementById('contents4').style.visibility = 'visible';">クリック</button> <button class ="btn" onclick=cloneElement3()>追加</button> </div> </div> <div class="menu-card"> <div class="menu-card-inner"> <img class="menu-image" src="./images/mv_raffia-1.jpg" alt="カフェラテ"> <h3 class="menu-title">ベット<br> 16000円</h3> <button class ="btn" onclick="document.getElementById('contents5').style.visibility = 'visible';">クリック</button> <button class ="btn" onclick=cloneElement4()>追加</button> </div> </div> //追加しました css .box2{ background-color: rgb(206, 182, 106); float:right; width: 400px; height:470px; margin-right:250px ; background-image:url(../images/depositphotos_22441037-stock-photo-room-interior-vintage-with-white.jpg); } .menu-card { width: 33%; margin-top: 50px; } .menu-card-inner { padding: 10px 10px; background-color: #084d85; border-radius: 7px; box-shadow: 1px 1px 4px #d2d4d6; text-align: center; margin: 0 20px; width: 100px; height: 110px; margin-top: 10px; } .menu-image { width: 50px; height: 50px; margin-bottom: 8px; border-radius: 5px; } .menu-title { margin-bottom: 8px; font-size: 90%; } .menu-text { font-size: 14px; } .menu-card-wrapper { display: flex; flex-wrap: wrap; } h3{ color: white; } h2{ margin-top: px; text-align: center; } .button1{ width: 50px; height: 20px; } .menu-nedan { margin-bottom: 8px; font-size: 90%; } javascript ライブラリは Yahoo! YUI Libraryを使用しています //回答を受けて再び編集しました   協力していただきたけると助かります //ロード YAHOO.util.Event.addListener(window, "load", function(){ //家具の配列データ var kagu =['contents1','contents2','contents3','contents4','contents5'];                  //kagu[0]→ 本棚です var ddObj = new YAHOO.util.DD(kagu[0]); //X軸とY軸の指定 //フローリング規定 X300 Y322 ddObj.setXConstraint(0, 400, 10); ddObj.setYConstraint(0, 400, 10); var ddObj2 = new YAHOO.util.DD(kagu[1]); ddObj2.setXConstraint(0, 400, 10); ddObj2.setYConstraint(0, 400, 10); var ddObj3 = new YAHOO.util.DD(kagu[2]); ddObj3.setXConstraint(0, 400, 10); ddObj3.setYConstraint(0, 400, 10); var ddObj4 = new YAHOO.util.DD(kagu[3]); ddObj4.setXConstraint(0, 400, 10); ddObj4.setYConstraint(0, 400, 10); var ddObj5 = new YAHOO.util.DD(kagu[4]); ddObj5.setXConstraint(0, 400, 10); ddObj5.setYConstraint(0, 400, 10); // 家具の追加オブジャクト }); //家具配列データ var kagu =['contents1','contents2','contents3','contents4','contents5']; //ボタン機能 //スタートボタン function btn(){ document.getElementById(kagu[0]).style.left = "0px"; document.getElementById(kagu[1]).style.left = "80px"; document.getElementById(kagu[2]).style.left = "160px"; document.getElementById(kagu[3]).style.left = "240px"; document.getElementById(kagu[4]).style.left = "320px"; } //商品一覧から画面遷移ボタン function btn0(){ document.getElementById(kagu[0]).style.left = 'visible'; } function btn1(){ document.getElementById(kagu[1]).style.left = "80px"; } function btn2(){ document.getElementById(kagu[2]).style.left = "160px"; } function btn3(){ document.getElementById(kagu[3]).style.left = "240px"; } function btn4(){ document.getElementById(kagu[4]).style.left = "320px"; } // 追加 ☆ 質問する場所 エラーが起こっている場所 複製ボタン YAHOO.util.Event.addLister(window,"load",moveItems) function moveItems(){ //クローンの配列化 //なんかの処理→移動制限 var ddObj = new YAHOO.util.DD("targetID"); ddObj.setXConstraint(0, 322, 10); ddObj.setYConstraint(0, 300, 10); var ddObj7 = new YAHOO.util.DD("clone1"); ddObj7.setXConstraint(0, 322, 10); ddObj7.setYConstraint(0, 300, 10); var ddObj8 = new YAHOO.util.DD("clone2"); ddObj8.setXConstraint(0, 322, 10); ddObj8.setYConstraint(0, 300, 10); var ddObj9 = new YAHOO.util.DD("clone3"); ddObj9.setXConstraint(0, 322, 10); ddObj9.setYConstraint(0, 300, 10); var ddObj10 = new YAHOO.util.DD("clone4"); ddObj10.setXConstraint(0, 322, 10); ddObj10.setYConstraint(0, 300, 10); } // 家具の追加オブジャクト //回答者様に教えてもらったところ function cloneElement(furniture,kaguInd){                /*furnitureは種類として       kaguIndは添え字として配列としてデータを格納するべきなのか?*/        //既存の家具をコピーする                //kagu[0]のcloneを作りたい場合?は具体例があると助かります!          //kagu[0]は本棚です             /*kagu[0]は?となった場合は一番最初のコードに記載している              既存の本棚のデータです              既存の本棚のクローンを作る具体例をよろしくお願いします!*/ const tpl = document.getElementById(kagu[kaguInd]); const clone = tpl.cloneNode(true); const targetIDPrefix = furniture + "clone"; const suffix = document.querySelectorAll('[id^='+targetIDPrefix+']').length; // ~Clone0とか~Clone1みたいに後ろの数字が要素の数に応じて増えていく clone.id = targetIDPrefix + suffix; // idとdisplayの設定 clone.id = furniture+"clone"; clone.class = "sample"; clone.style.left ="0px"; clone.style.display ="block"; //クローンにマウスドラックイベントを追加する clone.addEventListener("drag",function(){ moveItems(this.id); }); //フローリングに出力 base = document.getElementById('box1') base.appendChild(clone); }

試したこと

for文を用いて繰り返しなのかと考え試行錯誤して
クローンの複製のところcloenElementに
for文をつけ足してみたのですが,うまく動きませんでした。

補足情報(FW/ツールのバージョンなど)

投稿者はまだjavascriptを学習し始めた初心者ですので
知識不足なので

お手数ですがよろしくお願いします

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

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

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

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

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

Jon_do

2020/12/20 17:32

html、css、使っているライブラリの名前 を追記するのをおすすめします。
oasis

2020/12/21 09:12

コメントありがとうございます。 追記しました。
k_n_h_r

2020/12/22 05:44

クローンで作った要素のIDがすべて'clone'になっていませんか?
oasis

2020/12/22 06:50

コメントありがとうございます! ここに記載はないですがIDもclone1,clone2,clone3を設定していますので すべての要素のIDがcloneとして設定してはいないです
oasis

2020/12/22 06:53

cloneで作った要素は最初の追加ボタンでは 同じイベント処理(マウスドラック)で動くのですが 二回目追加ボタンでは 画像だけが出力されてマウスドラックできない現状です..
k_n_h_r

2020/12/22 06:59

では本文中の > clone.id = "clone"; この箇所は実際には clone.id = "clone" + i; みたいになっているという認識でよろしいですか?
oasis

2020/12/22 07:14

丁寧にコメント返信ありがとうございます "clone"+i;にはなっていないので しっかりとソースコードを乗せてもらいます 初心者なのでお手数かけてすみませんよろしくお願いします!
k_n_h_r

2020/12/22 07:25

編集後のソース拝見いたしました。 なるほど、追加する家具ごとにclone*となっているわけですね
oasis

2020/12/22 07:39

コメント返信ありがとうございます 本当に初心者ですみません 同じイベント処理(マウスドラック)で動くのですが 二回目追加ボタンでは 画像だけが出力されてマウスドラックできない現状です.. ↑これを解決できるために ソースコードの編集やヒントなどくださると大変助かります!よろしくお願いします!
Jon_do

2020/12/22 16:08

とりあえず、質問するときはhtml、css、Javascriptそれぞれ分けましょう。 じゃないとコピーするのが面倒です。 あと、cssにbox2とありますがこの要素がhtmlに見当たりません。 基本的に質問するときは中途半端なコードではなく 今現在、出来ているところまでを出来る限り再現できているコードを貼り付けるようにしてください。
guest

回答1

0

ベストアンサー

(2つまでの出力は成功)

(3つ目を試みると)

もう一度
追加ボタンを押すと本棚は出力されるのですが、
イベント処理(枠内マウスドラック)が追加されず適用されずにドラックができません。

JavaScript

1function moveItems(){ 2 var ddObj6 = new YAHOO.util.DD("clone"); 3 4 ddObj6.setXConstraint(0, 322, 10); 5 ddObj6.setYConstraint(0, 300, 10); 6 // 以下略

moveItems関数内でidがcloneの要素を指定されていますが、最初に複製されたid=cloneの要素しか取得できていないためかと思われます。
なのでクローンを作るたびに重複しないidの指定が必要になります。
HTMLでのIDの重複が文法違反です。

1つ目はclone0、2つ目はclone1、3つ目はclone2...といった感じですかね。

しかし今回クローンする家具の種類によってcloneの後ろの添え字が入っているので、そこは変更したほうが作りやすいのかな?と思います。
テレビのクローンはteleviClone、机のクローンはtableCloneなど

その時にcloneElementと名のある関数の中身のclone.id=の箇所をすべて修正するのは面倒かと思います。

1つにまとめてしまった方がいいと思います。

JavaScript

1function cloneElement(furniture, kaguInd) { // furnitureは家具の種類、kaguIndはkaguの添え字 2 const tpl = document.getElementById(kagu[kaguInd]); 3 const clone = tpl.cloneNode(true); 4 5 clone.id = furniture + "Clone"; // televiCloneとかtableCloneみたいになる。 6 clone.class = "sample"; 7 clone.style.left = "0px"; 8 clone.style.display = "block"; 9 10 clone.addEventListener("drag", function() { 11 moveItems(this.id); // thisはcloneを表しています。 12 }); 13 14 // フローリングに表示 15 base = document.getElementById('box1'); 16 base.appendChild(clone); 17 18}

一旦これでHTMLのonclickでcloneElement~を呼び出していた部分を
cloneElement('televi', 1)とかcloneElement('table', 2)とかにできるようになるかと思います。
※まだクローンされた要素のidに添え字振ってないので2回目のクローンから動かないです。

ついでにaddEventListenerも変更しています。
addEventListenerの中身のmoveItemsにクローンされた要素のidを引数として渡しています。
※thisについてはご自身で調べてください・・・

引数を渡すようになったことでmoveItems関数も変更することになります。

JavaScript

1function moveItems(targetID) { 2 var ddObj = new YAHOO.util.DD(targetID); 3 4 ddObj.setXConstraint(0, 322, 10); 5 ddObj.setYConstraint(0, 300, 10); 6} 7

targetIDには複製されたクローンのIDが入っているのでこれで問題ないかと思います。
あとは最初に書いたIDの重複の問題を解決するだけです。

JavaScript

1function cloneElement(furniture, kaguInd) { 2 const tpl = document.getElementById(kagu[kaguInd]); 3 const clone = tpl.cloneNode(true); 4 const targetIDPrefix = furniture + "Clone"; 5 const suffix = document.querySelectorAll('[id^='+targetIDPrefix+']').length; 6 7 // ~Clone0とか~Clone1みたいに後ろの数字が要素の数に応じて増えていく 8 clone.id = targetIDPrefix + suffix; 9 // 以下略 10

で、完成かと思います。(HTMLのonclickのcloneElementの引数はご自身で入れてください。)
(clone作った後につけているstyleは全部sampleというクラスに持たせればもうちょっと短くできたりはしますが、長くなるので割愛します。)

動作の確認はしていません!
なにかエラーが出るようであればコメントで教えてください。(誤字脱字等も含めて)
それにもっと可読性高く、スマートにやる方法もいっぱいあると思います。
(教えていただけると嬉しいです)
私もまだまだプログラム初心者の域を脱していないレベルなので、今の私にはこれが限界でした。

投稿2020/12/22 08:44

k_n_h_r

総合スコア58

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

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

oasis

2020/12/22 14:48

返信遅くなりすみません 返信ありがとうございます ぜひやってみます! ありがとうございます!
oasis

2020/12/22 15:22

実際にやってみましたが動きませんでした.. 悔しいのですもう一度教えてください furniture, kaguInd // furnitureは家具の種類、kaguIndはkaguの添え字 これは配列としてデータを格納しておくべきなのでしょうか? 例えば 具体例 kagu[0]→(本棚)これを追加する方法を記載していただきたけると助かります kagu[0] 用いてもう一度おしえてもらえないでしょうか? ソースコードももう一度編集しなおすので 知識不足なため初歩的な質問でわがままですみません! よろしくお願いします!
k_n_h_r

2020/12/23 00:32

> // furnitureは家具の種類、kaguIndはkaguの添え字 > これは配列としてデータを格納しておくべきなのでしょうか? ちょっと質問の意図がわからないのですが編集されたコードのHTMLのonclickイベントのcloneElement()の中に引数は入れていないでしょうか? 私の回答の'以下略'が良くなかったかもしれません。 clone.idにtargetIDPrefix + suffixを代入したのちに下の行でclone.idを上書きしてしまっていると思いますので下の上書いてしまっている行は削除していただいて構いません。 function moveItems()となっていますが、私の回答のやり方で行うならmoveItems(targetID)となります。 > var ddObj = new YAHOO.util.DD("targetID"); このDDに渡すのは文字列のtargetIDではなくmoveItems関数が引数として受け取ったtargetIDなので var ddObj = new YAHOO.util.DD(targetID);とダブルクォートを外してください。 >clone.Nodeも用いて出力することができましたが と質問文中に書いてあったので、質問に記載されているコードの中にないだけでidがbox1になっている要素などは既に存在しておりそこにクローンを表示できていたと思っています。
oasis

2020/12/23 02:41

すみません丁寧にありがとうございます! 協力していただきありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問