利用KindEditor实现公司通讯录的维护
引言:
本人所属施工单位,在建项目较多,通讯录是以项目为单位挂接在公司内部网站通讯录板块,以静态页面展示。一直以来都是项目部办公室通过电话、邮件等方式通知总部信息部门变更通讯录,日常维护的工作量较大。最近受领导委托设计一款能让项目部自助维护通讯录的软件,一二级部门标题要加以区分,要方便排序,方便维护,还要统一风格显示。
↑公司现有通讯录效果展示
第一种方案是后台挂接Excel表格,前台展示,这种显示效果一般,不符合要求。
↑Excel通讯录效果展示
第二种方案是后台单条录入,前台用表格(XXGrid,Repeater)展示,这种维护方便,但是不太方便排版。
↑第三方表格通讯录效果展示
第三种方案是后台编辑HTML表格,前台使用css样式调整显示风格。这种方案符合预期,但是让非技术人员编辑HTML表格,而且要统一风格,难度有点大。于是构思怎样简化用户操作,想到了用在线编辑器固定Table样式,然后通过自定义按钮实现简单的文字调整。
↑预期效果展示
其实技术实现并不难,主要是细节问题处理和调试工作繁琐,本人花费两天时间研究并实现了这个功能,下面详细展开说一下。
我这里使用的是KindEditor,最新版可以到官网下载。
首先新建一个空白页面,引用以下脚本文件:
<script src="Script/jquery-1.8.2.min.js"></script>
<script src="Script/kindeditor/kindeditor-all-min.js"></script>
<script src="Script/kindeditor/lang/zh-CN.js"></script>
然后自己设计或从网上找一些漂亮的table样式,比如我在百度找了一段css样式(版权归原作者啊):
* {
margin: 0;
padding: 0;
} body {
padding: 40px 50px;
} .demo {
width: 600px;
margin: 40px auto;
font-family: 'trebuchet MS', 'Lucida sans', Arial;
font-size: 14px;
color: #444;
}
.header {
text-align:center;
background-color:#dfefff;
height:90px;
width:100%;
}
.footer {
text-align:center;
background-color:#dfefff;
height:30px;
width:100%;
position:fixed;
bottom:0;
}
table {
*border-collapse: collapse; /* IE7 and lower */
border-spacing: 0;
width: 100%;
border: solid #ccc 1px;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
border-radius: 6px;
-webkit-box-shadow: 0 1px 1px #ccc;
-moz-box-shadow: 0 1px 1px #ccc;
box-shadow: 0 1px 1px #ccc;
} table tr {
-o-transition: all 0.1s ease-in-out;
-webkit-transition: all 0.1s ease-in-out;
-moz-transition: all 0.1s ease-in-out;
-ms-transition: all 0.1s ease-in-out;
transition: all 0.1s ease-in-out;
} table .highlight,
table tr:hover {
background: #fbf8e9;
} table td,
table th {
border-left: 1px solid #ccc;
border-top: 1px solid #ccc;
padding: 10px;
text-align: left;
} table th {
background-color: #dce9f9;
-ms-filter: "progid:DXImageTransform.Microsoft.gradient (GradientType=0, startColorstr=#ebf3fc, endColorstr=#dce9f9)";
-webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, .8) inset;
-moz-box-shadow: 0 1px 0 rgba(255, 255, 255, .8) inset;
box-shadow: 0 1px 0 rgba(255, 255, 255, .8) inset;
text-shadow: 0 1px 0 rgba(255, 255, 255, .5);
background-image: linear-gradient(top, #ebf3fc, #dce9f9);
border-top-style: none;
border-top-color: inherit;
border-top-width: medium;
} table td:first-child,
table th:first-child {
border-left: none;
} table th:first-child {
-moz-border-radius: 6px 0 0 0;
-webkit-border-radius: 6px 0 0 0;
border-radius: 6px 0 0 0;
} table th:last-child {
-moz-border-radius: 0 6px 0 0;
-webkit-border-radius: 0 6px 0 0;
border-radius: 0 6px 0 0;
} table tr:last-child td:first-child {
-moz-border-radius: 0 0 0 6px;
-webkit-border-radius: 0 0 0 6px;
border-radius: 0 0 0 6px;
} table tr:last-child td:last-child {
-moz-border-radius: 0 0 6px 0;
-webkit-border-radius: 0 0 6px 0;
border-radius: 0 0 6px 0;
}
/*----------------------*/
.zebra td,
.zebra th {
padding: 10px;
border-bottom: 1px solid #f2f2f2;
} .zebra .alternate,
.zebra tbody tr:nth-child(even) {
background: #f5f5f5;
-webkit-box-shadow: 0 1px 0 rgba(255,255,255,.8) inset;
-moz-box-shadow: 0 1px 0 rgba(255,255,255,.8) inset;
box-shadow: 0 1px 0 rgba(255,255,255,.8) inset;
} .zebra th {
text-align: left;
text-shadow: 0 1px 0 rgba(255,255,255,.5);
border-bottom: 1px solid #ccc;
background-color: #eee;
-ms-filter: "progid:DXImageTransform.Microsoft.gradient (GradientType=0, startColorstr=#f5f5f5, endColorstr=#eeeeee)";
background-image: linear-gradient(top, #f5f5f5, #eee);
} .zebra th:first-child {
-moz-border-radius: 6px 0 0 0;
-webkit-border-radius: 6px 0 0 0;
border-radius: 6px 0 0 0;
} .zebra th:last-child {
-moz-border-radius: 0 6px 0 0;
-webkit-border-radius: 0 6px 0 0;
border-radius: 0 6px 0 0;
} .zebra tfoot td {
border-bottom: 0;
border-top: 1px solid #fff;
background-color: #f1f1f1;
} .zebra tfoot td:first-child {
-moz-border-radius: 0 0 0 6px;
-webkit-border-radius: 0 0 0 6px;
border-radius: 0 0 0 6px;
} .zebra tfoot td:last-child {
-moz-border-radius: 0 0 6px 0;
-webkit-border-radius: 0 0 6px 0;
border-radius: 0 0 6px 0;
}
第三步需要找一些自定义按钮图标,添加到页面的Body里,为啥不能放到Head里呢,我也有点郁闷,放到Head里自定义按钮都不显示了,为此还调试了老半天。
/*----------编辑器上的自定义按钮图标------------*/ .ke-icon-settfirst {
background-image:url(/Resource/first.gif);
width: 16px;
height: 16px;
}
.ke-icon-settsecond {
background-image:url(/Resource/second.gif);
width: 16px;
height: 16px;
}
.ke-icon-cancelthead {
background-image:url(/Resource/cancel.gif);
width: 16px;
height: 16px;
}
.ke-icon-moveup {
background-image:url(/Resource/moveup.gif);
width: 16px;
height: 16px;
}
.ke-icon-movedown {
background-image:url(/Resource/movedown.gif);
width: 16px;
height: 16px;
}
第四步在Body里添加textarea元素
<div>
<textarea id="editor_id" name="content" style="width:700px;height:300px;">
</textarea>
</div>
第五步是编写KindEditor脚本,也是难度最大的部分,主要实现的功能就是设置标题,上下左右移动和保存。闲话不说,具体看代码吧。
// 自定义插件
KindEditor.lang({
settfirst: '设置为一级标题',
settsecond: '设置为二级标题',
cancelthead: '取消标题',
moveup: '向上移动',
movedown: '向下移动',
moveleft: '向左移动',
moveright: '向右移动',
savedata: '保存'
});
KindEditor.plugin('settfirst', function (K) {
var self = this, name = 'settfirst';
self.clickToolbar(name, function () {
table = self.plugin.getSelectedTable();
if (table) {
var cell = self.plugin.getSelectedCell();
if (cell == null) return;
cell[0].style.cssText = '';
cell[0].outerHTML = cell[0].outerHTML.replace(/td/g, "th"); }
});
});
KindEditor.plugin('settsecond', function (K) {
var self = this, name = 'settsecond';
self.clickToolbar(name, function () {
table = self.plugin.getSelectedTable();
if (table) {
var cell = self.plugin.getSelectedCell();
if (cell == null) return;
cell[0].style.cssText = 'font-color:#0000ff;font-size:10px;font-name:隶书';
cell[0].outerHTML = cell[0].outerHTML.replace(/td/g, "th"); }
});
});
KindEditor.plugin('cancelthead', function (K) {
var self = this, name = 'cancelthead';
self.clickToolbar(name, function () {
table = self.plugin.getSelectedTable();
if (table) {
var cell = self.plugin.getSelectedThead();
if (cell == null) return;
cell[0].style.cssText = '';
cell[0].outerHTML = cell[0].outerHTML.replace(/th/g, "td"); }
});
self.plugin.getSelectedThead = function () {
return self.cmd.commonAncestor('th');
};
});
KindEditor.plugin('moveup', function (K) {
var self = this, name = 'moveup';
self.clickToolbar(name, function () {
var table = self.plugin.getSelectedTable();
if (table) {
var row = self.plugin.getSelectedRow()[0]; var cells = self.plugin.getSelectedCell();
if (cells == null)
cells = self.plugin.getSelectedThead();
var cell = cells[0]; var rowIndex = row.rowIndex,
cellIndex = cell.cellIndex,
preRowIndex = rowIndex - 1;
// 第一行不能移动
if (preRowIndex <= 0) {
return;
}
var prevCell = table[0].rows[preRowIndex].cells[cellIndex];
if (prevCell.innerHTML != "" && prevCell.innerHTML != " ") {
if (confirm('目标单元格不为空,是否替换?')) { }
else {
return;
}
}
prevCell.innerHTML = cell.innerHTML;
cell.innerHTML = ""; }
});
self.plugin.getSelectedThead = function () {
return self.cmd.commonAncestor('th');
};
});
KindEditor.plugin('movedown', function (K) {
var self = this, name = 'movedown';
self.clickToolbar(name, function () {
var table = self.plugin.getSelectedTable();
if (table) {
var row = self.plugin.getSelectedRow()[0]; var cells = self.plugin.getSelectedCell();
if (cells == null)
cells = self.plugin.getSelectedThead();
var cell = cells[0]; var rowIndex = row.rowIndex,
cellIndex = cell.cellIndex,
nextRowIndex = rowIndex + 1;
// 最后一行不能移动
if (nextRowIndex >= table[0].rows.length) {
return;
}
var nextCell = table[0].rows[nextRowIndex].cells[cellIndex];
if (nextCell.innerHTML != "" && nextCell.innerHTML != " ") {
if (confirm('目标单元格不为空,是否替换?')) { }
else {
return;
}
}
nextCell.innerHTML = cell.innerHTML;
cell.innerHTML = ""; }
});
self.plugin.getSelectedThead = function () {
return self.cmd.commonAncestor('th');
};
});
KindEditor.plugin('moveleft', function (K) {
var self = this, name = 'moveleft';
self.clickToolbar(name, function () {
var table = self.plugin.getSelectedTable();
if (table) {
var row = self.plugin.getSelectedRow()[0]; var cells = self.plugin.getSelectedCell();
if (cells == null)
cells = self.plugin.getSelectedThead();
var cell = cells[0]; var rowIndex = row.rowIndex,
cellIndex = cell.cellIndex,
prevCellIndex = cellIndex - 1;
// 最左一列不能移动
if (prevCellIndex < 0) {
return;
}
var prevCell = table[0].rows[rowIndex].cells[prevCellIndex];
if (prevCell.innerHTML != "" && prevCell.innerHTML != " ") {
if (confirm('目标单元格不为空,是否替换?')) { }
else {
return;
}
}
prevCell.innerHTML = cell.innerHTML;
cell.innerHTML = ""; }
});
self.plugin.getSelectedThead = function () {
return self.cmd.commonAncestor('th');
};
});
KindEditor.plugin('moveright', function (K) {
var self = this, name = 'moveright';
self.clickToolbar(name, function () {
var table = self.plugin.getSelectedTable();
if (table) {
var row = self.plugin.getSelectedRow()[0]; var cells = self.plugin.getSelectedCell();
if (cells == null)
cells = self.plugin.getSelectedThead();
var cell = cells[0]; var rowIndex = row.rowIndex,
cellIndex = cell.cellIndex,
nextCellIndex = cellIndex + 1;
// 最右一列不能移动
if (nextCellIndex >= table[0].rows[rowIndex].cells.length) {
return;
}
var nextCell = table[0].rows[rowIndex].cells[nextCellIndex];
if (nextCell.innerHTML != "" && nextCell.innerHTML != " ") {
if (confirm('目标单元格不为空,是否替换?')) { }
else {
return;
}
}
nextCell.innerHTML = cell.innerHTML;
cell.innerHTML = ""; }
});
self.plugin.getSelectedThead = function () {
return self.cmd.commonAncestor('th');
};
});
KindEditor.plugin('savedata', function (K) {
var self = this, name = 'savedata';
self.clickToolbar(name, function () { SaveData(); });
});
KindEditor.ready(function (K) {
window.editor = K.create('#editor_id', {
cssPath: 'Style/table.css',
items: ['source', 'settfirst', 'settsecond', 'cancelthead', 'moveup', 'movedown', 'moveleft', 'moveright', '|', 'savedata'],
fullscreenMode: true
}); });
需要说明的是KindEditor可以引用外部样式,我就是用 cssPath: 'Style/table.css'来把表格样式固定的,也就是说,在外部定义好Table的css样式,在KindEditor里只需要考虑<tr><td>元素的创建合并,不需要考虑样式问题。
表格的保存按钮实现也很简单,我这里是用Ajax实现的保存功能,代码如下:
function SaveData() { var postData = { mode: "0", data: encodeURIComponent(window.editor.html()) }; $.ajax({
type: 'post',
dataType: "text",
url: RootPath() + "/DataHandler.ashx",//请求保存的服务器目录
data: postData,
cache: false,
async: false,
success: function (data) {
if (data == "ok") {
location.href = "ShowPhone.html";
}
},
error: function (data) {
alert("error:" + JSON.stringify(data));
}
});
}
其中window.editor.html()是表格的内容,最好用encodeURIComponent函数对内容进行编码,不然到后台接收的时候可能会出现乱码或被拒绝的情况,后台接收到然后在解码即可。我这里用的C#语言,用Uri.UnescapeDataString 方法可实现解码。
展示页在这里就不介绍了,先引用table的样式文件,再从数据库提取到Table代码,加载到Body里即可。以下是编辑器显示效果。
利用KindEditor实现公司通讯录的维护的更多相关文章
- 利用KindEditor的uploadbutton实现异步上传图片
利用KindEditor的uploadbutton实现异步上传图片 异步上传图片最经常使用的方法就是图片在iframe中上传.这样仅仅须要刷新iframe.而不用刷新整个页面. KindEdi ...
- .net mvc4 利用 kindeditor 上传本地图片
http://blog.csdn.net/ycwol/article/details/41824371?utm_source=tuicool&utm_medium=referral 最近在用k ...
- 利用本地SQL Server维护计划来维护SQL Database
On-Premise的SQL Server提供了维护计划来定期.定时的维护SQL Server.一般的做法是:定义SQL Server Agent Jobs,而后维护计划帮助我们定期.定时执行SQL ...
- [gj]来公司停电了-维护机器
停电出现的问题 一早来机房跳闸了. 很多vm手动起来后有些服务不太正常了. 机房锁坏了.不知道谁进去干啥了.导致跳闸 闸门不知道在哪里.导致所有机器停电了 牵扯到的技术点: 1,nexus启动. ng ...
- 利用Powershell获取公司内部机器的资源信息,作为企业兴许资产管理的基本途径!
今天一个哥们问我是否用Powershell 实现.我好久没有写脚本,脚本的协作和调试还是费了一些时间,兴许调试了下.运作没有问题,大家能够參考以下的脚本来丰富您企业须要做的一些事情,脚本代码例如以下: ...
- 利用Ossim系统进行主机漏洞扫描
利用Ossim系统进行主机漏洞扫描 企业中查找漏洞要付出很大的努力,不能简单的在服务器上安装一个漏洞扫描软件那么简单,那样起不了多大作用.这并不是因为企业中拥有大量服务器和主机设备,这些服务器和设备又 ...
- 如何利用Flink实现超大规模用户行为分析
如何利用Flink实现超大规模用户行为分析 各位晚上好,首先感谢大家参与我的这次主题分享,同时也感谢 InfoQ AI 前线组织这次瀚思科技主题月! 瀚思科技成立于 2014 年,按行业划分我们是 ...
- 杂项-公司:Apple
ylbtech-杂项-公司:Apple 苹果公司(Apple Inc. )是美国的一家高科技公司.由史蒂夫·乔布斯.斯蒂夫·沃兹尼亚克和罗·韦恩(Ron Wayne)等人于1976年4月1日创立,并命 ...
- 利用KMeans聚类进行航空公司客户价值分析
准确的客户分类的结果是企业优化营销资源的重要依据,本文利用了航空公司的部分数据,利用Kmeans聚类方法,对航空公司的客户进行了分类,来识别出不同的客户群体,从来发现有用的客户,从而对不同价值的客户类 ...
随机推荐
- 版本控制之二:SVN的初步使用(转)
转自http://www.cnblogs.com/xiaobaihome/archive/2012/03/20/2407979.html 上一篇介绍了VisualSVN Server和Tortoise ...
- C++STL之双端队列容器
C++STL之双端队列容器 deque双端队列容器与vector很类似,采用线性表顺序存储结构.但与vector区别,deque采用分块的线性存储结构来存储数据,每块的大小一般为512B,将之称为de ...
- The Suspects(并查集维护根节点信息)
The Suspects Time Limit: 1000MS Memory Limit: 20000K Total Submissions: 37090 Accepted: 17980 De ...
- Problem J
Problem Description 有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法? Input 输入数据首先包含一个整数N,表示测试实例的个数,然后是 ...
- Building Block
Building Block Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- java中自动装箱带来的性能问题
之前没有特别注意自动封装所带来的性能问题,今天看了effective java,实验了一下,结果大吃一惊: 考虑下面这段代码: public static void main(String args[ ...
- js 切换全屏
公司有一个需求就是点击某一个按钮实现全屏切换功能,然后呢我就在网上扒了段代码.封装了一下.使用的小伙伴们可以看看哦! 切换全屏代码 <!DOCTYPE html> <html> ...
- 让C++控制台程序停下来,实现暂停功能
一.针对Microsoft #include <stdlib.h> (1)第一种方式system( "PAUSE "); -------------------- ...
- bzoj1003
考虑dp[i]表示前i天的最小总成本. 枚举上一次在第j天之后对路线进行了修改,那么就由dp[j]转移至dp[i],转移的代价是把第[j+1,i]天所有被占用的点全删掉后的最短路(不连通当然就是INF ...
- asp.net web api 版本控制
版本控制 版本控制的方法有很多,这里提供一种将Odata与普通web api版本控制机制统一的方法,但也可以单独控制,整合控制与单独控制主要的不同是:整合控制通过VersionController ...