» tagged pages
» logout

sorted by: recent | see : popular
Content Tagged with jQuery + DOM

XML.com: jQuery and XML

Nice tutorial about JQuery and parsing XML

XML: del.icio.us/tag/xml

PHP Simple HTML DOM Parser (jQuery Style)

The Simple HTML DOM Parser is implemented as a simple PHP class and a few helper functions. It supports CSS selector style screen scraping (such as in jQuery), can handle invalid HTML, and even provides a familiar interface to manipulate a DOM.

XML: del.icio.us/tag/xml

jQuery Taconite Plugin

jQuery plugin, that allows to easy update content on the page in the several places without any xml parsing.

XML: del.icio.us/tag/xml

jQuery Taconite Plugin

Плагин для jQuery, который позволяет легко обновлять DOM в нескольких местах используя AJAX запрос.

XML: del.icio.us/tag/xml

Three Quick Ways to Avoid Widows

A few months ago I threw together a quick redesign of the Learning jQuery site. It's nothing fancy, mind you, but I was itching to retire the thin veil covering the tired old WordPress Kubrick theme, so something had to be done.

Almost immediately upon changing the font-family and font-size of the blog post titles, I noticed a few unsightly widows (just to clarify, we're talking about typographical widows. My mother already suspects me of avoiding her; I don't want to add to her anxiety. ;) ).

Here is an example of one such widow:
widow

See how the last word, "plugin," appears on its own line? According to a couple designerly friends of mine, that's a no-no. So, I considered for half a minute how to get that title to look more like this:
no widow

The lowly yet lovely non-breaking space ( ) would do the trick, but how to replace it for the regular, breaking space? I certainly wasn't about to manually edit all of the entries' titles. Not only would it take too long, but it would also pollute the markup with something that really shouldn't be there. No, what I needed was a little JavaScript.

Selecting the Titles

On this site, entry titles are wrapped in <h2><a href="foo"></a></h2>, which can be selected in jQuery with $('h2 a'). Easy. Now, because I want to manipulate the text of each title independently, I'll need to use the .each() method, which is basically a chainable for loop. Inside the .each() is where I substitute the last breaking space with the non-breaking variety. Here are three ways I came up with to achieve this.

Array

The first approach was to convert the title string into an array of words and then stitch the array items back together, dealing with the last one specially.

JavaScript:
  1. $(document).ready(function() {
  2.   var h2Text = '';
  3.   $('h2 a').each(function() {
  4.     var h2Array = $(this).text().split(' '),
  5.       h2Last = h2Array.pop();
  6.     h2Text = h2Array.join(' ') + '&nbsp;' + h2Last;
  7.     $(this).html(h2Text);
  8.   })
  9. });

A couple things to note about line 5 above: (a) the variable is actually being declared (with a "var") because it's separated from the previous variable declaration by a comma rather than a statement-ending semicolon. (b) The JavaScript .pop() array method "pops" the last item off the array and returns it; so it's no longer part of h2Array, but its value is stored in the h2Last variable. This is especially handy for us, because we don't want the last word to appear twice.

Line 6 joins the remaining array items with a space between them and then appends the non-breaking space and the popped last item. Line 7 dumps that concatenated string back into the title, inside <h2><a></a></h2>.

String

The next approach involved working solely with strings, using the slice and lastIndexOf methods to split the the string into two pieces — one leading up to the last space, and one immediately following the last space.

JavaScript:
  1. $(document).ready(function() {
  2.   var h2all, h2a, h2b;
  3.   $('h2 a').each(function() {
  4.     h2all = $(this).text();
  5.     h2a = h2all.slice(0, h2all.lastIndexOf(' '));
  6.     h2b = '&nbsp;' + h2all.slice(h2all.lastIndexOf(' ')+1);
  7.     $(this).html(h2a + h2b);
  8.   });
  9. });

As line 7 demonstrates, the two sliced strings are stitched back together to keep the last two words on the same line.

Regular Expression

The final technique is the one I ended up sticking with, partly because it's the tersest and partly because I have a fondness for regular expressions:

JavaScript:
  1. $(document).ready(function() {
  2.   var h2Text = '';
  3.   $('h2 a').each(function() {
  4.     h2Text  = $(this).text().replace(/ (\w+)$/,'&nbsp;$1');
  5.     $(this).html(h2Text);
  6.   });
  7. });

