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

b3

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

b4

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

b5

We then load up the dialog

b6

Run the JavaScript to cause a partialRefresh

b7

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

Conclusion

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

Advertisements

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.

Introduction

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

nr1

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

nr2

The code change looks like this

nr3becomes

nr4

 

 

Decoupling your CSS from your JavaScript, a “well no duh” moment

This weekend I had one of those “oh DUH” moments which I have been struggling with for quite some time. How can I better structure my jQuery selectors and make the code more maintainable? I came across this excellent article – Decoupling your HTML CSS and JavaScript and it all came into focus.

The problem

Using JavaScript selectors (dojo or jQuery) in XPages can be a problem because of the id naming scheme used by the JSP generator “id=”view:_id1:_id2:link5” and how this falls over in a selector. So an alternate to not having to mess with is attributes is to use class selectors $(‘.class’) which is actually much simpler and less troubling to get your head around.

When you are using class selectors for a DOM element which already has a class then awesome I don’t have to add any more classes. Using this bootstrap example there are multiple classes I can get a hold of to manipulate the dialog contents.

 <div class="modal fade myModal" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
			<button type="button" class="close modal-maxmin" aria-hidden="true">
				<i class="icon-external-link"> </i>
			</button>
			<button type="button" data-dismiss="modal" class="close" aria-hidden="true">
				<i class="icon-remove"> </i>
			</button>
          <h4 class="modal-title">modal-title</h4>
        </div>
        <div class="modal-body">
         modal-body : HERE GOES THE MESSAGE
        </div>
        <div class="modal-footer">
	        <div class="btn-group">
	          <button type="button" class="btn btn-default modal-cancel" data-dismiss="modal">CANCEL</button>
	          <button type="button" class="btn btn-primary modal-ok">OK</button>
	        </div>
        </div>
      </div><!-- /.modal-content -->
    </div><!-- /.modal-dialog -->
  </div><!-- /.modal -->

To add something to the body of the dialog I would do something like this

  $(".modal-body").html('Hi Marky')

The other problem

This example is very “coupled” code whereby my JavaScript selector is coupled to the real class file used by the HTML code. In reality what it means is that if I have to change the classname for some reason (hmm an example – oh I don’t know – going from Bootstrap2 to Bootstrap3 for example) then my JavaScript breaks down. While tightly coupled code is easy to follow, easy to create initially, it can be an absolute nightmare in the long run.

The epiphany moment

As I am reading Philip Walton’s article  I am struck by the “oh well no duh” moment when he talks about using js-* as a naming convention for classes which only exist for JavaScript selection.

  • My personal recommendation is to use a prefix for all JavaScript hooks. I use js-*. That way, when a developer sees such a class in the HTML source, she’ll know exactly where to look to discover its purpose.

Well no duh – brilliant idea!

In all senses this makes perfect sense:

  • The developer does not have to search through CSS files looking to see if you used the class as a selector as a real CSS marker
    • (well ok they changed something and the CSS broke, then they started to look for it)
  • It is immediately apparent from looking at the HTML that there is some dojo or jQuery selection/manipulation going to go on in this area because of the js-* class naming scheme
  • Within eclipse you can do a quick search and find out what is trying to manipulate this area before you go and ruin it

The new code

A very simple change to the modal-body but this then decouples my code form the bootstrap code – allowing me to make changes to the bootstrap classes int he future without breaking my JavaScript

 <div class="modal fade myModal" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
			<button type="button" class="close modal-maxmin" aria-hidden="true">
				<i class="icon-external-link"> </i>
			</button>
			<button type="button" data-dismiss="modal" class="close" aria-hidden="true">
				<i class="icon-remove"> </i>
			</button>
          <h4 class="modal-title">modal-title</h4>
        </div>
        <div class="modal-body js-modal-body"> <!-- js-modal-body change here -->
         modal-body : HERE GOES THE MESSAGE
        </div>
        <div class="modal-footer">
	        <div class="btn-group">
	          <button type="button" class="btn btn-default modal-cancel" data-dismiss="modal">CANCEL</button>
	          <button type="button" class="btn btn-primary modal-ok">OK</button>
	        </div>
        </div>
      </div><!-- /.modal-content -->
    </div><!-- /.modal-dialog -->
  </div><!-- /.modal -->

To add something to the body of the dialog I would now select the js-* class not the modal-body itself

  $(".js-modal-body").html('Hi Marky')

Comment

One of the things I love about my career is that it is an “always learning” experience for me. There are times like this where you think to yourself that is an awesome idea and you are very happy to learn it – and at the same time feel so stupid that you didn’t think of it yourself before 🙂

XPages ND9 (Dojo 1.8) does not work with other AMD loaders (and the work around)

Today I took a new jQuery plugin that I was playing with from an R8.5.3 environment where it worked, to an R9 environment and it failed – I figured it had something to do with something I had been reading about over the last month and in fixing my problem this lead to a more serious realization that I KNOW other people are also going to come across.

Background

