jQuery, Radio-buttons and attr(‘checked’)

To make this a bit more searcable on the magic intarwebs:

jQuery 1.6.x changed the behaviour of attr(‘checked’), as it is no longer used to manipulate the state of radio buttons (or other elements using the checked element). This is considered a property, not an attribute (the difference is subtle), so instead of:

    $("#element").attr('checked', 'checked'); // or
    $("#element").attr('checked', true);

The correct ™ way of doing this is:

    $("#element").prop('checked', true);

Complete Example of Tracking Start and End of Drag Operations with jQuery and Table Rows

After writing my previous post about “Keeping track of indexes while dragging in jQuery UI Sortable” I received a question about how this would work for sortable table rows. The code I included in the previous post should actually be enough to make everything work (.. as long as I understood the question correctly). I’ve created a minimal example as a complete implementation of the code from the previous post, and I’ve also included it as a live demo here.

This is based on jQuery 1.5.1 and jQuery UI 1.8.13. I’ve simply used the distribution versions of this example (you probably want to build your own UI bundle using the interface on the jQuery UI website).

Here’s a live demo that you can play with.

Inline javascript and WordPress could possibly be better friends.

The complete source for the minimal (but complete) example is included here:



    
        
        jQuery UI Example Page
        
        
        
        
    
    
        
Dragging from index
None
Hovering index
None
Keys Values
Key 1 Value 1
Key 2 Value 2
Key 3 Value 3
Key 4 Value 4
Key 5 Value 5
Key 6 Value 6

Keeping track of indexes while dragging in jQuery ui.sortable

While you’re handling a drag operation in the jQuery UI Sortable handler, there’s a few small issues that might almost drive you insane. These two solutions are based on information from various places on the net (such as a few discussions on Stack Overflow).

If you want to keep track of which location the item you’re dragging originated from, you can attach to the ‘start’ event in the Sortable configuration constructor. Use this event to attach the origin index as a data element:

start: function(event, ui) {
    ui.item.data('originIndex', ui.item.index());
},

If you want to find out what index the user is currently hovering above (to change the numbering of a list instantly), you can use the same method on the placeholder element (available as ui.placeholder, so to fetch the current index the user is hovering over, call ui.placeholder.index()). There is however a gotcha’ here, as the original element is still present in the list – just allow to float freely around (the dragging action). We handle this by fetching the origin index and subtracting one if we’re after the location we started at.

You can handle these events in the ‘change’ event handler:

change: function (event, ui) {
    var originIndex = ui.item.data('originIndex');
    var currentIndex = ui.placeholder.index();

    if (currentIndex > originIndex)
    {
        currentIndex -= 1;
    }

    // do magic
}

Unbreak My Hea.. Firefox Ctrl Click Please!

When we launched Gamer.no over a year ago, we had to come up with a wallpaper advertising solution in a rush (everything were a rush back then as we built and launched a site from scratch (after disagreements between the previous owner and Gamer) in just under four days (or 96 hours)). While this solution has worked .. good enough .. it has always had a few irky bugs that I’ve never really had the right inspiration to uncover the cause of. Usually I’ve spent an hour and decided that the time wasn’t worth it at the moment and then moved onto something else, but today! Today is a glorious day!

The bug has been fixed!

The wallpaper element is placed around the main content div, which sadly also makes the wallpaper element receive any click elements that the main content div receives. This leads to the wallpaper getting clicked and the wallpaper ad window opening regardless of where people click – which will get very, very annoying very quick. So to battle this issue the original solution was to call .stopPropagation() on the evt object in a click handler for the main content div. This solved the issue and everyone rejoiced! However, all was not perfect in paradise.

Some time later we discovered that the .stopPropagation() fix borked ctrl-click a link in Firefox. Other browsers handled it just fine, but Firefox were obviously not happy. Not happy at all. Mad and going on a killing spree it shot down the proposed fixes from both myself and other people who had a brief look at the code. It wasn’t a big issue as we only run the wallpaper code for small intervals of time and people didn’t complain (maybe we were some of the few who had the issue).

Today I decided to have a look at the issue again, and finally I realized that we had been way to focused on our call to .stopPropagation(). Everyone had been planning how we could get .stopPropagation to do what we wanted it to do – after all – the issue was that stopPropagation didn’t behave when we ctrl-clicked in Firefox. But wait.

If you instead think of the original problem; the window.open gets triggered when people click the inner element instead of the outer, there may be alternative solutions to using stopPropagation. And yes, THAT was quite a simple fix. Instead of trying to stop the event from bubling up through the cloud.. let’s just set a status variable that tells the code handling the wallpaper click that THIS CLICK IS NOT FOR YOU BAD HANDLER GO AWAY LET OTHER GROWNUPS HANDLE THIS. So that I did.

$(document).ready(function () {
    innerClick = false;
    $('#wallpaper').click(function() {
        if (innerClick)
        {
            innerClick = false;
            return true;
        }
        
        window.open("..");
    });
    $('#content').click(function(evt) {
        innerClick = true;
    });
});

