index.html
<!DOCTYPE html>
<html>
<head>
<title>Datatable-serverSide 自行封装请求参数和返回数据例子</title>
<!-- Bootstrap -->
<link rel="stylesheet" href="asset/lib/bootstrap-2.3.2/css/bootstrap.min.css" media="screen">
<link rel="stylesheet" href="asset/lib/bootstrap-2.3.2/css/bootstrap-responsive.min.css" media="screen">
<!-- FontAwesome -->
<link rel="stylesheet" href="asset/lib/font-awesome-4.2.0/css/font-awesome.min.css">
<!-- DataTables CSS start-->
<link rel="stylesheet" href="asset/lib/dataTables-1.10.7/plugins/integration/bootstrap/2/dataTables.bootstrap.css">
<link rel="stylesheet"
href="asset/lib/dataTables-1.10.7/plugins/integration/font-awesome/dataTables.fontAwesome.css">
<!-- DataTables CSS end-->
<link rel="stylesheet" href="asset/css/user-manage.css">
</head>
<body>
<div class="container-fluid">
<div class="row-fluid">
<div class="span12" id="content">
<div class="row-fluid">
<div class="navbar" id="breadcrumb">
<div class="navbar-inner">
<ul class="breadcrumb">
<li>
<a href="#">首页</a>
<span class="divider">/</span>
</li>
<li class="active">用户管理</li>
</ul>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<div class="btn-toolbar">
<div class="pull-right">
<div class="input-append">
<input type="text" placeholder="模糊查询" id="fuzzy-search">
<div class="btn-group">
<button type="button" class="btn" id="btn-simple-search"><i
class="fa fa-search"></i></button>
<button type="button" class="btn" title="高级查询" id="toggle-advanced-search">
<i class="fa fa-angle-double-down"></i>
</button>
</div>
</div>
</div>
<button type="button" class="btn btn-primary" id="btn-add"><i class="fa fa-plus"></i> 添加
</button>
<button type="button" class="btn btn-danger" id="btn-del"><i class="fa fa-remove"></i> 批量删除
</button>
</div>
</div>
</div>
<div class="row-fluid" style="display:none;" id="div-advanced-search">
<form class="form-inline well">
<span>姓名:</span>
<input type="text" class="input-medium" placeholder="姓名" id="name-search">
<span>职位:</span>
<input type="text" class="input-medium" placeholder="职位" id="position-search">
<span>工作地点:</span>
<input type="text" class="input-medium" placeholder="工作地点" id="office-search">
<span>编号:</span>
<input type="text" class="input-medium" placeholder="编号" id="extn-search">
<span>在线状态:</span>
<select class="input-small" id="status-search">
<option value="">全部</option>
<option value="1">在线</option>
<option value="0">离线</option>
</select>
<select class="input-small" id="role-search">
<option value="">全部</option>
<option value="1">管理员</option>
<option value="0">操作员</option>
</select>
<button type="button" class="btn" id="btn-advanced-search"><i class="fa fa-search"></i> 查询</button>
</form>
</div>
<div class="block info-block" id="user-view">
<div class="navbar navbar-inner block-header">
<div class="block-title">用户详情</div>
<div class="header-buttons">
<button type="button" class="btn btn-primary" id="btn-view-edit">修改</button>
</div>
</div>
<div class="block-content info-content clearfix">
<div class="row-fluid">
<div class="span4">
<label class="prop-name">编号:</label>
<div class="prop-value" id="extn-view"></div>
</div>
<div class="span4">
<label class="prop-name">姓名:</label>
<div class="prop-value" id="name-view"></div>
</div>
<div class="span4">
<label class="prop-name">角色:</label>
<div class="prop-value" id="role-view"></div>
</div>
</div>
<div class="row-fluid">
<div class="span4">
<label class="prop-name">职位:</label>
<div class="prop-value" id="position-view"></div>
</div>
<div class="span4">
<label class="prop-name">薪水:</label>
<div class="prop-value" id="salary-view"></div>
</div>
<div class="span4">
<label class="prop-name">状态:</label>
<div class="prop-value" id="status-view"></div>
</div>
</div>
<div class="row-fluid">
<div class="span4">
<label class="prop-name">入职时间:</label>
<div class="prop-value" id="start-date-view"></div>
</div>
<div class="span8">
<label class="prop-name">办公地点:</label>
<div class="prop-value" id="office-view"></div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<label class="prop-name">备注:</label>
<div class="prop-value"></div>
</div>
</div>
</div>
</div>
<div class="block info-block" id="user-add" style="display:none;">
<div class="navbar navbar-inner block-header">
<div class="block-title">添加账户</div>
<div class="header-buttons">
<button type="button" class="btn btn-primary" id="btn-save-add">确定添加</button>
<button type="button" class="btn btn-cancel">取消</button>
</div>
</div>
<div class="block-content info-content clearfix">
<form id="form-add">
<div class="control-group">
<label class="control-label" for="extn-add"><span
class="red-asterisk">*</span>编号:</label>
<div class="controls">
<input type="text" id="extn-add" name="extn-add">
</div>
</div>
<div class="control-group">
<label class="control-label" for="name-add"><span
class="red-asterisk">*</span>姓名:</label>
<div class="controls">
<input type="text" id="name-add" name="name-add">
</div>
</div>
<div class="control-group">
<label class="control-label" for="role-add">角色:</label>
<div class="controls">
<select id="role-add" name="role-add">
<option value="1" selected>管理员</option>
<option value="0">操作员</option>
</select>
</div>
</div>
<div class="control-group">
<label class="control-label" for="position-add">职位:</label>
<div class="controls">
<input type="text" id="position-add" name="position-add">
</div>
</div>
<div class="control-group">
<label class="control-label" for="salary-add">薪水:</label>
<div class="controls">
<input type="text" id="salary-add" name="salary-add">
</div>
</div>
<div class="control-group">
<label class="control-label" for="start-date-add">入职时间:</label>
<div class="controls">
<input type="text" id="start-date-add" name="start-date-add">
</div>
</div>
<div class="control-group">
<label class="control-label" for="office-add">办公地点:</label>
<div class="controls">
<input type="text" class="xlarge" id="office-add" name="office-add">
</div>
</div>
<div class="control-group">
<label class="control-label" for="remark-add">备注:</label>
<div class="controls">
<input type="text" class="xxxlarge" id="remark-add" name="remark-add">
</div>
</div>
</form>
</div>
</div>
<div class="block info-block" id="user-edit" style="display:none;">
<div class="navbar navbar-inner block-header">
<div class="block-title">修改账户:<span id="title-edit"></span></div>
<div class="header-buttons">
<button type="button" class="btn btn-primary" id="btn-save-edit">保存更改</button>
<button type="button" class="btn btn-cancel">取消</button>
</div>
</div>
<div class="block-content info-content clearfix">
<form id="form-edit">
<div class="control-group">
<label class="control-label" for="extn-edit"><span
class="red-asterisk">*</span>编号:</label>
<div class="controls">
<input type="text" id="extn-edit" name="extn-edit">
</div>
</div>
<div class="control-group">
<label class="control-label" for="name-edit"><span
class="red-asterisk">*</span>姓名:</label>
<div class="controls">
<input type="text" id="name-edit" name="name-edit">
</div>
</div>
<div class="control-group">
<label class="control-label" for="role-edit">角色:</label>
<div class="controls">
<select id="role-edit" name="role-edit">
<option value="1" selected>管理员</option>
<option value="0">操作员</option>
</select>
</div>
</div>
<div class="control-group">
<label class="control-label" for="position-edit">职位:</label>
<div class="controls">
<input type="text" id="position-edit" name="position-edit">
</div>
</div>
<div class="control-group">
<label class="control-label" for="salary-edit">薪水:</label>
<div class="controls">
<input type="text" id="salary-edit" name="salary-edit">
</div>
</div>
<div class="control-group">
<label class="control-label" for="start-date-edit">入职时间:</label>
<div class="controls">
<input type="text" id="start-date-edit" name="start-date-edit">
</div>
</div>
<div class="control-group">
<label class="control-label" for="office-edit">办公地点:</label>
<div class="controls">
<input type="text" class="xlarge" id="office-edit" name="office-edit">
</div>
</div>
<div class="control-group">
<label class="control-label" for="remark-edit">备注:</label>
<div class="controls">
<input type="text" class="xxxlarge" id="remark-edit" name="remark-edit">
</div>
</div>
</form>
</div>
</div>
<div class="row-fluid">
<div class="span12" id="div-table-container">
<table class="table table-striped table-bordered table-hover table-condensed" id="table-user"
cellspacing="0" width="100%">
<thead>
<tr>
<th>
<input type="checkbox" name="cb-check-all">
</th>
<th>姓名</th>
<th>职位</th>
<th>状态</th>
<th>入职时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<th>
<input type="checkbox" name="cb-check-all">
</th>
<th>姓名</th>
<th>职位</th>
<th>状态</th>
<th>入职时间</th>
<th>操作</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
<script src="asset/lib/json2.js"></script>
<!-- JQuery -->
<script src="asset/lib/jquery-1.11.3.min.js"></script>
<!-- Bootstrap -->
<script src="asset/lib/bootstrap-2.3.2/js/bootstrap.min.js"></script>
<!-- SpinJS-->
<script src="asset/lib/spin-2.1.0/jquery.spin.merge.js"></script>
<!-- lhgdialog -->
<script src="asset/lib/lhgdialog-4.2.0/lhgdialog.js?skin=bootstrap2"></script>
<!-- DataTables JS-->
<script src="asset/lib/dataTables-1.10.7/media/js/jquery.dataTables.js"></script>
<script src="asset/lib/dataTables-1.10.7/plugins/integration/bootstrap/2/dataTables.bootstrap.js"></script>
<!-- DataTables JS end-->
<script src="asset/js/constant.js"></script>
<script src="asset/js/user-manage.js"></script>
</body>
</html>
constant.js
/*常量*/
var CONSTANT = {
DATA_TABLES: {
DEFAULT_OPTION: { //DataTables初始化选项
language: {
"sProcessing": "处理中...",
"sLengthMenu": "每页 _MENU_ 项",
"sZeroRecords": "没有匹配结果",
"sInfo": "当前显示第 _START_ 至 _END_ 项,共 _TOTAL_ 项。",
"sInfoEmpty": "当前显示第 0 至 0 项,共 0 项",
"sInfoFiltered": "(由 _MAX_ 项结果过滤)",
"sInfoPostFix": "",
"sSearch": "搜索:",
"sUrl": "",
"sEmptyTable": "表中数据为空",
"sLoadingRecords": "载入中...",
"sInfoThousands": ",",
"oPaginate": {
"sFirst": "首页",
"sPrevious": "上页",
"sNext": "下页",
"sLast": "末页",
"sJump": "跳转"
},
"oAria": {
"sSortAscending": ": 以升序排列此列",
"sSortDescending": ": 以降序排列此列"
}
},
autoWidth: false, //禁用自动调整列宽
stripeClasses: ["odd", "even"],//为奇偶行加上样式,兼容不支持CSS伪类的场合
order: [], //取消默认排序查询,否则复选框一列会出现小箭头
processing: false, //隐藏加载提示,自行处理
serverSide: true, //启用服务器端分页
searching: false //禁用原生搜索
},
COLUMN: {
CHECKBOX: { //复选框单元格
className: "td-checkbox",
orderable: false,
width: "30px",
data: null,
render: function (data, type, row, meta) {
return '<input type="checkbox" class="iCheck">';
}
}
},
RENDER: { //常用render可以抽取出来,如日期时间、头像等
ELLIPSIS: function (data, type, row, meta) {
data = data || "";
return '<span title="' + data + '">' + data + '</span>';
}
}
}
};
userManage.js
$(function () {
var $wrapper = $('#div-table-container');
var $table = $('#table-user');
var _table = $table.dataTable($.extend(true, {}, CONSTANT.DATA_TABLES.DEFAULT_OPTION, {
ajax: function (data, callback, settings) {//ajax配置为function,手动调用异步查询
//手动控制遮罩
$wrapper.spinModal();
//封装请求参数
var param = userManage.getQueryCondition(data);
$.ajax({
type: "GET",
url: "datasource.php",
cache: false, //禁用缓存
data: param, //传入已封装的参数
dataType: "json",
success: function (result) {
//setTimeout仅为测试遮罩效果
setTimeout(function () {
//异常判断与处理
if (result.errorCode) {
$.dialog.alert("查询失败。错误码:" + result.errorCode);
return;
}
//封装返回数据,这里仅演示了修改属性名
var returnData = {};
returnData.draw = data.draw;//这里直接自行返回了draw计数器,应该由后台返回
returnData.recordsTotal = result.total;
returnData.recordsFiltered = result.total;//后台不实现过滤功能,每次查询均视作全部结果
returnData.data = result.pageData;
//关闭遮罩
$wrapper.spinModal(false);
//调用DataTables提供的callback方法,代表数据已封装完成并传回DataTables进行渲染
//此时的数据需确保正确无误,异常判断应在执行此回调前自行处理完毕
callback(returnData);
}, 200);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
$.dialog.alert("查询失败");
$wrapper.spinModal(false);
}
});
},
columns: [
CONSTANT.DATA_TABLES.COLUMN.CHECKBOX,
{
className: "ellipsis", //文字过长时用省略号显示,CSS实现
data: "name",
render: CONSTANT.DATA_TABLES.RENDER.ELLIPSIS,//会显示省略号的列,需要用title属性实现划过时显示全部文本的效果
},
{
className: "ellipsis",
data: "position",
render: CONSTANT.DATA_TABLES.RENDER.ELLIPSIS,
//固定列宽,但至少留下一个活动列不要固定宽度,让表格自行调整。不要将所有列都指定列宽,否则页面伸缩时所有列都会随之按比例伸缩。
//切记设置table样式为table-layout:fixed; 否则列宽不会强制为指定宽度,也不会出现省略号。
width: "80px"
},
{
data: "status",
width: "80px",
render: function (data, type, row, meta) {
return '<i class="fa fa-male"></i> ' + (data ? "在线" : "离线");
}
},
{
data: "start_date",
width: "80px"
},
{
className: "td-operation",
data: null,
defaultContent: "",
orderable: false,
width: "120px"
}
],
"createdRow": function (row, data, index) {
//行渲染回调,在这里可以对该行dom元素进行任何操作
//给当前行加样式
if (data.role) {
$(row).addClass("info");
}
//给当前行某列加样式
$('td', row).eq(3).addClass(data.status ? "text-success" : "text-error");
//不使用render,改用jquery文档操作呈现单元格
var $btnEdit = $('<button type="button" class="btn btn-small btn-primary btn-edit">修改</button>');
var $btnDel = $('<button type="button" class="btn btn-small btn-danger btn-del">删除</button>');
$('td', row).eq(5).append($btnEdit).append($btnDel);
},
"drawCallback": function (settings) {
//渲染完毕后的回调
//清空全选状态
$(":checkbox[name='cb-check-all']", $wrapper).prop('checked', false);
//默认选中第一行
$("tbody tr", $table).eq(0).click();
}
})).api();//此处需调用api()方法,否则返回的是JQuery对象而不是DataTables的API对象
$("#btn-add").click(function () {
userManage.addItemInit();
});
$("#btn-del").click(function () {
var arrItemId = [];
$("tbody :checkbox:checked", $table).each(function (i) {
var item = _table.row($(this).closest('tr')).data();
arrItemId.push(item);
});
userManage.deleteItem(arrItemId);
});
$("#btn-simple-search").click(function () {
userManage.fuzzySearch = true;
//reload效果与draw(true)或者draw()类似,draw(false)则可在获取新数据的同时停留在当前页码,可自行试验
// _table.ajax.reload();
// _table.draw(false);
_table.draw();
});
$("#btn-advanced-search").click(function () {
userManage.fuzzySearch = false;
_table.draw();
});
$("#btn-save-add").click(function () {
userManage.addItemSubmit();
});
$("#btn-save-edit").click(function () {
userManage.editItemSubmit();
});
//行点击事件
$("tbody", $table).on("click", "tr", function (event) {
$(this).addClass("active").siblings().removeClass("active");
//获取该行对应的数据
var item = _table.row($(this).closest('tr')).data();
userManage.currentItem = item;
userManage.showItemDetail(item);
});
$table.on("change", ":checkbox", function () {
if ($(this).is("[name='cb-check-all']")) {
//全选
$(":checkbox", $table).prop("checked", $(this).prop("checked"));
} else {
//一般复选
var checkbox = $("tbody :checkbox", $table);
$(":checkbox[name='cb-check-all']", $table).prop('checked', checkbox.length == checkbox.filter(':checked').length);
}
}).on("click", ".td-checkbox", function (event) {
//点击单元格即点击复选框
!$(event.target).is(":checkbox") && $(":checkbox", this).trigger("click");
}).on("click", ".btn-edit", function () {
//点击编辑按钮
var item = _table.row($(this).closest('tr')).data();
$(this).closest('tr').addClass("active").siblings().removeClass("active");
userManage.currentItem = item;
userManage.editItemInit(item);
}).on("click", ".btn-del", function () {
//点击删除按钮
var item = _table.row($(this).closest('tr')).data();
$(this).closest('tr').addClass("active").siblings().removeClass("active");
userManage.deleteItem([item]);
});
$("#toggle-advanced-search").click(function () {
$("i", this).toggleClass("fa-angle-double-down fa-angle-double-up");
$("#div-advanced-search").slideToggle("fast");
});
$("#btn-info-content-collapse").click(function () {
$("i", this).toggleClass("fa-minus fa-plus");
$("span", this).toggle();
$("#user-view .info-content").slideToggle("fast");
});
$("#btn-view-edit").click(function () {
userManage.editItemInit(userManage.currentItem);
});
$(".btn-cancel").click(function () {
userManage.showItemDetail(userManage.currentItem);
});
});
var userManage = {
currentItem: null,
fuzzySearch: true,
getQueryCondition: function (data) {
var param = {};
//组装排序参数
if (data.order && data.order.length && data.order[0]) {
switch (data.order[0].column) {
case 1:
param.orderColumn = "name";
break;
case 2:
param.orderColumn = "position";
break;
case 3:
param.orderColumn = "status";
break;
case 4:
param.orderColumn = "start_date";
break;
default:
param.orderColumn = "name";
break;
}
param.orderDir = data.order[0].dir;
}
//组装查询参数
param.fuzzySearch = userManage.fuzzySearch;
if (userManage.fuzzySearch) {
param.fuzzy = $("#fuzzy-search").val();
} else {
param.name = $("#name-search").val();
param.position = $("#position-search").val();
param.office = $("#office-search").val();
param.extn = $("#extn-search").val();
param.status = $("#status-search").val();
param.role = $("#role-search").val();
}
//组装分页参数
param.startIndex = data.start;
param.pageSize = data.length;
param.draw = data.draw;
return param;
},
showItemDetail: function (item) {
$("#user-view").show().siblings(".info-block").hide();
if (!item) {
$("#user-view .prop-value").text("");
return;
}
$("#name-view").text(item.name);
$("#position-view").text(item.position);
$("#salary-view").text(item.salary);
$("#start-date-view").text(item.start_date);
$("#office-view").text(item.office);
$("#extn-view").text(item.extn);
$("#role-view").text(item.role ? "管理员" : "操作员");
$("#status-view").text(item.status ? "在线" : "离线");
},
addItemInit: function () {
$("#form-add")[0].reset();
$("#user-add").show().siblings(".info-block").hide();
},
editItemInit: function (item) {
if (!item) {
return;
}
$("#form-edit")[0].reset();
$("#title-edit").text(item.name);
$("#name-edit").val(item.name);
$("#position-edit").val(item.position);
$("#salary-edit").val(item.salary);
$("#start-date-edit").val(item.start_date);
$("#office-edit").val(item.office);
$("#extn-edit").val(item.extn);
$("#role-edit").val(item.role);
$("#user-edit").show().siblings(".info-block").hide();
},
addItemSubmit: function () {
$.dialog.tips('保存当前添加用户');
},
editItemSubmit: function () {
$.dialog.tips('保存当前编辑用户');
},
deleteItem: function (selectedItems) {
var message;
if (selectedItems && selectedItems.length) {
if (selectedItems.length == 1) {
message = "确定要删除 '" + selectedItems[0].name + "' 吗?";
} else {
message = "确定要删除选中的" + selectedItems.length + "项记录吗?";
}
$.dialog.confirmDanger(message, function () {
$.dialog.tips('执行删除操作');
});
} else {
$.dialog.tips('请先选中要操作的行');
}
}
};