Flexible Developments

Musings of a freelance PHP, Django and Flex Developer

Howto: Create custom thumbnails from Flutter image fields

Posted by calisza on September 24, 2009

If you’ve worked with Flutter / Fresh pages (wordpress plugin) before, you’ll know that you can use the supplied get_image() function to insert the relevant image field into your template. The problem however is that these images are generated automatically during the upload process and thus conform to the whatever dimensions are set for that field.

There are instances however where you’d need to display the same image but at different sizes, for example a widget vs ‘more info’ display. This is when the following function becomes quite handy.

The auto thumbnail function

You can insert this function straight into your functions.php, a usage example will follow below.

function jt_get_thumb($fieldName, $groupIndex=1, $fieldIndex=1, $readyForEIP=true, $params, $returnimg=true){
        // use flutter's default function to get our field value (non thumbnailed image).
	$file = get($fieldName, $groupIndex, $fieldIndex, $readyForEIP);
        // if the field's empty, we can't continue, return an empty string
        if (empty($file)){
            return "";
        }
        // we want the base filename
	$file = str_replace(FLUTTER_FILES_URI, "", $file);

        // get the current image dimensions
	$jtSize = getimagesize(FLUTTER_FILES_PATH.$file);

        // break our params up into a useable array.
        $params = explode("&",$params);
	$i = 0;
	foreach($params as $p){
		$tmp = explode("=", $p);
		$jtParams[$tmp[0]] = $tmp[1];
		$i++;
	}

       // no point in continuing if the width or height params aren't set, or the original image's dimensions are smaller than the supplied params
	if ((!isset($jtParams["w"]) || !isset($jtParams["h"])) || ($jtSize[0] <= $jtParams["w"] && $jtSize[1] <= $jtParams["h"])){
		return ($returnimg) ? "<img src='". FLUTTER_FILES_URI.$file ."' />" : FLUTTER_FILES_URI.$file;
	}
	//generate thumb using flutter's default method (phpThumb class)
	include_once(FLUTTER_PATH . "/thirdparty/phpthumb/phpthumb.class.php");
	$phpThumb = new phpThumb();
	$phpThumb->setSourceFilename(FLUTTER_FILES_PATH.$file);
	$md5_params = md5($file . $params);
	$create_md5_filename = 'jt_th_'.$md5_params."_".$file;
	$output_filename = FLUTTER_FILES_PATH.$create_md5_filename;
	$final_filename = FLUTTER_FILES_URI.$create_md5_filename;

// experimental, uncomment to test : check if the thumbnail has already been created and use that instead
//	if (file_exists($output_filename)){
//		$attr_params = "style='width:".$jtParams['w']."px;  height:".$jtParams['h']."px;'";
//		return ($returnimg) ? "<img src='$final_filename' $attr_params />" : $final_filename;
//	}

	foreach($jtParams as $key => $val){
		$phpThumb->setParameter($key, $val);
	}

	if ($phpThumb->GenerateThumbnail()) {
		if ($phpThumb->RenderToFile($output_filename)) {
			$file = $final_filename;
		}
		$attr_params = "";
	} else {
                // if the thumbnail generator fails for some reason, rather return the original image with a forced style attribute
		$file = FLUTTER_FILES_URI.$file;
		$attr_params = "style='width:".$jtParams['w']."px;  height:".$jtParams['h']."px;'";

	}

	return ($returnimg) ? "<img src='$file' $attr_params />" : $file;

}

Pretty straightforward, the function accepts the standard flutter get() parameters with 2 extras added on to the end. The last two parameters are as follows :

  • $params (string): a standard query string containing the various parameters for the thumbnail generator. Example – “w=400&h=200&zc=1″. The available parameters conform to flutter’s default image thumbnail parameters, see flutter’s documentation for a full reference.
  • $returnimg (bool, default true): set to true to return a formatted img tag, whereas false will return just the full URI based path to the image.

Example Useage

// will output full img tag
echo jt_get_thumb("news_img", 1, 1, false, "w=250&h=250&zc=1");

// build the image string up manually
echo "<img src='" . jt_get_thumb("news_img",1,1,false,"w=250&h=250&zc=1",false) . "' class='newsImgClass' />";

