Keeping your jQuery interface updated when using an XPages pager – XSP.addOnLoad()

In this article I will describe how the judicious use of SCRIPT tags XSP.addOnLoad() can keep your jQuery UI enhancements applied when used with a pager control and a repeat control. This article is a follow on from the original article Using jQuery to add table interactivity to your XPage .

Introduction

First of all – many thanks to Jeremy Hodge who pointed me in this direction !

In the original article I demonstrated how you can add some interactivity to a table with a few lines of jQuery. But there is a catch – when you use a pager and it reloads the data table, the jQuery enhancements are not reapplied to the table and the effect is lost 😦

Adding table interactivity to an XPage data table
Adding table interactivity to an XPage data table

Pager’s and partial refresh.

In this case we have a pager control and repeat control which looks something like this

<xp:div id="internalDiv">
	<xp:pager layout="Previous Group Next"
		partialRefresh="true" id="pager1" for="repeat1">
	</xp:pager>
	<table id="tabRepeat" cellpadding="5"
		style="width: 100%">

	<xp:repeat id="repeat1" rows="5" value="#{view1}" var="myPeople">
		TABLE ROWS HERE
	</xp:repeat>
	</table>
</div>

and when the pager it clicked to go to another page it refreshes itself and everything up to the 1st DIV parent – in this case xp:div id=”internalDiv”

When clicking on page 2, a partialRefresh is executed and internalDiv is refreshed. Any and all jQuery DOM manipulations are lost and not re-applied to the new code.

Interactivity lost after pager partialRefresh :(
Interactivity lost after pager partialRefresh 😦


XSP.addOnload()

XSP.addOnLoad() (Page 181-182 of the Portable Command Guide) allows us to trigger a JavaScript function once the object being worked on is Complete. This is in comparison to a normal SCRIPT tag which will not always be triggered when inserted into a DOM (depending on browser).
What’s also nice is that this function will not trigger until the load is complete. Analogous to the $(document).ready() jQuery function we need to make sure everything is loaded before we take action.

NOTE

XSP.addOnLoad() creates a listener function reference for the XSP.onLoad function and as such does not require the () at the end of the function name as you would normally expect.

So by adding an XSP.addOnLoad function call at the end of the DIV means that the jQuery is always called at the end of every partialRefresh,

<script>
function niceRows(){
	$(".reveal TR:odd").css('background', '#DDDDFF')
	$(".reveal TR").hover(function(){
		  $(this).css('cursor', 'pointer' ).toggleClass("active");
	});
}
</script>

<xp:div id="internalDiv">
	<xp:pager layout="Previous Group Next"
		partialRefresh="true" id="pager1" for="repeat1">
	</xp:pager>
	<table id="tabRepeat" cellpadding="5"
		style="width: 100%">

	<xp:repeat id="repeat1" rows="5" value="#{view1}" var="myPeople">
		TABLE ROWS HERE
	</xp:repeat>
	</table>

	<script>
		XSP.addOnLoad(niceRows)
	</script>

</div>
interactivity is retained even after paging
interactivity is retained even after paging

5 thoughts on “Keeping your jQuery interface updated when using an XPages pager – XSP.addOnLoad()

  1. Great sample, Marky.
    I could use it in my application where I have set complete table rows as links (not only a column – in a viewPanel).
    Now it also works with the pager 🙂 Thanks.
    Here’s the sample code:
    function linkRow(){
    $(‘.viewTable tr’).dblclick(function() {
    var href = $(this).find(“a”).attr(“href”);
    if(href) {
    window.open(href, “_blank”);
    }
    });
    }

    But do you have an idea how it will work with a categorized column?
    If I collapse a category this code is not reloaded and the doubleclick event is not triggered for the new data.

    Thanks,
    Alex

    • Thanks for the feedback Alex – I purposefully stayed away from viewPanel in the example because I could not find a way to insert my script tag inside of the viewPanel code – it is a lot more particular than the repeat control on how it handles things.

      My theory though (unproven as yet) is that anything is possible if you intercept the partialRefresh itself you should be able to add your jQuery function call into the onComplete event of the dojo. Check out the XSnippet I used to intercept the partialRefresh for xTypeAheadify.js…

      http://openntf.org/XSnippets.nsf/snippet.xsp?id=typeahead-onstartoncomplete-event

      Except in our case content[‘$$ajaxmode’] == “typeahead” is not the case it is in fact not there at all. So if you remove the if statement and generalize the code you should be able to get the onComplete event and use it.

      That’s the theory but I have not “done” it yet – but I would like to and wrap it as a jquery plugin as well so that we are able to apply it to any element on the page – but that is for later……

      let me know if this make sense 🙂

      one caveat which occurred to me – in your use case – once the section is collapsed – are you going to color that as an odd row or now? If you are going to color only content rows – how are you going to figure out which is content and which is collapsed section? I think there is enough to key off but I want to see what you think 🙂

      • Regarding the insertion of the script tag inside the viewPanel, you could try placing it inside the facet for the footerPager. Usually, the xp:pager is added inside xp:this.facets for the xp:viewPanel, but if you take the xp:key=”footerPanel” off the pager, wrap the pager in an xp:panel/xp:div and place the xp:key on that, you can place your script inside the panel/div and it should update when you fire the viewPanel’s pager events, etc.

  2. Daniel – you can, but I suggest for better structure of your code you only call the one function from addOnLoad – and then within that function call the others that you are looking for. Remember that multiple function calls will run asynchronously unless you structure them in a callback loop.

    🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s