Download as pdf or txt
Download as pdf or txt
You are on page 1of 34

Introduction Table of Contents

1.When the Caller is VIP set the incident urgency to High and alert a message 19.Group incidents by assigned_to and list only grouped records where the
This documentation presents 30 requirements and
assigned_to have more than two records
solutions that i have already published, it differs only in
2.Servicenow to servicnow Integration
the way the information is presented, each requirement
20.Group incidents by assigned_to and list only grouped records where the
with a script is illustrated with a diagram that you can
3.If the current incident is a child incident, add a info message with a clickable assigned_to have more than two records
visualize to better understand the code.
parent incident number.
21.If a user in his profile has position equal to agent, add ITIL role to the user.
A page is divided into three vertical sections, the first one
4.If the incident short description starts with the string 'Database', set database
contains the script, the second section contains
as category 22.Send a notification to the assigned to of an incident , whenever a custom
commentary on each line of the script, and the last
date field is superieur than the current date time.
section is where you can find the diagram.
5.onclick of a checkbox, open the list of active users in a new window
23.In the Incident form make the contact type field editable only for Assignment
6.Remove any attached files that are more than 15kb in incident and service group members.
Topics covered in this documentation are for servicenow
catalog request tables
beginners, you will learn the following : clients scripts, ui
24.Add 30 seconds to the current date/time and set this value to a custom date
macro, notifiaction, events, business rules, scheduled
7.Show an error message if the incident priority is critical time field from an UI Action.
script, ui actions , ui policy and integration.

8.For every hour automatically assign analytics_admin role for users who don't 25.Restrict Submission of an incident form when the description field is empty
For more information about the requirement read the
have analytics_admin or analytics_viewer role. and the state field value is 2 or 3.
content table and consult the next page to know How to
read this documentation.
26.Open a empty incident form from an problem record
9.In a problem record, hide Notes section when problem state is equal to '102'.
27. Hide an icon of the incident form.
10.Calculate elapsed time from the Incident record creation and add the result
to duration type field 28.Abort the submission of an incident in resolved state if the related change
record is not complete.
11.Extract IP address from the short description and assign the value to
another field called Caller IP. 29.When the CI changes in the incident, update subquently the description with
asset tag, and company name
12.Copy the entire journal from Change Request to a RITM when REQ Task is
updated. 30.In the story form, if the state is in progress and acceptance criteria is not
empty, make accetpance read only
13.Create a child incident from the Incident Form

14.Update the incident priority to critical with an UI Action

15.Create a Knowledge Base article using an UI macro

16.Update the incident priority to critical with an UI Action and save the record (
client and server side script )

17.If a user in his profile has position equal to non-agent, the user has ITIL role,
remove ITIL role for the user.

18.Create 2 problem task linked to one problem


queryselector
queryselector

'body'
'button'

How to Read this documentation 1.1 We begin by creating colors Array which contains the
following colors : red, green, blue, yellow, pink and purple.
This array to pick any color assign it to the body background
Array
"0":"red";
1.2 Then create a body object, for that use dom api and its "1":"green";
DOM
method such querySelector(), "n":"y"; DOM API
"5":"purple";

Javascript code At step 1.3 assign violet as a initial body background color,
1
note we use style.background property.
1.2 1.4
1.1 const colors = ['red', 'green', 'blue', 'yellow', 'pink', 1.1
1.2 'purple'];
1.4. create button object, the same way we have created the
const body = document.querySelector('body');
body object, use dom api and querySelector method in order
body.style.backgroundColor = 'violet';
to create it.

const button = document.querySelector('button');


colors array object body object button Object
button.addEventListener('click',
changeBackground);
1.5 use addEventListener method to listen to the click event
and call a changeBackground callback function on a click.
function changeBackground(){
const colorIndex= parseInt(Math.random()*colors.length);
body.style.backgroundColor = colors[colorIndex];
}
Callback Function : style.background addEventListener

1.7 use parseInt method to round the random colors index


number, the highest possible value is 5. as the length of the click changeBackground
array is 5

1.3
1.8 use the colorsIndex as an index for the colors Array and
assign array value to the background colors, the background
This first section contains a Javascript Code, this code color is determined based on the the random number
'violet'
here it is changing the body background color based on

the user action. when the user click on the button, it will
generated and will change based on the user clicks
1.5

change the background color.

1.1 , 1.2, 1.3 are not line numbers, they should be seen as
steps in our code.

For each step you have the comments in the the second
section,of the page, details explanation of what the code changeBackground Function
is exactly doing..

The third section contains the most interesting part which 1.7
is the diagram of the script, refer to the step number to parseInt colorIndex
see the code behaviour in the diagram.

for example step 1.1 we create an array which contains Math.random()*colors.length


some data, the dot for the step will only come afterwards.

Green arrow indicates in which direction the code is colors array object
executed, for example if you are assigning a value to
variable, the arrow will point in the direction of the
[colorIndex]
variable where you will actually store the value.

1.8
Thin black line indicates how one element it is reused
multiple times in the code. for example.the array object is
used first at step 1.1 when we are creating it, then at step
1.7 when we look for the arrays length and third time at
step 1.8 when we actually use it to assign a random body object
color to the body background element.

Properties of a class are italicized and api's are in a black


boxes.

Follow these guidelines for the rest of tthe documentation, style.background


some exceptions are made based on the requirement. for
example servicenow to servicenow integration do not have
any script.
01 OnChange Function
When the Caller is VIP set the incident urgency
to High and alert a message.

2.3 The first block will return an user object which we can
dotwalk to get values from the reference field, in our code
we are sending the caller as input for the reference field.
and aslo call a callback function. getReference
Use GlideForm API and getReference method to get
referencen field data, here it will the caller field, caller field
GlideForm API
is sent as parameter in the getReference method, the inputs
second parameter is the vip callback function which can
Caller : not vip use the user object to manipulate values.
Urgency : medium Caller ID vipFunction
Vip Callback function Callback Function
Reference field
2.4. Sending user Object as input in the callback function
User or system changes the caller
field value, and the caller is VIP 2.5. The user object is dotwalkable, we can check the vip
1
field is activated or not, use the if condition to check
user.vip is true if yes then we execute the code further.
2.3

Client script is written on 2.6. Setting the urgency field value to 1.


the caller field
2.7. Adding a info message, the caller of this incident is vip
2
and set the priority to high. Changing the value of urgency
function onChange(control, oldValue, newValue, isLoading, will automatically change the priority field value. Output : user Object
isTemplate)
{

if (isLoading || newValue === '') { return; }

2.3 var user = g_form.getReference('caller_id', vipFunction); 2.4

2.4 function vipFunction(user){


vipFunction callback Function

Input : user Object
2.5 if(user.vip=='true'){

2.6 g_form.setValue('urgency',1);
2.7 g_form.addInfoMessage
('the caller of this incident is vip, set the priority to High.');
} 2.5 if the user is a vip condition

}
} NO
YES

Caller : vip
Priority : High
3 Control is given to the user. no code is
executed for this
condition
GlideForm API
setValue

input : urgency =1

2.6 setting urgency value to 1

GlideForm API addInfoMessage

Message:"The caller..."

2.7 adding message


02
Section C, Navigate to outbound REST message and create A REST
ServiceNow to ServiceNow Integration
message. To know about what is REST, see the previous page. REST
has several methods, like GET, PUT, POST and DELETE, this is not be
confused with the profile scopes, for example you can send a
Even though there is a data repilcation application in servicenow request to GET user profile information but you may requird read
dedicated to integration inbetween servicenow intances, here is a profile info scope to actually receive profile information.
another way to integrate two servicenow instances.
In this exercise, we will use the following endpoint or url for the REST
There isn't only one particular grant flow to perfom integration in Message Endpoint :
servicenow, in this exercise, we will see how we can use OAuth Code
Grant flow to do the integration. https://instance_b_name/api/now/table/incident

Procedure: when you create the REST Message , it will automaitcally create the
default GET method (section C.1) with the same endpoint. Link the
The explanation below explains how to integrate servicenow Rest method the OAuth Profile. rename the GET method to Get
instance A and Instance B, instance a will have the following url : Incidents Info for more clarity.
https://instance_a_name/ and b https://instance_b_name/ (section C.2) click on Get OAuth Token link to execute the Auth 2.0 instance B
Grant flow, servicenow doesnt shows you anywhere in their app the Servicenow API
Section A represents servicenow OAuth Provider Application, grant flow as described in the diagram here, you can take a
that's the application which will provide access to servicenow API'S, screenshot of the browser when the user in step 2, to see the code
once you have configured the OAuth Provider, you will get the in the url.
credentials which will be further used in the grant flow for A positive green message will be shown once you have the token,
communication. Look at the step 1, to see how it is being used, an Test your integration by calling the method Section C.1 to get JSON
authorization request is sent from Instance A to B with the response of a list of incidents. Token have an expiration date, some
credentials. "Client id and Client Secret" scripting knowledge is often required to extend the token life.
Servicenow OAuth provider application
A
Begin first by creating, servicenow OAuth Provider, in Instance B
navigate to OAuth, under Application registry and create OAuth API
APPS 6
Form details
for external clients and note down the Client ID and Client Secret, Client id and secrect Access
Also insert the redirect URL : Redirect url: Servicenow
https://instance_a_name/oauth_redirect_do https://instance_a_name/oauth_redirect_do API with the
Token
The redirect url is used in order to send a Code from Instance B to A,
see step 2 and 3, a user approves instance A to access instance B,
after credentials verification, instance B sends a code to the
redirection url.


4 Request OAuth token
Section B represents servicenow OAuth 2.0 Application, and 2 User approval in exchange of Code
here you provide the credentials provided OAuth Provider App from
instance B, also the authoriszation url and token url.
Authorization Request With
https://instance_b_name/oauth_auth.do for Authorization URL. 5 Token Received
Client ID- Secret- Scope From
https://instance_b_name/oauth_token.do for Token URL.
instance A to Instance B 1 3 Code Received in
Redirect URL
Authorization url is used to send authorize request in the step 1 and
Token url is used to exchange a code for a token, step 4.
In the instance A Navigate to OAuth and under the application
registry and create an OAuth Application (click on Connect to
theThird party OAuth Provider), by default when you create an
OAuth 2.0 client application, it will aslo create a OAuth entity profile Servicenow OAuth 2.0 Application
section B.1 Which contains the application profile information and B
as well the oauth profile scopes (Section B.2) APPS Form details : REST Message
OAuth authorization and token C
endpoints. REST
Scopes tells you what kind of operation you can do with the provider Form details :
Client id and secrect from Instance B
application, for example create, read records, in this exercise there https://instance_b_name/api/now/table/incident
application. abccd and ******
will be no scopes added but if you integrate servicenow with a third
Type : Authorization code
party application such as Salesforce or Linkedin, detais of scopes will
be provided by the service provider.

rest method
B.1 C.1
OAuth Profile

C.2 OAuth Token Related linl

B.2 OAuth Profile Scopes

instance A
03
If the current incident is a child incident, onLoad Function
add a info message with a clickable parent
incident number
.3 The first block will return an parent object which we can dotwalk to
get values from the reference field, in our code we are sending the
parent_incident field as input for the reference field. and also call a
callback function.
Use GlideForm API and getReference method to get referencen field
getReference
data, here it will the parent incident field, this fielld is sent as GlideForm API
parameter in the getReference method, the second parameter is the
parentFunct callback function which can use the user object to inputs
User clicks on a manipulate values.
incident record
Parent Incident : INC0125148
1
parent_incident parentFunc
Reference field Callback Function
ParentFunct Callback function
Data loads from
the database 3.2. Sending parent Object as input in the callback function
2

3.3 Getting the parent field value, the incident number and storing p
2.3
variable.
Client script execution and loading
data from the database.
3 3.4. Checking if p is not empty, if yes then executing the next code
function onLoad()
{ Output : parent Object
3.5. Adding a message which contains the parent incident number ,
3.1 var parent = g_form.getReference('parent_incident',parentFunc); sys id , we use the parent object to get the sys_id and number like
parent.sys_id and parent.number

function parentFunc(parent){ 3.2 parent object used as input


3.2 in the call back function

var p = g_form.getValue('parent_incident');
3.3
if (p!=""){

parentFunc CallBack Function


is a
child
3.4
g_form.addInfoMessage('This incident of '+'<a Input : parent object
3.5 href=\'https://dev64478.service-now.com/nav_to.do?
uri=incident.do?sys_id='+parent.sys_id+'\'
target=\'_blank\'>'+parent.number +'</a>');

}
}
}

getting the parent


incident number

