famo.usは描画エンジンです。 先日紹介したときに言及したデモは下記にありました。

こちら

このfamo.usをAngularと統合した人たちがいます。

http://famo.us/integrations/angular/

これがなかなかいいのです。famo.usはJavaScriptですべて書くのですが、ちょっと手続き的な感じになります。それをAngularのdirectiveに書けるようにするのです。ちゃんと、bindingも動くので、更新系がなんとも簡単なのです。Angularの経験があれば普通なので、特に驚きもないと言えばそれまでなのですが、これに慣れると、生のfamo.usを書くのは面倒くさく感じるようになるかもしれません。

というわけで、サンプルを作ってみました。 1つのHTMLにすべて詰め込みたかったので、single fileのfamous-angularを使いました。通常は、bowerでインストールする方法が紹介されています。

single fileのものはcdnにないので、http://rawgit.com/を使いました。ところで、rawgitはcdn版(beta)もあってすばらしいです。これは続いて欲しいものです。

さて、出来上がったサンプルは

こちら

です。ソースコードはgistにありますが、下記にも貼り付けます。

<html ng-app="MyApp">
<head>
  <title>famo.us angular sample</title>
  <link type="text/css" href="//code.famo.us/famous/0.2/famous.css" rel="stylesheet" />
  <link type="text/css" href="//cdn.rawgit.com/Famous/famous-angular/fee2b717a53ad762c9e3157580ce255901f4ccad/dist/famous-angular.min.css" rel="stylesheet" />
  <script type="text/javascript" src="//code.famo.us/lib/require.js"></script>
  <script type="text/javascript" src="//code.famo.us/famous/0.2/famous.js"></script>
  <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.min.js"></script>
  <script type="text/javascript" src="//cdn.rawgit.com/Famous/famous-angular/fee2b717a53ad762c9e3157580ce255901f4ccad/dist/famous-angular.min.js"></script>
  <script type="text/javascript">
angular.module('MyApp', ['famous.angular'])
.controller('MyController', ['$scope', function($scope) {
  $scope.items = [];
  for (var y = 0; y < 1; y += 0.1) {
    for (var x = 0; x < 1; x += 0.1) {
      $scope.items.push({x: x, y: y, color: 'yellow'});
    }
  }
}]);
  </script>
</head>
<body ng-controller="MyController">
  <fa-app>
    <fa-modifier ng-repeat="item in items" fa-origin="[item.x, item.y]">
      <fa-surface fa-size="[30, 20]" fa-click="item.color = 'red'" fa-background-color="item.color" fa-properties="{textAlign: 'center', lineHeight: '20px'}">{{$index}}</fa-surface>
    </fa-modifier>
  </fa-app>
</body>
</html>

Famo.us/Angularはまだ発展途上ですべての機能がdirective化されていませんが、今後に期待しています。

Famo.us Physicsの簡単なサンプル

  • 投稿日:
  • by

最近注目しているライブラリfamo.us、なにがいいってURLがいいです。

http://famo.us/

今年になってオープンソース化されたのですが、以前プレビュー版のデモを見たときは3次元でぐりぐり動くものだったのですが、正式リリースではモバイルのリッチアプリのデモになっていて、ある意味おとなしくなっていました。実用的ではあります。

famo.usは技術的にもDOMの階層を使わずに自力でレイアウトして、fpsを保証するという面白いものになっています。

もっと感心したのは、Famo.us Universityです。ステップを追ってfamo.usの使い方を学習できます。ACEエディタでその場でいじって動作を確認できるのもすばらしい。

さて、3次元のぐりぐりですが、どうやらfamo.us Physicsというサブライブラリを使うといろいろできるようです。Famo.us Universityのコースではcoming soonとなっています。が、待ちきれずに試してみました。

とにかく簡単に面白いものができないかと思って、作ってみました。 まずはご覧ください。

こちら

どうですか?水色の玉をクリックしてみましたか?まだの人はもう一度。

なんと、これは1つのHTMLファイルに書いています。もちろん中身はほとんどJavaScriptのコードですが。63行なのでブログに貼り付けてもいいのですが、 gistにアップしてあるのでそちらをご参照ください。

