本文介绍SharePoint 2013 中开发可以被标记为未读和已读的列表之代码实现,只介绍核心代码,完整代码请到codeplex 下载:http://readmarkablelist.codeplex.com/ 。
ReadMarkAction.js:
function EnableUnRead() {
// Get the client context first
var ctx = SP.ClientContext.get_current();
var items = SP.ListOperation.Selection.getSelectedItems(ctx);
if (items.length == 0) {
return false;
}
// Check whether all the selected items are read, otherwise disable the unread button
for (i = 0; i < items.length ; i++) {
var currentItem = items[i];
for (j = 0; j < listData.Row.length; j++) {
var currentRow = listData.Row[j];
if (currentRow.ID == currentItem.id) {
if (currentRow.Readed != "1") {
return false;
}
}
}
}
return true;
}
function EnableUnReadContextMenu() {
// To do: Add your logical for how to determine enable or disable the unread context menu for current item
// Seems the item context menu don't support EnabledScript, need further investigation here
return false;
}
function ClickUnReadRibbonButton() {
// To do: Add your logical for operating the items once the end use click UnReadRibbonButton
var selectedRows = GetSelectedDataRows();
var ctx = SP.ClientContext.get_current();
var readList = ctx.get_web().get_lists().getByTitle("ReadList");
for (i = 0; i < selectedRows.length; i++) {
var currentRow = selectedRows[i];
var deleteItem = readList.getItemById(currentRow.readItemId);
deleteItem.deleteObject();
currentRow.Readed = currentRow.readMarkId;
var readMarkPlaceHolder = document.getElementById(currentRow.Readed);
BoldItemRow(readMarkPlaceHolder);
}
ctx.executeQueryAsync(
Function.createDelegate(this, this.onDeleteSucceeded),
Function.createDelegate(this, this.onDeleteFailed)
);
// alert("ClickUnReadRibbonButton");
}
function ClickUnReadContextMenu() {
// Check whether the selected item is read, it not dispaly a message says that message is already unread status
var ctx = SP.ClientContext.get_current();
var items = SP.ListOperation.Selection.getSelectedItems(ctx);
var currentRow;
for (j = 0; j < listData.Row.length; j++) {
currentRow = listData.Row[j];
if (currentRow.ID == items[0].id) {
if (currentRow.Readed != "1") {
alert("This item already unread");
return;
}
break;
}
}
// To do: Add your logical for operating the items once the end use click UnReadContextMenu
// Delete the remarkId from read list currentRow.readItemId
var readList = ctx.get_web().get_lists().getByTitle("ReadList");
var deleteItem = readList.getItemById(currentRow.readItemId);
deleteItem.deleteObject();
ctx.executeQueryAsync(
Function.createDelegate(this, this.onDeleteSucceeded),
Function.createDelegate(this, this.onDeleteFailed)
);
// Update the readed property to readMarkId
currentRow.Readed = currentRow.readMarkId;
// Update the item row style to bold
var readMarkPlaceHolder = document.getElementById(currentRow.Readed);
BoldItemRow(readMarkPlaceHolder);
}
// Bold the item row
function BoldItemRow(readMarkPlaceHolder) {
readMarkPlaceHolder.innerText = "Unread";
var parentTR = getParentNode_TR(readMarkPlaceHolder.parentNode);
parentTR.style.fontWeight = 'bold';
}
// Handle the on delete successed event
function onDeleteSucceeded() {
}
// Handle the on delete failed event
function onDeleteFailed(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
// Get the selected data rows
function GetSelectedDataRows() {
var ctx = SP.ClientContext.get_current();
var items = SP.ListOperation.Selection.getSelectedItems(ctx);
var selectdRows = new Array(items.length);
for (i = 0; i < items.length ; i++) {
var currentItem = items[i];
for (j = 0; j < listData.Row.length; j++) {
var currentRow = listData.Row[j];
if (currentRow.ID == currentItem.id) {
selectdRows[i] = currentRow;
}
}
}
return selectdRows;
}
ReadMarkFieldType.js
(function () {
var ReadMarkContext = {};
// You can provide templates for:
// View, DisplayForm, EditForm and NewForm
ReadMarkContext.Templates = {};
ReadMarkContext.Templates.Fields = {
"ReadMarkField": {
"View": ReadMarkViewTemplate,
"DisplayForm": RenderDisplayFormForReadMark
}
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(
ReadMarkContext
);
})();
// The ReadMarkViewTemplate provides the rendering logic
// the custom field type when it is displayed in the view form.
function ReadMarkViewTemplate(ctx) {
var readMarkId = ctx.listUrlDir.replace(/\//g, "_") + "$" + ctx.CurrentItem.ID + "$" + ctx.CurrentUserId;
ctx.CurrentItem.Readed = readMarkId;
ctx.CurrentItem.readMarkId = readMarkId;
return "data loading";
}
var readMarkIdForDisplayForm;
function RenderDisplayFormForReadMark(ctx)
{
// var readMarkId = ctx.listUrlDir.replace(/\//g, "_") + "$" + ctx.CurrentItem.ID + "$" + ctx.CurrentUserId;
// readMarkIdForDisplayForm = readMarkId + "DisplayFormForReadMark";
// Insert one item into ReadList
ExecuteOrDelayUntilScriptLoaded(InsertReadMarkItem, "sp.js");
return "data loading...";
}
// user for storing current user object
var currentUser;
function InsertReadMarkItem()
{
var ctx = SP.ClientContext.get_current();
var currentweb = ctx.get_web();
ctx.load(currentweb);
currentUser = currentweb.get_currentUser();
currentUser.retrieve();
ctx.load(currentweb);
ctx.executeQueryAsync(onLoadCurrentUserSuccessed, onLoadCurrentUserFailed);
}
// Once load the current user successfully, then generate the read mark by list name + itemId + currentUserId
function onLoadCurrentUserSuccessed() {
var currentUserId = currentUser.get_id();
var itemId = getUrlParam("ID");
var path = window.location.pathname;
var index = path.lastIndexOf('/', path.length);
var listPath = path.substring(0, index);
var readMarkId = listPath.replace(/\//g, "_") + "$" + itemId + "$" + currentUserId;
UpdateReadMarkItem(readMarkId);
}
// Insert the read mark into ReadList
function UpdateReadMarkItem(readMarkId) {
var clientContext = new SP.ClientContext();
var readList = clientContext.get_web().get_lists().getByTitle("ReadList");
var itemCreateInfo = new SP.ListItemCreationInformation();
var readItem = readList.addItem(itemCreateInfo);
readItem.set_item("Title", readMarkId);
readItem.update();
clientContext.load(readItem);
clientContext.executeQueryAsync(
Function.createDelegate(this, ReadMarkInsertSuccessed),
Function.createDelegate(this, ReadMarkInsertFailed)
);
}
function onLoadCurrentUserFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
function ReadMarkInsertSuccessed()
{
var readMarkIdPlaceHolderForDisplayForm = document.getElementById("readMarkIdPlaceHolderForDisplayForm");
readMarkIdPlaceHolderForDisplayForm.innerText = "read";
}
function ReadMarkInsertFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
function getUrlParam(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]); return null;
}
ReadMarkListView.js:
(function () {
// Initialize the variable that store the objects.
var overrideCtx = {};
overrideCtx.Templates = {};
overrideCtx.BaseViewID = 2;
overrideCtx.ListTemplateType = 10057;
// Assign a function to handle the
// PreRender and PostRender events
overrideCtx.OnPreRender = preRenderHandler;
overrideCtx.OnPostRender = postRenderHandler;
// Register the template overrides.
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();
var listData;
// This function builds the output for the item template,
// it uses the context object to access announcement data.
function customItem(ctx) {
// Build a listitem entry for every announcement in the list.
var ret = "" + ctx.CurrentItem.Title + " ";
return ret;
}
// The preRenderHandler handles the
// OnPreRender event
function preRenderHandler(ctx) {
// Override the default title with user input
// ctx.ListTitle = prompt("Type a title", ctx.ListTitle);
}
// The postRenderHandler handles the
// OnPostRender event
function postRenderHandler(ctx) {
listData = ctx.ListData;
ExecuteOrDelayUntilScriptLoaded(RefreshReadMark, "sp.js");
}
// Used for storing list item collection which return by caml query
var collListItem;
var readMarkPlaceHolders;
// Refresh read mark for the list view
function RefreshReadMark()
{
readMarkPlaceHolders = $(".ReadMarkFiledPlaceHloderClass");
var clientContext = new SP.ClientContext();
var targetList = clientContext.get_web().get_lists().getByTitle("ReadList");
var query = new SP.CamlQuery();
query.set_viewXml(GenerateCaml(readMarkPlaceHolders));
collListItem = targetList.getItems(query);
clientContext.load(collListItem, "Include(Title,ID)");
clientContext.executeQueryAsync(
Function.createDelegate(this, onCamlQuerySucceeded),
Function.createDelegate(this, onCamlQueryFailed)
);
}
// Generate the caml
function GenerateCaml(readMarkPlaceHolders) {
var values ='';
readMarkPlaceHolders.each(function () {
values += " " + $(this)[0].id + " "
});
return '' +
'' + values +
' ' +
'200 ';
}
function onCamlQuerySucceeded(sender, args)
{
// Set all rows fontWeight to bold implies these rows are unread
readMarkPlaceHolders.each(function () {
$(this)[0].innerText = "Unread";
var parentTR = getParentNode_TR($(this)[0].parentNode);
parentTR.style.fontWeight = 'bold';
});
var listItemEnumerator = collListItem.getEnumerator();
// Set the rows(which is read) fontWeight to normal implies these rows are read
while (listItemEnumerator.moveNext()) {
var readItem = listItemEnumerator.get_current();
var currentReadMarkPlaceHolder = document.getElementById(readItem.get_item('Title'));
currentReadMarkPlaceHolder.innerText = "Read";
var currentParentTR = getParentNode_TR(currentReadMarkPlaceHolder.parentNode);
currentParentTR.style.fontWeight = 'normal';
for (index = 0; index < listData.Row.length; index++) {
var currentRow = listData.Row[index];
if (currentRow.Readed == readItem.get_item('Title')) {
// Set the readed to 1 implies that row has been read by the current user
// and the unread button in the rbbion area will be enable for this item(row)
// unread context menu will be enable for this item(row)
currentRow.Readed = '1';
currentRow.readItemId = readItem.get_item('ID');
}
}
}
}
// Handle the caml query failed event
function onCamlQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
// Get the elelemt's TR parent
function getParentNode_TR(parent) {
while (parent && parent.tagName != 'TR') {
parent = parent.parentNode;
}
return parent;
}