library.onLoad – what does it do and who loads last?

In this article I will demonstrate that there multiple methods for determining the “onLoad” event of you page and discuss which method you should use and when.

Introduction

Once upon a time when the world was young and we did not have JavaScript libraries we had the onLoad event of the document.

	<body onload="alert('Hi Marky')">

This caused some issues in itself because it indicated that the HTML was loaded – but did not have any knowledge of the images on the page and they might not have finished downloading – so this was not a reliable way of determining if the page was really loaded.

Then came the Library

If you are including functionality from a Library there is a high probability that the Library is doing some sort of Document Model (DOM) manipulation when the page loads – it has to do this to provide the functionality you are asking it to do.

Take your XPage as a prime example – you are including (well ok the XPage is including) the dojo Library and with that the XSP library built to provide XPage functionality. If you look at the source of an XPage containing a date control you will see this

<input id="view:_id1:_id2:_id39:inputText2" class="xspInputFieldDateTimePicker" type="text" name="view:_id1:_id2:_id39:inputText2" />

But if you look at the HTML created AFTER dojo and the XSP have done their magic the field looks like this!!

<span class="xspInputFieldDateTimePicker" style="display: inline-block;">
</span>
<div id="widget_view:_id1:_id2:_id39:inputText2" class="dijit dijitReset dijitInlineTable dijitLeft xspInputFieldDateTimePicker dijitTextBox">
	<div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" tabindex="-1" type="text" value="? " readonly="readonly" />
	</div>
	<div class="dijitReset dijitInputField dijitInputContainer"><input id="view:_id1:_id2:_id39:inputText2" class="dijitReset dijitInputInner" tabindex="0" type="text" value="" />
		<input style="display: none;" type="text" name="view:_id1:_id2:_id39:inputText2" />
	</div>
</div>

<span id="view:_id1:_id2:_id39:inputText2_Container" class="xspInputFieldDateTimePicker" style="display: inline-block;">
	<span class="dijit dijitReset dijitInline dijitButton xspInputFieldDateTimePicker">
		<span class="dijitReset dijitInline dijitButtonNode">
			<span id="dijit_form_Button_0" class="dijitReset dijitStretch dijitButtonContents" style="background-image: none; margin: 0px; border: none; padding-left: 0px; background-position: 0% 0%; background-repeat: initial initial;" title="">
				<span class="dijitReset dijitInline dijitIcon xspInputFieldDatePickerIcon">
				</span>
				<span class="dijitReset dijitToggleButtonIconChar">?</span>
				<span id="dijit_form_Button_0_label" class="dijitReset dijitInline dijitButtonText dijitDisplayNone">
				</span>
			</span>
		</span>
		<input class="dijitOffScreen" tabindex="-1" type="button" value="" />
	</span>
</span>

And that doesn’t happen in an instant – it takes time……and if we want to programmatically interact with the “new” date picker code we have to wait for the dojo and XSP to do their thang.

Library.onLoad
This is where library.onLoad comes into play – it is an event triggered when the library believes that the page is safe to interact with – i.e. everything it needs to do is complete.

dojo.addOnLoad

The dojo.addOnLoad page explains better than I can

dojo.addOnLoad is a fundamental aspect of using Dojo. Passing addOnLoad a function will register the function to run when the Dom is ready. This differs slightly from document.ready and body.onload in that addOnLoad waits until all dojo.require() (and their recursive dependencies) have loaded before firing.

XSP.addOnLoad

The XSP is a library built on top of a library and has dependencies on the dojo library.

In our XPage environment we have the onClientLoad event accessible from the XPage event section – this is actually the GUI equivalent to XSP.addOnLoad which is a programmatic function we have available through the XSP library.

onClientLoad
onClientLoad

jQuery – $(‘document’).ready()

jQuery’s version of this onLoad capability is described as follows:

While JavaScript provides the load event for executing code when a page is rendered, this event does not get triggered until all assets such as images have been completely received. In most cases, the script can be run as soon as the DOM hierarchy has been fully constructed. The handler passed to .ready() is guaranteed to be executed after the DOM is ready, so this is usually the best place to attach all other event handlers and run other jQuery code. When using scripts that rely on the value of CSS style properties, it’s important to reference external stylesheets or embed style elements before referencing the scripts.

These people are so much more eloquent that I 🙂

