jQuery Datepicker Accessiblity

Primefaces has not updated its datepicker for accessibility but we can fix it by using


/**
*
*/
function handleDatepicker(xhr, status, args) {
renderDatePicker();
}

function renderDatePicker() {

// Add aria-describedby to the button referring to the label
$('.ui-datepicker-trigger').attr('aria-describedby', 'datepickerLabel');
dayTripper();
return false;
}

function dayTripper() {
$('.ui-datepicker-trigger').click(function(event) {
var currobj = $(this);
setTimeout(function() {
var today = $('.ui-datepicker-today a')[0];

if (!today) {
today = $('.ui-state-active')[0] ||
$('.ui-state-default')[0];
}
// Hide the entire page (except the date picker)
// from screen readers to prevent document navigation
// (by headings, etc.) while the popup is open
$("main").attr('id', 'dp-container');
$("#dp-container").attr('aria-hidden', 'true');
// $("#skipnav").attr('aria-hidden','true');

// Hide the "today" button because it doesn't do what
// you think it supposed to do
$(".ui-datepicker-current").hide();

today.focus();
console.log($(this));

datePickHandler(currobj);

}, 0);
});
return false;
}

function datePickHandler(element) {
var activeDate;
var container = document.getElementById('ui-datepicker-div');
//var input = document.getElementById('datepicker');

$(container).find('table').first().attr('role', 'grid');

container.setAttribute('role', 'application');
container.setAttribute('aria-label', 'Calendar view date-picker');

// the top controls:
var prev = $('.ui-datepicker-prev', container)[0],
next = $('.ui-datepicker-next', container)[0];
// This is the line that needs to be fixed for use on pages with base URL set in head
next.href = 'javascript:void(0)';
prev.href = 'javascript:void(0)';

next.setAttribute('role', 'button');
next.removeAttribute('title');
prev.setAttribute('role', 'button');
prev.removeAttribute('title');

appendOffscreenMonthText(next);
appendOffscreenMonthText(prev);

// delegation won't work here for whatever reason, so we are
// forced to attach individual click listeners to the prev /
// next month buttons each time they are added to the DOM
$(next).on('click', handleNextClicks);
$(prev).on('click', handlePrevClicks);

monthDayYearText();

$(container).on('keydown', function calendarKeyboardListener(keyVent) {
var which = keyVent.which;
var target = keyVent.target;
var dateCurrent = getCurrentDate(container);

if (!dateCurrent) {
dateCurrent = $('a.ui-state-default')[0];
setHighlightState(dateCurrent, container);
}

if (27 === which) {
keyVent.stopPropagation();
return closeCalendar(element);
} else if (which === 9 && keyVent.shiftKey) { // SHIFT + TAB
keyVent.preventDefault();
if ($(target).hasClass('ui-datepicker-close')) { // close button
$('.ui-datepicker-prev')[0].focus();
} else if ($(target).hasClass('ui-state-default')) { // a date link
$('.ui-datepicker-close')[0].focus();
} else if ($(target).hasClass('ui-datepicker-prev')) { // the prev link
$('.ui-datepicker-next')[0].focus();
} else if ($(target).hasClass('ui-datepicker-next')) { // the next link
activeDate = $('.ui-state-highlight') ||
$('.ui-state-active')[0];
if (activeDate) {
activeDate.focus();
}
}
} else if (which === 9) { // TAB
keyVent.preventDefault();
if ($(target).hasClass('ui-datepicker-close')) { // close button
activeDate = $('.ui-state-highlight') ||
$('.ui-state-active')[0];
if (activeDate) {
activeDate.focus();
}
} else if ($(target).hasClass('ui-state-default')) {
$('.ui-datepicker-next')[0].focus();
} else if ($(target).hasClass('ui-datepicker-next')) {
$('.ui-datepicker-prev')[0].focus();
} else if ($(target).hasClass('ui-datepicker-prev')) {
$('.ui-datepicker-close')[0].focus();
}
} else if (which === 37) { // LEFT arrow key
// if we're on a date link...
if (!$(target).hasClass('ui-datepicker-close') && $(target).hasClass('ui-state-default')) {
keyVent.preventDefault();
previousDay(target);
}
} else if (which === 39) { // RIGHT arrow key
// if we're on a date link...
if (!$(target).hasClass('ui-datepicker-close') && $(target).hasClass('ui-state-default')) {
keyVent.preventDefault();
nextDay(target);
}
} else if (which === 38) { // UP arrow key
if (!$(target).hasClass('ui-datepicker-close') && $(target).hasClass('ui-state-default')) {
keyVent.preventDefault();
upHandler(target, container, prev);
}
} else if (which === 40) { // DOWN arrow key
if (!$(target).hasClass('ui-datepicker-close') && $(target).hasClass('ui-state-default')) {
keyVent.preventDefault();
downHandler(target, container, next);
}
} else if (which === 13) { // ENTER
if ($(target).hasClass('ui-state-default')) {
setTimeout(function() {
closeCalendar(element);
}, 100);
} else if ($(target).hasClass('ui-datepicker-prev')) {
handlePrevClicks();
} else if ($(target).hasClass('ui-datepicker-next')) {
handleNextClicks();
}
} else if (32 === which) {
if ($(target).hasClass('ui-datepicker-prev') || $(target).hasClass('ui-datepicker-next')) {
target.click();
}
} else if (33 === which) { // PAGE UP
keyVent.preventDefault();
moveOneMonth(target, 'prev');
} else if (34 === which) { // PAGE DOWN
keyVent.preventDefault();
moveOneMonth(target, 'next');
} else if (36 === which) { // HOME
var firstOfMonth = $(target).closest('tbody').find('.ui-state-default')[0];
if (firstOfMonth) {
firstOfMonth.focus();
setHighlightState(firstOfMonth, $('#ui-datepicker-div')[0]);
}
} else if (35 === which) { // END
var $daysOfMonth = $(target).closest('tbody').find('.ui-state-default');
var lastDay = $daysOfMonth[$daysOfMonth.length - 1];
if (lastDay) {
lastDay.focus();
setHighlightState(lastDay, $('#ui-datepicker-div')[0]);
}
}
$(".ui-datepicker-current").hide();
});
return false;
}

