Update 'SC Categories' widget so that mouse hover display the content of the Category 'description'
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎04-12-2023 11:49 PM
We have a requirement to update the 'SC Categories' widget in ServiceNow Service Portal so that the mouse 'hover over' action displays the content of the Category 'description' field and not the name of the category.
How this can be achievable? I tried following the below link but that does not actually helped:
Pasting below the HTML and Server Script in our system.
HTML:
<section aria-label="${Service Catalog categories}">
<div ng-if="c.data.catalogSelectorArr.length > 2" ng-class="{'hidden-xs' : hideCategoryWidgetInXS}" class="panel panel-{{::options.color}} category-widget no-border">
<div class="panel-primary panel-heading">
<h2 class="h4 panel-title">
{{::data.messages.catalogTitle}}
</h2>
</div>
<ul class="list-group category-list" role="list" aria-label="{{::data.messages.catalogTitle}}">
<li role="listitem" class="list-group-item text-overflow-ellipsis" ng-include="'catalog-template.html'"/>
</ul>
</div>
<script type="text/ng-template" id="catalog-template.html">
<select class="sc-basic-select" aria-label="{{::data.messages.catalogTitle}}" ng-change="changeCatalog(selectedCatalog)" sn-focus="true" ng-model="selectedCatalog" ng-options="catalog.displayValue for catalog in c.data.catalogSelectorArr track by catalog.value"/>
</script>
<div ng-class="{'hidden-xs' : hideCategoryWidgetInXS}" class="panel panel-{{::options.color}} category-widget no-border">
<div class="panel-heading">
<h2 class="h4 panel-title">
<span class="pull-right visible-xs" >
<i class="fa fa-times-circle" ng-click="hideBrowseCategory()" aria-label="${Show Items}" tabindex="0"/>
</span>
<span ng-if="::options.glyph">
<fa name="{{::options.glyph}}" />
</span>{{::options.title}}</h2>
</div>
<ul class="list-group category-list" role="tablist" aria-label="${Categories}">
<li role="presentation"
class="list-group-item text-overflow-ellipsis"
ng-if="category.totalCount > 0" ng-include="'category-template.html'"
ng-repeat="category in data.categoriesList | limitTo: data.limit track by category.sys_id">
</li>
</ul>
<div class="panel-footer text-center" ng-if="data.showMore">
<a href="javascript:void(0)" role="button" class="text-center" ng-click="loadMore()" >{{::data.showMoreMsg}}</a>
<div class="text-muted text-center">
{{data.more_msg}}
</div>
</div>
</div>
<script type="text/ng-template" id="category-template.html">
<div ng-click="categorySelected(category)"
ng-keydown="handleKeyPressOnCategory($event, category)"
sn-focus="category.sys_id == data.categoryId"
ng-enabled="category.totalCount > 0"
id="tab_{{::category.sys_id}}"
role="tab"
aria-selected ="{{category.sys_id == data.categoryId}}"
aria-controls="tabpanel_{{::category.sys_id}}"
ng-class="{true: 'text-active', false: ''}[category.sys_id == data.categoryId]"
tabindex="0" class="group-item group-item-primary pointer" data-ng-attr-style="padding-left:{{getCategoryPadding(category.level + 1)}}">
<i ng-if="::category.subcategories.length > 0 && category.totalCount > category.count"
class="l-h-1_6x pull-left fa collapse-icon"
ng-class="{true: 'fa-minus-square-o', false: 'fa-plus-square-o'}[category.showChildren]"
aria-label="{{category.showChildren? '${collapse category} ' + category.title : '${expand category} ' + category.title}}"
ng-click="displayChildren($event, category)"/></i>
<span class="badge pull-right pointer" ng-if="options.omit_badges != 'true' && data.largeDataSet != 'true'">{{::category.totalCount}}</span>
<span class="block text-overflow-ellipsis category"
id="{{::category.sys_id}}"
uib-tooltip="{{::category.title}} {{::category.catalog_tooltip}}"
tooltip-placement="top"
tooltip-enable="!isTouchDevice()"
tooltip-append-to-body="true">
{{::category.title}}
<span class="sr-only">${items}</span>
</span>
</div>
<ul class="list-group sub-category-list list-bg-primary" role="tablist" aria-label="{{category.title}} ${subcategories}" ng-if="category.showChildren && category.subcategories.length > 0" ng-class="{true: 'no-indent', false: ''}[category.level > 2]">
<li role="presentation"
class="list-group-item text-overflow-ellipsis"
ng-include="'category-template.html'"
ng-repeat="category in category.subcategories track by category.sys_id"
ng-if="category.totalCount > 0">
</li>
</ul>
</script>
</section>
Server Script:
(function() {
var catalog_id = $sp.getParameter("catalog_id") ? $sp.getParameter("catalog_id") + "" : "-1";
var catalogSelectorArr = [{value: "-1", displayValue: gs.getMessage("All")}];
data.selectedCatalogIndex = catalog_id == -1 ? 0 : -1;
var catalogIDs = $sp.getCatalogs().value + "";
var catalogs = catalogIDs.split(",");
var isCatalogAccessibleViaPortal = catalog_id == -1 ? true : false;
catalogs.forEach(function(catalogSysId) {
if (catalog_id == catalogSysId) {
isCatalogAccessibleViaPortal = true;
}
});
var counter = 1;
catalogs.forEach(function(catalogSysId) {
var catalog = new sn_sc.Catalog(catalogSysId);
var catalogObj = {value: catalogSysId, displayValue: catalog.getTitle()};
if (catalog.canView()) {
if (catalog_id === catalogSysId) {
data.selectedCatalogIndex = counter;
}
catalogSelectorArr.push(catalogObj);
counter++;
}
});
data.catalogSelectorArr = catalogSelectorArr;
data.catalog_id = catalog_id ? catalog_id : "-1";
data.showMoreMsg = gs.getMessage("Show More");
data.pleaseWait = gs.getMessage("Please wait... fetching categories");
var categoryId = JSUtil.nil($sp.getParameter('sys_id')) ? "" : $sp.getParameter('sys_id') + "";
data.categoryId = categoryId;
var catalogIDs = (data.catalog_id && data.catalog_id !== "-1") ? data.catalog_id : $sp.getCatalogs().value + "";
var viewType = '';
var checkCanView = false;
var showBadge = false;
var nestedLayout = (options.category_layout !== "Flat");
var dynamicCategory = false;
var catalogArr = catalogIDs.split(",");
var catalogs = [];
catalogArr.forEach(function(catalogSysId) {
var catalog = new sn_sc.Catalog(catalogSysId);
if (catalog.canView()) {
catalogs.push(catalogSysId);
}
});
data.categoryId = categoryId;
var msg = data.messages = {};
msg.expanded = gs.getMessage("Expanded");
msg.collapsed = gs.getMessage("Collapsed");
msg.catalogTitle = options.catalog_title? gs.getMessage(options.catalog_title) : gs.getMessage('Catalogs');
data.largeDataSet = gs.getProperty("glide.sc.largeSet.optimization.enable", "false");
if (data.largeDataSet == 'true')
nestedLayout = false;
if (options.page) {
var page = new GlideRecord('sp_page');
if (page.get(options.page))
data.page = page.id + '';
}
checkCanView = String(options.check_can_view) == 'true';
showBadge = String(options.omit_badges) == 'false';
if(!isCatalogAccessibleViaPortal) {
return;
}
data.categoriesList = [];
var categoriesInPage = options.number_of_categories_to_load || 15;
data.limit = categoriesInPage;
if (input && input.new_limit)
data.limit = input.new_limit;
if (input && input.categoriesList)
data.categoriesList = input.categoriesList.slice(); //Copy the input array
if (input && input.startWindow) {
data.endWindow = input.endWindow;
}
else {
data.startWindow = 0;
data.endWindow = 0;
}
while (data.categoriesList.length < data.limit + 1) {
data.startWindow = data.endWindow;
data.endWindow = data.endWindow + categoriesInPage;
var catGr = queryCategory(catalogs, nestedLayout, dynamicCategory, data.startWindow, data.endWindow);
if (!catGr.hasNext())
break;
fetchCategories(catGr, data.categoriesList);
}
if (data.categoriesList.length > data.limit)
data.showMore = true;
else
data.showMore = false;
data.more_msg = gs.getMessage("Showing {0} categories", data.limit);
function fetchCategories(categoriesGr, categories) {
while (categoriesGr.next()) {
var categoryJS = new sn_sc.CatCategory(categoriesGr.getUniqueValue() + '');
if (!categoryJS.canView())
continue;
var categoryDetails = getCategoryDetails(categoryJS, 0);
categoryDetails.sys_id = categoriesGr.getUniqueValue();
categories.push(categoryDetails);
}
}
function queryCategory(catalogs, nestedLayout, dynamicCategory, startWindow, endWindow) {
var categoriesGr = new GlideRecord('sc_category');
categoriesGr.addQuery("sc_catalog", catalogs);
if (!dynamicCategory)
categoriesGr.addQuery("sys_class_name", "sc_category");
categoriesGr.addActiveQuery();
categoriesGr.orderBy('order');
categoriesGr.orderBy('title');
if (nestedLayout)
categoriesGr.addNullQuery("parent");
categoriesGr.chooseWindow(startWindow, endWindow);
categoriesGr.query();
return categoriesGr;
}
function getItemCount(categoryJS) {
if (showBadge)
return checkCanView ? categoryJS.getViewableItemsCount(true) : categoryJS.getItemsCount(true);
else
return categoryJS.hasVisibleItem(true, checkCanView) ? 1 : 0;
}
function getCategoryDetails(categoryJS, level) {
var categoryDetails = {};
var showChildren = false;
if (!categoryJS) {
return categoryDetails;
}
categoryDetails.title = categoryJS.getTitle();
categoryDetails.level = level;
categoryDetails.description = categoryJS.getDescription();
categoryDetails.full_description = categoryJS.getFullDescription();
categoryDetails.icon = categoryJS.getIconSRC();
categoryDetails.header_icon = categoryJS.getHeaderIconSRC();
categoryDetails.homepage_image = categoryJS.getHomepageImageSRC();
categoryDetails.sys_id = categoryJS.getID();
categoryDetails.showChildren = (categoryDetails.sys_id === categoryId);
categoryDetails.catalog = {"sys_id": categoryJS.getCatalog(), "title": new sn_sc.Catalog(categoryJS.getCatalog()).getTitle()}
categoryDetails.count = categoryDetails.totalCount = ((data.largeDataSet != 'true') ? getItemCount(categoryJS) : 1);
if (catalog_id == -1 && catalogSelectorArr.length > 2)
categoryDetails.catalog_tooltip = gs.getMessage("[{0}]", categoryDetails.catalog.title);
else
categoryDetails.catalog_tooltip = '';
var subCategoryCounts = 0;
if (nestedLayout) {
var subcategories = categoryJS.getViewableSubCategories();
if (subcategories.length == 0) {
categoryDetails.subcategories = [];
}
else {
categoryDetails.subcategories = [];
subcategories.forEach(function(subCategory) {
var subCategoryJS = new sn_sc.CatCategory(subCategory.sys_id + '');
var category = getCategoryDetails(subCategoryJS, level + 1);
categoryDetails.totalCount = categoryDetails.totalCount + category.totalCount;
categoryDetails.subcategories.push(category);
categoryDetails.showChildren = categoryDetails.showChildren || category.showChildren;
});
}
}
else {
categoryDetails.totalCount = categoryDetails.count;
}
return categoryDetails;
}
})();