Skip to content

Instantly share code, notes, and snippets.

@balony88
Forked from iOnline247/$sp.wf.js
Last active August 28, 2018 12:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save balony88/9fad769b9daaad8829d6ffa63828e18f to your computer and use it in GitHub Desktop.
Save balony88/9fad769b9daaad8829d6ffa63828e18f to your computer and use it in GitHub Desktop.
Use this to fire list workflows by name or subscriptionId.
/*!
* Created by Matthew Bramer
* Released under the MIT license
* Date: 2015-04-18
* Props to: http://plumsail.com/blog/2015/02/start-sharepoint-2013-workflows-selected-items/
* Tested using SharePoint Online.
* On-Prem still needs testing.
*
* https://gist.github.com/iOnline247/1b3c26f7175296a44274
*/
window.$sp = window.$sp || {};
window.$sp.wf = (function ($, undefined) {
"use strict";
var ctx,
web,
wfManager,
JS_SUFFIX = ".js",
SP_WORKFLOW_SERVICES = "SP.WorkflowServices",
SP_WORKFLOW_SERVICES_SCRIPT_NAME = SP_WORKFLOW_SERVICES + JS_SUFFIX,
risGuid = /[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i,
oDataHeader = "application/json;odata=verbose",
initializeVariables = function () {
ctx = SP.ClientContext.get_current();
web = ctx.get_web();
wfManager = SP.WorkflowServices.WorkflowServicesManager.newObject(ctx, web);
},
registerWFscripts = function () {
SP.SOD.registerSod(
SP_WORKFLOW_SERVICES_SCRIPT_NAME,
SP.Utilities.Utility.getLayoutsPageUrl(SP_WORKFLOW_SERVICES + JS_SUFFIX)
);
SP.SOD.executeFunc(
SP_WORKFLOW_SERVICES_SCRIPT_NAME,
SP_WORKFLOW_SERVICES + ".WorkflowServicesManager",
initializeVariables
);
},
init = function () {
SP.SOD.executeFunc(
"sp" + JS_SUFFIX,
"SP.ClientContext",
registerWFscripts
);
},
set_errorHandler = function (func) {
errorHandler = func;
},
errorHandler = function (sender, args) {
var message = this,
spError = args && args.get_message,
restAPIError = sender && sender.responseText
;
if (this.id) {
message += " on item with ID: " + this.id;
}
SP.UI.Notify.addNotification(message, false);
console.log(message);
if (spError) {
console.log("Error:", args.get_message(), "\nStackTrace:", args.get_stackTrace());
}
if (restAPIError) {
console.log(restAPIError);
}
},
set_successHandler = function (func) {
successHandler = func;
},
successHandler = function (sender, args) {
var wfName = this.name || this.subscription && this.subscription.get_name(),
message = "Workflow " + wfName + " has started."
;
if (this.id) {
message = message.replace(".", "");
message += " on this item. ID: " + this.id;
}
SP.UI.Notify.addNotification(message, false);
},
fireWfByName = function (sender, args) {
var subscription = this.subscription,
id = this.id,
initiationParams = this.initiationParams || {},
workflows = subscription.getEnumerator(),
workflow,
foundWrkFlow = false
;
while (workflows.moveNext()) {
workflow = workflows.get_current();
if (workflow.get_name() === this.name) {
startWorkflow({
subscriptionId: workflow.get_id(),
id: id,
initiationParams: initiationParams
});
foundWrkFlow = true;
break;
}
}
if (!foundWrkFlow) {
errorHandler.call("Could not find workflow named: " + this.name);
}
},
fireWfBySubscription = function (sender, args) {
var subscription = this.subscription,
id = this.id,
initiationParams = this.initiationParams || {},
wfInstance = wfManager.getWorkflowInstanceService()
;
// https://msdn.microsoft.com/en-us/library/office/microsoft.sharepoint.client.workflowservices.workflowinstanceservice_methods.aspx
if (id) {
wfInstance.startWorkflowOnListItem(subscription, id, initiationParams);
} else {
wfInstance.startWorkflow(subscription, initiationParams);
}
ctx.executeQueryAsync(
successHandler.bind(this),
errorHandler.bind("Could not fire workflow. SubscriptionId: " + this.subscriptionId)
);
},
startWorkflow = function (opt) {
var subscriptionService = wfManager.getWorkflowSubscriptionService(),
success,
error,
deffered = $.Deferred()
;
// different methods to fire workflows with 2013.
// https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.workflowservices.workflowsubscriptionservice_members.aspx
if (opt.subscriptionId) {
opt.subscription = subscriptionService.getSubscription(opt.subscriptionId);
ctx.load(opt.subscription);
success = fireWfBySubscription.bind(opt);
error = errorHandler.bind("Failed to load subscription: " + opt.subscriptionId);
} else {
opt.subscription = subscriptionService.enumerateSubscriptions();
ctx.load(opt.subscription);
success = fireWfByName.bind(opt);
error = errorHandler.bind("Failed to load workflow subscriptions.");
}
ctx.executeQueryAsync(
function () {
success();
deffered.resolve();
},
function () {
error();
deffered.reject();
}
);
return deffered;
},
removeDemCurlies = function (v) {
return v.replace(/{|}/g, "");
},
getListItemDeets = function (listUrl) {
return $.ajax({
type: "GET",
url: listUrl,
dataType: "json",
headers: {
"Accept": oDataHeader,
"Content-Type": oDataHeader
}
});
},
fire2010Workflow = function (data, opt) {
var promise = $.Deferred();
var success,
listGuid = data.d.__metadata.uri.match(risGuid)[0],
itemId = data.d.GUID
;
opt.result = opt.subscriptionService.startWorkflow(opt.name, null, listGuid, itemId, opt.initiationParams);
success = successHandler.bind(opt);
ctx.executeQueryAsync(
function () {
success();
promise.resolve();
},
function () {
opt.error();
promise.reject();
}
);
return promise;
},
start2010Workflow = function (opt) {
var subscriptionService = wfManager.getWorkflowInteropService(),
wfName = opt.name,
id = opt.id,
itemGuid,
initiationParams = opt.initiationParams,
queryPrefix = "/_api/web/lists",
querySuffix = "/items(" + id + ")?$select=GUID",
// May need to do this later when ctx is dynamic.
// listUrl = web.get_url(),
listUrl = _spPageContextInfo.webAbsoluteUrl + queryPrefix,
listGuid,
errorMessage = "Failed to fire 2010 {0} Workflow.",
success,
error,
deffered = $.Deferred();
;
// Fire 2010 workflows!
// https://msdn.microsoft.com/en-us/library/office/microsoft.sharepoint.client.workflowservices.interopservice.startworkflow.aspx
// Not sure if opt.result is going to be helpful, but leaving it here for the meantime.
// If it is useful, then I'll bind it to the both handlers.
// If not, I'll drop it altogether.
if (id) {
listGuid = opt.list.match(risGuid);
if (listGuid) {
listGuid = removeDemCurlies(listGuid[0]);
listUrl += "(guid'" + listGuid + "')";
} else {
listUrl += "/GetByTitle('" + opt.list + "')";
}
listUrl += querySuffix;
// converts numbers to strings.
id = id + "";
itemGuid = id.match(risGuid);
if (listGuid && itemGuid) {
// List GUID and item GUID were provided, no need for API call.
opt.result = subscriptionService.startWorkflow(wfName, null, listGuid, itemGuid[0], initiationParams);
success = successHandler.bind(opt);
error = errorHandler.bind(errorMessage.replace("{0}", "Site"));
} else {
// Need to resolve List GUID and get the item GUID.
opt.subscriptionService = subscriptionService;
opt.error = errorHandler.bind(errorMessage.replace("{0}", "List"));
getListItemDeets.bind(opt)(listUrl)
//.then(fire2010Workflow.bind(opt), opt.error);
.then(function (data) {
var promise = fire2010Workflow(data, opt);
$.when(promise).then(function () { deffered.resolve() }, function () { deffered.reject() });
});
return deffered;
}
} else {
// Site WF
opt.result = subscriptionService.startWorkflow(wfName, null, null, null, initiationParams);
success = successHandler.bind(opt);
error = errorHandler.bind(errorMessage.replace("{0}", "Site"));
}
ctx.executeQueryAsync(
function () {
success();
deffered.resolve();
},
function () {
error();
deffered.reject();
}
);
return deffered;
}
;
//init();
// TODO:
// On-Prem testing.
// Look at custom events.
// https://msdn.microsoft.com/en-us/library/office/dn481315.aspx
// Add promises.
return {
set_errorHandler: set_errorHandler,
set_successHandler: set_successHandler,
startWorkflow: startWorkflow,
start2010Workflow: start2010Workflow,
init: init
};
}(window.jQuery));
// Init after everithing else is loaded
_spBodyOnLoadFunctionNames.push("$sp.wf.init");
/*
* Usage
* via subscriptionId or Workflow Name. Preferably the latter.
*/
// List bound WF fired by Workflow Name, Muy bien!
$sp.wf.startWorkflow({
name: "Send Email",
id: 1,
initiationParams: {
EasyText: "What's up?",
// `Here I Am` is the real initation parameter name. Note the spaces.
HereIam: "<p><b>heyo!</b></p><p>otra ves</p>"
}
});
// Site workflows! YaY!
$sp.wf.startWorkflow({
name: "Site WF",
initiationParams: {
WooP: "<b>That's what's up!</b>"
}
});
// 2010 Site WF!
$sp.wf.start2010Workflow({
name: "Site WF - 2010",
initiationParams: {
// `Something with Spaces` is the real initation parameter name. Note the spaces and casing.
SomethingwithSpaces: "<b>That's what's up!</b>"
}
});
// 2010 List Bound WF.
$sp.wf.start2010Workflow({
name: "SendEmail2010",
list: "Test",
id: 1,
initiationParams: {
"ThingsChangePeopleChange": "<b>Used list display name and item id.</b>"
}
});
$sp.wf.start2010Workflow({
name: "SendEmail2010",
list: "{FD21AC5B-15D9-443A-B7A5-1FB6A2AF667D}",
id: 1,
initiationParams: {
"ThingsChangePeopleChange": "<b>Used list GUID and item id.</b>"
}
});
$sp.wf.start2010Workflow({
name: "SendEmail2010",
list: "{FD21AC5B-15D9-443A-B7A5-1FB6A2AF667D}",
id: "{211ffdfc-69c5-4206-917d-befe62a6ffb4}",
initiationParams: {
"ThingsChangePeopleChange": "<b>Used list GUID and item GUID. Prevents a call to SP's REST API.</b>"
}
});
// The ugly duckling... Don't use this, please. :)
// Via Subscription ID, YUCK!
$sp.wf.startWorkflow({
subscriptionId: "{CE3890BC-3361-4F1C-9036-40A07E0EC449}",
id: 1
});
// 2018.06.19 - Balint Rozsa
// Fixed bug with initiation,
// Added promises to return
// Now you can use them like ajax requests
$sp.wf.startWorkflow({ name: "My workflow"})
.done (function () {
alert("My workflow succesfully started;")
})
.fail (function () {
alert("Something went wrong")}
)
// Or you can use them to start more workflows at once, by paralell requests
var promises = [];
var selectedItems = SP.ListOperation.Selection.getSelectedItems();
for (var i in selectedItems) {
var item = selectedItems[i];
var promise = $sp.wf.startWorkflow({ name: "My workflow", initiationParams: {}});
promises.push(promise);
}
$.when.apply($, promises).then(
function () {
alert("All workflows have started successfully");
},
function (error) {
alert("One of the workflows doesen't start normaly");
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment