WebCenter Spaces – steps to change the template and skin

April 22, 2014

By: Andreja Sambolec – Application Consultant

Create a new template and skin

If you want to change the default template and skin for your Spaces application, the first step is to create a new template and skin based on the OOTB template which looks similar to the design you want, and apply them to the Spaces application.

In our example we want to have the menu on the top of the page so we created a new template based on the ‘WebCenter Spaces Top Navigation’ template.

 

You can create a new template and skin from the ‘Resources’ tab (Administration-> Spaces-> select Space and select ‘Edit space’).

You can apply your new template and skin using the General tab:

skins1

The default menu looks like this:

skins2

We want to have something like this:

skins3

And this is how the drop-down menu should look:

skins4

 Change the template

We need to change the template because the logo icon has to be on the left side of the menu.

The best way to find what has to be changed is:

  • Create a new portal or ADF application in jDeveloper
  • Create a new .jspx page
  • Copy the templates source code and paste to .jspx file

Now you can easy see the structure of the template and decide what to change.

  1. Using browser ‘Developer Tools’ you can find which component holds the menu:
    skins5
  2. Using jDeveloper you can see the <af:decorativeBox  id =‘db1’ > component  contains  the Global navigation menu and the logo. The component with id set to ‘pt_pgl4’ holds the Top navigation menu.
  3. We decided to replace decorativeBox component with panelGroupLayout component.
    1. Replace af:decorativeBox with af:panelGroupLayut
    2. Delete facet:center
    3. Set layout property for panelGroupLayout to ‘horizontal’
    4. Create two panelGroupLayout components inside of ‘db1’ to hold the logo icon and the menu
    5. Set layout to ‘vertical’ for the second panelGroupLayout
    6. Cut and paste <cust:panelCustomizable id=”pcust1″> inside of the first panelGroupLayout
    7. Cut and paste  <af:panelGroupLayout id=”gtbppgl3″> inside of the second panelGroupLayout
    8. Cut and paste  <af:panelGroupLayout id=”pt_pgl4″> inside of the second panelGroupLayout
    9. Delete the component with id ‘gtbppbl1’
      skins6

This is the result:
skins7

  1. Place the Search input box to the right side:
    1. Using Chrome Developer tool you can see that we need to change the component with id= ‘pcust2’  because this component holds the menu:
      skins8
    2. You will see that the task-flow is used for the search component and it’s placed as the first component inside of ‘pcust2 ‘ so we just need to move it to the last place:
      skins9

New order:
skins10

 

  1. Change Spaces logo using Spaces Settings tab
    skins12
  2. Search for ‘gtbrspmxi1’ component and change the width and the height property for af:image component to 74px and also change the source property to “#{WCPrepareImageURL[spaceContext.space[WCAppContext.currentScope.name].metadata.logo][‘LOGO75’]}”skins13

 

  1. Set the property ‘rendered’ to false for ‘gtbrspmxgl2’ (to hide the link next to logo icon)

The result:
skins14

Change the skin

Next we want to change the menus background color.

The background color for the global menu should be in white.

Steps to change:

  1. Using browser Developer Tool, check which style is used to apply this color

When we deselect the background image for .WCSiteTemplateBackground, .x1r4,

we don’t see the  background color  anymore  on the top of the page .
skins15

  1. So, open the source of your custom skin and add this:

.WCSiteTemplateBackground{

background-image:none;

}
skins16

When you are checking out the styles for some components, you will not see the name of the component but some code, for example, .x106 (the skin is compressed).

You can apply changes using those compressed names or if you know, for example, which component is used you can try with af|commandLink. You could also open the page fragment in jdeveloper and check which component and style class is used and use it in your skin to add changes.

 

Change the navigation model

We also want to add some new pages, so we are going to change the navigation model.

  1. Create a new one based on default one (you can check which model is currently used using the General tab when you are editing your spaces app)
    skins17
  2. Edit your newly created navigation model (add links for your pages – you can create pages later and update Path for links)
    skins18
    skins19
    skins20
  1. Select custom navigation model as the default one for your spaces app
    skins21
    skins22We currently don’t see any sub-menus, so next we are going to change the menu component in our template.

 