Naturally, this function assumes that the field being queried points to a valid image file, you could of course flesh it out with some fail-safe checks if you’re that way inclined. Please feel free to post any improvements in the comments and I’ll see about adding them to the next version for everyone to use.

Posted in PHP, Wordpress | 2 Comments »

Simplifying Flutter duplicate groups and fields

Posted by calisza on September 21, 2009

Flutter or Fresh-pages is a really handy plugin for WordPress. With it, you can quite easily create custom write panels, fields and groups of information.

Having worked with this plugin quite extensively recently, I have encountered a few issues which have proved somewhat frustrating, dealing with duplicate groups or fields in particular. Flutter uses a counter based system in which to access duplicate groups. Simple enough when using a standard for loop and all the duplicates are in the correct order – but somewhat tricky to handle when say, deleting one of the duplicates.

I’ve since resorted to writing a function to make handling these duplicates and a number of associated problems whilst looping through them much, much simpler.

Which brings us to the following function – which you can paste straight into your theme’s functions.php file :

function jt_get_flutter_duplicates($field, $group){
	if (is_string($group)){
		$numfiles = getGroupDuplicates($group);
		$isgroup = true;
	} else {
    	$numfiles = getFieldDuplicates($field, $group);
    	$isgroup = false;
	}
    $return = false;
    if ($numfiles > 0){
        $return = array();
        $count = 1;
        $tmp = "";
        $first = "";
        $total = ($numfiles > 1) ? 100 : 1;
        while($count <= $total){
        	if ($isgroup){
        		$value = get($field, $count, 1);
        	} else {
            	$value = get($field, $group, $count);
        	}
            if (empty($value) || $value == $first || $tmp == $value){
                $count++;
                continue;
            } elseif ($count == 1){
                $first = $value;
            }

            $tmp = $value;
            $return[] = ($isgroup) ? $count : $value;
        }
    }
    return (is_array($return) && count($return) > 0) ? $return : false;
}

I’m not going to go into too much detail right now, but essentially what this function does is gets the required field or group duplicates, loops through them (up to a max of 100 iterations just to be safe) and places them into an array containing the correct index values (if a group) or an array of field values (if a field).

Group duplicates

Set the first parameter to the name of a field within the group which should contain a unique value (such as name, or caption). The second parameter can be any field within the required group.

$groupItems = jt_get_flutter_duplicates("news_image", "news_image");
if (is_array($groupItems) && count($groupItems) > 0){
    foreach($groupItems as $i) {
	echo get_image("news_image",$i, 1, 1);
        echo "<br />" . get("news_image_caption",$i, 1, false);
    }
}

Field Duplicates

Set the first parameter to the name of the field you want to retrieve. Set the second parameter to the group index you want to retrieve the field duplicates from. For instance, you could have 1 group which can be duplicated, containing 3 fields, one of which can be duplicated. When looping through the group duplicates, you’ll want another sub-loop to handle the duplicated field contents. The function will return an array of values which you can then use in a standard foreach loop.

$groupItems = jt_get_flutter_duplicates("office_title", "office_title");
if (is_array($groupItems) && count($groupItems) > 0){
    foreach($groupItems as $i) {
        echo get("office_title",$i,1,false);
        $contacts = jt_get_flutter_duplicates("office_contact", $i);
        if (is_array($contacts) && count($contacts) > 0) {
           foreach($contacts as $contact){
               echo "<br />Contact Person: " . $contact;
           }
        }
    }
}

This is of course a quick fix and by no means infallible, so I’d love to hear if you have any improvements or a simpler way of dealing with this particular issue.

Posted in PHP, Wordpress | 1 Comment »

Circular Image Slide with jQuery

Posted by calisza on April 25, 2009

A friend of mine asked me to write a little script for him the other day that would do the following :

1. Slide a list of images from right to left across the screen.
2. When an image moves out of view on the left, it should get appended to the end of the list thus creating the illusion of a never ending or circular procession of images across the screen.
3. Display a “loader” image while the photographs are downloading.
4. You can view a demo of the end result here.

