TODOアプリの作成の準備
- 下記の構造でファイルを作成
TODO
├── index.html
├── index.js
└── style.css
HTMLで構造を作成する(マークアップ)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TODOアプリ</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div>
<input placeholder="TODOを入力">
<button>追加</button>
</div>
<div>
<p>予定のTODO</p>
<ul>
<li>
<div>
<p>勉強会</p>
<button>完了</button>
<button>削除</button>
</div>
</li>
</ul>
</div>
<div>
<p>完了したTODO</p>
<ul>
<li>
<div>
<p>飲み会</p>
<button>戻す</button>
</div>
</li>
</ul>
</div>
<script src="./index.js"></script>
</body>
</html>
CSSでスタイリング
- まずは
index.html
にclass
を付与
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TODOアプリ</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div class="input-area">
<input placeholder="TODOを入力">
<button>追加</button>
</div>
<div class="incomplete-area">
<p class="title">予定のTODO</p>
<ul>
<li>
<div class="list-row">
<p class="todo-item">勉強会</p>
<button>完了</button>
<button>削除</button>
</div>
</li>
<li>
<div class="list-row">
<p class="todo-item">勉強会</p>
<button>完了</button>
<button>削除</button>
</div>
</li>
</ul>
</div>
<div class="complete-area">
<p class="title">完了したTODO</p>
<ul>
<li>
<div class="list-row">
<p class="todo-item">飲み会</p>
<button>戻す</button>
</div>
</li>
<li>
<div class="list-row">
<p class="todo-item">飲み会</p>
<button>戻す</button>
</div>
</li>
</ul>
</div>
<script src="./index.js"></script>
</body>
</html>
-
styles.css
を編集
body {
font-family: sans-serif;
color: #666;
}
input {
border-radius: 8px;
border: none;
padding: 6px 16px;
}
button {
border-radius: 8px;
border: none;
padding: 4px 16px;
margin: 0px 2px;
}
button:hover {
background-color: #79a8a9;
color: #fff;
cursor: pointer;
}
.input-area {
background-color: #c6e5d9;
width: 400px;
height: 30px;
padding: 8px;
margin: 8px;
border-radius: 8px;
}
.incomplete-area {
border: 2px solid #aacfd0;
width: 400px;
min-height: 200px;
padding: 8px;
margin: 8px;
border-radius: 8px;
}
.complete-area {
border: 2px solid #aacfd0;
width: 400px;
min-height: 200px;
padding: 8px;
margin: 8px;
border-radius: 8px;
background-color: #c9dede;
}
.title {
text-align: center;
margin-top: 0;
font-weight: bold;
}
.list-row {
display: flex;
align-items: center;
}
.todo-item {
margin: 6px;
}
タスクの追加機能を実装していく
index.html
を編集
-
追加
ボタンにid
を付与 (id="add-button")
<!-- 省略 -->
<body>
<div class="input-area">
<input placeholder="TODOを入力">
<button id="add-button">追加</button>
</div>
<!-- 省略 -->
</body>
<!-- 省略 -->
index.js
を編集
-
id="add-button"
のある追加
ボタンをクリックしたらアラートがでるようにする。(onClickAdd関数が動作するかどうかの確認)
'use strict';
const onClickAdd = () => {
alert();
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
追加
ボタンをクリックしてアラートがでるか試してみる。
-
TODOを入力して
追加
ボタンをクリックするとアラートに追加したTODOが表示されるか試してみる(onClickAdd関数の実行時)。 -
class="input-area"
のinput
にid="add-text"
を付与する。
index.html
を編集
<!-- 省略 -->
<body>
<div class="input-area">
<input id="add-text" placeholder="TODOを入力">
<button id="add-button">追加</button>
</div>
<!-- 省略 -->
</body>
<!-- 省略 -->
index.js
を編集
'use strict';
const onClickAdd = () => {
// 入力したTODOを const inputText に格納
const inputText = document.getElementById('add-text').value;
alert(inputText);
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
何か入力して 追加
ボタン押下時にアラートテキストが出力されるか確認。
- 追加後は テキストボックスにテキストが残らないようにするため、
value
を空にする(初期化)。
index.js
を編集
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
// 追加した後にテキストボックスを空白にして初期化する
document.getElementById('add-text').value = '';
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
-
index.js
にli
タグを生成する。
index.js
を編集
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
document.getElementById('add-text').value = '';
// liタグの生成
const li = document.createElement("li");
console.log(li); // TODO追加後に生成されているかどうか確認
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
TODO追加後はコンソールを確認
<li></li>
- 続いて
div
タグの生成
index.js
に追加
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
document.getElementById('add-text').value = '';
const li = document.createElement("li");
// divタグの生成
const div = document.createElement("div");
console.log(div);
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
同じくコンソールを確認
<div></div>
-
div
タグにclass="list-row"
を付ける
index.js
を編集
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
document.getElementById('add-text').value = '';
const li = document.createElement("li");
const div = document.createElement("div");
div.className = "list-row"; // divにclass="list-row"を付ける
console.log(div);
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
<div class="list-row"></div>
-
p
タグを生成 -
p
タグにはtodo-item
クラスを付ける -
p
タグには追加されたTODOが入るようにする(定数inputText
に追加するTODOが入る)
index.js
を編集
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
document.getElementById('add-text').value = '';
const li = document.createElement("li");
const div = document.createElement("div");
div.className = "list-row";
// pタグの生成
const p = document.createElement("p");
// pタグにclass="todo-item"を付ける
p.className = "todo-item";
// pタグに追加されたTODOを入れる
p.innerText = inputText;
console.log(p);
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
<p class="todo-item">hoge</p>
-
<div class="list-row">
の子要素に<p class="todo-item"></p>
を配置する。
index.js
を編集
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
document.getElementById('add-text').value = '';
const li = document.createElement("li");
const div = document.createElement("div");
div.className = "list-row";
const p = document.createElement("p");
p.className = "todo-item";
p.innerText = inputText;
// divタグの子要素にpタグを配置
div.appendChild(p);
console.log(div);
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
<div class="list-row">
<p class="todo-item">hoge</p>
</div>
-
li
タグの子要素に<div class="list-row>
を配置する
index.js
を編集
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
document.getElementById('add-text').value = '';
const li = document.createElement("li");
const div = document.createElement("div");
div.className = "list-row";
const p = document.createElement("p");
p.className = "todo-item";
p.innerText = inputText;
div.appendChild(p);
// liタグの子要素にdivを配置
li.appendChild(div);
console.log(li);
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
<li>
<div class="list-row">
<p class="todo-item">hoge</p>
</div>
</li>
-
incomplete-area
内のul
タグにid="incomplete-list"
を付与する
index.html
を編集
<!-- 省略 -->
<div class="incomplete-area">
<p class="title">予定のTODO</p>
<ul id="incomplete-list"> <!-- id="incomplete-list"の付与 -->
<li>
<div class="list-row">
<p class="todo-item">勉強会</p>
<button>完了</button>
<button>削除</button>
</div>
</li>
<li>
<div class="list-row">
<p class="todo-item">勉強会</p>
<button>完了</button>
<button>削除</button>
</div>
</li>
</ul>
</div>
<!-- 以下省略 -->
-
<ul id="incomlete-list">
の子要素にli
タグを配置する(未完了リストに追加)。
index.js
を編集
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
document.getElementById('add-text').value = '';
const li = document.createElement("li");
const div = document.createElement("div");
div.className = "list-row";
const p = document.createElement("p");
p.className = "todo-item";
p.innerText = inputText;
div.appendChild(p);
li.appendChild(div);
// idがincomlete-listの子要素にliタグを入れる(未完了リストに追加)
document.getElementById("incomplete-list").appendChild(li);
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
これで、ブラウザに追加したTODOが表示される。
TODOの完了ボタンと削除ボタンの生成
- 完了ボタンの生成
index.js
を編集
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
document.getElementById('add-text').value = '';
const li = document.createElement("li");
const div = document.createElement("div");
div.className = "list-row";
const p = document.createElement("p");
p.className = "todo-item";
p.innerText = inputText;
// button(完了)ボタンの生成
const completeButton = document.createElement("button");
completeButton.innerText = "完了";
console.log(completeButton);
div.appendChild(p);
li.appendChild(div);
document.getElementById("incomplete-list").appendChild(li);
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
<button>完了</button>
- 削除ボタンの生成
index.js
を編集
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
document.getElementById('add-text').value = '';
const li = document.createElement("li");
const div = document.createElement("div");
div.className = "list-row";
const p = document.createElement("p");
p.className = "todo-item";
p.innerText = inputText;
const completeButton = document.createElement("button");
completeButton.innerText = "完了";
// button(削除)ボタンの生成
const deleteButton = document.createElement("button");
deleteButton.innerText = "削除";
console.log(deleteButton);
div.appendChild(p);
li.appendChild(div);
document.getElementById("incomplete-list").appendChild(li);
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
<button>削除</button>
-
div
タグ(incomplete-list内) の子要素に完了
ボタンと削除
ボタンを配置する。
index.js
を編集
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
document.getElementById('add-text').value = '';
const li = document.createElement("li");
const div = document.createElement("div");
div.className = "list-row";
const p = document.createElement("p");
p.className = "todo-item";
p.innerText = inputText;
const completeButton = document.createElement("button");
completeButton.innerText = "完了";
const deleteButton = document.createElement("button");
deleteButton.innerText = "削除";
// 順番通りに。。。
div.appendChild(p);
div.appendChild(completeButton); // 完了ボタンをdivの子要素に配置
div.appendChild(deleteButton); // 削除ボタンをdivの子要素に配置
li.appendChild(div);
document.getElementById("incomplete-list").appendChild(li);
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
これで何かTodo追加時に完了
ボタンと削除
ボタンがブラウザで表示される。
TODOの削除機能を作成
-
削除
ボタンと完了
ボタンにaddEventListener
の適用
index.js
を編集
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
document.getElementById('add-text').value = '';
const li = document.createElement("li");
const div = document.createElement("div");
div.className = "list-row";
const p = document.createElement("p");
p.className = "todo-item";
p.innerText = inputText;
const completeButton = document.createElement("button");
completeButton.innerText = "完了";
// addEventListenerの適用
completeButton.addEventListener('click', () => {
alert("完了"); // 完了ボタン押下時の処理
});
const deleteButton = document.createElement("button");
deleteButton.innerText = "削除";
deleteButton.addEventListener('click', () => {
alert("削除"); // 削除ボタンを押下時の処理
});
div.appendChild(p);
div.appendChild(completeButton);
div.appendChild(deleteButton);
li.appendChild(div);
document.getElementById("incomplete-list").appendChild(li);
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
完了
ボタン及び削除
ボタンをクリックするとアラートがでる(テスト)。
- TODOを削除する際は、
li
タグから削除されるようにするclosest
を使用すると良い。
(削除ボタンの親にあるli
タグから拾う)
index.js
を編集
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
document.getElementById('add-text').value = '';
const li = document.createElement("li");
const div = document.createElement("div");
div.className = "list-row";
const p = document.createElement("p");
p.className = "todo-item";
p.innerText = inputText;
const completeButton = document.createElement("button");
completeButton.innerText = "完了";
completeButton.addEventListener('click', () => {
alert("完了");
});
const deleteButton = document.createElement("button");
deleteButton.innerText = "削除";
deleteButton.addEventListener('click', () => {
// 削除ボタンの親にあるliから要素を拾う
// deleteTargetには削除する要素が入っている
const deleteTarget = deleteButton.closest("li");
console.log(deleteTarget);
});
div.appendChild(p);
div.appendChild(completeButton);
div.appendChild(deleteButton);
li.appendChild(div);
document.getElementById("incomplete-list").appendChild(li);
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
下記が削除したい要素になる
<li>
<div class="list-row">
<p class="todo-item">hoge</p>
<button>完了</button>
</div>
</li>
index.js
を編集
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
document.getElementById('add-text').value = '';
const li = document.createElement("li");
const div = document.createElement("div");
div.className = "list-row";
const p = document.createElement("p");
p.className = "todo-item";
p.innerText = inputText;
const completeButton = document.createElement("button");
completeButton.innerText = "完了";
completeButton.addEventListener('click', () => {
alert("完了");
});
const deleteButton = document.createElement("button");
deleteButton.innerText = "削除";
deleteButton.addEventListener('click', () => {
const deleteTarget = deleteButton.closest("li");
// deleteTargetは<ul id="incomplete-list">の子要素になるため removeChildメソッドにdeleteTargetを指定して上げればよい
document.getElementById('incomplete-list').removeChild(deleteTarget);
});
div.appendChild(p);
div.appendChild(completeButton);
div.appendChild(deleteButton);
li.appendChild(div);
document.getElementById("incomplete-list").appendChild(li);
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
これでTODOは削除可能になる。
TODOの完了機能を作成
-
完了
ボタン押下時のプロセス
-
完了
ボタン押下するとcomplete-area
の方へ移動するようになるので、その要素を選択するようにする。 -
削除
ボタンが削除される
(nextElementSibling
メソッドを使い完了
ボタン要素の次に続く兄弟要素ノードを選択できる。つまり、ボタンの直後に存在するHTML要素を取得して、それをremove
メソッドで削除
ボタンを削除できる) -
完了
ボタンが削除される
(単純にcompleteButton
をremove
メソッドを使って削除すればよい)
完了
ボタンを押下時に削除
ボタンが消えるようにする
index.js
を編集
// 省略
const completeButton = document.createElement("button");
completeButton.innerText = "完了";
completeButton.addEventListener('click', () => {
// completeエリアに移動する要素を選択
const moveTarget = completeButton.closest("li");
// 完了ボタンの兄弟要素の削除ボタンを選択し、削除する
completeButton.nextElementSibling.remove();
// 完了ボタンを削除
completeButton.remove();
});
// 以下省略
これで完了
ボタンを押下すると削除
ボタンと完了
ボタンは削除される。
完了
ボタン押下後に戻す
ボタンが追加されるようにする
-
moveTarget
の要素の初めの子要素(div
)の子要素に戻す
ボタンを追加するようにするにはfirstElementChild
メソッドとappendChild
メソッドを繋げるようにする。
index.js
を編集
// 省略
const completeButton = document.createElement("button");
completeButton.innerText = "完了";
completeButton.addEventListener('click', () => {
const moveTarget = completeButton.closest("li");
completeButton.nextElementSibling.remove();
completeButton.remove();
// ボタン要素の作成
const backButton = document.createElement("button");
// ボタン要素にテキスト '戻す'を設定
backButton.innerText = "戻す";
// moveTarget(li要素)の子要素(div)のさらに子要素に'戻す'ボタンを追加
moveTarget.firstElementChild.appendChild(backButton);
});
// 以下省略
これで完了
ボタンを押下すると 戻す
ボタンが追加される
完了したTODOエリア(complete-area)に移動する
-
html
のcomplete-area
のul
タグにid="complete-list"
を付与する。 -
moveTarget
を<ul id="complete-list">
の子要素に配置する。
<!-- 省略 -->
<div class="complete-area">
<p class="title">完了したTODO</p>
<ul id="complete-list"> <!-- id="complete-list"を付与 -->
<li>
<div class="list-row">
<p class="todo-item">飲み会</p>
<button>戻す</button>
</div>
</li>
<li>
<div class="list-row">
<p class="todo-item">飲み会</p>
<button>戻す</button>
</div>
</li>
</ul>
</div>
<!-- 以下省略 -->
-
moveTarget
をid="complete-list"
の子要素に移動
index.js
を編集
// 省略
const completeButton = document.createElement("button");
completeButton.innerText = "完了";
completeButton.addEventListener('click', () => {
const moveTarget = completeButton.closest("li");
completeButton.nextElementSibling.remove();
completeButton.remove();
const backButton = document.createElement("button");
backButton.innerText = "戻す";
moveTarget.firstElementChild.appendChild(backButton);
// complete-listの子要素に moveTargetを移動
document.getElementById("complete-list").appendChild(moveTarget);
});
// 以下省略
これで 完了
ボタンを押下すると完了したTODOのリストに移動する
完了したTODOを予定のTODOへ戻す機能の実装
-
createIncompleteTodo
関数を作成して渡された引数を基に未完了のTODOを作成する機能を実装します。 -
下記の
index.js
の 下記のコードの部分をcreateImcompleteTodo
関数の中に移動します。 -
onClickAdd
関数の中の 定数inputText
をcreateIncompleteTodo
に送るようにしなくてはならないので、onClickAdd
関数の中にcreateIncompleteTodo
関数を実行させる記述が必要になります。
// 下記の部分のコードをcreateImcompleteTodo関数を作成して、その中に移動する
const li = document.createElement("li");
const div = document.createElement("div");
div.className = "list-row";
const p = document.createElement("p");
p.className = "todo-item";
p.innerText = inputText;
const completeButton = document.createElement("button");
completeButton.innerText = "完了";
completeButton.addEventListener('click', () => {
const moveTarget = completeButton.closest("li");
completeButton.nextElementSibling.remove();
completeButton.remove();
const backButton = document.createElement("button");
backButton.innerText = "戻す";
moveTarget.firstElementChild.appendChild(backButton);
document.getElementById("complete-list").appendChild(moveTarget);
});
const deleteButton = document.createElement("button");
deleteButton.innerText = "削除";
deleteButton.addEventListener('click', () => {
const deleteTarget = deleteButton.closest("li");
document.getElementById('incomplete-list').removeChild(deleteTarget);
});
div.appendChild(p);
div.appendChild(completeButton);
div.appendChild(deleteButton);
li.appendChild(div);
document.getElementById("incomplete-list").appendChild(li);
index.js
を編集
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
document.getElementById('add-text').value = '';
// inputTextをcreateIncompleteTodo関数に送る
createIncompleteTodo(inputText);
}
// 渡された引数を基に未完了のTODOを作成する関数
const createIncompleteTodo = (todo) => {
// ここから移動してきたコード
const li = document.createElement("li");
const div = document.createElement("div");
div.className = "list-row";
const p = document.createElement("p");
p.className = "todo-item";
// inputTextはtodoの引数に入ってくるので todo に変更する
p.innerText = todo;
const completeButton = document.createElement("button");
completeButton.innerText = "完了";
completeButton.addEventListener('click', () => {
const moveTarget = completeButton.closest("li");
completeButton.nextElementSibling.remove();
completeButton.remove();
const backButton = document.createElement("button");
backButton.innerText = "戻す";
moveTarget.firstElementChild.appendChild(backButton);
document.getElementById("complete-list").appendChild(moveTarget);
});
const deleteButton = document.createElement("button");
deleteButton.innerText = "削除";
deleteButton.addEventListener('click', () => {
const deleteTarget = deleteButton.closest("li");
document.getElementById('incomplete-list').removeChild(deleteTarget);
});
div.appendChild(p);
div.appendChild(completeButton);
div.appendChild(deleteButton);
li.appendChild(div);
document.getElementById("incomplete-list").appendChild(li);
// ここまで
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
-
戻す
ボタンをクリックした時のaddEventListener
を追加します。
index.js
を編集
'use strict';
const onClickAdd = () => {
const inputText = document.getElementById('add-text').value;
document.getElementById('add-text').value = '';
createIncompleteTodo(inputText);
}
const createIncompleteTodo = (todo) => {
const li = document.createElement("li");
const div = document.createElement("div");
div.className = "list-row";
const p = document.createElement("p");
p.className = "todo-item";
p.innerText = todo;
const completeButton = document.createElement("button");
completeButton.innerText = "完了";
completeButton.addEventListener('click', () => {
const moveTarget = completeButton.closest("li");
completeButton.nextElementSibling.remove();
completeButton.remove();
const backButton = document.createElement("button");
backButton.innerText = "戻す";
// 戻すボタンのイベントリスナーを追加
backButton.addEventListener("click", () => {
alert();
});
moveTarget.firstElementChild.appendChild(backButton);
document.getElementById("complete-list").appendChild(moveTarget);
});
const deleteButton = document.createElement("button");
deleteButton.innerText = "削除";
deleteButton.addEventListener('click', () => {
const deleteTarget = deleteButton.closest("li");
document.getElementById('incomplete-list').removeChild(deleteTarget);
});
div.appendChild(p);
div.appendChild(completeButton);
div.appendChild(deleteButton);
li.appendChild(div);
document.getElementById("incomplete-list").appendChild(li);
}
document.getElementById('add-button').addEventListener('click', onClickAdd);
-
戻す
ボタンのイベントリスナーの中の処理内容
-
previousElementSibling
メソッドを使ってbuckButton
の一個手前に要素(pタグになる)を参照してinnerText
メソッドでテキストだけを取得する。 -
createIncompleteTodo
関数の引数にそのテキストを入れるようにして実行させる
(予定のTODOのリストに追加される) - まだ
戻す
ボタンを押下しても完了したTODOに残ってるのでそれを削除するようにする
index.js
を編集
// 省略
backButton.addEventListener("click", () => {
// backbutton.previousElementSiblingはbuckButtonの一個手前に要素(pタグになる)を参照してinnerTextでテキストだけを取得する
const todoText = backButton.previousElementSibling.innerText;
// createIncompleteTodoの引数にtodoTextを入れて実行
createIncompleteTodo(todoText);
// 完了したTODOに戻したTODOが残ってしまうので削除する
backButton.closest("li").remove();
});
// 以下省略
以上で 戻す機能の実装は終了です。
後は以下のように index.html
の li
要素ノードを消しておけばOKです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TODOアプリ</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div class="input-area">
<input id="add-text" placeholder="TODOを入力">
<button id="add-button">追加</button>
</div>
<div class="incomplete-area">
<p class="title">予定のTODO</p>
<ul id="incomplete-list">
</ul>
</div>
<div class="complete-area">
<p class="title">完了したTODO</p>
<ul id="complete-list">
</ul>
</div>
<script src="./index.js"></script>
</body>
</html>
JavaScriptだけでこのようなアプリを作成するとなるとこんなに複雑になるのですね。
仕組みはよく理解できました。