Learn jQuery in 10 Minutes

jQuery is a great toolkit to manipulate DOM and provide special effects. Use of jQuery in a site can greatly reduce development time. It takes only a few minutes to get started with jQuery.

In a previous article, I had covered downloading and installing jQuery. In this article, we will cover the API.

Importing the JavaScript Library

You need to import only one JavaScript file. Depending on the version of jQuery and installation location, it can be something like this.

<script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>

You can also get the script from Google.

<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

When to Manipulate DOM?

You can start DOM manipulation as soon as the DOM has been constructed. This happens at an earlier stage than the onload event of the window. However, handling the DOM readiness event in a browser neutral way can be tricky. FF fires the “DOMContentLoaded” event and IE the “onreadystatechange” event for the document object. jQuery makes it easy to attach an event handler for the DOM readiness event.

<script type="text/javascript">
	$(function(){
		$("#p1").text("Hello World");
	});
</script>

<body>
	<p id="p1"></p>
</body>

The $() function is used in two separate contexts in the snippet above. What does that do? Well, the $() function is the core of jQuery. We will discuss it in more details later.

A slightly more verbose way to attach a DOM ready handler is as follows.

$(document).ready(function(){
	$("#p1").text("Hello World");
});

jQuery Core Function

At the very heart of the jQuery toolkit, there is the core function. It can be called using either jQuery() or $(). It is a highly overloaded function. Meaning, the function does completely different things depending on the arguments supplied.

For example, the following two code snippets will return the jQuery object for a DOM element with ID #p1.

jQuery("#p1"); //Full name of the core function
$("#p1"); //Shortcut name

You will use the shortcut name for the core function in most cases.

We have seen another use of the core function. When the argument parameter is a function, the function is registered as a DOM ready event handler.

$(function(){
	$("#p1").text("Hello World");
});

There are many more uses of the core function as we will see shortly.

jQuery Selectors

One of the main uses of the core function is to return one or more jQuery objects corresponding to DOM elements that match certain selection criteria. You can then invoke methods of these jQuery objects to achieve some effect. The concept of selector was borrowed from CSS. jQuery then extended it quite a bit in most clever ways.

We have already seen the ID selector. This returns only one jQuery object. The ID is specified after #.

$("#p1")

You can select all elements with a given tag name. For example:

$("p").text("Hello World");

<body>
	<p id="p1"></p>
	<p id="p2"></p>
</body>

This will set the inner text of all <p> tags to “Hello World”.

You can further qualify an element by matching an attribute value. For example:

$("p[important=true]").text("This is an important paragraph.");

<p important="true"></p>
<p id="p2"></p>

This will set the inner text of only the first paragraph to “This is an important paragraph.”.

The class selector returns the jQuery objects that have a certain CSS class. The class name is supplied after a “.”. Example:

$(function(){
	$(".c1").text("You have class c1");
});

<p class="c1">Hello World</p>
<p class="c2">Hello Moon</p>

This will change the text of the first paragraph only.

The odd and even selectors are great for styling different rows in a table differently. For example:

$(function(){
	$("tr:even").css("background-color", "grey");
	$("tr:odd").css("background-color", "yellow");
});

<table border="1">
	<tr>
		<td>John Doe</td>
		<td>19</td>
	</tr>

	<tr>
		<td>Jane Doe</td>
		<td>21</td>
	</tr>
	<tr>
		<td>Mary Doe</td>
		<td>22</td>
	</tr>
</table>

 

This will produce a look as follows.

image

You can get the jQuery object for a DOM element using the DOM element object itself. For example $(document) will return the jQuery object for the document DOM object. Similarly, both expressions below will return the jQuery object for the element with ID p1.

$("#p1")

$(document.getElementById("p1"))

For a complete list of selectors, see the documentation page.

Event Handler Registration

jQuery makes it easy to register an event handler in a browser neutral way. Events are registered by calling the appropriate method of the jQuery object. For example:

$("p").click(
	function() {
		alert($(this).text());
	}
);

<p>
Hello world!
</p>
<p>
Hello moon!
</p>

This will attach a onclick event handler for all paragraph elements in the page. In this example, the handler function displays the text of the clicked paragraph. Note the use of the $(this) expression. The this keyword returns the DOM object for which the event handler is called (the clicked paragraph). Hence, $(this) returns the jQuery object for that DOM element.

