タグ「JavaScript」が付けられているもの

node.jsとかブラウザで簡単な統計処理をしようと考えて使えそうなライブラリがないか調べました。 できるだけ依存ライブラリがないものがいいです。

構築にMakeを使うと書いてアイルからネイティブコードがあるのかと思いましたが、そうではなくpure JavaScriptでした。 http://jstat.github.io/にドキュメントがあります。かなり色々な関数がそろっているようです。 検定などもできるようです。JavaScriptのArrayをそのまま渡すこともできるので、お手軽です。 GitHubのStarは712です。

こちらも同じような感じです。Arrayを使うのが基本です。回帰や分類もできるようです。 これが紹介ページですが、フォントがいい感じです。 GitHubのStarは821なので、jStatとこれがメジャーどころでしょうか。

こちらはCollectionやVectorといったクラスを導入して抽象化しているようです。 と思いましたが、作られたオブジェクトは普通のArrayとしても扱うことができ、とても便利そうです。 READMEにはJavaScript標準のMathと連携しているサンプルが載っています。 JavaScriptのprototype chainのおかげですね。魅力的です。 Star数は327です。

ドキュメントページはこちらです。 Star数は711なので初めの2つと同じくらいですね。ここまで来るとStar数だけでは判断できないでしょう。 Vector and Matrix math for JavaScriptというふれこみで、他のものよりMatrix系が充実しているようにも見えます。

READMEにはほとんど情報がないのに、Star数が530という状態が不思議です。最近更新されていないところを みると過去に集めたStarでしょうか。それともどこか別のところにドキュメントページがあるのでしょうか。 Rっぽいことができるらしいです。コードとしては枯れているのかもしれません。

これまでのライブラリと比べると小規模なもので、Arrayを拡張して基本的な関数群を追加してくれます。 機能は少ないですが、これだけがやりたい場合はいいかもしれません。Star数は23です。


最後に、こんなページを見つけました。 中身はよく理解していませんが、JavaScript(というかv8)は意外と速いと言う気付きだそうです。

http://julialang.org/には新しく、もう少し見やすいベンチマークの表が載っています。

上記のライブラリたちのベンチマークも気になるところです。

以前の記事で、 x-rayというライブラリを使ってスクレイピングをしてみた話を書きました。 その時に、ページネーションだけでなく、リンク先取得もできればいいと思ったのですが、 先日バージョンアップしていた2.0.0ではすばらしいことに複合的な処理が書けるようになっていました。

さっそく、試してみましょう。 サンプルををちょっといじって実行してみます。

var xray = require('x-ray')();
xray('https://www.google.com/', {
  title: 'title',
  image: xray('#gbar a:nth-child(2)@href', 'title'),
  map: xray('#gbar a:nth-child(3)@href', 'title'),
  play: xray('#gbar a:nth-child(4)@href', 'title'),
  youtube: xray('#gbar a:nth-child(5)@href', 'title')
})(function(err, obj) {
  console.log(obj);
});

ちゃんとそれぞれのページのタイトルが取れました。 「画像検索」はなぜか文字化けしました。

これは便利です。しかも、delayやthrottleの設定までできます。 今度勉強がてらコードも読んでみるといいかもしれません。

また、小ネタでした。

ところで、x-rayってだけだと検索キーワードとしてはあいまいすぎますね。

今さらながら、node-v0.12.3を入れました。 vmが新しくなったことはどこかで聞いたのですが、timeoutが指定できるようになっているというのは認識できていませんでした。

これまで、 rss-pipescodeonmobile で、vmモジュールを使ってなんちゃってsandbox環境を作っていました。 その際、無限ループだけは避けたかったため、safeCode.jsというのを作って ループのカウントをしてexceptionを投げるようにしていました。

ところが、node-v0.12で新しくなったvmはtimeoutの指定ができるので、簡単にできるようになりました。 今後はこれを使うことにします。

サンプルコードはこちら。

var vm = require('vm');
var x = vm.runInNewContext('x=0;for(i=0;i<100;i++){x++;}x', {}, {
  timeout: 10
});
console.log(x);
x = vm.runInNewContext('x=0;for(i=0;i<10000;i++){x++;}x', {}, {
  timeout: 10
});
console.log(x);

実行するとこんな感じ。

$ node vm-test.js
100

vm.js:38
  return this.runInContext(context, options);
              ^
Error: Script execution timed out.
    at Error (native)
    at ContextifyScript.Script.runInNewContext (vm.js:38:15)
    at Object.exports.runInNewContext (vm.js:69:17)
    at Object.<anonymous> (/tmp/vm-test.js:6:8)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)

というわけで、なんちゃってsandboxが簡単に作れるようになりました。 ドキュメントにはuntrusted codeは別processで走らせるべきだというように書いてあります。確かに、メモリを大量に消費するようなmalicious codeには対処できないと思います。他にはどういう穴があるのでしょうか。globalオブジェクトだけを渡しているうちはそこまで悪いことはできないような気もしますが、どうなんでしょう。