Change the Top Menu

 

  1. Using the browser Developer Tool, you can see the menu is placed in the component with id  ‘T:spcNavPanel’.

Search for this component in your template file and you can see a region (task-flow) is used to display the menu.

We are going to replace this region with this code (loop through the navigation model and its children):

  <div class=menu>

    <c:set var=”navNodes”    value=”${navigationContext.defaultNavigationModel.listModel[‘startNode=/, includeStartNode=false’]}” scope=”session”/>

    <ul id=topnav>

      <c:forEach var=”menu” varStatus=”vs” items=”${navNodes}”>

        <li><a href=“/webcenter${menu.goLinkPrettyUrl}”> ${menu.title}</a>

           <c:if test=”${not empty menu.children}”>

             <div class=“submenu”><table width=100%><tr><td>

                <ol class=“blocks-four-up”>

                <c:forEach var=”child” items=”#{menu.children}”>

                 <li>

<p><a href=“/webcenter${child.goLinkPrettyUrl}”>

${child.title}

</a></p>

                 <c:if test=”${not empty child.children}”>

                 <ol>

                 <forEach var=”child1″ items=”#{child.children}”>

                 <li><a href=/webcenter${child1.goLinkPrettyUrl}”>

${child1.title}

</a></li>

                 </c:forEach>

                 </ol>

                 </c:if>

                 </li>

                 </c:forEach>

                 </ol>

              </td></tr></table></div>

            </c:if>

         </li>

      </c:forEach>

    </ul>

  </div>

 

You can find the meaning of EL expressions related to Navigation in this   document:

http://docs.oracle.com/cd/E23943_01/webcenter.1111/e10148/jpsdg_app_els.htm#CHDCBJGJ

 

 

  1. Add this to your skin:

 

.menu ul#topnav{

margin-top: 18px;

padding: 0;

float: left;

width: 880px;

position: absolute;

liststyle: none;

position: relative;

fontsize: 1.2em;

background:url(http://1-ps.googleusercontent.com/h/www.htmldrive.net/edit_media/2010/201007/20100728/Horizontal%20Subnav/images/xtopnav_s.gif.pagespeed.ic.v1mnjAEAt5.webp) repeat-x;

}

.menu ul#topnav li .submenu{  

padding: 15px 0;

position: absolute;

left: 0; top:35px;

display: none;

width: 760px;

background: #282828;;

color: #fff;

z-index:1;

-moz-border-radius-bottomright: 5px;

-khtml-border-radius-bottomright: 5px;

-webkit-border-bottom-right-radius: 5px;

-moz-border-radius-bottomleft: 5px;

-khtml-border-radius-bottomleft: 5px;

-webkit-border-bottom-left-radius: 5px;

}

.menu ul#topnav li{

float: left;

list-style: none;

}

.menu ul#topnav li:hover.submenu{

display:block;

}

.menu ul#topnav li a {

padding: 10px 15px;

display: block;

text-decoration: none;

color: #f0f0f0;

}

.menu.blocks-four-up{

list-style: none;

position:relative:;

}

.menu.blocks-four-up>li {

float: left;

width: 25%;

}

.menu#topnav.blocks-four-up>li ol li{

float: none;

}

.menu ul#topnav li .submenu a {

padding: 10px 0;

display: inline;

color: #f0f0f0;

text-decoration: none;

}

 

  1. To display four (4) submenus in one row, we have to use nth-child selector. If we include the selector in our skin file it’s not going to work, so we can just add it to the template:

<af:resource type=”css”>

.blocks-four-up>li:nth-child(4n+1)

{clear:left;}

</af:resource>

The result:
skins23

 

Next, we want to display the ‘More Info’ menu at the bottom.

How do we know which menu we are going to use as a bottom menu?  We can add some attribute (menuType) to the menu using the navigation model:

skins24

Change the template :

<c:forEach var=”child” items=”#{menu.children}”>

<li>

