masaakibの日記

2011-06-15

[][]expressでpostでundefined

console.logでpostしたデータを確認しようとすると、

undefinedとなってしまうのがなかなか解決しなかった。

にわか知識ではつらい。。。


環境:

Mac OS X 10.6.7

node.js 0.4.8

express 2.3.7


とりあえず、このあたりを参考に:

node.js+expressでPOSTパラメーターを取得する方法 ::ハブろぐ

HideYukiSaito.com: The Leading Hide Yuki Saito Site on the Net


html(index.htmlという名前で)のform部分はこんな感じ:

<form action="/" method="post">
	<input type="text" name="user[name]" />
	<input type="submit" value="送信" />
</form>

で、server.jsというファイルを用意して(元ネタは前の記事を参照)、

postの部分は以下のような感じ:

app.use(express.bodyParser());
app.post('/', function(req, res){
	console.log(req.body);
	res.redirect('back');
});

res.redirect('back');

がないと、ブラウザでレスポンスが返ってこなかった。。。


ターミナルを起動して、server.jsを実行。

$ node server.js

(以下が表示、されるようにconsole.logを書いておく。)

Server running at http://127.0.0.1:8124/


ブラウザで、

http://127.0.0.1:8124/

アクセスし、postしてみると、ターミナルに、

undefined

と表示される。


ググッてみると、

bodyParserがないから、というのがヒットするけど、あるんだけどね。。。


で、

HideYukiSaito.com: The Leading Hide Yuki Saito Site on the Net

を見直して、

bodyParser()をconfigureで指定したところ、postした中身が表示された。


修正したserver.jsは以下。

// モジュールの読み込み
var express = require('express');

// サーバーを作成
var app = express.createServer();

// configure
app.configure(function() {
	app.use(express.bodyParser());
});

// '/'のリクエストハンドラ
app.get('/', function(req, res) {
	res.sendfile('index.html');
});

// post
app.post('/', function(req, res) {
	console.log(req.body);
	res.redirect('back');
});

// サーバーを起動
app.listen(8124, '127.0.0.1');
console.log('Server running at http://127.0.0.1:8124/');

で、「おれ」とか入力してpostすると、

ターミナルに以下のように表示された。

{ user: { name: 'おれ' } }

2011-05-26

[][]express使おうとしら、Error: Cannot find module 'express'

こういうのは、UNIX系のOSを扱い慣れてれば、

それほど悩まなくてもいいのかもしれないけど、

慣れてないので書いておく。

Macだけど。


node.jsの設置は以下を参考に:

node.jsとMySQLで割と普通のデータベースウェブアプリを作ってみるチュートリアル | さくらたんどっとびーず

naveでNode.jsのバージョン管理&イベントループ詳説(1/3)- @IT

エラーにたどり着くまでの手順をざっと。


1. ターミナルを起動。


2. 一般ユーザーのホームディレクトリ下に設置するので、

インストールディレクトリを作成、移動。

$ mkdir nodejs

$ cd nodejs


3. naveをインストール

$ git clone http://github.com/isaacs/nave.git

~/nodejs/nave

が作成される。


naveを使うと、node.jsの更新、バージョンの切り替えが楽、とか。


4. 最新版のnode.jsインストール

$ cd nave

$ ./nave.sh install latest

結構時間がかかった。


5. node.jsを使えるようにする。

$ ./nave.sh use latest


6. バージョンを確認。

$ node -v

v0.4.7

と表示された。


7. 続けて、npmをインストール

$ curl http://npmjs.org/install.sh | sh

途中で、

Is this OK? enter 'yes' or 'no'

と問われるので、「yes」と入力。


8. サーバー用のディレクトリを作って、example.jsを設置する。

$ cd ~

$ mkdir node_server

$ cd node_server

「node_server」ディレクトリ内にexample.jsを設置。


example.jsの中身は上の参考サイトを参照:

node.jsとMySQLで割と普通のデータベースウェブアプリを作ってみるチュートリアル | さくらたんどっとびーず


9. example.jsを動かしてみる。

$ node example.js

パスが通ってないので動きません。

(node command not found)


10. .bash_profileにパスを記述して、node.jsのパスを通す。

$ cd ~

vi .bash_profile

