GlideAjax Response Null - Script Include not running?

Hurleybird
Tera Expert

Hi there, I'm a newbie that feels like I'm trying to do something beyond my skills - so I apologise in advanced if I'm missing any real basics.

Ultimate Goal: Use a Client Script to trigger a Guided Tour when a Case is in a specific state. Once the Tour has been viewed (tourCompleted) or dismissed (tourDismissed), the tour should not start.

I've used a script from Community Member athm (https://community.servicenow.com/community?id=community_article&sys_id=4d846de3db47130023f4a345ca961...) to achieve the conditional triggering. This works like a charm!

I plan to write an entry to "sys_guided_tour_user_overrides" if the user views or dismisses the tour. For now, I have manually added the entry in the table to test whether I can read from the table:

find_real_file.png

In order to read from the table, I was originally planning to utilise the Script Include "GTAutoLaunchController". However, rather than messing with a "system" Script, I created my own version of it, to allow me to make it Client Callable and mess around with it. From the Client Script, I am attempting a GlideAjax call. But no matter what I have tried, I believe that it's not triggering the script.

I have added gs.info in various places within the Script Include in an attempt to help me troubleshoot, but nothing appears in the System Log (syslog.list).

The Client Script is as follows:

function onChange(control, oldValue, newValue, isLoading, isTemplate) {
   if (isLoading || newValue === '') {
      return;
   }
	
	//If the current state of the form meets your conditions, launch the tour
if(g_form.getValue('resolution_code') != '0'){
	
	var ga = new GlideAjax('sn_tourbuilder.GTAutoLaunchUtils');
	ga.addParam('sysparm_name', 'getOverriddenToursForUser');
	ga.addParam('sysparm_userID', g_user.userID);
	ga.getXML(checkOveride);
	g_form.addInfoMessage(JSON.stringify(ga));
}
	
	function checkOveride(response) {
		g_form.addInfoMessage("Response was: " + JSON.stringify(response));
		var answer = response.responseXML.documentElement.getAttribute("tourId");
		g_form.addInfoMessage(JSON.stringify(answer));
// 		answer = answer.evalJSON();
// 		g_form.addInfoMessage(answer);
		
// 		for (var i=0 ; i < answer.length ; i++) { //Loop into the array
		
// 				g_form.addInfoMessage(answer[i].tourID);
		}
// 	}

top.NOW.guidedToursService.startTour("81996c861b515810e8a7eca13d4bcb6c", 0);
//(sys_id of the guided tour you want to launch, step#)

//Check if the guided tour is dismissed by the user, if so then end the tour. 
//If not the system will dispaly a message if the user navigates to a different form
//before the completion of the guided tour.

	setInterval(function(){
		if(top.NOW.guidedToursService.isDismissed){
			top.NOW.guidedToursService.endTour(); 

			clearInterval();
		}
		
	},2000);
}

The results from the InfoMessages are as follows:

g_form.addInfoMessage(JSON.stringify(ga));

{"contextPath":"xmlhttp.do","params":{"sysparm_processor":"sn_tourbuilder.GTAutoLaunchUtils","sysparm_scope":"sn_customerservice","sysparm_want_session_messages":true,"sysparm_name":"getOverriddenToursForUser","sysparm_userID":"a1fa60be1b6e40d044addac3cc4bcbb9"},"encodedString":"","encode":true,"processor":"sn_tourbuilder.GTAutoLaunchUtils","wantRequestObject":false,"runRequestInBatch":false,"wantAnswer":false,"async":true}
 
I've bolded what I believe are the key parameters, that seems to suggest it's passing what I believe is required to trigger the script and pass the correct variables?
 
g_form.addInfoMessage("Response was: " + JSON.stringify(response));
 
Info MessageResponse was: {}
 
g_form.addInfoMessage(JSON.stringify(answer));
Info Messagenull
 
The Script Include is as follows:
var GTAutoLaunchUtils = Class.create();
var tourTypes = {
	SERVICE_PORTAL: 'service_portal',
	PLATFORM: 'platform',
	CUSTOM: 'custom_ui'
};
GTAutoLaunchUtils.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {

    type: 'GTAutoLaunchUtils'
});
GTAutoLaunchUtils.prototype.tableNames = {
	tours: 'sys_embedded_tour_guide',
	userOverrides: 'sys_guided_tour_user_overrides'
};
insertOverride = function(tourId, userId) {
	var rec = new GlideRecord(this.tableNames.userOverrides);
	rec.initialize();
	rec.tour = tourId;
	rec.user = userId;
	rec.disable_autolaunch = true;
	rec.insert();
};

removeOverrides = function(page, userId, portal) {
	var self = this;
	var pages = this.getToursForPage(page, portal);
	var ids = pages
				.map(function(d) { return d.id; })
	;
	if (ids.length) {
		var rec = new GlideRecord(self.tableNames.userOverrides);
		if (userId) {
			rec.addQuery('user', '=', userId);
		}
		rec.addQuery('tour', 'IN', ids.join(','));
		rec.deleteMultiple();
		return {ids: ids};
	} else {
		return null;
	}
};

