ActiveDirectoryって?? その2
ActiveDirectoryでは、「認証」と「承認」作業に「kerberos」(ケルベロス)を使用してます。
Kerberosでの認証/承認では、
認証に成功すると「TGT」(Ticket Granting Ticket)と呼ばれるチケットを発行されます。
その後、承認を行う際に、クライアント側は受け取った「TGT」を提示し、
アクセスしてもよいユーザーであることを確認されると、「ST」(Service Ticket)と呼ばれるチケットが発行され、
ActiveDirectoryドメインの各種リソース(PC、プリンターなど)にアクセスできるようになります。
その後、クライアント側は、「Kerberos」に対して、「再度認証/承認作業は行わず、サービスチケットを使いまわし、
各種リソースにアクセスします。
ActiveDirectory側がTGTとSTをクライアントPCに提供することで認証と承認を制御します。
Kerberos認証は、ActiveDirectoryから受け取った「TGT」をパスワードで復号化します。
そのためパスワードを送信しないため、
ネットワークを介して情報が盗まれるリスクが低い特徴があります。
Kerbros認証の流れ
・認証に成功後「TGT」(Ticket Granting Ticket)が発行
・「TGT」をパスワードで復号化
・クライアント側が「TGT」をActiveDirectoryに提示し、サービスチケットを取得
その3では、「ドメインコントローラー」に関して記載します。
ActiveDirectoryって?? その2
ActiveDirectoryって?? その3
ActiveDirectoryって?? その3
ドメインコントローラーの概要を記載します。
まず、「ActiveDirectory」、「ドメインコントローラー」は一緒くたに考えがちですが、
「ActiveDirectory」はあくまで製品名で、
「ドメインコントローラー」はActiveDirectoryが提供する、
ディレクトリ データを格納し、ユーザーのログオン プロセス、認証、およびディレクトリ検索など、
ユーザーとドメイン間の通信を管理を行う「ActiveDirectoryドメインサービス」(AD DS) を実行するサーバーです。
「ドメイン」を制御する中心的なサーバーとなり、
主に「登録されたデータの保持」、「認証と承認」、「グループポリシーによる制御する役割」の役割を行います。
・登録されたデータの保持
ユーザー名、パスワードなどユーザー情報を保持します。
ユーザー情報には「属性値」に色々な情報を設定することが出来ます。
・認証と承認
ユーザー名とパスワードを確認します。
こちらはKerberos認証(その2に記載しました)を使用してます。
・グループポリシーによる制御する役割
基本的にはPC1台1台にポリシーを設定する必要があるが、
グループポリシーを使用することで、すべてのPCに設定したポリシーを割り当てることが可能です。
ブラウザ自動テスト 「Selenium」
ブラウザ自動テスト 「Selenium」
Seleniumは、Webブラウザのテストを自動化オープンソースです。
以下のような複数のブラウザにも対応しています。
・Internet Explorer
・Firefox
・Chrome
・Safan
・Opera
など
また、以下の言語でSeleniumテストスクリプトを作成できます。
・Java
・C#
・Python
・Ruby
・JavaScript
Webアプリケーションでソース修正が発生した際、影響範囲に対して回帰テストを行うが
影響範囲の洗い出しの漏れによって、デグレが発生することがあります。
Webアプリケーション全体に影響がある共通のJavaScriptを修正した際、
すべての画面に対してテストを行う必要があり、面倒で時間のかかる作業となります。
また、製品上、保障するブラウザが複数あればその分テストを行うことになります。
そこで、SeleniumでWebアプリケーションのテストケースを作成しておけば、
回帰テストはほぼ自動で行うことができ、デグレの可能性が少なくなります。
回帰テストを自動化すれば、作業工数を大幅に減らすこともできるので、
試してみてはどうかと思います。
「Selenium」のツール
ブラウザ自動テスト 「Selenium」のツール
・Selenium Core
JavaScript/HTMLベースのテストツールです。
Webサーバー上にSelenium Coreのエンジンとテストスクリプトを配備しておき、
ローカルPCからアクセスを受けた時に、JavaScriptのブラウザ操作ロジックを埋め込んだページを返します。
Selenium Coreのブラウザ操作ロジックは、「Selenium RC」や「Selenium IDE」の内部で現在でも使われているため、
単体で使用して自動テストを組む機会はほぼなくなりました。
・Selenium RC
Selenium RCはSelenium Coreを「Webサーバー上にスクリプトを置かなくても利用できるようにしたもの」と
いうような感じです。
Selenium RCでは、「Selenium Server」というサーバーを起動し、このサーバーを中継し、
JavaScriptのブラウザ操作ロジックをWebページに埋め込みます。
・Selenium IDE
ユーザーのブラウザ操作を記録して、そこからSeleniumのスクリプトを生成するFirefoxプラグインです。
Selenium IDEにはSelenium Coreのロジックが埋め込まれており、Firefox上でのテスト実行ならばSelenium RCがなくても行うことができます。
Selenium IDEはSeleniumのダウンロードサイトからダウンロードし、
通常のFirefoxのプラグインのインストールと同じ手順でインストールします。
インストール後、Firefoxの[ツール]メニューに[Selenium IDE]が表示されます。
Selenium IDEを起動後、ブラウザを操作すると以下の画像のように操作が登録されます。
Webアプリケーションに対する操作を一通り行い、
テストケースを作成したらSelenium IDEの右上の赤色ボタンを押して記録を停止し、
Selenium IDEの[ファイル]メニューからテストケースを保存します。
テストケースはリスト1のようなHTML形式で保存されます。
このように「Selenium IDE」を使用することで簡単にテストケースを作成することが出来ます。
RobotFrameworkとSelenium
RobotFrameWorkとSelenium
RobotFameworkはオープンソースとして公開されている、Python製のテストフレームワークです。
RobotFameworkはキーワードを表示形式でテストケースを記述していきます。
Selenium2用のものをはじめ、豊富な外部ライブラリが公開されています。
自分でキーワードを新規に作るのも簡単にでき、日本語でキーワードを作成することも可能です。
RobotFameworkのテストケースの例)
*** TestCases ***
認証が正常に行われることのテスト >>> テストケースのタイトル
ログインページを firefox で表示する >>> 以下キーワード
ユーザー名を入力する
パスワードを入力する
ログインボタンを押下する
正常にログインされたことを確認する
上記のキーワードに対して、SeleniumAPIを設定することで
ブラウザ上で認証処理を自動的に実施します。
※Seleniumのテストケースを作成する内容は「「Selenium」のツール」に記載してます。
RobotFamework, Selenium2Libraryは、PyPIで公開されています。
日本語のキーワードの組み合わせでテストケースを作成できるため、
とても便利と思います。
興味があれば、試してみてください。
ドメインコントローラ: バックアップ環境作成時に注意すること
メイン環境に対して、災害対策としてバックアップ環境を作成し、ドメインコントローラやエクスチェンジサーバなどのリプリケーションを行い災害時に備えます。
そのために、メイン環境の構築後、バックアップ環境を作成し、ドメインコントローラを作成、データの複製を実施します。
その後、メンバーサーバを構築し、ドメインに参加させていくのが通常、一般的な流れだと思います。
その一番最初のドメインの複製の際に見落としがちで、意外と嵌ってしまうことを備忘録的に記載いたします。
----
手順としては
----
1. メイン環境に対してバックアップ環境のドメインコントローラとなるサーバを立てる
2. メイン環境のドメインコントローラにバックアップ環境のサイトを追加
3. 2.に対応するサブネットなどを追加
4. DCPROMOなどを実行し、ドメインコントローラの機能をインストール
5. 複製を開始
-----
が大まかな流れですが、少し前までは、GUIを使用し手順を実施するか、
BATコマンドを使用して手順を実施するというのが主流でした。
最近はPowershellを使用し構築を容易に進めていくという流れになってきています。
内容によってはBATコマンドでも実行できるのですが、GUI操作か、Powershellコマンドでないと実施できないものも存在しています。
以下は、いろいろな原因でエラーが発生し構築をすることができなかったのですが、
原因がわかると、・・・・・ガッカリ

