jQuery Minute™

…a jQuery Minute™ later and you're done!

Archive for the ‘Plugin-Extension’ Category

SwitchView Plugin Released

without comments

Greetings all!

I’m pleased to release a new plugin called switchView. The SwitchView jQuery plugin provides the ability to easily define groups of elements to show and hide in one fell swoop. Let’s take a look at how the plugin works!

Given the following HTML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<p>
    <label>Username</label>
    <input type="text" name="username" />
</p>
 
<p>
    <label>Password</label>
    <input type="text" name="password" />
</p>
 
<p>
    <label>Confirm Password</label>
    <input type="password" name="confirmPassword" />
</p>
 
<a href="#">Change Password</a>
 
<input type="submit" value="Login" />
<input type="cancel" value="Cancel" />
<input type="submit" value="Change Password" />

The requirement is to toggle between a set of elements for the “login” view and the “change password” view. When using the switchView plugin, you define a “view” simply by placing a CSS class prefixed with view-on- on an element (the prefix can be configured). So let’s define two views: view-on-login and view-on-change-pw. Then to switch to the change-pw view, do:

1
$('body').switchView('changePw');

Now let’s look at how we would add the CSS classes to our elements:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<p>
    <label>Username</label>
    <input type="text" name="username" />
</p>
 
<p>
    <label>Password</label>
    <input type="text" name="password" />
</p>
 
<p class="view-on-change-pw view-hidden">
    <label>Confirm Password</label>
    <input type="password" name="confirmPassword" />
</p>
 
<a href="#" class="view-on-login">Change Password</a>
 
<input type="submit" value="Login" class="view-on-login" />
<input type="cancel" value="Cancel" class="view-on-change-pw view-hidden" />
<input type="submit" value="Change Password" class="view-on-change-pw view-hidden" />

You’ll notice that I didn’t add any classes to the Username or Password fields as these are used in both views. Another option would be to place two view classes on those such as:

1
2
3
4
<p class="view-on-login view-on-change-pw">
    <label>Username</label>
    <input type="text" name="username" />
</p>

Additionally the view-hidden class has a single rule of .view-hidden { display: none; } which is used to hide elements by default.

Two final points to wrap up here, the context and groups. In the code below:

1
$('body').switchView('changePw');

The switchView plugin is looking for any elements that contain a view-on-* class within the BODY. It’s possible to scope switchView to only work on say a div with ID #navigation.

1
$('#navigation').switchView('changePw');

The one thing to watch out for, is if you change the view based on the BODY element, it will then potentially hide the elements inside of #navigation which is most likely not what you want. So to address this, the switchView jQuery Plugin provides for the concept of a “group”.

1
2
3
4
5
6
7
<div class="view-group-login">
<p>
    <label>Username</label>
    <input type="text" name="username" />
</p>
...
</div>

Now that we have grouped our login form, we would do the following:

1
$('body').switchView('login.changePw');

You can still use ungrouped elements, but doing so will not affect the elements within the view-group-login. It’s also worth noting that you can have grouped elements located anywhere on the page. So for example, if you have two parts to your form that are in physically different locations in your document, you can just add a view-group-login to each section.

jQuery switchView Plugin by jdsharp

Enjoy!

Cheers,
– Jonathan

Written by jdsharp

November 24th, 2009 at 12:56 pm

Posted in Plugin-Extension

Duplicate and Clone Elements Multiple Times

without comments

Greeting again from the heartland. Here is a quick plugin that duplicates one or more elements n times. This function is similar to the clone() method but will clone the elements multiple times placing them in the same collection. If you were to call clone 5 times such as:

1
$('<div></div>').clone().clone().clone().clone().clone();

it would give you 5 separate collections of a div. The duplicate plugin below, puts a new collection of all elements duplicated on the jQuery stack.

1
2
3
<ul id="myList">
    <li><a href="http://www.flickr.com/photos/jdsharp-com/4088227698/">Percheron's are cool</a></li> 
