一、结构
使用合理的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