• 2012.05.25 jq Tab


    经过这段时间的奋斗,jq tab的基础功能已经在昨天完成,不包括样式。 到目前为止,算是完成了v0.1版本。

    接下来要完成的功能包括:

    1.设置要显示的item属性(现在每个数据单元被称为json)

    2.添加样式,让这个jq tab好看一点,不过应该还是最先实现公司那种样式。

    下面贴上这个基础版本的代码,包括演示html:

    js:

    这里引用了jquery 1.72 min文件,这个就自己下载去吧。

    View Code
      1 /**
      2 * @author Steven
      3 先不考虑页面resize的情况,做好设置先
      4 */
      5 
      6 /*-------------- Common Functions ------------------*/
      7 function stopPropagation(e) {
      8     e = e || window.event;
      9     if (e.stopPropagation) { //W3C阻止冒泡方法
     10         e.stopPropagation();
     11     } else {
     12         e.cancelBubble = true; //IE阻止冒泡方法
     13     }
     14 }
     15 function removeEleFromArr(arr,obj) {
     16     if (!arr) {
     17         return false;
     18     }
     19     var removeIndexArr = [];
     20     for (var i = 0; i < arr.length; i++) {
     21         if (arr[i] == obj) {
     22             removeIndexArr.push(i);
     23         }
     24     }
     25     for (var i = removeIndexArr.length - 1; i >= 0; i--) {       
     26          arr.splice(removeIndexArr[i], 1);
     27     }
     28 }
     29 
     30 function removeArrFromArr(arr1, arr2) {
     31     if (!arr1 || !arr2) {
     32         return false;
     33     }
     34     var copyArr1 = arrayCopy(arr1);
     35     for (var i = 0; i < arr2.length; i++) {
     36         removeEleFromArr(copyArr1, arr2[i]);
     37     }
     38     return copyArr1;
     39 }
     40 
     41 function arrayCopy(arr) {
     42     if (!!arr && typeof arr.slice == "function") {
     43         return arr.slice();
     44     }
     45     else {
     46         return null;
     47     }
     48 }
     49 //window.onresize = function () {
     50 //    var me = jqTabMaster.prototype,
     51 //        config = me.config;
     52 //    config.isResize = true;
     53 //    alert("resize");
     54 //}
     55 
     56 /*--------------------------------------------------*/
     57 var jqTabMaster = function () {
     58 };
     59 jqTabMaster.prototype.config = {
     60     containerID: "",
     61     size: 0,
     62     items: [],
     63     allItemsIndex:[],
     64     showItemsIndex: [],
     65     notShowItemsIndex: [],
     66      "",
     67     callback: null
     68 };
     69 
     70 
     71 jqTabMaster.prototype.packingItems = function (items) {
     72     for (var i = 0; i < items.length; i++) {
     73         items[i]["__jqTabIndex"] = i;
     74     }
     75     return items;
     76 }
     77 jqTabMaster.prototype.getContinueousIndexArr = function (startIndex, endIndex) {
     78     var me = jqTabMaster.prototype,
     79          config = me.config,
     80          items = config.items,
     81          max = items.length - 1,
     82          startIndex = (typeof startIndex == 'undefined' || isNaN(startIndex)) ? 0 : startIndex,
     83          endIndex = (typeof endIndex == 'undefined' || isNaN(endIndex)) ? max : endIndex,
     84          indexArr = [];
     85 
     86     for (var i = startIndex; i <= endIndex; i++) {
     87         indexArr.push(i);
     88     }
     89     
     90     return indexArr;
     91 }
     92 // 传入需要显示的items的索引数组,根据该数组来显示
     93 jqTabMaster.prototype.buildUl = function (indexArr, className) {
     94     if (!indexArr) {
     95         return false;
     96     }
     97 
     98     var me = jqTabMaster.prototype,
     99         config = me.config,
    100         items = config.items,
    101         currentIndex,
    102         callback = config.callback,
    103         ul = document.createElement("ul"),
    104         li;
    105     
    106     for (var i = 0; i < indexArr.length; i++) {
    107         currentIndex = indexArr[i];
    108       
    109         li = document.createElement("li");
    110         li.innerHTML = items[currentIndex].text;
    111         li.index = items[currentIndex].__jqTabIndex;
    112         ul.appendChild(li);
    113     }
    114     if (!!className) {
    115         ul.className = className;
    116     }
    117 
    118     me.bindTabsClickEvent(ul, callback);
    119     return ul;
    120 }
    121 
    122 jqTabMaster.prototype.bindTabsClickEvent = function (ul, callback) {
    123     if (!!ul && ul.tagName == "UL" && typeof callback == "function") {
    124         ul.onclick = function (ev) {
    125             var ev = ev || window.event,
    126                  target = ev.target || ev.srcElement,
    127                  me = jqTabMaster.prototype,
    128                  config = me.config,
    129                  currentIndex;
    130             if (target.tagName == "LI") {
    131                 currentIndex = target.index;
    132                 callback.call(this, config.items[currentIndex]);
    133             }
    134             else {
    135                 return false;
    136             }
    137         }
    138     }
    139 }
    140 jqTabMaster.prototype.unbindTabsClickEvent = function (ul) {
    141     if (!!ul && ul.tagName == "UL" && typeof callback == "function") {
    142         ul.onclick = null;
    143     }
    144 }
    145 
    146 jqTabMaster.prototype.initial = function (option) {
    147     var me = jqTabMaster.prototype,
    148         allItemsIndex = me.getContinueousIndexArr(0, option.items.length - 1);
    149 
    150     this.config.containerID = option.containerID;
    151     this.config.size = option.size;
    152     this.config.items = me.packingItems(option.items);
    153     this.config.allItemsIndex = allItemsIndex;
    154     this.config.width = option.width;
    155     this.config.callback = option.callback;
    156 
    157     var container = $("#" + this.config.containerID),
    158          iLen,
    159          ul,
    160          needShowIndexArr = [],
    161          showItemsIndex = [],
    162          moreItemsCount = 0;
    163 
    164     container.hide();
    165     container.addClass('container');
    166     container.css('width', this.config.width);
    167     container.css('overflow', 'hidden');
    168     /*增加”更多“按钮,默认为disabled*/
    169     container.css({ 'width': '-=40px' });
    170     var moreBtn = $("<div id='divMoreBtn' class='no-more'><span>更多</span></div>");
    171     moreBtn.insertAfter(container);
    172 
    173     /* 添加可显示的tabs */
    174     iLen = Math.min(this.config.items.length, this.config.size);
    175     needShowIndexArr = me.getContinueousIndexArr(0, iLen - 1);
    176     ul = me.buildUl(needShowIndexArr);
    177     container.append(ul);
    178 
    179     container.show();
    180     /* Get Real Size 
    181     由于这里要调用offsetTop来判断是否超出边界,调用offset的参数会比较耗性能,
    182     现在是用从头开始便利数组获取的,之后可以使用二分法来进行快速查找,以提高性能。
    183     * */
    184     var displayInfo = me.getRealDisplayInfo();
    185     this.config.showItemsIndex = displayInfo.showItemsIndex;
    186     this.config.notShowItemsIndex = displayInfo.notShowItemsIndex;
    187 
    188     /* 当tab没有完全显示时 */
    189     if ((this.config.items.length - this.config.showItemsIndex.length) > 0) {
    190         $("#divMoreBtn").toggleClass('no-more');
    191         /*绑定显示更多tab事件*/
    192         $("#divMoreBtn").bind('click', function (ev) {
    193             me.showMoreTabs(ev);
    194         });
    195     }
    196 }
    197 
    198 jqTabMaster.prototype.getRealDisplayInfo = function () {
    199     var me = jqTabMaster.prototype,
    200         config = me.config,
    201         items = config.items,
    202         lis = $("#" + config.containerID + " ul li"),
    203         showItemsIndex = [],
    204         allItemsIndex = me.config.allItemsIndex,
    205         notShowItemsIndex = [],
    206         originOffsetTop = null;
    207 
    208 
    209     lis.each(function (i) {
    210         if (originOffsetTop == null || originOffsetTop == this.offsetTop) {
    211             originOffsetTop = this.offsetTop;
    212             showItemsIndex.push(this.index);
    213         }
    214         else if (this.offsetTop != originOffsetTop) {
    215             return false;
    216         }
    217     });
    218 
    219     notShowItemsIndex = removeArrFromArr(allItemsIndex, showItemsIndex);
    220 
    221     return { showItemsIndex: showItemsIndex, notShowItemsIndex: notShowItemsIndex };
    222 }
    223 
    224 /*
    225 * params:
    226 * ev: window.event
    227 * me: jqTabMaster.prototype
    228 */
    229 jqTabMaster.prototype.showMoreTabs = function (ev) {
    230     var me = jqTabMaster.prototype,
    231          config = me.config,
    232          ev = ev || window.event,
    233          target = $("#divMoreBtn"),
    234     /* 需要显示的items索引数组 */
    235          needShowIndexArr = [],
    236     /* 容器的offset Left、top和尺寸信息 */
    237          offset, offsetLeft, offsetTop,
    238          width, height,
    239     /* 弹出层的绝对坐标和宽度 */
    240          moreX, moreY,
    241          moreWidth,
    242     /* 空隙值 */
    243          spaceX = 10, spaceY = 5,
    244     /* more tabs*/
    245          ul;
    246 
    247     offset = target.offset();
    248     offsetLeft = offset.left;
    249     offsetTop = offset.top;
    250     width = parseInt(target.css('width'));
    251     height = parseInt(target.css('height'));
    252 
    253 
    254     moreWidth = 200;
    255     moreX = offsetLeft + width - moreWidth;
    256     moreY = offsetTop + height + spaceY;
    257     /* 这样计算能让弹出层的右边和more按钮的右边对齐*/
    258     moreX < 0 && (moreWidth += (moreX - spaceX)) && (moreX = spaceX);
    259 
    260 
    261     var moreDiv = $("<div>"),
    262              moreTabsContainer = $("<div>"),
    263              moreSetting = $("<div>");
    264     moreDiv.attr('id', 'divMore');
    265     moreDiv.addClass("more-div");
    266     moreDiv.css({
    267         'width': moreWidth + 'px',
    268         'left': moreX + 'px',
    269         'top': moreY + 'px'
    270     });
    271 
    272     moreTabsContainer.addClass('more-tabs-container');
    273 
    274     needShowIndexArr = this.config.notShowItemsIndex;
    275     ul = me.buildUl(needShowIndexArr);
    276     moreTabsContainer.append(ul);
    277 
    278     moreSetting.addClass('more-setting');
    279     moreSetting.html('设置');
    280     moreSetting.toggle(
    281              function () {
    282                  this.innerHTML = "保存";
    283                  var uls = $("#divMore ul,#" + config.containerID + " ul");
    284                  for (var i = 0; i < uls.length; i++) {
    285                      uls[i].onclick = null;
    286                      me.buildSettingBtns(uls[i]);
    287                  }
    288                  me.unbindEventsWhenSettingTabs();
    289              }, function () {
    290                  this.innerHTML = "设置";
    291                  var uls = $("#divMore ul,#" + config.containerID + " ul");
    292                  uls.each(function (i) {
    293                      me.bindTabsClickEvent(uls[i], me.config.callback);
    294                      me.removeSettingBtns(uls[i]);
    295                  });
    296                  me.bindEventsWhenMoreTabsShow();
    297              });
    298 
    299     moreDiv.append(moreTabsContainer).append(moreSetting);
    300 
    301     $(document.body).append(moreDiv);
    302     stopPropagation(ev);
    303 
    304     /* more tabs显示后,重新绑定事件*/
    305     me.bindEventsWhenMoreTabsShow();
    306 
    307     /*阻止选中文本*/
    308     me.bankSelect();
    309 }
    310 jqTabMaster.prototype.hideMoreTabs = function () {
    311     $("#divMore").remove();
    312 
    313     /* more tabs隐藏后重新绑定事件*/
    314     jqTabMaster.prototype.bindEventsWhenMoreTabsHide();
    315 }
    316 jqTabMaster.prototype.unbindEventsWhenSettingTabs = function () {
    317     $(document).unbind('click');
    318     $("#divMoreBtn").unbind('click');
    319 }
    320 jqTabMaster.prototype.bindEventsWhenMoreTabsHide = function () {
    321     $(document).unbind('click');
    322     $("#divMoreBtn").unbind('click')
    323      .bind('click', function () {
    324          jqTabMaster.prototype.showMoreTabs();
    325      });
    326 }
    327 jqTabMaster.prototype.bindEventsWhenMoreTabsShow = function () {
    328     /* 刷新more按钮的click事件。再点击click时也隐藏more*/
    329     $("#divMoreBtn").unbind('click')
    330      .bind('click', function () {
    331          jqTabMaster.prototype.hideMoreTabs();
    332      }); ;
    333 
    334     /* 点击more tabs容器外地地方时,隐藏more tabs*/
    335     $(document).unbind('click').bind('click', function (ev) {
    336         var me = jqTabMaster.prototype,
    337              ev = ev || window.event,
    338              target = ev.target || ev.srcElement,
    339              isDivMore = target.id == "divMore",
    340              isBelong2DivMore = $(target).parents("#divMore").length > 0;
    341 
    342         if (!isBelong2DivMore) {
    343             me.hideMoreTabs();
    344         }
    345         else {
    346             stopPropagation(ev);
    347             return false;
    348         }
    349     });
    350 }
    351 
    352 jqTabMaster.prototype.buildSettingBtns = function (ul) {
    353     if (!ul || ul.tagName != "UL") {
    354         return false;
    355     }
    356 
    357     var me = jqTabMaster.prototype,
    358         config = me.config,
    359         isBelong2DivMore = $(ul).parents("#divMore").length > 0,
    360         isBelong2TabsContainer = $(ul).parents("#" + config.containerID).length > 0,
    361         optType = isBelong2DivMore ? "add" : "remove",
    362         lis = ul.getElementsByTagName("li"),
    363         li,
    364         iLen = lis.length,
    365         spnOpt;
    366 
    367     for (var i = 0; i < iLen; i++) {
    368         li = lis[i];
    369         (function (li, me) {
    370             me.bindSettingOpt(li, optType);
    371         })(li, me);
    372     }
    373 }
    374 jqTabMaster.prototype.bindSettingOpt = function (li, optType) {
    375     var me = jqTabMaster.prototype,
    376         spnOpt = document.createElement("span"),
    377         className = "opt";
    378 
    379     spnOpt.className = className;
    380     spnOpt.innerHTML = optType == "add" ? "+" : "-";
    381 
    382     if (optType == "add") {
    383         spnOpt.onclick = function () {
    384             me.addTab($(li)[0]);
    385         }
    386     }
    387     else {
    388         spnOpt.onclick = function () {
    389             me.removeTab($(li)[0]);
    390         }
    391     };
    392     $(li).append(spnOpt);
    393 }
    394 
    395 jqTabMaster.prototype.removeSettingBtns = function (ul) {
    396     if (!ul || ul.tagName != "UL") {
    397         return false;
    398     }
    399 
    400     var spnOpts = $(ul).find("li span");
    401     spnOpts.remove();
    402 }
    403 
    404 jqTabMaster.prototype.addTab = function (li) {
    405     var me = jqTabMaster.prototype,
    406         config = me.config,
    407         maxSize = config.size,
    408         realSize = config.showItemsIndex.length;
    409 
    410     if (realSize >= maxSize) {
    411         return false;
    412     }
    413 
    414     var showItemsIndex = config.showItemsIndex,
    415         notShowItemsIndex = config.notShowItemsIndex,
    416         items = config.items,
    417         showedTabs = $("#" + config.containerID + " ul li"),
    418         lastShowTab = realSize > 0 ? showedTabs.eq(realSize - 1) : null,
    419         moreTabsUl = $("#divMore ul"),
    420         moreTabsLi = moreTabsUl.find("li"),
    421         newLi = document.createElement("li"),
    422         currentLiIndex = li.index,
    423         currentItem = items[currentLiIndex],
    424         addSuccessful = false;
    425 
    426     /* Build New Li need to insert */
    427     newLi.index = currentLiIndex;
    428     newLi.innerHTML = currentItem.text;
    429     newLi = $(newLi);
    430     me.bindSettingOpt(newLi, "remove");
    431 
    432     if (!!lastShowTab) {
    433         newLi.insertAfter(lastShowTab);
    434     }
    435     else {
    436         $("#" + config.containerID + " ul").append(newLi);
    437     }
    438     addSuccessful = !lastShowTab || lastShowTab.offset().top == newLi.offset().top;
    439     if (!addSuccessful) {
    440         newLi.remove();
    441     }
    442     else {
    443         showItemsIndex.push(currentLiIndex);
    444         removeEleFromArr(notShowItemsIndex, currentLiIndex);
    445         $(li).remove();
    446     }
    447 }
    448 jqTabMaster.prototype.removeTab = function (li) {
    449     var me = jqTabMaster.prototype,
    450         config = me.config,
    451         items = config.items,
    452         showItemsIndex = config.showItemsIndex,
    453         notShowItemsIndex = config.notShowItemsIndex,
    454         realSize = config.showItemsIndex.length,
    455 
    456         showedTabs = $("#divMore ul li"),
    457         lastShowTab = showedTabs.eq(notShowItemsIndex.length - 1),
    458         currentLiIndex = li.index,
    459         currentItem = items[currentLiIndex],
    460         newLi = document.createElement("li"),
    461         move2Index = 0;
    462 
    463     newLi.index = currentLiIndex;
    464     newLi.innerHTML = currentItem.text;
    465     newLi = $(newLi);
    466     me.bindSettingOpt(newLi, "add");
    467     
    468     $(li).remove();
    469     removeEleFromArr(showItemsIndex, currentLiIndex);
    470    
    471     newLi.insertAfter(lastShowTab);
    472     notShowItemsIndex.push(currentLiIndex);
    473 }
    474 
    475 jqTabMaster.prototype.getNotShowItemsIndex = function () { 
    476     
    477 }
    478 jqTabMaster.prototype.getItemRank = function (num, arr) {
    479     var me = jqTabMaster.prototype,
    480         config = me.config,
    481         showItemsIndex = config.showItemsIndex,
    482         notShowItemsIndex = config.notShowItemsIndex,
    483         items = config.items,
    484         allItemsIndex = [];
    485 
    486     for (var i = 0; i < items.length; i++) {
    487 
    488     }
    489 }
    490 
    491 /* 禁止文本被选中 */
    492 jqTabMaster.prototype.bankSelect = function () {
    493     $("#divMore,#divMoreBtn,#" + jqTabMaster.prototype.config.containerID).bind('selectstart', function () {
    494         return false;
    495     })
    496      .css({
    497          '-moz-user-select': 'none',
    498          '-webkit-user-select': 'none',
    499          'user-select': 'none'
    500      });
    501 }

    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  }
     98  .opt
     99  {
    100      border:solid #333333 1px; 
    101      color:red;
    102      cursor:pointer;
    103      display:inline-block;
    104      float:right;
    105      font-weight:bold;
    106      height:13px;
    107      margin:2px 1px;
    108      line-height:13px;
    109      vertical-align:middle;
    110      width:10px;
    111  }

    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=gbk2312" />
     6          <title>Jq Tab Demo</title>
     7          <link href="css/jqTab.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.2.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: 6,
    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                   "50%",
    35                  callback: callback
    36              });
    37              function callback(data) {
    38                  alert(data.__jqTabIndex);
    39              }
    40              
    41          </script>
    42      </body>
    43  </html>

                                                                  这篇就这么多。 补2012.05.25

  • 相关阅读:
    Python中if __name__ == '__main__':的作用
    Java集合面试题及答案总结(2020版)
    Java多线程面试题及答案(2020版)
    poi: 如何获取cell的行号对应的字母
    gogs: 进入Docker实例并修改MySQL帐号
    多音源多声卡背景音乐播放系统,可在一台电脑上同时播放10种音乐
    弱电图纸中敷设方式符号表示大全
    HashMap集合详解----源码分析--之--高级篇
    正则表达式总结及主要事项
    使用接口进行form表单提交
  • 原文地址:https://www.cnblogs.com/bee0060/p/2519123.html
Copyright © 2020-2023  润新知