簡單、通用的JQuery Tab實現

        http://www.cnblogs.com/dvbhack/archive/2009/04/17/portable-interchangeable-jquery-based-tabs.html

        網頁上的空間是寸土寸金,雖然顯示器的分辨率越來越大,可是直到今天,網頁設計中仍然是以至少1024x768 像素的支持爲主,也就是說,每一屏頁面只有區區 955x600像素 的安全尺寸可以用而已。於是,爲了在有限的空間裏容納更多的內容,滑動門式的標籤切換(Tabs)方式越來越受歡迎。通過滑動門技術,可以在同一塊頁面區域內放置數倍的內容。根據用戶的選擇來決定顯示哪一部分。最近我在實際應用中,逐步完善出一種基於jQuery,但是比jQuery UI Tabs 插件更小巧也更通用的簡單 Tabs 實現。

最早的滑動門的技術,一般都是結合 onclick 或者 onmouseover 事件傳遞一個參數給 JS 函數,根據傳遞的參數來決定顯示哪一個標籤。比如:


function showTabs(n) {
  var tabsNumber = 3;
  for (i = 0; i < tabsNumber; i++) {
      if (i == n) {
          document.getElementById("tabPanel-" + i).style.display = "block";
      } else {
          document.getElementById("tabPanel-" + i).style.display = "none";
      }
  }
}

加入有這樣的一個函數,就可以在tab的標題按鈕中設置 onclick = “showTabs(1)”來設置第二塊內容顯示,而其它塊隱藏。

這種方式最大的缺點是:

  1. HTML代碼和JS代碼混合;
  2. 可擴展性差;

儘管可以通過window.onload綁定事件等方式來是實現JS代碼從HTML中分離,也可以把函數改得更復雜以實現通用性。但是總的來說,還是很難做到一處定義到處引用。

後來隨着各種JS類庫的出現,更強大的Tabs出現了,最出名的就是jQuery UI中的tabs插件。一旦加載了jQuery框架和jQuery UI插件,那麼要在頁面中實現Tabs,就變得簡單了許多。首先我們的頁面中的Tabs代碼這樣寫:

<div class="tabs">
    <ul>
        <li><a href="#panel-1">標籤一</a></li>
        <li><a href="#panel-2">標籤二</a></li>
    </ul>
    <div id="panel-1">區域一</div>
    <div id="panel-2">區域二</div>
</div>

注意:這裏的代碼非常乾淨,不含任何的JS代碼或者與文檔結構無關的定義。然後,在head區域,或者在頁面任何地方增加一段js代碼:

$(function() {
    $(".tabs").tabs();
});

就實現了Tabs功能,這行JS代碼執行後,上面的HTML代碼就會變成:

<div class="tabs">
    <ul class="ui-tabs-nav" jquery1239647486215="2">
        <li class="ui-tabs-selected"><a href="#panel-1" jquery1239647486215="8">標籤一</a></li>
        <li><a href="#panel-2" jquery1239647486215="9">標籤二</a></li>
        ></ul>
    <div id="panel-1" class="ui-tabs-panel" jquery1239647486215="4">
        區域一
    </div>
    <div id="panel-2" class="ui-tabs-panel ui-tabs-hide" jquery1239647486215="5">
        區域二
    </div>
</div>

結合我們自己編寫的css,或者jQuery UI 自帶的CSS,就可以實現滑動門效果。並且,由於jQuery的強大,我們可以在頁面中放置多組滑動門,然後一次性設定。

要說明的是,這個地方由於只啓用了jQuery UI 中的 Tabs 插件,因此生成的代碼還是比較乾淨的,只增加了 ui-tabs-xxxx 這幾個相關的css類。如果你同時包含了jQuery UI的其它插件,那麼即使不啓用,也會添加一堆的css定義。而且,jQuery UI Tabs 還提供了非常強大的控制功能,你可以動態地添加 tab,可以隨意更改激活事件,可以定義切換效果,還可以設置默認激活狀態和禁用等。

但是我在實際應用中遇到了一些問題,除了 jQuery UI 自帶的js腳本很大,css不符合實際應用需求外,還有一個最大的問題,你可能已經注意到了,在作爲導航的標籤定義中,每個標籤對應哪一個區域是用鏈接目標來定義的。比如 <a href="#panel-1">標籤一</a>和<div id="panel-1">區域一</div>對應,如果你的標籤和區域沒有對應起來,綁定tabs()就不起作用了。

而且,這種方式來帶來另一個麻煩,就是當我們需要給標籤加上鍊接的時候,沒辦法加。即使你將標籤的激活事件設置爲onmouseover而不是onclick,鏈接也不能實現,因爲鏈接用於指定目標了。這種需求在我們的實際應用中並不是不存在的。比如:

這兩個圖片中的tabs標籤,都要添加到對應的新聞類別或者論壇板塊的鏈接。這時候 jQuery UI的默認綁定就帶來了麻煩。

其實分析一下,我們在實現滑動門的時候,用以下HTML結構就可以滿足需要:

<div class="tabs">
    <ul>
        <li>標籤一</li>
        <li>標籤二</li>
    </ul>
    <div>區域一</div>
    <div>區域二</div>
</div>


藉助 jQuery 庫,我們可以通過 $(".tabs")找到要實現的標籤,然後 .find("li") 來找到要添加事件的元素,綁定事件的時候,我們可以通過該元素在$(".tabs li")集合中的索引值來明確是哪一個標籤被激活,然後對應索引值的panel顯示。代碼類似這樣:


<script type="text/javascript">
    $(function() {
        $(".tabs").find("li").onmouseover(function(e) {
            if (e.target == this) {
                var tabs = $(this).parent().children("li");
                var panels = $(this).parent().parent().children("div");
                var index = $.inArray(this, tabs);
                if (panels.eq(index)[0]) {
                    tabs.removeClass("ui-tabs-selected")
                        .eq(index).addClass("ui-tabs-selected");
                    panels.addClass("ui-tabs-hide")
                        .eq(index).removeClass("ui-tabs-hide");
                }
            }
        });
    });
</script>

這段代碼只使用了兩個css類來處理,並且,自動判斷tabs和panels的對應狀態,假如你有4個tab,但是隻有前三個啓用了,那麼你只需要寫三個panel就可以,第四個panel不存在,則第四個tab自動不生效。

在實際使用中,會遇到一個問題,一般我們會給tab中的文字加鏈接,那麼當鼠標滑過這個tab的時候,如果指到了文字,那麼激發事件的對象有可能是a元素而不是li元素,則事件就不能正確激發。所以我們改進代碼如下:

<script type="text/javascript">
    $(function() {
        $(".ui-tabs-nav > li > a")onmouseover(function(e) {
            if (e.target == this) {
                var tabs = $(this).parent().parent().children("li");
                var panels = $(this).parent().parent().parent().children(".ui-tabs-panel");
                var index = $.inArray(this, tabs);
                if (panels.eq(index)[0]) {
                    tabs.removeClass("ui-tabs-selected")
                        .eq(index).addClass("ui-tabs-selected");
                    panels.addClass("ui-tabs-hide")
                        .eq(index).removeClass("ui-tabs-hide");
                }
            }
        });
    });
</script>

與此對應的HTML結構是:

<div>
    <ul class="ui-tabs-nav">
        <li class="ui-tabs-selected"><a href="/bbs">論壇新帖</a></li>
        <li><a href="/blog">最新博文</a></li>
    </ul>
    <div class="ui-tabs-panel">
      <!--這裏調用最新論壇文章-->
    </div>
    <div class="ui-tabs-panel ui-tabs-hide">
      <!--這裏調用最新博客文章-->
    </div>
</div>

同時,我們有以下的css類定義:

.ui-tabs-nav
{
    /*導航容器定義*/
}
.ui-tabs-nav li
{
    /*默認標籤樣式*/
}
.ui-tabs-nav li.ui-tabs-selected
{
    /*激活的標籤樣式*/
}
.ui-tabs-panel
{
    /*默認的顯示區域樣式*/
}
.ui-tabs-hide
{
    display: none;
}


這樣,就可以根據你的需要,結合自己的css,定製不同樣式的滑動門了。把相應的js代碼放到頁面中,那麼在頁面裏任何地方只要你按照HTML結構編寫了一段html,這段html就會自動變成滑動門。而不用在每個頁面裏單獨指定特定的selector來應用滑動門的tabs()方法。並且,根據需要給你的滑動門標籤添加需要的鏈接,或者不要鏈接(href="#" 或者 href="javascript:void(0)")。

這段滑動門代碼只要具有jQuery core 就可以正常運行,不需要加載jQuery UI。非常簡單,而且很通用,樣式上喜歡怎麼擴展都可以。

具體效果可以參見 http:/www.taihainet.com , 在 臺海網 首頁中,我一共應用了四個樣式共九組滑動門,代碼就只是上面給出的那一段。四個樣式列舉如下:

 
滑動門一:多個搜索表單,暫時只實現兩個,後面三個由於沒有對應的ui-tabs-panel,自動禁用,但是鏈接可以點擊。

 
滑動門二:多塊商務信息區域,其中第三個由於沒有對應的ui-tabs-panel,自動禁用。

 

 
滑動門三:新聞欄目切換,標籤中的文字鏈接到對應的新聞欄目。

 
滑動門四:論壇分板塊帖子調用。標籤中的文字鏈接到對應的論壇板塊。

本文首發自 刀刀博客




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章