ソースはこちら

他にもconstraintのモジュールがあるので、いろいろできそうです。 ただ、ドキュメントはまだ少ないので、現状ではソースを読まざるを得ないことがありました。

しばらく楽しめそうです。

自作のライブラリsocial-cms-backendでは、socket.ioのmiddlewareが使いたかったのでv1.0を先取りして使っていました。

socket.ioのv1.0はengine.ioという低レイヤから書き直しているらしいですが、一向にリリースされないなぁと思っていました。計画も分かりません。

socket.ioのの代替としてSockJSがあることを知りました。メインサイトのhttp://sockjs.org/がhttps://github.com/sockjs/sockjs-clientにリダイレクトされるのがなんかさびしいですが、そのうちかっこいいページを作るつもりなのでしょうか。

比較記事を探しましょう。

http://www.quora.com/Sock-js/What-are-the-pros-and-cons-of-socket-io-vs-sockjs

両方を実装した経験というのは説得力あります。 SockJSはWebSocketのAPIを中心にしていてシンプルなようですね。 今のところコミュニティもアクティブだそうで、なによりです。

http://stackoverflow.com/questions/22134061/engine-io-or-sockjs-which-one-to-choose

こちらもいい質問です。回答は集まっていませんが。 WebSocketを前提としてない場合はemulationするSockJSか、全ブラウザで動く確実な方式からアップグレードするengine.ioか、方針が逆ですね。時代の流れとしてはSockJSの方がいい気もします。

さて、SockJSのnodeのサーバはというと、 https://github.com/sockjs/sockjs-node ですね。 しかし、中身を読もうとしたら、、、

CoffeeScript

でした。うーん、なぜかワクワクしない。

もともとnode.jsを始めたきっかけもsocket.ioを手軽に使いたかったからなので、socket.ioも応援したいところです。と思って、https://github.com/learnboost/socket.ioを久しぶりに見てみると、おお、最近コミットがあるじゃないですか、1.0.0-preとかなっていていい感じです。ちょっと期待できるかなと思いつつも、このあとコミュニティがアクティブになるかどうかが気になります。

というわけで、しばらく様子を見ましょう。

mongodbのaggregateがパワフルで便利

  • 投稿日:
  • by

mongodbはドキュメントベースのデータベースですが、APIがシンプルでよいです。これまで、find()とcount()で足りていたのですが、ちょっと複雑なことをやろうとするとクライアント側で処理するはめになってしまいました。

mongodbの集計機能にはいくつかの種類があります。

http://docs.mongodb.org/manual/core/aggregation/

によると、Aggregation Pipeline, Map-Reduce, Single Purpose Aggregation Operationsとあります。 最後のSingle Purpose Aggregation Operationsはまさにcount()のようなものなのですが、他にもdistinct()やgroup()もあります。SQLから類推すれば機能は分かりやすいでしょう。 Map-Reduceは並列処理にはいいでしょう。ただ、JavaScriptの関数を記述することになります。なんでもできるといえばなんでもできるのですが。 残るは、Aggregation Pipelineです。これは処理を逐次的に書くので分かりやすいのが利点ですが、注目したのはJSONで記述できることです。JavaScriptの関数と違ってシリアライズができるのがうれしい。Pipeline Operatorsというのがあって、そこそこ柔軟に書けます。

今回は詳しく述べませんが、参考までにパイプラインのサンプルを載せておきます。

var pipeline = [{
  $project: {
    record: '$records'
  }
}, {
  $unwind: '$record'
}, {
  $match: {
    'record.name': target_name
  }
}, {
  $group: {
    _id: 'all',
    count: {
      $sum: '$record.score'
    }
  }
}];

この$unwindがいいですね。ドキュメントを展開してくれるのです。

欲を言えば、パイプラインではなく、処理を分岐できる有効グラフを記述できたらさらに強力だったろうに。

さて、なぜJSONで記述したかったかというと、social-cms-backendで使いたかったからです。aggregateをサポートしてバージョンアップしました。

https://www.npmjs.org/package/social-cms-backend

