Sunday, October 30, 2016

Creating New Theme in Oracle Sites Cloud Service - Part 4

In Part 1, Part 2 and Part 3 of this blog post you learned how to convert a Bootstrap theme into static SCS theme, use page layouts to add new pages and then how create navigation menu that dynamically includes links to pages that you added to your site in the Site Builder. In the last part of this blog post - Part 4 - you will learn how to add breadcrumbs and then add SCS slots to page layouts in your new theme to make site pages editable in the Site Builder. This part will complete the steps required to convert a Bootstrap theme into SCS theme that you can then use for creating new sites in Oracle Sites Cloud Service. 

Step 8: Add Breadcrumbs to Page Layouts

In addition to the navigation bar, pages in the Modern Business theme display Breadcrumbs at the top of page content area. In this step you will use SCS Render API to replace static Breadcrumbs with dynamically generated path.

1. Find HTML that renders Breadcrumbs:

 <!-- Page Heading/Breadcrumbs -->  
 <div class="row">  
      <div class="col-lg-12">  
      …   
      </div>  
 </div>  
2. Replace it with the HTML snippet below (note id=”breadcrumb” that you will use to add dynamically generated HTML to this <div>):

 <!-- Page Heading/Breadcrumbs -->  
 <div class="row">  
      <div id="breadcrumb" class="col-lg-12">  
           <!-- page breadcrumbs goes in here -->  
      </div>  
 </div>  
3. Open navigation.js file in your favorite editor and add the following code:

 // render breadcrumbs...  
 function renderBreadcrumbs() {  
   var breadcrumb = $('#breadcrumb');  
   // generate title using page name and page title...  
   var id = SCS.navigationCurr,  
     header = document.createElement('h1');  
   $(header).addClass("page-header");  
   $(header).text(SCS.structureMap[id].name + " ");  
   var subheading = document.createElement('small');  
   $(subheading).text(SCS.pageModel.properties.title);  
   $(header).append(subheading);  
   $(breadcrumb).append(header);  
   // generate [age breadcrumb...  
   var path = document.createElement('ol');  
   $(path).addClass("breadcrumb");  
   if ( id == SCS.navigationRoot ) {  
     // Home page...  
     var bcItem = document.createElement('li');  
     $(bcItem).addClass("active");  
     $(bcItem).text(SCS.structureMap[id].name);  
     $(path).append(bcItem);  
   } else {  
     // one of sub-pages...  
     var ids = getParnetIds(id), bcItem, bcLink, linkData;  
     for (var i = ids.length - 1; i >= 0; i--) {  
       bcItem = document.createElement('li');  
       if ( ids[i] == id ) {  
         $(bcItem).addClass("active");  
         $(bcItem).text(SCS.structureMap[ids[i]].name);  
       } else {  
         bcLink = document.createElement('a');  
         linkData = SCSRenderAPI.getPageLinkData(ids[i]) || {};  
         if ( linkData.href ) {  
           $(bcLink).attr("href", linkData.href);  
         }  
         $(bcLink).text(SCS.structureMap[ids[i]].name);  
         $(bcItem).append(bcLink);  
       }  
       $(path).append(bcItem);  
     }  
   }  
   $(breadcrumb).append(path);  
 }  
 // returns array of parent page id's...  
 function getParnetIds (nodeId) {  
   var ids =[], i = 0;  
   ids[i] = nodeId;  
   while ( nodeId != SCS.navigationRoot ) {  
     nodeId = SCS.structureMap[nodeId].parentId;  
     i = i + 1;  
     ids[ i ] = nodeId;  
   }  
   return ids;  
 }  
4. Extend code at the bottom of the navigation.js file to add event listener to call on renderBreadcrumbs() function:

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

Checkpoint 5

In the Site Builder, check that now you can use Breadcrumbs displayed on the site pages (apart from Home) that you can use to navigate to parent page.

Step 9: Add SCS Slots to the Page Layouts


On this step you will convert content areas in the page layouts to use SCS slots instead of original HTML code. SCS slots are <div> elements in the layout that have the value “scs-slot” in the class attribute. A slot is where you can add components to fill in the page content. Multiple <div> elements can be designated as slots by assigning the "scs-slot" class attribute. Each slot must have a unique id attribute. Slots that additionally have a class attribute value of "scs-responsive" will refresh their content as the browser viewport changes resolution.

There are different options available to add SCS slots to a Bootstrap HTML page:

  • you can convert into a single slot the <div class=”container”> element that contains the whole page content
  • you can convert into a slot each <div class=”row”> element that contains a row of content in a Bootstrap grid on the page
  • or you can convert into a slot each <div> element that contains a column of content in a Bootstrap grid on the page 

