Blog


JQuery ‘exists’ and ‘checked’ functionality

  • April 20, 2010
  • None

One of the brilliant things about jquery is that it’s so easy to extend, whether that be by writing your own full blown plugin, or with a quick 1 liner to add new functionality.

Here’s a couple that I always find handy. First up, adding an ‘exists’ function, so you can do this:

if ($(selector).exists()){
    //do something here if our selected element exists
}

the code is really quite simple, basically we return true if the JQuery object returned by our selector has a length greater than 0 (ie: if the selector matches anything), and false if it doesn’t.

jQuery.fn.exists = function(){
          return jQuery(this).length>0;
}

Next we have something I use all the time, a really simple function that returns true if the checkbox element you call it on is in the ‘checked’ state, and false if it isn’t. So you can do this:

if ('#mycheckbox').checked(){
      //do something here if the checkbox is checked
}

and the code to add that function is:

jQuery.fn.checked = function(){
         return jQuery(this).is(':checked');
}

Hopefully those will be of use to someone else, they’re not particularly complex but they can make your code easier to understand and save you a bit of typing.




Produce a ‘patch’ from a subversion repository

I use subversion quite extensively for PHP code versioning (in particular the excellent Redmine software project management tool has a built in subversion server) and recently had a requirement to produce a set of files that had changed from one revision to another. Specifically my repository has some changes committed to it that I don’t want propagating to the live server just yet, but I want some later changes moving across.

Subversion offers excellent branch / tag support, so if I’d thought this through properly I could have created a new branch for the dangerous changes I didn’t want to move to live, then merged any changes from there onwards back into the ‘live’ trunk…basically keeping two seperate branches in the repository.

However, as usual I didn’t think it through and had to hack together a solution to fit the problem.

Here’s the solution, it’s a bash shell script that takes 2 revisions as an argument and produces a directory containing all the files that have changed between those two revisions, maintaining the directory structure. You pretty much end up with a directory that you can drop straight into your live site to update it to whatever revision you like.

For example, my live site is at revision 10. I committed changes at revision 11 that I don’t want going into the live site, but everything from 12 onwards to the current revision of 15 needs patching in. run ‘make patch 12 15’ and then drop the produced directory into your live site.

#!/bin/bash
#simple script to make a very simple patch from a repository
#call with make patch.sh low high
#
# where low is the revision your unpatched project is currently at
# and high is the revision you want the patch to go up to
# eg: if your live system is at revision 100 and you want to
# patch it to revision 120 you'd do:
# 
#our subversion url
url=svn://svn-server/my-repo/

#first we need to get a list of changes since requested revision 
svn diff -r$1:$2 $url --summarize > filelist.txt

#now remove the repo information from each line, so we're just left with the path from the root upwards
sed -i "s#svn://redmine.tyrrellsystems.com/tms/tms_dev/Trunk/# #g" filelist.txt
sed -i "s#M  # #g" filelist.txt
sed -i "s#A  # #g" filelist.txt

#now loop through what we've got
#create the relevant folder, and export the file into it
for i in $(cat filelist.txt); 
do 
	filename=$(basename $i);
	path=$(dirname $i);
	mkdir -p patch-r$1/$path 
	svn export --force $url$path/$filename patch-r$1/$path/$filename
	echo "$filename"; 
done



PHP: clean up your includes!

If you’ve ever worked on any kind of PHP framework, you’ll likely know the pain that a misplaced ‘space’ in one of your includes can cause.  For the rest of you imagine this scenario:

To load a page in my framework, I have an index.php that loads in a ‘core.php’ (which isn’t web accessible for security purposes) which itself then loads in a long (20 or so) list of included files which make up my framework.  So, my core.php might look like this:

require_once("database.php");
require_once("mail.php");
require_once("something_else.php");
etc
etc
require_once("page_loader.php");
send_headers();
load_page($page_id);
send_footers();

which is lovely, keeps all the functionality of the framework nice and segregated.  However, if one of those included files actually outputs anything to the screen, it can cause all sorts of issues, especially if our ‘send_headers’ function is sending our actual HTML headers…. in this case, anything output to the screen before our HTML headers are sent can really cock things up. Even worse, trying to track down where the output is coming from can be a nightmare when you have a large number of included files.

After a bit of thinking I stumbled across the (probably) blindingly obvious way round this without spending hours debugging and trying to track down which included file is the culprit:

good old fashioned output buffering!

by doing this:

// start buffering
ob_start();

require_once("database.php");
require_once("mail.php");
require_once("something_else.php");
etc
etc
require_once("page_loader.php");

//stop buffering, discard buffer contents
ob_end_clean();

send_headers();
load_page($page_id);
send_footers();

we ensure that anything output by the included files is buffered, then discarded before we actually start outputting stuff.

lovely.




VirtualBox seamless mode

This is my current desktop in the office:

As you can see, KDE4 taskbar on the right, windows 7 taskbar on the left.  Windows from the right can move onto the left screen freely (note the linux terminal on the left screen).  Unfortunately due to limitations in the virtualbox seamless mode windows from the left screen (from windows 7) are limited to that screen.  Also, there’s no fancy aero 3D effects.

Still, it’s a nice way to run windows and Linux side by side.

virtualbox




PHP Javascript / CSS loader

I’m currently working on an in-house management system here at Tyrrell Systems, and employ a lot (seriously, a lot) of javascript for everything from ajax loading of information to various layout tweaks and so on.

When I inherited the project (a good 2 years ago now) the previous coders had made use of various scripts they’d found on the web, as well as a lot of hand crafted stuff.  I started swapping things over to the rather spiffy Jquery library and added a load more functionality.

However, the system has inevitably started to slow down over the last year or so, loading in all those javascript libraries has taken its toll on page load times.  As well as the javascript overhead there’s also around 30 different css files to load in (I like to keep things well segregated!).  This leads to the following problem:

As you can see, it was taking nearly 30 seconds just to load in the css & javascript for a typical page.

So, I started looking for a solution.  Now, the general (and rather obvious) approach to this is to ‘munge’ all your css (or javascript) files into one big file, run that through some kind of optimiser and then serve the resulting file instead.  This reduces page requests & bandwidth used in one go.  This is a good example of this general approach.  Unfortunately, 90% of these scripts rely on using mod_rewrite to redirect calls to css / js files through a PHP script.  My site runs on IIS, so they’re no good for me.  To cut a long story short, I decided to write a class that would:

  • Allow me to merge multiple css / js files into 1.
  • optionally optimise that file before serving it.
  • Cache the output so I only have to do this process when I actually change any of the css / javascript.

This is what I came up with.  It makes use of jsmin-php for javascript minification, and css-tidy for well, css-tidying so you’ll need to have those if you want to use optimisation.  Or you can optionally turn it off.  To use the class:

First initialise it:

$main-css = new cacher("main.css","css");

The first parameter is a filename (can be anything you like) and the second is the type (must be css or js).

Next we add our files:

$main-css->add_file("path/to/my/file.css");

or we can add every css/js file in a folder like so:

$main-css->add_folder("path/to/my/folder/");

then when we’ve added everything, we output the files:

$main-css->output();

The output file will be cached (in /theme/cache by default) until you delete the cached copy from that folder. So if you change any of the files included using this class, remember to delete your cached file!

and that’s it.

Just to complete the before / after theme here’s what this did to my loading times:

Here’s the code (as usual, it’s free to use but please give some credit if you do).

nb: the variable $cfg used here is a global class used in the project this came from. Basically, $cfg->root needs to point at the webroot for your project.

<?php
class cacher{	    
	function __construct($filename,$type)
	    $this->type = $type;
            $this->filename = $cfg->root."\theme\cache\".$filename;
            $this->url = "/theme/cache/$filename";
            $this->optimise = $optimise;
            if (file_exists($this->filename)) {
                $this->output();
                $this->cached = true;
            } else {
                $this->cached = false;
                $this->fh = fopen($this->filename,"a") or die("unable to open file $this->filename");
            }
        }

        function add_folder($newfolder){
            global $cfg;
            if ($this->cached == true){
                return;
            } else {
                $dh = opendir($cfg->root.$newfolder);
                while (false !== ($file = readdir($dh))){
                     $ext = substr($file,strrpos($file,'.')+1);
                     if ($this->type == $ext){
                         fwrite($this->fh,file_get_contents($cfg->root.$newfolder."\".$file));
                         fwrite($this->fh,"n");
                     }
                }
                closedir($dh);
            }
        }

        function add_file($newfile){
            if ($this->cached == true){
                return;
            } else {
                fwrite($this->fh,file_get_contents($newfile));
                fwrite($this->fh,"n");
            }
        }

        function output(){
             if ($this->cached == true){
                 return;
             } else {
             if ($this->type == "css"){
                    fclose($this->fh);
                    if ($this->optimise == true){
                        require("lib/csstidy/class.csstidy.php");
                        $css_out = new csstidy();
                        $css_out->parse(file_get_contents($this->filename));
                        $this->fh = fopen($this->filename,"w");
                        fwrite($this->fh,$css_out->print->plain());
                        fclose($this->fh);
                    }
                    echo "";
             } elseif ($this->type == "js") {
                    fclose($this->fh);
                    if ($this->optimise == true){
                        require("lib/jsmin/jsmin.php");
                        $js_out = JSMin::minify(file_get_contents($this->filename));
                         $this->fh = fopen($this->filename,"w");
                        fwrite($this->fh,$js_out);
                        fclose($this->fh);
                    }
                    echo "";
             }

            }
        }

    }

?>