x$ – now a part of XPages Extension Library

I am very flattered to find out that not only is my x$ OpenNTF xSnippet being used more widely than I realized (over 600 downloads). It now being used in the latest release of the OpenNTF Extension library.

If you look here – http://bootstrap4xpages.com/xsp/.ibmxspres/.extlib/responsive/xpages/js/xsp-mixin.js and search for it you will find


//jQuery selector that works with XPages IDs
//See - http://openntf.org/XSnippets.nsf/snippet.xsp?id=x-jquery-selector-for-xpages
function x$(idTag, param){
	idTag = idTag.replace(/:/gi, "\\:") + (param ? param : "");
	return($("#" + idTag));
}

Who knew my first foray into the XPages community would have such an impact.

The lesson here boys and girls should be that you should *share* your work however small and insignificant you think it is. Like all scientific research, very little code is “a completely new way of doing things”. Generally everything grows incrementally and just because you don’t think something is significant, someone else might.

You are reading this – what have you shared recently?

🙂

 

Advertisements

Improving user interaction with the XPages date picker

Problem

When using a date picker in an XPage, user’s can still type incorrect data into the field which requires validation when saving.

Solution

Don’t let them type anything into the field and provide the calendar picker when they click into the field.

When you turn an XPage Edit Box into a “date field” you can select to use the date/time picker popup as we see below

Creating a date field with picker
Creating a date field with picker

But when that translates onto the webpage, the user can still type in the field and enter any old rubbish, which then needs to be validated.

Users can still type rubbish into the date field
Users can still type rubbish into the date field

Avoiding unnecessary validation is good for two reasons:

  • Less user frustration when they get the input wrong
  • Less code to write

We are going to change the form dynamics so that:

  • When the user clicks in the field
    • The calendar popup will appear
  • When the user tries to type anything
    • Nothing will happen (so they can’t type anything)

We can achieve this by adding a simple function to the onClientLoad event of the XPage.

First we have to look at the created HTML for the date control in the webpage.

Date field container for the Edit Box and the Calendar Button
Date field container for the Edit Box and the Calendar Button

What we can decipher is that the XPage has created a <SPAN> container (amongst other things) around the Edit Box and the Calendar Button. However, we do not know the name of the function which is called when the button is clicked (it is dynamically created as part of the dijit widget).

We do not need to know the function name because we can programmatically trigger the onClick event of the button.

The following code works like this:

  • When the onFocus() event of the Edit Box is triggered the the onClick event of the calendar button is triggered
  • When the user tries to type in a value they are prevented from doing so

in the clientOnLoad event of your XPage or Custom Control add

	improveDatePicker("#{id:contractTermDate1}")

and in a script library add the following

function improveDatePicker(idTag){

	//Select the BUTTON within the container
	var calButton = x$(idTag+"_Container", " .dijitButtonContents")
	//Select the dateField
	var dateField = x$(idTag)
	//When focusing on the field click the button
	dateField.focusin(function (){
		calButton.click()
	})
	//When pressing a key in the field
	dateField.keypress(function(evt){
	//prevent the event from completing
		evt.preventDefault()
	})

}
Clicking in the improved date field
Clicking in the improved date field

x$ update for dojo

Problem
dojo selector –  “dojo.query” doesn’t work for elements generated by xpages

Background

This is a follow on to the jQuery selector function for xPages – x$(“#{id:inputText1}”) article I wrote previously.

Solution

Turns out that dojo.query suffers from the same problem:  dojo.query cannot understand elements with colons (:) in it. We have to convert the idTag of the element to escape the colons with a backslash.

  • dojo.query(“view:_id1:inputText1”).style(“border”, “1px solid red”) – will not work
  • dojo.query(“view\:_id1\:inputText1”).style(“border”, “1px solid red”) – will work and is converted using the function

So I have updated my x$ function to cover dojo and jQuery


function x$(idTag, param, jd){ //Updated 28 Feb 2012
      idTag=idTag.replace(/:/gi, "\\:")+(param ? param : "");
      return( jd=="d" ? "#"+idTag : $("#"+idTag));
}

the param and jd parameters are optional (in fact jd is only necessary if you are using dojo)

Interesting Note

For the uninitiated you will note that jQuery returns a $() rather than a string – this is because it is actually returning a jQuery Object. That is a fundamental difference in the way that dojo and jQuery function as code libraries.

Examples

here is an example code of how it would be used in dojo or jQuery


//dojo
dojo.query(x$("#{id:inputText1}", "", "d")).style("border", "1px solid red")

//jQuery equivalent

x$("#{id:inputText1}").css("background-image", "1px solid red")

An example is shown below

<?xml version="1.0" encoding="UTF-8"?>

<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

<xp:br></xp:br>
 <xp:scriptBlock id="scriptBlock1">
 <xp:this.value><![CDATA[
 function x$(idTag, param, jd){ //Updated 28 Feb 2012
 idTag=idTag.replace(/:/gi, "\\:")+(param ? param : "");
 return( jd=="d" ? "#"+idTag : $("#"+idTag));
 }
 ]]>
 </xp:this.value>
 </xp:scriptBlock>
 <xp:inputText id="inputText1"></xp:inputText>
 <xp:br></xp:br>
 <xp:br></xp:br>
 <xp:button value="Change Border (Fail)" id="button2">
 <xp:eventHandler event="onclick" submit="false">
 <xp:this.script><![CDATA[dojo.query("#{id:inputText1}").style("border", "1px solid red")]]></xp:this.script>
 </xp:eventHandler>
 </xp:button>
 <xp:br></xp:br>
 <xp:br></xp:br>
 <xp:button value="Change Border X$" id="button1">
 <xp:eventHandler event="onclick" submit="false">
 <xp:this.script><![CDATA[dojo.query(x$("#{id:inputText1}", "", "d")).style("border", "1px solid red")]]></xp:this.script>
 </xp:eventHandler>
 </xp:button>
</xp:view>