You should use options (a) or (b) above if you want to allow end users adding more than one SCS component into the slot. If that is the case you should use the “scs-slot” class attribute in combination with the ”scs-responsive” attribute, e.g. <div id=”row-slot” class=”scs-slot scs-responsive row”>. Option (c) allows you to create SCS page layout that matches closely structure of the original page in the Bootstrap theme. For example, you can create a grid of SCS slots similar to one below:

 <div class="container">  
     <div class="row">  
       <div id=”grid-title" class="scs-slot col-lg-12"></div>  
       <div id="grid-col1" class="scs-slot col-md-4"></div>  
       <div id="grid-col2" class="scs-slot col-md-4"></div>  
       <div id="grid-col3" class="scs-slot col-md-4"></div>  
     </div>  
 </div>  
This arrangement would typically be one where you intend to put only one SCS component per slot and use Bootstrap responsiveness. If that is the case, you do not need to use the “scs-responsive” class attribute. You can further restrict each slot by defining what seeded or custom components can be added to it, see Restricting Components in Slots for further details.

The steps below show an example of how you can add SCS slots to the Home page layout in the Modern Business theme (index.html file). You can use a different layout of slots based on your requirements.

1. Open index.html file in your favorite editor and modify <div> elements that define columns in the Bootstrap grid layout for this page to include id attributes and ‘scs-slot’ class. Once finished, the content area should look something like that:
 <!-- Page Content -->  
 <div class="container">  
      <!-- Marketing Icons Section -->  
      <div class="row">  
           <div id="mrkt-title" class="scs-slot col-lg-12"></div>  
           <div id="mrkt-col1" class="scs-slot col-md-4"></div>  
           <div id="mrkt-col2" class="scs-slot col-md-4"></div>  
           <div id="mrkt-col3" class="scs-slot col-md-4"></div>  
      </div>  
      <!-- Portfolio Section -->  
      <div class="row">  
           <div id="prtf-title" class="scs-slot col-lg-12"></div>  
           <div id="prtf-col1" class="scs-slot col-md-4 col-sm-6"></div>  
           <div id="prtf-col2" class="scs-slot col-md-4 col-sm-6"></div>  
           <div id="prtf-col3" class="scs-slot col-md-4 col-sm-6"></div>  
      </div>  
      <!-- Features Section -->  
      <div class="row">  
           <div id="frts-title" class="scs-slot col-lg-12"></div>  
           <div id="frts-col1" class="scs-slot col-md-6"></div>  
           <div id="frts-col2" class="scs-slot col-md-6"></div>  
      </div>  
      <hr>  
      <!-- Call to Action Section -->  
      <div class="well">  
           <div class="row">  
                <div id="well-col1" class="scs-slot col-md-8"></div>  
                <div id="well-col2" class="scs-slot col-md-4"></div>  
           </div>  
      </div>  
      <hr>  
      <!-- Footer -->  
      <footer>  
           <div class="row">  
                <div class="col-lg-12">  
                     <p>Copyright &copy; Modern Business 2016</p>  
                </div>  
           </div>  
      </footer>  
 </div>  

2. Open Home page of the site in the Site Builder and switch to the Edit mode. You should see all the slots that you added highlighted. If you hover over a slot, you can see slot id displayed in the slot bar.

3. Edit other page layout files to add SCS slots. Once done, use Edit mode in the Site Builder to validate that you can see all the slots that you added to page layouts.


Checkpoint 6

SCS theme Modern Business is complete. You can use page layouts to add new pages to your site and then drag and drop components to the slots that you defined. Once new site is complete, you can convert it into a new template and then share it with your colleagues.

Note: Pages in a Bootstrap theme often use a similar page structure. You should review what page layouts you really need to create / keep in your SCS theme to allow creating the site.

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 create navigation menu that will dynamically include links to pages that you added to your site in the Sit Builder.

Step 7: Create dynamic navigation menu

In this step you will use 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 on Step 5.

1. Find the HTML 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 <script> tag at the bottom of all the page layouts 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 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.
       

Sunday, October 16, 2016

What is new in October release of Oracle SCS

In October (16.4.1) release of Oracle Sites Cloud Service we added a number of new features and capabilities that will help you with creating new hight-fidelity sites and developing custom components that make use of assets stored in Documents repository.

Preview site update in a new browser tab

You can now preview a site update in a separate browser tab. The URL for a site update has a user-friendly format so you can easily view it on a different device such as mobile phone.

New seeded components

Several new seeded components were added to the Site Builder:
  • Text: Plain text component that allows you to select HTML tag that will be used to enclose entered  text (<p>, <h1>,...,<h6> options are supported) and then format the text using styles defined in the theme
  • Video: Now you can stream Video in MP4/h264 format directly from the Oracle Documents Cloud Service repository
  • Conversation: This component allows you to select existing or create new Conversation that will be displayed on a page in your secure site.

Resource Links

Using download links to files in the Documents repository or sharing access to documents or conversation via Documents Manager or Conversation components has been made easy. You do not need to create Member or Public Links anymore, instead you have an option to select link that reference resource in Documents directly. Reference links are generated automatically, including for use in Documents Manager or Conversation components

Ability to use custom jQuery library in a theme

