
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎10-07-2011 03:06 PM
So I needed the Process Flow formatter to show a Flow Formatter dynamically and since some of the java code was not available I updated the UI Macro "process_flow" to do what I needed. Including it all here for those who mite be interested in such an enhancement.
Add the field "u_view_condition" with a type of "conditions" to the sys_process_flow table.
Here is the new code for the UI Macro "process_flow"
<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<link rel="stylesheet" type="text/css" href="styles/process_flow_formatter.cssx"></link>
<tr>
<td colspan="2" width="100%" nowrap="true">
<div>
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<g2:flow_formatter var="jvar_flows" table="$[__ref__.getRecordClass()]" current="$[__ref__]" />
<g2:evaluate var="jvar_table" jelly="true">
var afterCurrent = false;
var tableText = "";
var show = [];
var label = "";
var gr = new GlideRecord("sys_process_flow");
gr.addQuery("table", current.sys_class_name);
gr.orderBy("order");
gr.query();
while(gr.next()){
//If you do not do this you get the last value of gr.label in all elements, do not know why exactly.
label = new String(gr.label);
//Check to see if the record should be displayed. If so add element to array.
//Array info
// show[] -> Each element is a flow formatter record to display
// show[][0] -> Label for the flow formatter to display.
// show[][1] -> state: used to indicate the state of the flow formatter.
// Possible values: past, current, future
// show[][2] -> next_state: used to indicate the state of the next flow formatter.
// Possible values: past, current, future
if(Packages.com.glide.script.Filter.checkRecord(current, gr.u_view_condition)){
show.push(new Array(3));
show[show.length - 1][0] = label;
//Check if this is the current flow that should be green/selected.
if(Packages.com.glide.script.Filter.checkRecord(current, gr.condition)){
show[show.length - 1][1] = "current";
show[show.length - 1][2] = "future";
//Once current is found update the previous element
if(show.length > 1){
show[show.length - 2][2] = "current";
}
afterCurrent = true;
} else {
if(afterCurrent){
show[show.length - 1][1] = "future";
show[show.length - 1][2] = "future";
} else {
show[show.length - 1][1] = "past";
show[show.length - 1][2] = "past";
}
}
}
}
//clear the next_state element so that the process flow has a pointer at the end.
show[show.length - 1][2] = "";
if(!afterCurrent){
show[show.length - 1][1] = "future";
}
//Build the table
for(i in show){
tableText += '<td class="process_flow ' + show<i>[1] + '" title="' + show<i>[0] + '">';
tableText += show<i>[0];
tableText += '</td>';
tableText += '<td width="16" height="100%">';
tableText += ' <img style="height: 24px; width: 21px; margin: 0px; padding: 0px;" src="images/chevron_' + show<i>[1] + '_' + show<i>[2] + '.pngx" />';
tableText += '</td>';
}
tableText;
</g2:evaluate>
$[jvar_table]
</tr>
</table>
</div>
</td>
</tr>
</j:jelly>
Solved! Go to Solution.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-04-2014 09:16 AM
For those of you how would like to use the updated version that I put on ServiceNow Share with out having to load the update set here is the updated UI Macro code.
<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<link rel="stylesheet" type="text/css" href="styles/process_flow_formatter.cssx"></link>
<tr>
<td colspan="2" width="100%" nowrap="true">
<div>
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<g2:flow_formatter var="jvar_flows" table="$[__ref__.getRecordClass()]" current="$[__ref__]" />
<g2:evaluate var="jvar_elements" jelly="true" object="true">
var afterCurrent = false;
var tableText = '';
var show = [];
var label = "";
var gr = new GlideRecord("sys_process_flow");
gr.addQuery("table", current.sys_class_name);
gr.orderBy("order");
gr.query();
while(gr.next()){
//Check to see if the record should be displayed. If so add element to array.
//Array info
// show[] -> Each element is a flow formatter record to display
// show[].label -> Label for the flow formatter to display.
// show[].state -> used to indicate the state of the flow formatter.
// Possible values: past, current, future
// show[].next_state -> used to indicate the state of the next flow formatter.
// Possible values: past, current, future
if(GlideFilter.checkRecord(current, gr.u_view_condition)){
var item = new Object();
item.label = gr.getValue("label");
//Check if this is the current flow that should be green/selected.
if(GlideFilter.checkRecord(current, gr.condition)){
item.state = "current";
item.next_state = "future";
//Once current is found update the previous element
if(show.length > 1){
show[show.length - 1].next_state = "current";
}
afterCurrent = true;
} else {
if(afterCurrent){
item.state = "future";
item.next_state = "future";
} else {
item.state = "past";
item.next_state = "past";
}
}
show.push(item);
}
}
//clear the next_state element so that the process flow has a pointer at the end.
show[show.length - 1].next_state = "";
if(!afterCurrent){
show[show.length - 1].state = "future";
}
show;
</g2:evaluate>
<j2:forEach items="$[jvar_elements]" var="jvar_el">
<g2:evaluate jelly="true">
var label = jelly.jvar_el.label;
var state = jelly.jvar_el.state;
var next_state = jelly.jvar_el.next_state;
</g2:evaluate>
<td nowrap="nowrap" class="process_flow $[state]" title="$[label]">
$[label]
</td>
<td width="16" height="100%">
<img style="height: 24px; width: 21px; margin: 0px; padding: 0px;" src="images/chevron_$[state]_$[next_state].pngx" />
</td>
</j2:forEach>
</tr>
</table>
</div>
</td>
</tr>
</j:jelly>
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎11-13-2012 08:13 AM
Okay, I guess I need more help. I'm new to Jelly, although I am a very experienced Programmer. So, I thought I would first just start out by simplifying it all to see if I could figure out what was going on. I started just by using the smallest example possible:
<div>
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td>
<g2:evaluate var="jvar_table" jelly="true">
var textTable = "<b>Hello World</b>";
textTable;
</g2:evaluate>
$[jvar_table]
</td>
</tr>
</table>
</div>
The output of this was literally:
<b>Hello World</b>
Now, if I removed the g2:evaluate and just did the following:
<div>
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td>
<b>Hello World</b>
</td>
</tr>
</table>
</div>
This actually showed Hello World
So, I guess my equestion is why is when i'm passing the HTML as a variable output to the g2:evaluator, why is it then not executing the HTML whenever it writes it to the webpage? If there is a setting that I need to change on the server, do you know the setting?
I played around with the data on the following page, but couldn't get anything there to help:
http://wiki.servicenow.com/index.php?title=How_to_Escape_in_Jelly
Thanks!
Gary Opela

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎11-13-2012 08:45 AM
The reason that I put everything into a var and output the var is because I was having a great deal of difficulty understanding how to deal with an Array in Jelly. Dealing with it in the JavaScript was much easier.
This is how my system properties are set, at least the ones I seam to remember impacting this.
glide.ui.escape_all_script= false
glide.ui.escape_text = false
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎11-13-2012 08:56 AM
Awesome +rep for you.
glide.ui.escape_text was True for me, I set it to False and now the Hello World properly renders rather than showing the HTML code. I'll put the macro back like you have it and then test and update this thread.
Thanks a ton for this Drew, i was looking at how these flows work, and though, you know, i need to be able to tell the macro dynamically which of the blocks i want to show. Then I found your thread that did exactly what I wanted.
This will be used on Change to help my customers understand which approvals have been accomplished, on which approval it is currently waiting, and which approvals it will need in the future. Not all CIs have the same approvals required, so I didn't want to show approvals which would not be required, as this would cause confusion.
Gary Opela
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎11-13-2012 08:58 AM
Okay, it works like a charm now! This should be included out of the box (cloud whatever)....

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎11-13-2012 09:04 AM
Keep in mind that there are some security concerns with that property. Do a search on it in the wiki just to make sure you are making an informed decision on the possible issues.