My first impression was that there’s almost certainly a jQuery plugin capable of doing this. Well if there is, I haven’t found it yet. While there are a myriad of “Slide” plugins available, and some come quite close, none could fulfill these requirements.

So I had to go and write my own little script. I haven’t converted the code to plugin form just yet as I need to look a few things up.

If you’d like to just jump straight in, here’s a zipped version of the demo.

First, the HTML:

<div id="slider">
<div id="imageloader">
			<img src="images/ajax-loader.gif" /></div>
<img src="images/sample1.jpg" />
		<img src="images/sample2.jpg" />
		<img src="images/sample3.jpg" />
		<img src="images/sample4.jpg" />
		<img src="images/sample5.jpg" /></div>

Nothing out of the ordinary here, just a div with a bunch of image tags. The only thing to note is the div’s “id”. The real magic happens in the JS and CSS. The pre-loader image is located inside a nested div with an id of “imageloader”. By default, our loader will be visible while our photographs are hidden.

That brings us to the CSS:

#slider {position: relative; overflow: hidden; height:155px;}
#slider img {position:absolute;	margin:0; display:none;}
#imageloader {position:relative; display:block; width: 100%; margin: 0px auto; text-align: center;}
#imageloader img { position:relative; top:70px; z-index:100; width:128px; height:15px; display:inline;}

Firstly, due to the nature of the script we have to make use of relative and absolute positioning. With that in mind, we first set our container div to relative positioning. This allows us to assign an absolute position to each child image, this is critical to the functioning of this script.

Next we set the overflow style to “hidden” – this makes sure that we don’t get ugly scroll-bars when images are moving outside of the containing div’s bounds.

We also need to set a fixed height for the container div. Failing to do so will result in the images not being displayed at all (due to the absolute positioning and overflow setting).

For the nested images, we want to set their initial display attribute to “none”. This is so they don’t display until our DOM is ready and all the images are loaded. We also need to set their positions to absolute.

For the pre-loader we just set some styles to make sure it get’s displayed in the correct position : in this case 70px from the top and horizontally in the middle of the container div. We also make sure to set the display attribute to “inline”, thus making sure the pre-loader img is shown while all other img’s are hidden.

Now for the Javascript/jQuery:

	var speed = 50;
	var pic, numImgs, arrLeft, i, totalWidth, n, myInterval; 

$(window).load(function(){
	pic = $("#slider").children("img");
	numImgs = pic.length;
	arrLeft = new Array(numImgs);

	for (i=0;i<numImgs;i++){

		totalWidth=0;
		for(n=0;n<i;n++){
			totalWidth += $(pic[n]).width();
		}

		arrLeft[i] = totalWidth;
		$(pic[i]).css("left",totalWidth);
	}

	myInterval = setInterval("flexiScroll()",speed);
	$('#imageloader').hide();
	$(pic).show();
});

function flexiScroll(){

	for (i=0;i<numImgs;i++){
		arrLeft[i] -= 1;		

		if (arrLeft[i] == -($(pic[i]).width())){
			totalWidth = 0;
			for (n=0;n<numImgs;n++){
				if (n!=i){
					totalWidth += $(pic[n]).width();
				}
			}
			arrLeft[i] =  totalWidth;
		}
		$(pic[i]).css("left",arrLeft[i]);
	}
}

