欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  web前端

用jQuery打造TabPanel效果代码_jquery

程序员文章站 2022-05-20 15:01:50
...
如大量信息查看,当网页多窗口框架等都会用到,现在网上基于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
    相关标签: jQuery TabPanel