facebookはアプリを開発するときにテストユーザを作ることができます。これは非常に便利で、複数のユーザでの操作などもテストできます。

これまで、facebookアプリ(というかライブラリ)を自動でテストするときにテストユーザも自動で作っていました。過去記事を参照。他にも例えば、Qiitaの投稿に手順が載っています。

Facebookアプリのテストユーザーの作り方手順

ところが、このlogin_urlが使えなくなっているのに気づきました。404エラーになってしまうのです。Google検索すると、

http://stackoverflow.com/questions/22583963/404-error-trying-to-use-facebook-test-user-login-url

がヒットしました。今回は、stackoverflowでいい投稿を見つけました。すばらしい。stackoverflowは便利なときは便利です。facebookにバグ報告していて、

https://developers.facebook.com/bugs/276245435872240/

これによると、ポリシーが変わって使えなくなったと。「ドキュメントもアップデートしてくれ」と要望がでてますね。さて、stackoverflowのAnswerにはworkaroundも出ていて、簡単に回避できました。この方法が止められなければいいのですが。

参考までに、node.jsでのテストユーザのログインのコードの抜粋を載せておきます。

request.get('https://www.facebook.com', function() {
  request.post('https://www.facebook.com/login.php', {
    followAllRedirects: true,
    form: {
      email: facebook_user_email,
      pass: facebook_user_password
    }
  }, function(error, response) {
    //check response
  });
});

完全なコードはこちらです。

nodeのchild_processにはちょっと紛らわしい3つのメソッドがあります。 execとexecFileとspawnです。

いきなり話題がそれますが、forkも紛らわしいですよね。システムコールのforkを連想させるのに、中身は違うので。forkはどちらかと言うと、spawnのラッパーみたいな感じです。

本題に戻ります。google検索すると、execとspawnの違いはいっぱい引っかかります。例えば、これ。

http://www.hacksparrow.com/difference-between-spawn-and-exec-of-node-js-child_process.html

ところが、execFileとの比較は極端に少ないです。どうやら、昔はexecFileはundocumentedだったようですね。

https://github.com/joyent/node/issues/1700

一言で言うと、spawnが自由度が高いメソッドで、execはそのラッパーです。execFileはその中間とでも言いましょうか。execとexecFileの最大の違いは、execは/bin/shを経由してプロセスを起動することです。

nodeのソースを見ると分かりますが、execはexecFileのシンプルなラッパーになっています。また余談ですが、v0.10.18のソースと比較すると少しリファクタリングされて分かりやすくなっています。

個人的には、通常のコーディングではexecFileを使う方がベターだと思います。/bin/shを介さないからです。多くの場合、コマンドラインのスペース区切りを配列に変換するだけのために/bin/shを使っているのではないでしょうか。「通常」というのは誤解を招くかもしれませんが、webのserver sideプログラミングをするという程度の想定です。逆に、execが便利なケースとしては、linux上でちょっとしたスクリプトを書きたい場合ですかね。bashとかperlの代わりに、という感じ。/bin/shのパワーを使いたい場合ですね。例えば、

child_process.exec("cat foo | sort | uniq > bar");

とか。

まとめると、spawnは柔軟なメソッド、execFileはBufferを戻り値にして簡単に扱えるようにしたメソッド、execはスクリプト用の簡易メソッド、という感じですね。というわけで、おすすめはspawnかexecFile、ということで。

node-http-proxyというのはnode.jsでhttpプロクシを作るためのライブラリです。 WebSocketsに対応しているリバースプロクシが作れるということで注目していました。

さて、気づいたら、いつの間にかバージョンアップしていました。

http://blog.nodejitsu.com/node-http-proxy-1dot0/

node-0.10用に書き直してv1.0になったということです。 ところが、以前のバージョンで使えていたProxyTableは使えなくなっていて、 userlandでコーディングしてねということでした。 以前のバージョンではほとんどコーディングしなくても使えるようになっていて それはそれでよかったのですが、v1.0ではシンプルなAPIとなっていて 基本的にコーディングして使うモジュールという位置づけになっています。 個人的にはv1.0の方が好みです。

