2010年12月31日金曜日

ホームセンターとナルシルバー

楓を移植した際に作った花壇のレンガが自転車が倒れてぶつかったことで
ぼろっとひとつだけもげてしまった。

またモルタル練るの?この寒い季節に?
いや、そんなことはなく。
そんな時に思いつくのがモルタル用の接着剤みたいな品物。

で、ホームセンターに行った。
T-REXは量が多いので隣にあったネバットをみると適用下地が
こちらもモルタルなのでよさそう。

店員さんに聞いてみた。
ネバット、タイル用接着剤なのでモルタル、レンガはダメらしいとのこと。
T-REXはいいんだけどコレだと量が多すぎだよ。
困った。
コニシボンドとのK10を紹介され、ほほーこれでできるの?
とおもいきや

これがベストです。
とすすめてもらったのが


















成瀬科学株式会社のナルシルバー。
ちょっとT-REXより接着力は劣るかも。。。とのことだったけど、
量がイイし、ちょっとなおすだけだし。
なんせ名前がなんとなく気に入った。


モルタル、レンガの組み合わせで
ちょっとなおしたいときは「ナルシルバー」で。



あ、
あと18cm6Fの板も購入したので本棚を増築することにした。
これも明日。
今年最後の日、
花壇直しと本棚作りは決定。

そんな2010年末。



2010年12月29日水曜日

Android2.2(MT3G-test3_S.zip+ezBiffTestKernel20101031-ebi0_S.zip)を入れてみる

今年3月に1.6のカスタムロムに書き換えたあと
調子こいて2.1いれて失敗して、結局1.6のカスタムロムに
戻し、数ヶ月。
しばらく興味なくて.
でもこの間みたらどうやら2.2が調子いいみたい。
でもってクロックアップしてみようと思い。。。

今に至るんだけどど忘れ&環境が吹っ飛んでてどこにも無い。
という状況です。

結局、titaniumをいれたAcer1410にSDKが入ってるってことで
作業はこのPCをメインに行うことに決定。

で、まずUSBドライバーをインストール。
こちらはSDK入れるときに付いてくるようになったSDKManagerからインストール可能。













フォルダができる。


















フォルダの中身









次にUSB接続するときに手動でさっきのインストールフォルダを指定する。
んだろうけど、さっき一回接続しちゃってるからデバイスマネージャからドライバの更新でインストール。











あとはshell接続したAndroidにShellたたいて。ここから先はなんとなくおぼえてるから楽。

最後は2ちゃんの379さんに助けられた。
http://desktop2ch.net/smartphone/1291345291/

0:前提として全データ削除されても大丈夫なようにデータだけはPCにバックアップ。
1:ユーティリティAPをDLしておいてSDカードにDL

2:カスタムロムをDLしておいてSDカードにDL
http://forum.xda-developers.com/showthread.php?t=811620
(MT3G-test3_S.zip)


http://forum.xda-developers.com/showpost.php?p=8930875&postcount=475
(ezBiffTestKernel20101031-ebi0_S.zip)
コレはメモリ増量していない端末向けの追加ROM。(これ当ててなくてはまった)

3:SDカードをGDDPhoneにセット
4:GDDをUSB接続
5:コマンドプロンプトからadb shell
6:su でrootになって
# su
7:1:のユーティリティをやく。
# mount -o remount,rw /dev/block/mtdblock3 /system
# flash_image recovery /sdcard/recovery-RA-sapphire-v1.7.0G.img
# mount -o remount,ro /dev/block/mtdblock3 /system
8:PCと同期とって
# sync
9:リカバリリブート
# reboot recovery
10:ワイプしておこう。一旦電源落として「戻る」+「電源」でfastbootで起動
11:コマンドプロンプトからfastboot erase system -wでユーザデータとキャッシュをクリア
12:homeボタンで電源落として
13:「Home」+「電源」でrecoverybootで起動
14:Flash zip from sdcardからMT3G-test3_S.zip焼いて
15:Flash zip from sdcardからezBiffTestKernel20101031-ebi0_S.zip焼いて
16:再起動
でいいのかな。

実際は
MT3G-test3_S.zipやいてGDD2009の起動画面でフリーズして。。
右往左往してezBiffTestKernel20101031-ebi0_S.zipを追加であてたから
上記手順でやったわけじゃない。


3月16日に1.6に上げた時に残した備忘録よりはましだな。

morelocale2でひとまず日本語化して
OpenWnn入れて。
Twitter入れて。



あとはソフトを。。。ってなに使ってたっけか。。。

あ、あとクロックアップしなきゃ。

















ひとまずGDDPhone。これからもしばらくはよろしくです。

2010年12月17日金曜日

Titaniumを入れてみたよ

昨日、Titanium Desktopで作られたAPIDocをみて、
あーExtjsでネイティブアプリってなんかおもろいなぁ。

アカベコさんのTitanium と Aptana でモバイル開発がほんと丁寧にしっかりとまとまってて
今それを見ながらインストールが終わったところ。こちらのサイトで予習はほぼおしまい。
でも手を動かさなきゃ。ということでインストールして動かしてみるところまではやろうとおもう。

僕はマカーじゃないし、ipad持っているけど使いこなせていない。
iphone、ipadのWin用エミュレータも無い(?)。
で、GDDPhoneもあるのでひとまずAndroid向けのAPを試してみようかと思う。
まさしく解説していただいたサイトそのままですね。

■必要なのは
・JDK
・Android SDK

・titanium

■DL、インストール、各種パス通しが終わったら




■titaniumにSDKの場所を設定。
間違った場所を指定すると事細かく指示してくれれるんだけどうまくいかない。
バージョンあがって変わったみたい。です。こちらより。
要するにplatform-toolsからtoolsの下にadb.exeをコピーする。


















■プロジェクトを作ってみた。

プロジェクトのタイプをデスクトップからモバイルにして。。




















■エミュレータを起動確認して。。


















今日はここまで。

※とくに躓くこと無くサクっとできました。情報を公開してくださってる方にホント感謝。
あすからようやく予習の開始。サンプル動かしてすこーしいじくって終わる予定。
次回の勉強会はnodejsからみもあり、より楽しみになってきた。

2010年12月15日水曜日

ExtJS-105 TitaniumなAPIDoc

咳がひどいのでプログラムはおあずけ。
コメントだけ書いてあたまのなか整理して終了。

で、JSDocな感じでかくべきなんだろなぁ。とextdocとかあったっけなぁ。とか
思って検索してたらTitanium Desktop ApplicationなAPIDocがあったので
試しに入れてみたよ。

titaniumは次回の勉強会(今年最後)で紹介されるし、
事前として記事読んでおいても良いかもあなぁ。。
集まる人はみんな知ってるだろうし。
最近話してて、ヤベ。知らないの俺だけだ。感が結構あるしね。

ダウンロードはこちら













で、いれてみた。
titaniumのruntimeとかで結構時間取られるけどさっくり。



















デスクトップにショートカットできた。














動かしてみた。バージョンは3.1.1の物だけどね。
昔Airバージョンもあったよね。そういえば。その頃はポケファイ持ってなかったから
重宝したっけな。
いれてどうこうってわけでもなかったんですが、
どこまでサクっとできるのかJSとHTMLでモバイル、Rubyとか合わせて?デスクトップアプリ。
とかできるのかな。。

なにはともあれ、楽しみ。ExtJSもちゃんと動いてるしね。















楽しみだらけだけど、、、、
じかんがないんだよね。

ExtJS-104 Ext.ux.UnitTestを使う準備

昨日引っ張っておいた
Ext.ux.UnitTestを使う準備を。。
いろいろ細々とファイルはあるものの、最低限のファイルだけにして
最小構成にしてみた。

まだサラッと見ただけだからちょっと調査しないと使えないけどね。

ちなみにこちらからDLしてきました。


配置はこんな感じにしてみた。











で、
テストとなるコードの雛形はこんな感じで切り分けておいた。


/*
assertTrue: function(actual, errorMsg)
assertFalse: function(actual, errorMsg)
assertEquals: function(actual, expected, errorMsg)
assertNotEquals: function(actual, expected, errorMsg)
assertUndefinedOrNull: function(actual, errorMsg)
assertNotUndefinedOrNull: function(actual, errorMsg)
assertContains: function(parentString, subString, errorMsg)
assertNotContains: function(parentString, subString, errorMsg)
*/
Ext.ux.NewUnitTest({
    testName: 'ほげのテスト',
    testGroup: 'hogehogetestGroup',
    testFunction: function(testObj) {
      
        var stringVariable = '1';
        var integerVariable = 1;
        var floatingVariable = 1.00;
      
        this.assertEquals(
            stringVariable,
            '1',
            'stringVariable has unexpected value'
        );

        this.assertEquals(
            integerVariable,
            1,
            'integerVariable has unexpected value'
        );

        this.assertEquals(
            floatingVariable,
            1.00,
            'floatingVariable has unexpected value'
        );
    }
});

で、動かす方は、

Ext.onReady(function() {
Ext.ux.UnitTest.init();
});

で、動かすとこんな感じで。

















これ、グループで分けられるからイイネ。
左上のスタートで円グラフ更新されたグリーンに。


開発がおっそろしく牛歩なのでこのような
小さな小さな環境でサックリできるのはうれしいこと。




2010年12月13日月曜日

ExtJS-103 階層構造のGrid4

一ヶ月以上放置状態でした。
たまにコードをいじったりしてたけどほぼ進展なし。

で、
混乱したので整理した。









で、UnitTestしよーって思って
Ext.ux.UnitTestを引っ張ってきておしまい。

風邪も引いてるし。
年末だし。
すすまんなぁ。

ねよ。

2010年11月9日火曜日

ExtJS-102 階層構造のGrid3

毎度のことながらずいぶんと時間がたった。
今日は少し進捗が見られたので残しておこ。

超特化しててまだ使い回せないけど、
Alt+Rで兄弟行挿入。
Alt+Cで子行挿入。
ってのまではできた。

あとは
・F2、Enterで名前の変更切り替え
→コレはカッコ悪いけどひとまずEditorGridPanel継承してeditorそのままでいいかも
・サーバへの仕組み
→今日のところは親IDを更新してないからコレを後日対応。
→サーバサイドでは親登録後の本IDで受信した一時IDを置換しつつ登録すればOK。
・複数選択+Tab/Shift+Tabで小/親の切り替え
これくらい出来ればWBS作るとき便利そう。


このへんてこりんなGridと進捗バーグリッドがネックだったから
今日の成果はうれしい。

2010年10月27日水曜日

コスモスと秘密兵器

ツイッターし始めると日々のことをブログに残すことをしなくなる。
ExtJsだけは以前までやってたことがすっかり頭から消えるのでブログは必要だけど。


コスモスを見てきた。
まぁなんとも素晴らしく。
曇っていたのが残念だったのですが、量に圧倒されました。














と、

週末扇風機をしまってたら
なんと!!
出てきました!!
ながらダイエットの決定版!!













ナイキのおもり。

手に巻くやつが700g弱。
足に巻くやつが1100gちょい。

これ肩こり倍増です。3、4年前、これ付けてジョギングとかしてたなんて信じられない。

てか、この姿、なんかアホだな。

2010年10月16日土曜日

ExtJS-101 階層構造のGrid2

既存のTreePanelを半写経しつつ作っている。
んだけど、

CSSを既存のものをつかいたかったから
それにあわせて作った。

それっぽくなった。
あとはコンテキストメニューから挿入、追加、削除。とか
keymapのこと勉強してAlt+I→Rで挿入とかそんな実装を加えて操作用のパス情報、ID情報を非表示にしたらそれとなく使えそう。
それができたら階層構造Gridはもうやめよう。

でもクラス化せずにhtmlベタでサンプルとして作ってるから
これからモジュール化するのが面倒だね。
これ、やっぱりlineバージョンに切り替えられるようにしておいたほうが後々らくだよなぁ。

2010年10月14日木曜日

ExtJS-100 階層構造のGrid

あ、100番だ。
あー100番くらいには少し形にしたかったんだけどなぁ。

もう一ヶ月くらいゆっくり時間をとってExtJsをやっておらず、
やったとしても30分位しかさわってなくて、、ちょっと調べておしまい。とか。
もしかしたら前進せず、後退してるんじゃないかという勢いでした。

ので、

すこし時間をとってみました。っても1時間~2時間ですが。
なんか休日どっぷり時間をとってプログラムしてみたい。

さて、また
の続き。ほんの少し実装を変えて再構築中。










もともとTreePanelってのがあるんだけど
データ構造を合わすのが面倒なのと
ひとまずどうしたらこうした階層構造なGridを簡単に作れるかの
勉強ではじめたこのGrid。

DDで親子関係のそれはできるようになったけど、、、
CSSがうまく当たらない。はてはて。

ちょっとはまるととたんに止まる。
でもって止まるととたんに眠くなる。

まぁ、サンプルをまねてみよ。
という状況。

またしばらくできなそうだなぁ。

2010年10月10日日曜日

本棚を作った

そう、狭い作業場なので本が溜まり始め。。。
雑誌は処分したんだけど、残りの本が邪魔すぎる。
「自炊」をしたいんだけど、自炊セット、高い。

高い。高いってのは高価だってことだ。


高いので、本棚を作ろうということにした。
鳥居となる部分は先日出来ていたので追加作業。
出来るまでの手順はいたって簡単。

作業場なので景観は気にしない。
2×4材買ってきて。
18cm幅の板買ってきて。


1:鳥居みたいの作って















2:天板くっつけて(この天板も本棚の一部)全部本が並ぶ。















3:幅にあわせてボックス作って














4:ドッキング。
















5:出来上がり。






















穴ぐらがますます穴ぐら化(笑)。

まぁよしとしよう。

裁断機、スキャナを買ったら多分窓側に棚を作っ
て設置するんだろうけどそうすると光が。。。

2010年10月6日水曜日

ExtJS-99 Ext.form.ComboBoxとhiddenName

今日、先日の勉強会でご一緒させて頂いた@taka_2さんが
ふとつぶやいていた件について
「あー、そういわれれば確かに。なんでComboBoxでhidenNameを指定すると取得できるんだろか?」
ととっても新鮮な気付きをいただきました。

で、ちょっと調べてみた。
ちょっと読んだだけだからばっちりあってるとはかぎらないけど、
概要はあってるはず。

まず、しょっぱなから本題からそれるけど、storeプロパティに配列指定だけで動いている
仕組みを追ってみた。

storeを配列で指定した場合、ComboBoxのstoreは内部でストアマネージャでlookupしてる。
指定されたidが配列だったら'field1'、'field2'…というフィールド名でArrayStoreを内部で生成してるようです。
だから配列で設定しても内部ではArrayStoreなんですね。

次。

FormPanel.getForm().getValuesで取得な話。
form.getValuesは内部でExtのコンポーネントのgetValue()をしているわけじゃなく、
HTMLElementのvalueを取得している。

もう少し構造を追ってみる。

getValuesはBasicFormで実装されてて,
Ext.lib.Ajax.serializeForm(this.el.dom);となっている。
key=valueの形でelement.name = element.value/element.textになる。
各値は&結合。

このelementはExt.ElementじゃなくてDomのエレメント。
serializeFormするときのelement.valueはDomのHTMLInputElement.valueということになる。
で、DomのHTMLInputElement.valueはtypeが「text,file,password」の時は入力されている値がそのまま
セットされるためシリアライズするときのvalueは表示されているものが設定される。
ということになるっぽい。

ComboBoxっていったってもとはTextFiledクラスを継承したTrggerFieldクラスを継承してるだけで、
選択肢がみえているのはComboListLayerで別Divでそう見させているから。
実はinputタグのtypeがtext。

だからgetValuesすると表示している値が取得できてしまうのである。っぽい。

まずはこれがComboBoxがgetValuesで取得するとvalueが取得できない理由でした。

ではhiddenNameを設定するとなぜ取得できるのか。。

hiddenNameを設定するとComboBox内部でinputタグをtypeをhiddenで作成する。
DomのHTMLInputElement.valueはtypeが「button,hidden,submit,reset,image,checkbox,radio」の時は
value属性値が設定されるからhiddenタグはvalue値になるわけ。
ComboboxのSetValueでhiddeenField.valueにvalue値を設定しているもんね。

だからシリアライズするときはvalue値が設定される。
と、こういう解釈で良いのかな??。。

でもひとつ腑に落ちない。

hiddenNameを設定するとvalueが取得できて、いままで取得できてた元の値が取得できなくなるのはなぜか?
insertSiblingで挿入しているので
type='text'な値とtype='hidden'な値が取得できても良いじゃないか。
とおもった。

