MB26
ServiceNow Employee

find_real_file.png
So where is the Order Guide Item Attachment love? On a normal catalog item you are able to attach files, however when using that same catalog item within an order guide, there is no attachment icon. Hopefully I did not miss some functionality somewhere because here is a solution I came up with for you to enable attachments on Order Guides Items.

I have created a UI Macro that can be added to any catalog item (or variable set). This UI Macro first checks to see if the catalog item is coming from an order guide. If it is, it will display the UI Macro, if not it won't, which will allow the default catalog item attachment icon to be used as normal.
Here is what it looks like.
find_real_file.png


When you click on the "Manage Attachements" you get the standard attachment popup.
find_real_file.png

All you need to do is to create a UI Macro with the following code. The add this macro as a variable into any catalog item or variable set. This UI Macro does NOT take into account attachment roles property as the standard form attachment use does. This is more of a "lite" version.



<?xml version="1.0" encoding="utf-8"?>
<j:jelly trim="true" xmlns:g="glide" xmlns:g2="null" xmlns:j="jelly:core" xmlns:j2="null">

<g:evaluate>
var rprf = RP.getReferringURL();
var og = rprf.indexOf('sysparm_guide') >= 0;
</g:evaluate>

<j:if test="${og}">
<div id="order_guide_item_attachment">
<div id="header_attachment" style="display: block; width: 100%; overflow: hidden;">
<div id="header_attachment_size_checker">
<ul id="header_attachment_list">
<li>
<a id="header_attachment_list_link" href='#' class="attachment" onclick="saveCatAttachment(gel('sysparm_cart_edit').value, 'sc_cart_item'); return false;">
<img title="Attachments..." src="images/icons/attachment.gifx" height="16" border="0" width="16" /> $[sp]
${gs.getMessage('Manage Attachments')} (<span class="attachmentNumber"></span>):
</a>
</li>
<script>
updateAttachmentCount(gel('sysparm_cart_edit').value);
if($('header_attachment'))
$('header_attachment').style.height = '20px';
</script>

</ul>
</div>
</div>
</div>
</j:if>

<script>
//This initializes the default action. Do you want attachments to be displayed or not onload. To show, change the .show() to .hide()
$('order_guide_item_attachment').show();
</script>
</j:jelly>


Show/Hide this Macro


What if you wanted to only show this macro in certain scenarios. The ones I had implements was, if someone selected a high risk, or slected a checkbox.
A simple client script can be created. Evaluate your condition like...


var risk = g_form.getValue('risk');
if(risk == 1){
//Here is the one-liner to show or hide the attachment macro.
$('order_guide_item_attachment').show();
//Here is the hide
$('order_guide_item_attachment').hide();
}

The UI Macro is wrappered in a DIV with the ID of "order_guide_item_attachment" making it easy to use a prototypejs selector and hide or show it.

Bonus - Confirm someone has attached something


How can you make sure that someone has uploaded an attachment? I have used an onsubmit script I use to check this. I don't want someone to select a high risk value and then just submit the order guide item without any attachment.



function onSubmit() {
var og = $('sysparm_guide');
var rk = g_form.getValue('variables.risk');
var cont = 'yes';
if(og &amp;&amp; rk == 1){
$$('#header_attachment_list span[class="attachmentNumber"]').each(function(item){
var amt = item.innerHTML;
if(amt == 0){
cont = 'no';
alert('You have specified a High Risk Request. Please attach the necessary forms.');
}
});
if(cont == 'no'){
$('order_guide_item_attachment').show();
return false;
}
}
}


Bonus, Bonus -- Popup the attachment dialog whenever


If you want to open the attachment dialog after someone clicks a checkbox use the following code.


//some sort of onChange client script with a condition statement
if(checkbox == true){
//This function will open the window to attach files to the order guide item.
saveCatAttachment(gel('sysparm_cart_edit').value, 'sc_cart_item');
}


NOTE: CALGARY UPDATE


It appears that in Calgary some additional Access Controls (ACL) were added which prevents the end user from using this functionality. I have found that the attachment popup (UI Page) checks to see if the user can write to the record. In this case the user is actually being displayed a record from the "Item" (sc_cart_item) table. Thus the attachment UI Page validates if the user can write to this particular record. In this scenario the end user (Requester) does not have write permissions to this "cart item" record resulting in a blank (no buttons etc.) on the attachment UI Page.



SOLUTION:

In order to get around this you will need to add in two ACLs on the "sc_cart_item" table. We don't want to open this table wide up to everyone so here is what I suggest.


Create a READ ACL on the sc_cart_item table so the logged in user can only read their cart items. You will need to dot walk on the condition to get to the user field.

Type: record

Operation: read

Name: Item [sc_cart_item] --> -- None --

Condition: Cart.User --> IS --> javascript:gs.getUserID()


Create a WRITE ACL on the sc_cart_item table so the logged in user can only write to their cart items. You will need to dot walk on the condition to get to the user field.

Type: record

Operation: write

Name: Item [sc_cart_item] --> -- None --

Condition: Cart.User --> IS --> javascript:gs.getUserID()



This should allow anyone logged in to see and write to only their cart items. In reality the end user should not know that they can read or write to these records as it is all behind the scenes, but from a security perspective this is how it works.
All in all this is obviously modifying the OOB functionality, in terms of security. So this solution is an AS IS, USE AT YOUR OWN RISK solution. The functionality could potentially change from one version to another, as we have seen. So take all of this into account when using this solution.



