How to implement dependancy injection for catalog client scripts and UI policy scripts
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-11-2016 07:18 AM
We have some catalog items where the UI scripts and UI policy scripts get rather complex, and often are repeated (copy-paste) when different variable scripts need to share functionality. Currently if we want to share a client side JS library with the catalog client script code block, we have to add the library to a macro, and add the macro to the variable list.
The macro approach for client script dependencies seems problematic for onload scripts, and I have found occurrences where catalog client scripts for onload events may begin executing before the script call in the macro finishes fetching the library...so our onload code fails if it is not wrapped in a setTimout with a 1/2 second delay. I really don't want to implement the full script in the macro. It seems like that is just shifting the problem. Client scripts should live in the client scripts tables...
How do other developers handle client side script dependencies in catalog client scripts and catalog UI policy scripts? How do you prevent that problem of the same code getting copy-pasted over and over when variable scripts need to share functionality?
I don't like setting a huge litany of scripts to load globally...and I would really like a convent way to inject client side script libraries into the catalog item form for use by these catalog client scripts that are attached to variables on the form.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-11-2016 07:45 AM
I follow rather a simple approach for sharing script and very rarely use Macro or UI script.
Create a onload catalog client script like below and have your custom function outside the onLoad() script.
function onLoad() {
//default
}
function getParmVal(name){
//shared function
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-11-2016 08:15 AM
This still leaves me with the problem of having to copy these common functions to separate onload events when the functionality is shared across many catalog items.
ex: I want to be able to create a UI script call My_Company_Library, and then any developer can add this library to the catalog items they are developing, and be able to call those class functions in client code.
I could use a global script for this if we only have a single file, but I foresee the list of library files growing (don't want to be maintaining 1 multi thousand line file), and I don't like the idea of strapping multiple big JS files onto every page the platform loads, that may only add functionality used by a few catalog items.
There are several ways I am aware to achieve this, but I think they are messy.
1. an onload script that does a document.write with a script tag and the source
2. a macro that injects the script tag.
I want to get away from copy - paste the same script over an over. Hoping some devs on here can point me to a more elegant solution that will be easy for our large team of developers to use.
In a perfect world, there would be a set of fields on the catalog UI script and UI policy scripts where I could define the dependencies that the platform would inject into the browser DOM before any catalog client events begin to fire on the form.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-11-2016 08:24 AM
I add such scripts in Variable sets and relate to catalogs that I needs. Not sure if that answers your question.
Create one time and reuse whenever needed.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-11-2016 10:25 AM
I know this is padantic, but I really want to keep scripts in script tables.
This is something I have been playing with this am, but I'm not sure how much I like the end result. Opinions on this approach are appreciated.
1. a UI script I want to include - lets call it "my_test_class", stored in the sys_ui_script table
2. a UI macro "inject_ui_script_into_client" - takes the parameter script_names
- the contents of this macro performs a glide record query against sys_ui_script where name IN jelly.jvar_script_names
- any matches to the glide record query, are dumped into <script> tags in the macro body
3. a UI macro "test_add_script_catalog_item" that calls inject_ui_script_into_client, and passes the comma delim list of scripts to read
4. a variable set with the macro "test_add_script_catalog_item" as a variable member
5. Add the variable set to your favorite catalog item
The result then looks like this on the form:
UI Macro: test_add_script_catalog_item
<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<g:macro_invoke macro="inject_ui_script_into_client" script_names="my_test_class" />
</j:jelly>
UI Macro: inject_ui_script_into_client
<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<!-- usage: <g:macro_invoke macro="inject_ui_script_into_client" script_names="[comma delimeted list of scripts to inject into client]" /> --><g:evaluate var="jvar_script_contents" jelly="true">
try{
var script_names = jelly.jvar_script_names.toString();
var script_contents_arr = [];
if (script_names.length){
var rec = new GlideRecord('sys_ui_script');
rec.addQuery('active',true);
rec.addQuery('name', 'IN', script_names);
rec.query();
while(rec.next()){
script_contents_arr.push(rec.getDisplayValue('script'));
}
}
}
catch(e){
gs.log('Error: '+e.message,'UI Macro - inject_ui_script_into_client');
}
script_contents_arr;
</g:evaluate>
<div style="display:none;" data-name="ui_scripts">
<j:forEach items="${jvar_script_contents}" var="jvar_script">
<!-- inject UI Script -->
<script>
${jvar_script}
</script>
</j:forEach>
</div>
</j:jelly>