<c:if test=”${child.attributes.menuType != ‘bottom’}”>

    <p>

    <a href=/webcenter${child.goLinkPrettyUrl}>${child.title}</a>

    </p>

<c:if test=”${not empty child.children}”>

<ol>

    <c:forEach var=”child1″ items=”#{child.children}”>

    <li>

    <a href=/webcenter${child1.goLinkPrettyUrl}>

    ${child1.title}</a>

    </li>

    </c:forEach>

</ol>

</c:if>

</c:if>

<c:if test=”${child.attributes.menuType == ‘bottom’}”>

    <c:set var=”bottomMenu” value=”${child}” scope=”session”/>

</c:if>

</li>

</c:forEach>

</ol>

<p class=“menu_bottom_title”>

 ${bottomMenu.title}

</p>

<ul class=“menu_botom_links”>

<c:forEach var=”child1″ items=”#{bottomMenu.children}”>

    <li>

    <a href=“/webcenter${child1.goLinkPrettyUrl}”>

    ${child1.title}</a>

    </li>

</c:forEach>

</ul>

 

Add/change this to the skin:

.menu ul#topnav li  .submenu.menu_bottom_title{

clear: both;

margin: 0 8px .5em 12px;

padding: .75em 27px 0;

border-top: 1px solid #5e5f62;

font-weight: normal;

font-size: 1.230769em;

line-height: 1.125;

}

.menu.blocks-four-up>li ol{

-webkit-padding-start: 0;

}

.menu.blocks-four-up>li {

float: left;

width: 25%;

padding-bottom: 5px;

}

skins25

Using the same directions, we are going to add some images on the right side of the menu:

  • Create a new link and add attribute ‘menuType’ with value set to ‘image’.
  • Add attribute ‘imageUrl’ with the value which points to your image:
    skins26

Change your template (apply changes related to image in red color):

<td width=85%><ol class=blocks-four-up>

<c:forEach var=”child” items=”#{menu.children}”>

    <li>

    <c:if test=”${ child.attributes.menuType != ‘bottom’ &amp;&amp; child.attributes.menuType != ‘image’}”>

        <p><a href=/webcenter${child.goLinkPrettyUrl}> ${child.title}</a></p>

    <c:if test=”${not empty child.children}”>

    <ol>

    <c:forEach var=”child1″ items=”#{child.children}”>

        <li>

        <a href=/webcenter${child1.goLinkPrettyUrl}> ${child1.title}</a>

        </li>

    </c:forEach>

    </ol>

    </c:if>

    </c:if>

    <c:if test=”${child.attributes.menuType == ‘bottom’}”>

        <c:set var=”bottomMenu” value=”${child}” scope=”session”/>

    </c:if>

    <c:if test=”${child.attributes.menuType == ‘image’}”>

        <c:set var=”linkimage” value=”${child.attributes.imageUrl}” scope=”session”/>

    </c:if>

    </li>

    </c:forEach>

    </ol>

    <p class=menu_bottom_title> ${bottomMenu.title} </p>

    <ul class=menu_botom_links>

    <c:forEach var=”child1″ items=”#{bottomMenu.children}”>

        <li>

        <a href=/webcenter${child1.goLinkPrettyUrl}> ${child1.title}</a>

        </li>

    </c:forEach>

    </ul>

</td>

<td width=“15%” valign=“top”><img src=“${linkimage}”/></td> 

 

 

Finally, we want the submenu to cover the entire page.

To do this:

  1. Create a new div container as child of ‘pt_pgl5’ component:

<af:panelGroupLayout id=”pt_pgl5″ layout=”vertical” styleClass=”WCSiteTemplateBackground”>

            <div id=submenu/>

<af:panelGroupLayout id=”pt_pbl1″ layout=”vertical” inlineStyle=”width:#{attrs.templateFixedWidth}px;margin:0px auto;padding-top:8px;”>

 

We are going to clone the submenu in a mouse over action with this container.

  1. Add javascript to the template:

<af:resource type=“javascript>

