うちは共働きなので、買い物は帰りが早いほうが買い出しをすることが多いですが、例えば洗面所周りは、モノの消費を妻のほうが把握していることが多いのでこれらを共有する仕組みを作りたかった、というところから始まりました。
Firebaseなら無料で作れそうなので、FirebaseとJavaScriptを合わせて勉強しながら作ってみました。
完成イメージ。
要件定義
・夫婦で共有できること。・無料で使えること。
・Androidでもiphoneでも使えること。
・入手済みのものを保存できること。
上の3つはFirebaseを使う時点で成立します。
4つ目は「欲しいものリスト」と「入手済みリスト」を作ることで実現しました。
html
htmlの本文はタイトル、入力ボックス、ボタンなどとリストul
です。リストは名前を付けるために、 form name="form1”
で囲みます。
<body> <h1>買い物リスト</h1> <div> <p> <div><input type="text" name="" id="message" placeholder="品物を入力して追加"></div> <div><input type="button" value="追加" id="btnUpload" onclick="addData()"></div> </p> <div><input type="button" value="再読み込み" id="btnReload" onclick="ListLoad()"></div> </div> <h3>欲しいものリスト</h3> <form name="form1"> <ul id="List1"></ul> </form> <div><input type="button" value="入手完了" id="btnDone" onclick="done()"></div> <h3>入手済みリスト</h3> <form name="form2"> <ul id="List2"></ul> </form> <div><input type="button" value="削除" id="btnDelete" onclick="deleteItem()"></div> </body>
css
簡単にスタイルシートをコピペで作成。最低限の文字の大きさの指定だけです。/* css checkbox01 */ input[type=checkbox] { width: 20px; height: 20px; vertical-align: middle; } input[type="text"] { width: 300px; height: 20px; } html { font-size: 20px; } h1 { font-size: 40px; } h2 { font-size: 20px; }
このほかに、htmlのhead
には、文字コードとスマホ表示用の設定とcssの読み込みを設定します。
<meta http-equiv="content-type" charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"><!-- スマホ用の表示拡大 --> <link rel="stylesheet" type="text/css" href="css.css">
JavaScript
Firebaseの初期化は管理画面のSettingをコピーします。<script src="https://www.gstatic.com/firebasejs/5.8.6/firebase.js"></script> <script> // Your web app's Firebase configuration var firebaseConfig = { apiKey: "*************", authDomain: "*************", databaseURL: "*************", projectId: "*************", storageBucket: "", messagingSenderId: "*************", appId: "*************" }; // Initialize Firebase firebase.initializeApp(firebaseConfig);
これ以降、要素を追加、要素を削除、画面に表示されるリストの更新、などの関数を作成します。
初めてJavaScriptを触って、はまったところを少し解説します。
JavaScriptは基本文法をQiitaで流れてきた↓でざっと学習したうえで取り組んでいます。
ja.javascript.info
欲しいものリストに追加するときにすでに登録されているモノとの重複を確認するのに、「ローカルに保持した配列をループで確認して一致するものを探す」という方法を使いました。JavaScriptではobj in subject
のようなメソッドがないらしいです。本当か?
要素と一致するものがあるかどうかは、インデックスが0以上になるかどうかで確認します。
if (subject.indexOf(message) >= 0) { //if (obj in subject)のようなメソッドが無い alert("重複しています。") }
リストの中でチェックボックスの状態を確認するには、form
で範囲を決めてあげてelements[i]
で確認します。
ここで、iをチェックボックスの数を数えて範囲指定をしようとしたら、要素数1のときになぜかundefined
となってうまくいかなかないという問題がありました。
チェックボックス(リストの要素)の数を別にカウントitemCount
として持たせることで解決しました。
// i番目のチェックボックスがチェックされているかを判定 if (document.form1.elements[i].checked) { let object_done = document.form1.elements[i].value; }
サーバー上の要素を削除するには、キーを指定してあげる必要があります。
コーダーからすると、要素の名前?中身と一致するもの、という考え方をしますが、要素が一致するオブジェクトを探してそのキーで指定する必要があります。
var childData = childSnapshot.val().message; if (childData) { database1.child(childSnapshot.key).remove(); // .keyでIDを取得 }
JavaScriptでの日付の取得の仕方は基本ではありますが一応書いておきます。"月" が+1
必要です。
var today = new Date(); //日付 let date = today.getMonth() + 1 + "/" + today.getDate()
チェックボックスのついたリストの作成は、一度リストの中を空にしてからサーバー上の要素にforEach
でアクセスし、append
します。
pushするときに重複を確認するためにローカルの配列subject
を用意してサーバーにアクセスしなくてもいいようにしてみました。
cb.value
はチェックされた要素を確認するときに使っています。実際に表示される文字はelement.innerHTML
で設定します。
function ListLoad() { deleteAllElement() var list1 = document.getElementById("List1"); database1.on("value", function (snapshot) { snapshot.forEach(function (childSnapshot) { var childData = childSnapshot.val(); var element = document.createElement("li"); subject.push(childData.message); //リストの中身を配列に追加し保持、重複確認のため //チェックボックスの追加 var cb = document.createElement("input");//チェックを作成 cb.type = "checkbox"; cb.name = "cb" cb.value = childData.message; element.innerHTML = childData.message; cb.textContent = element.innerHTML; element.appendChild(cb); list1.append(element); }); });
ページ読み込み時の動作はwindow.onload
で指定します。
window.onload = function () { ListLoad(); };
まとめ
これで、一通りのFirebaseのリアルタイムデータベースが使えるようになったと思います。アイデア次第でいろいろ出来そうです。
github.com