function closeCalendar(element) {

var container = $('#ui-datepicker-div');
$(container).off('keydown');
// var input = $('#datepicker')[0];
// $(input).datepicker('hide');
//
// input.focus();
//console.log(element[0].previousSibling);
$(element[0].previousSibling).datepicker('hide'); //this gives access to input field beside it

element[0].focus(); // Focus the button
}

function removeAria() {
// make the rest of the page accessible again:
$("#dp-container").removeAttr('aria-hidden');
$("#skipnav").removeAttr('aria-hidden');
}

///////////////////////////////
//////////////////////////// //
///////////////////////// // //
// UTILITY-LIKE THINGS // // //
///////////////////////// // //
//////////////////////////// //
///////////////////////////////
function isOdd(num) {
return num % 2;
}

function moveOneMonth(currentDate, dir) {
var button = (dir === 'next') ?
$('.ui-datepicker-next')[0] :
$('.ui-datepicker-prev')[0];

if (!button) {
return;
}

var ENABLED_SELECTOR = '#ui-datepicker-div tbody td:not(.ui-state-disabled)';
var $currentCells = $(ENABLED_SELECTOR);
var currentIdx = $.inArray(currentDate.parentNode, $currentCells);

button.click();
setTimeout(function() {
updateHeaderElements();

var $newCells = $(ENABLED_SELECTOR);
var newTd = $newCells[currentIdx];
var newAnchor = newTd && $(newTd).find('a')[0];

while (!newAnchor) {
currentIdx--;
newTd = $newCells[currentIdx];
newAnchor = newTd && $(newTd).find('a')[0];
//Updated by shiva incase user is trying to access page up/down at high speed newAnchor is undefnied in which case use day 1 as cursor.
if (newAnchor == undefined) {
newAnchor = $("td[data-handler='selectDay']")[0].children[0]
}
}

setHighlightState(newAnchor, $('#ui-datepicker-div')[0]);
newAnchor.focus();

}, 0);

}

function handleNextClicks() {
setTimeout(function() {
updateHeaderElements();
prepHighlightState();
$('.ui-datepicker-next').focus();
$(".ui-datepicker-current").hide();
}, 0);
}

function handlePrevClicks() {
setTimeout(function() {
updateHeaderElements();
prepHighlightState();
$('.ui-datepicker-prev').focus();
$(".ui-datepicker-current").hide();
}, 0);
}

