在需要表示级联、层级的关系中,Tree作为最直观的表达方式常出现在组织架构、权限选择等层级关系中。典型的表现形试类似于:

一颗树的生成常常包括三个部分:1)数据库设计;2)后台程序;3)前端代码。那么,具体是怎么样的呢?

一、数据库设计

数据库设计对于树的表达常会包含这么几个类似意思的字段:

parent_id、id、name。

id:用于描述自己;

parent_id:用于描述自己的上一级;

name:用于描述自己的名称;

例如:总办(id=3,parent_id=0,name=总办),客户服务中心(id=10,parent_id=3,name=客户服务中心) ,客户部(id=12,parent_id=10,name=客户部)。由此建立了三级层级关系。

二、后台程序

对于一个层级,可能会用于描述部门关系,还可能用于描述菜单关系等等,不同的用途有不同的数据库设计字段。但为了程序的通用性,不可能为一了一个表或功能做单独的前端插件,因此就要在后台为前端插件需要使用到的字段做一个规范(或者在数据库设计中做规范)。在此为“树结构”在后台作这样的规范:

     /// <summary>

     /// 层级

     /// </summary>

     public class vmHierarchy

     {

         public int id { get; set; }

         public int pid { get; set; }

         public string name { get; set; }

         public object sub { get; set; }

         public int status { get; set; }

 }

Pid:用于描述上级关系;

Sub:用于描述子级关系;

Status:用于描述自身状态或特殊标识;

以做部门的层级关系为例:分为两个部分:

1)  取数据:

        /// <summary>

        /// 取部门层级

        /// </summary>

        /// <returns></returns>

        public List<vmHierarchy> GetDepartmentRelation()

        {

            List<vmHierarchy> vmdrlist = new List<vmHierarchy>();

            using (var ctx = DB.ContextForName(DBConnection.DefaultConnection).UseTransaction(true))

            {

                List<au_Department> adlist = new List<au_Department>();

                adlist = base.GetModelAll();

                vmdrlist = GetDepartmentRelationSub(, adlist);

            }

            return vmdrlist;

        }

2) 定层级:

       /// <summary>

        /// 取部门层级-子级

        /// </summary>

        /// <param name="parentid"></param>

        /// <param name="adlist"></param>

        /// <returns></returns>

        public List<vmHierarchy> GetDepartmentRelationSub(int parentid, List<au_Department> adlist)

        {

            List<vmHierarchy> vmdrlist = new List<vmHierarchy>();

            List<au_Department> modellist = new List<au_Department>();

            modellist = adlist.Where(s => s.parent_id == parentid).OrderBy(s => s.sequence).ToList<au_Department>();

            foreach (au_Department item in modellist)

            {

                vmHierarchy vmmodel = new vmHierarchy();

                vmmodel.id = item.id;

                vmmodel.pid = item.parent_id;

                vmmodel.name = item.name;

                vmmodel.sub = GetDepartmentRelationSub(item.id, adlist);

                vmdrlist.Add(vmmodel);

            }

            return vmdrlist;

        }

由此在前端可以得到类似这样的关系数据:

三、前端代码

在与前端代码时,关于树的逻辑关系理清是最为主要的。

1)  如何生成当前层级关系和期子级关系,每个节点的子节点都不同。

2)  需要复选框吗?

3)  需要折叠吗?

4)  当点击一个节点:

  A:其下还有一串节点,要全部选中/全部不选中?

  B:当前点击中其它子节点都被选中了,再选中这个节点,如何影响上级的选中与不选中?

总结为:在有复选框的情况下,如何影响它的下级和上级节点关系?

5)  三个事件:

  A:单击选中复选框事件;

  B:单击取消选中复选框事件;

  C:单击行事件;

事件顺序?冒泡?必要事件与用户自定义事件?

有需求的童鞋可以看看下面的jQuery代码:

jQuery:

//Tree层级关系 Begin
; (function ($, window, document, undefined) {
var defaults = {
ajaxurl: '',//ajax取数据的url[data==null时有效]
data: null,//数据
erow: null,//点击行时要执行的事件function(){}
checbox: true,//是否有复选框
initunfold: true,//初始展开true 初始折叠false
event: {
selectedrows: null,//单击行时要执行的事件
checked: null,//选中了复选框时要执行的事件
unchecked: null//取消选中复选框时要执行的事件
},//事件
exchangebar: false,//是否有全部展开 全部折叠 按钮
onlyleafcheck: false//是否只有最终子节点才显示checkbox
};
$.fn.etree = function (options) {
var $that = $(this);
var _ops = $.extend(true, {}, defaults, options);
var $con = null, _activehtml;
var _lv = 0;
//初始化数据
function initdata() {
if (_ops.data !== null) {
generateTree(_ops.data);
} else {
$.ajax({
url: _ops.ajaxurl,
dataType: "JSON",
success: function (result) {
_ops.data = result;
generateTree(_ops.data);
}
});
}
};
function generateTree(_data) {
console.log(_data);
$con = $('<div></div>').appendTo($that);
var $ul = $('<ul class="e-tree-ul"></ul>').appendTo($con);
generateSub($con, _data, _lv);
initEvent();
if (_ops.initunfold == false) {
$con.find('.tge-inv').each(function () {
$(this).click();
})
}
};
function generateSub($e, _data, _lv) {
for (var i = 0; i < _data.length; i++) {
var _tdata = _data[i];
var $li = $('<li class="e-tree-li"></li>').appendTo($e);
var $p = $('<p class="e-tree-p" lv=' + _lv + '></p>').appendTo($li);
var $ti = $('<i class="tge-inv"></i>').appendTo($p);
var $tif = $('<i class="tge-invf"></i>').appendTo($p);
var $tc = null;
if (_ops.checbox == true) {
if (_ops.onlyleafcheck == true && _tdata.sub.length == 0) {
$tc = $('<i class="sck" tid="' + _tdata.id + '"></i>').appendTo($p);
} else if (_ops.onlyleafcheck == false) {
$tc = $('<i class="sck" tid="' + _tdata.id + '"></i>').appendTo($p);
}
}
var $ts = $('<span class="e-tree-s"></span>').html(_tdata.name).appendTo($p);
if (_tdata.sub.length > 0) {
$tif.addClass('tge-invfr');
var $ul = $('<ul class="e-tree-ul"></ul>').appendTo($li);
generateSub($ul, _tdata.sub, (_lv + 1));
$ti.addClass('tge-invd');
} else {
$tif.addClass('tge-invfd');
}
if ($tc != null) {
if (_tdata.status == 1) {
$tc.addClass('ck');//选中
} else {
$tc.addClass('nock');//未选中
}
}
}
};
function checksubordinate($e) {
var $slv = $e.parent('p').next('ul');
if ($e.hasClass('ck')) {
$slv.find('.sck').removeClass('nock').addClass('ck');
} else if ($e.hasClass('nock')) {
$slv.find('.sck').removeClass('ck').addClass('nock');
}
};
function checksuperior($e) {
var $plv = $e.parent('p').parent('li').parent('ul');
if ($plv.length > 0) {
var $sib = $plv.children('li');
var $sumckdcount = $sib.children('p').children('.ck').length;
var $scount = $sib.length - $sumckdcount;
var $ppsck = $plv.prev('p').children('.sck');
if ($scount == 0) {
$plv.prev('p').children('.sck').removeClass('nock').addClass('ck');
} else {
$plv.prev('p').children('.sck').removeClass('ck').addClass('nock');
}
if ($ppsck.length > 0) {
checksuperior($ppsck);
}
}
};
function checkselect($e) {
checksuperior($e);
checksubordinate($e);
};
function setAction($e) {
var $ts = $e;
var $te = $ts.parent('p');
var $thisid = parseInt($e.attr('tid'));
$con.find('.e-tree-active').removeClass('e-tree-active');
if ($ts.hasClass('ck')) {
$ts.removeClass('ck').addClass('nock');
checkselect($ts);
if (typeof _ops.event.unchecked == "function") {
_ops.event.unchecked($te, iselectedhtml());//活动项,唯一选中项|null
}
} else if ($ts.hasClass('nock')) {
$ts.removeClass('nock').addClass('ck');
checkselect($ts);
if (_ops.event.checked != null) {
_ops.event.checked($te, iselectedhtml());//活动项,唯一选中项|null
}
}
var $shtml = iselectedhtml();
if ($shtml != null) {
var $ck = $shtml.children('.ck');
var $sid = parseInt($shtml.attr('tid'));
$ck.parent('p').addClass('e-tree-active');
if ($thisid == $sid) {
setAction($ck);
}
}
};
function initEvent() {
$con.find('.tge-inv').bind('click', function (e) {
var $ts = $(this);
var $next = $ts.parent('p').next();
var $tsnext = $ts.next();
if ($ts.hasClass('tge-invd')) {
$ts.removeClass('tge-invd').addClass('tge-invr');
$next.slideUp();
if ($tsnext.hasClass('tge-invfr')) {
$tsnext.removeClass('tge-invfr').addClass('tge-invfd');
}
} else if ($ts.hasClass('tge-invr')) {
$ts.removeClass('tge-invr').addClass('tge-invd');
$next.slideDown();
if ($tsnext.hasClass('tge-invfd')) {
$tsnext.removeClass('tge-invfd').addClass('tge-invfr');
}
}
e.stopPropagation();
});
$con.find('.sck').bind('click', function (e) {
var $ts = $(this);
setAction($ts);
e.stopPropagation();
});
$con.find('.e-tree-p').bind('click', function () {
$(this).children('.sck').click();
});
if (typeof _ops.event.selectedrows == "function") {
$con.find('.e-tree-p').bind('click', function () {
var $te = $(this).context;
_ops.event.selectedrows($($te), iselectedhtml());//活动项,唯一选中项|null
});
}
$con.find('.e-tree-s').bind('click', function () {
return false;
});
};
function iactivehtml() {
_activehtml = $con.find('.e-tree-active').html();
return _activehtml;
};
function iactiveid() {
var $thtml = $con.find('.e-tree-active');
_activeid = parseInt($thtml.find('.sck').attr('tid'));
return _activeid;
};
function iselectedids() {
var _ids = new Array();
$con.find('.ck').each(function () {
_ids.push(parseInt($(this).attr('tid')));
});
return _ids;
};
function iselectedhtml() {
if (iselectedids().length == 1) {
return $con.find('.ck').parent('p');
} else {
return null;
}
};
function iselectedid() {
if (iselectedids().length == 1) {
return parseInt($con.find('.ck').attr('tid'));
} else {
return null;
}
};
initdata();
//活动项html [活动项:当前点击的项]
this.activehtml = function () {
return iactivehtml();
};
//活动项id [活动项:当前点击的项]
this.activeid = function () {
return iactiveid();
};
//获取所有选中的项id
this.selectedids = function () {
return iselectedids();
};
//当前唯一选中项的html 不满足唯一选中时,返回null
this.selectedhtml = function () {
return iselectedhtml();
};
//当前唯一选中项的id 不满足唯一选中时,返回null
this.selectedid = function () {
return iselectedid();
};
return this;
};
})(jQuery, window, document);
//Tree层级关系 End

