CustomEvent.observe does not get triggered

jiral
Giga Sage

We have recently upgraded from Helsinki to Kingston and in one of our catalog item, the CustomEvent.observe seemed to have stopped working. The client script that is no longer working is provided below. 

function onChange(control, oldValue, newValue, isLoading) {
	var collectors = [ "shared_mbx_privs_owner", "shared_mbx_privs_read", "shared_mbx_privs_full", "shared_mbx_privs_send" ];
	if (isLoading) {
		return;
	}
	if (!newValue || newValue == '') {
		for(var i=0; i < collectors.length; i++) {
			clearCollectorValues(collectors[i]);
		}
		g_form.clearValue('shared_mbx_display_name');
		g_form.clearValue('shared_mbx_smtp');
		return;
	}
	
	if (newValue != '' && newValue != oldValue) {
		for(var i=0; i < collectors.length; i++) {
			clearCollectorValues(collectors[i]);
		}
		g_form.clearValue('shared_mbx_display_name');
		g_form.clearValue('shared_mbx_smtp');
		
		var ga = new GlideAjax('CovanceSharedMailboxHelper');
		ga.addParam('sysparm_name', 'getMailboxDetailsAndPermissions');
		ga.addParam('sysparm_user_id', g_user.userID);
		ga.addParam('sysparm_mbx_id', newValue);
		ga.getXML(getMailboxDetailsAndPermissionsCallBack);
	}
}

function getMailboxDetailsAndPermissionsCallBack(response) {
	var activeUserWithEmailFilter = 'active=true^employee_numberISNOTEMPTY^emailISNOTEMPTY';
	console.log('getMailboxDetailsAndPermissionsCallBack response' + JSON.stringify(response));
	var result = response.responseXML.getElementsByTagName("result");
	if (result != null)
	{
		window.smbx_details.DisplayName = result[0].getAttribute("displayName");
		window.smbx_details.PrimaryEmail = result[0].getAttribute("primaryEmail");
		window.smbx_details.MinOwners = result[0].getAttribute("minOwners");
		window.smbx_details.MaxOwners = result[0].getAttribute("maxOwners");
		window.smbx_details.BlockNewIfPending = result[0].getAttribute("blockNewIfPending");
		window.smbx_details.PendingRequest = result[0].getAttribute("pendingRequest");
		if (window.smbx_details.PendingRequest != '') {
			g_form.showFieldMsg('mbx_reference', "Request Item " + window.smbx_details.PendingRequest + " is currently active for this mailbox.", (window.smbx_details.BlockNewIfPending ? 'error' : 'info'));
		}
		g_form.setValue('shared_mbx_display_name', result[0].getAttribute("displayName"));
		g_form.setValue('shared_mbx_smtp', result[0].getAttribute("primaryEmail"));
		setCollectorFilterWithSelectedItemsAsync('shared_mbx_privs_owner', activeUserWithEmailFilter ,'sys_idIN'+result[0].getAttribute("Owner"));
		setCollectorFilterWithSelectedItemsAsync('shared_mbx_privs_full', activeUserWithEmailFilter ,'sys_idIN'+result[0].getAttribute("Full"));
		setCollectorFilterWithSelectedItemsAsync('shared_mbx_privs_read', activeUserWithEmailFilter ,'sys_idIN'+result[0].getAttribute("Read"));
		setCollectorFilterWithSelectedItemsAsync('shared_mbx_privs_send', activeUserWithEmailFilter ,'sys_idIN'+result[0].getAttribute("Send"));
	}
}

function setCollectorFilterWithSelectedItemsAsync(collectorName,filterString,selectedItemsFilterString) {
	//Test if the g_filter property is defined on our list collector.
	//If it hasn't rendered yet, wait 100ms and try again.
	if(typeof(window[collectorName + 'g_filter']) == 'undefined'){
		setTimeout(function () { setCollectorFilterWithSelectedItemsAsync(collectorName,filterString,selectedItemsFilterString); }, 100);
		return;
	}
	
	CustomEvent.observe(collectorName +':applyFilter', function() {
		setCollectorFilterAsync(collectorName, filterString);
		CustomEvent.unAll(collectorName +':applyFilter');
	});
		
	//Reset the filter query
	window[collectorName + 'g_filter'].reset();
	
	if (selectedItemsFilterString != '' && selectedItemsFilterString != 'sys_idIN') {
		window[collectorName + 'g_filter'].setQueryCallback = function () {
			if (this.destroyed)
				return;
			this.reset();
			this.build();
			if (this.getFilterReadOnly()){
				this.setReadOnly(true);
			}
			CustomEvent.fire('filter:' + this.type + '-done', true);
			CustomEvent.fire('filter:collectorAsyncDone', collectorName);
		};
		CustomEvent.observe(collectorName +':itemsChanged', selectedItemsChangedTriggered);
		window[collectorName + 'g_filter'].setQueryAsync(selectedItemsFilterString);
	}
	else {
		CustomEvent.fire(collectorName +':applyFilter', true);
	}
}