In a nutshell what’s happening is this :

  1. We use $(window).load() instead of the standard $(function(){}) or $(document).ready() methods due to a timing glitch in Safari. Safari reports the DOM as finished loading even while images are still downloading – not ideal if we want our pre-loader to work correctly.
  2. When the DOM has finished loading, and the images have finished downloading we execute our code.
  3. First we read all our images into an array of jQuery objects. We make sure the pre-loader isn’t included in this array by using $(“#slider”).children(“img”) instead of $(“#slider img”).
  4. Next we loop through each image in our array and calculate a totalWidth. We need this value so that we know where to append each image when needed. Within this loop, we also set the correct absolute position for each image so that they all line up next to each other. Otherwise they’d all just sit on top of each other.
  5. Once our loop is complete and we have all the initial positions setup, we create a standard javascript interval. Using this interval we can call a function every x milliseconds. We use the “speed” variable to make this configurable.
  6. Now that everything’s set up, we hide our pre-loader, unhide our images and wait for the interval to fire.

The “flexiScroll()” function simply moves each image to the left by 1 pixel, recalculates the totalWidth and if necessary, moves the left-most image to the end of the list. Since the end of the list is currently outside of the viewable area, this gives the illusion that the list never ends.

And that’s all there is to it.

There of course must be a more efficient way of doing this, so if you would like to contribute, please leave a comment or contact me.

Posted in javascript, jquery | Tagged: , , , , , , , , | 15 Comments »

6 jQuery snippets you can use to manipulate select inputs

Posted by calisza on March 29, 2009

When it comes to manipulating the DOM, fewer elements are more tiresome than the good old select input. Fortunately for us, jQuery makes what was once a headache, a walk in the park.

Listed below are 6 snippets which should make manipulating those selects more pleasant than say, pulling your own teeth.

1. Getting the value of a selected option.

$('#selectList').val();

This couldn’t be simpler. Remember how before jQuery, you had to use selectedIndex and all those lovely javascript methods. I do, and I don’t miss it one bit.

2. Getting the text of a selected option.

$('#selectList :selected').text();

Similar in concept to the first snippet with one difference. Where the first example gives you the “value” of the selected option, this example gives you the actual text contained inside the option tag.

3. Getting the text/value of multiple selected options.

var foo = [];
$('#multiple :selected').each(function(i, selected){
foo[i] = $(selected).text();
});
// to get the selected values, just use .val() - this returns a string or array
foo = $('#multiple :selected').val();

Once again, the same concept as the first two examples, except we’re now using jQuery’s “each()” method to loop through all selected options in a multiple select list. Each value or text value is read into an array for later use.

4. Using selected options in conditional statements

switch ($('#selectList :selected').text()) {
case 'First Option':
//do something
break;
case 'Something Else':
// do something else

break;
}

Much like example 2, we’re getting the text() value of a selected option, only this time we’re going to use it inside a switch statement.

5. Removing an option.

$("#selectList option[value='2']").remove();

Using an attribute filter, we can find and therefore manipulate specific options within a select list. In this example we’re telling jQuery to find the option with value=”2″ and then remove it from the select list. We can similarly add options to a select list as we’ll see in example 6.

6. Moving options from list A to list B.

$().ready(function() {
$('#add').click(function() {
return !$('#select1 option:selected').appendTo('#select2');
});
$('#remove').click(function() {
return !$('#select2 option:selected').appendTo('#select1');
});
});

Originally posted by Jeremy Martin, here we have 2 select lists and 2 buttons. If you click the “add” button, we remove the selected option from select1 and add that same option to select2. The “remove” button just does things the opposite way around. Thanks to jQuery’s chaining capabilities, what was once a rather tricky undertaking with JS can now be done in 6 lines of code.

And there you go. That wasn’t so bad now was it ? If you have any other handy snippets, or you’ve found an easier way to do something already covered here, why not leave a comment and share the love!

Update:

Incidentally, a few hours after first publishing this post I came across the following “select element cheat sheet”. Technically speaking, it may be a little big to be called a cheat sheet, but the author has given a very thorough and practical guide which I’m definitely going to be making use of.

Posted in javascript, jquery | Tagged: , , , , | 29 Comments »

How to validate Date of Birth with jQuery

Posted by calisza on March 9, 2009

In a recent project I had to implement what’s commonly referred to as a Legal Drinking Age (LDA) page. Basically what needs to happen is that the user has to enter their date of birth and thus ‘confirm’ that they are of a legal drinking age for their respective country. You can view an example of just such a page here.

This brought me to an interesting requirement – the user needs to enter their birth of date (in this case via 3 select boxes), their age then needs to be calculated from the entered date and they are either granted, or denied access based on the result.

Interestingly enough, after having a quick look around I hadn’t been able to find any similar example, so I had to come up with something myself. The following code is my solution :

$("#lda-form").submit(function(){
		var day = $("#day").val();
		var month = $("#month").val();
		var year = $("#year").val();
		var age = 18;

		var mydate = new Date();
		mydate.setFullYear(year, month-1, day);

		var currdate = new Date();
		currdate.setFullYear(currdate.getFullYear() - age);
		if ((currdate - mydate) < 0){
			alert("Sorry, only persons over the age of " + age + " may enter this site");
			return false;
		}
		return true;
});

First, we get the relevant entered date values – the “day”, “month” and “year”. I’ve also added an “age” var so that this can be easily edited if necessary – the current value is set to 18.

Next we create a Date object and call it “mydate”. We then use the object’s “setFullYear” method to set the value of “mydate” to the user’s entered birth date. You can view more information about this method here. The only thing to notice here is that we have subtract 1 from the “month” value as it’s 0 indexed.

Now that we have the user’s birth date sorted, we then create another Date object and call it “currdate”. The default value for “currdate” is the current date. We then set “currdate” to whatever the current date is minus our “age” value – i.e. Today – 18 years. Once again, we use the “setFullYear” method to set the date. However, to get the current date in a useable format, we use the “getFullYear” method and THEN subtract 18 from the resulting value. So to do this we use “currdate.getFullYear() – age”.

Once we have the date of 18 years ago and the user’s birth date, both in the same format, it’s simply a matter of making sure that the required date minus the birth date isn’t greater than 0. If so, we output an alert to inform the user then return “false” to make sure that the form doesn’t get submitted.

Pretty straightforward.

Posted in Uncategorized | Leave a Comment »

Still alive and kicking

Posted by calisza on February 17, 2009

Wow, what a crazy 6 weeks I’ve just had. Probably the busiest, most stressful and yet most rewarding stretch of my entire working career.

With that said, this is just a quick note to tell anyone out there who actually cares that I’m still alive, still kicking and will resume posting to this fascinatingly entertaining and informative blog shortly.

Posted in General | Tagged: , , | Leave a Comment »

jQuery plugin : jqPageFlow – scrolling pagination made easy

Posted by calisza on January 18, 2009

jqPageFlow

Simply put, this plugin makes the scrolling pagination found on sites like dzone.com and Google Reader easy to implement on your site.

A working demo is viewable here

This is of course all configurable, and intended to be used on an automatically generated page using a backend script (eg php).

Please note that this script is still currently in beta, so if you find any problems please post a bug submission to http://code.google.com/p/flexidev/issues/ with as much information as possible

Usage

  1. Download the latest source code from the repository : http://code.google.com/p/flexidev/downloads
  2. Include the jQuery library into your page header (this plugin supports both jQuery v1.2.6 and v1.3)
  3. Include the jquery.jqpageflow.js file into your page header
  4. Include the supplied css file in your page header : modify as you see fit
  5. View the source of this page: copy, paste and modify the javascript block as required. Use $(“body”).jqpageflow(); to use defaults.
  6. Create a php/.net/perl/python etc backend script to handle the serverside stuff – see the index.php file (this page) included in the download source for a basic example

Features

  • Compatable with jQuery v1.2.6 and 1.3
  • Chainable
  • Configurable options : including the url to call, current page, pager var, container element etc
  • Server side platform independant : tell it how to interact with your backend scripts
  • Cross browser compatability, tested in FF 2.5+, Safari 3+ (more browsers to come soon)
  • Skinnable loader with CSS and customizable image path

Options

  • url: Specify which url (relative or absolute) the plugin should submit the ajax request to. Defaults to current window.location
  • currentPage: Gets appended to url as a GET value to help your backend script keep track of which page of results the user is on. Defaults to 0 (first page)
  • pagerVar: Related to currentPage, gets appended to url as a GET var to help your backend script keep track of which page of results the user is on (e.g. index.php?page=2). Defaults to “p”
  • perPage: Used for calculation and display purposes, tell the plugin how many results are being displayed per page. Defaults to 50.
  • totalResults: Tells the plugin when it needs to stop trying to look for more results. Defaults to 100
  • container: Specify which html element contains the result items, can be any jQuery compatible selector (eg “#mycontainer”, “.results”, “body”).
    Any html returned to the ajax call gets appended to this element. Defaults to “body”
  • loaderImgPath: Tell the plugin where to find the loader img relative to the page calling the plugin. Defaults to “images/loader.gif”
  • debug: When set to 1, the plugin will print debugging information to the console (firebug). Defaults to 0

Changelog

  • 18 Jan 2009 : version 0.1b released

Credits

Posted in javascript, jquery | Tagged: , , , , , | 16 Comments »

How to use jQuery to select a radio button from parent element

Posted by calisza on January 9, 2009

A friend asked me for some help on doing the following :
1. You have an unordered list – within each list item you have a radio input.
2. When you click on the list item (i.e. the entire container), it must a) select the radio input and b) add a css classname of “selected” to the list item.

