AJAX Photo Organizer
Dit is een fotoalbum met een ajax beheer applicatie. Helaas heb ik het nooit helemaal afgemaakt, dat is ook de reden dat het enkel acceptabel werkt in FF, van Opera en IE weet ik dat er een aantal functies niet naar behoren werken. Aanpassingen voor database en inlog instellingen kunnen gemaakt worden in config.inc.php display_photoset.php & display_photosets.php kan je met enige aanpassingen als fotoalbum gebruiken en werkt zelfs op een externe (!) site. Voor de MySQL verbinding maak ik gebruik van PDO ( www.php.net/pdo ) hierdoor is PHP 5.x.x nodig om het te kunnen gebruiken, ik heb het enkel met PHP 5.2.x getest. Om de foto's te resizen maak ik gebruik van een eerste versie van mijn clsImage, zou je een watermerk o.i.d willen toevoegen zou je een nieuwere versie moeten gebruiken. ( http://www.phphulp.nl/php/scripts/4/1017/ ) Verder maak ik gebruik van o.a. - Prototype ( http://www.prototypejs.org ) - script.aculo.us ( http://script.aculo.us ) - Lightbox 2 ( http://www.huddletogether.com/projects/lightbox2/ ) Hier onder volgen een aantal code fragmenten, de gehele versie inclusief css, prototype etc. is hier te downloaden: php.n3rd.nl/photos.zip Voorbeeld Om het voorbeeld te kunnen bekijken moet je gewoon op 'cancel' drukken bij de login. Dan krijg je een voorbeeld met beperkte functionaliteit. Bugs Gelieve in de reactie geen bugs te posten, gezien ik hier niet direct iets mee zal doen. Als je een bug vind pm (of mail) die dan, dan kan ik dat gebruiken als ik iets ga verbeteren. Geef wel een duidelijke beschrijving , liever te veel informatie dan te weinig!
./sql/photos.sql
[code]CREATE TABLE album(
albumid INT(6) PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(60) NULL,
volgorde INT(6) NULL
)ENGINE=innoDB;
CREATE TABLE photos(
photoid INT(6) PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(60) NULL,
volgorde INT(6) NULL,
photo VARCHAR(100) NOT NULL,
albumid INT(6) NULL,
CONSTRAINT fk_album_albumid FOREIGN KEY (albumid) REFERENCES album (albumid),
CONSTRAINT ak_photos_photo UNIQUE (photo)
)ENGINE=innoDB;[/code]
./organize.php
[code]
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Organize Photos</title>
<link rel="stylesheet" href="./css/organize.css" type="text/css" media="screen" />
<link rel="stylesheet" href="./css/uploadbox.css" type="text/css" media="screen" />
<link rel="stylesheet" href="./css/loginbox.css" type="text/css" media="screen" />
<script src="./js/prototype.js" type="text/javascript"></script>
<script src="./js/scriptaculous.js" type="text/javascript"></script>
<script src="./js/organize.js" type="text/javascript"></script>
<script src="./js/uploadbox.js" type="text/javascript"></script>
<script src="./js/loginbox.js" type="text/javascript"></script>
</head>
<body>
<div id="delete" style="display: none;" class="top"><img alt="recycle" src="./images/recycle.png">Drop items here to delete them<img alt="recycle" src="./images/recycle.png"></div>
<div id="options" class="top">N3RD's Photo Organizer</div>
<div id="menu">
<a id="addalbum" href="#">New Photoset</a>
<ul id="photosets"></ul>
</div>
<div id="all">
<a id="upload" href="#">Upload</a>
<ul id="listall"></ul>
</div>
<div id="footer">Copyright 2007 - Boaz den Besten</div>
<div id="container"><ul id="mylist"></ul></div>
<div class="center" id="systemWorking"><img src="./images/loading.gif" alt="loading"></div>
<div class="center" id="dropzone" style="display: none;">Drop here to add to the set</div>
<iframe id="uploader" name="uploader" style="display:none;"></iframe>
</body>
</html>
[/code]
./photoset.php
[code]
<?php
try{
require_once 'settings.php';
if(isset($_GET['albumid']) && is_numeric($_GET['albumid'])){
$sAlbum = 'albumid='.$_GET['albumid'];
}else{
$sAlbum = 'albumid IS NULL';
}
$oDOM = new DOMDocument();
$oPDO = new PDO('mysql:host='.$aSetting['dbHost'].';dbname='.$aSetting['dbDatabase'], $aSetting['dbUsername'], $aSetting['dbPassword'], array(PDO::ATTR_PERSISTENT => true));
$oPDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
function addNode($p_oParentNode, $p_sName, $p_sValue, $oDOM){
$oNode = $oDOM->createElement($p_sName);
$oNode->appendChild($oDOM->createTextNode($p_sValue));
$p_oParentNode->appendChild($oNode);
}
$oDOMRoot = $oDOM->createElement('photos');
if(isset($_GET['albumid']) && is_numeric($_GET['albumid'])){
$oPDOStatement = $oPDO->prepare("SELECT albumid, title FROM album WHERE ".$sAlbum.";");
$oPDOStatement->execute();
$aRow = $oPDOStatement->fetch();
addNode($oDOMRoot, 'albumid', $aRow['albumid'], $oDOM);
addNode($oDOMRoot, 'title', $aRow['title'], $oDOM);
}else{
$sAlbum = 'albumid IS NULL';
addNode($oDOMRoot, 'albumid', null, $oDOM);
addNode($oDOMRoot, 'title', 'no album', $oDOM);
}
foreach($oPDO->query("SELECT photoid, title, photo FROM photos WHERE ".$sAlbum." ORDER BY volgorde ASC, photoid ASC;", PDO::FETCH_ASSOC) as $aRow){
$oDOMPhoto = $oDOM->createElement('photo');
addNode($oDOMPhoto, 'photoid', $aRow['photoid'], $oDOM);
addNode($oDOMPhoto, 'title', $aRow['title'], $oDOM);
addNode($oDOMPhoto, 'filename', $aRow['photo'], $oDOM);
$oDOMRoot->appendChild($oDOMPhoto);
}
header('Content-type: application/xml');
echo $oDOM->saveXML($oDOMRoot);
}catch(PDOException $e){
echo 'Database error: '.$e->getCode();
}catch(Exception $e){
echo 'Unkown error: '.$e->getCode();
}
?>
[/code]
./photoset_save.php
[code]
<?php
try{
session_start();
require_once 'settings.php';
if(!checkLogin()){
die('User not logged in.');
}
$oDb = new PDO('mysql:host='.$aSetting['dbHost'].';dbname='.$aSetting['dbDatabase'], $aSetting['dbUsername'], $aSetting['dbPassword']);
if($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST['mylist']) && !empty($_POST['albumid'])){
echo '<pre>';
print_r($_POST);
echo '</pre>';
$oQuery = $oDb->prepare("UPDATE photos SET volgorde = :volgorde, albumid = :albumid WHERE photoid = :photoid");
foreach($_POST['mylist'] as $iKey => $iValue){
$oQuery->bindParam(':volgorde', $iKey, PDO::PARAM_INT);
$oQuery->bindParam(':photoid', $iValue, PDO::PARAM_INT);
$oQuery->bindParam(':albumid', $_POST['albumid'], PDO::PARAM_INT);
$oQuery->execute();
}
}elseif($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST['listall'])){
echo '<pre>';
print_r($_POST);
echo '</pre>';
$oQuery = $oDb->prepare("UPDATE photos SET volgorde = NULL, albumid = NULL WHERE photoid = :photoid");
foreach($_POST['listall'] as $iPhotoId){
$oQuery->bindParam(':photoid', $iPhotoId, PDO::PARAM_INT);
$oQuery->execute();
}
}elseif($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST['delete'])){
echo '<pre>';
print_r($_POST);
echo '</pre>';
$oQuery = $oDb->prepare("SELECT photo FROM photos WHERE photoid = :photoid");
$oQuery->bindParam(':photoid', $_POST['delete'], PDO::PARAM_INT);
$oQuery->execute();
$aRow = $oQuery->fetch();
$aLocations = array(
'album/normal/',
'album/small/',
'album/thumb/'
);
foreach($aLocations as $sLocation){
unlink($sLocation.$aRow['photo']);
}
$oQuery = $oDb->prepare("DELETE FROM photos WHERE photoid = :photoid");
$oQuery->bindParam(':photoid', $_POST['delete'], PDO::PARAM_INT);
$oQuery->execute();
}
}catch(PDOException $e){
echo 'Database error: '.$e->getCode();
}catch(Exception $e){
echo 'Unkown error: '.$e->getCode();
}
?>
[/code]
./login.php
[code]
<?php
session_start();
require_once 'settings.php';
if($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST['username']) && !empty($_POST['password'])){
$bFlag = false;
foreach($aUsers as $aUser){
if($aUser['username'] == $_POST['username'] && $aUser['password'] == $_POST['password']){
$bFlag = true;
}
}
if($bFlag){
$_SESSION['login']['username'] = $_POST['username'];
$_SESSION['login']['password'] = $_POST['password'];
$_SESSION['login']['ip'] = $_SERVER['REMOTE_ADDR'];
echo 'ok';
}else{
$_SESSION['login'] = null;
echo 'fail';
}
}else{
echo checkLogin() ? 'ok' : 'fail';
}
?>
[/code]
./js/organize.js
[code]
// The application must know if a photoset is loaded:
var bPhotoSetLoaded = false;
// Need for the drag 'n scroll effect
Position.includeScrollOffsets = true;
// thnx ppk
function getNodeValue(obj, tag){
return obj.getElementsByTagName(tag)[0].firstChild.nodeValue;
}
// -- Loading image
var myGlobalHandlers = {
onCreate: function(){
Element.show('systemWorking');
},
onComplete: function() {
Element.hide('systemWorking');
}
};
Ajax.Responders.register(myGlobalHandlers);
// -- End loading image
// -- Handle a drag event
Draggables.addObserver({
onStart: function(){
$('options').hide();
$('delete').show();
$('dropzone').show();
},
onEnd: function(){
$('options').show();
$('delete').hide();
$('dropzone').hide();
}
});
// -- Stop handeling a drag event
// PhotoSet laden
function loadPhotoSet(PhotoSetId){
//Eerst oude photos verwijderen:
var descendants = $('mylist').immediateDescendants();
for(var i = 0; i < descendants.size(); i++){
descendants[i].remove();
}
new Ajax.Request('photoset.php', {
method: 'get',
parameters: 'albumid='+PhotoSetId,
onComplete: function(transport){
var root = transport.responseXML.documentElement;
var photos = root.getElementsByTagName('photo');
var photoid = null;
var filename = null;
var item = null;
for(var i = 0; i < photos.length; i++)
{
photoid = getNodeValue(photos.item(i), 'photoid');
filename = getNodeValue(photos.item(i), 'filename');
item = Builder.node('li', {id: 'option_'+photoid}, [
Builder.node('img', {src: 'album/small/'+filename, alt: 'album/small/'+filename})
]);
$('mylist').appendChild(item);
}
Sortable.create('mylist', {tag: 'li', scroll: window, constraint: false, containment: ['listall', 'mylist'], onUpdate: function() {
new Ajax.Request('photoset_save.php', {
method : 'post',
parameters : Sortable.serialize('mylist')+'&albumid='+PhotoSetId,
onComplete: function(){
var img = $$('#photoset_'+PhotoSetId+' a img');
//alert(img[0].src);
var newImg = $$('#mylist li img');
//alert(newImg[0].src);
img[0].src = newImg[0].src;
}
});
}
});
}
});
// -- scroll to top and show me the photos
new Effect.ScrollTo(window);
// -- let the app know a photoset is loaded
bPhotoSetLoaded = true;
}
// Alles laden:
function loadAll(){
//Eerst oude verwijderen:
var descendants = $('listall').immediateDescendants();
for(var i = 0; i < descendants.size(); i++){
descendants[i].remove();
}
new Ajax.Request('photoset.php', {
method: 'get',
onComplete: function(transport){
var root = transport.responseXML.documentElement;
var photos = root.getElementsByTagName('photo');
var photoid = null;
var filename = null;
var item = null;
for(var i = 0; i < photos.length; i++)
{
photoid = getNodeValue(photos.item(i), 'photoid');
filename = getNodeValue(photos.item(i), 'filename');
item = Builder.node('li', {id: 'all_'+photoid}, [
Builder.node('img', {src: 'album/small/'+filename, alt: 'album/small/'+filename})
]);
$('listall').appendChild(item);
}
Sortable.create('listall', {tag: 'li', scroll: window, constraint: false, containment: ['mylist', 'listall'], onUpdate: function() {
new Ajax.Request('photoset_save.php', {
method : 'post',
parameters : Sortable.serialize('listall')
});
}
});
}
});
}
// PhotoSets laden:
function loadPhotoSets(){
//Eerst oude verwijderen:
var descendants = $('photosets').immediateDescendants();
for(var i = 0; i < descendants.size(); i++){
descendants[i].remove();
}
new Ajax.Request('photosets.php', {
method: 'get',
onComplete: function(transport){
var root = transport.responseXML.documentElement;
var photosets = root.getElementsByTagName('photoset');
var albumid = null;
var title = null;
var photo = null;
sets = $('photosets');
var item = null;
for(var i = 0; i < photosets.length; i++)
{
albumid = getNodeValue(photosets.item(i), 'albumid');
title = getNodeValue(photosets.item(i), 'title');
photo = getNodeValue(photosets.item(i), 'photo');
item = Builder.node('li', {id: 'photoset_'+albumid});
var albumlink = Builder.node('a', {href: 'javascript: loadPhotoSet('+albumid+');', 'class': 'album'}, [
Builder.node('img', {src: 'album/small/'+photo, alt: title, 'title': title}),
Builder.node('br'),
Builder.node('small', title)
]);
item.appendChild(albumlink);
sets.appendChild(item);
}
$('menu').appendChild(sets);
Sortable.create(sets, {tag: 'li', scroll: window, constraint: false, onUpdate: function(){
new Ajax.Request('photosets_save.php', {
method : 'post',
parameters : Sortable.serialize('photosets')
});
}
});
}
});
}
// -- Create a new photoset
function newPhotoSet(event){
// -- Een ajax request om het album te maken en vervolgens het last_instert_id terug te krijgen.
var title = prompt('Wat is de titel van het nieuwe album?');
if(title && title != null && title != 'null'){
new Ajax.Request('photosets_save.php', {
method: 'post',
parameters: 'title='+title,
onComplete: function(transport){
var albumid = transport.responseText;
loadPhotoSet(albumid);
loadPhotoSets();
}
});
}
Event.stop(event);
}
Event.observe(window, 'load', function() {
// -- Load all data
loadPhotoSets();
//loadPhotoSet(1);
loadAll();
// -- Set a new PhotoSet button:
Event.observe('addalbum', 'click', newPhotoSet);
// -- Make a dropzone for photos (new albums as special)
Droppables.add('dropzone', {
containment: 'listall',
onDrop: function(element){
if(!bPhotoSetLoaded){
alert('Select a photoset first.');
}else{
element.remove();
$('mylist').appendChild(element);
}
}
});
// -- Make a allphoto dropzone:
Droppables.add('all', {
containment: 'mylist',
onDrop: function(element){
element.remove();
$('listall').appendChild(element);
}
});
// -- Make a dropzone to delete photos AND photosets
Droppables.add('delete', {
containment: ['listall', 'mylist', 'photosets'],
onDrop: function(element){
var aPhotoInfo = element.id.split('_');
var iPhotoId = aPhotoInfo[1];
// Album verwijderen:
if(aPhotoInfo[0] == 'photoset' && confirm('Are you sure you want to delete this photoset?')){// Als het een photoset is die verwijderen:
new Ajax.Request('photosets_save.php', {
method: 'post',
parameters: 'delete='+iPhotoId
});
// Geselecteerde photos verwijderen:
var descendants = $('mylist').immediateDescendants();
for(var i = 0; i < descendants.size(); i++){
descendants[i].remove();
}
// Boolean zetten dat er geen album geselecteerd is:
bPhotoSetLoaded = false;
// Album verwijderen:
Element.remove(element);
// Alle photos opnieuw laden:
loadAll();
}
// Photo verwijderen:
if(aPhotoInfo[0] != 'photoset' && confirm('Are you sure you want to permanatly remove this photo?')){ // Anders is het een photo, deze verwijderen
new Ajax.Request('photoset_save.php', {
method: 'post',
parameters: 'delete='+iPhotoId
});
Element.remove(element);
}
}
});
});
[/code]
Reacties
0