jQuery event delegation

So it turns out that I may have blogged a moment too soon over the weekend….

While the following code works

	$('.modal').on('shown.bs.modal', function () {
			.append($('.modal-backdrop, .modal-scrollable'));

It only works the FIRST time – and if you had tested your code properly Mark you would have found this out to be the case. Too eager to blog weren’t we Marky……*pouts*

So anyway like all mistakes a good excuse for more learning – and in this case it wasn’t so much learning it was more muscle memory and more (oh duh Marky – which happens a lot)

The problem
What is happening is that the original code above is only binding to the modal once – and once the modal is being shown on the page and then hidden again apparently that event binding is being lost. I have no proof of this but I suspect that the DOM objects are being destroyed and recreated which is what is causing the loss ūüė¶

The solution
Event delegation – oh it is a wonderful thing once you get your head around it and extremely powerful – go read up about it here and check out the last example specifically

What I was doing is binding to the exact element and once that element is gone – no more binding.

What is Event Delegation?
Event delegation is basically the same thing as event binding, but it works on any matching element whether it exists yet or not.
What I mean to say is that this piece of code REALLY WORKS and I will explain

$('body').on('shown.bs.modal', '.modal', function () {
        .append($('.modal-backdrop, .modal-scrollable'));

In this example we are:

  • Selecting the Body
  • And then in the shown.bs.modal event of anything matching the .modal selector
  • do stuff as before.

So if you imagine a simple analogy of feeding a dog.

If you have a child – let’s say your son and you tell him that on the “breakfast event” put food in that exact blue dog bowl – he will do that

Being the obedient child that he is he will fill that bowl every day when it appears.

But being the obstinate child he is, when you replace *that* blue bowl with a new one he will not fill it because you told him to fill the old one

A fight ensues and he loses minecraft privileges!

You then change your instructions: ¬†On the “breakfast event” put food in any dog bowl which appears in the Kitchen. So even if you replace it every day he will have to still do as he is told and fill the bowl.

That is what Event Delegation is – telling the DOM to do things to anything which exists now and anything which appears in the future.

The way it works is because of the second selector – you are telling the DOM body to look for anything with a shown.bs.modal and bind to it. So even though my original dialog apparently lost the binding, in the new case it is automatically re-applied because of the delegated event on the Body

If only I had remembered that before blogging earlier…….

Ah well – we all learned something new

I wonder what I missed today………..

Making XPages partialRefresh work in a bootstrap 3 dialog box.

In this article I will improve on the solution I posted last week to my form submittal problem and actually provide a more elegant and robust solution.

The problem

Dave Leedy

I mean to say that Dave Leedy posed a problem to me last Friday which gave me pause for thought. Obviously he had come across this issue before. “Marky have you tried to do a partialRefresh inside of the bootstrap modal dialog?”. I had not and I knew that I had plans to…..

Then it struck me – of course the partialRefresh can’t work in the dialog because the dialog is outside of the form. The partialRefresh relies on the ability to post data back to the server (via the form) and the collect the response and re-draw. Of course it isn’t going to work.

The solution

As I said the other day – the bootstrap dialog is not purposefully removing itself from the form, it is moving itself to the end of the DOM tree. Why? I couldn’t say but it seems to be pretty consistent. So on the assumption it is nothing to do with the “form” I figured the easiest solution would be to put it back *into* the form once it was visible.

As we saw before when the modal is created there are two elements moved to the end – the dialog itself and the faded out background


Using a bit of jQuery magic we select those two DIVs and “append()” them back into the form. Using the append() method they are always added to the end of the target DOM element container. You should add this code to every page where you have a dialog. Add this code to a CSJS library and include it on every page where you have a bootstrap modal.

$(document).ready( function(){
	$('.modal').on('shown.bs.modal', function () {
		$('FORM').append($('.modal-backdrop, .modal-scrollable'));

  What does that mean exactly?

  • In the ‘shown.bs.modal’ event of the selected $(‘.modal’)
  • Get the $(‘FORM’) and .append() into it the two selected $(‘.modal-backdrop, .modal-scrollable’) DIVs

and then you get this


Once the modal is then inside the dialog we can post it to our hearts content.

We can prove that with a simple @Random within the dialog box and a quick code snippet in firebug

We add a “random” class to the computed text so that we can select it


We then load up the dialog


Run the JavaScript to cause a partialRefresh


Et voila a partialRefresh with a dialog. It also works of course with XPage controls and buttons and the like but this was just a simple way to demonstrate how to do it


Once we understand the DOM changes which are being made for a bootstrap dialog we are able to use jQuery to easily manipulate the  resulting DOM to be able to make our application work.


ADDENDUM – updated

Please see the jQuery Event Delegation blog post to understand why this approach is limited and needed to be updated….new solution provided

Why does hitting submit from within a bootstrap dialog not work?

In this article I will show why submitting an XPage from within a Bootstrap dialog does not work correctly and also discuss some options for working around the issue.


The bootstrap modal¬†rocks (In Marky’s opinion) and it can be enhanced with the Bootstrap-Modal extension which gives greater control and more options. But I came across an issue recently whereby I could not “Submit” from within a dialog. Well ok I could submit but none of the fields seemed to be updated.

The Dialog

Initially the bootstrap dialog code sits within the XPage quite happily and it is hidden by CSS.


But what happen when the dialog is displayed on the page? The HTML is manipulated and the modal dialog HTML code is moved within the DOM and apparently outside of the <form> tags.


I do not think that it is intentionally moved outside of the form – what is really happening is that it is being moved to the last entry within the DOM – the following highlights it better – it is moved to the last DOM element within the body


What does this mean?

Well what it means is that then you have a custom control displayed within the Dialog, and you try to hit a submit button from within the dialog, the fields are not “in the form” and therefore are not submitted back to the server. Simple answer once you figure it out (an “oh well no duh” moment)

So what can we do about it?

We have a number of options all of which are to do…….

  1. Do not submit from a dialog (not always practical)
  2. Looking at the bootstrap modal API event (http://getbootstrap.com/javascript/#modals-usage) we can see that there is a hidden.bs.modal event with this we know that the modal is closed. Once the modal is closed it is reinserted back into the DOM correctly in the same place as it was originally. Once that happens if the form is submitted then the fields are in the “<form>” tag and we are good to go.
  3. We can manipulate the form to “re-surround” the whole page including the dialog
  4. We can insert a new <xp:form> tag within the dialog and submit that one instead http://stackoverflow.com/a/9349329/1171653
    1. (in this author’s opinion embedded forms are just asking for trouble and should be avoided)

Whichever you prefer to do depends on your circumstances and needs from the code. If anyone has any other suggestions I would love to hear them!


Love Bootstrap, Love the Dialog, but like everything, sometimes you need to get a better understanding of how it works and tweak it a little.

Inserting a new Row into a viewPanel (any table) using jQuery

This is a short and sweet blog post showing how to programmatically add a new line into a table using jQuery.


I am playing around with some column ordering and I want to add some dummy data to a table – rather than go to the trouble of doing it on the back end I decided to do it using jQuery so that i can easily change the values using Firebug

The .before() function

The .before() function inserts a set of HTML “before” the selected DOM element. It has a companion .after() function¬†which unsurprisingly adds HTML after a DOM element.

Inserting a new row
I want to add my new line as the top row of this table


and I do this by:

  1. Selecting the first child in the viewPanel (class=.xspDataTable) tbody
  2. adding the new row before it
$('.xspDataTable tbody')    //select the tbody within the viewPanel
        .children(':eq(0)') //select the first child therein
        .before("<tr class='marky'><td>9</td><td>3</td><td>1</td><td>7</td></tr>")

Now why do I do that you ask? – good question. As I found out it turns out that the viewPanel has a TR in the header before the TBody – so if I select the first row in the table then I do not get the first “data row” so I go for the first child in the TBODY which is the TR element representing the first row I am looking for.

Here is what we get – short and simple


The code change looks like this