在上篇随笔《基于Metronic的Bootstrap开发框架经验总结(12)--页面链接收藏夹功能的实现》上,我介绍了链接收藏夹功能的实现,以及对收藏记录的排序处理。该篇随笔主要使用功能按钮的方式移动收藏记录,功能虽然实现的还算不错,不过文章出来后,有读者同行指出可以利用直接拖动的方式实现排序更方便,因此对其中列表记录的排序进行了研究,从而介绍了如何利用Sortable开源JS组件实现拖动排序的处理,本篇随笔介绍了该组件在连接收藏夹排序中的应用。
1、收藏记录的排序处理回顾
上篇随笔介绍的收藏夹处理,主要就是为了方便用户快速进入常用功能的一个模块,随着收藏夹记录的增多,我们有必要对它们进行合理的排序,以方便我们的使用。
原来的收藏夹记录排序界面如下所示。
这个界面里面包含了对记录的移动处理,包括向上或者向下。
实现的逻辑代码主要就是对当前记录的前后记录的排序进行调整的处理,从而实现位置的调整,代码如下所示。
/// <summary> /// 更新向上或者向下的顺序 /// </summary> /// <param name="id">记录的ID</param> /// <param name="moveUp">往上,还是往下移动,往上则为true</param> /// <returns></returns> public bool UpDown(string id, bool moveUp) { //设置排序的规则 bool IsDescending = true; bool result = false; WebFavoriteInfo info = FindByID(id); if (info != null) { //构建查询的条件 string condition = ""; if (IsDescending) { condition = string.Format("Seq {0} {1}", moveUp ? ">" : "<", info.Seq); } else { condition = string.Format("Seq {0} {1}", moveUp ? "<" : ">", info.Seq); } var list = baseDal.Find(condition); decimal newSeq = 0M; switch (list.Count) { case 0: newSeq = info.Seq;//已在顶部或者底部,顺序默认不变 break; case 1: //上面或者下面有一个记录 if (IsDescending) { newSeq = moveUp ? (list[0].Seq + 1M) : (list[0].Seq - 1M); } else { newSeq = !moveUp ? (list[0].Seq + 1M) : (list[0].Seq - 1M); } break; case 2: //中间区域,取平均值 newSeq = (list[0].Seq + list[1].Seq) / 2M; break; default: //多于两个的情况 if (moveUp) { newSeq = (list[list.Count - 2].Seq + list[list.Count - 1].Seq) / 2M; } else { newSeq = (list[0].Seq + list[1].Seq) / 2M; } break; } //统一修改顺序 info.Seq = newSeq; result = Update(info, info.ID); } return result; }
以上的代码,通过判断当前移动记录的位置,然后获取排序在其上面或者下面的记录,如果记录数量为0 ,那么就是顶端或者底端的了,如果是1条记录,那么就是在该记录上增加或者减除某个数值就作为新排序位置的值即可。如果是大于或等于2条记录记录,则取其最近的两个记录,取他们的平均值即可。
2、收藏夹的拖动排序处理
上面的处理能够满足基本的要求,而且调整位置也是正确的。但是我们如果能够拖动列表项进行排序的话,那样就更加方便、更加友好的了。
基于拖动的排序,我寻找到了一个比较好的JS处理组件(Sortable)这个在github上排名比较高,估计用的人也很多。
这个控件的使用相对比较简单,代码如下所示。
<ul id="items"> <li>item 1</li> <li>item 2</li> <li>item 3</li> </ul> var el = document.getElementById(‘items‘); var sortable = new Sortable(el);
我们先来看看我最终使用Sortable整合好的界面效果。
这样我们就可以通过移动记录的方式进行调整位置。
列表的展示,我们还是使用分页的方式,为了提高检索效率。
<div class="portlet-body flip-scroll"> <div class="portlet-body"> <div> <span>每页显示</span> <select id="rows" onchange="ChangeRows()"> <option>10</option> <option selected>50</option> <option>100</option> <option>1000</option> </select> <span>条记录</span> <span>共有记录:</span><span id=‘totalCount‘ class="label label-success">0</span>条,总页数:<span id=‘totalPageCount‘ class="label label-success">0</span>页。 </div> <hr /> <div id="grid_body" class=‘list-group‘></div> <div class="paging-toolbar"> <ul id=‘grid_paging‘></ul> </div> </div> </div>
在这里面我们通过在grid_body里面构建一系列的列表记录即可。
<div class="list-group-item"> <span class="glyphicon glyphicon-move" aria-hidden="true"></span> <a class="btn btn-sm blue" id="e1f462c6-c749-4258-836f-e13ee8c8acd7" href="http://localhost:2251/User/Index?tid=2744DBF5-A648-47C1-9E9A-D8B405884389">系统用户信息</a> <i class="js-remove">?</i> </div>
在记录的更新后,该Sortable组件有一个OnUpdate的事件可以处理,如下所示。
var grid_body = document.getElementById(‘grid_body‘); new Sortable(grid_body, { handle: ‘.glyphicon-move‘, filter: ".js-remove", animation: 150, onUpdate: function (/**Event*/evt) { var list = [];//构造集合对象 $(‘.list-group div a‘).each(function (i, item) { list.push({ ‘Text‘: item.text, ‘Value‘: item.href }); }); var url = "/WebFavorite/EditFavorite"; var postData = { list: list }; $.post(url, postData, function (json) { var data = $.parseJSON(json); if (data.Success) { //showTips("操作成功"); Refresh();//刷新页面数据 } else { showTips(data.ErrorMessage); } }); }, });
这样我们把业务处理交给EditFavorite方法了,这里面主要对列表记录进行统一更新即可,处理逻辑就是先删除以前的记录,然后添加列表的集合记录,并且设置它们的排序记录为合适的顺序即可。
/// <summary> /// 编辑记录列表 /// </summary> /// <param name="list">记录列表</param> /// <returns></returns> [HttpPost] public ActionResult EditFavorite(List<CListItem> list) { CommonResult result = new CommonResult(); var userid = CurrentUser.ID; DbTransaction trans = BLLFactory<WebFavorite>.Instance.CreateTransaction(); if (trans != null) { try { //先删除就记录 var condition = string.Format("Creator=‘{0}‘", userid); BLLFactory<WebFavorite>.Instance.DeleteByCondition(condition, trans); //逐条添加记录 int i = list.Count; foreach (CListItem item in list) { WebFavoriteInfo info = new WebFavoriteInfo(); info.Title = item.Text; info.Url = item.Value; info.Seq = i--; info.Creator = CurrentUser.ID.ToString(); BLLFactory<WebFavorite>.Instance.Insert(info, trans); } trans.Commit(); result.Success = true; } catch(Exception ex) { result.ErrorMessage = ex.Message; trans.Rollback(); LogHelper.Error(ex); } } return ToJsonContent(result); }
以上就是对收藏夹列表进行拖动排序的改进处理,希望在实际的项目中能够合理利用这个Sortable的JS组件,能够提高我们用户的体检效果。