XPage partial refresh with a script block - javascript

I'm trying to make my Data View look and feel a bit better, by adding some client side functionality.
In this case I made a script, that let's the user hover over a row and it shows it's detail.
The structure looks something like this:
The script block contains some basic jquery:
function x$(idTag){
idTag = idTag.replace(/:/gi, "\\:");
return("#"+idTag);
}
var dataView = x$('#{id:dataView1}');
var detail;
$(dataView + ' > table > tbody > tr').mouseenter(function (e) {
detail = $(this).attr('id').replace(':_row', '_detail');
detail = x$(detail);
$(detail).show();
});
$(dataView + ' > table > tbody > tr').mouseleave(function () {
$(detail).hide();
});
Everything works fine, until I click on one of the row expand/collapse buttons, at which point the script code stops working.
My guess is it has something to do with the partial refresh, that happens when I expand or collapse a level in the data view, and it doesn't reload the script block or reloads it wrong.
If I turn off partial refresh it keeps working afterward, but of course a full page refresh just to expand or collapse a row is too slow and not realistically usable
Any ideas?

The jQuery code only runs on the items it can see on the page - you need to change the selection criteria so that it runs as a delegated event. In this case whenever you move the mouseevent over the data view it will detect the selector which triggered the event and if that matches then it will run accordingly. This way it will run on all rows regardless of whether they were "on the page" before or after the partialRefresh.
http://api.jquery.com/on/
Try this instead
$(dataView).on ('mouseenter', 'table > tbody > tr', function (e) {
detail = $(this).attr('id').replace(':_row', '_detail');
detail = x$(detail);
$(detail).show();
});
$(dataView).on('mouseleave', 'table > tbody > tr', function () {
$(detail).hide();
});
Code not tested as I don't have your environment :)

Thanks to another source got a quick hack to help here.
Placed both the dataView and scriptBlock in a panel and then set the refreshID of the dataView to the panel's ID.

Related

Add div programmatically to a refreshing table

I am currently working on my own ColumnResizer for a table. I know that there are some PlugIns that are doing exactly this, but I would love to write my own one.
To create a resizable column I am appending a div to each th-Element of the table programmatically like this:
jQuery.each($("#table > table > thead > tr > th"), function() {
if(this.id !== ""){
var div = createDiv($(this).outerHeight());
$(this).append($(div));
$(this).css('position','relative');
this.width = $(this).outerWidth()
console.log(div)
}
});
The function "createDiv()" looks like this:
function createDiv(tableHeight){
var div = document.createElement('div');
$(div).css('top','0');
$(div).css('right','0');
$(div).css('width','2px');
$(div).css('position','absolute');
$(div).css('cursor','col-resize');
$(div).css('userSelect','none');
$(div).css('height',tableHeight + 'px');
return div;
}
This is working fine then entering the page.
The problem is that the table can be multi-paged. So you can switch between pages of the same table. Each page switch is refreshing the table and here is the problem: After such a refresh I cant append the div to the th-elements .... Its just not working. I am calling exactly the same methods when the table is being refreshed. I also added a timeOut because I thought that the table isnt finished loading yet but it also didnt help.
I already tried to add
$(document).ready()
but it also didnt work.
One funny thing is that then I am adding an
alert("test")
to the refreshTable() function, the divs are there after closing the alert.
Does any one know how to solve this problem?

Javascript stops running after the page is polled

