<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java學(xué)習(xí)

    java,spring,structs,hibernate,jsf,ireport,jfreechart,jasperreport,tomcat,jboss -----本博客已經(jīng)搬家了,新的地址是 http://www.javaly.cn 如果有對(duì)文章有任何疑問(wèn)或者有任何不懂的地方,歡迎到www.javaly.cn (Java樂(lè)園)指出,我會(huì)盡力幫助解決。一起進(jìn)步

     

    EXT學(xué)習(xí)資料

    EXT學(xué)習(xí)資料
    EXT簡(jiǎn)介
    無(wú)論你是Ext庫(kù)的新手,抑或是想了解Ext的人,本篇文章的內(nèi)容都適合你。本文將簡(jiǎn)單地介紹Ext的幾個(gè)基本概念,和如何快速地做出一個(gè)動(dòng)態(tài)的頁(yè)面并運(yùn)行起來(lái),假設(shè)讀者已具備了一些JavaScript經(jīng)驗(yàn)和初級(jí)了解HTML Dom。
    目錄
    • 1 下載Ext
    • 2 開(kāi)始!
    • 3 Element:Ext的核心
    • 4 獲取多個(gè)DOM的節(jié)點(diǎn)
    • 5 響應(yīng)事件
    • 6 使用Widgets
    o 6.1 MessageBox
    o 6.2 Grid
    o 6.3 還有更多的..
    • 7 使用Ajax
    o 7.1 PHP
    o 7.2 ASP.Net
    o 7.3 Cold Fusion

    下載Ext
    如果你未曾下載過(guò),那應(yīng)從這里下載最新版本的Ext http://extjs.com/downloads 。
    針對(duì)你的下載需求,有幾個(gè)不同的彈性選項(xiàng)。通常地,最穩(wěn)定的版本,是較多人的選擇。下載解包后,那個(gè)example文件夾便是一個(gè)探索Ext的好地方!
    開(kāi)始!
    Download Example File
    • IntroToExt.zip

    我們將使用Ext,來(lái)完成一些JavaScript任務(wù)。
    Zip文件包括三個(gè)文件:ExtStart.html, ExtStart.js和ExtStart.css。解包這三個(gè)文件到Ext的安裝目錄中(例如,Ext是在“C:"code"Ext"v1.0”中,那 應(yīng)該在"v1.0"里面新建目錄“tutorial”。雙擊ExtStart.htm,接著你的瀏覽器打開(kāi)啟動(dòng)頁(yè)面,應(yīng)該會(huì)有一條消息告訴你配置已完畢。 如果是一個(gè)Javascript錯(cuò)誤,請(qǐng)按照頁(yè)面上的指引操作。
    在你常用的IDE中或文本編輯器中,打開(kāi)ExtStart.js看看:
    Ext.onReady可能是你接觸的第一個(gè)方法。這個(gè)方法是指當(dāng)前DOM加載完畢后,保證頁(yè)面內(nèi)的所有元素能被Script引用(reference)。你可刪除alert()那行,加入一些實(shí)際用途的代碼試試:
    Ext.onReady(function() {
    alert("Congratulations!  You have Ext configured correctly!");
    });
    Element:Ext的核心
    大多數(shù)的JavaScript操作都需要先獲取頁(yè)面上的某個(gè)元素(reference),好讓你來(lái)做些實(shí)質(zhì)性的事情。傳統(tǒng)的JavaScript方法,是通過(guò)ID獲取Dom節(jié)點(diǎn)的:
    var myDiv = document.getElementById('myDiv');
    這毫無(wú)問(wèn)題,不過(guò)這樣單單返回一個(gè)對(duì)象(DOM節(jié)點(diǎn)),用起來(lái)并不是太實(shí)用和方便。為了要用那節(jié)點(diǎn)干點(diǎn)事情,你還將要手工編寫(xiě)不少的代碼;另外,對(duì)于不同類(lèi)型瀏覽器之間的差異,要你處理起來(lái)可真頭大了。
    進(jìn)入Ext.element 對(duì)象。元素(element)的的確確是Ext的心臟地帶,--無(wú)論是訪(fǎng)問(wèn)元素(elements)還是完成一些其他動(dòng)作,都要涉及它。Element的 API是整個(gè)Ext庫(kù)的基礎(chǔ),如果你時(shí)間不多,只是想了解Ext中的一兩個(gè)類(lèi)的話(huà),Element一定是首選!
    由ID獲取一個(gè)Ext Element如下(首頁(yè)ExtStart.htm包含一個(gè)div,ID名字為“myDiv”,然后,在ExtStart.js中加入下列語(yǔ)句):
    Ext.onReady(function() {var myDiv = Ext.get('myDiv');});
    再回頭看看Element對(duì)象,發(fā)現(xiàn)什么有趣的東東呢?
    • Element包含了常見(jiàn)的DOM方法和屬性,提供一個(gè)快捷的、統(tǒng)一的、跨瀏覽器的接口(若使用Element.dom的話(huà),就可以直接訪(fǎng)問(wèn)底層DOM的節(jié)點(diǎn)。);
    • Element.get()方法內(nèi)置緩存處理(Cache),多次訪(fǎng)問(wèn)同一對(duì)象效率上有極大優(yōu)勢(shì);
    • 內(nèi)置常用的DOM節(jié)點(diǎn)的動(dòng)作,并且是跨瀏覽器的定位的位置、大小、動(dòng)畫(huà)、拖放等等(add/remove CSS classes, add/remove event handlers, positioning, sizing, animation, drag/drop)。
    這意味著你可用少量的代碼來(lái)做各種各樣的事情,這里僅僅是一個(gè)簡(jiǎn)單的例子(完整的列表在ElementAPI中)。
    繼續(xù)在ExtStart.js中,在剛才我們獲取好myDiv的位置中加入:
    Java代碼
    1. myDiv.highlight();      //黃色高亮顯示然后漸退  
    2. myDiv.addClass('red');  // 添加自定義CSS類(lèi) (在ExtStart.css定義)  
    3. myDiv.center();         //在視圖中將元素居中  
    4. myDiv.setOpacity(.25);  // 使元素半透明  

    獲取多個(gè)DOM的節(jié)點(diǎn)
    通常情況下,想獲取多個(gè)DOM的節(jié)點(diǎn),難以依靠ID的方式來(lái)獲取。有可能因?yàn)闆](méi)設(shè)置ID,或者你不知道ID,又或者直接用ID方式引用有太多元素 了。這種情況下,你就會(huì)不用ID來(lái)作為獲取元素的依據(jù),可能會(huì)用屬性(attribute)或CSS Classname代替。基于以上的原因,Ext引入了一個(gè)功能異常強(qiáng)大的Dom Selector庫(kù),叫做DomQuery。
    DomQuery可作為單獨(dú)的庫(kù)使用,但常用于Ext,你可以在上下文環(huán)境中(Context)獲取多個(gè)元素,然后通過(guò)Element接口調(diào) 用。令人欣喜的是,Element對(duì)象本身便有Element.selcect的方法來(lái)實(shí)現(xiàn)查詢(xún),即內(nèi)部調(diào)用DomQuery選取元素。這個(gè)簡(jiǎn)單的例子 中, ExtStart.htm包含若干段落(
    標(biāo)簽),沒(méi)有一個(gè)是有ID的,而你想輕松地通過(guò)一次操作馬上獲取每一段,全體執(zhí)行它們的動(dòng)作,可以這樣做:
    // 每段高亮顯示
    Ext.select('p').highlight();
    DomQuery的選取參數(shù)是一段較長(zhǎng)的數(shù)組,其中包括W3C CSS3 Dom選取器、基本XPatch、HTML屬性和更多,請(qǐng)參閱DomQuery API文檔以了解這功能強(qiáng)大的庫(kù)個(gè)中細(xì)節(jié)。
    響應(yīng)事件
    到這范例為止,我們所寫(xiě)的代碼都是放在onReady中,即當(dāng)頁(yè)面加載后總會(huì)立即執(zhí)行,功能較單一——這樣的話(huà),你便知道,如何響應(yīng)某個(gè)動(dòng)作或事 件來(lái)執(zhí)行你希望做的事情,做法是,先分配一個(gè)function,再定義一個(gè)event handler事件處理器來(lái)響應(yīng)。我們由這個(gè)簡(jiǎn)單的范例開(kāi)始,打開(kāi)ExtStart.js,編輯下列的代碼:
    Java代碼
    1. Ext.onReady(function() {  
    2.     Ext.get('myButton').on('click', function(){  
    3.         alert("You clicked the button");  
    4.     });  
    5. });  

    加載好頁(yè)面,代碼依然會(huì)執(zhí)行,不過(guò)區(qū)別是,包含alert()的function是已定義好的,但它不會(huì)立即地被執(zhí)行,是分配到按鈕的單擊事件 中。用淺顯的文字解釋?zhuān)褪牵韩@取ID為'myDottom'元素的引用,監(jiān)聽(tīng)任何發(fā)生這個(gè)元素上被單擊的情況,并分配一個(gè)function,以準(zhǔn)備任何 單擊元素的情況。
    正路來(lái)說(shuō),Element.select也能做同樣的事情,即作用在獲取一組元素上。下一例中,演示了頁(yè)面中的某一段落被單擊后,便有彈出窗口:
    Java代碼
    1. Ext.onReady(function() {  
    2.     Ext.select('p').on('click', function() {  
    3.         alert("You clicked a paragraph");  
    4.     });  
    5. });  

    這兩個(gè)例子中,事件處理的function均是簡(jiǎn)單幾句,沒(méi)有函數(shù)的名稱(chēng),這種類(lèi)型函數(shù)稱(chēng)為“匿名函數(shù)(anonymous function)”,即是沒(méi)有名的的函數(shù)。你也可以分配一個(gè)有名字的event handler,這對(duì)于代碼的重用或多個(gè)事件很有用。下一例等效于上一例:
    Java代碼
    1. Ext.onReady(function() {  
    2.     var paragraphClicked = function() {  
    3.         alert("You clicked a paragraph");  
    4.     }  
    5.     Ext.select('p').on('click', paragraphClicked);  
    6. });  

    到目前為止,我們已經(jīng)知道如何執(zhí)行某個(gè)動(dòng)作。但當(dāng)事件觸發(fā)時(shí),我們?nèi)绾蔚弥@個(gè)event handler執(zhí)行時(shí)是作用在哪一個(gè)特定的元素上呢?要明確這一點(diǎn)非常簡(jiǎn)單,Element.on方法傳入到even handler的function中(我們這里先討論第一個(gè)參數(shù),不過(guò)你應(yīng)該瀏覽API文檔以了解even handler更多的細(xì)節(jié))。在我們之前的例子中,function是忽略這些參數(shù)的,到這里可有少許的改變,——我們?cè)诠δ苌咸峁┝烁顚哟蔚目刂啤1? 須先說(shuō)明的是,這實(shí)際上是Ext的事件對(duì)象(event object),一個(gè)跨瀏覽器和擁有更多控制的事件的對(duì)象。例如,可以用下列的語(yǔ)句,得到這個(gè)事件響應(yīng)所在的DOM節(jié)點(diǎn):
    Java代碼
    1. Ext.onReady(function() {  
    2.     var paragraphClicked = function(e) {  
    3.         Ext.get(e.target).highlight();  
    4.     }  
    5.     Ext.select('p').on('click', paragraphClicked);  
    6. });  

    注意得到的e.target是DOM節(jié)點(diǎn),所以我們首先將其轉(zhuǎn)換成為EXT的Elemnet元素,然后執(zhí)行欲完成的事件,這個(gè)例子中,我們看見(jiàn)段落是高亮顯示的。
    使用Widgets
    (Widget原意為“小器件”,現(xiàn)指頁(yè)面中UI控件)
    除了我們已經(jīng)討論過(guò)的核心JavaScript庫(kù),當(dāng)前的Ext亦包括了一系列的最前端的JavaScirptUI組件庫(kù)。文本以一個(gè)常用的widget為例子,作簡(jiǎn)單的介紹。
    MessageBox
    比起略為沉悶的“HelloWolrd”消息窗口,我們做少許變化,前面我們寫(xiě)的代碼是,單擊某個(gè)段落便會(huì)高亮顯示,現(xiàn)在是單擊段落,在消息窗口中顯示段落內(nèi)容出來(lái)。
    在上面的paragraphClicked的function中,將這行代碼:
    Ext.get(e.target).highlight();
    替換為:
    Java代碼
    1. var paragraph = Ext.get(e.target);  
    2. paragraph.highlight();  
    3. Ext.MessageBox.show({  
    4.     title: 'Paragraph Clicked',  
    5.     msg: paragraph.dom.innerHTML,  
    6.     width:400,  
    7.     buttons: Ext.MessageBox.OK,  
    8.     animEl: paragraph  
    9. });  

    這里有些新的概念需要討論一下。在第一行中我們創(chuàng)建了一個(gè)局部變量(Local Variable)來(lái)保存某個(gè)元素的引用,即被單擊的那個(gè)DOM節(jié)點(diǎn)(本例中,DOM節(jié)點(diǎn)指的是段落paragrah,事因我們已經(jīng)定義該事件與< p>標(biāo)簽發(fā)生關(guān)聯(lián)的了)。為什么要這樣做呢?嗯...觀察上面的代碼,我們需要引用同一元素來(lái)高亮顯示,在MessageBox中也是引用同一元素 作為參數(shù)使用。
    一般來(lái)說(shuō),多次重復(fù)使用同一值(Value)或?qū)ο螅且粋€(gè)不好的方式,所以,作為一個(gè)具備良好OO思維的開(kāi)發(fā)者,應(yīng)該是將其分配到一個(gè)局部變量中,反復(fù)使用這變量!
    現(xiàn)在,為了我們接下來(lái)闡述新概念的演示,請(qǐng)觀察MessageBox的調(diào)用。乍一看,這像一連串的參數(shù)傳入到方法中,但仔細(xì)看,這是一個(gè)非常特別 的語(yǔ)法。實(shí)際上,傳入到MessageBox.show的只有一個(gè)參數(shù):一個(gè)Object literal,包含一組屬性和屬性值。在Javascript中,Object Literal是動(dòng)態(tài)的,你可在任何時(shí)候用{和}創(chuàng)建一個(gè)典型的對(duì)象(object)。其中的字符由一系列的name/value組成的屬性,屬性的格式 是[property name]:[property value]。在整個(gè)Ext中,你將會(huì)經(jīng)常遇到這種語(yǔ)法,因此你應(yīng)該馬上消化并吸收這個(gè)知識(shí)點(diǎn)!
    使用Object Literal的原因是什么呢?主要的原因是“可伸縮性(flexibility)”的考慮",隨時(shí)可新增、刪除屬性,亦可不管順序地插入。而方法不需要 改變。這也是多個(gè)參數(shù)的情況下,為最終開(kāi)發(fā)者帶來(lái)不少的方便(本例中的MessageBox.show())。例如,我們說(shuō)這兒的foo.action方 法,有四個(gè)參數(shù),而只有一個(gè)是你必須傳入的。本例中,你想像中的代碼可能會(huì)是這樣的foo.action(null, null, null, 'hello').,若果那方法用Object Literal來(lái)寫(xiě),卻是這樣, foo.action({ param4: 'hello' }),這更易用和易讀。
    Grid
    Grid是Ext中人們最想先睹為快的和最為流行Widgets之一。好,讓我們看看怎么輕松地創(chuàng)建一個(gè)Grid并運(yùn)行。用下列代碼替換ExtStart.js中全部語(yǔ)句:
    Java代碼
    1. Ext.onReady(function() {  
    2.     var myData = [  
    3.         ['Apple',29.89,0.24,0.81,'9/1 12:00am'],  
    4.         ['Ext',83.81,0.28,0.34,'9/12 12:00am'],  
    5.         ['Google',71.72,0.02,0.03,'10/1 12:00am'],  
    6.         ['Microsoft',52.55,0.01,0.02,'7/4 12:00am'],  
    7.         ['Yahoo!',29.01,0.42,1.47,'5/22 12:00am']  
    8.     ];  
    9.    
    10.     var ds = new Ext.data.Store({  
    11.         proxy: new Ext.data.MemoryProxy(myData),  
    12.         reader: new Ext.data.ArrayReader({id: 0}, [  
    13.             {name: 'company'},  
    14.             {name: 'price', type: 'float'},  
    15.             {name: 'change', type: 'float'},  
    16.             {name: 'pctChange', type: 'float'},  
    17.             {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}  
    18.     ])  
    19.     });  
    20.     ds.load();  
    21.    
    22.     var colModel = new Ext.grid.ColumnModel([  
    23.         {header: "Company", width: 120, sortable: true, dataIndex: 'company'},  
    24.         {header: "Price", width: 90, sortable: true, dataIndex: 'price'},  
    25.         {header: "Change", width: 90, sortable: true, dataIndex: 'change'},  
    26.         {header: "% Change", width: 90, sortable: true, dataIndex: 'pctChange'},  
    27.         {header: "Last Updated", width: 120, sortable: true,   
    28.         renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}  
    29.     ]);  
    30.    
    31.     var grid = new Ext.grid.Grid('grid-example', {ds: ds, cm: colModel});  
    32.         grid.render();  
    33.         grid.getSelectionModel().selectFirstRow();  
    34.     });  

    這看上去很復(fù)雜,但實(shí)際上加起來(lái),只有七行代碼。第一行創(chuàng)建數(shù)組并作為數(shù)據(jù)源。實(shí)際案例中,你很可能從數(shù)據(jù)庫(kù)、或者WebService那里得到 動(dòng)態(tài)的數(shù)據(jù)。接著,我們創(chuàng)建并加載data store, data store將會(huì)告訴Ext的底層庫(kù)接手處理和格式化這些數(shù)據(jù)。接著,我們定義一個(gè)column模型,用來(lái)輕松地調(diào)配Grid的每一列參數(shù)。最后我們生成這 個(gè)Grid,傳入data store和column模型兩個(gè)對(duì)象,進(jìn)行渲染并選好第一行。不是太困難吧?如果一切順利,完成之后你會(huì)看到像這樣的:

    當(dāng)然,你可能未掌握這段代碼的某些細(xì)節(jié)(像MemoryProxy究竟是什么?)但先不要緊,這個(gè)例子的目的是告訴你,用少量的代碼,創(chuàng)建一個(gè)富 界面的多功能的UI組件而已——這是完全可能的,只要讀者您有興趣學(xué)習(xí)。這兒有許多學(xué)習(xí)Grid的資源。Ext Grid教程、交叉Gird演示和Grid API文檔。
    還有更多的..
    這只是冰山一角。還有一打的UI Widgets可以供調(diào)用,如 layouts, tabs, menus, toolbars, dialogs, tree view等等。請(qǐng)參閱API文檔中范例演示。
    使用Ajax
    在弄好一些頁(yè)面后,你已經(jīng)懂得在頁(yè)面和腳本之間的交互原理(interact)。接下來(lái),你應(yīng)該掌握的是,怎樣與遠(yuǎn)程服務(wù)器(remote server)交換數(shù)據(jù),常見(jiàn)的是從數(shù)據(jù)庫(kù)加載數(shù)據(jù)(load)或是保存數(shù)據(jù)(save)到數(shù)據(jù)庫(kù)中。通過(guò)JavaScript異步無(wú)刷新交換數(shù)據(jù)的這種 方式,就是所謂的Ajax。Ext內(nèi)建卓越的Ajax支持,例如,一個(gè)普遍的用戶(hù)操作就是,異步發(fā)送一些東西到服務(wù)器,然后,UI元素根據(jù)回應(yīng) (Response)作出更新。這是一個(gè)包含text input的表單,一個(gè)div用于顯示消息(注意,你可以在ExtStart.html中加入下列代碼,但這必須要訪(fǎng)問(wèn)服務(wù)器):
    <div id="msg" style="visibility: hidden"></div>

    Name: <input type="text" id="name" /><br />

    <input type="button" id="oKButton" value="OK" />
    接著,我們加入這些處理交換數(shù)據(jù)的JavaScript代碼到文件ExtStart.js中(用下面的代碼覆蓋):
    Java代碼
    1. Ext.onReady(function(){  
    2.     Ext.get('oKButton').on('click', function(){  
    3.         var msg = Ext.get('msg');  
    4.             msg.load({  
    5.             url: [server url], //換成你的URL  
    6.             params: 'name=' + Ext.get('name').dom.value,  
    7.             text: 'Updating...'  
    8.    
    9.         });  
    10.         msg.show();  
    11.     });  
    12. });  

    這種模式看起來(lái)已經(jīng)比較熟悉了吧!先獲取按鈕元素,加入單擊事件的監(jiān)聽(tīng)。在事件處理器中(event handler),我們使用一個(gè)負(fù)責(zé)處理Ajax請(qǐng)求、接受響應(yīng)(Response)和更新另一個(gè)元素的Ext內(nèi)建類(lèi),稱(chēng)作UpdateManager。 UpdateManager可以直接使用,或者和我們現(xiàn)在的做法一樣,通過(guò)Element的load方法來(lái)引用(本例中該元素是id為“msg“的 div)。當(dāng)使用Element.load方法,請(qǐng)求(request)會(huì)在加工處理后發(fā)送,等待服務(wù)器的響應(yīng)(Response),來(lái)自動(dòng)替換元素的 innerHTML。簡(jiǎn)單傳入服務(wù)器url地址,加上字符串參數(shù),便可以處理這個(gè)請(qǐng)求(本例中,參數(shù)值來(lái)自“name”元素的value),而text值 是請(qǐng)求發(fā)送時(shí)提示的文本,完畢后顯示那個(gè)msg的div(因?yàn)殚_(kāi)始時(shí)默認(rèn)隱藏)。當(dāng)然,和大多數(shù)Ext組件一樣,UpdateManager有許多的參數(shù) 可選,不同的Ajax請(qǐng)求有不同的方案。而這里僅演示最簡(jiǎn)單的那種。
    PHP
    Java代碼
    1. <? if(isset($_GET['name'])) {  
    2.     echo 'From Server: '.$_GET['name'];  
    3. }  
    4. ?>  
    5. ASP.Net  
    6. protected void Page_Load(object sender, EventArgs e)  
    7. {  
    8.     if (Request["name"] != null)  
    9.        {  
    10.         Response.Write("From Server: " + Request["name"]);  
    11.         Response.End();  
    12.     }  
    13. }  
    14. Cold Fusion   
    15. <cfif StructKeyExists(url, "name")>  
    16.     <cfoutput>From Server: #url.name#</cfoutput>  
    17. </cfif>  

    最后一個(gè)關(guān)于Ajax隱晦的地方就是,服務(wù)器實(shí)際處理請(qǐng)求和返回(Resposne)是具體過(guò)程。這個(gè)過(guò)程會(huì)是一個(gè)服務(wù)端頁(yè)面,一個(gè) Servlet,一個(gè) Http調(diào)度過(guò)程,一個(gè)WebService,甚至是Perl或CGI腳本,即不指定一個(gè)服務(wù)器都可以處理的http請(qǐng)求。讓人無(wú)法預(yù)料的是,服務(wù)器返回 什么是服務(wù)器的事情,無(wú)法給一個(gè)標(biāo)準(zhǔn)的例子來(lái)覆蓋闡述所有的可能性。(這段代碼輸出剛才我們傳入'name'的那個(gè)值到客戶(hù)端,即發(fā)送什么,返回什么)。
    使用Ajax的真正挑戰(zhàn),是需要進(jìn)行適當(dāng)?shù)氖止ぞ幋a,并相應(yīng)格式化為服務(wù)端可用接受的數(shù)據(jù)結(jié)構(gòu)。有幾種格式供人們選擇(最常用為 JSON/XML)。正因 Ext是一種與服務(wù)器語(yǔ)言免依賴(lài)的機(jī)制,使得其它特定語(yǔ)言的庫(kù)亦可用于Ext處理Ajax服務(wù)。只要頁(yè)面接受到結(jié)果是EXT能處理的數(shù)據(jù)格式,Ext絕不 會(huì)干涉服務(wù)器其他的事情!要全面討論這個(gè)問(wèn)題,已超出本文的范圍。推薦正在Ajax環(huán)境下開(kāi)發(fā)的您,繼續(xù)深入閱讀Ext Ajax教程。

    下一步是?
    現(xiàn)在你已經(jīng)一睹Ext其芳容,知道她大概能做些什么了。下面的資源有助您進(jìn)一步深入了解:
    EXT源碼概述
    揭示源代碼
    Javascript是一門(mén)解釋型的語(yǔ)言,意味著在運(yùn)行之前代碼是沒(méi)有經(jīng)過(guò)編譯的。按照這種理論,在你網(wǎng)站上所發(fā)播的Ext代碼是我們看的懂的 (human-readible)。我這里說(shuō)“理論上”,是因?yàn)閷?shí)際情況中,很多源代碼是經(jīng)過(guò)某些自動(dòng)化步驟的處理,生成很小幾行的文件最終發(fā)布的,通過(guò) 剔除空白符號(hào)和注釋?zhuān)蚧煜鹊姆椒ǎ詼p小文件大小。
    仔細(xì)看看EXT標(biāo)準(zhǔn)源碼ext-core.js,你會(huì)發(fā)現(xiàn)這是一段超長(zhǎng)的源碼。這是剛才提及的自動(dòng)化步驟生成的結(jié)果--對(duì)瀏覽器來(lái)說(shuō)不錯(cuò)!可是對(duì)于我們是難以閱讀的。
    ext-core.js
    Java代碼
    1. /* 
    2.  * Ext JS Library 1.1 
    3.  * Copyright(c) 2006-2007, Ext JS, LLC. 
    4.  * licensing@extjs.com 
    5.  *  
    6.  * http://www.extjs.com/license 
    7.  */  
    8.    
    9. Ext.DomHelper=function(){var _1=null;var _2=/^(?:br|frame...  
    10.    
    11. Ext.Template=function(_1){if(_1 instanceof Array){_1...  

    ...
    接著看下去的是ext-core-debug.js (注意在文件名后面加上-debug的JS文件), 我會(huì)發(fā)現(xiàn)是全部已格式化好的源代碼。這個(gè)文件是配合調(diào)時(shí)器所使用的,像Firebug的工具能夠可以讓你一步一步地、一行一行地調(diào)試代碼。你也會(huì)發(fā)現(xiàn)文件 的體積將近大了一倍之多,這便是沒(méi)有壓縮或混淆的緣故。
    ext-core-debug.js
    Java代碼
    1. /* 
    2.  * Ext JS Library 1.1 
    3.  * Copyright(c) 2006-2007, Ext JS, LLC. 
    4.  * licensing@extjs.com 
    5.  *  
    6.  * http://www.extjs.com/license 
    7.  */  
    8.    
    9. Ext.DomHelper = function(){  
    10.     var tempTableEl = null;  
    11.     var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;  
    12.     var tableRe = /^table|tbody|tr|td$/i;  

    ...
    該調(diào)試版本可以在調(diào)試階段方便地檢查EXT庫(kù)運(yùn)行到哪一步,但是你還是會(huì)錯(cuò)過(guò)一個(gè)有價(jià)值的...代碼注釋?zhuān)∫暾乜吹酱a,就要閱讀真正的原始代碼!
    發(fā)布Ext源碼時(shí)的一些細(xì)節(jié)
    你在download得到的壓縮文檔,包含在這些文件夾之中的,有一source的子目錄。在這個(gè)文件夾里面,正如所料,是全部的EXT的源文件,遵從Lesser GNU (LGPL) 開(kāi)源的協(xié)議。對(duì)于EXT開(kāi)發(fā)者來(lái)說(shuō)應(yīng)該非常適合。
    用你日常使用文本編輯器打開(kāi)源代碼的任意一個(gè)文件(推薦有高亮顯示的編輯器,或是在這里full-featured IDE看看),便可以開(kāi)始我們的探險(xiǎn)!
    我應(yīng)該從哪里開(kāi)始?
    Ext代碼庫(kù)里面包含了許多各種各樣的文件,甚至令人覺(jué)得有點(diǎn)望而生畏。好在,Ext是一個(gè)通過(guò)充分考慮后而設(shè)計(jì)的JavaScript庫(kù),-- 在底層的代碼為各項(xiàng)應(yīng)用提供穩(wěn)健的基礎(chǔ)如跨瀏覽器的各種DOM操控,使得在上層的類(lèi)classes運(yùn)行于一個(gè)較高級(jí)的抽象層面(class 一術(shù)語(yǔ)與我們已習(xí)慣的Java和C++語(yǔ)言稍微有所不同,但一些概念如繼承則可是如此類(lèi)推去理解的--有關(guān)面向?qū)ο蟮腏avaScript的更多資料,請(qǐng) 參見(jiàn)Introduction to object-oriented (OO) JavaScript)。
    這意味著,當(dāng)瀏覽源碼的時(shí)候,采取“自頂向下(bottom-up)”還是“自下向頂(top-down)”的方式,都是無(wú)關(guān)緊要的。你所熟 悉API里面的代碼已經(jīng)是屬于最高的抽象層面的范疇,你可以根據(jù)你的興趣,順著這些你熟悉的API逐步深入。但是你若贊同我的看法,并打算深入了解其個(gè)中 原理,最理想的地方是從底層代碼開(kāi)始。
    適配器Adapters
    瀏覽器讀取第一個(gè)源文件,當(dāng)中的一個(gè)任務(wù)就是創(chuàng)建Ext對(duì)象本身。 Ext.js
    Ext = {};
    Ext成型于YahooUI的Javascript庫(kù)的擴(kuò)展。在當(dāng)時(shí),Ext須依賴(lài)YUI的底層代碼來(lái)處理跨瀏覽器的問(wèn)題。現(xiàn)在ExtJS已經(jīng)是 獨(dú)立、免依賴(lài)的庫(kù)了(standalone ),你可將YUI替換為另外你所選擇javascript庫(kù),如prototype、jQuery、或者是這些之中的最佳選擇,-Ext自帶的底層庫(kù)。負(fù) 責(zé)將這些庫(kù)(包括Ext自帶的底層庫(kù))映射為Ext底層庫(kù)的這部分代碼,我們稱(chēng)之為適配器(Adapters)。這部分源碼位于 source/adapter的子目錄。當(dāng)項(xiàng)目引入Ext的時(shí)候便需要選擇好你準(zhǔn)備使用的適配器。
    核心Core
    source/core中的文件是構(gòu)建于適配器API之上的“相對(duì)”最底層的源碼。有些的源碼甚至“底層”到直接為獨(dú)立庫(kù)的代碼直接使用。這意味 著應(yīng)先了解和學(xué)習(xí)這整個(gè)庫(kù),再學(xué)習(xí)剩余的部分也不遲。要了解Ext的各種“Magic”和核心層面,就應(yīng)該把重點(diǎn)放在source/core 目錄下的各個(gè)源代碼。

    Javascript中的作用域(scope)
    事前準(zhǔn)備
    學(xué)習(xí)本教程的最佳方法是隨手準(zhǔn)備好Firefox中的工具Firebug。這樣使得您可以即刻測(cè)試教程的例子。
    如果機(jī)子上還沒(méi)有FireFox和FireBug,就應(yīng)該盡快安裝一套來(lái)用。
    定義
    作用域scope
    1.(名詞)某樣事物執(zhí)行、操作、擁有控制權(quán)的那么一個(gè)區(qū)域 [1]
    2. (名詞) 編寫(xiě)程序時(shí),程序之中變量的可見(jiàn)度;例如,一個(gè)函數(shù)能否使用另外一個(gè)函數(shù)所創(chuàng)建的變量。[2]
    可是這能夠說(shuō)明什么問(wèn)題呢? 每當(dāng)有人在說(shuō)“這是作用域的問(wèn)題”或“作用域搞錯(cuò)了”的時(shí)候,那就是說(shuō)某個(gè)函數(shù)運(yùn)行起來(lái)的時(shí)候,找不到正確變量的位置。這樣我們便知道應(yīng)該從哪一方面入手,查找出問(wèn)題所在。
    正式開(kāi)始
    實(shí)際上每一個(gè)你定義的函數(shù)都是某個(gè)對(duì)象的方法。甚至是這樣的寫(xiě)法:
    function fn() {
        alert(11);
    }
    老兄你不是故弄玄虛吧~。做一個(gè)這樣的演示可真得是簡(jiǎn)單得要命。沒(méi)錯(cuò)!本例不需要任何Javascript文件,服務(wù)器或html。你只要打開(kāi) firefox,彈出firebug,點(diǎn)擊console tab。在Firefox狀態(tài)欄上面看到有>>>提示的地方就可以輸入了。
    輸入:
    function fn() { alert(11); };
    然后回車(chē)。一切安然...你剛才做的實(shí)際上是定義了一個(gè)函數(shù)fn。接著試試:
    fn();
    然后回車(chē)。得到11的警告窗口?還不錯(cuò)吧?接著試試:
    window.fn();
    this.fn();
    得到一樣的結(jié)果吧?這是因?yàn)楹瘮?shù)fn是window對(duì)象的一個(gè)方法,在第二行的"this"的作用域?qū)嶋H指向了windows對(duì)象。不過(guò)多數(shù)情況中你不需要像這樣window.myFunction(...)地調(diào)用函數(shù),這樣太麻煩了,程序員工作起來(lái)會(huì)很不方便。
    window對(duì)象
    window 對(duì)象總是存在的,你可理解其為一個(gè)瀏覽器窗口對(duì)象。它包含了其它所有的對(duì)象如document 和所有的全局變量。
    你可以打開(kāi)Firebug,切換到 Script 頁(yè)面并在Firebug右側(cè)的New watch expression... 里面輸入 window。觀察window對(duì)象究竟有什么在里面。
    接著,嘗試找出我們之前定義過(guò)的fn函數(shù)。
    另外,每個(gè)frame或iframe擁有其自身的window對(duì)象,其自身的全局空間。
    理解作用域
    接下的內(nèi)容開(kāi)始有點(diǎn)復(fù)雜了。切換到Firebug Console標(biāo)簽頁(yè)然后輸入:
    var o1 = {testvar:22, fun:function() { alert('o1: ' + this.testvar); }};
    var o2 = {testvar:33, fun:function() { alert('o2: ' + this.testvar); }};
    結(jié)果是什么?你聲明了o1 和 o2兩個(gè)對(duì)象,分別都有一些屬性和方法,但值不同。

    接著試試:
    fun();
    window.fun();
    this.fun();
    出錯(cuò)了,是吧?因?yàn)閣indow對(duì)象(等價(jià)于this)并沒(méi)有fun的方法。試一試下面的:
    o1.fun();
    o2.fun();
    22和33出來(lái)了?非常好!
    接下來(lái)這部分的內(nèi)容最復(fù)雜啦。基于這個(gè)原始的函數(shù),如果對(duì)象的數(shù)量多的話(huà),你必須為每個(gè)對(duì)象加上這個(gè)函數(shù)-明顯是重復(fù)勞動(dòng)了。這樣說(shuō) 吧,o1.fun寫(xiě)得非常清晰的而且為了搞掂它已經(jīng)占用了我一個(gè)星期的開(kāi)發(fā)時(shí)間。想象一下代碼到處散布著this變量,怎么能不頭疼?如果要將調(diào)用(執(zhí) 行)的o1.fun方法但this會(huì)執(zhí)行o2,應(yīng)該怎么實(shí)現(xiàn)呢?試一試下面的:
    o1.fun.call(o2);
    明白了嗎?當(dāng)執(zhí)行o1的fun方法時(shí)你強(qiáng)行將變量this指向到o2這個(gè)對(duì)象,換句話(huà)說(shuō),更加嚴(yán)謹(jǐn)?shù)卣f(shuō):o1.fun的方法在對(duì)象o2的作用域下運(yùn)行。
    當(dāng)運(yùn)行一個(gè)函數(shù),一個(gè)對(duì)象的方法時(shí),你可將作用域當(dāng)作this值的變量。
    變量的可見(jiàn)度
    變量的可見(jiàn)度和作用域的關(guān)系非常密切。我們已經(jīng)了解到,可在任何對(duì)象的外部,聲明變量,或在全局的函數(shù)(函數(shù)也是變量的一種)也可以,更嚴(yán)格說(shuō), 它們是全局對(duì)象window的屬性。 全局變量在任何地方都可見(jiàn);無(wú)論函數(shù)的內(nèi)部還是外部。如果你在某一個(gè)函數(shù)內(nèi)修改了一個(gè)全局變量,其它函數(shù)也會(huì)得知這個(gè)值是修改過(guò)的。
    對(duì)象可以有它自己的屬性(像上面的testvar),這些屬性允許從內(nèi)部或是外部均是可見(jiàn)的。試:
    alert(o1.testvar); // 從外部訪(fǎng)問(wèn)o1的屬性testvar
    從內(nèi)部訪(fǎng)問(wèn)的演示可在兩個(gè)測(cè)試對(duì)象的fun方法找到。
    用關(guān)鍵字var在內(nèi)部聲明,相當(dāng)于聲明局部變量(局部聲明也是在一條鏈上,即Scope Chain 作用域鏈上,Frank注):
    Java代碼
    1. i = 44;   
    2. function fn2() {   
    3.     var i = 55;   
    4.     alert(i);   
    5. }  
    6. fn2();  

    將得到什么?對(duì)了,55。聲明在函數(shù)fn2的變量i是一個(gè)本地變量(局部變量),和等于44的全局變量i 44沒(méi)什么關(guān)系。 But:
    alert(i);
    這會(huì)訪(fǎng)問(wèn)全局變量i,顯示44。
    希望本文能幫助讀者徹底理解作用域變量可見(jiàn)性的含義。
    EXT程序規(guī)劃入門(mén)
    事前準(zhǔn)備
    本教程假設(shè)你已經(jīng)安裝好ExtJS庫(kù)。安裝的目錄是extjs 并位于你程序的上一級(jí)目錄。如果安裝在其它地方你必須更改路徑,更改示例文件中script標(biāo)簽的src的屬性。
    需要些什么?
    除ExtJS庫(kù)本身外,我們還需要兩個(gè)文件:
    • applayout.html
    • applayout.js

    先看看一份html文檔,比較精簡(jiǎn)。并附有詳細(xì)說(shuō)明:
    applayout.html
    Java代碼
    1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"   
    2.     "http://www.w3.org/TR/html4/loose.dtd">  
    3. <html>  
    4. <head>  
    5.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
    6.     <link rel="stylesheet" type="text/css" href="../extjs/resources/css/ext-all.css">  
    7.     <script type="text/javascript" src="../extjs/adapter/ext/ext-base.js"></script>  
    8.     <script type="text/javascript" src="../extjs/ext-all-debug.js"></script>  
    9.     <script type="text/javascript" src="applayout.js"></script>  
    10.     <!-- 本地化的腳本引用在這里 -->  
    11.     <script type="text/javascript">  
    12.         Ext.onReady(myNameSpace.app.init, myNameSpace.app);  
    13.     </script>  
    14.     <title>Application Layout Tutorial</title>  
    15. </head>  
    16. <body>  
    17. </body>  
    18. </html>  

    開(kāi)頭的兩行聲明了文檔的類(lèi)型。程序可以不用doctype,但是這樣的話(huà)瀏覽器可能默認(rèn)其為Quirks怪僻類(lèi)型,會(huì)導(dǎo)致處理跨瀏覽器這一問(wèn)題上出現(xiàn)差異。

    我們采用HTML 4.01 Transitional的文檔類(lèi)型,該類(lèi)型在主流瀏覽器上支持得不錯(cuò)。當(dāng)然,你也可以根據(jù)你的需求采用其它類(lèi)型的doctype,但是記住別忘了要加上doctype。
    接著指定HTML頭部的Content-Type。做這些事情其實(shí)很瑣碎,但總是有益處。
    然后引入EXT的樣式,適配器和EXTJS本身。有兩種版本的ExtJS:
    • ext-all.js - 不能直接閱讀,加載時(shí)更快,用于產(chǎn)品發(fā)布
    • ext-all-debug.js - 便于閱讀,開(kāi)發(fā)階段使用,
    開(kāi)發(fā)階段的時(shí)候便需要引入debug的版本。

    applayout.js這個(gè)文件就是我們的程序,緊跟著的是本地化的腳本,這里可以換成Extjs翻譯好的版本
    跟著我們開(kāi)始分配事件句柄(event handler),使得在文檔全部加載完畢后,程序就可以初始化(運(yùn)行)。
    下面的這一行:
    Ext.onReady(myNameSpace.app.init, myNameSpace.app);
    可這樣說(shuō):當(dāng)文檔全部加載完畢,就運(yùn)行myNameSpace.app的init方法,規(guī)定的作用域是myNameSpace.app。
    然后是標(biāo)題,頭部的結(jié)尾,body(當(dāng)前空)和結(jié)束標(biāo)簽。
    文檔的解說(shuō)就說(shuō)到這兒了。
    applayout.js
    Java代碼
    1. /** 
    2.   * Application Layout 
    3.   * by Jozef Sakalos, aka Saki 
    4.   * http://extjs.com/learn/Tutorial:Application_Layout_for_Beginners_(Chinese) 
    5.   */  
    6.    
    7. // 填充圖片的本地引用  
    8. Ext.BLANK_IMAGE_URL = '../extjs/resources/images/default/s.gif';  
    9.    
    10. // 創(chuàng)建命名空間  
    11. Ext.namespace('myNameSpace');  
    12.    
    13. // 創(chuàng)建應(yīng)用程序  
    14. myNameSpace.app = function() {  
    15.     // 元素還沒(méi)創(chuàng)建,未能訪(fǎng)問(wèn)  
    16.    
    17.     // 私有變量  
    18.    
    19.     // 私有函數(shù)  
    20.    
    21.     // 公共空間  
    22.     return {  
    23.         // 公共的屬性,如,要轉(zhuǎn)換的字符串  
    24.         // 公共方法  
    25.         init: function() {  
    26.             alert('應(yīng)用程序初始化成功。');  
    27.         }  
    28.     };  
    29. }(); // 程序底部  
    30.    

    // 文件底部
    文件最開(kāi)始的幾行是注釋?zhuān)f(shuō)明該文件的主要內(nèi)容,作者,作者相關(guān)的資訊。沒(méi)有任何注釋的程序也可以正常的運(yùn)行,-但請(qǐng)記住:每次寫(xiě)的程序要容易給 人看得懂的 Always write your application as if you would write it for another.當(dāng)你回頭看你幾個(gè)月前寫(xiě)的代碼,發(fā)現(xiàn)你根本不記得自己寫(xiě)過(guò)什么的時(shí)候,就會(huì)明白這個(gè)道理,并養(yǎng)成編碼的好習(xí)慣。接著是要指向你服務(wù)器的填 充圖片,如不指定則默認(rèn)extjs.com。每次運(yùn)行程序的時(shí)候都訪(fǎng)問(wèn)extjs.com,不推薦這樣,應(yīng)該先修改這個(gè)常量值指向到本地。

    現(xiàn)在自定義命名空間。將所有變量和方法都劃分到一個(gè)全局對(duì)象下管理,這樣的好處是避免了變量名沖突和由不同函數(shù)干擾了全局變量的值。名字(namespace)可按自己的方案選擇。

    整段代碼的重點(diǎn)是,我們創(chuàng)建了 myNameSpace對(duì)象的屬性app,其值是一個(gè)函數(shù)立刻運(yùn)行之后的返回值。
    如果運(yùn)行我們的代碼:
    var o = function() {
        return {p1:11, p2:22};
    }();
    實(shí)際上我們創(chuàng)建了一個(gè)匿名函數(shù)(沒(méi)有名字的函數(shù)),經(jīng)過(guò)解釋?zhuān)A(yù)編譯?)之后讓它立刻運(yùn)行(注意函數(shù)后面的())。最后將函數(shù)返回的對(duì)象(注意此時(shí)是一個(gè)object變量)分配到變量o。我們的程序便是這種思路去寫(xiě)的。
    你可以把私有變量和私有函數(shù)直接定義在function和return這兩個(gè)聲明之間,但是請(qǐng)切記:此時(shí)不能訪(fǎng)問(wèn)任何html頁(yè)面中的元素,那會(huì)導(dǎo)致錯(cuò)誤,因?yàn)檫@段代碼在加載時(shí)頁(yè)面的head中就運(yùn)行了,而這時(shí)候html頁(yè)面中的其它元素還沒(méi)有被加載進(jìn)來(lái)。
    另外一方面,函數(shù)init,是由匿名函數(shù)返回的對(duì)象的一個(gè)方法而已。它會(huì)在文檔全部加載后才運(yùn)行。換言之整個(gè)DOM樹(shù)已經(jīng)是可用的了。
    一切都還好吧~如果能正確運(yùn)行http://yourserver.com/applayout/applayout.html,不出現(xiàn)什么錯(cuò)誤的話(huà)將出現(xiàn)一個(gè)警告。
    接下來(lái)是利用這個(gè)空白的模板,討論本文的重點(diǎn)。
    公開(kāi)Public、私有Private、特權(quán)的Privileged?
    讓我們加入一些有趣內(nèi)容到程序中去吧。在頁(yè)面applayout.html的body標(biāo)簽中加入:
    <div id="btn1-ct"></div>
    空白的div會(huì)當(dāng)作按鈕的容器來(lái)使用。然后在applayout.js加入下來(lái)代碼:
    Java代碼
    1. /** 
    2.   * Application Layout 
    3.   * by Jozef Sakalos, aka Saki 
    4.   * http://extjs.com/learn/Tutorial:Application_Layout_for_Beginners_(Chinese) 
    5.   */  
    6.    
    7. //  填充圖片的本地引用  
    8. Ext.BLANK_IMAGE_URL = '../extjs/resources/images/default/s.gif';  
    9.    
    10. // 創(chuàng)建命名空間  
    11. Ext.namespace('myNameSpace');  
    12.    
    13. // 創(chuàng)建應(yīng)用程序  
    14. myNameSpace.app = function() {  
    15.     // 元素還沒(méi)創(chuàng)建,未能訪(fǎng)問(wèn)  
    16.    
    17.     // 私有變量  
    18.     var btn1;  
    19.     var privVar1 = 11;  
    20.    
    21.     // 私有函數(shù)  
    22.     var btn1Handler = function(button, event) {  
    23.         alert('privVar1=' + privVar1);  
    24.         alert('this.btn1Text=' + this.btn1Text);  
    25.     };  
    26.    
    27.     // 公共空間  
    28.     return {  
    29.         // 公共的屬性,如,要轉(zhuǎn)譯的字符串  
    30.         btn1Text: 'Button 1'  
    31.    
    32.         // 公共方法  
    33.         , init: function() {  
    34.             btn1 = new Ext.Button('btn1-ct', {  
    35.                   text: this.btn1Text  
    36.                 , handler: btn1Handler  
    37.             });  
    38.         }  
    39.     };  
    40. }(); //程序底部  

    // 文件底部
    變量btn1 和privVar1 是私有的。 那意味著在程序外部他們是不能夠被訪(fǎng)問(wèn)的,而且也不可見(jiàn)。私有函數(shù)btn1Handler也是同樣道理。
    另外一個(gè)方面,btn1Text是公共變量所以可以被程序外部訪(fǎng)問(wèn)或者是修改(我們稍后將會(huì)演示)。
    函數(shù)init是特權(quán)的,即是私有變量和公共變量?jī)烧叨伎梢员凰L(fǎng)問(wèn)到。在本例中,公共變量this.btn1Text和私有函數(shù)btn1Handler都能夠被特權(quán)函數(shù)init所訪(fǎng)問(wèn)。同時(shí),相對(duì)外界來(lái)說(shuō),它也屬于公共成員的一種。
    Ok,運(yùn)行看看。能看到左上角的按鈕嗎?很好,點(diǎn)擊它。得到一個(gè)privVar1=11的警告。這說(shuō)明私有函數(shù)能訪(fǎng)問(wèn)私有變量。
    但是在第二個(gè)警告中遇到了this.btn1Text=undefined的問(wèn)題,這好像不應(yīng)該這樣。個(gè)中原因是因?yàn)槲挥谑录浔?event handler)中的變量this沒(méi)有正確指向到我們的程序。你需要用scope:this 指明這個(gè)作用域(這里的this關(guān)鍵字所指示的scope應(yīng)該是btn1變量):
    Java代碼
    1. btn1 = new Ext.Button('btn1-ct', {  
    2.       text: this.btn1Text  
    3.     , handler: btn1Handler  
    4.     , scope: this  
    5. });  

    刷新一下,可以了吧?
    重寫(xiě)公共變量
    在applayout.js底部加入下列代碼:
    Ext.apply(myNameSpace.app, {
        btn1Text:'Taste 1'
    });

    // 文件底部
    這代碼是用來(lái)干什么的呢?首先它創(chuàng)建了我們的程序?qū)ο笕缓蟾淖儯ㄖ貙?xiě))公共變量btn1Text的值。運(yùn)行后將看到按鈕上文字的變化。

    把文本都放到公共變量,以便于以后的國(guó)際化翻譯工作,而不需要修改程序的內(nèi)部代碼。
    當(dāng)然你也可以將其它的值例如尺寸、樣式、等等的總之是可自定義的選項(xiàng)都放到公共變量中。免于在數(shù)千行代碼之中為查找某個(gè)顏色而費(fèi)勁。
    重寫(xiě)(Overriding)公共函數(shù)
    接著更改一下代碼,讓它讀起來(lái)是這樣的:
    Java代碼
    1. Ext.apply(myNameSpace.app, {  
    2.       btn1Text:'Taste 1'  
    3.     , init: function() {  
    4.         try {  
    5.             btn1 = new Ext.Button('btn1-ct', {  
    6.                   text: this.btn1Text  
    7.                 , handler: btn1Handler  
    8.                 , scope: this  
    9.             });  
    10.         }  
    11.         catch(e) {  
    12.             alert('錯(cuò)誤: "' + e.message + '" 發(fā)生在行: ' + e.lineNumber);  
    13.         }  
    14.     }  
    15. });  


    // end of file
    我們這里將init重寫(xiě)了一篇,主要是在原來(lái)代碼的基礎(chǔ)上加入異常控制,以便能夠捕獲異常。試運(yùn)行一下看還有沒(méi)有其它的變化?
    嗯 是的,出現(xiàn)了btn1Handler 未定義的錯(cuò)誤。這是因?yàn)樾碌暮瘮?shù)雖然嘗試訪(fǎng)問(wèn)私有變量但它實(shí)際是不允許的。正如所見(jiàn),原init是特權(quán)函數(shù)可訪(fǎng)問(wèn)私有空間,但新的init卻不能。之所以 不能訪(fǎng)問(wèn)私有空間,是因?yàn)椋航雇獠看aNo code from outside,哪怕是嘗試重寫(xiě)特權(quán)方法。
    DomQuery基礎(chǔ)
    本教程旨在為讀者了解怎樣利用單例對(duì)象Ext.DomQuery,瀏覽穿梭于DOM樹(shù)之中和獲取對(duì)象,提供一個(gè)起點(diǎn)。
    DomQuery基礎(chǔ)
    DomQuery的select函數(shù)有兩個(gè)參數(shù)。第一個(gè)是選擇符字符(selector string )而第二個(gè)是欲生成查詢(xún)的標(biāo)簽ID(TAG ID)。
    本文中我準(zhǔn)備使用函數(shù)“Ext.query”但讀者須謹(jǐn)記它是“Ext.DomQuery.select()”的簡(jiǎn)寫(xiě)方式。
    這是要入手的html:
    Java代碼
    1. <html>  
    2.  <head>  
    3.   <script type="text/javascript" src="../js/firebug/firebug.js"></script>  
    4.  </head>  
    5.  <body>  
    6.   <script type="text/javascript" src="../ext/ext-base.js"></script>  
    7.   <script type="text/javascript" src="../ext/ext-core.js"></script>  
    8.   <div id="bar"  class="foo">  
    9.    I'm a div ==> my id: bar, my class: foo  
    10.    <span class="bar">I'm a span within the div with a foo class</span>  
    11.    <a >An ExtJs link</a>  
    12.   </div>  
    13.   <div id="foo" class="bar">  
    14.    my id: foo, my class: bar  
    15.    <p>I'm a P tag within the foo div</p>  
    16.    <span class="bar">I'm a span within the div with a bar class</span>  
    17.    <a href="#">An internal link</a>  
    18.   </div>  
    19.  </body>  
    20. </html>  

    第一部分:元素選擇符Selector
    假設(shè)我想獲取文檔內(nèi)所有的“span”標(biāo)簽:
    Java代碼
    1. // 這個(gè)查詢(xún)會(huì)返回有兩個(gè)元素的數(shù)組因?yàn)椴樵?xún)選中對(duì)整個(gè)文檔的所有span標(biāo)簽。  
    2. Ext.query("span");   
    3. // 這個(gè)查詢(xún)會(huì)返回有一個(gè)元素的數(shù)組因?yàn)椴樵?xún)顧及到了foo這個(gè)id。  
    4. Ext.query("span", "foo");  
    5. 注意剛才怎么傳入一個(gè)普通的字符串作為第一個(gè)參數(shù)。   
    6. 按id獲取標(biāo)簽,你需要加上“#”的前綴:   
    7. // 這個(gè)查詢(xún)會(huì)返回包含我們foo div一個(gè)元素的數(shù)組!  
    8. Ext.query("#foo");  
    9. 按class name獲取標(biāo)簽,你需要加上“.”的前綴:   
    10. /*這個(gè)查詢(xún)會(huì)返回有一個(gè)元素的數(shù)組, 
    11. 包含與之前例子一樣的div但是我們使用了class name來(lái)獲取*/  
    12. Ext.query(".foo");  
    13. 你也可以使用關(guān)鍵字“*”來(lái)獲取所有的元素:   
    14. // 這會(huì)返回一個(gè)數(shù)組,包含文檔的所有元素。  
    15. Ext.query("*");  
    16. 要獲取子標(biāo)簽,我們只須在兩個(gè)選擇符之間插入一個(gè)空格:   
    17. // 這會(huì)返回有一個(gè)元素的數(shù)組,包含p標(biāo)簽的div標(biāo)簽   
    18. Ext.query("div p");  
    19. // 這會(huì)返回有兩個(gè)元素的數(shù)組,包含span標(biāo)簽的div標(biāo)簽   
    20. Ext.query("div span");  
    21.   
    22. 還有三個(gè)的元素選擇符,待后續(xù)的教程會(huì)敘述。 ""   
    23. 如果朋友你覺(jué)得這里說(shuō)得太簡(jiǎn)單的話(huà),你可以選擇到DomQuery 文檔看看,可能會(huì)有不少收獲:)   
    24. 第二部分:屬性選擇符Attributes selectors   
    25. 這些選擇符可讓你得到基于一些屬性值的元素。屬性指的是html元素中的href, id 或 class。   
    26. // 我們檢查出任何存在有class屬性的元素。  
    27. // 這個(gè)查詢(xún)會(huì)返回5個(gè)元素的數(shù)組。  
    28. Ext.query("*[class]"); // 結(jié)果: [body#ext-gen2.ext-gecko, div#bar.foo, span.bar, div#foo.bar, span.bar]  
    29. 現(xiàn)在我們針對(duì)特定的class屬性進(jìn)行搜索。   
    30. // 這會(huì)得到class等于“bar”的所有元素  
    31. Ext.query("*[class=bar]");  
    32.    
    33. // 這會(huì)得到class不等于“bar”的所有元素  
    34. Ext.query("*[class!=bar]");  
    35.    
    36. // 這會(huì)得到class從“b”字頭開(kāi)始的所有元素  
    37. Ext.query("*[class^=b]");  
    38.    
    39. //這會(huì)得到class由“r”結(jié)尾的所有元素  
    40. Ext.query("*[class$=r]");  
    41.    
    42. //這會(huì)得到在class中抽出“a”字符的所有元素  
    43. Ext.query("*[class*=a]");  
    44. 第三部分: CSS值元素選擇符  
    45. 這些選擇符會(huì)匹配DOM元素的style屬性。嘗試在那份html中加上一些顏色:   
    46. <html>  
    47.  <head>  
    48.   <script type="text/javascript" src="../js/firebug/firebug.js"></script>  
    49.  </head>  
    50.  <body>  
    51.   <script type="text/javascript" src="../ext/ext-base.js"></script>  
    52.   <script type="text/javascript" src="../ext/ext-core.js"></script>  
    53.   <div id="bar" class="foo" style="color:red;">  
    54.    我是一個(gè)div ==> 我的id是: bar, 我的class: foo  
    55.    <span class="bar" style="color:pink;">I'm a span within the div with a foo class</span>  
    56.    <a >An ExtJs link with a blank target!</a>  
    57.   </div>  
    58.   <div id="foo" class="bar" style="color:fushia;">  
    59.    my id: foo, my class: bar  
    60.    <p>I'm a P tag within the foo div</p>  
    61.    <span class="bar" style="color:brown;">I'm a span within the div with a bar class</span>  
    62.    <a href="#" style="color:green;">An internal link</a>  
    63.   </div>  
    64.  </body>  
    65. </html>  
    66. 基于這個(gè)CSS的顏色值我們不會(huì)作任何查詢(xún),但可以是其它的內(nèi)容。它的格式規(guī)定是這樣的:   
    67. 元素{屬性 操作符 值}   
    68. 注意我在這里是怎么插入一個(gè)不同的括號(hào)。   
    69. 所以,操作符(operators)和屬性選擇符(attribute selectors)是一樣的。   
    70. // 獲取所以紅色的元素  
    71. Ext.query("*{color=red}"); // [div#bar.foo]  
    72.    
    73. // 獲取所有粉紅顏色的并且是有紅色子元素的元素  
    74. Ext.query("*{color=red} *{color=pink}"); // [span.bar]  
    75.    
    76. // 獲取所有不是紅色文字的元素  
    77. Ext.query("*{color!=red}");    
    78. //[html, head, script firebug.js, link, body#ext-gen2.ext-gecko,  
    79. // script ext-base.js, script ext-core.js, span.bar,   
    80. //a www.extjs.com, div#foo.bar, p, span.bar, a test.html#]  
    81.    
    82. // 獲取所有顏色屬性是從“yel”開(kāi)始的元素  
    83. Ext.query("*{color^=yel}"); // [a www.extjs.com]  
    84.    
    85. // 獲取所有顏色屬性是以“ow”結(jié)束的元素  
    86. Ext.query("*{color$=ow}"); // [a www.extjs.com]  
    87.    
    88. // 獲取所有顏色屬性包含“ow”字符的元素  
    89. Ext.query("*{color*=ow}"); // [a www.extjs.com, span.bar]  
    90.   
    91. 第四部分:偽類(lèi)選擇符Pseudo Classes selectors   
    92. 仍然是剛才的網(wǎng)頁(yè),但是有所不同的只是新加上了一個(gè)UL元素、一個(gè)TABLE元素和一個(gè)FORM元素,以便我們可以使用不同的偽類(lèi)選擇符,來(lái)獲取節(jié)點(diǎn)。   
    93. <html>  
    94.  <head>  
    95.   <script type="text/javascript" src="../js/firebug/firebug.js"></script>  
    96.  </head>  
    97.  <body>  
    98.   <script type="text/javascript" src="../ext/ext-base.js"></script>  
    99.   <script type="text/javascript" src="../ext/ext-core.js"></script>  
    100.   <div id="bar" class="foo" style="color:red; border: 2px dotted red; margin:5px; padding:5px;">  
    101.    I'm a div ==> my id: bar, my class: foo  
    102.    <span class="bar" style="color:pink;">I'm a span within the div with a foo class</span>  
    103.    <a >An ExtJs link with a blank target!</a>  
    104.   </div>  
    105.   <div id="foo" class="bar" style="color:fushia; border: 2px dotted black; margin:5px; padding:5px;">  
    106.    my id: foo, my class: bar  
    107.    <p>I'm a P tag within the foo div</p>  
    108.    <span class="bar" style="color:brown;">I'm a span within the div with a bar class</span>  
    109.    <a href="#" style="color:green;">An internal link</a>  
    110.   </div>  
    111.   <div style="border:2px dotted pink; margin:5px; padding:5px;">  
    112.    <ul>  
    113.     <li>Some choice #1</li>  
    114.     <li>Some choice #2</li>  
    115.     <li>Some choice #3</li>  
    116.     <li>Some choice #4 with a <a href="#">link</a></li>  
    117.    </ul>  
    118.    <table style="border:1px dotted black;">  
    119.     <tr style="color:pink">  
    120.      <td>1st row, 1st column</td>  
    121.      <td>1st row, 2nd column</td>  
    122.     </tr>  
    123.     <tr style="color:brown">  
    124.         <td colspan="2">2nd row, colspanned! </td>  
    125.     </tr>  
    126.     <tr>  
    127.      <td>3rd row, 1st column</td>  
    128.      <td>3rd row, 2nd column</td>  
    129.     </tr>   
    130.    </table>  
    131.   </div>  
    132.   <div style="border:2px dotted red; margin:5px; padding:5px;">  
    133.    <form>  
    134.     <input id="chked" type="checkbox" checked/><label for="chked">I'm checked</label>  
    135.     <br /><br />  
    136.     <input id="notChked" type="checkbox" /><label for="notChked">not me brotha!</label>  
    137.    </form>  
    138.   </div>  
    139.  </body>  
    140. </html>  
    141.    
    142. 接著:  
    143. /* 
    144.  this one gives us the first SPAN child of its parent 
    145. */  
    146. Ext.query("span:first-child"); // [span.bar]  
    147.    
    148. /* 
    149.  this one gives us the last A child of its parent 
    150. */  
    151. Ext.query("a:last-child") // [a www.extjs.com, a test.html#]  
    152.    
    153. /* 
    154.  this one gives us the second SPAN child of its parent 
    155. */  
    156. Ext.query("span:nth-child(2)") // [span.bar]  
    157.    
    158. /* 
    159.  this one gives us ODD TR of its parents 
    160. */  
    161. Ext.query("tr:nth-child(odd)") // [tr, tr]  
    162.    
    163. /* 
    164.  this one gives us even LI of its parents 
    165. */  
    166. Ext.query("li:nth-child(even)") // [li, li]  
    167.    
    168. /* 
    169.  this one gives us A that are the only child of its parents 
    170. */  
    171.    
    172. Ext.query("a:only-child") // [a test.html#]  
    173.    
    174. /* 
    175.  this one gives us the checked INPUT 
    176. */  
    177. Ext.query("input:checked") // [input#chked on]  
    178.    
    179. /* 
    180.  this one gives us the first TR 
    181. */  
    182. Ext.query("tr:first") // [tr]  
    183.    
    184. /* 
    185.  this one gives us the last INPUT 
    186. */  
    187. Ext.query("input:last") // [input#notChked on]  
    188.    
    189. /* 
    190.  this one gives us the 2nd TD 
    191. */  
    192. Ext.query("td:nth(2)") // [td]  
    193.    
    194. /* 
    195.  this one gives us every DIV that has the "within" string 
    196. */  
    197. Ext.query("div:contains(within)") // [div#bar.foo, div#foo.bar]  
    198.    
    199. /* 
    200.  this one gives us every DIV that doesn't have a FORM child 
    201. */  
    202. Ext.query("div:not(form)") [div#bar.foo, div#foo.bar, div]  
    203.    
    204. /* 
    205.  This one gives use every DIV that has an A child 
    206. */  
    207. Ext.query("div:has(a)") // [div#bar.foo, div#foo.bar, div]  
    208.    
    209. /*  
    210.  this one gives us every TD that is followed by another TD.  
    211.  obviously, the one that has a colspan property is ignored. 
    212. */  
    213. Ext.query("td:next(td)") // [td, td]  
    214.    
    215. /* 
    216.  this one gives us every LABEL that is preceded by an INPUT 
    217. */  
    218. Ext.query("label:prev(input)") //[label, label]  

    擴(kuò)展EXT組件
    要?jiǎng)?chuàng)建的擴(kuò)展是一個(gè)在文字前面能夠顯示圖標(biāo)的這么一個(gè)Ext.form.Combobox。將其中一個(gè)功能舉例來(lái)說(shuō),就是要在一塊選擇里,國(guó)家名稱(chēng)連同國(guó)旗一并出現(xiàn)。
    我們先給擴(kuò)展起個(gè)名字,就叫Ext.ux.IconCombo。
    文件的創(chuàng)建
    首要的步驟是準(zhǔn)備好開(kāi)發(fā)中將會(huì)使用的文件。需下列文件:
    • iconcombo.html: 新擴(kuò)展將會(huì)使用的 html markup
    • iconcombo.js: 程序javascript代碼
    • Ext.ux.IconCombo.js: 擴(kuò)展的javascript文件
    • Ext.ux.IconCombo.css: 擴(kuò)展樣式表
    Java代碼
    1. iconcombo.html  
    2. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"   
    3.     "http://www.w3.org/TR/html4/loose.dtd">  
    4. <html>  
    5. <head>  
    6.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
    7.     <link rel="stylesheet" type="text/css" href="../extjs/resources/css/ext-all.css">  
    8.     <link rel="stylesheet" type="text/css" href="Ext.ux.IconCombo.css">  
    9.     <script type="text/javascript" src="../extjs/adapter/ext/ext-base.js"></script>  
    10.     <script type="text/javascript" src="../extjs/ext-all-debug.js"></script>  
    11.     <script type="text/javascript" src="Ext.ux.IconCombo.js"></script>  
    12.     <script type="text/javascript" src="iconcombo.js"></script>  
    13.     <!-- A Localization Script File comes here -->  
    14.     <script type="text/javascript">Ext.onReady(iconcombo.init, iconcombo);</script>  
    15.     <title>Ext.ux.IconCombo Tutorial</title>  
    16. </head>  
    17. <body>  
    18. <div style="position:relative;width:300px;top:24px;left:64px;font-size:11px">  
    19.     <div>Icon combo:</div>  
    20.     <div id="combo-ct"></div>  
    21. </div>  
    22. </body>  
    23. </html>  
    24. 該文件來(lái)自教程Ext程序規(guī)劃入門(mén) 的輕微修改。   
    25. iconcombo.js  
    26. /** 
    27.   * Ext.ux.IconCombo Tutorial 
    28.   * by Jozef Sakalos, aka Saki 
    29.   * http://extjs.com/learn/Tutorial:Extending_Ext_Class 
    30.   */  
    31.    
    32. // 引用本地空白文件  
    33. Ext.BLANK_IMAGE_URL = '../extjs/resources/images/default/s.gif';  
    34.    
    35. // 創(chuàng)建程序  
    36. iconcombo = function() {  
    37.    
    38.     // 公共空間  
    39.     return {  
    40.         // public properties, e.g. strings to translate  
    41.    
    42.         // public methods  
    43.         init: function() {  
    44.             var icnCombo = new Ext.ux.IconCombo({  
    45.                 store: new Ext.data.SimpleStore({  
    46.                     fields: ['countryCode', 'countryName', 'countryFlag'],  
    47.                     data: [  
    48.                         ['US', 'United States', 'x-flag-us'],  
    49.                         ['DE', 'Germany', 'x-flag-de'],  
    50.                         ['FR', 'France', 'x-flag-fr']  
    51.                     ]  
    52.                 }),  
    53.                 valueField: 'countryCode',  
    54.                 displayField: 'countryName',  
    55.                 iconClsField: 'countryFlag',  
    56.                 triggerAction: 'all',  
    57.                 mode: 'local',  
    58.                 width: 160  
    59.             });  
    60.             icnCombo.render('combo-ct');  
    61.             icnCombo.setValue('DE');  
    62.         }  
    63.     };  
    64. }(); // end of app  
    65.    
    66. // end of file  
    67.   
    68. 我們?cè)谶@個(gè)文件中創(chuàng)建IconCombo,以便可以進(jìn)行擴(kuò)展和測(cè)試。   
    69. Ext.ux.IconCombo.js  
    70. // Create創(chuàng)建用戶(hù)的擴(kuò)展(User eXtensions namespace (Ext.ux))  
    71. Ext.namespace('Ext.ux');  
    72.    
    73. /** 
    74.   * Ext.ux.IconCombo 擴(kuò)展類(lèi) 
    75.   * 
    76.   * @author Jozef Sakalos, aka Saki 
    77.   * @version 1.0 
    78.   * 
    79.   * @class Ext.ux.IconCombo 
    80.   * @extends Ext.form.ComboBox 
    81.   * @constructor 
    82.   * @param {Object} config 配置項(xiàng)參數(shù) 
    83.   */  
    84. Ext.ux.IconCombo = function(config) {  
    85.    
    86.     // 調(diào)用父類(lèi)的構(gòu)建函數(shù)  
    87.     Ext.ux.IconCombo.superclass.constructor.call(this, config);  
    88.    
    89. } // Ext.ux.IconCombo構(gòu)建器的底部  
    90.    
    91. // 進(jìn)行擴(kuò)展  
    92. Ext.extend(Ext.ux.IconCombo, Ext.form.ComboBox, {  
    93.    
    94. }); // 擴(kuò)展完畢  
    95.    
    96. // 文件底部  
    97. 運(yùn)行到這一步,實(shí)際這是一個(gè)沒(méi)有對(duì)Ext.form.ComboBox新加任何東西的空擴(kuò)展。我們正是需要這個(gè)完成好的空擴(kuò)展,再繼續(xù)下一步。   
    98. Ext.ux.IconCombo.css  
    99. .x-flag-us {  
    100.     background-image: url(../img/flags/us.png);  
    101. }  
    102. .x-flag-de {  
    103.     background-image: url(../img/flags/de.png);  
    104. }  
    105. .x-flag-fr {  
    106.     background-image: url(../img/flags/fr.png);  
    107. }  
    108. 路徑可能根據(jù)你所在的國(guó)旗放置目錄有所不同。國(guó)旗的資源可在here下載。   
    109. Let's go  
    110. So far so good!如果你瀏覽iconcombo.html應(yīng)該會(huì)發(fā)現(xiàn)一個(gè)包含三個(gè)選項(xiàng)的標(biāo)準(zhǔn)combo,而德國(guó)的那個(gè)是選中的...是吧?不過(guò)還沒(méi)有圖標(biāo)...   
    111. 現(xiàn)在正是開(kāi)始工作。在調(diào)用父類(lèi)構(gòu)建器之后加入下列行:   
    112. this.tpl = config.tpl ||  
    113.       '<div class="x-combo-list-item">'  
    114.     + '<table><tbody><tr>'  
    115.     + '<td>'  
    116.     + '<div class="{' + this.iconClsField + '} x-icon-combo-icon"></div></td>'  
    117.     + '<td>{' + this.displayField + '}</td>'  
    118.     + '</tr></tbody></table>'  
    119.     + '</div>'  
    120. ;  
    121. 在這一步,我們將默認(rèn)combox box的模版重寫(xiě)為iconClsField模版。   
    122. 現(xiàn)在加入Ext.ux.IconCombo.css中的樣式文件:   
    123. .x-icon-combo-icon {  
    124.     background-repeat: no-repeat;  
    125.     background-position: 0 50%;  
    126.     width: 18px;  
    127.     height: 14px;  
    128. }  
    129. 不錯(cuò)!可以測(cè)試一下了,刷新的頁(yè)面,還好吧!?嗯,列表展開(kāi)時(shí)那些漂亮的圖標(biāo)就出來(lái)了。。還有。。我們不是要在關(guān)閉時(shí)也出現(xiàn)圖標(biāo)的嗎?   
    130. 在構(gòu)建器中加入創(chuàng)建模版的過(guò)程:   
    131. this.on({  
    132.     render:{scope:this, fn:function() {  
    133.         var wrap = this.el.up('div.x-form-field-wrap');  
    134.         this.wrap.applyStyles({position:'relative'});  
    135.         this.el.addClass('x-icon-combo-input');  
    136.         this.flag = Ext.DomHelper.append(wrap, {  
    137.             tag: 'div', style:'position:absolute'  
    138.         });  
    139.     }}  
    140. });  
    141. 加入 事件render的偵聽(tīng)器,用于調(diào)整元素樣式和創(chuàng)建國(guó)旗的div容器。如后按照下列方式進(jìn)行擴(kuò)展:   
    142. // 進(jìn)行擴(kuò)展  
    143. Ext.extend(Ext.ux.IconCombo, Ext.form.ComboBox, {  
    144.    
    145.     setIconCls: function() {  
    146.         var rec = this.store.query(this.valueField, this.getValue()).itemAt(0);  
    147.         if(rec) {  
    148.             this.flag.className = 'x-icon-combo-icon ' + rec.get(this.iconClsField);  
    149.         }  
    150.     },  
    151.    
    152.     setValue: function(value) {  
    153.         Ext.ux.IconCombo.superclass.setValue.call(this, value);  
    154.         this.setIconCls();  
    155.     }  
    156.    
    157. }); // 擴(kuò)展完畢  
    158. 新增 setIconCls函數(shù)并重寫(xiě)setValue函數(shù)。我們還是需要父類(lèi)的setValue的方法來(lái)調(diào)用一下,接著再調(diào)用setIconCls的函數(shù)。最后,我們應(yīng)該在文件Ext.ux.IconCombo.css加入下列代碼:   
    159. .x-icon-combo-input {  
    160.     padding-left: 26px;  
    161. }  
    162. .x-form-field-wrap .x-icon-combo-icon {  
    163.     top: 3px;  
    164.     left: 6px;  
    165. }  
    166. 完成  
    167. 最后再刷新一下,如果一切順利,那這個(gè)就是新的Ext.ux.IconCombo擴(kuò)展! 希望你能在此基礎(chǔ)上擴(kuò)展更多的組件!   
    168. 謝謝Brian Moeskau提醒,使得能進(jìn)一步精簡(jiǎn)Ext.ux.IconCombo 代碼,才稱(chēng)得上最終版本。最終代碼和CSS為:   
    169. Ext.ux.IconCombo.js  
    170. // Create user extensions namespace (Ext.ux)  
    171. Ext.namespace('Ext.ux');  
    172.    
    173. /** 
    174.   * Ext.ux.IconCombo Extension Class 
    175.   * 
    176.   * @author  Jozef Sakalos 
    177.   * @version 1.0 
    178.   * 
    179.   * @class Ext.ux.IconCombo 
    180.   * @extends Ext.form.ComboBox 
    181.   * @constructor 
    182.   * @param {Object} config Configuration options 
    183.   */  
    184. Ext.ux.IconCombo = function(config) {  
    185.    
    186.     // call parent constructor  
    187.     Ext.ux.IconCombo.superclass.constructor.call(this, config);  
    188.    
    189.     this.tpl = config.tpl ||  
    190.           '  
    191. {'   
    192.         + this.displayField   
    193.         + '}  
    194. '  
    195.     ;  
    196.    
    197.     this.on({  
    198.         render:{scope:this, fn:function() {  
    199.             var wrap = this.el.up('div.x-form-field-wrap');  
    200.             this.wrap.applyStyles({position:'relative'});  
    201.             this.el.addClass('x-icon-combo-input');  
    202.             this.flag = Ext.DomHelper.append(wrap, {  
    203.                 tag: 'div', style:'position:absolute'  
    204.             });  
    205.         }}  
    206.     });  
    207. } // end of Ext.ux.IconCombo constructor  
    208.    
    209. // extend  
    210. Ext.extend(Ext.ux.IconCombo, Ext.form.ComboBox, {  
    211.    
    212.     setIconCls: function() {  
    213.         var rec = this.store.query(this.valueField, this.getValue()).itemAt(0);  
    214.         if(rec) {  
    215.             this.flag.className = 'x-icon-combo-icon ' + rec.get(this.iconClsField);  
    216.         }  
    217.     },  
    218.    
    219.     setValue: function(value) {  
    220.         Ext.ux.IconCombo.superclass.setValue.call(this, value);  
    221.         this.setIconCls();  
    222.     }  
    223.    
    224. }); // end of extend  
    225.    
    226. // end of file  
    227. Ext.ux.IconCombo.css  
    228. css  
    229. /* application specific styles */  
    230. .x-flag-us {  
    231.     background-image:url(../img/flags/us.png);  
    232. }  
    233. .x-flag-de {  
    234.     background-image:url(../img/flags/de.png);  
    235. }  
    236. .x-flag-fr {  
    237.     background-image:url(../img/flags/fr.png);  
    238. }  
    239.    
    240. /* Ext.ux.IconCombo mandatory styles */  
    241. .x-icon-combo-icon {  
    242.     background-repeat: no-repeat;  
    243.     background-position: 0 50%;  
    244.     width: 18px;  
    245.     height: 14px;  
    246. }  
    247. .x-icon-combo-input {  
    248.     padding-left: 25px;  
    249. }  
    250. .x-form-field-wrap .x-icon-combo-icon {  
    251.     top: 3px;  
    252.     left: 5px;  
    253. }  
    254. .x-icon-combo-item {  
    255.     background-repeat: no-repeat;  
    256.     background-position: 3px 50%;  
    257.     padding-left: 24px;  
    258. }  

    EXT的布局(Layout)
    Ext的layout布局對(duì)于建立WEB程序尤為有用。關(guān)于布局引擎(layout engine),區(qū)域管理器(region manager)的教程將分為幾部分,本文是第一篇,為您介紹如何創(chuàng)建區(qū)域,如何增加版面到這些區(qū)域。
    布局引擎(layout engine)這一功能早已在EXT前個(gè)ALPHA實(shí)現(xiàn)了。 Jack Slocum對(duì)于怎樣環(huán)繞某一區(qū)域,給與指定區(qū)域管理的策略,和建立界面的問(wèn)題,在他的第一、第二篇關(guān)于跨瀏覽器的WEB2.0布局功能的博客中,進(jìn)行過(guò) 討論。定義一個(gè)DOM元素的邊界(edge),使之一個(gè)布局的邊框(border)--這種做法使得創(chuàng)建“富界面”客戶(hù)端UI的開(kāi)發(fā)更進(jìn)一大步。
    布局管理器(layout manager)負(fù)責(zé)管理這些區(qū)域。布局管理的主要的用戶(hù)組件是BorderLayout類(lèi)。該類(lèi)為EXT開(kāi)發(fā)富界面的程序提供了一個(gè)切入點(diǎn)。 Layout的含意是劃分好一些預(yù)定的區(qū)域。可用的區(qū)域分別有south, east, west, north,和center。每一個(gè)BorderLayout對(duì)象都提供這些區(qū)域但只有center要求必須使用的。如果你在單獨(dú)一個(gè)區(qū)域中包含多個(gè)面 板,你可通過(guò)NestedLayoutPanel 類(lèi)套嵌到BorderLayout 實(shí)例中。
    注意事項(xiàng):本教程的每個(gè)文件都是.html和.js格式的。教程每一步都有演示,你也可以下載這些文件在編輯器(zip格式提供在這里)中看看發(fā)生什么事。
    面板(Panel)是區(qū)域管理(region management)的另外一個(gè)組件。面板提供了這么一個(gè)地方,可為您的EXT器件(widget)、加載的HTML,嵌入的IFrames、或者是你 日常在HTML頁(yè)面上擺放的隨便一樣?xùn)|西。NestedLayoutPanel也是一個(gè)面板,只不過(guò)用于鏈接多個(gè)BorderLayout的區(qū)域,其它的 面板包括內(nèi)容面板 ContentPanel,Grid面板 GridPanel,和Tree面板 TreePanel。
    簡(jiǎn)單的例子
    下面的layout包含 north, south, east, west,和center的區(qū)域,而且每個(gè)區(qū)域包含一個(gè)ContentPanel,各區(qū)域之間使用得了分隔條分割開(kāi)。
    Java代碼
    1.    
    2. var mainLayout = new Ext.BorderLayout(document.body,   
    3. {  
    4.     north: {   
    5.         split: true, initialSize: 50   
    6.     },  
    7.     south: {  
    8.         split: true, initialSize: 50   
    9.     },  
    10.     east: {   
    11.         split: true, initialSize: 100   
    12.     },   
    13.     west: {   
    14.         split: true, initialSize: 100   
    15.     },   
    16.     center: {  
    17.     }  
    18. });  
    19. 這是一個(gè)非常基本的layout,只是分配了東南西北中間的區(qū)域、分隔條、設(shè)置一下初始尺寸,并最遲定義中間區(qū)域。本例中, BorderLayout被綁定到"document.body"這個(gè)DOM元素,其實(shí)BorderLayout還可以綁定到任何一個(gè)封閉的DOM元素。定義好BorderLayout之后,我們加入ContentPanel對(duì)象(基于本例)。  
    20. mainLayout.beginUpdate();  
    21. mainLayout.add('north', new Ext.ContentPanel('north-div', {  
    22.     fitToFrame: true, closable: false  
    23. }));  
    24. mainLayout.add('south', new Ext.ContentPanel('south-div', {  
    25.     fitToFrame: true, closable: false   
    26. }));  
    27. mainLayout.add('east', new Ext.ContentPanel('east-div', {  
    28.     fitToFrame: true, closable: false  
    29. }));  
    30. mainLayout.add('west', new Ext.ContentPanel('west-div', {  
    31.     fitToFrame: true, closable: false  
    32. }));  
    33. mainLayout.add('center', new Ext.ContentPanel('center-div', {  
    34.     fitToFrame: true  
    35. }));  
    36. mainLayout.endUpdate();  

    當(dāng)前的例子是將ContentPanel加入到所有區(qū)域中。由調(diào)用mainLayout.beginUpdate()開(kāi)始。 beginUpdate ()告訴BorderLayout對(duì)象在執(zhí)行endUpate()方法之前,先不要對(duì)加入的對(duì)象排版布局。這樣的好處是避免了ContentPanel有 對(duì)象加入時(shí),導(dǎo)致UI的刷新,改進(jìn)了整體的用戶(hù)體驗(yàn)。執(zhí)行beginUpdate()之后,加入五個(gè)ContentPanel對(duì)象到區(qū)域。所有的 ContentPanel對(duì)象(除中間的那個(gè)外),都設(shè)置是可關(guān)閉的(closbale)。所有的ContentPanel對(duì)象也都設(shè)置為自動(dòng)適配它們的 父元素。最后執(zhí)行endUpdate()渲染layout。
    InternetExploer注意事項(xiàng):BorderLayout所容納的元素必須有一個(gè)SIZE以便正確渲染。典型地你無(wú)須為 document.body 指明size,因?yàn)閐ocument.body通常是有size的了(大多數(shù)情況,-除非你在瀏覽器上什么也看不到)。但是如果你將layout連同容器 放到現(xiàn)有的web頁(yè)面上(‘可能是DIV),那么DIV的size應(yīng)該先指明以便正確渲染。如下列顯示正常:
    好,讓我們趁熱打鐵,看看完整的layout是怎樣的。假設(shè)ext是一子目錄叫做ext-1.0,父目錄下面的代碼。
    simple.html:


       
       
        

        
        
        



       


       

       

       


       




    simple.js:
    Java代碼
    1. Simple = function() {  
    2.     return {  
    3.         init : function() {  
    4.             var mainLayout = new Ext.BorderLayout(document.body, {  
    5.                 north: {  
    6.                     split: true, initialSize: 50  
    7.                 },  
    8.                 south: {  
    9.                     split: true, initialSize: 50  
    10.                 },  
    11.                 east: {  
    12.                     split: true, initialSize: 100  
    13.                 },  
    14.                 west: {  
    15.                     split: true, initialSize: 100  
    16.                 },  
    17.                 center: {  
    18.                 }  
    19.             });  
    20.             mainLayout.beginUpdate();  
    21.             mainLayout.add('north', new Ext.ContentPanel('north-div', {  
    22.                 fitToFrame: true, closable: false   
    23.             }));  
    24.             mainLayout.add('south', new Ext.ContentPanel('south-div', {  
    25.                 fitToFrame: true, closable: false  
    26.             }));  
    27.             mainLayout.add('east', new Ext.ContentPanel('east-div', {  
    28.                 fitToFrame: true, closable: false  
    29.             }));  
    30.             mainLayout.add('west', new Ext.ContentPanel('west-div', {  
    31.                 fitToFrame: true, closable: false  
    32.             }));  
    33.             mainLayout.add('center', new Ext.ContentPanel('center-div', {  
    34.                 fitToFrame: true  
    35.             }));  
    36.             mainLayout.endUpdate();  
    37.         }  
    38.     };  
    39. }();  
    40. Ext.EventManager.onDocumentReady(Simple.init, Simple, true);  

    加入內(nèi)容
    上面的例子做的layout,除了可移動(dòng)分割欄外,功能還不強(qiáng)大。需要加入些內(nèi)容。有幾種的辦法加入內(nèi)容。如果您直接加入內(nèi)容到DIV中 (ContentPanel綁定的那個(gè)),ContentPanel對(duì)象會(huì)對(duì)div里面的內(nèi)容進(jìn)行渲染。盡管試試!我們會(huì)更改html內(nèi)容加入 center-div中。
    simple2.html:


       
       
        

        
        
        



       


       

       

       


       

            This is some content that will display in a panel
            when a ContentPanel object is attached to the div.
       




    除此之外,還可以利用ContentPanel對(duì)象帶有的function加載數(shù)據(jù)。可用的方法有幾種,這里我們使用其中兩 種:setContent() 與 setUrl()。setContent()允許您直接從JavaScipt程序中插入HTML。setUrl(),允許您從服務(wù)端得到數(shù)據(jù)加入 ContentPanel中。
    我們?cè)瓉?lái)的例子中,ContentPanel對(duì)象創(chuàng)建的時(shí)候是匿名的(anonymous)。這沒(méi)問(wèn)題,但要引用它們,你需要遍歷區(qū)域管理器所分配的對(duì)象以獲得引用的對(duì)象。這不是最好的辦法,所有我的做法是分配一個(gè)變量給ContentPanel然后便可直接引用。
    simple3.js:
    Java代碼
    1. Simple = function() {  
    2.     var northPanel, southPanel, eastPanel, westPanel, centerPanel;  
    3.     return {  
    4.         init : function() {  
    5.             var mainLayout = new Ext.BorderLayout(document.body, {  
    6.                 north: {   
    7.                     split: true, initialSize: 50   
    8.                 },   
    9.                 south: {   
    10.                     split: true, initialSize: 50   
    11.                 },   
    12.                 east: {   
    13.                     split: true, initialSize: 100   
    14.                 },   
    15.                 west: {   
    16.                     split: true, initialSize: 100   
    17.                 },   
    18.                 center: {   
    19.                 }  
    20.             });  
    21.             mainLayout.beginUpdate();  
    22.             mainLayout.add('north', northPanel = new Ext.ContentPanel('north-div', {   
    23.                 fitToFrame: true, closable: false   
    24.             }));  
    25.             mainLayout.add('south', southPanel = new Ext.ContentPanel('south-div', {   
    26.                 fitToFrame: true, closable: false   
    27.             }));  
    28.             mainLayout.add('east', eastPanel = new Ext.ContentPanel('east-div', {   
    29.                 fitToFrame: true, closable: false   
    30.             }));  
    31.             mainLayout.add('west', westPanel = new Ext.ContentPanel('west-div', {   
    32.                 fitToFrame: true, closable: false   
    33.             }));  
    34.             mainLayout.add('center', centerPanel = new Ext.ContentPanel('center-div', {   
    35.                 fitToFrame: true   
    36.             }));  
    37.             mainLayout.endUpdate();  
    38.             northPanel.setContent('This panel will be used for a header');  
    39.             westPanel.setContent(' ');  
    40.             centerPanel.setUrl('index.html');  
    41.             centerPanel.refresh();  
    42.         }  
    43.     };  
    44. }();  
    45. Ext.EventManager.onDocumentReady(Simple.init, Simple, true);  

    我們現(xiàn)在從現(xiàn)有的頁(yè)面動(dòng)態(tài)加載內(nèi)容。但是這里有個(gè)問(wèn)題。若果內(nèi)容頁(yè)面積過(guò)大而撐破頁(yè)面的話(huà)將沒(méi)有意義了。我們提供了一些配置屬性以解決這類(lèi)問(wèn)題。 當(dāng) fitToFrame為true時(shí),就自動(dòng)配置autoScroll。內(nèi)容一旦溢出就會(huì)出現(xiàn)滾動(dòng)條。另外一個(gè)涉及InternetExploer的問(wèn)題, 是中間的內(nèi)容的樣式?jīng)]有生效,原因是一些瀏覽器支持動(dòng)態(tài)樣式而一些不支持,要較好地解決上述問(wèn)題,推薦使用Iframe標(biāo)簽。
    用IFRAME標(biāo)簽做布局可靈活地處理,我們準(zhǔn)備在DOM中直接操縱IFRAME.這里IFRAME成為面板的容器,以填入中間區(qū)域的內(nèi)容
    設(shè)置一下 IFRAME的滾動(dòng)條并放到中間的頁(yè)面。.
    simple4.html:




       
       
        
        

        
        


       

       


       

       

       

           
       




    simple4.js:
    Java代碼
    1. Simple = function() {  
    2.     var northPanel, southPanel, eastPanel, westPanel, centerPanel;  
    3.     return {  
    4.         init : function() {  
    5.             var mainLayout = new Ext.BorderLayout(document.body, {  
    6.                 north: {   
    7.                     split: true, initialSize: 50   
    8.                 },   
    9.                 south: {   
    10.                     split: true, initialSize: 50   
    11.                 },   
    12.                 east: {   
    13.                     split: true, initialSize: 100   
    14.                 },   
    15.                 west: {   
    16.                     split: true, initialSize: 100   
    17.                 },   
    18.                 center: {   
    19.                 }  
    20.             });  
    21.             mainLayout.beginUpdate();  
    22.             mainLayout.add('north', northPanel = new Ext.ContentPanel('north-div', {   
    23.                 fitToF  
    24.  

    zhuan:http://programming.javaeye.com/blog/167808

    posted on 2009-07-09 09:34 找個(gè)美女做老婆 閱讀(4855) 評(píng)論(0)  編輯  收藏


    只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     

    導(dǎo)航

    統(tǒng)計(jì)

    公告

    本blog已經(jīng)搬到新家了, 新家:www.javaly.cn
     http://www.javaly.cn

    常用鏈接

    留言簿(6)

    隨筆檔案

    文章檔案

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 亚洲自偷自拍另类12p| 免费日本黄色网址| 在线观看亚洲人成网站| 久久久久久久久久免免费精品| 日韩人妻无码免费视频一区二区三区| 亚洲永久在线观看| 日韩精品无码人妻免费视频| 亚洲欧美日韩综合久久久| 四虎成人免费网址在线| 国产AV无码专区亚洲AV蜜芽| 免费国产怡红院在线观看| 青青草国产免费国产是公开| 在线观看国产区亚洲一区成人| 久久精品无码专区免费| 久久精品国产亚洲av成人| 猫咪免费人成网站在线观看| 亚洲三级在线免费观看| 日本特黄特黄刺激大片免费| 特级aa**毛片免费观看| 亚洲欧洲日产国码无码网站| 99精品视频在线视频免费观看| 亚洲国产成人精品无码区在线网站| 久久不见久久见免费影院| 国产精品亚洲综合一区在线观看| 亚洲伊人久久成综合人影院| 可以免费观看的国产视频| 亚洲中文字幕无码av在线| 性做久久久久免费观看| 97超高清在线观看免费视频| 亚洲电影免费观看| 国产又长又粗又爽免费视频| jzzjzz免费观看大片免费| 4444亚洲国产成人精品| 日本久久久免费高清| 在线看片免费人成视频久网下载| 亚洲神级电影国语版| 免费a级黄色毛片| 99爱在线观看免费完整版| 亚洲1区2区3区精华液| 亚洲色欲久久久综合网东京热| 99久久精品日本一区二区免费|