Message : This is a child incident of INC0125148 3.3 output : p


4 Control is given to the user. GlideForm API getValue object

parent_incident
3.4 if p is different than empty

YES NO

addInfoMessage
GlideForm API 3.5
Adding Message.

Message:"This is..." no code is


executed for this
condition
04
If the incident short description starts
with the string 'Database', set database onChange Function
as category

NO no code is

executed for
this condition

2.3 Use GlideForm API and its method getValue to get the
short_description value, and store the value in the short output : position
2.5 if position is

Short Description: Email server is down description variable object


Category : Network equal to 0

User or system changes the short 2.4. Use Search Method, to check if the value database is Searching database value in the
description to -> Database, email server is available in the short description, store the return value in 2.4 short description and returning the
1 the position variable result to position variable.
down

2.5 if the position is equal to 0, it means, the database


2.3
Client script execution value is available at the first position in the short
description variable. getValue output : short_desc
Client script is written on the short GlideForm API getting the short object
description field description value
2 YES
short_decription
function onChange(control, oldValue, newValue, 2.6 Setting database as value for the category field.
isLoading, isTemplate)
{

if (isLoading || newValue === '') {return;} search

2.3 var short_desc= g_form.getValue('short_description');


2.4 var position = short_desc.search('Database'); 'Database'

2.5 if (position==0){
2.6 setting database
as value for the
2.6 g_form.setValue('category','database'); category field

Short Description : Database, email server is down


3 Category : Database
Control is given to the user.

setValue
GlideForm API

category : database
05

onclick of a checkbox, open the list of active


users in a new window

onChange Function
NO
2.2 We begin by checking if the checkbox is checked, if is ₹

checked it will be true otherwise false, but it is boolean


1 User checks a custom check box value, we need to convert it to string and check with the
true literal string.if the condition is true, we execute the
code further newValue is equal to
true CONDITION

Client script is written on the check 2.3 creating an url for listing a list of active users
2.2
box field and for incident table
2 The newValue is boolean variable as it is a
2.4 use GlideNavigation API and its method open in orde
check box. converting to string and
function onChange(control, oldValue, newValue, to open an URL
comparing the newValue to true string
isLoading, isTemplate) { YES

if (isLoading || newValue === '') {return;}

2.2 if (newValue.toString() == 'true') {


2.3 creating the url for listing
2.3 var url = "sys_user_list.do?sysparm_query=active=true"; active users
URL : List active users
2.4 g_navigation.open(url, "_blank");

}
} opening the url in a new
window 2.4
Opens a new window with the list of
3 active users

open
GlideNavigationV3 API

url _blank
06
Remove any attached files that are more
than 15kb in incident and service catalog
request tables

3.1 Creating a GlideRecord Object of sys_attachement


table and storing the value in grSys variable. 3.1

3.2 Adding a query, lookups only records where table Output : grsys
creating grsys a
name is incident and sc_request GlideRecord API new
gliderecord object
User creates a
3.3 quering with grSys Object
record.
1 sys_attachement table

3.4 for each record found in the query check if the


byte size is superiror than 15kb

Database is addQuery
2 updated.
3.5 if yes, then delete the record with deleteRecord
method. table in incident
and sc_request

After Business
Rule Execution
3
3.2 adding specific queries
3.1 var grsys = new GlideRecord("sys_attachment");
3.2 grsys.addQuery("table_name", "IN"
,"incident,sc_request");
3.3 grsys.query();
Output : grsys with
the added query
3.4 while(grsys.next()) { 3.6 delete the record
3.5 if(parseInt(grsys.size_bytes) >15000)
3.6 grsys.deleteRecord();

}
Query
DeleteRecord
All attachements with the
size more than 15kb are
4 deleted from the incident
and service request table. 3.3 quering the table

Output : grsys object


3.4 While LOOP

Output : grsys object next

if YES if the size of the record


is more than 15 k.
Record 1 Record x Record 10
3.5

grsys.size_bytes>15k

if NO

no code is
executed for this
condition
07
Show an error message if the incident
priority is critical

User opens an
incident record
1 Priority : critical

onLoad Function

Loading data from the


2 database.

The client script is written for the


incident table. 3.1.Use GlideForm API and its method getValue for getting
3 the priority field value and assign the value priorityValue
function onLoad(){ field .
3.1
3.1 var priorityValue = g_form.getValue('priority');

Output :priorityValue
getValue
3.2 create the if Condition to check if the priority is critical GlideForm API object
getting the priority
value
priority
3.2 if(priorityValue=='1'){ 3.3. If the priority Value is 1 , it means it is critical, add an
3.3 g_form.addErrorMessage('this incident priority is error messge : "This incident priority is critical"
critical'); 3.2 priority is equal to 1.
} CONDITION
}

Message : this incident priority is critical'


4 Control is given to the user.
3.3 YES NO
GlideForm API addErrorMessage

Adding error message :


priority "this incident priority is
critical" no code is
executed for this
condition
08
For every hour automatically assign
analytics_admin role for users who don't have
analytics_admin or analytics_viewer role.
The goal is to assign a role to specific users within a time period, write the
script which will check the conditions, make sure that these users don't
have analytics_admin or analytics_viewer role, use the the script in a
scheduled script and schedule it for every hour.

Code explanation Part 1

Scheduled script
for every hour

3.3 create grUser a GlideRecord Object of the sys_user


giveRole(); 3.3
table.
Output : gruser
function giveRole(){
GlideRecord API creating gruser
3.4 query with the object new
gliderecord object
try{
3.3 var gruser = new GlideRecord("sys_user");
3.5 in a while loop, for each user record, 3.6 create a
3.4 gruser.query(); sys_user table
GlideRecord Objec of sys_user_has_role table
Query

3.5 while(gruser.next()) { 3.7 Filter the result by adding a query, the query is : role
name should be analytics admin and analytics viewer
3.6 var grurole = new GlideRecord("sys_user_has_role"); set limit to one to return only one record 3.4 quering the table
grurole.addQuery("user", gruser.sys_id);
3.7
grurole.addQuery("role.name",
"IN","analytics_admin,analytics_viewer");
3.8 grurole.setLimit(1); 3.5 While LOOP
grurole.query();
Output : gruser next
GlideRecord API new object

if(!grurole.next()){ sys_user_has role table


Record 1 Record x Record 10
grurole.initialize();
grurole.user = gruser.sys_id; 3.6
grurole.setDisplayValue("role", "analytics_admin"); Output :
grurole.insert(); grurole
creating grurole
}
gliderecord object
}
}
catch(ex){ gs.info(ex);}
}
addQuery

filter user sys id


and roles

3.7 adding query

Output : grurole
with the added
query

setLimit

3.8 returni one record


08
For every hour automatically assign
analytics_admin role for users who don't have
analytics_admin or analytics_viewer role.
The goal is to assign a role to specific users within a time period, write the
script which will check the conditions, make sure that these users don't
have analytics_admin or analytics_viewer role, use the the script in a
scheduled script and schedule it for every hour.

Code explanation Part 2


Output : grurole
with the added
3.8 query to get the result query

Scheduled script 3.9 if there is a user without the role defined in the query,
for every hour execute further the code
query
giveRole(); 3.10 initialize grurole object, setvalue for the grurole user
field with 3.11 grUser object sys_id and 3.12 setdispay value
function giveRole(){ for role field the value analytics admin, and 3.13 insert a
record, we have added a new role to the user is
3.8 quering the table
try{ sys_user_has_role table. if YES
var gruser = new GlideRecord("sys_user");
gruser.query(); if we find a user without
if NO 3.9
thoes roles in the
no code is condition
executed for this
condition
while(gruser.next()) {
Output : grurole
initialize
var grurole = new GlideRecord("sys_user_has_role"); query result
grurole.addQuery("user", gruser.sys_id);
grurole.addQuery("role.name",
"IN","analytics_admin,analytics_viewer");
grurole.setLimit(1);
3.8 grurole.query(); 3.10 initializing

3.9 if(!grurole.next()){ grurole.user gruser.sys_id


3.10 grurole.initialize();
3.11 grurole.user = gruser.sys_id;
3.12 grurole.setDisplayValue("role", "analytics_admin");
3.13 grurole.insert();
}
3.11 assigning user value from gruser object
}
}
catch(ex){ gs.info(ex);}
}

grurole setDisplayValue

3.12 setting admin role as value

grurole insert

3.13 inserting a new record


09
In a problem record, hide Notes section when
problem state is equal to '102'.
The onchange client script will if there is a new value for state field, here if
the database value is equal to 102, it wil hide the note changing section
display value to false, this client script will also check the state value while
the form is loading. 3.1 checking with a if condition is the form is loading or When the data is loading from the database, check if
not if yes 3.1 The form is loading problem state is equal is 102, if yes then hide the notes
1.2 use glideform api and getValue method in the second CONDITION section by changing display value to false
condition to get the state value and compare it to 102.

if YES
1.3 if the second condition is true, use glideform api and
setsectionDisplay method to hide the section.
3.2 If state is 102

3.4 now we want to do the same logic describle previously if NO


when we there is a new value equal to 102 meaning
if YES
where there is a change. if the contion newValue equal to no code is
102 is true, executed for this
condition 3.3 hiding notes section
.3.5 hide the section with glideform api and
setSectionDisplay method. if NO

User opens a return


1 3.6 else make it visiblle using the glideform api and
problem record setSectionDisplay value, the notes value will be false.

Data loads from setSectionDisplay


the database GlideForm API
2

notes : false
Client script execution
The client script is written
for the problem table.
3

function onChange(control, oldValue, newValue, isLoading,


isTemplate) {
3.1 if (isLoading) {
3.2 if(g_form.getValue('state') == '102'){ When user or system changes the database value of the
3.3 g_form.setSectionDisplay('notes', false); state field to 102, hide the notes section by changing
} the display value to false else show the section.
return;
} 3.4 newValue is 102
CONDITION
3.4 if (newValue == "102") {
3.5 g_form.setSectionDisplay('notes', false);
if YES
} else {
3.6 g_form.setSectionDisplay('notes', true);
} 3.6 showing notes section 3.5 hiding notes section
}

else

state is 102
4 notes section is hiddent
GlideForm API setSectionDisplay GlideForm API setSectionDisplay

notes : true notes : false


10
Calculate elapsed time from the Incident
record creation and add the result to
duration type field
Add a duration type field to the incident form, the field will
contain the elapsed time and by default the database name for
this field is u_duration

2.1 Creating the start date GlideDateTime Object and


storing the value in the start variable start
Database.
1 2.1
2.2 Creating the stop date GlideDateTime Object and
storing the value in the end variable
GlideDateTime API new
Display business
rule 2.3 Use GlideDateTime API and it s substract method
stop
2 to substract start and stop, storing then the value in
(function executeRule(current, previous /*null when the duration field
2.2
async*/) {

2.4 Assigning the duration field value to


2.1 var start = new GlideDateTime(current.sys_created_on);
2.2
current.duration field value
var stop = new GlideDateTime();

2.3 var duration = GlideDateTime.subtract(start,stop);


GlideDateTime API substract
2.4 current.u_duration=duration;

})(current, previous); start stop

User creates a record. 2.3


3 duration : Days 75 Hours 00 09 49

duration
Object

2.4

current.duration
11
Extract IP address from the short description and
assign the value to another field called Caller IP.

Incidents gets created with the following short description (sample):

[RESOLVED] CafeAddressCafeXYZ- ABCD - MNOP 96.233.79.10 is


unavailable by SMTP

1 User updates an incident record.


short description : [RESOLVED] CafeAddressCafeXYZ- ABCD -
MNOP 96.233.79.10 is unavailable by SMTP
Caller ip : 2.1 create r variable which will contains a regex
expressions

current getValue a
2.2 Get the short description field value, with the current 2.2
Before Business Rule Execution on the
incident table object, current to the incident table. getting the short
2 short_description description value

var r = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/;
3.2 use match method and give as inputs the regex value
availabe in r variable, store the result in the t variable.

2.2 var a = current.getValue('short_description'); match


2.3 2.4 use current object again, to set value for the ip address
var t = a.match(r);
2.4
field, the value in the index 0 of t array object.
current.setValue('ip_address_field', t[0]); r variable with a
regex string as value

Caller ip field value :


3 96.233.79.10

2.3 using match method


current setValue to retrive only
numbers
4
t[0]
T

Database is updated.

2.4 setting the result to


ip address field

ip_address_field
12
Copy the entire journal from Change Request
to a RITM when REQ Task is updated.

Code Part 1 : Explanation

3.1 create a grcr a GlideRecord Object of change request 3.1


table Output : grcr
creating grcr a
GlideRecord API new
gliderecord object
3.2 add query with the current parent field value, which is
User updates the change request record
REQ task
1 Change Request table
3.3 query with grCr object

addQuery
Database is 3.4 If there is a record with the query mentioned
updated. before execute the code further
2 current parent
sys_id
After Business
Rule Execution
3

(function executeRule(current, previous /*null 3.2 adding specific queries


when async*/) {

3.1 var grcr = new GlideRecord('change_request');


3.2 grcr.addQuery('sys_id', current.parent);
3.3 grcr.query(); Output : grcr
with the added
query
3.4 if(grcr.next()){
var notes = grcr.work_notes.getJournalEntry(-1);
var grsc = new GlideRecord('sc_req_item');
grsc.addQuery('request', current.sys_id);
grsc.query(); Query

if (grsc.next()){
grsc.work_notes = notes;
grsc.update();
}
} 3.3 quering the table

})(current, previous);

Output : grcr
next
4 Worknotes is updated in current change
the ritm record record

if there is a
3.4 record condition

no code is
if NO
executed for this
condition

if YES
12
Copy the entire journal from Change Request
to a RITM when REQ Task is updated.

Code Part 2 : Explanation

User updates
REQ task 3.4 If there is a record with the query mentioned before,
1 if YES if YES
execute the code further
updating notes to
grsc.work_notes
3.5 use getJournalEntry Method and grcr object to get
Database is the entire worknotes from the change request , store the Output : notes gbsc.work_notes
value into the notes variable. current.work_notes getJournalEntry 3.5 3.10
updated.
2
storing change record
After Business worknotes values to
Rule Execution 3.6 creating grSc a GlideRecord Object of sc_req_item notes variable
3 table

(function executeRule(current, previous /*null


3.6
when async*/) { Output : grsc
3.7 add query witt the current sys_id value and creating grsc a
var grcr = new GlideRecord('change_request'); request field for finding the related request ritm. GlideRecord API new
grcr.addQuery('sys_id', current.parent); gliderecord object
grcr.query(); 3.8 query the table 3.11 grsc updates
service catalog table

3.4 if(grcr.next()){ 3.9 if there is a RITM, 3.10 assign notes value to


3.5 var notes = grcr.work_notes.getJournalEntry(-1); grsc.worknotes which ritm worknotes field and
3.6 var grsc = new GlideRecord('sc_req_item'); 3.11 update
3.7 grsc.addQuery('request', current.sys_id); addQuery
grsc.query();
request is current
if (grsc.next()){ sys_id
grsc.work_notes = notes;
grsc.update();
}
}
3.7 adding specific queries

})(current, previous);

Output : grsc
4 Worknotes is updated in with the added
the ritm record query

if NO
Query 3.9 no code is
if there is a executed for this
record condition condition

3.8 quering the table

Output : grcr
next
RITM record of the
current task
13
Create a child incident from the Incident Form
Create an ui action in the incident table, give it a name, choose
type form button and select show insert and update.

2.1 creating grInc a GlideRecord Object of the incident


table
create a child incident

2.2 current represent the incident table and current.short new


GlideRecord API
description, is the current incident record short description,
store this value in the grInc object more spefically in the the
Parent Incident short_description variable. incident
use the same analogie to store caller id, sys_id and also
User clicks on work notes, respectively in step 2.3, 2.4, 2.5
the ui action
1
2.6 initialize the grInc object and 2.7 insert a new record
2.1
UI Action Script
The ui action script is written on the
incident table
2
2.2 current.short_descri
2.1 var grinc = new GlideRecord(’incident’); short_description ption

2.2 rinc.short_description=current.short_description;
g
2.3 grinc.caller_id=current.caller_id;

2.4 grinc.parent_incident = current.sys_id;

2.5 grinc.work_notes = ‘this incident is copied from’+ current.number;

2.3
2.6 rinc.initialize();
g caller_id caller id
Output : grinc
2.7 grinc.insert();


action.setRedirectURL(grinc);
 2.4
parent incident current.sys_id

Parent Incident
3
worknotes 2.5
current.number

Child Incident

initialize

2.6 initialize

insert

2.7 insert record


14
Update the incident priority to critical with
an UI Action
Create an ui action in the incident table, give it a name,
choose type form button and select show insert and update
also client, create function setPriority() ;add this function to
the Onclick field.

3.1 setting values to


3.1. Use GlideForm API and setValue method to set urgency field
urgency field value to 1
Update Incident Priority

3.2. Use GlideForm API and setValue method to set


impact field value to 1
setValue
User clicks on GlideForm API
1 the ui action
input urgency =1

2 calling the onClick function


setPriority function
setting values to
3.2 impact field

The ui action script is written on


the incident table
setValue
3 GlideForm API
function setPriority(){
input impact=1
3.1 g_form.setValue(’urgency’,1);
3.2 g_form.setValue(’impact’,1);

Urgency: High
Impact : High
Priority ; High
4
15
Create a Knowledge Base article using an UI
macro
UI macros are scripted components in servicenow that admins can add to the user
interface.

The ui macro here is button visible to the caller reference create gliderecord
field, to make it visible, all you need to do is to create a ui object of kb_knowledge
macro, note down the ui macro database name and table
The ui macro name is create_kb, which is navigate to incident caller reference dictionary field and
the following line : Attributes : GlideRecord API new
a database name, mention it in the 1.1
attribute field, attribute is a dictionary ref_contributions=create_kb Output : grkb initialize
field of caller reference field.
This will automatically create a ui macro button, now add kb_knowledge
more functionality to it, here we would like to create a
Caller Reference Field dictionary fields form knowledge base article by retrieving some info form the
Attributes : ref_contributions=create_kb incident form.

1.1 Begin by creating xml and jelly tag.


UI Macro script :
kb_create 1.2 Create html button and create kbCreate function
which will be called on a click.
1.2
Output :
2 1 1.3 inside the script tag, create the kb create function getValue grkb.short_description
<?xml version="1.0" encoding="utf-8" ?> GlideRecord API
<j:jelly trim="false" xmlns:j="jelly:core"
1.4 Create a GlideRecord Object of kb_knowledge table,
xmlns:g="glide" xmlns:j2="null" xmlns:g2="null"> getting short the
short_description description storing into
1.5 initialize the object
grkb object
1.6 Assign object a value for the object short description,
<button id="button" onclick="kbCreate();">Post
it will be the incident short description,
Knowledge</button>
Incident form 1.7 for text field, assign incident description
Caller Reference Field create kb ui
<script>
macro button available next to 1.8 Insert a record
the field
function kbCreate(){
getValue
1.1 var grkb= new GlideRecord('kb_knowledge'); 1.3
Output : grkb.text
grkb.initialize(); GlideRecord API
1.2 grkb.short_description =
g_form.getValue('incident.short_description'); description
1.3 grkb.text=g_form.getValue('incident.description'); getting the description storing into
grkb.insert(); grkb object
1.4
}

</script>

</j:jelly> insert
Output : grkb

1.4 inserting a new


record
16
Update the incident priority to critical with an UI
Action and save the record ( client and server side
script )
Create an ui action in the incident table, give it a name, choose
type form button and select show insert and update also client,
create function updateToPriority() add this function to the Onclick
field.

In this script the ui action is called twice, first when


the user clicks the ui action and for the second time, 3.1 calling the ui action
the code itself call the ui action from the script

Update Incident Priority


3.1 Calling the ui action from the script, with the method
gsftSubmit which gets as input the update_to-priority, the
3.2 if type of window is


database name for the ui action undefined
User clicks on
the ui action
1
3.2 if the type of window is undefined, we can call a server
side code otherwise not NO YES
2 calling the onClick function
updateToPriority

3.3 In the function set priority, 3.4 setting the impact and no code is
3.5 urgency value to 1. 3.6 in the end update the current executed for this
record condition
UI Action client / server Script 3.3 Calling setPriority Function
The ui action script is written on the incident table
3
function updateToPriority()
{
alert(’you are going to change the priority’);
3.1 gsftSubmit(null,g_form.getFormElement(),’update_to_priority’);
} current.urgency =1

3.2 if ( typeof window==”undefined”) 3.4 setting urgency value to 1


3.3
setPriority();
function setPriority()
{
current.impact=1
3.4 current.urgency=‘1’;
3.5 current.impact =’1’;
3.6 current.update();
3.5 setting impact value to 1

action.setRedirectURL(current); current.update
}

3.6 update values

4 Urgency: High
Impact : High
Priority ; High
17
If a user in his profile has position equal to non-
agent, the user has ITIL role, remove ITIL role for
the user.
This requirement is a verification of field values and action taken based on the
value, therefore, write an after business rule, for updates and insert. This br will 1.1 Create a GlideRecord Object of sys_user_has_role
have in condition : postion is equal to non-agent, run a script which will look for the table, the objet is grrole.
current user and verify if the user has ITIL role, if yes it will remove the role by
deleting the record. 1.2 Add query, the query is the user is the current user sys grrole
GlideRecord API new
id an d role is itil.
1.1

1.3 Query with grrole object creating grrole a


sys_user_has_role gliderecord object
1.4 if there is record with the condition mentioned
previoulsy,

1.5 delete the record addQuery

itil role and current


user

user updates or
1 creates a record 1.2 adding encoded
query

Data data is updated 1.5 delete record


2
Output : grrole
with the added
NO After Business Rule query
CONDITION delete
Position is non-agent

YES
After Business Rule query
execution in the user table
3
grrole
(function executeRule(current, previous /*null when async*/) {
1.3 quering the table
3.1 var grrole = new GlideRecord('sys_user_has_role');
3.2 grrole.addQuery('user', current.sys_id); if YES
grrole.addQuery('role.name', 'itil');
3.3 grrole.query();

3.4 if(grrole.next()){
3.5 grrole.deleteRecord(); 1.4 if there is a record grrole next
}

})(current, previous);
if NO
no code is
executed for this
4 itil role record is deleted condition
18
Create 2 problem task linked to one problem
Create an ui action in the problem table, give it a name,
choose type form button and select show insert and update.

des Array
create 2 problem task
2.1 Begin by creating an Array which contains two values
test 1 and test 2. the name of the array is des. Test 1 Test 2

2.2 Run a for loop for the array's length, for each iteration
User clicks on execture the upcoming steps.
1 the ui action
2.1

2.3 Create a grPb a GlideRecord object of problem_task


UI Action Script, it is table
written on the problem
table for LOOP 2.2 running for loop ,for the
2.4 current represents the problem table, current.short- length of the array
2
description is the current problem table record short
2.1 var des =[“Test 1”, “Test 2”];
description , store that value in the grPb object, exactly in
I=0 I=1
grPb.description.
2.2 or(var i=0;i<des.length;i++){
f
2.3 var grpb = new GlideRecord(’problem_task’);
2.5 Do the same thing for problem sys id and 2.6 assign
grpb.initialize();
the value general to problem type.

2.7.Insert the record.


2.3 grpb.short_description=des[i];
2.4 grpb.description=current.short_description;
As the loop will run twice, it will insert two records.
2.5 grpb.problem = current.sys_id;
2.6 grpb.problem_type=’General’;
2.7 grpb.insert();

} new
GlideForm API
Output : grpb
2.3
action.setRedirectURL(current);
Problem

3 Problem record

short_description
des[i]
2.4

Task 1 Task 2

problem current.sys_id
2.5

problem type general


2.6

insert
2.7
19
Group incidents by assigned_to and list
only grouped records where the
assigned_to have more than two records
Test the script in background script to see the result

1.1 Use GlideAggregate API to create agg object of


incident table.

new agg
1.2 Use addAggregate method to aggregate the result GlideAggregate API
1.1
by assigned it will return the number of records
Background script assigned for each user.
incident table
1.3 query with agg object to have those results
1.1 var agg = new GlideAggregate('incident');
1.2 agg.addAggregate('COUNT', 'assigned_to'); 1.4 create an empty array.
addAggregate
1.3 agg.query();
1.5 create a while loop, in the loop as a first step, get the
1.4 var arr = [];
agrregated count of incidents and 1.6 store in the
incidentCount variable.
COUNT Assigned_to
1.7 now compare the incidentCount value to 2, if it is
more than two, than means, that particular use have
1.5 while (agg.next()) {
more than two records.
1.6 var incidentCount = agg.getAggregate('COUNT', 'assigned_to');
count aggregate agg
object ,for example abel 1.2
tuter 2 records, frank
norman 3 records

Output : agg
with
1.7 if (incidentCount > 2) { aggregated
result
var inc = new GlideRecord('incident');
inc.addEncodedQuery('assigned_to=' + agg.assigned_to);
inc.query();
query
while (inc.next())
arr.push(inc.sys_id.toString());
}}

return arr;

1.3 quering the table

count aggregate agg object ,for 1.4 defining empty array


example abel tuter 2 records,
frank norman 3 records

1.5 While LOOP

Output : agg Output : agg object next


storing the incident with
count for each user aggregated
result
Abel Tuter Frank Norman Billie Sea
Incident Count
1.6
query
1.7
if the incident count
is more than 2
if NO

if YES
no code is
executed for this
condition
20
Group incidents by assigned_to and list
only grouped records where the
assigned_to have more than two records
Test the script in background script to see the result

At this point, we have a user who have more than two if YES
records, and now we write the code to group all incidents
belongs to the user and put it an array, we have already
created an empty array, we will use that.
Background script

1.8. we remain in the if condition, create a grInc a


var agg = new GlideAggregate('incident'); GlideReocrd object of the incident table, 1.9 add a GlideRecord API new grinc
agg.addAggregate('COUNT', 'assigned_to'); encoded query , filter by assigned to , use agg object the 1.8
agg.query(); get the assigned to value. creating grinc a
var arr = [];
incident table gliderecord object
1.10 query.

1.11. create a while loop, for each incdent found in the


loop, push the sys id to the arr empty array. the while addEncodequery
while (agg.next()) { loop will end once we are with alll filter incidents.
var incidentCount = agg.getAggregate('COUNT', 'assigned_to');
it seems like we have many while loops and a condition.
we can group all incidents which belongs to an user and 'assigned_to=' +
push the result into an empty array without writing the agg.assigned_to
first loop, but the first loop is necessary to make sure that
the user has more two records, therefore we need it,
check that info in a condition and trigger the second
1.9 adding encoded
if (incidentCount > 2) { while loop for grouping records.
query
1.8 var grinc = new GlideRecord('incident');
1.9 grinc.addEncodedQuery('assigned_to=' + agg.assigned_to);
1.10 grinc.query(); Output : agg
with the added
1.11 while (grinc.next())
returning 1.13 query
1.12 arr.push(grinc.sys_id.toString());
the array
}}
arr
1.13 return arr;
query

pushing 1.12
incident sysid
into the array
1.10 quering the table

push
1.11 While LOOP

grinc.sys_id next
Output : grinc object

Abel Tuter Frank Norman Billy Ewards

arr
21
If a user in his profile has position equal to agent,
add ITIL role to the user.
This requirement is a verification of field values and action taken based
on the value, therefore, write an after business rule, for updates and
insert. This br will have in condition : postion is equal to agent, run a
script which will get the current user and add itil role.

1.1 Create a GlideRecord Object of sys_user_has_role


table, the objet is role.

1.2 initialize the role object


GlideRecord API new
1.3 use role object to assign a value for the user field,
assign the current user sys id
sys_user_has_role
1.4 use rold object to assign itil sys id to role field

user updates or 1.5 insert a new record.


1 creates a record Creating role a gliderecord
3.1
object of sys_user_has_role
table, Output role variable.
Data data is
2 updated
Output : role object

After Business
Rule Condition :
3.5
Position is agent
Inserting the record in the
sys_user_has_role table
NO YES

After Business Rule


execution in the user table user role insert
3 initialize

(function executeRule(current, previous /*null


when async*/) { 3.2
3.3 3.4
var role = new GlideRecord('sys_user_has_role'); Initilalizing the role object Assigning the ITIL sys_id to
3.1 Assigning the current sys_id
role.initialize(); before an insert. the role field.
3.2 to the user field.
3.3 role.user = current.sys_id;
3.4 role.role= "282bf1fac6112285017366cb5f867469"; itil sys id "282fb..."
role.insert(); current.sys_id
3.5
})(current, previous);

4
itil role record is created
22
Send a notification to the assigned to of an
incident , whenever a custom date field is
superieur than the current date time.
Register an trigger.notification event for the incident table, create as well a
beta notification triggerd when the event is fired, then write a scheduled
script to query the incident table for meeting the condition above, if there are 1.1 create grInc a GlideRecord object of incident table,
records overdue 30, 60, 90 days , generate overdue reminder from the script,
which will automaticatlly send the notifications. 1.2 add query to retrieve only active records Output : grInc

GlideRecord API new


1.3 query the table

1.4 for each record found , get the reached date time
numerical value and compare ti to current date time incident
numerical value, if it it is superior , execute the code
further.
addActiveQuery

Scheduled script 1.5 queue an event which is already created, mention the
for every hour assigned to with the grInc object in the paremeter, so the
notification will be sent to that person.
1
var grInc = new GlideRecord('incident');
grInc.addActiveQuery();
grInc.query();
while(grInc.next()){
Output : grInc
if(new GlideDateTime(gr.reached_date).getNumericValue()
object with added
>= new GlideDateTime().getNumericValue()){
query

gs.eventQueue('trigger.sendoverdueremindernotification'
,grInc,grInc.assigned_to.toString());
}} eventQueue
GlideSystem API
query

notification grInc object assigned to 1.3 quering the table

notification
3
send overdue reminder
is executed

1.5
While LOOP

Output : grInc object next


if YES

if reached time is >


than current time
record 1 record 2 record 3
1.7

if NO

no code is
executed for this
condition
23
In the Incident form make the contact type
field editable only for Assignment group
members.
For this requirement use a scratchpad object which will have a boolean
value either true or false, if the current user is not member of that particular
assignment group it will be false, based on the scratchpad value, modify
field attributes. write a display Business Rule on Insert and update, which
will have a scratchpad object, the value it will be true if the logged in user is
member of the assignement group, use the scratchpad on the client side, if
the value is false, meaning the user is not member then you set the field read
only, the opposite condition will let the user access the field.

3.1 Create a Display Business Rule for the incident


table, use the script which checks if the current user
is part the assignment group and stores the value in
a scratchpad object g_scratchpad.isMember
GlideSystem API getUser isMemberOf g_scratchpad isMember
1 User opens a incident record

current assignement
group

Data loads from the database


2

A Display Business Rule can instantiate g_scratchpad object which Server Code
can be passed to the client side and it can be used in client script.
3
(function executeRule(current, previous /*null when 1.1 Create a onLoad Client script on the incident table
use the scratchpad object in a onload client script Client Code
async*/) {
if the value is false, meaning the user is not part of the
group, make the contact type read only with setReadOnly
3.1 g_scratchpad.isMember = 1.1 g_scratchpad object value is
method
gs.getUser().isMemberOf(current.assignment_group.toString() false CONDITION ,meaing the
); user is not part of the group

})(current, previous);
if YES

1.2 making contact type field


Client script execution readonly
The client script is written for the incident table.
if NO
1
function onLoad(){

1.1 if(g_scratchpad.isMember.toString() == 'false'){


1.2 g_form.setReadOnly('contact_type', true);
// add few more fields as per your requirement GlideForm API setReadOnly
}

} contact type : true

contact type is editable


2 for group members
24
Add 30 seconds to the current date/time
and set this value to a custom date time
field from an UI Action.
create an ui action, it will have a script which will get
the current time, add 30 seconds and then the new
value to the custom date field, the script is called
whenever you click on the ui action.

2.1 create a glidedatetime object, the object is gdt

2.1 user addSeconds method, add 30 second the current


date time object GlideDateTime API new

2.3 assign this value to the current purblished date filed

2.4 update the record and redirect the user to the current
record

Add 30 seconds

2.1 Creating gdt a glideDateTime


object. to get the current time

User clicks on
1 the ui action

gdt
UI Action Script, it is written on
the incident table
2

2.1 var gdt = new GlideDateTime();

2.2 gdt.addSecondsUTC(30); addSeconds(30)

2.3 current.published_date= gdt;

2.4 current.update();

action.setRedirectURL(current);
2.2 adding 30 seconds to gdt
assign the date value to datetime object
a custom date field

Incident record 2.3


current. published date gdt
published date : 2022-12-05 : 15:25:15
3

2.4 updating the


current record

current. update
25
Restrict Submission of an incident form when the
description field is empty and the state field value is 2
or 3.

Write a before business rule and the script to abort the action, this br is written
on insert and update.

User updates an incident record. User updates an incident User updates an incident
Short Descrption : ''Server is slow" record. record.
State :1 Short Description : Short Description :
State : 2 State : 3
c a b

NO YES

Before Business Rule Conditions :


Short Description is EMPTY
State is 2 or 3

CONDITIONS a and b are meet.

(function executeRule(current, previous /*null when


Before Business Rule async*/) {
Execution on the This code adds an error message and
incident table setAbortAction, abort the current
2 gs.addErrorMessage('Your Message Here');
submission whether it is an insert or an
current.setAbortAction(true);
update.
})(current, previous);

Incident record.
Short Description :
State : 2

Database
26
Open a empty incident form from an
problem record
Create an ui action in problem table, give it a name, choose
type form button, and select show insert and update.

Open new Incident

User clicks on
1 the ui action

2
var url = ‘/incident.do?sys_id=-1’;
creating the url for opening a new
action.setRedirectURL(url);
incident, -1 is the sys id value for a new
incident form, and redircting the user to
that form.
UI Action Script
The ui action script is written
on the problem table

New Incident
3 Form
27
Hide an icon of the incident form.
There is an icon of the form for more options, hide that icon
when the form loads.

1 User opens an
incident record

Data loads from


2 the database

Client script execution


The client script is written
for the incident table.
3
function onLoad() {
Get the HTML element of the icon and store it in a
var icon=document.getElementById("toggleMoreOptions"); variable. Change css display style to none.
icon.style.display='none';
}

4 3 dotted icon is not visible


28
Abort the submission of an incident
in resolved state if the related
change record is not complete.

Related Change Record User updates a


State : In progress incident record.
1

NO YES

1. Change request field is NOT EMPTY.


Do not execute the Before 2. Incident state changes to RESOLVED.
Business Rule when the 3. Change request state is NOT CLOSED
conditions are not meet Above we have all the conditions that we
need to set for this business rule

DotWalk to change request state field, type


change and select change request=>change
request fields, then select state field.

2 Before Business Rule Execution on the incident table


Action : Abort record submission with
a html message, the associated change
is not resolved.

Database is not updated.


29
When the CI changes in the incident,
update subquently the description
with asset tag, and company name

Configuration Item : *BUD-IBM

User or system changes the CI


field value, and the CI is now
1 *BOW-IBM

Client script is written on the Configuration Item field


2
function onChange(control, oldValue, newValue,
isLoading, isTemplate)
/* Instantiate CIUpdates Script Include with GlideAjax,
{ var CIUpdates = Class.create();
add getCIdetails method and cmdb ci field value as
parameters. CIUpdates.prototype = Object.extendsObject(AbstractAjaxProcessor, {
if (isLoading || newValue === '') { return; }
Use getXML method to make a server side call /* Create grci a GlideRecord object of
CIUpdates().getCIdetails() along with cmdb ci value as cmbd_ci_computer and query
an input parameter. getCIDetails:function(){ cmbd_ci_computer table with the cmbd_ci
var ga = new GlideAjax('CIUpdates'); var grci = new GlideRecord('cmdb_ci_computer');
The result will be returned to showDetails callback value, */
ga.addParam('sysparm_name', 'getCIDetails'); grci.addQuery('sys_id',this.getParameter('sysparm_ci'));
funcion. */
ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci')); grci.query();
ga.getXML(showDetails);

with sysparm_ci we get the cmbd


if (grci.next()){
Asynchronous Call ci value.
var details = "asset tag:" + grci.asset_tag + "\n" + "company:" +
Client / Server script execution /* If there is a cmdb record, assign tag field
grci.company.name;
value and company name field value to the
return details;
details variable, return details values. */
}
},

function showDetails(response) { type: 'CIUpdates'

var answer = });


response.responseXML.documentElement.getAttribute("ans /* response variable holds the result in XML format,
wer"); results are available in the answer Attribute, which will
g_form.setValue('description', answer); retrieve and assign those values to the description field.
*/
}

3
Configuration Item : *BOW-IBM
Description : 'Asset tag : P1000230 company : ACME North America
30
In the story form, if the state is in UI policy :,Make Acceptance
Crtiteria read only.
UI policy Action : On the acceptance
criteria field.Make Read only is True,
progress and acceptance criteria is visible and Mandatory are leave
only.
not empty, make accetpance read
If there are mulitple ui policies for
only the same field, change the order to
solve this issue.
When to Apply : When STATE is in
Work In Progress AND
Acceptance Criteria IS NOT
EMPTY

onload global

reverse

onload, global and reverse is


false are checked

You might also like