Basic implementation for tags

- Edit Tags
- Delete Tags
- Search Tags

Multiselect:
- Only when logged in
This commit is contained in:
Tobias Reich 2014-02-02 15:11:46 +01:00
parent d14a3dbf8b
commit be404366bc
12 changed files with 172 additions and 22 deletions

View File

@ -131,10 +131,15 @@
/* Tags ------------------------------------------------*/
#infobox #tags {
margin: 20px 20px 15px 20px;
width: calc(100% - 40px);
margin: 16px 20px 12px 20px;
color: #fff;
display: inline-block;
}
#infobox #tags .empty {
font-size: 14px;
margin-bottom: 8px;
}
#infobox .tag {
float: left;
padding: 4px 7px;

View File

@ -18,11 +18,11 @@ build = {
return "<div id='" + id + "' class='edit'><a class='icon-pencil'></a></div>";
},
multiselect: function(top, left) {
return "<div id='multiselect' style='top: " + top + "px; left: " + left + "px;'></div>";
},
album: function(albumJSON) {
@ -37,7 +37,7 @@ build = {
title = albumJSON.title.substr(0, 18) + "...";
longTitle = albumJSON.title;
}
typeThumb0 = albumJSON.thumb0.split('.').pop();
typeThumb1 = albumJSON.thumb1.split('.').pop();
typeThumb2 = albumJSON.thumb2.split('.').pop();
@ -241,6 +241,32 @@ build = {
},
tags: function(tags, forView) {
var html = "",
editTagsHTML;
if (tags!=="") {
tags = tags.split(",");
tags.forEach(function(tag, index, array) {
html += "<a class='tag'>" + tag + "<span class='icon-remove' data-index='" + index + "'></span></a>";
});
} else {
editTagsHTML = (forView===true||lychee.publicMode) ? "" : " " + build.editIcon("edit_tags");
html = "<div class='empty'>No Tags" + editTagsHTML + "</div>";
}
return html;
},
infoboxPhoto: function(photoJSON, forView) {
if (!photoJSON) return "";
@ -272,7 +298,6 @@ build = {
editTitleHTML = (forView===true||lychee.publicMode) ? "" : " " + build.editIcon("edit_title");
editDescriptionHTML = (forView===true||lychee.publicMode) ? "" : " " + build.editIcon("edit_description");
//["Tags", "<a class='tag'>Abstract<span class='icon-remove'></span></a><a class='tag'>Colors<span class='icon-remove'></span></a><a class='tag'>Photoshop<span class='icon-remove'></span></a><a class='tag'>Something<span class='icon-remove'></span></a><a class='tag'>Lychee<span class='icon-remove'></span></a><a class='tag'>Tags<span class='icon-remove'></span></a><a class='tag icon-plus'></a>"]
infos = [
["", "Basics"],
["Name", photoJSON.title + editTitleHTML],
@ -281,7 +306,8 @@ build = {
["", "Image"],
["Size", photoJSON.size],
["Format", photoJSON.type],
["Resolution", photoJSON.width + " x " + photoJSON.height]
["Resolution", photoJSON.width + " x " + photoJSON.height],
["Tags", build.tags(photoJSON.tags, forView)]
];
if ((photoJSON.takedate+photoJSON.make+photoJSON.model+photoJSON.shutter+photoJSON.aperture+photoJSON.focal+photoJSON.iso)!="") {
@ -319,9 +345,7 @@ build = {
case "Tags": // Tags
infobox += "</table>";
infobox += "<div class='separator'><h1>" + infos[index][0] + "</h1></div>";
infobox += "<tr>";
infobox += "<div id='tags'>" + infos[index][1] + "</div>";
infobox += "</tr>";
infobox += "<div id='tags'>" + infos[index][1] + "</div>";
break;
default: // Item

View File

@ -110,8 +110,8 @@ contextMenu = {
if (albumID==="0"||albumID==="f"||albumID==="s") return false;
contextMenu.fns = [
function() { album.setTitle(albumID) },
function() { album.delete(albumID) }
function() { album.setTitle([albumID]) },
function() { album.delete([albumID]) }
];
items = [

View File

@ -35,7 +35,7 @@ $(document).ready(function(){
else modal.show("Share Album", "All photos inside this album will be public and visible for everyone. Existing public photos will have the same sharing permission as this album. Are your sure you want to share this album? <input class='text' type='password' placeholder='password (optional)' value=''>", [["Share Album", function() { album.setPublic(album.getID(), e) }], ["Cancel", function() {}]]);
});
$("#button_download").on(event_name, function() { photo.getArchive(photo.getID()) });
$("#button_trash_album").on(event_name, function() { album.delete(album.getID()) });
$("#button_trash_album").on(event_name, function() { album.delete([album.getID()]) });
$("#button_move").on(event_name, function(e) { contextMenu.move([photo.getID()], e) });
$("#button_trash").on(event_name, function() { photo.delete([photo.getID()]) });
$("#button_info_album").on(event_name, function() { view.infobox.show() });
@ -68,10 +68,12 @@ $(document).ready(function(){
/* Infobox */
$("#infobox")
.on(event_name, ".header a", function() { view.infobox.hide() })
.on(event_name, "#edit_title_album", function() { album.setTitle(album.getID()) })
.on(event_name, "#edit_title_album", function() { album.setTitle([album.getID()]) })
.on(event_name, "#edit_description_album", function() { album.setDescription(album.getID()) })
.on(event_name, "#edit_title", function() { photo.setTitle([photo.getID()]) })
.on(event_name, "#edit_description", function() { photo.setDescription(photo.getID()) });
.on(event_name, "#edit_description", function() { photo.setDescription(photo.getID()) })
.on(event_name, "#edit_tags", function() { photo.editTags([photo.getID()]) })
.on(event_name, "#tags .tag span", function() { photo.deleteTag(photo.getID(), $(this).data('index')) });
/* Keyboard */
Mousetrap
@ -108,7 +110,7 @@ $(document).ready(function(){
/* Header */
.on(event_name, "#title.editable", function() {
if (visible.photo()) photo.setTitle([photo.getID()]);
else album.setTitle(album.getID());
else album.setTitle([album.getID()]);
})
/* Navigation */

View File

@ -19,6 +19,7 @@ multiselect = {
show: function(e) {
if (mobileBrowser()) return false;
if (lychee.publicMode) return false;
if ($('.album:hover, .photo:hover').length!=0) return false;
if (visible.multiselect()) $('#multiselect').remove();
@ -133,7 +134,7 @@ multiselect = {
id = $(this).data('id');
if (id!=="0"&&id!==0&&id!=="f"&&id!=="s"&&id!==null&id!==undefined) {
if (id!=='0'&&id!==0&&id!=='f'&&id!=='s'&&id!==null&id!==undefined) {
ids.push(id);
$(this).addClass('active');
@ -159,7 +160,7 @@ multiselect = {
multiselect.position.bottom = null;
multiselect.position.left = null;
lychee.animate('#multiselect', "fadeOut");
lychee.animate('#multiselect', 'fadeOut');
setTimeout(function() {
$('#multiselect').remove();
}, 300);

View File

@ -302,7 +302,69 @@ photo = {
modal.show("Set Description", "Please enter a description for this photo: <input class='text' type='text' placeholder='Description' value='" + oldDescription + "'>", buttons);
},
editTags: function(photoIDs) {
var oldTags = "";
if (!photoIDs) return false;
if (photoIDs instanceof Array===false) photoIDs = [photoIDs];
if (visible.photo()) oldTags = photo.json.tags;
buttons = [
["Set Tags", function() {
tags = $(".message input.text").val();
if (tags.length<800) {
if (visible.photo()) {
photo.json.tags = tags;
view.photo.tags();
}
photo.setTags(photoIDs, tags)
} else loadingBar.show("error", "Description too long. Please try again!");
}],
["Cancel", function() {}]
];
modal.show("Set Tags", "Please enter your tags for this photo. You can add multiple tags by separating them with a comma: <input class='text' type='text' placeholder='Tags' value='" + oldTags + "'>", buttons);
},
setTags: function(photoIDs, tags) {
var params;
if (!photoIDs) return false;
if (photoIDs instanceof Array===false) photoIDs = [photoIDs];
params = "setTags&photoIDs=" + photoIDs + "&tags=" + tags;
lychee.api(params, function(data) {
if (data!==true) lychee.error(null, params, data);
});
},
deleteTag: function(photoID, index) {
var tags;
// Remove
tags = photo.json.tags.split(',');
tags.splice(index, 1);
// Save
photo.json.tags = tags.toString();
view.photo.tags();
photo.setTags([photoID], photo.json.tags);
},
share: function(photoID, service) {
var link = "",

View File

@ -447,6 +447,12 @@ view = {
}
},
tags: function() {
$("#infobox #tags").html(build.tags(photo.json.tags));
},
photo: function() {

View File

@ -24,6 +24,7 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) {
require('modules/upload.php');
require('modules/album.php');
require('modules/photo.php');
require('modules/tags.php');
require('modules/misc.php');
if (file_exists('config.php')) require('config.php');
@ -157,6 +158,16 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) {
case 'search': if (isset($_POST['term']))
echo json_encode(search($_POST['term']));
break;
// Tag Functions
case 'getTags': if (isset($_POST['photoID']))
echo json_encode(getTags($_POST['photoID']));
break;
case 'setTags': if (isset($_POST['photoIDs'])&&isset($_POST['tags']))
echo setTags($_POST['photoIDs'], $_POST['tags']);
break;
// Session Function

View File

@ -16,8 +16,8 @@ function addAlbum($title) {
if (strlen($title)<1||strlen($title)>30) return false;
$sysdate = date("d.m.Y");
$result = $database->query("INSERT INTO lychee_albums (title, sysdate) VALUES ('$title', '$sysdate');");
if (!$result) return false;
return $database->insert_id;
}

View File

@ -152,6 +152,7 @@ function createTables($database) {
`title` varchar(50) NOT NULL,
`description` varchar(1000) NOT NULL DEFAULT '',
`url` varchar(100) NOT NULL,
`tags` varchar(1000) NOT NULL DEFAULT '',
`public` tinyint(1) NOT NULL,
`type` varchar(10) NOT NULL,
`width` int(11) NOT NULL,

View File

@ -44,13 +44,13 @@ function search($term) {
$return["albums"] = "";
$result = $database->query("SELECT * FROM lychee_photos WHERE title like '%$term%' OR description like '%$term%';");
$result = $database->query("SELECT * FROM lychee_photos WHERE title like '%$term%' OR description like '%$term%' OR tags like '%$term%';");
while($row = $result->fetch_array()) {
$return['photos'][$row['id']] = $row;
$return['photos'][$row['id']]['sysdate'] = date('d F Y', strtotime($row['sysdate']));
}
$result = $database->query("SELECT * FROM lychee_albums WHERE title like '%$term%';");
$result = $database->query("SELECT * FROM lychee_albums WHERE title like '%$term%' OR description like '%$term%';");
$i=0;
while($row = $result->fetch_object()) {
@ -85,7 +85,7 @@ function update() {
if($database->query("SELECT `password` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` CHANGE `password` `password` VARCHAR( 100 ) NULL DEFAULT ''");
if($database->query("SELECT `description` FROM `lychee_photos` LIMIT 1;")) $database->query("ALTER TABLE `lychee_photos` CHANGE `description` `description` VARCHAR( 1000 ) NULL DEFAULT ''");
if($database->query("SELECT `shortlink` FROM `lychee_photos` LIMIT 1;")) $database->query("ALTER TABLE `lychee_photos` DROP `shortlink`");
if(!$database->query("SELECT `tags` FROM `lychee_photos` LIMIT 1;")) $database->query("ALTER TABLE `lychee_photos` ADD `tags` VARCHAR( 1000 ) NULL DEFAULT ''");
$database->query("UPDATE `lychee_photos` SET url = replace(url, 'uploads/big/', ''), thumbUrl = replace(thumbUrl, 'uploads/thumb/', '')");
$result = $database->query("SELECT `value` FROM `lychee_settings` WHERE `key` = 'importFilename' LIMIT 1;");

38
php/modules/tags.php Normal file
View File

@ -0,0 +1,38 @@
<?php
/**
* @name Album Module
* @author Tobias Reich
* @copyright 2014 by Philipp Maurer, Tobias Reich
*/
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
function getTags($photoID) {
global $database;
$result = $database->query("SELECT tags FROM lychee_photos WHERE id = '$photoID';");
$return = $result->fetch_array();
if (!$result) return false;
return $return;
}
function setTags($photoIDs, $tags) {
global $database;
if (substr($tags, strlen($tags)-1)===',') $tags = substr($tags, 0, strlen($tags)-1);
$tags = str_replace(' , ', ',', $tags);
$tags = str_replace(', ', ',', $tags);
$tags = str_replace(' ,', ',', $tags);
$tags = str_replace(',,', ',', $tags);
$result = $database->query("UPDATE lychee_photos SET tags = '$tags' WHERE id IN ($photoIDs);");
if (!$result) return false;
return true;
}