JavaScript: 2012年10月アーカイブ

タイトルの通りです。
興味を持ちましたのでKnockout.jsを使ってみました。
要はMVVMフレームワーク(MVVMについてはWikipediaをご参照)。
端的に言ってしまうとインタラクティブな仕組みをJavaScriptで実現するためのライブラリです。
どこかで値が変わったときにそれを他の箇所でも自動で反映するということが容易にできます。
使ってみましたが、本当に便利です。
jQueryと一緒でなくてはならない存在になりそう。
ということでKnockout.jsの使い方の第一歩を紹介!


動作環境とか

チュートリアルの紹介

これからKnockout.jsがどんなものか、サンプルコードを元にしてさわりだけですが紹介していこうと思います。
内容としては、公式ページのチュートリアルのIntroductionを少しいじったぐらいの感じです。
かなりよくできたチュートリアルなので、英語に抵抗がなければぜひどうぞ。
以下、公式ページチュートリアル各章へのリンクです。

準備

まず、HTMLのhead内にてknockout.jsを読み込みます。
(サンプルファイルではMicrosoft Ajax CDNで読み込んでいますが、以下の記述はダウンロードしてjsフォルダに入れたと仮定)
<script type='text/javascript' src='js/knockout-2.1.0.js'></script>
私は一緒にjQueryも読み込んでおきました。
現時点ではファイル読み込み完了の検知のためぐらいにしか使っていないですが。
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
また、自分でJavaScriptのコードを書くファイルも準備。
私はdatabind.jsとしてjsフォルダに入れました。
<script type='text/javascript' src='js/databind.js'></script>


お試しその1

キャプチャ
画面にsample textと表示されています。
この文字はHTMLではなく、JavaScriptにて記述しています。
以下、実際のコードです。まずはHTML側。
<span data-bind="text:sample"></span>
data-bindという属性がKnockout.jsを使っていく上での鍵となります。
ちなみに、データバインド(あるいはデータバインディング)とはデータ結合を意味します。
今回の場合、このspanはtext形式のsampleという名前、であることを記述しています。
続きましてJavaScript側です。
$(function() {
    function TestViewModel(){
        this.sample = "sample text";
    }
    ko.applyBindings(new TestViewModel());
});
まず、TestViewModelと名付けられたファンクションが、実際の処理を行う部分です。
this.sample = "sample text";の行で、sampleに"sample text"という文字列を代入しています。
sampleというのはHTML側でspanに指定した名前です。
ko.applyBindings(new TestViewModel());はデータバインドの適用を意味します。
要は上で指定したファンクションlが機能するための定義部みたいなもの。
ko.applyBindingsというコマンドは今後常に出てきます。
これだけだとなにがすごいのかわからないですよね。
なんか回りくどいコードを書いて一行表示しただけ。
ということで、次のお試しその2を見てください。

お試しその2

キャプチャ
入力欄にNakanoと書かれていて、その下にはHello , dear Nakanoと書かれています。
入力欄の内容を変更しますと、それに合わせて自動で下の文章も変わることがわかります。
たとえば、入力欄をAkiyamaとすると、その下にはHello , dear Akiyamaと表示されます。
コードを見てみましょう。
まずはHTML側。
<input data-bind="value:sample"><br>
<span data-bind="text:sample_add"></span>
inputにはvalue形式でsampleという名前が、spanにはtext形式でsample_addという名前を指定しています。
続きましてJavaScript側です。
$(function() {
    function TestViewModel(){
        this.sample = ko.observable("Nakano");
        this.sample_add = ko.computed(function() {
            return "Hello , dear " + this.sample();
        }, this);
    }
    ko.applyBindings(new TestViewModel());
});
お試しその1と似ていますが、違う点が二つあります。
まず一つ目が、sampleがobservable指定されていること。
これは、sampleを監視対象にすることを意味します。
つまり、sampleの値が変わったことをJavaScript側で検知できます。
次に二つ目としまして、sample_addにcomputed時の動作が記述されています。
computed時にHello , dear と、sampleにて指定した値が表示されるようになっています。
computedは、observableで指定した値の変化を検知し、処理を実行するという関数です。
つまり、sampleの値が変化するとこの関数が呼び出され、sample_addの表示内容が変わります。
たかだか数行のコードでインタラクティブな仕組みを可能とするのがKnockout.jsのすごいところです。


お試しその3

