(番外編)Node-REDで簡単アンケート回答Webページを作る

社内ハッカソンで使うアンケート結果収集ぺージをNode-REDで作ったので、備忘録的に書きます。
[はまりどころ](#はまりどころ)にはまったので、三時間ぐらいかかりました。。。
コピペなら、アカウントを用意するところから始めても30分ぐらいでできるはずです。


#背景
「メンバーにアンケートをとって、回答データを元に人員最適配置を考える」というソリューションのモックアップを作ることになりました。

ここに書くのは、動作概要1,2にある、入力データをWeb画面からとってきてDBに格納する部分のソースコードです。
"質問回答ページ"フローのHTMLをお好みで修正すればいろいろな目的のWeb入力ページとして応用できます。
![nodered_html.png](https://qiita-image-store.s3.amazonaws.com/0/105029/74813b2f-e8aa-7ee6-a175-62a08e41962d.png)




#前提環境・用意するもの
* IBM Bluemix の無料アカウント　（詳しくは[ここに書いてます](http://qiita.com/manamana/items/434cfc7ed6797851e2cc) ）
* IBM Bluemixの Node-REDのプロジェクト（ボイラープレートで、「Internet of Things Platform Starter」 を選択。詳しくは[ここに書いてます](http://qiita.com/manamana/items/434cfc7ed6797851e2cc) ）
* IBM BluemixのCloudantサービス ([こことか](http://qiita.com/asmanabu/items/809e1276f95e76b989a3) わかりやすいです。）
* Webブラウザ（今回はFirefox）
* テキストエディタ（今回はサクラエディタ）

基本的にタダで！！


#動作概要
1. Web画面でユーザーがアンケート回答を入力する。
1. 回答結果をJSON形式でCloudantに格納する
1. （結果はCloudantを直接覗いて華麗にデータ分析する by [IBM Data Scientist Experience (DSX)](http://datascience.ibm.com/) 　（担当外））


#セットアップ方法
1. https://(Noderedのプロジェクト名).mybluemix.net/red/ にアクセスして、[ソースコード](#ソース)をインポートします。（Node-RED画面の三本線アイコン＞Import > Clipboard　のダイアログにソースコードを丸ごと貼り付けます）
1. Cloudantフロー（水色）をダブルクリックして、DBのURL、認証情報を自分のDBの設定に書き換えます。
1. Deployボタンを押してアプリケーションを更新します。


#使い方
http://(Node-REDのプロジェクト名).mybluemix.net/answerget  
にアクセスすると、アンケート回答ページが表示されます。
回答して"Submit"ボタンを押すと、回答結果がJSON形式でCloudantに格納されます。


#やっていること
1. GET : アンケートページの表示。
2. アンケートページに仕込んだjavascript : 画面で指定した入力結果をJSON形式に変換して送信
3. POST : 送られてきたデータをCloudantに突っ込む

#はまりどころ
## header設定が必要
”headerの小細工”フローの処理を入れておかないと、データが送れません。
ドメインをまたぐときのセキュリティ設定を明示的に解除します。

```
msg.headers = {
 "Access-Control-Allow-Origin":"*",
 "Access-Control-Allow-Method":"GET,POST,PUT,DELETE,OPTIONS",
 "Access-Control-Allow-Headers":"Origin, X-Requested-With, Content-Type, Accept"
}
return msg;
```

## アンケート回答ページにはhttpでアクセス
↓にhttpsでアクセスしてたらエラーになった。（横着してNode-REDのURLを基にした）. Firefoxのコンソールログ(F12押す)でエラーログが確認できます。
http://(Node-REDのプロジェクト名).mybluemix.net/answerget  


#フローのイメージ
![nodered.png](https://qiita-image-store.s3.amazonaws.com/0/105029/575d10fa-872a-1c41-d887-3cdd7ac2ab5c.png)



#ソース
Node-REDの三本線アイコン＞Import > Clipboard で以下のテキストを貼り付けると読み込めます。CloudantのURL、サービス名、APIキー、パスワードは自分用のCloudantの設定に書き換えてください。

```
[{"id":"270a7cf.9b4a184","type":"http in","z":"d0bfacd3.26b4d","name":"/answerpost","url":"/answerpost","method":"post","swaggerDoc":"","x":141,"y":265,"wires":[["1931547f.3a3d8c","c5d5fdb6.862e8"]]},{"id":"1931547f.3a3d8c","type":"debug","z":"d0bfacd3.26b4d","name":"","active":true,"console":"false","complete":"payload","x":341,"y":218.5,"wires":[]},{"id":"b2aff6a4.bf0e38","type":"http response","z":"d0bfacd3.26b4d","name":"","x":672,"y":274.5,"wires":[]},{"id":"2d844b0.5f7b6b6","type":"http in","z":"d0bfacd3.26b4d","name":"/answerget","url":"/answerget","method":"get","swaggerDoc":"","x":133,"y":99.5,"wires":[["539fffff.1d36b","fcdc058b.6b8c78"]]},{"id":"539fffff.1d36b","type":"debug","z":"d0bfacd3.26b4d","name":"","active":false,"console":"false","complete":"true","x":287,"y":51,"wires":[]},{"id":"f56c3564.947238","type":"http response","z":"d0bfacd3.26b4d","name":"","x":656,"y":121,"wires":[]},{"id":"c5d5fdb6.862e8","type":"function","z":"d0bfacd3.26b4d","name":"headerの小細工","func":"msg.headers = {\n \"Access-Control-Allow-Origin\":\"*\",\n \"Access-Control-Allow-Method\":\"GET,POST,PUT,DELETE,OPTIONS\",\n \"Access-Control-Allow-Headers\":\"Origin, X-Requested-With, Content-Type, Accept\"\n}\n//正常終了\n//msg.payload = {\"message\":\"Success insert\"};\nmsg.statusCode=200;\nreturn msg;","outputs":1,"noerr":0,"x":357,"y":280,"wires":[["55c79e9b.5bd86","53d800fd.c81f2"]]},{"id":"8ffbe37e.4e84b","type":"function","z":"d0bfacd3.26b4d","name":"headerの小細工","func":"msg.headers = {\n \"Access-Control-Allow-Origin\":\"*\",\n \"Access-Control-Allow-Method\":\"GET,POST,PUT,DELETE,OPTIONS\",\n \"Access-Control-Allow-Headers\":\"Origin, X-Requested-With, Content-Type, Accept\"\n}\n//正常終了\n//msg.payload = {\"message\":\"Success insert\"};\nmsg.statusCode=200;\nreturn msg;","outputs":1,"noerr":0,"x":501,"y":123.5,"wires":[["f56c3564.947238"]]},{"id":"fcdc058b.6b8c78","type":"template","z":"d0bfacd3.26b4d","name":"質問回答ページ","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>あなたの恋愛感は？</title>\n<script type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js\"></script>\n\n<script type=\"text/javascript\">\n    $(function(){\n        $(\"#response\").html(\"Response Values\");\n\n        $(\"#button\").click( function(){\n            var url = $(\"#url_post\").val();\n\n                var JSONdata = {\n                    uname: $(\"#uname\").val(),\n                    a1: $('#answerform [name=a1]:checked').val(),\n                    a2: $('#answerform [name=a2]:checked').val(),\n                    a3: $('#answerform [name=a3]:checked').val(),\n                    a4: $('#answerform [name=a4]:checked').val()\n                };\n\n             //alert(JSON.stringify(JSONdata));\n             alert(\"回答を送信しました！！\");\n\n            $.ajax({\n                type : 'post',\n//                url : url,\n                url : '/answerpost',\n                data : JSON.stringify(JSONdata),\n                contentType: 'application/json',\n                dataType : 'json',\n                scriptCharset: 'utf-8',\n                success : function(data) {\n\n                    // Success\n                    //alert(\"回答を送信しました！！\");\n                    //alert(JSON.stringify(data));\n                    $(\"#response\").html(JSON.stringify(data));\n                },\n                error : function(data) {\n\n                    // Error\n                    //alert(\"error\");\n                    //alert(JSON.stringify(data));\n                    $(\"#response\").html(JSON.stringify(data));\n                }\n            });\n        })\n    })\n</script>\n\n</head>\n<body>\n    <h1>あなたの恋愛感は？</h1>\n    \n<form id=\"answerform\" method=\"POST\">\n    <p>お名前： <input type=\"text\" id=\"uname\" name=\"uname\" size=\"50\" value=\"\"></p>\n    <p>追いかける恋がいい： <input type=\"radio\" name=\"a1\" value=\"1\" checked=\"checked\" >1 <input type=\"radio\" name=\"a1\" value=\"2\" >2 <input type=\"radio\" name=\"a1\" value=\"3\" >3 <input type=\"radio\" name=\"a1\" value=\"4\" >4 ：追われる恋がいい</p>\n    <p>面白くて飽きない人： <input type=\"radio\" name=\"a2\" value=\"1\" checked=\"checked\" >1 <input type=\"radio\" name=\"a2\" value=\"2\" >2 <input type=\"radio\" name=\"a2\" value=\"3\" >3 <input type=\"radio\" name=\"a2\" value=\"4\" >4  ：一緒にいると癒される</p>\n    <p>ルックス重視： <input type=\"radio\" name=\"a3\" value=\"1\" checked=\"checked\" >1  <input type=\"radio\" name=\"a3\" value=\"2\" >2  <input type=\"radio\" name=\"a3\" value=\"3\" >3 <input type=\"radio\" name=\"a3\" value=\"4\" >4  ：人柄重視</p>\n    <p>プロポーズはド派手なサプライズ： <input type=\"radio\" name=\"a4\" value=\"1\"