• 一个javascript选项卡的进化史


    一、结构

    使用合理的HTML结构是javascript UI组件优雅的最重要条件之一,这里使用dl、dt、dd构建选项卡结构(js罗浮宫讨论成果,见司徒正美:jquery tabs插件

     以下为引用的内容:

    <dl class="artTabs">
    <dt id="tabs"><a href="#tabContent1" class="select">link1</a> <a href="#tabContent2">link2</a> <a href="#tabContent3">link3</a></dt>
    <dd id="tabContent1" style="display:block">tabContent1</dd>
    <dd id="tabContent2">tabContent2</dd>
    <dd id="tabContent3">tabContent3</dd>
    </dl>

    选项卡按钮的锚点都指向内容,这样在脚本与样式失效的情况下仍然能够进行基本的跳转。

    二、编写核心javascript代码

    接下来就是js编写。使用事件代理机制可以更加高效的处理业务,无需循环遍历操作去给每个按钮绑定事件,也能节省内存:

    //// 参数:选项卡按钮外包裹元素, 按钮选中的样式, 初始化选中的按钮索引值(以0开始)
    //在这个例子中就是tabs dt
    var artTabs=function(bar,className,index)
    {
        var gid=function(id){ return document.getElementById(id); };
        var buttons=bar.getElementsByTagName("a");
        var selectButton=buttons[index];
        var showContent=gid(selectButton.href.split('#')[1]);
        
        bar.onclick=function(event){
            event=event||window.event;
            var target=event.target||event.srcElement;
            
            if(target.nodeName.toLowerCase()==='a')
            {
                //更改display
                showContent.style.display='none';
                showContent=gid(target.href.split('#')[1]);
                showContent.style.display='block';
                //更改className;
                selectButton.className='';
                selectButton=target;
                target.className=className;
                return false;
            }
        };
        
    };
    
    window.onload=function()
    {
        artTabs(document.getElementById("tabs"),'select',0);
    }

    还有结合css来开始来隐藏刚开始的元素显示:

    .artTabs { background:#ffffff; }
    .artTabs dt {
        padding:5px 5px 0 5px;
        background:#9FC;
        border-bottom:1px solid red;
    }
    .artTabs dt  a {
        display:inline-block;
    }
    .artTabs dt a.select{
        border-color:#F0F;
        color:green;
        background:#eee;
    }
    .artTabs dd{
        display:none; 最重要
        padding:10px;
        margin:0;
    }

    完整代码如下:

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>无标题文档</title>
    <style>
    .artTabs { background:#ffffff; }
    .artTabs dt {
        padding:5px 5px 0 5px;
        background:#9FC;
        border-bottom:1px solid red;
    }
    .artTabs dt  a {
        display:inline-block;
    }
    .artTabs dt a.select{
        border-color:#F0F;
        color:green;
        background:#eee;
    }
    .artTabs dd{
        display:none;
        padding:10px;
        margin:0;
    }
    
    
    </style>
    <script>
    //// 参数:选项卡按钮外包裹元素, 按钮选中的样式, 初始化选中的按钮索引值(以0开始)
    //在这个例子中就是tabs dt
    var artTabs=function(bar,className,index)
    {
        var gid=function(id){ return document.getElementById(id); };
        var buttons=bar.getElementsByTagName("a");
        var selectButton=buttons[index];
        var showContent=gid(selectButton.href.split('#')[1]);
        
        bar.onclick=function(event){
            event=event||window.event;
            var target=event.target||event.srcElement;
            
            if(target.nodeName.toLowerCase()==='a')
            {
                //更改display
                showContent.style.display='none';
                showContent=gid(target.href.split('#')[1]);
                showContent.style.display='block';
                //更改className;
                selectButton.className='';
                selectButton=target;
                target.className=className;
                return false;
            }
        };
        
    };
    
    window.onload=function()
    {
        artTabs(document.getElementById("tabs"),'select',0);
    }
    
    
    </script>
    
    </head>
    
    <body>
    <dl class="artTabs">
        <dt id="tabs">
       
           <a href="#tabContent1" class="select">Link1</a>
            <a href="#tabContent2"  >Link2</a>
            <a href="#tabContent3"  >Link3</a>
          </dt>
        
          <dd id="tabContent1" style="display:block;">tabContent1</dd>
          <dd id="tabContent2">tabContent2</dd>
          <dd id="tabContent3">tabContent3</dd>
          
          
    </dl>
    </body>
    </html>

    三、优化接口

    是否发现这个刚出炉的选项卡参数有点麻烦?如果要支持鼠标靠近触发怎么办?或者点击选项卡的时候要采用ajax加载填充内容要如何处理回调函数?

    显然我们前面的API设计并不能优雅的处理这些需求,我们改用字面量的方式传入参数,增加一些新接口,如:

     以下为引用的内容:

    var artTabs=function(bar,config){
        var gid=function(id){ return document.getElementById(id); };
        
        config=config||{};
        var bar=typeof bar==='string'?gid(bar):bar,//从这里开始后面的定义都是变量,所有为逗号
        className = config.className || 'select',
        callback=config.callback||function(){ },
        isMouseover=config.isMouseover,
        
        buttons=bar.getElementsByTagName("a"),
        selectButton=buttons[
                config.index||
                function(){
                    var ret=0;
                    for(i=0;i<buttons.length;i++){
                        if(buttons[i].className===className) 
                            ret=i;
                    }
                    return ret;
                }()
             ],
            
        showContent=gid(selectButton.href.split('#')[1]),
        target,
        fn=function(event){
            event = event || window.event;
                target = event.target || event.srcElement;
                
                if (target.nodeName.toLowerCase() === 'a') {
                    showContent.style.display = 'none';
                    showContent = gid(target.href.split('#')[1]);
                    showContent.style.display = 'block';
                    selectButton.className = '';
                    selectButton = target;
                    target.className = className;
                    target.focus();
                    
                    callback(selectButton,showContent);
                    return false;
                }
        };
        
        if (isMouseover) bar.onmouseover = fn;
        bar.onclick = fn;// click事件至少能保证手持设备可以使用
    };

    注意var bar后面定义的都是一些变量,要以逗号结束。

    我们可以这样调用:

    artTabs('tabs');

    或:

    artTabs('tabs',{
        className:'select',
        isMouseover:true,
        callback:function(on,content){
            if(on.innerHTML==='Link3'){
                //ajax code [ajax取得数据后。。】
                content.innerHTML='我是动态写入的数据!';
            }
        }
    });

    四、扩展

    原生代码执行效率往往会比框架高,当然我们还是可以很简单写几行代码为jQuery献身,成为其插件:

    以下为引用的内容:

    jQuery.fn.artTabs = function (config) {
    return this.each(function () {
    artTabs(this, config);
    });
    };

     调用范例:jQuery(‘.artTabs > dt’).artTabs();

    查看演示:artTabs3.html

    以上实现了选项卡最基本的功能,如果需要可以连选项卡HTML结构都封装进去、历史记录支持、URL记忆支持、Ajax数据加载支持等…

    来自:http://www.kouok.net/html/1045.html

     

  • 相关阅读:
    qsort
    strcmp
    LotteryDrawing
    retire or not retire ? is a question.
    alloc && afree
    strlen
    c point
    c point ccccc
    MySQL MGR源码分析2
    MySQL MGR实现分析
  • 原文地址:https://www.cnblogs.com/youxin/p/2739125.html
Copyright © 2020-2023  润新知