將時間類型的篩選框改成樹形顯示
改之前:
改之後:
用到了Jquery EasyUI的Tree
和moment.js
代码如下:
// 給表頭綁定右擊事件
var table = $("#" + headTableId + " th");
// 判断鼠标左/右击
table.mousedown(function (e) {
if (3 === e.which) { // 鼠標右擊
addSearchFrame($(this));
} else if (1 === e.which) { // 鼠標左擊
}
});
function addSearchFrame(obj) {
let key;
const index = obj.index();
// 为了使弹窗过滤条件保存后禁用掉表头的右键点击
if (obj.hasClass("not-right-click")) {
return;
}
if (obj.attr("column-param")) {
key = obj.attr("column-param");
} else {
key = obj.attr("data-param");
}
var filtrateBox = $(".filtrate-box");
$.ajax({
url: window.location.pathname.substr(window.location.pathname.lastIndexOf('/') + 1) + "?action=getAllHead",
type: "post",
data: {column: key},
success: function (result) {
var html = "";
var year = "";
var month = "";
var day = "";
let list = [];
let dateList = [];
var dateTree = [];
result.forEach(function (data) {
if (data != null) {
let colunmResult = findValue(data, obj.attr("header-param"));
list.push(colunmResult);
}
});
if (key.contains('date') || key.contains('Date')) {
// 如果篩選條件是時間類型,就將list重組為樹形結構並顯示
html += "<ul id='tt1'></ul>"
let yearMap = {}
// 將2022/01/01這種單條時間,構造成jQuery-tree所需要的JSON數據格式
list.forEach(function (s) {
s = moment(s.toString(), "YYYY/MM/DD").format('YYYY年M月D日');
dateList.push(s);
year = s.substring(0, s.indexOf('年'));
month = s.substring(s.indexOf('年')+1, s.indexOf('月'));
day = s.substring(s.indexOf('月')+1, s.indexOf('日'));
/*yearMap = {
'y1': {
'M1': set['d1', 'd2'],
'M2': ['d1', 'd2']
},
'y2': {
}
}*/
let monthMap = {}
if (yearMap[year]) {
monthMap = yearMap[year]
} else {
yearMap[year] = monthMap
}
let daySet = new Set()
if (monthMap[month]) {
daySet = monthMap[month];
} else {
monthMap[month] = daySet;
}
daySet.add(day)
});
for (let year in yearMap) {
let yearObj = {
"id":year,
"text": year+"年",
"type": "year",
"iconCls":"icon-save",
"children": []
};
dateTree.push(yearObj)
for (let month in yearMap[year]) {
let monthObj = {
"id": month,
"text": month + "月",
"children": []
};
yearObj.children.push(monthObj)
for (let day of yearMap[year][month]) {
let dayObj = {
"id": year + '-' + month + '-' + day,
"text": day + "日",
}
monthObj.children.push(dayObj)
}
}
}
var innerHTML = "<div id='searchFilterDiv'>" +
"<input type='search' value='' size='35' placeholder='搜索' οnkeyup='searchFilterForDateTree()'>" +
"<span style='cursor:pointer'><i class='search_right' οnclick='searchFilterByInput()'></i></span>" +
"</div>" +
"<div class='filtrate'>" +
"<ul>" +
"<li><input type='checkbox' value='checkedAll' οnclick='allCheckedForTree()' id='allChecked'><span style='margin-left:15px'>全選</span></li>" +
html +
"</ul>" +
"</div>" +
"<div class='searchBtn'>" +
"<input class='btn' type='submit' name='submit' value='重置所有' οnclick='clearData()'>" +
"<input class='btn' type='submit' name='submit' value='確 定' οnclick='selectDataByDateTree(" + index + ")'>" +
"<input class='btn' type='button' name='cancel' value='取 消' οnclick='frameClose()'>" +
"</div>";
} else {
list.forEach(function (s) {
let str = s;
if (typeof(s) === "string"){
str = s.replaceAll("\"","\"").replaceAll("\'","\'");
}
if(!(s == undefined || s==null || s=="")){
html += "<li><input type='checkbox' value=\"" + str + "\" name='filter' οnclick='unChecked()'>" +
"<span class='columnDesc'>" + s + "</span></li>";
}
});
var innerHTML = "<div id='searchFilterDiv'>" +
"<input type='search' value='' size='35' placeholder='搜索' οnkeyup='searchFilterByInput()'>" +
"<span style='cursor:pointer'><i class='search_right' οnclick='searchFilterByInput()'></i></span>" +
"</div>" +
"<div class='filtrate'>" +
"<ul>" +
"<li><input type='checkbox' value='checkedAll' οnclick='allChecked()' id='allChecked'><span style='margin-left:15px'>全選</span></li>" +
html +
"</ul>" +
"</div>" +
"<div class='searchBtn'>" +
"<input class='btn' type='submit' name='submit' value='重置所有' οnclick='clearData()'>" +
"<input class='btn' type='submit' name='submit' value='確 定' οnclick='selectData(" + index + ")'>" +
"<input class='btn' type='button' name='cancel' value='取 消' οnclick='frameClose()'>" +
"</div>";
}
// 初始化
filtrateBox.text("");
filtrateBox.append(innerHTML);
// 將日期類型的json傳給easyui-tree插件來初始化數據
addDataToTree(dateTree);
// 对选中的过滤条件进行还原
if (filterMap[key] != null) {
if (key.contains('date') || key.contains('Date')) {
var nodes = $('#tt1').tree('getChecked', 'unchecked'); //获取未选中的节点
nodes.forEach(s => {
var ifLeaf = $("#tt1").tree('isLeaf', s.target);
if (ifLeaf) {
filterMap[key].forEach(function (value) {
value = moment(value.toString(), "YYYY/MM/DD").format('YYYY-M-D')
if (value === s.id) {
$("#tt1").tree('check', s.target);
}
})
}
});
/**
* 使全選框也對應還原後的狀態來選擇是否勾選
*/
let searchStr = $("#searchFilterDiv input[type='search']").val();
let allLength = $('#tt1').tree('getChecked', ['checked', 'unchecked', 'indeterminate']).length;
let checkedLength = $('#tt1').tree('getChecked').length;
if (searchStr !== "" && allLength !== checkedLength) {
$(".filtrate #allChecked").prop("checked", false);
} else {
$(".filtrate #allChecked").prop("checked", true);
}
} else {
$(".filtrate>ul").find("input").each(function () {
var domValue = $(this);
filterMap[key].forEach(function (value) {
if (value === domValue.val()) {
domValue.attr("checked", "true");
}
})
});
}
}
filtrateBox.show();
$("#searchFilterDiv input[type='search']").focus();
}
});
}
function addDataToTree(dateTreeJson) {
// 初始化日期篩選框的數據
$('#tt1').tree({
data:dateTreeJson,
method: "get",
checkbox:true,
cascadeCheck:true
});
}
// 針對日期篩選框中的樹形複選框的全選和取消全選
function allCheckedForTree() {
var roots = $('#tt1').tree('getRoots');//返回tree的所有根节点数组
var nodes = $('#tt1').tree('getChecked', 'unchecked'); //获取未选中的节点
if (nodes.length > 0) {
//全选
for (var i = 0; i < roots.length; i++) {
var node = $('#tt1').tree('find', roots[i].id);//查找节点
$('#tt1').tree('check', node.target);//将得到的节点选中
}
} else {
for (var i = 0; i < roots.length; i++) {
var node = $('#tt1').tree('find', roots[i].id);
$('#tt1').tree('uncheck', node.target);
}
}
}
(function ($) {
$.extend($.fn.tree.methods, {
/**
* 扩展easyui tree的搜索方法
* @param tree easyui tree的根DOM节点(UL节点)的jQuery对象
* @param searchText 检索的文本
* @param this-context easyui tree的tree对象
*/
search: function (jqTree, searchText) {
//easyui tree的tree对象。可以通过tree.methodName(jqTree)方式调用easyui tree的方法
var tree = this;
//获取所有的树节点
var nodeList = getAllNodes(jqTree, tree);
//如果没有搜索条件,则展示所有树节点
searchText = $.trim(searchText);
if (searchText == "") {
for (var i = 0; i < nodeList.length; i++) {
$(".tree-node-targeted", nodeList[i].target).removeClass("tree-node-targeted");
$(nodeList[i].target).show();
}
//展开已选择的节点(如果之前选择了)
var selectedNode = tree.getSelected(jqTree);
if (selectedNode) {
tree.expandTo(jqTree, selectedNode.target);
}
return;
}
//搜索匹配的节点并高亮显示
var matchedNodeList = [];
if (nodeList && nodeList.length > 0) {
var node = null;
for (var i = 0; i < nodeList.length; i++) {
node = nodeList[i];
if (isMatch(searchText, node.text)) {
matchedNodeList.push(node);
}
}
//隐藏所有节点
for (var i = 0; i < nodeList.length; i++) {
$(".tree-node-targeted", nodeList[i].target).removeClass("tree-node-targeted");
$(nodeList[i].target).hide();
}
//折叠所有节点
tree.collapseAll(jqTree);
//展示所有匹配的节点以及父节点
for (var i = 0; i < matchedNodeList.length; i++) {
showMatchedNode(jqTree, tree, matchedNodeList[i]);
}
}
},
/**
* 展示节点的子节点(子节点有可能在搜索的过程中被隐藏了)
* @param node easyui tree节点
*/
showChildren: function (jqTree, node) {
//easyui tree的tree对象。可以通过tree.methodName(jqTree)方式调用easyui tree的方法
var tree = this;
//展示子节点
if (!tree.isLeaf(jqTree, node.target)) {
var children = tree.getChildren(jqTree, node.target);
if (children && children.length > 0) {
for (var i = 0; i < children.length; i++) {
if ($(children[i].target).is(":hidden")) {
$(children[i].target).show();
}
}
}
}
},
/**
* 将滚动条滚动到指定的节点位置,使该节点可见(如果有滚动条才滚动,没有滚动条就不滚动)
* @param param {
* treeContainer: easyui tree的容器(即存在滚动条的树容器)。如果为null,则取easyui tree的根UL节点的父节点。
* targetNode: 将要滚动到的easyui tree节点。如果targetNode为空,则默认滚动到当前已选中的节点,如果没有选中的节点,则不滚动
* }
*/
scrollTo: function (jqTree, param) {
//easyui tree的tree对象。可以通过tree.methodName(jqTree)方式调用easyui tree的方法
var tree = this;
//如果node为空,则获取当前选中的node
var targetNode = param && param.targetNode ? param.targetNode : tree.getSelected(jqTree);
if (targetNode != null) {
//判断节点是否在可视区域
var root = tree.getRoot(jqTree);
var $targetNode = $(targetNode.target);
var container = param && param.treeContainer ? param.treeContainer : jqTree.parent();
var containerH = container.height();
var nodeOffsetHeight = $targetNode.offset().top - container.offset().top;
if (nodeOffsetHeight > (containerH - 30)) {
var scrollHeight = container.scrollTop() + nodeOffsetHeight - containerH + 30;
container.scrollTop(scrollHeight);
}
}
}
});
/**
* 展示搜索匹配的节点
*/
function showMatchedNode(jqTree, tree, node) {
//展示所有父节点
$(node.target).show();
$(".tree-title", node.target).addClass("tree-node-targeted");
var pNode = node;
while ((pNode = tree.getParent(jqTree, pNode.target))) {
$(pNode.target).show();
}
//展开到该节点
tree.expandTo(jqTree, node.target);
//如果是非叶子节点,需折叠该节点的所有子节点
if (!tree.isLeaf(jqTree, node.target)) {
tree.collapse(jqTree, node.target);
}
}
/**
* 判断searchText是否与targetText匹配
* @param searchText 检索的文本
* @param targetText 目标文本
* @return true-检索的文本与目标文本匹配;否则为false.
*/
function isMatch(searchText, targetText) {
return $.trim(targetText) != "" && targetText.indexOf(searchText) != -1;
}
/**
* 获取easyui tree的所有node节点
*/
function getAllNodes(jqTree, tree) {
var allNodeList = jqTree.data("allNodeList");
if (!allNodeList) {
var roots = tree.getRoots(jqTree);
allNodeList = getChildNodeList(jqTree, tree, roots);
jqTree.data("allNodeList", allNodeList);
}
return allNodeList;
}
/**
* 定义获取easyui tree的子节点的递归算法
*/
function getChildNodeList(jqTree, tree, nodes) {
var childNodeList = [];
if (nodes && nodes.length > 0) {
var node = null;
for (var i = 0; i < nodes.length; i++) {
node = nodes[i];
childNodeList.push(node);
if (!tree.isLeaf(jqTree, node.target)) {
var children = tree.getChildren(jqTree, node.target);
childNodeList = childNodeList.concat(getChildNodeList(jqTree, tree, children));
}
}
}
return childNodeList;
}
})(jQuery);
// 根據輸入框中的內容顯示樹形節點
function searchFilterForDateTree() {
var searchText = $("#searchFilterDiv input[ type='search' ] ").val();
$("#tt1").tree("search", searchText);
}
// 根據選中的日期查詢相關數據
function selectDataByDateTree(index) {
if (toDoSelect) {
let searchStr = $("#searchFilterDiv input[type='search']").val();
/**
* 在条件过滤框里选中的条件
* @type {Array}
*/
var checkedDomList = [];
var checkedDom = $("#tt1").tree('getChecked');
checkedDom.forEach(s => {
var ifLeaf = $("#tt1").tree('isLeaf', s.target);
if (ifLeaf) {
checkedDomList.push(moment(s.id.toString(), "YYYY-M-D").format('YYYY/MM/DD'));
}
});
let allLength = $('#tt1').tree('getChecked', ['checked', 'unchecked', 'indeterminate']).length;
let checkedLength = $('#tt1').tree('getChecked').length;
if (searchStr !== "" && allLength !== checkedLength) {
$(".filtrate #allChecked").prop("checked", false);
}
// 保存需要显示的tr和表头id
if (checkedDomList.length > 0) {
filterMap[headList[index]] = checkedDomList;
saveHeadList[headList[index]] = headNameList[index];
} else {
delete filterMap[headList[index]];
delete saveHeadList[headList[index]];
}
frameClose();
saveFilterMap();
} else {
frameClose();
}
}