
Portal is a fun beast.
I mean for all it’s awesomeness, there are still a few seemingly simple tasks that can prove a tad….”interesting” to accomplish. This morning I was greeted to an email request from a client asking how one would go about applying a custom icon to the “chrome” of a portal gadget. As it stands, our gadgets are equipped with several interactive icons for controlling it’s state (minimize, maximize, refresh, close, edit preferences, and restore). Adding yet another button to that list HAS to be straightforward no? Turns out while it wasn’t terribly intrusive, it is one of those tasks that has not yet made it into the BB Portal documentation. The following article will outline the steps taken in making the “custom button” requirement a reality.
Before we begin you should understand is that the developers over in Amsterdam have taken great pains to ensure that almost every aspect of the BB portal is as open and flexible as possible. Given the extent of what you can actually DO with portal, the documentation of these efforts requires almost as much manpower as their actual development; an area that we have so far been unable to devote the required small army of writers to. Therefore it is up to us… the few, the proud, the geeky, to assist one another in our respective efforts. So onto the fun stuff.
So here’s what you need to REALLY know. For starters there are 2 use cases that can crop up. The first entails equipping your gadgets with a new GLOBAL icon (ie. one that can be applied to any gadget regardless of type). By design these “core” gadget icons are hardcoded into the gadget and portal definitions.
It all starts with the portal setting titled “gadgetWindowButtons”. This portal setting is a comma delimitated string of name/value pairs that indicates what buttons even exist for the portal gadget chrome. Out of the box this setting is written as follows:
unload;Close,maximize;Maximize,restore;Restore,minimize;Minimize,showPreferences;Edit preferences,hidePreferences;Close preferences,refresh;Refresh
This string is dynamically parsed and used to add our icons to the gadget chrome in the reverse order in which they are written here. This means that the Refresh icon is the leftmost icon, and the close icon is the rightmost. For the sake of our experiment we will add our new icon “notify” right after the “preferences” icon.
unload;Close,maximize;Maximize,restore;Restore,minimize;Minimize,notify;Notification On,no-notify;Notification Off,showPreferences;Edit preferences,hidePreferences;Close preferences,refresh;Refresh
You should now go into the portal admin page, and hit up the “Setting Groups” page and edit the “portal_settings” settings group as this will undoubtedly be the portal settings group you are using. Once inside you should add the “gadgetWindowButtons” setting as it is not by default available!
You should know that the first value in the name/value pairs refers to the CSS classname of the icon, and the detailed value of the “buttonClick” even that is fired when the user clicks on the icon. The “value” of the name/value pairing refers to the tooltip text content presented to the user when she hovers OVER the icon. Also notice that BOTH states for the icon are defined here, since there will be a notification on AND a notification off icon for the gadget.
“Wait… what is this ‘buttonClick’ event nonsense that you just mentioned?”. Well grasshopper, the inner workings of the gadget code ensure that each button icon that is added fires a “buttonClicked” event. This you will note is NOT a standard DOM level event. It is instead a custom event that is only recognizable by the portal itself. When this event is created, a “details” object is appended to the “event” object that gets triggered. This details object is a string indicating what icon was clicked.
Now comes the fun part. That is creating the function that is triggered by that event. Here is where we need to dip into the file “portal.customize.xml”. This file SHOULD exist under WebContent/demo/bindings. If you don’t have this file, look in the portal_demo WAR file that came with your installation, it lives there.
The purpose of portal.customize.xml is to do just that, CUSTOMIZE the portal by extending it’s various components. Now the details of how this is done are a weee bit outside the scope of this article, and as such I suggest that you get yourself familiar with the Backbase Frameworks documentation to understand the structure of BB components. A quick look at this code shows an XML node titled with a name atttribute of “gadgetWindow” this is what we care about. It is within this block that we will extend our gadget window to correctly handle our newly created icon.
<d:element name="gadgetWindow" extends="p:gadgetWindow">
<d:resource type="text/css">
<![CDATA[
.p-gadget-button-notify{
background-image:url("../../demo/themes/default/media/gadgetWindow-buttons.png");
background-position:-80px 0;
}
]]>
</d:resource>
<d:method name="alertMe">
<d:body type="application/javascript">
<![CDATA[
console.log('Alerted');
]]>
</d:body>
</d:method>
<d:handler event="buttonClick" type="application/javascript">
<![CDATA[
switch (event.detail) {
case "notify":
this.alertMe();
break;
default:
}
]]>
</d:handler>
<d:handler event="beforeload" type="application/javascript">
<![CDATA[
if (!this.getSetting("notify", "boolean")) { ((bb.selector.query(this.viewNode, ".p-gadget-button-notify") || 0).style || 0).display = "none";
}
]]>
</d:handler>
<d:handler event="beforeunload" type="application/javascript"><![CDATA[
if (!this.confirmed && this != demo.dialog) {
var that=this;
demo.showDialog('Close Gadget', demo.dialogs.closeGadget, function() {
that.confirmed = true;
that.unload();
});
event.preventDefault();
}
]]></d:handler>
</d:element>
So here are the important parts. First, there is a resource tag of type “text/css”. This little diddy is where you place the styling for your newly created button. Mind you you need to add 2 classes for each icon, the first is default state, the second is the hover state. The names for those CSS classes are “.p-gadget-button-[BUTTON NAME]” and “.p-gadget-button-[BUTTON NAME]-hover”.
NOTE: The location of CSS sprites in the url or src fields is in relation to the portal.customize.xml file, not the root of the application!
Next up is the method tag. This is the function that will be called when you actually press the gadget button. It’s name should match that of your button although as you will soon see it does not have to. Within this method, you have complete access to the gadget whose button has been pressed, meaning that you can alter your gadget and it’s contents in any way that you see fit.
The final required component you will see is the “buttonClick” event handler. Here we have a switch statement that is triggered on the “event.detail” object. Simply add your gadget button name as a case and then fire the method that you want triggered when the button is pressed (see why the name of the method didn’t really matter?). And there you have it.. all done. You should now see your lil gadget and be happy.
But what about that lil “beforeload” event handler? Ooooooo your an observant one! Well my friend, we may want to give the portal administrator the ability to hide this newly created button on certain gadgets so that they don’t ALL have the ability to “notify” the user that their button has been pressed (although I couldn’t possible see why not!). Once added, the user can create a gadget setting group with a setting whose name is the same as that of our little gadget chrome button, and a boolean value to indicate whether that gadget shows the chrome button or not.
I hope this helps everyone. It took me about an hour to muddle through the BB portal code and identify how all this stuff fit together, so hopefully it saves you the same amount of time. Till the next post…. be good and happy coding.
Source: “Needs me some custom buttons…” @ www.thenerdnomad.com