2007年9月27日木曜日

Extでツリーのアイコンを変更2

Extでツリーのアイコンを変更に加えて、ドラッグ&ドロップ時のアイコンも変更できる。

.x-tree-node-expanded img.xxx,
.x-tree-node-collapsed img.xxx,
.x-tree-node-leaf img.xxx,
.x-tree-node img.xxx {
background-image:url(images/xxx.gif);
}

2007年9月21日金曜日

ExtのsetStyleで数値の指定は要注意

Ext.ElementのsetStyleでtopやleftを設定していたらハマった。IEとFFで動かしていたら、それぞれ微妙に動作が違った。なのでDOCTYPEをstrictにした。今度は微妙どころかポジションが設定できていなかった。setTopsetLeftを使用せずに、setStyle('top', 120)とかしていたのが原因だった。strictの場合にsetStyleを使うなら、きちんと単位'px'を付けてsetStyle('top', 120 + 'px')でないといけないらしい。当たり前かもしれないけど今度からはsetTopとか使おう。そしてCSSにはちゃんと'px'を付けようorz

2007年9月18日火曜日

Extで要素の追加

Ext.DomHelperを使うと要素を簡単に追加できる。cnで配列を渡すと一度に作れるので便利。idやclsと同じようにtagでタグ名を指定できる。デフォルトではdiv要素を作って追加するようだ。append以外にもinsertBeforeなどがある。

Ext.DomHelper.append(document.body, {
cn:[
{id:'header', cls:'x-layout-inactive-content'},
{id:'footer', cls:'x-layout-inactive-content'}
]
});

そういえば2.0のサンプルが公開されてた。Web Desktopがかっこいい。

2007年9月16日日曜日

ExtのDragDropにバグ?

DDProxyでいろいろ試しているが、maintainOffsetを設定して要素をボックス内から出さないようにすると、スクロールとチック?がうまく動作しない。ソースコードを見ると親要素のスクロール位置を気にしてはいるものの、Ticksの再計算に利用されていない。

まずはstartDragでconstrainToを呼び出さないといけない。ただ、それだけではうまくいかず、ポジションを初期化する必要がある。

var proxy = Ext.get(elmt.id).initDDProxy('proxytest', {
maintainOffset:true
}, {
startDrag : function(){
this.setInitPosition();
this.constrainTo('container');
},

次に、Ticksの再計算のあたりを修正する。暫定対処として、setYConstraintなどを書き換える。

    setYConstraint: function(iUp, iDown, iTickSize) {
this.topConstraint = iUp;
this.bottomConstraint = iDown;

// minとmaxにスクロール位置の考慮が抜けてる
// this.minY = this.initPageY - iUp;
// this.maxY = this.initPageY + iDown;
var adjustment = Ext.get('constrainTo').getScroll().top;
this.minY = this.initPageY - iUp - adjustment;
this.maxY = this.initPageY + iDown - adjustment;

// 呼出元のconstrainToがiTickSizeを渡してこない
// this.setYTicks(this.initPageY, iTickSize);
this.setYTicks(this.initPageY, 25);

this.constrainY = true;
}
});

2007年9月12日水曜日

Grailsで素敵にJSON

JSonBuilderを使用してみた。結論から言えば、単純なテーブルっぽいのを返すなら使える。複雑なのを返そうとするなら素敵とは言えない。Grails - Ajaxには使い方が少ししか載ってないので、ソースコードを追ってみたらテストケースにいろいろ書いてあった。テストケースはgrails-src-0.6.zipなどを解凍して、test\commons\grails\util\JSonBuilderTests.java。テスト用のparseメソッドでいろいろ試せるのがよい。

render(builder:'json') {
A{
B("BB") {
C("CC") {
// D("DD") 例外が発生する。
}
}
}
}
Dがないと動く。結果は{"A":[{"B":"BB","C":"CC"}]}。配列を使う場合は繰り返し文を使用しないといけないよう。例えば、
render(builder:'json') {
A {
B(C:"C1", D:"D1")
B(C:"C2", D:"D2")
}
}
とは書けない。何かしらeachでもforでも回してあげるとうまくいく。
render(builder:'json') {
A {
BList.each {
B(C:it.C, D:it.D)
}
}
}
こんな感じ。他にもいろいろ試してみた。

render(builder:'json') {
A {
B("BB") {
C {
D(E:"EE", F:"FF") {
G("GG") {
// H("HH") { 例外が発生する。
I {
J("JJ")
}
// }
}
}
}
}
}
}

Hの箇所で例外が発生する。3階層が駄目なのか?上記のコードの結果は下記。結果が微妙すぎる。名前のみのAとCは配列になるみたい。

{"A":[
{"B":"BB", "C":[
{"E":"EE","F":"FF"},
{"G":"GG","I":[
{"J":"JJ"}
]}
]}
]}

とりあえず配列を2つ持つようなのの返し方がわからなかった。あと配列もたせる場合に、その他の要素?を2つ以上持たせる方法もわからなかった。そもそも階層がずれてるあたりは意味がわからない。parseメソッドで例外が発生するタイミングもよくわからないので解析する気にならない。それくらいなら自分でビルダー組んだ方が良いかも。そのうち直るのかな?複雑な使い方はやめた方が良い感じ。

JSonBuilderのソースコードを見たら'a'とか'o'とかでarrayとobjectを何とかしようとしてるみたいだけど、これもよくわからず。今日はここまで。

2007年9月11日火曜日

Extでカレンダー表示

DatePickerをid属性と結びつければ表示される。とりあえず日付を選択したら日付をalertするようにしてみた。詳しい説明は不要ですね。

<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8">
<title>Sample - DatePicker</title>
<link rel="stylesheet" type="text/css" href="css/ext-all.css" />
<script type="text/javascript" src="js/ext-base.js"></script>
<script type="text/javascript" src="js/ext-all.js"></script>
<script type="text/javascript"><!--
var DatePickerSample = function() {
var picker = false

return {
init : function() {
if (!picker) {
picker = new Ext.DatePicker({
dayNames:['日', '月', '火', '水',
'木', '金', '土'],
monthNames:['1月', '2月', '3月', '4月',
'5月', '6月', '7月', '8月',
'9月','10月','11月','12月'],
prevText:'先月',
nextText:'翌月',
todayText:'今日'
});
picker.render('calendarId');
picker.on('select', this.onSelect, this);
}
},

onSelect : function(picker, date) {
alert(date);
return true;
}
};

}();

Ext.onReady(DatePickerSample.init, DatePickerSample, true);
//--></script>
</head>
<body>
<div id='calendarId' />
</body>
</html>

2007年9月6日木曜日

ExtでDrag & Dropしたら要素が移動


Drag & Drop exampleを参考にして作ってみた。多分これがBox間の移動の基本だと思う。あとは適当にDragZoneに移行していこう。とりあえずDropTargetを用意してそこにDrag & Dropで要素が移動する。

// elmtは移動する要素
var ds = new Ext.dd.DragSource(elmt.id, {});
// ドラッグ対象の要素をいったん隠す
ds.onStartDrag=function(x, y) {
var srcEl = Ext.get(this.getEl());
srcEl.setStyle('visibility', 'hidden');
return true;
};
// ドラッグ対象の要素をドロップ対象に移す
ds.onDragDrop=function(e, id) {
var srcEl = Ext.get(this.getEl());
var destEl = Ext.get(id);
destEl.appendChild(srcEl);
this.hideProxy(true);
return true;
};
// ドラッグ対象の要素を再表示する
ds.onEndDrag=function(e) {
var srcEl = Ext.get(this.getEl());
srcEl.setStyle('visibility', '');
return true;
};

2007年9月5日水曜日

Extでモーダルダイアログ

ダイアログのサンプルをいじってみた。<div class="x-dlg-hd"><div class="x-dlg-bd">がそれぞれダイアログのタイトルと中身になる。中身は普通にフォーム要素を書いておけばOK。Ext.formを利用すればコンボボックスや日付入力フィールドなどをダイアログに表示できる。

<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8">
<title>Sample - Date</title>
<link rel="stylesheet" type="text/css" href="css/ext-all.css" />
<script type="text/javascript" src="js/ext-base.js"></script>
<script type="text/javascript" src="js/ext-all.js"></script>
<script type="text/javascript"><!--
var DialogSample = function() {
var dialog, showBtn;

return {
init : function() {
// 日付入力フィールドを用意する
new Ext.form.DateField({
format:'Y/m/d',
value: new Date().format('Y/m/d'),
allowBlank:false
}).applyTo('dateId');

// idがbuttonIdのonclickアクションを設定する
showBtn = Ext.get('buttonId');
showBtn.on('click', this.show, this);
},

show : function() {
// 一回だけ初期化する。
if(!dialog){
dialog = new Ext.BasicDialog("dialogId", {
width:200,
height:100,
shadow:true,
minWidth:200,
minHeight:100,
proxyDrag: true
});
dialog.addKeyListener(27, dialog.hide, dialog);
dialog.addButton('Submit', dialog.hide, dialog)
.disable();
dialog.addButton('Close', dialog.hide, dialog);
}
dialog.show(showBtn.dom);
}
};
}();

