需要做一个选择分类工具,大致要求如下:

  点击按钮,显示一级分类,指向某个一级分类显示对应二级分类,分类有几层不定。

只能选择最后一个分类,然后把分类的ID 传值给按钮的value

我的思路:

1.后台传过来的值是json,结构如下:

var json = [
  {"name":"衣服" , "id" : "1" , "pid" : 0},
  {"name":"裤子" , "id" : "2" , "pid" : 1}

];

pid是父类的ID,pid为0代表1级分类

2.根据json建立dom树,css样式很简单等会看最后的代码,结构如下:

<ul>
  <li>
    <span>衣服</span>
    <ul>
      <li><span title="1">衬衣</span></li>
      <li><span title="2">毛衣</span></li>
      <li><span title="3">内衣</span></li>
    </ul>
  </li>

</ul>

3.查询是否有下级分类,如果没有可以点击,点击后复制给按钮;否则绑定显示下级分类的hover事件

写了一下午,代码量大,头也晕,写得也确实不容易读。想要查看,直接复制以下代码,无图片,无外带JS,不是歪货功能OK。

  1. <!doctype html>
  2. <html>
  3. <head>
  4. <title>分类选择器</title>
  5. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  6.  
  7. <style>
  8. #classifyTree{position:absolute;left:0;top:100%;z-index:1111;display:none;}
  9. #classifyTree ul{position:absolute;left:100%;top:0;border:1px solid #ccc;margin:0;padding:0;display:none}
  10. #classifyTree li{float:left;list-style-type:none;position:relative;cursor:pointer}
  11. #classifyTree span:hover{background:#09C}
  12. #classifyTree span{float:left;display:block;width:100px;text-align:center;height:25px;white-space:nowrap;background:#f1f1f1;border-bottom:1px dashed #CCC;line-height:25px}
  13. #cid1{visibility:hidden;}
  14. #cid1Text{width:75px;height:25px;border-color:#CCC;border-style:solid;border-width:1px 0 1px 1px;background:#f1f1f1;cursor:pointer;line-height:25px;float:left;text-indent:5px;padding:0;ss}
  15. .classifyBox{height:25px;cursor:pointer;display:inline-block;position:relative}
  16. .arrowBorder{width:25px;height:25px;border-color:#CCC;border-style:solid;border-width:1px 1px 1px 0px;background:#f1f1f1;display:inline-block;float:left}
  17. .downArrow{margin:8px 0 0 8px; width: 0;height: 0; border-left: 5px solid transparent;border-right: 5px solid transparent;border-top: 10px solid #181818;float:left}
  18. </style>
  19. </head>
  20. <body>
  21. <div class="classifyBox">
  22. <div id="classifyClick">
  23. <input type="text" id="cid1Text"/>
  24. <div class="arrowBorder">
  25. <div class="downArrow"></div>
  26. </div>
  27. </div>
  28. <div id="classifyTree">
  29. </div>
  30. </div>
  31.  
  32. <input type="text" name="category_id" value="" id="cid1"/>
  33. </body>
  34. <script type="text/javascript"> 
  35. //pid代表父ID,0代表根
  36. var json = [
  37. {"name":"衣服" , "id" : "1" , "pid" : 0},
  38. {"name":"裤子" , "id" : "2" , "pid" : 0},
  39. {"name":"鞋子" , "id" : "3" , "pid" : 0},
  40.  
  41. {"name":"衬衣" , "id" : "4" , "pid" : 1},
  42. {"name":"毛衣" , "id" : "5" , "pid" : 1},
  43. {"name":"内衣" , "id" : "6" , "pid" : 1},
  44.  
  45. {"name":"大" , "id" : "10" , "pid" : 6},
  46. {"name":"大" , "id" : "11" , "pid" : 7},
  47. {"name":"大" , "id" : "7" , "pid" : 4},
  48. {"name":"中" , "id" : "8" , "pid" : 4},
  49. {"name":"小" , "id" : "9" , "pid" : 4}
  50. ];//IE下 最后一个数组不能给逗号,否则会多算一条
  51.  
  52. var classifySelect = {
  53. treeRoot : document.getElementById("classifyTree"),//dom树根
  54. btn : document.getElementById("cid1"),
  55. btnText : document.getElementById("cid1Text"),
  56. btnClick : document.getElementById("classifyClick"),
  57. json : this.json,
  58. rootId : 0,//一级分类ID
  59. //根据json建立dom树
  60. setDomTree : function(){
  61. function creatEl(name){return document.createElement(name);}//创建标签
  62. var ul = creatEl("ul");
  63. //先建立根节点
  64. for(var i=0;i<this.json.length;i++){
  65. if(this.json[i].pid==this.rootId){
  66. var li = creatEl("li");
  67. var span = creatEl("span");
  68. span.alt = this.json[i].id;
  69. span.innerHTML = this.json[i].name;
  70. li.appendChild(span);
  71. ul.appendChild(li);
  72. this.json.splice(i,1);//已经载入页面删除当前数组
  73. i--;//数组删除,下次循环继续查询当前位置
  74. }
  75. }
  76. this.treeRoot.appendChild(ul);
  77.  
  78. this.addNodes(this.treeRoot.getElementsByTagName("ul")[0]);//获取插入的根ul,再查询是否有子类
  79. },
  80.  
  81. //查询是否还有子分类,有则添加
  82. addNodes : function(pUl){//parent ul
  83. function creatEl(name){return document.createElement(name);}//创建标签
  84. var li = pUl.getElementsByTagName("li");
  85. /*
  86. 遍历li。特别注意:由于下个for循环条件满足添加了子类后,pUl(也就是根ul)中便添加了li,li.length会改变。
  87. 新添加的li永远在当前指针节点之后,所以不会冲突或者遗漏,而且能够在此循环结束后完成整个dom树
  88. */
  89. for(var i=0;i<li.length;i++){
  90. var pid = parseInt(li[i].getElementsByTagName("span")[0].alt);//根据span的title存储的ID,查找json队列里是否还有子类//alert(typeof(pid));
  91. var ul = creatEl("ul");
  92. var isExist = false;//是否存在子类
  93. for(var j=0;j<this.json.length;j++){//遍历json,
  94. if(this.json[j].pid == pid){//pid相同,添加节点到pUl
  95. var newLi = creatEl("li");
  96. var newSpan = creatEl("span");
  97. newSpan.alt = this.json[j].id;
  98. newSpan.innerHTML = this.json[j].name;
  99. newLi.appendChild(newSpan);
  100. ul.appendChild(newLi);
  101. this.json.splice(j,1);
  102. j--;
  103. isExist = true;
  104. }
  105. }
  106. if(isExist){
  107. li[i].appendChild(ul);
  108. }
  109. }
  110. },
  111.  
  112. //查找分类
  113. seekClassify : function(){
  114. var self = this;
  115. //点击触发分类显示
  116. this.btnClick.onclick = function(){
  117. self.treeRoot.style.display = "block";
  118. self.nextClassify(self.treeRoot,"block");//显示根分类
  119. }
  120. },
  121.  
  122. //绑定事件,隐藏和显示下级分类
  123. bindHover : function(){
  124. var self = this;
  125. var li = self.treeRoot.getElementsByTagName("li");//获取所有li
  126. //绑定根
  127. var root =self.treeRoot.getElementsByTagName("ul")[0];
  128. root.onmouseover= function(){
  129. self.nextClassify(self.treeRoot,"block");
  130. }
  131. root.onmouseout = function(){
  132. self.nextClassify(self.treeRoot,"none");
  133. }
  134. for(var i=0;i<li.length;i++){
  135. li[i].onmouseover = function(){
  136. if(self.isNextClassify(this)){
  137. self.nextClassify(this,"block");
  138. }
  139. }
  140. li[i].onmouseout = function(){
  141. if(self.isNextClassify(this)){
  142. self.nextClassify(this,"none");
  143. }
  144. }
  145. }
  146. },
  147.  
  148. //显示或者隐藏下级分类
  149. nextClassify : function(self,status){
  150. var ul = self.getElementsByTagName("ul")[0];
  151. ul.style.display = status;
  152. },
  153.  
  154. //检查是否有下级分类,如果没有可以选择
  155. isNextClassify : function(li){
  156. var self = this;
  157. if(li.getElementsByTagName("ul")[0]){
  158. return true;
  159. }else{
  160. li.getElementsByTagName("span")[0].onclick = function(){//绑定选择事件
  161. self.btn.value = this.alt;
  162. self.btnText.value = this.innerHTML;
  163. //document.getElementById("cid2").value = self.titlePlace;//绑定到保存草稿input
  164. self.nextClassify(self.treeRoot,"none");//选择完毕隐藏
  165. }
  166. return false;
  167. }
  168. },
  169.  
  170. init : function(){
  171. this.setDomTree();
  172. this.seekClassify();
  173. this.bindHover();
  174. }
  175. }
  176.  
  177. classifySelect.init();
  178. </script>
  179. </html>

JS分类选择插件的更多相关文章

  1. js 颜色选择插件

    COLPICK是一款非常的轻小,无需图片就可以实现颜色选择器的jquery插件,只用 JS 和 CSS 就实现了全部功能,而且非常直观,类似Photoshop的界面,使用方便.颜色的明暗很容易自定义, ...

  2. 4个好用的JS联动选择插件

    jQuery City Select 一个简单的jQuery省市联动插件,可以自定义JSON字典实现其他内容的联动选择菜单. PCAS省.市.地区联动选择JS封装类 PCAS可能是国内使用人数最多的J ...

  3. 【JS】一款好用的JS日历选择插件【bootstrap-datetimepicker.js】

    1.插件名称:bootstrap-datetimepicker.js,下载地址:上Github下载或者下面链接 2.效果图: 3.使用方法:里面有Demo 链接: https://pan.baidu. ...

  4. 纯原生js移动端城市选择插件

    接着上一篇纯js移动端日期选择插件,话说今天同事又来咨询省市县联动的效果在移动端中如何实现,还是老样子,百度上一搜,诶~又全是基于jquery.zepto的,更加可恨的是大多数都是PC版的,三个sel ...

  5. 原生js日期时间插件鼠标点击文本框弹出日期时间表格选择日期时间

    原文出处 (这是我从互联网上搜来的,感觉能满足各方面的需求.个人感觉挺不错的,所以后期修改了一下向大家推荐!) 效果图: html代码: <!DOCTYPE html PUBLIC " ...

  6. 纯原生js移动端日期选择插件

    最近在项目上需要使用日期选择插件,由于是移动端的项目,对请求资源还是蛮节约的,可是百度上一搜,诶~全是基于jquery.zepto的,本来类库就很大,特别像mobiscroll这种样式文件一大堆又丑又 ...

  7. 移动设备日期选择插件(基于JQUERY)

    上周花了2个小时写的一个日期选择插件,比较适合移动端的设备.先看个效果图吧.如果刚好是你需要的就往下吧,不需要的也可以继续..... 其实网络上已经有的了类似的成熟插件,比如基于mobiscroll, ...

  8. 日期时间范围选择插件:daterangepicker使用总结

    分享说明: 项目中要使用日期时间范围选择对数据进行筛选;精确到年月日 时分秒;起初,使用了layui的时间日期选择插件;但是在IIE8第一次点击会报设置格式错误;研究了很久没解决,但能确定不是layu ...

  9. 原生js版分页插件

    之前我在自己的博客里发表了一篇用angularJs自定义指令实现的分页插件,今天简单改造了一下,改成了原生JavaScript版本的分页插件,可以自定义一些简单配置,特此记录下来.如有不足之处,欢迎指 ...

随机推荐

  1. 三、动态SQL

    动态SQL MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑. 动态SQL的元素 元素 作用 备注 if 判断语句 单条件分支判断 choose.whe ...

  2. mysql中的ifnull()函数判断空值

    我们知道,在不同的数据库引擎中,内置函数的实现.命名都是存在差异的,如果经常切换使用这几个数据库引擎的话,很容易会将这些函数弄混淆. 比如说判断空值的函数,在Oracle中是NVL()函数.NVL2( ...

  3. File 删除给定的文件或目录

    package seday03; import java.io.File; /*** 创建一个多级目录* @author xingsir*/public class MkDirsDemo { publ ...

  4. 计科菜鸟玩生信(一)——Windows10下用docker安装GATK

    1.官网下载GATK. (学校网速实在是太慢了,下载几个小时到自闭) 下载地址:https://software.broadinstitute.org/gatk/download/ 下载完成后文件夹中 ...

  5. git安装和项目上传到GitHub

    重装系统后,Git安装也要来重来 下载 国内下载地址:https://npm.taobao.org/mirrors/git-for-windows 安装忽略 生成密钥 输入然后都是下一步,生成密钥,生 ...

  6. java.lang.IllegalArgumentException: java.util.zip.ZipException: invalid LOC header (bad signature)异常解决方法

    java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start com ...

  7. curl ftp libcurl 功能使用

    struct FtpFile { const char *filename; FILE *stream; }; static size_t my_fwrite(void *buffer, size_t ...

  8. haproxy动静分离的验证

    线上出现过项目的静态文件被拦截,不能直接访问.所以想到了haproxy指向对应的url来访问静态文件,想到这里在网络搜索了下,确实有此功能.立即上测试环境验证下: 在listen中增加两行: ​ #定 ...

  9. rabbitmq多消费者

    rabbitmq多消费者处理 当rabbitmq拥有多个消费者时,队列收到的消息将以轮询(round-robin)的分发方式发送给消费者.每条消息只会发送给订阅列表里的一个消费者.这种方式非常适合扩展 ...

  10. mysql常见错误代码解释

    mysql常见错误代码解释 原创 作者:bayaim 时间:2017-12-26 11:07:14 38  ---------------------------------------------- ...