Thursday, March 13, 2008

Highlighting current ADF Table row by Javascript

Hi,

I played a little bit with adf table row highlighting this afternoon.
See demonstration.

I found maybe not better (in comparison to my previous post) but definitely easier solution based only on javascript.

Some notes:
- solution depends on structure of generated html table so if the structure is changed in next JDeveloper version (I used 10.1.3.1), the code will not work
- I don't think it will work without modification when there is a partial rendering used inside the table. I didn't test it.

Implementation into your page is easy:
  1. Add javascript code to your application (source is bellow)
  2. Add reference to the javascript into your page
  3. Add onload="onBodyLoad()" to body tag
  4. Edit javascript code and change firstRadioId variable value. It is "result id" of af:tableSelectOne element. If you don't know this result id, just set the element id to some value, run page and find it in html source code. Default value is 'table:0:rowSel' so you can also set table id to table, tableSelectOne id to rowSel, use af:form instead of h:form and then leave the firstRadioId value unchanged

Javascript source code (highlihgt.js):
var currentRowColor = '#ddddff';
var selectedRowColor = '#ffcccc';
var firstRadioId = 'table:0:rowSel';

var lastRow;
var lastBackgroundColors = new Array();
var lastSelRow;
var lastSelBackgroundColors = new Array();

function mouseOverRow(tableRow) {
var j = 0;
for (var i = 0; i < tableRow.childNodes.length; i++) {
lastBackgroundColors[j++] = tableRow.childNodes[i].style.backgroundColor;
tableRow.childNodes[i].style.backgroundColor = currentRowColor;
if (tableRow.childNodes[i].firstChild) {
if (tableRow.childNodes[i].firstChild.nodeName.toLowerCase() == 'input') {
lastBackgroundColors[j++] = tableRow.childNodes[i].firstChild.style.backgroundColor;
tableRow.childNodes[i].firstChild.style.backgroundColor = currentRowColor;
}
}
}
lastRow = tableRow;
}

function mouseOutOfRow(currentRow) {
if (lastRow) {
var j = 0;
for (var i = 0; i < lastRow.childNodes.length; i++) {
var bgcolor;
if (lastSelRow && currentRow == lastSelRow) {
bgcolor = selectedRowColor;
} else {
bgcolor = lastBackgroundColors[j++];
}
lastRow.childNodes[i].style.backgroundColor = bgcolor;
if (lastRow.childNodes[i].firstChild) {
if (lastRow.childNodes[i].firstChild.nodeName.toLowerCase() == 'input') {
if (lastSelRow && currentRow == lastSelRow) {
bgcolor = selectedRowColor;
} else {
bgcolor = lastBackgroundColors[j++];
}
lastRow.childNodes[i].firstChild.style.backgroundColor = bgcolor;
}
}
}
}
}

function highlightRow(selectedRow) {
if (lastSelRow && lastSelRow == selectedRow) {
return;
}

var j;
if (lastSelRow) {
j = 0;
for (var i = 0; i < lastSelRow.childNodes.length; i++) {
lastSelRow.childNodes[i].style.backgroundColor = lastSelBackgroundColors[j++];
if (lastSelRow.childNodes[i].firstChild) {
if (lastSelRow.childNodes[i].firstChild.nodeName.toLowerCase() == 'input') {
lastSelRow.childNodes[i].firstChild.style.backgroundColor = lastSelBackgroundColors[j++];
}
}
}
}

if (selectedRow.childNodes[0] && selectedRow.childNodes[0].firstChild) {
rowSelector = selectedRow.childNodes[0].firstChild;
rowSelector.checked = true;
}

j = 0;
for (var i = 0; i < selectedRow.childNodes.length; i++) {
lastSelBackgroundColors[j] = lastBackgroundColors[j];
j++;
selectedRow.childNodes[i].style.backgroundColor = selectedRowColor;
if (selectedRow.childNodes[i].firstChild) {
if (selectedRow.childNodes[i].firstChild.nodeName.toLowerCase() == 'input') {
lastSelBackgroundColors[j] = lastBackgroundColors[j];
j++;
selectedRow.childNodes[i].firstChild.style.backgroundColor = selectedRowColor;
}
}
}
lastSelRow = selectedRow;
}

function onBodyLoad() {
if (document.getElementById(firstRadioId)) {
var tableRow = document.getElementById(firstRadioId).parentNode.parentNode;
while (tableRow) {
tableRow.onmouseover = function() {mouseOverRow(this);}
tableRow.onmouseout = function() {mouseOutOfRow(this);}
tableRow.onclick = function() {highlightRow(this);}
tableRow = tableRow.nextSibling;
}
}
}
Update:
Today I found I have problem when the table contains page navigation. I will try to solve the problem soon.

Rado

Tuesday, January 16, 2007

ADF: Oracle Form like overflow in ADF Faces + current row highlighting

This is step-by-step instruction how to create Oracle Forms like overflow layout in ADF Faces and how to highlight selected row in data table.



1. In your adf faces page change form tag from h:form to af:form to have simple item ids.

2. Create overflow.js javascript file with this method:

function selectRow(itemClicked, tableId, radioId) {
var rowId = itemClicked.id.substring(itemClicked.id.indexOf(":") + 1,
itemClicked.id.lastIndexOf(":"));
radioItem = document.getElementById(tableId+":"+rowId+":"+radioId);
if (!radioItem.checked) {
radioItem.click();
}
}

3. Attach the javascript to your page with:

<script src="overflow.js" type="text/javascript"> </script>

Change path of js file as needed.
Note: there must be a space character between <script> tag and enclosing </script> tag otherwise the generated html code will not be correct.

4. Drop your data source on the page as an adf table and choose desired columns. Drop the same data source as an adf form under the table and choose items you want to see in overflowed block.

5. Enable select one selection in the table

6. Give the table id = tbl, selection radio button (tableSelectOne component) id = selRow

7. Enable Auto Submit for the tableSelectOne radio button

8. Set overflowed panelForm partialTriggers to table id "tbl"


9. Add these properties to each table item:

styleClass="#{row.rowKeyStr == bindings.YourIterator.currentRowKeyString ?
'currentRow' : ''}"
onfocus="selectRow(this, 'tbl', 'selRow')"

where "YourIterator" is name of your data source iterator and "currentRow" is name of css skin selector for highlighed items. The selector could look like:
.currentRow {
background-color: rgb(255,255,181);
}

Now you can run the page.
Mouse click on any table item will change current row and the row will be highlighed. Overflowed block will always contain values from the current row.

You can temporarily download zipped JDeveloper 10.1.3.1 demo applicaton of adf overflow from here.
It is based on emp and dept tables from scott db schema.

Rado