2015年03月28日

React.js入門1

posted by ねこまんま at 08:25 | Comment(0) | TrackBack(0) | React | 更新情報をチェックする

2015年02月22日

SUIT CSS

SUIT CSSはコンポーネントベースのCSS設計手法。ReactやEmber、 AngularといったコンポーネントベースのUI設計と相性がよい。個人的にはBEMよりこちらの設計手法のほうが使いやすい

SUIT CSSはCSSのclassの命名規則CSS preprocessor(プリプロセッサー)などで定義される。続きを読む
タグ:CSS suit
posted by ねこまんま at 07:30 | Comment(0) | TrackBack(0) | CSS | 更新情報をチェックする

2014年08月28日

RequireJS 入門

RequireJSはJavaScriptをモジュール開発するためのツール。

JavaScriptはグローバル領域が共通なので複数のモジュールを利用しようとするとバッティングするおそれがある。基本的にはグローバル使うな!となるが他のモジュールなどでどの名前空間を使うかなど色々決めなくてはいけない。

var Fuga = function() {};

var NameSpace = {}
NameSpace.Fuga = function() {}


RequireJSを使うとコレを簡単にすることができる。

まず、以下の様なディレクトリ構成だと考える。script/module/fuga.jsとscript/module/hoge.jsが独立したモジュールである

.
├── index.html
└── script
├── lib
│   ├── jquery-1.11.1.min.js
│   └── require.js
├── main.js
└── module
   ├── fuga.js
   └── hoge.js

まず、index.htmlではrequire.jsを読みこみ、data-main属性にメインのスクリプトのURLを記述する。

<script data-main="script/main.js" src="script/lib/require.js"></script>


まず、main.jsに以下のように設定してみよう。module/fuga.jsの読み込みが終了した際にコールバック関数が実行されます。

require([
'module/fuga'
], function(fuga) {
console.log(fuga.doo())
});


fuga.jsには以下のように記述してみる。

define({
bar:"fuga",
foo:"hoge",
doo:function(){
return this.bar+this.foo
}
});


main.jsがfuga.jsを読み込み、defineの定義内容はdefine()で指定ができる。これは以下のように記述することもできる。

define(function(){
var fuga = {
bar:"fuga",
foo:"hoge",
doo:function(){
return this.bar+this.foo
}
}
return fuga;
});


他のモジュールやライブラリを参照して利用したい場合は以下のように記述を行う。

define([
'lib/jquery-1.11.1.min'
], function(){
var fuga = {
bar:"fuga",
foo:"hoge",
doo:function(){
return this.bar+this.foo+$("body").text();
}
}
return fuga;
});
タグ:RequireJS
posted by ねこまんま at 17:54 | Comment(0) | TrackBack(0) | 開発環境・ツール | 更新情報をチェックする

2014年08月27日

GruntでJade

GruntでJadeをコンパイルしようとすると以下のようにする。ただこれだと対象ファイルが増えるたびに手動でGruntfile.jsにファイルを追加していかなくていはいけない。

module.exports = function(grunt) {
grunt.initConfig({
jade: {
compile: {
files: {
"dest/sample1.html": ["jade/sample1.jade"],
"dest/sample2.html": ["jade/sample2.jade"],
"dest/sample3.html": ["jade/sample3.jade"],
}
}
}
});
}


これは以下のようにするとjadeディレクトリ内のjadeファイルが更新された際にdestに書きだすようにすることができる。

module.exports = function(grunt) {
grunt.initConfig({
jade: {
compile: {
files: [ {
expand: true,
cwd: "jade/",
src: "*.jade",
dest: "dest/",
ext: ".html"
}]
}
}
});
}


あと、以下のように指定するとjadeディレクトリにある_xxx.jadeみないなアンスコ付きのファイルはコンパイル対象化から外すことができる。

module.exports = function(grunt) {
grunt.initConfig({
jade: {
compile: {
files: [ {
expand: true,
cwd: "jade/",
src: [
"*.jade",
"!_*.jade"
],
dest: "dest/",
ext: ".html"
}]
}
}
});
}


Gruntは面倒くさいので、みんなgulpを使おうよ。
タグ:Grunt JADE
posted by ねこまんま at 12:36 | Comment(0) | TrackBack(0) | Grunt | 更新情報をチェックする

jasmine-jqueryとkarmaでの自動テスト

jasmineのfixture(テスト用のHTMLをロードする奴)であるjasmine-jquerykarmaを利用しようとする色々とハマったのでメモ。

まず、karmaではconfigのfilesに指定したファイルしか読み込みが出来ない。そこでkarma.conf.jsのfilesにfixturesで読み込むURLを指定しなくてはいけない。オプションでincluded:falseを指定しないと初回で読み込まれてしまうので注意。

module.exports = function(config) {
config.set({
(中略)
files: [
'module/lib/jquery-1.11.1.js',
'module/lib/underscore-min.js',
'module/lib/backbone-min.js',
(中略)
{ pattern: 'fixtures/*.inc', included: false }
],
(中略)
});
}



また、filesで指定したファイルはbaseディレクトリ配下に読み込まれるので以下のようにKarma経由の場合(ポート番号9876)とブラウザ経由の場合でfixturesPathパスを変更する必要がある。

if(location.port==9876){
jasmine.getFixtures().fixturesPath = 'base/fixtures/';
}else{
jasmine.getFixtures().fixturesPath = '../fixtures/';
}


一番ハマったのは以下のコマンドでインストールした「karma-jasmine」のバージョンが古かったこと。jasmine-jqueryの組み合わせるとclearTimeoutがundefinedとか訳の分からないエラーが出てしまった

npm install karma-jasmine --save-dev


以下のコマンドじゃないと2系のkarma-jasmineはインストール出来ない

npm install karma-jasmine@2_0 --save-dev
posted by ねこまんま at 11:52 | Comment(0) | TrackBack(0) | test | 更新情報をチェックする

2014年08月08日

Selenium入門

Seleniumの使い方。

まずはRuby Gemをインストール

gem install selenium-webdriver


test.rbなど適当なファイル名で以下の内容を記述。

require "selenium-webdriver"
# Firefox用のドライバを使う
driver = Selenium::WebDriver.for :firefox
# Googleにアクセス
driver.navigate.to "http://google.com"
# `q`というnameを持つ要素を取得
element = driver.find_element(:name, 'q')
# `Hello WebDriver!`という文字を、上記で取得したinput要素に入力
element.send_keys "Hello WebDriver!"
# submitを実行する(つまり検索する)
element.submit
# 表示されたページのタイトルをコンソールに出力
puts driver.title
# テストを終了する(ブラウザを終了させる)
driver.quit


以下のコマンドでSeleniumが実行される。

ruby tesr.rb


参考:WebのUIテスト自動化 - Seleniumを使ってみる - Qiita

ちょっと上記のスクリプトだと表示が微妙だったが以下のコードのほうが良さげだった。

require "selenium-webdriver"
driver = Selenium::WebDriver.for :firefox
driver.get "http://www.google.co.jp/"
driver.find_element(:class,"gsfi").send_key "Selenium"
driver.find_element(:name,"btnK").submit
driver.close


参考:Ruby - Selenium 入門 - Qiita
タグ:Selenium
posted by ねこまんま at 15:08 | Comment(0) | TrackBack(0) | test | 更新情報をチェックする

Karmaでmocha + chaiのテストを自動化

Karma + を利用すればテストが自動化できるので自動化してみました。

ひとまずはkarmaをインストール。

npm install -g karma
karma --version


このままでは「-bash: karma: command not found」と怒られてしまうのでkarma-cliもインストール。

npm install -g karma-cli
karma --version


これでちゃんとバージョンが表示される。

Karma version: 0.12.21


まずは設定ファイルの作成。対話式で作成できます。

karma init


まず、

Which testing framework do you want to use ?
Press tab to list possible options. Enter to move to the next question.

と利用するフレームワークについて聞かれる。QUnitJasmineMochaから選択できるのでひとまずはMochaを選択(tabか下ボタンで候補をきりかえられます)

次に、

Do you want to use Require.js ?
This will add Require.js plugin.
Press tab to list possible options. Enter to move to the next question.

Require.jsを利用するかどうか聞かれます。「no」でEnter

Do you want to capture a browser automatically ?
Press tab to list possible options. Enter empty string to move to the next question.

次に、利用するブラウザを聞かれます。PhantomJSでヘッドレステストなんかもできますがターゲットブラウザ以外でテストするのもあれなのでChromeとFirefoxを選択。(WinならIEとかも指定するとよいかも)

What is the location of your source and test files ?
You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".
Enter empty string to move to the next question.

次にスクリプトの場所が聞かれます。"js/*.js" or "test/**/*Spec.js"みたいにして読み込むファイルを指定しましょう。
ちなみにChaiやSinon.JS、jQueryなんかMocha以外にライブラリも指定しておく必要があります。

あと、mocha.run();を実行しているファイルを読み込んじゃうとテストが2回走ってしまいます。ここでハマった。

Should any of the files included by the previous patterns be excluded ?
You can use glob patterns, eg. "**/*.swp".
Enter empty string to move to the next question.

swpファイルの出力場所が聞かれます。これは無視。

Do you want Karma to watch all the files and run the tests on change ?
Press tab to list possible options.

ファイルを監視するか聞かれるので「yes」。

これで「karma.conf.js」が作られます。

karma start


と打つと自動でブラウザが立ち上がりテストが開始されます。また、監視ファイルが更新された際にも再テストが自動で行われます。
タグ:KARMA mocha chai test
posted by ねこまんま at 11:26 | Comment(0) | TrackBack(0) | test | 更新情報をチェックする

2014年08月05日

Mocha+Chai+Sinon.JS 入門

最近注目のテストフレームワーク「Mocha」、軽量ですがアサーション機能すらありませんので別のライブラリを組み合わせて使うのが一般的。今回はアサーションライブラリとして「Chai」とテストタブル用にSinon.JSをチョイス。

Mocha



Mochaはnode.jsでも利用できますがクライアントJavaScriptではGitHubからダウンロードしたmocha.cssとmocha.jsを読み込みます、今回はChaiとSinon.JSを読み込んだ以下のテンプレートで解説をします。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="mocha.css">
</head>
<body>
<div id="mocha"></div>
<script src="mocha.js"></script>
<script src="chai.js"></script>
<script src="sinon-1.10.3.js"></script>
<script>
mocha.setup('bdd');
var expect = chai.expect;
window.onload = function() {
mocha.run();
};
</script>
<script src="テストするコード"></script>
<script src="テストコード"></script>
<div id="sandbox"></div>
</body>
</html>


以下の箇所ではmochaの設定でスタイルをBDD(ビヘイビア駆動開発 )にしてchaiのexpectを利用するようにしています。

mocha.setup('bdd');
var expect = chai.expect;
window.onload = function() {
mocha.run();
};



テストコードではJasmineと同じようにdescribe()で見出しをつけて記述していきます。

describe('テスト内容', function() {
//テストコード
});


describe()は入れ子でも利用できます。

describe('テスト内容1', function() {
describe('テスト内容1-1', function() {
//テストコード
});
describe('テスト内容1-2', function() {
//テストコード
});
});


テストはit()を利用して記述します。

describe('テスト内容', function() {
it("メソッドが存在する", function() {
//テストコード
});
});


実際のテストでは以下のアサーションメソッドを利用利します。

describe('テスト内容', function() {
it("aがおんなじ", function() {
expect("a").to.equal("a");
});
});


これでブラウザを見ればテストが成功しているのがわかります。

chaiの利用方法



mochaはBDDを利用する場合はJasmineと利用方法が変わらないので問題ないでしょう。chaiは少し利用方法が違います。

.toや.equalといったメソッドをチェーンさせながら記述します。

たとえば以下のように.notを追加することでaとbは同じじゃない、つまり異なることをテストしています。

describe('テスト内容', function() {
it("aとbがちがう", function() {
expect("a").to.not.equal("b");
});
});


参考:Expect / Should - Chai

Sinon.JSの使い方



Sinon.JSはテストダブルを行うことができます。

たとえば次のような謎のメソッドがあったとします。

var a = function(){
b();
}
var b = function(){
return "b";
}


a.b()のテストは以下の様な感じでできます。

it("bのテスト", function() {
var value = b();
expect(value).to.equal("b");
});


しかし、a()のテストはできません。a()ではb()が実行されているかテストしたいのです。Sinon.JSを利用すると以下のようにテストできます。

it("aのテスト", function() {
var spy = sinon.spy(window,'b');
a();
expect(spy.callCount).to.equal(1);
});
posted by ねこまんま at 21:41 | Comment(0) | TrackBack(0) | test | 更新情報をチェックする

Jasmine入門

Jasmineは様々な機能が盛り込まれた汎用型のJavaScriptテストフレームワーク。

ダウンロードしたファイルの中からdist/jasmine-standalone-2.0.1.zipを解凍して利用します。以下のようにtest用のHTMLを作成しします。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jasmine Example</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-2.0.1/jasmine_favicon.png">
<link rel="stylesheet" href="lib/jasmine-2.0.1/jasmine.css">
<script src="lib/jasmine-2.0.1/jasmine.js"></script>
<script src="lib/jasmine-2.0.1/jasmine-html.js"></script>
<script src="lib/jasmine-2.0.1/boot.js"></script>
<script src="テストするJS"></script>
<script>
//テストコード
</script>
</head>
<body>
</body>
</html>


テストコードではdescribe()で見出しをつけて記述していきます。

describe('テスト内容', function() {
//テストコード
});


describe()は入れ子でも利用できます。

describe('テスト内容1', function() {
describe('テスト内容1-1', function() {
//テストコード
});
describe('テスト内容1-2', function() {
//テストコード
});
});



テストはit()を利用して記述します。

describe('テスト内容', function() {
it("メソッドが存在する", function() {
//テストコード
});
});


