Switching Themes by Topic – A Color Code System for the Portal
Have you ever wanted to change the color palette of the portal according to the current top level topic (i.e. entry point)? Like on http://portale.web.de , http://www.n-tv.de, or http://www.gmx.de (sorry, all German sites). Well, with this bit of code you’ll be able to do so. And the best for frightened aah-no-we-sure-don’t-want-to-modify-the-standard managers: you don’t have to modify anything, you just enhance the standard!</p>
The code
Here is the recipe:
Create a new Portal Application (say: com.company.navigation.themeswitcher) and a new Portal Component (say: com.company.navigation.themeswitcher.default, class name: ThemeSwitcher).
Then place the following Javascript code into the component (either with repeating response.write() statements or by including a JS/JSP):
// contains the ID of the currently displayed theme
var oldTheme = “”;
// the matching table is an associative array (with the exception of the default entry)
// having the match strings as keys and the theme IDs as values
var matchTable = new Array();
matchTable[0] = ‘sap_standard’;
// the default theme
matchTable[‘/super_admin/super_admin_role/’] = ‘sap_chrome’;
matchTable[‘/every_user/general/eu_role/’] = ‘sap_tradeshow’;
/…add more matches here…/
// themeSwitcher function subscribed to the “UpdateTLN” event,
// which is fired before the actual navigation takes place
function themeSwitcher(evt) {
// get the current NavigationTarget
var navigationTarget = evt.dataObject;
// decide on theme by looking at the current NavigationTarget
var theme = matchTable[0];
for (var match in matchTable) {
if(navigationTarget.indexOf(match)>-1) {
theme = matchTable[match];
break;
}
}
// do nothing more if the theme has been set already,
// otherwise save theme in oldTheme (for performance opts)
if(oldTheme == theme)
return;
else
oldTheme = theme;
// add – if not already happened – the post parameter (-> form input) “theme” to
// the form “frmChangeContent” that is posted against the innerpage when navigating;
// the additional parameter will cause the innerpage to load with the new theme
var themeInput = document.getElementById(‘themeInput’);
if(themeInput == null)
document.getElementById(‘frmChangeContent’).innerHTML += ‘Remember to exchange the match table with your data (here: match strings and resulting themes) as stated in the comment. The match strings should be substrings of the names of navigation nodes (like ROLES://portal_content<b>/every_user/general/eu_role/</b>com.sap.km.home_ws). If you rewrite the code a bit you could even switch themes using a “dynamical” match table by including the theme name in the technical name of the role (by using some convention, like com.company.role.acme<b>__theme__topic_one</b> for the theme topic_one) and cutting out the theme name with Javascript.
The theme switch could even be done for (sub)nodes other than entry points – just provide corresponding match strings.
If you just want the inner page to load with the new theme and not the framework page as well, then leave out the last for-loop.
Nota bene:
(1) This code currently works only for themes that are stored in the theme root folder (not “customer” or alike).
(2) And it has been successfully tested for a NW portal (mine is currently SPS 12). It might work for previous SPS’ as well. But I don’t guarantee it for future versions ;-).
Why does that work?
The mystery behind the code is that navigation in the portal is done by calling EPCM.doNavigate(). This in turn will internally raise a portal event (EPCM.raiseEvent(“urn:com.sapportals:navigation”, “Navigate”, navigationTarget)) that is caught by a subscribing function named onNavigate(evt). That function then raises an update event (EPCM.raiseEvent(“urn:com.sapportals:navigation”, “UpdateTLN”, navigationTarget)) before the actual navigation takes place, i.e. before the new NavigationTarget parameter is posted to the inner page. Well, this is exactly when we want the theme switch to happen.</p>
Hi Sven,<br/><br/>This code works really well. I'm using it myself, and it works like a dream.<br/><br/>This is the code change (the for statement at the end):<br/><br/> for (var s=0; s<document.styleSheets.length; s++) {<br/> var styleSheet = document.styleSheets[s];<br/> var href = styleSheet.href;<br/> var pos = href.indexOf('/themes/portal/');<br/> var posCus = href.indexOf('/themes/portal/customer/');<br/> if(posCus > -1) {<br/> pos += '/themes/portal/'.length;<br/> posCus += '/themes/portal/customer/'.length;<br/> var nextSlashPos = href.indexOf('/', posCus);<br/> styleSheet.href = href.substring(0, pos) + theme + href.substring(nextSlashPos);<br/> } else if(pos > -1) {<br/> pos += '/themes/portal/'.length;<br/> var nextSlashPos = href.indexOf('/', pos);<br/> styleSheet.href = href.substring(0, pos) + theme + href.substring(nextSlashPos);<br/> }<br/> }<br/><br/><br/>It's funny how I have been trying to figure this out for the last week and this blog comes up. Perfect timing.<br/><br/>Cheers,<br/>Kevin
Anand
Did you test this code in a SP15 Portal? Seems that changes were made to the Portal logic.
The header area is updated with the new themes. However, the inner page is not affected by the theme changes and also additional links other than entry points are not updated as well (all of them still using the default theme)
Could you please help me to understand what is happening?
Thanks in advance
the answer is simple: since SPS14 there is this new feature called "Short/Hashed URLs", i.e. a NavigationTarget of type "ROLES://portal_content/path_to_role/role/path_within_role/page" can be shortened to something like "navurl://a1c86b637e4a836f689ef74ae4663b79". My code described here actually *needs* the first version since it tries to find patterns therein. So, if you want this piece of code to work then turn off the Short URLs: System Administration > Navigation > Short URLs >> Use Short ULRs = false. Otherwise you'd have to develop a new Theme Switcher component/iView that reads the NavigationTarget parameter, get's the corresponding NavigationNode and its (long) name (via API), and once it has recognized a pattern causes a reload of the request together with the new "theme=" parameter. Sort of like this. Remember, I gave no guarantee for future versions 🙂
Best regards
Sven
Fernando Urzedo
The header area is updated with the new themes. However, the inner page is not affected by the theme changes. We are trying to change the back color of the portal, but when we change the theme it only changes in the header area but not in the content area
I was trying this code on the Light framework page and it does not work!!. Also when we navigate from one top level navigation to other this theme change component automatically dis appears .. Dotn know why...... I checked from the browser view source and I just cant find the theme component ... Please advice !!.
Is there any way to get this to work on SP2? I have tried but the theme does not appear to be applied before the URL's are built in the detailed navigation.
Thank you
please try the parameter "prttheme" instead of "theme" (form input).
BR
Sven
Thank you
Can you tell me if there is a way to launch an iView in one portal that us a URL iView to another portal but applies a theme to the remote iView?
/thread/124748 [original link is broken]
Thank you
Bernard
Congratulations for this code. I'ts genial.
But ... have you tested with Firefox/Mozilla?
I've run on IE and work's perfect, but not in Mozilla.
david
Hi David
Anyone got idea why and how can this be fixed?
Tomer
Is it possible to switch Portal Desktops instead of Portal Themes?
Cheers,
Kevin
you can switch desktops if you use different Portal Aliases (e.g. portal/desktopA and portal/desktopB) which you maintain in the display rules. Then you can switch between desktops using the different URLs /irj/portal/desktopA and /irj/portal/desktopB. Please have a look in the SAP Help: http://help.sap.com/saphelp_nw04/helpdata/de/6e/8590f1d6d349c9adc34c6a8085189b/frameset.htm
You could also make use of the Navigation Zoom feature: http://help.sap.com/saphelp_nw70/helpdata/en/e6/436dab861a42389146fdb4990892bc/frameset.htm
Best regards,
Sven