前に書いた様に、
getValuesで取得できるのはExt.lib.Ajax.serializeFormでシリアライズしてるから。
でその対象の条件は!element.disabled && name。
が、hiddenNameが設定してあると元となる表示されている方のエレメントはname属性がついていない。

なぜか。

このname属性、ComboBoxのhiddenName指定すると
onRender内で
submitValue = falseにする。
で、ComboBoxの基底クラスであるFieldクラスのonRenderでは
submitValue === falseだと
this.el.dom.removeAttribute('name');
としていてname属性を削除している。

ということでname属性が無くなり、
getvaluesしても取得できないんだ。。。










↑hiddenName未設定時のDomツリー











↑hiddenName設定時(「hidden」という名前で設定)のDomツリー


====
おさらい。

ComboBoxその1:storeを配列で指定した場合の話
ComboBoxのstoreは内部でストアマネージャでlookupしてる。指定されたidが配列だったら'field1'、'field2'…というフィールド名で
ことでArrayStoreを内部で生成してた。
だから配列で設定しても内部ではArrayStoreなんですね。

ComboBoxその2:Comboboxの値の話
フォーム内の値はHTMLElementのvalueをシリアライズ化しているのでCombboxの実体はtype=textなので表示されている
値がvalueとなっちゃうよ。ということ。

ComboBoxその3-1:Comboboxの値の話
表示している値(displayFiled)じゃなくて(valueFild)が取得したい場合はhiddenNameを指定する。
これを指定するとinsertSiblingでhiddenタグをname属性をhiddenNameで挿入してくれる。
で、元からあるinputタグのname属性は削除される。

ComboBoxその3-2:フォームのgetValuesについて
内部でformが抱えるDomエレメント分まわしてシリアライズ化する。key(name属性)/value(value属性)で。
で、そのときの対象は!element.disabled && name。

=====
まとめ

ComboBoxを利用するときは配列指定であれば特にArrayStore=SimpleStoreは
指定することなく利用できるようです。

hiddenNameを指定することで値が取得できるようになるのは
内部でinputタグをtype=hiddenで作成しているからgetForm時のシリアライズ化時に
value値をちゃんと取得してくれるから。

hiddenNameを指定するといままで設定していたname属性は排除されて
シリアライズ化対象から外れます。

=====
おしまい。

自分なりにすっきり!!

2010年9月29日水曜日

ExtJS-98 勉強会にて発表してきた

GoogleDevelopersDay2010に参加してから、、
Ext JS & Sencha Touch勉強会9月@東京
で発表してきました。

GDDは去年から参加してるんですが、今年はドキドキはちょっと抑えめな感じだった気がします。
けど、API周りな話とか、JS関連の話を中心に聞けたのでよかったです。
さて、

コードリーディングなんですが、
一行づつおってたら日がくれてしまうので
事前に超斜め読みして資料を起こしたやつを発表してきました。

後半グダグダになってしまったのですが、
勉強になったといってくださる心優しい方もいて
人生初、勉強会講師は無事(?)終わったワケで。

今度は自分の作ったExtJsAPで事例発表がしてみたい。

まぁ、牛歩なのでいつできることやら。。
懇親会も楽しく、名古屋な話とかPHPな話とかPerlな話も
ふまえつつ、交流させていただきました!!

いつもいつも交流していただけるみなさんには感謝です。
今日も本当、いい刺激をたくさん頂きました。
明日からは心機一転!ExtJsを書くぞ!と言いたいけど、、、
資格の方がさきかな?

いや、積ん読になってる6冊な本が先か。。。



嬉しい?悩みなわけで。。


おやすみなさい。

2010年9月3日金曜日

sql久しぶりすぎて四苦八苦2

今日、SQLクックブックって本を買ってみた。
なんで技術本って高いんだろね。3800円なり。

はぁ、別名つけて共通テーブル。って知らなかった。。
with句についてはこちらを参照させていただきました。
ありがとうございました。

先日作ってたやつはIDによるソート依存だったので
リファクタしてソート列指定も可能にしようと思ってた。
だから、一時テーブルに格納してそれを再帰呼び出しする
ことを考えてたんだけど、そんなことはする必要もなく。

ひとまず写経ということで。


with tree(name,dataindex,parentId)
    as (
    select CAST(name as nvarchar(100)),dataindex,parentId
        from Hierarchy_Basic
        where parentId is null
        union all
    select CAST(tree.name + '-' + base.name as nvarchar(100)),base.dataindex,base.parentId
        from Hierarchy_Basic base,tree
        where base.parentId = tree.dataindex
)
select name,dataindex,parentId
    from tree
    order by name


こいつにテーブル名、列名とかを引数にもたせて
階層化ストアドにしよう。


土日の隙をみつけて。


このストアドでGridPanelの嘘っぱち階層化実装がすすんで、
それが終わればいよいよChartに突入。
Chartが終われば次はテンプレート。
テンプレートが終われば
3.3からのカレンダー。これさくっとつかえるのかなぁ。
それが終わればようやくアプリの外枠作り。

先長すぎるなぁ。
ってか俺は何を作ってるんだww忘れそうになる。

2010年9月1日水曜日

あんばん

朝のくそ忙しいときに下の娘が
アンパンマン書いてよーて。
6時前に出なきゃ危ういのに仕方なく
書いたアンパンマンとバイキンマン。とドキンちゃん。

これが我ながらうまく書けた!
ように思う。
まずまず子供達にも好評で何も見ずに
書けたのがうれしく。。

ドキンちゃんはさすがに水筒のちっさな絵をみて書いた。


三歳の娘がそれをみて書いた絵。
これがまた新しい。

バイキンはすでにそれとなく新しいキャラだよ。
「顔つぶれたー」って言ってたようで。


で、
アンパンマンは描かないって言う。


まぁ、こーしたレスがあると午前五時半にアンパンマン書いてやろうという気になる。

という普通な日記を書いた。

2010年8月25日水曜日

ExtJS-97 ヘッダを拡張したらスクローラがでなくなった

気がつくと5日から更新してない。
JSは触ってたけどExtJSは触ってなかった。
GoogleMapAPIを触ってみたみたくてそっちで遊んでました。
あとはTwitterAPIで遊んでみたく。
それで慣れたらyouRoomAPIとか。youRoom、メンバーの食いつきはうまいこといったんだけど
その後、うまく展開できなかったから次の策を考えなければ。
あとは。Hyper Estraierってのを@Mt_blue81さんに聞いたのでそちらも。
やりたいことだらけですね。本当に。仕事じゃないから楽しいのかな?仕事でも楽しいんだろうな。

今年も残りわずかなので資格も取らなきゃいけなそう。
ExtJsとも疎遠になってしまうのかな。。
明日は勉強会。
================
さて、ExtJs-56 階層構造のつぶしこみ5ガントチャートのラインとカンレダへっだでやってたことをほじくりかえしたら
スクローラが消えてでないことがわかった。
もう一年前のことをもう一度掘り起こして実装の続きをするってわりときびしいw


このヘッダはロード後のコールバック内で動的にヘッダセル内に構築してて
その際に三行分に拡張するものだからスクローラがそのまま下に下がって
Gridの枠外にでてしまっていた。
仕方ないのでGridViewのコードを引用してヘッダをレンダリングするときに
スクローラを無理やり取得してヘッダ拡張分を引いてやることにした。
もうマジックナンバー埋めちゃってるけどw。

    
//ヘッダの描画
me.hedderRender = function() {
    var me = this,
    Element = Ext.Element,
    grid = me.getView().grid;
    el = Ext.get(grid.getGridEl().dom.firstChild),
    mainWrap = new Element(el.child('div.x-grid3-viewport')),
    mainHd = new Element(mainWrap.child('div.x-grid3-header')),
    scroller = new Element(mainWrap.child('div.x-grid3-scroller'));

    //YMD用カラムへYMDのテーブル構成をAppend
    var headercellElement = me.getView().getHeaderCell((me.config.model.configGenerator.columnModelConfig.length - 1));
   headercellElement.innerHTML = me.ganttManager.generateGanttHeader();

    //水平スクローラが押し出されてしまうのでヘッダ、スクローラともに明示的に再計算する
    headerHeight = mainHd.getHeight();
    scrollHeight = grid.getSize(true).height - ((headerHeight*2)-4);
    scroller.setHeight(scrollHeight);
}

まぁ、でるようになったっていうことで。









ねよ。

2010年8月5日木曜日

sql久しぶりすぎて四苦八苦

