gist

ラベル JavaScript の投稿を表示しています。 すべての投稿を表示
ラベル JavaScript の投稿を表示しています。 すべての投稿を表示

2012年3月21日水曜日

複数のJavaScriptライブラリをコンパクトに!「Ender」をインストール。

近頃のウェブサイトでは、複数のJavaScriptライブラリが使わるのが珍しく有りません。

複数のJavaScriptライブラリをまとめて管理できるのが「Ender」です。例えば、domready、qwery、underscoreといったライブラリをコンパクトにまとめて ender.js として呼び出して使うことができます。

Enderのインストールには、node と npm が必要です。Nodeの開発環境が整っていれば、問題なくインストールできます。

nodeやnpmインストール方法は

あたりを参考に(OSはMacです)。

では、Enderを早速インストールしてみます。

$ npm install -g ender

まとめたいパッケージを複数指定してみます。ender build package1 package2... のように指定します。

$ ender build domready qwery underscore
Welcome to ENDER - The no-library library
-----------------------------------------
installing packages: "ender-js domready qwery underscore"...
this can take a minute...
npm http GET https://registry.npmjs.org/ender-js
npm http GET https://registry.npmjs.org/domready
npm http GET https://registry.npmjs.org/qwery
npm http GET https://registry.npmjs.org/underscore
npm http 200 https://registry.npmjs.org/underscore
npm http 200 https://registry.npmjs.org/domready
npm http GET https://registry.npmjs.org/underscore/-/underscore-1.3.1.tgz
npm http GET https://registry.npmjs.org/domready/-/domready-0.2.11.tgz
npm http 200 https://registry.npmjs.org/ender-js
npm http GET https://registry.npmjs.org/ender-js/-/ender-js-0.3.7.tgz
npm http 200 https://registry.npmjs.org/qwery
npm http GET https://registry.npmjs.org/qwery/-/qwery-3.3.3.tgz
npm http 200 https://registry.npmjs.org/domready/-/domready-0.2.11.tgz
npm http 200 https://registry.npmjs.org/underscore/-/underscore-1.3.1.tgz
npm http 200 https://registry.npmjs.org/qwery/-/qwery-3.3.3.tgz
npm http 200 https://registry.npmjs.org/ender-js/-/ender-js-0.3.7.tgz
ender-js@0.3.7 ./node_modules/ender-js 
domready@0.2.11 ./node_modules/domready 
underscore@1.3.1 ./node_modules/underscore 
qwery@3.3.3 ./node_modules/qwery
successfully finished installing packages
assembling packages...
ender.js successfully built!
ender.min.js successfully built!


ender.jsとender.min.jsが出来上がります。

.
├── ender.js
├── ender.min.js
└── node_modules/

このender.jsをhtmlから読み込むだけで、domready, qwery, underscode を使えるようになります。

<script type="text/javascript" src="ender.min.js"></script>
<script type="text/javascript">
$('#content a.button')
  .bind('click.button', function (e) {
    $(this).data('clicked', true).unbind()
    e.preventDefault()
  })
  .css({
      opacity: 1
    , color: 'red'
  })
  .fadeOut(250)
$.map(['a', 'b', 'c'], function (letter) {
  return letter.toUpperCase()
})
$.ajax('/data', function (resp) {
  $('#content').html(resp)
})
</script>

現在有効なライブラリを見るには、ender info コマンドです。


$ ender info
Welcome to ENDER - The no-library library
-----------------------------------------
Your current build type is "build"
Your current minified and compressed library size is 7.2 kB

Active packages:
├── domready@0.2.11 - bullet proof DOM ready method
├── qwery@3.3.3 - blazing fast CSS3 query selector engine
└── underscore@1.3.1 - JavaScript's functional programming helper library.
 

パッケージを追加したい場合は、ender add package コマンドです。

$ ender add bean
Welcome to ENDER - The no-library library
-----------------------------------------
installing packages: "bean"...
this can take a minute...
npm http GET https://registry.npmjs.org/bean
npm http 200 https://registry.npmjs.org/bean
npm http GET https://registry.npmjs.org/bean/-/bean-0.4.9.tgz
npm http 200 https://registry.npmjs.org/bean/-/bean-0.4.9.tgz
bean@0.4.9 ./node_modules/bean
successfully finished installing packages
assembling packages...
ender.js successfully built!
ender.min.js successfully built!

