Creating New Theme in Oracle Sites Cloud Service – Part 3

In Part 1 and Part 2 of this blog post you learned how to convert a Bootstrap theme into a static SCS theme. In this part you will learn how to create navigation menu that will dynamically include links to pages that you added to your site in the Site Builder.

Step 7: Create dynamic navigation menu

In this step you will use Oracle SCS Render API to replace static navigation menu in the page layout files with the menu that is rendered dynamically to display pages that you added to the ‘ModernBusiness’ site in Step 5.

1.   Find HTML code that renders navigation in the Bootstrap theme:

<!-- Navigation -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
      …
</nav>

2.   Replace it with the HTML snippet below. The <ul> tag has no content. You will dynamically generate HTML that renders list of menu items and add it to this tag using its id=”navbar-list”. Another HTML element that needs to be dynamically updated is the<a id=”navbar-brand”> tag in the “navbar-header” <div> tag

<!-- Navigation -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
  <!-- brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
      <span class="sr-only">Toggle navigation</span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
    </button>
    <a id="navbar-brand" class="navbar-brand" href="index.html">Modern Business</a></div>
<!-- collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul id="navbar-list" class="nav navbar-nav navbar-right">
      <!-- navigation menu goes in here --></ul>
</div>
</div>
</nav>

3.   Add a new JavaScript file to the theme that will include code to render navigation dynamically (e.g. create ModernBusinessTheme (<user_name>)/assets/js/navigation.js) and then add the following <script> tag at the bottom of all page layout files to load this file:


<!-- SCS JS libraries -->
<script src="_scs_theme_root_/assets/js/navigation.js"></script>
<script data-main="/_sitescloud/renderer/renderer.js" src="/_sitescloud/renderer/require.js"></script>

4.   To the navigation.js file you need to add JavaScript to generate HTML for the navigation menu that is similar to that in the original Bootstrap theme, but includes page links that are dynamically generated using Oracle SCS Render API.

5.   Open navigation.js file in your favorite editor and add the following code:

// render navigation bar...
 function renderNavbar() {
 }
 // must wait for the script to be ready...
 if (document.addEventListener) {
   document.addEventListener('scsrenderstart', renderNavbar, false);
 } else if (document.attachEvent) {
   document.documentElement.scsrenderstart = 0;
   document.documentElement.attachEvent('onpropertychange', function(event) {
     if (event && (event.propertyName == "scsrenderstart")) {
       renderNavbar();
     }
   });
 }

Note: The above code is required to make sure that the renderNavbar() function is called at the right time during SCS page lifecycle.

6.   Now add JavaScript that will generate the same HTML as in the Modern Business theme using SCS Render API to generate menu hierarchy dynamically:

// render navigation bar...
 function renderNavbar() {
   var id = SCS.navigationRoot;
   var linkData, navBrand = $("#navbar-brand");
   // add link to Home page...
   if (navBrand) {
     linkData = SCSRenderAPI.getPageLinkData(id) || {};
     if (linkData.href) {
       $(navBrand).attr("href", linkData.href);
     }
   }
   // build navigation menu...
   var navList = $("#navbar-list");
   // add Home link...
   $(navList).append(createNavItem(id));
   // top level pages...
   var curID, nodes = SCS.structureMap[id].children;
   for (var n = 0; n < nodes.length; n++) {        curID = nodes[n];        // skip hidden node...        if (isNodeHidden(curID))           continue;        // add navigstion node...        if ((SCS.structureMap[curID].children.length > 0) && !allNodeChildrenAreHidden(curID)) {
       // add navigation node with childern nodes...
       navItem = document.createElement("li");
       $(navItem).addClass("dropdown");
       navLink = document.createElement("a");
       $(navLink).addClass("dropdown-toggle");
       $(navLink).attr("href", "#");
       $(navLink).attr("data-toggle", "dropdown");
       $(navLink).attr("data-hover", "dropdown");
       $(navLink).attr("data-delay", "0");
       $(navLink).attr("data-close-others", "false");
       $(navLink).text(SCS.structureMap[curID].name);
       // add downarroe top level to activate sub-menu...
       var navLabel = document.createElement("b");
       $(navLabel).addClass("caret");
       $(navLink).append(navLabel);
       $(navItem).append(navLink);
       // sub-menu...
       var navSubList = document.createElement("ul");
       $(navSubList).addClass("dropdown-menu");
       var subnodes = SCS.structureMap[curID].children;
       for(var sub = 0; sub < subnodes.length; sub++) {
         if (isNodeHidden(subnodes[sub]))
           continue;
         // add item in the sub-level navigation menu...
         $(navSubList).append(createNavItem(subnodes[sub]));
       }
       $(navItem).append(navSubList);
     } else {
       // add top level node without children...
       navItem = createNavItem(curID);
     }
     // add to the navigation menu...
     $(navList).append(navItem);
   }
 }
 // returns
	<li> tag for a navigation menu entry...
 function createNavItem(id) {
   var navItem = document.createElement("li");
   if ( id ==SCS.navigationCurr )
     $(navItem).addClass("active");
   var navLink = document.createElement("a");
   var linkData = SCSRenderAPI.getPageLinkData(id) || {};
   if ( linkData.href ) {
     $(navLink).attr("href", linkData.href);
   }
   if ( linkData.target ) {
     $(navLink).attr("target", linkData.target);
   }
   $(navLink).text(SCS.structureMap[id].name);
   $(navItem).append(navLink);
   return navItem;
 }
 // returns true if given navigation node is hidden...
 function isNodeHidden(id) {
   var navNode, isHidden = false;
   if (SCS.structureMap) {
     navNode = SCS.structureMap[id];
     if (navNode) {
       isHidden = (true === navNode.hideInNavigation);
     }
   }
   return isHidden;
 }
 // returns true if all children of given navigation node are hidden...
 function allNodeChildrenAreHidden(id) {
   var subnodes = SCS.structureMap[id].children,
     allHidden = ( subnodes.length > 0 ) ? true: false;
   for( var sub = 0; sub < subnodes.length; sub++ ) {
     if( !isNodeHidden( subnodes[sub] ) ) {
       allHidden = false;
       break;
     }
   }
   return allHidden;
 }

7.   Save navigation.js file.

Note: The above code generates a two-level navigation menu. if you need to use menu that supports more levels, you should extend this code.

Checkpoint 4

In the Site Builder, check that now you can use navigation bar on a page to navigate pages in your site. Open site in the Edit mode and use Site Tree palette to add new page – check that new page correctly appears in the navigation.
At this point you can add new page to your SCS site and see new pages appearing in the navigation menu. In the Part 4 you will learn how to add Breadcrumbs and make pages editable in the Site Builder by adding SCS slots to page layouts in your new theme.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s