The distinguishing feature here is line 4, which uses the replace regular-expression method. This method takes two arguments, a pattern to match against and a replacement value. For the pattern, which appears between the two slashes, we first match a space and then match one or more "word characters" (letters, numerals, or underscores). The parentheses capture all but that initials space, and the "$" at the end ensures that the match appears at the end of the string. The replacement argument starts with the non-breaking space and follows with $1, which refers to the first (and in our case, only) parenthetical "capture group." (Please forgive me if I've provided too much detail about the regular expression. I'm never quite sure how much of this stuff is worth mentioning, but since this entry is targeting beginners, I suppose it's better to err on the side of too much.)

Update

A few people pointed out in the comments that my regular expression could be improved, and I agree. In particular, as noted by Art Lawry, the \w can be changed to \S (that's an uppercase S) to match any non-whitespace character. That way it'll match characters such as ö and ç as well.

By the way, all three of these code examples can be reduced in length quite a bit. For example, the regular expression example can be pared down from 7 to 5 lines if we don't bother with the h2Text variable and instead do something like this:
$(this).html($(this).text().replace(/ (\w+)$/,' $1'));
However, the code is usually easier to read and maintain (for me, at least) if the value is first stored in a variable.

Any suggestions for improvement here? Any other approaches that you would recommend instead? Leave a comment.

jQuery: Learning jQuery

jQuery Taconite Plugin

Милый плагин для jQuery, который берет на вход XML-сниппет и позволяет одновременно вносить ряд изменений в DOM-модель документа.

XML: del.icio.us/tag/xml

jQuery Plugin - FlyDOM: Create DOM on the Fly

FlyDOM aims to be an easy-to-use plugin for jQuery that makes generating dynamic content quick and easy.

json: del.icio.us/tag/json

Using Low Pro for jQuery

Recently I have been getting a real buzz out of developing with jQuery. I've been using the library since 2006, releasing sporadic bits of code. In April of this year, I released the third revision of my most complex plugin, jMaps, and updated several other plugins, which are available in my mercurial repository.

This was also the same month I discovered a new plugin which has dramatically changed how I develop applications with jQuery. The plugin in question is Dan Webb's Low Pro for jQuery, a port of the plugin of the same name for Prototype.

What is Low Pro?

So what is Low Pro? It's a plugin that provides a way of making more object-oriented JavaScript through event delegation. jQuery's plugin architecture provides a really simple way of extending the core functionality, but there is no easy way of making macros of code that do several types of events on one element. Until now!

Probably the simplest way to explain how Low Pro works is to build a quick demonstration. Sometimes I find that too many tutorials out there expect prior knowledge, so with that in mind, I will try to make the tutorial as simple as possible. However, this example does use another couple of plugins that are outside the scope of this tutorial:

  • Live Query - Low Pro uses this plugin to make binding to dynamic elements in the DOM easier.
  • jQuery Validation - We'll use this plugin to show how we can bind other plugin functions to events.

Both these plugins already have excellent documentation, so if you wish to extend this example, please check them out.

Example 1: Creating a re-usable registration form

For this example we'll build a simple user registration form. This is something that is common enough on the web, but a nice advantage of this example is that it
can be used over and over again with little or no modification. Hopefully once you have learned this pattern, you will be able to see lots
of other applications that can be reused over and over again in the same fashion.

Our first step is to create our basic form:

HTML:
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  2.   "http://www.w3.org/TR/html4/strict.dtd">
  3. <html>
  4.   <head>
  5.     <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  6.     <title>Lowpro Example</title>
  7.     <script type="text/javascript" src="js/jquery.js" /></script>
  8.     <script type="text/javascript" src="js/jquery.livequery.js" /></script>
  9.     <script type="text/javascript" src="js/lowpro.jquery.js" /></script>
  10.     <script type="text/javascript" src="js/jquery.validate.js" /></script>
  11.     <script type="text/javascript" src="js/reg-form.js" /></script>
  12.   </head>
  13.   <body>
  14.     <div id="form-container">
  15.       <form method="post" action="." id="lowpro-form">
  16.         <fieldset>
  17.           <legend>User Details</legend>
  18.           <ul>
  19.             <li>
  20.               <label for="username">Username</label>
  21.               <input type="text" id="username" name="username" />
  22.             </li>
  23.             <li>
  24.               <label for="email">Email</label>
  25.               <input type="text" id="email" name="email" />
  26.             </li>
  27.             <li>
  28.               <label for="password1">Password</label>
  29.               <input type="password" id="password1" name="password1" />
  30.             </li>
  31.             <li>
  32.               <label for="username">Password (Again)</label>
  33.               <input type="password" id="password2" name="password2" />
  34.             </li>
  35.           </ul>
  36.           <input type="submit" class="register" value="Register" />
  37.         </fieldset>
  38.       </form>
  39.     </div>
  40.   </body>
  41. </html>

Now, we create our JavaScript file called reg-form.js. In here, we will create our class that we'll attach to the form. Inside this class, we'll create some functions that trigger on specific events. Every class created with Low Pro takes the form of $.klass({...});. Inside the curly braces, we use JavaScript prototype nature to create a pseudo-class. We will call our example RegisterForm.

JavaScript:
  1. RegisterForm = $.klass({
  2.   initialize : function(options) {
  3.  
  4.   }
  5. });

If you have developed in languages like PHP, Python, or Java, you've probably seen something like this before. This first function, initialize, is a reserved function in Low Pro that accepts one parameter—an options parameter (we'll discuss that later). This function is always called whenever you bind a class to an element. Because it does not require any event to trigger, it is very useful for setting up initial data or events on dynamic DOM elements.

Validation

The first thing we'll do is create our JavaScript validation rules. This tutorial does not cover the creation of these rules; however, they should be reasonably understandable. If you would like more information, please check out the excellent documentation.

JavaScript:
  1. RegisterForm = $.klass({
  2.   initialize : function(options) {
  3.     this.element.validate({
  4.       rules: {
  5.         username: {
  6.           required: true,
  7.           minlength: 4
  8.         },
  9.         email : {
  10.           required: true,
  11.           email: true
  12.         },
  13.         password2 : {
  14.           equalTo: "#password1"
  15.         }
  16.       },
  17.       messages : {
  18.         username : {
  19.           required: 'Your username is required',
  20.           minlength: 'The minimum number of characters is 4'
  21.         },
  22.         email : {
  23.           required: 'You must enter your email',
  24.           email: 'You must enter a valid email'
  25.         },
  26.         password2 : {
  27.           equalTo: 'Your passwords must match'
  28.         }
  29.       }
  30.     });
  31.   }
  32. });

Notice that I am using this.element instead of $('#lowpro-form') inside the function. Low Pro provides this handy alias so you always work with the correct object. If you are going to be writing a complex function, it's always a good idea within the function to assign it to another variable.

But this code isn't actually doing anything yet. This is because we now need to bind the class to the form. Here is where we go back to the good old jQuery we know and love. Below the class, put this in the file:

JavaScript:
  1. $(document).ready(function(){
  2.   $('#lowpro-form').attach(RegisterForm);
  3. });


Now, open up the page in your browser and start to type into the fields. You should start to see the validation rules apply to the fields. Congratulations, you've written your first re-usable class with Low Pro!

Enhancements

Now that we have our validation rules, let's start to make the form a bit more sexy. First, something simple. Let's make sure that the first field (the username field) is always selected first, so the user can easily tab down the form. After the validation method inside the initalize function, add this:

JavaScript:
  1. $('#username').focus();

Refresh the page, and your username field should now get the focus.

Now let's introduce another event into the mix. When the user submits the form, we want to let the user know that it's being sent to the server. To do this, we could notify the user by changing the text on the button from "Register" to "Submitting".

JavaScript:
  1. RegisterForm = $.klass({
  2.   initialize : function(options) {
  3.     ...
  4.   },
  5.   onsubmit : function() {
  6.     $form = this.element;
  7.     $('.register').val('Submitting');
  8.         /* If your using Ajax it goes in here */
  9.         return false;
  10.   }
  11. });

So there we have it: A reusable, fully functional Ajax registration form with validation. You can check out a demo here and also grab the source code of this example from my repository.

One final thing I should touch on in this first tutorial is the initialize function's options parameter. When attaching any Low Pro class, the initialize function accepts an object containing any options you want to pass into the function:

JavaScript:
  1. $('#myform').attach(MyFunction, {foo:'moo', bar:2}

In our above example, we'll add a tag to display a message of the day. In the HTML, create a div with a class of motd. Next, add the following code into the initalize function:

JavaScript:
  1. if (options.motd) {
  2.   $('.motd').text(options.motd);
  3. }

Now, when we attach our class to the form, we use the following:

JavaScript:
  1. $(document).ready(function(){
  2.   $('#lowpro-form').attach(RegisterForm, {motd: 'jQuery Rocks!'});
  3. });

When you now refresh the form, you should see a message on the screen.

Well, that wraps it up for this tutorial. I hope I've given you a small idea of the power that Low Pro contains. In conjunction with LiveQuery, you can really create some dynamic and interesting applications.

If anyone would be interested in more tutorials like this, then please leave a comment and let me know what you think.

Tane Piper is a full time web developer, geek and Humanist from Edinburgh, Scotland.(55.957898, -3.159792)
He has released or is working on several open source projects including jMaps and Mercurial manager.
He is also available for hire as a freelance developer, working with PHP, Python and JavaScript.

jQuery: Learning jQuery

Working with Events, part 1

CSS and JavaScript are different in many ways, almost all of which are too obvious to mention. However, one difference between the two bears explanation, because it is often the cause of confusion and consternation, especially among those who are making the transition from CSS guru to jQuery novice. In fact, it was one of the first things I asked about on the jQuery mailing list back in 2006. Since then, I've seen at least one question on the subject every week, and sometimes as many as one per day—despite an FAQ page and these three plugins to help users deal with it.

How CSS and JavaScript Are Different

So, what's this important difference?

In CSS, style rules are automatically applied to any element that matches the selectors, no matter when those elements are added to the document (DOM).

In JavaScript, event handlers that are registered for elements in the document apply only to those elements that are part of the DOM at the time the event is attached. If we add similar elements to the DOM at a later time, whether through simple DOM manipulation or ajax, CSS will give those elements the same appearance, but JavaScript will not automatically make them act the same way.

For example, let's say we have "<button class="alert">Alert!</button>" in our document, and we want to attach a click handler to it that generates an alert message. In jQuery, we might do so with the following code:

JavaScript:
  1. $(document).ready(function() {
  2.   $('button.alert').click(function() {
  3.     alert('this is an alert message');
  4.   });
  5. });

Here we are registering the click handler for the button with a class of "alert" as soon as the DOM has loaded. So, the button is there, and we have a click function bound to it. If we add a second <button class="alert"> later on, however, it will know nothing about that click handler. The click event had been dealt with before this second button existed. So, the second button will not generate an alert.

Let's test what we've just discussed. I've added a script with the above three lines of jQuery code so that the following button will produce an alert message when clicked. Try it: Alert!

Events Don't Work with Added Elements

Now, let's create a new button (if we don't already have a second one) using jQuery code like this:

JavaScript:
  1. $('#create-button').click(function() {
  2.   if ( $('button.alert').length <2) {
  3.     $('<button class="alert">Not another alert</button>').insertAfter(this);
  4.   }
  5.   return false;
  6. });

create the button

Have you clicked the link to create the second button? Great. Now click that button. It does nothing. Just as expected.

CSS Continues to "Work" with Newly Created Elements

Now let's take a look at another example. In this one, we have three list items—two plain items and one with a class of special:

HTML:
  1. <ul id="list1" class="eventlist">
  2.   <li>plain</li>
  3.   <li class="special">special <button>I am special</button></li>
  4.   <li>plain</li>
  5. </ul>

Press the "I am special" button to create a new list item with a class of "special":

  • plain
  • special I am special
  • plain

Notice that, like the first special li, the new one has the yellow background. The CSS has come through for us. But press the newly created "I am new" button and, just as with the second alert above, nothing happens. The jQuery code we're using to add the new item says that upon clicking a button inside a list item with a class of "special" (which itself is inside an element with id of "list1") a new list item with class="special" should be inserted after the list item in which the button was clicked:

JavaScript:
  1. $(document).ready(function() {
  2.   $('#list1 li.special button').click(function() {
  3.     var $newLi = $('<li class="special">special and new <button>I am new</button></li>');
  4.     $(this).parent().after($newLi);
  5.   });
  6. });

So, how can we get the events to carry over to the new elements? Two common approaches are event delegation and "re-binding" event handlers. In this entry, we'll examine event delegation; in part 2, we'll explore ways to re-bind.

Event Delegation: Getting Events to Embrace New Elements

The general idea of event delegation is to bind the event handler to a containing element and then have an action take place based on which specific element within that containing element is targeted. Let's say we have another unordered list: <ul id="list2"> ... </ul>. Instead of attaching the .click() method to a button — $('#list2 li.special button').click(...) — we can attach it to the entire surrounding <ul>. Through the magic of "bubbling," any click on the button is also a click on the button's surrounding list item, the list as a whole, the containing div, and all the way up to the window object. Since the <ul> that gets clicked is the same one each time (we're only creating items within the <ul>), the same thing will happen when clicking on all of the buttons, regardless of when they were created.

When we use event delegation, we need to pass in the "event" argument. So, in our case, instead of .click(), we'll have .click(event). We don't have to name this argument event. We can call it e or evt or gummy or whatever we want. I just like to use labels that are as obvious as possible because I have a hard time keeping track of things. Here is what we have so far:

JavaScript:
  1. $(document).ready(function() {
  2.   $('#list2').click(function(event) {
  3.     var $newLi = $('<li class="special">special and new <button>I am new</button></li>');
  4.   });