要求输入框点击出现下拉菜单,并实现以下功能:
1.首先点击地点标签页,选择好地点;
2.自动显示相应节点标签页显示节点信息,选择好节点
3.自动显示相应的连接点,选择连接点,连接点被选中并被传送的输入框input控件中
这个控件实际上要在前面的tab的某个子项选中以后,动态更新后面的tab内容,并且跳到后面的tab,如果tab是最后一页,则将选择内容提交到input中。为了通用性,该控件从外部接收json数据,以及调用参数,可以生成对应下拉菜单。该tab菜单支持层次可以任意设置,根据接收到的json数据的层次,以及level_length限制
参数:
data_url:json数据的ajax地址;
level_length:菜单层次,如果菜单为2层,则即使接收到3层的数据,也只显示二层tab。
例子:
点击连接点A的输入框
选择北京
选错了到地区tab页面重新选择上海
选择上海东方广场
选择上海东方广场1号
制作了该控件的jquery插件,格式采用bootstrap的。
调用方法:
input控件写成
<input class="form-control dropdown-toggle"id="dropdownMenu" type="text" value="" size="3"/>
在script里面调用
$('#dropdownMenu').endpoint();
方法:对input元素添加一个兄弟节点(after),该兄弟节点即为下拉菜单,兄弟节点各个元素对click事件进行不同响应。
1.关闭input里面的data-toggle,否则,bootstrap有一个全局监控,会在你点击地点后立即关闭下拉菜单
2.使用手动的toggle,开启,关闭下拉菜单
3.当同一个页面使用多个该控件的实例时候,为了避免控件之间元素的干扰,需要一个全局变量索引_index,表明是那个实例的,设置点击链接为 href='"#region'+_index+'"';这样各个实例之间不会干扰。
jQuery.parent(expr) //找父元素
jQuery.parents(expr) //找到所有祖先元素,不限于父元素
jQuery.children(expr) //查找所有子元素,只会找到直接的孩子节点,不会返回所有子孙
jQuery.contents() //查找下面的所有内容,包括节点和文本。
jQuery.prev() //查找上一个兄弟节点,不是所有的兄弟节点
jQuery.prevAll() //查找所有之前的兄弟节点
jQuery.next() //查找下一个兄弟节点,不是所有的兄弟节点
jQuery.nextAll() //查找所有之后的兄弟节点
jQuery.siblings() //查找兄弟节点,不分前后
jQuery.find(expr) //跟jQuery.filter(expr)完全不一样,jQuery.filter(expr)是从初始的
这个代码经过了好几天的艰辛制作,可以接受json数据,然后生成下拉菜单控件;
接收的数据格式为:
json_data= { 'tabs':[{'code':'region','name':'地区'},{'code':'node','name':'节点'},{'code':'endpoint','name':'连接点'}], 'content':[ {'region':{'code':'bj','name':'北京'}, 'node':{'code':'bjdf','name':'北京东方广场'}, 'endpoint':{'code':'bjdf1','name':'北京东方广场1号'} }, {'region':{'code':'bj','name':'北京'}, 'node':{'code':'bjdf','name':'北京东方广场'}, 'endpoint':{'code':'bjdf2','name':'北京东方广场2号'} }, {'region':{'code':'bj','name':'北京'}, 'node':{'code':'bjyz','name':'北京亦庄广场'}, 'endpoint':{'code':'bjyz1','name':'北京亦庄广场1号'} }, {'region':{'code':'bj','name':'北京'}, 'node':{'code':'bjyz','name':'北京亦庄广场'}, 'endpoint':{'code':'bjyz2','name':'北京亦庄广场2号'} }, {'region':{'code':'sh','name':'上海'}, 'node':{'code':'shdf','name':'上海东方广场'}, 'endpoint':{'code':'shdf1','name':'上海东方广场1号'} }, {'region':{'code':'sh','name':'上海'}, 'node':{'code':'shdf','name':'上海东方广场'}, 'endpoint':{'code':'shdf2','name':'上海东方广场2号'} }, {'region':{'code':'sh','name':'上海'}, 'node':{'code':'shdf','name':'上海东方广场'}, 'endpoint':{'code':'shdf3','name':'上海东方广场3号'} }, ] }
菜单的js代码
/* ========================================================= * endpoint.js * ========================================================= * Copyright 2016 xuyamin yamin_xu@163.com * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ========================================================= */ (function ($) { //这里放入插件代码 var endpoint_index=1;//实例索引,以便于生成的html块中的id不同 $.fn.endpoint = function(options) { //定义插件的名称,这里为endpoint var dft = { //以下为该插件的属性及其默认值 version: "0.1", //版本 data_url: "/account/endpoint", //json链接 level_length:2 //菜单层次,如果是三层,显示三层菜单,如果二层,显示二层菜单 }; var ops = $.extend(dft,options);//加入外部属性 json_data=$.ajax({url:dft['data_url'],dataType: "json", async:false}); var tab_data=$.parseJSON(json_data.responseText);//data的格式 {'tabs':[],'content':{ {},{}}} var levels=tab_data['tabs']; if (dft.level_length){levels=levels.slice(0,dft.level_length)} var style = ''; //调用默认的样式 var _this=this; var _index=endpoint_index; var path1=[];//记录已经选择的路径,应该是level1的code,level2的code,level3的code endpoint_index=endpoint_index+1; var dropdown_tabs='<div class="dropdown-menu" aria-labelledby="'+$(this).attr('id')+'">'+ '<ul class="nav nav-tabs" role="tablist">'; for (var i = 0; i < levels.length; i++){ item =levels[i]; dropdown_tabs+='<li role="presentation"><a href="#'+item['code']+_index+'" aria-controls="home"'+' value="'+item['code']+'" role="tab" data-toggle="tab">'+item['name']+'</a></li>' } dropdown_tabs+='</ul>'+ '<div class="tab-content">'; for (var i = 0; i < levels.length; i++){ //建立空的标签页内容 item =levels[i]; dropdown_tabs+='<div role="tabpanel" class="tab-pane" id="'+item['code']+_index+'" >'; dropdown_tabs+='</div>' } dropdown_tabs+='</div>'+'</div>'; function get_active_tab(){ //获取当前active的tab的名字 active_tab=$(_this).next().find('ul>li[class="active"]>a') return active_tab.attr('value') } function filter_array(choosed_code){ //该函数根据目前的choosed_code,筛选出content filter_str=""; current_tab=get_active_tab(); content=tab_data['content']; var list=content.filter(function (item){ return item[current_tab]['code']==choosed_code }); return list } function get_level_content(tab_code,content){ //content为经过过滤的列表,返回某个tab页面下面所有项目,不可重复 var list=[]; var dict={}; for (var i = 0; i < content.length; i++){ item=content[i]; if (!dict[item[tab_code]['code']]){ list.push({'code':item[tab_code]['code'],'name':item[tab_code]['name']}); dict[item[tab_code]['code']]=true } } return list } function tab_content(tab_code,content){ //该函数根据content,创建一个tab页;content是经过筛选过的 content_page='<div role="tabpanel" class="tab-pane active" id="'+tab_code+_index+'" >'; content_list=get_level_content(tab_code,content); for (var i = 0; i < content_list.length; i++){ item=content_list[i]; content_page+='<a value="'+item['code']+'">'+item['name']+'</a><br>' } content_page+='</div>'; //找到相应的标签页,将其内容替换 $(_this).next().find('#'+tab_code+_index).prop('outerHTML', content_page); } function get_next_tab(tab_code){ //根据目前code获取下个code,到最后一页则返回空 find_next=false; next_tab_code=false; for (var i = 0; i < levels.length; i++){ item=levels[i]; if (item['code']==tab_code) {find_next=true;continue;} if (find_next) {next_tab_code=item['code'];break;} } return next_tab_code } function choose(choosed_code){ //在当前tab下选择了某个标签,获取下个tab,以及下个tab的内容,并将其组合 current_tab=get_active_tab();//当前的tab页 next_tab=get_next_tab(current_tab); content_list=filter_array(choose_code); if (next_tab) {//有下个tab tab_content(next_tab,content_list);//刷新下个页面的内容 return next_tab;//返回选中tab } else{//没有下个tab return false } } $(this).after(dropdown_tabs); //下拉菜单载入 $(this).click(function(){ //点击input时候,初始化第一个标签 tab_code=levels[0]['code']; content_list=tab_data['content']; tab_content(tab_code,content_list); reg_click(tab_code); $(this).next().toggle(); $(this).next().find('a[href="#'+tab_id+'"]').tab('show'); }); function reg_click(tab_code){ //注册某个tab的click响应事件 tab_id=tab_code+_index; $(_this).next().find('#'+tab_id).find('a').click(function(e){ choose_code=$(this).attr('value'); next_tab=choose(choose_code);// next_tab_id=next_tab+_index; if (next_tab) { reg_click(next_tab);//重新注册一下click事件,因为该tab该被生成} $(this).parents('.dropdown-menu').children('.nav-tabs').find('a[href="#'+next_tab_id+'"]').tab('show'); } else{ //最后一个标签页 $(this).parents('.dropdown-menu').prev().val($(this).text()); $(this).parents('.dropdown-menu').toggle(); } }) } } })(jQuery);