もともとSQLではじょいんしてしゅとくしてとか
うにおんしてとか基本的なところをやった程度だった。
で、以前いろいろ調べて参考にさせてもらって作ったものはSSDの事故により紛失。

先日から作り直すことになった。
ほしい情報は
ID、ネストレベル、パス。
なんかうまくかけないし、三つに分かれちゃったけど、
親ID、IDな階層構造を持つテーブルから取得するストアドができたかな。

疲れているときのビールでふらふらしながらコードを書くのは面白い。

元はこちら。

--情報取得

CREATE PROC [dbo].[S_showHierarchy]
(
 @tableName nvarchar(256),
 @parentFieldName nvarchar(256),
 @childFieldName nvarchar(256),
 @rootId int,
 @idpath nvarchar(256) OUTPUT
)
AS
BEGIN
 SET NOCOUNT ON
 --テンポラリテーブル作成
 CREATE TABLE #hierarchy(id int NOT NULL,level int NOT NULL,idpath nvarchar(256))
 
 --呼び出し
 EXEC [dbo].[S_createHierarchyTable]
  @tableName = @tableName,
  @parentFieldName = @parentFieldName,
  @childFieldName = @childFieldName,
  @rootId = @rootId,
  @idpath = @idpath OUTPUT
 
 --最後に返却用にSELECTを実施
 SELECT * FROM #hierarchy
END


--テーブル作成

CREATE PROC [dbo].[S_createHierarchyTable]
(
 @tableName nvarchar(256),
 @parentFieldName nvarchar(256),
 @childFieldName nvarchar(256),
 @rootId int,
 @idpath nvarchar(256) OUTPUT
)
AS
BEGIN
 SET NOCOUNT ON
 DECLARE @minID int, @whereToken nvarchar(1024)

 --指定親ID取得
 SET @whereToken = @childFieldName+' = '+STR(@rootId)
 EXEC dbo.S_getHierarchyMinID @tableName,@childFieldName,@whereToken,@minID OUTPUT
 --ネストパスの生成
 SET @idpath = @idpath + '-' + CONVERT(nvarchar,@minID)
 --PRINT REPLICATE('-', @@NESTLEVEL * 1) + STR(@minID) + STR(@@NESTLEVEL) + @idpath
 PRINT CONVERT(nvarchar,@minID) + '|' + CONVERT(nvarchar,@@NESTLEVEL) + '|' + @idpath
 
 --テンポラリテーブルに挿入
 INSERT INTO #hierarchy VALUES(@minID,@@NESTLEVEL,@idpath)
  
 --■次の階層の準備処理 --
 --指定親ID配下の最小値取得
 SET @whereToken = @parentFieldName+' = '+CONVERT(nvarchar,@rootId)
 EXEC dbo.S_getHierarchyMinID @tableName,@childFieldName,@whereToken,@minID OUTPUT
 --SET @EmpID = (SELECT MIN(EmpID) FROM dbo.Emp WHERE MgrID = @Root)
 
 WHILE @minID IS NOT NULL
 BEGIN
  --再帰
  EXEC dbo.S_createHierarchyTable @tableName,@parentFieldName,@childFieldName,@minID, @idpath
  SET @whereToken = @parentFieldName+' = '+CONVERT(nvarchar,@rootId)+' AND '+@childFieldName+' > '+CONVERT(nvarchar,@minID)
  EXEC dbo.S_getHierarchyMinID @tableName,@childFieldName,@whereToken,@minID OUTPUT
 END
 
END


--最小ID取得

CREATE PROC [dbo].[S_getHierarchyMinID]
(
 @tableName nvarchar(256),
 @childFieldName nvarchar(256),
 @whereToken nvarchar(256),
 @minID int OUTPUT
)
AS
DECLARE @SqlQuery nvarchar(1024)
SET @SqlQuery = '' + 
 'SELECT @minID = MIN('+@childFieldName+')' +
 ' FROM '+@tableName+
 ' WHERE '+@whereToken + ''
--PRINT @SqlQuery
EXECUTE SP_EXECUTESQL @SqlQuery,N'@minID int OUTPUT', @minID OUTPUT

2010年8月3日火曜日

気分だけMac














気分だけMacにしてみた。

キーボードはさっくりと スタート→デバイスとプリンタ→デバイスの追加
でキーボードの電源いればOK。

トラックパッドはこちらのサイトにお世話になりました。
私の場合、64bit版でしたが、とっても丁寧にかかれていたので迷わずできました。

感謝です。

こちらもドライバ入れた後、スタート→デバイスとプリンタ→デバイスの追加から・・・
トラックパッドの電源入れてOKです。

お金、なくなりましたとさ。

2010年8月2日月曜日

気合いが入る


今週は一人暮らし。コード組むぞと気合いいれる。みんな実家だし、環境出しっぱなしでもオーケー。だからキーボードをデスクトップから引っこ抜いてきた。がんばるぞ。

2010年7月30日金曜日

またプロジェクト作り直す

ExtJsを勉強し始めて、そのうち遊びになって
これでもう四回目のプロジェクト作り直し。

よく飽きないもので。。
今年に入ってからの汎化作業は右に左に揺れるはするものの、
エイヤときめて先に進むという方法をとってきたから今回の
プロジェクト作り直しも良い方向に進むんだろうと信じて。

フォルダ構成はこんな感じで行こう。

■フォルダ構成
プロジェクトフォルダ
├App(アプリケーションフォルダ) 
│ ├Client
│ │ └各テーブルごとのフォルダとコンフィグファイル★
│ └Server
│   └各テーブルごとのフォルダとサーバサイドページ★
├App_Code
│ ├BasePage(ページ基底クラス)
│ ├DataTierAP(アプリケーション層DataTier)
│ ├DataTierAutoGenerate(自動生成層DataTier)★
│ ├DataUtil(データ加工ヘルパ)
│ ├JsonUtil(Json用加工ヘルパ)
│ └SQL(自動生成SQL←保管用)★
│ 
├extjs(ExtJs関連フォルダ:ExtJs/Sencha絡み)
│ ├ext(最新版のバージョンを排除して配置)■
│ ├sencha(最新版の-touchXXXXを排除して配置)■
│ ├extWrapper.css(ExtJsラッパ用CSS)
│ └extWrapper.js(ExtJsラッパ用)

├Fwx(ExtJS拡張層)
│ ├Omega(今後ここにomegaがくる予定??)●
│ └Crud(Crudに特化した拡張層)
│  ├Config.js(Configクラスの基底クラス)
│  ├ConfigFactory.js(ConfigFactoryクラスの基底クラス)
│  ├EditorGrid.js(EditorGridクラスの基底クラス【M】)
│  ├Form.js(Formクラスの基底クラス【V】)
│  ├FormControl.js(Formクラスの基底クラス【C】)
│  ├FormModel.js(Formクラスの基底クラス【M】)
│  ├GridContainer.js(Crudのコンテナクラス)
│  ├GridControl.js(Formクラスの基底クラス【C】)
│  └GridModel.js(Formクラスの基底クラス【M】)

├Owx(Apx)(アプリケーション用拡張層:基本的にFwx、ExtWrapperを拡張)
│ ├Controls
│ │└各種システム固有のコントロールクラス群
│ │
│ ├Utils
│ │└各種システム固有のロジッククラス群
│ │
│ └Crud
│  ├Config.js(Configクラスの基底クラス)
│  ├ConfigFactory.js(ConfigFactoryクラスの基底クラス)
│  ├EditorGrid.js(EditorGridクラスの基底クラス【M】)
│  ├Form.js(Formクラスの基底クラス【V】)
│  ├FormControl.js(Formクラスの基底クラス【C】)
│  ├FormModel.js(Formクラスの基底クラス【M】)
│  ├GridContainer.js(Crudのコンテナクラス)
│  ├GridControl.js(Formクラスの基底クラス【C】)
│  └GridModel.js(Formクラスの基底クラス【M】)

├Test(どーすっかなぁ)

└DataTierGeneratorhogehoge.exe(仮称)★

あー3.3だけDLして寝よ。
あっ、コード書いてないorz。。

2010年7月23日金曜日

ExtJs-96 サーバサイドコードを吐き出す

眠くなってさいごはかなりぐだぐだになったけどようやく
吐き出されるコードがそろった。
適当なテーブルをいくつか作って動作検証しなくちゃね。
これで先日のクライアント側のしくみと組で動いてくれればわずらわしい足回りから
ようやく一旦卒業できる。もう少し。もう少し。

2010年7月22日木曜日

埋め込みリソース

先日からサーバサイドの実装に入った。ものすごく久しぶりすぎて書き方忘れていたり。
internalとかでてこられてあれ?なんだっこの修飾子?とか戸惑いながら
ジェネレータのコードを拡張するだけなので楽チンなんだけど、、

フォーマットファイルを埋め込みリソースとして
アクセスしたかったののでやりかたわかんなかったから残しておこう。

Assembly.GetExecutingAssembly().GetManifestResourceStream(name))

これをStreamReaderにかましてReadToEndでよみだすっていう。
らくちんだねぇ。どっとネットって。
ちなみに
埋め込みリソースはファイルへの設定が少し必要で。
ビルドアクションに埋め込まれたリソースってやってやる。それだけ。

あとはリソース内部にちりばめられたキーワードに対してデータをリプレイスすれば
サーバサイドのコードができあがりってわけですね。

CreateFormはできたのであとはチョコっとじっそうしたらOK.

残すはクライアントサイドのConfigクラスのJson生成。

来週くらいには素地はできそうww。たのしみだ。

2010年7月18日日曜日

今日はようやく野菜をつくろうかと

お花とか木とか竹とか。
そんなんばっかだったので野菜をそだててみたくって。

ちょうど今日はぷらんたーで 【エダマメ】 。

■栽培ポイント

①プランター向きの品種選び
早生・ごく早稲70プランターに向いている20から30

種まき今からすれば9-10月に取れる。
【プランターに向いている早生を。】

②プランター選び
早生の高さは60cmほど
奥行深さ20センチ。幅60cm。
20~30粒取れる。

【これは去年ゴーヤ用が二つあるのでOKだ】
山ほど作れそうww。

※エダマメは密植できる!!!

■枝豆
20×65×20で12株うえられる。
============
①種まき
・種まき用培養度
・セルトレイ
水を張った容器のに浸す。
10分ほどね。

②種はセルトレイの中央に一つ
 ラベルを忘れず。

③「ぎゅー」っと押しこんであげて乾燥を防いでくこと・水をたっぷりね。
常にに観察できるところにおいて観察。
3、4日で発芽
ただし、枝豆を大好きなナメクジがいるのでもうひとつ大きな容器を用意して
外堀を作って塩水、砂糖水、で防いであげる。
なるほど。

■土作り。
枝豆の根っこには根粒があってそれは窒素を取り込んで養分にすることができるって。
だから窒素をふくんだものを与えすぎると葉っぱ育ちすぎてだめってさ。

野菜用培養度
窒素リン酸カリないつもの完熟堆肥。
培養度:完熟堆肥=3:1で両手でさっくりと混ぜてあげるのさ。

⑤うえつける
発芽から7日ほどで10センチほどできる。
本場が生えそろえてから羽越生ける

たくさん植えつけられる植え付け方。
密植しつつ風通しの良い

奥行4~5センチ奥行方向で
よこ10~15センチほどあけて。移植ごての深さ程度ね。

列を決める。
割り箸で。ガイドラインを決めてあげよ。
三つの植え穴を決める。
セルとレイのみっつでぐいっと穴の配置をつけてあげる。

①:虫、病気なし
②:父子と父子のあいだが短い
③:双葉がついていること

で植え付け:
割り箸でズぼっとセルとレイから抜いて植えつける。
支柱を60cmで誘引してあげる。

水をタップり上げてひあたりの良い場所で管理。

ExtJs-95 サーバサイド開始

なんだか金、土とぐっすりで、今朝は5時おきで少しだけコードを組めた。
まぁ、すぐにこどもたちに邪魔されたので中止したけど。。

====
サーバサイドの取りまとめと
ジェネレートフォーマットの整理。

こりゃ汎用性皆無だけど、自分用のシステム構築であればべんりだね。
====
今晩これでサーバサイドコードを。

2010年7月14日水曜日

ExtJs-94 キモとなる部分の残り3とチェックボックス

手抜き。。いや、妥協したところはいろいろあったけど
はるか昔にExtJs-68 汎化作業の予定で立てた予定は脱線してプロパティグリッドを使わなくなったものの、ガントチャート用の実装を残して一旦収束を迎えられた。

振り返ってみた。

この間5ヶ月。このだらだら感がすごい。よく続くもので。
最近職が変わってプログラムくまなくなったからこのひと時が一番の楽しみになってきたんだろうなぁ。
===============












===============




で、FrameworkExtention層とアプリケーション用拡張層として分けてみたものの
もうちょっとうまくできたような気もする。
ファイル数とクラス数の増加は予想よりかは小さかったのは良かった。
OOP経験が浅い自分にとっては四苦八苦だ。

ExtJsのコンポーネント系をwrapperとして面倒だけど必ずラップして使うようにしてたのも
後々変更するのが楽だった。

===============
チェックボックスのhiddenName対応。
たぶん、こんなことする必要もなく、かつ推奨されないんだろうけど
手短にチェックボックスの値を常にtrue/falseで送信したかったのでひとまず
Comboの実装を移植してhiddenName対応をしてみる。
これからしばらくはサーバサイドの汎化作業。
これは数日で終わるだろーかと。
共通実装部分の切り出しで終わりにしようと思う。

2010年7月9日金曜日

ExtJs-93 キモとなる部分の残り2

結局今週はトレーニングと自転車回収と子供の寝かし付け寝落ちと飲み会で一切触れず。
気がつくと一週間。

見直すと、
結局先に進むのを優先して
Observableなつくりにしなかった。
おのおのを呼び合って結びつけるっていうダサくて
わかりづらい実装になってしまった。
イベント登録してリスナー関数登録すればいいだけなんだろうけど、
やる気が起きず。。
ひと段落したらこれは作り直し。

今電車のなかで今夜から週末にかけての実装計画を練った。
今夜と明日の晩でコンテナのワンセットは終了させよ。
つまりクライアントについての骨格は都合悪くない限り土曜日に終わらせる。

日曜の晩でサーバサイドの汎化をおこなって変動部分を外出しに。
このエントリの改版でちゃんと予定どおりになってればいいなぁ。

2010年7月3日土曜日

ExtJs-92 キモとなる部分の残り

午前一時にビリーズブートキャンプなんてやるものではない。
==

先日、そろそろレイアウトだ!と喜んでいたら肝となる部分がどこまで進んでて
あとなにすりゃいいかわからなくなってしまった。
のでレイアウト系はまたお預け。まぁ本は山ほどあるわけだし、ちょっと後回し。

今日はフォームクラスの検索用モードの実装とグリッドと関連付けるためのコンテナクラスを
作った。作ったっていっても数十行だけど、、、ほんと牛歩。

まぁ、検索できるようになってきたわけで。
検索条件の結合オペレータとSQLの比較オペレータとDBの方による文字列検索句が残るけど、、
少なくとも絞込みができるってことはうれしい限りですね。



残すは詳細フォームでの削除とグリッドとの結合、
検索用フォームの拡充。

ああ、これでクライアント再度の汎用化はゴール目の前。
これでサーバ再度の汎用化。

でレイアウト。

何度も何度も自分に言い聞かせ。。

寝よ。
#タッチパッドで文字を書くものではない。イライラ最高値。

2010年6月23日水曜日

ExtJs-91 そろそろ平行してシステムっぽく(メモ)

CRUD系の実装がそろそろ終焉にむかっているので本を読みながら
もう一度ふりだしにもどって作っていこうと思う。

Omegaに頼る前に苦労しなきゃということで。。

■アプリケーションクラスについて
Property.
カレントのcategory
Categoryリスト

Method.
category change
Viewmode change

階層的に保持することで
アプリケーション、アプリケーション内種別、、
と言った管理にする。

■初期画面について
ロード画面は、windowクラスで、最小化、リサイズ、ドラッグをfalseに、modalで実装。
この時に表示する内容は、HTMLで静的にマークアップされたdivタグ。
500msのタイマはって、アプリケーションメインの初期化関数呼び出し。
この500msは、windowのアニメーション用のディレイタイマ。

■アプリケーションメインの初期関数
各パラメタの初期化、ui構築関数呼び出しと、初期画面用マークアップの削除getCmp.destroy()で実装。。
Qtipの初期化も。

■ui構築関数
Viewportの作成。
各リージョンの作成。
データの受け渡しはアプリケーションクラスを渡そうか?

ってことで。
またのんびり。

あれれ。sencha touchは??

2010年6月21日月曜日

ipadでリモートデスクトップ