キャプチャ
お試しその2に消去というボタンをつけたものです。
このボタンを押すと、入力欄もその下の出力欄も、値が消えます。
まずはHTMLのコードです。
<input data-bind="value:sample"></br>
<span data-bind="text:sample_add"></span></br>
<button data-bind="click:clearButton">消去</button>
新たにbuttonが追記されています。
data-bindeはclick:clearButtonです。
これはclickした際にclearButtonを呼び出すことを意味します。
続きましてJavaScript側のコードです。
$(function() {
    function TestViewModel(){
        this.sample = ko.observable("Nakano");
        this.sample_add = ko.computed(function() {
            return "Hello , dear " + this.sample();
        }, this);
        this.clearButton = function() {
            this.sample("");
        };
    }
    ko.applyBindings(new TestViewModel());
});
this.clearButtonにて、this.sampleを空にしています。
this.sample_addthis.sampleを監視しているため、新たになにも記述しなくても勝手に内容が変わってくれます。
トリガはclickの他にも以下のようなものが用意されています。


最後に

今回はKnockout.jsがどんなものなのか、とりあえずさわりだけ紹介してみました。
便利さの片鱗は伝わったのではないかなと。
機会があれば続編記事も書く予定です!
jQuery Masonryはfloatブロック配置用のjQueryプラグインです。
ブラウザの幅によって配置した要素がアニメーション付きで綺麗に並び変わります。
これを活用すればレスポンシブなWebサイトが制作しやすくなるかも?
ということで早速使ってみましたので、以下、そのまとめです!
※レスポンシブデザイン(レスポンシブWebデザイン)とは、単一のHTMLで様々なディスプレイサイズの各端末で最適化表示をする手法です。

はじめに

jQuery MasonryはMIT licenseにて配布されています。
現在のバージョンは2.1.05です。

お試しその1

アニメーション抜きでとりあえず配置してみました。
スクリーンショット
スクリーンショット
HTML
長いですが、JavaScriptファイル、CSSファイルの読み込みと適当なdivの配置のみです。
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<title>jQuery Masonry Sample 1</title>
<link rel="stylesheet" href="css/sample.css" type="text/css" media="all">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type='text/javascript' src='js/jquery.masonry.min.js'></script>
<script type='text/javascript' src='js/sample.js'></script>
</head>
<body>
<div id="container">
<div class="item">
あああああああああああああああああああああああああああああああああああああああああああああああ
</div>
<div class="item">
いいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいい
</div>
<div class="item">
うううううううううううううううううううううううううううううううううううううううううううううううううううううううううううううう
</div>
<div class="item">
ええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええ
</div>
<div class="item">
おおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおお
</div>
<div class="item">
かかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかか
</div>
<div class="item">
きききききききききききききききききききききききききききききききききききききききききききききききききききき
</div>
<div class="item">
くくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくく
</div>
<div class="item">
けけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけ
</div>
<div class="item">
こここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここ
</div>
</div>
<!-- container -->
</body>
</html>
CSS
floatの指定を忘れずにしてください。
.item{
width:200px;
margin:10px;
float:left;
background-color:#ccffcc;
color:#333333;
}
JavaScript
$(function() {
    $('#container').masonry({
        itemSelector : '.item',
        columnWidth : 220
    });
});
オプション項目については後述しますが、columnWidthは列幅です。
この数値によって配置を計算しています。
たとえばcolumnWidthが240pxでその中のdivのwidthが100pxだったりすると、不自然な余白が140pxできてしまいます。
画像ロード完了した後でMasonryを動作させたい場合は、imageLoadedというメソッドを指定します。
以下、その際のサンプルコードです。
var $container = $('#container');
$container.imagesLoaded(function(){
    $container.masonry({
        itemSelector : '.item',
        columnWidth : 240
    });
});

お試しその2

上と同じものにアニメーションを指定してみました。
ブラウザの横幅を変えるとアニメーションと共に配置が変更されます。
HTML
変更なし
CSS
変更なし
JavaScript
isAnimatedにてtrueを、animationOptionsにてdurationとして600を指定しています。
前者はアニメーション可否、後者はアニメーションの時間(m秒)を意味します。
オプションについては本記事の最後に一覧をつけています。
$(function() {
    $('#container').masonry({
        itemSelector : '.item',
        columnWidth : 220,
        isAnimated : true,
        animationOptions: {
            duration: 600
        }
    });
});

お試しその3