手順2でメインのドメインコントローラにバックアップ環境のサイトを追加しています。
GUIで実施すると、「サイトの追加」時に"Servers"と"NTDS・・・"も自動に作成されます。
ところが、Powershellコマンドで「サイトの追加」を行うと、純粋に「サイト」のみが追加され、"Servers"も"NTDS・・・"も追加されません。
この状態でGUIで追加されたか確認すると、一見"Servers"も"NTDS・・・"も追加されているように見えるのです。
それで、安心し、次の作業を進めていくと、手順4でサイト名の検証に失敗してしまい構築に失敗してしまいます。
ところが、この「サイト名の検証に失敗」とは、TCP/IP設定の問題、ファイアウォールの問題、名前解決の問題等いろいろなことが要因となって発生します。
Powershellコマンドでのサイトの追加が一見正常に見えているので、そこのミスが原因だとなかなか気づくことができないことが多く、少し嵌ってしまいました
お読みの皆様も、お気を付けください。
RWDのデバッグ方法|Chromeでスマフォをエミュレートする
こんにちは。ひらのです。
Web系の開発者であれば、RWD(レスポンシブウェブデザイン)という単語を
聞いたことがあると思います。
昨年、自社製品のWebページの作成時にRWDを意識したのですが、
その時に使用したHTMLのデバッグツールをご紹介します。
Google Chromeは標準でスマフォのエミュレート機能を備えています。
下記手順で簡単にスマフォエミュレートが可能です。
- [F12]キーを押下して Developer Tool を開く
- Hide drawerマーク(>≡)をクリックして drawer領域を開き、[Emulation]タブをクリック
[Emulation]タブが無ければ、下記の記事を確認してみてください。
デベロッパーツールにOverridesがない!?Google Chromeでユーザーエージェントの変え方 - ノンエンジニアの僕が僭越ながらもwebサービスについてああだこうだ言ってみたり作ってみたり - モバイルマークが表示されていたら、モバイルマークをダブルクリック
- [Model]にエミュレートするデバイスを指定
- [F5]キーを押下して画面更新
下記は私がRWDで作成してみたページです。
画面サイズを変えて遊んでみてください(^^)
[GitHub Pages] GitHubでWebサイトを公開する
こんばんは。ゆんぼうです。
今回は、GitHubでWebサイトを公開します。
GitHubと言えば、ソースコードを共有するサービスですが、
GitHub Pages の機能を使えば、Webサイトを公開することができます。
公開できるWebページは、静的ページ(HTML/JavaScript/CSS)になります。
■GitHubのアカウント登録
まず、GitHubにアクセスしてアカウントを取得します。
GitHub
https://github.com/

GitHubのトップページで、以下の内容を入力します。
・[Pick a username]にユーザー名を入力します。
・[Your email]にEメールを入力します。
・[Create a password]にパスワードを入力します。
[Sign up for GitHub]をクリックします。
[Welcome to GitHub]ページに遷移します。

[Choose your person plan]から有料プランを選択します。
デフォルトでは、無料プラン[Free]となっています。
[Finish sign up]をクリックすると、アカウントが作成されます。
■GitHubのリポジトリ作成

GitHubにログインして、[New repository]を選択します。

以下の内容を設定します。
・[Repository name]にリポジトリ名を入力します。
・[Public]を選択します。
[Create repository]をクリックすると、リポジトリが作成されます。
■GitHub Pagesの設定

GitHubにログインして、リポジトリを選択して、
[Settings]をクリックします。

[GitHub Pages]の[Automatic page generator]をクリックします。
[New project site]ページに遷移します。
[Continue to layouts]をクリックします。
[Welcome to GitHub Pages.]ページに遷移します。
[Publish Page]をクリックします。
GitHub Pages の設定が完了します。

リポジトリの設定ページで
[Default branch]が[gh-pages]になっていることを確認してください。

また、リポジトリの設定ページで
[GitHub Pages]にWebサイト用のURLが表示されています。
残りは、GitHubにWebサイト用のファイルをプッシュするだけとなります。
■SSHキーの作成と設定
今回は、Gitクライアントに Windowsの TortoiseGit を使用します。
TortoiseGit
https://code.google.com/p/tortoisegit/
GitHubとGitクライアントの通信には、
SSHキーの設定が必要となります。

TortoiseGitのSSHキーを生成するアプリケーション[Puttygen]を起動します。

[Generate]をクリックして、キーの生成を開始します。
マウスカーソルをランダムに移動すると、
プログレスバーが進んでいきます。
プログレスバーがいっぱいになると、SSHキーが生成されます。
このSSHキーは、GitHubに設定します。

GitHubにログインして、[Settings]を選択します。
[SSH Keys]を選択して、先ほどのSSHキーを設定します。
[Puttygen]に戻りまして、
[Save public key]をクリックして、*.ppkファイルを保存します。
■Gitのクローン
Windowsの任意のフォルダで、右クリックして
[Git クローン]を選択します。
リポジトリ名には、GitHubのGitURLを入力します。

GitHubの「HTTPS Clone URL」となります。

