nooshu - Matt Hobbs' Web Development Blog

Kneeling on the shoulders of giants

Category: jQuery

Posts relating to my favourite JavaScript library, jQuery.

Auto-spacing input field text

On a recent project, a set of wireframes landed on my desk which contained some “interesting” ideas, particularly when it came to form fields. One that really stood out was having a credit card number auto-space as the user types it into a single input box. This of course would depend completely on what type of card they are entering, as different cards have different layouts. American Express for example have a [4, 6, 5] layout, where as Visa use a [4, 4, 4, 4] number layout.

Thankfully this functionality was eventually removed from the UI specifications after concerns from myself and others were raised. Just to make this perfectly clear; I think this is a bad idea, and here is why:

  • Users are very wary when it comes entering their credit card details. Spaces magically appearing in their credit card number could freak a few of them out.
  • Most e-commerce website I’ve ever used ask for the credit card number as one long string of numbers with no spaces. Auto-spacing goes against this convention, so a user may actually go back and try to remove the spaces (I know I would).
  • Validation scripts for credit card numbers usually ask for the input to have no spaces, or will remove any spaces on submit.
  • If you do want to space out the credit card number, why not use different input boxes for each set of numbers? It looks cleaner and is simpler to implement. Just have your JavaScript automatically jump between boxes as the user types.

Even though this functionality was removed, I decided to build a prototype of it in action because… well because I can and I was bored. :) Please, (please!), whatever you do don’t use this code in production. I created it as an experiment and should be treated that way. It’s very simple to get around the auto-spacing and then all hell breaks loose! (not really, but it is easy to break).

The spacing is implemented by counting the length of the string inside the input field, but you could also monitor the current position of the cursor. Anyone wishing to do this see this excellent set of answers on Stackoverflow.

You can see the prototype here. Remember, don’t use it. It’s not big and it’s not clever :)

Remote Loading HTML5 Elements with jQuery

I ran into a rather annoying problem a few months ago while developing my travel blog; the problem of course was involving Internet Explorer. I’m used to working with WordPress as I use it all the time, but I wanted to get away from the standard pagination you find on a blog. So I decided to use jQuery 1.6.4 to pull in articles from other pages (blogname.com/page/2, blogname.com/page/3 etc). Now this is all fairly simple using the handy jQuery .load() method; point it to a URL, pull in the page, pick the bits you need and reinsert into the page. Simple! Unfortunately once I got a prototype working in ‘good’ browsers, IE8 and below was having non of it!

After a little head scratching to work out what was failing, I worked out it was because I was using HTML5 elements such as ‘article’, ‘header’ and ‘footer’. There was no problem displaying them on the page, as I’d used Remy Sharps excellent HTML5 Shiv script. It only failed when trying to pull in these ‘new’ elements via Ajax.

Note: Before you read on you’ll be happy to hear that this issue no longer occurs in jQuery 1.7.0. Horray!

If you can’t upgrade, for whatever reason, I hashed together a little work-around for browsers IE8 and below, so read on. I admit the work around isn’t pretty, but it works. I tried for a few hours to get IE8- to recognise the ‘new’ elements after an Ajax request, but to no avail. Eventually I had to wrap the HTML5 tags in a div using conditionals:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--[if lt IE 9]><div id="ieHackContainer"><![endif]-->

<article id="html5Content">
    <header>
        <h2>H2 wrapped in a header element</h2>
    </header>
    <!-- Other HTML here... -->
    <footer>
        <p>This is the footer element</p>
    </footer>
</article>

<!--[if lt IE 9]></div><![endif]-->

The div is added for browsers IE8 and below, you can then use it as a hook to pull in the elements inside the div. I was hoping that wrapping the HTML5 elements in a standard div would be the end of it, I’m afraid not. The .load() method still didn’t work, IE just ignored the elements it didn’t recognise. I used jQuerys much more customisable .ajax() method to fix the issue in IE6, 7 and 8:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//IE8- work around to load HTML5 elements into a page
$("#loadHTML5LinkOld").click(function(){
        $.ajax({
                url: "page_to_load.html",
                cache: false,
                success: function(html){
                        var HTML;
                        //Clear before load
                        $("#html5LoadHolder").empty();
                       
                        //IE: Look for the hacky wrapper before insertion
                        HTML = $(html).filter("div#ieHackContainer").html();
                       
                        //If HTML var is empty assume using newer browsers
                        if(!HTML){
                                HTML = $(html).filter("#html5Content").html();
                        }
                       
                        //Append to page
                        $("#html5LoadHolder").append(HTML);
                }
        });
       
        return false;
});

This method works in all browsers I’ve tested in as I’ve added a fall back (or should that be forward?) for newer browsers. The solution isn’t ideal (I really hate the conditional comments), but older versions of IE aren’t going away any time soon, and it works. Maybe there’s a more obvious solution that I missed? Leave a comment if there is, I’d love to know!

You can see a working example here. The page I’m loading from is here and the JavaScript in full here.

Visual thesaurus using arbor.js

Wow, I can’t believe we are at the end of January – one twelfth of the year gone already! I’ve been so busy this month I’ve barely had time to sit down and work on any personal projects. Thankfully I had a spare few hours over the weekend to work on a project I’ve been meaning to finish for a couple of weeks: a visual thesaurus using JavaScript.