I am creating a web page using primefaces and I have a script embedded so that I can toggle rows. In the page I also have a poll to update the contents of the page. When the page is first loaded the script runs perfectly, however once the page polls itself to update the contents the script stops working.
The script is from another stackoverflow post and I have no experience in javascript so I am not sure what part is causing this issue.
<script type="text/javascript">
$(document).ready(function() {
rowExpansion(PF('dtbl'));
});
function rowExpansion(dataTable) {
//dataTable should be the widgetVar object
var $this = dataTable;
//add the 'hand' when hovering on row
$this.tbody.children('tr').css('cursor', 'pointer')
$this.tbody.off('click.datatable-expansion', '> tr')
.on('click.datatable-expansion', '> tr', null, function() {
//toggle the current row the old toggler
$this.toggleExpansion($(this).find('div.ui-row-toggler'));
});
}
</script>
As per the advice given by #Kukeltje and #AdamS I fixed this issue by calling the function in the script at oncomplete in my poll object. The script was only being called at the page initialization and needed to be recalled whenever the poll was triggered. Was previously...
<p:poll interval="30" listener="#{dashboardBean.update}" update="reporttbl"/>
and is now...
<p:poll interval="30" listener="#{dashboardBean.update}" update="reporttbl" oncomplete="rowExpansion(PF('dtbl'))" />

Tree View Open it's respective Div in the right side

I have downloaded a Tree View Code and it is working fine. The code is in this way :
d = new dTree('d');
d.add(0,-1,'StratApps');
d.add(1,0,'First Folder','example.html');
d.add(2,1,'Packages','example1.html');
d.add(3,2,'Pkg_Load_Dim','example2.html');
d.add(4,2,'Pkg_Write_to_File','#');
d.add(5,1,'Interfaces','#');
d.add(6,5,'Int_Load_Order_Dim','#');
d.add(7,5,'Int_Load_Channel_Dim','#');
d.add(8,1,'Procedures','#');
d.add(9,8,'Proc_Update_Order','#');
d.add(10,8,'Proc_Process_Errors','#');
document.write(d);
Now I want to give the links to open respective Divs in the right-side. Can anyone help me in this regard...
You could try something along these lines:
$('.dtree a.node').prop('onclick', '').click(function(e) {
var href = $(this).prop('href');
$('#divOnRightSide').load(href);
e.preventDefault();
});
Basically, what you say is: for every node (i.e. link) there is in every dtree on the page, remove the onClick-event directly from the HTML and add a click event handler.
In this handler, get the href-attr, and load the content of that link into the div with id="divOnRightSide".
Then, so no page navigation is triggered, use e.preventDefault().
Hope this helps.
EDIT:
Here is a jsFiddle to demonstrate the purpose: jsFiddle.

How do I run a jQuery function when any link (a) on my site is clicked