Ext.onReady(DialogSample.init, DialogSample, true);
//--></script>
</head>
<body>
<div id='dialogId' style="visibility:hidden;position:absolute;">
<div class="x-dlg-hd">Title</div>
<div class="x-dlg-bd">
<input type="text" size="20" name="dateId" id="dateId" />
</div>
</div>
<button id='buttonId'>show</button>
</body>
</html>

2007年9月3日月曜日

ExtでDraggable&Resizableなdiv要素

とりあえずGoogleカレンダー的なものをExt使って作りたいのです。そのうちExtに用意されたりして。

<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8">
<title>Sample - Drag & Resize</title>
<link rel="stylesheet" type="text/css" href="css/ext-all.css" />
<script type="text/javascript" src="js/ext-base.js"></script>
<script type="text/javascript" src="js/ext-all.js"></script>
<script type="text/javascript"><!--
Ext.onReady(function(){
var elmt = document.createElement('div');
elmt.id = 0;
elmt.className='increment';
document.body.appendChild(elmt);

new Ext.Resizable(elmt.id, {
handles: 's',
heightIncrement:50,
minHeight: 50,
pinned:true
});

new Ext.dd.DragSource(elmt.id);

});
//--></script>
<style type="text/css">
.increment {
border:1px solid #c3daf9;
width:100;
height:200;
}
</style>
</head>
<body>
</body>
</html>

生成した要素でDragSourceを利用する場合はappendChild後じゃないと動作しないみたい。要素を取得できないのかな?先に試したResizableがappendChild前でOKだったので結構はまった。

Extでツリーのアイコンを変更

ノードにiconCls:'xxx'を設定すると、そのノードのアイコンに対応するスタイルが.x-tree-node img.xxxになる。あとはbackground-image:url()でアイコンを指定する。あとcls:'yyy'を設定すると独自のスタイルを適用できる。ちなみにleafとfolderはext-all.cssで定義済みなので使用しないこと。

<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8">
<title>Sample - Tree</title>
<link rel="stylesheet" type="text/css" href="css/ext-all.css" />
<script type="text/javascript" src="js/ext-base.js"></script>
<script type="text/javascript" src="js/ext-all.js"></script>
<script type="text/javascript"><!--
Ext.onReady(function(){
var json =
[
{'text':'A', 'id':1, 'leaf':false, 'children':[
{'text':'AA', 'id':11, 'leaf':true}
], 'iconCls':'xxx', 'cls':'yyy'}
];

var tree = new Ext.tree.TreePanel('tree', {
loader: new Ext.tree.TreeLoader(),
rootVisible:false,
});

var root = new Ext.tree.AsyncTreeNode({
children: json
});

tree.setRootNode(root);
tree.render();
root.expand();
});
//--></script>
<style type="text/css">
.x-tree-node img.xxx {
background-image:url(images/icon.gif);
}
.yyy {
background-color:#c3f9da;
}

#tree {
height:200px;
width:100px;
border:1px solid #c3daf9;
overflow:auto;
}
</style>
</head>
<body>
<div id="tree" />
</body>
</html>

Extでツリー表示

JSONを使用したstaticなツリーを試してみた。サーバからJSON返せれば素敵だけど、それは先のお話。

<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8">
<title>Sample - Tree</title>
<link rel="stylesheet" type="text/css" href="css/ext-all.css" />
<script type="text/javascript" src="js/ext-base.js"></script>
<script type="text/javascript" src="js/ext-all.js"></script>
<script type="text/javascript"><!--
Ext.onReady(function(){
var json =
[
{'text':'A', 'id':1, 'leaf':false, 'children':[
{'text':'AA', 'id':11, 'leaf':false, 'children':[
{'text':'AAA', 'id':111, 'leaf':true},
{'text':'AAB', 'id':112, 'leaf':true},
]},
{'text':'AB', 'id':12, 'leaf':false, 'children':[
{'text':'ABA', 'id':121, 'leaf':true},
{'text':'ABB', 'id':122, 'leaf':true},
]}
]},
{'text':'B', 'id':2, 'leaf':false, 'children':[
{'text':'BA', 'id':21, 'leaf':false, 'children':[
{'text':'BAA', 'id':211, 'leaf':true},
{'text':'BAB', 'id':212, 'leaf':true},
]},
{'text':'BB', 'id':12, 'leaf':false, 'children':[
{'text':'BBA', 'id':221, 'leaf':true},
{'text':'BBB', 'id':222, 'leaf':true},
]}
]}
];

var tree = new Ext.tree.TreePanel('tree', {
// jsonを内部でcreateNodeするために必要
loader: new Ext.tree.TreeLoader(),
// 要素のドラッグ&ドロップを許可
enableDD:true,
// ルート要素の可視設定
rootVisible:true,
});

var root = new Ext.tree.AsyncTreeNode({
text: 'Root',
id:'root',
// ルート要素のドラッグを許可しない
draggable:false,
// 上記の変数jsonを設定
children: json
});

tree.setRootNode(root);
tree.render();

// ルート要素を展開
root.expand();
});
//--></script>
<style type="text/css">
#tree {
height:200px;
width:100px;
border:1px solid #c3daf9;
overflow:auto;
}
</style>
</head>
<body>
<div id="tree" />
</body>
</html>

