Handy jQuery Plugins/Snippets

It seems almost the entire world has switched to using jQuery, and for good reason too! Here are some simple but helpful plugins and snippets I've written recently.

jQuery.fn.otherwise

jQuery first-timers always seem to be asking "How can I check if my selection didn't match anything?", to which the common answer is "just check the .length property". Try the following for a chainable solution instead.

Usage Example

$('button').click(function(){
    $('#msg p:first')
        .remove()
        .otherwise(function(){
            $('#msg').html('<div class="error">There are no more paragraphs to remove!</div>');
        });
});
 

<button type="button">Click me!</button>

<div id="msg">
    <p>This is the first paragraph.</p>
    <p>This is the second paragraph.</p>
    <p>This is the third paragraph.</p>
</div>

See it in action!

Plugin Code

jQuery.fn.otherwise = function(func) {
    if (!this.length) {
        func.apply(this);
    }
    return this;
};

jQuery.fn.followLink

This was my first attempt at a jQuery plugin. I wanted to simulate a link being clicked, however .click() only triggers jQuery click handlers and doesn't change the current page.

Usage Example

// navigate prev/next depending on left/right arrows pressed
$(document).keydown(function(e){
    if (e.which == 37) {
        $('#prev').followLink();
    } else if (e.which == 39) {
        $('#next').followLink();
    }
});

<a href="prev.html" id="prev">Go to the previous page</a><br />
<a href="next.html" id="next">Go to the next page</a>

See it in action!

Plugin Code

jQuery.fn.followLink = function(){
    this.attr('href', function(){ 
        window.location = this.href;
    });
};

jQuery.fromXMLString

Ever had a string of XML that you'd love to use jQuery on? Although you can pass an XML string to jQuery in Firefox without additional code, it doesn't work in IE7. Try this baby instead!

Usage Example

var strXML = '<people><person id="69"><name>Trent</name><location>Punchy</location></person></people>';
$('#location').text(
    $.fromXMLString(strXML).find("person[id='69'] location").text()
);

<p>Trent is from <span id="location"></span>.</p>

See it in action!

Plugin Code

jQuery.fromXMLString = function(strXML){
    if (window.DOMParser) {
        return jQuery(new DOMParser().parseFromString(strXML, "text/xml"));
    } else if (window.ActiveXObject) {
        var doc = new ActiveXObject("Microsoft.XMLDOM");
        doc.async = "false";
        doc.loadXML(strXML);
        return jQuery(doc);
    } else {
        return jQuery(strXML);
    }
};

Open external website links in a new window

Want all links away from your site to open in a new window? Although this is not as "jQuery-like" as the previous examples, it's fast and gets the job done.

It only modifies links that don't have a "target" attribute already set. I also like to make all pdfs open in a new window.

$(function(){
    $('A, AREA').filter(function(){
        return (!this.target && (this.href.indexOf(window.location.hostname) == -1 || this.href.match(/\.pdf$/i)));
    }).attr('target', '_blank');
});

See it in action!

New CakePHP “multitask” Plugin

What is multitask?

Multitask is a CakePHP plugin designed as a proof of concept task manager for non-interactive tasks.

It consists of:

  1. MultitaskerShell - a daemon that manages the tasks/threads
  2. MultitaskQueuedTask - a model for adding queued tasks
  3. ThreadedTask - a base class for your tasks

What does it do?

The multitasker shell acts as a daemon, getting a task from a model, executing it, and updating its status when done.

It could be used for executing long-running tasks in the background, such as tasks involving significant network activity or encoding video, etc.

Installation & Usage

  1. Copy the "multitask" folder into the plugins folder of your CakePHP app.
  2. Import the database schema from config/multitask.sql
  3. Run "multitasker" shell from the command line.

cd cake/console/
./cake multitasker -app ../../app

Then add some tasks into your database and it will execute them. :)

Here is some code that will add a task into the queue. Look in vendors/shells/tasks/echo.php for the task being executed.

$this->MultitaskQueuedTask = ClassRegistry::init('Multitask.MultitaskQueuedTask');

$task = array(
    'task' => 'echo',
    'data' => 'Hello, World!',
);

$this->MultitaskQueuedTask->create($task, true);
$this->MultitaskQueuedTask->save();


$task = array(
    'task' => 'echo',
    'method' => 'delayed',
    'data' => array('duration' => 3, 'message' => 'That was a nice sleep!'),
);

$this->MultitaskQueuedTask->create($task, true);
$this->MultitaskQueuedTask->save();

Known Issues

I've not used this in production and don't recommend you do either! Heck, I haven't used it aside from a few small tests, so use with caution.

The plugin is in its elementary stages, and doesn't handle scripting errors, task progress, task dependencies, task priorities, etc.

Requirements

PHP needs to be configured with pcntl and shmop extensions, as it uses PHP_Fork to handle threading.

I have only tested it on PHP5. Please let me know if you get it working on PHP4.

Windows Compatibility

Although the pcntl and shmop extensions don't run on Windows, I have added "linear threading" (ie. no threading) so you can test the functionality of your tasks on Windows.

Where can I get it?

UPDATE: I've now pushed it to github - http://github.com/ifunk/Multitask for easy downloading...