The setTimer function didn't work in the long run, because I couldn't get the PreItemSave action to continue after everything was done.
I tried to do a Deferred Object to respond back with a final TRUE value to the PreItemSave at the end of the updates, but I found that it would just continue on after the initial Task creation.
My final solution was to use a checkbox that I already had in the form to run the script to do the creations and updates and then use a .click() to save the form and have it continue. I made a made a little more wordy post on my blog.
Here is the final code snippet.
// Get Group Routing list based off of selected value
function startGroupRouting(groupRouting) {
var clientContext = new SP.ClientContext.get_current();
var approveList = clientContext.get_web().get_lists().getByTitle('Approvers');
var approveQuery = new SP.CamlQuery();
var ql = '<View>' +
'<Query>' +
'<Where><Eq>' +
'<FieldRef Name="Routing_x0020_Group" />' +
'<Value Type="Text">' + groupRouting + '</Value>' +
'</Eq></Where>' +
'<OrderBy>' +
'<FieldRef Name="Step" Ascending="false"></FieldRef>' +
'</OrderBy>' +
'</Query>' +
'</View>';
approveQuery.set_viewXml(ql);
this.approveSelectList = approveList.getItems(approveQuery);
clientContext.load(approveSelectList, 'Include(Approver,Approver_x0020_Type,Step)');
clientContext.executeQueryAsync(
Function.createDelegate(this, groupRouteSuccess),
Function.createDelegate(this, onGetFail)
);
}
// After Success, Create Each Task
function groupRouteSuccess() {
var memoDeliverDate = $('nobr:contains("Deliver By")').closest('tr').find('input[title^="Deliver By"]').val();
var approveGrpEnumerator = approveSelectList.getEnumerator();
// loop through list items
var i = 0;
var listCount = approveSelectList.get_count();
var lastMemoCnt = listCount - 1;
var lastMemo = false;
while(i < listCount) {
approveGrpEnumerator.moveNext();
if(i == lastMemoCnt) {
lastMemo = true;
}
var thisGrpItem = approveGrpEnumerator.get_current();
var approver = thisGrpItem.get_item('Approver');
var approverType = new String(thisGrpItem.get_item('Approver_x0020_Type'));
var step = new String(thisGrpItem.get_item('Step'));
var clientContext = new SP.ClientContext.get_current();
var oList = clientContext.get_web().get_lists().getByTitle('Memo Tasks');
var today = new Date();
var itemCreateInfo = new SP.ListItemCreationInformation();
var oListItem = oList.addItem(itemCreateInfo);
oListItem.set_item('Title', $.local.memoTitle + ' - ' + approverType);
oListItem.set_item('Task_x0020_Group', $.local.memoTitle);
oListItem.set_item('Step', step);
oListItem.set_item('AssignedTo', approver);
oListItem.set_item('Body', approverType);
oListItem.set_item('DueDate', memoDeliverDate);
oListItem.set_item('StartDate', today.format('M/dd/yyyy'));
oListItem.update();
clientContext.load(oListItem);
if(i == lastMemoCnt){
clientContext.executeQueryAsync(createFinalTaskSuccess, onGetFail);
} else {
clientContext.executeQueryAsync(createTaskSuccess(step), onGetFail);
}
i++;
}
}
// Success for creating each task, except the last
function createTaskSuccess(step) {
SP.UI.Notify.addNotification('New Task Created for Step ' + step);
}
// Success for creating each task, then start Task Update loop
function createFinalTaskSuccess() {
SP.UI.Notify.addNotification('Final New Task Created');
var clientContext = new SP.ClientContext.get_current();
console.info("Starting Update Memo retrieve");
var taskGrpList = clientContext.get_web().get_lists().getByTitle('Memo Tasks');
var taskGrpQuery = new SP.CamlQuery();
console.info("Query for Get Memos of taskGroup : " + $.local.memoTitle);
var ql = '<View>' +
'<Query>' +
'<Where><Eq>' +
'<FieldRef Name="Task_x0020_Group" />' +
'<Value Type="Text">' + $.local.memoTitle + '</Value>' +
'</Eq></Where>' +
'<OrderBy>' +
'<FieldRef Name="Step" Ascending="true"></FieldRef>' +
'</OrderBy>' +
'</Query>' +
'</View>';
taskGrpQuery.set_viewXml(ql);
taskSelectGrpList = taskGrpList.getItems(taskGrpQuery);
clientContext.load(taskSelectGrpList);
clientContext.executeQueryAsync(
Function.createDelegate(this,
function() {
var clientContext = new SP.ClientContext.get_current();
var updTaskGrpList = clientContext.get_web().get_lists().getByTitle('Memo Tasks');
console.info("Approval Group retrieve success");
var taskGrpEnumerator = taskSelectGrpList.getEnumerator();
var listCount = taskSelectGrpList.get_count();
var lastMemoCnt = listCount - 1;
console.info("Update memos retrieved: " + listCount + " lastMemo cnt = " + lastMemoCnt);
while(taskGrpEnumerator.moveNext()) {
var oListItem = taskGrpEnumerator.get_current();
$.local.memoArray.push(oListItem);
}
for(var x = 1; x < listCount; x++) {
console.info("task(" + x
+ ") ID = " + $.local.memoArray[x].get_item('ID')
+ " predID = " + $.local.memoArray[x-1].get_item('ID')
+ " isLastUpdate = " + $.local.isLastUpdate);
var taskItem = updTaskGrpList.getItemById($.local.memoArray[x].get_item('ID'));
taskItem.set_item('Predecessors', $.local.memoArray[x-1].get_item('ID'));
taskItem.update();
if(x == lastMemoCnt) {
clientContext.executeQueryAsync(updateFinalTaskSuccess($.local.memoArray[x].get_item('ID')), onGetFail);
} else {
clientContext.executeQueryAsync(updateTaskSuccess($.local.memoArray[x].get_item('ID')), onGetFail);
}
}
}
),
Function.createDelegate(this, onGetFail)
);
}
// Success for every Task update, except last one
function updateTaskSuccess(taskID) {
SP.UI.Notify.addNotification('Task Predecessor Added to Task ' + taskID);
}
// Success for final Task Update
function updateFinalTaskSuccess() {
SP.UI.Notify.addNotification('Task Predecessor Added to Final Task');
console.info("Final Update Task Success");
disableSaveBtn(false);
$('input[name$="SaveItem"]').click();
}
// all fail
function onGetFail(sender, args) {
var msgError = 'Request failed. ' + args.get_message() + '\n' + args.get_stackTrace();
// add error message
SP.UI.Notify.addNotification('Error : ' + args.get_message());
console.error('Error occured: ' + msgError);
}