Collaboration Store, Part XXII

“Doubt is an uncomfortable condition, but certainty is a ridiculous one.”
Voltaire

Now that we have the face of our new pop-up window laid out, it’s time to build out the code underneath that will do all of the work. Since this is all server-side activity, we will need some kind of client accessible Script Include that we can call from the client side for each step of the process. Just to do a little testing on the structure and the process, I created a stubbed-out version of a Script Include that I can call from the client-side code to do a little testing before we get too far into the weeds.

var ApplicationPublisher = Class.create();
ApplicationPublisher.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {

    processPhaseClient: function() {
		var phase = this.getParameter('sysparm_phase');
		var mbrAppId = this.getParameter('sysparm_mbr_app_id');
		var appSysId = this.getParameter('sysparm_app_sys_id');
		var updSetId = this.getParameter('sysparm_upd_set_id');
		var origAppId = this.getParameter('sysparm_orig_app_id');
		return this.processPhase(phase, mbrAppId, appSysId, updSetId, origAppId);
	},

    processPhase: function(phase, mbrAppId, appSysId, updSetId, origAppId) {
		return 'success';
	},

    type: 'ApplicationPublisher'
});

At this point, all it does is return the value ‘success’ each time that it is called. This will be enough to prove out all of the client-side code before we dig into the actual work on the server side. For now, we just want to prove that the design is functional before we invest too much time in the actual tasks ahead of us.

On the client side, we will want to create a generic function that will work essentially the same for every step of the process. To keep track of where we are, I created a variable called phase, which is basically just the number of the current step. I called this function processPhase.

function processPhase(phase, mbrAppId, appSysId, updSetId, origAppId) {
	var ga = new GlideAjax('ApplicationPublisher');
	ga.addParam('sysparm_name', 'processPhaseClient');
	ga.addParam('sysparm_phase', phase);
	ga.addParam('sysparm_mbr_app_id', mbrAppId);
	ga.addParam('sysparm_app_sys_id', appSysId);
	ga.addParam('sysparm_upd_set_id', updSetId);
	ga.addParam('sysparm_orig_app_id', origAppId);
	ga.getXMLAnswer(function (answer) {
		if (answer == 'success') {
			hideElement('loading_' + phase);
			showElement('success_' + phase);
			phase++;
			if (phase < 7) {
				showElement('phase_' + phase);
				processPhase(phase, mbrAppId, appSysId, updSetId, origAppId);
			} else {
				showElement('done_button');
			}
		} else {
			showElement('done_button');
		}
	});
}

This is a recursive function that calls itself for every step until all six steps have been completed or there was some kind of an error. If the response from the Ajax call is ‘success’, then the loading icon for that step is hidden and replaced with the success icon, and then the phase is incremented. If we haven’t reached the end of the steps, then the HTML block for the next step is revealed and the process is repeated. If we reach the end of the steps, or if the Ajax call returns anything other than success, then the process comes to an end and the Done button is revealed. There is no effort on the client side to communicate any error or completion message to the operator. The assumption is that all messaging will be handled on the server side.

For the hideElement and showElement functions, I just stole some old code from some other component where I needed to do the same thing. There’s not much exciting here, but just for the sake of including everything, here it is:

function showElement(elementName) {
	var elem = gel(elementName);
	elem.style.visibility = 'visible';
	elem.style.display = '';
}

function hideElement(elementName) {
	var elem = gel(elementName);
	elem.style.visibility = 'hidden';
	elem.style.display = 'none';
}

Even though the processPhase function calls itself once it gets going, something has to initially get the ball rolling to kicks things off. For that, we can use an onload function to initialize all of the values and make that first call.

function onLoad() {
	var phase = 1;
	var mbrAppId = gel('mbr_app_id').value;
	var appSysId = gel('app_sys_id').value;
	var updSetId = gel('upd_set_id').value;
	var origAppId = gel('mbr_app_id').value;
	processPhase(phase, mbrAppId, appSysId, updSetId, origAppId);
}

Although that seemed like a good plan, when I ran my first test run, nothing happened. After doing a little online research, I discovered that the onLoad function is not a natural thing for a UI Page, and if I wanted something to run on load, I needed to add just a bit more code.

addLoadEvent(function() {  
	onLoad();
});

That was much better! Now after calling the server side six times in succession, the final rendition of the pop-up screen looked like this:

Pop-up structure test results

That proves that the client-side process functions as we intended and the stubbed-out Script Include is getting called and is returning the hard-coded ‘success’ value. This should now complete the work on the UI Page itself, so all that is left is to finish out the server-side Script Include to perform all of the tasks itemized in our list of steps. Next time, we can get started on the fist step, which will involve calling the global function that we created earlier to convert the Update Set to XML.