遅刻の「言い訳」選手権

1.ダブルクリックするとテキストエリアの要素が作成される(複数作成可能)
2.作成したテキストエリアを右クリックするとメニューが表示される
3.文字の大きさメニューの上にカーソルを置くと文字の大きさメニューが表示される
4.↑をクリックするとテキストボックスの数字を大きくなりに伴い、テキストボックスに記入した文字が大きくなる

問題点:文字の大きさメニューのイベントが最初に作成したテキストボックスにしか適用されない

解決したいこと:作成した要素ごとに文字の大きさメニューが適用されるようにしたい(
        全体でまとめて適用されるのではなく要素ごとに個別に適用される様にしたい

宜しくお願い致します。

<style>
#test {
position: absolute;
top: 50%;
left: 50%;
transform: translateY(-50%) translateX(-50%);
background-color: sandybrown;
width: 70%;
height: 80%;
margin: 0 auto;

}

#book-design {
margin: 0 auto;
background-color: salmon;
width: 85%;
height: 100%;
}

.canvas-parent {
width: 40%;
height: 100%;
background-color:rgb(247, 245, 232);
background-image:
linear-gradient(transparent 97%, rgb(230, 206, 71) 0%);
background-repeat: repeat;
background-size: 10px 30px;
position: relative;
}

.child {
position: absolute;
width: 25%;
height: 3%;

ul {
list-style: none;
display: flex;
justify-content: flex-end;
}

#reset, #prevpage, #nextpage {
cursor: pointer;
background-color: rgb(240, 166, 20);
margin: 10px 0 10px 10px;
padding: 10px;
width: 7%;
text-align: center;
font-weight: bolder;
text-shadow: 2px 5px 5px black;
}

/* 次のページ、前のページhober */
#prevpage:hover, #nextpage:hover {
border-bottom: solid 5px #a7902c;
border-right: solid 5px #a7902c;
}

.menu {
position: absolute;
width: 150px;
background-color:rgb(243, 243, 132);
text-align: center;
display: none;
left: 650px;

}

.button {
background-color: rgb(135, 238, 115);
padding: 0 10px;
margin: 10px;
}

.menu-font {
position: absolute;
background-color: rgb(231, 135, 175);
border: 1px solid black;
width: 130px;
padding: 2px;
margin-left: 30px;
display: none;
left: 770px;
}

.input-font {
width: 40px;
margin: 0 30px 0 10px;
text-align: right;
}
</style>

<script>

const doubleClick = (e) => {
obj.elm = document.createElement('textarea');
$(function() {$('textarea').autosize();});
obj.elm.classList.add('child');
const combine = obj.elm;

combine.onchange = () => {
if(combine.value !== "") {
combine.style.backgroundColor = 'transparent';
combine.style.border = 'none';
} else {
combine.style.backgroundColor = 'white';
combine.style.border = 'solid';
combine.style.borderWidth = 'thin';
}
}
canvas.appendChild(obj.elm);
obj.setPos(e);
obj.elm = null;
};

const contextMenu = (e) => {
const rightclick = document.querySelector('.menu');
let t = e.target;
if(t.nodeName != 'TEXTAREA' || !t.classList.contains('child')) return;
rightclick.style.display = "block";
}

function setEvent(elm, evt, func) {
elm.addEventListener(evt, func);
}

setEvent(canvas, 'dblclick', doubleClick);
setEvent(canvas, 'contextmenu', contextMenu);


var fontS = document.querySelector('.size');
var fontMenu = document.querySelector('.menu-font');
var inputFont = document.querySelector('.input-font');
//child.style.fontSize = Number(inputFont.value) + 'px';

fontS.onmousemove = () => {
fontMenu.style.display = "block";
}

var fontUp = document.querySelector('.up-arrow');

fontUp.onclick = () => {
if(inputFont.value >= 64) {
alert('64以上の数値は入力できません')
return;
}
inputFont.value = Number(inputFont.value) + 1;
const child = document.querySelector('.child');
child.style.fontSize = Number(inputFont.value) + 'px';
console.log(child);
}