ProxyTableはないけれど簡単できるよ、というサンプルが上記ブログに乗っていて、 ホスト名で振り分ける例が載っています。 ただ、前のProxyTableはパスでも振り分けられたのです。 完全互換というわけではありませんが、パスで振り分けるサンプルを紹介します。 ついでに、WebSocketsもHTTPSもどんな組み合わせでも大丈夫なように。

というわけで、コードです。

var fs = require('fs');
var http = require('http');
var https = require('https');
var httpProxy = require('http-proxy');

var proxyTable = {
  "/path1/": "http://localhost:1234/",
  "/path2/": "http://localhost:2345/",
  "/sslpath3/": "https://localhost:3456/",
  "/sslpath4/": "https://localhost:4567/"
};

var sslOptions = {
  key: fs.readFileSync('key.pem', 'utf8'),
  cert: fs.readFileSync('cert.pem', 'utf8')
};

var proxy = httpProxy.createProxyServer();

function makeHandler(type) {
  return function(req, res, head) {
    for (path in proxyTable) {
      if (req.url.lastIndexOf(path, 0) === 0) {
        if (type === 'web') {
          proxy.web(req, res, {
            target: proxyTable[path]
          })
        } else if (type === 'ws') {
          proxy.ws(req, res, head, {
            target: proxyTable[path]
          })
        } else {
          res.writeHead(500);
          res.end();
        }
        return;
      }
    }
    res.writeHead(404);
    res.end();
  };
}

var proxyServer = http.createServer(makeHandler('web'));
proxyServer.on('upgrade', makeHandler('ws'));
proxyServer.listen(80);

var sslProxyServer = https.createServer(sslOptions, makeHandler('web'));
sslProxyServer.on('upgrade', makeHandler('ws'));
sslProxyServer.listen(443);

いかがでしょう?

モバイルファーストの次はオフラインファーストってことで、前から作ってみたいと思っていたアプリを作ってみました。

アプリ自体は「メモ」アプリで特に目新しいものではありません。機能も単純です。

ですが、BMEANスタックで作ったことが新しいかと思っています。 BMEANとは、

を利用するソフトウエアスタックです。

今回、「Railsより簡単にTwitterクローンを作るためのnode.jsのライブラリ」を目指したsocial-cms-backendを改良してBreezeをサポートする機能を追加しました。そのため、サーバ側のコードはほとんど書かずにアプリを作ることができます。また、HTML5のキャッシュマニフェストを使うために、connect-cache-manifestも利用しています。

アプリは、OpenShiftを使って配置しました。ぜひ、一度お試しください。

http://notesappsample-nodeangularapp.rhcloud.com/

左上にLoginがありますが、Loginしなくても使用できます。 その場合、localStorageにデータが保存されます。 LoginするとSyncが使えるようになり、サーバ側にデータを保存することができるため、複数のデバイスでデータの同期ができます。

iPhoneのWebアプリにもなります。「ホーム画面に追加」してください。スプラッシュイメージがうまく表示されないのですが、これは深追いしていません。

ソースコードはこちらです。よろしければ見てみてください。細かいところは、Breezeとsocial-cms-backendがやってくれるので、だいぶシンプルになっていると思います。

https://github.com/dai-shi/notes-app-sample

RSS Pipesを使って、実用的なことをしよう、というお話です。

以前、RSS Pipesで広告エントリの除去という記事を書いたのですが、あまり自分でも使っていませんでした。今回、どうしてもやりたいことがあったので、久しぶりにRSS Pipesをいじりました。

やりたいことというのは、RSSのURLの修正です。RSSのURLにリダイレクトURLが使われていることがあります。例えば、bit.lyなどの短縮URLが使われている場合です。通常は困らないのですが、そのRSSをプログラムで処理しようとする場合に、短縮URLではなく最終的なURLが欲しい場合があります。めずらしいケースだとは思います。

URLのリダイレクトをたどるにはこれまでのRSS Pipesの仕組みの上だけではできず、新たな関数を作り込む必要がありました。具体的には、getRedirectURL()という関数を作りました。

