tumblr counter
2014
06.23

howdy,
I’ve recently stumbled onto this excellent little app for debugging browser side issues.

Fiddler

It allows you to monitor/sniff all of the browser activity on your computer. You can literally run through your OBI dashboards and target specific pages that may be giving you browser erorrs/issues and drill in on the log entries to investigate quickly and efficiently.

Get it here.

2014
05.20

1. HTML Encoding/Decoding
2. URL Encoding/Decoding
3. Colour Picking/HEX Conversion tool
4. ASCII & HTML Code table

2014
05.20

This post is a long overdue upgrade from my 10g Dynamic Banner post.

Most of my stakeholders don’t like the visual noise that dominates a typical Oracle BI project.
I usually take control of the look and feel by hiding away the banner and “branding” my Oracle BI projects using a logo.

This post will help you take control of the look & feel. It also forms the basis for other advanced dashboarding posts in my blog. From this foundation we can explore other usability topics and really boost the user acceptance of your projects.

1. Open the dashboard page you wish to add your banner to. Edit the Dashboard.
editing the dashboard

2. Add a TEXT object to the top of the dashboard.
Then copy/paste the code below into the TEXT object. Save your Page and then Run.

editing the dashboard


<script type="text/javascript">
/*
____________________________________________________________________
Created By: Leigh Wilson (leigh@wilson-is.com) http://www.wilson-is.com
____________________________________________________________________
*/
function renderBanner(pagetitle) {
//Note: the usual method of inserting an innerHTML with the full div tag defined isn't friendly across browsers.
//The approach below, although cumbersome, is a very clean way to define the div and render it safely on chrome, ie and FF.
//Insert the image on the top left of the screen.
var div = document.createElement("div");
div.id = "wilson_banner_image";
div.style.top = "-1px";
div.style.left = "0px";
div.style.position = "absolute";
div.style.right = "0px";
div.style.zIndex = 10;

div.innerHTML = "<img src=\"http://www.wilson-is.com/blog/wp-content/uploads/2014/05/banner_logo.png\">";
document.body.insertBefore(div, document.body.firstChild);

//Insert the title
div = document.createElement("div");
div.id = "wilson_banner_title";
div.style.top = "-1px";
div.style.left = "0px";
div.style.position = "absolute";
div.style.right = "0px";
div.style.zIndex = 11;
div.style.width = "100%";
div.innerHTML = "<font style=\"top:17px; position:absolute; font-weight:bold; font-family:Calibri, Verdana; font-size:18px; color:rgb(227, 236, 241); text-align:center; margin-left:auto; margin-right:auto; width:100%;\">" + pagetitle + "</font>";
document.body.insertBefore(div, document.body.firstChild);

//Insert the banner background, the blue filled rectangle
div = document.createElement("div");
div.id = "wilson_banner_rectangle";
div.style.top = "-1px";
div.style.left = "0px";
div.style.position = "absolute";
div.style.right = "0px";
div.style.zIndex = 9; //this allows the image div to be layed over the top via the zindex 10, as seen in div "wilson_banner_image".
div.style.width = "100%";

div.innerHTML = '<table style="text-align:left; vertical-align:middle; background-color: rgb(36, 38, 63); height:54px; padding:0px; width:100%; z-index:10;"><tr><td>&nbsp;</td></tr></table>';
document.body.insertBefore(div, document.body.firstChild);

//Insert the top right home icon, should the users want to return to the default home page/catalog
div = document.createElement("div");
div.id = "wilson_banner_home_icon";
div.style.top = "-1px";
div.style.left = "0px";
div.style.position = "absolute";
div.style.right = "0px";
div.style.zIndex = 15; //this allows the image div to be layed over the top via the zindex 10, as seen in div "wilson_banner_image".
div.style.width = "100%";
div.innerHTML = '<table style="text-align:right; vertical-align:middle; height:54px; padding:0px; width:100%; z-index:10;"><tr><td><a href="/analytics/saw.dll?bieehome" alt="Home Area for Reporting"><img src="http://www.wilson-is.com/blog/wp-content/uploads/2014/05/home.png" border=0 alt="Home Area for Reporting"></a></td></tr></table>';
document.body.insertBefore(div, document.body.firstChild);

return false;

} //renderBanner