実際のテストでは以下のアサーションメソッドを利用利します。

expect(A).toEqual(B)

expect(A).toEqual(B)でAとBの値が等しいかテストを行います。

describe('テスト内容', function() {
it('expect("a").toEqual("a")', function() {
expect("a").toEqual("a");
});
});


expect(A).toBe(B)

expect(A).toBe(B)でAとBが同じオブジェクトかテストを行います。

以下の場合は異なるオブジェクトとしてテストは失敗します。

describe('テスト内容', function() {
it('expect(bar1).toBe(bar2)', function() {
var bar1 = {"foo":"daaa"};
var bar2 = {"foo":"daaa"};
expect(bar1).toBe(bar2);
});
});


以下の場合は同じオブジェクトとしてテストは成功します。

describe('テスト内容', function() {
it('expect(bar1).toBe(bar2)', function() {
var bar1 = {"foo":"daaa"};
var bar2 = bar1;
expect(bar1).toBe(bar2);
});
});


expext(A).toBeDefined()

expext(A).toBeDefined()ではAが定義されているかテストをします。

以下の場合はbar1は定義されていないのでテストは失敗します。

describe('テスト内容', function() {
it('expect(bar1).toBeDefined()', function() {
expect(bar1).toBeDefined();
});
});


以下の場合はbar1は定義されているのでテストは成功します。

describe('テスト内容', function() {
it('expect(bar1).toBeDefined()', function() {
var bar1="aa";
expect(bar1).toBeDefined();
});
});


他にも、

expect(A).toBeNull()でAがNULLであるかテストを行う
expect(A).toBeTruthy()でAがtrueであるかテストを行う
expect(A).toBeFalsy()でAがfalseであるかテストを行う
expect(A).toContain(B)でAにBが含まれているかテストを行う
expect(A).toBeLessThan(B)でAよりBが小さいかテストを行う
expect(A).toBeGreaterThan(b)でBよりAが小さいかテストを行う
expect(fn).toThrow(e)でfnが例外をスローするかテストを行う

などが可能です。

beforeEach()やafterEach()を利用するとit()が実行される前後に処理を差し込むことができます。

次のようなコードを実行すると

describe('テスト内容', function() {
beforeEach(function(){
console.log("beforeEach");
});
it('test1', function() {
console.log("test1");
expect("a").toEqual("a");
});
it('test2', function() {
console.log("test2");
expect("a").toEqual("a");
});
afterEach(function(){
console.log("afterEach");
});
});


以下の様にコンソールが表示されます

beforeEach
test1
afterEach
beforeEach
test2
afterEach


参考 : JasmineによるJavaScriptのテスト その4 « サーバーワークス エンジニアブログ
タグ:test JASMINE
posted by ねこまんま at 17:15 | Comment(0) | TrackBack(0) | test | 更新情報をチェックする

2014年07月31日

gulpでJadeをコンパイル

基本は「タスクランナーgulp入門 - to-R」を参考に。

以下がgulpでJadeをコンパイルする為の処理。

gulp.task('jade', function () {
gulp.src('htdocs/jade/**/*.jade')
.pipe(jade())
.pipe(gulp.dest('htdocs/'));
});


ただし、このままだとincludeファイルなども書き出してしまう。

以下のようにすると_付きのファイルは出力されなくなります。

gulp.task('jade', function () {
gulp.src(['htdocs/jade/**/*.jade','!htdocs/jade/**/_*.jade'])
.pipe(jade())
.pipe(gulp.dest('htdocs/'));
});
タグ:JADE GULP
posted by ねこまんま at 15:36 | Comment(0) | TrackBack(0) | gulp | 更新情報をチェックする

2014年07月30日

QUnit入門

JavaScriptテストフレームワークの「QUnit」について解説します。

まずはQUnitのJSファイルとCSSファイルを読み込みます。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>QUnit Example</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
<script>
//コード
</script>
<script>
//テストコード
</script>
</body>
</html>


以下、コードとテストコードの別けて解説していきます。

QUnitではQUnit.test( )でテストを定義できます。第1引数にテストの名前、第2引数にコールバック関数としてテストの内容を記述します。

QUnit.test( "hello test", function( assert ) {
assert.ok( 1 == "1", "Passed!" );
});


コールバック関数内ではassertオブジェクトを利用できます。

assert.ok()では第1引数でstate(boolean値に変換されたもの)、第2引数にメッセージを指定できます。

以下のサンプルでは最初に2つのassert.ok( )以外は失敗を返します。

QUnit.test( "hello test", function( assert ) {
assert.ok( true, "true succeeds" );
assert.ok( "non-empty", "non-empty string succeeds" );
assert.ok( false, "false fails" );
assert.ok( 0, "0 fails" );
assert.ok( NaN, "NaN fails" );
assert.ok( "", "empty string fails" );
assert.ok( null, "null fails" );
assert.ok( undefined, "undefined fails" );
});


他にもassert.deepEqual()で第1引数と第2引数に与えられたオブジェクトが同一の値を持つか確認したり、

QUnit.test( "deepEqual test", function( assert ) {
var obj = { foo: "bar" };
assert.deepEqual( obj, { foo: "bar" }, "Two objects can be the same in value" );
});


assert.equal()で値が同じかどうか確認できます。

QUnit.test( "equal test", function( assert ) {
assert.equal( 0, 0, "Zero, Zero; equal succeeds" );
assert.equal( "", 0, "Empty, Zero; equal succeeds" );
assert.equal( "", "", "Empty, Empty; equal succeeds" );
assert.equal( "three", 3, "Three, 3; equal fails" );
assert.equal( null, false, "null, false; equal fails" );
});


expect()でテストの回数を指定できます。expect( 2 )と指定すると2回assertがsuccessを返さなければ失敗とみなします。

QUnit.test( "a test", function( assert ) {
expect( 2 );
function calc( x, operation ) {
return operation( x );
}
var result = calc( 2, function( x ) {
assert.ok( true, "calc() calls operation function" );
return x * x;
});
assert.equal( result, 4, "2 squared equals 4" );
});


イベントの確認はtriggerを利用して確認。

QUnit.test( "a test", function( assert ) {
expect( 1 );
var $body = $( "body" );
$body.on( "click", function() {
assert.ok( true, "body was clicked!" );
});
$body.trigger( "click" );
});


非同期のテストはQUnit.asyncTest()QUnit.start()を利用する。

QUnit.asyncTest( "asynchronous test: one second later!", function( assert ) {
expect( 1 );
setTimeout(function() {
assert.ok( true, "Passed and ready to resume!" );
QUnit.start();
}, 1000);
});


タグ:テスト QUnit test
posted by ねこまんま at 20:20 | Comment(0) | TrackBack(0) | test | 更新情報をチェックする

WebRTCで通信を中断させる

WebRTCで通信を中断させる方法。ストリームの送信側のRTCPeerConnectionオブジェクトからlocalStreamを取り出し、removeStream()を利用してストリームを取り出します。そうすると送信先のストリームオブジェクトにメディアストリームが除かれる形になり、addStream()でストリームを復元することができる。

var localStream = peer.getLocalStreams()[0];
$(".stop").click(function(){
peer.removeStream(localstream);
});
$(".start").click(function(){
peer.addStream(localstream);
});
タグ:WebRTC HTML5
posted by ねこまんま at 14:35 | Comment(0) | TrackBack(0) | HTML5 | 更新情報をチェックする

2014年07月17日

Knockout-es5でrateLimitを設定する

Knockout-ES5はKnockout.jsをES5のgetter/setterに対応してくれる便利なプラグイン。ただrateLimitなどの標準の機能を利用しようとするとちょっと工夫が必要。

ko.track(this);
ko.getObservable(this, 'fuga').extend({ rateLimit: 100 });


ko.track()した後にko.getObservable()でrateLimitを設定したいオブジェクトを取得してからextendで機能拡張を行うとOK。
posted by ねこまんま at 15:13 | Comment(0) | TrackBack(0) | Knockout.js | 更新情報をチェックする

Socket.IOでクライアントサイドのデバッグを行う

Socket.IOでのデバッグが以外と面倒臭かったのでメモ書き。

以下のようにsocket.on()のコールバック関数内でエラーが出ても、JavaScriptコンソール内にエラーが表示されない。謎にSocket.IOが新しいコネクションを張ります。

socket.on('fuga', function (data) {
//ここでJavaScriptエラー
});


ソースコード中に以下のようにlocalStorage.debugに*を入れておくとコンソール上に様々な情報が表示されるようになる。

localStorage.debug = '*';


ただ、表示されるログは非常に多いので以下のようにすると絞り込むことができる。(ただ、まだ多い)

localStorage.debug = 'socket.io-client:socket';


これにどのコールバック関数でエラーが出ているか、どのようなエラーが出ているかが含まれているのでそれを参考にデバッグ。行数とか教えてくれないので想像力をかなり働かせなくてはエラーが見つけられないので注意。
タグ:socket.io
posted by ねこまんま at 15:08 | Comment(0) | TrackBack(0) | HTML5 | 更新情報をチェックする

2014年07月09日

Knockout入門2

Knockout入門1の続き、Knockout : Computed Observablesの内容を確認していく。

以下のようにAppViewModelコンストラクタを使ってインスタンスをko.applyBindings()で監視。

<span data-bind="text: firstName"></span>
<span data-bind="text: lastName"></span>
<script>
function AppViewModel() {
this.firstName = ko.observable('Bob');
this.lastName = ko.observable('Smith');
}
ko.applyBindings(new AppViewModel());
</script>


以下のようにko.computed()を使ってfirstNameとlastNameからfullNameというプロパティを作成する。

function AppViewModel() {
this.firstName = ko.observable('Bob');
this.lastName = ko.observable('Smith');
this.fullName = ko.computed(function() {
return this.firstName() + " " + this.lastName();
}, this);
}
ko.applyBindings(new AppViewModel());


次のようにthisを変数selfの中に入れておいて参照することも可能。

function AppViewModel() {
var self = this;
self.firstName = ko.observable('Bob');
self.lastName = ko.observable('Smith');
self.fullName = ko.computed(function() {
return self.firstName() + " " + self.lastName();
});
}
ko.applyBindings(new AppViewModel());


次のように指定することも可能。

function AppViewModel() {
this.firstName = ko.observable('Bob');
this.lastName = ko.observable('Smith');
}
var myViewModel = new AppViewModel()
myViewModel.fullName = ko.computed(function() {
return myViewModel.firstName() + " " + myViewModel.lastName();
})
ko.applyBindings(myViewModel);
myViewModel.firstName("fuga");


このままではfullName()はあくまで読み取り専用である。以下のようにすることで書き込みも可能になる。
(lastIndexOf()で半角スペースがあるか判定してsubstring()でその前後を抽出)

function MyViewModel() {
this.firstName = ko.observable('Planet');
this.lastName = ko.observable('Earth');
this.fullName = ko.computed({
read: function () {
return this.firstName() + " " + this.lastName();
},
write: function (value) {
var lastSpacePos = value.lastIndexOf(" ");
if (lastSpacePos > 0) { // Ignore values with no space character
this.firstName(value.substring(0, lastSpacePos)); // Update "firstName"
this.lastName(value.substring(lastSpacePos + 1)); // Update "lastName"
}
},
owner: this
});
}
var myViewModel = new MyViewModel();
ko.applyBindings(myViewModel);
myViewModel.fullName("hoge fuga");


ここからは別サンプル。formattedPriceは数値を$123.00といったフォーマットに整形して表示する機能。toFixed()で少数表示に対応している。priceプロパティにはあくまで数値が格納されているがformattedPriceでそれを$表記に変更して出力している。

<p>Enter bid price: <input data-bind="value: formattedPrice"/></p>
<script>
function MyViewModel() {
this.price = ko.observable(25.99);
this.formattedPrice = ko.computed({
read: function () {
return '$' + this.price().toFixed(2);
},
write: function (value) {
// Strip out unwanted characters, parse as float, then write the raw data back to the underlying "price" observable
value = parseFloat(value.replace(/[^\.\d]/g, ""));
this.price(isNaN(value) ? 0 : value); // Write to underlying storage
},
owner: this
});
}
ko.applyBindings(new MyViewModel());
</script>


次のサンプルは入力フォーム(attemptedValue)の値が数値の場合はlastInputWasValid()がfalseをそうでない場合あtrueを返す

<p>Enter a numeric value: <input data-bind="value: attemptedValue"/></p>
<div data-bind="visible: !lastInputWasValid()">That's not a number!</div>
<script>
function MyViewModel() {
this.acceptedNumericValue = ko.observable(123);
this.lastInputWasValid = ko.observable(true);
this.attemptedValue = ko.computed({
read: this.acceptedNumericValue,
write: function (value) {
if (isNaN(value))
this.lastInputWasValid(false);
else {
this.lastInputWasValid(true);
this.acceptedNumericValue(value); // Write to underlying storage
}
},
owner: this
});
}
ko.applyBindings(new MyViewModel());
</script>
タグ:KNOCKOUT
posted by ねこまんま at 06:38 | Comment(0) | TrackBack(0) | Knockout.js | 更新情報をチェックする

Knockout入門1

Knockoutをお仕事で使うのでメモ。

Knockout入門1ではKnockout : Observablesを読みながら基本機能の確認。

まず、以下のようにCDNからサクッと読み込める

<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0.js"></script>


最新の3.1は以下のCDNで配布されている。

<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script>


まずは基本のko.applyBindings()を使ってみる。ko.applyBindings()はオブジェクトの内容をDOMに反映させるメソッド。

<span data-bind="text: personName"></span>
<span data-bind="text: personAge"></span>
<script>
var myViewModel = {
personName: 'Bob',
personAge: 123
};
ko.applyBindings(myViewModel);
</script>


上記のように記述するとspanの内容が以下のように書き換えられる。

<span data-bind="text: personName">Bob</span>
<span data-bind="text: personAge">123</span>


