2012.05.21 jq Tab

昨天星期天,玩了一天,晚上看了需求文档,所以没有花时间学习。

今天继续实现jq tab。

根据之前的进度,剩余的工作量包括:

1.提供callback函数接口(完成)

2.样式(实在非我所长。这个带回公司再用公司的样式加以调整)

3.调整应该显示的tabs,数量不超过size(实现了添加设置按钮,还剩下添加加减符号,并实现从默认显示的tab和更多tab之间添加移除tab,相当于已实现三分之一)

4.每个tab可以接受任意数据格式(未实现,这个想过,难度应该不大。)

这里的callback函数接口,也是记录在config中,在初始化时传入。在创建ul时,会判断callback函数是否被正确传入,是的话,用callback.call(this, li.value)实现。

暂时callback函数只能接受li的value属性。 当功能修改成可以接受任意数据格式后,这个callback函数会接受li对应的json对象。

贴上代码和css,方便回公司修改:

js:

View Code
  1 /**
  2  * @author Steven
  3  */
  4 
  5 /*-------------- Common Functions ------------------*/
  6 function stopPropagation(e) {
  7     e = e || window.event;
  8     if(e.stopPropagation) { //W3C阻止冒泡方法
  9         e.stopPropagation();
 10     } else {
 11         e.cancelBubble = true; //IE阻止冒泡方法
 12     }
 13 }
 14 
 15 
 16 /*--------------------------------------------------*/
 17 var jqTabMaster = function(){
 18 };
 19 jqTabMaster.prototype.config = {
 20     containerID:"",
 21     size:0,
 22     realSize:0,
 23     items:[],
 24     showItems:[],
 25     "",
 26     callback:null
 27 };
 28 
 29 jqTabMaster.prototype.buildUl = function(startIndex, endIndex, className){
 30     var me = jqTabMaster.prototype,
 31         config = me.config,
 32         items = config.items,
 33         callback = config.callback,
 34         max = items.length-1,
 35         startIndex = (typeof startindex =='undefined' || isNaN(startIndex))? 0:startIndex,
 36         endIndex = (typeof endIndex =='undefined' || isNaN(endIndex))? max:endIndex,
 37         ul = document.createElement("ul"),
 38         li;
 39         
 40     for(var i =startIndex;i<=endIndex;i++){
 41         li = document.createElement("li");
 42         li.innerHTML = items[i].text;
 43         li.value = items[i].value;
 44         ul.appendChild(li);
 45     }
 46     if(!!className){
 47         ul.className = className;
 48     }
 49 
 50     me.bindTabsClickEvent(ul,callback);
 51     return ul;
 52 }
 53 
 54 jqTabMaster.prototype.bindTabsClickEvent = function(ul,callback){
 55     if(!!ul && ul.tagName=="UL" && typeof callback =="function"){
 56         ul.onclick = function(ev){
 57             var ev = ev || window.event,
 58                 target = ev.target || ev.srcElement;
 59             if(target.tagName == "LI"){
 60                 callback.call(this, target.value);
 61             }
 62             else
 63             {
 64                 return false;
 65             }                
 66         }
 67     }    
 68 }
 69 jqTabMaster.prototype.unbindTabsClickEvent = function(ul){
 70     if(!!ul && ul.tagName=="UL" && typeof callback =="function"){
 71         ul.onclick = null;
 72     }    
 73 }
 74 
 75 jqTabMaster.prototype.initial = function(option){
 76     this.config.containerID = option.containerID;
 77     this.config.size = option.size;
 78     this.config.items = option.items;
 79     this.config.width = option.width;    
 80     this.config.callback = option.callback;
 81 
 82     var me = jqTabMaster.prototype,
 83         container = $("#"+this.config.containerID),
 84         iLen,
 85         ul, 
 86         showItems = [],
 87         moreItemsCount = 0;
 88 
 89     container.hide();
 90     container.addClass('container');
 91     container.css('width',this.config.width);
 92     container.css('overflow','hidden');
 93     /*增加”更多“按钮,默认为disabled*/
 94     container.css({'width':'-=40px'});
 95     var moreBtn = $("<div id='divMoreBtn' class='no-more'><span>更多</span></div>");
 96     moreBtn.insertAfter(container);
 97  
 98      /* 添加可显示的tabs */
 99      iLen = Math.min(this.config.items.length,this.config.size);
100      ul = jqTabMaster.prototype.buildUl(0, iLen);
101     container.append(ul);    
102     
103     container.show();
104     /* Get Real Size 
105          由于这里要调用offsetTop来判断是否超出边界,调用offset的参数会比较耗性能,
106          现在是用从头开始便利数组获取的,之后可以使用二分法来进行快速查找,以提高性能。
107      * */
108     var displayInfo = me.getRealDisplayInfo();
109     this.config.realSize = displayInfo.realSize;
110     this.config.showItems = displayInfo.showItems;
111     
112     /* 当tab没有完全显示时 */    
113     if((this.config.items.length - this.config.realSize)>0){
114         $("#divMoreBtn").toggleClass('no-more');
115         /*绑定显示更多tab事件*/
116         $("#divMoreBtn").bind('click',function(ev){
117             me.showMoreTabs(ev);
118         });
119     }
120 }
121 
122 jqTabMaster.prototype.getRealDisplayInfo = function(){
123     var me = jqTabMaster.prototype,
124         config = me.config,
125         realSize = 0,
126         lis = $("#"+config.containerID+" ul li"),
127         showItems = [],
128         originOffsetTop=null;
129     
130     lis.each(function(i){
131         if(originOffsetTop==null){
132             originOffsetTop = this.offsetTop;
133             showItems.push(i);
134         } else if( this.offsetTop!=originOffsetTop){
135             return false;
136         }
137         realSize++;
138     });
139     return {realSize:realSize,showItems:showItems};
140 }
141 
142 /*
143  * params:
144  * ev: window.event
145  * me: jqTabMaster.prototype
146  */
147 jqTabMaster.prototype.showMoreTabs = function(ev){
148     var me = jqTabMaster.prototype,
149         config = me.config,
150         ev = ev || window.event,
151         target = $("#divMoreBtn"),
152         /* 容器的offset Left、top和尺寸信息 */
153         offset, offsetLeft, offsetTop,
154         width, height,
155         /* 弹出层的绝对坐标和宽度 */ 
156         moreX, moreY,
157         moreWidth,
158         /* 空隙值 */
159         spaceX=10, spaceY=5,
160         /* more tabs*/
161         ul;     
162             
163         offset = target.offset();
164         offsetLeft = offset.left;
165         offsetTop =offset.top;
166         width = parseInt(target.css('width'));
167         height = parseInt(target.css('height'));
168         
169         
170         moreWidth = 200;
171         moreX = offsetLeft + width - moreWidth;
172         moreY = offsetTop + height + spaceY;
173         /* 这样计算能让弹出层的右边和more按钮的右边对齐*/
174         moreX < 0 && (moreWidth += (moreX - spaceX)) && (moreX = spaceX);
175         
176         //alert(offsetTop+" "+moreY+" "+height);
177         var moreDiv = $("<div>"),
178             moreTabsContainer = $("<div>"),
179             moreSetting = $("<div>");
180         moreDiv.attr('id','divMore');
181         moreDiv.addClass("more-div");
182         moreDiv.css({
183             'width':moreWidth+'px',
184             'left':moreX+'px',
185             'top':moreY+'px'
186         });
187         
188         moreTabsContainer.addClass('more-tabs-container');                
189         ul = me.buildUl(me.config.realSize);
190         moreTabsContainer.append(ul);
191                 
192         moreSetting.addClass('more-setting');
193         moreSetting.html('设置');        
194         moreSetting.toggle(
195             function(){
196                 this.innerHTML = "保存";
197                 var uls = $("#divMore ul,#"+config.containerID+" ul");
198                 for(var i =0;i<uls.length;i++){
199                     uls[i].onclick=null;
200                 }
201                 me.unbindEventsWhenSettingTabs();
202             },function(){
203                 this.innerHTML = "设置";
204                 var uls = $("#divMore ul,#"+config.containerID+" ul");
205                 uls.each(function(i){                
206                     me.bindTabsClickEvent(uls[i]);
207                 });
208                 me.bindEventsWhenMoreTabsShow();
209             });
210         
211         moreDiv.append(moreTabsContainer).append(moreSetting);
212         
213         $(document.body).append(moreDiv);            
214         stopPropagation(ev);
215         
216         /* more tabs显示后,重新绑定事件*/
217         me.bindEventsWhenMoreTabsShow();
218         
219         /*阻止选中文本*/
220         me.bankSelect();
221 }
222 jqTabMaster.prototype.hideMoreTabs = function(){
223     $("#divMore").remove();
224     
225     /* more tabs隐藏后重新绑定事件*/
226     jqTabMaster.prototype.bindEventsWhenMoreTabsHide();
227 }
228 jqTabMaster.prototype.unbindEventsWhenSettingTabs = function(){
229     $(document).unbind('click');
230     $("#divMoreBtn").unbind('click');
231 }
232 jqTabMaster.prototype.bindEventsWhenMoreTabsHide = function(){
233     $(document).unbind('click');
234     $("#divMoreBtn").unbind('click')
235     .bind('click',function(){
236         jqTabMaster.prototype.showMoreTabs();
237     });
238 }
239 jqTabMaster.prototype.bindEventsWhenMoreTabsShow = function(){    
240     /* 刷新more按钮的click事件。再点击click时也隐藏more*/
241     $("#divMoreBtn").unbind('click')
242     .bind('click',function(){
243         jqTabMaster.prototype.hideMoreTabs();
244     });;
245     
246     /* 点击more tabs容器外地地方时,隐藏more tabs*/
247     $(document).unbind('click').bind('click', function(ev){
248         var me = jqTabMaster.prototype,
249             ev = ev || window.event,
250             target = ev.target||ev.srcElement,
251             isDivMore = target.id=="divMore",
252             isBelong2DivMore = $(target).parents("#divMore").length>0;
253         
254         if(!isBelong2DivMore){
255             me.hideMoreTabs();
256         }
257         else {
258             stopPropagation(ev);
259             return false;
260         }
261     });
262 }
263 
264 jqTabMaster.prototype.bankSelect = function(){
265     $("#divMore,#divMoreBtn,#"+jqTabMaster.prototype.config.containerID).bind('selectstart',function(){
266         return false;
267     })
268     .css({
269         '-moz-user-select':'none',
270         '-webkit-user-select':'none',
271         'user-select':'none'    
272     });
273 }

