SharePoint客户端对象模型—任务日历生成
1,憋了好几天在经理帮助下用Js根据任务列表,生成的个人任务日历。
(1)需要用到的CSS样式
<style type="text/css"> th.ms-vh { color:white; background-color:rgb(68, 68, 68); line-height:25px; } th.ms-vh td.ms-vb a { color:white !important; } .taskstatus { background-position:center center; background-repeat:no-repeat; } .datespan { height: 100%; text-align: left; overflow: hidden; padding-bottom: 5px; padding-left: 5px; font-family: Segoe UI; font-size: 8pt; float: left; white-space: nowrap; } .dateline { border-color: rgb(210, 210, 210); height: 100%; overflow: hidden; border-left-width: 1px; border-left-style: solid; float: left; white-space: nowrap; } .taskitem { height: 36px; background-color: rgb(216, 216, 216); } .taskitem span { color: rgb(68, 68, 68); font-family: Segoe UI; font-size: 8pt; } .ms-tl-mainArea{ position:static !important; margin-bottom:10px; } .inline{ display:none !important; } .ms-cui-topBarMaximized{ display:none !important; } #CSRListViewControlDivWPQ2{ display:none; } #Hero-WPQ2{ display:none; } #contentBox { margin-right:5px !important; } </style>
(2),用到的Js代码
2.1 页面加载运行该方法
$(function () { ExecuteOrDelayUntilScriptLoaded(getcanderCertType, "sp.js"); })
2.2 根据当前项目和当前用户查询数据
function retrieveListItems() { var projectId = getQueryString('projectId'); var userName = $("#O365_MainLink_Me").attr("title"); var siteUrl = _spPageContextInfo.webServerRelativeUrl; var clientContext = new SP.ClientContext(siteUrl); //列表名一定要用中文 var oList = clientContext.get_web().get_lists().getByTitle('项目工作项'); var camlQuery = new SP.CamlQuery(); camlQuery.set_viewXml( '<View><Query>' + '<Where>' + '<And>' + '<Eq>' + '<FieldRef Name=\'Project\' LookupId=\'TRUE\'/><Value Type=\'Lookup\'>' + projectId + '</Value>' + '</Eq>' + '<Eq>' + '<FieldRef Name=\'AssignedTo\'/><Value Type=\'User\'>' + userName + '</Value>' + '</Eq>' + '</And>' + '</Where></Query>' + '<RowLimit>10</RowLimit></View>' ); this.collListItem = oList.getItems(camlQuery); clientContext.load(collListItem); clientContext.executeQueryAsync( Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed) ); } function onQuerySucceeded(sender, args) { var listItemInfo = ''; var listItemEnumerator = collListItem.getEnumerator(); var today = new Date(); today.setDate(today.getDate() + 14); var nowday = new Date(); CreateTimeLine(nowday, today, listItemEnumerator); } function onQueryFailed(sender, args) { alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace()); }
2.3 开始根据查询出来的数据动态生成HTML
function CreateTimeLine(startdate, enddate, listItemEnumeratorCertType) { //将时间段传进来 var alldays = 14; //将时间段分为6部,每一步的天数 var steplength = parseInt(alldays / 6); //如果小于零,至少有一部!!!我这儿用不到 //if (steplength == 0) { //steplength++; //} //获取最外层的容器 var liufirstlevelcontainer = $("#liufirstlevelcontainer"); //显示时间的div var liufirstleveldate = $("#liufirstleveldate"); //显示时间线的div var liufirstleveldateline = $("#liufirstleveldateline"); //获得外层容器的长度800px var containerlength = parseInt($("#DeltaPlaceHolderMain").css("width")); //获得每一天的长度,我这儿直接除以14就可以了 //一共14天,长度800px!相除得到每一天的长度 var onedaylength = parseInt(containerlength / alldays); //给最外层的线添加一个属性 $(liufirstleveldateline).attr("cutomernumber", alldays) var time1 = startdate; //获取开始时间 do { //每天的长度乘以每段表示的天数 var spanlength = onedaylength * steplength; //创建一个span标签 var timespan = document.createElement("span"); //给这个span设置宽度! $(timespan).css("width", spanlength - 4); //添加样式 $(timespan).addClass("datespan"); //将开始时间写到span里面 $(timespan).text(time1.toLocaleDateString()); //将每一步的天数添加到cutomernumber属性上 $(timespan).attr("cutomernumber", steplength); //将这个span加入到div中 $(timespan).appendTo($(liufirstleveldate)); //在创建一个span var timelinespan = document.createElement("span"); //span的宽度为每段的长度 $(timelinespan).css("width", spanlength); //添加样式 $(timelinespan).addClass("dateline"); //添加属性 $(timelinespan).attr("cutomernumber", steplength); //添加到div中 $(timelinespan).appendTo($(liufirstleveldateline)); //将当前时间加一天 time1 = DateAddDays(time1, steplength); } while (time1 <= enddate); //创建一个对象 var taskdates = new Map(); //声明一个变量表示div的高度 var divheightnumber = 1; //获取所有条目 var taskrow = new Map(); startdate = new Date(startdate.getFullYear(), startdate.getMonth(), startdate.getDate(), 0, 0, 10); enddate = new Date(enddate.getFullYear(), enddate.getMonth(), enddate.getDate(), 23, 59, 59); while (listItemEnumeratorCertType.moveNext()) { var listitem = listItemEnumeratorCertType.get_current(); //获取每个条目的开始日期结束日期 var itemstartdate = listitem.get_item('StartDate'); itemstartdate = new Date(itemstartdate.getFullYear(), itemstartdate.getMonth(), itemstartdate.getDate(), 0, 0, 10); var itemenddate = listitem.get_item('DueDate'); itemenddate = new Date(itemenddate.getFullYear(), itemenddate.getMonth(), itemenddate.getDate(), 23, 59, 59); //声明一个变量等于开始日期 var tempdate = itemstartdate; //定义一个变量表示这个任务上面有几个任务 if ((itemstartdate >= startdate && itemstartdate <= enddate) || (itemstartdate >= startdate && itemenddate <= enddate) || (itemstartdate <= startdate && itemenddate >= enddate) || (itemenddate >= startdate && itemenddate <= enddate)) { var topnumber = 0; do { //将开始时间转为本地时间 var timekey = topnumber + ";" + tempdate.toLocaleDateString(); if (taskrow.ContainsKey(timekey)) { var timevalue = taskrow.get(timekey); if (timevalue >= 1) { topnumber = topnumber + 1; tempdate = itemstartdate; continue; } } //开始时间加一天 tempdate = DateAddDays(tempdate, 1); //开始时间每次加一天,当大于结束时间的时候跳出循环 } while (tempdate <= itemenddate); var tempsetdate = itemstartdate; do { var timekey = topnumber + ";" + tempsetdate.toLocaleDateString(); taskrow.set(timekey, 1); tempsetdate = DateAddDays(tempsetdate, 1); } while (tempsetdate <= itemenddate); if (topnumber + 1 > divheightnumber) { //将外层的div的高度基数加一 divheightnumber = topnumber + 1; } //计算每个开始时间结束时间差 var itemdays; if (itemenddate >= enddate) { if (itemstartdate <= startdate) { itemdays = daysBetween(enddate, startdate); } else { itemdays = daysBetween(enddate, itemstartdate); } } else { if (itemstartdate <= startdate) { itemdays = daysBetween(itemenddate, startdate); } else { itemdays = daysBetween(itemenddate, itemstartdate); } } //每个条目的长度等于每一天的长度乘以天数 if (itemdays == 0) { itemdays = itemdays + 1; } var itemdivlength = onedaylength * itemdays; //任务的开始时间和当前日历左端开始时间差 var leftdays; if (itemstartdate <= startdate) { leftdays = 0 } else { leftdays = daysBetween(itemstartdate, startdate); } //距离左边的距离 var itemdivleft = onedaylength * leftdays; //距离上边的距离 var itemdivtop = topnumber * 38; //创建一个div,并定位 var itemdiv = document.createElement("div"); if(itemdivlength+itemdivleft >containerlength ) { itemdivlength=containerlength -itemdivleft ; } $(itemdiv).css("width", itemdivlength); if (itemdivleft == 0) { itemdivleft = parseInt(itemdivleft) + 1; $(itemdiv).css("border-left", "1px solid white"); } $(itemdiv).css("left", itemdivleft); $(itemdiv).css("border-right", "1px solid white"); if (itemdivtop == 0) { itemdivtop = parseInt(itemdivtop) + 1; } $(itemdiv).css("top", itemdivtop); $(itemdiv).addClass("ms-tl-bar"); $(itemdiv).addClass(" js-callout-launchPoint"); $(itemdiv).addClass("taskitem"); $(itemdiv).attr("cutomernumber", itemdays); $(itemdiv).attr("leftnumber", itemdivleft); //创建一个span var itemtitlespan = document.createElement("span"); $(itemtitlespan).addClass("ms-tl-barTitle"); //将任务的标题写在上面 $(itemtitlespan).text(listitem.get_item('Title')); $(itemtitlespan).appendTo($(itemdiv)); //创建换行标签 var itembr = document.createElement("br"); $(itembr).appendTo($(itemdiv)); //创建span标签 var itemtimespan = document.createElement("span"); $(itemtimespan).addClass("ms-tl-barDate"); //添加样式 var itemtimestr = (itemstartdate.getMonth() + 1) + "/" + itemstartdate.getDate() + " - " + (itemenddate.getMonth() + 1) + "/" + itemenddate.getDate(); //将任务时间写在任务span上 $(itemtimespan).text(itemtimestr); $(itemdiv).attr("title",itemtimestr); $(itemtimespan).appendTo($(itemdiv)); //最后加到外层div上 $(itemdiv).appendTo($(liufirstlevelcontainer)); } } //给最外层的div设置高度 $(liufirstlevelcontainer).css("height", divheightnumber * 38); $(liufirstlevelcontainer).find("span.liutooltip").css("display", "none"); }
2.4 需要用到的一些辅助的方法
function Map() { this.keys = new Array(); this.data = new Array(); //添加键值对 this.set = function (key, value) { if (this.data[key] == null) {//如键不存在则身【键】数组添加键名 this.keys.push(key); } this.data[key] = value;//给键赋值 }; //获取键对应的值 this.get = function (key) { return this.data[key]; }; //去除键值,(去除键数据中的键名及对应的值) this.remove = function (key) { this.keys.remove(key); this.data[key] = null; }; //判断键值元素是否为空 this.isEmpty = function () { return this.keys.length == 0; }; //获取键值元素大小 this.size = function () { return this.keys.length; }; this.ContainsKey = function (key) { if (this.data[key] == null) {//如键不存在则身【键】数组添加键名 return false; } else { return true; } } } function DateAddDays(date, number) { return new Date(Date.parse(date) + number * 86400000); } function daysBetween(today, nowday) { var dt1 = new Date(); dt1.setFullYear(today.getFullYear()); dt1.setMonth(today.getMonth()); dt1.setDate(today.getDate()); var dt2 = new Date(); dt2.setFullYear(nowday.getFullYear()); dt2.setMonth(nowday.getMonth()); dt2.setDate(nowday.getDate()); var dif = dt1.getTime() - dt2.getTime(); var days = dif / (24 * 60 * 60 * 1000); return Math.abs(days); }
3,页面上的HTML容器
<div style="margin-bottom:20px;color:black; font-size:large">当前项目一级工作项</div> <div style="left: 0px; top: 0px; width: 100%; position: relative; -ms-content-zooming: none; -ms-touch-action: none;"> <div id="firstlevelcontainer" class="ms-tl-mainArea" style="left: 0px; top: 46px; width: 100%; min-width: 800px; height: 37px; background-color: rgb(252, 252, 252);"> <span class="tooltip" style="color: red;">正在生成日历....</span> <div class="ms-tl-timescale" style="left: 0px; top: -20px; width: 100%; height: 20px;"> <div id="firstleveldate" style="left: 0px; top: 0px; width: 10000px; height: 19px; color: rgb(119, 119, 119); overflow: hidden; margin-left: 2px; border-bottom-color: rgb(119, 119, 119); border-bottom-width: 1px; border-bottom-style: hidden; white-space: nowrap; position: absolute;"> </div> <div id="firstleveldateline" style="left: 0px; top: 9px; width: 10000px; height: 10px; color: rgb(119, 119, 119); overflow: hidden; margin-left: 0px; border-bottom-color: rgb(119, 119, 119); border-bottom-width: 1px; border-bottom-style: hidden; white-space: nowrap; position: absolute;"> </div> </div> </div> </div>
4,最后上传一下效果图