はじめに
こんにちは。javascript初学者のたけしです。
javascriptで自分なりにtodoリストを作成したので、備忘録とアウトプットを兼ねて投稿します。
全てのコードを自分でググりながら書いたので、わかりにくい箇所やもっと良いやり方があるかもしれませんが私と同じような初学者の方の参考になれば幸いです。
##作成の流れ
まずはtodoリストに追加したい機能を洗い出していきました。
機能の洗い出しの方法は前回私が投稿した記事を参考にして頂ければと思います。
「JavaScript初学者の私がFizzBuzzアプリを自作して学んだこと」
今回私が洗い出した機能
・入力された値の読み取り
・追加ボタンを押すことで入力された内容を追加する
・追加した内容にボタンを追加する(作業中・完了ボタンのことです)
・作業中・完了をボタンを押すことで切り替える
・ラジオボタンを押すことでリストの表示を切り替える
・削除ボタンを押すことでリストから削除する
・入力したら中身のテキストがクリアされる
・何も入力していない状態では機能が作動しない
以上となります。
最初から全てを洗い出していた訳ではありませんが、作っている最中にこれもつけよみたいな感じで継ぎ足していくのもいいと思います。
イメージがあるとわかりやすいと思うので、完成品のイメージを載せておきます。
###htmlをまずは書いていく
まずはざっとhtmlで必要なものだけ書いていきました。
参考程度に載せておきます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<h2>新規タスクの追加</h2>
<input type="text" id="newtask">
<button id="add">追加</button>
<ul class="radio">
<li>
<input type="radio" id="r1" name="list" value="1" checked><label for="r1">全て</label>
</li>
<li>
<input type="radio" id="r2" name="list" value="2"><label for="r2">作業中</label>
</li>
<li>
<input type="radio" id="r3" name="list" value="3"><label for="r3">完了</label>
</li>
</ul>
<h1>TODOリスト</h1>
<section>
<ul id="list">
</ul>
</section>
<script src="js/main.js"></script>
</body>
</html>
cssも表示の切替などに必要なので載せておきます。
.radio {
display: flex;
}
.radio li {
list-style: none;
margin-right: 15px;
}
button {
background-color: whitesmoke;
padding: 5px 15px;
}
.wrap {
display: flex;
flex-flow: row;
}
.divoneli {
margin-right: 50px;
}
.btntwo {
margin-right: 20px;
}
.none {
display: none;
}
###JavaScriptを書いていく
htmlで骨組みを作り終わったら早速javascriptを書いていきました。
コードを読みやすくするために最初に全てのコードを載せますが、後から一つずつどういう理由で書いたのか説明していきます。
'use strict';
{
// 値を読み取る
let newtask = document.getElementById('newtask');
// 入力された値をリストに追加する
let add = document.getElementById('add');
add.addEventListener('click', () => {
if (newtask.value !== '') {
// TODOリストに表示する
let list = document.getElementById('list');
// div要素を作成
let wrapper = document.createElement('div');
wrapper.className = 'wrap';
let divone = document.createElement('div');
let divtwo = document.createElement('div');
// 作成した要素に追加 ①
list.appendChild(wrapper);
wrapper.appendChild(divone);
wrapper.appendChild(divtwo);
// li.button要素の作成 ②
let li = document.createElement('li');
li.className = 'divoneli';
let btnone = document.createElement('button');
btnone.innerHTML = '削除';
btnone.className = 'btnone';
let btntwo = document.createElement('button');
btntwo.innerHTML = '作業中';
btntwo.className = 'btntwo';
// ②を①に追加
wrapper.insertBefore(li, divone);
wrapper.insertBefore(btnone, divtwo);
wrapper.insertBefore(btntwo, btnone);
// inputで読み取った値を表示
li.innerHTML = newtask.value;
// 作業中・完了ボタンの切替
btntwo.addEventListener('click', () => {
if (btntwo.innerHTML === '作業中') {
btntwo.innerHTML = '完了';
} else {
btntwo.innerHTML ='作業中';
}
});
// 削除ボタンを押すと削除される
btnone.addEventListener('click', () => {
list.removeChild(wrapper);
});
// チェックボックスの表示の切替
let all = document.getElementById('r1');
let working = document.getElementById('r2');
let done = document.getElementById('r3');
// 作業中
working.addEventListener('click', () => {
if (btntwo.innerHTML !== '作業中') {
wrapper.classList.add('none')
} else {
wrapper.classList.remove('none')
}
});
// 完了
done.addEventListener('click', () => {
if(btntwo.innerHTML !== '完了') {
wrapper.classList.add('none');
} else {
wrapper.classList.remove('none')
}
});
// 全て
all.addEventListener('click', () => {
wrapper.classList.remove('none');
});
document.getElementById('newtask').value = '';
}
});
}
###入力された値を読み取る
まずは入力された値を読み取るための変数を作ります。
let newtask = document.getElementById('newtask');
inputタグからid属性を取得しています。
変数newtask.valueで入力された値を読み取ることができます。
###追加ボタンを押すことで入力された値を追加する
ボタンを押した時に関数を実行して欲しいので、タグのid属性を取得し、addEventListnerを使います。
let add = document.getElementById('add');
add.addEventListener('click', () => {
###入力した値の表示
ボタンを押すことで値を追加していけるようにしたいのですが、その追加した値の横に作業中・完了のボタンを追加したいのでDOMを扱っていきます。
DOMとは簡単に言うと、HTMLをJavaScriptから操作するものです。
DOMの使い方などに関する説明についてはここでは割愛し、私がどのような意図で要素を作っていったのかだけ説明していきます。
私はリストの横にボタンを表示したかったので、flexboxを使うためにdivをdivで囲むようにしました。
// div要素を作成
let wrapper = document.createElement('div');
wrapper.className = 'wrap';
let divone = document.createElement('div');
let divtwo = document.createElement('div');
下のコードで作ったdiv要素にボタンを追加しています。
// 作成した要素に追加 ①
list.appendChild(wrapper);
wrapper.appendChild(divone);
wrapper.appendChild(divtwo);
// li.button要素の作成 ②
let li = document.createElement('li');
li.className = 'divoneli';
let btnone = document.createElement('button');
btnone.innerHTML = '削除';
btnone.className = 'btnone';
let btntwo = document.createElement('button');
btntwo.innerHTML = '作業中';
btntwo.className = 'btntwo';
// ②を①に追加
wrapper.insertBefore(li, divone);
wrapper.insertBefore(btnone, divtwo);
wrapper.insertBefore(btntwo, btnone);
###ボタンの切替
ボタンの切替(作業中・完了)のために再度addEventListenerを使います。
if文を使って、現在のボタンの表示によって、ボタンのhtmlの書き換えをinnerhtmlでしています。
btntwo.addEventListener('click', () => {
if (btntwo.innerHTML === '作業中') {
btntwo.innerHTML = '完了';
} else {
btntwo.innerHTML ='作業中';
}
});
###削除ボタンを押すとリストから削除される
ボタンを押したときにリストから削除したいので、こちらでもaddEventListenerを使い、追加した要素を取り除くことでリストから削除しています。
btnone.addEventListener('click', () => {
list.removeChild(wrapper);
});
###ラジオボタンを押すことでリストの表示を切り替える
ここが一番苦労して色々書いては消してを繰り返してやっと機能を追加できたところです(笑)
まず、ラジオボタンをクリックしたときに関数を実行したいので、ラジオボタンのid属性を取得し、addEventListenerを使っていきます。
ただし、今回のtodoリストではラジオボタンの選択肢が3つあるので、それぞれでaddEventListenerを使いました。
if文でボタン(作業中・完了)のinnerhtmlを調べて、classをつけたり外したりすることで表示を切り替えています。
// チェックボックスの表示の切替
let all = document.getElementById('r1');
let working = document.getElementById('r2');
let done = document.getElementById('r3');
// 作業中
working.addEventListener('click', () => {
if (btntwo.innerHTML !== '作業中') {
wrapper.classList.add('none')
} else {
wrapper.classList.remove('none')
}
});
// 完了
done.addEventListener('click', () => {
if(btntwo.innerHTML !== '完了') {
wrapper.classList.add('none');
} else {
wrapper.classList.remove('none')
}
});
// 全て
all.addEventListener('click', () => {
wrapper.classList.remove('none');
});
###おわりに
ここまで読んで頂きありがとうございました。
読みにくい箇所やわかりにくい箇所などあったと思いますが、少しでも参考になれば幸いです。
長くなってしまいましたが、ここでおわりにしたいと思います。
あ!最後にもっとこうした方がいいよってアドバイスして頂ける方がいらっしゃいましたらぜひお願い致します!