2008年12月29日

第 6 章 奔騰吧!讓不同的瀏覽器裡顯示一樣的佈局。

6.1. 有了它,我們就可以擺脫那些自稱ui設計師的人了。

 



對佈局很是不熟,至今為止,也是一直在抄土豆demo裡的BorderLayout,frank的deepcms ProjectTracker裡的ViewPort佈局而已,不過有了佈局,咱們不用再去擺弄frameset了,只需要div就可以做成端端正正的佈局,嗯,只這一點兒就吸引了多少眼球啊。



唉,咱們一起學學關於佈局的用法吧。

6.2. 關於BorderLayout

 



理論上說,把整個視窗切成五塊就夠了吧?東南西北中,east,south,west,north,center其中只有center中間這個部分是必須的,你完全可以把圍繞在它四周的東西當作配角。



這樣說還是太抽象,這個時候效果圖絕對比其他途徑來的直觀。



實際上代碼還是比較乾淨的。



var mainLayout = new Ext.BorderLayout(document.body, {

    north: {

        initialSize: 50

    }, south: {

        initialSize: 50

    }, east: {

        initialSize: 100

    }, west: {

        initialSize: 100

    }, center: {

    }

});



mainLayout.beginUpdate();

mainLayout.add('north', new Ext.ContentPanel('north-div', {

    fitToFrame: true, closable: false

}));

mainLayout.add('south', new Ext.ContentPanel('south-div', {

    fitToFrame: true, closable: false

}));

mainLayout.add('east', new Ext.ContentPanel('east-div', {

    fitToFrame: true, closable: false

}));

mainLayout.add('west', new Ext.ContentPanel('west-div', {

    fitToFrame: true, closable: false

}));

mainLayout.add('center', new Ext.ContentPanel('center-div', {

    fitToFrame: true

}));

mainLayout.endUpdate();



html需要五個div與其對應,div與ContentPanel是一一對應的,請看他們的id。



<div id="north-div">north</div>

<div id="south-div">south</div>

<div id="east-div">east</div>

<div id="west-div">west</div>

<div id="center-div">center</div>



這個其實挺有意思的,你必須先構造一個BorderLayout,指定需要渲染的部分,這裡是document.body,並指定5個部分的初始化大小,然後調用beginUpdate()讓整個佈局先不要刷新,當然我們最後會調用endUpdate()刷新佈局,這樣用戶就獲得了更好的體驗。



beginUpdate()之後,我們立刻使用add方法,向5個部分分別加入Ext.ContentPanel,這些面板的第一個參數是對應 dom的id,後邊是附加的參數,比如fitToFrame:true,它告訴面板在佈局區域改變大小的時候調整自己的大小,然後是 closable:false,這樣用戶就不能點擊關閉按鈕,關閉這個面板。



好了,你也看到了,這五個部分明顯已經分隔開了,使用的時候我們只需要在合適的地方放上合適的東西就行了。



例子在lingo-sample/1.1.1/06-01.html。

6.3. 嗯,不如再看看附加效果

 



其實,即使只能在不同瀏覽器,把一個視窗切成相同的部分,也是足夠了,不過ext帶給我們的不僅僅是如此,讓我們再看看其他部分吧。

<h3 class="title">6.3.1. 先看看split</h3>

 



var mainLayout = new Ext.BorderLayout(document.body, {

    north: {

        initialSize: 50,

        split: true

    }, south: {

        initialSize: 50,

        split: true

    }, east: {

        initialSize: 100,

        split: true

    }, west: {

        initialSize: 100,

        split: true

    }, center: {

    }

});



讓我們給所有區域都加上split:true,看看會有什麼效果?



請注意一點,這並不僅僅是那些邊框變粗了,split讓我們可以自由拖動邊框,讓用戶可以改變各個區域的大小。



當然,我們不會讓用戶為所欲為的,讓我們加上一點點限制,這點兒限制絕對不會讓用戶感到難堪。



var mainLayout = new Ext.BorderLayout(document.body, {

    north: {

        initialSize: 50,

        minSize: 40,

        maxSize: 60,

        split: true

    }, south: {

        initialSize: 50,

        minSize: 40,

        maxSize: 60,

        split: true

    }, east: {

        initialSize: 100,

        minSize: 80,

        maxSize: 120,

        split: true

    }, west: {

        initialSize: 100,

        minSize: 80,

        maxSize: 120,

        split: true

    }, center: {

    }

});



minSize和maxSize讓用戶只能在我們決定的範圍內修改區域的大小,既不會太大,也不會太小。用戶的行為受限,也減少了他們抱怨的機會。嘿嘿,一切盡在掌握中。



例子見lingo-sample/1.1.1/06-02.html

<h3 class="title">6.3.2. 再試試titlebar</h3>

 



var mainLayout = new Ext.BorderLayout(document.body, {

    north: {

        initialSize: 50,

        minSize: 40,

        maxSize: 60,

        titlebar: true,

        split: true

    }, south: {

        initialSize: 50,

        minSize: 40,

        maxSize: 60,

        titlebar: true,

        split: true

    }, east: {

        initialSize: 100,

        minSize: 40,

        maxSize: 60,

        titlebar: true,

        split: true

    }, west: {

        initialSize: 100,

        minSize: 40,

        maxSize: 60,

        titlebar: true,

        split: true

    }, center: {

    }

});



在上面的基礎上,我們加入了titlebar,然後看到的就是這幅情景。



標題欄是空的,要加標題我們另有地方,看看ContentPanel的部分。



mainLayout.beginUpdate();

mainLayout.add('north', new Ext.ContentPanel('north-div', {

    fitToFrame: true, closable: false, title: '北'

}));

mainLayout.add('south', new Ext.ContentPanel('south-div', {

    fitToFrame: true, closable: false, title: '南'

}));

