Toggle non-consecutive checkboxes with jQuery UI

You’re all probably familiar with the UI convention of allowing users to select ALL or NONE for a list of checkboxes (like in Gmail). Recently I was working on a project that had a large table full of checkboxes (imagine a 10x10 grid) where the user would need to toggle some but not all of the checkboxes in a given row. And to make matters more complex, they would need to toggle groups of non-consecutive checkboxes (say 15, skip 10, 5, etc.). I threw on the thinking cap but couldn’t think of any similar interactions I’d seen and couldn’t think of a particularly good way to achieve this.

Enter jQuery UI. I happened to stumble across the jQuery UI Selectable documentation and realized it would provide a good UI experience to toggle some but not all of the checkboxes. The code to implement this is surprisingly simple:

Note: You don’t actually need the div container - that was just for JSFiddle.
<div id="checkboxes">

<table id="checkboxTable">
     <tr>
         <td><input type="checkbox" /></td>    
          <td><input type="checkbox" /></td>
          <td><input type="checkbox" /></td>
          <td><input type="checkbox" /></td>
     </tr>
     <tr>
         <td><input type="checkbox" /></td>    
          <td><input type="checkbox" /></td>
          <td><input type="checkbox" /></td>
          <td><input type="checkbox" /></td>
     </tr>
     <tr>
         <td><input type="checkbox" /></td>    
          <td><input type="checkbox" /></td>
          <td><input type="checkbox" /></td>
          <td><input type="checkbox" /></td>
     </tr>
     <tr>
         <td><input type="checkbox" /></td>    
          <td><input type="checkbox" /></td>
          <td><input type="checkbox" /></td>
          <td><input type="checkbox" /></td>
     </tr>
     <tr>
         <td><input type="checkbox" /></td>    
          <td><input type="checkbox" /></td>
          <td><input type="checkbox" /></td>
          <td><input type="checkbox" /></td>
     </tr>
</table> 
</div> 

And then the Javascript (jQuery + jQuery UI):

$("#checkboxes").selectable( {filter: "input:checkbox",
            stop: function(event, ui) {
                
                $(".ui-selected").each( function(){

                    $(this).each( function(){
                        var val = $(this).attr("checked") ? null : "checked";
                        $(this).attr("checked", val);
                    });
                    
                });
}});

You can check out a live demo at http://jsfiddle.net/whMyQ/3/

As always, questions and comments are welcome!

Happy Holidays!

We just wanted to wish everyone a great holiday season. We hope everyone brings in the new year with a bang!

See you next year, Setfive

Facebook: How-to force users to LIKE page

With Facebook’s move to deprecate FBML for tabs the documentation around how to make a “please Like! before…” has become much more choppy and inconsistent. Anyway, I recently found myself in a position where I needed to make this happen so here goes.

With in-line FBML deprecated, the only way to accomplish this without using a third party branded solution is to create a Facebook iframe app. Here are the steps you need to take to get something up using PHP and the Facebook PHP SDK.

1. Create a new Facebook Application at https://developers.facebook.com/apps

2. Configure your new Facebook App the enable “Website” and “Page Tab”. You’ll need to enter a valid URL for the following fields:

  • Site URL
  • Page Tab URL
  • Secure Page Tab URL

You’ll also want to use a HTTPs URL since Facebook sessions default to HTTPs by default and your iframe will be marked insecure if its over vanilla HTTP. For this walk through, lets assume were using https://www.setfive.com/fb/index.php? as the URL.

3. Now, you’ll want to add your new App to a Facebook Page. The easiest way to do this is to use this URL https://www.facebook.com/dialog/pagetab?app_id=YOUR_APP_ID&amp;next=YOUR_URL replacing YOUR_APP_ID and YOUR_URL with your App ID and then a URL that is derived from your endpoint (or even just your endpoint). When you load that URL, you’ll be prompted to add your app to a page - select the page you want and submit the form.