css:

View Code
 1 div{
 2     border:solid 1px #000;    
 3 }
 4 
 5 .container{
 6     border:solid 1px #000;
 7     display:block;
 8     float:left;
 9     height:50px;    
10     margin:0px;
11     padding:0px;
12 }
13 
14 .container ul{
15     float:left;
16     list-style:none;
17     margin:12px 5px 5px 5px;
18     padding:0px;
19     text-align: left;
20 }
21 .container ul li{
22     border:solid 1px #f00;
23     display:inline-block;
24     margin: 5px 5px 105px 5px;
25     overflow:visible;
26     text-align:center;
27     width:40px;
28     
29 }
30 
31 #divMoreBtn{
32     border:solid 1px #000;
33     display:block;
34     float:left;
35     height:50px;
36     margin:0px 0px 0px 5px;
37     vertical-align:bottom;
38     width:35px;
39 }
40 
41 #divMoreBtn span{
42     display:block;
43     line-height:60px;    
44     text-align:center;
45     vertical-align:middle;
46 }
47 
48 .no-more{
49     background-color#111;
50     color:#ddd;
51 }
52 .more{
53     background-color:#fff;
54     color:#000;
55 }
56 .more-div{
57     height:420px;
58     position:absolute;
59 }
60 .more-div .more-tabs-container{
61     height:360px;
62     margin:5px;
63     overflow-x:none;
64     overflow-y:auto;
65     position:relative;
66 }
67 .more-div .more-setting{
68     color:#f00;
69     display:block;
70     font-weight:bold;
71     line-height:40px;
72     margin:8px 5px;
73     height:40px;
74     text-align:center;
75     position:relative;
76     vertical-align: bottom;
77 }
78 
79 .more-tabs-container ul{
80     margin:0px;
81     padding: 0px;
82     clear:both;
83     float:left;
84     list-style:none;    
85 }
86 
87 .more-tabs-container ul li{
88     border:solid 1px #DDDDDD;
89     display:block;
90     list-style:none;
91     line-height:30px;    
92     height:30px;
93     margin:2px 10px 5px 10px;
94     text-align:center;
95     vertical-align:middle;
96     width:120px;
97 }

