Archive for the ‘Plugin-Extension’ Category
SwitchView Plugin Released
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
Duplicate and Clone Elements Multiple Times
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
Calculating The Sum of Inputs
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
Finding Immediately Adjacent Siblings
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
Set Focus to the Next Input Field with jQuery
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 > -1 && ( index + 1 ) < 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!
jQuery Calculate Plugin
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
Aspect Oriented Programming and jQuery – APO and JavaScript
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!
Plugin Namespace
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