I have two reports. Clicking on a column link in the primary report reveals details about it in the secondary report, and clicking the link refreshes the page (Maybe if only the second report was refreshed using AJAX I wouldn't have the following problem, but I figure this will be harder to implement and maintain).
I have a javascript function like this to highlight the row:
function highlight(pThis) {
$x_RowHighlight($x_UpTill(pThis,'TR'), 'pink');
}
But the row of course does not remain highlighted when the page refreshes. I would love to maintain the session state of pThis, if that is possible.
I also have a requirement to place a next button in the secondary report, that would show the details of the next row in the primary report, and highlight that row as well.
Any suggestions?
I have two reports. Clicking on a column link in the primary report reveals details about it in the secondary report, and clicking the link refreshes the page (Maybe if only the second report was refreshed using AJAX I wouldn't have the following problem, but I figure this will be harder to implement and maintain).
I have a javascript function like this to highlight the row:
function highlight(pThis) {
$x_RowHighlight($x_UpTill(pThis,'TR'), 'pink');
}
But the row of course does not remain highlighted when the page refreshes. I would love to maintain the session state of pThis, if that is possible.
I also have a requirement to place a next button in the secondary report, that would show the details of the next row in the primary report, and highlight that row as well.
Any suggestions?
Share Improve this question edited Jan 10, 2013 at 18:33 asgoth 35.8k12 gold badges91 silver badges98 bronze badges asked Jan 10, 2013 at 18:21 Matthew MoisenMatthew Moisen 18.4k32 gold badges146 silver badges249 bronze badges 1- Does your primary report contain some sort of unique key by any chance (such as an ID), in the HTML? And not in a column that can be hidden by the user? There are several issues that make this technique hard to achieve with an IR. – Tom Commented Jan 11, 2013 at 8:53
3 Answers
Reset to default 2I've put together an example page with all code on it: http://apex.oracle./pls/apex/f?p=54687:39
I've made it a bit more involved because i wanted to account for a column link. When the link is clicked, the row has to bee highlighted aswell. Note that it will only work as long as you remain on the same page (or rather, as long as you are on the same IR page) like this. I now even notice that it'll keep the row colored when you navigate to the page and reset pagination - oh well, this is a good jumping point.
I used the rowindex for a good reason: a good solution for an IR doesn't really exist, and will always be very much custom coded. You'd actually need a value(or values) by which you could uniquely identify rows. That gives some problems since for example hidden columns are not rendered in the HTML. If it is in column, it could very well be that users can hide or in some way remove the column from the html (don't display it, apply grouping,...).
I've edited my example application page to include a way to deal with classic reports too, after viewing Matthew's own answer. I'll try to pick it apart a bit.
1) i wouldn't 'hide' my column by reducing the width. Just hide your column using the column attributes and change the type to hidden.
2) you don't really need a column item, unless you really mean to remember that. But i don't really see the point of it unless you allow clicking an entire row (as i did in my IR example, but i dismissed that idea for the classic report)
3) (a+b+c) I did this pletely different. I think it is a much better way to assign a class to the row element, as this allows much better manipulation and traverse. The $x_RowHighlight
function adds a style
attribute to the td
elements, and i don't like that. Controlling the style through a class and CSS is much more versatile.
I'd also argue that AJAX is not required here! When you click the link, you can directly set the item value and not go through an ajax call. I'd also argue that this does not need to be a synchronous call (which htmldb_Get is by default), but can be asynchronous as to not make the browser wait for a return (there is none).
Nevertheless, you could require ajax if you want to set it up as in my IR example so that clicking anywhere on a row would select the row.
As for selecting the next row: in my example you'd need to replace the changing of the input item to a click on the link column - shouldn't be to hard!
Performing an async call with htmldb_Get:
var ajaxRequest = new htmldb_Get(null, $v("pFlowId"), "APPLICATION_PROCESS=some_process", $v("pFlowStepId"));
ajaxRequest.addParam("x01","some value"); -- adds a parameter to the request, good for the x## variables
ajaxRequest.add("P1_EMPNO", "some value"); -- adds the key-value to p_args_names en values: page items!
ajaxRequest.getAsync(function(pResponse){
if(pResponse.readyState==4&&pResponse.status==200){
//call finished successfully
console.log(pResponse.responseText);
};
});
Ok. I found a solution before Tom posted his. His use of the JQuery index() function is fantastic; I wish I had known about that before hand. On the other hand, like Tom mentioned, the index() would be difficult or impossible to use in the event of pagination. What follows is The ROWID Column Method
,
I will split this into 2 answers, one for Classic Reports, and one for IR reports.
What follows is for CR.
1)Add a rowid as the first column in the SQL query and set its alias and thus header to " ". In a classic report, set the column width to 1, and under Column Formatting, in CSS Style, put display:none;
.
2a)Add the following hidden items to your page: PX_CURRENT_ROW
,PX_CURRENT_COLUMN
.
2b)If you want a Next and Previous button, and add the following buttons to your page: NEXT
, PREVIOUS
.
3)a In the page settings, under JavaScript, and in Execute when Page Loads, add the following:
bind_validations(); //Tom will note whom I have learned my APEX/JQ tactics from :)
highlight();
3b) In the page settings, under JavaScript, and in Function and Variable Declaration, add the following code for the three functions: identification, highlight, and bind_validations. We will start with the bind validations, which sends the TD of the column when the column link is clicked to the identify_row function. I am using a PLSQL function returning a SQL query for my reports, so all column headers as ID'd by JQuery are generic COL0x. Use an array with your column headers if you are using a regular query.
function bind_validations() {
var columnHeader = 'COL0';
for (var i = 2; i <10; i++) {
columnHeader = 'COL0' + i;
$("td[headers='" + columnHeader + "']").find('a').each(function(){
$(this).click(function(){
if ($(this).text.length != 0) { //necessary for next/previous buttons
identification(this);
window.location.href=this.href; //necessary for next/previous buttons
}
});
});
}
}
3b) Now es the identification function. This highlights the row temporarily before the page loads (nice effect for lag, as it lets the user know that row will be activated) using $x_UpTill on the TD passed to the function by the links that were binded in the previous function.
function identification(pThis) {
var currentColumn = $x_UpTill(pThis, 'TD');
var currentColumnHeader = $(currentColumn).attr('headers');
var currentRow = $x_UpTill(pThis,'TR');
var currentRownum = $(currentRow).find("td[headers='COL01']").text();
$x_RowHighlight(currentRow, 'pink');
//AJAX
/* As Tom mentions, AJAX is unnecessary: use f?p via column links instead.
In my particular situation, the idiosyncrasies render the passing of values
through f?p inappropriate. The purpose of passing the column header is for
the previous/next buttons, which will activate blank columns otherwise if
everyone of your columns has a link on it.
*/
var get = new htmldb_Get(null, &APP_ID., 'APPLICATION_PROCESS=dummy', &APP_PAGE_ID.);
get.add('PX_CURRENT_COLUMN' , currentColumnHeader);
get.add('PX_CURRENT_ROW', currentRownum);
gReturn = get.get();
get = null;
}
3)c Here is the highlight function:
function highlight() {
var currentRownum = $v('PX_CURRENT_ROW')
$("tr").each(function() {
var rownum = $(this).find("td[headers='COL01']").text(); //Use ' ' if you don't have generic columns like I do
if (parseInt(rownum) == parseInt(currentRownum)) $x_RowHighlight(this, 'red');
});
}
4) Now add dynamic actions on the next and previous buttons. For the NEXT button, do a dynamic action: Execute JavaScript Code, don't fire on page load:
var currentRownum = $v('PX_CURRENT_ROW');
var currentColumnHeader = $v('PX_CURRENT_COLUMN');
$("tr").each(function() {
var nextRownum = $(this).find("td[headers='COL01']").text();
if (parseInt(nextRownum) == parseInt(currentRownum) + 1) { //use -1 for the previous button
$(this).find("td[headers='" + currentColHeader + "']").find('a').trigger('click');
}
});
For the previous button change the condition to: `if (parseInt(nextRownum) == parseInt(currentRownum) - 1)
Could you achieve this with using cookies? I've used the jquery cookie plugin which I've found very useful.
I don't know anything about oracle-apex, but below is a basic javascript/jquery solution that might work,
$("tr").click(function (){
var activeTR = function (){
$(this).addClass('.active');
$.cookie("activeTR","activated",({ expires:7, path: '/' }));
};
});
if ($.cookie("activeTR") == "activated"){activeTR()}
Basically adding a class to the clicked tr, then adding a cookie to say which is the clicked tr, and then when the page loads it reapplies that class to the clicked tr.
Please note I haven't tried this so It wont work, but it's an idea to get you started.