London to Brighton Trek 2013

Update: Read my post walk blog post over at Team Pacific Rowers

On the 22nd June 2013, I will be taking part in the London to Brighton Trek; a 100km (AKA welllllll long) walk…… from…. well…. London to Brighton…. if that wasn’t already apparent. I will be walking with a group of friends – Dan, Mike, Tom, Stu and James – under the moniker “Colossal Velocity” (name chosen by Dan at everyone else’s lethargy). There will be free energy drinks and snacks.

The walk sets off from Richmond Upon Thames, heads through the London suburbs then down through Surrey and Sussex before finishing in Brighton for a well earned curry (Mike is tasked with securing these for our arrival) and numerous much needed ales to occupy our mouths since every ounce of conversation will have been well and truly exhausted in the previous 20-30 hours and our legs will ache.

We will be raising money for the British Heart Foundation (not the Fraser Hart foundation). If you are feeling generous enough to sponsor us, you can do so at our Just Giving page.

Those pledging any amount of sponsorship will be publicly thanked on this blog with a link your blog/site/business, whether it’s £0.20 or …….

dr_evil_one_million_dollars

Thank you’s

Update – 15/04/2013
I originally thought we were doing the London to Brighton Challenge, a similar walk on May 25. I have today been put right. This is a good thing for me as I have an extra month to train. All money already already donated is going to the same charity for the new walk and will be passing straight to them via Just Giving.

AJAX Contact Form Tutorial with PHP and jQuery

A quick and easy AJAX Contact Form Tutorial using PHP and jQuery. I decided to put this together as I’ve received comments from a number of people who like the AJAX contact form on my main site.

VIEW THE DEMO (note, in the demo, I have commented out the line which actually fires the email) | DOWNLOAD THE FILES

As a base line, we will take the standard PHP contact form example on W3schools. We’ll throw in some jQuery and CSS and modify it slightly to make it to work with AJAX. This is what we will start with:

<html>
<body>
 
<?php
if (isset($_REQUEST['email']))
//if "email" is filled out, send email
  {
  //send email
  $email = $_REQUEST['email'] ;
  $subject = $_REQUEST['subject'] ;
  $message = $_REQUEST['message'] ;
  mail("[email protected]", $subject,
  $message, "From:" . $email);
  echo "Thank you for using our mail form";
  }
else
//if "email" is not filled out, display the form
  {
  echo "<form method='post' action='mailform.php'>
  Email: <input name='email' type='text'><br>
  Subject: <input name='subject' type='text'><br>
  Message:<br>
  <textarea name='message' rows='15' cols='40'>
  </textarea><br>
  <input type='submit'>
  </form>";
  }
?>
 
</body>
</html>

The first thing you will want to do is to separate the code which actually sends the email from the display of the form so you will have two files:

index.php

<html>
<head>
  <title>AJAX Contact Form with PHP and jQuery</title>
</head>
<body>
  <form method='post' action='mailform.php'>
    Email: <input name='email' type='text'><br>
    Subject: <input name='subject' type='text'><br>
    Message:<br>
    <textarea name='message' rows='15' cols='40'></textarea><br>
    <input type='submit'>
  </form>
</body>
</html>

mailform.php

<?php
if (isset($_REQUEST['email']))
//if "email" is filled out, send email
{
	//send email
	$email = $_REQUEST['email'] ;
	$subject = $_REQUEST['subject'] ;
	$message = $_REQUEST['message'] ;
	mail("[email protected]", $subject, $message, "From:" . $email);
	echo "Thank you for using our mail form";
}
?>

We will be using jQuery.ajax() to post the form data through to the send script which requires no further modifications (you can also use jQuery.post() as a slightly simpler way of doing this but I always opt for ajax() as it offers a greater amount of control if needed). But first we need to add a loading indicator and a success message. Both of which will be initially hidden via the CSS. With jQuery, we will show and hide these at the appropriate stage of the process:

index.php

<html>
<head>
  <title>AJAX Contact Form with PHP and jQuery</title>
  <style>
    #loading, #success{display: none}
  </style>
</head>
 
<body>
  <form method='post' action='mailform.php'>
    Email: <input name='email' type='text'><br>
    Subject: <input name='subject' type='text'><br>
    Message:<br>
    <textarea name='message' rows='15' cols='40'></textarea><br>
    <input type='submit'>
  </form>
  <div id="loading">
    Sending your message....
  </div>
  <div id="success">
  </div>
</body>
</html>

Now the jQuery. With the jQuery we will:

  1. Prevent the default form action
  2. Hide the form
  3. Display the “loading” message
  4. Post the form to the send script
  5. Wait for a successful response
  6. Hide the “loading” message
  7. Display the “success” message
$(function(){
      $('form').submit(function(e){
        var thisForm = $(this);
        //Prevent the default form action
        e.preventDefault();
        //Hide the form
        $(this).fadeOut(function(){
          //Display the "loading" message
          $("#loading").fadeIn(function(){
            //Post the form to the send script
            $.ajax({
              type: 'POST',
              url: thisForm.attr("action"),
              data: thisForm.serialize(),
              //Wait for a successful response
              success: function(data){
                //Hide the "loading" message
                $("#loading").fadeOut(function(){
                  //Display the "success" message
                  $("#success").text(data).fadeIn();
                });
              }
            });
          });
        });
      })
    });

Here is the complete code:

<html>
<head>
  <title>AJAX Contact Form with PHP and jQuery</title>
  <style>
    #loading, #success{display: none}
  </style>
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
  <script>
    $(function(){
      $('form').submit(function(e){
        var thisForm = $(this);
        //Prevent the default form action
        e.preventDefault();
        //Hide the form
        $(this).fadeOut(function(){
          //Display the "loading" message
          $("#loading").fadeIn(function(){
            //Post the form to the send script
            $.ajax({
              type: 'POST',
              url: thisForm.attr("action"),
              data: thisForm.serialize(),
              //Wait for a successful response
              success: function(data){
                //Hide the "loading" message
                $("#loading").fadeOut(function(){
                  //Display the "success" message
                  $("#success").text(data).fadeIn();
                });
              }
            });
          });
        });
      })
    });
  </script>
</head>
 
<body>
  <form method='post' action='mailform.php'>
    Email: <input name='email' type='text'><br>
    Subject: <input name='subject' type='text'><br>
    Message:<br>
    <textarea name='message' rows='15' cols='40'></textarea><br>
    <input type='submit'>
  </form>
  <div id="loading">
    Sending your message....
  </div>
  <div id="success">
  </div>
</body>
</html>

Obviously, there is no validation or styling on the form, it is simply a quick demo on how to make a working contact form using AJAX with PHP and jQuery. If you’d like me to expand on this and incorporate validation and some nice styling, let me know in the comments below and I will write another post to take this contact form a stage further.

Any questions? Feel free to ask.

Want to hear me talk? I co-host the web development podcast “Three Devs and a Maybe”. Check us out here

aspupload – File(s) not uploaded

This post is more for my reference as I still work on a number of classic ASP projects which use aspupload in my day job. When attempting to upload images via an upload form in the CMS a client was getting the error:

File(s) not uploaded.

After 2hrs of trial and error and attempting various fixes including IIS security settings and folder permissions, I was finally able to narrow it down to the form tag. I had omitted:

enctype="multipart/form-data"

This instructs the browser to send the entire file and not just the file input. The whole tag should look like:

<form method="post" enctype="multipart/form-data" action="s_uploader/inc_upload_page_image.asp?page_id=<% response.write(request.QueryString("page")) %>">

GoPro HD Hero 3 Black Edition – SD ERR

A slight deviation from my usual web development posts but thought I’d share my experience and solution to what seems to be a common issue with the new GoPro HD Hero 3 Black Edition relating to microSD cards – SD ERR.

This is my 3rd GoPro, having previously owned the 960 and the 1080. With the exception of a faulty battery on my 1080 (which GoPro promptly replaced), I’d experienced no issues with either so was a little dismayed to find that I couldn’t just fire up the camera and start shooting out of the box.

The day I ordered my GoPro 3 Black Edition (from a seller on eBay) I also ordered a class 10 32Gb microSD card from a different seller. As many will do, I opted for the cheapest option rather than a name brand (long story short – this is the issue).

When both arrived, I put the microSD straight from the packaging into my new camera and turned it on, only to be presented with the message “SD ERR“. A little perplexed by this, I did some research and found a number of forum posts with similar issues, suggesting formatting the card would solve my woes. I plugged the microSD into the supplied adapter and into my laptop and formatted the microSD (on Mac OSX – Disc Utility > Erase (MS-DOS (FAT))). I popped it back into my camera and sure enough the error had gone away. I proceeded to perform the manual firmware update and took a couple of photos. Everything seemed fine.

A couple of days later, I took my my new GoPro Black Edition out to film for the first time. I wanted to try some sweet slow-mo’s with WGA 240fps. I set the camera up, connected to it through the iPhone app and pressed record. I went back to the camera a couple of minutes later and it wasn’t recording. Strange. Maybe I hadn’t pressed the record button. I started recording again and watched it. It cut out after 11 seconds (I found reports online of other people’s cutting out at 4s, 8s and some seemed to be random, sometimes 2s sometimes 2 minutes). It did this over and over again.

I tried other resolutions and frame rates and had this issue with all the higher ones (720p @120fps, 1080 @ 60fps). They all stopped recording after 11 seconds. Lower res and frame rates were fine (720 @ 60fps, 1080 @ 30fps, etc etc) and I could seemingly record for as long as I wanted.

When I got the footage home and plugged it into my mac, all the video files I had recorded were there but they were an identical file size (~42MB) and seemed to be corrupt. They wouldn’t play in VLC (I’ve never had issues playing raw GoPro video on VLC before) and Quicktime was telling me they were an unrecognised file type. I tried formatting the card again a few times and kept getting the Same “SD ERR” I had before.

I sent an email to GoPro to this effect. Very fast reply which I appreciate but it was mostly a copy and paste response and there was not a lot of useful info. I have pasted their reply below for reference.

I turned to Google again and discovered that class 10 memory cards can vary greatly in quality so decided to splash out for a quality one to see if this would work. I bought the sandisk card recommended on GoPro’s site. I put it into my camera and it worked straight away without needing to format. I can record for as long as I want at any res and frame rate and so far no issues.

It wasn’t a problem with the camera. It was just me being a cheapskate.

This is the Sandisk card I bought which you can buy from amazon here: http://amzn.to/13exDNn

SanDisk MicroSD card for GoPro HD 3 Black Edition

SanDisk MicroSD

You can access my YouTube channel here, where you can see my GoPro videos and edits

Hey Fraser, 

I am sorry to hear that you are having troubles with your new camera. If your camera is freezing while recording it is usually related to the firmware. I realize that you have updated to the most recent firmware. Sometimes the updates don't install fully and it can lead to the problems that you are seeing. I recommend that you re-update your camera manually. Manually updating is the best remedy to solve these kind of glitches. When you manually install the firmware it is like a factory reset for your camera. 

I am a little perplexed about your SD card. I'm not sure why the camera is unable to recognize it. Have you tried reformatting it inside the computer again and re-inserting to your camera?  

Click here to watch a video that walks you through the HERO3 firmware update.  If your camera's firmware is already up-to-date, but you need to re-update it, you'll need to follow the manual update path.  The video walks you through how to manually update the camera.  We also typed out the manual update instructions for you below.


Here’s how to manually update your HERO3 camera’s firmware:

Go to http://gopro.com/support/product-registration/hd-hero3-cameras/ and complete all of the steps on the first page except for Step 6.  Be sure to reformat your SD card either in the camera or on your computer with a card reader.  Then, click "Continue" without the camera connected to the computer.  The firmware updater will let you download the firmware files to your computer after you enter the customer and camera information.  It'll also give you instructions on how to manually complete the firmware update after you’ve downloaded the files to your computer.

Here are some things to take note of as you go through the update:

Steps 1 and 2 require you to enter your personal information and your camera’s serial number.

Step 3 – Camera Setup:
We recommend against skipping this step, even though you’re given the option to do so.  This is the step where you create your camera’s name and Wi-Fi password.  If your camera has had trouble connecting to the GoPro App in the past, renaming the camera and resetting its password can clear up the issue.

Here are camera name and password requirements:

Your camera name and password must be at least 8 characters.  It can contain the following characters: Lower and upper case letters, numbers 0-9, at symbol "@", dash "-", and underscore "_".  

Step 4 – Product Update
This is the step where you download the firmware files to your computer.  This is also where you’re told how to place the files on your SD card and update the camera.  We’ll walk you through the steps:

1.  Download and unzip files on your computer:
When you click the “Download Update” button, a zip file called “Update.zip” downloads to your computer. 

Mac:
If you’re on a Mac, Update.zip will be downloaded to your Downloads folder in your Dock, next to your trashcan.  Click on “Update.zip” to unzip the folder and get to your firmware files.   

Windows:
If you’re using windows, Update.zip will be downloaded to your Downloads folder (note – if you don’t see the file in your Downloads folder after clicking on the “Download Update” button, then you should research what location your files download to for the web browser that opened when you clicked on the link).  Update.zip will be in that location.  Double-click “Update.zip” to unzip the folder and get to your firmware files.  Do not double-click on any of the files inside the folder Update.zip folder though.

2.  Double-check that you have the correct files for your camera:
Once you’ve unzipped the Update.zip folder on your Mac or Windows computer, you’ll see a new window open with your firmware files in it.  There will be 4 files if you set up your camera’s name and Wi-Fi password in “Step 3 – Camera Setup”.  If you skipped this step, there will be 3 files.  Here’s a list of the files you’ll see for your camera.  Remember; do not double-click on any of these files.  

Black Edition:
HD3.03-firmware.bin
WF3.03-app.bin
update.cmd
settings.in (Note – You will NOT have this file if you skipped “Step 3 – Camera Setup".)

3.  Put the firmware files on your SD card.
Now you need to put all (3 or 4) firmware files on the root level of your SD card.  To do this, you need to open your SD card on your computer by using a card reader or your camera.  To open your SD card on your computer with the camera, power on your camera with your SD card inserted, then connect your camera to your computer.  

Next, locate your SD card in your “Computer” window if you’re on Windows or your “Finder” window if you’re on a Mac.  Your SD card will be named something like “NO NAME”, “UNTITLED”, "Removable Disk (E:)", or "Removable Disk (F:)".  Open your SD card by double-clicking on it.  A window will open that shows you the contents of your SD card.  Next, drag all (3 or 4) firmware files we listed above into the empty space in the middle of SD card window.  If you see MISC and DCIM folders in the SD card window, put the files next to those two folders, NOT inside them.  The files will copy over, and you should then see them in the window.

4.  Safely eject your SD card:
To do this, locate your SD card in your “Computer” window if you’re on a PC or your “Finder” window if you’re on a Mac.  Right-click on your SD card and click “Eject”.  If your camera is connected to the computer, physically disconnect your camera from the computer, and make sure the camera is powered OFF.

5.  Update the camera’s firmware:
If it isn’t already, insert the SD card in the camera while it’s powered OFF and already disconnected from the computer.   Next, power ON your camera with it still disconnected from the computer.  The update will begin automatically. 

Once the camera beeps and turns itself OFF, power it back on by pressing the Power button one time.  You should see 00 on the file counter, indicating that your firmware update was successful and your camera is ready to use.

I hope this clears things up.  Please let me know if you have any questions.

Many Thanks,
Cooper M. 
GoPro Support
http://gopro.com/support/

jQuery Fullscreen Background Slideshow

I recently worked on a project where there was the requirement to implement a full screen/window background slideshow. Rather than just pick one of the many plug-ins out there, I decided to put my jQuery to work and come up with my own solution. What I came up with is very simple.

You can SEE THE DEMO HERE and DOWNLOAD THE CODE HERE.

Firstly the HTML and CSS. We are not applying the backgrounds to the body of the page, we are faking this by putting them in a fixed position, 100% width and height div which will sit behind our content. The images that we put in the background div are also 100% height and width and absolutely positioned on top of each other. The images have a min-width so they are not able to get too small. If the window is resized smaller than the min width, they simply overflow.

<body>
	<div id="bg">
	        <img src="image3.jpg" />
	        <img src="image2.jpg" />
	        <img src="image1.jpg" />
	</div>
	<div class="mainContent"></div>
</body>
body{
	background:#333;
}
#bg{
	position:fixed; 
	top: -50%; 
	left: -50%; 
	width: 200%; 
	height: 200%; 
	z-index: -2;
}
#bg img{
	position:absolute; 
	top: 0; 
	left: 0; 
	right: 0; 
	bottom: 0; 
	margin: auto; 
	min-width: 70%; 
	min-height: 70%;
}
.mainContent{
	width:300px; 
	height:500px;
	position:fixed;
	right:0;
	top:50px;
	padding:25px;
	background:#fff;
	overflow:hidden;
}

If you take a look at your page now, your background (as the backgrounds are absolutely positioned, they sit on top of each other so you only see the top (last) one in the stack) fills the screen nicely and expands and contracts as you resize the window. All we need to do now is make the slideshow come together with jQuery.

To do this, we just fade out the top most image to reveal the one behind – repeat. When we get to the final image, we fade them all back in again and start over. Simple:

//get the number of images we have to cycle through
var numberOfBackgrounds = $('#bg img').length;
 
//keep track of the current background - we start with the last (top) one in the stack
var currentBG = numberOfBackgrounds;
 
//swap out backgrounds
setInterval(function(){
    if (currentBG == 1){
        //we have reached the last image so we fade them all back in and reset the counter
        $('#bg img').fadeIn(1200);
        currentBG = numberOfBackgrounds;
    }else{
        //fade out the current visible background to reveal the next in the stack
        $('#bg img:nth-child('+currentBG+')').fadeOut(1200);
        currentBG = currentBG - 1;
    }
},
4000);

And there you have a working fullscreen background slideshow.

We can, however improve on this slightly. In it’s current state, it does’t look too appealing while it is loading – You can see all the background images chugging away as they download – so a nice touch is to show a loading overlay until the first visible (last in the stack) image has finished downloading.

Head over to ajaxload.info and generate yourself a loading gif.

You need to insert another overlay div in the same way that you did the background one. This will just have a blank background and a loading gif. We simply show this and then fade it out when the first visible image has finished downloading.

Add the new div into your HTML after your background div:

<div id="bg">
    <img src="image3.jpg" />
    <img src="image2.jpg" />
    <img src="image1.jpg" />
</div>
<div id="bgloader"></div>
<div class="mainContent">
   ......
</div>

.. and update your styles:

#bg, #bgloader{
	position:fixed; 
	top: -50%; 
	left: -50%; 
	width: 200%; 
	height: 200%; 
	z-index: -2;
}
#bgloader{
	z-index: -1; 
	background:url(ajax-loader.gif) center center no-repeat #000
}

If you look at your project now, you will just see the loading overlay. All we need is the jQuery to fade this out when the visible image has loaded and we do this like so:

//to fade out the loader			    
$("#bg img:last-child").one('load', function() {
    $('#bgloader').fadeOut();
  }).each(function() {
    if(this.complete) $(this).load();
});

If you’ve any questions or comments, post them below and I will be glad to lend a hand where it’s needed.

How to Ajaxify your website with Ajaxify and history.js

Ajaxify is a great gist over on github by balupton that allows you to load page changes in via AJAX with a nice fade effect. URL’s are also kept intact while browsing and using History.js, browser history is handled correctly.

It is very easy to install, however, aside from the the initial set up, there is not much documentation so I’m going to share some things that I discovered while setting up a couple of different sites.

The initial set up if offensively easy and is exactly the as described on the Gist page. You just need to include jQuery, jQuery ScrollTo, History.js and the Ajaxify gist:

<!-- jQuery --> 
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> 
 
<!-- jQuery ScrollTo Plugin -->
<script defer src="http://balupton.github.com/jquery-scrollto/scripts/jquery.scrollto.min.js"></script>
 
<!-- History.js --> 
<script defer src="http://balupton.github.com/history.js/scripts/bundled/html4+html5/jquery.history.js"></script>
 
<!-- Ajaxify -->
<script defer src="http://gist.github.com/raw/854622/ajaxify-html5.js"></script>

This is all you need. If you take a look at this EXAMPLE, you will see that pages are already loading with AJAX.

Something quite annoying I have noticed though is that it also outputs the page title at the top of the page on page change. You can easily hide this in CSS with:

.document-title{display:none}

The page change here is using AJAX but the whole page fades in and out with a white haze which is fine, but if you have a site with a common layout – static nav and content area throughout – we can improve on it by specifying just the main content to be Ajaxified.

Looking in the code for the gist, you will notice this line:

       ......
       contentSelector = '#content,article:first,.article:first,.post:first',
       ......

Ajaxify looks for any elements matching these selectors and applies the effect just to them. So, using the above example, we can Ajaxify just the main content div by adding an id of “content” to it (you can also achieve this by structuring your page using the HTML5 elements “article” or “post”):

.....
<div class="mainContent" id="content">
  ......
</div>
.....

Now, when you look at this EXAMPLE, you can see that when you change pages, only the main content is switched – notice the URL and titles still change too. You are also able to navigate to either of the pages directly by entering their URL in the address bar and clicking the ‘back’ and ‘forward’ buttons in your browser takes you through your history correctly.

Sometimes, you will want to disable AJAX from a link. A common situation is with image lightboxes such as fancybox where ajaxyify will interfere with the plugin. You will have a link like so:

<a class="fancybox" href="image.jpg"><img src="thumb.jpg" alt="Image Title" /></a>

AJAX will automatically be applied to this link so you will need to disable it. In ajaxyify.html5.js there is this line watches links to ajaxify:

...
$this.find('a:internal:not(.no-ajaxy)').click(function(event){
...

From this selector, you can easily see that by adding the class no-ajaxy to a link you can get ajaxify to ignore it. Like so:

<a href="/link/" class="no-ajaxy">Click me</a>
<a class="fancybox no-ajaxy" href="image.jpg"><img src="thumb.jpg" alt="Image Title" /></a>

From the below lines, you will notice that Ajaxify triggers a ‘statechangecomplete’ event on page change:

...
completedEventName = 'statechangecomplete',
...
// Complete the change
$window.trigger(completedEventName);
...

You can listen for this event like so:

...
$(window).on('statechangecomplete', function(e, eventInfo){
//your code
})
...

Silverstripe 3 SQL Queries

You will occasionally need to to perform custom SQL queries in Silverstripe 3 and return this data for display in your template rather than just returning a standard DataObject.

Rather than just writing raw SQL, you need to build your SQL query using the SQLQuery class and execute the query:

$sqlQuery = new SQLQuery();
$sqlQuery->setFrom('Source_Table'); //the name of the table you want to select data from
$sqlQuery->selectField('Title, Content, Other_Field'); //the fields you want to return
$sqlQuery->addLeftJoin('Table_To_Join', '"Source_Table"."Relation_Column" = "Table_To_Join"."Relation_Column"'); //any joining tables
//other joins can also be specified like the left join example above
$sqlQuery->addWhere('"Column" = "Value"'); //add a where clause
$result = $sqlQuery->execute(); //execute the SQL

Now you have your result, you need to create a new ArrayList and into it, push the results from the SQL query to return to your template:

$returnedRecords = new ArrayList();
foreach($result as $row) { 
    $returnedRecords->push(new ArrayData($row)); 
}

Full example:

YourClass.php

function getResults(){
    $sqlQuery = new SQLQuery();
    $sqlQuery->setFrom('Source_Table');
    $sqlQuery->selectField('Title, Content, Other_Field');
    $sqlQuery->addLeftJoin('Table_To_Join', '"Source_Table"."Relation_Column" = "Table_To_Join"."Relation_Column"');
    $sqlQuery->addWhere('"Column" = "Value"');
    $result = $sqlQuery->execute();
    $returnedRecords = new ArrayList();
    foreach($result as $row) { 
        $returnedRecords->push(new ArrayData($row)); 
    }
    return $returnedRecords;
}

And loop through your results like so:

YourClass.ss

<% loop Results %>
	$Title
	$Content
	$etc
<% end_loop %>

Thumbnails in Silverstripe 3 GridField Summaries

Often, you will use Silverstripe 3 GridFields to handle images and will want to show image thumbnails in the summary view rather than have to give every image a title that you can later refer to when you need to edit the image. I have managed to achieve this fairly simply using the below code snippet which will give you something looking like this:

Silverstripe 3 GridField summary with Thumbnails

The important parts of the snippet are the ‘Thumbnail’ item in the the summary_fields static and the getThumbnail function:

<?php
class HeroImage extends DataObject{
	public static $db = array(
		'Title' => 'Varchar(255)',
  		'SortOrder' => 'Int'
 	);
 
 	static $has_one = array( 
		'HomePage' => 'HomePage',
		'HeroImage' => 'Image'
	);
 
 	public static $summary_fields = array(
  		'Thumbnail'=>'Thumbnail',
  		'Title' => 'Title'
 	);
 
 	public function getThumbnail() { 
		if ($Image = $this->HeroImage()->ID) { 
			return $this->HeroImage()->SetWidth(80); 
		} else { 
			return '(No Image)'; 
		} 
	}
 
 	public static $default_sort='SortOrder';
 
 	public function getCMSFields() {
	  	return new FieldList(
	   		new TextField('Title', 'Title'),
	   		new UploadField('HeroImage', 'Image')
	  	);
	}
}

A fairly short post but if you have any questions about anything on here, post them in the comments below or you can contact me and I will get back to you with an answer.

Add Captions to jQuery Cycle Slideshows

It is pretty easy to add captions to jQuery Cycle slideshows even though there is no ‘out of the box’ way of doing this.

The after option allows you to specify a function to be executed after the slide transition has finished and this is what we will be using to add captions to your slideshow.

You simply need to modify your image tags to include a caption for the image and add in a placeholder for the caption to go:

<ul id="slides">
	<li><img src="img1.jpg" alt="" data-caption="Caption for Image 1"></li>
	<li><img src="img2.jpg" alt="" data-caption="Caption for Image 2"></li>
	<li><img src="img3.jpg" alt="" data-caption="Caption for Image 3"></li>
	<li><img src="img4.jpg" alt="" data-caption="Caption for Image 4"></li>
</ul>
</div>
<div id="imageCaption"></div>

Then, you can put a simple function in the after option to extract the caption from the visible slide with jQuery and put this into your placeholder:

$("ul#slides").cycle({
	after: function(){
		$('#imageCaption').html($('#slides li:visible img').data('caption'));
	}
});

This can be easily extended to titles and any other information you need to present with your images. You just put any additional data for the image in to the image tag’s data-attributes and you can access them in the same way:

$('#slides li:visible img').data('your-data-attribute');

You can download the jQuery Cycle plug here

jQuery Content Slider – Basic plug in

I was looking for a jQuery Content Slider plug in for a project I was working on today. I couldn’t find one that fit the bill so decided to develop my own. It is in no way as fully featured as some of the other jQuery sliders out there as it was developed in as quick a time as possible to fill the specific need I had.

If you have any questions or comments about the usage of this plug in or would like to see me develop this further, let me know in the comments or contact me.

SEE THE DEMO HERE.

DOWNLOAD THE JQUERY CONTENT SLIDER PLUG-IN HERE.

Usage
Firstly, you need to link to jQuery and the plug-in files (download the files using the above link).

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script src="jquery.content.slider.min.js"></script>
<link rel="stylesheet" type="text/css" href="jquery.content.slider.css" />

You will want to change (at least) 3 of the values in the CSS to make your slider the required size. The first 2 define the height and width of the viewable area and the third defines with width of the individual slides. If want to show 1 slide at a time you simply need to set both widths to the same value. In the demo you will see that we have 3 slides visible at a time. You can of course change other values to tailor the content slider.

You can put any content you like into this jQuery content slider. Whatever you put between list items constitutes a slide.

Your slider is laid out like this:

<div id="contentSlider">
	<ul>
		<li>Content area 1</li>
		<li>Content area 2</li>
		<li>Content area 3</li>
		<li>Content area 4</li>
		<li>Content area 5</li>
		<li>Content area 6</li>
		<li>Content area 7</li>
		<li>Content area 8</li>
		<li>Content area 9</li>
	</ul>
</div>

And finally you initialise the slider like so:

$('#contentSlider').subSlider();

Options
As mentioned previously, this content slider is not as fully featured as some out there at the moment. Currently, there are only 2 configurable options which can be specified at initialisation:

$('#contentSlider').subSlider({
    speed: 200, //specifies the time in milliseconds for each transition
    addClasses: 'additionalClass1 additionalClass1' //allows you to specify additional classes to add to the slider (useful if you need 2 or more differently styled sliders on your page)
});