いや、本題は
ipadでsencha touchのIFで開発中の画面を見たいなってなったんですが、
今の開発環境ってVisualStudioのダミーサーバ&ノート上のSQLServerで
ノートPCの閉じられた世界でやってたもので。。。ipadからは接続できず。。。

なのでもう半年とかそういうレベルで起動していなかったデスクトップを起動して
VirtualPCにWebサーバを構築した。
(以前とっておいたイメージファイルはどこにいってしまったんだろうか ・・・)

死ぬほどってわけじゃないけど、かなりセットアップ周りとかこのファイアウォールの
穴あけとかが嫌いなので概要をのこしておこう。
どうせまたいつか再構築したくなるんだろうし。
==========================
■サーバPCのセットアップ
VirtualPCへは
・.NETFramework3.5
・EnterpriseLibrary4.1
・WindowsInstaller4.5
・SQLServerExpress
と、、あとはVisualStudioWebなんたらをいれるだけ。
ジェネレータをいじくるのはノートPCだからWindowsAPを作る環境はいらないしね。
開発環境を入れるのはipadでリモートで開発とかできたらいいねぇということで。
これでサーバの環境はオーケー。
==========================
■DDNSへ登録
次にDDNSに自サーバを登録する。
むかーし登録してたはずだけど、当然、すでに有効期限は切れていて
再度登録。
いろいろあるね。こういうサービス、本当に感謝です。
==========================
■ルータの設定
あとは外部からの穴あけ。
HTTP
ICMP
リモート用のポートをあける。
※このサーバ機だけは静的なIP割り当てにしておいた。

pingうって確認。
(ICMPあけるの忘れてて、しばらく「あれーなんで通らんの?」とスタックしたorz)
==========================
■サーバの設定
再度VirtualPCに。
ファイアウォール設定です嫌いなんだよなぁ。なんか。

コントロールパネル→ネットワーク接続→「詳細設定」タブ→ファイアウォール設定ボタン

「詳細設定」タブ→ 
  ネットワーク接続の設定ボタン
   ↓
   「サービス」タブ→追加ボタン→・IPにサーバのローカルIP(静的にしたのはこのため)
                  ・内部、外部ともにDNS用ポート53を設定
                  ・で、DNSではUDPとTCP使うんでこの設定をTCPひとつ、
                  ・UDPひとつ。と計二つ追加する。
                  ・もちろんチェックを忘れずに。
                 →Webサーバ(HTTP)にチェック
                 →リモートデスクトップにチェック
  セキュリティログ(ログの設定を)
  ICMPの設定
   ↓
   エコーだけチェックした


この段階で
サンプルページをIISに設定してipadから自宅サーバに設置した
サンプルを参照することの確認が取れた。

あとはリモートデスクトップ。

==========================
■リモートの許可
 コントロールパネル→システム→「リモート」タブ
 「このコンピュータにユーザがリモートで接続することを許可する」にチェック

==========================

あとはipadのAppStoreでRemoteDeskTopLiteをDL

■Menu→EditConnectionで接続先設定を登録。
 IP address:DDNSに登録したIPを設定
 Port:リモート用にあけたポート番号
 ユーザ名:
 パスワード:
 っというところで
ほかはデフォルトでもOKかな。

=========================

うまくいきました。



   
  

2010年6月17日木曜日

ExtJs-90 フォームのidはmappingで解決。GridできてFormをつくって、レイアウトに入る前に。。

Ext-89での一件はmappingで対応した。Ext側は@kotsutusmiさんの
コメントからいただいてdataindexってことにしてフォームでの
登録もオーケー。


長かったなぁ。ここまで。
Gridは抽象化して実装とパラメータを切り分けられたし、共通部分の実装はおおむね完了。
Panelはこちらも抽象化してってGridの構造のままだけど、共通部分お実装はおおむね完了。

さて、
ここまでできたら次は
GridとPanelを結合しなけりゃ意味がない。


データに対して編集可能なGridを。
そんで、
パネル=検索条件=詳細な入力IFとして位置づけるため、
Gridとつなげてパネルから入力された条件で検索→Gridへ
GridでDblClick→パネルへ
っていう結合を実装する必要があるんだな。


■PanelのReadIFのキーはrowid(DB設計はすべてidentifierを持つようにして)で統一。

■検索条件とのつながり
Panelには検索ボタンをつけな
Panel→GridのLoadコールってことになる。

■詳細な入力IFとのつながり
ダブルクリック時にPanelのloadを行情報から取得したrowidを設定してPanelのLoad
をコールすればよいということになるわけで

Panel for search→Grid
Grid→Panel for Input

ってことになる。

でも、これ、関係を持つためにはお互いを知る必要が出てくる。
けど、相手を知るのはいやなので
それをくるむCRUDコンテナみたいなメッセージハンドリング用のクラスを
つくってそこに乗っけてみることにする。。
もう一年位前の勉強会で@kotsutsumiさんが教えてくれたやつの
縮小版みたいなイメージになるのかなぁ。。


あとはまたサーバサイドの実装になるわけで。。
特定の引数と比較演算子を対としたパラメータをクライアント側で用意するようにする。
デフォルトはANDでよいな。


もらった情報をWHERE句として生成するモジュールはあるからよし。
あとはほしいフィールド句を生成するモジュールを作ってあげて
それを内部で連結して問い合わせるストアドを作成すればおk。


もうチョイ。これを抜ければレイアウト!@kotsutusmiさん直伝、@ispernさん検証の
レイアウト。これやってみたい。

だからあとは、
やるってきめたらからやるリスト
・検索用のモードの設置
・Grid、Panelを結びつけるコンテナ作成
・(Panel for search)、Gridを乗せてみる
・Grid、 (Panel for input)を乗せてみる
・Panel for searchの条件実装
・Panel for searchからの条件ポスト実装
・Panel for searchからの条件解析→WHERE句実装(サーバ)

ExtJs-89 formの内コントロールのIDというかなんというか

grindのIDPropertyにあわせて
formのも実装すると'id'っていうnameのコントロールを設置することになるけーすがあり、
サーバサイドで受け取るとき、必然的に

reqid = Request.Form["id"];
こんな実装になる。
これじゃだめだ。


FormPanelのコントロールは未指定だと
ExtJs側でext-XXXX-XXXXという具合に
idを振る(これはコントロールID)



これが取得できちゃう。まぁ、そうだよな。。。


FormPanelはPanelとかとちがってPanelBodyがDIVではなくてFORMタグで実装されていてこのDOM(FORM)を利用する場合 は、from.getForm().submit()で操作します。
つまり、Formタグで送信するのでPanelの中に存在するものだけが送信されます。
って教えてもらいました。。


@kotsutsumiさん、またもや夜分に感謝です。


なのでデータ識別用のIDという名前とコントロール識別用の「ID」が重複する
ということになる。

回避策は。。。仕方なくForm時のサーバサイドの実装だけDBとは別にidってなまえじゃなくて
dataidとかにして別名にするかな。。。

めんどーだなぁ。仕方ないのかなぁ。

2010年6月16日水曜日

ExtJs-88 Senchaになりましたね

会社名がSenchaになったようですね。


http://www.extjs.co.jp/blog/2010/06/15/sencha-press-release/


jQtouchは知ってたけど、
Raphaelって知らなかった。

基本、JSの畑はExtJsな私にとって広すぎる。
興味だらけでおぼれますね。あー。

2010年6月10日木曜日

ExtJs-87 フォームはさくっと終了させたいなぁ

今日はジョギングしようと思ってたら子供の寝かしつけでぐっすりと。
ビール片手にコーディングです。

ExtJs86でフォームに搭載するコントロールの定型句は決めたので
あとは実装を。
Gridと同様、コントローラとモデルを「わざわざ」作ってあくまでFormPanelを実装から
切り離してみたかった。