$ ender info
Welcome to ENDER - The no-library library
-----------------------------------------
Your current build type is "build"
Your current minified and compressed library size is 10.8 kB

Active packages:
├── domready@0.2.11 - bullet proof DOM ready method
├── qwery@3.3.3 - blazing fast CSS3 query selector engine
├── underscore@1.3.1 - JavaScript's functional programming helper library.
└── bean@0.4.9 - an events api for javascript

削除は ender remove package コマンドで。

EnderでJavaScriptライブラリが足りない!script書き忘れた!ということがなくなりそうです。是非お試しあれ。

2012年2月16日木曜日

イヌ型ドキュメントで開発効率アップ!? JSDogを使ってみよう。

JavaScriptのドキュメント生成ツールと言えば、JSDoc Toolkitが有名です。

でも何か、物 足 り な い。

そこでJSDogです。

JSDogは、JSDocの書き方で「犬」のドキュメントが生成されます。

インストールはnpmで。

$ sudo npm install -g jsdog

書き方はこんな感じです。

/** ++*[npmtools.js]*++ - npmのpackage.jsonを読み込むプログラム
 * 
 * @version 0.0.1
 * @author Tomoyuki Inoue
 */

var fs = require('fs');

/**
 * 指定したパスからpackage.jsonファイルを探索します。
 * @method readPackageJson
 * @param {string} path 読み込みを開始するパスを指定します。
 * @param {function} cb 読み込み完了かエラー時のコールバックを指定します。
 */
var readPackageJson = function(path, cb){
    // パスの読み込み開始
    var path = path + "/node_modules";
    fs.readdir(path, function(err, dirs){
        if(err) cb(err, null);
        // dirsには指定したパスのファイル名・ディレクトリ名の一覧が入っている
        for(var i = 0; i < dirs.length; i++){

            var dir = dirs[i];
            // 頭文字が.の場合読み込まない
            if(dir.charAt(0) === '.') continue;
    
            // package.jsonのパスを指定
            var jsonPath = path + "/" + dir + "/package.json";
    
            // package.jsonを読み込み開始
            fs.readFile(jsonPath, function(err, data){
                if(err) cb(err, null);
                // dataには読み込んだBufferが入っている
                // toString('utf8')で文字列にする
                var jsonStr = data.toString('utf8');
                // JSONをパースしてコールバック
                cb(null, JSON.parse(jsonStr));
            }); 
        }   
    }); 
};

readPackageJson(".", function(err, json){
    if(err) throw err;
    console.log(json.name +"@" + json.version );
});


使い方はコマンドラインで。

$ jsdog -s npmtools.js > index.html

見事に文字化けします。

テンプレートの最初の数行を修正します。

テンプレートはJadeで書かれています。ファイルは、/usr/local/lib/node_modules/jsdog/default.jade あたりにあると思います。

修正前

!!! 5
html(lang="en")
  head
    title= pageTitle

修正後(lang属性削除、メタcharset追加)

!!! 5
html
  head
    meta(charset="utf-8")
    title= pageTitle

もう一度実行すると文字化けが解消。

まだまだ不安定ですが面白いですね。

テンプレートもJade形式なので簡単です。ちょっと修正すると・・・

な事もできます。

2012年2月14日火曜日

JavaScriptの綺麗なドキュメントを作るためのメモ

githubを散策していたら、こんなReadmeを見つけました。「Beautiful Docs」というタイトルでJavaScriptに限らず、様々なAPIのドキュメントリンク集となっています。流行の技術ばかりです。

ドキュメントが綺麗で読みやすいというのも、普及していく上で重要なファクターなのかもしれませんね。

JavaScriptのドキュメント生成ツールは、JSDocというのが有名のようです。(若干Activeでないような気もします。)

面白そうなのは、docco というツール。リンク先のようにコメントとコードを同時に見れるようなHTMLを生成します。

今週はJavaScriptのドキュメントをやってみようと思います。

関連ページ

イヌ型ドキュメントで開発効率アップ!? JSDogを使ってみよう。

2012年1月29日日曜日

「デバッグで問題を切り分けよう!」Nodeのデバッグ機能を使ってみる。

Nodeには標準でデバッグ機能が搭載されています。

server.js


var http = require('http');

http.createServer(function(rq, rs) {
    rs.writeHead(200, {'Content-Type': 'text/plain'});
    rs.end('Hello Debugger!');
}).listen(3000, 'localhost');