The hover() function takes two parameters. The first function is registered with the mouse enter event and the second with the mouse leave event. Example:

$("tr").hover(
	function() {
		$(this).css("background-color", "yellow");
	},
	function() {
		$(this).css("background-color", "white");
	}
);

<table border="1">
	<tr>
		<td>John Doe</td>
		<td>19</td>
	</tr>

	<tr>
		<td>Jane Doe</td>
		<td>21</td>
	</tr>
	<tr>
		<td>Mary Doe</td>
		<td>22</td>
	</tr>
</table>

For a complete list of event registration methods, see the documentation.

Summary

This article covers the very basics and the underlying principles of jQuery. This should give you a good foundation as you move on to more advanced features of jQuery.

6 Comments

Converting Mouse Event Coordinates to Canvas Coordinate

The coordinate system of a HTML5 canvas object starts with 0,0 in its upper left hand corner. Coordinate system for a mouse event object, on the other hand, is highly ambiguous. QuirksMode has a detail discussion on this topic. If you are developing an interactive drawing application, you will need to convert mouse event coordinates to the coordinate system of a canvas.

Based on the QuirksMode article, I developed these utility methods that can do the conversion. I have only tested this with FF 3.6.8.

/*
 * Get mouse event coordinate converted to canvas coordinate
 * c: The canvas object
 * e: A mouse event
 */
function toCanvasX(c, e) {
  var posx = 0;
  
  if (e.pageX)   {
    posx = e.pageX;
  } else if (e.clientX)   {
    posx = e.clientX + document.body.scrollLeft
      + document.documentElement.scrollLeft;
  }
  posx = posx - c.offsetLeft;
  return posx;
}

function toCanvasY(c, e) {
  var posy = 0;
  
  if (e.pageY)   {
    posy = e.pageY;
  } else if (e.clientY)   {
    posy = e.clientY + document.body.scrollTop
      + document.documentElement.scrollTop;
  }
  posy = posy - c.offsetTop;
  
  return posy;
}

Below is an example application that uses these methods. This is perhaps one of the simplest interactive drawing applications using HTML 5 canvas.

<!DOCTYPE html>
<html>
<head>
<title>Canvas Test</title>

<script type="text/javascript">
// globals
var x = 0;
var y = 0;

function init() {
	var canvas = document.getElementById('canvas');
	canvas.addEventListener("mousedown", drawLine, false);
}

/*
 * Get mouse event coordinate converted to canvas coordinate
 * c: The canvas object
 * e: A mouse event
 */
function toCanvasX(c, e) {
  var posx = 0;
  
  if (e.pageX)   {
    posx = e.pageX;
  } else if (e.clientX)   {
    posx = e.clientX + document.body.scrollLeft
      + document.documentElement.scrollLeft;
  }
  posx = posx - c.offsetLeft;
  return posx;
}

function toCanvasY(c, e) {
  var posy = 0;
  
  if (e.pageY)   {
    posy = e.pageY;
  } else if (e.clientY)   {
    posy = e.clientY + document.body.scrollTop
      + document.documentElement.scrollTop;
  }
  posy = posy - c.offsetTop;
  
  return posy;
}

function drawLine(e) {
  var posx = toCanvasX(this, e);
  var posy = toCanvasY(this, e);
  var ctx= this.getContext('2d');

  ctx.beginPath();
  ctx.moveTo(x, y);
  ctx.lineTo(posx, posy);
  ctx.stroke();
  
  x = posx;
  y = posy;
}
</script>

</head>

<body onload="init();">

<canvas id="canvas" width="500" height="500" style="border: 1px dotted;">
      This text is displayed if your browser does not support HTML5 Canvas.
</canvas>
</body>
</html>

1 Comment

Oracle Moving to Derby from Pointbase?

This morning, I started porting WA1858 Architecting SOA Using Oracle Service Bus (OSB) 10g to Oracle Service Bus 11g. I noticed that, by default Derby database is used to create various schema. This is a welcome departure from oracle SOA Suite which requires you to use an Oracle database. This complicates installation and adds overhead. I was also somewhat surprised to see that Pointbase database was not used. This is probably a good thing. Derby is also what is used by IBM’s SOA platform (WebSphere Process Server and ESB). Many of our courses have started using Derby in one way or other.

No Comments

Portlet URL Issues