Browserify CDNはよさそう

  • 投稿日:
  • by

先日、Browserifyを使ってみたという記事を書きましたが、 その後、Browserify CDNというもをの知りました。Browserify界隈では普通なのかもしれませんが、Browserifyというのはてっきりローカルで動かすものという先入観があったので、眼から鱗でした。

初めに知ったのは、

https://wzrd.in/

です。 browserify-as-a-serviceとのこと、いいですね。URLも短くてよいです。 説明も分かりやすく、APIも直感的です。

これはいいと思っていたところ、さらに、

https://www.brcdn.org/

を見つけました。 こちらは後発ですが、wzrd.inとの比較が書かれています。 コンパイルしたファイルはAmazon S3に置かれるということで、productionにも使えそうです。 minifyもproductionを想定しているとのことです。

なるほどと思ってhttps://github.com/jfhbrook/browserify-cdnを見直すと、 Heroku installが書いてあったり、キャッシュが消えると書いてあったり、 どちらかというとa serviceであって複数のインスタンスが立ち上がることを想定しているようです。

というわけで、今後はhttps://www.brcdn.org/を積極的に使ってみようかと思います。

Browserifyを使ってみた、browserify-shimも

  • 投稿日:
  • by

今さらながらbrowserifyを使ってみました。 存在は知っていたものの普段はcdnを使ってライブラリを読み込むようにしていたので、 必要性を感じていませんでした。 今回、ライブラリをローカルに保存したかったので使ってみました。 bowerと比較してnpmだけで済むのがいいです。

しかし、npm上のライブラリが対応しているかどうか分からないというのは難点ですね。 実際に使おうとしていたライブラリがうまくラップしていないものがありました。 そこで、browserify-shimを使いました。 これは、CommonJSでexportしていないライブラリをexportしたかのように使えるようにするものです。 関連して、napaを思い出しました。 うまくやればnapaとbrowserify-shimの組み合わせは最強ではないでしょうか。

browserify-shimの使い方はあまり検索しても見つからなかったので、メモしておきます。 基本的にはREADMEに書いてあるのがそのままなのですが、一瞬理解しにくかったです。

以下、package.jsonの中身の書き方です。まず、

{ 
  "browserify": {
    "transform": [ "browserify-shim" ]
  }
}

これが必須です。これにより、browserify-shimが認識されるようです。 transformは他にも用途があるのでしょうか。それも興味あります。 次に、

{
  "browserify-shim": {
    "./node_modules/foo/bar.js": { "exports": "Bar" }
  }
}

これはどのファイルのどのようにラップするのかを記述します。 詳細は調べていませんが、これはbar.jsのファイルの最後に

exports = Bar;

を追加したような感じです。もちろん、function(){}でスコープを切っているでしょうが。 さて、一番悩んだのは、どうやってこれを利用するかでした。 状況としては、./public/javascripts/hoge.jsというファイルでどのように使うかというものです。 これは、

var bar = require('../../node_modules/foo/bar.js');

としたら動きました。パスが違うのが曲者です。

改めて、これはnapaと組み合わせると便利かもしれません。 最近自分でよく使っているcdnとhttp://rawgit.com/の組み合わせに匹敵するかも。


5/13追記。

よりよい設定方法が分かりました。というか単にbrowserify自体の設定方法をよく理解していなかっただけでした。 package.jsonを、

{ 
  "browserify": {
    "transform": [ "browserify-shim" ]
  },
  "browser": {
    "bar": "./node_modules/foo/bar.js"
  },
  "browserify-shim": {
    "bar": { "exports": "Bar" }
  }
}

のように書けば、

var bar = require('bar');

として利用することができました。 分かってしまえば簡単なのですが、browserify-shimのドキュメントだけでは理解できなかったです。

http://dailyjs.com/2015/02/05/xray/ で紹介されていたx-rayというツールを試してみました。

https://github.com/lapwinglabs/x-ray のサンプルをほぼそのまま実行しました。

すこし脱線しますが、yieldableというのを知りました。利用者がcallbackタイプとyieldタイプを使い分けられるのはいいですね。

x-rayはpaginationがサポートされているのが便利でした。もう一歩進んで、一つリンクを進んで詳細ページも扱えるといいのですが。

さて、プロクシの設定をしたかったのですが、x-ray自体にはサポートされていません。しかし、内部で使われているsuperagentを差し替えることはできます。superagent-proxyというライブラリがあるのでそれを使えばできそうです。 今回はいつも使っているrequestを使ってみました。下記にコードスニペットを載せておきます。

var xray = require('x-ray');
xray.prototype.request = function(url, callback) {
  require('request').get(url, function(err, response, body) {
    callback(err, body);
  });
};

あまりうまいやり方ではないですが、一応こんな感じで動いています。

小ネタでした。