以下を記述。

# node.js

NODE_PATH=~/.nave/installed/0.4.7/bin

export NODE_PATH

node.jsの本体の位置を、

「NODE_PATH=」以下に記述。


参考:

Setting up Node.js and npm on Mac OSX | Shape Shed


11. パスの記述を有効化。

$ source .bash_profile


12. 再度、example.jsを動かす。

$ cd ~/node_server

$ node example.js

ブラウザで、

http://127.0.0.1:8124

アクセスしてみると、

Hello, World

と表示された。


続いてexample2.jsもやってみてうまくいった(詳細は割愛)。


13. 続いてserver.jsをやってみるので、expressをインストール

$ cd ~/nodejs/nave

$ npm install experss

以下が表示された。

mime@1.2.2 ./node_modules/express/node_modules/mime

connect@1.4.1 ./node_modules/express/node_modules/connect

qs@0.1.0 ./node_modules/express/node_modules/qs

express@2.3.7 ./node_modules/express

14. server.jsを実行してみる。

$ cd ~/node_server

$ node server.js

で、タイトルのエラーにたどりつく。

node.js:134

throw e; // process.nextTick error, or 'error' event on first tick

^

Error: Cannot find module 'express'

at Function._resolveFilename (module.js:320:11)

at Function._load (module.js:266:25)

at require (module.js:348:19)

at Object.<anonymous> (/Users/(ユーザー名)/node_server/server.js:2:15)

at Module._compile (module.js:404:26)

at Object..js (module.js:410:10)

at Module.load (module.js:336:31)

at Function._load (module.js:297:12)

at Array.<anonymous> (module.js:423:10)

at EventEmitter._tickCallback (node.js:126:26)

expressがどこにあるかわかんねーよ、

と言われてるんで、

どこにあるか教えてあげないと動いてくれない。


ここで疑問に思ったのが、

    • expressはどこに入ってるのか?
    • node.jsはどこにあるものを見つけてくれるのか?

というあたり。


2点目については、

$ node -e require.paths

で確認できる。


参考:

node.js server side javascript ()


1点目については、

expressのインストール時に、

express@2.3.7 ./node_modules/express

と出たのを頭の片隅に置いておく。


手順10の、node.js本体の位置を環境設定のところであっさり通り過ぎましたが、

ホームディレクトリ直下には、いつの間にやら、

.nave

.npm

というディレクトリができていた。

node.jsは.naveの下だったので、

.npmの下をさがすと、

~/.npm/express/2.3.7/package/bin

にexpressがあったので、これを.bash_profileに指定してみたけど動かず。


で、2点目の、

$ node -e require.paths

をやってみると、

[ '/Users/(ユーザー名)/.nave/installed/0.4.7/bin',

'/Users/(ユーザー名)/.node_modules',

'/Users/(ユーザー名)/.node_libraries']

と表示。

1行目は、手順10で追加したもの。

2行目、3行目は実在していない。

expressの位置はわからんよね、というのがよくわかった。


ディレクトリ構成とか、コマンドの実行位置とか、よくわからず...。


いろいろと調べて、node.jsマニュアルモジュールの最後のところをよく読む。

http://nodejs.jp/nodejs.org_ja/api/modules.html

「Addenda: Package Manager Tips」のところ。


で、また探してみると、

~/nodejs/nave/node_module

にexpressがあったので、

.bash_profileを以下のように編集。

# node.js

NODE_PATH=~/.nave/installed/0.4.7/bin

#express

NODE_PATH=$NODE_PATH:~/nodejs/nave/node_modules

export NODE_PATH

有効化。

$ source .bash_export

で、server.jsがやっと動いた。


そしてその後、node.jsを0.4.8に更新し、

$ node -e require.paths

をやってみると、

[ '/Users/(ユーザー名)/.nave/installed/0.4.8/lib/node',

'/Users/(ユーザー名)/.node_modules',

'/Users/(ユーザー名)/.node_libraries',

'/Users/(ユーザー名)/.nave/installed/0.4.8/lib/node' ]

と出た。うーん。


.bash_profileの中身が書き換えられたわけではないので、

$ source .bash_profile

$ node -e require.paths

で、