So if everyone fires when the DOM is ready then they should all fire at the same time…right?

Well that is what occurred to me and I wanted to find out – people have told me through the life of this blog that I should always use the XSP.addOnLoad because it fires when the XPage is ready – but if I use jQuery is that ready as well?

Experiment

It is really not all that complicated to test who fires first – what I created was a variable to track when the page started to load and then asked each library to subtract the time when they fired “when the DOM was ready” and write it to the page. This code sample was added to the top of my XPage so the variable “a” is created immediately when the page is loaded and each library then triggers when it is ready.

<script type="text/javascript">// <![CDATA[
		var a = new Date()
		document.write("Started at: "+a)

		$('document').ready(function(){
			// alert('jQuery')
			var b = new Date()
			document.getElementById('divJquery').innerHTML = b-a
			var s=document.createElement('div');
			s.innerHTML = "<div>"+"jQuery - "+(b-a)+"</div>"
			document.getElementById('iAmFinished').appendChild(s)
		})

		XSP.addOnLoad(function(){
			// alert('XSP')
			var c = new Date()
			document.getElementById('divXSP').innerHTML = c-a
			var s=document.createElement('div');
			s.innerHTML = "<div>"+"XSP - "+(c-a)+"</div>"
			document.getElementById('iAmFinished').appendChild(s)
		})

		dojo.ready(function(){
			// alert('dojo')
			var d = new Date()
			document.getElementById('divDojo').innerHTML = d-a
			var s=document.createElement('div');
			s.innerHTML = "<div>"+"dojo - "+(d-a)+"</div>"
			document.getElementById('iAmFinished').appendChild(s)
		})

// ]]></script>

and in the onClientLoad event


		<xp:this.script><![CDATA[
			var e = new Date()
			document.getElementById('divOnClientLoad').innerHTML = e-a
			var s=document.createElement('div');
			s.innerHTML = "<div>"+"onClientLoad - "+(e-a)+"</div>"
			document.getElementById('iAmFinished').appendChild(s)
			]]>
		</xp:this.script>

Demonstration

You can see the page I created to test this experiment here

http://demo.xomino.com/xomino/xPlay.nsf/xOnLoad.xsp

You will see that there are a lot of typeAhead and date picker fields on the page – the reason I did this was to slow down the loading of the page – The libraries were all firing very close together and I wanted to see if I could separate them by delaying the page loading – it didn’t see to make a difference they all fired with the same delay between them.

The results

Well I have to say I was surprised and very glad that I created this experiment because it will change how I determine when the DOM is ready in the future. You can keep testing this for yourself by refreshing the test page above but you will see consistently that the libraries fire in this order:

Library Time to
DOM ready (ms)
Dojo 198
XSP 197
onClientLoad (XSP) 198
jQuery 209

As you refresh the page you will see different load times but they are always grouped XSP, clientOnLoad

results of load order
results of load order

Why are these different?

Each library determines when they believe the DOM is ready differently – each one is assuming that the DOM is ready when everything is loaded for it’s own library (naturally dojo doesn’t care when jQuery is loaded). For some insight check this StackOverflow post out

How does the jQuery ready() function work?

From my experiments I noticed that dojo, XSP and onClient load were always no more than 1 milisecond apart and each one of them sometimes came first – i think there is an aspect of the fact that they are all trying to create a DIV and append it to the page (my test code) and that has some nominal time associated with it and they are all trying to append to the same DOM element – for the sake of statistical accuracy my observation is that dojo is usually the first to record a result but because it is not always first I cannot claim that categorically.

I also have to add that there is a discrepancy with the onClientLoad test because it does not use the same variable as the other libraries – because it is being added to the page in a different fashion it is not an identical test. I am not however going to add the whole of the code to the onClientLoad event because then I would be asking the onClientLoad event to trigger the other libraries which isn’t right.

Conclusion

So here is the important things to remember when you are developing your xPage

  1. Never use dojo.addOnLoad – it fires almost exactly the same time as the XSP but more importantly your xPage XSP library is not ready
  2. If you are using jQuery *always* use $(‘document’).ready()
  3. Otherwise use XSP.addOnLoad/onClientLoad

It is interesting to see that jQuery takes longer to be ready and why that is, is way beyond the comprehension of this developer but there is a clear separation and because almost all of my work uses jQuery in one fashion or another I will always use $(‘document’).ready()