ng-conf 2015の動画を見ていたら、angular meteor integrationの動画がありました。

https://www.youtube.com/watch?v=uFmf-DeCdEE

Meteorを試した時に、angularを利用する可能性は考えましたし、 そのような記事もどこかで読んだ気がします。 しかし、Meteorが元から持っているテンプレート機能と重複しますし、 Meteorの恩恵をあまり受けられないかと思っていました。

ところが、Angular-Meteorはそれなりにうまく作られているようです。 興味がある方は、チュートリアル を見てみるとよいでしょう。 話が脱線しますが、このチュートリアルとてもやりやすいです。 Meteor本体のチュートリアルもそうですが、チュートリアルなのにかなり本格的な アプリを作っています。 Famo.us universityを見たときも思いましたが、チュートリアル周りの ベストプラクティスがたまってきていますね。 自分でもうまく活用できればいいと思います。

Angular-Meteorのチュートリアルをやってみて一番気に入ったのは、 3-way data bindingです。 これができるということは、AngularFireの代替になるのではないでしょうか。 ちょっとなにか作ってみたくなりました。 逆に一番気になったのは、getReactively周りの処理です。 特に手動でunsubscribeしなければいけないのは面倒です。

Maybe in the future we will add an automatic way to open and close subscriptions in scope's load and destroy events.

とあるので、解決されることを期待します。

話はまた変わりますが、Firebaseのtalkもng-conf 2015にありました。

https://www.youtube.com/watch?v=4nD5fjpIesk

こちらは、本家本流なのですごいですね。v1.0がリリースされたそうです。 彼らが3-way data bindingの名付け親です、たぶん。

Meteorはとても魅力的なのですが、自分が本当に気に入るか分からずちょっと悩んでいます。 その理由は、Fiberを使っていることと、jQueryを使っていること。 callbackは結構好きなのでFiberに魅力をあまり感じません。 一応、Fiberの流儀を使わず、callbackでも書けるので プロジェクトのコーディング規約で気をつければいいのですが。 jQueryの方は、非依存にする話もあるようですが、コアが依存しているという記述もあり、 完全に非依存になるには時間がかかりそうです。

https://groups.google.com/forum/?fromgroups=#!topic/meteor-talk/21y9NbM9v90

別に、jQuery依存だからといって困ることはないのですが、単に気分の問題です。

いずれにしても、Angualr-Meteorにはちょっと興味を持ちました。

今まで、Chromeアプリにはそれほど興味を持っていなかったのですが、 下記の記事でangular.jsと組み合わせているのを見て興味が湧きました。

https://developer.chrome.com/apps/angular_framework

これは、手軽に作れそうです。 Chromeのディベロッパーモードをオンにすると、 Chromeアプリをパッケージする前にフォルダ指定でアプリを実行できます。 しかし、コードをいじるたびにリロードボタンを押さないといけないです。

これは不便、なんとかして先日作った easy-livereload を使いたいと思って、Chromeアプリをexpressと組み合わせて 開発してみることにしました。

manifest.jsonやbackground.jsはサンプル通りに作って、 jadeはパッケージ化するときにコンパイルするようにしました。 package.jsonのscriptsはこんな感じです。

"build": "mkdir -p build; cp manifest.json public/*.js public/*.css build; jade views/main.jade --out build"

Chromeアプリのパスと合わせるようにexpessのルートを設定します。 ひと手間必要だったのは、httpで外部サイトにアクセスする場合です。 Chromeアプリではmanifest.jsonに書けば制限を外せるのですが、 expressでブラウザで動作させる場合はcross domainで引っかかります。 そこで、express側で中継するようにしました。

app.get(/^\/proxy-(http|https)\/(.*)/, function(req, res) {
  request.get(req.params[0] + '://' + req.params[1], {
    encoding: null,
    qs: req.query
  }, function(error, response, body) {
    if (!error && response.statusCode === 200) {
      res.type(response.headers['content-type']);
      res.send(body);
    } else {
      console.log(error, body);
      res.status(500).send('proxy error');
    }
  });
});

こんな感じです。場合によっては、ヘッダーなども中継する必要があるでしょう。 これをクライアント側から呼び出すときは、例えば次のようにしました。

var serverMode = $location.host() === 'localhost';
$http.get((serverMode ? 'proxy-http/' : 'http://') + 'www.foo.bar/hoge.json')

もっといい書き方があるかもしれませんが、まあとりあえずはいいでしょう。これで開発効率が格段に上がりました。

Angularのdependency injectionはminifyに弱いです。 angular.jsのチュートリアルにも書かれています。

https://code.angularjs.org/1.3.8/docs/tutorial/step_05

A Note on Minificationのセクションに、 annotationをつけると書いてあります。

しばらく悩まずこの書式で書いていましたが、これはとても気をつかいます。スペルミスや並び替えをするときなど。なによりも、同じ文字を2回タイプするのは効率が悪いです。