つぎにデータバインディングの醍醐味であるko.observable()。上記のスクリプトを下記のように変更。

最初は画面にBobと表示される。myViewModel.personName()のように引数に何も入れなければプロパティの取得が可能で、myViewModel.personName("Tomy")のように引数に値を入れればプロパティの内容の変更が可能。変更を行うと即座にHTML上に反映させられる。

var myViewModel = {
personName: ko.observable('Bob'),
personAge: ko.observable('123')
};
ko.applyBindings(myViewModel);
alert(myViewModel.personName());
myViewModel.personName("Tomy");


subscribe()で変更をscript側で感知することも可能

var myViewModel = {
personName: ko.observable('Bob'),
personAge: ko.observable('123')
};
ko.applyBindings(myViewModel);
myViewModel.personName.subscribe(function(newValue) {
alert("The person's new name is " + newValue);
});
myViewModel.personName("Tomy");


変更直前にスクリプトを実行したい場合は以下のように第3引数に"beforeChange"を記述する。

var myViewModel = {
personName: ko.observable('Bob'),
personAge: ko.observable('123')
};
ko.applyBindings(myViewModel);
myViewModel.personName.subscribe(function(oldValue) {
alert("The person's previous name is " + oldValue);
}, null, "beforeChange");
myViewModel.personName("Tomy");


ちなみに第2引数にはコールバック関数内のthisで利用するオブジェクトが指定できる。以下のように指定をすると「hogeBob」とアラートが表示される。

var myViewModel = {
personName: ko.observable('Bob'),
personAge: ko.observable('123')
};
ko.applyBindings(myViewModel);
myViewModel.personName.subscribe(function(oldValue) {
alert(this.fuga + oldValue);
}, {"fuga":"hoge"}, "beforeChange");
myViewModel.personName("Tomy");


バインドしたsubscribeイベントはdispose();で破棄することができる。"Tomy1"への変更の時点ではアラートがでるが"Tomy2"への変更ではアラートが表示されない。

var myViewModel = {
personName: ko.observable('Bob'),
personAge: ko.observable('123')
};
ko.applyBindings(myViewModel);
var subscription = myViewModel.personName.subscribe(function(newValue) {
alert("The person's new name is " + newValue);
});
myViewModel.personName("Tomy1");
subscription.dispose();
myViewModel.personName("Tomy2");


subscribeイベントは基本的には変更があった場合に発火する。たとえば次のケースではpersonNameをBob→Bobに変更しているので変更がないとみなされてアラートは表示されない。

var myViewModel = {
personName: ko.observable('Bob'),
personAge: ko.observable('123')
};
ko.applyBindings(myViewModel);
var subscription = myViewModel.personName.subscribe(function(newValue) {
alert("The person's new name is " + newValue);
});
myViewModel.personName("Bob");


ただし、この挙動はextend({ notify: 'always' })を指定することで変更でき、同じ値でもsubscribeイベントを発火させることができる。

var myViewModel = {
personName: ko.observable('Bob'),
personAge: ko.observable('123')
};
ko.applyBindings(myViewModel);
myViewModel.personName.extend({ notify: 'always' });
var subscription = myViewModel.personName.subscribe(function(newValue) {
alert("The person's new name is " + newValue);
});
myViewModel.personName("Bob");


他にも、extend({ rateLimit: Number })などがある。これは変更のタイミングを制御するための機能です(Knockout 3.1より追加)。

以下のように記述するとsubscribeイベントは4回発火する。

var myViewModel = {
personName: ko.observable('Bob'),
personAge: ko.observable('123')
};
ko.applyBindings(myViewModel);
var subscription = myViewModel.personName.subscribe(function(newValue) {
alert("The person's new name is " + newValue);
});
myViewModel.personName("Bob1");
myViewModel.personName("Bob2");
myViewModel.personName("Bob3");
myViewModel.personName("Bob4");


これを以下のようにextend({ rateLimit: 50 })を追加すると変更のタイミングは50ms秒後になり、アラートは「Bob4」のみが表示されるようになる。

var myViewModel = {
personName: ko.observable('Bob'),
personAge: ko.observable('123')
};
ko.applyBindings(myViewModel);
var subscription = myViewModel.personName.subscribe(function(newValue) {
alert("The person's new name is " + newValue);
});
myViewModel.personName.extend({ rateLimit: 50 });
myViewModel.personName("Bob1");
myViewModel.personName("Bob2");
myViewModel.personName("Bob3");
myViewModel.personName("Bob4");


ひとまず、Knockout入門1はこんなかんじでKnockout入門2に続く。
タグ:KNOCKOUT
posted by ねこまんま at 06:05 | Comment(0) | TrackBack(0) | Knockout.js | 更新情報をチェックする

2014年07月04日

video要素の内容をcanvasを使って画像に変換する

次のような感じでvideo要素の内容をcanvasに変換してからData URIに変換する

var getVideoCapture = function(video){
var canvas = document.createElement("canvas");
canvas.width = video.width;
canvas.height = video.height;
var context = canvas.getContext("2d");
context.drawImage(video, 0, 0, canvas.width, canvas.height);
var getVideoCaptureURL = canvas.toDataURL();
delete canvas;
return getVideoCaptureURL;
}
posted by ねこまんま at 16:32 | Comment(0) | TrackBack(0) | HTML5 | 更新情報をチェックする

2014年05月29日

MacでMongoDBを利用する

MongoDBのインストール



まずはHomebrewを利用してMongoDBをインストール

brew install mongodb


インストールが終わったら指示にしたがって以下のコマンドを実行