Please feel free to argue my experimental methodology if you think it can be improved 🙂

Auto-focus – Do it! It’s just lazy not to.

In this article I will discuss the need as a developer to use an auto-focus on your XPages. You do this when the end-user needs to type something onto your webpage and should not have to use their mouse to click in the field first.

Introduction

You’ve been there – you go to a website internal or external to your company and you have to login in or type something into the page – the search field or something of that ilk. It is the only field on the whole page and you have to use your mouse to focus on the field – frustrating beyond belief and quite frankly, lazy on the part of the developer. It is a pet peeve of mine when something as simple as one line of code can make a big difference to the first thing a user does on your site.

Can you imagine going to Google.com and having to focus on the field to get started on your search? Stupid idea – or so you would think.

Login Pages

The login page is perhaps the most obvious thing – as the developer you should ALWAYS focus on the username field – it is just lazy not to! It is harder on the user to have to click in the field and they are entering your website with an irritation on their mind already.

Auto-focus on the Username field
Auto-focus on the Username field

 

So how do we do this?

Well it depends on what takes your fancy that day…..but this is normally something you would do within some <script> tags on your web page.

Using the plain old JavaScript method

  document.getElementById("username").focus()

In Dojo

  dojo.byId("username").focus()

In jQuery

  $("#username")[0].focus()

NOTE

We use the [0] to get the DOM Node element and use the HTML focus() method
.focus() when applied to a jQuery object is an event handler which determines what happens when you focus on something  – be careful to use correctly

$('#target').focus(function() {
  alert('Handler for .focus() called.');
});

In HTML5

The autofocus attribute of a field is new in HTML5 (thanks to David Walsh). You can also focus on a button and other DOM objects

<input autofocus="autofocus" />
<button autofocus="autofocus">Hi!</button>
<textarea autofocus="autofocus"></textarea>

Dojo Firebug Extension – from an XPage developer’s perspective

In this article I take a rather irreverent look at, and describe some what I was hoping would be, the useful capabilities of the dojo firebug extension available at https://addons.mozilla.org/en-US/firefox/addon/dojofirebugextension/

Introduction

I love firebug for my client side JavaScript development – for many reasons too numerous to mention here. If you have no idea what firebug is then you should google it and find out – USE IT and you will never go back…..

So what’s this Dojo extension all about then ?

Right off the bat I loved finding this quote “The Dojo Firebug Extension started as an internal IBM initiative to help IBMers working with Dojo.”, and more importantly got me straight off on the thought of what can this do for me in my XPages?

The documentation is available here – https://getfirebug.com/wiki/index.php/DojoFirebugExtension_Reference_Guide and as firebug extensions go – this one is fairly well documented – nice job 🙂

You have to download a different version based on your firebug and your firefox version….that’s kinda weird and disconcerting and they don’t have my version of firebug or firefox – but hey we truck on in hope.

So What does it do for me as an XPages developer?

Good question – let’s find out…

Well the first thing it showed me was how MASSIVELY complicated the Dojo integration with XPages is……check out some of these idTags on this Tab Container!! 😮

Dojo Firebug extension in action
Dojo Firebug extension in action

 

Open API documentation

This *could be* really useful – if you can get over how useless the API documentation site is – let me paraphrase…….IF you understand how the Dojo API documentation works this *could be* fantastically helpful…..

In my previous article on how I figured out how to use the Dojo Tab Container doLayout (where the screenshots come from) I was struggling to find out what I needed to make the Tab Panel heights dynamic. Would this have helped?….I was kinda bitter at this point as I figured it would have….so i soldiered on..

Select the tab container and look at the extension

Selecting open API documentation
Selecting open API documentation

 

and opening the API documentation

Dojo API documentation
Dojo API documentation

 

*yawns* – so not really – but stay with me

The next options *looks* more useful (so why did you show us the API link? Yes you guessed it…… it *is* ‘cos I hate you and I wanted to force you to look at Dojo API documentation – get over it and don’t ask daft questions)

Open Reference Guide Doc

Open Reference Guide Doc
Open Reference Guide Doc

 

Which shows you this…….

Dojo Reference Guide Documentation
Dojo Reference Guide Documentation

 

First of all I am really impressed that this actually links to the 1.8 version which was only released this week – but that is also not helpful because XPages 8.5.(What I am using) uses 1.6 so which a quite switch over on the right hand side