console.log('サーバーが起動しました: http://localhost:3000/');

デバッグモードで起動するには、nodeコマンドにdebugオプションをつけます。
node debug filePath 
$ node debug server.js 
< debugger listening on port 5858
connecting... ok
break in server.js:1
  1 var http = require('http');
  2 
  3 http.createServer(function(rq, rs) {
debug> 

debug> で入力待ちの状態になります。
break in server.js:1  
は、止まっている位置を示しています。server.jsの1行目で処理が中断しています。
  1 var http = require('http');
  2 
  3 http.createServer(function(rq, rs) {
は、中断している位置周辺のコードが表示されます。

この状態のまま、ブラウザから http://localhost:3000/ にアクセスすると、接続できないはずです。

server.js の1行目で処理が中断しているので、6行目のlisten関数が実行されておらず、ウェブサーバが起動していないためです。

処理を再開するには、debug> で「c」と入力します。

debug> c
< サーバーが起動しました: http://localhost:3000/
debug> 

「サーバーが起動しました」の出力があり、「break in server.js:N」の表示もありません。server.jsの最終行まで実行されています。ブラウザからアクセスすると、Hello Debugger! と表示されるはずです。

server.jsを修正し、クライアントからリクエストを受け取ったところで止めてみます。


var http = require('http');

http.createServer(function(rq, rs) {
    debugger;  // 追加。リクエストがきたら止める。
    rs.writeHead(200, {'Content-Type': 'text/plain'});
    rs.end('Hello Debugger!');
}).listen(3000, 'localhost');

console.log('サーバーが起動しました: http://localhost:3000/');

デバッグモードで実行してみます。

$ node debug server.js 
< debugger listening on port 5858
connecting... ok
break in server.js:1
  1 var http = require('http');
  2 
  3 http.createServer(function(rq, rs) {
debug%gt; c
< サーバーが起動しました: http://localhost:3000/
debug< 

「c」でサーバーが起動したら、ブラウザからアクセスしてみます。処理が完了しないはずです。

デバッガが起動しており、4行目で処理が中断しています。

(続き)
< サーバーが起動しました: http://localhost:3000/
break in server.js:4
  2 
  3 http.createServer(function(rq, rs) {
  4     debugger;
  5     rs.writeHead(200, {'Content-Type': 'text/plain'});
  6     rs.end('Hello Debugger!');
debug> 

インスタンス rq の中身を知るには、repl を使います。

(続き)
debug> repl
Press Ctrl + C to leave debug repl
>

replが起動します。REPL(Read-Eval-Print-Loop)は、読込→評価→表示を繰り返す対話型評価環境のこと。rubyやphythonなんかで使われています。

rqの中身を表示するには、rqと打ってReturnします。

> rq
{ httpVersion: '1.1',
  method: 'GET',
  headers: 
   { 'cache-control': 'max-age=0',
     'accept-encoding': 'gzip, deflate',
     'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/534.51.22 (KHTML, lik... (length: 119)',
     'accept-language': 'ja-jp',
     accept: 'text/html,application/xhtml xml,application/xml;q=0.9,*/*;q=0.8',
     connection: 'keep-alive',
     host: 'localhost:3000' },
  client: 

  (ズラーリ)

}
>

ポイントを絞ってHTTPヘッダだけ表示してみます。

> rq.headers
{ 'cache-control': 'max-age=0',
  'accept-encoding': 'gzip, deflate',
  'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/534.51.22 (KHTML, lik... (length: 119)',
  'accept-language': 'ja-jp',
  accept: 'text/html,application/xhtml xml,application/xml;q=0.9,*/*;q=0.8',
  connection: 'keep-alive',
  host: 'localhost:3000' }
> 

いい具合です。

REPLを抜けるにはCtrl+Cです。

中断している行がわからない場合、bt, listコマンドを使います。

debug> list()
  1 var http = require('http');
  2 
  3 http.createServer(function(rq, rs) {
  4     debugger;
  5     rs.writeHead(200, {'Content-Type': 'text/plain'});
  6     rs.end('Hello Debugger!');
  7 }).listen(3000, 'localhost');
  8 
  9 console.log('サーバーが起動しました: http://localhost:3000/');
debug> bt
#0 server.js:4:5
debug> 

listは、中断しているコードの前後を表示します。表示された行の真ん中が、現在の行です。(例では、1行目が近いので、実際どこかわかりません。)

btは、現在の行、スタックを表示します。(例では4行目で止まっていることがわかります。)

ウオッチリストを追加しています。

watchでウオッチ追加、unwatchでウオッチ削除、watchersでウオッチの一覧を表示します。

rs.finishedを監視に加え、nコマンドで一行進めます。

(続き)
debug> watch('rs.finished')
debug> n
break in server.js:5
Watchers:
  0: rs.finished = false

  3 http.createServer(function(rq, rs) {
  4     debugger;
  5     rs.writeHead(200, {'Content-Type': 'text/plain'});
  6     rs.end('Hello Debugger!');
  7 }).listen(3000, 'localhost');
debug>

行が1行進んで5行目に、ウオッチリストと値が表示されます。

nを続けてみます。

(続き)
debug> n
break in server.js:6
Watchers:
  0: rs.finished = false

  4     debugger;
  5     rs.writeHead(200, {'Content-Type': 'text/plain'});
  6     rs.end('Hello Debugger!');
  7 }).listen(3000, 'localhost');
  8 
debug> n
break in server.js:7
Watchers:
  0: rs.finished = true

  5     rs.writeHead(200, {'Content-Type': 'text/plain'});
  6     rs.end('Hello Debugger!');
  7 }).listen(3000, 'localhost');
  8 
  9 console.log('サーバーが起動しました: http://localhost:3000/');
debug>

7行目で、rs.finishedがtrueに変化しました。

ウオッチを削除してみます。

debug> watchers
  0: rs.finished = true
debug> unwatch(0)
debug> watchers
debug> 

現在の行にブレークポイントを追加してみます。sbコマンドを使います。

debug> sb()
  2 
  3 http.createServer(function(rq, rs) {
  4     debugger;
  5     rs.writeHead(200, {'Content-Type': 'text/plain'});
  6     rs.end('Hello Debugger!');
* 7 }).listen(3000, 'localhost');
  8 
  9 console.log('サーバーが起動しました: http://localhost:3000/');
 10 
 11 
 12 });
debug>

「*」印がついて7行目にブレークポイントが設定されました。

「c」で継続して、再度ブラウザからアクセスしてみます。

debug> c
break in server.js:4
  2 
  3 http.createServer(function(rq, rs) {
  4     debugger;
  5     rs.writeHead(200, {'Content-Type': 'text/plain'});
  6     rs.end('Hello Debugger!');
debug> c
break in server.js:7
  5     rs.writeHead(200, {'Content-Type': 'text/plain'});
  6     rs.end('Hello Debugger!');
* 7 }).listen(3000, 'localhost');
  8 
  9 console.log('サーバーが起動しました: http://localhost:3000/');
debug> 

4行目のdebuggerで一度止まります。c で継続するとブレークポイントの7行目まで処理が飛びます。

こんな感じでデバッグできます。より詳しいデバッグコマンドは、公式リファレンスを参考に。

2012年1月26日木曜日

JavaScriptでUUIDを生成する


JavaScriptでUUIDを生成してみます。
UUIDを生成する
    var uuid = (function(){
        var S4 = function() {
            return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
        }   
        return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4() +S4());
    })();

    console.log(uuid);
実行結果
6ad6c236-65e7-3f80-998c-25c861006168
参考
How to create a GUID / UUID in Javascript?

2012年1月24日火曜日

socket.ioでマウスの動きを共有してみよう

自分のマウスの動きが他の人のブラウザにリアルタイムで表示されたら面白いことできそうです。socket.ioを使って、ブラウザから取得したマウスの位置情報を他のブラウザにブロードキャストしてみます。

$ express mouse_share
$ cd mouse_share && npm install
jade@0.20.0 ./node_modules/jade 
├── mkdirp@0.3.0
└── commander@0.2.1
express@2.5.5 ./node_modules/express 
├── qs@0.4.0
├── mkdirp@0.0.7
├── mime@1.2.4
└── connect@1.8.5
$ npm install socket.io
socket.io@0.8.7 ./node_modules/socket.io 
├── policyfile@0.0.4
├── redis@0.6.7
└── socket.io-client@0.8.7

app.js

/**
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes')

var app = module.exports = express.createServer();

var io = require('socket.io').listen(app);
io.set('log level', 1);

// Configuration

app.configure(function(){
  app.set('views', __dirname   '/views');
  app.set('view engine', 'jade');
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(require('stylus').middleware({ src: __dirname   '/public' }));
  app.use(app.router);
  app.use(express.static(__dirname   '/public'));
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  app.use(express.errorHandler());
});
    
// Routes
    
app.get('/', routes.index);
    
app.listen(3000);
            
io.sockets.on('connection', function(socket) {
    socket.on('mousemove', function(mouse) {
        socket.broadcast.json.send({x:mouse.x, y:mouse.y});
    });             
});                 
                    
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);

views/layout.jade

!!!
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
    script(src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js' ,type='text/javascript')
    script(src='/socket.io/socket.io.js' ,type='text/javascript')
    script(type='text/javascript')
        $(document).ready(function() {
            var socket = io.connect('http://localhost:3000/');
            socket.on('message', function(mouse) {
                $('#point').css({
                    'position':'fixed',
                    'width':'8px',
                    'height':'8px',
                    'background-color':'#f00',
                    'border-radius':'8px',
                    'left':mouse.x,
                    'top':mouse.y,
                });
            });
            $(document).mousemove(function(event) {
                socket.emit('mousemove', {x:event.pageX, y:event.pageY});
            });
        });
  body!= body


実行ー。

$ node app.js

実行結果

ブラウザをSafariとChromeで別々のセッションになるように開いて並べます(Chromeのシークレットウィンドウと普通のウィンドウを並べても可)。片方のブラウザ上でマウスを動かすと、もう片方のブラウザの赤丸ポインタが動きます。

カクカクです。

カクカクを減らすには、サーバからの再送をやめてみます。sendの前にvolatileをつけます。

io.sockets.on('connection', function(socket) {
    socket.on('mousemove', function(mouse) {
        socket.broadcast.json.volatile.send({x:mouse.x, y:mouse.y});
    });             
});                 

さっきよりもスムーズに動きます。

超楽しい!

2012年1月2日月曜日

QUnitの文字化けを解消する

QUnitで日本語を表示できるようにしてみます。といってもたった一行追加するだけです。前回のエントリーのqunit.htmlのヘッダに以下を追加します。

<head>
  <meta charset="utf-8" />
  ...
</head>

実行結果

2012年1月1日日曜日

QUnitでJavaScriptのユニットテストを始める

JavaScriptでユニットテストを実行するには、QUnitを使うのが良いかと思います。QUnitはもともとjQuery用のユニットテストでしたが、今ではjQueryに依存しないように作られていますので、JavaScriptをテストできます。JavaScriptの特徴でもある非同期のテストにも対応していますので、オススメです。

ここではQUnitのインストールと実行までやってみます。

まず、テストを実行するためのHTMLファイルを用意します。

qunit.html

<!DOCTYPE html>
<html>
<head>
    <title>QUnit Test Suite</title>
    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" media="screen">
    <script type="text/javascript" src="http://code.jquery.com/qunit/qunit-git.js"></script>
    <script type="text/javascript" src="myTests.js"></script>
</head>
<body>
    <h1 id="qunit-header">QUnit Test Suite</h1>
    <h2 id="qunit-banner"></h2>
    <div id="qunit-testrunner-toolbar"></div>
    <h2 id="qunit-userAgent"></h2>
    <ol id="qunit-tests"></ol>
    <div id="qunit-fixture">test markup, will be hidden</div>
</body>
</html>

次に、テストコードを記述するためのmyTests.jsを用意します。先ほどのqunit.htmlと同じ階層に配置します。必ずOKになるテストです。

myTests.js

test('a test', function() {
    ok(true, 'Happy New Year!');
});

では実行してみます。index.htmlをブラウザで開きます。

実行結果

グリーンになりました。

実行結果のデザインが見やすくカッコイイのでモチベーションが保てそうです。デザインの良さもQUnitを選択する理由かもしれません。

詳しい使い方は、公式のqunit(英語)をご覧いただければと思います。日本語ですとNodeで活躍されているJxckさんのサイトがとても詳しいです。

2008年6月2日月曜日

ブラウザの[×]ボタン押下時に画面遷移をキャンセルさせる

HTMLの<header>タグ内にJavaScriptで以下のように記述します。

window.onbeforeunload = function(){
    return '本当に終了しますか?';
}

FireFox 2.0以降ではブラウザから以下のような確認メッセージが表示されます。


[キャンセル]ボタンを押すと画面遷移しません。[OK]ボタンを押すと画面が閉じられます。

確認画面へのメッセージは、スクリプトの返り値として(return)記述します。