Recently, I had to port a few portlets from WebSphere Portal 6.1 to WebLogic Portal 10g. Things mostly went smoothly. Except for portlet and resource URLs.

Weblogic portal adds URL parameters to portlet and resources URLs. For example:

http://localhost:7001/AjaxWeb/ProductSearch.portlet?_nfpb=true&_st=&_windowLabel=ProductSearch_portlet…

These parameters caused unexpected problems.

POST Only

For one thing, these URLs can not be used with a form that makes a GET request.

<form method="GET" action="&lt;portlet:actionURL/&gt;"> 

<input type="firstName"/> 
  ... 

</form>

If you submit this form, the input elements will overwrite the URL parameters that are in the action URL. Things will work out badly from that point on.

Lesson learned, you can only make POST requests from a form.

Watch Out for Resource URLs

By default, the <portlet:resourceURL> tag escapes XML in the URL. That means, all “&” parameter separators in the URL will be replaced by “&amp;”. If you send a request to that URL, the serveResource() method will not be invoked. You must set escapeXml attribute to false. For example:

var url = "<portlet:resourceURL escapeXml="false"/>&searchText=" + txt;

None of these are issues in WebSphere Portal since the URLs do not contain any parameters.

No Comments

Notes About Portlet Events in JSR 286

JSR 286 allows portlets to fire events and consume events. An event is first fired from the processAction method. Portlet container notifies a consumer portlet by invoking its processEvent method. A consumer portlet can also fire an event from the processEvent method.

There is no way to fire an event during the rendering phase.

For the event mechanism to work, you need to follow a few ground rules. This article discusses those.

Defining an Event

An event is first defined in portlet.xml. This definition has to exist for the portlet application of both the publisher and consumer.

An event has a namespace qualified name and a payload data type. For example:

<portlet-app …>

<event-definition>
    <qname xmlns:x="http://www.webagesolutions.com">x:was</qname>
    <value-type>com.mycom.address.model.Address</value-type>
</event-definition>
</portlet-app>

In this example, the qualified name of the event is as follows:

– Namespace URL is “http://www.webagesolutions.com”

– The local part is “was”

The Java class for the payload data is com.mycom.address.model.Address. We will discuss the requirements for this class shortly.

You can also define an event using a simple name instead of a qualified name.

<event-definition>
    <name>AddressEvent</name>
    <value-type>com.mycom.address.model.Address</value-type>
</event-definition>

This is not recommended. To avoid any naming conflict, you should always use the qualified name approach.

The Payload Class

The event payload class is declared using the <value-type> element in portlet.xml. This class can be a Java primitive class, such as String and Integer. If you wish to use your own class, it must conform to a few rules:

  1. Must implement java.io.Serializable
  2. Must have a JAXB binding. To quickly do that, use the @XmlRootElement annotation.

For example:

@XmlRootElement
public class Address implements Serializable {

//…

}

Firing an Event

The publisher portlet needs to declare all the events it will fire in portlet.xml.

<portlet>

    <supported-publishing-event>
        <qname xmlns:x="http://www.webagesolutions.com">x:was</qname>
    </supported-publishing-event>
</portlet>

The local part and namespace URL must be exactly as stated in the event definition.

To fire an event, you need to call the setEvent method of either the ActionResponse or EventResponse object.

For example:

public void processAction(ActionRequest request, ActionResponse response)
        throws PortletException, java.io.IOException {

    //…

    Address a = new Address();
    response.setEvent(
        new QName("http://www.webagesolutions.com", "was"), a);

}

Note how the namespace URI and local part of the QName object matches the event definition.

Consuming an Event

The consumer side needs to declare all the events it is interested in consuming.

<portlet>

<supported-processing-event>
    <qname xmlns:x="http://www.webagesolutions.com">x:was</qname>
</supported-processing-event>
</portlet>

The namespace and local part must match the event definition. Otherwise, the consumer will not be notified.

Develop the processEvent method. This will be automatically called when a matching event is fired.

public void processEvent(EventRequest request, EventResponse response)
        throws PortletException, IOException {
    Event e = request.getEvent();

    logger.info("Got an event.");
    logger.info("QName: " + e.getQName());
    logger.info("Name: " + e.getName());
    logger.info("Value type: " + e.getValue().getClass().getName());
   
    Address a = (Address) e.getValue(); //Get the payload
}