html:

View Code
 1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 2 "http://www.w3.org/TR/html4/loose.dtd">
 3 <html xmlns="http://www.w3.org/1999/xhtml">
 4     <head>
 5         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 6         <title>Jq Tab Demo</title>
 7         <link href="css/css.css" rel="stylesheet"  />
 8     </head>
 9     <body>
10         <h1>jq Tab</h1>
11         
12         
13         <div id="div1">                 
14         </div>
15         <script type="text/javascript" src="js/jquery-1.7.1.min.js"></script>
16         <script type="text/javascript" src="js/jqTab.js"></script>
17         <script type="text/javascript">
18             var jqTab = new jqTabMaster();
19             jqTab.initial({
20                 containerID:"div1",
21                 size:7,
22                 items:[
23                     {value:"1",text:"1"},
24                     {value:"2",text:"2"},
25                     {value:"3",text:"3"},
26                     {value:"4",text:"4"},
27                     {value:"5",text:"5"},
28                     {value:"6",text:"6"},
29                     {value:"7",text:"7"},
30                     {value:"8",text:"8"},
31                     {value:"9",text:"9"},
32                     {value:"10",text:"10"}
33                 ],
34                 "300px",
35                 callback:callback
36             });
37             function callback(value){
38                 alert(value);
39             }
40             
41         </script>
42     </body>
43 </html>

                                            今天就到这里

原文地址:https://www.cnblogs.com/bee0060/p/2512441.html