//render the banner and place the title on the top of the banner
renderBanner('Dynamic Main Menu Title');

</script>

Your new page should look something like this, with a nice banner, title, logo and a small icon on the right hand side. The small icon on the right is designed to navigate the user to the OBIEE Home page (should the user want to escape your page).

This simple example is easy to use and you can copy/paste it to any Dashboard Page. To edit the title you simply edit the last line of code, ie: “renderBanner(‘Dynamic Main Menu Title’);”.

This approach works nicely by forcing the browser to “inject” the code into the top of the document and it then executes nice and safely at the page loads. It’s recommended that you place your TEXT box on the dashboard page at the top, only to speed up the rendering time of the banner.
(A more advanced approach would be to include this piece of javascript code in a .js file and include it on the server side. The browser caching will boost performance by a tiny fraction. I’m not covering the .js approach in this post).

Explore the code, give it a go and don’t be afraid to challenge the browser.

Have a good week,

L, out.

2012
10.13

OBIEE 11g: A Hands-On Tutorial

Hi there,

There’s been a flurry of activity in the publishing world recently. I knew there was a couple of OBI 11g books in the works but given the large scale of the OBI 11g product suite and the level of expertise required to compile a book of this magnitude I wasn’t holding my breath. To my surprise, there has been a recent publication called:

Oracle Business Intelligence Enterprise Edition 11g: A Hands-On Tutorial.

The book is co-authored by Haroun Khan, Adrian Ward and Christian Screen – 3 long standing members of the OBI community. They’ve worked together to produce a solid OBI “hands on” book for practictioners. 569 pages of real world, practical examples across the OBI product suite. They include loads of real world scenarios, tips and tricks to encourage best practices in the enterprise.

My strengths on the OBI workstack are very business facing these days so I spent 90% of my time in the presentation layer with reporting, dashboarding and some light repository. For me, this book is a one-stop-shop for quick OBI referencing (across the whole OBI 11g product suite) and to sanity check my work before I commit to a solution, particularly if it’s a strategic solution.

L out.

2012
04.21

Approximately six years ago I entered the OBI world by attending a Siebel Analytics developer & admin course in Perth, Australia. Since that time I have been focused 100% on OBI development and covered the full product stack. Recently though my skill set has been very business facing and as a result my RPD and Physical database side was becoming rusty. Coupled with the new 11g product suite I decided I needed a solid revision across the 11g OBI platform – the Rittmanmead 11g Bootcamp course was the natural choice.

Located at the Rittmanmead HQ in Brighton, the office/training room was brand new! Each attendee was using a new 15″ mac book pro (remote desktop to a dedicated obi 11g instance). Based near the sea, it was a refreshing feeling being out of the hustle and bustle of inner London. The instructor was Adam Seed a Rittmanmead OBI consultant. He was excellent, best instructor I’ve come across by a long shot. He worked his way through the very detailed and thorough 11g notes and explained his own methods, bugs/issues in past versions and he delivered the course very well. 12 attendees of varying IT backgrounds, we all walked away with a solid OBI 11g understanding and ready to solve problems.

I have an 11g migration to get stuck into when I get back to the office on Monday ;-)… wish me luck!

L out.

2012
03.29

Update!!

it’s been a very busy few months (for everyone in the OBI space)…

I’m booked on a Rittmanmead 11g Bootcamp course in mid April, Brighton Beach. Looking forward to relaxing on the beach, beers, smashing some 11g course material and getting a tan. I have doubts about the tan, and the beer… but it will be a solid week and I’m looking forward to taking time out from work and hitting the bootcamp hard. 16th to 20th April… give me a shout if you’re joining that bootcamp and we’ll sort out a beer beforehand…

L out.

2012
01.09