Switching to 1.6
Switching to 1.6

We get…

Aw Butts - really?/?
Aw Butts – really?/?

And I was just saying how awesome you guys were – CRAP.

As it turns out the plugin is too smart and not smart enough to detect 1) the version of dojo I am using and 2) that this feature it thinks I am using is available in 1.6…

DOH
DOH

DOH *grrr*

Que?

So I didn’t solve that problem but I did find another one – I noticed that IBM modified the Dojo specifically for the extlib!! …if you look at the code reference in the extension

Well that is kinda interesting I guess..
Well that is kinda interesting I guess..

[view:_id1:_id2:_id39:djTabContainer1 (Widget extlib.dijit.TabContainer)]

and when we select to go to the Reference Guide Docs – the URL it is sent to

http://dojotoolkit.org/reference-guide/1.8/extlib/dijit/TabContainer.html

You will see that extlib has been inserted into the URL

the REAL documentation is here

http://dojotoolkit.org/reference-guide/1.8/dijit/layout/TabContainer.html

dijit/layout and not extlib/digit.

If you look at an example from david walsh’s blog you can see the difference…

vive la difference
vive la difference

 

Anything else?

Well I found out how to manage FireFox profiles – http://www.howtogeek.com/howto/internet/firefox/use-multiple-firefox-profiles-at-the-same-time/ which is kinda useful – so I did learn something useful from this investigation.

There are a number of cool Dojo debugging capabilities if you are really into writing seriously with the dijits whereby you can subscribe to the data and watch it move all over the place – kinda cool – not helpful for XPage development though.

So is this really useful for an XPages developer?

Well I have to say from an purely educational perspective it is really interesting to get an insight into how the dijits work…

Some really complex cool stuff going on  in here
Some really complex cool stuff going on in here

 

But I think my overall impression of the extension is that it will not help an XPage developer develop their XPages at all in any sort of way

Shame really 😦

PS

Let me rephrase that last sentiment – I think this COULD be really useful if IBM were inclined to apply some time and effort to making a similar extension for XPages Dojo development – but isn’t the point of XPages is kinda so we don’t have to worry about Dojo…so it would be an uber-dojo-geek expert XPages developer tool only…meh…who wants to do that?? 😉

Shame really 😦

PPS

That is two blog articles in a row about dojo – don’t worry I am not going back to the dark side – jQuery still rocks my world 😉

Dynamic TabPanel height with Dojo TabContainer in XPages

In this article I will discuss how to make your Tab Panels dynamically resize to the size of their content. I will use the doLayout property of the dijit control, exposed through the extension library control properties in XPages Designer.

Introduction

The Extension Library provides us with many easy to use Dojo “containers” including the TabContainer and TabPanel. What is sometimes difficult to decifer though is how to configure the dojo container to bend to your will and meet your requirements.

The Problem

My problem was that I have a container with multiple tabs and some are really large and some are small. The out of box the box functionality provides the ability to size the TabContainer and it forces that size on all the panels. This leaves me with two options (see the demo):

  • Make all the boxes large enough to cover the largest panel
    • which looks daft on the panels with very little content
  • Make the overflow of the larger panels use a scroll bar
    • style=”overflow-y: auto”
    • This is “ok” but with a lot of scrolling it makes the panel difficult to use

The solution

So I was searching around Google and I could not find an answer to “dojo TabContainer dynamic resize” which was very frustrating – so I came upon the dojo documentation for the TabContainer. http://dojotoolkit.org/reference-guide/1.7/dijit/layout/TabContainer.html And experience has told me I am wasting my time with the Dojo documentation but I figured what the hey and clicked in……

Now I would rather stab my eyes out than read the dojo API documentation – but I have to hold my hand up and give them props for this one – it is right there in the demonstrations on the first page “A TabContainer with flexible height” – Brilliant!

The trick is to add doLayout=”false” to your dojo container – simple – and a working demonstration as well – well done sirs!!!

So then I went to the XPages designer to look and see if the property was there on the custom control – and yes it was – brilliant – and how absolutely 100% USELESS the help was for it……How is this helpful???

XPages designer help for the doLayout property of the TabContainer control
XPages designer help for the doLayout property of the TabContainer control

