Saturday, November 6, 2010

Finding elements using jQuery - Part 3

In this part of the series, I will be discussing a few more ways that are offered by jQuery to traverse siblings of an element.

The methods that we are going to discuss in this post are

prev()
prevAll()
prevUntil()
next()
nextAll()
nextUntil()

All these functions provide us with a way to traverse the siblings of a given DOM element. Lets see some examples.

  • 0
  • a
  • b
  • c


The prev() function selects the DOM element that lies immediately above the current element. So, if we were to apply the prev function to our list item3, it would select the list item 2. However, if you want to select the previous item only if it matches a particular criteria, then you can pass a selector to the prev() function. Note tat the selector function DOES not select the first matching previous sibling. Instead it first select the previous sibling, and then applies the test criteria to it.

$(".item3").prev().addClass("highlighted");

The above code would select the second list item and would add a class called highlighted to it.

Now lets see this

$(".item3").prev(".other").addClass("highlighted");

The above code would select the previous element and then check if it has a class called other. If not, as it in in our case, it will return an empty jQuery object(note that an empty jQuery object is not a null object. Its just like an empty array). The addClass function is called on the empty array and hence has no effect.

Now lets take a look at the prevAll() function

$(".item3").prevAll().addClass("highlighted");

This function, when called without the arguments will select all the previous siblings of the current element. In our case, all list items except list item with clas .item3 will be selected.

When passed an argument, only those previous siblings are returned that satisfy the test criteria.

$(".item3").prevAll(".item1").addClass("other");

In this case, only the previous siblings that have the class as 'other' will be returned by the selector.

Sometimes you have a requirement of selecting the first previous sibling that matches your selection criteria. For example in the below DOM structure, i have 2 list items with a class called 'other'. Suppose that i am traversing from list item 'item3' and i need to get the item having the html value of 'a'.i.e. the second list item.

  • 0
  • a
  • b
  • c

Here is how it can be done

$(".item3").prevAll(".other").eq(0).addClass("highlighted");

As you see, the prevAll function will traverse in upwards in the DOM for all the siblings. Since you need the first match, you select the element 0 of the matched set and apply your style class to it.


Another very useful function is the prevUntil() function. this function is used to select all the DOM siblings, before the current element, until an element is found that satisfies the search criteria.


$(".item3").prevUntil(".other").addClass("highlighted");

So, in our example, all the previous list items of class 'item3' will be selected until a list item with class 'other' is found on the DOM. This function, when called without the selector argument, works the same way as the prevAll function. So, it would be pointless to call this function without the selector argument.

The other functions - next(), nextAll() and nextUntil() work in exactly the same way as their counterpart function, apart from the fact that instead of selecting the previous siblings, these functions work on the siblings that follow the currently selected element.

These six functions make traversing in a given sibling structure pretty easy.

Happy Programming :)
Signing Off
Ryan

Friday, November 5, 2010

Finding elements using jQuery - Part 2

Today in this post, I am going to pick up from where i left off in the previous post where I discussed about how to use contexts and the usage of the find function and the children function.

Now, lets take a look at another cool way in which a jQuery allows us to traverse the DOM.

One of my favorite functions is the siblings function. This function, as the name suggests allows you to get the siblings of a the current element. For example, suppose you have a unordered list and you need to change the css of a particular list item on mouse hover to indicate that it is being highlighted, but at the same time, you will also need to clear the other list items that were previously hovered over. As is common in jQuery, there is more than one way to achieve this. Lets check out two different ways in which this can be done.

  • a
  • b
  • c


In order to achieve the effect that we desire, we can simply make use of the hover function.

$(".level1>li").hover(
     function(){$(this).addClass("highlighted")},
     function(){$(this).removeClass("highlighted")}
    );

But lets make things a bit more complicated. Suppose instead of simply highlighting the current li, your currently highlighted elements also need to print the information of the previously highlighted element. In this case, the hover function wont suffice. I know example sound a bit silly, but its a silly silly world out there, and requirements can be bizarre and unpredictable. In the next snippet, i am just going to demonstrate how the siblings function can come to the rescue when we need to countenance such requirements.

