Files
Backend-Api/ServiceHost/wwwroot/AdminTheme/DynamicMenu/checkTree.js
2024-07-05 21:36:15 +03:30

211 lines
8.2 KiB
JavaScript

/**
*name: jquery.checkTree
*author: Elyor Latipov
*version: 0.1.1
*/
/**input data format:
[{
item:{id:'id', label:'label',value:1, checked:false},
chidren:[{
item:{id:'id', label:'label', checked:false},
chidren:[...]
}]
}, ....]
*/
(function ($) {
jQuery.fn.checkTree = function (settings) {
settings = $.extend({
data: [], // input data which will be used to initilze the tree
onExpand: null, // an event will be triggered when the tree node was expanded
onCollapse: null, // an event will be triigered when the tree node was collapsed
onPreCheck: null, // an event will be triggered before the tree node was checked
onCheck: null, // an event will be triggered when the tree node was checked
onUnCheck: null, // an event will be triggered when the tree node was unchecked
onLabelHoverOver: null,// an event will be triggered when mouse hover over the label
onLabelHoverOut: null // an event will be triggered when mouse hover out the label
}, settings);
var container = $(this), $tree = this;
//get children html tag string
function getChildrenHtml(treesdata) {
var result = '', len = treesdata.length, node, clen, arrowClass, checkedClass = ''
checkedChildren;
for (i = 0; i < len; i++) {
node = treesdata[i];
$.data($tree, node.item.id, node); //attach node data to node id
clen = node.children ? node.children.length : 0;
arrowClass = 'collapsed';
if (clen === 0) {
arrowClass = 'nochildren';
checkClass = node.item.checked ? 'checked' : '';
} else {
var checkedChildren = $.grep(node.children, function (el) {
return el.item.checked;
});
checkClass = checkedChildren.length === 0 ? '' : checkedChildren.length === clen ? 'checked' : 'half_checked';
}
result += '<li rel="' + node.item.id + '"><div class="arrow ' + arrowClass + '"></div><div class="checkbox ' + checkClass + '"><input type="hidden" value="'+node.item.value+'"/></div><label>' +
node.item.label + '</label></li>';
}
return result;
}
//display children node with data source
function updateChildrenNodes($li, data, isExpanded) {
if (data.children && data.children.length > 0) {
var innerHtml = isExpanded ? '<ul>' : '<ul style="display:none;">';
innerHtml += getChildrenHtml(data.children) + '</ul>';
$li.append(innerHtml);
}
$li.addClass('updated');
}
//initialize the check tree with the input data
(function initalCheckTree() {
var treesHtml = '<ul class="checktree">';
treesHtml += getChildrenHtml(settings.data);
container.empty().append(treesHtml + '<ul>');
})();
//bind select change to checkbox
container.off('selectchange', '.checkbox').on('selectchange', '.checkbox', function () {
if (settings.onPreCheck) {
if (!settings.onPreCheck($(this).parent())) {
return;
}
}
var $li = $(this).parent();
var dataSource = $.data($tree, $li.attr('rel'));
var $all = $(this).siblings('ul').find('.checkbox');
var $checked = $all.filter('.checked');
//all children checked
if ($all.length === $checked.length) {
$(this).removeClass('half_checked').addClass('checked');
dataSource.item.checked = true;
if (settings.onCheck) {
settings.onCheck($li);
}
//all children are unchecked
} else if ($checked.length === 0) {
dataSource.item.checked = false;
$(this).removeClass('checked').removeClass('half_checked');
if (settings.onUnCheck) {
settings.onUnCheck($li);
}
//some children are checked
} else {
dataSource.item.checked = false;
if (settings.onHalfCheck && !$(this).hasClass('half_checked')) {
settings.onHalfCheck($li);
}
$(this).removeClass('checked').addClass('half_checked');
}
});
//expand and collapse node
container.off('click', '.arrow').on('click', '.arrow', function () {
if ($(this).hasClass('nochildren')) {
return;
}
var $li = $(this).parent();
if (!$li.hasClass('updated')) {
updateChildrenNodes($li, $.data($tree, $li.attr('rel')), true);
$(this).removeClass('collapsed').addClass('expanded');
if (settings.onExpand) {
settings.onExpand($li);
}
} else {
$(this).siblings("ul").toggle();
if ($(this).hasClass('collapsed')) {
$(this).removeClass('collapsed').addClass('expanded');
if (settings.onExpand) {
settings.onExpand($li);
}
} else {
$(this).removeClass('expanded').addClass('collapsed');
if (settings.onCollapse) {
settings.onCollapse($li);
}
}
}
});
//check and uncheck node
container.off('click', '.checkbox').on('click', '.checkbox', function () {
var $li = $(this).parent();
var dataSource = $.data($tree, $li.attr('rel'));
if (!$li.hasClass('updated')) {
updateChildrenNodes($li, dataSource, false);
}
if (settings.onPreCheck) {
if (!settings.onPreCheck($li)) {
return;
}
}
$(this).removeClass('half_checked').toggleClass('checked');
if ($(this).hasClass('checked')) {
dataSource.item.checked = true;
if (settings.onCheck) {
settings.onCheck($li, true);
}
$(this).siblings('ul').find('.checkbox').not('.checked').removeClass('half_checked').addClass('checked').each(function () {
var $subli = $(this).parent();
$.data($tree, $subli.attr('rel')).item.checked = true;
if (settings.onCheck) {
settings.onCheck($subli, false);
}
});
} else {
dataSource.item.checked = false;
if (settings.onUnCheck) {
settings.onUnCheck($li, true);
}
$(this).siblings('ul').find('.checkbox').filter('.checked').removeClass('half_checked').removeClass('checked').each(function () {
var $subli = $(this).parent();
$.data($tree, $subli.attr('rel')).item.checked = false;
if (settings.onUnCheck) {
settings.onUnCheck($subli, false);
}
});
}
$(this).parents('ul').siblings('.checkbox').trigger('selectchange');
});
//click label also trigger check action
container.off('click', 'label').on('click', 'label', function () {
$(this).prev('.checkbox').trigger('click');
});
container.off('mouseenter', 'label').on('mouseenter', 'label', function () {
$(this).addClass("hover");
if (settings.onLabelHoverOver) settings.onLabelHoverOver($(this).parent());
});
container.off('mouseleave', 'label').on('mouseleave', 'label', function () {
$(this).removeClass("hover");
if (settings.onLabelHoverOut) settings.onLabelHoverOut($(this).parent());
});
};
})(jQuery);