Visual Thesaurus using JavaScript

Visual thesaurus representation of the word 'clean'.

You may (or may not) know of the Visual Thesaurus by Thinkmap; very useful but it’s a paid for service, I use it so infrequently I can’t justify paying for it (there is a free trial though). Recently a very interesting graph visualisation library popped up on delicious called arbor.js, so I decided to have a closer look and see if I could use it for the JavaScript version. For the word data I’ve used the Bighugelabs thesaurus API which I previously used to create my Post Thesaurus WordPress plug-in (shameless plug!).

Arbor.js took a little getting used to as it uses a mixture jQuery, canvas and its own methods; but there’s a fairly extensive set of documentation and a set of usage examples. Once you get your head around adding nodes and edges to the system, arbor takes care of the rest. One thing I did notice is the site examples and my VT experiment run much smoother in Firefox than they do in Chrome, which is quite surprising considering how quick the V8 engine is in Chrome. Maybe this will be improved in future versions.

So to the demo; I’ve tried to keep it very simple to use. Enter the word you wish to visualise and click search. Once the API returns a result it’s plotted by arbor. You can drill down into the result by clicking on the sub-particles (and remove them by clicking again). The individual words can be clicked and you’re given the option to search again using the selected word. I still haven’t got the perfect system setup as some results can be a little jittery; usually when an even set of words are returned. I’ll keep playing with system settings to see if I can improve this.

Any suggestions, comments or feature improvements please leave a comment below!

jCarousel missing item width

On a recent project the UX team put together a set of wireframes where the use of carousels featured heavily. Luckily when you choose a JavaScript library like jQuery you have quite a few carousel plug-ins to choose from. I’ve used various different ones in the past, but my favorite is called jCarousel. You only have to take a quick look at the jCarousel homepage to see that it will do pretty much anything you ask of it. So in theory it should be a case of copy / paste the code into your site and you’re away. Unfortunately Web Development doesn’t always work that way; a small oversight can leave you racking your brains for hours… arghh!

The design and layout layout had already been created in the usual fashion. All that was left to do was to layer on all the JavaScript goodies (the fun part!). While implementing jCarousel I ran into a curious console error message:

“jCarousel: No width/height set for items. This will cause an infinite loop. Aborting…”

When I checked the carousel CSS, the item width had been set:

1
2
3
4
5
6
7
.product {
    float: left;
    display: inline;
    text-align: center;
    font-size: 0.75em;
    width: 75px;
    }

Strange. The width had been set, so the error message must be from something else. After a few minutes investigation it turned out that the carousel didn’t have a parent with a set width. When fired the carousel is wrapped with two divs; one wraps the carousel, the other wraps the carousel and the navigation. Neither of these divs have an explicit width set which is what was causing the problem. It was a very quick fix in the end:

1
2
3
4
.jcarousel-container {
    padding: 20px 0 0;
    width: 300px;/* Fixed! */
}

Upon a little more investigation it seems you can fix this issue in other ways too. Instead of using a class of “product” to set the item widths I tried using the following:

1
2
3
4
5
#carousel li {/* New selector also fixed it! */
    /*...*/
    font-size: 0.75em;
    width: 75px;
    }

Very strange! The CSS in both cases changes the same elements, it just ignored the width in the ‘product’ class.

So for anyone else encountering the same “No width/height set for items” issue here’s a quick check list for you to try:

  1. Make sure you set a width on the items (duh!). Maybe try different CSS selectors if necessary.
  2. Set a width on the “jcarousel-container” class or one of its parents.
  3. If all else fails, adapt one of the skin examples bundled with jCarousel.

The last one is very annoying if you have your carousel already styled up, but it is guaranteed to work.

Headspace2 JavaScript error

Update: An update of Headspace2 has just been released that seems to solve this issue as well as a few others.

After updating to WordPress 3.0 (yay!) I decided to check the plug-ins that I’ve written to see if they still worked in version 3.0; to my dismay Post Thesaurus had stopped working… nooooo! Not good! A quick scan using Firebug revealed the issue: the Headspace2 plug-in.

Headspace2 is a superb plug-in that allows you to tweak the SEO potential of your site. There are tonnes of options available; All In One SEO is easier to use, but I prefer the flexibility of Headspace2. The problem was occurring in the headspace-tags.js file:

1
2
3
$(get_tag_element()).val() is undefined
/wp-content/plugins/headspace2/js/headspace-tags.js?ver=3.6.32
Line 76

This error was stopping the rest of the JavaScript on a post page from firing (hence breaking Post Thesaurus). Looking at line 76 of headspace-tags.js you will see:

1
2
3
4
5
// Highlights headspace tags using the WordPress tag field as source
function highlight_tags () {
    var words = $(get_tag_element()).val().toLowerCase().split(',');
    //...
}

The code seems to be falling over when there are no tags, so I just added a ternary operator which checks the array length first.

1
2
3
var words;
var wordArray = $(get_tag_element());
(wordArray.length) ? words = $(get_tag_element()).val().toLowerCase().split(',') : words = [];

If there are no tags create an empty array, else run the usual code. Adding this code fixed the issue and Post Thesaurus works again. Phew! Panic over. I’m sure this error will be picked up by the developer straight away and fixed in the next update.

Currently on page 1 of 512345