で、モデルの基底クラスはこんな感じで固めた。
/// 
Ext.ns('Fwx.BasicCrud');
//abstract class
//config: class Config
//コンストラクタでinitializeメソッドコールすること。
Fwx.BasicCrud.FormModel = function () {
};
Fwx.BasicCrud.FormModel.prototype = {};
(function() {
    var me = this;
    me.form = {};
    me.configGenerator = {};
    //config:formpanel.getform()=Ext.form.Basicform
    me.initialize = function(config) {
        var me = this;
        me.configGenerator = config;
    };
    me.loadFailcallback = function(store, action, result, tran, r) {
        switch (action.failureType) {
            case Ext.form.Action.CLIENT_INVALID:
                Ext.Msg.alert('エラー', 'クライアントサイドでの異常。');
                break;
            case Ext.form.Action.CONNECT_FAILURE:
                Ext.Msg.alert('エラー', '通信エラーが発生しました。');
                break;
            case Ext.form.Action.SERVER_INVALID:
                Ext.Msg.alert('エラー', action.result.msg);
        }
    };
    me.loadSuccesscallback = function(r, options, success) {
        //Ext.Msg.alert('Failure', action.result.msg);
    };
    me.saveFailcallback = function(store, action, result, tran, r) {
        switch (action.failureType) {
            case Ext.form.Action.CLIENT_INVALID:
                Ext.Msg.alert('エラー', '入力されたフォーム情報に不備があります。');
                break;
            case Ext.form.Action.CONNECT_FAILURE:
                Ext.Msg.alert('エラー', '通信エラーが発生しました。');
                break;
            case Ext.form.Action.SERVER_INVALID:
                Ext.Msg.alert('エラー', action.result.msg);
        }
    };
    me.saveSuccesscallback = function(r, options, success) {
        Ext.Msg.alert('成功', '保存しました。');
    };
    me.deleteFailcallback = function(store, action, result, tran, r) {
        switch (action.failureType) {
            case Ext.form.Action.CLIENT_INVALID:
                Ext.Msg.alert('エラー', 'クライアントサイドでの異常');
                break;
            case Ext.form.Action.CONNECT_FAILURE:
                Ext.Msg.alert('エラー', '通信エラーが発生しました。');
                break;
            case Ext.form.Action.SERVER_INVALID:
                Ext.Msg.alert('エラー', action.result.msg);
        }
    };
    me.deleteSuccesscallback = function(r, options, success) {
        var me = this;
        Ext.Msg.alert('成功', '削除しました。');
        me.doReset();
    };
    me.doLoad = function(params) {
        var me = this;
        me.form.load({
            url: me.configGenerator.getFormAPIs().read,
            params: params,
            waitTitle: 'サーバ接続中',
            waitMsg: '読み込んでいます...',
            success: me.loadSuccesscallback,
            failure: me.loadFailcallback
        });
    };
    me.doSave = function(params) {
        var me = this;
        me.form.submit({
            clientValidation: true,
            url: me.configGenerator.getFormAPIs().write,
            params: params,
            waitTitle: 'サーバ接続中',
            waitMsg: '保存しています...',
            success: me.saveSuccesscallback,
            failure: me.saveFailcallback
        });
    };
    me.doDelete = function(params) {
        var me = this;
        me.form.submit({
            clientValidation: true,
            url: me.configGenerator.getFormAPIs().destroy,
            params: params,
            waitTitle: 'サーバ接続中',
            waitMsg: '削除しています...',
            success: me.deleteSuccesscallback,
            failure: me.deleteFailcallback
        });
    };
    me.doReset = function() {
        var me = this;
        me.form.reset();
    };
    me.setForm = function(form) {
        var me = this;
        me.form = form;
    };
}).apply(Fwx.BasicCrud.FormModel.prototype);


で、コントローラはこんなかんじだろうと。
Ext.ns('Fwx.BasicCrud');
//abstract
//config: { model: Model };
//コンストラクタでinitializeメソッドコールすること。
Fwx.BasicCrud.FormControl = function () {};
Fwx.BasicCrud.FormControl.prototype = {};
(function() {
    var me = this;
    //初期化処理
    me.initialize = function(config) {
        var me = this;
        me.model = config.model;
    };
    me.onSave = function(params) {
        var me = this;
        me.model.doSave(params);
    };
    //Loadイベントハンドラ
    me.onLoad = function(params) {
        var me = this;
        me.model.doLoad(params);
    };
    //Deleteイベントハンドラ
    me.onDelete = function(params) {
        var me = this;
        me.model.doDelete(params);
    };
    //Resetイベントハンドラ
    me.onReset = function() {
        var me = this;
        me.model.doReset();
    };
}).apply(Fwx.BasicCrud.FormControl.prototype);

動かせてないからなぁ。
これから継承した具象クラス作って。
サーバサイドをちょいちょい組んで。それから動作確認ってってあれ?24時。。

でももうチョイ。
これとGrid用とForm用のConfigパラメータクラスを作った。

Ext.ns('Owx.Crud');

Ext.ns('Fwx.BasicCrud');

//abstract
//config class for crud
Fwx.BasicCrud.Config = function () {};
Fwx.BasicCrud.Config.prototype = {};
(function() {
    var me = this;
    me.columnModelConfig = {};
    me.readerConfig = {};
    me.proxyAPIs = {};
    me.formAPIs = {};
    me.defaultRecord = {};
    me.extGridPanelConfig = {};
    me.extStoreConfig = {
        autoLoad: {},
        autoSave: {},
        proxy: {},
        reader: {},
        writer: {}
    };
    me.pageSize = 0;
    //TODO:
    me.getColumnModelConfig = function() {
        var me = this;
        return me.columnModelConfig;
    };
    me.getReaderConfig = function() {
        var me = this;
        return me.readerConfig;
    };
    me.getProxyAPIs = function() {
        var me = this;
        return me.proxyAPIs;
    };
    me.getFormAPIs = function() {
        var me = this;
        return me.formAPIs;
    }
    me.getDefaultRecord = function() {
        var me = this;
        return me.defaultRecord;
    };
    me.getExtStoreConfig = function() {
        var me = this;
        return me.extStoreConfig;
    };
    me.getExtGridPanelConfig = function() {
        var me = this;
        return me.extGridPanelConfig;
    };
    me.getPageSize = function() {
        var me = this;
        return me.pageSize;
    };
}).apply(Fwx.BasicCrud.Config.prototype);