ところが、このgetRedirectURL()は同期的には結果を返すことができません。nodeでは、通常callbackを使って非同期処理を書くのですが、RSS Pipesのフィルターは同期的に書くように作られていたので困りました。仕方なく、promiseを使うことにしました。

フィルターの方でもpromiseを扱えるようにする必要があるため、Qを使えるようにしました。しかし、これでブロックするようなコードも書けてしまうので、悪意コード対策がいずれ必要になりますね。promiseにタイムアウトの概念を持ち込めれば簡単にできるかしら。

さて、新しくなったRSS Pipesで書いたフィルターがこちらです。

function rssPipesFilterFunction(articles) {
  var promises = [];
  articles.forEach(function(article) {
    var maxRedirects = 5;
    var loop = function() {
      var promise = getRedirectURL(article.link).then(function(link) {
        if (article.link === link || --maxRedirects < 0) {
          return article;
        } else {
          article.link = link;
          return loop();
        }
      });
      return promise;
    };
    promises.push(loop());
  });
  return Q.all(promises);
}

https://gist.github.com/dai-shi/8934864

にも同じものを同じものを置いてあります。

リダイレクトが多重になっている場合を想定してループにしてみましたが、promiseをちゃんと理解していればもっとうまく書けるのかもしれません。どなたか改良してくれたら、うれしいです。

しかしこれでサーバ側の処理がますます重くなるので、キャッシュ機構を入れる必要がでてきそうです。そのうち、気が向いたらやりますか。今のところ、それほどユーザがいないのでほっておいても大丈夫です。それはそれでさびしいものの。

ng-conf 2014っていうイベントが1月にあったようですね。

YouTubeで動画が公開されている(でもすべてではない)ので助かります。とても勉強になりますね。ほんと、いい時代になったものです。

さて、Daniel ZenのTalkを見ました。AngularJSでモバイルアプリを作るために使えるライブラリがいっぱい紹介されていたのでメモしておきます。

PhoneGap

まず、PhoneGap。 今では、Open Sourceなんですね。

http://cordova.apache.org/

使ったことはないですが興味はあります。 一部ネイティブ関数にもアクセスできるようです。

http://en.wikipedia.org/wiki/Phonegap#Supported_platforms

APNも使えるようですね。個人的にはこれが一番大きいかな。

ngTouch

次は、ngTouch。 これは、Angularのモジュールです。タッチイベントを扱えるそうです。 一方、300ms問題だけなら、fastclickでよさそうです。

angular-mobile-nav

続いて、angular-mobile-nav。iOS5くらいのLook&Feelが簡単に作れるライブラリのようですが、READMEによるとangular-1.2だったらもっと簡単にできるということなので、今後使う機会はなさそうです。

angular-gestures

angular-gesturesは、その名の通りジェスチャーを使うためのディレクティブを提供してくれるようです。基本的には、hammer.jsのラッパーなのでしょうか。

angular-jqm

angular-jqmはjQuery Mobileのラッパーディレクティブです。jQueryなんて使わないぜ、と思っていたら、なんとこのライブラリ、jQueryとjQuery MobileのJSには非依存だそうです。つまり、jQuery MobileのCSSを使っているだけ。一気に気に入りました。そのセンスがいいです。機会があれば使ってみたいと思います。

AngularJS Native

これは、PhoneGapのネイティブ関数を呼ぶためのラッパーのようなものでしょうか。それぞれモジュールごとに分かれているようです。

angular-carousel

angular-carouselは、carouselを簡単に実現するためのライブラリです。 carouselってなんて訳すのでしょう?カルーセル? デモを見れば一発で分かると思います。

angular-snap

angular-snapは、snap.jsのラッパーディレクティブです。最近のモバイルアプリでよくある画面全体がスライドしてメニューがでるUIができるようです。snap.jsは依存ライブラリもなく、サポートブラウザも多く、設定も柔軟なようで魅力的です。

Ionic Framework

Ionic Frameworkは、PhoneGap用のフレームワークです。AngularJSも使われているとのことです。このフレームワークの範囲内でできることをやる分には簡単にできそうです。


その他、Tips等も紹介されていますので、興味がある方は直接スライドを見るとよいでしょう。

http://bit.ly/zen-ng-phonegap