I am just going to print the value of the previously selected item on the firefox console(ah, yes I am a firefox fan, if you haven't already noticed that by now, although I occasionally use chrome as well for my adventures). Note that I will be printing it when my mouse pointer is over the new element, instead of when the mouse is coming out of the previous element.

$(".level1>li").mouseover(
     function(){
      var prevHovered = $(this).siblings(".highlighted");
      if(prevHovered.length!=0){
       console.log("prev html : "+prevHovered.html());
       prevHovered.removeClass("highlighted");
      }
      $(this).addClass("highlighted");
     }
    );


As you see in the above code, I use the mouseover function to handle the selection of the element. The siblings function will select all the siblings of the ul, but the important thing to note here is that the current element is not returned in the selected set. So, all you have is a set of siblings of the current element. You can narrow down the search by providing an optional selector to the siblings function so that only those siblings that match the selected criteria will be returned in the set. However, if you don't pass any argument, all the siblings will be returned.

All the above code did was to select the previously selected element, check if it was not null. It its not, print the html of that element on the console and remove the highlighting from that element.

Easy stuff.

But I mentioned before that I used the mouseover function instead of the hover function. The hover function can take either 1 or 2 arguments as callbacks that can be used to call your function. If only one argument is sent, it will called on both of the mouseover and mouseout event. If you provide two functions as arguments, the first will be used for a mouseover and the second will be used for the mouseout event.

I figured, instead of having an empty mouseout, i'd rather use the mouseover function since it is more natural to our requirement in this case. However you can replace the mouseover function with the single argument hover function in the above code, and it would still work the same.


There's more from where that came from. Stay tuned!


Happy Programming :)
Signing Off
Ryan

Struts 2 : Creating and accessing maps.

Today, in this post, I am going to discuss how to create and access HashMaps in Struts 2.

My environment has the following jar files.
struts2-core-2.1.8.1.jar
ognl-2.7.3.jar

Struts 2 makes extensive use of OGNL in order to retrieve the values of elements. OGNL stands for Object Graph Navigation Language. As the name suggests, OGNL is used to navigate an object graph. In this post, i am going to use the OGNL syntax to create Map on a jsp page, and show you how to iterate over it to fetch the keys and values from the map.

In the following example, i will create a map, on they fly in the iterator tag, and will use it in the body of the iterator tag.







Note the syntax that has been used to create a Map on a jsp page in struts 2 using OGNL. Once the map is created, the iterator tag can be used to iterate over each element of the map.

Now suppose the map that we want to access is in a map inside the HttpRequest. Assume that some action somewhere in the chain has kept a map in the request using the key "myMap". In order to iterate over the elements of the map, we can do the following







Okey now, enough with iterating over maps. I don't think there are any more permutations for accessing maps. But if i do find more, ill document them down here.

Consider a case where you dont want to iterate over the entire map. Instead, all that you want to do is to extract a value form the map based upon a key that is already known to you in your jsp page.

Assume that you have a variable in page scope called "runtimeKey" that you set using the s:set tag. The value of this variable is a string key that can be used to get a value from a map.

Here is how you can fetch the value from the map without iterating over it.




As you see, since the variable "runtimeKey" is an OGNL variable and is available on the value stack, it can be referenced using the # notations. Also not that instead of using the dot notation, I have used square brackets to fetch the key. This is because the value of my expression "#runtimeKey will only be evaluated when its inside the brackets. Also note that the value of the key runtimeKey is contained within single quotes to direct OGNL to evaluate it as a string when setting as the value for my key.


Consider another situation where your keys follow a pattern. For example key_1, key_2. And you have the values 1 and 2 as page scoped variables. So, now instead of having the string value of the key directly, you may have to construct the key using concatenation.



Your key pattern was set above. And you Map has a key called key_1. So, here is how you would have to concatenate your strings in order to construct the key and fetch the value.



Huh. So easy!

Thats all for now folks.. Stay tuned for more!

Happy Programming :)
Signing Off
Ryan

Thursday, November 4, 2010

Finding elements using jQuery - Part 1


Today in this blog post I am going to discuss a few ways in which we can find DOM elements using jQuery.

We all use jQuery selectors in order to select elements to work upon. Most of our selectors are usually based upon the id or the class or some other attribute, and sometimes even the structure of the elements being selected. However, apart from these selectors, jQuery also allows you to select elements in a completely different way, like all the siblings of an element, all the children of an element. It also allows you to search within the context of another element.

Lets see what I mean by that. Consider the following DOM structure.

  • a
  • b
  • c
    • c1
    • c2

As seen in the structure, i have one main ul which has three li elements. this ul acts as the main container. The third li element in the main container in turn has another ul which has three li subelements.

For both the ul elements, the li elements have been assigned classes pertaining to their location in the list. So, we ended up with a total of four li elements having the same class for the li element- item1 and item2.

Now let us see the various ways in which we can select the different elements in this structure.

As usual, we will be writing all our code in the jQuery onload function which is as follows.