It would have been much more helpful to say “default=true – forces all the Tab Panels to be the same height as the TabContainer. Set to false to allow for flexible tab Panel height!”

The dojo API documentation says “If true, change the size of my currently displayed child to match my size” – written by closet programmers and not by real people, apparently.

Demo

Here is the simple demonstration of the difference – quite striking really

http://demo.xomino.com/xomino/xPlay.nsf/xTabContainer.xsp

Conclusion

Dojo reference guide actually helped………and I need to use it more often apparently.

(I still refuse to waste my time on the API documentation though)

The Moral

I think for me it is imperative to understand more about how the dojo containers work in their original environment – the CSJS library before attempting to use them in XPages. I realize this is contrary to the idea that we don’t “have” to understand them to use them in XPages – but actually – I now think it is essential

For more information check out the Dijit information – reference guide – real people speak!

http://dojotoolkit.org/reference-guide/1.7/dijit/info.html#dijit-info

HTML5 drag and drop demonstration in an XPage

I saw an article on HTML5 drag and drop and wondered how hard it would be in XPages.

Demonstration

Here is a link to the working demo of HTML5 drag and drop in an XPage – this is FF and Chrome only as drag/drop is not supported until IE10

How does it work?

I created an XPage and added a simple data table

Data Table
XPages Data Table

Going off the text in the article I tried to add the events to the Fruit label column – unfortunately you cannot add custom attributes to an xp:text

Cannot add custom attributes to an <xp:text
Cannot add custom attributes to an <xp:text

So once again – back to using dojo selectors to get what we want.

The HTML generated by the XPage creates all the fruit labels (Oranges, Bananas, Apples) with an id=blah:_1blah ending in “someFruit”

<tr><td class="xspColumn"><span id="view:_id1:_id2:_id31:viewPanel1:0:column3:someFruit" class="xspTextComputedField">Oranges</span></td>
<td class="xspColumn"><span id="view:_id1:_id2:_id31:viewPanel1:0:column1:computedField2" class="xspTextComputedField">2.0</span></td>
<td class="xspColumn"><span id="view:_id1:_id2:_id31:viewPanel1:0:column2:computedField3" class="xspTextComputedField">4</span></td>
</tr>
<tr><td class="xspColumn"><span id="view:_id1:_id2:_id31:viewPanel1:1:column3:someFruit" class="xspTextComputedField">Bananas</span></td>
<td class="xspColumn"><span id="view:_id1:_id2:_id31:viewPanel1:1:column1:computedField2" class="xspTextComputedField">1.0</span></td>
<td class="xspColumn"><span id="view:_id1:_id2:_id31:viewPanel1:1:column2:computedField3" class="xspTextComputedField">2</span></td>
</tr>

We can get a handle on these labels using dojo.query(“[id$=someFruit]”) which will get all elements with an id attribute ending in “someFruit”

Once we have all of those elements we can add a draggable and ondragstart attribute to them easily using dojo.attr

			dojo.query("[id$=someFruit]").forEach( function(node){
				 dojo.attr(node, "draggable", "true");
				 dojo.attr(node, "ondragstart", "dragIt(event);");
			});

Update – Thanks to Tim Tripcony for pointing this out
If you are using 8.5.3 you can add the custom attributes to the field in the designer client. This removes the need to use the dojo.query

<xp:text escape="true" id="someFruit" value="#{colname1.Fruit}" style="color:rgb(0,0,255)">
	<xp:this.attrs>
		<xp:attr name="ondragstart" value="dragIt(event);"></xp:attr>
		<xp:attr name="draggable" value="true"></xp:attr>
	</xp:this.attrs>
</xp:text>

Then we just need somewhere to drop them…
I added the same DIV elements from the example to the XPage

				<xp:td>
					<div id="place1" ondrop="dropIt(event);"
						ondragover="event.preventDefault();">
					</div>
				</xp:td>
				<xp:td>
					<div id="place2" ondrop="dropIt(event, true);"
						ondragover="event.preventDefault();">
					</div>
				</xp:td>