function showSubmenu(e){

var childrens = e.parentNode.children;

var  len = childrens.length;

document.getElementById(submenu).innerHTML =;

for (i = 0; i &lt; len; i++) {

if(childrens[i].className==submenu){

newNode=childrens[i].cloneNode(true);

document.getElementById(submenu).appendChild(newNode);

}

}}

</af:resource>

 

  1. Add onMouseOver event to the link

<a href=/webcenter${menu.goLinkPrettyUrl}     onmouseover=showSubmenu(this)>

 

  1. Add this to css:

.menu ul#topnav li:hover.submenu{

display:none;

}

div#submenu.blocks-four-up>li ol li{

float: none;

}

div#submenu.blocks-four-up>li {

float: left;

width: 25%;

padding-bottom: 5px;

}

div#submenu.blocks-four-up{

list-style: none;

position:relative:;

}

div#submenu.blocks-four-up>li ol{

-webkit-padding-start: 0;

}

div#submenu.menu_bottom_title{

clear: both;

margin: 0 8px .5em 12px;

padding: .75em 27px 0;

border-top: 1px solid #5e5f62;

font-weight: normal;

font-size: 1.230769em;

line-height: 1.125;

}

div#submenu div{

padding: 15px 0;

position: relative;

left: 0;

width:1000px;

display: block;

background: #282828;

color: #fff;

margin: 0 auto;

 

}

 

div#submenu  {

width:100%;

top: 90px;

position: absolute;

z-index: 3;

background: #282828;

}

 

div#submenu li{

margin-bottom: .3076923em;

}

 

div#submenu p a{

font-weight:bold

}

 

div#submenu p {

margin-bottom: 3px;

}

div#submenu a{

padding: 10px 0;

display: inline;

color: #f0f0f0;

text-decoration: none;

}

 

div#submenu div>ol {

min-height: 109px;

list-style: none;

}

div#submenu div>ol ol {

padding:0px;

list-style: none;}

div#submenu div>table tr td ol ol {

padding:0px;

list-style: none;

}

skins28

You also need to add an event to clear the container when exiting from the submenu.

Those are the basic steps to change the template and skin of your Portal application.

Using a browser Developer Tool enables you to discover which component has to be changed or what to change in your skin.

 

Any questions? Feel free to contact us.

 

 


WebCenter Portal – Access to WC Spaces Services over REST running on Oracle VM from your Mobile Application

December 18, 2013

By: Andreja Sambolec – Application Consultant

Developing ADF Mobile application – accessing WC services running on VM

If you are using the Oracle SOA Suite/BPM Suite VirtualBox Appliance (Pre-Built Developer VM for Oracle VM VirtualBox) and want to start developing an ADF Mobile application accessing WC Spaces REST services running on this VM, you have to make sure:

  • Your mobile device and local machine have access to the same wireless network
  • NAT is selected as the available network mode on your VM

portal1

  • To check Port Forwarding

potral2

Now you can access WebCenter Spaces from your mobile device or from your local machine using IP address of your local machine: http://192.168.1.33:8888/rest/api/resourceIndex

In your ADF Mobile application, create a new connection:

portal3

If you want use programmatic approach for Spaces REST Service invocation, use the following:

RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();
restServiceAdapter.clearRequestProperties();
restServiceAdapter.setConnectionName(“WCRest”);
restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_GET);
String theUsername = “weblogic”;
String thePassword = “welcome1”;
String userPassword = theUsername + “:” + thePassword;
String encoding = new sun.misc.BASE64Encoder().encode(userPassword.getBytes());
restServiceAdapter.addRequestProperty(“Authorization”, “Basic ” + encoding);
restServiceAdapter.addRequestProperty(“Accept”, “application/json; charset=UTF-8”);
restServiceAdapter.addRequestProperty(“Content-Type”, “application/json; charset=UTF-8”);

restServiceAdapter.setRetryLimit(0);

restServiceAdapter.setRequestURI(“/rest/api/resourceIndex”);

try {

System.out.println(restServiceAdapter.send(“”));

} catch (Exception e) {

e.printStackTrace();

}