Putty認証キーには、ppkファイルを設定します。
[OK]でクローンが完了します。
この後は、Webページを作成して、プッシュしてください。
以上です。
Backbone.js入門その4「SuperViewとSubViewのアクセスを作成する」
こんばんは。ゆんぼうです。
今回は、Backbone.jsで、
SuperViewとSubViewのアクセスを作成します。
具体的には、
更新と削除の2つのボタンを表示して、
押下すると、それぞれのボタン固有の文字列を表示する内容を作成します。
今回使用する環境は下記の通りです。
Webブラウザ
・Mozilla Firefox (v34.05) https://www.mozilla.org/ja/firefox/new/
・FireBug (v2.0.7) https://addons.mozilla.org/ja/firefox/addon/firebug/
JavaScriptライブラリ
・Backbone.js (v1.1.2) http://backbonejs.org/
・Underscore.js (v1.7.0) http://underscorejs.org/
・jQuery (v2.1.1) http://jquery.com/
■SubViewにSuperViewのオブジェクトを渡す
【デモはこちら】
【ソースファイルはこちら】
SubViewにSuperViewのオブジェクトを渡して
それぞれのSubViewでボタンを押下すると
SuperViewの関数を実行して文字列を描画します。
main.js に下記の内容を記述します。
$(function() {
var BaseView = Backbone.View.extend({
initialize : function() { // (1)
this.updateButtonView = new UpdateButtonView({
'parent' : this
});
this.deleteButtonView = new DeleteButtonView({
'parent' : this
});
},
render : function() {
this.$el.append($('', {
'id' : 'id_label'
}));
this.$el.append(this.updateButtonView.el).append(this.deleteButtonView.el);
return this;
},
renderLabel : function(message) {
this.$el.find('#id_label').html(message); // (4)
}
});
var UpdateButtonView = Backbone.View.extend({
tagName : 'input',
id : 'id_button_update',
attributes : {
type : 'button',
value : '更新'
},
events : {
'click' : 'onClick',
},
initialize : function(args) {
this.parent = args.parent; // (2)
},
onClick : function(event) {
console.log('UpdateButtonView#onClick');
this.parent.renderLabel('UpdateButtonView'); // (3)
}
});
var DeleteButtonView = Backbone.View.extend({
tagName : 'input',
id : 'id_button_delete',
attributes : {
type : 'button',
value : '削除'
},
events : {
'click' : 'onClick',
},
initialize : function(args) {
this.parent = args.parent;
},
onClick : function(event) {
console.log('DeleteButtonView#onClick');
this.parent.renderLabel('DeleteButtonView');
}
});
var baseView = new BaseView();
$('body').append(baseView.render().el);
});
BaseView がSuperView(親View)で、
UpdateButtonViewとDeleteButtonViewがSubView(子View)となります。
(1)SuperViewのinitialize関数で、SubViewを定義します。new する際にSuperView(this)をSubViewの引数に渡しています。
(2)SubViewのinitialize関数で、SuperViewのオブジェクトを保持しています。
更新ボタンを押下した場合は、(3)UpdateButtonViewのonClick関数が実行され、SuperViewのrenderLabel関数が実行され、(4)で文字列を描画します。
削除ボタンを押下した場合も同様です。
■イベント(listenToとtrigger)を使う
【デモはこちら】
【ソースファイルはこちら】
別の方法として、
SuperViewでSubViewのイベントを監視して、
それぞれのSubViewでボタンを押下すると
イベントを発火して、そのイベントをハンドリングすることで文字列を描画します。
main.js に下記の内容を記述します。
$(function() {
var BaseView = Backbone.View.extend({
initialize : function() { // (1)
this.updateButtonView = new UpdateButtonView();
this.deleteButtonView = new DeleteButtonView();
this.listenTo(this.updateButtonView, 'update', this.onUpdate);
this.listenTo(this.deleteButtonView, 'delete', this.onDelete);
},
render : function() {
this.$el.append($('', {
'id' : 'id_label'
}));
this.$el.append(this.updateButtonView.el).append(this.deleteButtonView.el);
return this;
},
renderLabel : function(message) {
this.$el.find('#id_label').html(message);
},
onUpdate : function(message) {
console.log('BaseView#onUpdate'); // (3)
this.renderLabel(message);
},
onDelete : function(message) {
console.log('BaseView#onDelete');
this.renderLabel(message);
}
});
var UpdateButtonView = Backbone.View.extend({
tagName : 'input',
id : 'id_button_update',
attributes : {
type : 'button',
value : '更新'
},
events : {
'click' : 'onClick',
},
onClick : function(event) {
console.log('UpdateButtonView#onClick');
this.trigger('update', 'UpdateButtonView'); // (2)
}
});
var DeleteButtonView = Backbone.View.extend({
tagName : 'input',
id : 'id_button_delete',
attributes : {
type : 'button',
value : '削除'
},
events : {
'click' : 'onClick',
},
onClick : function(event) {
console.log('DeleteButtonView#onClick');
this.trigger('delete', 'DeleteButtonView');
}
});
var baseView = new BaseView();
$('body').append(baseView.render().el);
});
(1)SuperViewのinitialize関数で、SubViewを定義します。それぞれのSubViewに対して、listenToでイベントを監視します。
・UpdateButtonView は、「update」イベントを監視。イベント発火時には、onUpdate関数が実行されます。
・DeleteButtonView は、「delete」イベントを監視。イベント発火時には、onDelete関数が実行されます。
更新ボタンが押下した場合、(2)UpdateButtonViewのonClick関数が実行され、「update」イベントを発火します。(3)SuperViewのonUpdate関数が実行されます。
triggerの第2引数には、SuperViewで描画する文字列を設定します。そうすると、SuperViewのonUpdate関数の引数に渡されます。
削除ボタンを押下した場合も同様です。
以上です。
Backbone.js入門その5「静的HTMLでBackbone.Viewを作る」
こんばんは。ゆんぼうです。
今回は、Backbone.jsで、
静的HTMLでViewを作成します。
前回までは、htmlのbodyにBackbone.Viewのelをappendして、Webページを表示しておりましたが、
今回は、htmlのbodyに要素を直接記述して、要素のidをBackbone.Viewのelに紐付けて表示します。
今回使用する環境は下記の通りです。
Webブラウザ
・Mozilla Firefox (v34.05) https://www.mozilla.org/ja/firefox/new/
・FireBug (v2.0.7) https://addons.mozilla.org/ja/firefox/addon/firebug/
JavaScriptライブラリ
・Backbone.js (v1.1.2) http://backbonejs.org/
・Underscore.js (v1.7.0) http://underscorejs.org/
・jQuery (v2.1.1) http://jquery.com/
index.html のbody に下記の内容を記述します。
<div id="id_buttons">
<input id="id_button_update" type="button" value="更新">
<input id="id_button_delete" type="button" value="削除">
</div>
■ViewにIDを定義する
【デモはこちら】
【ソースファイルはこちら】
Viewのelに要素のIDを定義して、Webページを表示します。
main.js に下記の内容を記述します。
$(function() {
var BaseView = Backbone.View.extend({
el : '#id_buttons', // (1)
events : {
'click #id_button_update' : 'onClickUpdateButton',
'click #id_button_delete' : 'onClickDeleteeButton'
},
onClickUpdateButton : function(event) {
console.log('onClickUpdateButton');
},
onClickDeleteeButton : function(event) {
console.log('onClickDeleteeButton');
}
});
var baseView = new BaseView();
});
(1)BaseViewのelプロパティに要素ID「id_buttons」を定義します。
そのBaseViewを new すると、要素IDとBaseView.Viewが紐付けられます。
(※ボタンを押下すると、ログが出力されることで、紐付けが確認できます。)
■IDをViewに渡す
【デモはこちら】
【ソースファイルはこちら】
Viewのオブジェクトに、要素IDを渡します。
main.js に下記の内容を記述します。
$(function() {
var ButtonView = Backbone.View.extend({
events : {
'click' : 'onClick'
},
onClick : function(event) {
console.log(event.target.id + '#onClick');
}
});
var buttonView1 = new ButtonView({ // (1)
'el' : '#id_button_update'
});
var buttonView2 = new ButtonView({ // (2)
'el' : '#id_button_delete'
});
});
(1)更新ボタンの要素ID「id_button_update」を渡して、ButtonViewのオブジェクト生成します。
更新ボタンとButtonViewが紐付けられます。
(2)削除ボタンも同様です。
更新ボタンと削除ボタンはそれぞれ別々のViewオブジェクトとなります。
以上です。
Backbone.js入門その6「ModelとCollection」
こんばんは。ゆんぼうです。
今回は、Backbone.jsのBackbone.ModelとBackbone.Collectionを使ったViewを作成します。
Modelは、データを表します。
Backbone.jsでは、データの更新や検証、Ajax通信などの機能を提供します。
Collectionは、Modelの配列を表します。
Backbone.jsでは、配列の追加、削除、並び替えなどの機能を提供します。
今回使用する環境は下記の通りです。
Webブラウザ
・Mozilla Firefox (v34.05) https://www.mozilla.org/ja/firefox/new/
・FireBug (v2.0.7) https://addons.mozilla.org/ja/firefox/addon/firebug/
JavaScriptライブラリ
・Backbone.js (v1.1.2) http://backbonejs.org/
・Underscore.js (v1.7.0) http://underscorejs.org/
・jQuery (v2.1.1) http://jquery.com/
■プルダウン
【デモはこちら】
【ソースファイルはこちら】
以前の記事で作成したプルダウンを
今回は、ModelとCollectionを使用して作成します。
index.html のhead に下記の内容を記述します。
こちらは前回と同じです。
<script type="text/template" id="template-programing-subview">
<label for="language"><%= title %></label>
<select id="language"></select>
</script>
main.js に下記の内容を記述します。
$(function() {
var ProgramingLanguageModel = Backbone.Model.extend({ // (1)
defaults : { // (2)
'name' : '',
'value' : 0
}
});
var ProgramingLanguageCollection = Backbone.Collection.extend({ // (3)
model : ProgramingLanguageModel // (4)
});
var SampleView = Backbone.View.extend({
events : {
'change #language' : 'onChange'
},
initialize : function() {
this.compiledTemplate = _.template($('#template-programing-subview').text());
this.collection = new ProgramingLanguageCollection([ { // (5)
'name' : 'JavaScript',
'value' : 1
}, {
'name' : 'Java',
'value' : 2
}, {
'name' : 'C言語',
'value' : 3
}, {
'name' : 'Ruby',
'value' : 4
}, {
'name' : 'Python',
'value' : 5
} ]);
},
render : function() {
var data = {
'title' : 'プログラミング言語を選択してください'
};
this.$el.append(this.compiledTemplate(data));
_.each(this.collection.models, function(model) { // (6)
this.$el.find('#language').append((new OptionView(model)).render().el);
}, this);
return this;
},
onChange : function(event) {
console.log('onChange:' + event.target.value);
}
});
var OptionView = Backbone.View.extend({
tagName : 'option',
initialize : function(model) {
this.label = model.get('name'); // (7)
this.attributes = {
'value' : model.get('value') // (8)
};
},
render : function() {
this.$el.html(this.label);
return this;
}
});
var sampleView = new SampleView();
$('body').append(sampleView.render().el);
});
(1)Modelを定義します。Modelは、Backbone.Model.extend()関数を使用します。
(2)defaultsプロパティで、デフォルト値の設定を行います。
(3)Collectionを定義します。Collectionは、Backbone.Collection.extend()関数を使用します。
(4)CollectionにModelを設定します。ProgramingLanguageCollection は、ProgramingLanguageModel の配列を持つということを表します。
(5)Viewのinitialize関数で、ProgramingLanguageCollectionのオブジェクトを生成しています。その引数に、5つ分のデータを設定しています。
このとき、ProgramingLanguageCollection には、5つ分のProgramingLanguageModelを保持しています。
(6)Viewのrender関数で、Collectionの配列のサイズ分をSubViewに追加しています。this.collection.models は、ProgramingLanguageModelの配列を指します。
(7)1つ分のProgramingLanguageModelから、nameプロパティを取得しています。
(8)1つ分のProgramingLanguageModelから、valueプロパティを取得しています。
以上です。
Backbone.js入門その7「リストと登録ボタンを作る」
こんばんは。ゆんぼうです。
今回は、Backbone.jsを使用して、リストと登録ボタンを作成します。
今回使用する環境は下記の通りです。
Webブラウザ
・Mozilla Firefox (v34.05) https://www.mozilla.org/ja/firefox/new/
・FireBug (v2.0.7) https://addons.mozilla.org/ja/firefox/addon/firebug/
JavaScriptライブラリ
・Backbone.js (v1.1.2) http://backbonejs.org/
・Underscore.js (v1.7.0) http://underscorejs.org/
・jQuery (v2.1.1) http://jquery.com/
■リストと登録ボタン
【デモはこちら】
【ソースファイルはこちら】
リストと登録ボタンを作成します。
登録ボタンを押下すると、リストに追加されます。
index.html のhead に下記の内容を記述します。
<script type="text/template" id="template-user-list-item">
<%= label.name %>
</script>
<script type="text/template" id="template-user-register">
<label for="id_input_name"><%= label.name %></label>
<input id="id_input_name" type="text">
<br>
<input id="id_button_regist" type="button" value="<%= label.registButton %>">
<hr>
</script>
main.js に下記の内容を記述します。
$(function() {
var UserModel = Backbone.Model.extend({ // (1)
defaults : {
'name' : ''
}
});
var UserCollection = Backbone.Collection.extend({ // (2)
model : UserModel
});
var UserListView = Backbone.View.extend({
name : 'UserListView',
tagName : 'ul',
initialize : function(args) {
this.collection = args.collection;
this.listenTo(this.collection, 'add', this.onAdd);
},
render : function() {
this.$el.html('');
_.each(this.collection.models, function(model) {
this.$el.append((new UserListItemView({
'model' : model
})).render().el);
}, this);
return this;
},
onAdd : function() { // (5)
console.log(this.name + '#onAdd');
this.render();
}
});
var UserListItemView = Backbone.View.extend({
name : 'UserListItemView',
tagName : 'li',
initialize : function(args) {
this.model = args.model;
this.compiledTemplate = _.template($('#template-user-list-item').text());
},
render : function() {
var templateData = {
'label' : {
'name' : this.model.get('name')
}
};
this.$el.append(this.compiledTemplate(templateData));
return this;
}
});
var UserRegisterView = Backbone.View.extend({
name : 'UserRegisterView',
events : {
'click #id_button_regist' : 'onClickRegistButton'
},
initialize : function(args) {
this.collection = args.collection;
this.compiledTemplate = _.template($('#template-user-register').text());
},
render : function() {
var templateData = {
'label' : {
'name' : '名前 : ',
'registButton' : '登録'
}
};
this.$el.append(this.compiledTemplate(templateData))
return this;
},
onClickRegistButton : function() { // (4)
console.log(this.name + '#onClickRegistButton');
this.collection.add({
'name' : this.$el.find('#id_input_name').val()
});
}
});
var BaseView = Backbone.View.extend({
name : 'BaseView',
initialize : function() { // (3)
this.collection = new UserCollection();
this.userListView = new UserListView({
'collection' : this.collection
});
this.userRegisterView = new UserRegisterView({
'collection' : this.collection
});
},
render : function() {
this.$el.append(this.userRegisterView.render().el).append(this.userListView.render().el);
return this;
}
});
var baseView = new BaseView();
$('body').append(baseView.render().el);
});
(1)ユーザーの情報を表すUserModelを定義します。
(2)UserModelの配列を表すUserCollectionを定義します。
(3)BaseViewがページ全体のViewになります。BaseViewのinitialize関数で、UserCollectionのオブジェクトを生成して、それぞれのSubViewに渡しています。
(4)UserRegisterViewのonClickRegistButton関数で、登録ボタン押下時にUserCollectionにデータを追加しています。
(5)UserCollectionにデータが追加された場合、「add」イベントを発火されます。その後、UserListViewのonAddが実行され、UserCollectionのデータを元にリストが描画されます。
■バリデーション
【デモはこちら】
【ソースファイルはこちら】
リストと登録ボタンを拡張します。
Modelのvalidate関数を用いて、何も入力されていない状態で
登録ボタンを押下すると、アラートが表示されるように修正します。
main.js に下記の内容を記述します。
var UserModel = Backbone.Model.extend({
defaults : {
'name' : ''
},
validate : function(attribuite) { // (1)
if (_.isEmpty(attribuite.name)) {
return "名前が入力されていません";
}
}
});
(1)UserModelにvalidate関数を追加します。ここでは、「name」属性が空の場合、メッセージを返します。
var UserRegisterView = Backbone.View.extend({
name : 'UserRegisterView',
events : {
'click #id_button_regist' : 'onClickRegistButton'
},
initialize : function(args) {
this.collection = args.collection;
this.listenTo(this.collection, 'invalid', this.onInvalid);
this.compiledTemplate = _.template($('#template-user-register').text());
},
render : function() {
var templateData = {
'label' : {
'name' : '名前 : ',
'registButton' : '登録'
}
};
this.$el.append(this.compiledTemplate(templateData))
return this;
},
onClickRegistButton : function() {
console.log(this.name + '#onClickRegistButton');
this.collection.add({
'name' : this.$el.find('#id_input_name').val(),
}, {
validate : true // (1)
});
},
onInvalid : function(collection, message) { // (2)
console.log(this.name + '#onInvalid');
alert(message);
}
});
(1)UserCollectionにデータを追加する引数に、「validate : true」を追記します。この追記で、UserCollectionのadd関数を実行すると、UserCollectionのvalidate関数も実行されます。
(2)UserCollectionのvalidate関数が実行され、検証に失敗すると、「invalid」イベントが発火されます。その後、UserRegisterViewのonInvalid関数が実行され、アラートが表示されます。
以上です。
Automatorではファイルの保存場所を取得できない
MacのGUI操作の自動再生アプリ「Automator」では、
自分自身(Automatorファイル)の保存場所を取得できなくて困ったので、
パスの取り方について纏めたいと思いました。
(検証環境はYosemite/10.10.1です)
Automatorファイルを保存した場所を取得して、
そこからの相対パスでファイルを開く動作をさせたかったのですが、
Automatorでカレントディレクトリを取得すると
Automator自体の場所が表示されてしまいます。
■shellファイルの場合
#!/bin/sh pwd echo $(cd $(dirname $0); pwd) | → 実行時のカレントディレクトリが表示される → シェルスクリプトの保存ディレクトリが表示される |
■Automatorでshellを書いた場合
#!/bin/sh pwd echo $(cd $(dirname $0); pwd) | → ユーザーのホームディレクトリになる → ユーザーのホームディレクトリになる |
■AppleScriptの場合
return (path to me) as text | → AppleScriptの保存ディレクトリが表示される |
■AutomatorでAppleScriptを書いた場合
そのため、Automatorで任意のパスを扱いたい場合は、
下記の手段を使用することになります。
■諦めて固定パスを使用する
■環境変数を使用する
私はユーザーのホームディレクトリから固定パスを使用しました。
■Automator実行時にユーザーに入力させる
Automator実行のたびにユーザーにファイルの位置を指定させます。
Backbone.js入門その8「リストと削除ボタンを作る」
こんばんは。ゆんぼうです。
今回は、Backbone.jsを使用して、リストと削除ボタンを作成します。
今回使用する環境は下記の通りです。
Webブラウザ
・Mozilla Firefox (v34.05) https://www.mozilla.org/ja/firefox/new/
・FireBug (v2.0.7) https://addons.mozilla.org/ja/firefox/addon/firebug/
JavaScriptライブラリ
・Backbone.js (v1.1.2) http://backbonejs.org/
・Underscore.js (v1.7.0) http://underscorejs.org/
・jQuery (v2.1.1) http://jquery.com/
■リスト毎の削除ボタン
【デモはこちら】
【ソースファイルはこちら】
ここで作成する内容は下記の通りです。
リスト毎に、削除ボタンを表示します。
削除ボタンを押下すると、対象のリストが削除されます。
index.html の head に下記の内容を記述します。
<script type="text/template" id="template-user-list-item">
<%= label.name %>
<input type="button" class="cls_button_delete" value="<%= label.deleteButton %>">
</script>
<script type="text/template" id="template-user-register">
<label for="id_input_name"><%= label.name %></label>
<input id="id_input_name" type="text">
<br>
<input id="id_button_regist" type="button" value="<%= label.registButton %>">
<hr>
</script>
テンプレートID template-user-list-item はリスト1件分のテンプレート、
template-user-register が登録画面のテンプレートです。
main.js に下記の内容を記述します。
var UserListView = Backbone.View.extend({
name : 'UserListView',
tagName : 'ul',
initialize : function(args) {
this.collection = args.collection;
this.listenTo(this.collection, 'add', this.onAdd);
this.listenTo(this.collection, 'remove', this.onRemove);
},
render : function() {
this.$el.html('');
_.each(this.collection.models, function(model) {
this.$el.append((new UserListItemView({
'model' : model,
'collection' : this.collection
})).render().el);
}, this);
return this;
},
onAdd : function() {
console.log(this.name + '#onAdd');
this.render();
},
onRemove : function() { // (3)
console.log(this.name + '#onRemove');
this.render();
}
});
var UserListItemView = Backbone.View.extend({
name : 'UserListItemView',
tagName : 'li',
events : {
'click .cls_button_delete' : 'onClickDeleteButton'
},
initialize : function(args) {
this.model = args.model;
this.collection = args.collection;
this.compiledTemplate = _.template($('#template-user-list-item').text());
},
render : function() {
var templateData = {
'label' : {
'name' : this.model.get('name'),
'deleteButton' : '削除'
}
};
this.$el.append(this.compiledTemplate(templateData)); // (1)
return this;
},
onClickDeleteButton : function() {
console.log(this.name + '#onClickDeleteButton');
this.collection.remove(this.model); // (2)
}
});
(1) リスト1件分を表す UserListItemView に削除ボタンのテンプレートを追加します。
(2) 削除ボタンを押下したときに、collection.remove で collection から該当の model を削除します。
(3) collection には既に model が削除されています。remove イベントが発火されたときに、render 関数を呼び出しリストを再描画します。その結果、削除された後のリストが表示されます。
■チェックボックスリストと削除ボタン
【デモはこちら】
【ソースファイルはこちら】
先ほどは、リスト毎に削除しておりましたが、
ここでは、チェックボックスにチェックがあるリストを纏めて削除するものを作成します。
index.html のhead に下記の内容を記述します。
<script type="text/template" id="template-user-list">
<input id="id_button_delete" type="button" value="<%= label.deleteButton %>">
<hr>
<ul id="id_ul_user_list"></ul>
</script>
<script type="text/template" id="template-user-list-item">
<input class="cls_checkbox" type="checkbox"> <%= label.name %>
</script>
<script type="text/template" id="template-user-register">
<label for="id_input_name"><%= label.name %></label>
<input id="id_input_name" type="text">
<br>
<input id="id_button_regist" type="button" value="<%= label.registButton %>">
<hr>
</script>
テンプレートID template-user-list はリスト全体のテンプレートです。
main.js に下記の内容を記述します。
var UserModel = Backbone.Model.extend({
defaults : {
'name' : ''
},
isSelected : false, // (2)
validate : function(attribuite) {
if (_.isEmpty(attribuite.name)) {
return "名前が入力されていません";
}
}
});
var UserCollection = Backbone.Collection.extend({
model : UserModel,
removeSelectedModel : function() { // (5)
var selectedCollection = this.models.filter(function(model) {
return model.isSelected;
});
this.remove(selectedCollection);
}
});
var UserListView = Backbone.View.extend({
name : 'UserListView',
events : {
'click #id_button_delete' : 'onClickDeleteButton'
},
initialize : function(args) {
this.collection = args.collection;
this.listenTo(this.collection, 'add', this.onAdd);
this.listenTo(this.collection, 'remove', this.onRemove);
this.compiledTemplate = _.template($('#template-user-list').text());
},
render : function() {
var templateData = {
'label' : {
'deleteButton' : '削除'
}
};
this.$el.append(this.compiledTemplate(templateData)) // (1)
return this;
},
renderItem : function() {
this.$el.find('#id_ul_user_list').html('');
_.each(this.collection.models, function(model) {
this.$el.find('#id_ul_user_list').append((new UserListItemView({
'model' : model,
'collection' : this.collection
})).render().el);
}, this);
},
onAdd : function() {
console.log(this.name + '#onAdd');
this.renderItem();
},
onRemove : function() {
console.log(this.name + '#onRemove');
this.renderItem(); // (6)
},
onClickDeleteButton : function() {
console.log(this.name + '#onClickDeleteButton');
this.collection.removeSelectedModel(); // (4)
}
});
var UserListItemView = Backbone.View.extend({
name : 'UserListItemView',
tagName : 'li',
events : {
'click .cls_checkbox' : 'onClickCheckBox'
},
initialize : function(args) {
this.model = args.model;
this.collection = args.collection;
this.compiledTemplate = _.template($('#template-user-list-item').text());
},
render : function() {
var templateData = {
'label' : {
'name' : this.model.get('name')
}
};
this.$el.append(this.compiledTemplate(templateData));
return this;
},
onClickCheckBox : function(event) {
console.log(this.name + '#onClickCheckBox');
this.model.isSelected = event.target.checked; // (3)
}
});
(1) リスト全体を表す UserListView に削除ボタンのテンプレートを追加します。
(2) model に isSelected プロパティを追加します。
(3) チェックボックスをON/OFFすると、model の isSelected にチェック状態を代入します。
(4) 削除ボタンを押下すると、collection の removeSelectedModel 関数を実行します。
(5) isSelected=true である model を削除します。
(6) remove イベントが発火されたときに、render 関数を呼び出しリストを再描画します。
以上です。
Backbone.js入門その9「リストと詳細ボタンを作る」
今回は、Backbone.jsを使用して、リストと詳細ボタンを作成します。
今回使用する環境は下記の通りです。
Webブラウザ
・Mozilla Firefox (v34.05) https://www.mozilla.org/ja/firefox/new/
・FireBug (v2.0.7) https://addons.mozilla.org/ja/firefox/addon/firebug/
JavaScriptライブラリ
・Backbone.js (v1.1.2) http://backbonejs.org/
・Underscore.js (v1.7.0) http://underscorejs.org/
・jQuery (v2.1.1) http://jquery.com/
■リストと詳細ボタン
【デモはこちら】
【ソースファイルはこちら】
今回は、登録する項目を増やします。
リスト毎の詳細ボタンを押下すると、アラートが表示され、
登録した項目が表示されるものを作成します。
index.html の head に下記の内容を記述します。
<script type="text/template" id="template-user-list-item">
<%= label.name %>
<input type="button" class="cls_button_detail" value="<%= label.detailButton %>">
<input type="button" class="cls_button_delete" value="<%= label.deleteButton %>">
</script>
<script type="text/template" id="template-user-register">
<label for="id_input_name"><%= label.name %></label>
<input id="id_input_name" type="text">
<br>
<label for="id_input_age"><%= label.age %></label>
<input id="id_input_age" type="number" min="0" max="99">
<br>
<label for="id_select_gender"><%= label.gender %></label>
<select id="id_select_gender">
<option><%= label.male %></option>
<option><%= label.female %></option>
</select>
<br>
<label for="id_select_blood"><%= label.blood %></label>
<select id="id_select_blood">
<option>A</option>
<option>B</option>
<option>O</option>
<option>AB</option>
</select>
<br>
<label for="id_input_mail"><%= label.mail %></label>
<input id="id_input_mail" type="text">
<br>
<input id="id_button_regist" type="button" value="<%= label.registButton %>">
<hr>
</script>
テンプレートID template-user-list-item はリスト1件分のテンプレートです。
削除ボタンと詳細ボタンを表示します。
template-user-register が登録画面のテンプレートです。
名前、年齢、性別、血液型、メールアドレスの入力項目を表示します。
main.js に下記の内容を記述します。
var UserListItemView = Backbone.View.extend({
name : 'UserListItemView',
tagName : 'li',
events : {
'click .cls_button_detail' : 'onClickDetailButton',
'click .cls_button_delete' : 'onClickDeleteButton'
},
initialize : function(args) {
this.model = args.model;
this.collection = args.collection
this.compiledTemplate = _.template($('#template-user-list-item').text());
},
render : function() {
var templateData = {
'label' : {
'name' : this.model.get('name'),
'detailButton' : '詳細',
'deleteButton' : '削除'
}
};
this.$el.append(this.compiledTemplate(templateData));
return this;
},
onClickDetailButton : function() {
console.log(this.name + '#onClickDetailButton');
var message = '';
message += '\n名前 : ' + this.model.get('name'); // (1)
message += '\n年齢 : ' + this.model.get('age');
message += '\n性別 : ' + this.model.get('gender');
message += '\n血液型 : ' + this.model.get('blood');
message += '\nメールアドレス : ' + this.model.get('mailAddress');
alert(message); // (2)
},
onClickDeleteButton : function() {
console.log(this.name + '#onClickDeleteButton');
this.collection.remove(this.model);
}
});
(1) model.get で指定したプロパティを取得することができます。
(2) アラートに生成した文字列を渡しています。
以上です。
AutomatorでAppleScriptに値を渡す
こんにちは。ひらのです。
今回はMacのGUI操作の自動再生アプリ「Automator」で、
AppleScriptに値(変数)を渡す方法を2パターンご紹介します。
(検証環境はYosemite/10.10.1です)
①Automatorの変数を渡す
なので、AppleScriptの入力として[変数の値を取得]を指定します。