overrideTourForUser = function(tourId) {
	var currentUser = gs.getUser();
	var rec = new GlideRecord(this.tableNames.userOverrides);
	rec.addQuery('user', '=', currentUser.getID());
	rec.addQuery('tour', '=', tourId);
	rec.query();
	var exists = rec.next();
	var tourRecord = new GlideAggregate(this.tableNames.tours);
	tourRecord.addQuery('sys_id', '=', tourId);
	tourRecord.query();
	if(tourRecord.hasNext() && !exists) {
		this._insertOverride(tourId, currentUser.getID());
		return {msg: this.messages.done};
	} else if(tourRecord.hasNext() && exists && !rec.disable_autolaunch){
		rec.disable_autolaunch = true;
		rec.update();
		return {msg: this.messages.done};
	}else {
		return null;
	}
};

overrideAllToursForUserInPage = function(page, portal) {
	var self = this;
	var currentUser = gs.getUser();
	var userId = currentUser.getID();
	var res = this._removeOverrides(page, userId, portal);
	if (res) {
		res.ids.forEach(function(id) {
			self._insertOverride(id, userId);
		});
		return {msg: self.messages.done};
	} else {
		return null;
	}
};

getOverriddenToursForUser = function() {
	gs.info("The script ran");
 	var userID = this.getParameter('sysparm_userID');
	var gr = new GlideRecord("sys_guided_tour_user_overrides");
  var data = [];
  gr.addQuery('user', userID);
  gr.addQuery('disable_autolaunch',true);
  gr.query();
	gs.info("This is killing me, will this work " + gr.tour);
  while(gr.next()) {
	gs.info("Results from this script " + gr.tour);
	var elem = {tourId: '' + gr.tour};
	data.push(elem);
  }
	return data.toString();
};

I have tried to follow all of the advice in GlideAjax Troubleshooting Guide, I've attempted multiple variations on passing arrays, JSON etc. I've tried different methods of logging, but I believe that gs.info is correct for a Scoped Application.

Ultimately, I'm not convinced that the script is being called (due to the lack of logging). I have run a couple basic Background Scripts (in Global scope) to test whether I can indeed get a result back from the table - and I can:

var gr = new GlideRecord('sys_guided_tour_user_overrides');
gr.addQuery('user','a1fa60be1b6e40d044addac3cc4bcbb9');
gr.addQuery('disable_autolaunch',true);
gr.query();
while(gr.next()){
gs.info("Tour ID: " + gr.tour);
}

Returns:

*** Script: Tour ID: 81996c861b515810e8a7eca13d4bcb6c
var gr = new GlideRecord('sys_guided_tour_user_overrides');
gr.addQuery('user','a1fa60be1b6e40d044addac3cc4bcbb9');
gr.addQuery('disable_autolaunch',true);
gr.query();
var data = [];
while(gr.next()){
var elem = {tourId: '' + gr.tour};
data.push(elem);
}
data.toString();
gs.info(JSON.stringify(data));

Returns:

*** Script: [{"tourId":"81996c861b515810e8a7eca13d4bcb6c"}]

I'm totally at a loss and hope you can help/point me in the right direction.

Thanks!
1 ACCEPTED SOLUTION

DirkRedeker
Mega Sage

Hi

I have not tested out, but I think, you closed your Prototype definition TOO early (look at my screenshot).

find_real_file.png

You need to put all the code within the curly braces, to make them belong to the Class. You put all of your functions outside, which will make them "unreachable".

 

Below, I copied the starting part of an OOB AJAX Script include. There you can see, that all functions are INSIDE.

find_real_file.png

Additionally, make sure to name your Script Include EXACTLY as you do in the code.

 

 

Let me know if that answers your question and mark my answer as correct/helpful.

Have fun & Enjoy ServiceNow

BR

Dirk

View solution in original post

14 REPLIES 14

MrMuhammad
Giga Sage

Hi Hurleybird,

is your client script created in global application or scoped application? 

 

if in global application then you need to check whether the script include is accessible from All application scopes or just within the scope it is created. In the script include check the value of Accessible from it should be All Application scope.

 

Please mark this accepted and helpful if it helps. Thanks!

Regards,
Muhammad

Thanks for the reply Muhammad!

The client script is in the Customer Service scope (as it runs on sn_customerservice_case)

find_real_file.png


The Script Include runs in ServiceNow Guided Tour Designer

find_real_file.png

Can you try running below script in background script to execute script include and see if it prints the log.

var guidedTourUtil = new sn_tourbuilder.GTAutoLaunchUtils();

var userTours = guidedTourUtil.getOverriddenToursForUser();

Regards,
Muhammad

DirkRedeker
Mega Sage

Hi

I have not tested out, but I think, you closed your Prototype definition TOO early (look at my screenshot).

find_real_file.png

You need to put all the code within the curly braces, to make them belong to the Class. You put all of your functions outside, which will make them "unreachable".

 

Below, I copied the starting part of an OOB AJAX Script include. There you can see, that all functions are INSIDE.

find_real_file.png

Additionally, make sure to name your Script Include EXACTLY as you do in the code.

 

 

Let me know if that answers your question and mark my answer as correct/helpful.

Have fun & Enjoy ServiceNow

BR

Dirk