使用:

@{
Layout = null;
}
@using UCMS_Commons;
@using UCMS_Model;
@using UCMS_Model.ViewModel; <!DOCTYPE html> <html>
<head>
<meta name="viewport" content="width=device-width" />
<title>DepatmentManage</title>
<link href="~/Content/themes/black/Css/eui.css" rel="stylesheet" />
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/extendjs/jquery.cookie.js"></script>
<script src="~/Content/themes/black/Script/jquery.eui.js"></script>
<style type="text/css">
#dp-content {
width: 920px;
margin: 0 auto;
} #de-cont {
width: 400px;
border: 1px solid #E4E4E4;
padding: 20px;
display: inline-block;
vertical-align: top;
} #oper-cont {
width: 400px;
border: 1px solid #E4E4E4;
padding: 20px;
display: inline-block;
vertical-align: top;
margin-left: 28px;
} fieldset {
border: 1px solid #ddd;
} legend {
color: #9b9b9b;
}
</style>
<script type="text/javascript">
$(function () {
var actionUrl = {
'GetDpInfo': '/SystemCenter/GetDpInfo',
'adddp': '/SystemCenter/AddDp',
'deletedp': '/SystemCenter/DeleteDp',
'updatedp': '/SystemCenter/UpdateDp'
}; var t = JSON.parse('@Html.Raw(JSONNet.Serialize(Model))');
var $opername = $('#oper-name');
var $opersub = $('#oper-cont-sub');
var $operinfoo = $('#oper-info-o');
var $operinfoname = $('#oper-info-name');
var $errormsg = $('#error-msg');
var $deletedp = $('#deletedp');
var $dpname = $('#dpname');
var _status = -1, _ttname = ''; $('input[name="opertype"]').bind('click', function () {
var _index = parseInt($(this).attr('tp'));
$operinfoo.show();
switch (_index) {
case 0: { $opername.attr('readonly', 'readonly'); $opersub.show(); $opername.val(_ttname); $('#oper-info-o').show(); }; break;
case 1: { $opername.removeAttr('readonly'); $opersub.hide(); $opername.focus().val(''); _status = 1; }; break;
case 2: { $opername.removeAttr('readonly'); $opersub.hide(); $opername.focus().val(''); _status = 2; }; break;
case 3: { $opername.removeAttr('readonly'); $opersub.hide(); $opername.focus(); _status = 3; }; break;
}
});
$('#savedp').bind('click', function () {
switch (_status) {
case 1: { adddp(1); }; break;
case 2: { adddp(2); }; break;
case 3: { updatedp(); }; break;
}
});
$('#deletedp').bind('click', function () {
deletedp();
});
function adddp(_type) {
var _id = _dptree.activeid();
var _dpname = $opername.val();
if (_dpname.length == 0) {
$errormsg.html('请填写 名称');
}
else {
$.ajax({
url: actionUrl.adddp,
data: { "thisid": _id, "addtype": _type == 1 ? 0 : 1, "addname": _dpname },
success: function (result) {
var _result = $.eui.checkresult(result);
if (_result) {
window.location.reload();
}
}
});
}
};
function deletedp() {
var _ids = _dptree.selectedids();
var _idarray = JSON.stringify(_ids);
$.ajax({
url: actionUrl.deletedp,
data: { "ids": _idarray },
success: function (result) {
var _result = $.eui.checkresult(result);
if (_result) {
window.location.reload();
}
}
});
};
function updatedp() {
var _id = _dptree.activeid();
var _name = $opername.val();
if (_name.length == 0) {
$errormsg.html('请填写 名称');
}
else {
$.ajax({
url: actionUrl.updatedp,
data: { "thisid": _id, "newname": _name },
success: function (result) {
var _result = $.eui.checkresult(result);
if (_result) {
window.location.reload();
}
}
});
}
};
function getdpinfo(_id) {
$.ajax({
url: actionUrl.GetDpInfo,
data: { "id": _id },
success: function (result) {
var $os = $('#oper-sub').html('');
for (var i = 0; i < result.length; i++) {
$('<span style="padding: 0 10px;"></span>').html(result[i].name + '(' + result[i].percount + '人)').appendTo($os);
}
}
});
};
function schecked(el, sl) {
$('input[name="opertype"]').eq(0).click();
if (sl != null) { var _name = sl.find('.e-tree-s').html();
$dpname.html(_name);
$opername.val(_name);
_ttname = _name;
getdpinfo(_dptree.selectedid());
$operinfoo.show();
} else {
$dpname.html('已选中个数:' + _dptree.selectedids().length);
$operinfoo.hide();
}
};
var _dptree = $('#de-cont-d').etree({
data: t,
checbox: true,
onlyleafcheck: true,
event: {
selectedrows: function (el, sl) { },
checked: function (el, sl) {
var _tname = el.find('.e-tree-s').html();
$deletedp.show();
$errormsg.html('');
schecked(el, sl);
},
unchecked: function (el, sl) {
$operinfoo.hide();
schecked(el, sl);
}
}
});
});
</script>
</head>
<body>
<div id="dp-content">
<fieldset id="de-cont">
<legend>部门</legend>
<div id="de-cont-d"> </div>
</fieldset>
<fieldset id="oper-cont">
<legend>信息</legend>
<div id="oper-info-name" style="line-height: 32px;">
名称:<span id="dpname"></span>
<a href="javascript:void(0);" class="eui-btns" style="float:right;display:none;" id="deletedp">删除?</a>
</div>
<div id="oper-info-o" style="display:none;">
<hr class="hrgrey" />
<p id="oper-cont-d" class="eui-p50">
操作类别:
<label><input name="opertype" type="radio" value="" tp="0" checked="checked" />查看信息</label>
<label><input name="opertype" type="radio" value="" tp="1" />添加同级</label>
<label><input name="opertype" type="radio" value="" tp="2" />添加子级</label>
<label><input name="opertype" type="radio" value="" tp="3" />修改自身</label>
</p>
<p class="eui-p50">
名称:
<input type="text" name="name" value="" id="oper-name" class="eui-input" readonly="readonly" />
</p>
<p class="eui-p50" id="oper-cont-sub">
下辖职位:<span id="oper-sub"></span>
</p>
<label id="error-msg" class="error-msg"></label>
<a href="javascript:void(0);" class="eui-btns" style="float:right;bottom:0;" id="savedp">保存</a>
</div>
</fieldset>
</div>
</body>
</html>