Most of my projects involve users who are in a hurry. They need information quickly and they don’t want to linger around, drilling down on reports for 30 minutes at a time. They usually have a small window of opportunity to get the information they need and get back to their main tasks. When presented with a typical set of dashboards they have over 10 links, menu items, high level reports to drill down on, chart… information overload.

This blog post will demonstrate how to setup a simple Search Page to guide the users to the relevant dashboard quickly, and to improve the overall user experience.

This example is based on the 10g sample sales repository. (Normally I would recommend a high performing database solution (ETL/Materialised Views, indexed and optimised for the search criteria) but in this case the samplesales data is an XML dataset and good enough for a demo. I will use a clustered UNION statement to show the various search results in one report). We will let the users “Search” through the various dimensional data and return exact or partial matches. The returned result will include a href link so the user can select the search result they wish to inspect, google-ized. On click, they are navigated to the most relevant dashboard for immediate results.

1. Create a “Search” Dashboard Page.
I have already constructed this in the find a prompt post where I setup the search page with a custom search prompt.

2. Setup your banner with home and search icons (optional).
This is a modification of a previous post where I demonstrated how to create a floating toolbar.
By adding a special home icon and a search icon the users won’t get lost in the dashboards. It’s important to create a user experience that is consistent between pages/dashboards, flows and hides the nonsense that typically litters a OBIEE dashboard page.
In this example I’ve added a home icon and a search icon.

<div id="my_banner" style="top:0px; left:0px; position: absolute; z-index=11; visibility=show; right=0px;">
<table cellspacing="0" style="text-align: left; vertical-align: middle; background-color: rgb(24, 24, 24); height: 70px; width:expression((width1 = window.innerWidth?document.body.clientWidth:document.documentElement.clientWidth) + 'px'); padding: 0px; white-space: nowrap;" class="SectionTable"><tr><td> </td></tr></table>
</div>

<div id="my_banner_title"><font color="#FFFFFF"; style="top:20px; position:absolute; font-size:26px; text-align:center; margin-left:auto; margin-right:auto; left:0px; right:0px; width:expression((width1 = window.innerWidth?document.body.clientWidth:document.documentElement.clientWidth) + 'px');">Main Menu</font>
</div>

<div id="my_logo" style="top:1px; left:1px; position: absolute; z-index=14; visibility=show;">
<img src="http://www.wilson-is.com/blog/wp-content/uploads/2011/07/logo.png" height=68 border=0></div>

<div id="my_toolbar" style="top:20px; right:10px; position: absolute; z-index=14; visibility=show;">
<a href="/analytics/saw.dll?Dashboard&PortalPath=/shared/Sample%20Sales/_portal/00%20Overview&Page=Content%20Index&Action=Navigate">
<img src="http://www.wilson-is.com/blog/wp-content/uploads/2012/01/house-icon.png" border=0></a>
<a href="mailto:noreply@wilson-is.com"><img src="http://www.wilson-is.com/blog/wp-content/uploads/2011/07/email.png" border=0></a>
<a href="/analytics/saw.dll?Dashboard&PortalPath=/shared/Sample%20Sales/_portal/Search%20Page&Page=Search&Action=Navigate"><img src="http://www.wilson-is.com/blog/wp-content/uploads/2012/01/Search-2-icon.png" border=0 alt="search dashboards"></a>
</div>


3. Construct your “Search Results” report and configure for the search page.
In the sample sales repository we have various dimensional data that the users could potentially search for. I have slapped together a quick example of some search results based on the Customer, Product, Orders, Employee and Market Dimension. On click of a result, the user will be navigated to the appropriate dashboard showing the appropriate result.



Make sure you set the result column to HTML type

The result column is now HTML format (see previous pic)… so we need to piece together a HTML HREF string using the results and the href navigation path. In this example we are going to setup the Customers Details navigation so if a customer record is clicked on, they are navigated over to that customer dashboard. Note: this string is passing the customer name as a parameter to the dashboard…


….