ngminというのは聞いたことがあったのですが、100%変換できるわけではないという噂を聞いて使っていませんでした。今ではng-annotateというツールがあります。

https://github.com/olov/ng-annotate

ngminとの違いも説明されています。うまく行かない場合のためにコメントで明示的に指示できるというのが安心感があります。

これで快適になりました。やはり、自動化できることを人がやるのは無駄ですね。

ng-annotateはminifyをしてくれないので、minifyツールと合わせて使うことになります。今回は、

https://github.com/mishoo/UglifyJS2

を使うことにしました。下記にpackage.jsonを載せます。

{
  "scripts": {
    "minify:main": "ng-annotate -a public/main.js | uglifyjs -c -m > public/main.min.js"
  },
  "devDependencies": {
    "ng-annotate": "*",
    "uglify-js": "*"
  }
}

これで、

npm run minify:main

で動きます。 grunt等を使いたい人は、対応しているプラグインを使えばできるでしょう。

AngularでBootstrapを使うライブラリとして、以前の記事では、UI Bootstrapを紹介しました。

最近、AngularStrapも使ってみたので感想を書いておきます。

AngularStrapは初期の頃に名前を聞いたことがあるような気がします。確か、bootstrap v2の時代に。今では、AngularStrapもv2になってjQuery依存がなくなりました。いい時代の流れです。

さて、AngularStrapはUI Bootstrapと比べると根本的な設計思想は似ています。どちらも、bootstrapのcssだけ再利用して、javascript部分は作り直し、jQueryには依存しない、Look&Feelのカスタマイズ性を考慮している、と言ったところです。

しかし、使ってみるとだいぶ考え方に違いがあるような気がします。 UI Bootstrapはできるだけシンプルにbootstrapのcssを使えるようにしている一方、AngularStrapはbootstrapのcssをベースにしてよりリッチな機能を提供しようとしているようです。最大の違いは、アニメーションのサポートでしょうか。

簡単な例として、Alertの違いを見てみます。最初は、UI Bootstrap。

<alert type="{{alert.type}}" close="closeAlert(alert)">{{alert.content}}</alert>

これだけです。ng-repeatを使う例がドキュメントに載っていますが、直感的です。ng-showとも組み合わせられます。

次に、AngularStrapです。いろいろあるようですが、attributeを使う例。

<button class="btn" title="{{alert.title}}" data-content="{{alert.content}}" data-type="{{alert.type}}" bs-alert>Show alert</button>

buttonではなくdivで直接表示しようと思いましたが、できませんでした。ドキュメントではできそうなので、何か間違えているのかもしれません。 ng-showは使わず、オプションか属性でshowフラグを指定します。このあたり思想が異なる感じです。durationとか指定できるのは便利です。 alertは単純な機能なので、そこまで違いませんが、他の機能はもっと違いがありそうです。

個人的には、ui-bootstrapの方が使いやすいです。しかし、AngularStrapでアニメーションが簡単に使えるのも魅力的です。使い分けることにします。

人に勧めるのはどちらがよいか迷います。勉強が目的ならui-bootstrapでしょうか、リッチな機能が欲しいならAngularStrapでしょうか。

LiveReloadをご存知でしょうか。Web開発をするときに、ブラウザのリロードを省く機能を提供するものです。 類似のものとしては、Live.jsというのもあります。 また、Meteorでも実装されています。

一言で言うと、websocketでコネクションを維持して、サーバ側のファイル変更を通知して自動でリロードするものです。 CSSの場合はリロードせずに変更を適用することもできます。 livereloadは商用のようですが、そのコアのソースコードはMITライセンスで公開されています。

livereloadはブラウザ拡張を使うことがメインのようですが、javascript版のクライアントもあります。 javascript版だと、mobile safariでも動きます。 livereloadのnode.js用のサーバは、https://github.com/livereload/livereload-serverで公開されていますが、 これはそのまますぐには使うことができません。 平たく言うとプロトコルが実装されているだけで、実際に更新通知する機能は含まれていません。

そこで、簡単に使えるライブラリとしてまとめてみました。特徴をまとめると、

  • livereloadのサーバコードの最新版を使用(現在npmに登録されているlivereload系のモジュールはほとんど旧バージョン)
  • livereloadのクライアントコードの最新版を使用(npm化されていないのでnapaというモジュールで導入)
  • fs.watch()を使ってファイル変更を迅速に監視(node-watchというモジュールを使用)
  • node-devを使うことでサーバ側のファイル変更を監視して、クライアントを自動リロードする機能を追加
  • これらの機能をたった一行を加えるだけで使えるようにパッケージ化

となります。

プロジェクトページは下記です。

https://github.com/dai-shi/easy-livereload

最低限の使い方は、

app.use(require('easy-livereload')())

ですが、細かい設定はオプションを引数に与えることでできます。

本質的には他人が作ったライブラリを結合して簡単に使えるようにしただけですが、 相当便利だと思いますので、ぜひお試しください。