Using ADB tool and command adb logcat, you can see the part of the response as a result of the command System.out.println(restServiceAdapter.send(“”)):

{“version”:”11.1.1.6.0″,”resourceType”:”urn:oracle:webcenter:
resourceindex”,”links”:[{“href”:”http://192.168.1.33:8888/rest/api/discussions/forums?utoken=FJnkGqA-W6YrfhjgagLvMj_AJapY_w**&#8221;,”template”:”http://192.168.1.33:8888/rest/api/discussions/forums?startIndex={startIndex}&itemsPerPage={itemsPerPage}&utoken=FJnkGqA-W6YrfhjgagLvMj_AJapY_w**”,”resourceType”:”urn:oracle:webcenter:discussions:forums”,”capabilities”:”urn:oracle:webcenter:read”},{“href”:”http://192.168.1.33:8888/rest/api/preferences/general?utoken=FJnkGqA-W6YrfhjgagLvMj_AJapY_w**&#8221;,”resourceType”:”urn:oracle:webcenter:preferences:general”,”capabilities”:”urn:oracle:webcenter:read”},{“href”:”http://192.168.1.33:8888/rest/api/spaces/siteresources?utoken=FJnkGqA-W6YrfhjgagLvMj_AJapY_w**&#8221;,”template”:”http://192.168.1.33:8888/rest/api/spaces/siteresources?projection={projection}&q={q}&utoken=FJnkGqA-W6YrfhjgagLvMj_AJapY_w**”,”resourceType”:”urn:oracle:webcenter:spaces:siteresources”,”capabilities”:”urn:oracle:webcenter:read”},{“href”:”http://192.168

After the above verification of access to WebCenter Spaces REST Services you can continue with development.

Running into trouble? Want to have a chat with members from TEAM? Contact us here.


TEAM Quick Tip: Using ADF and The jQuery.dotdotdot Plugin

October 29, 2013

By: Andreja Sambolec – Application Consultant

ellipses picThis blog will provide instructions on how to use the jQuery.dotdotdot plugin together with ADF Faces using JDeveloper 11.1.1.6. The purpose of the plugin is to cut the text and show ellipsis to indicate that there is more text than currently visible. It’s also possible to add the “read more” link and put it AFTER the ellipsis.

elipses

You can find more information about this plugin and download it from

http://dotdotdot.frebsite.nl/

In our project we are using this plugin to cut the text and show ‘read-more’ link. The main problem was the “read-more” link didn’t work using af:commandLink. The purpose of the link in our case was to navigate to some other page. To get this to work we had to use a combination of an HTML link and ADF command link. The HTML link was used to show the link on the page and simulate the click on the ADF command link to perform navigation (this could also be a backing bean action call).

The implementation steps were:

1.  Download jQuery library and jQuery.dotdotdot plugin.

2.  Save the libraries into the public-html/lib folder:

elip2

3.  Add those libraries as resources on the page (inside of af:document):

<af:resource type=”javascript” source=”/lib/jquery-1.10.2.min.js”/>
<af:resource type=”javascript” source=”/lib/jquery.dotdotdot.min.js”/>

4. Add component containing the content and link:

<af:panelGroupLayout id=”pgl1″ clientComponent=”true”>

<div id=”dotid” class=”dotcontent” style=”height:132px;overflow:hidden;”>

<af:panelGroupLayout  clientComponent=”true” id=”pgl2″>

 <af:outputText value=”Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.”  clientComponent=”true” id=”ot1″/>

</af:panelGroupLayout>

<a id=”rm-link” class=”rm-link” onclick=”readMoreContent()” style=”cursor:pointer;color:#688FCF;”> Read  More</a>

</div>

</af:panelGroupLayout>

5. Add ADF invisible command link which will perform the navigation:

<div>

<af:commandLink text=”Read more invisible” action=”details”

styleClass=”rm-invisible” clientComponent=”true”
id=”rm-invisible” visible=”false”/>

</div>

6. Create javascript function to call dotdotdot plugin and simulate click on ADF command link:

<af:resource type=”javascript”>

function Dot() {
$(“.rm-invisible“).on(‘simulate_click’, function () {

document.getElementById($(this).attr(‘id’)).click();
});

$(“.dotcontent“).dotdotdot( {

after : “a.rm-link“, callback : hideLinkIfNoTruncationAlert, watch: “window”

 });

 }
//it’s executed after dotdotdot function to hide the link if text is not cut
function hideLinkIfNoTruncationAlert(isTruncated, origContent) {

 if (!isTruncated) {

 $(‘.rm-link‘, this).remove();

 }

 }
//simulate click on ADF link to execute navigation

 function readMoreContent() {

$(“.rm-invisible“).trigger(‘simulate_click’);

  };

</af:resource>

7. Add af:clientListener to af:document to call the function after the page is loaded:

<af:clientListener type=”load” method=”Dot”/>

If you need to cut some text inside of the page fragment, you also need to add af:clientListener to the parent page.  Alternatively you can set ControllerClass, which implements the RegionController interface, to the pageDef file and call the javascript function from the refreshRegion method.

Now you can use the jQuery.dotdotdot plugin together with ADF Faces using JDeveloper 11.1.1.6. Cutting the text and showing the ellipsis to indicate that there is more text can really clean up your pages. Using a “read more” link provides another form of navigation to direct your visitors to content faster. For more information on ADF and other WebCenter questions, please reach out to us!


TEAM’s Customer, Mortenson Construction, Makes the Cover of Oracle Profit Magazine!

August 9, 2013

TEAM was excited to share when Mortenson Construction was awarded Oracle’s 2012 Industry Excellence Award for Engineering and Construction at Oracle OpenWorld last year. TEAM led the architecture and development of the WebCenter Spaces and WebCenter Content 11g implementations of their ProjectConnect application, and the project continues to receive great recognition. Now Mortenson has made the cover of Oracle Profit Magazine!

Check out the article.

mortmagazineDesign. Connect. Build.

Mortenson Construction helps large project teams collaborate and share information—on and off the construction site.

by David Baum, August 2013

 

 

 

 

If you want your own award winning project, contact TEAM today!


iOS 5.0 update fixes WebCenter Spaces mobile Safari issues

November 8, 2011

By: Nick Olmsted

Before the latest iOS 5.0 release the only way to view your WebCenter Spaces application without getting javascript errors was through the
Spaces native iPhone app available on iTunes. This worked great but it didn’t allow you to share that custom Spaces template you have spent so much time on. Apple must have beefed up the javascript engine within the Safari mobile browser with the latest iOS 5.0 update. With the update you should now be able to navigate to your WebCenter Spaces 11g application and be able to view it within the mobile Safari browser without any javascript errors (excluding any
customizations).  All of the Spaces functionality should now work within the mobile Safari browser such as your space’s wikis, blogs, announcements,
discussions, and viewing content. Hopefully now that Apple has updated their mobile javascript engine the other major mobile platform browsers will follow
suit.

Now that we have the mobile browser support (at least on iOS devices) the next step we will be doing in our implementation is applying some
changes to our custom template to maximize the viewing experience on an iPad. To accomplish this we will be using CSS3 media queries and adaptive design
techniques. Using CSS3 media queries we will be able to keep a single template and adjust the styles being used based on the end user’s device (i.e. Desktop,
phone, tablet). They will then get a viewing experience that will match that device and allow users to get at the functionality easily within the site independent
of the device used.

Here are some useful links on CSS3 media quires and adaptive design:

http://html5boilerplate.com/

http://code.google.com/p/css3-mediaqueries-js/

http://richardshepherd.com/css-media-queries-jquery/

http://www.alistapart.com/articles/responsive-web-design/

http://www.johnbrunswick.com/2011/09/e2-0-workbench-podcast-6-%e2%80%93-webcenter-portal-mobile-templates-using-adaptive-styles/

Here is some more information on the WebCenter Spaces 11g iPhone application

http://www.oracle.com/technetwork/middleware/webcenter/iphone-163241.html