$(function(){
//All our code goes here. });

Lets assume that we want to color all the elements that have the class 'item2' within our ul that has a class 'container'

There are actually three ways to achieve this.
Here is the first.

$(".container .item2").css({"background-color":"blue"});

This way is simple, and we use normal css selectors to find all the sub elements in the DOM under our .container that have a class named as .item2. This, in our case,would set the background color of both the li elements that have the 'item2' class.

Now lets see a second way to do it.

$(".item2",".container").css({"background-color":"blue"});

This is also equivalent tot the previous snippet. This selector makes use of "search context". A search context is nothing but the context in which the elements will be searched. So, if i were to read out the selector expression, it would be read something like this

'Select all the elements that have a class called item, that exist inside the element that has a class called container'

This means that the first argument that is passed to the selector is the actual search expression, whereas the second argument that we passed to the selector becomes the context of our search.

It also means that when we don't pass the second argument, the entire DOM structure is searched by default.

Here is the third way to do it.

$(".container").find(".item2").css({"background-color":"blue"});

In the above code, we are using the find() jQuery function to find the elements. If i were to read it aloud, it would be read as

'Select the elements with a class called container first, and inside all those selected containers, select the elements that have the class called item2.'

Sometimes, if your classes are unique, you may not feel the need to find elements using the context. Or, in many cases, it is possible to find the elements using a normal selector that would traverse the entire DOM. Why use contexts and confuse things?

However, when your structure becomes complicated, it may come in extremely handy to use contexts to find elements. Because, when you find using contexts, jQuery has to traverse fewer DOM elements to get the elements you desire to search, thereby saving you time and improving overall performance.

Sometimes, it it better to make use of a context when you already have a part of the search for the context already done for you.

For example, let us assume you register a click function for your container. And inside the click function, you need to do the same thing that we did above.

Here is how it could be done in the normal way

$(".container").click(function(){
$(".item2",".container").css({"background-color":"blue"});
});

But there is one thing to be noticed here. We are already in side the click handler of the container. That means, jQuery has already searched the DOM for our container. Then why do we need to again ask jQuery to search the DOM for the container? Instead, we can make use of the current context, and simply search for the item we want.

Here is how it can be done.

$(".container").click(function(){
$(".item2",$(this)).css({"background-color":"blue"});
});

The context in a click handler is determined by the value of the 'this' variable. So, finding elements can become easier for jQuery if you just know when and were you can reduce the lookups that jQuery has to do, by making use of an existing context.

That's all for now. I shall discuss more ways of finding elements using jQuery in future posts.
Till then, cya!

Happy Programming :)
Signing Off
Ryan

Wednesday, November 3, 2010

jQuery : Creating a custom widget


Today, in this post, I am going to discuss how to create a custom widget using jQuery.

Lets begin with the definition of a widget.

A widget in jQuery means nothing but a function that can be called on a jQuery selector that modifies the behaviour of all the selected elements by attaching data to the selected elements and maintaining individual state for each of these elements.

The important point to be noted here is the "state keeping" that is associated with each selected element. This is what makes the difference between a jQuery plugin and a jQuery widget. A widget can be considered to be an advanced form of a plugin.

Widgets can be of several types. For example, you may create a widget that simply formats the data in an element. Or you may create a widget that is closely associated to the structure of a html snippet, because it uses the html structure to create its layout. for e.g the "tabs" widget.

In this post, I am going to create a very basic widget, that actually does nothing useful. My objective here is to write a basic skeleton structure to create a widget that you can replace anytime with your own functionality.

Our prerequisites :

Download the jQuery UI plugin. This plugin contains the javascript files that are necessary to create a widget. Thats because the widget function is available to us via the UI plugin. Of course that does not mean that you can only create UI related widgets using this plugin. You are always only limited by your imagination.
You can download it from here. For the examples in this post, all you need is the four components that fall under the "UI Core" category. We will only be dealing with the basic stuff here. Come back when you are done.

Okey, now that you're back, I want to ensure two things before we begin.
  1. You have extracted the zip file in some arbitrary location on your disc. lets call it "jQueryUI". This folder should contain the "js" folder and the "development-bundle" folder. We shall be using he "jQueryUI" as the root directory where we would be creating our html page in which we would be using jQuery.
  2. You create a page called widgetExperiment.html in your root directory.


In the head section of your html page, include the following lines of code.


  
  
  
  


These are the scripts that we need to refer to in order to create our custom widget. As you can see, the version numbers of your script files may differ based upon when you are actually reading this blog. Just go to the appropriate directories and replace the src file names in the script tag with the proper file names.

Now, we are all set to crate our first jQuery widget.

Lets start with the standard "onload" function in jQuery.

$(function(){
//All our Code goes here
});

When creating a widget, the first thing that we need to do is to create an object that represents the functions and the data of our widget. This object acts as a prototype for our widget data. The purpose of this object is to encapsulate the functions and the properties that will be associated with each selected element returned by the jQuery selector expression.



var myPrototype={
      options:{level:1},
      setLevel:function(level){this.options.level=level;},
      getLevel: function () { return this.options.level; },
      _init: function() { this.setLevel(this.getLevel());}
     };

As can be seen above, I named my prototype object "myPrototype". Inside my prototype, i have a few functions and an object called "options".

There are two things that you need to know about the properties that are created inside a widget.
The function names that begin with an underscore are private. i.e. these functions cannot be called from outside of the widget.

All the data, pertaining to the state of the widget should be kept in an internal object called "options".
An instance of the widget is created for each element returned by the selector. The options object ensures that for each instance of the widget that is created, the properties remain private to that particular instance.

Initialization of your widget if required, must take place in the _init function. You can also create a destroy function to perform any cleanup when your widget instance is destroyed. These functions are called automatically and are part of your widget lifecycle.

As seen in the code, for my widget, i created a private property called "level" and two "getter/setter" functions to manipulate this property. The getter/setter functions are public by virtue of not starting with an underscore.

Calling these functions are not done in the usual manner. We shall see how to invoke these public functions once we have created the widget.

Creating a widget is very simple. All that you need to do is to associate your prototype object with a name and pass it to the jQuery widget function. Here is how it is done

$.widget("ui.myWidget",myPrototype);


The jQuery widget plugin function is used to create your widget by assigning it a name in the namespace "ui.myWidget" and then passing the object that we use as the prototype object in the second parameter.
Although the namespacing is "ui.myWidget", your widget is simply named myWidget and that is what your plugin function will be called.

Associating your widget with an element is a complete no brainer. For example, the following code associates all my divs on the page with my widget. (you dont want to associate all your divs with a widget unless ur a total nut, or if you are testing something like the way I am doing now)

$("div").myWidget();

Now lets see how to use our newly created widget. If you remember, when creating the widget, we declared a property called "level" that set to an initial value of 1 in the widget. Now we are going to write a simple click handler for our divs that sets the value of the level and prints it on the console.

$("div").click(function(){
      
      $(this).myWidget("setLevel",4);
      
      console.log($(this).myWidget("getLevel"));
      
     });



In the following example, notice how we called the public functions getLevel and setLevel. Also notice how we passed a parameter to the setLevel function of our widget. The first argument is treated as the function name and the second argument onwards are treated as the arguments for the function being invoked.

Here is the entire code in a single snippet


var myPrototype={
      options:{level:1},
      setLevel:function(level){this.options.level=level;},
      getLevel: function () { return this.options.level; },
      _init: function() { this.setLevel(this.getLevel());}
     };
     
     
     $.widget("ui.myPrototype",myPrototype);
     
     
     $("div").myPrototype();
     
     $("div").click(function(){
      
      $(this).myPrototype("setLevel",4);
      
      console.log($(this).myPrototype("getLevel"));
      
     });


Well, that seemed pretty easy, didn't it? But our widget lacks one important thing that we would need to do in most of our widgets. That is, to access the current element to which the widget is attached, inside the widget. You cannot use "this", because inside the object, the keyword "this" represents an instance of the widget. The actual element associated with the object is accessed via "this.element", which is a jQuery object representing the dom element.

So, if you were inside the init method and you wanted to print the value of the id of your selected element, that could easily done by the writing the following lines in the init method

console.log("inside init : "+this.element.attr("id"));

So, thats one more thing settled.

Lets add a little more 'dummy' functionality to our code by allowing it to interact with the mouse. In order to allow your widgets to interact with the mouse, you need to create your widgets in a slightly different way.

Here is how you created the widget in the normal case ;

$.widget("ui.myWidget",myPrototype);

And here is how you will create it when you need mouse interaction

$.widget("ui.myWidget",  $.ui.mouse,myPrototype);

Once you have done that, you can need to override a few functions to handle mouse related events on your widget. But before that you should call the _mouseInit and _mouseDestroy methods in the _init and destroy methods of your widget respectively.

Here is the code in all its mighty form!

var myPrototype={
      options:{level:1},
      setLevel:function(level){this.options.level=level;},
      getLevel: function () { return this.options.level; },
      _init: function() { this._mouseInit();},
      
      
      destroy: function() {
       this._mouseDestroy();
       return this;
      },
      
      _mouseCapture: function(event) {
       console.log("inside capture: x("+event.pageX +") y("+event.pageY+")" );
       return true;
      },
      
      _mouseStart: function(event) {
       console.log("inside start: x("+event.pageX +") y("+event.pageY+")" );
       return true;
      },
      
      _mouseDrag: function(event) {
       console.log("inside drag: x("+event.pageX +") y("+event.pageY+")" );
       return false;
      },
      
      _mouseStop: function(event) {
       console.log("inside stop: x("+event.pageX +") y("+event.pageY+")" );
       return false;
      }
      
     };
     
     
     $.widget("ui.myWidget",  $.ui.mouse,myPrototype);

I hope this bare bones example comes in handy to get you started quickly on creating simple widgets.

Thats all for now folks!

Happy Programming :)
Signing Off
Ryan