and added the javascript functions to a scriptblock at the bottom of the page

	//function called when drag starts
		function dragIt(theEvent) {
			//tell the browser what to drag
			theEvent.dataTransfer.setData("Text", theEvent.target.id);
		}

		//function called when element drops
		function dropIt(theEvent, keepMe) {
			//get a reference to the element being dragged
			var theData = theEvent.dataTransfer.getData("Text");
			//get the element
			var theDraggedElement = document.getElementById(theData);

			//add it to the drop element
			if (keepMe){
				//Add a clone of the element to the field - rather than move it
				var newObj=dojo.clone(theDraggedElement)
				theEvent.target.appendChild(newObj);
			} else {
				theEvent.target.appendChild(theDraggedElement);
			}
			//Add a new line for visual line up
			var theBR=document.createElement("br")
			theEvent.target.appendChild(theBR);
			//instruct the browser to allow the drop
			theEvent.preventDefault();
		}

I changed the example slightly to add a clone capability rather than just drag and drop

Drag and Drop example 1
Drag and Drop example 1 (Move)

Dragging to the first box “moves” the label

Drag and Drop example 2 (Clone)
Drag and Drop example 2 (Clone)

Dragging the label to the second box create a copy of it using dojo.clone(node)

Conclusion

This is merely a prototype but demonstrates nicely the new and exiting capabilities of HTML5 without having the need for a dojo or jQuery library to do the drag/drop for you

Demonstration (again)

Here is a link to the working demo of HTML5 drag and drop in an XPage

Don’t believe the HTML – timing is everything in XPages CSJS

So having made v2.0 of my TypeAhead control I am rapidly moving towards the next iteration making it easier to implement and not have to add functions to the fields in the designer. This becomes especially arduous if you have multiple TypeAheads in the same form and you want to add this capability to all of them.

The plan is to use a jQuery or dojo selector to get a handle on all the TypeAhead fields on the form and add the necessary function calls to each of them in one simple script library. (Because this is currently a capability without jQuery I am sticking with dojo, more verbose as it is)

So I created multiple TypeAhead fields (Copy/Paste) on the same XPage and looked at HTML to find out the selector I would need to create. I right click on the web page and view source and the out of the box HTML looks like this (pretty simple right..?):

<span
	id="view:_id1:_id2:_id30:_id43"
	dojoType="ibm.xsp.widget.layout.data.TypeAheadReadStore"
	jsId="view__id1__id2__id30__id43" mode="full">
</span>
<input type="text"
	id="view:_id1:_id2:_id30:inputText1"
	name="view:_id1:_id2:_id30:inputText1"
	class="xspInputFieldEditBox"
	dojoType="ibm.xsp.widget.layout.TypeAhead"
	store="view__id1__id2__id30__id43">
<br>
<span
	id="view:_id1:_id2:_id30:_id48"
	dojoType="ibm.xsp.widget.layout.data.TypeAheadReadStore"
	jsId="view__id1__id2__id30__id48" mode="full">
</span>
<input type="text"
	id="view:_id1:_id2:_id30:inputText2"
	name="view:_id1:_id2:_id30:inputText2"
	class="xspInputFieldEditBox"
	dojoType="ibm.xsp.widget.layout.TypeAhead"
	store="view__id1__id2__id30__id48">

So foolishly I thought – we need a simple attribute selector which will select attribute dojoType is like TypeAhead.

(I always start with changing the CSS as an easy indicator that I have a handle on the element)

	dojo.query('input[dojoType$=TypeAhead]').forEach(function(node){
   		dojo.style(node, {"border" : "2px solid red"})
 	 });

The Problem

I get a big fat nothing..

The most boring picture in blog history
Probably the most boring picture in blog history

So then I pulled up firebug to make sure I wasn’t being stupid, and sure enough I was…..it is not like I have already written about this before or anything….In firebug the actual DOM looks like this:

Right Click on the field and view in firebug
Right Click on the field and Inspect Element with firebug

 

Looking at the DOM within Firebug reveals Marky's stupidity
Looking at the DOM within Firebug reveals Marky's stupidity

Oh DUH – it is a dojo widget (remember) and once the page is loaded, dojo does some major DOM manipulation to create the functionality. This is actually a really nice demonstration of how XPages and dojo work in tandem. XPages creates some fairly innocuous HTML and dojo tranforms it into considerably more complex and voluminous HTML.

So looking at the DOM we have a problem because the final field which is created (that I want to get a handle on) does not have anything indicating that it is a TypeAhead and how can I “select” this out without adding client side events in the XPage….

The Answer