スクリーンショット
スクリーンショット
HTML(body要素のみ抜粋)
長いですが、同じようなdivを繰り返し書いているだけです。
<div id="container">
<div class="item small">
あああああああああああああああああああああああああああああああああああああああああああああああ
</div>
<div class="item big">
いいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいい
</div>
<div class="item small">
うううううううううううううううううううううううううううううううううううううううううううううううううううううううううううううう
</div>
<div class="item big">
ええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええええ
</div>
<div class="item small">
おおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおお
</div>
<div class="item small">
かかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかかか
</div>
<div class="item">
きききききききききききききききききききききききききききききききききききききききききききききききききききき
</div>
<div class="item">
くくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくくく
</div>
<div class="item small">
けけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけけ
</div>
<div class="item">
こここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここここ
</div>
<div class="item small">
ささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささささ
</div>
<div class="item">
ししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししししし
</div>
<div class="item small">
すすすすすすすすすすすすすすすすすすすすすすすすすすすすすす
</div>
<div class="item">
せせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせせ
</div>
</div>
CSS
.item{
width:420px;
margin:10px;
float:left;
background-color:#ccffcc;
color:#333333;
}

.small{
width:200px;
}

.big{
width:640px;
}
JavaScript
変更なし

お試しその4

スクリーンショット
スクリーンショット
HTML(body要素のみ抜粋)
長いですが、同じようなdivを繰り返し書いているだけです。
<div id="container">
<div class="item big">
1
</div>
<div class="item small">
2
</div>
<div class="item small">
3
</div>
<div class="item">
4
</div>
<div class="item small">
5
</div>
<div class="item small">
6
</div>
<div class="item small">
7
</div>
<div class="item small">
8
</div>
<div class="item small">
9
</div>
<div class="item small">
10
</div>
<div class="item big">
11
</div>
<div class="item small">
12
</div>
<div class="item small">
13
</div>
<div class="item small">
14
</div>
<div class="item small">
15
</div>
</div>
CSS
.item{
width:420px;
height:330px;
margin:10px;
float:left;
background-color:#ccffcc;
color:#333333;
}

.small{
width:200px;
height:330px;
}

.big{
width:420px;
height:450px;
}
JavaScript
変更なし

お試しその5

HTML
変更なし
CSS
以下を追加しました。
#container{
margin:0 auto;
}
JavaScript
オプションにisFitWidth : trueを追加しました。
$(function() {
    $('#container').masonry({
        itemSelector : '.item',
        columnWidth : 220,
        isAnimated : true,
        isFitWidth : true,
        animationOptions: {
            duration: 600
        }
    });
});

オプション

以下のようなオプションが用意されています。
itemSelectorとcolumnWidthは推奨項目ですので設定しましょう。
  • animationOptions
    アニメーションオプション指定。
  • columnWidth
    一列の幅。
  • containerStyle
    containerがrelativeかabsoluteか。
  • gutterWidth
    列と列の間にさらにつける間隔値です。
    デフォルトは0です。
  • isAnimated
    レイアウト変更時のアニメーション可否。
    デフォルトはfalseです。
  • isFitWidth
    containerのサイズを列幅に合わせて変更するかどうか。
    demoを見ると早いです。
    デフォルトはfalseです。
  • isResizable
    ブラウザのウィンドウサイズが変わったときにリサイズするか。
    デフォルトはtrueです。
  • isRTL
    右から左に視線を動かすようなレイアウト対応にするか。
    これもdemoを見ると早いです。
    デフォルトはfalseです。
  • itemSelector
    処理対象となる要素(#containerの中の.itemが並び変わるなら、.item)

メソッド

以下のようなメソッドが用意されています。
  • appended
    新たな要素を追加します。画面スクロールに合わせての要素追加にも対応。
  • destroy
    Masonryを削除し、元の状態に戻します。
  • layout
    レイアウトを特定要素に反映します。
  • option
    オプションをセットします。
  • reload
    リロード命令です。要素を挿入した際に使うと便利です(挿入はそれより後ろの要素も並べ替えとなるから、そのときに)。
  • reloadItems
    reloadと同じで再構成のようですが、私の方で違いをまだ試していません。
  • remove
    特定の要素を削除します。

アニメーション

animationについてさらに詳しくはこちらを参照
CSS3について、CSS3対応していないブラウザについて等も書かれています。

最後に

今回の話題の元となりましたNHKスタジオパークのソースが実用的かつシンプルなんで見てみると面白いです!
興味がある方はjQuery Masonry、ぜひ試してみてくださいませ
レスポンシブデザインは使いどころが難しく、制作陣の自己満足みたいになってしまうこともあるでしょうから、そこはご注意を。
1

概要

青春B運営メンバー多口カタンによる雑記blogです。
自己紹介はこちら。開発物をまとめたものはこちら
 
ヘッダーイラストはkojiさん制作です。
感想・意見・要望等ありましたら気軽にフォームにてコンタクトくださいませ。
 
Twitterはじめましたので誰でも気軽に声かけてくださいね。