function selectedItemsChangedTriggered(collectorName) {
	console.log('selectedItemsChangedTriggered TRIGGERED for collectorName = ' + collectorName);
	CustomEvent.un(collectorName +':itemsChanged', selectedItemsChangedTriggered);
	
	var leftBucket = gel(collectorName + '_select_0');
	var rightBucket = gel(collectorName + '_select_1');
	var availableOptionsArray = leftBucket.options;
	var selectedOptionsIDs = [];
	var i = 0;

	if (availableOptionsArray.length != 0) {
		for (var k = 0; k < availableOptionsArray.length; k++) {
			selectedOptionsIDs[i] = k;
			i++;
		}
	}

	try {
		if(rightBucket.options.length == 1 && rightBucket.options[0].text == '--None--'){
			console.log('setting rightBucket options length to 0');
			rightBucket.options.length = '0';
		}
		moveSelectedOptions(selectedOptionsIDs, leftBucket, rightBucket);
		sortSelect(rightBucket);
	} catch(exception) {
		jslog('Error in selectedItemsChangedTriggered: ' + exception);
	}
	
	CustomEvent.fire(collectorName +':applyFilter', true);
}

function setCollectorFilterAsync(collectorName, filterString) {
	//Test if the g_filter property is defined on our list collector.
	//If it hasn't rendered yet, wait 100ms and try again.
	if(typeof(window[collectorName + 'g_filter']) == 'undefined'){
		setTimeout(function () { setCollectorFilterAsync(collectorName, filterString); }, 100);
		return;
	}
	
	//g_form.setDisplay(collectorName, false);
	
	window[collectorName + 'g_filter'].reset();
	window[collectorName + 'g_filter'].setQueryCallback = function () {
			if (this.destroyed)
				return;
			this.reset();
			this.build();
			if (this.getFilterReadOnly()){
				this.setReadOnly(true);
			}
			CustomEvent.fire('filter:' + this.type + '-done', true);
			CustomEvent.fire('filter:collectorAsyncDone', collectorName);
		};
	CustomEvent.observe(collectorName +':itemsChanged', function() {
		gel(collectorName + 'recordpreview').hide();
	
		//Redisplay the list collector variable
		g_form.setDisplay(collectorName, true);
		CustomEvent.unAll(collectorName +':itemsChanged');
	});
	window[collectorName + 'g_filter'].setQueryAsync(filterString);
}

function clearCollectorValues(collectorName) {
	//g_form.setDisplay(collectorName, false);
	try {
		// Gets the right column of the List Collector
		var rightSlushbucket = gel(collectorName+"_select_1");
		// Loops through all the selected entries and remove them
		while(rightSlushbucket.firstChild) {
			if(rightSlushbucket.firstChild != null && rightSlushbucket.firstChild != "") {
				rightSlushbucket.removeChild(rightSlushbucket.firstChild);
			}
		}
	} catch(exception) {
		jslog('Error in Catalog Client Script "Clear Slushbucket values": ' + exception);
	}
}

On the code provided above, here is the part that seems to be failing:

CustomEvent.observe(collectorName +':itemsChanged', selectedItemsChangedTriggered);

This does not run selectedItemsChangedTriggered anymore.

Does anyone know what went wrong with this or something that the upgrade may have messed up?

3 REPLIES 3

thomas_wright1
Giga Contributor

Did you ever find a fix for this?  I'm seeing this issue in Jakarta.  

arthurcheung
Kilo Expert

This question was asked two years ago which is almost exactly the same. No answers to that one either though.

Someone must know?

arthurcheung
Kilo Expert

So after digging around in devtools for a bit, I think I've found the answer. Note that this in London, but you can do the same check on whatever version you're on.

It looks like ServiceNow removed their implementation of CustomEvent from the global scope (i.e. the window object) presumably to avoid overwriting the browsers version with the same name (similar function, but implemented differently).

It looks like they've ended up putting it in two places:

  1. NOW.CustomEvent
  2. CustomEventManager

Both appear to be the same implementation. I tested this by registering events on both. Firing from either one will fire events on both.

Therefore, you should be able to get your code working by replace occurances of CustomEvent with NOW.CustomEvent or CustomEventManager.

I can't vouch for how stable these changes will be over releases though.

find_real_file.png