Service Portal Catalog Item Menu Widget with Masonry JS
This article will explain how to create a simple widget which will display your current Service Catalog items in a menu leveraging MasonryJS.
-Tested on version: Istanbul-
First, let's start with creating and saving a widget: we can call it - "Mason Menu".
Now, let's add a dependency by scrolling down to the related lists at the bottom of the widget, which will point to a cdn (content delivery network) url, which can be found here at cdnjs.
Click new and name the dependency Masonry JS or a title of your choosing, and save the dependency.
Two related lists to add a js include and css include will appear on the bottom of the record.
Create a new js include, including the url you copied from cdnjs
After saving the js include, head back to the widget you created, and scroll down to the dependencies related list you
viewed previously, this time clicking 'edit'. Select masonry js from the slush bucket, and save the record.
Now that we've set up the dependency we needed, we can now structure out the widget within the widget editor, starting
with the server side script:
Server Script:
(function() {
data.categories = [];
var catalogsGR = new GlideRecord("sc_catalog");
catalogsGR.addActiveQuery();
catalogsGR.addQuery("title","Service Catalog");
catalogsGR.query();
if(catalogsGR.next()){
var categoriesGR = new GlideRecord("sc_category");
categoriesGR.addActiveQuery();
categoriesGR.addQuery("sc_catalog",catalogsGR.sys_id);
categoriesGR.orderBy("title");
categoriesGR.query();
while(categoriesGR.next()){
var category={};
category.name = categoriesGR.getDisplayValue("title");
category.sys_id = categoriesGR.getUniqueValue();
category.items=[];
var catalogItems = new GlideRecord("sc_cat_item");
catalogItems.addActiveQuery();
catalogItems.addQuery("sc_catalogs",catalogsGR.sys_id);
catalogItems.addQuery("category",categoriesGR.sys_id);
catalogItems.setLimit(5);
catalogItems.query();
while(catalogItems.next()){
var catalogItem={};
catalogItem.name = catalogItems.getValue("name");
catalogItem.sys_id=catalogItems.getUniqueValue();
category.items.push(catalogItem);
}
data.categories.push(category);
}
}
})();
Next lets set up the client script:
Client script:
function($scope) {
/* widget controller */
var c = this;
$scope.categories=c.data.categories; //assign the c.data.categories array from the server side script to the controller's $scope object
}
The html can be structured out like below:
<div class="container">
<a href="#" ng-click="showMenu()" class="menu btn btn-primary">Menu</a>
<div class="grid">
<div class="grid-item" ng-if="category.items.length!=0" ng-repeat="category in categories">
<div class="category-name">
{{category.name}}
</div>
<p class="text-muted" ng-repeat="item in category.items">
<a href="/sp?id=sc_cat_item&sys_id={{item.sys_id}}" target="_blank">{{item.name}}</a>
</p>
<p>
<a href="/sp?id=sc_category&sys_id={{category.sys_id}}" target="_blank" class="text-muted"><i class="fa fa-angle-right"></i> See all</a>
</p>
</div>
</div>
</div>
Let's set up a link function now where we can interact with the DOM and call the masonry js method: masonry()
Link Function
function(scope,element){
scope.showMenu=function(){
$(element[0]).closest(".container").find(".grid").fadeToggle().masonry(
{
// options
itemSelector: '.grid-item',
columnWidth: 160
});
}
}
Finally, add some css to define and control the width of both the grid and grid items, and provide some basic styling to the menu
.grid{
display: none;
max-height: 100%;
width: 100%;
padding:15px;
background:#fff;
border:thin solid rgba(0,0,0,.30);
border-radius:3px;
}
.grid-item {
width: 120px;
min-height: 20px;
}
.category-name{
font-weight:bold;
}
Open your menu by clicking the show menu button and view the results in your widget editor, also ry resizing your browser
to see the effect Masonry JS has on calculating available white space and placing your elements accordingly.
*** You can add options as needed, such as where to direct the 'See all' link in your own portal.***
***Please leave feedback and criticism, and point out anything I may have done incorrectly, as this will only make me a better developer.***
https://www.servicenow.com/community/developer-articles/service-portal-catalog-item-menu-widget-with-masonry-js/ta-p/2329872