function previousDay(dateLink) {
var container = document.getElementById('ui-datepicker-div');
if (!dateLink) {
return;
}
var td = $(dateLink).closest('td');
if (!td) {
return;
}

var prevTd = $(td).prev(),
prevDateLink = $('a.ui-state-default', prevTd)[0];

if (prevTd && prevDateLink) {
setHighlightState(prevDateLink, container);
prevDateLink.focus();
} else {
handlePrevious(dateLink);
}
}
function handlePrevious(target) {
var container = document.getElementById('ui-datepicker-div');
if (!target) {
return;
}
var currentRow = $(target).closest('tr');
if (!currentRow) {
return;
}
var previousRow = $(currentRow).prev();

if (!previousRow || previousRow.length === 0) {
// there is not previous row, so we go to previous month...
previousMonth();
} else {
var prevRowDates = $('td a.ui-state-default', previousRow);
var prevRowDate = prevRowDates[prevRowDates.length - 1];

if (prevRowDate) {
setTimeout(function() {
setHighlightState(prevRowDate, container);
prevRowDate.focus();
}, 0);
}
}
}

function previousMonth() {
var prevLink = $('.ui-datepicker-prev')[0];
var container = document.getElementById('ui-datepicker-div');
prevLink.click();
// focus last day of new month
setTimeout(function() {
var trs = $('tr', container),
lastRowTdLinks = $('td a.ui-state-default', trs[trs.length - 1]),
lastDate = lastRowTdLinks[lastRowTdLinks.length - 1];

// updating the cached header elements
updateHeaderElements();

setHighlightState(lastDate, container);
lastDate.focus();

}, 0);
}

///////////////// NEXT /////////////////
/**
* Handles right arrow key navigation
* @param {HTMLElement} dateLink The target of the keyboard event
*/
function nextDay(dateLink) {
var container = document.getElementById('ui-datepicker-div');
if (!dateLink) {
return;
}
var td = $(dateLink).closest('td');
if (!td) {
return;
}
var nextTd = $(td).next(),
nextDateLink = $('a.ui-state-default', nextTd)[0];

if (nextTd && nextDateLink) {
setHighlightState(nextDateLink, container);
nextDateLink.focus(); // the next day (same row)
} else {
handleNext(dateLink);
}
}

function handleNext(target) {
var container = document.getElementById('ui-datepicker-div');
if (!target) {
return;
}
var currentRow = $(target).closest('tr'),
nextRow = $(currentRow).next();

if (!nextRow || nextRow.length === 0) {
nextMonth();
} else {
var nextRowFirstDate = $('a.ui-state-default', nextRow)[0];
if (nextRowFirstDate) {
setHighlightState(nextRowFirstDate, container);
nextRowFirstDate.focus();
}
}
}

function nextMonth() {
nextMon = $('.ui-datepicker-next')[0];
var container = document.getElementById('ui-datepicker-div');
nextMon.click();
// focus the first day of the new month
setTimeout(function() {
// updating the cached header elements
updateHeaderElements();

var firstDate = $('a.ui-state-default', container)[0];
setHighlightState(firstDate, container);
firstDate.focus();
}, 0);
}

/////////// UP ///////////
/**
* Handle the up arrow navigation through dates
* @param {HTMLElement} target The target of the keyboard event (day)
* @param {HTMLElement} cont The calendar container
* @param {HTMLElement} prevLink Link to navigate to previous month
*/
function upHandler(target, cont, prevLink) {
prevLink = $('.ui-datepicker-prev')[0];
var rowContext = $(target).closest('tr');
if (!rowContext) {
return;
}
var rowTds = $('td', rowContext),
rowLinks = $('a.ui-state-default', rowContext),
targetIndex = $.inArray(target, rowLinks),
prevRow = $(rowContext).prev(),
prevRowTds = $('td', prevRow),
parallel = prevRowTds[targetIndex],
linkCheck = $('a.ui-state-default', parallel)[0];

if (prevRow && parallel && linkCheck) {
// there is a previous row, a td at the same index
// of the target AND theres a link in that td
setHighlightState(linkCheck, cont);
linkCheck.focus();
} else {
// we're either on the first row of a month, or we're on the
// second and there is not a date link directly above the target
prevLink.click();
setTimeout(function() {
// updating the cached header elements
updateHeaderElements();
var newRows = $('tr', cont),
lastRow = newRows[newRows.length - 1],
lastRowTds = $('td', lastRow),
tdParallelIndex = $.inArray(target.parentNode, rowTds),
newParallel = lastRowTds[tdParallelIndex],
newCheck = $('a.ui-state-default', newParallel)[0];

if (lastRow && newParallel && newCheck) {
setHighlightState(newCheck, cont);
newCheck.focus();
} else {
// theres no date link on the last week (row) of the new month
// meaning its an empty cell, so we'll try the 2nd to last week
var secondLastRow = newRows[newRows.length - 2],
secondTds = $('td', secondLastRow),
targetTd = secondTds[tdParallelIndex],
linkCheck = $('a.ui-state-default', targetTd)[0];

if (linkCheck) {
setHighlightState(linkCheck, cont);
linkCheck.focus();
}

}
}, 0);
}
}