[ '/Users/(ユーザー名)/.nave/installed/0.4.7/bin',

'/Users/(ユーザー名)/nodejs/nave/node_modules',

'/Users/(ユーザー名)/.node_modules',

'/Users/(ユーザー名)/.node_libraries',

'/Users/(ユーザー名)/.nave/installed/0.4.8/lib/node' ]

となった。


~/.node_modules

を作って、そこにnpmでモジュールインストールされるようにしとけばよさげなんだけど、

とりあえずディレクトリは作っておく。

ディレクトリがあれば、その場所にモジュールインストールしてくれる、

とかだといいけど。。。

あとでほかのモジュールをいれるので、そのときにまた確認。


追記

id:koichikさんのコメントを参考に、mongooseをローカルインストールしてみようとする、

が、またいろいろと壁が。。。


15. nodeのパスをもう1度。


まず、

$ cd ~/nodejs/nave

$ npm install mongoose

で、

bash: npm: command not found

となる。


この時点で、node.jsを0.4.8にしたので、

npmはバージョンごとにインストールしなければいかのか、

と思った、のはただの勘。


npmを再インストールしようと、

$ cd ~/nodejs/nave/

$ curl http://npmjs.org/install.sh | sh

(以下が表示)

% Total % Received % Xferd Average Speed Time Time Time Current

Dload Upload Total Spent Left Speed

0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 101 3874 101 3874 0 0 4893 0 --:--:-- --:--:-- --:--:-- 1101 3874 101 3874 0 0 4892 0 --:--:-- --:--:-- --:--:-- 11164

npm cannot be installed without nodejs.

Install node first, and then try again.

Maybe node is installed, but not in the PATH?

Note that running as sudo can change envs.

PATH=(云云...)


nodeコマンドが認識されないし。。。

「PATH=」の部分に0.4.8のパスはなし。


で、また、.bash_profileを編集。

NODE_PATHではなくて、PATHで指定。

PATH=$PATH:~/.nave/installed/0.4.8/bin

export PATH


で、動くようになった。


16. 「node_server」ディレクトリ以下に、「node_modules」ディレクトリ作成。

$ cd ~/node_server

$ mkdir node_modules


17. npmをnode.js 0.4.8用にインストール

npmのインストール先は、

~/.nave/installed/0.4.7/lib/node_modules

だった。。。


参考:

(Ubuntu で) Node.js 開発環境構築手順 - pekodeco のじんどぅ?


今回はホームディレクトリ直下で。

$ cd ~

$ curl http://npmjs.org/install.sh | sh


あとは手順7と同じ。


18. mongooseをインストール

$ cd ~/node_server

$ npm install mongoose

(以下が表示)

mongoose@1.3.7 ./node_modules/mongoose

└── hooks@0.1.6

~/node_server/node_modules/

に「mongoose」ディレクトリが作成された。

2009-11-11

[]fieldset要素はelements配列で取得される

入力フォームが設置された古いWebページの改修をやっていて引っかかる。


元のHTMLでは、form要素内に、inputやtextareaなどの操作する要素しか設置されていなくて、

それらをJavaScriptで以下のように取得していた。

for(var i = 0; i < form.elements.length; i++) {
	form.elements[i]....(do something)
}

で、このHTMLはtableレイアウトで組まれていたので、

XHTML+CSSで組み直したときに、

fieldset要素とかを使ってがんばってマークアップしたんだけど、

同じJavaScriptを適用したところ、ループのところでエラーが出るようになった。

例えば、こんな感じのHTML:

<form method="post" name="form1" action="#">

	<fieldset>
		<legend>フォームテスト</legend>
		
		<label for="input01">input01</label><input type="text" name="input01" />
		<input type="checkbox" name="check01" /><label for="check01">check01</label>
	
	</fieldset>

	<input type="submit" name="btn_submit" value="submit" />

</form>

該当箇所はtype属性を取得していたところで、

form.elements[i].type is undefined

などと、Firebugで表示される。


alert(form.elements[i].type);

とすると、

undefined

text

checkbox

submit

と出てくる。


alert(form.elements[i]);

とすると、

object HTMLFieldSetElement

object HTMLInputElement

object HTMLInputElement

object HTMLInputElement

と出てくる。


というわけで、