'<a href="/analytics/saw.dll?Dashboard&PortalPath=/shared/Sample%20Sales/_portal/00%20Overview&Page=02%20Customers%20Details&Action=Navigate&col1=%22D1%20Customer%22.%22C1%20%20Cust%20Name%22&val1=%22' || "D1 Customer"."C1 Cust Name" || '%22">' || 'Customer: ' || ucase("D1 Customer"."C1 Cust Name" || ', ' || "D1 Customer"."C2 Cust Status"|| ', ' || "D1 Customer"."C3 Cust Type"|| ', ' || "D1 Customer"."C5 Segment"|| ', ' || "D1 Customer"."C6 Cust Industry"|| ', ' || "D1 Customer"."C7 Credit Rate"|| ', ' || cast("D1 Customer"."C8 First Contact Date" as char)|| ', ' || cast("D1 Customer"."C0 Cust Key" as char) || ', ' || cast("D1 Customer"."C-00 Cust Key (Segmentation)" as char)) || '</a>'


Save your work!! 😉
..

4. Test your Search Results page.

5. On Click, the browser navigates to the appropriate dashboard displaying the appropriate result
If you look closely, the dashboard is automaticlally filtering for the customer “Andrew Jones”.

I know many OBIEE practitioners will *sigh* at this post but all too often we’re forgetting our target audience. Just a small amount of usability polishing can really improve the user experience, and the overall result of the project.

I hope this helps someone out – My project(s) have benefited from this approach.

My next post will consolidate all of my previous posts into a full package main menu, breadcrumbs etc. It redefines the OBIEE user experience altogether…

L out.
p.s. leave a comment.
p.p.s. please add my blog to your blogroll if you’re an OBIEE blogger, thanks.

2012
01.03

Update

Hi there, it’s been a while since my last post. I’ve been very busy with my recent project and it went live today. I will focus on updating my blog over the following weeks. Any requests/recommendations? email me. L out.

2011
08.17

This blog entry is about finding a prompt on a page and from there you can dynamically manipulate the html object. ie. resizing, style, setting focus (making the cursor default to that prompt) etc. This is a simple piece of DHTML (javascript) and very useful.

1. Setup the Dashboard Page with your prompts
In this example I have a simple dashboard page with one prompt on it. The prompt name is “Search”.

Why do I need to Find a Prompt?
In order to manipulate the prompt you need to find it in the HTML source. Every time the page is requested from the OBIEE presentation server it renders the prompts on the page with unique IDs making it difficult to locate and manipulate prompts. For this reason we need a piece of javascript to iterate through the dashboard page (HTML source) and look for the specific prompt and then return ID value.
You can do this yourself by clicking “View Source” in your browser and then searching for all occurrences of the prompt name, in this case “Search”.


This input box is the target, we want to find it and return the ID.

In this example we’re going to use the “Search” Edit Box prompt as seen in the screenshot above.

There are no easy ways to manipulate the input box prompt via the properties in OBIEE Dashboards. Yes you can manipulate the CSS style but it is limited. You can’t perform the following via style sheets:
1. uppercase/lowercase the input field before submitting to the database;
2. set focus/highlight the text onload;
3. adjust properties of the text field automatically;
4. perform javascript validations before executing database query;
5. add/remove custom events to the input box; etc

This blog post will demonstrate how to “find” the prompt on the page and then open up a world of options to you via javascript. In this example we will perform the following:
1. onload, injection of the “findTextPrompt” function into the HEAD of the document;
2. set the width of the Search Prompt so it looks good and longer than 10 chars;
3. set the colour of the text (why not) 😉
4. set focus so the user can start typing straight away without having to click inside the text box;
5. on “Enter” the field is submitted to the database;

Step 1. Add the Javascript to your dashboard page
(if you’re not sure how to add Javascript to your page please read my other blog posts ie. Adding a Dynamic Banner).


<script type="text/javascript">

/*
Created By: Leigh Wilson (leigh@wilson-is.com)

http://www.wilson-is.com

DEVELOPER NOTES
______________________________________________________________________
This code is tested on Internet Explorer 6, 7, 7 and 9.

*/

