首頁  >  文章  >  web前端  >  用jQuery打造TabPanel效果代码_jquery

用jQuery打造TabPanel效果代码_jquery

WBOY
WBOY原創
2016-05-16 18:26:401304瀏覽

如大量信息查看,当网页多窗口框架等都会用到,现在网上基于jquery Tab控件,其实也蛮多了,我以前用过的idtabs,就比较简单实用,也是比较灵活,但是对于复杂情况就要编码多些,太简单了些。还有就是jquery UI的里面的tab控件(没用过,我对jquery ui不太感冒),另外就是近期有点小火的easyui 中的tab控件,最早在javaeye上面看到的,界面还算漂亮,因为之前没开源,所以一直没跟进(好像最近开源了,前几天下载了看看,编码风格有点像prototype,看不出jquery的影子,不知道为什么叫jquery easyui呵呵,因为没太深入去学习,也不好做其他评价)。说了那么多,我们还是回到主题,因为种种原因不得不想着自己开发一个吧。于是就有了这篇,先来看看效果吧。

下图是单网页多窗口框架的效果图

用jQuery打造TabPanel效果代码_jquery 

下图是文末提供调用示例的效果截图。

用jQuery打造TabPanel效果代码_jquery 

大家可以看到了还是使用ExtJs的效果。其实CSS基本上是直接copy它的。我觉得它那个就非常好看,当然实际使用的时候大家有能力完全可以自己样子

第一 我们还是从HTML开始吧

注:我先控件的思路始终是先确定HTML结构,其次是样式,最终才是js实现的事件方法等。

其实看图我们就可以基本确定,tab控件主要有两个部分的html 一个是头,用于放tab选项卡的;另外一个是体,是内容的容器。那么就是两个Div容器,讲tab控件分成了header和body两部分。

其中header部分因为包含多选项卡 所以很容易想到ul +li的配合。来看一下header中的实际html结构

用jQuery打造TabPanel效果代码_jquery 

通过通过其中li即是一个选项卡,第一个a是关闭按钮,第二个a才是实际内容 通过嵌套标签来实现 左右中的背景图片设置(这个做法比较多见的)。当然能够有个好的效果,还是要靠CSS支持。必须对CSS有一定的了解。

Body的结构则更简单就是div嵌套div就就结束了。

第二 CSS样式表

因为CSS是copy EXTJS的我也就不多介绍了。大家可以看代码下载里面的实际代码,如果有问题可以再沟通交流

第三:开始编写JS了

老规矩先来一段完整的JS代码,大概有500行左右的代码,其实我换行比较勤快,实际的代码量其实还是比较少。

复制代码 代码如下:

; (function ($) {
$.fn.tabpanel =function(option){
var dfop ={
items:[], //选项卡数据项 {id,text,classes,disabled,closeable,content,url,cuscall,onactive}
width:500,
height:400,
scrollwidth:100,//如果存在滚动条,点击按钮次每次滚动的距离
autoscroll:true //当选项卡宽度大于容器时自动添加滚动按钮
};
var headerheight=28;
$.extend(dfop, option);
var me =$(this).addClass("x-tab-panel").width(dfop.width);
innerwidth = dfop.width-2;
//构建Tab的Html
var tcs= dfop.autoscroll?"x-tab-scrolling-top":"";
var header = $("
");
var stripwrap = $("
");
var scrollerright = $("");
var scrollerleft = $("");
var ulwrap = $("
    ");
    var stripspacer = $("
    ");
    var litemp =[];
    for(var i=0,l=dfop.items.length; i{
    var item =dfop.items[i];
    builditemlihtml(item,litemp);
    }
    litemp.push("
  • ");
    ulwrap.html(litemp.join(""));
    litemp =null;
    stripwrap.append(ulwrap);
    if(dfop.autoscroll)
    {
    header.append(scrollerright).append(scrollerleft);
    }
    header.append(stripwrap).append(stripspacer);
    var bodyheight=dfop.height-headerheight;
    var bodywrap = $("
    ");
    var body = $("
    ").css({width:innerwidth,height:bodyheight});
    var bodytemp=[];
    for(var i=0,l=dfop.items.length; ivar item =dfop.items[i];
    builditembodyhtml(item,bodytemp);
    }
    body.html(bodytemp.join("")).appendTo(bodywrap);
    me.append(header).append(bodywrap);
    initevents();
    function builditemlihtml(item,parray)
    {
    parray.push("
  • ");
    parray.push("");
    parray.push("");
    parray.push("",item.text,"");
    parray.push("
  • ");
    }
    function builditembodyhtml(item,parray)
    {
    parray.push("
    ");
    parray.push("
    ");
    parray.push("
    ");
    if(item.url){
    parray.push("");
    }
    else if(item.cuscall){
    parray.push("
    ");
    }
    else{
    parray.push(item.content);
    }
    parray.push("
    ");
    }
    function initevents()
    {
    //reset scoller
    resetscoller();
    scollerclick();
    ulwrap.find("li:not(.x-tab-edge)").each(function(e){
    inititemevents(this);
    });
    }
    function inititemevents(liitem)
    {
    liswaphover.call(liitem);
    liclick.call(liitem);
    closeitemclick.call(liitem);
    }
    function scollerclick()
    {
    if(dfop.autoscroll)
    {
    scrollerleft.click(function(e){scolling("left")});
    scrollerright.click(function(e){scolling("right")});
    }
    }
    function resetscoller()
    {
    if(dfop.autoscroll)
    {
    var edge = ulwrap.find("li.x-tab-edge");
    var eleft =edge.position().left;
    var sleft = stripwrap.attr("scrollLeft");
    if( sleft+eleft>innerwidth )
    {
    header.addClass("x-tab-scrolling");
    scrollerleft.css("visibility","visible");
    scrollerright.css("visibility","visible");
    if(sleft>0)
    {
    scrollerleft.removeClass("x-tab-scroller-left-disabled");
    }
    else{
    scrollerleft.addClass("x-tab-scroller-left-disabled");
    }
    if(eleft>innerwidth)
    {
    scrollerright.removeClass("x-tab-scroller-right-disabled");
    }
    else{
    scrollerright.addClass("x-tab-scroller-right-disabled");
    }
    dfop.showscrollnow =true;
    }
    else
    {
    header.removeClass("x-tab-scrolling");
    stripwrap.animate({"scrollLeft":0},"fast");
    scrollerleft.css("visibility","hidden");
    scrollerright.css("visibility","hidden");
    dfop.showscrollnow =false;
    }
    }
    }
    //
    function scolling(type,max)
    {
    //debugger;
    if(!dfop.autoscroll || !dfop.showscrollnow)
    {
    return;
    }
    //debugger;
    //var swidth = stripwrap.attr("scrollWidth");
    var sleft = stripwrap.attr("scrollLeft");
    var edge = ulwrap.find("li.x-tab-edge");
    var eleft = edge.position().left ;
    if(type=="left"){
    if(scrollerleft.hasClass("x-tab-scroller-left-disabled"))
    {
    return;
    }
    if(sleft-dfop.scrollwidth-20>0)
    {
    sleft -=dfop.scrollwidth;
    }
    else{
    sleft =0;
    scrollerleft.addClass("x-tab-scroller-left-disabled");
    }
    if(scrollerright.hasClass("x-tab-scroller-right-disabled"))
    {
    scrollerright.removeClass("x-tab-scroller-right-disabled");
    }
    stripwrap.animate({"scrollLeft":sleft},"fast");
    }
    else{
    if(scrollerright.hasClass("x-tab-scroller-right-disabled") && !max)
    {
    return;
    }
    //left + ;
    if(max || (eleft>innerwidth && eleft-dfop.scrollwidth-20{
    //debugger;
    sleft = sleft+eleft-(innerwidth-38) ;
    scrollerright.addClass("x-tab-scroller-right-disabled");
    // sleft = eleft-innerwidth;
    }
    else
    {
    sleft +=dfop.scrollwidth;
    }
    if(sleft>0)
    {
    if(scrollerleft.hasClass("x-tab-scroller-left-disabled"))
    {
    scrollerleft.removeClass("x-tab-scroller-left-disabled");
    }
    }
    stripwrap.animate({"scrollLeft":sleft},"fast");
    }
    }
    function scollingToli(liitem)
    {
    var sleft = stripwrap.attr("scrollLeft");
    var lleft = liitem.position().left;
    var lwidth = liitem.outerWidth();
    var edge = ulwrap.find("li.x-tab-edge");
    var eleft = edge.position().left ;
    if(lleft{
    sleft +=(lleft-2) ;
    if(sleft{
    sleft=0;
    scrollerleft.addClass("x-tab-scroller-left-disabled");
    }
    if(scrollerright.hasClass("x-tab-scroller-right-disabled"))
    {
    scrollerright.removeClass("x-tab-scroller-right-disabled");
    }
    stripwrap.animate({"scrollLeft":sleft},"fast");
    }
    else{
    if(lleft+lwidth>innerwidth-40)
    {
    sleft = sleft+lleft+lwidth+-innerwidth+40; // 40 =scrollerleft and scrollerrightwidth;
    if(scrollerleft.hasClass("x-tab-scroller-left-disabled"))
    {
    scrollerleft.removeClass("x-tab-scroller-left-disabled");
    }
    //滚到最后一个了,那么就要禁用right;
    if(eleft-(lleft+lwidth+-innerwidth+40){
    scrollerright.addClass("x-tab-scroller-right-disabled");
    }
    stripwrap.animate({"scrollLeft":sleft},"fast");
    }
    }
    liitem.click();
    }
    function liswaphover()
    {
    $(this).hover(function(e){
    if(!$(this).hasClass("x-tab-strip-disabled"))
    {
    $(this).addClass("x-tab-strip-over");
    }
    },function(e){
    if(!$(this).hasClass("x-tab-strip-disabled"))
    {
    $(this).removeClass("x-tab-strip-over");
    }
    });
    }
    function closeitemclick()
    {
    if($(this).hasClass("x-tab-strip-closable"))
    {
    $(this).find("a.x-tab-strip-close").click(function(){
    deleteitembyliid($(this).parent().attr("id"));
    });
    }
    }
    function liclick()
    {
    $(this).click(function(e){
    var itemid = this.id.substr(7);
    var curr = getactiveitem();
    if( curr !=null && itemid == curr.id)
    {
    return;
    }
    var clickitem = getitembyid(itemid);
    if(clickitem && clickitem.disabled)
    {
    return ;
    }
    if(curr)
    {
    $("#tab_li_"+curr.id).removeClass("x-tab-strip-active");
    $("#tab_item_"+curr.id).addClass("x-hide-display");
    curr.isactive =false;
    }
    if(clickitem)
    {
    $(this).addClass("x-tab-strip-active");
    $("#tab_item_"+clickitem.id).removeClass("x-hide-display");
    if(clickitem.url)
    {
    var cururl = $("#tab_item_frame_"+clickitem.id).attr("src");
    if(cururl =="about:blank")
    {
    $("#tab_item_frame_"+clickitem.id).attr("src",clickitem.url);
    }
    }
    else if(clickitem.cuscall && !clickitem.cuscalled)
    {
    var panel = $("#tab_item_content_"+clickitem.id);
    var ret = clickitem.cuscall(this,clickitem,panel);
    clickitem.cuscalled =true;
    if(ret) //如果存在返回值,且不为空
    {
    clickitem.content = ret;
    panel.html(ret);
    }
    }
    clickitem.isactive =true;
    if(clickitem.onactive)
    {
    clickitem.onactive.call(this,clickitem);
    }
    }
    });
    }
    //获取当前活跃项
    function getactiveitem()
    {
    for(var i=0,j=dfop.items.length;i{
    if(dfop.items[i].isactive)
    {
    return dfop.items[i];
    break;
    }
    }
    return null;
    }
    //根据ID获取Item数据
    function getitembyid(id)
    {
    for(var i=0,j=dfop.items.length;i{
    if(dfop.items[i].id == id)
    {
    return dfop.items[i];
    break;
    }
    }
    return null;
    }
    function getIndexbyId(id)
    {
    for(var i=0,j=dfop.items.length;i{
    if(dfop.items[i].id == id)
    {
    return i;
    break;
    }
    }
    return -1;
    }
    //添加项
    function addtabitem(item)
    {
    var chkitem =getitembyid(item.id);
    if(!chkitem){
    var isactive =item.isactive;
    item.isactive =false;
    var lastitem = dfop.items[dfop.items.length-1];
    dfop.items.push(item);
    var lastli = $("#tab_li_"+lastitem.id);
    var lastdiv = $("#tab_item_"+lastitem.id);
    var litemp =[];
    var bodytemp = [];
    builditemlihtml(item,litemp);
    builditembodyhtml(item,bodytemp);
    var liitem = $(litemp.join(""));
    var bodyitem= $(bodytemp.join(""));
    lastli.after(liitem);
    lastdiv.after(bodyitem);
    //事件
    var li = $("#tab_li_"+item.id);
    inititemevents(li);
    if(isactive)
    {
    li.click();
    }
    resetscoller();
    scolling("right",true);
    }
    else{
    alert("指定的tab项已存在!");
    }
    }
    function openitemOrAdd(item,allowAdd)
    {
    var checkitem = getitembyid(item.id);
    if(!checkitem && allowAdd )
    {
    addtabitem(item);
    }
    else{
    var li = $("#tab_li_"+item.id);
    scollingToli(li);
    }
    }
    //移除一个tab 项
    function deleteitembyliid(liid)
    {
    var id= liid.substr(7);
    $("#"+liid).remove();
    $("#tab_item_"+id).remove();
    var index = getIndexbyId(id);
    if(index>=0)
    {
    var nextcur;
    if(index {
    nextcur = dfop.items[index+1];
    }
    else if(index>0){
    nextcur = dfop.items[index-1];
    }
    if(nextcur)
    {
    $("#tab_li_"+nextcur.id).click();
    }
    dfop.items.splice(index,1);
    resetscoller();
    scolling("right",true);
    }
    }
    function resize(width,height)
    {
    if(width ==dfop.width && height ==dfop.height)
    {
    return;
    }
    if(width){ dfop.width=width};
    if(height){ dfop.height =height;}
    innerwidth = width-2;
    bodyheight=dfop.height-headerheight;
    me.css("width",dfop.width);
    header.css("width",innerwidth);
    body.css({width:innerwidth,height:bodyheight});
    for(var i=0,j=dfop.items.length;i{
    var item =dfop.items[i];
    $("#tab_item_"+item.id).css({width:innerwidth});
    $("#tab_item_content_"+item.id).css({width:innerwidth,height:bodyheight});
    }
    resetscoller();
    }
    //设置选项卡项是否disabled
    function setdisabletabitem(itemId,disabled)
    {
    var chitem= getitembyid(itemId);
    if(!chitem || chitem.disabled ==disabled)
    {
    return;
    }
    if(disabled)
    {
    chitem.disabled =true;
    $("#tab_item_"+item.id).addClass("x-tab-strip-disabled");
    }
    else{
    chitem.disabled =false;
    $("#tab_item_"+item.id).removeClass("x-tab-strip-disabled");
    }
    }
    me[0].tab = {
    addtabitem:addtabitem,
    opentabitem:openitemOrAdd,
    resize:resize,
    setdisabletabitem:setdisabletabitem
    };
    };
    $.fn.addtabitem =function(item)
    {
    if(this[0].tab)
    {
    return this[0].tab.addtabitem(item);
    }
    return false;
    }
    $.fn.opentabitem =function(item,orAdd)
    {
    if(this[0].tab)
    {
    return this[0].tab.opentabitem(item,orAdd);
    }
    return false;
    }
    $.fn.resizetabpanel =function(w,h)
    {
    if(this[0].tab)
    {
    return this[0].tab.resize(w,h);
    }
    return false;
    }
    $.fn.setdisabletabitem =function(itemId,disabled)
    {
    if(this[0].tab)
    {
    return this[0].tab.setdisabletabitem(itemId,disabled);
    }
    return false;
    }
    })(jQuery);

    接着我们来一步一步来分析我的实现,开始还是编写jQuery控件的“模板”,关于为什么要这么写,请参考这篇的说明
    复制代码 代码如下:

    ; (function ($) {
    $.fn.tabpanel =function(option){
    };
    )(jQuery);

    接着就是编写默认参数
    复制代码 代码如下:
    var dfop ={
    items:[], //选项卡数据项 {id,text,classes,disabled,closeable,content,url,cuscall,onactive}
    width:500,
    height:400,
    scrollwidth:100,//如果存在滚动条,点击按钮次每次滚动的距离
    autoscroll:true //当选项卡宽度大于容器时自动添加滚动按钮
    };

    默认参数还是比较简单,我已加上了注释,其中就是item数组的项麻烦些,不过我相信大家通过字面的意思就已经知道大半了,我还是描述一下吧:id 即标示,必须唯一、text显示的文本、classes 特定的样式,如效果中的主页,我加了个图标,就通过此属性实现、disabled 是否禁用、closeable 是否可关闭、

    content 和url 和cuscall 三个只要设置其中之一即可,content就是实际的内容html、url标示内容为网页,自动往内容中添加iframe,cuscall则是自定义,即内容显示什么有cuscall执行的结果来决定,可通过此属性来实现异步content内容。

    onactive是指当tab项被激活时触发的事件。 是一个接受item内容的函数,详见demo

    参数设置完了,通过外部传递的参数来更新默认的参数:

    $.extend(dfop, option);

    接着就是构建html的部分,这部分比较长,我就不重复贴代码了。

    当我们把html构建完成之后,就要给html元素添加事件,包括 选项卡的点击事件,左移按钮,右移按钮的点击事件,选项卡的鼠标hover效果事件等。

    复制代码 代码如下:


    function initevents()
    {
    //reset scoller
    resetscoller(); //设置默认是否出现滚动掉
    scollerclick(); //滚动条的点击事件,如果存在的话
    ulwrap.find("li:not(.x-tab-edge)").each(function(e){
    inititemevents(this); //给每个选项卡 添加事件
    });
    }
    function inititemevents(liitem)
    {
    liswaphover.call(liitem); //选项卡的鼠标hover效果
    liclick.call(liitem); //选项卡的点击事件
    closeitemclick.call(liitem); // 点击关闭按钮的事件
    }


    至于事件的实现,其实一个个来做,各个击破也就简单了。主要繁琐在控制滚动按钮的出现和禁用等的处理上,其他点击事件等都比较简单。

    最后就是公开方法,和为了公开这些方法来编写一些内部方法,这个tabpanel自然还是比较简单易用,同时扩展性。大家可以根据实际的需求做些调整,当然现在的功能应该也满足大部分的要求了。

    最后来看一下公开了哪些方法:

    1:动态 新增tab项的方法,即通过js动态新增tab项,这里其实就是对items数据的维护,然后重新调用tabitem的输出html方法,最后单独为其设置事件。简单

    2:选中或者新增。这也是通过js调用的方法,是对上一方法的扩展,即可通过js让某个tab项激活,如果该项不存在则通过参数来新增该选项卡

    3:重新设置tabpanel的大小,即通过js重新设置tabpanel的大小,这个在窗口大小变化时调用,非常实用哦。

    4:设置某项为禁用,通过js方法设置某项tabitem状态为禁用。


    最后大家可以通过 代码 包括之前控件的实例,我已经提供了一个压缩包,但是我更推荐大家实用SVN获取最新代码。因为有的时候一些小的变动我就不发文告知了。

    http://code.google.com/p/xjplugin/downloads/list

    http://xiazai.jb51.net/201005/yuanma/xjPlugin_addtabpanel.rar
    陳述:
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn