jQuery in XPages #4 – prettyPhoto

This week we are going to look at a lightbox. A lightbox is a capability whereby the user clicks on a thumbnail image and the full size image is displayed on the screen. There are many of them, but I chose prettyPhoto because it also includes videos and flash plugins which makes it more flexible. So here goes….

prettyPhoto

prettyPhoto provides the developer an easy way to create a powerful visual effect on the webpage, whereby the user is able to view a slideshow of images.

A user sees a group of thumbnails

A group of thumbnails
A group of thumbnails

and is able to interact with them like this

Using prettyPhoto you can also embed a youtube video effectively within your page without it taking up real-estate

prettyPhoto is very easy to use within your XPages – this example uses 8.5.3 attributes for the links but you can actually achive this effect by just pasting the HTML into your XPages source.

To see how the effect is created check out the How does this work article…. 🙂

jQuery in XPages – prettyPhoto – How does it work?

This article is written in support of the original jQuery in XPages #4 – prettyPhoto

Demonstration

To see the prettyPhoto plugin demonstrated in an XPage click on this link

Download

The sample database (as always from now on) is available from the link above and (here)

How does it work?

The plugin “.prettyPhoto()” acts on all elements which match the selector $(“a[rel^=’prettyPhoto’]”)

	$("a[rel^='prettyPhoto']").prettyPhoto();

The $(“a[rel^=’prettyPhoto’]”) selector translates to

  • For all the a tags (a)
  • get all those with the “rel” attribute
  • which starts with the word (^=) ‘prettyPhoto’

The following DOM elements would be selected

	<a href="/xomino/jQinX.nsf/1.jpg" rel="prettyPhoto[pp_gal]" title="Mark"></a>
	<a href="/xomino/jQinX.nsf/demos/xhr_response.html?open&amp;ajax=true" title="Ajax" rel="prettyPhoto[ajax]">Ajax</a>

but the following would not

<a href="1.jpg" rel="marky_prettyPhoto"></a>
<div rel="prettyPhoto" title="You can add caption to pictures.">Hi Mum</div>
  • in the first case prettyPhoto is not the start of the rel attribute,
  • in the second case it is not an anchor (A) tag but a div (div)

Adding prettyPhoto elements to the XPage

We need to add the “rel” attribute to an anchor tag (a link control) in our XPage and there are a number of ways we can achieve this. We can either:

1. Add the images to the database and reference them directly with HTML Directly in the XPage source

	<a title="You can add caption to pictures." href="images/fullscreen/1.jpg" rel="prettyPhoto[pp_gal]">
 <img src="images/thumbnails/t_1.jpg" alt="Red round shape" width="60" height="60" />
 </a>
	<a href="images/fullscreen/2.jpg" rel="prettyPhoto[pp_gal]">
 <img src="images/thumbnails/t_2.jpg" alt="Nice building" width="60" height="60" />
 </a>
	<a href="images/fullscreen/3.jpg" rel="prettyPhoto[pp_gal]">
 <img src="images/thumbnails/t_3.jpg" alt="Fire!" width="60" height="60" />
 </a>
	<a href="images/fullscreen/4.jpg" rel="prettyPhoto[pp_gal]">
 <img src="images/thumbnails/t_4.jpg" alt="Rock climbing" width="60" height="60" />
 </a>
	<a href="images/fullscreen/5.jpg" rel="prettyPhoto[pp_gal]">
 <img src="images/thumbnails/t_5.jpg" alt="Fly kite, fly!" width="60" height="60" />
 </a>

2. Add the images to the database and reference them using link controls in our XPage

	<xp:link escape="true" id="link4" value="images/fullscreen/3.jpg"
		title="Fire!">
		<xp:this.attrs>
			<xp:attr name="rel" value="prettyPhoto[pp_gal]"></xp:attr>
		</xp:this.attrs>
		<xp:image url="images/thumbnails/t_3.jpg" width="60" height="60"
			alt="Fire" id="image4">
		</xp:image>
	</xp:link>

Be aware that custom attributes cannot be added to the XPage Link control prior to 8.5.3

3. Add the images to documents within the database and reference them through a data source in a data table – and that is what we are going to show below…

Database Elements

The demonstration is made up of the following elements

  • XPages
    • The xPrettyPhoto container
  • CustomControls
    • The formPrettyPhoto (where the code lies)
  • JavaScript libraries
    • The jQuery library
    • The prettyPhoto Library
  • Form
    • The images form (data holder)
  • View
    • Images (data source)

The demonstration – Adding the images to a data source in the database

First of all we need to create a form which is going to hold the images

Creating the image upload form
Creating the image upload form

On the form we are going to create an image name, a RTF field to hold the attachment and a description field

Fields on the image form
Fields on the image form

Then we make our XPage and create a data source based on the imageHolder form

XPage data source
XPage data source

Dragging and dropping our data source onto the XPage creates out fields and add a File Upload control (which must be associated with the imageHolder field in the database source)

Fields on our XPage
Fields on our XPage

We add a submit button and reformatting the page a little creates out basic XPage

Basic Image Upload XPage
Basic Image Upload XPage

We need to create a view which shows our image name, description and the attachment name so that we can use them for reference.

Simple view

We will then create a repeat control on the page to display the thumbnail images

Adding a repeat control to the XPages
Adding a repeat control to the XPages

Inside the repeat control we are going to build our Anchor tags and Images.

To create the following HTML

	<a title="You can add caption to pictures." href="images/fullscreen/1.jpg" rel="prettyPhoto[pp_gal]">
 <img src="images/thumbnails/t_1.jpg" alt="Red round shape" width="60" height="60" />
 </a>

We need to need to get the href, title, alt and src tags from each document in the view.

So we add a data source to our repeat control

Assigning a data source to our repeat control
Assigning a data source to our repeat control

We then move to the XPage source to build our gallery HTML.

					<xp:repeat id="repeat1" rows="30"
						value="#{imagesView}" var="imageRepeat">

					<a href="??" rel="prettyPhoto[pp_gal]"
						title="??.">
						<img alt="??" height="60" src="??"
							width="60" style="padding: 5px"></img>
					</a>
					</xp:repeat>

and when we attach this to the repeat control data source (imagesRepeat) the code becomes:

					<xp:repeat id="repeat1" rows="30"
						value="#{imagesView}" var="imageRepeat">

					<a href="#{imageRepeat.imagePath}" rel="prettyPhoto[pp_gal]"
						title="#{imageRepeat.imageName}">
						<img alt="#{imageRepeat.imageDescription}" height="60" src="#{imageRepeat.imagePath}"
							width="60"  style="padding: 5px"></img>
					</a>

					 </xp:repeat>

and we have our gallery.

Image gallery
Image gallery

So now we have a basic functioning XPage which allows for the addition of images into a display gallery. To take it from here to the final product we need to add the prettyPhoto images/css and javascript libraries. The original prettyPhoto files are available here. I added the files to the WebContent by dragging and dropping them from my desktop.

I have added them to the WebContent folder which is accessible through the eclipse package explorer (Window/Show Eclipse Views/Package Explorer)

Adding prettyPhoto files to the WebContent folder int he database
Adding prettyPhoto files to the WebContent folder int he database

We then add the prettyPhoto.css,  jQuery and prettyPhoto javascript libraries to the XPage as a resource (I am referencing them here in the XPage source code)

	<xp:this.resources>
		<xp:script src="js/jquery-1.7.1.min.js" clientSide="true"></xp:script>
		<xp:script src="js/jquery.prettyPhoto.js" clientSide="true"></xp:script>
		<xp:styleSheet href="css/prettyPhoto.css"></xp:styleSheet>
	</xp:this.resources>

The final touch is to prettyPhoto-ify them by adding the activation code to a ScriptBlock at the end of the XPage

	$(document).ready(function(){
		  $("a[rel^='prettyPhoto']").prettyPhoto();
	});

And there we have it

The final prettyPhoto gallery
The final prettyPhoto gallery

There are more examples on the xomino demo website including prettyPhoto galleries containing:

  • iFrame content
  • youTube content
  • and even ajax content

Extra

The prettyPhoto library can also handle youtube/other videos by just making the a href link to a video link the prettyPhoto plugin is smart enough to pick it up and run with it.