</ul>

So here’s an example use case given the HTML above:

1
$('li').duplicate(5).appendTo('#myList');

The above code starts by selecting all LI on the page (in this case only 1 of them) then duplicate’s it 5 times and appends the duplicated element to the UL with an ID of myList.

Now for the plugin:

1
2
3
4
5
6
7
$.fn.duplicate = function(count, cloneEvents) {
	var tmp = [];
	for ( var i = 0; i < count; i++ ) {
		$.merge( tmp, this.clone( cloneEvents ).get() );
	}
	return this.pushStack( tmp );
};

Having this plugin return this.pushStack( tmp ) is what gives us a new collection. To pop this collection off the stack and return to our original elements call .end(). One final note, cloneEvents can be set to true to have jQuery’s clone method also clone any attached events. By default it clones just the element and not attached events.

That’s all for now!
– Jonathan

Written by jdsharp

November 9th, 2009 at 8:15 am

Calculating The Sum of Inputs

without comments

Greetings all, here’s a quick plugin to sum up the values of inputs or even html elements. I wrote this plugin recently for a fellow developer who had a series of input boxes that needed to be totaled. Let’s first take a look at the html:

1
2
3
4
5
6
Price 1: <input type="text" name="price01" class="price" /><br/>
Price 2: <input type="text" name="price02" class="price" /><br/>
Price 3: <input type="text" name="price03" class="price" /><br/>
Price 4: <input type="text" name="price04" class="price" /><br/>
Price 5: <input type="text" name="price05" class="price" /><br/>
Total: <span class="total"></span>

The HTML above allows for entering a price for each of five items. (price01 through price05). While it is possible to manually select each element and sum their totals, in the actual use case there are a number of additional inputs.

1
2
3
4
5
6
7
8
9
10
11
12
$.fn.sumValues = function() {
	var sum = 0; 
	this.each(function() {
		if ( $(this).is(':input') ) {
			var val = $(this).val();
		} else {
			var val = $(this).text();
		}
		sum += parseFloat( ('0' + val).replace(/[^0-9-\.]/g, ''), 10 );
	});
	return sum;
};

Now the actual plugin starts by iterating over each of the inputs that the user selected (in our case the selector is input.price) and keeps a running tally. Line 4 determines of the current element selected is an input element, otherwise it uses the .text() jQuery method to return the contents of the element minus any HTML tags. Line 9 strips out any non-digit characters, – and . and parses the string into a float. ('0' + val) portion ensures that we have at least a value in the field. Finally the second argument to parseFloat() ensures that the float is parsed in base 10 for the conditions where the user entered a leading zero.

Finally, let’s make use of our plugin and wire it up:

1
2
3
4
5
$(document).ready(function() {
	$('input.price').bind('keyup', function() {
		$('span.total').html( $('input.price').sumValues() );
	});
});

On line 2 we bind the keyup event to all inputs with a class of price, sum up the values of those inputs and assign the result to span.total. There you go!

Until next time,
– Jonathan

Written by jdsharp

November 6th, 2009 at 8:00 am

Finding Immediately Adjacent Siblings

without comments

Greetings! Here’s a quick tip for advanced filtering of adjacent sibling nodes.

Given the following HTML:

1
2
3
4
5
6
7
8
<ul>
    <li>Item 1</li>
    <li class=”hello”>Item 2</li>
    <li class=”hello” id=”three”>Item 3</li>
    <li class=”hello”>Item 4</li>
    <li>Item 5</li>
    <li class=”hello”>Item 6</li>
</ul>

If you needed to select the immediate siblings of #three that matched the class .hello (so the resulting element set would be Item 2, Item 3, Item 4) there isn’t an easy way to do this. jQuery provides a prev() and prevAll() methods (as well as their next() counter parts) but that would return all of the elements. Here’s a jQuery immediateSiblings function to take care of this for us:

$(‘#three’).immediateSiblings(‘li.hello’)

Here’s the code for the plugin:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * immediateSiblings 1.1.0 (2009-10-19)
 *
 * Copyright (c) 2006-2009 Jonathan Sharp (http://jdsharp.com)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://jdsharp.com/
 *
 * Built upon jQuery 1.3.2 (http://jquery.com)
 */
$.fn.immediateSiblings = function(selector) {
    var siblings = [];
    this.each(function() {
        var children = $(this).parent().children(selector).not(this).get();
        $.merge(siblings, children);
    });
    return this.pushStack( $.unique( siblings ) );
};

Cheers,
-Jonathan

Written by jdsharp

July 14th, 2008 at 8:34 pm

Set Focus to the Next Input Field with jQuery

without comments

Setting focus to input fields is easy enough with JavaScript: document.getElementById(‘theInputField’).focus(); but sometimes you need a more generic solution as what happens when the next input field changes ID?

I was recently faced with the problem of setting focus to the next input field. The challenge was that I didn’t know what that field was. So given an input field, find the next logical (in the order of the DOM) input field and set focus. I came up with the following jQuery function (plugin) to accomplish this:

1
2
3
4
5
6
7
8
9
10
$.fn.focusNextInputField = function() {
    return this.each(function() {
        var fields = $(this).parents('form:eq(0),body').find('button,input,textarea,select');
        var index = fields.index( this );
        if ( index > -1 && ( index + 1 ) < fields.length ) {
            fields.eq( index + 1 ).focus();
        }
        return false;
    });
};

The use is as follows:

$( 'current_field_selector' ).focusNextInputField();

Let’s break this code down some:

$.fn.focusNextInputField = function() {

Start off by adding a new jQuery function/plugin

return this.each(function() {

Given a set of elements (this => jQuery object), iterate over them (we’ll return false which stop iteration after the first element.)

var fields = $(this).parents('form:eq(0),body').find('button,input,textarea,select');

Walk up the DOM tree (parents) until we find either the first form element or reach the body tag. Now find all button,input,textarea and select elements.

var index = fields.index( this );

Find out if our current DOM element (this) is in the jQuery collection. Index will return -1 if it is not.

if ( index &gt; -1 &amp;&amp; ( index + 1 ) &lt; fields.length ) {

See if we have a match and make sure we aren’t the last element

fields.eq( index + 1 ).focus();

Select the next input field ( index + 1 ) and set focus to it.

}
return false;

Return false so we stop iteration after this element. So if you call $(…).focusNextInputField() with multiple elements, it will only set focus to the next input field of the first element.

Good luck & enjoy!

Written by jdsharp

May 27th, 2008 at 4:02 pm

jQuery Calculate Plugin

without comments

Dan G. Switzer, II wrote a plugin for easy calculation. It was recently brought up on the jQuery list (Google Groups | Nabble). Worth a look!

http://www.pengoworks.com/workshop/jquery/calculation.plugin.htm

Update: Dan has posted a blog entry that covers use cases and some of it’s innner workings in more detail, again worth a look! http://blog.pengoworks.com/index.cfm/2008/1/23/jQuery-Calculation-Plugin-Making-calculating-easy

Written by jdsharp

January 23rd, 2008 at 3:07 pm

Posted in Plugin-Extension

Aspect Oriented Programming and jQuery – APO and JavaScript

without comments

This was brought up on one of the jQuery lists a little while back. A solid implementation that is lean on code. Also worth noting is that while this uses the jQuery namespace, there isn’t anything jQuery specific. Great project!

http://code.google.com/p/jquery-aop/

Written by jdsharp

January 18th, 2008 at 10:00 am

Plugin Namespace

without comments

This recently came up again on the jquery-en Google Groups list, here’s a way that you can namespace your plugin.

http://www.nabble.com/Re%3A-passing-this-p13540912s27240.html

Written by jdsharp

December 12th, 2007 at 12:49 pm