The trick is to execute or “selector” before the dojo widget takes over and messes up the DOM. Instead of adding the code to the onClientLoad event (which is also when the dojo widget magic is triggered) we need to add it to a script block inside of the HTML – before the page has finished loading.

This is a subtle yet important timing detail during the rendering of HTML pages. You can add a script tag to an HTML page and have it execute before the page is rendered to the user, but it can only take action on what has already been “loaded”…this is also why dojo and jQuery are usually triggered when the HTML document is finally loaded – to make sure all the necessary fields are “loaded” on the page.

In this case we are going to add the script block right at the end of the XPage to make sure that everything we are looking for is “loaded” before we act on it. The script block is added at the bottom of the XPage after all the fields. This will execute before the onClientLoad event.

Adding an in-line script block at the end of the XPage

NOTE

I am being very specific in the selector to only select INPUT (input) with Attribute dojoType ([dojoType$]) which ends in TypeAhead – see here for more information on dojo selectors

And looking at the Sourcecode you can see the script is the last thing on the page before closing </the xp:view>.

	<xp:scriptBlock id="scriptBlock1">
		<xp:this.value>
		<![CDATA[
			dojo.query('input[dojoType$=TypeAhead]').forEach(function(node, index, arr){
   				dojo.style(node, {"border" : "2px solid red"})
 			 });
		]]>
		</xp:this.value>
	</xp:scriptBlock>
	</xp:view>

This time we get a much more satisfactory result:

Selecting the elements before they are manipulated by dojo
Selecting the elements before they are manipulated by dojo

 

But wait – there’s more to this that meets the eye….

What is also interesting to note is that the styling applied to the INPUT field before the dojo widget has it’s way with the HTML is retained….but it is NOT applied to the INPUT anymore..not even close…..

Don't trust the HTML

 

Because of this, I am not sure at this point if I am going to be able to add the timing handlers for the TypeAhead – it will be fun finding out though, watch this space….

 

When should you use jQuery in your XPage?

For full disclosure, I used jQuery with Domino long before v8.5 at a time when the dojo documentation sucked big ones and it was nearly impossible to figure anything out. Today though that is much improved and the dojotoolkit website and the work done by sitepen have done a lot to catch up.

I am more familiar with jQuery syntax and the core library capabilities and I think I will always prefer to use jQuery than dojo given a choice and even playing field. In traditional Domino it is a level playing field as neither library is loaded by default. But that all changed with XPages and I am forcing myself to have to learn dojo because it just doesn’t make sense to use jQuery “just cos dojo sucks”.

jQuery does not conflict with dojo and can be used very successfully in tandem with each other. But there are some things to consider before you do.

jQuery selectors are IMHO easier to read and more intuitive to understand. jQuery uses a combination XPath/CSS query selection process and dojo uses a CSS3 selector paradigm

So why shouldn’t I use jQuery?

If you are going to add jQuery there has to be a good reason/purpose other than “‘cos I like jQuery and dojo sucks”. If you add a jQuery library you are:

  • adding additional overhead to the database
  • adding potential maintenance issues down the road
  • adding to the download size of every XPage which already has the dojo overhead by default.
    • (Yes you can turn dojo off but why would you? If you not going to use the XPage functionality don’t use an XPage design element……)

So if you are just doing a basic selector to get a page element or a basic animation, there is really nothing dojo can’t do any worse than jQuery. If you want to see a simple comparison between dojo selectors and jQuery selectors check this out

Dojo & jQuery side by side. Part 1: DOM Basics

Dojo & jQuery side by side. Part 2: Animation

So when should I use jQuery?

When you can’t do something you need to in dojo, or just just does not make sense to re-invent the wheel. jQuery is now more popular than Flash in terms of web usage for the most popular sites. dojo isn’t even on the map when it comes to web usage tracking. In terms of community size and usage jQuery dwarfs dojo everything else and because of that there is a lot of libraries to chose from.

In an XPages environment, the real benefit is not so much using jQuery itself, but in taking advantage of the thousands of plugins available which other people have written. There are plugins for everything from:

  • Menus
  • Calendars
  • Embedded video players
  • Photo galleries
  • Page Design libraries
  • Effect libraries
  • MVC Framework design libraries

I think I am going to start a series of weekly jQuery plugin examples (in XPages) to show what can be achieved very easily with the minimum of code. Let’s see how far it takes me before I run out of the over 4000 jQuery plugins and jQuery mobile