You can find a demo here.

First, the html :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
	<!-- include our jquery scripts -->
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script>
    <script src="js/radio.js" type="text/javascript"></script>
    <style type="text/css">
    	li { color: #000; }
    	li.selected { color: #FF0000; }
    </style>
</head>
<body>
	<div>
		<ul>
			<li class="test">Test 1 <input type="radio" name="test" /></li>
			<li class="test">Test 2 <input type="radio" name="test" /></li>
			<li class="test">Test 3 <input type="radio" name="test" /></li>
			<li class="test">Test 4 <input type="radio" name="test" /></li>
			<li class="test">Test 5 <input type="radio" name="test" /></li>
		</ul>
	</div>
</body>
</html>

There is nothing out of the ordinary here – just a simple unordered list of radio inputs.

Next, the js (radio.js) :

$(document).ready(function(){
	$('li').click( function(){
		$('li.selected').removeClass('selected');
		$(this).addClass('selected');
		$(this).children("input[type=radio]").click();
	});
});

1. First – we tell jQuery to execute the following code once the document has finished loading, ensuring that the DOM has been registered successfully.
2. Next we bind a click event to all list item elements on the page – you can of course change this to all list items with a class of “myselection” for example ( $(“li.myselection”).click… )
3. When a list item is clicked – we first need to remove the “selected” class from all other list items.
4. Now we need to add the “selected” class to the list item which fired the event ( $(this) ).
5. Finally, we need to make sure that the radio button inside the list item is “clicked” : we do this by using the .children() selector and executing a click() event on the input.

The important bit is the $(this).children(“input[type=radio]“) selector. What we’re doing here is telling jQuery to find all inputs of type radio (i.e. all radio inputs) inside “this” list item (i.e. the list item which was clicked on). We then use .click() to..as you guessed it… execute a click event on the returned element (in this case the radio input).

And that’s all there is to it. You can read up some more on jQuery selectors here.
I would also highly recommend reading the following article : Improve your jQuery – 25 excellent tips.

Posted in javascript, jquery | Tagged: , , , , , , , | 4 Comments »

Jquery UI Layout Manager Plugin

Posted by calisza on December 31, 2008

While working on my new framework the other day I came across this excellent Jquery Plugin : UI.Layout – The Ultimate Page Layout Manager.

What it does with minimal markup and some well written javascript is transform your html page into a professional pane based layout. Like most jQuery plugins, it’s incredibly simple to implement and through the use of CSS and a large number of options is highly customizable.

All in all, a very well rounded and executed use of the jQuery library. Kudos to Fabrizio.

You can check out some demos here

Posted in javascript, jquery | Tagged: , , , , , , | Leave a Comment »

Search Engine Friendly URLs using PHP

Posted by calisza on December 11, 2008

A little while ago I wrote a post on Django Inspired SEF urls. I’ve since put together a working example and am now making it available for download.

There are a couple of things to note :

  1. You’ll need to edit the necessary path and url info found inside index.php and .htaccess
  2. The sample code inside index.php is for demonstration purposes only – I strongly recommend using a proper gateway/bootstrap interface typically found in MVC based systems such as Zend Framework and CakePHP (though they of course have their own SEF url implementations).
  3. Edit urls.php to play around with the regular expressions. I’ll be the first to admit that my regexp skills are not the best in the world, so if you notice something that will work better, please let me know – I’d really appreciate it
  4. I’ve included a url generator inside the class to try and make your life easier – view index.php for example usage

That should do it. You can download the script here.

Please play around with it and if you make any improvements I’d love to hear about it.

Posted in PHP | Tagged: , , , | 4 Comments »