//////////////// DOWN ////////////////
/**
* Handles down arrow navigation through dates in calendar
* @param {HTMLElement} target The target of the keyboard event (day)
* @param {HTMLElement} cont The calendar container
* @param {HTMLElement} nextLink Link to navigate to next month
*/
function downHandler(target, cont, nextLink) {
nextLink = $('.ui-datepicker-next')[0];
var targetRow = $(target).closest('tr');
if (!targetRow) {
return;
}
var targetCells = $('td', targetRow),
cellIndex = $.inArray(target.parentNode, targetCells), // the td (parent of target) index
nextRow = $(targetRow).next(),
nextRowCells = $('td', nextRow),
nextWeekTd = nextRowCells[cellIndex],
nextWeekCheck = $('a.ui-state-default', nextWeekTd)[0];

if (nextRow && nextWeekTd && nextWeekCheck) {
// theres a next row, a TD at the same index of `target`,
// and theres an anchor within that td
setHighlightState(nextWeekCheck, cont);
nextWeekCheck.focus();
} else {
nextLink.click();

setTimeout(function() {
// updating the cached header elements
updateHeaderElements();

var nextMonthTrs = $('tbody tr', cont),
firstTds = $('td', nextMonthTrs[0]),
firstParallel = firstTds[cellIndex],
firstCheck = $('a.ui-state-default', firstParallel)[0];

if (firstParallel && firstCheck) {
setHighlightState(firstCheck, cont);
firstCheck.focus();
} else {
// lets try the second row b/c we didnt find a
// date link in the first row at the target's index
var secondRow = nextMonthTrs[1],
secondTds = $('td', secondRow),
secondRowTd = secondTds[cellIndex],
secondCheck = $('a.ui-state-default', secondRowTd)[0];

if (secondRow && secondCheck) {
setHighlightState(secondCheck, cont);
secondCheck.focus();
}
}
}, 0);
}
}
function onCalendarHide() {
closeCalendar();
}

// add an aria-label to the date link indicating the currently focused date
// (formatted identically to the required format: mm/dd/yyyy)
function monthDayYearText() {
var cleanUps = $('.amaze-date');

$(cleanUps).each(function(clean) {
// each(cleanUps, function (clean) {
clean.parentNode.removeChild(clean);
});

var datePickDiv = document.getElementById('ui-datepicker-div');
// in case we find no datepick div
if (!datePickDiv) {
return;
}

var dates = $('a.ui-state-default', datePickDiv);

$(dates).each(function(index, date) {
var currentRow = $(date).closest('tr'),
currentTds = $('td', currentRow),
currentIndex = $.inArray(date.parentNode, currentTds),
headThs = $('thead tr th', datePickDiv),
dayIndex = headThs[currentIndex],
daySpan = $('span', dayIndex)[0],
monthName = $('.ui-datepicker-month', datePickDiv)[0].innerHTML,
year = $('.ui-datepicker-year', datePickDiv)[0].innerHTML,
number = date.innerHTML;

if (!daySpan || !monthName || !number || !year) {
return;
}

// AT Reads: {month} {date} {year} {day}
// "December 18 2014 Thursday"
var dateText = monthName + ' ' + date.innerHTML + ' ' + year + ' ' + daySpan.title;
// AT Reads: {date(number)} {name of day} {name of month} {year(number)}
// var dateText = date.innerHTML + ' ' + daySpan.title + ' ' + monthName + ' ' + year;
// add an aria-label to the date link reading out the currently focused date
date.setAttribute('aria-label', dateText);
});
}

// update the cached header elements because we're in a new month or year
function updateHeaderElements() {
var context = document.getElementById('ui-datepicker-div');
if (!context) {
return;
}

$(context).find('table').first().attr('role', 'grid');

prev = $('.ui-datepicker-prev', context)[0];
next = $('.ui-datepicker-next', context)[0];

//make them click/focus - able
next.href = 'javascript:void(0)';
prev.href = 'javascript:void(0)';

next.setAttribute('role', 'button');
prev.setAttribute('role', 'button');
appendOffscreenMonthText(next);
appendOffscreenMonthText(prev);

$(next).on('click', handleNextClicks);
$(prev).on('click', handlePrevClicks);

// add month day year text
monthDayYearText();
}
function prepHighlightState() {
var highlight;
var cage = document.getElementById('ui-datepicker-div');
highlight = $('.ui-state-highlight', cage)[0] ||
$('.ui-state-default', cage)[0];
if (highlight && cage) {
setHighlightState(highlight, cage);
}
}

