Java學習

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

           

          EXT學習資料

          EXT學習資料
          EXT簡介
          無論你是Ext庫的新手,抑或是想了解Ext的人,本篇文章的內容都適合你。本文將簡單地介紹Ext的幾個基本概念,和如何快速地做出一個動態的頁面并運行起來,假設讀者已具備了一些JavaScript經驗和初級了解HTML Dom。
          目錄
          • 1 下載Ext
          • 2 開始!
          • 3 Element:Ext的核心
          • 4 獲取多個DOM的節點
          • 5 響應事件
          • 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
          如果你未曾下載過,那應從這里下載最新版本的Ext http://extjs.com/downloads 。
          針對你的下載需求,有幾個不同的彈性選項。通常地,最穩定的版本,是較多人的選擇。下載解包后,那個example文件夾便是一個探索Ext的好地方!
          開始!
          Download Example File
          • IntroToExt.zip

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

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

          加載好頁面,代碼依然會執行,不過區別是,包含alert()的function是已定義好的,但它不會立即地被執行,是分配到按鈕的單擊事件 中。用淺顯的文字解釋,就是:獲取ID為'myDottom'元素的引用,監聽任何發生這個元素上被單擊的情況,并分配一個function,以準備任何 單擊元素的情況。
          正路來說,Element.select也能做同樣的事情,即作用在獲取一組元素上。下一例中,演示了頁面中的某一段落被單擊后,便有彈出窗口:
          Java代碼
          1. Ext.onReady(function() {  
          2.     Ext.select('p').on('click', function() {  
          3.         alert("You clicked a paragraph");  
          4.     });  
          5. });  

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

          到目前為止,我們已經知道如何執行某個動作。但當事件觸發時,我們如何得知這個event handler執行時是作用在哪一個特定的元素上呢?要明確這一點非常簡單,Element.on方法傳入到even handler的function中(我們這里先討論第一個參數,不過你應該瀏覽API文檔以了解even handler更多的細節)。在我們之前的例子中,function是忽略這些參數的,到這里可有少許的改變,——我們在功能上提供了更深層次的控制。必 須先說明的是,這實際上是Ext的事件對象(event object),一個跨瀏覽器和擁有更多控制的事件的對象。例如,可以用下列的語句,得到這個事件響應所在的DOM節點:
          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節點,所以我們首先將其轉換成為EXT的Elemnet元素,然后執行欲完成的事件,這個例子中,我們看見段落是高亮顯示的。
          使用Widgets
          (Widget原意為“小器件”,現指頁面中UI控件)
          除了我們已經討論過的核心JavaScript庫,當前的Ext亦包括了一系列的最前端的JavaScirptUI組件庫。文本以一個常用的widget為例子,作簡單的介紹。
          MessageBox
          比起略為沉悶的“HelloWolrd”消息窗口,我們做少許變化,前面我們寫的代碼是,單擊某個段落便會高亮顯示,現在是單擊段落,在消息窗口中顯示段落內容出來。
          在上面的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. });  

          這里有些新的概念需要討論一下。在第一行中我們創建了一個局部變量(Local Variable)來保存某個元素的引用,即被單擊的那個DOM節點(本例中,DOM節點指的是段落paragrah,事因我們已經定義該事件與< p>標簽發生關聯的了)。為什么要這樣做呢?嗯...觀察上面的代碼,我們需要引用同一元素來高亮顯示,在MessageBox中也是引用同一元素 作為參數使用。
          一般來說,多次重復使用同一值(Value)或對象,是一個不好的方式,所以,作為一個具備良好OO思維的開發者,應該是將其分配到一個局部變量中,反復使用這變量!
          現在,為了我們接下來闡述新概念的演示,請觀察MessageBox的調用。乍一看,這像一連串的參數傳入到方法中,但仔細看,這是一個非常特別 的語法。實際上,傳入到MessageBox.show的只有一個參數:一個Object literal,包含一組屬性和屬性值。在Javascript中,Object Literal是動態的,你可在任何時候用{和}創建一個典型的對象(object)。其中的字符由一系列的name/value組成的屬性,屬性的格式 是[property name]:[property value]。在整個Ext中,你將會經常遇到這種語法,因此你應該馬上消化并吸收這個知識點!
          使用Object Literal的原因是什么呢?主要的原因是“可伸縮性(flexibility)”的考慮",隨時可新增、刪除屬性,亦可不管順序地插入。而方法不需要 改變。這也是多個參數的情況下,為最終開發者帶來不少的方便(本例中的MessageBox.show())。例如,我們說這兒的foo.action方 法,有四個參數,而只有一個是你必須傳入的。本例中,你想像中的代碼可能會是這樣的foo.action(null, null, null, 'hello').,若果那方法用Object Literal來寫,卻是這樣, foo.action({ param4: 'hello' }),這更易用和易讀。
          Grid
          Grid是Ext中人們最想先睹為快的和最為流行Widgets之一。好,讓我們看看怎么輕松地創建一個Grid并運行。用下列代碼替換ExtStart.js中全部語句:
          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.     });  

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

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

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

          <input type="button" id="oKButton" value="OK" />
          接著,我們加入這些處理交換數據的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. });  

          這種模式看起來已經比較熟悉了吧!先獲取按鈕元素,加入單擊事件的監聽。在事件處理器中(event handler),我們使用一個負責處理Ajax請求、接受響應(Response)和更新另一個元素的Ext內建類,稱作UpdateManager。 UpdateManager可以直接使用,或者和我們現在的做法一樣,通過Element的load方法來引用(本例中該元素是id為“msg“的 div)。當使用Element.load方法,請求(request)會在加工處理后發送,等待服務器的響應(Response),來自動替換元素的 innerHTML。簡單傳入服務器url地址,加上字符串參數,便可以處理這個請求(本例中,參數值來自“name”元素的value),而text值 是請求發送時提示的文本,完畢后顯示那個msg的div(因為開始時默認隱藏)。當然,和大多數Ext組件一樣,UpdateManager有許多的參數 可選,不同的Ajax請求有不同的方案。而這里僅演示最簡單的那種。
          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>  

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

          下一步是?
          現在你已經一睹Ext其芳容,知道她大概能做些什么了。下面的資源有助您進一步深入了解:
          EXT源碼概述
          揭示源代碼
          Javascript是一門解釋型的語言,意味著在運行之前代碼是沒有經過編譯的。按照這種理論,在你網站上所發播的Ext代碼是我們看的懂的 (human-readible)。我這里說“理論上”,是因為實際情況中,很多源代碼是經過某些自動化步驟的處理,生成很小幾行的文件最終發布的,通過 剔除空白符號和注釋,或混淆等的方法,以減小文件大小。
          仔細看看EXT標準源碼ext-core.js,你會發現這是一段超長的源碼。這是剛才提及的自動化步驟生成的結果--對瀏覽器來說不錯!可是對于我們是難以閱讀的。
          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文件), 我會發現是全部已格式化好的源代碼。這個文件是配合調時器所使用的,像Firebug的工具能夠可以讓你一步一步地、一行一行地調試代碼。你也會發現文件 的體積將近大了一倍之多,這便是沒有壓縮或混淆的緣故。
          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;  

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

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

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

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

          先看看一份html文檔,比較精簡。并附有詳細說明:
          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>  

          開頭的兩行聲明了文檔的類型。程序可以不用doctype,但是這樣的話瀏覽器可能默認其為Quirks怪僻類型,會導致處理跨瀏覽器這一問題上出現差異。

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

          applayout.js這個文件就是我們的程序,緊跟著的是本地化的腳本,這里可以換成Extjs翻譯好的版本
          跟著我們開始分配事件句柄(event handler),使得在文檔全部加載完畢后,程序就可以初始化(運行)。
          下面的這一行:
          Ext.onReady(myNameSpace.app.init, myNameSpace.app);
          可這樣說:當文檔全部加載完畢,就運行myNameSpace.app的init方法,規定的作用域是myNameSpace.app。
          然后是標題,頭部的結尾,body(當前空)和結束標簽。
          文檔的解說就說到這兒了。
          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. // 創建命名空間  
          11. Ext.namespace('myNameSpace');  
          12.    
          13. // 創建應用程序  
          14. myNameSpace.app = function() {  
          15.     // 元素還沒創建,未能訪問  
          16.    
          17.     // 私有變量  
          18.    
          19.     // 私有函數  
          20.    
          21.     // 公共空間  
          22.     return {  
          23.         // 公共的屬性,如,要轉換的字符串  
          24.         // 公共方法  
          25.         init: function() {  
          26.             alert('應用程序初始化成功。');  
          27.         }  
          28.     };  
          29. }(); // 程序底部  
          30.    

          // 文件底部
          文件最開始的幾行是注釋,說明該文件的主要內容,作者,作者相關的資訊。沒有任何注釋的程序也可以正常的運行,-但請記住:每次寫的程序要容易給 人看得懂的 Always write your application as if you would write it for another.當你回頭看你幾個月前寫的代碼,發現你根本不記得自己寫過什么的時候,就會明白這個道理,并養成編碼的好習慣。接著是要指向你服務器的填 充圖片,如不指定則默認extjs.com。每次運行程序的時候都訪問extjs.com,不推薦這樣,應該先修改這個常量值指向到本地。

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

          整段代碼的重點是,我們創建了 myNameSpace對象的屬性app,其值是一個函數立刻運行之后的返回值。
          如果運行我們的代碼:
          var o = function() {
              return {p1:11, p2:22};
          }();
          實際上我們創建了一個匿名函數(沒有名字的函數),經過解釋(預編譯?)之后讓它立刻運行(注意函數后面的())。最后將函數返回的對象(注意此時是一個object變量)分配到變量o。我們的程序便是這種思路去寫的。
          你可以把私有變量和私有函數直接定義在function和return這兩個聲明之間,但是請切記:此時不能訪問任何html頁面中的元素,那會導致錯誤,因為這段代碼在加載時頁面的head中就運行了,而這時候html頁面中的其它元素還沒有被加載進來。
          另外一方面,函數init,是由匿名函數返回的對象的一個方法而已。它會在文檔全部加載后才運行。換言之整個DOM樹已經是可用的了。
          一切都還好吧~如果能正確運行http://yourserver.com/applayout/applayout.html,不出現什么錯誤的話將出現一個警告。
          接下來是利用這個空白的模板,討論本文的重點。
          公開Public、私有Private、特權的Privileged?
          讓我們加入一些有趣內容到程序中去吧。在頁面applayout.html的body標簽中加入:
          <div id="btn1-ct"></div>
          空白的div會當作按鈕的容器來使用。然后在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. // 創建命名空間  
          11. Ext.namespace('myNameSpace');  
          12.    
          13. // 創建應用程序  
          14. myNameSpace.app = function() {  
          15.     // 元素還沒創建,未能訪問  
          16.    
          17.     // 私有變量  
          18.     var btn1;  
          19.     var privVar1 = 11;  
          20.    
          21.     // 私有函數  
          22.     var btn1Handler = function(button, event) {  
          23.         alert('privVar1=' + privVar1);  
          24.         alert('this.btn1Text=' + this.btn1Text);  
          25.     };  
          26.    
          27.     // 公共空間  
          28.     return {  
          29.         // 公共的屬性,如,要轉譯的字符串  
          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 是私有的。 那意味著在程序外部他們是不能夠被訪問的,而且也不可見。私有函數btn1Handler也是同樣道理。
          另外一個方面,btn1Text是公共變量所以可以被程序外部訪問或者是修改(我們稍后將會演示)。
          函數init是特權的,即是私有變量和公共變量兩者都可以被它訪問到。在本例中,公共變量this.btn1Text和私有函數btn1Handler都能夠被特權函數init所訪問。同時,相對外界來說,它也屬于公共成員的一種。
          Ok,運行看看。能看到左上角的按鈕嗎?很好,點擊它。得到一個privVar1=11的警告。這說明私有函數能訪問私有變量。
          但是在第二個警告中遇到了this.btn1Text=undefined的問題,這好像不應該這樣。個中原因是因為位于事件句柄(event handler)中的變量this沒有正確指向到我們的程序。你需要用scope:this 指明這個作用域(這里的this關鍵字所指示的scope應該是btn1變量):
          Java代碼
          1. btn1 = new Ext.Button('btn1-ct', {  
          2.       text: this.btn1Text  
          3.     , handler: btn1Handler  
          4.     , scope: this  
          5. });  

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

          // 文件底部
          這代碼是用來干什么的呢?首先它創建了我們的程序對象然后改變(重寫)公共變量btn1Text的值。運行后將看到按鈕上文字的變化。

          把文本都放到公共變量,以便于以后的國際化翻譯工作,而不需要修改程序的內部代碼。
          當然你也可以將其它的值例如尺寸、樣式、等等的總之是可自定義的選項都放到公共變量中。免于在數千行代碼之中為查找某個顏色而費勁。
          重寫(Overriding)公共函數
          接著更改一下代碼,讓它讀起來是這樣的:
          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('錯誤: "' + e.message + '" 發生在行: ' + e.lineNumber);  
          13.         }  
          14.     }  
          15. });  


          // end of file
          我們這里將init重寫了一篇,主要是在原來代碼的基礎上加入異常控制,以便能夠捕獲異常。試運行一下看還有沒有其它的變化?
          嗯 是的,出現了btn1Handler 未定義的錯誤。這是因為新的函數雖然嘗試訪問私有變量但它實際是不允許的。正如所見,原init是特權函數可訪問私有空間,但新的init卻不能。之所以 不能訪問私有空間,是因為:禁止外部代碼No code from outside,哪怕是嘗試重寫特權方法。
          DomQuery基礎
          本教程旨在為讀者了解怎樣利用單例對象Ext.DomQuery,瀏覽穿梭于DOM樹之中和獲取對象,提供一個起點。
          DomQuery基礎
          DomQuery的select函數有兩個參數。第一個是選擇符字符(selector string )而第二個是欲生成查詢的標簽ID(TAG ID)。
          本文中我準備使用函數“Ext.query”但讀者須謹記它是“Ext.DomQuery.select()”的簡寫方式。
          這是要入手的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
          假設我想獲取文檔內所有的“span”標簽:
          Java代碼
          1. // 這個查詢會返回有兩個元素的數組因為查詢選中對整個文檔的所有span標簽。  
          2. Ext.query("span");   
          3. // 這個查詢會返回有一個元素的數組因為查詢顧及到了foo這個id。  
          4. Ext.query("span", "foo");  
          5. 注意剛才怎么傳入一個普通的字符串作為第一個參數。   
          6. 按id獲取標簽,你需要加上“#”的前綴:   
          7. // 這個查詢會返回包含我們foo div一個元素的數組!  
          8. Ext.query("#foo");  
          9. 按class name獲取標簽,你需要加上“.”的前綴:   
          10. /*這個查詢會返回有一個元素的數組, 
          11. 包含與之前例子一樣的div但是我們使用了class name來獲取*/  
          12. Ext.query(".foo");  
          13. 你也可以使用關鍵字“*”來獲取所有的元素:   
          14. // 這會返回一個數組,包含文檔的所有元素。  
          15. Ext.query("*");  
          16. 要獲取子標簽,我們只須在兩個選擇符之間插入一個空格:   
          17. // 這會返回有一個元素的數組,包含p標簽的div標簽   
          18. Ext.query("div p");  
          19. // 這會返回有兩個元素的數組,包含span標簽的div標簽   
          20. Ext.query("div span");  
          21.   
          22. 還有三個的元素選擇符,待后續的教程會敘述。 ""   
          23. 如果朋友你覺得這里說得太簡單的話,你可以選擇到DomQuery 文檔看看,可能會有不少收獲:)   
          24. 第二部分:屬性選擇符Attributes selectors   
          25. 這些選擇符可讓你得到基于一些屬性值的元素。屬性指的是html元素中的href, id 或 class。   
          26. // 我們檢查出任何存在有class屬性的元素。  
          27. // 這個查詢會返回5個元素的數組。  
          28. Ext.query("*[class]"); // 結果: [body#ext-gen2.ext-gecko, div#bar.foo, span.bar, div#foo.bar, span.bar]  
          29. 現在我們針對特定的class屬性進行搜索。   
          30. // 這會得到class等于“bar”的所有元素  
          31. Ext.query("*[class=bar]");  
          32.    
          33. // 這會得到class不等于“bar”的所有元素  
          34. Ext.query("*[class!=bar]");  
          35.    
          36. // 這會得到class從“b”字頭開始的所有元素  
          37. Ext.query("*[class^=b]");  
          38.    
          39. //這會得到class由“r”結尾的所有元素  
          40. Ext.query("*[class$=r]");  
          41.    
          42. //這會得到在class中抽出“a”字符的所有元素  
          43. Ext.query("*[class*=a]");  
          44. 第三部分: CSS值元素選擇符  
          45. 這些選擇符會匹配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.    我是一個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. 基于這個CSS的顏色值我們不會作任何查詢,但可以是其它的內容。它的格式規定是這樣的:   
          67. 元素{屬性 操作符 值}   
          68. 注意我在這里是怎么插入一個不同的括號。   
          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”開始的元素  
          83. Ext.query("*{color^=yel}"); // [a www.extjs.com]  
          84.    
          85. // 獲取所有顏色屬性是以“ow”結束的元素  
          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. 第四部分:偽類選擇符Pseudo Classes selectors   
          92. 仍然是剛才的網頁,但是有所不同的只是新加上了一個UL元素、一個TABLE元素和一個FORM元素,以便我們可以使用不同的偽類選擇符,來獲取節點。   
          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]  

          擴展EXT組件
          要創建的擴展是一個在文字前面能夠顯示圖標的這么一個Ext.form.Combobox。將其中一個功能舉例來說,就是要在一塊選擇里,國家名稱連同國旗一并出現。
          我們先給擴展起個名字,就叫Ext.ux.IconCombo。
          文件的創建
          首要的步驟是準備好開發中將會使用的文件。需下列文件:
          • iconcombo.html: 新擴展將會使用的 html markup
          • iconcombo.js: 程序javascript代碼
          • Ext.ux.IconCombo.js: 擴展的javascript文件
          • Ext.ux.IconCombo.css: 擴展樣式表
          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. 該文件來自教程Ext程序規劃入門 的輕微修改。   
          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. // 創建程序  
          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. 我們在這個文件中創建IconCombo,以便可以進行擴展和測試。   
          69. Ext.ux.IconCombo.js  
          70. // Create創建用戶的擴展(User eXtensions namespace (Ext.ux))  
          71. Ext.namespace('Ext.ux');  
          72.    
          73. /** 
          74.   * Ext.ux.IconCombo 擴展類 
          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 配置項參數 
          83.   */  
          84. Ext.ux.IconCombo = function(config) {  
          85.    
          86.     // 調用父類的構建函數  
          87.     Ext.ux.IconCombo.superclass.constructor.call(this, config);  
          88.    
          89. } // Ext.ux.IconCombo構建器的底部  
          90.    
          91. // 進行擴展  
          92. Ext.extend(Ext.ux.IconCombo, Ext.form.ComboBox, {  
          93.    
          94. }); // 擴展完畢  
          95.    
          96. // 文件底部  
          97. 運行到這一步,實際這是一個沒有對Ext.form.ComboBox新加任何東西的空擴展。我們正是需要這個完成好的空擴展,再繼續下一步。   
          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. 路徑可能根據你所在的國旗放置目錄有所不同。國旗的資源可在here下載。   
          109. Let's go  
          110. So far so good!如果你瀏覽iconcombo.html應該會發現一個包含三個選項的標準combo,而德國的那個是選中的...是吧?不過還沒有圖標...   
          111. 現在正是開始工作。在調用父類構建器之后加入下列行:   
          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. 在這一步,我們將默認combox box的模版重寫為iconClsField模版。   
          122. 現在加入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. 不錯!可以測試一下了,刷新的頁面,還好吧!?嗯,列表展開時那些漂亮的圖標就出來了。。還有。。我們不是要在關閉時也出現圖標的嗎?   
          130. 在構建器中加入創建模版的過程:   
          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的偵聽器,用于調整元素樣式和創建國旗的div容器。如后按照下列方式進行擴展:   
          142. // 進行擴展  
          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. }); // 擴展完畢  
          158. 新增 setIconCls函數并重寫setValue函數。我們還是需要父類的setValue的方法來調用一下,接著再調用setIconCls的函數。最后,我們應該在文件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. 最后再刷新一下,如果一切順利,那這個就是新的Ext.ux.IconCombo擴展! 希望你能在此基礎上擴展更多的組件!   
          168. 謝謝Brian Moeskau提醒,使得能進一步精簡Ext.ux.IconCombo 代碼,才稱得上最終版本。最終代碼和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布局對于建立WEB程序尤為有用。關于布局引擎(layout engine),區域管理器(region manager)的教程將分為幾部分,本文是第一篇,為您介紹如何創建區域,如何增加版面到這些區域。
          布局引擎(layout engine)這一功能早已在EXT前個ALPHA實現了。 Jack Slocum對于怎樣環繞某一區域,給與指定區域管理的策略,和建立界面的問題,在他的第一、第二篇關于跨瀏覽器的WEB2.0布局功能的博客中,進行過 討論。定義一個DOM元素的邊界(edge),使之一個布局的邊框(border)--這種做法使得創建“富界面”客戶端UI的開發更進一大步。
          布局管理器(layout manager)負責管理這些區域。布局管理的主要的用戶組件是BorderLayout類。該類為EXT開發富界面的程序提供了一個切入點。 Layout的含意是劃分好一些預定的區域。可用的區域分別有south, east, west, north,和center。每一個BorderLayout對象都提供這些區域但只有center要求必須使用的。如果你在單獨一個區域中包含多個面 板,你可通過NestedLayoutPanel 類套嵌到BorderLayout 實例中。
          注意事項:本教程的每個文件都是.html和.js格式的。教程每一步都有演示,你也可以下載這些文件在編輯器(zip格式提供在這里)中看看發生什么事。
          面板(Panel)是區域管理(region management)的另外一個組件。面板提供了這么一個地方,可為您的EXT器件(widget)、加載的HTML,嵌入的IFrames、或者是你 日常在HTML頁面上擺放的隨便一樣東西。NestedLayoutPanel也是一個面板,只不過用于鏈接多個BorderLayout的區域,其它的 面板包括內容面板 ContentPanel,Grid面板 GridPanel,和Tree面板 TreePanel。
          簡單的例子
          下面的layout包含 north, south, east, west,和center的區域,而且每個區域包含一個ContentPanel,各區域之間使用得了分隔條分割開。
          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. 這是一個非常基本的layout,只是分配了東南西北中間的區域、分隔條、設置一下初始尺寸,并最遲定義中間區域。本例中, BorderLayout被綁定到"document.body"這個DOM元素,其實BorderLayout還可以綁定到任何一個封閉的DOM元素。定義好BorderLayout之后,我們加入ContentPanel對象(基于本例)。  
          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();  

          當前的例子是將ContentPanel加入到所有區域中。由調用mainLayout.beginUpdate()開始。 beginUpdate ()告訴BorderLayout對象在執行endUpate()方法之前,先不要對加入的對象排版布局。這樣的好處是避免了ContentPanel有 對象加入時,導致UI的刷新,改進了整體的用戶體驗。執行beginUpdate()之后,加入五個ContentPanel對象到區域。所有的 ContentPanel對象(除中間的那個外),都設置是可關閉的(closbale)。所有的ContentPanel對象也都設置為自動適配它們的 父元素。最后執行endUpdate()渲染layout。
          InternetExploer注意事項:BorderLayout所容納的元素必須有一個SIZE以便正確渲染。典型地你無須為 document.body 指明size,因為document.body通常是有size的了(大多數情況,-除非你在瀏覽器上什么也看不到)。但是如果你將layout連同容器 放到現有的web頁面上(‘可能是DIV),那么DIV的size應該先指明以便正確渲染。如下列顯示正常:
          好,讓我們趁熱打鐵,看看完整的layout是怎樣的。假設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);  

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


             
             
              

              
              
              



             


             

             

             


             

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




          除此之外,還可以利用ContentPanel對象帶有的function加載數據。可用的方法有幾種,這里我們使用其中兩 種:setContent() 與 setUrl()。setContent()允許您直接從JavaScipt程序中插入HTML。setUrl(),允許您從服務端得到數據加入 ContentPanel中。
          我們原來的例子中,ContentPanel對象創建的時候是匿名的(anonymous)。這沒問題,但要引用它們,你需要遍歷區域管理器所分配的對象以獲得引用的對象。這不是最好的辦法,所有我的做法是分配一個變量給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);  

          我們現在從現有的頁面動態加載內容。但是這里有個問題。若果內容頁面積過大而撐破頁面的話將沒有意義了。我們提供了一些配置屬性以解決這類問題。 當 fitToFrame為true時,就自動配置autoScroll。內容一旦溢出就會出現滾動條。另外一個涉及InternetExploer的問題, 是中間的內容的樣式沒有生效,原因是一些瀏覽器支持動態樣式而一些不支持,要較好地解決上述問題,推薦使用Iframe標簽。
          用IFRAME標簽做布局可靈活地處理,我們準備在DOM中直接操縱IFRAME.這里IFRAME成為面板的容器,以填入中間區域的內容
          設置一下 IFRAME的滾動條并放到中間的頁面。.
          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 找個美女做老婆 閱讀(4853) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          導航

          統計

          公告

          本blog已經搬到新家了, 新家:www.javaly.cn
           http://www.javaly.cn

          常用鏈接

          留言簿(6)

          隨筆檔案

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 温宿县| 象山县| 临海市| 渭源县| 邵东县| 克山县| 平湖市| 科尔| 鱼台县| 公主岭市| 江北区| 西和县| 长丰县| 泌阳县| 沁水县| 酒泉市| 搜索| 新宾| 太保市| 乌拉特前旗| 柯坪县| 巩留县| 钟祥市| 广东省| 德昌县| 钦州市| 明光市| 南宫市| 靖州| 鄂州市| 三门县| 蓝田县| 象州县| 林西县| 炉霍县| 南京市| 凭祥市| 宁陕县| 曲周县| 修水县| 色达县|