SharePoint 2013/2010: Generate custom graphical workflows from SharePoint list data via JSOM & JSPlumb ApI
Context: Customer
wants to visualize his data in a graphical workflow as he is working in quick Edit mode with a SharePoint
List.
Solution: I used
JSOM and JS Plumb API to accomplish this task. I found JSPlumb (JavaScript
graphic API) as an excellent API to accomplish my task. It is very well
documented and one can find very nice and interactive examples at their site. So the scenario would be whenever the customer leaves the SharePoint list row, I am
refreshing the workflow and the customer immediately sees the changes that he has made in the list.
I created a page and added the List alongside with the content editor webpart and then referenced the html page. The following is the snapshot how it looks like;
I created a page and added the List alongside with the content editor webpart and then referenced the html page. The following is the snapshot how it looks like;
The following is another snapshot of how the SharePoint list is automated to work with the graphical workflow based content editor webpart;
The following code I wrote to achieve this task;
First of all there is a html file which consist of some divs and referencing js + css files from Site Assets;
The Sharepoint.js consist of following line of codes. An important idea here to understand is that workflow is generated everytime from the scratch by calling retreiveListItems function once the user click a row i.e. tr. The other line of codes are related to the JSOM and describing how to retrieve the SharePoint list data using JSOM;
Note: It is not the actual solution but the foundation from where I started building the bigger solution. Please do let me know if you have any comments and if you need help... I hope it would help someone.
Enjoy & Cheers…JThe Sharepoint.js consist of following line of codes. An important idea here to understand is that workflow is generated everytime from the scratch by calling retreiveListItems function once the user click a row i.e. tr. The other line of codes are related to the JSOM and describing how to retrieve the SharePoint list data using JSOM;
$(window).load(function () {
$(document).ready(function () {
jsPlumb.ready(function () {
makeSetup();
retrieveListItems();
$('tr').click(function () {
retrieveListItems();
});
});
});
});
function retrieveListItems() {
var clientContext = new SP.ClientContext.get_current();
var oList = clientContext.get_web().get_lists().getByTitle('Course schedule');
var camlQuery = new SP.CamlQuery();
var strCamlQuery = '';
strCamlQuery += '' +
'' +
'' +
'' +
'' +
'' +
' ';
camlQuery.set_viewXml(strCamlQuery);
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();
makeSetup();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
//oListItem.get_item('Task_x0020_Type').get_lookupValue()
var arrayListItem = [oListItem.get_id(), oListItem.get_item('Title'), oListItem.get_item('Task_x0020_Type'), oListItem.get_item('Publish_x0020_Date'), oListItem.get_item('Due_x0020_Date')];
collectInformation(arrayListItem);
}
drawConnectors();
}
function onQueryFailed(sender, args) {
alert("Failed");
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
} + args.get_stackTrace());
The purpose of Dynamic.js is generate the windows(divs) using the JSPlumb library in a sequential workflow. The following are the lines of codes that I wrote to generate sequential workflow;
var propertiesArray = []; //All Divs(Window) Array
var connectorArray = []; //JSPlumb Connector Array
var windowCounter = 0;
var currentWindowType = 'Default';
var top = 10;
var left = 30;
function makeSetup() {
jsPlumb.deleteEveryEndpoint(); // Delete all Endpoints
removeAllWindowsOnCanvas(); // Delete all Windows
$("
Start").insertAfter("#assessmentJsPlumb").parent();
propertiesArray = [];
propertiesArray.push({ 'windowID': 'windowStart', 'title': 'Start', 'type': 'Default', 'publishDate': "01/01/2013", 'dueDate': "01/02/2013" });
$(document).tooltip();
top = 10;
left = 30;
}
function removeAllWindowsOnCanvas() {
for (var i = 0; i < propertiesArray.length; i++) {
$("#" + propertiesArray[i]['windowID']).remove();
}
}
//Collect all the assessment items information into the propertiesArray Array Object.
function collectInformation(arrayListItem) {
var windowID = "window-" + arrayListItem[0];
//Format Dates
arrayListItem[3] = arrayListItem[3].format("mm/dd/yyyy"); //Format Publish Date
arrayListItem[4] = arrayListItem[4].format("mm/dd/yyyy"); //Format Due Date
propertiesArray.push({ 'windowID': windowID, 'title': arrayListItem[1], 'type': arrayListItem[2], 'publishDate': arrayListItem[3], 'dueDate': arrayListItem[4] }); //, , 'dueDate': $("#txtDueDate").val(), , 'Marks': $("#txtMarks").val()
}
//Calculate the positions of the window and add it.
function addWindowsToCanvas() {
for (var i = 1; i < propertiesArray.length; i++) {
if (i + 1 >= propertiesArray.length) {
left = 30;
createWindows(i);
top = top + 10;
}
else {
if (propertiesArray[i]['dueDate'] == propertiesArray[i + 1]['dueDate']) {
left = left - 10;
createWindows(i);
for (var j = i + 1 ; j < propertiesArray.length; j++) {
if (propertiesArray[i]['dueDate'] == propertiesArray[j]['dueDate']) {
left = left + 20;
top = top - 5;
i = j;
createWindows(j);
}
else {
i = j - 1;
left = 30;
top = top + 10;
break;
}
}
}
else {
createWindows(i);
top = top + 10;
}
}
}
}
//Add the windows on the canvas
function createWindows(index) {
var tooptip = "Publish date: " + propertiesArray[index]['publishDate'] + " Due date: " + propertiesArray[index]['dueDate'];
var window = "
";
var previndex = index - 1;
var prvWindowID = propertiesArray[previndex]['windowID'];
//Create a new div (window)
$(window).insertAfter("#" + prvWindowID);
// Make the new div draggable
jsPlumb.draggable($(".window"));
}
/* JsPlumb Methods */
//Draw the JsPlumb connectors between the windows.
function drawConnectors() {
jsPlumb.ready(function () {
//jsPlumb.detachEveryConnection();
propertiesArray.sort(function (a, b) {
var a1 = a.dueDate, b1 = b.dueDate;
if (a1 == b1) return 0;
return a1 > b1 ? 1 : -1;
});
addWindowsToCanvas();
//jsPlumb.removeEveryEndpoint();
for (var i = 0; i < propertiesArray.length; i++) {
for (var j = i + 1; j < propertiesArray.length; j++) {
if (propertiesArray[i]['dueDate'] != propertiesArray[j]['dueDate']) {
connectorArray.push( jsPlumb.connect({ source: propertiesArray[i]['windowID'], target: propertiesArray[j]['windowID'], anchor: "Continuous", connector: ["StateMachine", { curviness: 1 }], maxConnections: 1 }) );
for (var k = j + 1; k < propertiesArray.length; k++) {
if (propertiesArray[j]['dueDate'] == propertiesArray[k]['dueDate']) {
connectorArray.push( jsPlumb.connect({ source: propertiesArray[i]['windowID'], target: propertiesArray[k]['windowID'], anchor: "Continuous", connector: ["StateMachine", { curviness: 1 }], maxConnections: 1 }) );
}
else {
break;
}
}
break;
}
}
}
});
}
jsPlumb.ready(function () {
// helper method to generate a color from a cycle of colors.
var curColourIndex = 1, maxColourIndex = 24, nextColour = function () {
var R, G, B;
R = parseInt(128 + Math.sin((curColourIndex * 3 + 0) * 1.3) * 128);
G = parseInt(128 + Math.sin((curColourIndex * 3 + 1) * 1.3) * 128);
B = parseInt(128 + Math.sin((curColourIndex * 3 + 2) * 1.3) * 128);
curColourIndex = curColourIndex + 1;
if (curColourIndex > maxColourIndex) curColourIndex = 1;
return "rgb(" + R + "," + G + "," + B + ")";
};
// setup some defaults for jsPlumb.
jsPlumb.importDefaults({
Endpoint: ["Dot", { radius: 2 }],
HoverPaintStyle: { strokeStyle: "#42a62c", lineWidth: 2 },
ConnectionOverlays: [
["Arrow", {
location: 1,
id: "arrow",
length: 14,
foldback: 0.8
}]
]
});
jsPlumb.bind("connection", function (info) {
info.connection.setPaintStyle({ strokeStyle: "blue", lineWidth: 3 });
});
});


No comments:
Post a Comment