function injectJavascriptIntoHead(scripttext) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.text = scripttext;
document.getElementsByTagName('head')[0].appendChild(script);
return false;
} //injectJavascriptIntoHead

var findinputboxer = '';
findinputboxer += 'function findTextPrompt(fieldname) {\n';
findinputboxer += '// this function will traverse the DOM and return the input element that matches the search field.\n';
findinputboxer += ' var spans = document.getElementsByTagName("span");\n';
findinputboxer += ' for (var i=0;i<spans.length;i++) {\n';
findinputboxer += ' if (spans[i].className == \'GFPCaption\' && spans[i].innerHTML == fieldname) {\n';
findinputboxer += ' //ok, we\'ve found the field but the input box is in the next SPAN so let\'s get the next span\n';
findinputboxer += ' //alert(spans[i+1].innerHTML);\n';
findinputboxer += ' var inputbox = spans[i+1].innerHTML;\n';
findinputboxer += ' var pos = inputbox.indexOf("id=");\n';
findinputboxer += ' var pos2 = inputbox.indexOf(" ", pos+1);\n';
findinputboxer += ' var id = inputbox.substr(pos+3, pos2 - (pos+3));\n';
findinputboxer += ' id = id.replace( new RegExp(\'"\', \'g\'), \'\');\n';
findinputboxer += ' return id;\n';
findinputboxer += ' }\n';
findinputboxer += ' }\n';
findinputboxer += ' return \'\';\n';
findinputboxer += '}\n';

injectJavascriptIntoHead(findinputboxer);

var searchjs = '';
searchjs += 'function listen(evnt, elem, func) {\n';
searchjs += ' if (elem.addEventListener) \/\/ W3C DOM\n';
searchjs += ' elem.addEventListener(evnt,func,false);\n';
searchjs += ' else if (elem.attachEvent) {\n';
searchjs += ' \/\/ IE DOM\n';
searchjs += ' var r = elem.attachEvent("on"+evnt, func);\n';
searchjs += ' return r;\n';
searchjs += ' } else window.alert(\'Error: cant listen on event!!!\');\n';
searchjs += '} \/\/listen\n';
searchjs += '\n';
searchjs += 'function checkIfEnterPressed(e) { \n';
searchjs += ' if (!e) { e = window.event; if (!e) { e = event; } }\n';
searchjs += ' var key = e.keyCode ? e.keyCode : e.charCode\n';
searchjs += ' if (key == 13) { \n';
searchjs += ' global_go();\n';
searchjs += ' return false;\n';
searchjs += ' } \// if\n';
searchjs += '} \//checkIfEnterPressed\n';
searchjs += '\n';
searchjs += '\n';
searchjs += 'function loadSearchPage() {\n';
searchjs += ' NQOnLoadEvent(); \/\/we need to call the default OBIEE onload event first\n';
searchjs += ' var searchfield;\n';
searchjs += ' \n';
searchjs += ' searchfield = document.getElementById(findTextPrompt(\'Search\'));\n';
searchjs += ' searchfield.value = searchfield.value.toUpperCase();\n';
searchjs += ' \n';
searchjs += ' \//Set the search field so that on key press it will clear the hidden prompts of any values.\n';
searchjs += ' \n';
searchjs += ' searchfield.size="70";\n';
searchjs += ' searchfield.style.backgroundColor="black";\n';
searchjs += ' searchfield.style.color="white";\n';
//searchjs += ' listen("keypress", searchfield, checkIfEnterPressed);\n';
searchjs += '\n';
searchjs += ' searchfield.focus(); \//set focus\n';
searchjs += ' searchfield.select(); \//auto select the text\n';
searchjs += '}\n';

injectJavascriptIntoHead(searchjs);

listen("load", window, function() { loadSearchPage(); });
</script>

Step 2. Modify the code accordingly
The only place you need to modify the code is the name of the prompt. In this post the prompt (Label) is “Search” and must be the only prompt on the page with that specific name.

searchjs += ' searchfield = document.getElementById(findTextPrompt(\'Search\'));\n';