Extra Extra

If you look into the prettyPhoto.js file you will see that there are LOTS of configurations which you can play with yourself to change the behavior of the plugin. Because of the following from the website “prettyPhoto is totally free to use, it is licensed under Creative Commons Attribution 2.5. So you can use it in all you projects even commercial ones.” you can make any alterations you like.

	$.fn.prettyPhoto = function(pp_settings) {
		pp_settings = jQuery.extend({
			hook: 'rel', /* the attribute tag to use for prettyPhoto hooks. default: 'rel'. For HTML5, use "data-rel" or similar. */
			animation_speed: 'fast', /* fast/slow/normal */
			ajaxcallback: function() {},
			slideshow: 5000, /* false OR interval time in ms */
			autoplay_slideshow: false, /* true/false */
			opacity: 0.80, /* Value between 0 and 1 */
			show_title: true, /* true/false */
			allow_resize: true, /* Resize the photos bigger than viewport. true/false */
			allow_expand: true, /* Allow the user to expand a resized image. true/false */
			default_width: 500,
			default_height: 344,
			counter_separator_label: '/', /* The separator for the gallery counter 1 "of" 2 */
			theme: 'pp_default', /* light_rounded / dark_rounded / light_square / dark_square / facebook */
			horizontal_padding: 20, /* The padding on each side of the picture */
			hideflash: false, /* Hides all the flash object on a page, set to TRUE if flash appears over prettyPhoto */
			wmode: 'opaque', /* Set the flash wmode attribute */
			autoplay: true, /* Automatically start videos: True/False */
			modal: false, /* If set to true, only the close button will close the window */
			deeplinking: true, /* Allow prettyPhoto to update the url to enable deeplinking. */
			overlay_gallery: true, /* If set to true, a gallery will overlay the fullscreen image on mouse over */
			overlay_gallery_max: 30, /* Maximum number of pictures in the overlay gallery */
			keyboard_shortcuts: true, /* Set to false if you open forms inside prettyPhoto */
			changepicturecallback: function(){}, /* Called everytime an item is shown/changed */
			callback: function(){}, /* Called when prettyPhoto is closed */
			ie6_fallback: true,
			markup: '<div class="pp_pic_holder"> \
						<div class="ppt">&nbsp;</div> \
						<div class="pp_top"> \
							<div class="pp_left"></div> \
							<div class="pp_middle"></div> \
							<div class="pp_right"></div> \
						</div> \
						<div class="pp_content_container"> \
							<div class="pp_left"> \
							<div class="pp_right"> \
								<div class="pp_content"> \
									<div class="pp_loaderIcon"></div> \
									<div class="pp_fade"> \
										<a href="#" class="pp_expand" title="Expand the image">Expand</a> \
										<div class="pp_hoverContainer"> \
											<a class="pp_next" href="#">next</a> \
											<a class="pp_previous" href="#">previous</a> \
										</div> \
										<div id="pp_full_res"></div> \
										<div class="pp_details"> \
											<div class="pp_nav"> \
												<a href="#" class="pp_arrow_previous">Previous</a> \
												<p class="currentTextHolder">0/0</p> \
												<a href="#" class="pp_arrow_next">Next</a> \
											</div> \
											<p class="pp_description"></p> \
											<div class="pp_social">{pp_social}</div> \
											<a class="pp_close" href="#">Close</a> \
										</div> \
									</div> \
								</div> \
							</div> \
							</div> \
						</div> \
						<div class="pp_bottom"> \
							<div class="pp_left"></div> \
							<div class="pp_middle"></div> \
							<div class="pp_right"></div> \
						</div> \
					</div> \
					<div class="pp_overlay"></div>',
			gallery_markup: '<div class="pp_gallery"> \
								<a href="#" class="pp_arrow_previous">Previous</a> \
								<div> \
									<ul> \
										{gallery} \
									</ul> \
								</div> \
								<a href="#" class="pp_arrow_next">Next</a> \
							</div>',
			image_markup: '<img id="fullResImage" src="{path}" />',
			flash_markup: '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="{width}" height="{height}"><param name="wmode" value="{wmode}" /><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="{path}" /><embed src="{path}" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="{width}" height="{height}" wmode="{wmode}"></embed></object>',
			quicktime_markup: '<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" height="{height}" width="{width}"><param name="src" value="{path}"><param name="autoplay" value="{autoplay}"><param name="type" value="video/quicktime"><embed src="{path}" height="{height}" width="{width}" autoplay="{autoplay}" type="video/quicktime" pluginspage="http://www.apple.com/quicktime/download/"></embed></object>',
			iframe_markup: '<iframe src ="{path}" width="{width}" height="{height}" frameborder="no"></iframe>',
			inline_markup: '<div class="pp_inline">{content}</div>',
			custom_markup: '',
			social_tools: '<div class="twitter"><a href="http://twitter.com/share" class="twitter-share-button" data-count="none">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>' /* html or false to disable */
		}, pp_settings);

I hope that these examples are helpful and in general that the jQuery in XPages article series is enlightening and inspiring. There are so many different things we can easily incorporate into our XPages, the possibilities are endless 🙂

Demonstration

To see the prettyPhoto plugin demonstrated in an XPage click on this link

jQuery in XPages #3 – Masked Input – How does it work?

Masked Input

This article is published in conjunction with the main jQuery in XPages #3 – Masked Input

 

How does it work?

To add the Masked Input capability to your XPages in a generic, re-usable manner you will need to do the following:

Adding the JavaScript libraries

In the designer menu select Window | Show Eclipse Views | Package Explorer

Opening the package explorer in Domino Designer
Opening the package explorer in Domino Designer

Search for the WebContent folder
On your local machine make a “js” folder with the following files in it

Drag and drop the js folder into the WebContent folder of your database

Drag and Drop your Masked Input js file
Drag and Drop your Masked Input js file

Creating the custom control to load the JavaScript libraries

Create the following ccMaskedInput custom control in your database

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

	<xp:this.resources>
		<xp:script src="js/jquery-1.7.1.min.js"
			clientSide="true">
		</xp:script>
		<xp:script src="js/x$.js"
			clientSide="true">
		</xp:script>
		<xp:script src="js/jquery.maskedinput-1.3.min.js"
			clientSide="true">
		</xp:script>
	</xp:this.resources>
</xp:view>

You now have a re-usable custom control which can be added to any of the XPages in your database.

Creating your XPage

  • Create a new XPage and create a new Domino Document data source from one of the forms in the database.
  • Drag and drop your fields to the XPage
  • Drag and drop the ccMaskedInput custom control onto your XPage
  • Add the following script block to the bottom of your XPage/custom control and change the fields names to match your field names. (Change the masks to match the masks you want on your form)
 	<xp:scriptBlock id="scriptBlock1">
		<xp:this.value><![CDATA[
		jQuery(function($){
   			x$("#{id:date1}").mask("99/99/9999");		//change the field name
   			x$("#{id:phone1}").mask("(999) 999-9999");	//change the field name
   			x$("#{id:SSN1}").mask("999-99-9999");		//change the field name
   			x$("#{id:custom1}").mask("99-99-aaaa-9");	//change the field name
		});

		]]></xp:this.value>
	</xp:scriptBlock>

And it’s as easy as that !

In a Nutshell

The Input Mask code:

  • Adds the programmed “Mask” to the field as the page loads
  • Tracks what you type and how many characters you have added so far
  • Checks what you type and matches it against the allowable character list for that character at that position in the string
  • Updates the mask accordingly and moves past the “Mask” characters is applicable.


jQuery in XPages #3 – Masked input

This week we are going to look at a Masked Input plugin which provides another easy to implement but big impact to the users interface improvement capability.

The Demonstration

Click here to see a demonstration of the Input Mask plugin running within an XPage

The Sample Database

Rather than create a new URL every week I am going to stick with the same one from now on. It will contain a conglomeration of all the previous weeks examples and is basically a copy of the demo database on the website. The jQuery in XPages Sample Database

Masked Input

The Masked Input plugin by Josh Bush turns a plain editable field into a field which:

  • Increases user buy in by adding a visually appealing enhancement to the XPage
  • Allows the developer to pre-define the input order and type of keyboard characters
  • Shows the user what the application expects them to input
  • Enforces validation rules by preventing users from typing in potentially incorrect values
Input Mask example

The Input Mask adds the (__) ___-____ x_____ into the field and as the user starts to type the “Mask” is replaced by the keyed value.

Input Mask example user input
Input Mask example user input

If the user attempt to try and enter anything other than a number nothing happens. This effect is very easily implemented using only a few lines of JavaScript to instantiate the code. Remember in XPages we have to use the x$ functionand the {id:} name of the field to select the real id in the HTML Document Model (DOM)

jQuery(function($){
   x$("#{id:date}").mask("99/99/9999");
   x$("#{id:phone}").mask("(999) 999-9999");
   x$("#{id:ssn}").mask("999-99-9999");
});

The Input mask plugin API comes with an abundance of other features you can change like:

  • Changing the mask character from _ to something else
  • Triggering a function once the mask is complete (all characters filled in)
  • Supplying your own mask definition (i.e if you want a specific character other than a-zA-Z0-9)
  • Allowing for wildchard characters (you don’t care what the user types)
  • Allowing for optional characters – (option phone extension or 4 final characters on a 9 digit zip code)

Adding this plug in to your database will take less than 5 minutes and you can improve the user interface immediately. Check out The Masked Input website for more information and futher information on the API parameters/capabilities.

Note:When you are submitting the form you will still need to validate it as the Input Mask does not handle validation outside of the field itself. The whole field value is submitted (Input Mask value as well) so if you create a (123) 123-1234 mask you will need to make sure you can accept that on the back end in a text field and you don’t need a 9 digit number.

For more information on how to add this capability to your XPages check out the “how does it work” article

jQuery in XPages #2 – Labelify.js

This week’s article is about the visually effective jQuery plugin – labelify.js

Labelify.js

In the simplest terms we want to make our form look like the “label” is inside the field – here’s an example I am sure many of you are familiar with. The general concept is that instead of having the label adjacent to the field, the “Compose new Tweet” is inside the field itself and disappears once you click in the field.


Edit box with a "in-line" label

The demonstration

The demonstration can be found here – (demonstration)

The download

The sample jQuery in Xpages database (containing examples from all the articles) can be downloaded here – (download sample database)

How do we add Labelify to our XPages?

This effect works on an XPage where the labels and fields are generated by dragging and dropping the fields from a data source. How this works will be broken down later..

Adding fields to the XPages from a pre-defined data source
Adding fields to the XPages from a pre-defined data source

Here’s the steps:

  1. Add the xLabelify.js  script library to you database
  2. Add the xLabelify.js Javascript library to your XPage as a Resource

    Adding the xLabelify.js Resource to your XPage
    Adding the xLabelify.js Resource to your XPage
  3. Add the xLabel.css  to your database
  4. Add the xLabel.css as a resource to your XPage as a Resource
  5. Add the following code to the Client side JavaScript portion of the onClientLoad event of your XPage
$("input").labelify({ text: "label", labelledClass: "labelHighlight"  });
Adding the xLabelify code to the onClientLoad XPage event
Adding the xLabelify code to the onClientLoad XPage event

And that gives us the desired outcome:

Labelify your XPage
Labelify your XPage

Breaking it down

Click here to view the How does it work article

Thanks

Thanks to David Leedy once again for hosting the demonstration

jQuery in XPages #2 – Labelify.js – How does it work?

This article is in support of the jQuery in XPages article #2 – Labelify.js and goes into depth as to how the functionality was created and how you can modify it yourself. How does this work?The Labelify example is made up of the following elements:

  • XPages
    • xLabelify (the example XPage)
  • StyleSheet
    • xLabel.css (look and feel)
  • JavaScript Library
    • xLabelify.js (the jQuery library creating the effect)

This demonstration re-uses code which was already created for the jQuery in XPages #1- Highcharts article:

  • Form (data container)
    • Fruit

The xLabelify.js Javascript Library

The xLabelify.js library is based on the original labelify.js created by Stuart Langridge. I have made a couple of modifications to the library to make it work in our XPages environment. Here is the breakdown of how it works……..

Extending jQuery

For more information on extending jQuery check out the (website). But in a nutshell, jQuery was envisioned to be extended so that anyone could use the basic jQuery selector to create a collection of objects in the DOM and then process them however they wanted.


$("input").labelify({ text: "label", labelledClass: "labelHighlight"});

In this case “labelify” is the extension and it is:

  • collecting all the $(“input”) elements on the web page and then
  •  “.labelify” them with the text and labelledClass as parameters.”

(If we wanted to be more specific and wanted to select only the labels within a certain panel (rather than the whole page) or if we wanted to select individual elements by name/id we could do that too). The example below (using x$) selects just the fruit4 field.

x$("#{id:fruit4}").labelify({
	text: "label", labelledClass: "labelField"
})

The code

I have annotated the code so that you can understand what makes this effect work. It is also a nice short look inside a jQuery extension. It is really quite elegant in its simplicity.

//extend jQuery with the function name "labelify" and it will receive the array called "settings"
jQuery.fn.labelify = function(settings) {

//"settings" will contain the variable title and labeledClass which will be created as jQuery objects
//by default the text: value will be title (if nothing is passed in at all)
  settings = jQuery.extend({
    text: "title",
    labelledClass: ""
  }, settings);

//lookups will be the default values pulled from the document model (DOM) at startup
  var lookups = {
//The title: value will be taken from the title attribute of the input field being processed
    title: function(input) {
      return $(input).attr("title");
    },
//The label: value will be taken from the label with a "for" attribute matching the id of the input field being processed
    label: function(input) {
      return $('label[for="' + input.id + '"]').text();
    }
  };
  var lookup;
//$(this) refers to "this jQuery object" as opposed to "this" which in javascript is the current DOM element.
  var jQuery_labellified_elements = $(this);

	//for each labelified element ($(this).each)
	//we are setting the lookup variable for each of the elements which are within "lookups"
	//the value of lookup is going to be the text we are going to display within the field
	//that has come from either the LABEL or the title attribute
  return $(this).each(function() {
    if (typeof settings.text === "string") {
      lookup = lookups[settings.text]; // what if not there?
    } else {
      lookup = settings.text; // what if not a fn?
    };
    // bail if lookup isn't a function or if it returns undefined
    if (typeof lookup !== "function") {
      return;
    }
    var lookupval = lookup(this);
    if (!lookupval) {
      return;
    }

    // need to strip newlines because the browser strips them
    // if you set textbox.value to a string containing them
    $(this).data("label", lookup(this).replace(/\n/g, ''));

	//When the user clicks or tabs into the field (focus event)

    $(this).focus(function() {

	//if the jQuery data (more on this further down) "label" is exactly the same type and value (===)
	//Then the jQuery item (this).value equals the jQuery item defaultValue
	//then remove the labelledClass

	//in simple terms - if the user clicks into the field and the "labellify" text (e.g. enter a value) is displayed
	//Then remove it from the field, hide it and put the defaultValue into the field (normally blank)
      if (this.value === $(this).data("label")) {
        this.value = this.defaultValue;
        $(this).removeClass(settings.labelledClass);
      }

	//When the user clicks or tabs out of the field (blur event)
	//IF the current value = the defaultValue (usually blank)
	//Then put the labelified value (e.g. enter a name) back into the field
	//Add the labelledClass (make it gray)
	  }).blur(function() {
      if (this.value === this.defaultValue) {
        this.value = $(this).data("label");
        $(this).addClass(settings.labelledClass);
      }
    });

	//This function removes all the labelify information from the field
	//This function is called onSumit and means that if the deveoper validates for ""
	//the field will contain "" onSubmit and will therefore not be validated as (enter a name)
    var removeValuesOnExit = function() {
      jQuery_labellified_elements.each(function() {
        if (this.value === $(this).data("label")) {
          this.value = this.defaultValue;
          $(this).removeClass(settings.labelledClass);
        }
      })
    };

	//if the form is being submitted or the user has clicked onto another window (unload)
	//then call the remove labelify function above and remove all traces of labelify from the field (jQuery $(this))
    $(this).parents("form").submit(removeValuesOnExit);
    $(window).unload(removeValuesOnExit);

    if (this.value !== this.defaultValue) {
      // user already started typing; don't overwrite their work!
      return;
    }

    //MDR Mar 2012
    //else clause added to resolve existing default values
	//The function sets up the labelified field and says if the field is blank to start with insert the labelified information
    if (this.defaultValue == "") {
      // actually set the value
      this.value = $(this).data("label");
      $(this).addClass(settings.labelledClass);
    } else {

	//however in our XPages environment we often have default values in the field
	//we might want to see the labelified version if the user blanks out the field
	//but without this else clause the labelified value would be forced ontop of the default value

	//so if the field is not blank then
	//get the field value ("Cabbage" in our example")
	var sTemp = this.value
	//set the default value to blank (the code assumes Cabbage is the defaultValue)
      this.defaultValue = ""
	  //create the data label within the jQuery object to be the labelify text (Enter a Vegetable)
      $(this).data("label", lookup(this).replace(/\n/g, ''));
	  //put Cabbage back into the field
      this.value = sTemp
    }
  });
};

jQuery object data

For more indepth information on jQuery.data check out the jQuery (site). But one of the constructs within the jQuery object is the .data capability. What jQuery does is it assigns data attributes to the DOM element and it keeps track of them with internal jQuery pointers. What this allows us to do programmatically is push and pull “data” from the jQuery object $(this) without having to define more DOM elements to contains the data. Creating DOM elements is an expensive transaction and pushing/pulling data from existing DOM elements is much more efficient. Although less of a transaction bonus, but still more efficient is that fact that we do not have to create new variables for each value either. This is not exactly what happens but you can imagine it conceptually – e.g. <input type=”text” value=”Marky” /> becomes <input type=”text” value=”Marky” data-label=”Enter a Vegetable” />

NOTE

Some interesting jsPerf tests have shown that in this case in some browsers jQuery is actually slower than setting attributes in the DOM manually. Still both are more efficient than creating variables in memory or new DOM elements via document.createElement.

Where does the label come from then?

When we create our XPage fields by dragging and dropping from the data source, the XPage created the following HTML automagically

</pre>
<table>
      <tbody>
            <tr>
                  <td>
                        <label id="view:_id1:fruit_Label1" class="xspTextLabel" for="view:_id1:fruit1">Fruit:</label>
                  </td>
                  <td>
                        <input id="view:_id1:fruit1" class="xspInputFieldEditBox" type="text" name="view:_id1:fruit1" />
                  </td>
            </tr>
            <tr>
                  <td>
                        <label id="view:_id1:howManyAdam_Label1" class="xspTextLabel" for="view:_id1:howManyAdam1">How many adam:</label>
                  </td>
                  <td>
                        <input id="view:_id1:howManyAdam1" class="xspInputFieldEditBox" type="text" name="view:_id1:howManyAdam1" />
                  </td>
            </tr>
            <tr>
                  <td>
                        <label id="view:_id1:howManyJane_Label1" class="xspTextLabel" for="view:_id1:howManyJane1">How many jane:</label>
                  </td>
                  <td>
                        <input id="view:_id1:howManyJane1" class="xspInputFieldEditBox" type="text" name="view:_id1:howManyJane1" />
                  </td>
            </tr>
      </tbody>
</table>

So you can see from the code above that for every

  • <INPUT id=”view:_id1:fieldname” name=”view:_id1:fieldname” class-“xspInputFieldEditBox”>  there is a corresponding
  • <label id=”view:_id1:fieldname_Label1″ for=”view:_id1:fieldname”>Some Label Text</label>

So out of the box, XPages has provided us the constructs for us to labelify the fields without write more code.

This

XPages fields from a data source
XPages fields from a data source

Becomes This

XPage Pre-labelify
XPage Pre-labelify

Becomes Labelified

Labelified XPage
Labelified XPage

To see the full demo go here – http://watchtower.notesin9.com/xomino/jQinX.nsf/xLabelify.xsp

The full demo includes more specific examples of labelifying specific fields and or sections and not others. To be able to reference specific panels the demo also includes x$ (link) which is provided as a JavaScript library in the sample database.