fieldset要素は、elements配列で取得される、ということが確認できた。

legend要素は取得されていない。


fieldset要素にtype属性は指定していないから、

undefined

になる。


fieldset要素についてはこちらを参照:

Forms in HTML documents

type属性はない。


ここで、

alert(form.elements[i].getAttribute("type"));

としてみると、

null

text

checkbox

submit

となる。


なので、

for(var i = 0; i < form.elements.length; i++) {
	if(form.elements[i].getAttribute("type") != null){
		if(form.elements[i].getAttribute("type") == text) {
			(do something)
		}
	}
}

という感じで条件をつけると、とりあえずエラーは回避できる。

2009-10-27

[]window.open()でnameを指定する場合の注意事項

こちらを参照:

Liferium.com

window.nameは何?ってとこなんだけど、

framesetにつけられたname属性を参照したりするらしい。


window.open()の第2引数に名前を指定をすると、

新しく開いたウィンドウ(windowオブジェクト)に対して名前をつけられる。

で、クリックイベントが発生すると同じ関数を呼び出す複数の要素(ボタンなど)があったとき、

最初のクリックで新しいwindowオブジェクトが作られ、

2回目以降は、最初に開いたウィンドウの中身が置き換えられる。

というわけで、元のウィンドウとは別のウィンドウにしたいけど、

毎回ウィンドウを開くのはやだ、という場合に第2引数を指定すると、

意図通りの動作にできる。


で、この第2引数を指定するときに注意しなければならないのが、最初の引用。

半角英数以外のものが含まれていると、

クリックイベント発生時に、IEのステータスバーにエラーが出るんだけど、とりあえずウィンドウは開く。

だけど、毎回新しいウィンドウが開いてしまう。


今回引っかかったのは、半角スペースだった。

name属性だと思うと、半角スペースは使わないようにするという意識があるが、

制限は半角英数なので、アンダーバーもだめ。

アンダーバーは使いたくなってしまうから注意が必要。


この現象を確認したIEのバージョンは、6と8。

2009-10-01

[][]nextSiblingは何を取得するか

自分で確認しないと身に染みないので。


以下のようなHTMLを作成。

	<table>
		<tbody>
			<tr>
				<th>見出し1</th>
				<td id="data1_1">data1_1</td>
				<td id="data1_2">data1_2</td>
			</tr>
			<tr>
				<th>見出し2</th>
				<td id="data2_1">data2_1</td><td>data2_2</td>
			</tr>
		</tbody>
	</table>
		
	<div id="div_idtest">
		<p id="p_1">
			これは、(ここで改行)	
			<abbr id="abbr1_1">ここはabbr要素(ここで改行)</abbr>
			<span id="span1_1">ここはspan要素(ここで改行)</span>
			です。(ここで改行)
		</p>
		<p id="p_2">
			これは、(ここで改行)
			<abbr id="abbr2_1">ここはabbr要素(改行なし)</abbr><span id="span2_1">ここはspan要素(ここで改行)</span>
			です。(ここで改行)
		</p>
		<p id="p_3">3つ目のpタグ(改行なし)</p><p id="p_4">4つ目のpタグ</p>
	</div>

<td id="data1_1">のnextSiblingを確認(table要素:改行ありの場合)

ノードタイプを確認してみる。

HTML

	<td id="data1_1">data1_1</td>
	<td id="data1_2">data1_2</td>

JavaScript

	var data1_1 = document.getElementById("data1_1");
	alert(data1_1.nextSibling.nodeType);

ブラウザごとの結果:

  • Internet Explorer 6:1
  • Internet Explorer 8:1
  • Firefox 3.5:3
  • Safari 4:3

ノードタイプ1は、要素ノード、

ノードタイプ3は、テキストノード。


ノードバリューを取得してみると、

	var data1_1 = document.getElementById("data1_1");
	alert(data1_1.nextSibling.nodeValue);

ブラウザごとの結果:

  • Internet Explorer 6:null
  • Internet Explorer 8:null
  • Firefox 3.5:(空)
  • Safari 4:(空)

ノードネームを取得してみると、

	var data1_1 = document.getElementById("data1_1");
	alert(data1_1.nextSibling.nodeName);

