A reader asked me how he could show a random image to visitors. This is simple enough, so I thought I'd show an example of that along with an example of how you could rotate over a set of images and ensure the user sees each one.
First, here is an example of how to display a random image from a directory.
<!--- Get full path to images. --->
<cfset imageDirectory = expandPath(".")>
<!--- Get directory --->
<cfdirectory action="list" directory="#imageDirectory#" name="images" filter="*.jpg">
<!--- Do we have any images? --->
<cfif images.recordCount gt 0>
<!--- How many images? --->
<cfset totalImages = images.recordCount>
<!--- Pick one --->
<cfset pickedIndex = randRange(1, totalImages)>
<!--- get the file --->
<cfset image = images.name[pickedIndex]>
<!--- display it --->
<cfoutput><img src="#image#"></cfoutput>
</cfif>
In this example, I get a directory of images using the cfdirectory tag. You could also use a database of images. Since both return a ColdFusion query object, the only thing you would need to change is the first two lines. Outside of that though the rest of the code is trivial. Check to see we have any images, and then use the randRange() function to select a random row. Simple, right? Now look at a slightly different version.
<cfapplication name="img" sessionManagement="true">
<!--- Get full path to images. --->
<cfset imageDirectory = expandPath(".")>
<!--- Get directory --->
<cfdirectory action="list" directory="#imageDirectory#" name="images" filter="*.jpg">
<!--- Do we have any images? --->
<cfif images.recordCount gt 0>
<!--- How many images? --->
<cfset totalImages = images.recordCount>
<!--- param a session var --->
<cfparam name="session.pickedIndex" default="0">
<!--- Add one to the index --->
<cfset session.pickedIndex = session.pickedIndex + 1>
<!--- if past end, restart --->
<cfif session.pickedIndex gt images.recordCount>
<cfset session.pickedIndex = 1>
</cfif>
<!--- get the file --->
<cfset image = images.name[session.pickedIndex]>
<!--- display it --->
<cfoutput><img src="#image#"></cfoutput>
</cfif>
In this example, we don't select a random image. Instead, we use a session variable named pickedIndex. We increment the value on every hit, and if the value is higher than the number of images in the query, we reset it to 1. This means that as the user visits the page, they will see each image in order.
Archived Comments
Ray,
In your first bit of code you have this line:
<code>
<!--- How many images? --->
<cfset totalImages = images.recordCount>
</code>
Why do you make a new variable for this instead of simply working with the images.recordCount variable that already exists? You have already checked if the value is above zero in the <cfif> above, is there some trick I should know, or is this simply so you have a easily remembered var name?
No trick - I was just trying to make the code as simple as possible.
The issue would be more interesting if we display 5 images at a time randomly, then the next 5 randomly images... make sure there is no repeated images if total image >= 10...
how funny! I just wrote a function that is almost verbatim to your code for a project I'm working on. great minds think alike right? :)
Derek, exactly. :)
The only issue I see with the session approach is that if the session ends and they come back they see the first image again. The last image of the list will not be shown as much as the first. Lots of ways around this, each with their own limitations I suppose.
For showing multiple image sets at a time, with tracking, you could update a field 'TotalViewed' by one each time the image is shown from a db, and then sort TotalViewed maxrows=3 or something. Though that is a lot of DB calls.
So you can store that information into the application scope with periodic updates to the DB if you needed it to be recorded at all. That way you can ensure equal viewings of the image and if storing to the DB report back to someone about the overall views.