// Set the highlighted class to date elements, when focus is recieved
function setHighlightState(newHighlight, container) {
var prevHighlight = getCurrentDate(container);
// remove the highlight state from previously
// highlighted date and add it to our newly active date
$(prevHighlight).removeClass('ui-state-highlight');
$(newHighlight).addClass('ui-state-highlight');
}
// grabs the current date based on the hightlight class
function getCurrentDate(container) {
var currentDate = $('.ui-state-highlight', container)[0];
return currentDate;
}

/**
* Appends logical next/prev month text to the buttons
* - ex: Next Month, January 2015
* Previous Month, November 2014
*/
function appendOffscreenMonthText(button) {
var buttonText;
var isNext = $(button).hasClass('ui-datepicker-next');
var months = [
'january', 'february',
'march', 'april',
'may', 'june', 'july',
'august', 'september',
'october',
'november', 'december'
];

var currentMonth = $('.ui-datepicker-title .ui-datepicker-month').text().toLowerCase();
var monthIndex = $.inArray(currentMonth.toLowerCase(), months);
var currentYear = $('.ui-datepicker-title .ui-datepicker-year').text().toLowerCase();
var adjacentIndex = (isNext) ? monthIndex + 1 : monthIndex - 1;

if (isNext && currentMonth === 'december') {
currentYear = parseInt(currentYear, 10) + 1;
adjacentIndex = 0;
} else if (!isNext && currentMonth === 'january') {
currentYear = parseInt(currentYear, 10) - 1;
adjacentIndex = months.length - 1;
}

buttonText = (isNext) ?
'Next Month, ' + firstToCap(months[adjacentIndex]) + ' ' + currentYear :
'Previous Month, ' + firstToCap(months[adjacentIndex]) + ' ' + currentYear;

$(button).find('.ui-icon').html(buttonText);

}

// Returns the string with the first letter capitalized
function firstToCap(s) {
return s.charAt(0).toUpperCase() + s.slice(1);
}

 

Websphere Portal theme – uncompressed css/js

If you are seeing uncompressed css/js files loading in your theme instead of compressed it could be because of following trace enabled on the server.

com.ibm.wps.resourceaggregator.CombinerDataSource.RemoteDebug=all

When debug is enabled, the modules that contribute to the theme provide their uncompressed Javascript or CSS files if available. Additionally, all the files are retrieved with separate requests. This makes it much easier to find the offending file.

uncompressed

jQuery – Modify Primefaces Radiobutton

Updating Primefaces radiobutton using javascript is tricky.

Below code can be used to enable or clear a particular radio button.

enableRadioButton($(“[id*=’RADIOFIELDNAME:0′]”));
clearRadioButton($(“[id*=’RADIOFIELDNAME:1′]”));

function enableRadioButton(obj)
{

var a = obj.parent();
obj.prop(“checked”, true);
a.parent().children(‘.ui-radiobutton-box’).addClass(
“ui-state-active”).children(“.ui-radiobutton-icon”)
.addClass(“ui-icon-bullet”).removeClass(
“ui-icon-blank”);
}
function clearRadioButton(obj)
{
var a = obj.parent();
obj.prop(“checked”, false);
a.parent().children(‘.ui-radiobutton-box’).removeClass(
“ui-state-active”).children(“.ui-radiobutton-icon”)
.removeClass(“ui-icon-bullet”).addClass(
“ui-icon-blank”);

}

Customize Portal Session Timeout Message

Sometimes client would like to customise the default message displayed when WebSphere portal session time’s out.

It can be done by following below steps

  1. Extract the file engine.properties to the portal_server_root/shared/app/nls directory.
  2. Edit engine.properties and change the “error.timeout” parameter to the message that you want to be displayed when session expires.
  3. Save and close engine.properties.
  4. Restart portal server.

For multilingual sites, the file can have a language suffix corresponding to the locale, for example, engine_es.properties for Spanish.

error.timeout = You are too much time away from desk .. your session expired {0}.
error.timeout.answer = If a session is inactive too long, it is terminated for security reasons. Please log in again.

I think there are other ways to do as well which I did not test , like modifying properties  wp.ui.jar in C:\Program Files (x86)\IBM\WebSphere\PortalServer\ui\wp.ui\shared\app

 