ブラウザごとの結果:

  • Internet Explorer 6:TD
  • Internet Explorer 8:TD
  • Firefox 3.5:#text
  • Safari 4:#text

IEは要素ノード(<td id="data1_2">)を参照しているので、

nodeValueを取得しようとするとnullが返ってくる。

FirefoxとSafariでは、</td>のあとの改行が取得されるので、alertに何も表示されない。


<td id="data2_1">のnextSiblingを確認(table要素:改行なしの場合)

ノードタイプを確認してみる。

HTML

	<td id="data2_1">data2_1</td><td>data2_2</td>

JavaScript

	var data2_1 = document.getElementById("data2_1");
	alert(data2_1.nextSibling.nodeType);

ブラウザごとの結果:

  • Internet Explorer 6:1
  • Internet Explorer 8:1
  • Firefox 3.5:1
  • Safari 4:1

この場合、2つのtd要素が改行なしで記述されているので、

すべてのブラウザで、2つ目のtd要素が取得されている。


<p id="p_1">のnextSiblingを確認(ブロック要素:改行ありの場合)

ノードタイプを確認してみる。

HTML

	<p id="p_1">
		これは、(ここで改行)	
		<abbr id="span1_1">ここはabbr要素(ここで改行)</abbr>
		<span id="abbr1_1">ここはspan要素(ここで改行)</span>
		です。(ここで改行)
	</p>
	<p id="p_2">
		これは、(ここで改行)
		<abbr id="abbr2_1">ここはabbr要素(改行なし)</abbr><span id="span-2_1">ここはspan要素(ここで改行)</span>
		です。(ここで改行)
	</p>

JavaScript

	var p_1 = document.getElementById("p_1");
	alert(p_1.nextSibling.nodeType);

ブラウザごとの結果:

  • Internet Explorer 6:1
  • Internet Explorer 8:1
  • Firefox 3.5:3
  • Safari 4:3

ノードバリューを取得してみると、

	var p_1 = document.getElementById("p_1");
	alert(p_1.nextSibling.nodeValue);

ブラウザごとの結果:

  • Internet Explorer 6:null
  • Internet Explorer 8:null
  • Firefox 3.5:(空)
  • Safari 4:(空)

IEは要素ノード(<p id="p_2">)を参照しているので、

nodeValueを取得しようとするとnullが返ってくる。

FirefoxとSafariでは、</p>のあとの改行が取得されるので、alertに何も表示されない。


<p id="p_3">のnextSiblingを確認(ブロック要素:改行なしの場合)

ノードタイプを確認してみる。

HTML

	<p id="p_3">3つ目のpタグ(改行なし)</p><p id="p_4">4つ目のpタグ</p>

JavaScript

	var p_3 = document.getElementById("p_3");
	alert(p_3.nextSibling.nodeType);

ブラウザごとの結果:

  • Internet Explorer 6:1
  • Internet Explorer 8:1
  • Firefox 3.5:1
  • Safari 4:1

id属性を確認してみる。

JavaScript

	var p_3 = document.getElementById("p_3");
	alert(p_3.nextSibling.getAttribute("id"));

ブラウザごとの結果:

  • Internet Explorer 6:p_4
  • Internet Explorer 8:p_4
  • Firefox 3.5:p_4
  • Safari 4:p_4

この場合、2つのp要素が改行なしで記述されているので、

すべてのブラウザで、2つ目のp要素が取得されている。


<abbr id="abbr1_1">のnextSiblingを確認(インライン要素:改行ありの場合)

ノードタイプを確認してみる。

HTML

	<abbr id="abbr1_1">ここはabbr要素(ここで改行)</abbr>
	<span id="span1_1">ここはspan要素(ここで改行)</span>

JavaScript

	var abbr1_1 = document.getElementById("abbr1_1");
	alert(abbr1_1.nextSibling.nodeType);

ブラウザごとの結果:

  • Internet Explorer 6:3
  • Internet Explorer 8:3
  • Firefox 3.5:3
  • Safari 4:3

ノードバリューを確認してみる。

JavaScript

	var abbr1_1 = document.getElementById("abbr1_1");
	alert(abbr1_1.nextSibling.nodeValue);