This method will print out something like this:

INFO: QName: {http://www.webagesolutions.com}was
INFO: Name: was
INFO: Value type: com.mycom.address.model.Address

In Conclusion

You need to be extra careful in making sure that the qualified name of an event is correct in every place. Otherwise, events will not be dispatched to the right consumer. Also make sure that the payload type is serializable and has a JAXB binding.

3 Comments

Live from The Open Group Boston 2010

This year, we had a booth in the Open Group Boston 2010 conference. The conference organizers explain the event as follows.

The Open Group is a consortium of over 360 major IT users, suppliers and policy makers, which focuses on open standards for building large scale, interoperable business solutions. Member organizations work together, in a vendor and technology-neutral environment provided by The Open Group, to establish policies, share best practices, address current and emerging requirements, and evolve and integrate specifications, to facilitate interoperability.

Web Age Solutions, a Silver Member of the group, is exhibiting at this major conference that covers:

  • Security — "The Intentional Enterprise in an Uncertain World"
  • Architecture — "Evolving EA from IT to Business"
  • Cloud Computing — "Business Impact of Cloud Computing"

No Comments

HTML5 Strikes Again

Only weeks after releasing HTML5 enabled Gmail for iPad, Google has just launched a new mobile site for Youtube. This site takes advantage of HTML5. The user interface is ideal for small devices like iPod Touch and iPhone. The site has potential to be better than the built-in Youtube application in these devices. This New York Times article certainly hints that. I did a quick review of the site from an iPod Touch and was suitably impressed.

To see for yourself, just enter the URL in your mobile device:

http://m.youtube.com/

No Comments

Android 2.x Programming Course Announced

As promised in an earlier blog post, we have just announced our first Android programming class.

WA1921 Enterprise Android Application Development

From the web page of the course:

Android is an open source platform for mobile computing. Applications are developed using familiar Java and Eclipse tools. Many vendors and carriers offer Android based devices (phones). Android is enjoying a healthy growth, in terms of hand set sells, applications available and new project starts. This course teaches students the architecture, API and techniques to create robust, high performance and appealing applications for the Android devices. While most courses from other vendors focus only on the mobile device, this course also deals with the server side architecture. This makes the class ideal for enterprise class businesses.

No Comments

JSONObject No Longer Breaks Encapsulation

JSON is a string representation of a JavaScript object.  It’s been around since the dawn of JavaScript, but only recently gained popularity due to Ajax.  It’s commonly used as a data format for transmitting information from the server to the client.  The appeal of JSON is that the client doesn’t have to write a lot of code to update the page.  All he has to do is convert the JSON back to a JavaScript object (one line of code).  Then he can access the properties of the object and potentially update several portions of the page.

For example, below is the equivalent JSON for a JavaScript object representing a customer:

{"id":10,"name":"J. Buchman","active":true}

Below is the client code that is used to convert the JSON to a JavaScript object and update two div elements in the web page.

var customer = eval( "(" + replyString + ")" );

document.getElementById("name").innerHTML = customer.name;

document.getElementById("active").innerHTML = customer.active;

<div id="name"></div>
<div id="active"></div> 

On the server side, a utility library is typically used to convert Java objects into JSON strings.  www.json.org, which is responsible for monitoring all JSON related activities, provides such a library for Java.  The org.json.JSONObject class represents a JavaScript object.  Its toString method is to used to produce a JSON string.  When creating a  JSONObject, you typically do so based on some existing Java object.  Unfortunately, you need to declare all of its fields as public, which breaks encapsulation.

For example:

public class Customer {

   public int id;
   public String name;
   public boolean active;
}

To create the JSON string, you would:

1.  Construct an instance of the Customer class and initialize it.

2.  Construct an array of Strings specifying the class’s public field names.

3.  Construct a JSONObject passing in the Customer instance and array of Strings.

4.  Call the JSONObject’s toString method.

For example:

Customer c = new Customer(); 
c.id = 10; 
c.name = "John G. Reeves"; 
c.active = true; 

String propList[] = {"name", "id", "active"}; //List of public field names

JSONObject jo = new JSONObject(c, propList);

String replyData = jo.toString();

 

However, things have changed.  A new version of the JSONObject class was recently released, which no longer forces you to break encapsulation.  Instead, you can now pass in a JavaBean instance to the JSONObject constructor. 

JSONObject(Object bean)

The new constructor uses reflection to obtain the property names from the public methods that start with "get" or "is" followed by a capital letter.  Consequently, you can keep your fields private and have public methods for accessing them.  This way, you don’t break encapsulation.

Hence, your Customer class and JSON code are simplified and change to the following:

public class Customer {

   private int id;
   private String name;
   private boolean active;

public int getId() {
      return id;
   }
   

public void setId(int id) {
      this.id = id;
   }

// remaining getters and setters }

Customer c = new Customer(); c.setId(10); c.setName("John G. Reeves"); c.setActive(true);

JSONObject jo = new JSONObject(c);

String replyData = jo.toString();

For more information on JSON and other related Ajax topics, we recommend this training course:

WA1503 Comprehensive AJAX

No Comments

Having Fun With jQuery UI

jQuery UI provides a rich user interface library. It builds on the core jQuery framework. So, you know that development will be quick and productive. If you are new to jQuery UI, follow these simple steps to get started.

Downloading jQuery UI

jQuery UI has a unique download builder. It allows you to build a custom package for download containing only the components that you need. You can also choose the theme and the version of jQuery UI to be downloaded. Head to the download page. To keep things simple, accept all the default settings. This will select the UI Lightness theme (at the time of writing this article). Then click on Download.

Installing jQuery UI

The library is composed of static files, like, CSS and JavaScript. You can put them directly in a web server’s document root. Or, you can package the distribution within a web application (WAR).

In this tutorial, we will use Apache web server. Within the document root, create a folder called “jqui”. Extract the downloaded ZIP file within that folder. You will get these subfolders under jqui.

 image

To validate the installation, open a browser and run the URL: http://HOSTNAME/jqui/. Where HOSTNAME is your machine’s host name. And, “jqui” is the name of the folder where we installed jQuery UI.

You should see the example page (index.html):

image

Using jQuery UI from a Web Page

To find out what JavaScript and style sheet documents you need to include, simply open up the index.html that came with jQuery UI. By default, these lines are relevant:

<link type="text/css" href="css/ui-lightness/jquery-ui-1.8.2.custom.css" rel="stylesheet" />	
<script type="text/javascript" src="js/jquery-1.4.2.min.js">
</script>
<script type="text/javascript" src="js/jquery-ui-1.8.2.custom.min.js">
</script>

The style sheet will depend on your selection of theme. We are using the UI Lightness theme here.

In the same folder where you extracted jQuery UI, create a new file called test.html. Enter basic HTML there.

<!DOCTYPE html>
<html>
	<head>
	<title>jQuery UI Example Page</title>
	<link type="text/css" href="css/ui-lightness/jquery-ui-1.8.2.custom.css" rel="stylesheet" />	
	<script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
	<script type="text/javascript" src="js/jquery-ui-1.8.2.custom.min.js"></script>

	<script type="text/javascript">
	$(function(){
		// Dialog			
		$('#my_dialog').dialog({
			autoOpen: false,
			width: 600,
			buttons: {
				"Ok": function() { 
					$(this).dialog("close"); 
				}, 
				"Cancel": function() { 
					$(this).dialog("close"); 
				} 
			}
		});
				
		//Button
		$('#dialog_button').button();

		$('#dialog_button').click(function(){
			$('#my_dialog').dialog('open');
				return false;
			});
			
	});
	</script>
	</head>
	<body>
		<!-- Dialog -->
		<div id="my_dialog" title="Having Fun">
			<p>Hello. jQuery UI is fun to play with!</p>
		</div>
		<button id="dialog_button">Open dialog</button>
	</body>
</html>

Save the file. Run it from the browser: http://HOSTNAME/jqui/test.html.

image

Click on the Open dialog button. You should see the popup dialog come up.

image

Congratulations! You have successfully completed your first jQuery UI application.

Fixing Style

By default, most of the themes, including UI Lightness use very large font sizes for the widgets. This is due to a strange assumption made by the designers that the font size for the body will be 62.5%. To fix the problem, we need to shrink the font size for the ui-widget class that is inherited by almost all widgets.

Add the following snippet within the <head>, anywhere below the line where the theme’s style sheet is included.

<style type="text/css">
    .ui-widget { font-size: 0.8em;}
</style>

Save and refresh the browser. This time, you will get a more acceptable font size.

image

1 Comment