The version of jQuery used by Oracle Sites Cloud Service is now sandboxed. This avoids iQuery conflict between versions used internally by Oracle Sites Cloud Service and in third-party themes like Bootstrap themes. If you were previously using the Oracle Sites Cloud Service version of jQuery, then you must switch to using your own version.

Starter template

You can now use seeded Starter Template to create a new template and theme. The Creating New Theme in Oracle Sites Cloud Service post provides you with a step-by-step guide for using Starter template to create new theme.

Assets support in Sites SDK

SitesSDK has been extend to add new functions that allow you to use File Picker in your custom components to select assets from the Documents repository and then make use of selected assets, for example to implement custom Slider component:
  • SitesSDK.getProperty(‘componentAssets’, callback)
  • SitesSDK.setProperty(‘componentAssets’, [assets])
  • SitesSDK.filePicker({options}, callback)
For more details please refer to Sites SDK Reference.

Creating New Theme in Oracle Sites Cloud Service - Part 2

In Part 1 of this post you learned how to prepare a Bootstrap theme to make it easier to create a new Sites Cloud Service (SCS) theme.

Step 5: Add Bootstrap theme files to SCS theme

In this step you will add files from ‘Modern Business’ theme converted to use SCS folder structure to the ModernBusinessTheme that you created in Step 2:
  •  Copy HTML files from the ‘modern-business/layouts’ folder to ‘layouts’ folder in the SCS theme
  • Copy content of the ‘modern-business/assets’ folder to ‘assets’ folder in the SCS theme

Note: Both SCS ModernBusinessTheme and Bootstrap ‘Modern Business’ theme contain index.html file. Youi can rename original SCS file or simply overwrite it with a new index.html coming from the Bootstrap theme.

After sync of files is complete (check status in the Sync Manager), open ‘ModernBusiness’ site in the Site Builder.  If you decided to overwrite index.html file, the Home page of you site will look something like that:
To restore the look and feel, you need to make path to the ‘assets’ folder relative to the SCS theme. Open ModernBusinessTheme (<user_name>)/layouts/index.html file on the desktop in your favorite HTML editor and replace all entries of:
../assets  to  _scs_theme_root_/assets

Note: If path to the ‘assets’ folder is explicitly used in JavaScript files in the Bootstrap theme that you selected, then instead of the above replacement you should use SCS Render API to obtain path to the ‘assets’ folder in the theme – SCSRenderAPI.getThemeUrlPrefix() returns URL for SCS theme root.

Save the file. Once file sync is completed, you should see Home page correctly rendered in the Site Builder:

If this is the only HTML file from the Bootstrap theme that you want to convert into SCS page layout, you can proceed to the next step. Otherwise, you should re-create page hierarchy of the Bootstrap theme in the Site Builder and configure each SCS page to use corresponding HTML file as a page layout:
Edit remaining HTML files in the ModernBusinesTheme and replace all entries of:
../assets  to  _scs_theme_root_/assets

Checkpoint 2


Using Site Tree in the Builder open site pages that you created and confirm that each page renders correctly in the Site Builder. At this point you need to use Site Tree in the left palette to navigate site pages. On step 7 you will implement navigation bar that uses dynamically generated links to SCS pages in your site.

Step 6: Add SCS Pre-requisites to page layout files

In this step you will modify Bootstrap HTML files in the ModernBusinessTheme (<user_name>)/layouts folder to add code snippets that each SCS page layout should have.
Open ModernBusinessTheme (<user_name>)/layouts/index.html file in your favorite HTML editor and add the following code snippets:
1.     After the <head> tag add
 <!-- Avoid FOUC issue in FF with async loading of style sheets -->  
 <style> body {opacity: 0;}</style>

2.     Just before the closing </head> tad add:
 <!-- SCS components styles - design.css -->  
 <link rel="stylesheet" type="text/css" href="_scs_theme_root_/designs/_scs_design_name_/design.css">  
 <!-- SCS Renderer data -->  
 <!--$SCS_RENDER_INFO-->  
 <!--$SCS_SITE_HEADER-->  
 <!--$SCS_PAGE_HEADER-->  

3.     Just before the closing </body> tag add:
 <!-- SCS JS libraries -->  
 <script data-main="/_sitescloud/renderer/renderer.js" src="/_sitescloud/renderer/require.js">  
 <!--$SCS_PAGE_FOOTER-->  
 <!--$SCS_SITE_FOOTER-->  
 <!-- Avoid FOUC issue in FF with async loading of style sheets -->  
 <style> body {opacity: 1;}</style>  

Note: jQuery library that is used in SCS internally is 'sandboxed' (it is used in the noConflict mode), i.e. in your SCS theme, you can use any version of jQuery library that is included in the original Bootstrap theme as is.

Edit other page layouts and repeat the above steps.

Checkpoint 3


Using Site Tree in the Builder open site pages that you created and confirm that each page renders correctly in the Site Builder.

Now you can add any page from the original Bootstrap theme an make it render in SCS. However, you can't use menu on the site to navigate between pages. In Part 3 of this post you will learn how to create navigation menu for your SCS theme that dynamically render link to pages that you add in the Site Builder.