Owx.Crud.BasicTableConfig = function() {
    var me = this;
    me.columnModelConfig = [
        { name: 'id', mapping: 'id', dataIndex: 'id', header: 'id', width: 100, sortable: true, hidden: false, hideable: true },
        { name: 'charCol', mapping: 'charCol', dataIndex: 'charCol', header: 'charCol', width: 100, sortable: true, hidden: false, hideable: true, editor: new ExtWrapper.TextField(), allowBlank: true },
        { name: 'datetimeCol', mapping: 'datetimeCol', dataIndex: 'datetimeCol', header: 'datetimeCol', width: 100, sortable: true, hidden: false, hideable: true, editor: new ExtWrapper.DateField() },
        { name: 'decimalCol', mapping: 'decimalCol', dataIndex: 'decimalCol', header: 'decimalCol', width: 100, sortable: true, hidden: false, hideable: true, editor: new ExtWrapper.NumberField() },
        { name: 'ntextCol', mapping: 'ntextCol', dataIndex: 'ntextCol', header: 'ntextCol', width: 100, sortable: true, hidden: false, hideable: true, editor: new ExtWrapper.NumberField() },
        { name: 'nvarcharCol', mapping: 'nvarcharCol', dataIndex: 'nvarcharCol', header: 'nvarcharCol', width: 100, sortable: true, hidden: false, hideable: true, editor: new ExtWrapper.TextField() },
        { name: 'bitCol', mapping: 'bitCol', dataIndex: 'bitCol', header: 'bitCol', width: 100, sortable: true, hidden: false, hideable: true, editor: new ExtWrapper.Checkbox()}];
    me.readerConfig = [
        { name: 'id', mapping: 'id', dataIndex: 'id', header: 'id', width: 100, sortable: true, hidden: false, hideable: true },
        { name: 'charCol', mapping: 'charCol', dataIndex: 'charCol', header: 'charCol', width: 100, sortable: true, hidden: false, hideable: true, editor: new ExtWrapper.TextField() },
        { name: 'datetimeCol', mapping: 'datetimeCol', dataIndex: 'datetimeCol', header: 'datetimeCol', width: 100, sortable: true, hidden: false, hideable: true, editor: new ExtWrapper.DateField() },
        { name: 'decimalCol', mapping: 'decimalCol', dataIndex: 'decimalCol', header: 'decimalCol', width: 100, sortable: true, hidden: false, hideable: true, editor: new ExtWrapper.NumberField() },
        { name: 'ntextCol', mapping: 'ntextCol', dataIndex: 'ntextCol', header: 'ntextCol', width: 100, sortable: true, hidden: false, hideable: true, editor: new ExtWrapper.NumberField() },
        { name: 'nvarcharCol', mapping: 'nvarcharCol', dataIndex: 'nvarcharCol', header: 'nvarcharCol', width: 100, sortable: true, hidden: false, hideable: true, editor: new ExtWrapper.TextField() },
        { name: 'bitCol', mapping: 'bitCol', dataIndex: 'bitCol', header: 'bitCol', width: 100, sortable: true, hidden: false, hideable: true, editor: new ExtWrapper.Checkbox()}];
    me.formConfig = [
    //{ name:'id' , fieldLabel:'', width:, xtype:'', value:'', hiddenName:'', allowBlank:false},
        { name: 'id', fieldLabel: 'id', width: 100, value: '', hiddenName: '', allowBlank: true, xtype: 'ExtWrapperLabel' },
        { name: 'charCol', fieldLabel: 'charCol', width: 100, value: '', hiddenName: '', allowBlank: true, xtype: 'ExtWrapperNumberField' },
        { name: 'datetimeCol', fieldLabel: 'datetimeCol', width: 100, value: '', hiddenName: '', allowBlank: true, xtype: 'ExtWrapperDateField' },
        { name: 'decimalCol', fieldLabel: 'decimalCol', width: 100, value: '', width: 100, value: '', hiddenName: '', allowBlank: true, xtype: 'ExtWrapperNumberField' },
        { name: 'ntextCol', fieldLabel: 'ntextCol', width: 100, value: '', hiddenName: '', allowBlank: true, xtype: 'ExtWrapperTextField' },
        { name: 'nvarcharCol', fieldLabel: 'nvarcharCol', width: 100, value: '', hiddenName: '', allowBlank: true, xtype: 'ExtWrapperTextArea' },
        { name: 'bitCol', fieldLabel: 'bitCol', width: 100, value: '', hiddenName: '', allowBlank: true, xtype: 'ExtWrapperCheckbox' }
    ];
    //Grid時のAPI
    me.proxyAPIs = {
        read: '/Owx/__test/data/ReadList.aspx',
        create: '/Owx/__test/data/CreateList.aspx',
        update: '/Owx/__test/data/UpdateList.aspx',
        destroy: '/Owx/__test/data/DeleteList.aspx'
    };
    //Form時のAPI
    me.formAPIs = {
        read: '/Owx/__test/data/ReadForm.aspx',
        write: '/Owx/__test/data/CreateForm.aspx',
        destroy: '/Owx/__test/data/DeleteForm.aspx'
    };
    me.defaultRecord = {
        id: '',
        charCol: 'chardef',
        datetimeCol: '2010/10/10',
        decimalCol: '10.25',
        ntextCol: '長文フリーのデフォルトー',
        nvarcharCol: 'バーキャラノデフォルトー',
        bitCol: 'true'
    };
    //me.extGridPanelConfig = {};
    //me.extStoreConfig = {};
    me.pageSize = 40;
};
Owx.Crud.BasicTableConfig.prototype = new Owx.Crud.TableConfig();


こいつをまるっとぶち込めば
気持ちとしてはreconfigみたいなイメージで、実装とパラメータを切り離せた実装にちかずけたはず。。

コントロールの画面表示まではOK。

すごくいけてないけど、あとで何とでもなる。
詳細はWindowに載せるかなぁ。



しかし、ストレートで出してもかっこよく出るところがExtJsの好きなとこ。
やはり楽しい。

これで動作確認してパラメタだけをテーブル構成にあわせて作っていけば
最低限のCRUDを実装したシステムのガワができるはず。わくわく。
これでゼロからのスクラッチはなくなる。
フレームワークの拡張層ができる予定。
で、こいつを一通りシステムっぽくできたらOmegaに載せ変えて。
あと何ヶ月かかるんだろうか。
でものんびり楽しみだ。
それっぽくなりそうだ。

少し進んだ。
うーん、早く画面周りのエフェクトとかコントロールとかいろいろを触り触りたい。。。

2010年6月7日月曜日

Ipadだねぇ

先々月、世の中がipadって騒がれるちょっとまえに勉強会で触らせてもらったipad。

巡り合わせで、丁度wifi版が余った先輩が売ってくれるって話になり、
貯めてたお金で購入。
もちろん嫁ちゃんの稟議も通して。(勉強会直後、ものすごくアピールしてたから、すんなりだったけど。。)

数日使ってて思うことは、pgせんのであればこれ一台でok.
ということ。
ますますExtjsで自分のツール作って、ipadでアクセスな生活をしてみたく。

あーあと、資格本とかかさばるやつらを電子化ってのも吉。
ひとまず、コツコツたまーに参照するextjs本を電子化だ。
ってことでキンコーズに電話して詳細聞いてみた。
一応Webで確認はしてたんだけど。
断裁サービス、一回おおよそ250枚/105円だったかな。
と、scansnapも買えないんで、文書の電子化サービスについて聞いたら、一枚15円弱で。それも100枚以降は13円弱で。

こりゃたすかります、
ネタモトハ
http://www.ideaxidea.com/archives/2010/06/ipad_kinkos.html
で、ツイッターのRTで見た情報でした。

ほんと、良い気づき、良い発見、良い影響を頂きます。
いろいろと。

感謝です。

寝よー。

2010年5月31日月曜日

ExtJs-86 グリッドは本当に一旦終了。でフォームの開始

ようやくサーバサイドとクライアントサイドの実装方法と
穴あけを完了して、共通実装部分の汎化も完了。

さてフォーム。を。
以前の実装をそのまま行くと
フィールドセットでまとめてくってことになるんだろうけど、
まずは
ひとつづつのコントロールはこうだった。

{ xtype : 'SystemCommonFormUserComboBox',
                              name:todo_dataMapping[18].name,
                              fieldLabel: todo_dataMapping[18].header,
                              hiddenName: todo_dataMapping[18].name,
                              width:80,
allowBlank: false }

これはもう固めてしまう。
では後はレイアウトとフォームパネルの仕様を決めてしまおう。

ExtJs-85 Gridのサーバレスポンスを決めてみる。3

先日の82,83の結果を反映して
結局、

エラー時は、
{ 'total':'0',
'success': false ,
'data':[],
'resultMessage' : 'エラーメッセージ',
'resultOption' : ''
}

とかにしたんだけど、
この情報は、exceptionイベントハンドラの第五引数のrawの中に入ってくるみたい。



そのときのズ。

これは前のエントリにあったonWrite内のreader.readResponse
内のResponseオブジェクトがそういう風に作られているからそうみたいです。

dataオブジェクトにはgetRootで取得したroot情報を。
で、rawには引数で渡されたオブジェクトを渡してるので。
そんな具合。

res.raw.resultMessageとかでサーバエラー取得できる。
よしよし。解決。

2010年5月27日木曜日

ExtJs-84 writeイベントとsaveイベントの問題とexceptionイベント

なぜかわからないけど、
saveイベントにwrite用のハンドラが設定してあって。。
いわずもがな、write用に実装してあるから
期待した結果は得られないわけです。

直しました。過去のエントリでsaveイベントが発火されてwriteが呼ばれる云々
ってのはこれが原因でした。ごめんなさい。

で、今の基礎実装でサポートするのは
write
load
exception
と絞って実装することにした。

exceptionイベントハンドラの実装をモデルに追加して
今回の騒動もひとまず終了。

exceptionの
type: remoteとresponseの違いは
httpProxyのonWrite
reader.readResponseを実行してるブロック内で
例外が発生した場合はresponse
そうじゃなくてsuccessがfalseで設定されてきた場合はremoteと。
そんな具合っぽいです。

>(ほかのProxyクラスもたぶん同様になってるとおもう。ScriptTagProxyはそうだった。
>ブロックといってもres = reader.readResponse(action, response);の一行ですが、
>内部ではレスポンスの有無、rootの有無!!←(これこれ)。
>レスポンスオブジェクト生成、successプロパティ有無のチェックなどをやってます。)
>#rootの有無チェック・・・これらすべてちゃんとexception投げてくれてるではないか!
>#過去のwriterでどはまりした件。。。だからちゃんと実装しないとどはまりする。

だから雰囲気としてはこんなかんじになるのかな。
exceptioncallback = function(proxy, type, action, options, res, arg) {
    var me = this;
    if (type === 'remote') {
        alert('serverサイドでの不備');
    } else if (type === 'response') {
        alert('response内容解析中の例外発生');
    }
    //画面の再描画
    if (me.view.hasListener('crudreflesh')) {
        me.view.fireEvent('crudreflesh');
    }
};