文字数のため以下省略
<body>
<div id="test">
</div>
<ul class="menu">
<li class="size button">文字の大きさ</li>
<li class="color button">文字の色</li>
<li class="bgcolor button">背景色</li>
<li class="angle button">角度</li>
</div>
</body>
</html>

A 回答 (2件)

No1です。



>今回は、複数の要素(クラス名の違う)に同じイベントを付加します。
クラス名や要素は直接には関係ありません。
どこか勘違いなさっているようです。
その要素でイベントが発生するか否か、バブリングするイベントであるかどうかが関係しているだけです。

クラスや要素は、処理上の利便性から利用しているだけですし、一つの要素は複数のクラスを持てますので、同じ処理の対象には同じクラスを設定しておくなどの方が何かと便利なはずと思います。
(わざと、面倒で複雑にしたいのであるのなら別ですけれど)
まとめて処理ができないと言うのなら、No1の(1)に挙げたように、それぞれの要素にイベントを設定すればすむ話と思います。

なお、「動かないスクリプトだけ」を見せられても何もわかりません。
(というか、読む気にはなりません)
以下は、イベントをまとめて設定する際のご参考にでもなれば。
(この方法であれば、後から要素を追加してもイベントを取得できます)
※ 動作するスクリプトではありますが、仮に、この例のスクリプト部分だけを見せられても上述の意味は伝わらないだろうと思いますけれど・・・。

<!DOCTYPE HTML>
<html lang="ja">
<head><title>Sample</title></head>
<body>

<div id="target">
<span>hogehoge</span>
<p>fugafuga</p>
<div>piyopiyo</div>
</div>

<script>
document.getElementById('target').addEventListener('click', e=>{
let t = e.target;
alert(`タグ名:${t.tagName}\n内 容:${t.textContent}`);
});
</script>
</body>
</html>
    • good
    • 0

こんにちは



以前にも同じ内容のご質問をなさっていたと記憶していますが、回答は同様です。

方法としては、
1)新規生成した要素には、生成時にイベントを設定する
2)対象要素群の祖先要素にイベント処理を設定しておいて、
  各要素の処理に対応できる記述法にしておく
のどちらかになると思います。

ご質問文の、
>要素ごとにイベントが発生させたい
の文面通りであるなら、前者になるのかもしれませんが、対象要素が多いようであれば、後者の方法が簡単ではないかと思います。
https://oshiete.goo.ne.jp/qa/12198408.html


ご質問には関係ありませんが、クリックイベント処理の中に
>$(function() { ~~
とありますけれど、それって順序としておかしくないですか?
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

前回は同じ要素(同じ名前の要素複数)に複数のイベントを付加しました。
今回は、複数の要素(クラス名の違う)に同じイベントを付加します。

今までは作成した要素(テキストエリア)にイベントを付加しましたが、
今回のように別の要素(文字の大きさメニュー)から、
作成した要素(テキストエリア)にイベントを付加する方法がわかりません。

下記の様にonclickイベントをすると同時に作成した(し終えた)別の要素にもイベントが付加されるにはどうしたら宜しいでしょうか?

流れ:
・ダブルクリック→要素の作成
・作成した要素を右クリック→メニューの表示(文字の大きさメニュー)
・文字の大きさメニュークリック→文字を大きくする
・作成した要素の文字が大きくなる

var inputFont = document.querySelector('.input-font');
var fontUp = document.querySelector('.up-arrow');

fontUp.onclick = () => {
if(inputFont.value >= 64) {
alert('64以上の数値は入力できません')
return;
}
inputFont.value = Number(inputFont.value) + 1;

canvas.oncontextMenu = (e) => {
var t = event.target;
if(t.nodeName('TEXTEREA') || !t.classList.contains('child')) return;
obj.elm = join;
join.style.fontSize = Number(inputFont.value) + 'px';
}
}

宜しくお願い致します。

お礼日時:2021/03/10 13:56

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報