I have a new site build on corecommerce system which does not have much access to HTML and non to PHP. Only thing I can use is JavaScript. Their system is currently not great on page load speed so I wanted at least customers to know something is happening while they wait 5-8 seconds for a page to load. So I found some pieces of code and put them together to show an overlay loading GIF while page is loading. Currently it will run if you click anywhere on the page but I want it to run only when a link (a href) on the site is clicked (any link).
I know you can do a code that will run while page loading but this isn't good enough as it will execute too late (after few seconds)
Anyway, this is my website www.cosmeticsbynature.com and this is the code I use. Any help will be great.
<div id="loading"><img src="doen'tallowmetopostanimage" border=0></div>
<script type="text/javascript">
var ld=(document.all);
var ns4=document.layers;
var ns6=document.getElementById&&!document.all;
var ie4=document.all;
if (ns4)
ld=document.loading;
else if (ns6)
ld=document.getElementById("loading").style;
else if (ie4)
ld=document.all.loading.style;
jQuery(document).click(function()
{
if(ns4){ld.visibility="show";}
else if (ns6||ie4)
var pb = document.getElementById("loading");
pb.innerHTML = '<img src="http://www.cosmeticsbynature.com/00222-1/design/image/loading.gif" border=0>';
ld.display="block";
});
</script>
Doing this will be easier if you include jQuery in your pages. Once that is done, you can do:
$('a').click(function() {
// .. your code here ..
return true; // return true so that the browser will navigate to the clicked a's href
}
//to select all links on a page in jQuery
jQuery('a')
//and then to bind an event to all links present when this code runs (`.on()` is the same as `.bind()` here)
jQuery('a').on('click', function () {
//my click code here
});
//and to bind to all links even if you add them after the DOM initially loads (`on()` is the same as `.delegate()` here; with slightly different syntax, the event and selector are switched)
jQuery(document).on('click', 'a', function () {
//my click code here
});
Note: .on() is new in jQuery 1.7.
what you are doing is binding the click handler to the document so where ever the user will click the code will be executed, change this piece of code
jQuery(document).click(function()
to
jQuery("a").click(function()
$("a").click(function(){
//show the busy image
});
How about this - I assume #loading { display:none}
<div id="loading"><img src="http://www.cosmeticsbynature.com/00222-1/design/image/loading.gif" border=0></div>
<script type="text/javascript">
document.getElementById('loading').style.display='block'; // show the loading immediately
window.onload=function()
document.getElementById('loading').style.display='none'; // hide the loading when done
}
</script>
http://jsfiddle.net/vol7ron/wp7yU/
A problem that I see in most of the answers given is that people assume click events only come from <a> (anchor) tags. In my practice, I often add click events to span and li tags. The answers given do not take those into consideration.
The solution below sniffs for elements that contain both events, which are created with jQuery.click(function(){}) or <htmlelement onclick="" />.
$(document).ready(function(){
// create jQuery event (for test)
$('#jqueryevent').click(function(){alert('jqueryevent');});
// loop through all body elements
$('body *').each(function(){
// check for HTML created onclick
if(this.onclick && this.onclick.toString() != ''){
console.log($(this).text(), this.onclick.toString());
}
// jQuery set click events
if($(this).data('events')){
for (key in($(this).data('events')))
if (key == 'click')
console.log( $(this).text()
, $(this).data('events')[key][0].handler.toString());
}
});
});
Using the above, you might want to create an array and push elements found into the array (every place you see console.log

JQuery Async postback issue, how do I fix this?

I have the following JQuery code which does similar functionality like Stackoverflow where the user clicks on the comment link and it displays the comments or in this case replies to a member's status update, generally it works great except when a member posts a new status update which updates the list of status updates using an ajax async postback in ASP.net MVC.
What happens is if you click on the new item in the list it brings them to a new page instead of doing what the JQuery is suppose to do.
<script type="text/javascript">
$(function() {
$("a[id ^='commentLink-']").click(function() {
match = this.id.match(/commentLink-(\d+)/);
container = $("div#commentContainer-" + match[1])
container.toggle();
if (container.is(":visible")) {
container.load($(this).attr("href"));
} else {
container.html("Loading...");
}
return false; //Prevent default action
});
});
</script>
Note: I think what is causing it is the fact that the new item in the list isn't actually on the page as the list was updated through the ajax so the new html isn't there until the page is refreshed.
Update Okay how would I use this live/event functionality that Paolo Bergantino spoke of in his answer to trigger an ASP.net MVC ActionResult?
Check out the new Events/live feature in jQuery 1.3
Binds a handler to an event (like click) for all current - and future - matched element.
So as you add new items, jQuery should add the click event to them with this.
If for some odd reason you do not want to upgrade to jQuery 1.3, you can check out the livequery plugin.
EDIT in response to update:
The actual code to use .live would be something like this:
$(function() {
$("a[id ^='commentLink-']").live('click', function(event) {
match = this.id.match(/commentLink-(\d+)/);
container = $("div#commentContainer-" + match[1])
container.toggle();
if (container.is(":visible")) {
container.load($(this).attr("href"));
} else {
container.html("Loading...");
}
event.preventDefault();
});
});
The changes that were made are mostly in the 2nd line, where
$("a[id ^='commentLink-']").click(function() {
was replaced by
$("a[id ^='commentLink-']").live('click', function(event) {
I am now also receiving the argument event to use for event.preventDefault(); which is the way you are recommended to stop events by jQuery. If return false; does the trick, though, you can keep that.
I haven't used .live yet, but I think that should do the trick. Make sure that you get jQuery 1.3 in your server before trying this, though. :)

Categories

Resources