function ($scope, $http, nowServer, $timeout, spUtil, spScUtil, spModal, i18n, $window, $location, spAriaUtil, nowAttachmentHandler, $log, $sce, $q, spAtf, spSCNavStateManager, cabrillo) {
/**
* This is a copy of the SC Order Guide widget created to preserve modifications with
* the updates from upgrading the instance.
*
* This header is used to parse this with YUIDocs for documentation creation and can be
* parsed with a YUIDocs documentation parser.
*
* See the YUIDocs site for syntax or additional details;
* https://yui.github.io/yuidoc/
*
* Note that only the additions performed are documented in this fashion. ServiceNow code
* that was not modified or used was left as is.
*
* The modifications to this widget are summarized below for future considerations:
* + Displaying the "For" and "At" in the top right corner to indicate the employee being affected and the location at which this is being considered
*
* Future modifications should be noted above for consideration after upgrades.
*
* @author Alexander Anderson
* @class CWTSCOrderGuide
* @extends SPWidget
* @version 2.1
*/
var c = this;
$scope.guide_step = 0;
$scope.m = $scope.data.msgs;
$scope.evaluatingIncludes = false;
$scope.data.isMEE = $scope.options.native_mobile == 'true';
$scope.isItemOpened = false;
/**
* ServiceNow variable used for mapping sys_id values to the underlying glideform.
*
* This is updated on load, so for clarity and asynchronous timing, the values from
* here should be loaded in the function at time of need rather than attempting to
* pre-load any values.
* @property includedGformInstances
* @type Object
* @private
*/
// Variable Declaration correction (missing var) and public mapping in scope
var includedGformInstances = {};
/**
* Mapped along side includedGformInstances but is persisted to preserve values for
* reference. Currently only saves the GlideForm for the data.sys_id reference.
*
* @property _glideForms
* @type Object
*/
$scope._glideForms = {};
/**
* The GlideForm for the Order Guide itself. Set after load.
* @property primaryGlideForm
* @type Object
*/
$scope.primaryGlideForm = null;
$rootScope.$on('spModel.gForm.rendered', function () {
if ($scope.guide_step === 0) {
addCabrilloBottomButtons({
title: [$scope.data.msgs.nextMsg],
fn: [$scope.goNext]
});
}
$timeout(function () {
spAtf.init().then(function (atf) {
$scope._atf = atf;
atf.expose('catalog_util', catalogUtil);
});
}, 10);
});
if ($scope.options.isServiceWorkspace && $window.frameElement) {
var workspaceParams = {};
workspaceParams.sysparm_parent_table = $window.frameElement.getAttribute('parent-table');
workspaceParams.sysparm_parent_sys_id = $window.frameElement.getAttribute('parent-sys-id');
$scope.data.workspaceParams = workspaceParams;
}
if ($scope.data.sc_cat_item) {
$scope.data.sc_cat_item.description = $sce.trustAsHtml($scope.data.sc_cat_item.description);
if ($scope.data.sc_cat_item.request_method == "request")
$scope.submitButtonMsg = $scope.m.requestMsg;
else if ($scope.data.sc_cat_item.request_method == "submit")
$scope.submitButtonMsg = $scope.m.submitMsg;
else
$scope.submitButtonMsg = $scope.m.orderNowMsg;
// Breadcrumbs
if (!$scope.data.categories)
$scope.data.categories = [];
$scope.data.categories.forEach(function (category, index, categories) {
categories[index].url = category.url + '&catalog_id=' + $scope.data.catalog_id;
});
if ($scope.data.categories.length > 0) {
$scope.data.categories.unshift({
label: $scope.data.sc_catalog || $scope.page.title,
url: '?id=' + $scope.data.sc_category_page
});
$scope.data.categories.push({
label: $scope.data.sc_cat_item.name,
url: '#'
});
if ($scope.data.all_catalog_msg) {
$scope.data.categories.unshift({
label: $scope.data.all_catalog_msg,
url: '?id=' + $scope.data.sc_category_page + "&catalog_id=-1"
});
}
} else {
$scope.data.categories.push({
label: $scope.data.sc_cat_item.name,
url: '#'
});
}
$timeout(function () {
$scope.$emit('sp.update.breadcrumbs', $scope.data.categories);
});
spUtil.setSearchPage('sc');
} else {
var notFoundBC = [{
label: $scope.page.title,
url: '?id=' + $scope.data.sc_catalog_page
}
];
$timeout(function () {
$scope.$emit('sp.update.breadcrumbs', notFoundBC);
});
spUtil.setSearchPage('sc');
}
function isValidItemGform(g_form) {
if (g_form.getSysId() === $scope.data.sc_cat_item.sys_id)
return true;
if ($scope.includedItems)
for (var i in $scope.includedItems)
if ($scope.includedItems[i].sys_id === g_form.getSysId())
return true;
return false;
}
$scope.$on('spModel.gForm.initialized', function (e, gFormInstance) {
if (!isValidItemGform(gFormInstance))
return;
includedGformInstances[gFormInstance.getSysId()] = gFormInstance;
if($scope.data.sys_id == gFormInstance.getSysId()) {
$scope._glideForms[$scope.data.sys_id] = gFormInstance;
$scope.primaryGlideForm = gFormInstance;
}
spSCNavStateManager.register(gFormInstance);
gFormInstance.$private.events.on('submitted', function (event) {
gFormInstance.$private.processed = true;
if (gFormInstance.getSysId() == $scope.data.sc_cat_item.sys_id) {
$scope.$broadcast('$sp.service_catalog.form_submitted', {
action_name: 'submit'
});
$scope.guide_step = 1;
evalIncludes();
spSCNavStateManager.unregisterForms(Object.keys(includedGformInstances));
$scope.itemShown = 0;
} else
processChooseOptions();
});
if ($scope.options.native_mobile == 'true') {
cabrillo.viewLayout.showSpinner();
cabrillo.viewLayout.setTitle($scope.data.sc_cat_item.name);
}
$timeout(function () {
$rootScope.$emit('spModel.gForm.rendered');
if ($scope.options.native_mobile == 'true') {
cabrillo.viewLayout.hideSpinner();
}
}, 175);
});
$scope.$on('spModel.gForm.destroyed', function (e, sys_id) {
delete includedGformInstances[sys_id];
});
var validationComplete = $rootScope.$on('$sp.service_catalog.form_validation_complete', function () {
$scope.validating = false;
});
/* ************************************************************************************************ */
/* ******************************* Guide Navigation Start ******************************* */
/* ****#####################################################################################******* */
$scope.goPrev = function () {
if ($scope.submitted)
return;
clearCabrilloBottomButtons();
$scope.includedItems.forEach(function (item) {
item.isOpen = false;
})
$scope.guide_step--;
if ($scope.guide_step == 0)
spSCNavStateManager.unregisterForms(Object.keys(includedGformInstances));
if ($scope.guide_step === 1) {
addCabrilloBottomButtons({
title: [$scope.data.msgs.prevMsg, $scope.data.msgs.nextMsg],
fn: [$scope.goPrev, $scope.goNext]
});
}
}
$scope.goNext = function (timeout) {
var gForm;
if ($scope.guide_step == 0) {
$scope.$evalAsync(function () {
gForm = includedGformInstances[$scope.data.sys_id];
if (!spScUtil.isRegexDone($scope.data.sc_cat_item._fields))
$scope.validating = true;
else if (gForm && !gForm.submit()) {
timeout = timeout || 2000;
if (cabrillo.isNative())
openItemWithInvalidFields();
$timeout(function () {
$scope.$broadcast('$sp.service_catalog.form_submit_failed', {
action_name: 'submit'
});
}, timeout);
}
});
} else if ($scope.guide_step == 1) {
$scope.itemsIncluded = $scope.includedItems.length;
$scope.$evalAsync(function () {
for (var i = 0; i < $scope.includedItems.length; i++) {
if ($scope.includedItems[i].included) {
var g_form = includedGformInstances[$scope.includedItems[i].sys_id];
g_form.$private.processed = false;
if (!spScUtil.isRegexDone($scope.includedItems[i]._fields))
$scope.validating = true;
else if (g_form && !g_form.submit()) {
timeout = timeout || 500;
$timeout(function () {
$scope.$broadcast('$sp.service_catalog.form_submit_failed', {
action_name: 'submit'
});
openItemWithInvalidFields();
}, timeout);
}
} else
$scope.itemsIncluded--;
}
});
}
}
$scope.toggleItemState = function (item) {
if (item.included) {
$scope.totalIncluded--;
angular.element('#item_details_' + item.sys_id).find('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]').attr('tabindex', -1);
} else {
$scope.totalIncluded++;
angular.element('#item_details_' + item.sys_id).find('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]').removeAttr('tabindex');
}
}
function processChooseOptions() {
var canSubmit = true;
for (var i = 0; i < $scope.includedItems.length; i++) {
if ($scope.includedItems[i].included) {
var gForm = includedGformInstances[$scope.includedItems[i].sys_id];
if (gForm && !gForm.$private.processed) {
canSubmit = false;
break;
}
}
}
if (canSubmit) {
evalGuidePrice();
spSCNavStateManager.unregisterForms(Object.keys(includedGformInstances));
$scope.$broadcast('$sp.service_catalog.form_submitted', {
action_name: 'submit'
});
$scope.guide_step = 2;
$scope.showAddToCart = $scope.options.show_add_cart_button == 'true' && !$scope.data.sc_cat_item.no_cart;
addCabrilloBottomButtons({
title: [i18n.getMessage('Add to Cart'), $scope.submitButtonMsg],
fn: [$scope.triggerAddToCart, $scope.triggerSubmit]
});
}
}
var openItemWithInvalidFields = (function () {
var formsValidated = 0;
return function () {
formsValidated++;
if (formsValidated == $scope.itemsIncluded) {
var someFormIsInvalid = false;
for (var i = 0; i < $scope.includedItems.length; i++) {
if ($scope.includedItems[i].included) {
var gForm = includedGformInstances[$scope.includedItems[i].sys_id];
if (!gForm)
return;
var fields = gForm.getFieldNames();
for (var j = 0; j < fields.length; j++) {
var field = gForm.getField(fields[j]);
if (field.isInvalid) {
if (cabrillo.isNative()) {
$scope.includedItems[i].isOpen = true;
$scope.showCancel($scope.includedItems[i].sys_id);
} else
$scope.includedItems[i].isOpen = true;
someFormIsInvalid = true;
break;
}
}
if (cabrillo.isNative() && someFormIsInvalid)
break;
}
}
formsValidated = 0;
if (!cabrillo.isNative())
focusInvalidField();
}
}
})();
function focusInvalidField() {
$timeout(function () {
for (var i = 0; i < $scope.includedItems.length; i++) {
if ($scope.includedItems[i].included) {
var mandatory = $scope.includedItems[i]._mandatory;
if (mandatory && mandatory.length > 0) {
var elems = angular.element("[name*='" + mandatory[0].name + "']");
if (elems && elems.length > 0) //set focus the first element
elems[0].focus();
break;
} else {
var gForm = includedGformInstances[$scope.includedItems[i].sys_id];
getInvalidFields(gForm);
var invalidFields = gForm._invalidFields;
if (invalidFields && invalidFields.length > 0) {
var invalid = angular.element("[name*='" + invalidFields[0].name + "']");
if (invalid && invalid.length > 0) //set focus the first element
invalid[0].focus();
break;
}
}
}
}
}, 500);
}
$scope.closeItemAccordion = function (itemOpened) {
itemOpened.isOpen = false;
cabrillo.viewLayout.setNavigationBarButtons();
cabrillo.viewLayout.setTitle($scope.data.sc_cat_item.name);
addCabrilloBottomButtons({
title: [$scope.data.msgs.prevMsg, $scope.data.msgs.nextMsg],
fn: [$scope.goPrev, $scope.goNext]
});
$scope.isItemOpened = false;
}
$scope.showItem = function (index) {
if ($scope.itemShown == index)
$scope.itemShown = -1;
else
$scope.itemShown = index;
}
$scope.showCancel = function (id) {
var itemOpened,
buttons;
if (cabrillo.isNative()) {
clearCabrilloBottomButtons();
cabrillo.viewLayout.setNavigationBarButtons();
cabrillo.viewLayout.hideBackButton();
itemOpened = $scope.includedItems.find(function (item) {
return item.sys_id === id;
});
cabrillo.viewLayout.setTitle(itemOpened.name);
buttons = [{
title: i18n.getMessage('Done'),
enabled: true
}
];
cabrillo.viewLayout.setNavigationBarButtons(buttons, function (index) {
$scope.closeItemAccordion(itemOpened);
});
}
$scope.isItemOpened = true;
}
/* ****************************************************************************************** */
/* ******************************* Guide Navigation End ****************************** */
/* ****###############################################################################******* */
/* ****************************************************************************************** */
/* ******************************* Attachments ****************************** */
/* ****###############################################################################******* */
function initAttachmentHandlers() {
var setAttachments;
var appendError = function (error) {
spUtil.addErrorMessage(error.msg + error.fileName);
};
for (var i = 0; i < $scope.includedItems.length; i++) {
$scope.includedItems[i].attachmentHandler = new nowAttachmentHandler(setAttachments, appendError);
$scope.includedItems[i].attachmentHandler.setParams($scope.includedItems[i].targetTable, $scope.includedItems[i].sysparm_item_guid, 1024 * 1024 * $scope.data.maxAttachmentSize);
}
}
$scope.$on('dialog.upload_too_large.show', function (e) {
$log.error($scope.m.largeAttachmentMsg);
spUtil.addErrorMessage($scope.m.largeAttachmentMsg);
});
$scope.initAttachmentCallbacks = function (itemIndex) {
$scope.includedItems[itemIndex].attachmentHandler.setAttachments = function (attachments, action) {
$scope.includedItems[itemIndex].attachments = attachments;
if (action === "added") {
$scope.includedItems[itemIndex].attachment_submitted = true;
}
if (action === "renamed")
spAriaUtil.sendLiveMessage($scope.m.renameSuccessMsg);
if (action === "deleted") {
spAriaUtil.sendLiveMessage($scope.m.deleteSuccessMsg);
if ($scope.includedItems[itemIndex].attachments.length == 0)
$scope.includedItems[itemIndex].attachment_submitted = false;
}
spUtil.get($scope, {
action: "from_attachment"
});
};
$scope.includedItems[itemIndex].confirmDeleteAttachment = function (attachment) {
spModal.confirm($scope.data.msgs.delete_attachment).then(function () {
$scope.includedItems[itemIndex].attachmentHandler.deleteAttachment(attachment);
$scope.setFocusToAttachmentButton();
});
}
}
/* ****************************************************************************************** */
/* ******************************* Attachments End ****************************** */
/* ****###############################################################################******* */
/* ****************************************************************************************** */
/* ******************************* UTIL Functions ****************************** */
/* ****###############################################################################******* */
function evalGuidePrice() {
$scope.price = 0;
var frequencyMap = {};
for (var i = 0; i < $scope.includedItems.length; i++) {
if ($scope.includedItems[i].included && $scope.includedItems[i].process_price) {
var qty = parseInt($scope.includedItems[i].quantity);
var pricing = $scope.includedItems[i]._pricing;
var effectivePrice = 0;
var effectiveRecurringPrice = 0;
if (typeof $scope.includedItems[i].price != "undefined") {
effectivePrice = $scope.includedItems[i].price;
}
if (typeof $scope.includedItems[i].recurring_price != "undefined") {
effectiveRecurringPrice = $scope.includedItems[i].recurring_price;
}
if (effectiveRecurringPrice >= 0 && pricing.rfd) {
if (frequencyMap[pricing.rfd])
frequencyMap[pricing.rfd] += effectiveRecurringPrice * qty;
else
frequencyMap[pricing.rfd] = effectiveRecurringPrice * qty;
}
if (effectivePrice >= 0)
$scope.price += effectivePrice * qty;
}
}
frequencyMap.price = $scope.price;
$scope.server.get({
action: "format_prices",
prices: frequencyMap
}).then(function (response) {
$scope.frequencySequence = response.data.frequencySequence;
$scope.price_display = response.data.frequencyMap.price;
$scope.frequencyMap = response.data.frequencyMap;
});
}
function evalIncludes() {
// don't allow submit while waiting on included items eval
$scope.evaluatingIncludes = true;
$scope.includedItems = [];
var guideData = getFieldsData($scope.data.sc_cat_item);
guideData.sysparm_id = $scope.data.sys_id;
guideData.without_cart = true;
guideData._fields = $scope.data.sc_cat_item._fields;
guideData.cascade = $scope.data.sc_cat_item.cascade;
if ($scope.data.workspaceParams) {
guideData.sysparm_parent_sys_id = $scope.data.workspaceParams.sysparm_parent_sys_id;
guideData.sysparm_parent_table = $scope.data.workspaceParams.sysparm_parent_table;
}
$scope.server.get({
action: "init_guide",
orderGuideData: guideData
}).then(function (response) {
if (response.data.error) {
$scope.guide_step--;
return;
}
$scope.includedItems = response.data.items;
$scope.showIncludeToggle = response.data.showIncludeToggle;
initAttachmentHandlers();
$scope.includedItems.forEach(function (item) {
item.description = $sce.trustAsHtml(item.description);
});
$scope.totalIncluded = $scope.includedItems.length;
$scope.conflictingCartDomainMsg = response.data.conflictingCartDomainMsg;
$scope.evaluatingIncludes = false;
addCabrilloBottomButtons({
title: [$scope.data.msgs.prevMsg, $scope.data.msgs.nextMsg],
fn: [$scope.goPrev, $scope.goNext]
});
});
}
function getInvalidFields(gForm) {
gForm._invalidFields = [];
var fields = gForm.getFieldNames();
for (var j = 0; j < fields.length; j++) {
var field = gForm.getField(fields[j]);
if (field.isInvalid)
gForm._invalidFields.push(field);
}
}
function getCurrentGForm() {
if ($scope.guide_step == 0)
return includedGformInstances[$scope.data.sc_cat_item.sys_id];
else {
var openItem = $scope.includedItems.find(function (item) {
return item.isOpen === true;
});
return includedGformInstances[openItem.sys_id];
}
}
function openItemHelper(item, state, defer) {
for (var i = 0; i < $scope.includedItems.length; i++)
if ($scope.includedItems[i].sys_id == item) {
$scope.includedItems[i].included = state == 'true';
$scope.includedItems[i].isOpen = true;
$scope._atf.expose('g_form', spAtf.augmentForm(includedGformInstances[item]));
defer.resolve();
}
}
function getFieldsData(item) {
var fieldData = {
"variables": {}
};
for (var field in item._fields) {
var fieldValue = "";
if (item._fields[field].value != null && typeof item._fields[field].value != "string")
fieldValue = JSON.stringify(item._fields[field].value);
else
fieldValue = item._fields[field].value;
fieldData.variables[item._fields[field].name] = fieldValue;
}
return fieldData;
}
function getGuideItems(cartname) {
var items = [];
var item;
for (var i = 0; i < $scope.includedItems.length; i++) {
if ($scope.includedItems[i].included) {
item = getFieldsData($scope.includedItems[i]);
item.sysparm_id = item.sysparm_active = $scope.includedItems[i].sys_id;
item.sysparm_quantity = $scope.includedItems[i].quantity;
item.sysparm_cart_name = cartname;
item.sysparm_item_guid = $scope.includedItems[i].sysparm_item_guid;
items.push(item);
}
}
return items;
}
/* ******************************************************************************************* */
/* ******************************* UTIL Functions End ********************* */
/* ****################################################################################******* */
/* ******************************************************************************************* */
/* ******************************* Submit Handlers ********************* */
/* ****################################################################################******* */
$scope.triggerAddToCart = function () {
clearCabrilloBottomButtons();
if ($scope.conflictingCartDomainMsg) {
spUtil.addErrorMessage($scope.conflictingCartDomainMsg);
return;
}
if ($scope.submitted)
return;
$scope.server.get({
action: 'log_request',
itemDetails: {
sys_id: $scope.data.sc_cat_item.sys_id,
name: $scope.data.sc_cat_item.name,
sys_class_name: $scope.data.sc_cat_item.sys_class_name
}
});
$scope.submitted = true;
$scope.server.get({
action: "add_to_cart",
items: getGuideItems(""),
sys_id: $scope.data.sys_id
}).then(function (response) {
$rootScope.$broadcast("$sp.service_catalog.cart.add_item");
$rootScope.$broadcast("$sp.service_catalog.cart.update");
$scope.$emit("$sp.sc_order_guide.add_to_cart");
if (cabrillo.isNative()) {
$scope.submitted = true;
cabrillo.message.showMessage(cabrillo.message.SUCCESS_MESSAGE_STYLE, i18n.getMessage('Items have been added successfully to your cart'));
$timeout(function () {
cabrillo.flowControl.flowEnded();
return;
}, 200);
return;
}
spModal.open({
message: i18n.getMessage('Items have been added successfully'),
size: 'sm',
backdrop: 'static',
keyboard: false,
noDismiss: true,
buttons: [{
label: i18n.getMessage('Catalog Home'),
cancel: true
}, {
label: i18n.getMessage('View Cart'),
primary: true
}
]
}).then(function () {
$location.search("id=sc_cart");
}, function () {
$location.search("id=sc_home");
});
});
}
// order / create request
$scope.triggerSubmit = function () {
clearCabrilloBottomButtons();
if ($scope.submitted)
return;
$scope.server.get({
action: 'log_request',
itemDetails: {
sys_id: $scope.data.sc_cat_item.sys_id,
name: $scope.data.sc_cat_item.name,
sys_class_name: $scope.data.sc_cat_item.sys_class_name
}
});
$scope.submitted = true;
var hasItems = $scope.includedItems.filter(function (item) {
return item.sys_class_name != 'sc_cat_item_producer';
}).length > 0;
if ($scope.data.sys_properties.twostep && $scope.data.sc_cat_item.request_method != "submit") {
//Required to pass as payload for usage as embeddedWidget
var embeddedWidgetOptions = {
"auto_redirect": "true",
"requested_for_id": "",
"requested_for_display": ""
};
var payload = {
cart: '' + $scope.data.sys_id,
itemDetails: {
items: getGuideItems('' + $scope.data.sys_id),
request_method: $scope.data.sc_cat_item.request_method
},
workspaceParams: $scope.data.workspaceParams,
action: "order_guide"
};
for (var embeddedOption in embeddedWidgetOptions) {
payload[embeddedOption] = c.options[embeddedOption] || embeddedWidgetOptions[embeddedOption];
}
$scope.server.get(payload).then(function (response) {
var orderGuideModalCtrl;
var unregister = $scope.$on('$sp.service_catalog.cart.cancel_order', function () {
orderGuideModalCtrl.close();
$scope.submitted = false;
$timeout(function () {
addCabrilloBottomButtons({
title: [i18n.getMessage('Add to Cart'), $scope.submitButtonMsg],
fn: [$scope.triggerAddToCart, $scope.triggerSubmit]
});
});
});
var closeModalOnSubmit = $scope.$on("$sp.service_catalog.cart.submitted", function () {
orderGuideModalCtrl.close();
$scope.submitted = true;
});
var orderGuideModal = angular.copy(response.data.orderGuideModal);
orderGuideModal.options.afterOpen = function (ctrl) {
orderGuideModalCtrl = ctrl;
};
orderGuideModal.options.afterClose = function () {
unregister();
closeModalOnSubmit();
$scope.orderGuideModal = null;
orderGuideModalCtrl = null;
};
$scope.orderGuideModal = orderGuideModal;
});
return $scope.submitted;
} else {
$scope.data.action = 'checkout_guide';
$scope.data.guideItems = getGuideItems('' + $scope.data.sys_id);
$scope.server.update().then(function (response) {
$scope.data.action = undefined;
$scope.data.guideItems = undefined;
$scope.$emit("$sp.sc_order_guide.submitted", $scope.data.result);
$scope.submitted = true;
if ($scope.options.auto_redirect == 'false') {
spUtil.addInfoMessage($scope.m.requestSubmitted);
return;
} else {
if ($scope.data.result.request_id)
$location.search('id=sc_request&is_new_order=true&table=sc_request&sys_id=' + $scope.data.result.request_id);
else
$location.search('id=requests');
}
});
return $scope.submitted;
}
}
/* ******************************************************************************************* */
/* ******************************* Submit Handlers End ********************** */
/* ****################################################################################******* */
var catalogUtil = {
updateGform: function () {
var g_form = getCurrentGForm();
if (g_form)
$scope._atf.expose('g_form', spAtf.augmentForm(g_form));
},
addRow: function (fieldId, timeoutInMS) {
var deferred = $q.defer();
var g_form = getCurrentGForm();
if (g_form) {
if (timeoutInMS <= 0)
timeoutInMS = 1000;
$scope.$broadcast("$sp.sc_multi_row.create_row", fieldId, g_form.getSysId());
$scope.$on('spModel.gForm.initialized', function (e, gFormInstance) {
if (gFormInstance.getSysId() == fieldId)
deferred.resolve();
});
$timeout(function () {
deferred.reject();
}, timeoutInMS);
} else
deferred.reject();
return deferred.promise;
},
navigateToStep: function (num, timeout) {
var defer = $q.defer();
var step = parseInt(num) - 1;
if (Math.abs(step - $scope.guide_step) != 1) {
defer.reject("Can't navigate to next step");
return defer.promise;
}
if (step > $scope.guide_step)
$scope.goNext(timeout);
else {
$scope.goPrev();
defer.resolve();
}
var cleanup = $scope.$on('$sp.service_catalog.form_submit_failed', function () {
cleanup();
defer.reject("Can't navigate to next step");
});
var cleanup1 = $scope.$on('$sp.service_catalog.form_submitted', function () {
cleanup1();
defer.resolve("Can navigate to next step");
});
return defer.promise;
},
validateIncludedList: function (list, stage) {
var items = list.split(',').reduce(function (obj, item) {
obj[item] = false;
return obj;
}, {});
var included = stage == 1 ? $scope.includedItems : $scope.includedItems.filter(function (item) {
return item.included == true;
});
if (Object.keys(items).length != included.length)
return false;
for (var i = 0; i < included.length; i++)
if (!items.hasOwnProperty(included[i].sys_id))
return false;
return true;
},
openItem: function (item, state, timeoutInMS) {
if (timeoutInMS <= 0)
timeoutInMS = 10000;
var defer = $q.defer();
if (includedGformInstances[item]) {
openItemHelper(item, state, defer);
}
$scope.$on('spModel.gForm.initialized', function (e, gFormInstance) {
if (gFormInstance.getSysId() == item) {
openItemHelper(item, state, defer);
}
});
$timeout(function () {
defer.reject();
}, timeoutInMS);
return defer.promise;
},
getPrice: function () {
var res = {};
var item = $scope.includedItems.find(function (itemData) {
return itemData.isOpen == true;
});
if (item) {
res.price = item.price;
res.recurring_price = item.recurring_price;
res.recurring_frequency = item.recurring_frequency;
}
return res;
},
getGuidePrice: function () {
return $scope.price_display;
},
addToCart: function () {
var defer = $q.defer();
$scope.triggerAddToCart();
if (!$scope.submitted)
defer.reject("Can't submit form.");
else
defer.resolve();
return defer.promise;
},
submitOrderGuide: function () {
var defer = $q.defer();
if ($scope.triggerSubmit()) {
if ($scope.data.sys_properties.twostep && $scope.data.sc_cat_item.request_method != "submit") {
defer.resolve();
} else {
var cleanUp = $scope.$on('$sp.sc_order_guide.submitted', function (o, result) {
$timeout(function () {
cleanUp();
result.single_step = true;
defer.resolve(result);
}, 10);
});
}
} else
defer.reject();
return defer.promise;
}
};
/* ****************************************************************************************** */
/* ******************************* ATF End ************************ */
/* ****###############################################################################******* */
/* ****************************************************************************************** */
/* ******************************* Cabrillo Start ************************ */
/* ****###############################################################################******* */
function clearCabrilloBottomButtons() {
if (cabrillo.isNative()) {
cabrillo.viewLayout.setBottomButtons();
}
}
function showCabrilloBottomButtons() {
if (!cabrillo.isNative())
return;
if ($scope.guide_step === 0) {
addCabrilloBottomButtons({
title: [$scope.data.msgs.nextMsg],
fn: [$scope.goNext]
});
}
if ($scope.guide_step === 1) {
var itemOpened = $scope.includedItems.find(function (item) {
return item.isOpen;
});
if (itemOpened) {
$scope.showCancel(itemOpened.sys_id);
}
}
}
function addCabrilloBottomButtons(buttonDetails) {
if (cabrillo.isNative()) {
var buttons = [];
clearCabrilloBottomButtons();
switch ($scope.guide_step) {
case 0:
buttons = [{
title: buttonDetails.title[0],
enabled: true,
backgroundColor: $scope.data.sys_properties.mobileNativeColor,
textColor: '#FFFFFF'
}
];
cabrillo.viewLayout.setBottomButtons(buttons, function (buttonIndex) {
buttonDetails.fn[buttonIndex]();
});
cabrillo.viewLayout.showBackButton();
break;
case 1:
buttons = [{
title: buttonDetails.title[0],
enabled: true,
backgroundColor: '#f7f7f7',
textColor: '#000000'
}, {
title: buttonDetails.title[1],
enabled: true,
backgroundColor: $scope.data.sys_properties.mobileNativeColor,
textColor: '#FFFFFF'
}
];
cabrillo.viewLayout.setBottomButtons(buttons, function (buttonIndex) {
//Disable next button in choose option if all the items are marked as not included.
// however the previous button should still work
if (!($scope.submitted || $scope.totalIncluded <= 0) || buttonIndex === 0) {
buttonDetails.fn[buttonIndex]();
}
});
cabrillo.viewLayout.hideBackButton();
break;
case 2:
if ($scope.data.sys_properties.cartEnabled && $scope.showAddToCart) {
buttons = [{
title: buttonDetails.title[0],
enabled: true,
backgroundColor: '#f7f7f7',
textColor: '#000000'
}, {
title: buttonDetails.title[1],
enabled: true,
backgroundColor: $scope.data.sys_properties.mobileNativeColor,
textColor: '#FFFFFF'
}
];
cabrillo.viewLayout.setBottomButtons(buttons, function (buttonIndex) {
buttonDetails.fn[buttonIndex]();
});
} else {
buttons = [{
title: buttonDetails.title[1],
enabled: true,
backgroundColor: $scope.data.sys_properties.mobileNativeColor,
textColor: '#FFFFFF'
}
];
cabrillo.viewLayout.setBottomButtons(buttons, function (buttonIndex) {
buttonDetails.fn[1]();
});
}
cabrillo.viewLayout.hideBackButton();
break;
}
}
}
var mespOpenPopupUnregister = $rootScope.$on("mesp.popup.open", function () {
// Timeout is to give a better user experience otherwise when this popup opens,
// the cabrillo buttons will be displayed immediately giving a bad user experience.
$timeout(function () {
clearCabrilloBottomButtons();
});
});
var mespClosePopupUnregister = $rootScope.$on("mesp.popup.close", function () {
// Timeout is to give a better user experience otherwise when this popup opens,
// the cabrillo buttons will be displayed immediately giving a bad user experience.
$timeout(function () {
showCabrilloBottomButtons();
});
});
/* ********************************************************************************************* */
/* ******************************* Cabrillo End *************************** */
/* ****##################################################################################******* */
/**
* Value displayed in the "For" or "At" form locations when the values are not known or while the form
* is loading, such as the GlideForm not yet being available.
*
* This would otherwise result in empty displays or errors in the console if the considerations were
* skipped.
* @property waitingValue
* @type String
*/
var waitingValue = "[ Waiting... ]";
/**
* Maps values for display purposes that have been stored for preservation.
*
* This is used to keep values in place after "goNext" is called to
* @property locakedValues
* @type Object
*/
var lockedValues = {};
/**
* Retrieves the employee name from the glide form using the "getDisplayValue" method and parses
* the username from the string if one is determined to be present. The presence of a "-" character
* is used to determine this.
*
* Due to different variables being used to store the employee depeneding on access type, the type
* is read and used to determine the name to use with a general fall back on various naming conventions
* to isolate the name in a general case should variables change.
*
* The general fallback fails however as values are not (and likely should not) clear when the access
* type changes, meaning a name could become "stuck" displaying in the event the access type changes
* if this has not been updated with the map of "access type" to "variable used for employee name".
*
* However it would be recommended to consolidate the usage fo variables to one variable representing
* the employee for any access type, and that variable is assumed to be "requested_for" in the code
* below, and assignment priority is given to that variable name where considerations are made.
*
* Uses the private {{crossLink "localGlideForm"}}{{/crossLink}} value for gathering values.
* @method getEmployeeName
* @return {String} The Employee name per the localized GlideForm.
*/
$scope.getEmployeeName = function() {
var localGlideForm = $scope._glideForms[$scope.data.sys_id],
index,
type,
name,
hide;
if(localGlideForm || $scope.primaryGlideForm) {
localGlideForm = localGlideForm || $scope.primaryGlideForm;
type = localGlideForm.getDisplayValue("access_request_main");
// Isolate Name by Access Type
switch(type) {
case "delete":
name = localGlideForm.getDisplayValue("employee_terminated");
break;
case "transfer":
case "modify":
name = localGlideForm.getDisplayValue("employee_name");
break;
case "add":
name = localGlideForm.getDisplayValue("e_first_name") + " " + localGlideForm.getDisplayValue("e_last_name")
break;
default:
name = localGlideForm.getDisplayValue("requested_for") || localGlideForm.getDisplayValue("employee") || localGlideForm.getDisplayValue("employee_name") || localGlideForm.getDisplayValue("employee_terminated") || localGlideForm.getDisplayValue("u_requested_for") || localGlideForm.getDisplayValue("u_requested_for") || localGlideForm.getDisplayValue("u_employee") || localGlideForm.getDisplayValue("u_employee_terminated");
}
if(name && typeof(name) === "string") {
// Clean Username from Name string
index = name.indexOf(" - ");
if(index !== -1) {
name = name.substring(index + 3);
}
name = name.trim();
hide = name.toLowerCase();
if(name && hide !== "hideme" && hide !== "deme") { // Handle odd initialization cases
return name;
}
}
}
return waitingValue;
};
/**
* Retrieves the name of the location from the glide form using "getDisplayValue".
*
* Uses the private {{crossLink "localGlideForm"}}{{/crossLink}} value for gathering values.
* @method getLocationName
* @return {String} The name of the Location per the localized GlideForm.
*/
$scope.getLocationName = function() {
var localGlideForm = includedGformInstances[$scope.data.sys_id];
if(localGlideForm || $scope.primaryGlideForm) {
localGlideForm = localGlideForm || $scope.primaryGlideForm;
return localGlideForm.getDisplayValue("location") || waitingValue;
}
return waitingValue;
};
}