ln -s /usr/local/opt/mongodb/*.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.mongodb.plist
mongod


以下のコマンドでバージョンが表示されたらインストールは成功

mongo -version


MongoDBの利用方法



以下のコマンドでMongoDBが起動します。

mongo


対話モードに移るので以下のコマンドで「mydb」という新しいDBを作成できる

use mydb


以下のコマンドでDBに新しいデータを突っ込めて

db.mydata.save({hoge:"hogeの内容",fuga:"fugaの内容"})


保存したデータを取得するには以下のコマンドを実行する

db.mydata.save()
タグ:MongoDB
posted by ねこまんま at 18:04 | Comment(0) | TrackBack(0) | 開発環境・ツール | 更新情報をチェックする

2014年05月12日

御蔵入gulpタスク

作ったgulpタスクが使えなかったのでメモがてら残しておく。

やりたかったのはsassファイルなどが追加された際に、style.scssに@importでそのファイルを追加し更新して、その更新をトリガーにSassを再構築するというもの。仕組み自体はできたんだけども日本語のファイル名のファイルをインポートしようとするとSassがコンパイル時にエラーを吐くというので詰んだ。style2 のコピー.scssなんかのファイルがディレクトリ内に入るとSassのコンパイルエラーが出てgulpが落ちてしまうので使えない。

Sassのコンパイルエラーが出てもgulpが落ちないようにしたら使えそうな気もするけどひとまず御蔵入。

//Create main Sass File
gulp.task('createMainSassFile', function () {
var mainSassFile = config.path.sass+'/style.scss';
var newFile = '@charset "UTF-8";\n';
var length = 0;
var fileCheck = function(dir, cb){
fs.readdir(dir+"/.", function(err, files){
if (err) throw err;
if(length!=0)--length;
length += files.length;
files.forEach(function (file) {
var file = dir+"/"+file;
if(fs.statSync(file).isDirectory()){
fileCheck(file, cb);
}else if(!file.match(/.scss$/) || file==mainSassFile){
if(--length===0)cb();
}else{
newFile += '@import "'+file.replace(config.path.sass+"/","")+'";\n';
if(--length===0)cb();
}

});
});
}
fileCheck(config.path.sass,function(){
var fd = fs.openSync(mainSassFile, "w");
fs.writeSync(fd, newFile, 0, "UTF-8");
fs.closeSync(fd);
});

});
タグ:node.js GULP
posted by ねこまんま at 23:28 | Comment(1) | TrackBack(0) | node.js | 更新情報をチェックする

2014年05月01日

gulpをインストールしようとしたらエラーがでた件

結論から言うとnpmのバージョンが古かったのでインストールできなかったので以下のコマンドでupdateしてやればインストールできました。

npm install -g npm


インストール出来ない場合には以下の様なエラーがでます。

0 info it worked if it ends with ok
1 verbose cli [ '/Users/xxx/.nodebrew/current/bin/node',
1 verbose cli '/Users/xxx/.nodebrew/current/bin/npm',
1 verbose cli 'install',
1 verbose cli '-g',
1 verbose cli 'gulp' ]
2 info using npm@1.2.32
3 info using node@v0.10.12
4 verbose node symlink /Users/xxx/.nodebrew/current/bin/node
5 verbose read json /Users/xxx/.nodebrew/current/lib/package.json
6 verbose read json /Users/xxx/.nodebrew/current/lib/package.json
7 verbose cache add [ 'gulp', null ]
8 verbose cache add name=undefined spec="gulp" args=["gulp",null]
9 verbose parsed url { protocol: null,
9 verbose parsed url slashes: null,
9 verbose parsed url auth: null,
9 verbose parsed url host: null,
9 verbose parsed url port: null,
9 verbose parsed url hostname: null,
9 verbose parsed url hash: null,
9 verbose parsed url search: null,
9 verbose parsed url query: null,
9 verbose parsed url pathname: 'gulp',
9 verbose parsed url path: 'gulp',
9 verbose parsed url href: 'gulp' }
10 silly lockFile 9750c68d-gulp gulp
11 verbose lock gulp /Users/xxx/.npm/9750c68d-gulp.lock
12 silly lockFile 9750c68d-gulp gulp
13 silly lockFile 9750c68d-gulp gulp
14 verbose addNamed [ 'gulp', '' ]
15 verbose addNamed [ null, '' ]
16 silly lockFile 72f4391e-gulp gulp@
17 verbose lock gulp@ /Users/xxx/.npm/72f4391e-gulp.lock
18 silly addNameRange { name: 'gulp', range: '', hasData: false }
19 verbose url raw gulp
20 verbose url resolving [ 'https://registry.npmjs.org/', './gulp' ]
21 verbose url resolved https://registry.npmjs.org/gulp
22 info trying registry request attempt 1 at 12:39:01
23 verbose etag "2OKLP8BA8TBYIR1REW7VCG8II"
24 http GET https://registry.npmjs.org/gulp
25 http 304 https://registry.npmjs.org/gulp
26 silly registry.get cb [ 304,
26 silly registry.get { date: 'Thu, 01 May 2014 03:39:02 GMT',
26 silly registry.get server: 'Apache',
26 silly registry.get via: '1.1 varnish',
26 silly registry.get 'last-modified': 'Thu, 01 May 2014 03:39:02 GMT',
26 silly registry.get 'cache-control': 'max-age=1',
26 silly registry.get etag: '"2OKLP8BA8TBYIR1REW7VCG8II"',
26 silly registry.get 'x-served-by': 'cache-ty66-TYO',
26 silly registry.get 'x-cache': 'MISS',
26 silly registry.get 'x-cache-hits': '0',
26 silly registry.get 'x-timer': 'S1398915542.410850763,VS0,VE262',
26 silly registry.get vary: 'Accept',
26 silly registry.get 'content-length': '0',
26 silly registry.get 'keep-alive': 'timeout=10, max=50',
26 silly registry.get connection: 'Keep-Alive' } ]
27 verbose etag gulp from cache
28 silly addNameRange number 2 { name: 'gulp', range: '', hasData: true }
29 silly addNameRange versions [ 'gulp',
29 silly addNameRange [ '0.0.1',
29 silly addNameRange '0.0.2',
29 silly addNameRange '0.0.3',
29 silly addNameRange '0.0.4',
29 silly addNameRange '0.0.5',
29 silly addNameRange '0.0.7',
29 silly addNameRange '0.0.8',
29 silly addNameRange '0.0.9',
29 silly addNameRange '0.1.0',
29 silly addNameRange '0.2.0',
29 silly addNameRange '1.0.0',
29 silly addNameRange '1.1.0',
29 silly addNameRange '1.2.0',
29 silly addNameRange '1.2.1',
29 silly addNameRange '2.0.0',
29 silly addNameRange '2.0.1',
29 silly addNameRange '2.1.0',
29 silly addNameRange '2.2.0',
29 silly addNameRange '2.3.0',
29 silly addNameRange '2.4.0',
29 silly addNameRange '2.4.1',
29 silly addNameRange '2.6.0',
29 silly addNameRange '2.6.1',
29 silly addNameRange '2.7.0',
29 silly addNameRange '3.0.0',
29 silly addNameRange '3.1.1',
29 silly addNameRange '3.1.2',
29 silly addNameRange '3.1.3',
29 silly addNameRange '3.1.4',
29 silly addNameRange '3.2.0',
29 silly addNameRange '3.2.1',
29 silly addNameRange '3.2.2',
29 silly addNameRange '3.2.3',
29 silly addNameRange '3.2.4',
29 silly addNameRange '3.2.5',
29 silly addNameRange '3.3.0',
29 silly addNameRange '3.3.1',
29 silly addNameRange '3.3.2',
29 silly addNameRange '3.3.4',
29 silly addNameRange '3.4.0',
29 silly addNameRange '3.5.0',
29 silly addNameRange '3.5.1',
29 silly addNameRange '3.5.2',
29 silly addNameRange '3.5.5',
29 silly addNameRange '3.5.6',
29 silly addNameRange '3.6.0',
29 silly addNameRange '3.6.1',
29 silly addNameRange '3.6.2' ] ]
30 verbose addNamed [ 'gulp', '3.6.2' ]
31 verbose addNamed [ '3.6.2', '3.6.2' ]
32 silly lockFile 078bc9ff-gulp-3-6-2 gulp@3.6.2
33 verbose lock gulp@3.6.2 /Users/xxx/.npm/078bc9ff-gulp-3-6-2.lock
34 verbose read json /Users/xxx/.npm/gulp/3.6.2/package/package.json
35 silly lockFile 078bc9ff-gulp-3-6-2 gulp@3.6.2
36 silly lockFile 078bc9ff-gulp-3-6-2 gulp@3.6.2
37 silly lockFile 72f4391e-gulp gulp@
38 silly lockFile 72f4391e-gulp gulp@
39 silly resolved [ { name: 'gulp',
39 silly resolved description: 'The streaming build system',
39 silly resolved version: '3.6.2',
39 silly resolved homepage: 'http://gulpjs.com',
39 silly resolved repository: { type: 'git', url: 'gulpjs/gulp' },
39 silly resolved author:
39 silly resolved { name: 'Fractal',
39 silly resolved email: 'contact@wearefractal.com',
39 silly resolved url: 'http://wearefractal.com/' },
39 silly resolved tags: [ 'build', 'stream', 'system', 'make', 'tool', 'asset', 'pipeline' ],
39 silly resolved files: [ 'index.js', 'lib', 'bin', 'completion' ],
39 silly resolved bin: { gulp: './bin/gulp.js' },
39 silly resolved dependencies:
39 silly resolved { archy: '^0.0.2',
39 silly resolved chalk: '^0.4.0',
39 silly resolved deprecated: '^0.0.1',
39 silly resolved 'gulp-util': '^2.2.0',
39 silly resolved liftoff: '^0.9.3',
39 silly resolved orchestrator: '^0.3.0',
39 silly resolved 'pretty-hrtime': '^0.2.0',
39 silly resolved semver: '^2.2.1',
39 silly resolved tildify: '^0.2.0',
39 silly resolved 'vinyl-fs': '^0.1.3' },
39 silly resolved devDependencies:
39 silly resolved { mocha: '^1.17.0',
39 silly resolved 'mocha-lcov-reporter': '^0.0.1',
39 silly resolved coveralls: '^2.7.0',
39 silly resolved istanbul: '^0.2.3',
39 silly resolved should: '^3.1.0',
39 silly resolved rimraf: '^2.2.5',
39 silly resolved q: '^1.0.0',
39 silly resolved jshint: '^2.5.0',
39 silly resolved 'graceful-fs': '^2.0.1',
39 silly resolved mkdirp: '^0.3.5' },
39 silly resolved scripts:
39 silly resolved { test: 'jshint && mocha --reporter spec',
39 silly resolved coveralls: 'istanbul cover _mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage' },
39 silly resolved engineStrict: true,
39 silly resolved engines: { node: '>= 0.9' },
39 silly resolved licenses: [ [Object] ],
39 silly resolved readme: '<p align="center">\n <a href="http://gulpjs.com">\n <img height="194" width="98" src="https://raw.github.com/gulpjs/artwork/master/gulp.png"/>\n </a>\n</p>\n\n# gulp [![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Support us][gittip-image]][gittip-url] [![Build Status][travis-image]][travis-url] [![Coveralls Status][coveralls-image]][coveralls-url]\n> The streaming build system\n\n## Like what we do?\n\n[Support us via gittip](https://www.gittip.com/WeAreFractal/)\n\n## Documentation\n\nFor a Getting started guide, API docs, recipes, making a plugin, etc. see the [documentation page](/docs/README.md)!\n\n## Sample gulpfile\n\nThis file is just a quick sample to give you a taste of what gulp does.\n\n```javascript\nvar gulp = require(\'gulp\');\n\nvar coffee = require(\'gulp-coffee\');\nvar concat = require(\'gulp-concat\');\nvar uglify = require(\'gulp-uglify\');\nvar imagemin = require(\'gulp-imagemin\');\n\nvar paths = {\n scripts: [\'client/js/**/*.coffee\', \'!client/external/**/*.coffee\'],\n images: \'client/img/**/*\'\n};\n\ngulp.task(\'scripts\', function() {\n // Minify and copy all JavaScript (except vendor scripts)\n return gulp.src(paths.scripts)\n .pipe(coffee())\n .pipe(uglify())\n .pipe(concat(\'all.min.js\'))\n .pipe(gulp.dest(\'build/js\'));\n});\n\n// Copy all static images\ngulp.task(\'images\', function() {\n return gulp.src(paths.images)\n // Pass in options to the task\n .pipe(imagemin({optimizationLevel: 5}))\n .pipe(gulp.dest(\'build/img\'));\n});\n\n// Rerun the task when a file changes\ngulp.task(\'watch\', function() {\n gulp.watch(paths.scripts, [\'scripts\']);\n gulp.watch(paths.images, [\'images\']);\n});\n\n// The default task (called when you run `gulp` from cli)\ngulp.task(\'default\', [\'scripts\', \'images\', \'watch\']);\n\n```\n\n## Incremental Builds\n\nWe recommend these plugins:\n\n- [gulp-changed](https://github.com/sindresorhus/gulp-changed)\n- [gulp-cached](https://github.com/wearefractal/gulp-cached)\n- [gulp-newer](https://github.com/tschaub/gulp-newer)\n- [gulp-remember](https://github.com/ahaurw01/gulp-remember)\n\n## Want to contribute?\n\nAnyone can help make this project better - check out the [Contributing guide](/CONTRIBUTING.md)!\n\n\n[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/wearefractal/gulp/trend.png)](https://bitdeli.com/free "Bitdeli Badge")\n\n[gittip-url]: https://www.gittip.com/WeAreFractal/\n[gittip-image]: http://img.shields.io/gittip/WeAreFractal.svg\n\n[downloads-image]: http://img.shields.io/npm/dm/gulp.svg\n[npm-url]: https://npmjs.org/package/gulp\n[npm-image]: http://img.shields.io/npm/v/gulp.svg\n\n[travis-url]: https://travis-ci.org/gulpjs/gulp\n[travis-image]: http://img.shields.io/travis/gulpjs/gulp.svg\n\n[coveralls-url]: https://coveralls.io/r/gulpjs/gulp\n[coveralls-image]: http://img.shields.io/coveralls/gulpjs/gulp/master.svg\n',
39 silly resolved readmeFilename: 'README.md',
39 silly resolved _id: 'gulp@3.6.2',
39 silly resolved _from: 'gulp@' } ]
40 info install gulp@3.6.2 into /Users/xxx/.nodebrew/current/lib
41 info installOne gulp@3.6.2
42 verbose from cache /Users/xxx/.npm/gulp/3.6.2/package/package.json
43 info /Users/xxx/.nodebrew/current/lib/node_modules/gulp unbuild
44 verbose read json /Users/xxx/.nodebrew/current/lib/node_modules/gulp/package.json
45 verbose tar unpack /Users/xxx/.npm/gulp/3.6.2/package.tgz
46 silly lockFile aeedfb3c-ew-current-lib-node-modules-gulp tar:///Users/xxx/.nodebrew/current/lib/node_modules/gulp
47 verbose lock tar:///Users/xxx/.nodebrew/current/lib/node_modules/gulp /Users/xxx/.npm/aeedfb3c-ew-current-lib-node-modules-gulp.lock
48 silly lockFile 030068b2-azuma-npm-gulp-3-6-2-package-tgz tar:///Users/xxx/.npm/gulp/3.6.2/package.tgz
49 verbose lock tar:///Users/xxx/.npm/gulp/3.6.2/package.tgz /Users/xxx/.npm/030068b2-azuma-npm-gulp-3-6-2-package-tgz.lock
50 silly gunzTarPerm modes [ '755', '644' ]
51 silly gunzTarPerm extractEntry package.json
52 silly gunzTarPerm extractEntry README.md
53 silly gunzTarPerm extractEntry index.js
54 silly gunzTarPerm extractEntry bin/gulp.js
55 silly gunzTarPerm extractEntry completion/README.md
56 silly gunzTarPerm extractEntry completion/bash
57 silly gunzTarPerm extractEntry completion/zsh
58 silly gunzTarPerm extractEntry lib/completion.js
59 silly gunzTarPerm extractEntry lib/taskTree.js
60 verbose read json /Users/xxx/.nodebrew/current/lib/node_modules/gulp/package.json
61 silly lockFile aeedfb3c-ew-current-lib-node-modules-gulp tar:///Users/xxx/.nodebrew/current/lib/node_modules/gulp
62 silly lockFile aeedfb3c-ew-current-lib-node-modules-gulp tar:///Users/xxx/.nodebrew/current/lib/node_modules/gulp
63 silly lockFile 030068b2-azuma-npm-gulp-3-6-2-package-tgz tar:///Users/xxx/.npm/gulp/3.6.2/package.tgz
64 silly lockFile 030068b2-azuma-npm-gulp-3-6-2-package-tgz tar:///Users/xxx/.npm/gulp/3.6.2/package.tgz
65 info preinstall gulp@3.6.2
66 verbose from cache /Users/xxx/.nodebrew/current/lib/node_modules/gulp/package.json
67 verbose readDependencies using package.json deps
68 verbose from cache /Users/xxx/.nodebrew/current/lib/node_modules/gulp/package.json
69 verbose readDependencies using package.json deps
70 verbose cache add [ 'archy@^0.0.2', null ]
71 verbose cache add name=undefined spec="archy@^0.0.2" args=["archy@^0.0.2",null]
72 verbose parsed url { protocol: null,
72 verbose parsed url slashes: null,
72 verbose parsed url auth: null,
72 verbose parsed url host: null,
72 verbose parsed url port: null,
72 verbose parsed url hostname: null,
72 verbose parsed url hash: null,
72 verbose parsed url search: null,
72 verbose parsed url query: null,
72 verbose parsed url pathname: 'archy@^0.0.2',
72 verbose parsed url path: 'archy@^0.0.2',
72 verbose parsed url href: 'archy@^0.0.2' }
73 verbose cache add name="archy" spec="^0.0.2" args=["archy","^0.0.2"]
74 verbose parsed url { protocol: null,
74 verbose parsed url slashes: null,
74 verbose parsed url auth: null,
74 verbose parsed url host: null,
74 verbose parsed url port: null,
74 verbose parsed url hostname: null,
74 verbose parsed url hash: null,
74 verbose parsed url search: null,
74 verbose parsed url query: null,
74 verbose parsed url pathname: '^0.0.2',
74 verbose parsed url path: '^0.0.2',
74 verbose parsed url href: '^0.0.2' }
75 verbose addNamed [ 'archy', '^0.0.2' ]
76 verbose addNamed [ null, null ]
77 silly lockFile bdbf708d-archy-0-0-2 archy@^0.0.2
78 verbose lock archy@^0.0.2 /Users/xxx/.npm/bdbf708d-archy-0-0-2.lock
79 verbose cache add [ 'chalk@^0.4.0', null ]
80 verbose cache add name=undefined spec="chalk@^0.4.0" args=["chalk@^0.4.0",null]
81 verbose parsed url { protocol: null,
81 verbose parsed url slashes: null,
81 verbose parsed url auth: null,
81 verbose parsed url host: null,
81 verbose parsed url port: null,
81 verbose parsed url hostname: null,
81 verbose parsed url hash: null,
81 verbose parsed url search: null,
81 verbose parsed url query: null,
81 verbose parsed url pathname: 'chalk@^0.4.0',
81 verbose parsed url path: 'chalk@^0.4.0',
81 verbose parsed url href: 'chalk@^0.4.0' }
82 verbose cache add name="chalk" spec="^0.4.0" args=["chalk","^0.4.0"]
83 verbose parsed url { protocol: null,
83 verbose parsed url slashes: null,
83 verbose parsed url auth: null,
83 verbose parsed url host: null,
83 verbose parsed url port: null,
83 verbose parsed url hostname: null,
83 verbose parsed url hash: null,
83 verbose parsed url search: null,
83 verbose parsed url query: null,
83 verbose parsed url pathname: '^0.4.0',
83 verbose parsed url path: '^0.4.0',
83 verbose parsed url href: '^0.4.0' }
84 verbose addNamed [ 'chalk', '^0.4.0' ]
85 verbose addNamed [ null, null ]
86 silly lockFile b2f4396d-chalk-0-4-0 chalk@^0.4.0
87 verbose lock chalk@^0.4.0 /Users/xxx/.npm/b2f4396d-chalk-0-4-0.lock
88 info addNameTag [ 'archy', '^0.0.2' ]
89 verbose cache add [ 'deprecated@^0.0.1', null ]
90 verbose cache add name=undefined spec="deprecated@^0.0.1" args=["deprecated@^0.0.1",null]
91 verbose parsed url { protocol: null,
91 verbose parsed url slashes: null,
91 verbose parsed url auth: null,
91 verbose parsed url host: null,
91 verbose parsed url port: null,
91 verbose parsed url hostname: null,
91 verbose parsed url hash: null,
91 verbose parsed url search: null,
91 verbose parsed url query: null,
91 verbose parsed url pathname: 'deprecated@^0.0.1',
91 verbose parsed url path: 'deprecated@^0.0.1',
91 verbose parsed url href: 'deprecated@^0.0.1' }
92 verbose cache add name="deprecated" spec="^0.0.1" args=["deprecated","^0.0.1"]
93 verbose parsed url { protocol: null,
93 verbose parsed url slashes: null,
93 verbose parsed url auth: null,
93 verbose parsed url host: null,
93 verbose parsed url port: null,
93 verbose parsed url hostname: null,
93 verbose parsed url hash: null,
93 verbose parsed url search: null,
93 verbose parsed url query: null,
93 verbose parsed url pathname: '^0.0.1',
93 verbose parsed url path: '^0.0.1',
93 verbose parsed url href: '^0.0.1' }
94 verbose addNamed [ 'deprecated', '^0.0.1' ]
95 verbose addNamed [ null, null ]
96 silly lockFile 0e32a569-deprecated-0-0-1 deprecated@^0.0.1
97 verbose lock deprecated@^0.0.1 /Users/xxx/.npm/0e32a569-deprecated-0-0-1.lock
98 verbose cache add [ 'gulp-util@^2.2.0', null ]
99 verbose cache add name=undefined spec="gulp-util@^2.2.0" args=["gulp-util@^2.2.0",null]
100 verbose parsed url { protocol: null,
100 verbose parsed url slashes: null,
100 verbose parsed url auth: null,
100 verbose parsed url host: null,
100 verbose parsed url port: null,
100 verbose parsed url hostname: null,
100 verbose parsed url hash: null,
100 verbose parsed url search: null,
100 verbose parsed url query: null,
100 verbose parsed url pathname: 'gulp-util@^2.2.0',
100 verbose parsed url path: 'gulp-util@^2.2.0',
100 verbose parsed url href: 'gulp-util@^2.2.0' }
101 verbose cache add name="gulp-util" spec="^2.2.0" args=["gulp-util","^2.2.0"]
102 verbose parsed url { protocol: null,
102 verbose parsed url slashes: null,
102 verbose parsed url auth: null,
102 verbose parsed url host: null,
102 verbose parsed url port: null,
102 verbose parsed url hostname: null,
102 verbose parsed url hash: null,
102 verbose parsed url search: null,
102 verbose parsed url query: null,
102 verbose parsed url pathname: '^2.2.0',
102 verbose parsed url path: '^2.2.0',
102 verbose parsed url href: '^2.2.0' }
103 verbose addNamed [ 'gulp-util', '^2.2.0' ]
104 verbose addNamed [ null, null ]
105 silly lockFile b0a108b6-gulp-util-2-2-0 gulp-util@^2.2.0
106 verbose lock gulp-util@^2.2.0 /Users/xxx/.npm/b0a108b6-gulp-util-2-2-0.lock
107 info addNameTag [ 'chalk', '^0.4.0' ]
108 info addNameTag [ 'deprecated', '^0.0.1' ]
109 verbose cache add [ 'liftoff@^0.9.3', null ]
110 verbose cache add name=undefined spec="liftoff@^0.9.3" args=["liftoff@^0.9.3",null]
111 verbose parsed url { protocol: null,
111 verbose parsed url slashes: null,
111 verbose parsed url auth: null,
111 verbose parsed url host: null,
111 verbose parsed url port: null,
111 verbose parsed url hostname: null,
111 verbose parsed url hash: null,
111 verbose parsed url search: null,
111 verbose parsed url query: null,
111 verbose parsed url pathname: 'liftoff@^0.9.3',
111 verbose parsed url path: 'liftoff@^0.9.3',
111 verbose parsed url href: 'liftoff@^0.9.3' }
112 verbose cache add name="liftoff" spec="^0.9.3" args=["liftoff","^0.9.3"]
113 verbose parsed url { protocol: null,
113 verbose parsed url slashes: null,
113 verbose parsed url auth: null,
113 verbose parsed url host: null,
113 verbose parsed url port: null,
113 verbose parsed url hostname: null,
113 verbose parsed url hash: null,
113 verbose parsed url search: null,
113 verbose parsed url query: null,
113 verbose parsed url pathname: '^0.9.3',
113 verbose parsed url path: '^0.9.3',
113 verbose parsed url href: '^0.9.3' }
114 verbose addNamed [ 'liftoff', '^0.9.3' ]
115 verbose addNamed [ null, null ]
116 silly lockFile e16e48d9-liftoff-0-9-3 liftoff@^0.9.3
117 verbose lock liftoff@^0.9.3 /Users/xxx/.npm/e16e48d9-liftoff-0-9-3.lock
118 info addNameTag [ 'gulp-util', '^2.2.0' ]
119 info addNameTag [ 'liftoff', '^0.9.3' ]
120 verbose cache add [ 'orchestrator@^0.3.0', null ]
121 verbose cache add name=undefined spec="orchestrator@^0.3.0" args=["orchestrator@^0.3.0",null]
122 verbose parsed url { protocol: null,
122 verbose parsed url slashes: null,
122 verbose parsed url auth: null,
122 verbose parsed url host: null,
122 verbose parsed url port: null,
122 verbose parsed url hostname: null,
122 verbose parsed url hash: null,
122 verbose parsed url search: null,
122 verbose parsed url query: null,
122 verbose parsed url pathname: 'orchestrator@^0.3.0',
122 verbose parsed url path: 'orchestrator@^0.3.0',
122 verbose parsed url href: 'orchestrator@^0.3.0' }
123 verbose cache add name="orchestrator" spec="^0.3.0" args=["orchestrator","^0.3.0"]
124 verbose parsed url { protocol: null,
124 verbose parsed url slashes: null,
124 verbose parsed url auth: null,
124 verbose parsed url host: null,
124 verbose parsed url port: null,
124 verbose parsed url hostname: null,
124 verbose parsed url hash: null,
124 verbose parsed url search: null,
124 verbose parsed url query: null,
124 verbose parsed url pathname: '^0.3.0',
124 verbose parsed url path: '^0.3.0',
124 verbose parsed url href: '^0.3.0' }
125 verbose addNamed [ 'orchestrator', '^0.3.0' ]
126 verbose addNamed [ null, null ]
127 silly lockFile 74d9c599-orchestrator-0-3-0 orchestrator@^0.3.0
128 verbose lock orchestrator@^0.3.0 /Users/xxx/.npm/74d9c599-orchestrator-0-3-0.lock
129 verbose url raw archy
130 verbose url resolving [ 'https://registry.npmjs.org/', './archy' ]
131 verbose url resolved https://registry.npmjs.org/archy
132 info trying registry request attempt 1 at 12:39:02
133 verbose etag "8G937WVUQ9MMZVXIHKCSTNOPR"
134 http GET https://registry.npmjs.org/archy
135 verbose url raw chalk
136 verbose url resolving [ 'https://registry.npmjs.org/', './chalk' ]
137 verbose url resolved https://registry.npmjs.org/chalk
138 info trying registry request attempt 1 at 12:39:02
139 verbose etag "8N90ZCS3GC42U2PJJKL158M7V"
140 http GET https://registry.npmjs.org/chalk
141 verbose cache add [ 'pretty-hrtime@^0.2.0', null ]
142 verbose cache add name=undefined spec="pretty-hrtime@^0.2.0" args=["pretty-hrtime@^0.2.0",null]
143 verbose parsed url { protocol: null,
143 verbose parsed url slashes: null,
143 verbose parsed url auth: null,
143 verbose parsed url host: null,
143 verbose parsed url port: null,
143 verbose parsed url hostname: null,
143 verbose parsed url hash: null,
143 verbose parsed url search: null,
143 verbose parsed url query: null,
143 verbose parsed url pathname: 'pretty-hrtime@^0.2.0',
143 verbose parsed url path: 'pretty-hrtime@^0.2.0',
143 verbose parsed url href: 'pretty-hrtime@^0.2.0' }
144 verbose cache add name="pretty-hrtime" spec="^0.2.0" args=["pretty-hrtime","^0.2.0"]
145 verbose parsed url { protocol: null,
145 verbose parsed url slashes: null,
145 verbose parsed url auth: null,
145 verbose parsed url host: null,
145 verbose parsed url port: null,
145 verbose parsed url hostname: null,
145 verbose parsed url hash: null,
145 verbose parsed url search: null,
145 verbose parsed url query: null,
145 verbose parsed url pathname: '^0.2.0',
145 verbose parsed url path: '^0.2.0',
145 verbose parsed url href: '^0.2.0' }
146 verbose addNamed [ 'pretty-hrtime', '^0.2.0' ]
147 verbose addNamed [ null, null ]
148 silly lockFile 3ac7556f-pretty-hrtime-0-2-0 pretty-hrtime@^0.2.0
149 verbose lock pretty-hrtime@^0.2.0 /Users/xxx/.npm/3ac7556f-pretty-hrtime-0-2-0.lock
150 verbose cache add [ 'semver@^2.2.1', null ]
151 verbose cache add name=undefined spec="semver@^2.2.1" args=["semver@^2.2.1",null]
152 verbose parsed url { protocol: null,
152 verbose parsed url slashes: null,
152 verbose parsed url auth: null,
152 verbose parsed url host: null,
152 verbose parsed url port: null,
152 verbose parsed url hostname: null,
152 verbose parsed url hash: null,
152 verbose parsed url search: null,
152 verbose parsed url query: null,
152 verbose parsed url pathname: 'semver@^2.2.1',
152 verbose parsed url path: 'semver@^2.2.1',
152 verbose parsed url href: 'semver@^2.2.1' }
153 verbose cache add name="semver" spec="^2.2.1" args=["semver","^2.2.1"]
154 verbose parsed url { protocol: null,
154 verbose parsed url slashes: null,
154 verbose parsed url auth: null,
154 verbose parsed url host: null,
154 verbose parsed url port: null,
154 verbose parsed url hostname: null,
154 verbose parsed url hash: null,
154 verbose parsed url search: null,
154 verbose parsed url query: null,
154 verbose parsed url pathname: '^2.2.1',
154 verbose parsed url path: '^2.2.1',
154 verbose parsed url href: '^2.2.1' }
155 verbose addNamed [ 'semver', '^2.2.1' ]
156 verbose addNamed [ null, null ]
157 silly lockFile d8627689-semver-2-2-1 semver@^2.2.1
158 verbose lock semver@^2.2.1 /Users/xxx/.npm/d8627689-semver-2-2-1.lock
159 verbose cache add [ 'tildify@^0.2.0', null ]
160 verbose cache add name=undefined spec="tildify@^0.2.0" args=["tildify@^0.2.0",null]
161 verbose parsed url { protocol: null,
161 verbose parsed url slashes: null,
161 verbose parsed url auth: null,
161 verbose parsed url host: null,
161 verbose parsed url port: null,
161 verbose parsed url hostname: null,
161 verbose parsed url hash: null,
161 verbose parsed url search: null,
161 verbose parsed url query: null,
161 verbose parsed url pathname: 'tildify@^0.2.0',
161 verbose parsed url path: 'tildify@^0.2.0',
161 verbose parsed url href: 'tildify@^0.2.0' }
162 verbose cache add name="tildify" spec="^0.2.0" args=["tildify","^0.2.0"]
163 verbose parsed url { protocol: null,
163 verbose parsed url slashes: null,
163 verbose parsed url auth: null,
163 verbose parsed url host: null,
163 verbose parsed url port: null,
163 verbose parsed url hostname: null,
163 verbose parsed url hash: null,
163 verbose parsed url search: null,
163 verbose parsed url query: null,
163 verbose parsed url pathname: '^0.2.0',
163 verbose parsed url path: '^0.2.0',
163 verbose parsed url href: '^0.2.0' }
164 verbose addNamed [ 'tildify', '^0.2.0' ]
165 verbose addNamed [ null, null ]
166 silly lockFile b2e10727-tildify-0-2-0 tildify@^0.2.0
167 verbose lock tildify@^0.2.0 /Users/xxx/.npm/b2e10727-tildify-0-2-0.lock
168 verbose cache add [ 'vinyl-fs@^0.1.3', null ]
169 verbose cache add name=undefined spec="vinyl-fs@^0.1.3" args=["vinyl-fs@^0.1.3",null]
170 verbose parsed url { protocol: null,
170 verbose parsed url slashes: null,
170 verbose parsed url auth: null,
170 verbose parsed url host: null,
170 verbose parsed url port: null,
170 verbose parsed url hostname: null,
170 verbose parsed url hash: null,
170 verbose parsed url search: null,
170 verbose parsed url query: null,
170 verbose parsed url pathname: 'vinyl-fs@^0.1.3',
170 verbose parsed url path: 'vinyl-fs@^0.1.3',
170 verbose parsed url href: 'vinyl-fs@^0.1.3' }
171 verbose cache add name="vinyl-fs" spec="^0.1.3" args=["vinyl-fs","^0.1.3"]
172 verbose parsed url { protocol: null,
172 verbose parsed url slashes: null,
172 verbose parsed url auth: null,
172 verbose parsed url host: null,
172 verbose parsed url port: null,
172 verbose parsed url hostname: null,
172 verbose parsed url hash: null,
172 verbose parsed url search: null,
172 verbose parsed url query: null,
172 verbose parsed url pathname: '^0.1.3',
172 verbose parsed url path: '^0.1.3',
172 verbose parsed url href: '^0.1.3' }
173 verbose addNamed [ 'vinyl-fs', '^0.1.3' ]
174 verbose addNamed [ null, null ]
175 silly lockFile 27790ca9-vinyl-fs-0-1-3 vinyl-fs@^0.1.3
176 verbose lock vinyl-fs@^0.1.3 /Users/xxx/.npm/27790ca9-vinyl-fs-0-1-3.lock
177 info addNameTag [ 'orchestrator', '^0.3.0' ]
178 verbose url raw deprecated
179 verbose url resolving [ 'https://registry.npmjs.org/', './deprecated' ]
180 verbose url resolved https://registry.npmjs.org/deprecated
181 info trying registry request attempt 1 at 12:39:02
182 verbose etag "9K35WQCJOF7AXVG5WF6XI54C8"
183 http GET https://registry.npmjs.org/deprecated
184 info addNameTag [ 'pretty-hrtime', '^0.2.0' ]
185 info addNameTag [ 'semver', '^2.2.1' ]
186 info addNameTag [ 'tildify', '^0.2.0' ]
187 info addNameTag [ 'vinyl-fs', '^0.1.3' ]
188 verbose url raw gulp-util
189 verbose url resolving [ 'https://registry.npmjs.org/', './gulp-util' ]
190 verbose url resolved https://registry.npmjs.org/gulp-util
191 info trying registry request attempt 1 at 12:39:02
192 verbose etag "2IOSKPA6BYL3MDIVAI8M2PA9D"
193 http GET https://registry.npmjs.org/gulp-util
194 verbose url raw liftoff
195 verbose url resolving [ 'https://registry.npmjs.org/', './liftoff' ]
196 verbose url resolved https://registry.npmjs.org/liftoff
197 info trying registry request attempt 1 at 12:39:02
198 verbose etag "BE36708E06SQIZE939E1VUZ2Q"
199 http GET https://registry.npmjs.org/liftoff
200 verbose url raw pretty-hrtime
201 verbose url resolving [ 'https://registry.npmjs.org/', './pretty-hrtime' ]
202 verbose url resolved https://registry.npmjs.org/pretty-hrtime
203 info trying registry request attempt 1 at 12:39:02
204 verbose etag "EXBKHX110EX1PZMJGJK47SP0Q"
205 http GET https://registry.npmjs.org/pretty-hrtime
206 verbose url raw semver
207 verbose url resolving [ 'https://registry.npmjs.org/', './semver' ]
208 verbose url resolved https://registry.npmjs.org/semver
209 info trying registry request attempt 1 at 12:39:02
210 verbose etag "WOQCOHS95XWY6XL8H45AFWGP"
211 http GET https://registry.npmjs.org/semver
212 verbose url raw tildify
213 verbose url resolving [ 'https://registry.npmjs.org/', './tildify' ]
214 verbose url resolved https://registry.npmjs.org/tildify
215 info trying registry request attempt 1 at 12:39:02
216 verbose etag "7RTIQ6D5Y2SCN3J4CIQCX3FT0"
217 http GET https://registry.npmjs.org/tildify
218 verbose url raw orchestrator
219 verbose url resolving [ 'https://registry.npmjs.org/', './orchestrator' ]
220 verbose url resolved https://registry.npmjs.org/orchestrator
221 info trying registry request attempt 1 at 12:39:02
222 verbose etag "COVT4T4ZXHD6ZW8G88Z3CK9U3"
223 http GET https://registry.npmjs.org/orchestrator
224 verbose url raw vinyl-fs
225 verbose url resolving [ 'https://registry.npmjs.org/', './vinyl-fs' ]
226 verbose url resolved https://registry.npmjs.org/vinyl-fs
227 info trying registry request attempt 1 at 12:39:02
228 verbose etag "7M2L4H570UK7EOEL84PNJP9NH"
229 http GET https://registry.npmjs.org/vinyl-fs
230 http 304 https://registry.npmjs.org/archy
231 silly registry.get cb [ 304,
231 silly registry.get { date: 'Thu, 01 May 2014 03:39:02 GMT',
231 silly registry.get server: 'Apache',
231 silly registry.get via: '1.1 varnish',
231 silly registry.get 'last-modified': 'Thu, 01 May 2014 03:39:03 GMT',
231 silly registry.get 'cache-control': 'max-age=1',
231 silly registry.get etag: '"8G937WVUQ9MMZVXIHKCSTNOPR"',
231 silly registry.get 'x-served-by': 'cache-ty66-TYO',
231 silly registry.get 'x-cache': 'HIT',
231 silly registry.get 'x-cache-hits': '1',
231 silly registry.get 'x-timer': 'S1398915542.828933954,VS0,VE243',
231 silly registry.get vary: 'Accept',
231 silly registry.get 'content-length': '0',
231 silly registry.get 'keep-alive': 'timeout=10, max=50',
231 silly registry.get connection: 'Keep-Alive' } ]
232 verbose etag archy from cache
233 silly lockFile bdbf708d-archy-0-0-2 archy@^0.0.2
234 silly lockFile bdbf708d-archy-0-0-2 archy@^0.0.2
235 verbose about to build /Users/xxx/.nodebrew/current/lib/node_modules/gulp
236 info /Users/xxx/.nodebrew/current/lib/node_modules/gulp unbuild
237 verbose from cache /Users/xxx/.nodebrew/current/lib/node_modules/gulp/package.json
238 info preuninstall gulp@3.6.2
239 info uninstall gulp@3.6.2
240 http 304 https://registry.npmjs.org/chalk
241 silly registry.get cb [ 304,
241 silly registry.get { date: 'Thu, 01 May 2014 03:39:02 GMT',
241 silly registry.get server: 'Apache',
241 silly registry.get via: '1.1 varnish',
241 silly registry.get 'last-modified': 'Thu, 01 May 2014 03:39:03 GMT',
241 silly registry.get 'cache-control': 'max-age=1',
241 silly registry.get etag: '"8N90ZCS3GC42U2PJJKL158M7V"',
241 silly registry.get 'x-served-by': 'cache-ty66-TYO',
241 silly registry.get 'x-cache': 'HIT',
241 silly registry.get 'x-cache-hits': '1',
241 silly registry.get 'x-timer': 'S1398915542.829024315,VS0,VE254',
241 silly registry.get vary: 'Accept',
241 silly registry.get 'content-length': '0',
241 silly registry.get 'keep-alive': 'timeout=10, max=50',
241 silly registry.get connection: 'Keep-Alive' } ]
242 verbose etag chalk from cache
243 http 304 https://registry.npmjs.org/deprecated
244 silly registry.get cb [ 304,
244 silly registry.get { date: 'Thu, 01 May 2014 03:39:02 GMT',
244 silly registry.get server: 'Apache',
244 silly registry.get via: '1.1 varnish',
244 silly registry.get 'last-modified': 'Thu, 01 May 2014 03:39:03 GMT',
244 silly registry.get 'cache-control': 'max-age=1',
244 silly registry.get etag: '"9K35WQCJOF7AXVG5WF6XI54C8"',
244 silly registry.get 'x-served-by': 'cache-ty68-TYO',
244 silly registry.get 'x-cache': 'MISS',
244 silly registry.get 'x-cache-hits': '0',
244 silly registry.get 'x-timer': 'S1398915542.836422443,VS0,VE260',
244 silly registry.get vary: 'Accept',
244 silly registry.get 'content-length': '0',
244 silly registry.get 'keep-alive': 'timeout=10, max=50',
244 silly registry.get connection: 'Keep-Alive' } ]
245 verbose etag deprecated from cache
246 http 304 https://registry.npmjs.org/liftoff
247 silly registry.get cb [ 304,
247 silly registry.get { date: 'Thu, 01 May 2014 03:39:02 GMT',
247 silly registry.get server: 'Apache',
247 silly registry.get via: '1.1 varnish',
247 silly registry.get 'last-modified': 'Thu, 01 May 2014 03:39:03 GMT',
247 silly registry.get 'cache-control': 'max-age=1',
247 silly registry.get etag: '"BE36708E06SQIZE939E1VUZ2Q"',
247 silly registry.get 'x-served-by': 'cache-ty66-TYO',
247 silly registry.get 'x-cache': 'MISS',
247 silly registry.get 'x-cache-hits': '0',
247 silly registry.get 'x-timer': 'S1398915542.836016178,VS0,VE271',
247 silly registry.get vary: 'Accept',
247 silly registry.get 'content-length': '0',
247 silly registry.get 'keep-alive': 'timeout=10, max=50',
247 silly registry.get connection: 'Keep-Alive' } ]
248 verbose etag liftoff from cache
249 verbose true,/Users/xxx/.nodebrew/current/lib/node_modules,/Users/xxx/.nodebrew/current/lib/node_modules unbuild gulp@3.6.2
250 verbose /Users/xxx/.nodebrew/current/bin,[object Object] binRoot
251 info postuninstall gulp@3.6.2
252 silly lockFile 0e32a569-deprecated-0-0-1 deprecated@^0.0.1
253 silly lockFile 0e32a569-deprecated-0-0-1 deprecated@^0.0.1
254 silly lockFile e16e48d9-liftoff-0-9-3 liftoff@^0.9.3
255 silly lockFile e16e48d9-liftoff-0-9-3 liftoff@^0.9.3
256 silly lockFile b2f4396d-chalk-0-4-0 chalk@^0.4.0
257 silly lockFile b2f4396d-chalk-0-4-0 chalk@^0.4.0
258 error Error: No compatible version found: archy@'^0.0.2'
258 error Valid install targets:
258 error ["0.0.0","0.0.1","0.0.2"]
258 error at installTargetsError (/Users/xxx/.nodebrew/node/v0.10.12/lib/node_modules/npm/lib/cache.js:719:10)
258 error at /Users/xxx/.nodebrew/node/v0.10.12/lib/node_modules/npm/lib/cache.js:641:10
258 error at saved (/Users/xxx/.nodebrew/node/v0.10.12/lib/node_modules/npm/node_modules/npm-registry-client/lib/get.js:138:7)
258 error at Object.oncomplete (fs.js:107:15)
259 error If you need help, you may report this log at:
259 error <http://github.com/isaacs/npm/issues>
259 error or email it to:
259 error <npm-@googlegroups.com>
260 error System Darwin 13.1.0
261 error command "/Users/xxx/.nodebrew/current/bin/node" "/Users/xxx/.nodebrew/current/bin/npm" "install" "-g" "gulp"
262 error cwd /Users/xxx/Desktop/gulp
263 error node -v v0.10.12
264 error npm -v 1.2.32
265 verbose exit [ 1, true ]
タグ:GULP
posted by ねこまんま at 12:46 | Comment(0) | TrackBack(0) | node.js | 更新情報をチェックする

2014年04月30日

node.jsでExpress4系を使う

node.jsでExpressを使おうと思ったら4系になっててハマったのでメモ書き。

Expressのインストールはこれまでどおり。

sudo npm install -g express


次のコマンドでExpressのバージョンを調べたところ4.1.1

npm info express version


4系からはexpressコマンドはデフォルトでは利用できず、「express-generator」を合わせてインストールする必要がある。

sudo npm install -g express-generator


インストールするとexpressコマンドでプロジェクトを作成できるので

express myapp


作成したプロジェクトに移動してnodeモジュールのインストール。

cd myapp && npm install


アプリケーションの実行は以下のコード。これでExpressのサーバーが立ち上がります。

DEBUG=my-application ./bin/www
タグ:node.js
posted by ねこまんま at 14:51 | Comment(0) | TrackBack(0) | node.js | 更新情報をチェックする

2014年04月24日

Jadeで外部ファイルの読み込み

Jadeで外部ファイルの読み込むにはincludeとextendという2種類の方法があります。

includeは以下のような感じ

index.jade

h1 タイトル
include includeFile


includeFile.jade

p テキスト


これを展開すると以下の様なHTMLになる

<h1>タイトル</h1>
<p>テキスト</p>


純粋にファイルを読み込んで表示ができる

