2008年12月29日

第 8 章 哭泣吧!現在才開始講基礎問題

8.1. Ext.get

 



ext裡用來獲得Element的一個函數,用途還算比較廣,可以透過不少途徑獲得咱們需要的Element,而這個Element包括很多有趣的功能。



Element跟document.getElementById("myDiv")得到的dom對象是不一樣的,雖然你還可以使用老模式獲得指定id的元素,但那樣就失去了ext提供的各種常用操作,動畫啦,定位啦,css啦,事件啦,拖拽啦。其實也不用擔心,即便使用了Ext.get()獲得了 myDiv,還是可以直接訪問document.getElementById()應該得到的部分,而且挺簡單的,Ext.get().dom就可以了。



下面讓偶們來看看這些基本的功能會是咋樣呢?



   1.



      先獲得一個Element



      var myDiv = Ext.get('myDiv');



      這裡我們傳入的是一個id,你可以在html裡看到<div id="myDiv"></div>,然後我們用Ext.get('myDiv')從html裡取得這個div,然後封裝成Element對象,現下這個對象就已經放到緩存中了,以後再用的時候就更快撒。

   2.



      最吸引眼球的是動畫效果,所以我們先動兩下。



      myDiv.hightlight();



      紅色高亮,然後漸退。



      myDiv.addClass('red');



      添加自定義CSS類,css裡有.red {background: red;}的定義,這樣myDiv的背景直接變成了紅色。



      myDiv.center();



      myDiv移動的視窗中間,包括垂直和豎直居中。



      myDiv.setOpacity(.25);



      使myDiv半透明

   3.



      再看看怎么才好漸變動畫



      myDiv.setWidth(100);



      這樣可以直接設定myDiv的寬度,是沒有漸變動畫的。



      myDiv.setWidth(100, true);



      這樣就打開了動畫開關,如此簡單就可以看到myDiv在動咯。



      咱們還可以控制動畫的動作,如下



      myDiv.setWidth(100, {

          duration: 2,

          callback: this.highlight,

          scope: this

      });



      duration是間隔,數字越大移動越慢,callback說是動畫完成後執行,但我沒飾演出來,scope是callback執行的範圍。



動畫沒法截圖,還是看看lingo-sample/1.1.1/08-01.html,lingo-sample/2.0/08-01.html吧,四個按鈕可以讓myDiv在視窗裡亂動,哈哈。

8.2. 要是我們想一下子獲得一堆元素咋辦?

 



現下像css那樣的批量選擇模式真的很流行,ext裡也沒有落伍,一定會趕這個潮流。



   1.



      選擇所有<P>元素



      現下我們要獲得所有<P>元素,然後讓他們都閃一下。



      Ext.select("p").highlight();



   2.



      按照css的class選擇



      首先我們有幾個div,都使用class="red",然後我們讓他們都閃一下,嘿嘿嘿~因為highlight()調用比較簡單嘛。



      Ext.select("div.red").highlight();



這種模式在prototype和jquery裡已經發揚光大,而且還光大得很呢,你只需要按照css的選擇模式,就可以得到你需要的集合。這方面其實 jquery頗為神奇,把select用的真是出神入化,可嘆,它對js封裝太狠,你用jquery的時候完全感覺不到自己是在用javascript,這樣接觸原生方法的機會很少,等於把自己綁定到jquery上,最後權衡利弊,只好忍痛割愛了。



批量選擇,見lingo-sample/1.1.1/08-02.html和lingo-sample/2.0/08-02.html。

8.3. DomHelper和Template動態生成html

 



用dom生成html元素一直是頭疼的事情,以前都是聽springside的教導,使用jsTemplate和Scriptaculous的組合。現下到了ext裡面,我們就來看看它自己的實現。

8.3.1. DomHelper用來生成小片段

 



使用DomHelper非常靈活,超簡單就可以生成各種html片段,遇到複雜情況也要求助於它。



大概就是這么用



var list = Ext.DomHelper.append('parent', {tag: 'div', cls: 'red'});



它就是向id=parent這個元素裡,添加一個div元素。



按照文檔裡講的,第二個參數{}裡,除了四個特殊屬性以外都會複製給新生成元素的屬性,這四個特殊屬性是



   1.



      tag,告訴我們要生成一個什麼標籤,div啦,span啦,諸如此類。



      千萬別告訴我到現下你還不知道這些html標籤,中間告訴你多少次先去學學html和css啦?你飛過來的不成?

   2.



      cls,指的是<div class="red"></div>這種標籤中的class屬性,因為class是關鍵字,正常情況下應該寫成className,可jack說className太長了,最後就變成cls了。-_-。



      他就喜歡玩這個,把dataStore寫成ds,DomHelper寫成dh,Element寫成el,ColumnModel寫成cm,SelectionModel是sm。唉,發明的專業名詞縮寫好多呀。

   3.



      children,用來指定子節點,它的值是一個數組,裡邊包含了更多節點。

   4.



      html,對應innerHTML,覺得用children描述太煩瑣,直接告訴節點裡邊的html內容也是一樣。