ブラウザごとの結果:

  • Internet Explorer 6:ここはabbr要素(ここで改行)
  • Internet Explorer 8:(空)
  • Firefox 3.5:(空)
  • Safari 4:(空)

IE6はabbr要素をサポートしていない。

IE Developper Toolbarで確認すると、

「ここはabbr要素(ここで改行)」の部分は、

abbr要素の子要素ではなく、兄弟要素として扱われている。


下記のようにspanとabbrを入れ替えて、span要素のnextSiblingを確認してみる。

HTML:

	<span id="span1_2">ここはspan要素(ここで改行)</span>
	<abbr id="abbr1_2">ここはabbr要素(ここで改行)</abbr>

ノードタイプ:

JavaScript

	var span1_2 = document.getElementById("span1_2");
	alert(span1_2.nextSibling.nodeType);
  • Internet Explorer 6:3
  • Internet Explorer 8:3
  • Firefox 3.5:3
  • Safari 4:3

ノードバリュー:

JavaScript

	var span1_2 = document.getElementById("span1_2");
	alert(span1_2.nextSibling.nodeValue);
  • Internet Explorer 6:(空)
  • Internet Explorer 8:(空)
  • Firefox 3.5:(空)
  • Safari 4:(空)

さらにspan要素の後にテキストを追加してみる。

HTML:

	<span id="span1_2">ここはspan要素</span>ここにてきすと(ここで改行)
	<abbr id="abbr1_2">ここはabbr要素(ここで改行)</abbr>

ノードバリュー:

JavaScript

	var span1_2 = document.getElementById("span1_2");
	alert(span1_2.nextSibling.nodeValue);
  • Internet Explorer 6:ここにてきすと(ここで改行)
  • Internet Explorer 8:ここにてきすと(ここで改行)
  • Firefox 3.5:ここにてきすと(ここで改行)
  • Safari 4:ここにてきすと(ここで改行)

まあ、ブロック要素内なので、改行だろうとテキストだろうとテキストノードはテキストノードであると。


<abbr id="abbr2_1">のnextSiblingを確認(インライン要素:改行なしの場合)

ノードタイプを確認してみる。

HTML

	<abbr id="abbr2_1">ここはabbr要素(改行なし)</abbr><span id="span2_1">ここはspan要素(ここで改行)</span>

JavaScript

	var abbr2_1 = document.getElementById("abbr2_1");
	alert(abbr2_1.nextSibling.nodeType);

ブラウザごとの結果:

  • Internet Explorer 6:3
  • Internet Explorer 8:1
  • Firefox 3.5:1
  • Safari 4:1

ノードバリューを確認してみる。

JavaScript

	var abbr2_1 = document.getElementById("abbr2_1");
	alert(abbr2_1.nextSibling.nodeValue);

ブラウザごとの結果:

  • Internet Explorer 6:ここはabbr要素(改行なし)
  • Internet Explorer 8:null
  • Firefox 3.5:null
  • Safari 4:null

abbr要素とspan要素を入れ替えてみる。

HTML

	<span id="span2_2">ここはabbr要素(改行なし)</span><abbr id="abbr2_2">ここはspan要素(ここで改行)</abbr>

ノードタイプ:

JavaScript

	var span2_2 = document.getElementById("span2_2");
	alert(span2_2.nextSibling.nodeType);

ブラウザごとの結果:

  • Internet Explorer 6:1
  • Internet Explorer 8:1
  • Firefox 3.5:1
  • Safari 4:1

ノードネーム:

JavaScript

	var span2_2 = document.getElementById("span2_2");
	alert(span2_2.nextSibling.nodeName);

ブラウザごとの結果:

  • Internet Explorer 6:ABBR
  • Internet Explorer 8:ABBR
  • Firefox 3.5:ABBR
  • Safari 4:ABBR

まとめ

やってみると大したことではないような気もするけど、IE6のおかげで結構混乱してたな。


とりあえず、以下の3点。

  1. HTML内のブロック要素間、table要素間の改行について、IEは無視、そのほかはノードと解釈。
  2. インライン要素間の改行について、各ブラウザとも改行をノード(普通にテキストノード)と解釈。
  3. IE6ではサポートしていない要素を使うときは注意する。

3点目については、nextSibling以外についても注意する。

対応については、とりあえずその都度検討。