XSS – Sanatize Input

XSS is the most prevalent web application security flaw. XSS flaws occur when an application includes user supplied data in a page sent to the browser without properly validating or escaping that content.

There are many libraries online which can be used to prevent XSS but after trying most of the libraries I see AntiSamy library solves most of the scenarios.

The OWASP AntiSamy project is a few things. Technically, it is an API for ensuring user-supplied HTML/CSS is in compliance within an application’s rules. Another way of saying that could be: It’s an API that helps you make sure that clients don’t supply malicious cargo code in the HTML they supply for their profile, comments, etc., that get persisted on the server. The term “malicious code” in regards to web applications usually mean “JavaScript.” Cascading Stylesheets are only considered malicious when they invoke the JavaScript engine.

Customized Anti Sammy XML can be found here

antisamy-customized-1-4-3


import org.owasp.validator.html.*;

import java.util.regex.Pattern;
public class WebSecurityAPI {

private static final String POLICY_FILE_LOCATION = "com/application/security/policy/antisamy-customized-1.4.3.xml";
/*
* returns sanitized HTML*/
public static synchronized String sanitizeHTML(String input) throws PolicyException, ScanException {
ClassLoader CLDR = WebSecurityAPI.class.getClassLoader();
Policy policy = Policy.getInstance(CLDR.getResourceAsStream (POLICY_FILE_LOCATION));
AntiSamy as = new AntiSamy();
CleanResults cr = as.scan(input, policy, AntiSamy.SAX);
return cr.getCleanHTML();
}
}

 


import com.application.security.util.WebSecurityAPI;

/**
* @author Shiva Arvapalli
*
*/
public class SanatizeTest {

public static void main(String[] args)
{
try {
String dirtyInput = "\" Pour ac'c�der au journal de test<script>alert(1)</script>onMouseOver=\"alert(1);In anticipation of your t\"entative\" June 2016 Call to the Bar of Ontario, we ask that you select a call location by <strong>April</strong> 4 of this year.sd"; // Some fake input
String clearHTML=WebSecurityAPI.sanitizeHTML(dirtyInput);
System.out.println(clearHTML); // Do something with your clean output!
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

 

Accessibility Testing – Useful links

WAVE – Web Accessiblity Evaluation Tool

http://wave.webaim.org/extension/

The WAVE Chrome extension allows you to evaluate web content for accessibility issues directly within Chrome. Because the extension runs entirely within your web browser, no information is sent to the WAVE server.unnamed

 

NVAccess – Free screen reader software for testing accessibility of the website

http://www.nvaccess.org/

NVDA (NonVisual Desktop Access) is a free “screen reader” which enables blind and vision impaired people to use computers. It reads the text on the screen in a computerised voice. You can control what is read to you by moving the cursor to the relevant area of text with a mouse or the arrows on your keyboard.

 

  • Use NVDA to test software or website accessibility.
  • Ensure text, links, graphics etc. can be “read” by a blind person.
  • NVDA is free.
  • Easy to download.
  • Speech viewer (text) available as well as screen reader voice.

JSF redirect on page load

In JSF 2.0, you can use javax.faces.event.PreRenderViewEvent system event to perform custom logic before JSF page is displayed.

For eg : If user belongs to admin group you would like to redirect the user to Administration page and if its a normal user should be redirected to a different page.

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”&gt;
<html xmlns=”http://www.w3.org/1999/xhtml&#8221;
xmlns:h=”http://java.sun.com/jsf/html&#8221;
xmlns:f=”http://java.sun.com/jsf/core&#8221;
>

<f:event listener=”#{pageBean.isUserAdministrator}” type=”preRenderView” />

<h:body>

<h:outputText value=”Default Page ..” />

</h:body>

</html>


 

public void isUserAdministrator(ComponentSystemEvent event){
//If logged with admin ID
 if(userBean.getWpsadmin()!=null &amp;amp;amp;amp;&amp;amp;amp;amp; userBean.getWpsadmin().compareTo(Constants.WPSADMIN)==0)
 {
 //Redirect to admin page
 userBean.gotoPage(Constants.ADMINXHTML);
 }
else
{
//Redirect to normal page
}
 }
//Redirection ...
public void gotoPage(String pageName) {
 if (pageName != null) {
 FacesContext context = getFacesContext();
 UIViewRoot newView =
 context.getApplication().getViewHandler().createView(
 context,
 pageName);
 context.setViewRoot(newView);
 context.renderResponse();
 }
 }