DomHelper除了append還有幾個方法,指定將新節點添加到什麼位置。



為了比對效果,先放一個初始頁面。



原始的html是這樣的。一個div下有4個節點,其中第三個子節點下還有自己的子節點。



<div id="parent" style="border: 1px solid black;padding: 5px;margin: 5px;background: lightgray;">

  <p id="child1">child1</p>

  <p id="child2">child2</p>

  <div id="child3">

    <p id="child5">inner child</p>

  </div>

  <p id="child3">child4</p>

</div>



   1.



      append是將新節點放到指定節點的最後。



      Ext.DomHelper.append('parent', {tag: 'p', cls: 'red', html: 'append child'});



   2.



      insertBefore,新節點插入到指定節點前面。



      Ext.DomHelper.insertBefore('parent', {tag: 'p', cls: 'red', html: 'insert before child'})



   3.



      insertAfter,新節點插入到指定節點後面。



      Ext.DomHelper.insertAfter('parent', {tag: 'p', cls: 'red', html: 'insert before child'})



   4.



      overwrite,會替換指定節點的innerHTML內容。



      Ext.DomHelper.overwrite('child3', {tag: 'p', cls: 'red', html: 'overwrite child'})



閑來無聊,也看一看children這個屬性的用法。



Ext.DomHelper.append('parent', {

    tag: 'ul',

    style: 'background: white;list-style-type: disc;padding: 20px;',

    children: [

        {tag: 'li', html: 'li1'},

        {tag: 'li', html: 'li2'},

        {tag: 'li', html: 'li3'}

    ]

});



這樣就在parent裡添加了一個ul標籤,ul裡包含三個li。呵呵~炫啊。



代碼見lingo-sample/1.1.1/08-03.html和lingo-sample/2.0/08-03.html。

8.3.2. 批量生成還是需要Template模板

 



場景類比︰目前有三男兩女的json數據,要輸出成html顯示出來。



var data = [

    ['1','male','name1','descn1'],

    ['2','female','name2','descn2'],

    ['3','male','name3','descn3'],

    ['4','female','name4','descn4'],

    ['5','male','name5','descn5']

];



照搬grid時的測試數據呢,嘿嘿。只不過這次我們用的不再是ds,cm,grid的模式解析輸出,而是用模板自己定義輸出的格式。



首先要定義一個模板



var t = new Ext.Template(

    '<tr>',

        '<td>{0}</td>',

        '<td>{1}</td>',

        '<td>{2}</td>',

        '<td>{3}</td>',

    '</tr>'

);

t.compile();



索引從0開始,一共4個元素。然後在用的時候,這樣子。



for (var i = 0; i < data.length; i++) {

    t.append('some-element', data[]);

}



這段代碼對應html中的一個表格,id="some-element"是tbody的id,我們使用模板為table增添了四行。



<table border="1">

    <tbody id="some-element">

        <tr>

            <td>id</td>

            <td>sex</td>

            <td>name</td>

            <td>descn</td>

        </tr>

    </tbody>

</table>



最終的顯示結果就是包含五行數據的表格︰



定義模板的時候,可以使用Ext.util.Format裡的工具方法,對數據進行格式化。常用的就是trim去掉收尾空格和ellipsis(10),ellipsis判斷,當字符長度超過10時,自動截斷字元串並在末尾添加省略號,很常用的功能哩。



在模板裡使用這些函數的話也很簡單,不過我不說,你還是不知道,嘿嘿



var t = new Ext.Template(

    '<tr>',

        '<td>{0}</td>',

        '<td>{1:trim}</td>',

        '<td>{2:trim}</td>',

        '<td>{3:ellipsis(10)}</td>',

    '</tr>'

);

t.compile();



如此這般,冒號加函數名稱就可以實現我們的願望了。



可惜人算終不如天算,jack再神奇,也不可能考慮到所有的可能性,比如現下我們就想根據性別不同顯示圖片,jack怕是想破了腦袋,也想不出這種可能來,所以呢,他干脆不想了,而是給咱們留了一個自定義函數的界面。



var t = new Ext.Template(

    '<tr>',

        '<td>{0}</td>',

        '<td>{1:this.renderSex}</td>',

        '<td>{2:trim}</td>',

        '<td>{3:ellipsis(10)}</td>',

    '</tr>'

);

t.renderSex = function(value) {

    if (value == 'male') {

        return "<span style='color:red;font-weight:bold;'>紅男</span><img src='user_male.png' />";

    } else {

        return "<span style='color:green;font-weight:bold;'>綠女</span><img src='user_female.png' />";

    }

};

t.compile();



顯示的紅男綠女,就像我們預想的那樣呈現下我們眼前了。



你可以從lingo-sample/1.1.1/08-05.html和lingo-sample/2.0/08-05.html看到這些例子,實際上,這兩個檔案的內容是完全相同的