Again this UI Macro will run only if the item is coming from an Order Guide. Your normal catalog items will continue to use the standard attachment process.

Enjoy.
<script></script>
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-22945975-1']);
_gaq.push(['_trackPageview']);

(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();

61 Comments
ebayona
Kilo Contributor

Need to change the class attribute for the span

In Berlin there is some code that changed and is using a different class name for the span element where the number of attachments gets displayed. The line where the span element needs to be changes is the following:



${gs.getMessage('Manage Attachments')} (<span class="attachmentNumber"></span>):

So now instead of the span having a class of attachmentNumber it needs to be attachmentNumber_(sys_id) where the sys_id is the one that gets sent to the updateAttachmentCount() function.
In order to do this I added an id to the span element and then used javascript to change the class attribute.


...
${gs.getMessage('Manage Attachments')} (<span id="attachNumSpan" class=""></span>):


</a>

</li>


<script type="text/javascript">
document.getElementById('attachNumSpan').setAttribute('class','attachmentNumber_'+gel("sysparm_cart_edit").value);


updateAttachmentCount(gel('sysparm_cart_edit').value);


if($('header_attachment'))


$('header_attachment').style.height = '20px';


</script>
...




Julia7
Mega Contributor

work only for admin

On my end with Berlin the old way (coded for Aspen) still works for admins only on the normal Service-catalog but, for any other users I have the atthced pop up where it says "None" inside. On the CMS the "Manage Attachments" completly desapear from each of the forms...

any suggestions?


Attachments.PNG


MB26
ServiceNow Employee

Check out the comment #31151
and it's replies. I think what you are referring to is the same. The other came down to ACLs.


Julia7
Mega Contributor

it works thanks


it was a mix of ACL and this comment Mon, 01/14/2013 - 11:57 — ebayona that make it work on the regular Service-catalog
I still can not see it on my CMS I will check the other comments thanks


MB26
ServiceNow Employee

Glad you got it figured out. For CMS attachments see
http://community.servicenow.com/blog/mb/what-no-attachments-cms-portal-catalog-item
Hopefully this will help.


Julia7
Mega Contributor

Hey MB 🙂

Thanks for your help at KN13! It was not your code, your code was good haha!
FYI: Works fine on Explorer 9.


MB26
ServiceNow Employee

I'm glad to hear it worked for you.


Wendy Peterson
Tera Guru

Sorry if this is a dumb question but I get creating the UI Macro but what i don't get how do you add it as a variable or a variable set. I see the option of "Macro" but how do you get it to call the UI Macro listed above inside of that variable that you create?


Julia7
Mega Contributor

in the application menu "System UI" you need to create a New Macro by choosing the module "UI Macros"
NAME: attachment_order_guide
Description: This UI Macro is used in Service Catalog by Order Guides to add an attachment icon on the item
this UI is used by a variable Set called " Attachments"
XML Code: <?xml version="1.0" encoding="utf-8"?>



var rprf = RP.getReferringURL();
var og = rprf.indexOf('sysparm_guide') >= 0;












  • $[sp]

    ...
    ${gs.getMessage('Manage Attachments')} (😞







  • document.getElementById('attachNumSpan').setAttribute('class','attachmentNumber_'+gel("sysparm_cart_edit").value);


    updateAttachmentCount(gel('sysparm_cart_edit').value);


    if($('header_attachment'))


    $('header_attachment').style.height = '20px';











//This initializes the default action. Do you want attachments to be displayed or not onload. To show, change the .show() to .hide()
$('order_guide_item_attachment').show();



After this you need to create a Variable Set or varible but I suggest a Variable set that way you can re-use it anytime needed
NAME: Attachments ORder Guide
Order: 0
Layout 1 Column Wide
Description: This UI Macro first checks to see if the catalog item is coming from an order guide. If it is, it will display the UI Macro, if not it won't, which will allow the default catalog item attachment icon to be used as normal.

Add a varible in there called the same are your Macro
Name: attachment_order_guide
Type: Macro
Variable set: Attachment Order Guide

if you are using CMS with Order Guide create a Client Script (This script is for Berlin not Aspen)
NAME:Attachment Order Guide
Applies to: A Catalog Item
TYpe: onLoad
Catalog item: your catalog item where this script will be applied
Script: function onLoad() {

if(!$("form_header")){
$("header_attachment").setStyle({height: "1.4em"});
$("header_attachment_list_label").setStyle({visibility: "visible", display: "block" });
}

}



that's it


Wendy Peterson
Tera Guru

I must be missing something

Thanks for your help. I followed your instructions but it still doesn't work. We have Berlin Patch 4. Is there some property i need to adjust to make this to work? I created a UI Macro with the name the same and added the code
[code]
<?xml version="1.0" encoding="utf-8"?>



var rprf = RP.getReferringURL();
var og = rprf.indexOf('sysparm_guide') >= 0;












  • $[sp]
    ${gs.getMessage('Manage Attachments')} ():







  • document.getElementById('attachNumSpan').setAttribute('class','attachmentNumber_'+gel("sysparm_cart_edit").value);


    updateAttachmentCount(gel('sysparm_cart_edit').value);


    if($('header_attachment'))


    $('header_attachment').style.height = '20px';











//This initializes the default action. Do you want attachments to be displayed or not onload. To show, change the .show() to .hide()
$('order_guide_item_attachment').show();



[/code/

Then I created the Variable Set like you said see attachment. But when I go to the Order guide and then to the Item that i added the variable set to I don't see anything about attachments just a blank box so I must be doing something wrong?


variable.PNG
additional access.PNG