/*
|
* email: bigablecat@hotmail.com
|
* Date: 2018-04-14
|
*/
|
|
/**
|
* @param zTreeId the ztree id used to get the ztree object
|
* @param searchField selector of your input for fuzzy search
|
* @param isHighLight whether highlight the match words, default true
|
* @param isExpand whether to expand the node, default false
|
*
|
* @returns
|
*/
|
function fuzzySearch(zTreeId, searchField, isHighLight, isExpand){
|
var zTreeObj = $.fn.zTree.getZTreeObj(zTreeId);//get the ztree object by ztree id
|
if(!zTreeObj){
|
alert("fail to get ztree object");
|
}
|
var nameKey = zTreeObj.setting.data.key.name; //get the key of the node name
|
isHighLight = isHighLight===false?false:true;//default true, only use false to disable highlight
|
isExpand = isExpand?true:false; // not to expand in default
|
zTreeObj.setting.view.nameIsHTML = isHighLight; //allow use html in node name for highlight use
|
|
var metaChar = '[\\[\\]\\\\\^\\$\\.\\|\\?\\*\\+\\(\\)]'; //js meta characters
|
var rexMeta = new RegExp(metaChar, 'gi');//regular expression to match meta characters
|
|
// keywords filter function
|
function ztreeFilter(zTreeObj,_keywords,callBackFunc) {
|
if(!_keywords){
|
_keywords =''; //default blank for _keywords
|
}
|
|
// function to find the matching node
|
function filterFunc(node) {
|
if(node && node.oldname && node.oldname.length>0){
|
node[nameKey] = node.oldname; //recover oldname of the node if exist
|
}
|
zTreeObj.updateNode(node); //update node to for modifications take effect
|
if (_keywords.length == 0) {
|
//return true to show all nodes if the keyword is blank
|
zTreeObj.showNode(node);
|
zTreeObj.expandNode(node,isExpand);
|
return true;
|
}
|
//transform node name and keywords to lowercase
|
if (node[nameKey] && node[nameKey].toLowerCase().indexOf(_keywords.toLowerCase())!=-1) {
|
if(isHighLight){ //highlight process
|
//a new variable 'newKeywords' created to store the keywords information
|
//keep the parameter '_keywords' as initial and it will be used in next node
|
//process the meta characters in _keywords thus the RegExp can be correctly used in str.replace
|
var newKeywords = _keywords.replace(rexMeta,function(matchStr){
|
//add escape character before meta characters
|
return '\\' + matchStr;
|
});
|
node.oldname = node[nameKey]; //store the old name
|
var rexGlobal = new RegExp(newKeywords, 'gi');//'g' for global,'i' for ignore case
|
//use replace(RegExp,replacement) since replace(/substr/g,replacement) cannot be used here
|
node[nameKey] = node.oldname.replace(rexGlobal, function(originalText){
|
//highlight the matching words in node name
|
var highLightText =
|
'<span style="color: whitesmoke;background-color: darkred;">'
|
+ originalText
|
+'</span>';
|
return originalText;
|
});
|
zTreeObj.updateNode(node); //update node for modifications take effect
|
}
|
zTreeObj.showNode(node);//show node with matching keywords
|
return true; //return true and show this node
|
}
|
|
zTreeObj.hideNode(node); // hide node that not matched
|
return false; //return false for node not matched
|
}
|
|
var nodesShow = zTreeObj.getNodesByFilter(filterFunc); //get all nodes that would be shown
|
processShowNodes(nodesShow, _keywords);//nodes should be reprocessed to show correctly
|
}
|
|
/**
|
* reprocess of nodes before showing
|
*/
|
function processShowNodes(nodesShow,_keywords){
|
if(nodesShow && nodesShow.length>0){
|
//process the ancient nodes if _keywords is not blank
|
if(_keywords.length>0){
|
$.each(nodesShow, function(n,obj){
|
var pathOfOne = obj.getPath();//get all the ancient nodes including current node
|
if(pathOfOne && pathOfOne.length>0){
|
//i < pathOfOne.length-1 process every node in path except self
|
for(var i=0;i<pathOfOne.length-1;i++){
|
zTreeObj.showNode(pathOfOne[i]); //show node
|
zTreeObj.expandNode(pathOfOne[i],true); //expand node
|
}
|
}
|
});
|
}else{ //show all nodes when _keywords is blank and expand the root nodes
|
var rootNodes = zTreeObj.getNodesByParam('level','0');//get all root nodes
|
$.each(rootNodes,function(n,obj){
|
zTreeObj.expandNode(obj,true); //expand all root nodes
|
});
|
}
|
}
|
}
|
|
//listen to change in input element
|
$(searchField).bind('input propertychange', function() {
|
var _keywords = $(this).val();
|
searchNodeLazy(_keywords); //call lazy load
|
});
|
|
var timeoutId = null;
|
var lastKeyword = '';
|
// excute lazy load once after input change, the last pending task will be cancled
|
function searchNodeLazy(_keywords) {
|
if (timeoutId) {
|
//clear pending task
|
clearTimeout(timeoutId);
|
}
|
timeoutId = setTimeout(function() {
|
if (lastKeyword === _keywords) {
|
return;
|
}
|
ztreeFilter(zTreeObj,_keywords); //lazy load ztreeFilter function
|
// $(searchField).focus();//focus input field again after filtering
|
lastKeyword = _keywords;
|
}, 500);
|
}
|
}
|