8.2 实战过程
首先,看到题目的要求是制作一个列表管理,将它分为3部分:顶部的操作按钮和筛选条件、中间的列表内容、底部的分页码。
刚开始的时候,本来想只用一个table里的thead、tbody、tfoot实现这3个部分,但是后来在将第一列的checkbox居中对齐的时候,发现会对thead和tfoot有影响,所以就换成了panel组件、table以及list-group组件的组合了。示例代码如下:
- <div class="panel panel-default ">
- <div class="panel-heading">
- 这里是head区
- </div>
- <table class="table table-bordered table-hover">
- <thead></thead>
- <tbody></tbody>
- <tfoot></tfoot>
- </table>
- <ul class="list-group">
- <li class="list-group-item">
- 这里放分页码
- </li>
- </ul>
- </div>
panel里有3部分,panel-heading里放置操作按钮和筛选条件,中间放表格,并且在表格上应用了table-bordered样式,以便都有边框,另外还加了一个鼠标移动变化tr背景色的功能,显得富有动感。底部的list-group用于放置分页码,这里用list-group是因为该组件和panel一起用的时候,可以很好地处理横线和底部边框的效果,具体可以参考该组件的详细使用方法。上述代码的效果如图8-2所示。
图8-2 pannel里设置表格显示
表格设计得很不错。下一步,因为我很喜欢分页码,所以先处理这一块,把相关代码放到list-group-item样式元素里。代码如下:
- <li class="list-group-item">
- <ul class="pagination ">
- <li class="disabled"><span>Prev</span></li>
- <li class="active"><a href="#">1 <span class="sr-only">(current)
- </span></a></li>
- <li><a href="#">2</a></li>
- <li><a href="#">3</a></li>
- <li><a href="#">4</a></li>
- <li class="disabled"><span>...</span></li>
- <li><a href="#">14</a></li>
- <li><a href="#">15</a></li>
- <li><a href="#">16</a></li>
- <li><a href="#">17</a></li>
- <li><a href="#">Next</a></li>
- </ul>
- </li>
这里先设置第一页为当前页,那么上一页(prev)就得被禁用掉。另外,在分页码很多的情况下,中间经常要省略一部分页面,所以在它上面也使用了disabled样式,运行效果如图8-3所示。
图8-3 分页组件效果
分页显示不是很好看,上下边距太大了,而且我想让每个页码都单独分开,这样显得更有个性。那么就来改造一下pagination样式。由于不能影响原有的分页功能,所以我们按照再附加一个square样式的情况进行改造,主要是要改造上下边距,以及每个li元素的外边距。代码如下:
- .pagination.square {
- margin: 0;/* 去除外边距 */
- }
- .pagination.square > li > a,
- .pagination.square > li > span {
- margin: 0 5px;
- border: 1px solid #dddddd; /* 设置所有的边框都为1像素 */
- }
- .pagination.square > li:first-child > a,
- .pagination.square > li:first-child > span,
- .pagination.square > li:last-child > a,
- .pagination.square > li:last-child > span {
- margin-left: 0px;
- padding-left: 10px;
- padding-right: 10px;
- border-radius: 0px; /* 取消圆角 */
- }
不仅把外边边距都调整了,还把前后元素的圆角也都去除了,形成一个很干净的方形效果,如图8-4所示。
图8-4 分页数字方框间隔显示
现在可以处理head头部的内容了。在这里想将它分为左右两部分,左边放功能按钮,右边放筛选和排序选择菜单,所以加了两个div,分别是pull-left和pull-right,来实现左右浮动。代码如下:
- <div class="panel-heading">
- <div class="pull-right">
- 左边区域
- </div>
- <div class="pull-left">
- 右边区域
- </div>
- </div>
运行看效果,发现效果变形了(和table重叠了),原因是没有清除浮动。记得Bootstrap里有清除浮动的样式,查了一下手册,找到了clearfix,将该样式应用到panel-heading上即可,效果如图8-5所示。
图8-5 将pannel头部分为左右两部分
左边的按钮很简单,在里面直接放3个button元素即可,然后用颜色样式稍微修饰一下。
- <div class="pull-left">
- <button class="btn btn-success">New</button>
- <button class="btn btn-warning">Disable</button>
- <button class="btn btn-danger">Delete</button>
- </div>
右边的排序和筛选条件就比较复杂了。刚开始的时候,想直接用select元素就可以了,但是该元素在不同的操作系统和浏览器下显示效果不一样,而且想体现一下对Bootstrap的了解,所以就用了下拉菜单(Dropdown)组件。排序和筛选分别用两个下拉菜单,其外部用按钮组(btn-group)样式包住,这样就差不多了。代码如下:
- <div class="pull-right">
- <div class="btn-group">
- <button type="button" class="btn btn-default
- dropdown-toggle active" data-toggle="dropdown">
- Filter By Disabled <span class="caret"></span>
- </button>
- <ul class="dropdown-menu" role="menu">
- <li><a href="#">Filter by Account Status</a></li>
- <li><a href="#">Filter by Department</a></li>
- <li class="divider"></li>
- <li><a href="#">Reset</a></li>
- </ul>
- </div>
- <div class="btn-group">
- <button type="button" class="btn btn-default
- dropdown-toggle" data-toggle="dropdown">
- Sort By FirstName <span class="caret"></span>
- </button>
- <ul class="dropdown-menu pull-right" role="menu">
- <li><a href="#">Sort by FirstName</a></li>
- <li><a href="#">Sort by Email</a></li>
- <li class="divider"></li>
- <li><a href="#">Reset</a></li>
- </ul>
- </div>
- </div>
看到两段代码有点一样了吧,筛选条件下拉菜单里,我将button的样式多加了一个active样式,主要是告诉后端集成的开发人员,如果他想把(已经选择的条件)作为高亮显示就加active样式就可以了,如果没有选择条件,就不用加active样式。
另外一个排序下拉菜单,我多用了一个pull-right,这是因为,刚开始预览的时候发现,如果下拉菜单里的文字太长,就会超出屏幕右侧(溢出了),加了pull-right样式后就可以让它右对齐了,效果如图8-6所示。
图8-6 在Pannel头部添加操作按钮和筛选条件
有点做前端开发的感觉了。看看再增加点什么?最后一列的按钮还没做,应该可以做至少3个按钮:查看详细信息、查看该用户的角色、更多操作(再弹出一个下拉菜单)。还要选择合适的颜色(由于使用默认的btn样式会增加行高,所以使用了超小型按钮)。代码如下:
- <button class="btn btn-xs btn-info">Info</button>
- <button class="btn btn-xs btn-success">Role</button>
- <div class="btn-group">
- <button type="button" class="btn btn-xs btn-primary dropdown-toggle"
- data-toggle="dropdown">
- More <span class="caret"></span>
- </button>
- <ul class="dropdown-menu" role="menu">
- <li><a href="#">Projects</a></li>
- <li><a href="#">Tasks</a></li>
- <li><a href="#">Timesheet</a></li>
- <li class="divider"></li>
- <li><a href="#">Others</a></li>
- </ul>
- </div>
上述示例的运行效果如图8-7所示。
图8-7 表格行数据里的操作按钮显示
图8-7所示的效果看起来还行,但是稍微有点单调。添加一个小图标icon试试怎么样,示例如下:
- <button class="btn btn-xs btn-info">
- <span class="glyphicon glyphicon-list"> </span>Info
- </button>
- <button class="btn btn-xs btn-success">
- <span class="glyphicon glyphicon-user"> </span>Role
- </button>
添加完图标以后,发现小图标和文字靠在一起了,所以又重新定义了一下小图标的右外边距。代码如下:
- .btn > .glyphicon {
- margin-right: 3px;
- }
这样,完成以后,发现运行效果真的比之前好太多了,效果如图8-8所示。
图8-8 综合显示效果
应该能给自己打80分了。但还有问题。第一列的全选按钮checkbox忘记加了,而且ID也没有居中对齐。
于是在第一列和第二列的所有的td上都加了一个text-center样式,但是发现这种方式添加,样式重复出现的次数太多了,为了用最少的代码实现最多的功能,决定使用CSS的选择器来实现(虽然还不太熟),试验了很多次才搞定(看来CSS3还得再强化才行)。代码如下:
- thead > tr:not(:first-child) > td:nth-child(1),
- thead > tr:not(:first-child) > td:nth-child(2),
- tbody > tr > td:nth-child(1),
- tbody > tr > td:nth-child(2) {
- text-align: center;
- }
平时犯懒的时候肯定就只用一个样式,在所有的td上附加,但这次是竞赛,为了体现我还是懂一点CSS3的,所以使用了nth-child、first-child、not这样的选择器条件,保存刷新,效果如图8-9所示。
看着这样的效果,我自己都觉得挺满意了。但是时间还有1个多小时呢,应该再多做一点东西。想一下还要体现哪些能力。对了,弹窗还没用过,这个页面好多地方都可以用到弹窗,比如单击Info按钮的时候查看用户信息,单击Role按钮的时候查看角色信息,单击New按钮时也可以添加新用户。
由于Info按钮和Role按钮都是显示信息,所以我做了一个固定的弹窗,所有的单击事件都调用这一个弹窗(以后开发人员开发的时候再换id就行了)。首先,在所有的Role按钮上都添加了data-toggle和data-target,以便在单击的时候可以找到对应的id。代码如下:
图8-9 复选框显示效果
- <button class="btn btn-xs btn-info" data-toggle="modal"
- data-target="#rolePopUp"> </button>
然后按照Modal插件的要求,设置了一个隐藏的div,并在其中modal-body里设置角色列表,最后还提供一个“关闭”按钮。代码如下:
- <div class="modal fade" id="rolePopUp">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal"
- aria-hidden="true">×</button>
- <h4 class="modal-title" id="myModalLabel">Roles of Tom Xu</h4>
- </div>
- <div class="modal-body">
- <table class="table table-hover">…</table>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default"data-dismiss=
- "modal">Close</button>
- </div>
- </div>
- </div>
- </div>
上述示例的运行效果如图8-10所示。
同样的道理,在New按钮上也绑定一个弹窗,id为newPopup,只不过这一次弹窗的内容变成了表单。对于表单的字段,不用做太多工作,所以只用了email、password、Username这3个字段和一个复选框,但是按钮没有少,提供了3个,分别用于保存、重置和取消操作。表单的代码如下:
图8-10 弹窗显示效果
- <form class="form-horizontal" role="form">
- <div class="form-group">
- <label for="inputEmail3" class="col-sm-2 control-label">Email</label>
- <div class="col-sm-10">
- <input type="email" class="form-control" id="Email"
- placeholder="Email">
- </div>
- </div>
- <div class="form-group">
- <label for="inputPassword3" class="col-sm-2 control-label">Password</label>
- <div class="col-sm-10">
- <input type="password" class="form-control" id="Password"
- placeholder="Password">
- </div>
- </div>
- <div class="form-group">
- <label for="inputPassword3" class="col-sm-2 control-label">Username</label>
- <div class="col-sm-10">
- <input type="text" class="form-control" id="Username"
- placeholder="Username">
- </div>
- </div>
- <div class="form-group">
- <div class="col-sm-offset-2 col-sm-10">
- <div class="checkbox"><label><input type="checkbox">Enable
- </label></div>
- </div>
- </div>
- </form>
运行效果如图8-11所示。但是又发现鼠标单击灰色区域的时候,弹窗就关闭了,这说明缺少禁用这个事件了。于是又在New按钮上加了一个data-backdrop="static"属性,这样就没问题了。
图8-11 带表单的弹窗显示效果
做到这时候,时间还余半个小时,突然想起来,对JavaScript方面的能力还没有体现过呢。正好Modal插件提供了好几个事件回调可以使用。
首先,我想在单击Create按钮的时候对表单进行验证,所以我引入了jQuery的validate插件。在定义JS代码的时候,引入validate库以后,首先进行了设置,然后对单击事件进行监控。代码如下:
- $('#newPopUp').find('#btnCreate').on('click', function (e) {
- $('#newPopUp').find("form").validate({
- submitHandler: function (form) {
- // 处理内容
- }
- });
- })
发现这样做一点儿用都没有,弄了10多分钟也没找出问题,后来只有10多分钟了。所以我就放弃了。但是还有最后5分钟的时候突然发现,可以先使用popover插件伪造一个验证效果代码如下:
- $('#Username').popover({
- title: "Alert",
- content: "Username must be input.",
- placement: "bottom",
- trigger: "manual"
- })
- $('#newPopUp').find('#btnCreate').on('click', function (e) {
- $('#Username').popover("show");
- })
这样在单击按钮的时候,会弹出提示,说用户输入不合法。这样做的目的只是给客户展示我想实现这样的效果(只不过不完善而已)。
最后又发现了一个问题,popover信息提示以后关闭不了,所以我就在input的focus上添加了一个回调,手动关闭整个信息提示。代码如下:
- $('#Username').focus(function () {
- $('#Username').popover("hide");
- });
就这样,总算完成了。最后在评奖的时候,我居然是全公司的第一名,是做得最好的。其他同事大部分都只完成一半,很多人都抱怨说,仅全选、反选的JavaScript代码都浪费了很长时间。我当初没有做这个就是怕代码麻烦,其实说实话,我也没有好的办法哦。