自定义无限极简洁菜单展开(兼容IE8)
1.demo:单页html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义简洁无限极分类</title>
<link rel="stylesheet" type="text/css" href="js/plugins/tree-label/css/tree-label.css" />
<style>
.out {
font-size: 30px;
padding-left: 20px;
padding-top: 20px;
}
</style>
</head>
<body>
<div>
<div style="float: left; width: 20%">
<div id="box"></div>
</div>
<div id="content-out" class="out" style="float: left; width: 70%;">
<div>Joker</div>
</div>
</div>
<script type="text/javascript" src="https://libs.baidu.com/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="js/plugins/tree-label/js/tree-label.js"></script>
<script>
//数据格式
var data = [
{
id: '1003',
disabled: false,
label: '自定义分类3',
pid: null,
children: [
{id: '100301', disabled: false, label: '自定义分类100301', pid: '1003', children: [
{id: '10030101', disabled: true, label: '自定义分类10030100', pid: '100301', children: []},
{id: '10030102', disabled: true, label: '自定义分类10030200', pid: '100301', children: []},
{id: '10030103', disabled: true, label: '自定义分类10030300', pid: '100301', children: []},
{id: '10030104', disabled: true, label: '自定义分类10030400', pid: '100301', children: []},
{id: '10030105', disabled: true, label: '自定义分类10030500', pid: '100301', children: []},
]},
{id: '100302', disabled: false, label: '自定义分类100302', pid: '1003', children: []},
{id: '100303', disabled: false, label: '自定义分类100303', pid: '1003', children: []},
{id: '100304', disabled: false, label: '自定义分类100304', pid: '1003', children: []},
{id: '100305', disabled: false, label: '自定义分类100305', pid: '1003', children: []},
]
},
{
id: '1004',
disabled: false,
label: '自定义分类4',
pid: null,
children: [
{id: '100400', disabled: false, label: '自定义分类100301', pid: '1004', children: [
{id: '10040101', disabled: false, label: '自定义分类10040100', pid: '100400', children: []},
{id: '10040102', disabled: false, label: '自定义分类10040200', pid: '100400', children: []},
{id: '10040103', disabled: false, label: '自定义分类10040300', pid: '100400', children: []},
{id: '10040104', disabled: false, label: '自定义分类10040400', pid: '100400', children: []},
{id: '10040105', disabled: false, label: '自定义分类10040500', pid: '100400', children: []},
]},
{id: '100401', disabled: false, label: '自定义分类100401', pid: 1004, children: []},
{id: '100402', disabled: false, label: '自定义分类100402', pid: 1004, children: []},
{id: '100403', disabled: false, label: '自定义分类100403', pid: 1004, children: []},
{id: '100404', disabled: false, label: '自定义分类100404', pid: 1004, children: []},
{id: '100405', disabled: false, label: '自定义分类100405', pid: 1004, children: []},
]
},
];
var param = {
//父控件id
id: 'box',
//数据
data: data,
//展开速度
speed: 200,
//控件高度
height: $(this).height(),
//控件箭头图标
icon: 'img/jt_right.png',
//点击事件回调
clickCallback: function(id, isParent){
var content = {
id: id,
isParent: isParent,
isDisabled: false
}
$('#content-out').append('<div>'+JSON.stringify(content)+'</div>');
},
//disabled点击事件回调
disabledCallback: function(id, isParent){
var content = {
id: id,
isParent: isParent,
isDisabled: true
}
$('#content-out').append('<div>'+JSON.stringify(content)+'</div>');
}
}
//调用
Joker.init(param);
</script>
</body>
</html>
2. 框架css:tree-label.css
.height-joker {
height: 20px;
line-height: 20px;
}
.width-joker {
height: 20px;
line-height: 20px;
}
.text-content-joker {
height: 100%;
line-height: 100%;
vertical-align: top;
font-size: 20px;
}
.box-content-joker {
padding: 15px 0;
}
.box-content-joker:hover {
background-color: #ABA6AD;
}
.line-box-joker {
padding-left: 40px;
}
.open-joker {
transform:rotate(90deg);
-ms-transform:rotate(90deg); /* IE 9 */
-moz-transform:rotate(90deg); /* Firefox */
-webkit-transform:rotate(90deg); /* Safari 和 Chrome */
-o-transform:rotate(90deg); /* Opera */
}
.has-no-children-joker {
display: none;
}
.need-hide-joker {
display: none;
}
.none-select-joker{
-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
-webkit-text-size-adjust:none
}
.disable-select-joker:after {
content: attr(data-content);
}
.scroll-bar-joker {
scrollbar-face-color:#C1C1C1; /*滚动条3D表面(ThreedFace)的颜色*/
scrollbar-highlight-color:#fff; /*滚动条3D界面的亮边(ThreedHighlight)颜色*/
scrollbar-shadow-color:#eeeeee; /*滚动条3D界面的暗边(ThreedShadow)颜色*/
scrollbar-3dlight-color:#eeeeee; /*滚动条亮边框颜色*/
scrollbar-arrow-color:#000; /*滚动条方向箭头的颜色 */
scrollbar-track-color:#fff; /*滚动条的拖动区域(TrackBar)颜色*/
scrollbar-darkshadow-color:#fff; /*滚动条暗边框(ThreedDarkShadow)颜色*/
}
/*---滚动条默认显示样式--*/
::-webkit-scrollbar-thumb{
background-color: #C1C1C1;
height:50px;
outline-offset:-2px;
outline:2px solid #fff;
-webkit-border-radius:4px;
border: 2px solid #fff;
}
/*---鼠标点击滚动条显示样式--*/
::-webkit-scrollbar-thumb:hover{
background-color: #C1C1C1;
height:50px;
-webkit-border-radius:4px;
}
/*---滚动条大小--*/
::-webkit-scrollbar{
width:8px;
height:8px;
}
/*---滚动框背景样式--*/
::-webkit-scrollbar-track-piece{
background-color:#fff;
-webkit-border-radius:0;
}
3.框架js:tree-label.js
Joker = function () {
function initBox() {
var box = $('#' + id);
box.addClass('none-select-joker line-box-joker scroll-bar-joker')
box.css('overflow-y', 'auto');
box.attr('onselectstart', 'return false');
box.height(height);
box.append(setData(data));
}
function setData(data, pid, level) {
pid = getDefaultValue(pid);
level = getDefaultValue(level, 0);
var content = '<div class="' + isChildren(pid) + ' is-parent" p-id="' + getPid(pid) + '">';
for (var i = 0; i < data.length; i++) {
if (!hasValue(data[i])) {
break;
}
var has_children = hasValue(data[i]['children']) && data[i]['children'].length !== 0;
content += '<div class="box-content-joker" ' + getDisabled(data[i]) +
' style="margin-left: ' + level * 30 + 'px" ' +
's-id="' + data[i]["id"] + '">\n' +
' <div class="height-joker" style="vertical-align: middle">\n' +
' <span class="' + (has_children ? '' : 'has-no-children-joker') + '"><img class="height-joker width-joker" src="' + icon + '"></span>\n' +
' <span class="disable-select-joker text-content-joker" data-content="' + data[i]['label'] + '"></span>\n' +
' </div>\n' +
' </div>';
if (has_children) {
content += setData(data[i]['children'], data[i]['id'], level + 1);
}
}
content += '</div>';
return content;
}
function initClick() {
var isSmoothing = false;
$('.box-content-joker').click(function () {
if(isSmoothing){
return;
}
var next = $(this).next();
if ($(this).attr("disabled-joker")) {
if(typeof disabledCallback === "function"){
if(!next.hasClass('is-parent')){
disabledCallback($(this).attr('s-id'), false);
}else {
disabledCallback($(this).attr('s-id'), true);
}
}
return;
}
if(!next.hasClass('is-parent')){
if (typeof clickCallback === "function") {
clickCallback($(this).attr('s-id'), false);
}
return;
}
var useIe8 = useIE8();
if (next.is(':hidden')) {
//目前是隐藏的
if (useIe8) {
$(this).find('img').css({filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=1)'});
}
$(this).find('img').addClass('open-joker');
isSmoothing = true;
next.slideDown(speed, function () {
closeChildren();
});
} else {
if (useIe8) {
$(this).find('img.open-joker').css({filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=0)'});
}
$(this).find('img.open-joker').removeClass('open-joker');
isSmoothing = true;
next.slideUp(speed, function () {
closeChildren();
});
}
//所有子元素关闭
function closeChildren() {
isSmoothing = false;
//图标
if (useIe8) {
next.find('.is-parent').prev().find('img').css({filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=0)'});
}
next.find('.is-parent').prev().find('img').removeClass('open-joker');
//所有子元素
next.find('.is-parent').hide();
}
if (typeof clickCallback === "function") {
clickCallback($(this).attr('s-id'), true);
}
});
}
function getValue(param) {
id = getDefaultValue(param['id'], 'box');
speed = getDefaultValue(param['speed'], 100);
height = getDefaultValue(param['height'], $(this).height());
data = getDefaultValue(param['data']);
icon = getDefaultValue(param['icon'], 'img/jt_right.png');
clickCallback = getDefaultValue(param['clickCallback']);
disabledCallback = getDefaultValue(param['disabledCallback']);
}
var id;//父控件id
var data;//数据
var speed;//展开速度
var height;//控件高度
var icon;//控件箭头图标
var clickCallback;//点击事件回调
var disabledCallback;//disabled点击事件回调
return {
init: function (param) {
getValue(param);
initBox();
initClick();
}
}
}();
function hasValue(value) {
return typeof value !== 'undefined' && value !== undefined && value != null;
}
function getDisabled(data) {
return data['disabled'] ? 'disabled-joker=true' : '';
}
function isChildren(pid) {
return !!pid ? 'need-hide-joker' : '';
}
function getPid(pid) {
return !!pid ? pid : '';
}
function getDefaultValue(value, defaultValue) {
if (hasValue(value)) {
return value;
}
if (hasValue(defaultValue)) {
return defaultValue;
}
return "";
}
function useIE8() {
return $.browser.msie;
}
2021-09-08改进版
Joker = function () {
function initBox() {
box.height(height);
box.append('<div id="box_content" class="none-select-joker line-box-joker scroll-bar-joker"></div>');
var box_content = $('#box_content');
box_content.height(height - 32);
if (hasSearch) {
addSearchBox();
box_content.height(height - 85);
}
box_content.css('overflow-y', 'auto');
box.attr('onselectstart', 'return false');
box_content.append(setData(data));
}
function setData(data, pid, level) {
pid = getDefaultValue(pid);
level = getDefaultValue(level, 0);
var content = '<div class="' + isChildren(pid) + ' '+(level===0?'':'is-parent')+'" level="'+level+'" p-id="' + getPid(pid) + '">';
for (var i = 0; i < data.length; i++) {
if (!hasValue(data[i])) {
break;
}
var has_children = hasValue(data[i]['children']) && data[i]['children'].length !== 0;
content += '<div class="box-content-joker '+isRoot(pid)+'" ' + getDisabled(data[i]) +
' level="'+level+'" cgType="'+data[i]["cgType"]+'" cgPath="'+data[i]["cgPath"]+'" style="margin-left: ' + level * 30 + 'px" ' +
's-id="' + data[i]["id"] + '">\n' +
' <div class="height-joker" style="vertical-align: middle">\n' +
' <span class="' + (has_children ? '' : 'has-no-children-joker') + '"><img class="img-zqm height-joker width-joker" src="' + icon + '"></span>\n' +
' <span class="disable-select-joker text-content-joker" data-content="' + data[i]['label'] + '"></span>\n' +
' </div>\n' +
' </div>';
if (has_children) {
content += setData(data[i]['children'], data[i]['id'], level + 1);
}
}
content += '</div>';
return content;
}
function initSearchClick() {
var isClicking = false;
$('#search_btn_joker').click(function () {
if (isClicking) {
return;
}
isClicking = true;
var search_key = $('#search_text_joker').val();
if (!search_key) {
return;
}
setSearchData(getSearchData(data, 'label', 'children', search_key))
expandAll();
isClicking = false;
})
}
function initClick() {
box.click(function (e) {
var currentNode;
if ($(e.target).hasClass('box-content-joker')) {
currentNode = $(e.target);
} else if (e.target.nodeName.toUpperCase() === 'IMG') {
currentNode = $(e.target).parent().parent().parent('.box-content-joker');
} else if (e.target.nodeName.toUpperCase() === 'SPAN') {
currentNode = $(e.target).parent().parent('.box-content-joker');
} else if (e.target.nodeName.toUpperCase() === 'DIV') {
currentNode = $(e.target).parent('.box-content-joker');
}
if (currentNode && currentNode.hasClass('box-content-joker')) {
addClick(currentNode);
}
});
}
function addClick(currentNode) {
if (isSmoothing) {
return;
}
$('.box-content-joker').removeClass('select-joker');
currentNode.addClass('select-joker');
var next = currentNode.next();
if (currentNode.attr("disabled-joker")) {
if (typeof disabledCallback === "function") {
if (!next.hasClass('is-parent')) {
disabledCallback(currentNode.attr('s-id'), false, currentNode.find('span.text-content-joker').attr('data-content'));
} else {
disabledCallback(currentNode.attr('s-id'), true, currentNode.find('span.text-content-joker').attr('data-content'));
}
}
return;
}
if (!next.hasClass('is-parent')) {
if (typeof clickCallback === "function") {
clickCallback(currentNode.attr('s-id'), false, currentNode.find('span.text-content-joker').attr('data-content'));
}
return;
}
if (next.is(':hidden')) {
//目前是隐藏的
if (useIe8) {
currentNode.find('img').css({filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=1)'});
}
currentNode.find('img').addClass('open-joker');
isSmoothing = true;
next.slideDown(speed, function () {
closeChildren();
});
} else {
if (useIe8) {
currentNode.find('img.open-joker').css({filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=0)'});
}
currentNode.find('img.open-joker').removeClass('open-joker');
isSmoothing = true;
next.slideUp(speed, function () {
closeChildren();
});
}
//所有子元素关闭
function closeChildren() {
isSmoothing = false;
//图标
if (useIe8) {
next.find('.is-parent').prev().find('img').css({filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=0)'});
}
next.find('.is-parent').prev().find('img').removeClass('open-joker');
//所有子元素
next.find('.is-parent').hide();
}
if (typeof clickCallback === "function") {
clickCallback(currentNode.attr('s-id'), true, currentNode.find('span.text-content-joker').attr('data-content'));
}
}
function getValue(param) {
box = $('#' + getDefaultValue(param['id'], 'box'));
speed = getDefaultValue(param['speed'], 100);
hasSearch = getDefaultValue(param['hasSearch'], false);
height = getDefaultValue(param['height'], $(this).height());
data = getDefaultValue(param['data']);
icon = getDefaultValue(param['icon'], 'img/jt_right.png');
clickCallback = getDefaultValue(param['clickCallback']);
disabledCallback = getDefaultValue(param['disabledCallback']);
}
function addSearchBox() {
box.find('.row').remove();
var searchBox = '' +
'<div class="row" style="padding: 10px">\n' +
' <div class="col-lg-12">\n' +
' <div class="input-group group-zqm">\n' +
' <input type="text" id="search_text_joker" class="form-control group-zqm" placeholder="输入关键字">\n' +
' <span id="search_btn_joker" class="input-group-btn group-zqm">\n' +
' <button class="btn btn-default group-zqm" type="button"><i class="glyphicon glyphicon-search"></i></button>\n' +
' </span>\n' +
' </div>\n' +
' </div>\n' +
'</div>';
box.prepend(searchBox);
}
function setSearchData(new_data) {
var box_content = $('#box_content');
box_content.html('');
box_content.append(setData(new_data));
}
//展开单个
function expand(id, ex_self) {
if (isSmoothing) {
return;
}
closeAll();
var currentNode = $("[s-id='"+id+"']")
if(!currentNode){
return;
}
$('.select-joker').removeClass('select-joker');
currentNode.addClass('select-joker');
var nodeList = [];
nodeList = $.merge(nodeList, currentNode);
nodeList = $.merge(nodeList, currentNode.parents('.is-parent'));
nodeList = $.merge(nodeList, currentNode.parents('.is-root'));
for (var i = 0; i < nodeList.length; i++) {
var current = $(nodeList[i]);
ex_self = !!ex_self?true:current.attr('s-id') !== currentNode.attr('s-id');
if(current.next().hasClass('is-parent') && ex_self){
//图标
if (useIe8) {
current.find('img').css({filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=1)'});
}
current.find('img').addClass('open-joker');
//所有子元素
current.next().show();
}
if(current.hasClass('is-parent')){
//图标
if (useIe8) {
current.prev().find('img').css({filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=1)'});
}
current.prev().find('img').addClass('open-joker');
//所有子元素
current.show();
}
}
}
//展开所有
function expandAll() {
if (isSmoothing) {
return;
}
//图标
if (useIe8) {
box.find('.is-parent').prev().find('img').css({filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=1)'});
}
box.find('.is-parent').prev().find('img').addClass('open-joker');
//所有子元素
box.find('.is-parent').show();
}
//关闭所有
function closeAll() {
if (isSmoothing) {
return;
}
//图标
if (useIe8) {
box.find('.is-parent').prev().find('img').css({filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=0)'});
}
box.find('.is-parent').prev().find('img').removeClass('open-joker');
box.find('.is-parent').hide();
box.find('.is-root').show();
}
var box;//主控件
var data;//数据
var hasSearch;//是否展示搜索框
var speed;//展开速度
var height;//控件高度
var icon;//控件箭头图标
var isSmoothing = false;
var clickCallback;//点击事件回调
var disabledCallback;//disabled点击事件回调
var useIe8 = useIE8();
var isInit = false;
return {
init: function (param) {
getValue(param);
initBox();
initSearchClick();
initClick();
isInit = true;
},
initHeight: function (height_new) {
height = height_new;
},
setNewData: function (new_data) {
if(!isInit){
return null;
}
data = new_data;
setSearchData(new_data)
},
getCurrentSelect: function(){
if(!isInit){
return null;
}
var currentNode = box.find('.select-joker');
if(currentNode && currentNode.length !== 0){
currentNode = $(currentNode[0]);
return {
id: getDefaultValue(currentNode.attr('s-id'), ''),
cgPath: getDefaultValue(currentNode.attr('cgPath'), ''),
cgType: getDefaultValue(currentNode.attr('cgType'), ''),
isRoot: getDefaultValue(currentNode.hasClass('is-root'), ''),
isParent: currentNode.next().hasClass('is-parent'),
text: getDefaultValue(currentNode.find('span.text-content-joker').attr('data-content'), '')
}
}
return null;
},
needSearchBox: function (needSearch) {
if(!isInit){
return;
}
var box_content = $('#box_content');
if (needSearch) {
addSearchBox();
box_content.height(height - 85);
} else {
box.find('.row').remove();
box_content.height(height - 32);
}
},
expand: function (id, ex_self) {
if(!isInit){
return;
}
expand(id, ex_self);
},
expandAll: function () {
if(!isInit){
return;
}
expandAll();
},
closeAll: function () {
if(!isInit){
return;
}
closeAll();
}
}
}();
function hasValue(value) {
return typeof value !== 'undefined' && value !== undefined && value != null && value !== "null";
}
function getDisabled(data) {
return data['disabled'] ? 'disabled-joker=true' : '';
}
function isChildren(pid) {
return !!pid ? 'need-hide-joker' : '';
}
function isRoot(pid) {
return !pid ? 'is-root' : '';
}
function getPid(pid) {
return !!pid ? pid : '';
}
function getDefaultValue(value, defaultValue) {
if (hasValue(value)) {
return value;
}
if (hasValue(defaultValue)) {
return defaultValue;
}
return "";
}
function useIE8() {
jQuery.browser = {};
jQuery.browser.msie = false;
jQuery.browser.version = 0;
if (navigator.userAgent.match(/MSIE ([0-9]+)\./)) {
jQuery.browser.msie = true;
jQuery.browser.version = RegExp.$1;
}
return $.browser.msie;
}
function getSearchData(data, field, childrenField, searchKey) {
var result = [];
for (var i = 0; i < data.length; i++) {
var node = deepClone(data[i], childrenField);
var hasChildren = false;
if (data[i][childrenField] && Array.isArray(data[i][childrenField])) {
var children = getSearchData(data[i][childrenField], field, childrenField, searchKey);
node[childrenField] = children;
if (children.length !== 0) {
hasChildren = true;
}
}
if (hasChildren) {
result.push(node);
} else if (node[field] && typeof node[field] === 'string' && node[field].indexOf(searchKey) !== -1) {
result.push(node);
}
}
return result;
}
function deepClone(target, ex_field) {
var result;
if (typeof target === 'object') {
if (Array.isArray(target)) {
result = [];
for (var i in target) {
if (i === ex_field) {
continue;
}
result.push(deepClone(target[i]))
}
} else if (target === null) {
result = null;
} else if (target.constructor === RegExp) {
result = target;
} else {
result = {};
for (var j in target) {
if (j === ex_field) {
continue;
}
result[j] = deepClone(target[j]);
}
}
} else {
result = target;
}
return result;
}
4.所用图片
下图右键即可另存为,或者直接复制地址用浏览器打开再保存图片
https://img2020.cnblogs.com/blog/1345528/202108/1345528-20210813235523540-462798512.png
5.说明
- IE8兼容伪元素,所以文字使用伪元素展示,不易被选中
- IE8不兼容transform属性,所以使用滤镜filter来达到图片旋转目的
- 以上框架使用Jquery作为基础,且在1.4.2版本下通过测试
6.多个浏览器兼容

Firefox

Edge

IE8


浙公网安备 33010602011771号