MeteorでJadeのススメ

  • 投稿日:
  • by

Meteorのお話です。

Node.jsではExpressでよくjadeを使っています。

http://jade-lang.com/

なぜかjadeは好きです。RubyでHamlは使ったことがありますが、それほど好感を持った覚えはありません。なぜでしょう、%があると見栄えが悪いからでしょうか。

Meteorにもjadeのパッケージを作った人がいるようです。

https://atmospherejs.com/mquandalle/jade

これが思いのほか出来がよくて、気に入りました。 単にjadeの変換を再現しただけではなくて、Meteor用にチューンされている感じです。

インストールは、

$  meteor add mquandalle:jade

とするだけで、*.jadeファイルで書けばあとはよろしくやってくれます。上記ページに使い方は書いてありますが、いくつか転記します。

まず、テンプレート呼び出しの

{{> hello}}

は、

+hello

になります。最初はちょっと分かりにくいと思いました。慣れれば普通です。

次に、if文は、

{{if hoge}}
  <div>hello</div>
{{else}}
  <div>bye</div>
{{/if}

が、

+if hoge
  div hello
+else
  div bye

になります。この接頭辞+は省略もできるようですが、個人的には残しておいたほうが制御ブロックであることが見た目で分かりやすくてよいと思いました。else ifも独自実装しているようです。シンタックスシュガーとして。

最後にまだ実装されていないと書いてありますが、anonymous helperというのが載っています。

+if len > 0

みたいなことが書けるようになるそうです。これはとても実装されて欲しい機能です。これだけのためにhelperを書くのは手間でしょう。

以上、Meteorでjadeがすんなり使えるというお話でした。

ついでに、jade系で気になるツールを紹介します。

https://github.com/donpark/html2jade

HTMLをjadeに戻せるようです。まだ試していませんが、 これはいいですね。過去に書いたHTMLをjade化したくなります。 もし安定して使えるなら、人が書いたHTMLを一度jadeにしてから 編集して、再度HTMLに戻すということもできるかもしれません。

さらに、余談ですが、html2jadeを検索していたら、

https://github.com/vidalab/meteor-html2jade

を見つけました。何かと思ったら、html2jadeをwebで使えるようにしたMeteorアプリのようです。

最近、Angular以外も試そうと思って、2012年春にオープンソースになったときから気になっていたMeteorを使うことにしました。 当時は、FirefoxかChromeかどちらかでしか動かず、動かない方で見ると、背景画像しか見えないというすさまじいものでした。 一方、そのコンセプトはとても共感できて、social-cms-backendを自分で開発したときも同じではないものの似た問題意識でした。

さて、Meteorのサイトは、

http://meteor.com/

です。いいドメイン持ってますね。Meteorの発音は「ミーティア」です。 T.M.Revolutionの歌にありましたね。よし、それを聞きながらコーディングしよう。

さて、Meteorの基本的な説明は他に任せるとして、今回はちょっと変わった使い方をしようと思います。そもそも、普通のWebアプリを作るなら慣れたAngularの方が早いのですが、canvasベースのアプリを作りたいと思ったのがきっかけでした。canvasベースのアプリだとAngularの恩恵があまり得られないので、Angular以外を試してみようと。細かい経緯は省きますが、下記のサイトを見てやってみようと思いました。

http://www.html5gamedevs.com/topic/4886-how-to-use-phaser-with-meteor/

Phaserというのはhttp://phaser.io/で、WebGL/Canvasでゲームを作るフレームワークです。Phaserの説明も他に任せます。上記の記事はちょっと古くて、今では、

https://atmospherejs.com/robertlowe/meteor-phaser

が使えます。MeteorのパッケージがAtmosphereというのは、かっこいいですが、慣れるまでは戸惑いそうですね。

さて、お題は1bitコミュニケーションツールを考えています。 夏の暑いときに作った「暑さをみんなでふっとばせ!」というアプリを移植してみようと思います。このアプリについては、下記を参照。

1bitで使い捨てで匿名のコミュニケーションツールを作ってみた

Famo.us/AngularのサンプルアプリをGitHubに置きました

これは、Famo.us/Angularで作りました。とてもお手軽だったのですが、ちょっとゲームのようなものに使うにはパフォーマンスに難がありました。そこで今回は同じものをMeteor/Phaserで作ってみようと思います。

この記事を書きながらコーディングするのでうまく行くか分かりません。また、読みにくくなってしまうかもしれませんがご了承ください。

さて、まずはMeteorをインストールします。https://www.meteor.com/installに従います。このチュートリアルはよくできてますね。

$ curl https://install.meteor.com/ | sh

1.0.1になってroot権限も要求しなくなりました。1.0のときも、sudoのパスワードを入れなければ同じだったのですが、これはシンプルでよいです。

冬なのでアプリは「寒さをみんなでふっとばせ!」にします。ちょっとふっとばすというのは合わないかもしれませんが。アプリ名はsamufutにします。

$ meteor create samufut
$ cd samufut

チュートリアル通りです。ここで、phaserのライブラリを入れてしまいます。

$  meteor add robertlowe:meteor-phaser

これができるようになったのは最近のようですね。

$ meteor &

で起動して準備完了です。コーディング開始。


とりあえず、Phaserを使ったコードを書くところで時間がかかっています。これはあまりMeteorは関係ないところです。 一つだけ気になったこととして、本体のjsを編集すると毎回パッケージのアップデートをしようとして遅いので、Phaserのコードはclient配下に移動しました。この場合はrefreshするだけなので比較的早いです。

Meteorの話が出てくるのは明日になりそうなので、本記事はとりあえず一時保存します。


さて、一日経過しました。その後、Phaserのコードはほぼ完成し、次に通信部分のコードに着手します。Meteorは既にsockjsを使って通信を行う仕組みになっているのですが、それをアプリからも使えるとよいです。調べたところ、

http://arunoda.github.io/meteor-streams/

というのがありました。パッケージはこちらですね。

$ meteor add lepozepo:streams

でインストールします。簡単です。サンプルコードもそのまま貼り付けます。

chatStream = new Meteor.Stream('chat');

if(Meteor.isClient) {
  sendChat = function(message) {
    chatStream.emit('message', message);
    console.log('me: ' + message);
  };

  chatStream.on('message', function(message) {
    console.log('user: ' + message);
  });
}

直感的ですね。これで実装してみましょう。今回はinsecureは入れたままにします。

完成しました。コードは237行でした。 それでは、デプロイしてみます。

% meteor deploy samufut.meteor.com

できました。メールアドレスが要求されました。

しかし、このURLはgithub pagesやherokuと同じように問題になるのではないでしょうか。そのうち、*.meteorapp.comとかになるかもしれませんね。

デプロイされたサイトは、

http://samufut.meteor.com/

です。ぜひ、遊んでみてください。使い方は書きませんでしたので、暑さをみんなでふっとばせ!の方を参照してください。

少し試した範囲だと、環境によっては通信がうまく行かないケースがあるようです。遅延というか、反映されないのです。またの機会に調べましょう。

ソースコードは下記にアップしました。

https://github.com/dai-shi/samufut

当初は、もっとMeteorのことを書こうと思っていたのですが、苦労したのはPhaserまわりだったのであまり書くことがなくなってしまいました。まだ、やったことないですが、insecureを外してまじめに実装するといろいろコード量が増えて、結局大変っていうことにならないか心配です。それでも、プロトタイプが手軽に作れるのは利点だと思います。

気になったことを一つ思い出しました。普段非同期処理で書くことが多く、比較的好んでいるのですが、Meteorのクライアント側のmongoは同期的なので戸惑いました。キャッシュされているからなせるわざなのでしょうか。事前にpublishできないようなデータの場合どうなるかなど気になります。もう少し勉強しなければいけません。

それでは、Meteorの今後に期待します。


12/28追記。

sudoがいらないと思ったのは勘違いでした。たまたま、その時の環境が/usr/local/binにwrite権限があったため。

GitHub便利です。その一つが、Compare ViewのDiffです。Pull Requestを確認するときもよく見ます。コマンドラインでgit diffと普通にやるより見やすいです。

さて、背景は省略しますが、HTMLでdiffを表示したいと思いました。AngularJSでの利用を想定しているので、JavaScriptのライブラリが欲しいです。

ところが探してもあまり見つかりません。よくまとまっているのはこちら。

http://stackoverflow.com/questions/3053587/javascript-based-diff-utility

ちょっと古い投稿ですが。一番人気なのは、これです。

https://github.com/cemerick/jsdifflib

オンラインデモはこちら。

http://cemerick.github.io/jsdifflib/demo.html

だいぶ求めているもののイメージに近いです。 コードも枯れているらしい。 HTMLが出力されるので、Angularで使うならdirectiveを書かなければいけないですが、それは仕方ないですね。

これで行こうかと思ったところでしたが、なにか物足りません。 なんというか、見た目がワクワクしないのです。 改めてGitHubのDiffと比較してみると、全体的に色が濃すぎる。 あと、単語の差分がハイライトされない。色については自分でcssを書いて調整すればよいでしょうが、単語のハイライトはそれでは済みません。

というわけで、もう一度検索しました。見つけたのがこちらです。

https://github.com/rtfpessoa/diff2html

オンラインデモはこちら。

http://rtfpessoa.github.io/diff2html/

おお、おしゃれ。これですよこれ。なんとStar数は3でした。まったく注目されていません。コードも枯れていないでしょう。まだ不具合もあります。でも、魅力的です。これを使いましょう。

ところが、使うには一つ問題がありました。diff2htmlはdiffの出力を入力としているのです。例えば、

diff --git a/foo.txt b/foo.txt
---
+++
@@ -1,4 +1,5 @@
+zero
 one
 two
-three
+tree
 four

このようなものです。つまり、次はこれを出力するライブラリを探しました。いくつかありそうでしたが、比較的すんなり結合できたのはこちらです。

https://github.com/qiao/difflib.js

入力の行が配列になることと、出力の一行目のヘッダが付かないことなど不足点はありまして、それらは自力で対応しました。

最後にこれらを全部つなげて、angular.jsのdirectiveを書いてできあがりです。下記のような感じで使えるようになりました。

<my-diff path="foo.txt" old-content="one\ntwo\nthree\nfour\n" new-content="zero\none\ntwo\n\tree\nfour\n">

便利です。ちょっと気になることと言えば、依存javascriptが3ファイルもあって、グローバルに関数を定義するようなものであることです。なにかうまく隠蔽する方法があるのでしょうか。

AngularのUIライブラリにUI Bootstrapを使おう

  • 投稿日:
  • by

AngularJSの流れにちゃんとついていくためng-europeをyoutubeで見ようと思い始めて一ヶ月が過ぎてしまいました。 まだ全部は見ていませんが、今日は一本見ました。興味深かったので記事にします。

https://www.youtube.com/watch?v=tfVA1syv-3o

AngularUIのui-bootstrapのお話です。 単にラップするわけではなくAngular流に作られているのと、カスタマイズ性を重視しているあたりは参考になります。

ui-bootstrapはBootstrap 3のcssのみを利用していてjavascriptの部分は全部書き直しているようです。つまり、jQuery依存もなしです。

ちょっと昔話を。当初、Bootstrap 2を使っていたのですが、クラス名などがどうも好きになれず、その後inkというcssフレームワークを見つけて 、しばらく使っていました。

その時から、inkのcssのみを使ってコーディングしていました。ロジックが必要な場合はAngular側で自前で作ってました。 例えば、カレンダーも当初はAngularUIのui-calendarを使っていましたが、 jQuery依存に抵抗があったため、カレンダーも単純な機能ならinkで自前で実装していました。

その後、Bootstrap 3が登場し、クラス名がinkのようにシンプルになったので、少し気に入ってBootstrap 3を使い始めました。でも、cssだけで、jsは使いません。例えば、alertもロジックはangularで自前で書いていました。と言っても、あまりコーディング量は多くなく、特に困っていません。

さて、話を戻しますと、ui-bootstrapは上記でやっていたようなことをちゃんとやっているような印象です。cssだけを使って、ロジックはangular用にdirectiveを設計してあるようです。 alertを見る限りでは単純なので自前で用意しても変わりませんが、他の複雑な機能はui-bootstrapのdirectiveを使うとだいぶ楽できそうです。

というわけで、jQuery非依存のui-bootstrapはおすすめです。

夏ごろに「暑さをみんなでふっとばせ!」というアプリを作りました。

1bitで使い捨てで匿名のコミュニケーションツールを作ってみた

に経緯が書いてあります。

当時は、Famo.usやF/Aのライブラリに手を入れないといけなかったのですが、その後バージョンアップして不具合が解消されました。 新しいバージョンでは読み込み速度なども改善しています。

せっかくなので、GitHubにソースをアップロードしました。 Famo.us/Angularとsocket.ioの組み合わせでこんなことができるというサンプルによいかと思います。

ついでに、「暑」を「寒」に変更する機能もつけました。タイトルはそのままですが。

GitHubのページはこちらです。

https://github.com/dai-shi/atsufut

実際に動作しているアプリのページはこちらです。

http://atsufut.axlight.com/#?color=blue&label=%E5%AF%92

AngularJSの1.3.0がリリースされました。

これまで、1.2系を使っていたのですが、これを機に1.3も試してみようと思いました。

1.0から1.2に移行したときは、はまったのですが、今回はなにも不都合がありませんでした。

ところが、e2eテストが動かなくなってしまいました。具体的には、下記のようなテストがエラーになりました。

expect(element(by.repeater('item in list').row(0).column('{{item.name}}')).getText()).toEqual('foo');

エラー文は、

NoSuchElementError: No element found using locator: ...

です。

https://github.com/angular/protractor/blob/master/docs/api.md

のドキュメントを見ても問題なさそうですし、StackOverflowなどでも話題になっているのは見つからず、途方にくれていました。

が、試しに下記のように変更したら動きました。

expect(element(by.repeater('item in list').row(0).column('item.name')).getText()).toEqual('foo');

これって正しい解決法なのでしょうか。

自分が興味あるものの一つにコミュニケーションツールがあります。 と言っても普通のコミュニケーションではないです。 例えば、見知らぬ人と一時的なつながりを感じられるようなそんなツールがいいと思います。言語も使わず、世界のどこかの誰かと。

FacebookのPokeはよかったです。1bitで行うコミュニケーションとでも呼びましょうか。日本では「あいさつ」となり、意味が分からなくなりました。 ちなみに、Pokeは一度機能が隠れてしまったのですが、また復活しました。 最近は、Yoが流行っているらしいです。これも1bitコミュニケーションだと思います。どこまで流行るのか、気になるところです。

流行っているついでに、Snapchatについても気になるところです。 実は使ったことありませんが、これは使い捨てコミュニケーションだと思っています。 使い捨てコミュニケーションができたら面白いだろうなぁとは思っていましたが、 まさかそんなものが流行るとは想像していませんでした。 写真だからうまくいったのでしょうか。

あとは、匿名コミュニケーションにも興味あります。 最近は実名指向で、あまり匿名を重視したコミュニケーションツールは登場していないのでしょうか。

と言うわけで、前置きが長くなりましたが、1bitで使い捨てで匿名のコミュニケーションツールを作ってみようと思いました。 1bitで伝えたいことはなんだろう、と考えたその日が暑い日だったので、「暑い」にしました。 「暑い」を伝え合うだけでは、どんどん暑苦しくなるだけですので、 ストレス発散をできるような「吹き飛ばし」機能をつけることにしました。

atsufut_title.png

これがタイトル画面です。

atsufut_main.png

これがメイン画面です。これだけです。 画面の上半分をクリック(タップ)すると、丸が落ちてきます。 何度も押すと、丸がたまってきます。 次に画面の下半分をクリックすると、丸を吹き飛ばします。 それだけです。

それでは、やってみましょう。

http://atsufut.axlight.com/

このURLをスマホで開きましょう。PCでも大丈夫です。モダンブラウザ必須です。

一人でやると、すぐに飽きます。 複数人で同時にやるとまあまあ面白いとは思います。 しかし、たまたま同時に開いている人がいることは稀です。 ここをどうするかが悩みどころです。

今回、開発に利用したライブラリは、 node.js, socket.io, angular.js, famo.us あたりです。

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

  • 投稿日:
  • by

もうちょっとすばやくサンプルを作ってみるつもりがのんびりしてしまいました。

前回に引き続き、famo.us Physicsを使ったサンプルです。

3次元の物理演算もできるはずなので、Z軸も使った簡単なサンプルが作れないかと思ってやってみました。

こちら

当初、普通に回したらsurfaceの裏は真っ白で、180度回ると何も見えなくなってしまいました。そこで、仕方なく、各円を反対方向に回すことで表示しました。もっといい方法があればいいのですが。

また、遠くのsurfaceを縮小表示する方法が分かりませんでした。これができればだいぶ立体感がでると思うのですが。physicsとtransformを混ぜて使ってはいけないのかもしれません。

Famo.us Universityのphysicsコースは未だcoming soonのままです。

今回のサンプルのソースコードはこちらです。

Angularにng-touchstartが無かったので作ってみた

  • 投稿日:
  • by

angular.jsの話です。突然ですが、ng-clickというのはクリックが完了したときに実行され、ng-mousedownというのは押しただけで実行されます。しかし、ng-mousedownはタッチパネルでは発火しません。mousedownイベントはマウスだけであり、タブレットやスマートフォンのブラウザではtouchstartイベントがあります。なので、てっきりng-touchstartというのが用意されているものと思っていました。

が、それは勘違いでした。少なくとも現時点では。 ng-clickより細かい制御をしたかったので、ng-touchstartはどうしても欲しいです。

ところで、angular.jsのdirectiveはとても協力ですが、アプリケーション実装するときにdirective開発するのは無駄だと思っています。標準で用意されたdirectiveとcontrollerで済むことが多いです。directiveは再利用性が高いものを開発するときに使うものでしょう。アプリではなくライブラリ開発するときですね。

ところが、アプリ開発しているときにどうしてもng-touchstartが欲しくなってしまったので、directive書いてみました。今まで食わず嫌いでしたが、簡単なdirectiveなら書いてみるとすっきりすることもあるな、とちょっと考え直しました。

というわけで、開発したdirectiveを貼り付けておきます。

angular.module('MyModule').directive('myTouchstart', ['$parse', '$swipe',
  function($parse, $swipe) {
    return {
      restrict: 'A',
      link: function(scope, element, attrs) {
        var handler = $parse(attrs.myTouchstart);
        $swipe.bind(element, {
          start: function() {
            scope.$apply(function() {
              handler(scope);
            });
          }
        });
      }
    };
  }
]);

これだと、touchstartとmousedown両方に反応するのですが、ちゃんとやるならそのあたりも制御した方がいいですね。あと、touchstartだけでなく、touchmoveとtouchendもあったほうがいいでしょう。そこまでやったら、pullreqできそうです。というか、もう誰かがやっているのではないでしょうか。

これが一番近そうです。

https://github.com/angular/angular.js/issues/5334

まだ解決していない模様。確かに、ng-mousedownをoverrideしてもいいかもしれません。名前が直感的ではないですが。