<AppleScript>
on run {input, parameters} set val1 to item 1 of input end runset val2 to item 2 of input set cnt to (count of input) | ←[変数の値を取得]を並べた順番にinputに入ってくる ←inputに入っている値の個数を調べる |
上記画像のように、[変数の値を取得]をつなげることで、複数の値を渡すことができます。
この場合は、オプション項目[このアクションの入力を無視]にチェックをしないでください。
②シェルスクリプトから値を渡す
Backbone.js入門その10「テーブルと登録ボタンを作る」
こんばんは。ゆんぼうです。
前回までは、登録ボタンを押すと、リストが追加されていきました。
今回は、Backbone.jsでテーブルを作成します。
今回使用する環境は下記の通りです。
Webブラウザ
・Mozilla Firefox (v34.05) https://www.mozilla.org/ja/firefox/new/
・FireBug (v2.0.7) https://addons.mozilla.org/ja/firefox/addon/firebug/
JavaScriptライブラリ
・Backbone.js (v1.1.2) http://backbonejs.org/
・Underscore.js (v1.7.0) http://underscorejs.org/
・jQuery (v2.1.1) http://jquery.com/
■ヘッダーが1つのテーブル
【デモはこちら】
【ソースファイルはこちら】
「名前」ヘッダーを持つテーブルと登録ボタンを作成します。
名前のテキストボックスに入力して、このボタンを押下すると、
テーブルに名前が追加されます。
index.html のhead に下記の内容を記述します。
<script type="text/template" id="template-user-table">
<table class="cls_table">
<thead>
<tr>
<th><%= header.name %></th>
</tr>
</thead>
<tbody id="id_tbody">
</tbody>
</table>
</script>
<script type="text/template" id="template-user-table-item">
<td><%= data.name %></td>
</script>
テーブル用のテンプレートを用意します。
テンプレートID template-user-table がテーブルのヘッダー、
template-user-table-item がテーブルのデータとなります。
main.js に下記の内容を記述します。
var UserTableView = Backbone.View.extend({
name : 'UserTableView',
initialize : function(args) {
this.collection = args.collection;
this.listenTo(this.collection, 'add', this.onAdd);
this.compiledTemplate = _.template($('#template-user-table').text());
},
render : function() {
var tempData = {
'header' : {
'name' : '名前'
}
};
this.$el.append(this.compiledTemplate(tempData)); // (1)
return this;
},
renderItem : function() {
this.$el.find('#id_tbody').html('');
_.each(this.collection.models, function(model) { // (3)
this.$el.find('#id_tbody').append((new UserTableItemView({
'model' : model
})).render().el);
}, this);
},
onAdd : function() {
console.log(this.name + '#onAdd');
this.renderItem(); // (2)
}
});
UserRegisterView は前回と同じ内容です。
今回は、テーブル全体を現す UserTableView とテーブルの1件分のデータを表す UserTableItemView を新たに作成します。
(1) UserTableView でテーブルのヘッダーを描画します。
(2)(3) 登録ボタンを押下すると、UserCollection にデータが追加され、add イベントが発火されます。onAdd 関数が呼び出され、renderItem 関数でテーブルデータを描画します。
■ヘッダーが複数のテーブル
【デモはこちら】
【ソースファイルはこちら】
先ほど作成したテーブルに
「名前」以外に、「年齢」「性別「血液型」「メールアドレス」のヘッダーを追加します。
index.html のhead に下記の内容を記述します。
<script type="text/template" id="template-user-table">
<table class="cls_table">
<thead>
<tr>
<th><%= header.name %></th>
<th><%= header.age %></th>
<th><%= header.gender %></th>
<th><%= header.blood %></th>
<th><%= header.mailAddress %></th>
</tr>
</thead>
<tbody id="id_tbody">
</tbody>
</table>
</script>
<script type="text/template" id="template-user-table-item">
<td><%= data.name %></td>
<td><%= data.age %></td>
<td><%= data.gender %></td>
<td><%= data.blood %></td>
<td><%= data.mailAddress %></td>
</script>
テンプレートにそれぞれ「年齢」「性別「血液型」「メールアドレス」を追加します。
また、UserModel にも同様に追加します。
以上です。
□過去ログ
Backbone.js入門その9「リストと詳細ボタンを作る」
Backbone.js入門その8「リストと削除ボタンを作る」
Backbone.js入門その7「リストと登録ボタンを作る」
Backbone.js入門その6「ModelとCollection」
Backbone.js入門その5「静的HTMLでBackbone.Viewを作る」
Backbone.js入門その4「SuperViewとSubViewのアクセスを作成する」
Backbone.js入門その3「Backbone.ViewでSubViewを作る」
Backbone.js入門その2「Backbone.Viewで複数の要素を作る」
Backbone.js入門その1「Backbone.Viewで1つの要素を作る」
Backbone.js入門その11「ソートテーブルを作る」
今回は、Backbone.jsを使用して、ヘッダーを押す度にソートを行うテーブルを作成します。
今回使用する環境は下記の通りです。
Webブラウザ
・Mozilla Firefox (v34.05) https://www.mozilla.org/ja/firefox/new/
・FireBug (v2.0.7) https://addons.mozilla.org/ja/firefox/addon/firebug/
JavaScriptライブラリ
・Backbone.js (v1.1.2) http://backbonejs.org/
・Underscore.js (v1.7.0) http://underscorejs.org/
・jQuery (v2.1.1) http://jquery.com/
■数値のソート
【デモはこちら】
【ソースファイルはこちら】
「年齢」ヘッダーを持つテーブルと登録ボタンを作成します。
年齢のテキストボックスに入力して、このボタンを押下すると、
テーブルに年齢が追加されます。
さらに、テーブルのヘッダーを押下するたびに、ソートが行われます。
index.html のhead に下記の内容を記述します。
<script type="text/template" id="template-user-table">
<table class="cls_table">
<thead>
<tr>
<th><a href="javascript:void(0)" class="cls_header" name="age"><%= header.age %><span class="cls_sort_icon"></span></a></th>
</tr>
</thead>
<tbody id="id_tbody">
</tbody>
</table>
</script>
<script type="text/template" id="template-user-table-item">
<td><%= data.age %></td>
</script>
テーブルのヘッダーとデータのテンプレートを作成します。
前回と異なる点は、ヘッダーにリンクを追加しています。
main.js に下記の内容を記述します。
var UserCollection = Backbone.Collection.extend({
model : UserModel,
sortAttribute : '',
sortDirection : 1,
sortToggle : function(attribute) {
this.sortDirection *= -1; // (3)
this.sortAttribute = attribute;
this.sort(); // (4)
},
comparator : function(model) {
return model.get(this.sortAttribute) * this.sortDirection; // (5)
}
});
var UserTableView = Backbone.View.extend({
name : 'UserTableView',
events : {
'click .cls_header' : 'onClickHeader'
},
initialize : function(args) {
this.collection = args.collection;
this.listenTo(this.collection, 'add', this.onAdd);
this.listenTo(this.collection, 'sort', this.onSort);
this.compiledTemplate = _.template($('#template-user-table').text());
this.currentHeader = null;
},
render : function() {
var tempData = {
'header' : {
'age' : '年齢'
}
};
this.$el.append(this.compiledTemplate(tempData));
return this;
},
renderItem : function() {
this.$el.find('#id_tbody').html('');
_.each(this.collection.models, function(model) {
this.$el.find('#id_tbody').append((new UserTableItemView({
'model' : model
})).render().el);
}, this);
},
renderClearSortIcon : function() {
_.each([ 'cls_sort_up', 'cls_sort_down' ], function(sortClass) {
this.$el.find("a[name='" + this.collection.sortAttribute + "'] span").removeClass(sortClass);
}, this);
},
renderSortIcon : function() {
var sortClass = null;
if (this.collection.sortDirection == 1) {
sortClass = 'cls_sort_up';
} else {
sortClass = 'cls_sort_down';
}
this.$el.find("a[name='" + this.collection.sortAttribute + "'] span").addClass(sortClass);
},
onAdd : function() {
console.log(this.name + '#onAdd');
this.renderItem();
},
onSort : function() {
console.log(this.name + '#onSort');
this.renderItem(); // (6)
this.renderSortIcon(); // (7)
},
onClickHeader : function(event) {
console.log(this.name + '#onClickHeader');
this.renderClearSortIcon(); // (1)
this.collection.sortToggle(event.target.name); // (2)
}
});
(1) テーブルのヘッダーをクリックすると、ソートの向きを表すソートアイコンを消去します。
(2) event.target.name は、aタグのname属性値「age」を指します。これを引数にして、UserCollection の sortToggle 関数を実行します。
(3) ソートの向きを指定します。関数が実行する度にソートの向きが逆になります。
(4) sort 関数で UserCollection のソートを実行します。
(5) sort 関数の内部で使用する比較関数 comparator を作成します。comparator の引数は、UserModel になります。UserModel から取り出したデータがソートされます。[+]は昇順、[-]は降順になります。
(6) ソートを実行すると、「sort」 イベントが発火されます。sort イベントが発火されると、テーブルのデータを再描画します。
(7) ソートアイコンを描画します。
■文字列のソート
【デモはこちら】
【ソースファイルはこちら】
さきほど作成したテーブルを
「年齢」から「名前」に変更します。
main.js に下記の内容を記述します。
var UserCollection = Backbone.Collection.extend({
model : UserModel,
sortAttribute : '',
sortDirection : 1,
sortToggle : function(attribute) {
this.sortDirection *= -1;
this.sortAttribute = attribute;
this.sort();
},
comparator : function(a, b) { // (1)
var a = a.get(this.sortAttribute), b = b.get(this.sortAttribute);
if (a == b) {
return 0;
}
if (this.sortDirection == 1) {
return b < a ? 1 : -1;
} else {
return a < b ? 1 : -1;
}
}
})
(1) テーブルのデータが数値から文字列に変更することで、comparator の比較方法も文字列の比較に変更します。文字列は Unicode のコード順に基づいて比較されます。
■数値・文字列の混在ソート
【デモはこちら】
【ソースファイルはこちら】
先ほど作成したテーブルに
「名前」「年齢」「性別「血液型」「メールアドレス」のヘッダーを追加します。
main.js に下記の内容を記述します。
var UserCollection = Backbone.Collection.extend({
model : UserModel,
sortAttribute : '',
sortDirection : 1,
initialize : function() {
var that = this;
this.sortComparators = { // (3)
'name' : that.comparatorString,
'age' : that.comparatorInteger,
'gender' : that.comparatorString,
'blood' : that.comparatorString,
'mailAddress' : that.comparatorString
}
},
sortToggle : function(attribute) {
if (this.sortAttribute == attribute) {
this.sortDirection *= -1;
} else {
this.sortDirection = 1;
}
this.sortAttribute = attribute;
this.comparator = this.sortComparators[attribute];
this.sort();
},
comparatorString : function(a, b) { // (1)
var a = a.get(this.sortAttribute), b = b.get(this.sortAttribute);
if (a == b) {
return 0;
}
if (this.sortDirection == 1) {
return b < a ? 1 : -1;
} else {
return a < b ? 1 : -1;
}
},
comparatorInteger : function(model) { // (2)
return model.get(this.sortAttribute) * this.sortDirection;
}
});
(1)(2) ヘッダーを追加した UserCollection では数値と文字列が混在しているため、数値用と文字列用の比較関数を作成します。
(3) データ毎に、比較関数を定義します。
以上です。
□過去ログ
Backbone.js入門その9「リストと詳細ボタンを作る」
Backbone.js入門その8「リストと削除ボタンを作る」
Backbone.js入門その7「リストと登録ボタンを作る」
Backbone.js入門その6「ModelとCollection」
Backbone.js入門その5「静的HTMLでBackbone.Viewを作る」
Backbone.js入門その4「SuperViewとSubViewのアクセスを作成する」
Backbone.js入門その3「Backbone.ViewでSubViewを作る」
Backbone.js入門その2「Backbone.Viewで複数の要素を作る」
Backbone.js入門その1「Backbone.Viewで1つの要素を作る」
Backbone.js入門その12「ラジオボタンテーブルを作る」
こんばんは。ゆんぼうです。
今回は、Backbone.jsを使用して、ラジオボタンを表示するテーブルを作成します。
今回使用する環境は下記の通りです。
Webブラウザ
・Mozilla Firefox (v34.05) https://www.mozilla.org/ja/firefox/new/
・FireBug (v2.0.7) https://addons.mozilla.org/ja/firefox/addon/firebug/
JavaScriptライブラリ
・Backbone.js (v1.1.2) http://backbonejs.org/
・Underscore.js (v1.7.0) http://underscorejs.org/
・jQuery (v2.1.1) http://jquery.com/
■ラジオボタンのテーブル
【デモはこちら】
【ソースファイルはこちら】
ラジオボタン付きのテーブルと登録・削除ボタンを作成します。
名前のテキストボックスに入力して、登録ボタンを押下すると、
テーブルにラジオボタンと名前が追加されます。
ラジオボタンを選択して、削除ボタンを押下すると、そのテーブルデータが削除されます。
index.html のhead に下記の内容を記述します。
<script type="text/template" id="template-user-table-item">
<th>
<input class="cls_radio_button" type="radio" name="item">
</th>
<td><%= data.name %></td>
</script>
テーブルデータ1件分のテンプレート template-user-table-item を作成します。
ラジオボタンのスタイルクラス名は cls_radio_button と定義します。
main.js に下記の内容を記述します。
var UserCollection = Backbone.Collection.extend({
model : UserModel,
removeSelectedModel : function() {
this.remove(this.selectedModel); // (5)
},
selectedModel : null
});
var UserTableView = Backbone.View.extend({
name : 'UserTableView',
events : {
'click #id_button_delete' : 'onClickDeleteButton' // (3)
},
initialize : function(args) {
this.collection = args.collection;
this.listenTo(this.collection, 'add', this.onAdd);
this.listenTo(this.collection, 'remove', this.onRemove);
this.compiledTemplate = _.template($('#template-user-table').text());
},
render : function() {
var tempData = {
'header' : {
'name' : '名前'
},
'label' : {
'deleteButton' : '削除'
}
};
this.$el.append(this.compiledTemplate(tempData));
return this;
},
renderItem : function() {
this.$el.find('#id_tbody').html('');
_.each(this.collection.models, function(model) {
this.$el.find('#id_tbody').append((new UserTableItemView({
'model' : model,
'collection' : this.collection
})).render().el);
}, this);
},
onAdd : function() {
console.log(this.name + '#onAdd');
this.renderItem();
},
onRemove : function() {
console.log(this.name + '#onRemove');
this.renderItem();
},
onClickDeleteButton : function(event) {
console.log(this.name + '#onClickDeleteButton');
this.collection.removeSelectedModel(); // (4)
}
});
var UserTableItemView = Backbone.View.extend({
name : 'UserTableItemView',
tagName : 'tr',
events : {
'click .cls_radio_button' : 'onClickRadioButton' // (1)
},
initialize : function(args) {
this.model = args.model;
this.collection = args.collection;
this.compiledTemplate = _.template($('#template-user-table-item').text());
},
render : function() {
var templateData = {
'data' : this.model.toJSON()
};
this.$el.append(this.compiledTemplate(templateData));
return this;
},
onClickRadioButton : function(event) {
console.log(this.name + '#onClickRadioButton:' + event.target.checked);
this.collection.selectedModel = this.model; // (2)
}
});
(1) ラジオボタンのクリックイベントを監視します。
(2) ラジオボタンを押下すると、コレクションのプロパティ selectedModel にモデルを設定します。押下される度に、押下対象のモデルを設定します。
(3) 削除ボタンのクリックイベントを監視します。
(4) 削除ボタンを押下すると、コレクションの removeSelectedModel 関数を呼びます。
(5) コレクションの remove 関数で、selectedModel に設定されているモデルを削除します。
■ラジオボタンのテーブル (ソート・複数のヘッダー)
先ほどのラジオボタンのテーブルに
複数のヘッダーとソート機能を追加します。
しかし、そのまま追加すると、ソートの再描画時にラジオボタンが消去されてしまうため、
再描画時に、ラジオボタンの表示判定を行います。
【デモはこちら】
【ソースファイルはこちら】
main.js に下記の内容を記述します。
var UserCollection = Backbone.Collection.extend({
model : UserModel,
sortAttribute : '',
sortDirection : 1,
initialize : function() {
var that = this;
this.sortComparators = {
'name' : that.comparatorString,
'age' : that.comparatorInteger,
'gender' : that.comparatorString,
'blood' : that.comparatorString,
'mailAddress' : that.comparatorString
}
},
sortToggle : function(attribute) {
if (this.sortAttribute == attribute) {
this.sortDirection *= -1;
} else {
this.sortDirection = 1;
}
this.sortAttribute = attribute;
this.comparator = this.sortComparators[attribute];
this.sort();
},
comparatorString : function(a, b) {
var a = a.get(this.sortAttribute), b = b.get(this.sortAttribute);
if (a == b) {
return 0;
}
if (this.sortDirection == 1) {
return b < a ? 1 : -1;
} else {
return a < b ? 1 : -1;
}
},
comparatorInteger : function(model) {
return model.get(this.sortAttribute) * this.sortDirection;
},
removeSelectedModel : function() {
this.remove(this.selectedModel);
},
selectModel : function(model) {
_.each(this.models, function(model) { // (2)
model.isSelected = false;
}, this);
model.isSelected = true;
this.selectedModel = model;
}
});
var UserTableItemView = Backbone.View.extend({
name : 'UserTableItemView',
tagName : 'tr',
events : {
'click .cls_radio_button' : 'onClickRadioButton'
},
initialize : function(args) {
this.model = args.model;
this.collection = args.collection;
this.compiledTemplate = _.template($('#template-user-table-item').text());
},
render : function() {
var templateData = {
'data' : this.model.toJSON()
};
this.$el.append(this.compiledTemplate(templateData));
if (this.model.isSelected) { // (3)
this.$el.find('.cls_checkbox').prop('checked', true)
}
return this;
},
onClickRadioButton: function(event) {
console.log(this.name + '#onClickRadioButton:' + event.target.checked);
this.collection.selectModel(this.model); // (1)
}
});
(1) ラジオボタンを押下すると、モデルを引数にして、コレクションの selectModel 関数を呼び出します。
(2) モデルの選択フラグ isSelected を全て false にしてから、現在選択されているモデルの isSelected を true にします。また、selectedModel にモデルを設定します。
(3) テーブルデータの描画時に、モデルの isSelected を判定して、選択中であれば、ラジオボタンにチェックを入れます。
以上です。
□過去の記事
Backbone.js入門その11「ソートテーブルを作る」
Backbone.js入門その10「テーブルと登録ボタンを作る」
Backbone.js入門その9「リストと詳細ボタンを作る」
Backbone.js入門その8「リストと削除ボタンを作る」
Backbone.js入門その7「リストと登録ボタンを作る」
Backbone.js入門その6「ModelとCollection」
Backbone.js入門その5「静的HTMLでBackbone.Viewを作る」
Backbone.js入門その4「SuperViewとSubViewのアクセスを作成する」
Backbone.js入門その3「Backbone.ViewでSubViewを作る」
Backbone.js入門その2「Backbone.Viewで複数の要素を作る」
Backbone.js入門その1「Backbone.Viewで1つの要素を作る」
Backbone.js入門その13「チェックボックステーブルを作る」
こんばんは。ゆんぼうです。
今回は、Backbone.jsを使用して、チェックボックスを表示するテーブルを作成します。
今回使用する環境は下記の通りです。
Webブラウザ
・Mozilla Firefox (v34.05) https://www.mozilla.org/ja/firefox/new/
・FireBug (v2.0.7) https://addons.mozilla.org/ja/firefox/addon/firebug/
JavaScriptライブラリ
・Backbone.js (v1.1.2) http://backbonejs.org/
・Underscore.js (v1.7.0) http://underscorejs.org/
・jQuery (v2.1.1) http://jquery.com/
■チェックボックスのテーブル
【デモはこちら】
【ソースファイルはこちら】
チェックボックス付きのテーブルと登録・削除ボタンを作成します。
名前のテキストボックスに入力して、登録ボタンを押下すると、
テーブルにチェックボックスと名前が追加されます。
チェックボックスを選択して、削除ボタンを押下すると、そのテーブルデータが削除されます。
また、全てを選択するチェックボックスを押下すると、各チェックボックスが併せて変更されます。
index.html のhead に下記の内容を記述します。
<script type="text/template" id="template-user-table">
<input id="id_button_delete" type="button" value="<%= label.deleteButton %>">
<hr>
<table class="cls_table">
<thead>
<tr>
<th><input class="cls_all_checkbox" type="checkbox"></th>
<th><%= header.name %></th>
</tr>
</thead>
<tbody id="id_tbody">
</tbody>
</table>
</script>
<script type="text/template" id="template-user-table-item">
<th>
<input class="cls_checkbox" type="checkbox">
</th>
<td><%= data.name %></td>
</script>
テーブル全体のテンプレート template-user-table を作成します。
全て選択用のチェックボックスのスタイルクラス名は cls_all_checkbox と定義します。
テーブルデータ1件分のテンプレート template-user-table-item を作成します。
チェックボックスのスタイルクラス名は cls_checkbox と定義します。
main.js に下記の内容を記述します。
var UserCollection = Backbone.Collection.extend({
model : UserModel,
removeSelectedModel : function() {
var selectedCollection = this.models.filter(function(model) { // (17)
return model.isSelected;
});
this.remove(selectedCollection); // (18)
},
isSelectedAll : false,
selectModelAll : function(isSelected) {
this.isSelectedAll = isSelected;
_.each(this.models, function(model) { // (10)
model.isSelected = isSelected;
});
this.trigger('selectAll'); // (11)
},
selectModel : function() {
this.isSelectedAll = this.models.every(function(model) { // (3)
return model.isSelected
});
this.trigger('select'); // (4)
}
});
var UserTableView = Backbone.View.extend({
name : 'UserTableView',
events : {
'click .cls_all_checkbox' : 'onClickAllCheckbox', // (8)
'click #id_button_delete' : 'onClickDeleteButton' // (15)
},
initialize : function(args) {
this.collection = args.collection;
this.listenTo(this.collection, 'add', this.onAdd);
this.listenTo(this.collection, 'remove', this.onRemove); // (19)
this.listenTo(this.collection, 'select', this.onSelect); // (5)
this.listenTo(this.collection, 'selectAll', this.onSelectAll); // (12)
this.compiledTemplate = _.template($('#template-user-table').text());
this.currentHeader = null;
},
render : function() {
var tempData = {
'header' : {
'name' : '名前'
},
'label' : {
'deleteButton' : '削除'
}
};
this.$el.append(this.compiledTemplate(tempData));
return this;
},
renderItem : function() {
this.$el.find('#id_tbody').html('');
_.each(this.collection.models, function(model) {
this.$el.find('#id_tbody').append((new UserTableItemView({
'model' : model,
'collection' : this.collection
})).render().el);
}, this);
},
renderSelectAll : function() {
this.$el.find('.cls_all_checkbox').prop('checked', this.collection.isSelectedAll) // (7)
},
onAdd : function() {
console.log(this.name + '#onAdd');
this.renderItem();
},
onRemove : function() {
console.log(this.name + '#onRemove');
this.renderItem(); // (20)
},
onSelect : function() {
console.log(this.name + '#onSelect');
this.renderSelectAll(); // (6)
},
onSelectAll : function() {
console.log(this.name + '#onSelectAll');
this.renderItem(); // (13)
},
onClickAllCheckbox : function(event) {
console.log(this.name + '#onClickAllCheckbox');
this.collection.selectModelAll(event.target.checked); // (9)
},
onClickDeleteButton : function(event) {
console.log(this.name + '#onClickDeleteButton');
this.collection.removeSelectedModel(); // (16)
}
});
var UserTableItemView = Backbone.View.extend({
name : 'UserTableItemView',
tagName : 'tr',
events : {
'click .cls_checkbox' : 'onClickCheckbox' // (1)
},
initialize : function(args) {
this.model = args.model;
this.collection = args.collection;
this.compiledTemplate = _.template($('#template-user-table-item').text());
},
render : function() {
var templateData = {
'data' : this.model.toJSON()
};
this.$el.append(this.compiledTemplate(templateData));
if (this.model.isSelected) {
this.$el.find('.cls_checkbox').prop('checked', true) // (14)
}
return this;
},
onClickCheckbox : function(event) {
console.log(this.name + '#onClickCheckbox:' + event.target.checked);
this.model.isSelected = event.target.checked; // (2)
this.collection.selectModel();
}
});
各チェックボックスを押下したとき
(1) 各テーブルデータのチェックボックスのクリックイベントを監視します。
(2) チェックボックスを押下したとき、モデルの選択フラグ isSelected にチェック状態を設定します。また、コレクションの selectModel 関数を呼びます。
(3) コレクションの every 関数を使用して、全てのモデルの isSelected が true かどうかを真偽値を isSelectedAll に設定します。
(4) select イベントを発火します。
(5) select イベントを監視します。
(6) 全て選択用のチェックボックスを描画します。
(7) 全て選択用のチェックボックスのチェック状態は、コレクションの isSelectedAll プロパティの値で設定します。
全て選択用のチェックボックスを押下したとき
(8) 全て選択用のチェックボックスのクリックイベントを監視します。
(9) 全て選択用のチェックボックスを押下したとき、チェック状態を引数にして、コレクションの selectModelAll 関数を呼び出します。
(10) 全てのモデルの isSelected を同じ値に設定します。
(11) selectAll イベントを発火します。
(12) selectAll イベントを監視します。
(13) 各テーブルデータを描画します。
(14) モデルの isSelected が true のとき、チェックボックスのチェックを設定します。
削除ボタンを押下したとき
(15) 削除ボタンのクリックイベントを監視します。
(16) 削除ボタンを押下したとき、コレクションの removeSelectedModel 関数を呼びます。
(17) filter 関数を使用して、isSelected が true のモデル配列を取得します。
(18) コレクションの remove 関数を呼び出して、モデルを削除します。モデル配列が複数あるときは、複数のモデルを削除します。
(19) remove イベントを監視します。
(20) 各テーブルデータを描画します。
■チェックボックスのテーブル (ソート・複数のヘッダー)
【デモはこちら】
【ソースファイルはこちら】
先ほどのチェックボックスのテーブルに、複数のヘッダーとソート機能を追加します。
これらの追加に対する処理はありません。そのまま追加します。
リンク先のソースファイルをご覧ください。
以上です。
□過去の記事
Backbone.js入門その11「ソートテーブルを作る」
Backbone.js入門その10「テーブルと登録ボタンを作る」
Backbone.js入門その9「リストと詳細ボタンを作る」
Backbone.js入門その8「リストと削除ボタンを作る」
Backbone.js入門その7「リストと登録ボタンを作る」
Backbone.js入門その6「ModelとCollection」
Backbone.js入門その5「静的HTMLでBackbone.Viewを作る」
Backbone.js入門その4「SuperViewとSubViewのアクセスを作成する」
Backbone.js入門その3「Backbone.ViewでSubViewを作る」
Backbone.js入門その2「Backbone.Viewで複数の要素を作る」
Backbone.js入門その1「Backbone.Viewで1つの要素を作る」