AJAX Photo Gallery Logic
Posted: Tue Jun 13, 2006 11:18 am
This should be a piece of cake but I've got my head all in a muddle and can't get back on focus.
(I'm sort of writing this in hope I'll re-gain focus like I usually do and answer my own question
)
Basically, I have a page where it load initially with an empty DIV element of ID "node_holder".
Now, on the server side I've created a Matrix of Image ID's from the database which looks like this:
There will always be two or three ID's on each array, dependant upon if the images were determined to be portrait or landscape. Each array contains the list of images which should be displayed next on the page.
When the page loads it first needs to get the array at index 0 and cache that in JavaScript. Each time the user clicks a button called "next" on the client-side 2 things should happen:
1. The array of images which are currently cached in the JS are displayed on the page
2. an ajax request is sent asking if there are more images to display, and then they are cached in the background
That process happens repeatedly until there are no more images.
I seem to have got my logic all screwed up somewhere after trying to get the first set to display without the user clicking "next". Nothing happens when I click next but there are no errors.
Here's my (messy) code so far, with bits and pieces of attempted debugging.
Server side controller:
Client Side (Template)
I'll probably suss it out myself before long cos I doubt anybody's gonna be feeling lively enough to make sense of my code 
(I'm sort of writing this in hope I'll re-gain focus like I usually do and answer my own question
Basically, I have a page where it load initially with an empty DIV element of ID "node_holder".
Now, on the server side I've created a Matrix of Image ID's from the database which looks like this:
Code: Select all
array (
array ( id1, id2 ),
array ( id1, id2, id3 ),
array ( id1, id2 ),
array ( id1, id2 )
)When the page loads it first needs to get the array at index 0 and cache that in JavaScript. Each time the user clicks a button called "next" on the client-side 2 things should happen:
1. The array of images which are currently cached in the JS are displayed on the page
2. an ajax request is sent asking if there are more images to display, and then they are cached in the background
That process happens repeatedly until there are no more images.
I seem to have got my logic all screwed up somewhere after trying to get the first set to display without the user clicking "next". Nothing happens when I click next but there are no errors.
Here's my (messy) code so far, with bits and pieces of attempted debugging.
Server side controller:
Code: Select all
<?php
class controller extends core
{
private $input;
public function __construct()
{
parent::__construct();
$this->input = new inputFilter;
$this->input->expect(
array(
array('time', 'numeric'),
array('get', 'numeric')
),
$_GET
);
if (!$this->input->get('time')) $this->redirect('?page=home');
if (!isset($_SESSION['gallery'])) $_SESSION['gallery'] = array();
if (!isset($_SESSION['gallery'][$this->input->get('time')])) $this->generateMatrix();
if ($this->input->get('get') !== null)
{
$this->sendAjaxString();
exit();
}
}
public function getTime()
{
return $this->input->get('time');
}
private function sendAjaxString()
{
$sess = $_SESSION['gallery'][$this->input->get('time')];
if (empty($sess)) exit('NULL');
if (isset($sess[$this->input->get('get')]))
{
/*
Send a parseable string with the following:
----
Id of Attachment --
Id of Image --
Num Comments --
If Prev exists --
If next exists --
*/
$ret = '';
$collection = $sess[$this->input->get('get')];
$set = $this->input->get('time');
$next = (int) isset($sess[($this->input->get('get')+1)]);
$prev = (int) isset($sess[($this->input->get('get')-1)]);
$loop = false;
foreach ($collection as $id)
{
if ($loop) $ret .= ':';
$loop = true;
$query = "
select
b.id as attid,
a.id as imgid
from
gallery_sets as a,
attachments as b
where
a.image = b.id
and a.timeline_id = '{$set}'
and a.id = '{$id}'
order by
b.filename asc";
$result = $this->db->query($query);
$row = $this->db->fetchRow($result);
//Build string
$ret .= 'img='.$row->imgid.','.
'att='.$row->attid.','.
'next='.$next.','.
'prev='.$prev.',';
$query2 = "
select
count(*) as tot
from
gallery_comments
where
imgid = '".$row->imgid."'";
$result2 = $this->db->query($query2);
$row2 = $this->db->fetchRow($result2);
$ret .= 'comments='.$row2->tot;
}
exit($ret);
}
else exit('NULL');
}
//Get the title of the current image set (year range)
public function getSet()
{
$id = $this->input->get('time');
$query = "
select
concat(year_start, ' - ', year_end) as range
from
timeline
where
id = '$id'";
$result = $this->db->query($query);
if ($this->db->numRows($result))
{
$row = $this->db->fetchRow($result);
return $row->range;
}
else $this->redirect('?page=home');
}
//Build the matrix of images and cache it in the session
public function generateMatrix()
{
$set = $this->input->get('time');
$query = "
select
a.id,
a.image,
a.width,
a.height
from
gallery_sets as a,
attachments as b
where
a.image = b.id
and a.timeline_id = '{$set}'
order by
b.filename asc";
$result = $this->db->query($query);
$collection = array();
$last_dim = false;
$tmp = array();
$n = $this->db->numRows($result);
$x = 0;
while ($row = $this->db->fetchRow($result))
{
$x++;
switch (($row->width > $row->height))
{
case true:
$dim = 'landscape';
break;
case false:
$dim = 'portrait';
break;
}
if ($last_dim && $last_dim != $dim)
{
$collection[] = $tmp;
$tmp = array();
}
elseif ($dim == 'portrait' && count($tmp) >= 3)
{
$collection[] = $tmp;
$tmp = array();
}
elseif ($dim == 'landscape' && count($tmp) >= 2)
{
$collection[] = $tmp;
$tmp = array();
}
$tmp[] = $row->id;
$last_dim = $dim;
if ($x == $n) $collection[] = $tmp;
}
$_SESSION['gallery'][$this->input->get('time')] = $collection;
}
}
?>Code: Select all
<html>
<head>
<title>Gallery</title>
<script type="text/javascript">
<!--
var started = false;
var imgIndex = -1;
var imgIndexTmp = 0;
var myImages = new Array();
var lastResponse;
function getNextSet()
{
if (!started) return loadFirstSet();
http.open("GET", '?page=gallery&time=<?= $con->getTime(); ?>&get='+(imgIndex+1), true);
http.onreadystatechange = showImages;
http.send(false);
imgIndexTmp = imgIndex+1;
}
function getPrevSet()
{
alert(imgIndex);
http.open("GET", '?page=gallery&time=<?= $con->getTime(); ?>&get='+(imgIndex-1), true);
http.onreadystatechange = showImages;
http.send(false);
imgIndexTmp = imgIndex-1;
}
function loadFirstSet()
{
http.open("GET", '?page=gallery&time=<?= $con->getTime(); ?>&get=0', true);
http.onreadystatechange = loadImages;
http.send(false);
started = true;
}
function loadImages(foo)
{
if (http.readyState == 4)
{
var response = http.responseText;
if (response == 'NULL') return;
else
{
var imageData = response.split(':');
myImages = new Array();
for (var x in imageData)
{
var myVars = imageData[x].split(',');
for (var y in myVars) eval(myVars[y]);
myImages[x] = new Image();
myImages[x].src = '?page=getfile&id='+att;
}
if (!foo) getNextSet();
return;
}
}
}
function showImages()
{
var arrSize = arraySize(myImages);
if (arrSize == 3)
{
try {
document.getElementById('node_holder').removeChild(myNode);
} catch (e) {
//
}
add3columnTbl();
}
else if (arrSize != 0)
{
try {
document.getElementById('node_holder').removeChild(myNode);
} catch (e) {
//
}
add2columnTbl();
}
if (arrSize != 0)
{
loadImages('yes');
imgIndex = imgIndexTmp;
}
}
function arraySize(arr)
{
if (arr.constructor != Array) return 0;
var itsSize = 0;
for (var x in arr) itsSize++;
return itsSize;
}
function add2columnTbl()
{
myNode = document.createElement('table');
myNode.style.width = '1024px';
myNode.style.height = '350px';
myNode.style.backgroundColor = '#777777';
myTr = document.createElement('tr');
myTd1 = document.createElement('td');
myTd2 = document.createElement('td');
myTd1.style.width = '512px';
myTd1.style.textAlign = 'center';
myTd2.style.textAlign = 'center';
myTd1.appendChild(myImages[0]);
myTd2.appendChild(myImages[1]);
myTr.appendChild(myTd1);
myTr.appendChild(myTd2);
myNode.appendChild(myTr);
document.getElementById('node_holder').appendChild(myNode);
}
function add3columnTbl()
{
myNode = document.createElement('table');
myNode.style.width = '1024px';
myNode.style.height = '350px';
myNode.style.backgroundColor = '#777777';
myTr = document.createElement('tr');
myTd1 = document.createElement('td');
myTd2 = document.createElement('td');
myTd3 = document.createElement('td');
myTd1.style.width = '341px';
myTd2.style.width = '341px';
myTd1.style.textAlign = 'center';
myTd2.style.textAlign = 'center';
myTd3.style.textAlign = 'center';
myTd1.appendChild(myImages[0]);
myTd2.appendChild(myImages[1]);
myTd3.appendChild(myImages[2]);
myTr.appendChild(myTd1);
myTr.appendChild(myTd2);
myTr.appendChild(myTd3);
myNode.appendChild(myTr);
document.getElementById('node_holder').appendChild(myNode);
}
function getHTTPObj()
{
var XMLHttp;
if (window.XMLHttpRequest) XMLHttp = new XMLHttpRequest();
else if (window.ActiveXObject)
{
try {
XMLHttp = new window.ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
XMLHttp = false;
}
}
else XMLHttp = false;
return XMLHttp;
}
var http = getHTTPObj();
// -->
</script>
</head>
<body onload="getNextSet();">
<a href="javascript:getPrevSet();">Prev</a>
<a href="javascript:getNextSet();">Next</a>
<table style="width: 100%; height: 100%;">
<tr>
<td align="center">
<div id="node_holder"></div>
</td>
</tr>
</table>
</body>
</html>