A brief scan of the last month’s discussions on Xpages and jQuery Mobile 1.3 reveals a number of posts started by Dave Leedy regarding the use of IBM Notes Domino 9 and jQuery Mobile 1.3

http://notesin9.com/index.php/2013/04/20/jquery-mobile-seems-incompatible-with-xpages-in-domino-9-0

http://hasselba.ch/blog/?p=1216

http://stackoverflow.com/questions/16058039/jquery-mobile-in-xpages-passing-parameters

http://www.eknori.de/2013-04-21/followup-jquery-mobile-seems-incompatible-with-xpages-in-domino-9-0/

What’s going on?

I saw the following Tip from Sven Hasselbach (very smart man!) on Dave Leedy’s blog post

Looks like an AMD loader problem with Dojo & JQM. I have tried out to disable the Factory scan in a test page and this worked for me. To do this I have added the following parameters in the xsp.properties:

xsp.client.script.dojo.djConfig=dojo-amd-factory-scan: false

Maybe this can help you with your problems in ND9.

This lead me to this bug report

https://bugs.dojotoolkit.org/ticket/15616

make dojo work with other AMD loaders

Which then lead me to the realization that this is a bigger issue than just JQM 1.3 and I solved my problem and here is how.

Solution (ND9)

Within the Package Explorer  (Window—open perspective –> xpages) in the WebContent folder for your database you will find the xsp.properties file (as described http://heidloff.net/home.nsf/dx/06172011015521AMNHE8Y7.htm)

xsp1

Click to open the Source Tab

and enter the following

xsp.client.script.dojo.djConfig=dojo-amd-factory-scan: false

And Save – that’s it

Result

If you look at the source code of the created XPage you will see that the new parameter has been added to the script tab creating the dojo.js as a djConfig property

xsp3

doing a quick search explains what this property does

http://dojotoolkit.org/documentation/tutorials/1.8/dojo_config/

“For example, we could disable the amd factory scan (scanning the module for CommonJS require(module) statements to load as deps) with…”

Not only does that solve the problem with jQuery Mobile, it also solved my problem with the jQuery Table plugin which I wanted to use, which used require.js to load the jQuery dataTable plugin.

GENIUS

thank you Sven Hasselbach (again!)

jQuery in XPages #19 – Shadow (Add eye catching drop shadows to your page elements)

In this article I will describe how to implement and use the jQuery shadow plugin to create great looking shadowed panels within your XPages application.

Demonstration

The XPages integration of shadow is demonstrated here

Download

The demonstration database can be downloaded from the link above or from here

Shadow

Introduction

“Adapted from Nicholas Gallagher’s CSS drop shadows without images demo

Adding “depth” to the visual aspect of your website is one of those things which can make them “pop” (pun intended). Using the shadow plugin, one line of code can be the difference between “meh” and “wow”.

Browser support?

Here’s the nice bit IE9, Firefox 3.5 Chrome, Safari – which means it works in XPiNC as well, and that’s sweet!

shad4

How does it work?

The main driver behind this plugin is really Nicholas Gallagher’s CSS drop shadows without images demo. The plug author just wrapped it as a jQuery plugin to make his and everyone else’s life easier.

Using the plugin could not be easier. Using the normal jQuery selector you identify the design element(s) you want to add a shadow to and then determine which type of shadow to add.

We add the plugin to the WebContent folder within our database and reference it in our source code

<script src="jquery-shadow/jquery.shadow.js"></script>
<link rel="stylesheet" href="jquery-shadow/jquery.shadow.css" />

And then add the code to call the plugin updating the elements with the vpDemo class

   $('.vpDemo').shadow('raised')

Examples
The first example you can see on the website is just a simple view panel. You click the but to. And you can see the effect.

shad1

The second example is an xe:widgetContainer widget from the extension library – this has a dojo stylesheet already applied but the shadow works nicely

shad2

The final example allows you appling it to the xp:panel.

shad3

Other styles

There are other styles  available other than ‘raised’ check out the website demo examples to see the others but be aware that they do not all work in all browsers.

Conclusion

As with most of the plugins in this series – for next to no effort, you get a big payoff in user interface enhancements. In this case even more so because this is all CSS3 and no images necessary.

Just a note

Many people ask me how long it really takes to create the demos and get the functionality into the database.

Well figured this out at 3pm this afternoon, finished work (at 5pm), cooked dinner for the kids, went to a school PTA meeting, put the kids to bed, started writing the blog and finished the demo by 11pm – so not long really 🙂

Caveat from the author

These are his words on the git hub repo – heed them, or not 🙂

“The purpose of this is to make it easier, as you don’t need to remember the specific css class names.

However, this is extremely bad practice… and should not be used for a production site, but feel free to use it for prototyping…”

Webinar – jQuery: The World’s Most Popular JavaScript Library Comes to XPages – April 23rd

I am very pleased to announce that as part of the TLCC 2013 XPages Webinar Series with Teamstudio I have been invited to give a webinar presentation of my IBM Connect 2013 presentation on jQuery. In this webinar I will be going through the slides and showing some demonstrations of how to use jQuery in XPages. There will also be a question and answer session at the end of the presentation for all those who are interested.

 

Tuesday,April 23rd – 10:30 A.M. to noon, Eastern U.S. time

Whether you want to add some serious eye candy to your XPages Applications or just want to do more with less code, jQuery, the world’s most popular JavaScript framework can help you. Come to this webinar and find out how you can use some of the thousands of jQuery plugins, in harmony with Dojo, within your XPages applications to create a better experience not only for your users, but for you as a developer. In this webinar, we’ll look at how jQuery works, how to add it to your XPages, and how a complete JavaScript beginner can take advantage of its power. We’ll demonstrate many working examples —  and a sample database will be provided.

 

For more information please look at the TLCC website link below and sign up

http://www.tlcc.com/admin/tlccsite.nsf/pages/xpages-webinar?opendocument

jQuery in XPages #18 Galleria (Easy to use Picture Carousel)

In this article I will describe how to implement and use the Galleria jQuery plugin to create a powerful picture carousel within your XPages application

Demonstration

The XPages integration of Galleria is demonstrated here

Download

The demonstration database can be downloaded from the link above or from here

Galleria

Introduction

“Galleria is a JavaScript image gallery framework that simplifies the process of creating beautiful image galleries for the web and mobile devices.”

I came across this carousel while I was researching my talk for IBMConnect 2013 and I was amazed by the simplicity, how powerful it was and how in depth and easy to understand the help documentation was. This article may be short and sweet because the plugin is that easy to implement!

Take a look at the example page http://galleria.io/

How does it work?

Looking at the documentation page there is a myriad of information on how to make the carousel you really want. The Beginner’s Guide is one of the best I have seen for any plugin. It is a step by step instruction on how to create the carousel in your web page including how to add jQuery.

We have to change that slightly to make the carousel work in our XPage – but only a little….

Download the plugin files from here http://galleria.io/download/

We add the jQuery library and the Galleria library file(s) to the database by adding them to the Web-Contents folder accessible via the package explorer.  (Window–>Show Eclipse Views–>Package Explorer) and drag and drop the two libraries from your computer into the “js” folder. We also add the themes and css files to the WebContent folder in the galleria folder.

gal1

We add the libraries to our XPages like this in the source panel

<script src="js/galleria-1.2.8.min.js"></script>

Using the information on the Beginner’s guide we also add the style

<style>
	#galleria{ width: 700px; height: 400px; background: #000 }
</style>

as well as the code to load the carousel once the page is loaded

Galleria.loadTheme('galleria/themes/classic/galleria.classic.min.js');
Galleria.configure({
   transition: 'fade',
   lightbox: true,
   imageCrop: true
});
Galleria.run('#galleria');

Once this is added to the page we just need to add some images…..In the beginners guide it staes that we have to just add some images into the galleria DIV

<div id="galleria">
    <img src="photo1.jpg">
    <img src="photo2.jpg">
    <img src="photo3.jpg">
</div>

but in our case we going to pull the pictures from notes documents in a view. In the same way as we did for the prettyphoto lightbox example we are going to add a view as a data source and use a repeat control to add the images to the page itself.

The data source

<xp:this.data>
	<xp:dominoDocument var="imageDoc" formName="imageHolder"></xp:dominoDocument>
	<xp:dominoView var="imagesView" viewName="images"></xp:dominoView>
</xp:this.data>

and the repeat control placing the images inside the galleria DIV

<div id="galleria">
	<xp:repeat id="repeat1" rows="30" value="#{imagesView}" var="imageRepeat">
		<xp:image id="Image1">
			<xp:this.url><![CDATA[#{javascript:"#{imageRepeat.imagePath}"}]]></xp:this.url>
		</xp:image>
	</xp:repeat>
</div>

And that is the absolute basic carousel (not that much different from the prettyphoto lightbox really at this point”

So what’s the difference with this one then?

Well it looks different, that is often a deciding factor when trying to impress your customer – which do they prefer the look of?

There are significantly more options to this carousel than the prettyphoto lightbox and this carousel has been optimized for mobile which the prettyPhoto has not (as far as I can tell). Let’s take a look at some of them…

Galleria comes with the following options:

  • Theming (allowing the developer to use pre-build settings to change the colors surrounding the carousel and the speed of the show)
  • Fullscreen capability
  • Responsive mobile view with swipe actions
  • An extensive API

In real words what does this mean? It means that you have almost absolute control over everything which happens within the slideshow or within the picture popups. Look at the optional themes as well. There are different themes you can buy which would serve you well if you were trying to implement this in a commercial site or if you just wanted to pump up an internal site.

In my example I have added a number of options to the carousel which give it some features. You should look seriously into the API to see what is possible.

Galleria.loadTheme('galleria/themes/classic/galleria.classic.min.js');
	Galleria.configure({
		transition: 'fade',
		lightbox: true,
		showCounter: true,
		showInfo: true,
		showImageNav: true,
		imagePan: true,
		imageCrop: true
	});
Galleria.run('#galleria');

Demonstration

Check out the demo(s)

The XPages integration of Galleria is demonstrated here