プログラミング素人のはてなブログ

プログラミングも電気回路も専門外の技術屋の末端が勉強したことや作品をアウトプットするブログ。コードに間違いなど見つけられたら、気軽にコメントください。 C#、Python3、ラズパイなど。

買い物リストに画像を添付できるようにした

Firebaseで運用している買い物リストですが、似たような商品がいろいろある中でわかりにくい、という問題がありました。
そこで、リストに写真を追加できるようにしました。

TL;DR

・データの構造を変更
・画像の保存先はFirestorageを使用
・画像があるときはアップロードした時刻よりファイル名を作成しFirestorageにアップロードする。同時にデータ構造にイメージファイル名をPush。
・リストの読み込み時は、イメージファイル名があるときは、イメージのリンクを作成。

以下、技術的な解説をします。
↓の記事で作ったFirebaseプロジェクトがベースです。
s51517765.hatenadiary.jp

画像のプレビュー

btnFileUploadに、ボタンクリックイベントを登録します。
window.onloadでページ読み込み時に登録されます。

window.onload = function ()
{
    document.getElementById('btnFileUpload').addEventListener('change', handleFileSelect, false);
}

ボタンクリックで画像表示領域imgPreviewAreaformUploadに作成します。

var element = document.createElement("div");
element.id = "imgPreviewArea";
formUpload.append(element);

画像の大きさはCSSで設定しています。

画像表示部コードの全体

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="css.css">
    <title>Document</title>
</head>

<body>
    <div>
        <form name="formUpload">
            <input type="file" id="btnFileUpload" name="files[]">
            <output id="list"></output>
        </form>
    </div>
</body>
<script>
    function handleFileSelect(evt)
    {
        var element = document.createElement("div");
        element.id = "imgPreviewArea";
        formUpload.append(element);

        //https://www.html5rocks.com/ja/tutorials/file/dndfiles/
        imgFile = evt.target.files[0]; // File object

        if (!imgFile.type.match('image.*')) return;
        var reader = new FileReader();
        // Closure to capture the file information.
        reader.onload = (function (theFile)
        {
            return function (e)
            {
                // Render thumbnail.  
                imgPreviewArea.innerHTML = ['<img class="thumb" src="', e.target.result, '" title="', escape(theFile.name), '"/>'].join('');
            };
        })(imgFile);

        // Read in the image file as a data URL.
        reader.readAsDataURL(imgFile);
    }
    window.onload = function ()
    {
        document.getElementById('btnFileUpload').addEventListener('change', handleFileSelect, false);
    };
</script>

</html>

www.html5rocks.com

ボタンクリックで画像をアップロード

画像が読み込まれていたら、アップロードする画像があると判断して、imgUpload()を呼び出します。

function addData()
{
     if (imgID != "NoImage") imgUpload();
}

//ストレージのルートのリファレンスを取得
var storageRef = firebase.storage().ref();

var imgUpload = function (ev)
{
    //ストレージへアップロードするファイルのパスを生成する
    var uploadRef = storageRef.child(imgID);
    uploadRef.put(imgFile);
};

qiita.com

リストの読み込み時に画像も読み込む

データベースのキーを拡張して、imgIDが存在すれば画像を読み込みます。
従来のデータベースにはイメージのキーが無かったので、その辺も考慮して破壊的変更にならないようにしています。
これを入れないと、従来のデータが読み込めなくなります。

if (childData.imgID != undefined && childData.imgID != "" && childData.imgID != "NoImage")
{
   ImgURL(childData.imgID, element, childData.message, cb);
}

リストを読み込むときに画像も読み込みます。
画像はリストからIDを取り出し、ストレージ中の画像を指すURLを取得します。

function ListLoad()
{
	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;
	if (childData.imgID != undefined && childData.imgID != "" && childData.imgID != "NoImage")
	{
	    ImgURL(childData.imgID, element, childData.message, cb);
	}
	else
	{
	    element.innerHTML = childData.message;
	    element.appendChild(cb);
	}
	list1.append(element);
}

function ImgURL(imgID, element, message, cb)
{
    if (imgID == "NoImage") return;

    imgSample = storageRef.child(imgID);
    //thenで戻り値がfunctionの引数に入る
    imgSample.getDownloadURL().then(function (url)
    {
        console.log(url);
        element.innerHTML = message + " <a href =" + url + ">image</a>";
        element.appendChild(cb);
    });
}

まとめ

買い物リストに画像を添付できるようにしました。
ちなみに、画像の削除は実装していないのでリストから削除されてもストレージには残ったままです。
管理画面から削除するという運用をしています。
github.com