2009年8月31日 星期一
ext-doc
解開後在sample目錄下有ext-doc.bat執行檔,以及sample code(sample.js)和configure檔(ext.xml)。可以將js檔加入ext.xml的source裡面,至於document的描述可以參考sample code或者extjs的source file。設定好ext.xml後,直接執行ext-doc.bat就可以產生結果啦,預設的輸出目錄是在output的目錄下。接著把output複製到web server就可以看結果啦。
下載 ext-doc-1.0.131
相關網址:
http://code.google.com/p/ext-doc/downloads/list
http://extjs.com/forum/showthread.php?t=55214
http://groups.google.com/group/ext-doc?pli=1
http://ext-doc.org/docs/
2009年8月24日 星期一
新竹 - 日式料理 - 田秋屋 ☆☆
2009年8月18日 星期二
lex & yacc - lex introduction
lex被稱為Lexical Analyzer(中文要叫做語彙分析器?有點怪),用來產生辨識字詞的工具,透過regular expression定義pattern,當字詞符合某個pattern,就做特定的action。簡單的說就是切token。 lex檔分成三個部分: 1. definition section(declarations):用於初始化C和lex的,比如變數的宣告。 2. rule section(rules):定義pattern與相對應的action。 3. user subroutine section(programs):就是C code。
%{
/* comment: this is demo code
* file name: 01.l
*/
%}
%%
[\t ]+ /* ignore space */ ;
hello |
world { printf("I can recognize the word \"%s\"\n", yytext); }
%%
int main()
{
yylex();
return 0;
}
brook@debian:~/src/lex$ flex 01.l -o 01.yy.c brook@debian:~/src/lex$ flex 01.l brook@debian:~/src/lex$ gcc lex.yy.c -ll -Wall lex.yy.c:1085: warning: 'yyunput' defined but not used lex.yy.c:1128: warning: 'input' defined but not used brook@debian:~/src/lex$ ./a.out hello world hello world! brook I can recognize the word "hello" I can recognize the word "world" !brookregular expression
. | 代表任何一個字元,但不含換行(\n)。 |
* | 重覆前一個比對零次以上。 |
[] | 比對[]中任一個字元。 |
[^] | []的反向。 |
$ | 每行的結尾。 |
{n,m} | 前一個比對至少重複n次,最多m次。 |
+ | 重覆前一個比對一次以上。 |
? | 前一個比對可出現一次或零次。 |
| | or |
( ) | 定義subexpression。 |
標籤:
lex & yacc
2009年8月15日 星期六
為台灣致哀
看著電視媒體傳送著台灣50年來最大的災難,心中的難過總是一湧而上,淚水總是在自己的強忍下,停留在眼眶中打轉,望著那些長官們說的鬼話,心中的氣憤更是難平,平常這些辛勞的百姓為生活在大太陽底下工作,而這些高官卻只是在冷氣房裡決定政策,即便是錯誤的政策,而又或者是為了貪汙而制定了哪些莫名其妙的政策,百姓們也都只能苦笑買單。 但是今天,面對多少破碎的家庭,多少妻離子散的畫面,那怕是官員們演個戲也好,為這些苦難的百姓哀悼一下吧,不是他們不願撤離家園,而是誰都不知道有這麼大的災難。再者,如果今天人人都能在冷氣房裡辦公,誰還願意在大太陽底下,踩著滾燙的柏油路,辛勤的工作,再辛苦也是為了那口飯,還有那年幼的小孩,年邁的父母親。我也是一位農家子弟出身,小時候不管颳風下雨或者再大的太陽,總是要把田裡的工作完成,無奈靠天吃飯的農民,可能一個颱風就毀了這段時間的汗水,如果幸運逃過老天的考驗,到了收成的那刻,在田裡所受的大小傷都值得了,但是,這一切也都只能換取全家的溫飽,要多的是不可能的了。即便蔬菜水果再貴,永遠都是批發商在賺大錢,而農夫能感受到的只有曬在那刺痛的身體上的大太陽,還有寒風刺骨的寒流,這一切都夠可憐了,遠在市中心的長官們能感受到嗎?苦民所苦是騙人的。 看著電視,望著一幕一幕的救災畫面,面目可憎的名嘴們、政客們哪一個在第一時間到達災區?哪一個敢深入災區?騙人民的感情與信任,說再多都沒有用,因為災民們需要的是具體的行動,他們在挨餓的時候不會因為你們遠在電視機裡的一句話而飽了,但是他們的親人卻可能因為你晚來了一步而死了,每當時間經過一秒,他們內心的惶恐就多了一分,因為他們想像著親人被壓在土石堆裡,還有那一口氣等待救援,但是卻手無寸鐵,無法將親人在最後一刻救出。如果是你,你能承受嗎? 七天過了,即便人沒有被壓死,也該被活活的餓死渴死了,是政策殺人,卻沒有一個人為此負責,名嘴與政客也沒有在第一時間發揮他們的影響力前去救災,只有小兵們、小老百姓們還在為災民冒著生命危險持續搶救,這才是真正愛這片土地,這塊土地上的偉大英雄,每當畫面看到名嘴與政客的相互批判,讓我著實感到悲哀,為什麼還有人願意相信這群人,他們分不清誰才是真正愛他們的人嗎? 雨過就會天晴,但是人死不能復生,未來的路還相當的漫長,面對可能產生的孤兒,未來的路更顯的崎嶇,想到這心中又不免難過了起來。一夕之間,山河變色,希望的是,未來政府能多照顧這群災民,能讓她們面對自己未來的人生,更要想辦法照顧這些孤兒,因為他們真的是無辜的,他們的生命現在還很脆弱,很可能因為沒了父母,失了照顧,成了社會的邊緣人。
GCC (4.4.1)之C Preprocessor part I
C Preprocessor系列,其實就是CPP manual的讀書心得。
initial processing 在初始化的處理上,CPP主要有四個任務:
- 讀取檔案到記憶體中。
- 如果有啟動trigraphs,那麼會做trigraph轉換,如??/轉換成\,??-轉成~等等。
- 合併連續行成一行,就是每行後面有\當結尾的,會將該行和下一行合併成一行。
- 將註解的部分用一個空白取代。
brook@debian:~$ echo -e "#define foo() bar\nfoo()baz"|gcc -E - # 1 "<stdin>" # 1 "<built-in>" # 1 "<command-line>" # 1 "<stdin>" bar baz
The preprocessing language 所謂的preprocessing language,就是以#開頭的那些preprocessing directive,這些指令是固定的,無法讓使用者自訂新的。這些指令主要有四種用途:
- include of header file(比如#include)。
- Macro expansion(比如將#define展開)。
- Conditional Compilation(比如#if,決定哪些要被編譯,哪些不被編譯)。
- Line control(我不是很清楚,只知道#line num下一行就會由num當行數重新計算,也可以簡寫成# num)。
- Diagnostic(比如#error)。
Header files Header files主要分成兩類:
- System header files:提供OS部分的interface,<xx.h>。
- Your own header file:提供source files的interface,"xx.h"。
brook@desktop:~$ cat a.h #ifndef A_H #define A_H int hello(char *str); #endif brook@desktop:~$ cat a.c #include看到把a.h中的int hello(char *str)複製到source file中了嗎?隨後又重新計算行數# 3,而header files並沒有規定只能放啥東西,不過通常就是放置一些宣告。 include syntax #include有兩種變形:#include "a.h" int main(int argc, char * argv[]) { printf("hello world\n", __LINE__); return 0; } brook@desktop:~$ cpp -I./ a.c ... 略 ... # 2 "a.c" 2 # 1 "a.h" 1 int hello(char *str); # 3 "a.c" 2 int main(int argc, char * argv[]) { printf("hello world\n", 6); return 0; }
- #include <file>:for system header files,就是會尋找系統路徑。
- #include "file":for your own header files,會先尋找目前目錄,找不到就依循
的search path尋找。
search path 一般在UNIX底下,system header files的search path為 /usr/local/include libdir/gcc/target/version/include /usr/target/include /usr/include 透過GCC實際觀察一下吧
brook@desktop:~$ gcc -I./ -v a.c ... 略 ... ignoring nonexistent directory "/usr/local/include/i486-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../i486-linux-gnu/include" ignoring nonexistent directory "/usr/include/i486-linux-gnu" #include "..." search starts here: #include <...> search starts here: ./ /usr/local/include /usr/lib/gcc/i486-linux-gnu/4.3.2/include /usr/lib/gcc/i486-linux-gnu/4.3.2/include-fixed /usr/include End of search list. ... 略 ...您可以透過-I新增search path,新增的search path會優先被尋找,但是如果新增的search path已經在預設的(系統的)search path中,該search path會被忽略,避免影響預設的search path順序。有興趣可以再研究一下-I-和-iquote。
Once-Only headers 一個header files很可能被include兩次,進而造成重複define,引起compile error,標準做法應該是在header file中,使用conditional compilation防止被引入兩次,如:
#ifndef XX_H #define XX_H the entire file #endif /* !XX_H */XX_H我們稱為controlling macro或guard macro。macro name不應該使用'_'開頭的命名方式,而在system header files中應該使用'__'開頭,避免與user program造成衝突。 computed include 有時候我們會需要根據不同的configure引入不同的header files,比如:
#if SYSTEM_1 #include "system1.h" #elif SYSTEM_2 #include "system2.h" #elif ... 略 ... #endif像這樣需要經過計算然後才引入的行為就稱為computed include,你可以發現很就會被許多的#elif淹沒,你可以使用簡單的方式替代,比如:
#define SYSTEM1_H <stdio.h> #define SYSTEM2_H "system3.h" ... 略 ... #include SYSTEM1_H #include SYSTEM2_H甚至SYSTEM_H可以由Makefile傳遞進來。
System Headers是用來宣告OS和runtime libraries的interface,system header所產生的warning除了#warning會顯示出來,其他的都會被抑制住。一般而言,當GCC在編譯時就已經設定哪些目錄會被當成system header存放的目錄了,不過我們還是可以透過-isystem和#pragma GCC system_header兩種方式,將一般的header file當成system header file。
- -isystem後面接的目錄會被當成system header,用法上和-I一樣。
- #pragma GCC system_header這個指令告訴GCC把這個header file當成system header。
brook@ubuntu:~$ cat syshdr.c #include <stdio.h> #include "syshdr1.h" #include "syshdr2.h" #include "syshdr3.h" int main(int argc, char *argv[]) { syshdr1(); syshdr2(); syshdr3(); return 0; } brook@ubuntu:~$ cat syshdr/syshdr1.h #ifndef SYSHDR1_H #define SYSHDR1_H int syshdr1(void) { printf("%s\n", __FUNCTION__); } #endif brook@ubuntu:~$ cat syshdr2.h #ifndef SYSHDR2_H #define SYSHDR2_H #pragma GCC system_header int syshdr2(void) { printf("%s\n", __FUNCTION__); } #endif brook@ubuntu:~$ cat syshdr3.h #ifndef SYSHDR3_H #define SYSHDR3_H int syshdr3(void) { printf("%s\n", __FUNCTION__); } #endif brook@ubuntu:~$ gcc -Wall -isystem syshdr syshdr.c -o my_syshdr syshdr.c: In function ‘syshdr3’: syshdr3.h:3: warning: control reaches end of non-void function
標籤:
C,
GCC - C Preprocessor
2009年8月12日 星期三
extjs - Ext.PagingToolbar簡介
隨著records的增加,Browser會花更多的時間在畫grid,Ext.PagingToolbar主要用來處理這樣的問題,透過傳遞參數的方式(start:第幾筆開始,limit:共要幾筆),告知Server要傳送哪些資料。
注意,Ext.PagingToolbar只是告知Server要顯示的資料為何,而Ext.PagingToolbar預設會顯示所有的資料。
因為要讀取Server的資料,所以Store.proxy改用Ext.data.HttpProxy。而讀取的格式我們打算用json,所以,store.reader要用Ext.data.JsonReader。
我們的json file(phone_num.json)如下:
{ "success": true, "results": 12, // how many entry will be sent. "rows": [ // *Note: this must be an Array { "city": "台北市", "num": "02"}, { "city": "新竹市", "num": "03"}, { "city": "苗栗縣", "num": "037"}, { "city": "台中市", "num": "04"}, { "city": "南投縣", "num": "049"}, { "city": "嘉義市", "num": "05"}, { "city": "台南市", "num": "06"}, { "city": "高雄市", "num": "07"}, { "city": "屏東縣", "num": "08"}, { "city": "台東縣", "num": "089"}, { "city": "馬祖", "num": "0836"}, { "city": "烏坵", "num": "082"} ] }
Ext.onReady(function() { var cm = new Ext.grid.ColumnModel([ new Ext.grid.RowNumberer(), { header: 'City', dataIndex: 'city' }, { header: 'Num', dataIndex: 'num' } ]); var store = new Ext.data.Store({ proxy: new Ext.data.HttpProxy({url: 'phone_num.json'}), reader: new Ext.data.JsonReader({ totalProperty: 'results', root: 'rows', fields: [{name: 'city'}, {name: 'num'}] }) }); store.load(); var grid = new Ext.grid.GridPanel({ renderTo: Ext.getBody(), store: store, cm: cm, sm: new Ext.grid.RowSelectionModel(), viewConfig: { forceFit: true }, title: "區碼", loadMask: true, height: 200, width: 330, bbar: new Ext.PagingToolbar({ pageSize: 5, store: store, displayInfo: true }) }); });
由於,我們在Server-Side都只是把整個資料丟給client,所以,grid即便有Ext.PagingToolbar,但是還是會顯示所有由Server丟過來的資料。
Paging with Local Data
在local paging官方網站上有提到兩種方式:
- Ext.ux.data.PagingStore
- Paging Memory Proxy(examples/ux/PagingMemoryProxy.js)
根據Ext.ux.data.PagingStore作者的說法,PagingMemoryProxy缺點如下:
- You have to write extra code to remote load the data for the proxy.
- query, filter and collect only work on the current page. You have to write extra code to use the PagingMemoryProxy filter support.
- Local sorting works, but you need to set remoteSort:true. There is no remote sorting support.
- Added and removed records are only remembered for the current page.
- Changing the page is relatively slow (PagingMemoryProxy reprocesses all data).
PagingStore.js for ext-js v3
PagingStore.js for ext-js v2
以下是v2的code:
Ext.onReady(function() { var cm = new Ext.grid.ColumnModel([ new Ext.grid.RowNumberer(), {header: 'City', dataIndex: 'city'}, {header: 'Num', dataIndex: 'num'} ]); var store = new Ext.ux.data.PagingStore({ proxy: new Ext.data.HttpProxy({url: 'phone_num.json'}), reader: new Ext.data.JsonReader({ root: 'rows', totalRecords: 'results', fields: [{name: 'city'}, {name: 'num'}] }) }); store.load({params:{start:0, limit: 4}}); var grid = new Ext.grid.GridPanel({ renderTo: Ext.getBody(), store: store, cm: cm, sm: new Ext.grid.RowSelectionModel(), viewConfig: { forceFit: true }, title: "區碼", loadMask: true, height: 200, width: 330, bbar: new Ext.PagingToolbar({ pageSize: 4, store: store, displayInfo: true }) }); });
可以看到,Server一樣丟全部的資料,但是Grid已經可以以paging的方式顯示了。
2009年8月11日 星期二
誤用比不會用更可怕
最近因為研究extjs,所以花了些時間去研究一下Java Script, 才發現其實Java Script一直讓人誤解為非常簡單且基本的語言,原來是寫Java Script的大多應用在Web上,而且都只是執行非常簡單的功能,再加上大家都沒有花時間去研究這一語言,造成Java Script成為被誤解最深的語言。後來終於因為Ajax的流行,造成許多的Java Script Library的大量發展(如extjs或jquery),我們才有動力真正的想去了解Java Script。其實速食文化的興起,很多人都想(code)寫得少(function)做得多,很多都是抄來抄去的,根本就沒有去了解整個來龍去脈,進而導致誤用,很多也都沒被發現,甚至還為這個bug做workaround。 不過有時候這問題是沒有找到一本好的書,又是因為那該死的速食文化,造成輕鬆學會xxx或這24hr學會xxx之類的書大賣,而其他的書卻是又貴又不好賣,大師們也就不願意花時間去寫一本好書,更甚者,連課堂上也開始講求短時間內學會哪些東西,上了一個月的C,就可以在園區當RD,拚工時,拚廉價,那麼花大把時間在研究的人怎麼能堪的住哩,又有誰願意花時間去研究,畢竟大家都是夠用就好,而研究是想讓原本的東西更好。 總結上述,當您在使用任何東西時,應該要對其有一定程度的了解,至少先翻翻使用手冊吧,不要一在的抄襲前人的東西,而不知道為何要這樣做。好的書是值得大家支持的,不然好的書會越來越少。
extjs - Ext.grid.EditorGridPanel簡介
Ext.grid.EditorGridPanel繼承自Ext.grid.GridPanel,提供編輯Cell的能力。除了將Ext.grid.GridPanel改變成Ext.grid.EditorGridPanel外,還要設定Ext.grid.ColumnModel的欄位的editor。
Ext.onReady(function() { var data = [['Brook', '0921'], ['Rene', '0918']]; var cm = new Ext.grid.ColumnModel([ new Ext.grid.RowNumberer(), {header: 'Name', dataIndex: 'name', editor: new Ext.grid.GridEditor(new Ext.form.TextField())}, {header: 'Tel', dataIndex: 'tel', editor: new Ext.grid.GridEditor(new Ext.form.TextField())} ]); var store = new Ext.data.Store({ proxy: new Ext.data.MemoryProxy(data), reader: new Ext.data.ArrayReader({},[ {name: 'name'}, {name: 'tel'} ]) }); store.load(); var grid = new Ext.grid.EditorGridPanel({ renderTo: Ext.getBody(), store: store, cm: cm, sm: new Ext.grid.RowSelectionModel(), viewConfig: { forceFit: true }, title: "Brook's address book", loadMask: true, height: 200, width: 330 }); });
新增/刪除
我們在tbar新增兩個按鈕add/remove,add的流程如下:
- 停止grid的編輯。
- 接著插入一筆空白的資料到第一列的位置。
- 將第一行第一列變成編輯模式。
刪除的流程如下:
- 取得所有選取的列。
- 反覆的將所有選取列,移到store.removed(暫存起來,不然後面會遺失移除的列)。
Ext.onReady(function() { var record = Ext.data.Record.create([ {name: 'name', type: 'string'}, {name: 'tel', type: 'string'} ]); var data = [['Brook', '0921'], ['Rene', '0918']]; var cm = new Ext.grid.ColumnModel([ {header: 'Name', dataIndex: 'name', editor: new Ext.grid.GridEditor(new Ext.form.TextField())}, {header: 'Tel', dataIndex: 'tel', editor: new Ext.grid.GridEditor(new Ext.form.TextField())} ]); var store = new Ext.data.Store({ proxy: new Ext.data.MemoryProxy(data), reader: new Ext.data.ArrayReader({},[ {name: 'name'}, {name: 'tel'} ]), removed: [] /* 放置移除的列 */ }); store.load(); var grid = new Ext.grid.EditorGridPanel({ renderTo: Ext.getBody(), store: store, cm: cm, sm: new Ext.grid.RowSelectionModel(), viewConfig: { forceFit: true }, title: "Brook's address book", loadMask: true, height: 200, width: 330, tbar: new Ext.Toolbar(['-', /* '-' 是按鈕分隔符號 */ { text: 'add', handler: function() { var r = new record({ name: '', tel: '' }); grid.stopEditing(); store.insert(0, r); grid.startEditing(0,0); } }, { text: 'remove', handler: function() { var rows = grid.getSelectionModel().getSelections(); for (var i = 0; i < rows.length; i++) { store.removed.push(rows[i]); /* 暫存 */ store.remove(rows[i]); /* 移除 */ } } } ]) }); });
修改
Ext.onReady(function() { var data = [['Brook', '0921'], ['Rene', '0918']]; var cm = new Ext.grid.ColumnModel([ new Ext.grid.RowNumberer(), {header: 'Name', dataIndex: 'name', editor: new Ext.grid.GridEditor(new Ext.form.TextField())}, {header: 'Tel', dataIndex: 'tel', editor: new Ext.grid.GridEditor(new Ext.form.TextField())} ]); var store = new Ext.data.Store({ proxy: new Ext.data.MemoryProxy(data), reader: new Ext.data.ArrayReader({},[{name: 'name'}, {name: 'tel'}]) }); store.load(); var grid = new Ext.grid.EditorGridPanel({ renderTo: Ext.getBody(), store: store, cm: cm, sm: new Ext.grid.RowSelectionModel(), viewConfig: { forceFit: true }, title: "Brook's address book", loadMask: true, height: 200, width: 330, tbar: new Ext.Toolbar([{ text: 'show modified', handler: function () { var records = store.getModifiedRecords(); for (var i = 0; i < records.length; i++) { alert(Ext.encode(records[i].getChanges())); } } }]) }); });
Ext.grid.EditorGridPanel提供直接編輯Cell的能力,透過store.getModifiedRecords()可以取得修改過的rows,針對修改過的rows可以再透過getChanges()取得修改過的欄位,被修改的cell會出現紅色的標記。
限制輸入
cell通常都是由Ext.form.Field的Subclasses組成,而這些元件都具有regex的property可以限制使用者的輸入,比如regex:/[0-9]/就是限制只能輸入數字,一但輸入格式不對就會出現紅線啦。更多資訊可以參考一下Ext.form.Field。
Ext.onReady(function() { var data = [['Brook', '0921'], ['Rene', '0918']]; var cm = new Ext.grid.ColumnModel([ new Ext.grid.RowNumberer(), { header: 'Name', dataIndex: 'name', editor: new Ext.grid.GridEditor( new Ext.form.TextField({allowBlank:false})) }, { header: 'Tel', dataIndex: 'tel', editor: new Ext.grid.GridEditor( new Ext.form.TextField({regex:/[0-9]/})) } ]); var store = new Ext.data.Store({ proxy: new Ext.data.MemoryProxy(data), reader: new Ext.data.ArrayReader( {},[{name: 'name'}, {name: 'tel'}]) }); store.load(); var grid = new Ext.grid.EditorGridPanel({ renderTo: Ext.getBody(), store: store, cm: cm, sm: new Ext.grid.RowSelectionModel(), viewConfig: { forceFit: true }, title: "Brook's address book", loadMask: true, height: 200, width: 330 }); });
2009年8月10日 星期一
extjs - Ext.grid.GridPanel簡介
組成元件
要能正確顯示資料,必須包含資料倉儲(Store),資料欄位的定義(ColumnModel)。
首先我們先定義資料欄位:
var cm = new Ext.grid.ColumnModel({ {header: 'Name', dataIndex: 'name'}, {header: 'Tel', dataIndex: 'tel'} });
接著設定store,store包含資料取得方式(Proxy),以及分析方式(reader)。
var data = [ ['Brook', '0921'], ['Rene', '0918'] ]; var store = new Ext.data.Store({ proxy: new Ext.data.MemoryProxy(data), reader: new Ext.data.ArrayReader({},[ {name: 'name'}, {name: 'tel'} ]); }); store.load(); // 載入資料
最後再將他們和grid整合在一起:
var grid = new Ext.grid.GridPanel({ renderTo: Ext.getBody(), store: store, cm: cm, viewConfig: { forceFit: true // 自動調整欄寬[註1], }, title: "brook's guest book", width: 200, stripeRows: true, loadMask: true, height: 120 });
註1:forceFit在EditorGridPanel底下會出現錯誤(EditorGridPanel編輯後欄位錯亂的問題).
欄寬設定
調整欄寬除了forceFit以外,還可以設定autoExpandColumn: id,將特定欄寬expand以符合grid的大小,但如果設定了forceFit,autoExpandColumn將會被忽略。
var cm = new Ext.grid.ColumnModel([ { header:'Name', dataIndex:'name' }, { header:'Tel', dataIndex:'tel', id: 'tel' } ]); var grid = new Ext.grid.GridPanel({ renderTo: Ext.getBody(), store: store, cm: cm, title: "brook's guest book", loadMask: true, height: 120, autoExpandColumn: 'tel' });因為autoExpandColumn必須指定id,所以cm欄位也必須指定id。
排序
在cm中,將sortable設定為true後,該欄位就可以進行排序。
var cm = new Ext.grid.ColumnModel([ { header:'Name', dataIndex:'name', sortable: true }, { header:'Tel', dataIndex:'tel', id: 'tel' } ]);
也可以設定cm.defaultSortable = true,讓所有欄位都可以sort。
也可以預設某欄位排序的方向(由大到小,或由小到大),在store.sortInfo: {field: 'name', direction: "ASC"},就會將name以升冪排列,DESC則會降冪排列。
var store = new Ext.data.Store({ proxy: new Ext.data.MemoryProxy(data), reader: new Ext.data.ArrayReader({}, [ {name: 'name'}, {name: 'bd', type: 'date', dateFormat: 'Y-m-d'} ]), sortInfo: { field: 'name', direction: 'DESC' } });
日期顯示
在reader中將type設定為date,並且指定date的format,該欄位就會以date方式讀取,顯示的方式則要透過cm的renderer。
Ext.onReady(function() { var cm = new Ext.grid.ColumnModel([ { header: 'Name', dataIndex: 'name' }, { header: 'Birthday', dataIndex: 'bd', renderer: Ext.util.Format.dateRenderer('Y年m月d日') } ]); var data = [ ['Brook', '1999-12-03'], ['Rene', '1998-12-04'] ]; var store = new Ext.data.Store({ proxy: new Ext.data.MemoryProxy(data), reader: new Ext.data.ArrayReader({}, [ {name: 'name'}, {name: 'bd', type: 'date', dateFormat: 'Y-m-d'} ]) }); store.load(); var grid = new Ext.grid.GridPanel({ renderTo: Ext.getBody(), store: store, cm: cm, viewConfig: { forceFit: true }, title: "brook's guest book", loadMask: true, height: 120, }); });
由上例可知,只要透過cm.renderer就可以在顯示時加入一些變化。renderer函數包含value, metadata, css, record, rowIndex, colIndex, store等參數。
- value : Object 這個cell的資料
- metadata : Object 包含要套用在該CELL的CSS和HTML屬性的物件
- record : Ext.data.record 該列的資料物件
- rowIndex : Number Row index
- colIndex : Number Column index
- store : Ext.data.Store The Ext.data.Store object from which the Record was extracted.
Check box
CheckboxSelectionModel會在該欄位上顯示check box,讓使用者勾選。預設是多選,設定singleSelect為true可以改變為單選。
Ext.onReady(function() { var sm = new Ext.grid.CheckboxSelectionModel(); var cm = new Ext.grid.ColumnModel([ sm, { header: 'Name', dataIndex: 'name' }, { header: 'Tel', dataIndex: 'tel' } ]); var data = [ ['Brook', '0921'], ['Rene', '0918'] ]; var store = new Ext.data.Store({ proxy: new Ext.data.MemoryProxy(data), reader: new Ext.data.ArrayReader({}, [ {name: 'name'}, {name: 'tel'} ]) }); store.load(); var grid = new Ext.grid.GridPanel({ renderTo: Ext.getBody(), store: store, cm: cm, viewConfig: { forceFit: true }, title: "brook's guest book", loadMask: true, height: 120, width: 200 }); });
自動顯示行號 自動顯示行號是由Ext.grid.RowNumberer()提供的功能,和CheckboxSelectionModel一樣,放入cm就可以達到自動顯示行號之功能。
var cm = new Ext.grid.ColumnModel([ new Ext.grid.RowNumberer(), { header: 'Name', dataIndex: 'name' }, { header: 'Tel', dataIndex: 'tel' } ]);
Selection Model
在Ext.grid.GridPanel中,Selection Model預設是使用Ext.grid.RowSelectionModel,而且是可以多選,如果是單選就必須設定RowSelectionModel.singleSelect=true。
var grid = new Ext.grid.GridPanel({ renderTo: Ext.getBody(), store: store, cm: cm, sm: new Ext.grid.RowSelectionModel({singleSelect: true}), viewConfig: { forceFit: true }, title: "brook's guest book", loadMask: true, height: 120, width: 200 });
被選到的Row,可以透過grid.getSelectionModel().getSelections()取得。
var grid = new Ext.grid.GridPanel({ renderTo: Ext.getBody(), store: store, cm: cm, sm: new Ext.grid.RowSelectionModel(), viewConfig: { forceFit: true }, title: "brook's guest book", loadMask: true, height: 120, width: 200, buttons: [{ text:'show select', handler: function() { var selections = grid.getSelectionModel().getSelections(); for (var i = 0; i < selections.length; i++) { alert(selections[i].get('name') + ' is selection'); } } }] });
也可以選擇Cell Model,EditorGrid的預設Selection Model就是CellSelectionModel。
var grid = new Ext.grid.GridPanel({ renderTo: Ext.getBody(), store: store, cm: cm, sm: new Ext.grid.CellSelectionModel(), viewConfig: { forceFit: true }, title: "brook's guest book", loadMask: true, height: 120, width: 200 });
改變cell中的顯示(render)
圖文並茂的網頁是現在的趨勢,您可以透過Ext.grid.ColumnModel.renderer設定顯示cell時,要做哪些變化,比如,我想判斷電話號碼,顯示出電話號碼屬於哪家電信業者,程式碼如下:
Ext.onReady(function() { var record = Ext.data.Record.create([ {name: 'name', type: 'string'}, {name: 'tel', type: 'string'} ]); var data = [ ['Brook', '0921'], ['Rene', '0918'], ['John', '0980'] ]; function renderTel(value, metaData, record, rowIndex, colIndex, store) { if ('0921' == value) { return '<img src="images/cht.gif"/>' + value; } else if ('0918' == value) { return '<img src="images/twm.gif"/>' + value; } return value; } var cm = new Ext.grid.ColumnModel([ {header: 'Name', dataIndex: 'name'}, {header: 'Tel', dataIndex: 'tel', renderer: renderTel} ]); var store = new Ext.data.Store({ proxy: new Ext.data.MemoryProxy(data), reader: new Ext.data.ArrayReader({},[ {name: 'name'}, {name: 'tel'} ]), removed: [] }); store.load(); var grid = new Ext.grid.GridPanel({ renderTo: Ext.getBody(), store: store, cm: cm, sm: new Ext.grid.RowSelectionModel(), viewConfig: { forceFit: true }, title: "Brook's address book", loadMask: true, height: 200, width: 330 }); });
render function的參數說明如下:
- value: 將要顯示到cell的值。
- metaData:cell的屬性,包含css。
- record:該行資料。
- rowIndex:row index。
- colIndex:column index。
- store:使用中的store。
extjs - Ext.TabPanel 簡介
Ext.TabPanel中文名稱我也不知道稱為啥?不過感覺Tab應該是指標籤的意思,用於將panel分成幾個群組。
Ext.TabPanel算是個基本的container,所以可以將您想顯示的東西放入items中,就可以顯示了。
最基本的TabPanel如下:
Ext.onReady(function() { var tp = new Ext.TabPanel({ renderTo: Ext.getBody(), // activeTab: 1, width:300, height: 200, items: [ {title: 'p1', html: 'content 1'}, {title: 'p2', html: 'content 2'} ] }); });
activeTab指出在初始化的時候顯示的頁面,預設是不顯示任何頁面的。
剛剛提到, TabPanel算是container,所以也可以放置其他元件。
Ext.onReady(function() { var form = new Ext.form.FormPanel({ title: 'p2', defaultType: 'textfield', items: [{ fieldLabel: 'name' }], buttons: [{ text: 'send' }] }); var tp = new Ext.TabPanel({ renderTo: Ext.getBody(), activeTab: 1, width:300, height: 200, items: [ {title: 'p1', html: 'content 1'}, form // 在第二個頁面放置一個表單元件. ] }); });
也可以使用autoLoad載入URL(使用Ext.Updater.update Object),當成頁面的內容,如果有script要執行的話,必需將scripts設為true。
Ext.onReady(function() { var tp = new Ext.TabPanel({ renderTo: Ext.getBody(), activeTab: 1, width:300, height: 200, items: [ {title: 'p1', html: 'content 1'}, {title: 'p2', autoLoad: {url: 'tab.html', scripts: true}} ] }); });
2009年8月5日 星期三
extjs - Ext.tree.TreePanel 簡介
Ext.tree.TreePanel繼承自Ext.Panel,算是個container,必須給予節點(node)才能形成完整的樹。也就是說在render之前必須設定好root這個node。
空的樹(直接用renderTo())
Ext.onReady(function() { var root = new Ext.tree.TreeNode({ id: "root", text:'B_root' }); root.appendChild(new Ext.tree.TreeNode({ id: 'c1', text: 'B_C1' })); var tree = new Ext.tree.TreePanel({ renderTo: 't', //要有個div的id為't' width: 150, height: 50, root: root }); });
或者(用el+render())
Ext.onReady(function() { var root = new Ext.tree.TreeNode({ id: "root", text:'B_root' }); root.appendChild(new Ext.tree.TreeNode({ id: 'c1', text: 'B_C1' })); var tree = new Ext.tree.TreePanel({ el: 't', //要有個div的id為't' width: 150, height: 50, root: root }); tree.render(); });
利用setRootNode設定Root
Ext.onReady(function() { var root = new Ext.tree.TreeNode({ id: "root", text:'B_root' }); root.appendChild(new Ext.tree.TreeNode({ id: 'c1', text: 'B_C1' })); var tree = new Ext.tree.TreePanel({ el: 't', //要有個div的id為't' width: 150, autoHeight: true // 自動調整高度 }); tree.setRootNode(root); tree.render(); });
如果想動態變動root請參考https://extjs.net/forum/showthread.php?p=217227#post217227
可以利用Ext.tree.AsyncTreeNod定義樹狀結構,程式碼如下:
Ext.onReady(function() { var root = new Ext.tree.AsyncTreeNode({ id: 'aRoot', text: 'root', children: [ {id: 1, text: 'A leaf Node', leaf: true}, {id: 2, text: 'A folder Node', children: [ {id: 3, text: 'A child Node', leaf: true}] } ] }); var tree = new Ext.tree.TreePanel({ el: 't', //要有個div的id為't' width: 150, autoHeight: true, root: root }); tree.render(); });
記得如果是樹葉,記得要設定leaf:true,否則會認為不是leaf所以一直處於讀取狀態。
expandPath( String path, [String attr], [Function callback] ) : void
展開TreePanel中特定的路徑,比如我們要展開id2的id3:
Ext.onReady(function() { var root = new Ext.tree.AsyncTreeNode({ id: 'aRoot', text: 'root', children: [ {id: 1, text: 'A leaf Node', leaf: true}, {id: 2, text: 'A folder Node', children: [ {id: 3, text: 'A child Node', leaf: true}] } ] }); var tree = new Ext.tree.TreePanel({ el: 't', //要有個div的id為't' width: 150, autoHeight: true, root: root }); tree.render(); tree.expandPath('/aRoot/2/3'); });
selectPath( String path, [String attr], [Function callback] ) : void
選擇特定路徑上的node,用法和expandPath相同。
Ext.onReady(function() { var root = new Ext.tree.AsyncTreeNode({ id: 'aRoot', text: 'root', children: [ {id: 1, text: 'A leaf Node', leaf: true}, {id: 2, text: 'A folder Node', children: [ {id: 3, text: 'A child Node', leaf: true}] } ] }); var tree = new Ext.tree.TreePanel({ el: 't', //要有個div的id為't' width: 150, autoHeight: true, root: root }); tree.render(); tree.selectPath('/aRoot/2/3'); });
除了上述的建構方式,Ext.tree.TreeLoader也提供透過URL讀取JSON file來建構tree。JSON file(tree.json)如下:
[{ id: 1, text: 'A leaf Node', leaf: true },{ id: 2, text: 'A folder Node', children: [{ id: 3, text: 'A child Node', leaf: true }] }]
leaf屬性會在load的時候,判斷是否要在遞迴產生子節點。而原本的Ext.tree.TreeNode並不支援Ajax,所以也要改成Ext.tree.AsyncTreeNode.程式碼如下。
Ext.onReady(function() { var root = new Ext.tree.AsyncTreeNode({text: 'root'}); var tree = new Ext.tree.TreePanel({ el: 't', width: 150, autoHeight: true, root: root, loader: new Ext.tree.TreeLoader({dataUrl: 'tree.json'}) }); tree.render(); });
2009年8月3日 星期一
台中 - 日式料理 - 潤和壽司店 ☆☆☆
訂閱:
文章 (Atom)
熱門文章
-
轉自 http://www.wretch.cc/blog/redsonoma/14021073 基本概念: 1> tty(終端設備的統稱): tty一詞源於Teletypes,或者teletypewriters,原來指的是電傳打字機,是通過串行線用打印機鍵盤通過閱...
-
Work queue提供一個interface,讓使用者輕易的建立kernel thread並且將work綁在這個kernel thread上面,如下圖[1]所示。 由於work queue是建立一個kernel thread來執行,所以是在process context...
-
(V)將介紹file operations中的ioctl。ioctl的prototype為: int (*ioctl) (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); ...
-
這兩天電腦的word忽然都不能存檔,即便是另存新檔也不行,最後都只能放棄修改檔案,即便重新安裝過或者更新成2007也都不能存檔,最後就乖乖的google一下,原來是暫存的資料夾不存在,按照以下方式就可以解決了。 資料來源: word 2003不能存檔問題 編輯機碼的(reg...
-
System Call在HW和user space提供一層抽象層,主要目的有: 為user space提供硬體抽象層。比如,讀取檔案時,不用管檔案所在的媒體類型與檔案儲存類型。 System call能確保系統的安全與穩定。避免user space的無意或惡意的破壞。 ...
-
在kernel中建立thread可以使用kthread_create(),建立一個task,然後在調用wake_up_process(task)讓task真正的運行,如果要kill一個kthread可以使用kthread_stop()。 在kernel中,將kthread_cr...
-
Linux module練習手札I紀錄如何撰寫一個簡單的module,並且編輯它,以及load和unload一個module。 write a module #include <linux/init.h> #include <linux/module.h...
-
幾乎任何使用 TCP,UDP或UNIX-domain socket的動作都可以用nc來達成,常見的功能如。 simple TCP proxies shell-script based HTTP clients and servers network daemon testi...
-
很多人心中都有過一個問題 What is the difference between Platform driver and normal device driver? ,簡單的來說Platform devices就non-discoverable,也就是device本身沒辦法...
-
組成元件 要能正確顯示資料,必須包含資料倉儲(Store),資料欄位的定義(ColumnModel)。 首先我們先定義資料欄位: var cm = new Ext.grid.ColumnModel({ {header: 'Name', dataIndex...