This is Part 2 of my ServiceNow CMS + Twitter Bootstrap series.
Below are the code examples you will need as explained in the video:
cms_menu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?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 menu_sysid="" /> <j:if test="${jvar_menu_sysid!=''}"> <g:evaluate jelly="true"> var menuGR; if (jelly.jvar_menu_sysid == 'current') menuGR = current; else { menuGR = new GlideRecord('content_block_menu'); menuGR.get(jelly.jvar_menu_sysid); } </g:evaluate> <j:choose> <j:when test="${menuGR.sys_id!=null}"> <g:macro_invoke macro="cms_menu_${menuGR.type}" /> </j:when> <j:otherwise> <div style="background-color:red">Unknown menu type: ${menuGR.type}</div> </j:otherwise> </j:choose> </j:if> </j:jelly> |
cms_menu_bootstrap_nav
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | <?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:evaluate> var sectionGR = new GlideRecord('menu_section'); sectionGR.addQuery('content_block_menu', menuGR.getUniqueValue()); sectionGR.addQuery('active', 'true'); sectionGR.orderBy('order'); sectionGR.query(); </g:evaluate> <g:cms_menu_functions /> <j:if test="${sectionGR.hasNext()}"> <j:set var="jvar_is_first" value="true" /> <ul class="nav nav-tabs"> <j:while test="${sectionGR.next()}"> <j:if test="${canViewMenu(sectionGR)}"> <g:set_if var="jvar_tab_active" test="${jvar_is_first}" true="active" false="" /> <j:set var="jvar_is_first" value="false" /> <g:cms_menu_set_url_and_target link_sysid="${sectionGR.getUniqueValue()}"/> <j:set var="jvar_t" value="${sectionGR.sys_id}" /> <g:evaluate jelly="true"> var itemGR = new GlideRecord('menu_item'); itemGR.addQuery('menu_section', jelly.jvar_t); itemGR.addQuery('active', 'true'); itemGR.orderBy('order'); itemGR.query(); var rowCount = itemGR.getRowCount(); </g:evaluate> <j:if test="${rowCount == 0}"> <li role="presentation" class="${jvar_tab_active}"> <j:switch on="${jvar_link_url}"> <j:case value=""> ${sectionGR.name.getDisplayValue()} </j:case> <j:default> <a href="${jvar_link_url}" target="${jvar_link_target}">${sectionGR.name.getDisplayValue()}</a> </j:default> </j:switch> </li> </j:if> <j:if test="${rowCount > 0}"> <j:if test="${itemGR.hasNext()}"> <li role="presentation" class="dropdown"> <a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-expanded="false"> ${sectionGR.name.getDisplayValue()} <span class="caret"></span> </a> <ul class="dropdown-menu" role="menu"> <j:while test="${itemGR.next()}"> <j:if test="${canViewMenu(itemGR)}"> <g:cms_menu_set_url_and_target /> <li><a class="cms_menu_block_item" href="${jvar_link_url}" target="${jvar_link_target}">${itemGR.name.getDisplayValue()}</a> </li> </j:if> </j:while> </ul> </li> </j:if> </j:if> </j:if> </j:while> </ul> </j:if> </j:jelly> |
Layout Includes:
1 2 3 4 5 | <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet"/> <script src="//code.jquery.com/jquery-2.1.3.min.js"></script> <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script> <script>var $j = jQuery.noConflict();</script> <g:requires name="jQueryFix.jsdbx" /> |
jQueryFix:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | (function() { var isBootstrapEvent = false; if (window.jQuery) { var all = jQuery('*'); jQuery.each(['hide.bs.dropdown', 'hide.bs.collapse', 'hide.bs.modal', 'hide.bs.tooltip'], function(index, eventName) { all.on(eventName, function( event ) { isBootstrapEvent = true; }); }); } var originalHide = Element.hide; Element.addMethods({ hide: function(element) { if(isBootstrapEvent) { isBootstrapEvent = false; return element; } return originalHide(element); } }); })(); |
Hi Nathan. This is awsome thanks for sharing with you. Now tell me where is your “Buy me a coffe” button? :).
HI Nathan nice vedio..i an a starter with CMS. I am trying to figure out how to put a background image in t out of box ESS portal ..any thoughts?
Thank you
Putting a background image should be pretty straight forward. You can do this via CSS. First select the element that need the background (if the whole page you can use “body”), and in a style sheet do something like this: .element-class{ background-image: url(‘/url-to-image/image.jpg’); } This is not really a CMS specific question but really just HTML & CSS.
Also when i replaces the cms_menu macro my ESS portal navigation elements disappeared….
Mathew, that’s because you need to follow the next step in the video which is to rename the “cms_menu_section_blocks” to “cms_menu_blocks”.
Thank you Nathan…my cms page is taking shape now
With this method you could produce any markup you would like, but for this example you would need to include the Bootstrap styles
Really clever way to include a bootstrap navigation bar
Great work! thank you for sharing
Hey Nathan,
Have you experiences any conflicts in the past with JS libraries and page edit mode?
This has been a problem for me and so I put the following code around my JS includes in the layout to stop the conflicts happening:
… Other JS includes …
Joel,
I did run into this at some point. I forget what i did but most of the time if jQuery is in noConflict mode and your plugins are created correctly, it shouldn’t interfere. I do see a lot of issues between prototype.js and jquery though, and depending on what issue it is there are all sorts of workarounds.
Lately I’ve been playing with running everything with sysparm_direct=true but even that comes with it’s own issues.
<j:if test="${GlideTransaction.get().getRequest().getRequestURL().toString().indexOf('edit_content.do') == -1}">
<script src="//code.jquery.com/jquery-2.1.3.min.js"></script>
… Other JS includes …
</j:if>
Im struggling to include scripts in Fuji version of ServiceNow.
When i use the element inspector I cant see the latest jQuery Library loaded, and bootcamp logs a console error saying I need a later version of jQuery.
Hello Nathan – Have you ever seen a multi-column mega-menu created for ServiceNow? Is this design pattern possible? I’m looking for a reference or some secret recipe for CMS. 😉
It’s been done a few times, the old ServiceNow website used to live on CMS and had such a menu. I think using the technique covered in this video you could easily create one, however I don’t know of one available for download. The navigation content block schema would easily support it, so it would just be creating the UI Macro for rendering.
Hi Nathan,
I was following your tutorial but when I add the layout includes at the bottom of the layout, everything starts messing up. The style of the nav bar doesn’t look like yours and the drop down doesn’t even show up before the tabs start disappearing. Also, is the jQuery fix just a UI Script?
Thanks
Are you on Fuji?
Hi Nathan,
Does this functionality not work on Fuji? I can’t seem to make it work. The menu still disappears on click. Any suggestions?
Regards,
William Henry
William, see my latest post, I have a solution for the disappearing menus in Fuji.
Hi Nathan,
Great work with this tutorials.
One thing you mention in the video, you could include bootstrap in better ways then direct linking in Layout. You mention you should elaborate on this in later videos but haven’t found one yet.
Could you quickly describe how you’ll do it in a better way?
Peter,
Sure… so in Fuji and after it is already included on the instance for you. But the other way to manually include it would be to import the files into UI Scripts and Content Styles tables. Most of my portals share a common header and footer so I can include the JS at the end of my footer. The CSS will automatically get included as part of the theme.
Hi Nathan,
Dropdown menu does not render properly in IE8. We are using Geneva S-N release.
Do you have any solution for this?
Thanks