As soon as I actually spent some time on what we were trying to solve instead of what seemed like the cause of the issue .. everything went better than expected.

jQuery, .getJSON and the Same-Origin Policy

When creating a simple mash-up with data from external sources, you usually want to read the data in a suitable format – such as JSON. The tool for the job tends to be javascript, running in your favourite browser. The only problem is that requests made with XHR (XMLHttpRequest) has to follow the same origin policy, meaning that the request cannot be made for a resource living on another host than the host serving the original request.

To get around this clients usually use JSONP – or a simple modification of the usual JSON output. The data is still JSON, but the output also includes a simple callback at the end of the request, triggering a javascript in the local browser. This way the creator of the data actually tells the browser (in so many hacky ways) that it’s OK, I’ve actually thought this through. Help yourself.

In jQuery you can trigger the usual handling of events by using “?” as the name of your callback function. jQuery will handle this transparently and then trigger the function you provided to .getJSON in the first place.

Example

url = "http://feeds.delicious.com/v2/json/recent?callback=?";

$.getJSON(url, function(data) { alert(data); });

There’s an article up at IBM’s developerWorks giving quite a few more examples and information about the issue.

A couple of issues with SWFUpload 2.5.0b1

The first beta of SWFUpload 2.5.0 was released during christmas, and just a few quick notes for those who are going to attempt an upgrade:

button_cursor: SWFUpload.CURSOR.HAND,

.. seems broken. This will probably be fixed soon, but currently I’ve been unable to get the proper mouse cursor for a button.

If you previously relied on any custom settings being available in the settings object (by providing them when initializing the component), SWFUpload 2.5.0 does not include them in the this.settings object any longer.

If you want to include any custom settings, they’ll now have to be included in a setting for that purpose (together with the other options in the settings object):

swfu = new SWFUpload({
    [settings settings]
    custom_settings : {
        redirect : true,
        redirect_delay : 500
    },
    [more settings]
});

These values will then be availble through this.settings.custom_settings in your callback functions, such as this.settings.custom_settings.redirect etc.

Both issues has been reported on the v2.5.0b1 announcement.

Avoiding Resetting the Scroll Position in a Textarea When Inserting Content

Now, that’s quite a headline. And this post will explain just the simple concept posted in the headline. How to avoid (at least) firefox from scrolling to the top when you insert content into a textarea.

It’s simple. Very simple. And it was shown to be so very simple for someone who didn’t remember scrollTop by this thread.

In jQuery (which we use with the caret plugin):

currentScrollPosition = $("#textareaId").scrollTop();
/* do stuff */
$("#textareaId").scrollTop(currentScrollPosition);

Yep. So simple that it actually hurts a bit.

An Update to jQDynamicFontSize

When we released jQDynamicFontSize a couple of weeks ago, we hoped that others would find the plugin useful and keep it around as one of the many tools in your toolbox. We also had a small hope that people would find it useful to extend and maybe submit a patch or two back to us.

And lo’ and behold, during the weekend the first patch arrived in my mailbox. Written by Vegard Andreas Larsen, we now also support scaling against the width of a container. I didn’t even have an idea around this, and suddenly we have working code. The power of open source!

This adds two new options when initializing jqDFS:

  • limitWidth: Uses the width of the element to determine the size instead of the height. Defaults to false.
  • allowUpscaling: Allows the element to grow instead of shrink to fit the provided area. Only works when limitWidth is active currently. Defaults to false.

The original scale method should probably be rewritten to also use allowUpscaling, so if anyone feels slightly hackish tonight, just send the patch my way!

jQuery – IE triggers several click events

Strange problem occurred today, one of the very rare occasions were the behaviour of jQuery differed between Internet Explorer and Firefox. I’ve been trying to create a minimal example that replicates the behaviour, but have failed so far.

The problem was that in IE a click event triggered several times, which led an element to be expanded and then contracted again. This did not happen in Firefox. I found out that the problem was that I had placed my jQuery segment further inside the loop than I meant to, leading to code being duplicated four or five times through the page. After removing the duplicated function names and binds to .click(), everything worked as it should.

If you get several events triggered in Internet Explorer, but not in Firefox, check that you’re not accidentally binding the same function several times (.. while creating a minimized example that does this, I got the expected behaviour in both browsers, so I’m not completely sure of the reason). It might be worth a try as a fix, tho.

Internet Explorer 8 and Their XSS Filter

There’s an interesting post up on the technet Security Vulnerability Research & Defense blog, providing a deeper look into how the XSS filter destined for release together with Internet Explorer 8 works. While it looks like a novel approach, I’m not sure how many of the actual attacks will be detected and guarded against. It will be interesting to get to play around with it later, and if it works as good as they say, it’ll provide some protection for the users of Internet Explorer against a class of attacks.

They provide several examples of issues that will not be mitigated by this filter, which includes attacks where the content is inserted directly into javascript (instead of spawning from an HTML-context).