extendは以下の様な感じ

extend.jade

p
block text
|text


index.jade

h1 タイトル
extend extend
block text
|テキスト


<h1>タイトル</h1>
<p>テキスト</p>

タグ:include JADE
posted by ねこまんま at 14:17 | Comment(0) | TrackBack(0) | node.js | 更新情報をチェックする

2014年04月23日

Jadeの基本

Jadeの基本

次のように書くと

doctype
html
head
meta(charset="utf-8")
title test
body
h1 test


次のようにコンパイルされる。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
</head>
<body>
<h1 id="id00">test</h1>
<p class="class00">test</p>
</body>
</html>


基本はインデント記法で属性は(name="value")もしくは(name='value')で、idは#id名をclassは.class名を続けて書く。テキスト等は半角スペースを入れて書く。実際は改行されずに上記のコードが出力されます。

改行を入れたい場合は改行してインデントして|(パイプ)を入れる。

p hogehoge
|fugafuga


<p>hogehoge
fugafuga</p>


JavaScriptのコードを入れたり、HTMLをそのまま書きたい場合は.(ドット)で終わらした後にインデントして記述。

script.
$(function(){
alert("ok");
});


<script>$(function(){
alert("ok");
});</script>


-(ハイフン)で変数などを定義できるので#{変数名}でテンプレート内に記述できる

- hoge = "ほげ"
p #{hoge}


<p>ほげ</p>


=(イコール)で直接挿入することも可能

- hoge = "ほげ"
p=hoge


<p>ほげ</p>


=の後はJavaScriptの命令が記述できる



<p>ほげhoge3</p>


node.jsで定義した変数を渡したい場合は以下のように実行時に引数でわたしてあげる

jade.compile(index)({
fuga:"fuga"
});


if文、else if文、else文などもインデント記法で

- tenki = "曇り"

if tenki == "晴れ"
p 日傘を持っていく
else if tenki == "雨"
p 傘を持っていく
else
p 傘を持っていかない


for in構文も利用可能

- arr = [1,2,3]

for value in arr
p=value


同様にeach inも利用可能

each value in arr
p=value


通常のfor文を使いたい場合などは-をつかってJS構文を利用するとよい。JavaScripが使えるので複雑なこともできる

- arr = ["a","b","c","d"]
- for(var i = 0; i<arr.length ;i++){
- if(i==arr.length-1){
p.last-child=arr[i]
- }else{
p=arr[i]
- }
- }
タグ:JADE node.js
posted by ねこまんま at 15:38 | Comment(0) | TrackBack(0) | node.js | 更新情報をチェックする

node.jsでJadeを利用する

node.jsでJadeを利用する方法。

まずはJadeモジュールのインストール

npm install jade --save-dev


流れとしては、まずJadeモジュールを読み込み

var jade = require('jade');


fsオブジェクトのreadFileSyncメソッドでテンプレートファイルを読み込み

var index = fs.readFileSync('./index.jade','utf-8');


jadeオブジェクトのcompileメソッドでテンプレートをコンパイル後(コンパイル結果は関数オブジェクト)に実行します。

var tmp = jade.compile(index)();


一連の流れをファイルに落としこむと以下の様な感じです。

var http = require("http");
var fs = require('fs');
var url = require('url');
var jade = require('jade');

var index = fs.readFileSync('./index.jade','utf-8');

var server = http.createServer();
server.on("request",function(req,res){
var reqBody = "";
req.on('data',function(data){
reqBody += data;
}).on('end',function(){
var path = url.parse(req.url);
switch(path.pathname){
case '/':
var tmp = jade.compile(index)();
res.setHeader("Content-type","text/html");
res.write(tmp);
res.end();
break;
case '/favicon.ico':
break;
default:
res.setHeader('Content-Type','text/text');
res.write("404");
res.end();
break;
}
});
}).listen(1234);