jQuery插件实例七:一棵Tree的生成史的更多相关文章

  1. jQuery插件实例五:手风琴效果[动画效果可配置版]

    昨天写了个jQuery插件实例四:手风琴效果[无动画版]那个是没有动画效果的,且可配置性不高,本篇为有动画效果.对于一些数据做了动态的计算,以实现自适应. 欢迎大家入群相互交流,学习,新群初建,欢迎各 ...

  2. jQuery插件实例一:年华时代插件Alert对话框

    在工作中使用jQuery插件相信对于程序员来说非常普遍,在网络上也有很多优秀的插件可供大家使用,功能非常强大.在之前用过的一些插件中,有些太过追求功能的强大和可配置性,造成使用的复杂度上升.个人认为与 ...

  3. 一个很简单的jQuery插件实例教程(菜鸟级)

    很多公司的前端设计开发人员都是女孩子,而这些女孩子很多JavaScript技能都不是很好.而前端开发过程中,JavaScript技能又是必不可少的.所以,如果前端小MM正在为某个JavaScript效 ...

  4. 网站开发常用jQuery插件总结(七)背景插件backstretch

    一.backstretch插件功能 优化网站外观.主要用于设置页面背景图片,也可以设置html元素的背景图片.背景图片可以设置多张,在间隔时间内循环显示. 注 但是在设置背景图片时,如果图片过大,网站 ...

  5. jQuery插件实例四:手风琴效果[无动画版]

    手风琴效果就是内容的折叠与打开,在这个插件中,使用了三种数据来源:1.直接写在DOM结构中:2.将数据写在配置项中:3.从Ajax()中获取数据.在这一版中,各项的切换没有添加动画效果,在下一版中会是 ...

  6. jQuery插件实例三:图片滚动[切换]效果一

    图片切换效果在很多网站上都能看到,是一种常见的广告/活动宣传方式,通常位于网页上端.这个插件是众多图片切换效果的形式中的一种,数据源可在前端配置,也可从后台通JSON格式传输数据,当然,数据格式是固定 ...

  7. jQuery插件实例二:年华时代插件ReturnTop回到首页

    这个插件功能在于当网页内容高度很高时,方便用户快速回到顶部.核心在于对屏幕高度的获取,定时器的使用,在引用代码后,只使用$.nhsd.returnTop();即可实现效果 效果图: 代码: ; fun ...

  8. Jquery 插件 实例

    先说明下应用场景,通过可配项的配置和默认项覆盖,获取指定的需求数据,填充到指定的位置(两个指定其实都是可配的) (function($) { $.fn.extend({ getOneNews: fun ...

  9. jQuery插件实例六:jQuery 前端分页

    先来看看效果: 对于前端分页,关键是思路,和分页算法.本想多说两句,可又觉得没什么可说的,看代码吧: 如何使用? $("#pging").zPagination({ 'navEve ...

随机推荐

  1. CentOS系统中文改英文

    一.进入语言配置文件 vi  /etc/sysconfig/i18n 用SSH执行以上命令,用vi编辑器修改/etc/sysconfig/i18n文件. 二.修改语言 将默认的LANG="z ...

  2. 200个最常见的JAVA面试问题(附答案)

    本文内容: 20个最常见的JAVA面试问题(附答案) 13个单例模式JAVA面试问题(附答案) 说说JVM和垃圾收集是如何工作的(附答案) 说说如何避免JAVA线程死锁(附答案) Java中HashS ...

  3. Curling 2.0(DFS简单题)

    题目链接: https://vjudge.net/problem/POJ-3009 题目描述: On Planet MM-21, after their Olympic games this year ...

  4. 亲身实践 yui-compressor压缩js和css

    最近很懒散,个人感情.家庭原因,没有动力去学东西,老是发誓要搞好前端工程化,老中断,唉!没有魄力! 最近老觉得这前端工程化有什么好的,东西那么多,还得学!直到前几天产品提了个优化,说搜索结果页跳商品详 ...

  5. Java多线程——之一创建线程的四种方法

    1.实现Runnable接口,重载run(),无返回值 package thread; public class ThreadRunnable implements Runnable { public ...

  6. Android - ANR小结

    Application Not Responding 在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Applicatio ...

  7. How to write a professional email?

    Advantages and Disadvantages of Email communication compared with Face-To-Face communication:   Emai ...

  8. ORM--Entity Framework 学习(01)

    关键词:Entity Framework:微软官方提供的ORM工具,ORM让开发人员节省数据库访问的代码时间,将更多的时间放到业务逻辑层代码上.EF提供变更跟踪.唯一性约束.惰性加载.查询事物等.开发 ...

  9. 关于如何在本地IIS搭建网站

    步骤一: 首先安装与配置IIS服务,可借用百度经验:http://jingyan.baidu.com/article/d5a880eb75f74713f047cc57.html 步骤二: 修改web. ...

  10. django项目一 CRM表结构

    from django.db import models from django.contrib import auth from django.core.exceptions import Perm ...