L
ast week I had a request come in from a client where they wanted to require users to accept certain terms and conditions before ordering a specific catalog item. I have seen this type of request before, but I don’t think I’ve really seen an elegant solution to it…or anything that could really be called a solution at all
. Usually you end up with some combination of a wizard, some custom form, and some crazy scripts that make no sense to anyone but the person who created it. Then I realized that I had just written about a solution a week or so ago when I wrote about how to create a UI Page popup using GlideDialogWindow! The specific application of the solution I wrote about was a little bit different, but the basic pieces were identical. By making some basic tweaks to a solution I already knew about, I was able to come up with what I think is a really nice way to require acceptance of some terms before a user orders a catalog item. This same method could also be used on other forms and tables in Service-now.com.

The first part of this solution is to set up a client-side trigger for your terms dialog. For this example, we assume that the Terms dialog only needs to be displayed for a particular catalog item so our trigger can be in an ‘onLoad’ catalog client script set against the item in question. The script simply needs to create and render the dialog when the item (or potentially variables) load. It also needs to point to a UI Page (by name) that should load within the dialog. It’s the UI Page that will contain all of the specific form elements and terms. If you want your dialog to redirect to a specific location if the ‘Cancel’ button is clicked you can include the ‘cancel_url’ preference as shown below…
Name: Load Terms
Type: onLoad
Script:
//Initialize and open the Dialog Window
var dialog = new GlideDialogWindow('terms_and_conditions_dialog'); //Render the dialog containing the UI Page 'terms_and_conditions_dialog'
dialog.setTitle('Terms and Conditions'); //Set the dialog title
dialog.setSize(600,600); //Set the dialog size
dialog.removeCloseDecoration(); //Remove the dialog close icon
dialog.setPreference('cancel_url', 'catalog_home.do?sysparm_view=catalog_default'); //Set optional cancel redirect URL
dialog.render(); //Open the dialog
}
Now that we’ve set up a trigger, we need to make sure that we have a UI Page with the correct name to be triggered. Notice in the script above that we’re looking for a UI Page named ‘terms_and_conditions_dialog’ in our dialog client script. The correct name is the only absolute in the UI Page. It needs to match the name given in the client script trigger.
The other elements of the UI Page are up to you. Typically when I’ve seen a terms and conditions page, the page contains the terms, an ‘Agree’ checkbox of some sort, and buttons to agree or cancel. I’ve commented those portions of code below. The buttons both trigger specific client-side functions that make sure the ‘Agree’ checkbox is checked (for the ‘OK’ button) and redirect back to the default homepage – or the homepage passed in via the ‘cancel_url’ parameter (for the ‘Cancel’ button). The only thing I haven’t provided is the actual terms and formatting. In order to produce that in a nice HTML format, I actually cheated and pasted my terms into the HTML editor on a blank KB article. Then I could get it formatted like I want and then just toggle to the code editor and copy the HTML into the correct place in my UI Page…
HTML
<!-- Get values from dialog preferences passed in -->
<g:evaluate var="jvar_cancel_url"
expression= "RP.getWindowProperties().get('cancel_url')" />
<input type="hidden" id="cancel_url" value="${jvar_cancel_url}" />
<table width="100%">
<tr>
<td>
ENTER YOUR TERMS HERE...
</td>
</tr>
<tr>
<td>
<div style="margin-top: 10px;">
<!-- Pull in 'ui_checkbox' UI Macro for accept checkbox -->
<g:ui_checkbox id="accept_terms" name="accept_terms" value="false"/>
<label for="load_demo">I accept these terms and conditions.</label>
</div>
</td>
</tr>
<tr>
<td colspan="2">
</td>
</tr>
<tr id="dialog_buttons">
<td colspan="2" align="right">
<!-- Pull in 'dialog_buttons_ok_cancel' UI Macro for submit/cancel buttons -->
<g:dialog_buttons_ok_cancel ok="return termsOK()" cancel="termsCancel()" ok_type="button" cancel_type="button"/>
</td>
</tr>
</table>
</g:ui_form>
Client Script
//Gets called if the 'OK' dialog button is clicked
//Make sure terms have been accepted
var terms = gel('accept_terms').value;
if(terms != 'true'){
//If terms are false stop submission
alert('Please accept the terms and conditions to continue your order.');
return false;
}
//If accept checkbox is true do this...
GlideDialogWindow.get().destroy(); //Close the dialog window
//g_form.setValue('myvar', true); //Optionally set the value of a variable or field indicating acceptance
}
function termsCancel(){
//Redirect gets called if the 'Cancel' dialog button is clicked
if($('cancel_url').value != 'null'){
window.location = $('cancel_url').value;
}
else{
window.location = 'home.do'; //Redirect to default homepage
}
}
Comments
Posted On
Oct 12, 2010Posted By
alliHi,
The timing of this is awesome.
I tried this but the buttons doesn’t seem to check if the checkbox is checked or not.
also is this possible on the onsubmit function?
was playing around with it and I can’t get it to render, it always proceeds to the checkout
thanks for all your help
Posted On
Oct 13, 2010Posted By
Mark StangerI posted the wrong version of code to validate the checkbox. It’s updated now. The ‘onSubmit’ would be a little bit trickier. You would have to check for the value of a variable to see if the acceptance had already been done. Then if it hadn’t, pop the dialog. If you created a ‘Yes/No’ variable defaulted to ‘No’ and added it to your item, that could be done like this…
//Check 'terms' variable to see if it has been marked
var termsOK = g_form.getValue('terms_ok');
//If not then pop the dialog and stop the submission
if(termsOK == 'No'){
//Initialize and open the Dialog Window
var dialog = new GlideDialogWindow("demo_terms_and_conditions_dialog"); //Render the dialog containing the UI Page 'demo_terms_and_conditions_dialog'
dialog.setTitle("Terms and Conditions"); //Set the dialog title
dialog.setSize(600,600);
dialog.removeCloseDecoration();
dialog.render(); //Open the dialog
return false;
}
}
Then you would need to modify your UI page client script to set the value of that variable on acceptance. You would also want to change the ‘Cancel’ function to simply close the dialog instead of redirecting…
//Gets called if the 'OK' dialog button is clicked
//Make sure terms have been accepted
var terms = gel('accept_terms').value;
if(terms != 'true'){
//If terms are false stop submission
alert("Please accept the terms and conditions to continue your order.");
return false;
}
//If accept checkbox is true do this...
GlideDialogWindow.get().destroy(); //Close the dialog window
g_form.setValue('terms_ok', 'Yes');
}
function termsCancel(){
//Gets called if the 'Cancel' dialog button is clicked
GlideDialogWindow.get().destroy(); //Close the dialog window
}
This works fine in my testing. The only thing I wish I could add would be to have the submission automatically happen once the user approved the dialog. That would involve capturing the original submit action and calling that again. I couldn’t get that to work when I tested. If somebody else can figure it out I’d be happy to post it.
Posted On
Oct 17, 2010Posted By
alliThanks Mark
It’s working now, but needs to click submit button again after the dialog closes ,
Posted On
Oct 22, 2010Posted By
alliHi Mark,
Quick Question
Can you control the position where the dialog pops out?
thanks
Posted On
Oct 22, 2010Posted By
Mark StangerYou can. There is a ‘moveTo’ function you can utilize to move the dialog to any x,y coordinate within the frame. The dialogs are all set up to naturally want to be centered when they are rendered so you have to set a callback function to set this positioning when the dialog finishes loading. You need to add the callback function before your ‘dialog.render’ call.
If I wanted to position the dialog in the top-left corner of my frame I could do this…
dialog.moveTo('0', '0');
});
Posted On
Nov 05, 2011Posted By
Mark StangerI just tested this again. It looks like ‘setLoadCallback’ is not available for standard dialogs, just quickforms.
Posted On
Jul 20, 2011Posted By
Michael BakerHi Mark,
This works great. I was able to get the order to submit when clicking the OK button by adding a few lines to the Client Script. Hope this helps others…
//Gets called if the 'OK' dialog button is clicked
//Make sure terms have been accepted
var terms = gel('accept_terms').value;
if(terms != 'true'){
//If terms are false stop submission
alert('Please accept the terms and conditions to continue your order.');
return false;
}
//If accept checkbox is true do this...
GlideDialogWindow.get().destroy(); //Close the dialog window
//g_form.setValue('myvar', true); //Optionally set the value of a variable or field indicating acceptance
// This will submit the order
gel("order_now").onclick = "";
var item_guid = gel("sysparm_item_guid");
if (item_guid) {
item_guid = item_guid.value;
}
g_cart.order(gel("sysparm_id").value, getQuantity(), item_guid);
}
function termsCancel(){
//Gets called if the 'Cancel' dialog button is clicked
window.location = 'catalog_home.do?sysparm_view=catalog_default'; //Redirect to catalog homepage
}
Posted On
Jul 20, 2011Posted By
Mark StangerAwesome! Thanks for sharing.
Posted On
Aug 09, 2011Posted By
LibbyThis is working wonderfully for us in IE & Firefox.. but will not work (dialog pop up stays up and proceeds to fill the screen) in both Chrome & Safari. Any ideas on that?
Posted On
Oct 06, 2011Posted By
Mark StangerI just found a fix for this problem. The UI page above uses dialog buttons that need to have a special setting so that the button acts as a regular button instead of trying to perform a form submission…and redirecting the user. Take a look at your ‘dialog_buttons’ line in your UI page and make sure that it has both an ‘ok_type’ and a ‘cancel_type’ of ‘button’ as shown here…
Posted On
Oct 26, 2011Posted By
Matt WascakI am getting this XML error……
This page contains the following errors:
error on line 1 at column 47: Namespace prefix g on ui_form is not defined
error on line 12 at column 40: Namespace prefix g on ui_checkbox is not defined
error on line 24 at column 69: Namespace prefix g on dialog_buttons_ok_cancel is not defined
Below is a rendering of the page up to the first error.
ENTER YOUR TERMS HERE… I accept these terms and conditions.
Posted On
Oct 26, 2011Posted By
Mark StangerI’m not sure why this would be necessary, but you can try wrapping the UI page script in tags like this…
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
EXISTING CODE HERE
</j:jelly>
Posted On
Nov 05, 2011Posted By
Shaun OelofsenHi Mark,
Quick Question
Is there an option to control where the user can be returned to if they choose No.
We have a requirement that the user be returned to the homepage, as a hard cancel.
Would we need to build up a URL? Are we able to embed that into the dialog function, much the same as the setCallBack.
Thanks
Posted On
Nov 05, 2011Posted By
Mark StangerGood idea. I’ve modified the solution above to include an optional ‘cancel_url’ preference that you can pass in when you render the dialog. The default cancel redirect just goes to the regular user homepage unless you pass in an override redirect URL of your choosing. Please let me know how this works for you.
See this page for details on passing parameters into a dialog…
http://www.servicenowguru.com/system-ui/glidedialogwindow-advanced-popups-ui-pages/
Posted On
Feb 06, 2012Posted By
TrinuHI Mark,
Is there any onsubmit client script for Confirmation message like: when user clicks on OK it going to URL(incident form),similarly when clicks on cancel stay in the same page?
Thanks in advance
Posted On
Feb 06, 2012Posted By
Mark StangerYes, you’ve got a client-side function that runs when you click the ‘OK’ button. In this case, it’s called ‘termsOK’. You could modify that button to redirect you to another location if you want.