index.jade

doctype
html
head
meta(charset="utf-8")
title test
body
h1 sample
p sample
posted by ねこまんま at 14:39 | Comment(0) | TrackBack(0) | node.js | 更新情報をチェックする

2014年04月21日

node.jsのテンプレートエンジン「ejs」を使ってみる

モジュールのインストール

npm install ejs --save-dev


モジュールの読み込み。テンプレートファイルを読み込むためにfsモジュールも読み込む。

var fs = require('fs');
var ejs = require("ejs");


fsモジュールでテンプレートファイル「index.ejs」を読み込む。

var index = fs.readFileSync("./index.ejs",'UTF-8');


index.ejsの 内容は次のような感じ

<%= test %>


テンプレートファイルに対してオブジェクトを渡してあげるとテンプレートに組み込まれる形で表示できる。

var data = ejs.render(index,{
test : "test!!"
});


データ構造が複雑な場合もテンプレート側に<% ..... %>にスクリプトを記述できる。

var list = ["aaa","bbb","ccc"]
var data = ejs.render(index,{
list : list
});


<% for(var i = 0;i<list.length;i++){ %>
<%= list[i] %>
<% } %>
タグ:ejs node.js
posted by ねこまんま at 14:24 | Comment(0) | TrackBack(0) | node.js | 更新情報をチェックする

2014年04月18日

node.jsでcookieを管理

node.jsでcookieを管理でcookieを管理する方法。

cookieの登録自体はブラウザに以下のheaderを送ってやればできる。

res.setHeader('Set-Cookie',['cookieProp=cookieValue');


取得は以下のようにrequestオブジェクトのheaderから取得できる。

server.on("request",function(req,res){
req.on("end",function(){
console.log(req.headers.cookie);
});
});


簡単に扱いたい場合はcookieモジュールを使うと良い

npm install cookie  --save-dev


そうすれば以下のように簡単にcookieを取得できる

cookie.parse(req.headers.cookie).cookieProp


以下の様なサンプルで確認できる。

index.html

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<form action="/form" action="/form" method="post">
<input type="text" name="inputA">
<input type="submit" value="送信">
</form>
</body>
</html>


demo.js

var http = require("http");
var qs = require("querystring");
var fs = require('fs');
var url = require('url');
var cookie = require('cookie');

var server = http.createServer();
server.on("request",function(req,res){
var reqBody = "";
req.on('data',function(data){
reqBody += data;
}).on('end',function(){
var path = url.parse(req.url);
switch(path.pathname){
case '/':
var cookies = cookie.parse(req.headers.cookie);
if(cookies.cookieValue){
res.setHeader('Content-Type','text/text');
res.write(cookies.cookieValue);
res.end();
}else{
fs.readFile('./index.html','UTF-8',function(err,data){
res.setHeader('Content-Type','text/html');
res.write(data);
res.end();
});
}
break;
case '/favicon.ico':
break;
default:
res.setHeader('Content-Type','text/text');
var form = qs.parse(reqBody);
if(form && form.inputA]){
res.setHeader('Set-Cookie',['cookieValue='+form.inputA]);
}
res.write("set cookie");
res.end();
break;
}
});
}).listen(1234);


タグ:Cookie node.js
posted by ねこまんま at 14:24 | Comment(0) | TrackBack(0) | node.js | 更新情報をチェックする

2014年04月17日

node.jsでPOSTの値を取得する

node.jsでPOSTの値を取得するにはquerystringモジュールを読み込みreqBodyに対してparseメソッドを実行すれば取得できる。

var http = require("http");
var qs = require("querystring");
var fs = require('fs');
var url = require('url');

var server = http.createServer();
server.on("request",function(req,res){
var reqBody = "";
req.on('data',function(data){
reqBody += data;
}).on('end',function(){
var path = url.parse(req.url);
switch(path.pathname){
case '/':
fs.readFile('./index.html','UTF-8',function(err,data){
res.setHeader('Content-Type','text/html');
res.write(data);
res.end();
});
break;
default:
res.setHeader('Content-Type','text/text');
var form = qs.parse(reqBody);
if(form)res.write(form.inputA);
res.end();
break;
}
});
}).listen(1234);


GETの値の取得はnode.jsでGETの値を取得するを参考に。
タグ:node.js
posted by ねこまんま at 14:33 | Comment(0) | TrackBack(0) | node.js | 更新情報をチェックする

node.jsでファイルを読み込み表示する

node.jsではfsモジュールを読み込みreadFileメソッドでファイルの読み込みができるので以下のようにするとindex.htmlを読み込み表示することができる

var http = require("http");
var fs = require('fs');

var server = http.createServer();
server.on("request",function(req,res){
var reqBody = "";
req.on('data',function(data){
reqBody += data;
}).on('end',function(){
var path = url.parse(req.url);
switch(path.pathname){
case '/':
fs.readFile('./index.html','UTF-8',function(err,data){
res.setHeader('Content-Type','text/html');
res.write(data);
res.end();
});
break;
default:
res.setHeader('Content-Type','text/text');
res.write("404");
res.end();
break;
}
});
}).listen(1234);
タグ:readfile node.js
posted by ねこまんま at 14:22 | Comment(0) | TrackBack(0) | node.js | 更新情報をチェックする

node.jsでGETの値を取得する

node.jsでGETの値を取得するにはurlモジュールを利用します。http://localhost:1234?hoge=fugaなどでGET hogeの値を取得するには以下のようにする。

var http = require("http");
var url = require('url');

var server = http.createServer();
server.on("request",function(req,res){
var reqBody = "";
req.on('data',function(data){
reqBody += data
}).on('end',function(){
res.setHeader('Content-Type','text/plane');
var url_parts = url.parse(req.url,true);
res.write(url_parts.query.hoge);
res.end();
});
}).listen(1234);


参考:node.js GET POSTパラメーターを取得する -でじうぃき
タグ:GET node.js
posted by ねこまんま at 12:01 | Comment(0) | TrackBack(0) | node.js | 更新情報をチェックする

2014年04月02日

node.jsのurlモジュール

node.jsではURLの操作にはurlモジュールを利用する。

たとえばURLを取得して表示するには以下のようにする。

var http = require("http");
var url = require("url");

var server = http.createServer();
server.on("request",function(req,res){
var path = url.parse(req.url);
res.setHeader('Content-Type','text/plane');
res.write(path.pathname);
res.end();
}).listen(1234);


url.parse()で取得したオブジェクトはJavaScriptのLocationオブジェクトとおなじものが利用できる
タグ:URL node.js
posted by ねこまんま at 12:29 | Comment(0) | TrackBack(0) | node.js | 更新情報をチェックする

2014年03月24日

vue.jsファーストインプレッション

Backbone.jsやAngluar.js、Knockout.jsはもう遅い。これからはvue.jsらしいのでとりあえず触ってみた。

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="vue.js"></script>
</head>
<body>
<style>
li.done {
text-decoration: line-through;
}
</style>
<div id="demo">
<h1>{{title | uppercase}}</h1>
<ul>
<li
v-repeat="todos"
v-on="click: done = !done"
class="{{done ? 'done' : ''}}">
{{content}}
</li>
</ul>
</div>
<script>
var demo = new Vue({
el: '#demo',
data: {
title: 'todos',
todos: [
{
done: true,
content: 'Learn JavaScript'
},
{
done: false,
content: 'Learn vue.js'
}
]
}
});
</script>
</body>
</html>


タブパネルを作るとこんな感じ。

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="vue.js"></script>
</head>
<body>
<style>
a.active{
font-weight:bold;
}
</style>
<div id="tabpanel" v-on="click: tabChange">
<a href="#tab1" v-class="active:tabSelected=='#tab1'">tab1</a>
<a href="#tab2" v-class="active:tabSelected=='#tab2'">tab2</a>
<a href="#tab3" v-class="active:tabSelected=='#tab3'">tab3</a>
<div id="tab1" v-show="tabSelected=='#tab1'">CSS1</div>
<div id="tab2" v-show="tabSelected=='#tab2'">CSS2</div>
<div id="tab3" v-show="tabSelected=='#tab3'">CSS3</div>
</div>
<script>
var demo = new Vue({
el: '#tabpanel',
data: {
tabSelected: '#tab1',
},
methods: {
tabChange: function (e) {
console.log(e)
if(e.target.nodeName === 'A'){
this.tabSelected = e.target.getAttribute("href");
}
return false
}
}
});
</script>
</body>
</html>
タグ:vue.js
posted by ねこまんま at 14:05 | Comment(0) | TrackBack(0) | vue.js | 更新情報をチェックする

2014年03月21日

node.jsでWebSocket 1

node.jsでWebSocketを使ってみる。

利用するモジュールはWebSocket.IO。npm installを使ってインストール。

npm install websocket.io


server.jsとしてWebSocket用のJSを作成。

var ws = require("websocket.io"),
server = ws.listen(8888);

server.on('connection', function (socket) {
socket.on("message",function(data) {
server.clients.forEach(function(client) {
client.send(data)
});
});
socket.on('close', function () { });
});


コマンドラインから以下のコマンドを入力するとサーバーが起動します。

node server.js


クライントサイドではnew WebSocket(host)でWebSocketオブジェクトを作成し、WebSocket.onmessage()でメッセージ受信用の処理をWebSocket.send()でメッセージ送信用の処理を行う

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script>
$(function(){
var host = "ws://localhost:8888/",
ws = new WebSocket(host);
//データの受信
ws.onmessage = function(message){
$("ul").append("<li>"+message.data+"</li>")
}
//データの送信
$("#sendBtn").on("click",function(){
message = $("#message").val()
ws.send(message);
});
});
</script>
</head>
<body>
<input type="text" id="message" /><button id="sendBtn">send</button>
<ul>
</ul>
</body>
</html>


参考:Node.jsとWebSocket.IOでチャットアプリを作る | mawatari.jp
タグ:node.js WebSocket
posted by ねこまんま at 22:30 | Comment(0) | TrackBack(0) | node.js | 更新情報をチェックする

2014年03月15日

AngularJSでjqLiteを利用する

AngularJSにはjQueryの簡易版jqLiteが組み込まれており、jQueryの一部機能が利用できます。

angular.element()で対象の要素を指定するのですが、querySelectorAll()を利用することでCSSのセレクタが利用できます。

angular.element(document.querySelectorAll("a")).css("color","red")


利用できるjQueryの機能は以下のとおり

posted by ねこまんま at 17:54 | Comment(0) | TrackBack(0) | Angular | 更新情報をチェックする

AngularJSでタブパネル

タブパネルシリーズをAngularJSで。



<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
a.active{
font-weight:bold;
}
</style>
</head>
<body>
<div ng-app="tabPanel" ng-controller="tabPanelCtrl" ng-click="tabChange($event)">
<a href="#tab1" ng-class="{'active':tabSelected=='#tab1'}">tab1</a>
<a href="#tab2" ng-class="{'active':tabSelected=='#tab2'}">tab2</a>
<a href="#tab3" ng-class="{'active':tabSelected=='#tab3'}">tab3</a>
<div id="tab1" class="ng-hide" ng-show="tabSelected=='#tab1'">CSS1</div>
<div id="tab2" class="ng-hide" ng-show="tabSelected=='#tab2'">CSS2</div>
<div id="tab3" class="ng-hide" ng-show="tabSelected=='#tab3'">CSS3</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
<script>
var app = angular.module("tabPanel",[]);
app.controller("tabPanelCtrl",function($scope){
$scope.tabSelected = "#tab1";
$scope.tabChange = function(e){
if (e.target.nodeName === 'A') {
$scope.tabSelected = e.target.getAttribute("href");
e.preventDefault();
}
}
})
</script>
</body>
</html>
タグ:AngularJS
posted by ねこまんま at 11:31 | Comment(0) | TrackBack(0) | Angular | 更新情報をチェックする

Knockout.jsでタブパネル2

Knockout.jsでタブパネルで気になった点を修正。



<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<style>
button.active{
font-weight:bold;
}
</style>
<div data-bind="click: tabChange">
<a href="#tab1" data-bind="css: { active: tabCheck($element) }">tab1</a>
<a href="#tab2" data-bind="css: { active: tabCheck($element) }">tab2</a>
<a href="#tab3" data-bind="css: { active: tabCheck($element) }">tab3</a>
</div>
<div>
<div id="tab1" data-bind="visible:panelCheck($element)">CSS1</div>
<div id="tab2" data-bind="visible:panelCheck($element)">CSS2</div>
<div id="tab3" data-bind="visible:panelCheck($element)">CSS3</div>
</div>
<script src="knockout-3.1.0.js"></script>
<script>
//ViewModelを定義
var tabPanelViewModel = function(){
//Model作成
this.selectTab = ko.observable("#tab1");
}
//Modelチェンジ
tabPanelViewModel.prototype.tabChange = function(o,e){
if(e.target.tagName=="A"){
this.selectTab(e.target.getAttribute("href"));
}
}
//タブチェンジ
tabPanelViewModel.prototype.tabCheck = function(e){
return this.selectTab()== e.getAttribute("href");
}
//パネルチェンジ
tabPanelViewModel.prototype.panelCheck = function(e){
return this.selectTab()=="#"+e.getAttribute("id");
}
//bindingスタート
ko.applyBindings( new tabPanelViewModel() );
</script>
</body>
</html>


clickイベントのバインドがめんどくさいのでdelegateで実装。タブやパネルの変化も別メソッドで実装することでviewの記述やメンテナンス性を向上させている。
タグ:Knockout.js
posted by ねこまんま at 11:24 | Comment(0) | TrackBack(0) | Knockout.js | 更新情報をチェックする

2014年03月13日

Knockout.jsでタブパネル

Knockout.jsを使って簡単なタブパネルを作ってみた - E-riverstyle Vanguardを参考にKnockout.jsでタブパネルを作ってみた



<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<style>
button.active{
font-weight:bold;
}
</style>
<button data-bind="click: tabChange.bind($data,0),css: { active: selectTab() == 0 }">button</button>
<button data-bind="click: tabChange.bind($data,1),css: { active: selectTab() == 1 }">button</button>
<button data-bind="click: tabChange.bind($data,2),css: { active: selectTab() == 2 }">button</button>
<div data-bind="visible:selectTab()==0">CSS1</div>
<div data-bind="visible:selectTab()==1">CSS2</div>
<div data-bind="visible:selectTab()==2">CSS3</div>
<script src="knockout-3.1.0.js"></script>
<script>
//ViewModelを定義
function TabplanelModel(){
var self = this;
self.selectTab = ko.observable(0);
self.tabChange = function(n){
self.selectTab(n);
}
}
//bindingスタート
ko.applyBindings( new TabplanelModel() );
</script>
</body>
</html>


当初イベントのバインドは以下のように書いてたけど匿名関数で書くのめんどくさいなと思ったらbind()で行けるっぽい。

<button data-bind="click: function(){ tabChange(0) },css: { active: selectTab() == 0 }">button</button>


課題としてviewにvisible:selectTab()==2といった条件が複数あって汎用性が低いなとおもってるのでそこを改善したい
posted by ねこまんま at 11:15 | Comment(0) | TrackBack(0) | Knockout.js | 更新情報をチェックする

Sublime Text2で⌘+dの逆

いっつも忘れるけどSublime Text2で⌘+dの逆は⌘+u
タグ:Sublime Text2
posted by ねこまんま at 11:13 | Comment(0) | TrackBack(0) | 開発環境・ツール | 更新情報をチェックする

2014年03月11日

Knockout.js入門

必要に迫られてAngularJSそっちのけでKnockout.jsの勉強

Hello Worldは「knockout.jsでさくさくWebアプリ開発|1 pixel|サイバーエージェント公式クリエイターズブログ」がよかった。

つくったのは以下のようなサンプル。

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<p><input type="text" data-bind="value: message, valueUpdate: 'afterkeydown'"></p>
<p id="result" data-bind="text: message">ここに入力されたテキストと同じものが入る</p>
<script src="knockout-3.1.0.js"></script>
<script>
//ViewModelを定義
function TestappViewModel(){
var self = this;
self.message = ko.observable('');
}
//bindingスタート
ko.applyBindings( new TestappViewModel() );
</script>
</body>
</html>


data-bind属性でmodelとviewを関連付けられる。

data-bind="value: message"とするとinput要素やtextarea要素のvalueをdata-bind="value: text"とすると要素のinnerTextがが関連付けられる。

data-bind="visible:message"などとするとmodelに値がある場合のみ表示。

<button data-bind="enable: message">button</button>などのようにenableでdisable属性の制御ができる。
posted by ねこまんま at 15:10 | Comment(0) | TrackBack(0) | Knockout.js | 更新情報をチェックする

2014年03月04日

AngularJS1.2でng-bind-html-unsafe属性が使えない

AngularJS1.2でng-bind-html-unsafe属性が廃止されたらしく使えない。じゃあどうやってHTMLを突っ込むかというと、この記事によると以下のdirectiveを追加すると利用できるようになるみたい。

app.directive('bindHtmlUnsafe', function( $parse, $compile ) {
return function( $scope, $element, $attrs ) {
var compile = function( newHTML ) {
newHTML = $compile(newHTML)($scope);
$element.html('').append(newHTML);
};

var htmlName = $attrs.bindHtmlUnsafe;

$scope.$watch(htmlName, function( newHTML ) {
if(!newHTML) return;
compile(newHTML);
});

};
});
posted by ねこまんま at 23:50 | Comment(0) | TrackBack(0) | Angular | 更新情報をチェックする

AngularJSのスコープ

ng-appのみを指定した場合グローバルにスコープが取られるが、名前空間を指定することでスコープを限定することができる。module()でスコープが指定できる

var app = angular.module("Hello",[]);
app.controller("HelloCtrl",function($scope){
$scope.hello = "world";
});


<body ng-app="Hello">
<div ng-controller="HelloCtrl">
<p>{{hello}}</p>
</div>
</body>
posted by ねこまんま at 23:24 | Comment(0) | TrackBack(0) | Angular | 更新情報をチェックする

AngularJSのng属性の書き方

AngularJSではng属性に複数の記述方法が用意されている

<input type="text" ng-model="text">
<input type="text" ng:model="text">
<input type="text" data-ng-model="text">
<input type="text" x-ng-model="text">


原理向けにカスタムデータ属性まで用意されているのが素晴らしい。
タグ:AngularJS
posted by ねこまんま at 23:12 | Comment(0) | TrackBack(0) | Angular | 更新情報をチェックする

AngularJSで表示非表示を切り分ける



AngularJSで表示非表示を切り分けるにはng-hide属性やng-show属性を利用します。class="ng-hide"を指定するとひとまず非表示になるのであとはモデルの値によって表示を切り分けます。

<div class="ng-hide">show</div>


モデルの値が文字列の場合は属性にモデルを引き渡すだけ。

function todosCtrl($scope){
$scope.todos = "aa";
}


<div ng-show="todo" class="ng-hide">show</div>


モデルの値が配列の場合はmodel.lengthで条件を指定できる。(配列に値があるかどうか)

function todosCtrl($scope){
$scope.todos = ["aa","bb"];
}


<div ng-show="todos.length" class="ng-hide">show</div>


ちょっとはまったけどオブジェクトの場合はObject.keys(model).lengthで判定できる。ただし$scope.Object = Object;としてスコープにObjectオブジェクトを受け渡さないとダメ。

function todosCtrl($scope){
$scope.Object = Object;
$scope.todos = {"aa":"aa","bb":"bb"};
}


<div ng-show="Object.keys(todos).length > 0" class="ng-hide">show</div>
posted by ねこまんま at 15:00 | Comment(0) | TrackBack(0) | Angular | 更新情報をチェックする

2014年03月01日

初めてのGruntプラグイン - 非同期処理

初めてのGruntプラグイン - マルチタスクに引き続きGruntプラグイン作成。

Gruntではファイル操作など重めの処理を行っていると処理の合間にGruntの実行が終わってしまい処理中断されてしまいます。

async()で非同期処理を開始し、done()で次の処理にタスクを渡すことができます。

node.jsでファイルを作成と組み合わせると以下のようにするとマルチタスクでファイル作成が可能になります。

module.exports = function (grunt) {
grunt.registerMultiTask('sample', 'sample task', function () {
var done = this.async();
var option = grunt.config('sample')[this.target].option;
var data = "this is sample task!";
fs.writeFile(option.file, data , function (err) {
console.log(err);
done();
});
});
};
タグ:done() async() Grunt
posted by ねこまんま at 12:42 | Comment(0) | TrackBack(0) | Grunt | 更新情報をチェックする

node.jsでファイルを作成

node.jsでファイルを作成するにはfsモジュールをを読み込みwriteFileメソッドを利用する。

var fs = require('fs');
var data = "fuga";
fs.writeFile("./hoge.txt", data , function (err) {
console.log(err);
});


このスクリプトでは「fuga」という内容のhoge.txtというファイルを作成しています。
posted by ねこまんま at 12:35 | Comment(0) | TrackBack(0) | node.js | 更新情報をチェックする

初めてのGruntプラグイン - マルチタスク

前回の初めてのGruntプラグインに引き続きGruntプラグイン作成。

よくあるGruntプラグインのように実行条件を分岐したい場合の処理。たとえば次のようにGruntfile.jsを指定すると「gurnt sample:dev」と「grunt sample:prod」で実行条件を分けることができまる。

module.exports = function(grunt) {
//グラントタスクの設定
grunt.initConfig({
sample:{
dev:{
option:{
file:"hoge.txt"
}
},
prod:{
option:{
file:"hoge.mi.txt"
}
},
}
});
//プラグインの読み込み
grunt.loadNpmTasks('grunt-sample');
};


次のようにregisterTaskではなくregisterMultiTaskを利用する。

module.exports = function (grunt) {
grunt.registerMultiTask('cachebuster', 'sample task', function () {
console.log("this is sample task!");
});
};


optionで指定した値を取得するには次のようにgrunt.config()から値を取得できる。

module.exports = function (grunt) {
grunt.registerMultiTask('sample', 'sample task', function () {
var option = grunt.config('sample')[this.target].option;
console.log(option.file)
});
};
posted by ねこまんま at 12:31 | Comment(0) | TrackBack(0) | Grunt | 更新情報をチェックする

2014年02月28日

AngularJSでeventオブジェクトを取得

ng-clickやng-keyupイベントの指定時に$eventを引数に渡してあげればeventオブジェクトを取得できます。

以下のサンプルはToDoリストにエンターを押して追加するパターン

function todosCtrl($scope){
$scope.todos=[];
$scope.addTodo = function(e){
if(e.keyCode !=13)return false;
$scope.todos.push($scope.add_todo);
$scope.add_todo="";
}
}


<body ng-app>
<div ng-controller="todosCtrl">
<input type="text" ng-model="add_todo" ng-keyup="addTodo($event)">
<ul>
<li ng-repeat="todo in todos track by $index">{{todo}}</li>
</ul>
<div>
</body>
タグ:ng-click ng-keyup
posted by ねこまんま at 13:16 | Comment(0) | TrackBack(0) | Angular | 更新情報をチェックする

AngularJSのng-repeatでエラー

AngularJSで以下のようなコードでエラーが出た。

function todosCtrl($scope){
$scope.todos=["aa","aa];
}


<ul>
<li ng-repeat="todo in todos">{{todo}}</li>
</ul>


エラー内容は以下のとおり。

Error: [ngRepeat:dupes]


エラーページを確認するとng-repeatは配列のvalueを元にループを回すので同じ値があるとエラーになるっぽい。ng-repeat指定時に「track by $index」を追加するとkeyを元にループを回すので大丈夫なようです。

<ul>
<li ng-repeat="todo in todos track by $index">{{todo}}</li>
</ul>
posted by ねこまんま at 13:06 | Comment(0) | TrackBack(0) | Angular | 更新情報をチェックする

2014年02月27日

初めてのGruntプラグイン

ちょっと気になったのでNode.js - grunt-pluginの作り方と解剖 - Qiitaを参考にGruntプラグインの作り方を勉強中。

今回作成したのはコンソールに出力するだけのgrunt-sample、node_modules内にgrunt-sampleディレクトリを作り、package.json、tasksディレクトリを作成、tasksディレクトリ内にはsample.jsを作成してます。

node_modules
└── grunt-sample
├── package.json
└── tasks
└── sample.js


package.jsonには以下の内容を記述

{
"name": "grunt-sample",
"version": "0.0.1",
"description": "sample grunt plugin",
"keywords": [
"gruntplugin"
],
"devDependencies": {
"grunt": "~0.4.1"
}
}


sample.jsには以下の内容を記述。

module.exports = function (grunt) {
grunt.registerTask('sample', 'sample task', function () {
console.log('this is sample task!');
});
};


registerTaskでは「タスク名」、「タスクの説明」、「タスク」の順番で記述を行います。

最後にGruntfile.jsに以下の内容を記述

module.exports = function(grunt) {
//グラントタスクの設定
grunt.initConfig({
sample:{}
});
//プラグインの読み込み
grunt.loadNpmTasks('grunt-sample');
};


ターミナルから以下のコマンドを打つと先ほど設定したconsole.log()の内容が表示されます。

grunt sample
タグ:Grnt
posted by ねこまんま at 00:52 | Comment(0) | TrackBack(0) | Grunt | 更新情報をチェックする

2014年01月07日

Pallarelsにmodan.IEをインストール

VirtualBoxでmodan.IEを利用していたけどPallarels Desktop 9を購入したのでこちらに変更しました。

ダウンロードページで「無料のVMを入手する」をクリック。目的のOSはMacにして仮想環境のプラットフォームを「Pallarels(mac用)」にします。

part1.sfxなどのsfxファイルとrarファイルをダウンロードして同一ディレクトリにおき、以下のようにターミナルから入力すると「IE6 - WinXP.pvm」といったOSイメージが生成されます。

chmod +x ファイル名.sfx
ファイル名.sfx


あとは、OSイメージをダブルクリックするとWindowsが起動します。
posted by ねこまんま at 21:30 | Comment(0) | TrackBack(0) | 開発環境・ツール | 更新情報をチェックする

MarvericksにSass/Compassをインストールしようとしたらハマった

MarvericksにSass/Compassをインストールして「compass watch」をするとエラーが出てハマった。

/Library/Ruby/Site/2.0.0/rubygems/core_ext/kernel_require.rb:135:in `require': cannot load such file -- sass/script/node (LoadError)


Subtheme error. `require': cannot load such file -- sass/script/node (LoadError) [#2148277] | Drupal.org

を見るとruby 2.0.0p247だと動かないかもなのでruby-2.0.0-p353をインストールしろとのこと。ということで Homebrew と rbenvをインストールしてruby-2.0.0-p353にしても改善されず。

色々と見ているとCompassとSassの相性の問題らしい。CompassとSassをアンインストールしてからバージョンを指定してインストール。あと、compass-sourcemapsも必要らしいのでこちらもインストール。

gem uninstall sass
gem uninstall compass
gem install sass -v 3.3.0.alpha.149
gem install compas
gem install compass-sourcemaps -v 0.12.2.sourcemaps.57a186c --pre


これでもエラーが出てグヌヌ!ってなってたけどターミナル再起動したらちゃんと「compass watch」できるようになってた。
posted by ねこまんま at 21:21 | Comment(0) | TrackBack(0) | CSS | 更新情報をチェックする