Make sure the findTextPrompt function contains the name of the prompt you are searching for.

I customised the prompt using the following piece of code:

searchjs += ' searchfield.size="70";\n';
searchjs += ' searchfield.style.backgroundColor="black";\n';
searchjs += ' searchfield.style.color="white";\n';

Then the last piece of sexy code sets the prompt as the focus and selects the text inside it (if any). In the context of an input box, “Set Focus” is the term used when setting the cursor to default to this field so it’s ready for the user to start typing. They don’t need to click on it or in it to start typing their search results.

searchjs += ' searchfield.focus(); \//set focus\n';
searchjs += ' searchfield.select(); \//auto select the text\n';

The end result is a very cool looking Search Page….
Onload
The user types in “andrew”…

On Enter…the page uppercases the text, submits to the database and the report runs. As the page refreshes the text is “set focus” and the user can continue searching quickly without the need for clicking around. The way it should be!!

Give me a shout if you would like me to demo some other events/customisations. If i have time I will reply with an example post.

L out.

2011
07.29

In this post I will continue on from the Dynamic Banner post and add a floating toolbar to the top right of the page. In this example I’m going to add the Excel icon and a Email icon.

1. Icon Selection


In this example we need an excel icon and an email icon. More importantly, the icons/images need to be royalty free or you will need to purchase the right to use the icons. I find this website to be very useful because most of the images are royalty free, clean and they come in different scaled sizes. In this blog post we’re using 32×32 size which is a nice clickable size for icons. Use the search function to find the icons you would like to use on your site.

2. Download the icons
You will need to download the icons and host them on a productionised webserver. I typically use the OBIEE Production webserver and package up images into a custom WAR file. The important thing to remember is that these images will be requested by the users’ browser each time the page refreshes so to ensure the images are up and working it’s recommend to upload them onto a solid productionised webserver.

3. Adding the toolbar to the banner

<div id="my_banner" style="top:0px; left:0px; position: absolute; z-index=11; visibility=show; right=0px;">
<table cellspacing="0" style="text-align: left; vertical-align: middle; background-color: rgb(24, 24, 24); height: 70px; width:expression((width1 = window.innerWidth?document.body.clientWidth:document.documentElement.clientWidth) + 'px'); padding: 0px; white-space: nowrap;" class="SectionTable"><tr><td>&nbsp;</td></tr></table>
</div>
<div id="my_banner_title"><font color="#FFFFFF"; style="top:20px; position:absolute; font-size:26px; text-align:center; margin-left:auto; margin-right:auto; left:0px; right:0px; width:expression((width1 = window.innerWidth?document.body.clientWidth:document.documentElement.clientWidth) + 'px');">Main Menu</font>
</div>

<div id="my_logo" style="top:1px; left:1px; position: absolute; z-index=14; visibility=show;">
<img src="http://www.wilson-is.com/blog/wp-content/uploads/2011/07/logo.png" height=68 border=0></div>

<div id="my_toolbar" style="top:20px; right:10px; position: absolute; z-index=14; visibility=show;">
<img src="http://www.wilson-is.com/blog/wp-content/uploads/2011/07/excel.png" border=0>
<a href="mailto:testme@wilson-is.com"><img src="http://www.wilson-is.com/blog/wp-content/uploads/2011/07/email.png" border=0></a>
</div>

The Excel icon doesn’t have an event associated to it so it’s just an image at this stage. I will add functionality (onclick) events to it in a later post. I’ve added a simple “mail to” on the email icon.

From an end-user perspective having a handy toolbar on each page gives them comfort and stability. They know that by clicking on the email icon they can send their message to the correct team quickly. In a large scale environment there could be different teams servicing different dashboards so by using this dynamic toolbar you can direct the emails to the correct teams seamlessly. This way the users don’t need to go off digging around to find a contact person/team etc. It’s important to maintain them on the dashboard and retain their attention. We don’t want to lose them in a sea of Intranet pages do we?! 😉

I will look at adding an “onclick” event to the Excel icon in my next post.