tamuraです。

Googleスプレッドシートで忘年会の景品のリクエストを受け付けていたのですが、
スマートフォンからだと入力がしにくいようで、なかなか集まりません。

Firebaseを使ってHTMLでリクエスト受け付けるものを作ってみました。


プロジェクト作成まで

https://firebase.google.com/

右上のコンソールへ移動を押します。
 

fb001

新規プロジェクトを作成します。
 

fb002

プロジェクト名と国/地域を入力します。
 

fb003

できました。

fb004

気になる料金ですが、左下にプランが出ているのでそれでわかります。 今は Spark という Free プランです

fb005

データベースの作成

メニューから Database を選択します。

既存のセキュリティルールではユーザの認証が必要です

とでるので、認証が必要ない状態にしてしまいます。

ルールというタブを開くと読み書きに関する設定が出てきます。

fb006

これを true に変えてやることで誰でも読み書きできるようになります。

fb007

セキュリティルールが公開対象として定義されているため、誰でもデータベースの読み取りや書き込みを行えます

とありますが、上等です。

HTMLの作成

Overview画面から ウェブアプリにFirebaseを追加 を押すとJavaScriptが出てきます。

fb009
fb010

この初期値が入ったJavaScriptを使います。

データベースの使い方

基本的にドキュメントを見るとわかりやすく書いてあります。(日本語で!)

https://firebase.google.com/docs/database/web/start

var database = firebase.database();

これでデータベースを使えるようになります。

書き込み

今回は追記なので追記のやり方について書きます。 (追記以外は本家のドキュメントを見てください。日本語でわかりやすく書いてあります!)

https://firebase.google.com/docs/database/web/save-data

var newPostKey = database.ref().child('items').push().key,
    updates = {};
updates['items/' + newPostKey] = {
  name: '宝くじ10枚',
  price: '3000'
};
database.ref().update(updates);

まず、push()を使ってデータのリストに追加します。 keyで追加したデータの一意なIDを取得します。

updatesというオブジェクトに今取得したIDを使ってデータをセットします。

updates['items/' + newPostKey] = {
  name: '宝くじ10枚',
  price: '3000'
};

これは

updates = {
  'items/' + newPostKey: {
    name: '宝くじ10枚',
    price: '3000'
  }
}

と同じ(なはず)です。

ほかにセットしたいデータがあればこのタイミングでオブジェクトに突っ込んでおけます。

最後に、update()でデータを一気に更新します。

すばらしい。

読み込み

これも非常にわかりやすいドキュメントが用意されています。 今回は追加しかないので簡単です。

https://firebase.google.com/docs/database/web/retrieve-data

database.ref('items').on('child_added', function (snapshot) {
  var item = snapshot.val();
  $('#items').append(item.name + ':' + item.price);
});

これで追加されたタイミングで自動で更新してくれます。 最初にアクセスしたときもちゃんと反応してデータを取得してくれます。

便利。

ホスティング

作ったらデプロイです。 Firebaseはホスティングもやってくれます。SSLです。

npm install -g firebase-tools
npm login
npm init
npm deploy

でFirebaseにデプロイできます。 node.jsを入れていない人はこのタイミングで入れると良いです。

カスタムドメイン

CNAMEを使うことでカスタムドメインを使うことができます。 その際に、 Authentication の ログイン方法 タブにある OAuthリダイレクトドメイン に運用する予定のカスタムドメインを追加しておかないとデータの読み書きができなくなります。ご注意。

fb011

まとめ

できあがったソースはこんな感じです。

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  <title>忘年会景品アンケート</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  </head>
<body>
<div class="container-fluid">

<h2>忘年会景品アンケート</h2>

  <div>
    <input id="name" placeholder="商品名(必須)" required><br>
    <input id="price" placeholder="値段"><br>
    <input id="url" type="url" placeholder="商品URL(あれば)"><br>
    <textarea id="message" placeholder="あついコメント(必須)" required></textarea>
    <br>
    <button id="send">投稿</button>
  </div>

  <br>

  <table id="items" class="table table-striped table-bordered">
    <tr>
      <th>商品名</th>
      <th>値段</th>
      <th>商品URL</th>
      <th>あついコメント</th>
    </tr>
  </table>

</div>

  <script src="https://www.gstatic.com/firebasejs/3.5.0/firebase.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  <script>
(function(window, $, firebase, undefined) {
  var database;

  function pushItem(postData) {
    var newPostKey = database.ref().child('items').push().key,
        updates = {};
    updates['items/' + newPostKey] = postData;
    return database.ref().update(updates);
  }

  function validate(name, price, url, message) {
    return name && message;
  }

  function updateView(name, price, url, message) {
    var $name = '<td>' + name + '</td>',
        $price = '<td>' + (price ? price : '<br>') + '</td>',
        $url = '<td>' + (url ? '<a href="' + url + '">商品URL</a>' : '<br>') + '</td>',
        $message = '<td>' + message.replace(/\r?\n/g, '<br>') + '</td>';
    $('#items').append('<tr>' + $name + $price + $url + $message + '</tr>');
  }


  function init () {
    var config = {
      apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      authDomain: "xxxxxxxxxxxxxxxxxxx.firebaseapp.com",
      databaseURL: "https://xxxxxxxxxxxxxx.firebaseio.com",
      storageBucket: "xxxxxxxxxxxxxxxx.appspot.com",
      messagingSenderId: "xxxxxxxxxxxxxxxxxxxxxxxxxxx"
    };
    firebase.initializeApp(config);
    database = firebase.database();


    $('#send').click(function () {
      var name = $('#name').val(),
          price = $('#price').val(),
          url = $('#url').val(),
          message = $('#message').val(),
          postData = {
            name: name,
            price: price,
            url: url,
            message: message
          };
      if (validate(name, price, url, message)) {
        pushItem(postData);
        $('#name').val('');
        $('#price').val('');
        $('#url').val('');
        $('#message').val('');
      }
    });


    database.ref('items').on('child_added', function (snapshot) {
      var item = snapshot.val();
      updateView(item.name, item.price, item.url, item.message);
    });
  }

  window.anketo = {
    version: '0.0.1',
    init: init
  };

})(window, $, firebase);

window.anketo.init();

  </script>
</body>
</html>