客户需要在OA中实现每日动态功能,能够记录每一位员工的每天的工作动态,我很快想到了时间轴,因为时间轴能很直观的现实员工每一刻的动态。就像Facebook的Timeline效果(点击查看)。

尝试着搜索这个效果,园友的这篇博文正好给我启发,接下来就去实现吧。

成果演示

最终的效果如下所示:

点击每个员工的姓名,即可进入他当天的工作动态(只能看),若点击自己的名字(既能看又能发送/编辑/删除动态),如下所示:

动态的详细页,如下所示:

点击时间轴,即可新增动态,如下所示:

编辑效果,鼠标移至内容区域,现实黄色提醒,如下所示:

单击即可显示编辑界面,如下所示:

移开鼠标,即可自动保存。

当然如果想把一条当太删掉,点击右上角X即可。

实现原理

关于效果的实现原理可以参考这篇文章

了解了上面提到的这篇文章之后(Masonry.js),接下来就是Sharepoint 客户端对象模型的实现了,比如Ecmascript。

  • 根据登陆的用户点击的员工名字获取当天的动态,这儿需要利用CAML拼接出查询条件
function GetCurrentUser(){
//Get the current context
var context=new SP.ClientContext.get_current();
//Load the web object
var web=context.get_web();
//Get current user
this.currentUser=web.get_currentUser();
//load currentUser
context.load(currentUser);
//Make a query call to execute the above statements
context.executeQueryAsync(OnGetCurrentUserSuccess,OnGetCurrentUserFailed);
} function OnGetCurrentUserSuccess(){
GetDailyWorks();
}
function OnGetCurrentUserFailed(sender,args){
console.log('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
} function GetDailyWorks(){
//Get the current context
var context=new SP.ClientContext.get_current();
//Load the web object
var web=context.get_web();
//Get the list
var list=web.get_lists().getByTitle(listNameForDailyWork);
//Get items by caml in the specific list
var camlQuery=new SP.CamlQuery();
var d=new Date();
//Get specific field name
this.userNameWhenClickView=$("#currentUserHidden").val();
camlQuery.set_viewXml('<View><Query>'+
'<Where>'+
'<And>'+
'<And>'+
'<And>'+
'<Eq>'+
'<FieldRef Name=\'Title\'/>'+
'<Value Type=\'Text\'>'+userNameWhenClickView+'</Value>'+
'</Eq>'+
'<Eq>'+
'<FieldRef Name=\'CurrentYear\'/>'+
'<Value Type=\'Text\'>'+d.getFullYear()+'</Value>'+
'</Eq>'+
'</And>'+
'<Eq>'+
'<FieldRef Name=\'CurrentMonth\'/>'+
'<Value Type=\'Text\'>'+(d.getMonth()+)+'</Value>'+
'</Eq>'+
'</And>'+
'<Eq>'+
'<FieldRef Name=\'CurrentDay\'/>'+
'<Value Type=\'Text\'>'+d.getDate()+'</Value>'+
'</Eq>'+
'</And>'+
'</Where>'+
'<OrderBy>'+
'<FieldRef Name=\'Created\' Ascending=\'True\'/>'+
'</OrderBy></Query></View>');
dailyWorks=list.getItems(camlQuery);
//Load the web in the context and retrieve only selected columns to improve perfomance
context.load(dailyWorks,'Include(ID,Title,DailyContent,Created)');
//Make a query call to execute the above statements
context.executeQueryAsync(OnGetDailyWorksSuccess,OnGetDailyWorkFailed); }
function OnGetDailyWorksSuccess(){
//Get the collection
var dailyWorksCollection=dailyWorks.getEnumerator();
//Iterate through daily works
while(dailyWorksCollection.moveNext()){
//Load the current daily work item in iterate
var workItem=dailyWorksCollection.get_current();
//Add work item to container addWorkToContainer(workItem.get_item('ID'),workItem.get_item('Title'),workItem.get_item('DailyContent'),workItem.get_item("Created"));
}
//Items has added in container and execute AutoMasonry method
AutoMasonry();
//Init in line edit if current user has permission to edit
if(userNameWhenClickView==currentUser.get_title()){
InitInlineEdit($('.editable, .editable-area'));
} }
//Error Handler
function OnGetDailyWorkFailed(sender,args){
console.log('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
  • 当然Add一个Item也是比较方便的,当Add Item完毕后,很重要的一点是利用Masonry Reload一下所有的item
function AddNewDailyWorkItem(content){
//get the current context
var context=new SP.ClientContext.get_current();
//Load the web object
var web=context.get_web();
//Get the list
var list =web.get_lists().getByTitle(listNameForDailyWork);
//create the ListItemInfomational object
var listItemInfo=new SP.ListItemCreationInformation();
//add the item to the list
this.listItem=list.addItem(listItemInfo);
//get current user display name
var userDisplayName=currentUser.get_title();
//Assign values for fields
listItem.set_item('Title',userDisplayName);
listItem.set_item('DailyContent',content);
//Get current year ,month,day and assign values for fields
var newObj=new Date();
listItem.set_item('CurrentYear',newObj.getFullYear());
listItem.set_item('CurrentMonth',newObj.getMonth()+);
listItem.set_item('CurrentDay',newObj.getDate());
//Apply changes to item
listItem.update(listItem);
context.load(listItem);
//Make a query call to execute the above statements
context.executeQueryAsync(AddDailyWorkItemSuccess,AddDailyWorkItemFailed); }
function AddDailyWorkItemSuccess(sender,args){ var content = $("#update").val();
$('<div class="item"><a href="#" itemId="'+listItem.get_id()+'" class="deletebox">X</a>' + '<div class="inner"><p itemId="'+listItem.get_id()+'" class="editable-area">' + content + '</p></div><p class="sendStyle">发送于'+(new Date()).getHours()+':'+((new Date()).getMinutes()<?""+(new Date()).getMinutes():(new Date()).getMinutes())+'</p></div>').insertBefore("div#popup");
//reload masnory
$("#container").masonry("reload");
//Hiding existing arrows
$(".rightCorner").hide();
$(".leftCorner").hide();
//injecting fresh arrows
Arrow_Points();
//clear popup text box value
$("#update").val("");
//popup hide
$("#popup").hide();
//Init in line edit
$('p[itemId='+listItem.get_id()+']');
InitInlineEdit($('p[itemId='+listItem.get_id()+']')); }
function AddDailyWorkItemFailed(sender,args){
console.log('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
  • Update 和Add是相同的逻辑,记得最后Reload即可
function UpdateDailyWorkItem(itemId,updateContent){
//If no title is setted then show alert and set focus
/*if(updateContent==''){
$()
}*/
//Get the current context
var context = new SP.ClientContext.get_current();
//Load the web object
var web=context.get_web();
//Get the list
var list=web.get_lists().getByTitle(listNameForDailyWork);
//Get item to update by Id from the specific list
this.listItem=list.getItemById(itemId);
//Set the new property value
listItem.set_item('DailyContent',updateContent);
//Call the update method to commit the change
listItem.update(); context.executeQueryAsync(updateWorkItemSuccess,updateWorkItemFailed); } function updateWorkItemSuccess(){
$editable
.removeClass('active-inline')
.children()
.replaceWith(edited); if ($editable.hasClass('editable-area')) {
rapture($editable);
}
//reload masnory
$("#container").masonry("reload");
//Hiding existing arrows
$(".rightCorner").hide();
$(".leftCorner").hide();
//injecting fresh arrows
Arrow_Points(); } function updateWorkItemFailed(){ }
  • Delete Item,根据item id进行删除,同Add和Update逻辑,删除完毕后也是需要Reload
//Delete daily work item by item id
function deleteDailyWork(workElement){
//Get the daily work item id
var itemId=workElement.attr("itemId");
//Get the current context
var context=new SP.ClientContext.get_current();
//Load the web object
var web=context.get_web();
//Get the list
var list=web.get_lists().getByTitle(listNameForDailyWork);
//Get item to delete by if form the list
var itemToDelete=list.getItemById(itemId);
//Add Delete method to the query
itemToDelete.deleteObject();
//Execute the query to perform the deletion
context.executeQueryAsync(DeleteWorkItemSuccess,DeleteWorkItemFailed); } function DeleteWorkItemSuccess(){
//Masonry Reload
} function DeleteWorkItemFailed(sender,args){
console.log('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}

总结

值得注意的是我将每日的动态存入List中,对于List,他能负担的item的个数和一次从数据库里获取的item都是有限制,对于数据量很大的情况下,是有风险的。

SharePoint 中时间轴 Timeline的实现的更多相关文章

  1. 时间轴 timeline

    时间轴 timeline https://www.helloweba.net/javascript/285.html https://www.helloweba.net/demo/v_timeline ...

  2. Alamofire源码解读系列(十二)之时间轴(Timeline)

    本篇带来Alamofire中关于Timeline的一些思路 前言 Timeline翻译后的意思是时间轴,可以表示一个事件从开始到结束的时间节点.时间轴的概念能够应用在很多地方,比如说微博的主页就是一个 ...

  3. 横向、纵向时间轴timeline系列

    近期移动端项目用到了很多时间轴.纵向的.开始可以实现,但是不利于维护.整理下, 以作为备份留存学习参考.子元素的 标签的 :before实现圆点,:after实现边线border纵向时间轴,单一右边内 ...

  4. 超酷的JavaScript叙事性时间轴(Timeline)类库

    在线演示 Timeline 是我见过的最酷的展示事件随时间发展的javascript实现.你可以基于时间使用讲故事的方式来创建时间轴特效,整个时间轴以幻灯的方式来展示,你可以穿插图片,视频或者是网站, ...

  5. echarts使用结合时间轴timeline动态刷新案例

    1.echarts简介 ECharts,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Fire ...

  6. JQuery时间轴timeline插件的学习-Lateral On-Scroll Sliding with jQuery+technotarek / timeliner

    一.Lateral On-Scroll Sliding with jQuery的使用 View demo      Download source 1. HTML结构 <div id=" ...

  7. Android 时间轴TimeLine

    代码:这里

  8. iOS之TimeLine(时间轴)的实现

    这是一个关于OC时间轴的简单实现,我认为重要的是思路. 感谢作者:Cyandev 的文章<iOS 实现时间线列表效果>给的思路.这里先附上Objective-C的代码实现,有时间再去试试S ...

  9. Timeline Portfolio - 时间轴作品集效果

    这里分享一个超炫的时间轴展示作品集效果.设计师和前端开发人员可以借助这个效果来制作新颖的作品集和个人简历.时间轴专门用来呈现出年代的一系列事件.您可以把这种效果嵌入各种媒体,包括微博,视频和地图,并把 ...

随机推荐

  1. 使用Feign时报错Service id not legal hostname

    报错Service id not legal hostname的原因是服务名称不能带有下划线,可以使用中划线

  2. PAT《数据结构学习与实验指导》实验项目集 2-09 2-10 2-11 2-12 2-13

    pat 2-09 装箱问题模拟 #include<cstdio> #include<set> #include<vector> using namespace st ...

  3. MACD底背离选股公式——通达信、同花顺

    {底背离,通达信版.同花顺版} DIFF:=EMA(CLOSE,) - EMA(CLOSE,); DEA:=EMA(DIFF,); MACD:=*(DIFF-DEA); QZQ:=BARSLAST(R ...

  4. MySQL排序:SELECT ORDER BY

    SELECT 和ORDER BY结合进行排序: products表例如以下: a 按产品名称列进行排序: b 按多个列进行排序,默认排序顺序为升序: c 指定排序方向,即指定为降序: d 对多个列进行 ...

  5. iframe 与 frame 区别

    1.iframe iframe主要来内联一个外联的页面,如: <!DOCTYPE html> <html lang="zh"> <head> & ...

  6. 路由器mtu值设置

    MTU=最大传输单元 单位:字节 英文:Maximum Transmission Unit”我们平时上网时的各种操作,都是通过一个又一个“数据包”传输来实现的.而MTU指定了网络中可传输数据包的最大尺 ...

  7. ReactNative踩坑日志——代码执行方式(面向对象)

    在ReactNative中,是以面向对象的方式执行代码的.处于同一{}內的代码以对象的形式执行,也就是说,程序虽然会自上而下执行代码,但是它会保证当前整个代码块內的语句执行完毕才执行下一代码块. 举个 ...

  8. vim 窗口操作:多tab|窗口拆分

    转 我是一个vimer,还在用着这个上古时代的编辑器,但我并不是守旧派,因为即使是 现在,vim也在不断的创新.我用vim也有一两年的光景了,但是我还是不敢我自己 精通vim,当然我使用vim基本是两 ...

  9. Oracle Data Integrator 12c----一致性 CDC(Consistent CDC)

    一致性 CDC 中引入了变化集的概念.一个变化集中可以包括多个相互存在关联关系(如主外键引用关系)的表.CDC 在捕获和发布一个变化集中的变化时能够保证数据的一致性.这个练习介绍如何使用能够保证一致性 ...

  10. 转:Bullet物理引擎不完全指南(Bullet Physics Engine not complete Guide)

    write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie 讨论新闻组及文件 前言 Bullet据称为游戏世界占有率为第三的物理引擎,也是前几大引擎目前唯一能够 ...