mainLayout.add('east', new Ext.ContentPanel('east-div', {

    fitToFrame: true, closable: false, title: '東'

}));

mainLayout.add('west', new Ext.ContentPanel('west-div', {

    fitToFrame: true, closable: false, title: '西'

}));

mainLayout.add('center', new Ext.ContentPanel('center-div', {

    fitToFrame: true

}));

mainLayout.endUpdate();



經過這些改變,整個佈局就變成了這個樣子。



例子是lingo-sample/1.1.1/06-03.html。

<h3 class="title">6.3.3. 還不夠,還不夠,讓四周的區域可以縮起來</h3>

 



很多軟體都可以這樣哦,看小面板不順眼,就摺疊起來,為中間的工作區留出更多空間喲。就像這樣。



都摺疊上以後就變成這樣。



其實只要加一個屬性就可以了,看看代碼中的collapsible: true造就了現下的盛況。



var mainLayout = new Ext.BorderLayout(document.body, {

    north: {

        initialSize: 50,

        minSize: 40,

        maxSize: 60,

        titlebar: true,

        collapsible: true,

        split: true

    }, south: {

        initialSize: 50,

        minSize: 40,

        maxSize: 60,

        titlebar: true,

        collapsible: true,

        split: true

    }, east: {

        initialSize: 100,

        minSize: 40,

        maxSize: 60,

        titlebar: true,

        collapsible: true,

        split: true

    }, west: {

        initialSize: 100,

        minSize: 40,

        maxSize: 60,

        titlebar: true,

        collapsible: true,

        split: true

    }, center: {

    }

});



你還可以加上collapsedTitle屬性,讓北方和南方區域摺疊之後顯示,這個屬性只在north和south部分有效,因為west和east是垂直的,似乎沒有辦法讓文字旋轉90度顯示,所以我們需要其他方法。



參考網上的模式,是用一個圖片,窄窄高高的圖片,然後把它作為對應css樣式的背景圖,這樣在east和west摺疊的時候就會顯示它們了。讓咱們試驗一下好了。



我們需要設定的css有兩個,west對應左邊,east對應右邊。



.x-layout-collapsed-west {

    background-image: url(user_male.png);

    background-repeat: no-repeat;

    background-position: center;

}



.x-layout-collapsed-east {

    background-image: url(user_female.png);

    background-repeat: no-repeat;

    background-position: center;

}



最後就變成了這樣。



嘿嘿,有意思吧。代碼都在lingo-sample/1.1.1/06-04.html裡呢,你也試試吧。

<h3 class="title">6.3.4. 給這些區域都加上個關閉按鈕</h3>

 



mainLayout.beginUpdate();

mainLayout.add('north', new Ext.ContentPanel('north-div', {

    fitToFrame: true, closable: true, title: '北'

}));

mainLayout.add('south', new Ext.ContentPanel('south-div', {

    fitToFrame: true, closable: true, title: '南'

}));

mainLayout.add('east', new Ext.ContentPanel('east-div', {

    fitToFrame: true, closable: true, title: '東'

}));

mainLayout.add('west', new Ext.ContentPanel('west-div', {

    fitToFrame: true, closable: true, title: '西'

}));

mainLayout.add('center', new Ext.ContentPanel('center-div', {

    fitToFrame: true

}));

mainLayout.endUpdate();



這個部分跟ContentPanel有關,把參數closable改成true就會出現那個小叉叉,按一下這個區域就關上了。



可惜現下還不知道關閉以後再怎么打開,嘿嘿。

<h3 class="title">6.3.5. 用NestedLayoutPanel在五塊中再進行分割,實現更複雜的佈局</h3>

 



我不會用。

6.4. 2.0的ViewPort是完全不同的實現

 



簡單來說,用了ViewPort擺脫先定義BorderLayout,再beginUpdate,endUpdate的麻煩,我們就問了,為什麼事情不能更簡單明了呢,就讓我們看看用2.0解決上頭的五塊是個什麼樣子?



首先html裡的東東不變。



<div id="north-div">north</div>

<div id="south-div">south</div>

<div id="east-div">east</div>

<div id="west-div">west</div>

<div id="center-div">center</div>



剩下的就是代碼了,還是那句話,我們想要在一個地方配置好所有東西,不想東奔西跑,說不定丟了什麼也不知道,維護多個地方的配置簡直是噩夢,2.0啊,我們崇拜你。



var viewport = new Ext.Viewport({

    layout:'border',

    items:[{

        title: 'north',

        region: 'north',

        contentEl: 'north-div',

        split: true,

        border: true,

        collapsible: true,

        height: 50,

        minSize: 50,

        maxSize: 120

    },{

        title: 'south',

        region: 'south',

        contentEl: 'south-div',

        split: true,

        border: true,

        collapsible: true,

        height: 50,

        minSize: 50,

        maxSize: 120

    },{

        title: 'east',

        region: 'east',

        contentEl: 'east-div',

        split: true,

        border: true,

        collapsible: true,

        width: 120,

        minSize: 120,

        maxSize: 200

    },{

        title: 'west',

        region: 'west',

        contentEl: 'west-div',

        split: true,

        border: true,

        collapsible: true,

        width: 120,

        minSize: 120,

        maxSize: 200

    },{

        title: 'center',

        region: 'center',

        contentEl: 'center-div',

        split: true,

        border: true,

        collapsible: true

    }]

});



如果非要挑刺的話,那就是沒有closable的選項了,不過現實誰會去關閉一塊面板啊?至少我不會滴。



現下所有配置都放在一起了,也不用先創建後佈局兩步走,方便呀。

6.5. 稍稍感嘆一下2.0的簡潔吧,讓人吃驚的還在後頭呢。