4. The final piece is throwing together the actual PHP script. You’ll need the Facebook PHP SDK available on GitHub - https://github.com/facebook/php-sdk. Clone that and then this is the PHP script you’ll need:

<?php
require 'php-sdk/src/facebook.php';

$facebook = new Facebook(array(
  'appId'  => 'YOUR_APP_ID',
  'secret' => 'YOUR_APP_SECRET',
));

$req = $facebook->getSignedRequest();
?>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"xmlns:fb="http://ogp.me/ns/fb#">
    
<head>
    <meta charset="utf-8" />
    <title></title>
</head>

<body>

<?php if( $req["page"]["liked"] ): ?>

	Content for users that have LIKED the page.

<?php else: ?>
	
	Content for users that HAVE NOT LIKED the page.
	
<?php endif; ?>

</body>

</html>

And thats it! Now you’ll be able to gate content from non-fans while growing the fanbase of your Facebook Page.

Drop any questions in the comments.

Deleting files older than specified time with s3cmd and bash

Update: Amazon has now made it so you can set expiration times on objects in S3, see more here: https://forums.aws.amazon.com/ann.jspa?annID=1303

Recently I was working on a project where we upload backups to Amazon S3. I wanted to keep the files around for a certain duration and remove any files that were older than a month. We use the s3cmd utility for most of our command line based calls to S3, however it doesn’t have a built in “delete any file in this bucket that is older than 30 days” function. After googling around a bit, we found some python based scripts, however there wasn’t any that was a simple bash script that would do what I was looking for. I whipped this one up real quick, it may not be the best looking but it gets the job done:

#!/bin/bash

# Usage: ./deleteOld "bucketname" "30 days"

s3cmd ls s3://$1 | while read -r line;
  do
    createDate=`echo $line|awk {'print $1" "$2'}`
    createDate=`date -d"$createDate" +%s`
    olderThan=`date -d"-$2" +%s`
    if [[ $createDate -lt $olderThan ]]
      then 
        fileName=`echo $line|awk {'print $4'}`
        echo $fileName
        if [[ $fileName != "" ]]
          then
            s3cmd del "$fileName"
        fi
    fi
  done;

jQuery: binding DOM events to objects

A few days ago I was working on a project for a client that basically involved allowing a non-technical end user to build arbitrarily complex boolean queries using a UI. The user could basically click, configure, and drag/drop queries to build expressions like (A AND B OR C) AND (Z OR X). They would also need the ability to edit the pieces in-line, toggle ANDs to ORs, and so on.

Anyway, not to difficult to represent with a data structure but the complexity was going to be in tying the UI to the data structure with callbacks and events. Usually, I would of used a single $(“a”).click() handler to handle all the edit, delete, and configuration clicks in the UI but that quickly devolves into a disastrous mess of if statements and hasClass() checks.

Hoping to avoid this, I started thinking about cleaner ways to implement this and realized if I actually bound events to the individual objects they were going to effect the resulting code would be much cleaner. The UI elements were going to be dynamically generated each time the data structure was updated anyway so binding $.click() events on the <a> tags to their corresponding objects wouldn’t be to much extra work.

All in all, things worked out pretty well. The final code is much easier to follow and there isn’t a gigantic if() block which is impossible to trace.

I can’t share the actual implementation I used but I threw together an example which outlines the technique. Check out the JSFiddle at http://jsfiddle.net/fN46q/4/

Looking at the code, the Board object is an Array that in turn contains Piece objects to form a 3x3 grid.

The Piece objects individually supply a render function to display themselves and then contain a click() function which handles their $.click() events.

The key line which makes this work is:

   $(td).find("a").bind("click", {piece: this[i][j]}, this[i][j].click);

What the second parameter does is add the object into the Event object that is passed to the event handler. More info is available on the $.bind() documentation but looking at the click() function in the Piece object you can see where it comes in to play:

 click: function( e ){
    e.data.piece.val = !e.data.piece.val;
    e.data.piece.board.render();
    return false;
 }

So effectively, the data structure is now linked to the DOM.

As always, thoughts, comments and are feedback welcome!