最終的にはGrailsと連携させる予定。GrailsのJsonビルダーが素敵。

Grails - Ajax

Extでリサイズ

ボックスのリサイズを試してみた。Googleカレンダーみたいなのがこれで作れそうな感じ。

<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="css/ext-all.css" />
<script type="text/javascript" src="js/ext-base.js"></script>
<script type="text/javascript" src="js/ext-all.js"></script>
<script type="text/javascript"><!--
Ext.onReady(function(){
new Ext.Resizable('incrementId', {
// 増分を設定
widthIncrement:100,
heightIncrement:50
});

new Ext.Resizable('handlesId', {
// リサイズ可能な方向を右側(east)だけに設定
handles:'e',
// リサイズ可能な辺を表示
pinned:true
});

new Ext.Resizable('animateId', {
// アニメーション
animate:true,
// アニメーションの速さ
duration:.6
});
});
//--></script>
<style type="text/css">
.increment, .handles, .animate {
border:1px solid #c3daf9;
width:200;
height:100;
}
</style>
</head>
<body>
<div id="incrementId" class="increment">increment</div><hr />
<div id="handlesId" class="handles">handles</div><hr />
<div id="animateId" class="animate">animate</div><hr />
</body>
</html>

2007年9月2日日曜日

Extでコンボボックス

コンボボックスのサンプルを試してみた。いくつか種類があって、今回は既存のリストボックスをコンボボックスに変換するタイプのものを選択。既存リストボックスのid属性を指定してあげればよいだけ。直接入力できて選択要素をフィルタリング&補完してくれる。

<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8">
<title>Sample - ComboBox</title>
<link rel="stylesheet" type="text/css" href="css/ext-all.css" />
<script type="text/javascript" src="js/ext-base.js"></script>
<script type="text/javascript" src="js/ext-all.js"></script>
<script type="text/javascript"><!--
Ext.onReady(function(){
new Ext.form.ComboBox({
// 対象のリストボックスのidを設定する
transform:'comboId',
// 必ず要素を選択させる
forceSelection:true,
// 候補となる要素文字列を補完する
typeAhead: true,
// 一文字ごとにチェックする
triggerAction: 'all',
// サイズを設定する
width:135
});
});
//--></script>
</head>
<body>
<form action="">
<select name="combo" id="comboId">
<option value="0001">0001</option>
<option value="0011">0011</option>
<option value="0111">0111</option>
<option value="1111">1111</option>
</select>
</form>
</body>
</html>

Extで日付入力

日付の入力フィールドを使ってみた。既存のテキストフィールドにid属性で結び付けるだけで簡単に使えるのが嬉しい。テキストフィールドの横にカレンダーボタンが付いて、日付を選択できるようになる。あとバリデートしてくれる。今日の日付を初期値にするためにDateも少しだけ使った。日付のフォーマットがすごく簡単。


<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8">
<title>Sample - Date</title>
<link rel="stylesheet" type="text/css" href="css/ext-all.css" />
<script type="text/javascript" src="js/ext-base.js"></script>
<script type="text/javascript" src="js/ext-all.js"></script>
<script type="text/javascript"><!--
Ext.onReady(function(){
var df = new Ext.form.DateField({
// 2007/09/01の形式を指定する
format:'Y/m/d',
// 今日の日付を初期値に設定する
value: new Date().format('Y/m/d'),
// 入力を必須にする
allowBlank:false
});
// 対象のテキストフィールドのidを設定する
df.applyTo('dateId');
});
//--></script>
</head>
<body>
<form action="">
<input type="text" size="20" name="date" id="dateId" />
</form>
</body>
</html>

サンプルをいくつか見たけど、スタイルに統一感があって素敵。

追記:使いまわしはできないみたいで、もうひとつテキストフィールド作ってdf.applyTo('dateId2');みたいなコードを追加すると変な動作をする。

2007年8月31日金曜日

Extに挑戦!

Ajaxを使ってみたかったので調査してたらExtに辿り着いた。ドキュメントもサンプルも豊富なので取り掛かりやそうだ。

Ext JS

Ext Documentation Center