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
shill
Mega Sage

Having issues with IE on this macro

I had implemented this macro more than a year ago (while on Aspen) and it works great.
The problem I have run into now is that it appears it is throwing an JS error on IE8.
As I am not sure when this started, it may have been when we switched to Berlin.
Until now, it didn't seem to create a problem.

Now it throws the error on both current items and a new item I just created with this macro.
The current items still work, but the new item will not respond to the checkout button at all.
If I take the macro off the form, the error goes away and the checkout button works fine.

I've added this macro to a demo instance and it gives the same error:
Message: 'null' is null or not an object

Any ideas??


dave_knight
ServiceNow Employee

Proposed Fix

The following should work with the new Berlin attachmentNumber class and the 'order_guide_item_attachment' macro defined in this thread (the attachment span class is now attachmentNumber_). We are using the new 'attachNumSpan' id that ebayona put in the Berlin fix for the macro itself...

function onSubmit() {
var og = $('sysparm_guide');
var rk = g_form.getValue('variables.risk');
var cont = 'yes';
if(og && rk == 1){

var amt = parseInt($('attachNumSpan').innerHTML);
if(amt == 0){
cont = 'no';
alert('You have specified a High Risk Request. Please attach the necessary server disposal forms.');
}

if(cont == 'no'){
$('order_guide_item_attachment').show();
return false;
}
}
}


felipe_barbosa
ServiceNow Employee

Solution Works, but Disappear when I remove all attachments

Hi everyone,

thanks soooooo much for all this information, I've been able to solve a lot of stuff on my current client.

While implementing this solution, I noticed that when I open the attachment pop-up, and I add a new attachment, I can see the new attachment on top of my order guide, but if I remove all attachments, the manage attachments link disappears.

Have you guys crossed this issue? How to solve it?

Thanks!


ss_hide.png


felipe_barbosa
ServiceNow Employee

Ok I just solved this issue and would like to share

Ok, I just solved this issue and I would like to take the opportunity to share the solution, which is pretty simple.

I opened the UI Page "attachment" and added one line of code into it's client script to detect if currently the user is on a form or not (in this case the important thing is not being in a form) and avoid the removal of the header after all attachments are gone.

Here is the changes:



if(g_form.getFormElement()) {
hideObject($("header_attachment_list_label"));

if (header_attachment)
header_attachment.style.height = "auto";
var line = $("header_attachment_line");
if (line) {
line.style.visibility = "hidden";
line.style.display = "none";
}
}


This first line "if(g_form.getFormElement()) {" was added on the line 487 of the code, and then I closed the bracket after the if(line) {...} (the latest bracket on my piece of code). With this modification, users can play around with attachments on a service catalog / order guide / record producer and still be able to open the attachment pop-up.

g_form.getFormElement() will return null in case the user is not viewing a service now form, like incident or task, and therefore, enclosed in a if check, will return false, validating the form/non-form case.

Cheers!


Ivan Martez
ServiceNow Employee

I ran into the same issue, so with the help of one of my co-workers, we got this to work.



function onLoad() {
var x = $$('img[src$="images/icons/attachment.gifx"]');
if (x &amp;&amp; x[0] &amp;&amp; x[0].remove) {
x[0].remove();
}
}


Unfortunately IE doesn't read the image path the way the code displays it "images/icons/attachment.gifx" it needs to entire path https://instance.service-now.com/images/icons/attachment.gifx. So, in the code above the $ after the "src" performs a match, when the match is made the rest of the code performs a check.

This will work for all browsers. I checked IE, FF, Chrome and Safari.


Mark Stanger
Giga Sage

Can we get this put in the core product?

45 replies and close to 4,000 page views. Seems like this is a pretty obvious need in ServiceNow. Any chance this can be put into the core product?


felipe_barbosa
ServiceNow Employee

I couldn't agree more

Nuff said, nice point.

Cheers!


Wendy Peterson
Tera Guru

Any idea which ACL is locking the attachment down

See my attachment - I didn't realize users couldn't attach it doesn't give them the browse button. Any idea which ACL unlocks this? TIA
attachment issue.PNG


Paramita
Mega Contributor

Facing the same issue

Hi,
I am facing the same issue.Are you able to solve the issue?


felipe_barbosa
ServiceNow Employee

Hi, this:

http://community.servicenow.com/blog/mb/where-order-guide-item-attachment-love#comment-38830

Let me know if this doesn't work for you...