From dd8de66bd357edd2ad005a641252d0a73bc88ca6 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 28 Jan 2014 17:00:55 +0100 Subject: [PATCH 01/87] Basic Multiselect --- assets/css/modules/multiselect.css | 12 ++++ assets/js/modules/init.js | 12 ++-- assets/js/modules/multiselect.js | 110 +++++++++++++++++++++++++++++ index.html | 18 ++--- 4 files changed, 140 insertions(+), 12 deletions(-) create mode 100644 assets/css/modules/multiselect.css create mode 100644 assets/js/modules/multiselect.js diff --git a/assets/css/modules/multiselect.css b/assets/css/modules/multiselect.css new file mode 100644 index 0000000..b6eb242 --- /dev/null +++ b/assets/css/modules/multiselect.css @@ -0,0 +1,12 @@ +/** + * @name multiselect.css + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +#multiselect { + position: absolute; + background-color: RGBA(0, 94, 204, .4); + border: 1px solid RGBA(0, 94, 204, 1); + border-radius: 3px; +} \ No newline at end of file diff --git a/assets/js/modules/init.js b/assets/js/modules/init.js index f6e2236..2b45ed7 100755 --- a/assets/js/modules/init.js +++ b/assets/js/modules/init.js @@ -11,13 +11,17 @@ $(document).ready(function(){ /* Notifications */ if (window.webkitNotifications) window.webkitNotifications.requestPermission(); - + /* Disable ContextMenu */ $(document).bind("contextmenu", function(e) { e.preventDefault() }); /* Tooltips */ if (!mobileBrowser()) $(".tools").tipsy({gravity: 'n', fade: false, delayIn: 0, opacity: 1}); + /* Multiselect */ + $("#content").on("mousedown", multiselect.show); + $(document).on("mouseup", multiselect.close); + /* Header */ $("#hostedwith").on(event_name, function() { window.open(lychee.website,"_newtab") }); $("#button_signin").on(event_name, lychee.loginDialog); @@ -41,9 +45,9 @@ $(document).ready(function(){ /* Search */ $("#search").on("keyup click", function() { search.find($(this).val()) }); - + /* Clear Search */ - $("#clearSearch").on(event_name, function () { + $("#clearSearch").on(event_name, function () { $("#search").focus(); search.reset(); }); @@ -106,7 +110,7 @@ $(document).ready(function(){ if (visible.photo()) photo.setTitle(photo.getID()); else album.setTitle(album.getID()); }) - + /* Navigation */ .on("click", ".album", function() { lychee.goto($(this).attr("data-id")) }) .on("click", ".photo", function() { lychee.goto(album.getID() + "/" + $(this).attr("data-id")) }) diff --git a/assets/js/modules/multiselect.js b/assets/js/modules/multiselect.js new file mode 100644 index 0000000..12fd0ae --- /dev/null +++ b/assets/js/modules/multiselect.js @@ -0,0 +1,110 @@ +/** + * @name Multiselect Module + * @description Select multiple albums or photos. + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +multiselect = { + + position: { + + top: null, + right: null, + bottom: null, + left: null + + }, + + show: function(e) { + + if ($('.album:hover, .photo:hover').length!=0) return false; + if (visible.multiselect()) $('#multiselect').remove(); + + multiselect.position.top = e.pageY; + multiselect.position.right = -1 * (e.pageX - $(document).width()); + multiselect.position.bottom = -1 * (multiselect.position.top - $(window).height()); + multiselect.position.left = e.pageX; + + $('body').append(build.multiselect(multiselect.position.top, multiselect.position.left)); + $(document).on('mousemove', multiselect.resize); + + }, + + resize: function(e) { + + var mouse_x = e.pageX, + mouse_y = e.pageY, + newHeight, + newWidth; + + if (multiselect.position.top===null|| + multiselect.position.right===null|| + multiselect.position.bottom===null|| + multiselect.position.left===null) return false; + + if (mouse_y>=multiselect.position.top) { + + // Do not leave the screen + newHeight = e.pageY - multiselect.position.top; + if ((multiselect.position.top+newHeight)>=$(document).height()) + newHeight -= (multiselect.position.top + newHeight) - $(document).height() + 2; + + $('#multiselect').css({ + top: multiselect.position.top, + bottom: 'inherit', + height: newHeight + }); + + } else { + + $('#multiselect').css({ + top: 'inherit', + bottom: multiselect.position.bottom, + height: multiselect.position.top - e.pageY + }); + + } + + if (mouse_x>=multiselect.position.left) { + + // Do not leave the screen + newWidth = e.pageX - multiselect.position.left; + if ((multiselect.position.left+newWidth)>=$(document).width()) + newWidth -= (multiselect.position.left + newWidth) - $(document).width() + 2; + + $('#multiselect').css({ + right: 'inherit', + left: multiselect.position.left, + width: newWidth + }); + + } else { + + $('#multiselect').css({ + right: multiselect.position.right, + left: 'inherit', + width: multiselect.position.left - e.pageX + }); + + } + + }, + + close: function() { + + $(document).off('mousemove'); + + multiselect.position.top = null; + multiselect.position.right = null; + multiselect.position.bottom = null; + multiselect.position.left = null; + + lychee.animate('#multiselect', "fadeOut"); + setTimeout(function() { + $('#multiselect').remove(); + }, 300); + + } + +} \ No newline at end of file diff --git a/index.html b/index.html index 24b4913..84793b5 100644 --- a/index.html +++ b/index.html @@ -12,7 +12,7 @@ - @@ -25,10 +25,11 @@ - --> + + - - + @@ -99,7 +100,7 @@ - @@ -114,10 +115,11 @@ - --> + + - - + \ No newline at end of file From 7b07f43d1971eccf0d3b648e2f8ea811b2c688dc Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 28 Jan 2014 17:15:23 +0100 Subject: [PATCH 02/87] Added missing functions for multiselect --- assets/js/modules/build.js | 6 ++++++ assets/js/modules/visible.js | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/assets/js/modules/build.js b/assets/js/modules/build.js index 9ac35de..91e3d78 100755 --- a/assets/js/modules/build.js +++ b/assets/js/modules/build.js @@ -18,6 +18,12 @@ build = { return "
"; }, + + multiselect: function(top, left) { + + return "
"; + + }, album: function(albumJSON) { diff --git a/assets/js/modules/visible.js b/assets/js/modules/visible.js index 2855354..505e5c8 100755 --- a/assets/js/modules/visible.js +++ b/assets/js/modules/visible.js @@ -45,6 +45,11 @@ visible = { contextMenu: function() { if ($(".contextmenu").length>0) return true; else return false; + }, + + multiselect: function() { + if ($("#multiselect").length>0) return true; + else return false; } } \ No newline at end of file From ef46bd183ae77bda6af4dda731e47903f07aecc0 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 28 Jan 2014 20:44:25 +0100 Subject: [PATCH 03/87] Move all and Star all --- assets/js/modules/contextMenu.js | 80 ++++++++++++++++++++------------ assets/js/modules/init.js | 6 +-- assets/js/modules/multiselect.js | 50 +++++++++++++++++++- assets/js/modules/photo.js | 48 ++++++++++--------- php/api.php | 8 ++-- php/modules/photo.php | 32 +++++++------ 6 files changed, 153 insertions(+), 71 deletions(-) diff --git a/assets/js/modules/contextMenu.js b/assets/js/modules/contextMenu.js index a21177c..bfcc2a1 100644 --- a/assets/js/modules/contextMenu.js +++ b/assets/js/modules/contextMenu.js @@ -11,12 +11,13 @@ contextMenu = { show: function(items, mouse_x, mouse_y, orientation) { - if (visible.contextMenu()) contextMenu.close(); + contextMenu.close(); $("body") .css("overflow", "hidden") .append(build.contextMenu(items)); + // Do not leave the screen if ((mouse_x+$(".contextmenu").outerWidth(true))>$("html").width()) orientation = "left"; if ((mouse_y+$(".contextmenu").outerHeight(true))>$("html").height()) mouse_y -= (mouse_y+$(".contextmenu").outerHeight(true)-$("html").height()) @@ -38,11 +39,9 @@ contextMenu = { add: function(e) { var mouse_x = e.pageX, - mouse_y = e.pageY, + mouse_y = e.pageY - $(document).scrollTop(), items; - mouse_y -= $(document).scrollTop(); - contextMenu.fns = [ function() { $("#upload_files").click() }, function() { upload.start.url() }, @@ -68,11 +67,9 @@ contextMenu = { settings: function(e) { var mouse_x = e.pageX, - mouse_y = e.pageY, + mouse_y = e.pageY - $(document).scrollTop(), items; - mouse_y -= $(document).scrollTop(); - contextMenu.fns = [ function() { settings.setLogin() }, function() { settings.setSorting() }, @@ -95,13 +92,11 @@ contextMenu = { album: function(albumID, e) { var mouse_x = e.pageX, - mouse_y = e.pageY, + mouse_y = e.pageY - $(document).scrollTop(), items; if (albumID==="0"||albumID==="f"||albumID==="s") return false; - mouse_y -= $(document).scrollTop(); - contextMenu.fns = [ function() { album.setTitle(albumID) }, function() { album.delete(albumID) } @@ -121,15 +116,13 @@ contextMenu = { photo: function(photoID, e) { var mouse_x = e.pageX, - mouse_y = e.pageY, + mouse_y = e.pageY - $(document).scrollTop(), items; - mouse_y -= $(document).scrollTop(); - contextMenu.fns = [ - function() { photo.setStar(photoID) }, + function() { photo.setStar([photoID]) }, function() { photo.setTitle(photoID) }, - function() { contextMenu.move(photoID, e, "right") }, + function() { contextMenu.move([photoID], e, "right") }, function() { photo.delete(photoID) } ]; @@ -146,18 +139,45 @@ contextMenu = { $(".photo[data-id='" + photoID + "']").addClass("active"); }, + + photoMulti: function(ids, e) { + + var mouse_x = e.pageX, + mouse_y = e.pageY - $(document).scrollTop(), + items; - move: function(photoID, e, orientation) { + multiselect.stopResize(); + + contextMenu.fns = [ + function() { photo.setStar(ids) }, + function() { photo.setTitle(ids) }, + function() { contextMenu.move(ids, e, "right") }, + function() { photo.delete(ids) } + ]; + + items = [ + [" Star All", 0], + ["separator", -1], + [" Rename All", 1], + [" Move All", 2], + [" Delete All", 3] + ]; + + contextMenu.show(items, mouse_x, mouse_y, "right"); + + }, + + move: function(ids, e, orientation) { var mouse_x = e.pageX, - mouse_y = e.pageY, + mouse_y = e.pageY - $(document).scrollTop(), items = []; - contextMenu.fns = []; + contextMenu.close(true); if (album.getID()!=="0") { items = [ - ["Unsorted", 0, "photo.setAlbum(0, " + photoID + ")"], + ["Unsorted", 0, "photo.setAlbum([" + ids + "], 0)"], ["separator", -1] ]; } @@ -168,14 +188,10 @@ contextMenu = { items = [["New Album", 0, "album.add()"]]; } else { $.each(data.content, function(index) { - if (this.id!=album.getID()) items.push([this.title, 0, "photo.setAlbum(" + this.id + ", " + photoID + ")"]); + if (this.id!=album.getID()) items.push([this.title, 0, "photo.setAlbum([" + ids + "], " + this.id + ")"]); }); } - contextMenu.close(); - - $(".photo[data-id='" + photoID + "']").addClass("active"); - if (!visible.photo()) contextMenu.show(items, mouse_x, mouse_y, "right"); else contextMenu.show(items, mouse_x, mouse_y, "left"); @@ -255,13 +271,19 @@ contextMenu = { }, - close: function() { - - contextMenu.js = null; - + close: function(leaveSelection) { + + if (!visible.contextMenu()) return false; + + contextMenu.fns = []; + $(".contextmenu_bg, .contextmenu").remove(); - $(".photo.active, .album.active").removeClass("active"); $("body").css("overflow", "auto"); + + if (leaveSelection!==true) { + $(".photo.active, .album.active").removeClass("active"); + if (visible.multiselect()) multiselect.close(); + } } diff --git a/assets/js/modules/init.js b/assets/js/modules/init.js index 2b45ed7..c67fb07 100755 --- a/assets/js/modules/init.js +++ b/assets/js/modules/init.js @@ -20,7 +20,7 @@ $(document).ready(function(){ /* Multiselect */ $("#content").on("mousedown", multiselect.show); - $(document).on("mouseup", multiselect.close); + $(document).on("mouseup", multiselect.getSelection); /* Header */ $("#hostedwith").on(event_name, function() { window.open(lychee.website,"_newtab") }); @@ -36,12 +36,12 @@ $(document).ready(function(){ }); $("#button_download").on(event_name, function() { photo.getArchive(photo.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_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() }); $("#button_info").on(event_name, function() { view.infobox.show() }); $("#button_archive").on(event_name, function() { album.getArchive(album.getID()) }); - $("#button_star").on(event_name, function() { photo.setStar(photo.getID()) }); + $("#button_star").on(event_name, function() { photo.setStar([photo.getID()]) }); /* Search */ $("#search").on("keyup click", function() { search.find($(this).val()) }); diff --git a/assets/js/modules/multiselect.js b/assets/js/modules/multiselect.js index 12fd0ae..d4263c3 100644 --- a/assets/js/modules/multiselect.js +++ b/assets/js/modules/multiselect.js @@ -90,10 +90,58 @@ multiselect = { } }, + + stopResize: function() { + + $(document).off('mousemove'); + + }, + + getSize: function() { + + if (!visible.multiselect()) return false; + + return { + top: $('#multiselect').offset().top, + left: $('#multiselect').offset().left, + width: parseInt($('#multiselect').css('width').replace('px', '')), + height: parseInt($('#multiselect').css('height').replace('px', '')) + } + + }, + + getSelection: function(e) { + + var ids = [], + offset, + size = multiselect.getSize(); + + if (visible.contextMenu()) return false; + if (!visible.multiselect()) return false; + + $('.photo, .album').each(function() { + + offset = $(this).offset(); + + if (offset.top>=size.top&& + offset.left>=size.left&& + (offset.top+206)<=(size.top+size.height)&& + (offset.left+206)<=(size.left+size.width)) { + ids.push($(this).data('id')); + $(this).addClass('active'); + } + + }); + + if (ids.length!=0&&visible.album()) contextMenu.photoMulti(ids, e); + else if (ids.length!=0&&visible.albums()) contextMenu.albumMulti(ids, e); + else multiselect.close(); + + }, close: function() { - $(document).off('mousemove'); + multiselect.stopResize(); multiselect.position.top = null; multiselect.position.right = null; diff --git a/assets/js/modules/photo.js b/assets/js/modules/photo.js index 0964d20..2d26f40 100644 --- a/assets/js/modules/photo.js +++ b/assets/js/modules/photo.js @@ -145,39 +145,43 @@ photo = { }, - setAlbum: function(albumID, photoID) { + setAlbum: function(ids, albumID) { - var params; - - if (albumID>=0) { + var params, + nextPhoto, + previousPhoto; + + if (visible.photo) lychee.goto(album.getID()); + if (ids instanceof Array===false) ids = [ids]; + + ids.forEach(function(id, index, array) { // Change reference for the next and previous photo - if (album.json.content[photoID].nextPhoto!==""||album.json.content[photoID].previousPhoto!=="") { + if (album.json.content[id].nextPhoto!==""||album.json.content[id].previousPhoto!=="") { - nextPhoto = album.json.content[photoID].nextPhoto; - previousPhoto = album.json.content[photoID].previousPhoto; + nextPhoto = album.json.content[id].nextPhoto; + previousPhoto = album.json.content[id].previousPhoto; album.json.content[previousPhoto].nextPhoto = nextPhoto; album.json.content[nextPhoto].previousPhoto = previousPhoto; } + + album.json.content[id] = null; + view.album.content.delete(id); + + }); - if (visible.photo) lychee.goto(album.getID()); - album.json.content[photoID] = null; - view.album.content.delete(photoID); + params = "setAlbum&ids=" + ids + "&albumID=" + albumID; + lychee.api(params, function(data) { - params = "setAlbum&photoID=" + photoID + "&albumID=" + albumID; - lychee.api(params, function(data) { + if (data!==true) lychee.error(null, params, data); - if (data!==true) lychee.error(null, params, data); - - }); - - } + }); }, - setStar: function(photoID) { + setStar: function(ids) { var params; @@ -186,10 +190,12 @@ photo = { view.photo.star(); } - album.json.content[photoID].star = (album.json.content[photoID].star==0) ? 1 : 0; - view.album.content.star(photoID); + ids.forEach(function(id, index, array) { + album.json.content[id].star = (album.json.content[id].star==0) ? 1 : 0; + view.album.content.star(id); + }); - params = "setPhotoStar&photoID=" + photoID; + params = "setPhotoStar&ids=" + ids; lychee.api(params, function(data) { if (data!==true) lychee.error(null, params, data); diff --git a/php/api.php b/php/api.php index eee65f7..88cf456 100755 --- a/php/api.php +++ b/php/api.php @@ -114,16 +114,16 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { echo deletePhoto($_POST['photoID']); break; - case 'setAlbum': if (isset($_POST['photoID'])&&isset($_POST['albumID'])) - echo setAlbum($_POST['photoID'], $_POST['albumID']); + case 'setAlbum': if (isset($_POST['ids'])&&isset($_POST['albumID'])) + echo setAlbum($_POST['ids'], $_POST['albumID']); break; case 'setPhotoTitle': if (isset($_POST['photoID'])&&isset($_POST['title'])) echo setPhotoTitle($_POST['photoID'], $_POST['title']); break; - case 'setPhotoStar': if (isset($_POST['photoID'])) - echo setPhotoStar($_POST['photoID']); + case 'setPhotoStar': if (isset($_POST['ids'])) + echo setPhotoStar($_POST['ids']); break; case 'setPhotoPublic': if (isset($_POST['photoID'])&&isset($_POST['url'])) diff --git a/php/modules/photo.php b/php/modules/photo.php index fa71986..799198b 100755 --- a/php/modules/photo.php +++ b/php/modules/photo.php @@ -71,30 +71,36 @@ function setPhotoPublic($photoID, $url) { } -function setPhotoStar($photoID) { +function setPhotoStar($ids) { global $database; - - $result = $database->query("SELECT star FROM lychee_photos WHERE id = '$photoID';"); - $row = $result->fetch_object(); - if ($row->star == 0) { - $star = 1; - } else { - $star = 0; + + $error = false; + $result = $database->query("SELECT id, star FROM lychee_photos WHERE id IN ($ids);"); + + while ($row = $result->fetch_object()) { + + if ($row->star==0) $star = 1; + else $star = 0; + + $star = $database->query("UPDATE lychee_photos SET star = '$star' WHERE id = '$row->id';"); + if (!$star) $error = true; + } - $result = $database->query("UPDATE lychee_photos SET star = '$star' WHERE id = '$photoID';"); + + if ($error) return false; return true; } -function setAlbum($photoID, $newAlbum) { +function setAlbum($ids, $albumID) { global $database; - $result = $database->query("UPDATE lychee_photos SET album = '$newAlbum' WHERE id = '$photoID';"); + $result = $database->query("UPDATE lychee_photos SET album = '$albumID' WHERE id IN ($ids);"); if (!$result) return false; - else return true; + return true; } @@ -106,7 +112,7 @@ function setPhotoTitle($photoID, $title) { $result = $database->query("UPDATE lychee_photos SET title = '$title' WHERE id = '$photoID';"); if (!$result) return false; - else return true; + return true; } From ec8a80cd3f0bb3c749a7a1ca7f5685aec6bf2176 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Wed, 29 Jan 2014 00:43:06 +0100 Subject: [PATCH 04/87] Delete all and Move all --- assets/js/modules/contextMenu.js | 4 +- assets/js/modules/init.js | 8 +-- assets/js/modules/lychee.js | 1 + assets/js/modules/photo.js | 92 +++++++++++++++++++------------- php/api.php | 8 +-- php/modules/album.php | 2 +- php/modules/photo.php | 41 ++++++++------ 7 files changed, 93 insertions(+), 63 deletions(-) diff --git a/assets/js/modules/contextMenu.js b/assets/js/modules/contextMenu.js index bfcc2a1..7c8d8aa 100644 --- a/assets/js/modules/contextMenu.js +++ b/assets/js/modules/contextMenu.js @@ -121,9 +121,9 @@ contextMenu = { contextMenu.fns = [ function() { photo.setStar([photoID]) }, - function() { photo.setTitle(photoID) }, + function() { photo.setTitle([photoID]) }, function() { contextMenu.move([photoID], e, "right") }, - function() { photo.delete(photoID) } + function() { photo.delete([photoID]) } ]; items = [ diff --git a/assets/js/modules/init.js b/assets/js/modules/init.js index c67fb07..88c1877 100755 --- a/assets/js/modules/init.js +++ b/assets/js/modules/init.js @@ -37,7 +37,7 @@ $(document).ready(function(){ $("#button_download").on(event_name, function() { photo.getArchive(photo.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_trash").on(event_name, function() { photo.delete([photo.getID()]) }); $("#button_info_album").on(event_name, function() { view.infobox.show() }); $("#button_info").on(event_name, function() { view.infobox.show() }); $("#button_archive").on(event_name, function() { album.getArchive(album.getID()) }); @@ -70,14 +70,14 @@ $(document).ready(function(){ .on(event_name, ".header a", function() { view.infobox.hide() }) .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_title", function() { photo.setTitle([photo.getID()]) }) .on(event_name, "#edit_description", function() { photo.setDescription(photo.getID()) }); /* Keyboard */ Mousetrap .bind('u', function() { $("#upload_files").click() }) .bind('s', function() { if (visible.photo()) $("#button_star").click() }) - .bind('command+backspace', function() { if (visible.photo()&&!visible.message()) photo.delete(photo.getID()) }) + .bind('command+backspace', function() { if (visible.photo()&&!visible.message()) photo.delete([photo.getID()]) }) .bind('left', function() { if (visible.photo()) $("#imageview a#previous").click() }) .bind('right', function() { if (visible.photo()) $("#imageview a#next").click() }) .bind('i', function() { @@ -107,7 +107,7 @@ $(document).ready(function(){ /* Header */ .on(event_name, "#title.editable", function() { - if (visible.photo()) photo.setTitle(photo.getID()); + if (visible.photo()) photo.setTitle([photo.getID()]); else album.setTitle(album.getID()); }) diff --git a/assets/js/modules/lychee.js b/assets/js/modules/lychee.js index 8c2994b..7e58b74 100644 --- a/assets/js/modules/lychee.js +++ b/assets/js/modules/lychee.js @@ -161,6 +161,7 @@ var lychee = { hash = document.location.hash.replace("#", "").split("/"); contextMenu.close(); + multiselect.close(); if (hash[0]!==undefined) albumID = hash[0]; if (hash[1]!==undefined) photoID = hash[1]; diff --git a/assets/js/modules/photo.js b/assets/js/modules/photo.js index 2d26f40..175707c 100644 --- a/assets/js/modules/photo.js +++ b/assets/js/modules/photo.js @@ -56,40 +56,47 @@ photo = { }, - delete: function(photoID) { + delete: function(ids) { var params, buttons, photoTitle; - if (!photoID) return false; + if (!ids) return false; + if (ids instanceof Array===false) ids = [ids]; - if (visible.photo()) photoTitle = photo.json.title; - else photoTitle = album.json.content[photoID].title; - if (photoTitle=="") photoTitle = "Untitled"; + if (ids.length===1) { + // Get title if only one photo is selected + if (visible.photo()) photoTitle = photo.json.title; + else photoTitle = album.json.content[ids].title; + if (photoTitle=="") photoTitle = "Untitled"; + } buttons = [ - ["Delete Photo", function() { + ["Delete", function() { + + ids.forEach(function(id, index, array) { - // Change reference for the next and previous photo - if (album.json.content[photoID].nextPhoto!==""||album.json.content[photoID].previousPhoto!=="") { - - nextPhoto = album.json.content[photoID].nextPhoto; - previousPhoto = album.json.content[photoID].previousPhoto; - - album.json.content[previousPhoto].nextPhoto = nextPhoto; - album.json.content[nextPhoto].previousPhoto = previousPhoto; - - } - - album.json.content[photoID] = null; - - view.album.content.delete(photoID); + // Change reference for the next and previous photo + if (album.json.content[id].nextPhoto!==""||album.json.content[id].previousPhoto!=="") { + + nextPhoto = album.json.content[id].nextPhoto; + previousPhoto = album.json.content[id].previousPhoto; + + album.json.content[previousPhoto].nextPhoto = nextPhoto; + album.json.content[nextPhoto].previousPhoto = previousPhoto; + + } + + album.json.content[id] = null; + view.album.content.delete(id); + + }); // Only when search is not active if (!visible.albums()) lychee.goto(album.getID()); - params = "deletePhoto&photoID=" + photoID; + params = "deletePhoto&ids=" + ids; lychee.api(params, function(data) { if (data!==true) lychee.error(null, params, data); @@ -97,51 +104,62 @@ photo = { }); }], - ["Keep Photo", function() {}] + ["Cancel", function() {}] ]; - modal.show("Delete Photo", "Are you sure you want to delete the photo '" + photoTitle + "'?
This action can't be undone!", buttons); + + if (ids.length===1) modal.show("Delete Photo", "Are you sure you want to delete the photo '" + photoTitle + "'?
This action can't be undone!", buttons); + else modal.show("Delete Photos", "Are you sure you want to delete all " + ids.length + " selected photo?
This action can't be undone!", buttons); }, - setTitle: function(photoID) { - + setTitle: function(ids) { + var oldTitle = "", newTitle, params, buttons; - if (!photoID) return false; - if (photo.json) oldTitle = photo.json.title; - else if (album.json) oldTitle = album.json.content[photoID].title; + if (!ids) return false; + if (ids instanceof Array===false) ids = [ids]; + + if (ids.length===1) { + // Get old title if only one photo is selected + if (photo.json) oldTitle = photo.json.title; + else if (album.json) oldTitle = album.json.content[ids].title; + } buttons = [ ["Set Title", function() { newTitle = $(".message input.text").val(); - if (photoID!=null&&photoID&&newTitle.length<31) { - + if (newTitle.length<31) { + if (visible.photo()) { photo.json.title = (newTitle==="") ? "Untitled" : newTitle; view.photo.title(oldTitle); } + + ids.forEach(function(id, index, array) { + album.json.content[id].title = newTitle; + view.album.content.title(id); + }); - album.json.content[photoID].title = newTitle; - view.album.content.title(photoID); - - params = "setPhotoTitle&photoID=" + photoID + "&title=" + escape(encodeURI(newTitle)); + params = "setPhotoTitle&ids=" + ids + "&title=" + escape(encodeURI(newTitle)); lychee.api(params, function(data) { if (data!==true) lychee.error(null, params, data); }); - } else if (newTitle.length>0) loadingBar.show("error", "New title to short or too long. Please try another one!"); + } else if (newTitle.length>30) loadingBar.show("error", "New title too long. Please try another one!"); }], ["Cancel", function() {}] ]; - modal.show("Set Title", "Please enter a new title for this photo: ", buttons); + + if (ids.length===1) modal.show("Set Title", "Please enter a new title for this photo: ", buttons); + else modal.show("Set Titles", "Please enter a title for all selected photos: ", buttons); }, @@ -151,6 +169,7 @@ photo = { nextPhoto, previousPhoto; + if (!ids) return false; if (visible.photo) lychee.goto(album.getID()); if (ids instanceof Array===false) ids = [ids]; @@ -185,6 +204,7 @@ photo = { var params; + if (!ids) return false; if (visible.photo()) { photo.json.star = (photo.json.star==0) ? 1 : 0; view.photo.star(); diff --git a/php/api.php b/php/api.php index 88cf456..f57a237 100755 --- a/php/api.php +++ b/php/api.php @@ -110,16 +110,16 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { echo json_encode(getPhoto($_POST['photoID'], $_POST['albumID'])); break; - case 'deletePhoto': if (isset($_POST['photoID'])) - echo deletePhoto($_POST['photoID']); + case 'deletePhoto': if (isset($_POST['ids'])) + echo deletePhoto($_POST['ids']); break; case 'setAlbum': if (isset($_POST['ids'])&&isset($_POST['albumID'])) echo setAlbum($_POST['ids'], $_POST['albumID']); break; - case 'setPhotoTitle': if (isset($_POST['photoID'])&&isset($_POST['title'])) - echo setPhotoTitle($_POST['photoID'], $_POST['title']); + case 'setPhotoTitle': if (isset($_POST['ids'])&&isset($_POST['title'])) + echo setPhotoTitle($_POST['ids'], $_POST['title']); break; case 'setPhotoStar': if (isset($_POST['ids'])) diff --git a/php/modules/album.php b/php/modules/album.php index 28868a5..294ddf8 100755 --- a/php/modules/album.php +++ b/php/modules/album.php @@ -221,7 +221,7 @@ function deleteAlbum($albumID) { $error = false; $result = $database->query("SELECT id FROM lychee_photos WHERE album = '$albumID';"); - while($row = $result->fetch_object()) { + while ($row = $result->fetch_object()) { if (!deletePhoto($row->id)) $error = true; } diff --git a/php/modules/photo.php b/php/modules/photo.php index 799198b..d78a20c 100755 --- a/php/modules/photo.php +++ b/php/modules/photo.php @@ -104,12 +104,12 @@ function setAlbum($ids, $albumID) { } -function setPhotoTitle($photoID, $title) { +function setPhotoTitle($ids, $title) { global $database; if (strlen($title)>30) return false; - $result = $database->query("UPDATE lychee_photos SET title = '$title' WHERE id = '$photoID';"); + $result = $database->query("UPDATE lychee_photos SET title = '$title' WHERE id IN ($ids);"); if (!$result) return false; return true; @@ -129,22 +129,31 @@ function setPhotoDescription($photoID, $description) { } -function deletePhoto($photoID) { +function deletePhoto($ids) { global $database; - - $result = $database->query("SELECT * FROM lychee_photos WHERE id = '$photoID';"); - if (!$result) return false; - $row = $result->fetch_object(); - $retinaUrl = explode(".", $row->thumbUrl); - $unlink1 = unlink("../uploads/big/".$row->url); - $unlink2 = unlink("../uploads/thumb/".$row->thumbUrl); - $unlink3 = unlink("../uploads/thumb/".$retinaUrl[0].'@2x.'.$retinaUrl[1]); - $result = $database->query("DELETE FROM lychee_photos WHERE id = '$photoID';"); - if (!$unlink1 || !$unlink2 || !$unlink3) return false; - if (!$result) return false; - - return true; + + $result = $database->query("SELECT * FROM lychee_photos WHERE id IN ($ids);"); + + while ($row = $result->fetch_object()) { + + // Get retina thumb url + $thumbUrl2x = explode(".", $row->thumbUrl); + $thumbUrl2x = $thumbUrl2x[0] . '@2x.' . $thumbUrl2x[1]; + + // Delete files + if (!unlink('../uploads/big/' . $row->url)) return false; + if (!unlink('../uploads/thumb/' . $row->thumbUrl)) return false; + if (!unlink('../uploads/thumb/' . $thumbUrl2x)) return false; + + // Delete db entry + $delete = $database->query("DELETE FROM lychee_photos WHERE id = $row->id;"); + if (!$delete) return false; + + } + + if (!$result) return false; + return true; } From cbb96404cd21299f29acf2c82952774e7df13f0d Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Wed, 29 Jan 2014 00:43:29 +0100 Subject: [PATCH 05/87] Improved background and z-index of multiselect --- assets/css/modules/multiselect.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/css/modules/multiselect.css b/assets/css/modules/multiselect.css index b6eb242..7acc7a3 100644 --- a/assets/css/modules/multiselect.css +++ b/assets/css/modules/multiselect.css @@ -6,7 +6,8 @@ #multiselect { position: absolute; - background-color: RGBA(0, 94, 204, .4); + background-color: RGBA(0, 94, 204, .3); border: 1px solid RGBA(0, 94, 204, 1); border-radius: 3px; + z-index: 3; } \ No newline at end of file From f3aa01dc051713f0cefb5b758cc99054a5e51fd4 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 31 Jan 2014 20:11:28 +0100 Subject: [PATCH 06/87] ids -> photoIDs --- assets/js/modules/contextMenu.js | 16 +++++----- assets/js/modules/multiselect.js | 8 ++--- assets/js/modules/photo.js | 52 ++++++++++++++++---------------- php/api.php | 16 +++++----- php/modules/photo.php | 16 +++++----- 5 files changed, 54 insertions(+), 54 deletions(-) diff --git a/assets/js/modules/contextMenu.js b/assets/js/modules/contextMenu.js index 7c8d8aa..7ca5c30 100644 --- a/assets/js/modules/contextMenu.js +++ b/assets/js/modules/contextMenu.js @@ -140,7 +140,7 @@ contextMenu = { }, - photoMulti: function(ids, e) { + photoMulti: function(photoIDs, e) { var mouse_x = e.pageX, mouse_y = e.pageY - $(document).scrollTop(), @@ -149,10 +149,10 @@ contextMenu = { multiselect.stopResize(); contextMenu.fns = [ - function() { photo.setStar(ids) }, - function() { photo.setTitle(ids) }, - function() { contextMenu.move(ids, e, "right") }, - function() { photo.delete(ids) } + function() { photo.setStar(photoIDs) }, + function() { photo.setTitle(photoIDs) }, + function() { contextMenu.move(photoIDs, e, "right") }, + function() { photo.delete(photoIDs) } ]; items = [ @@ -167,7 +167,7 @@ contextMenu = { }, - move: function(ids, e, orientation) { + move: function(photoIDs, e, orientation) { var mouse_x = e.pageX, mouse_y = e.pageY - $(document).scrollTop(), @@ -177,7 +177,7 @@ contextMenu = { if (album.getID()!=="0") { items = [ - ["Unsorted", 0, "photo.setAlbum([" + ids + "], 0)"], + ["Unsorted", 0, "photo.setAlbum([" + photoIDs + "], 0)"], ["separator", -1] ]; } @@ -188,7 +188,7 @@ contextMenu = { items = [["New Album", 0, "album.add()"]]; } else { $.each(data.content, function(index) { - if (this.id!=album.getID()) items.push([this.title, 0, "photo.setAlbum([" + ids + "], " + this.id + ")"]); + if (this.id!=album.getID()) items.push([this.title, 0, "photo.setAlbum([" + photoIDs + "], " + this.id + ")"]); }); } diff --git a/assets/js/modules/multiselect.js b/assets/js/modules/multiselect.js index d4263c3..8f9cd31 100644 --- a/assets/js/modules/multiselect.js +++ b/assets/js/modules/multiselect.js @@ -112,7 +112,7 @@ multiselect = { getSelection: function(e) { - var ids = [], + var photoIDs = [], offset, size = multiselect.getSize(); @@ -127,14 +127,14 @@ multiselect = { offset.left>=size.left&& (offset.top+206)<=(size.top+size.height)&& (offset.left+206)<=(size.left+size.width)) { - ids.push($(this).data('id')); + photoIDs.push($(this).data('id')); $(this).addClass('active'); } }); - if (ids.length!=0&&visible.album()) contextMenu.photoMulti(ids, e); - else if (ids.length!=0&&visible.albums()) contextMenu.albumMulti(ids, e); + if (photoIDs.length!=0&&visible.album()) contextMenu.photoMulti(photoIDs, e); + else if (photoIDs.length!=0&&visible.albums()) contextMenu.albumMulti(photoIDs, e); else multiselect.close(); }, diff --git a/assets/js/modules/photo.js b/assets/js/modules/photo.js index 175707c..3e0a5e9 100644 --- a/assets/js/modules/photo.js +++ b/assets/js/modules/photo.js @@ -56,26 +56,26 @@ photo = { }, - delete: function(ids) { + delete: function(photoIDs) { var params, buttons, photoTitle; - if (!ids) return false; - if (ids instanceof Array===false) ids = [ids]; + if (!photoIDs) return false; + if (photoIDs instanceof Array===false) photoIDs = [photoIDs]; - if (ids.length===1) { + if (photoIDs.length===1) { // Get title if only one photo is selected if (visible.photo()) photoTitle = photo.json.title; - else photoTitle = album.json.content[ids].title; + else photoTitle = album.json.content[photoIDs].title; if (photoTitle=="") photoTitle = "Untitled"; } buttons = [ ["Delete", function() { - ids.forEach(function(id, index, array) { + photoIDs.forEach(function(id, index, array) { // Change reference for the next and previous photo if (album.json.content[id].nextPhoto!==""||album.json.content[id].previousPhoto!=="") { @@ -96,7 +96,7 @@ photo = { // Only when search is not active if (!visible.albums()) lychee.goto(album.getID()); - params = "deletePhoto&ids=" + ids; + params = "deletePhoto&photoIDs=" + photoIDs; lychee.api(params, function(data) { if (data!==true) lychee.error(null, params, data); @@ -107,25 +107,25 @@ photo = { ["Cancel", function() {}] ]; - if (ids.length===1) modal.show("Delete Photo", "Are you sure you want to delete the photo '" + photoTitle + "'?
This action can't be undone!", buttons); - else modal.show("Delete Photos", "Are you sure you want to delete all " + ids.length + " selected photo?
This action can't be undone!", buttons); + if (photoIDs.length===1) modal.show("Delete Photo", "Are you sure you want to delete the photo '" + photoTitle + "'?
This action can't be undone!", buttons); + else modal.show("Delete Photos", "Are you sure you want to delete all " + photoIDs.length + " selected photo?
This action can't be undone!", buttons); }, - setTitle: function(ids) { + setTitle: function(photoIDs) { var oldTitle = "", newTitle, params, buttons; - if (!ids) return false; - if (ids instanceof Array===false) ids = [ids]; + if (!photoIDs) return false; + if (photoIDs instanceof Array===false) photoIDs = [photoIDs]; - if (ids.length===1) { + if (photoIDs.length===1) { // Get old title if only one photo is selected if (photo.json) oldTitle = photo.json.title; - else if (album.json) oldTitle = album.json.content[ids].title; + else if (album.json) oldTitle = album.json.content[photoIDs].title; } buttons = [ @@ -140,12 +140,12 @@ photo = { view.photo.title(oldTitle); } - ids.forEach(function(id, index, array) { + photoIDs.forEach(function(id, index, array) { album.json.content[id].title = newTitle; view.album.content.title(id); }); - params = "setPhotoTitle&ids=" + ids + "&title=" + escape(encodeURI(newTitle)); + params = "setPhotoTitle&photoIDs=" + photoIDs + "&title=" + escape(encodeURI(newTitle)); lychee.api(params, function(data) { if (data!==true) lychee.error(null, params, data); @@ -158,22 +158,22 @@ photo = { ["Cancel", function() {}] ]; - if (ids.length===1) modal.show("Set Title", "Please enter a new title for this photo: ", buttons); + if (photoIDs.length===1) modal.show("Set Title", "Please enter a new title for this photo: ", buttons); else modal.show("Set Titles", "Please enter a title for all selected photos: ", buttons); }, - setAlbum: function(ids, albumID) { + setAlbum: function(photoIDs, albumID) { var params, nextPhoto, previousPhoto; - if (!ids) return false; + if (!photoIDs) return false; if (visible.photo) lychee.goto(album.getID()); - if (ids instanceof Array===false) ids = [ids]; + if (photoIDs instanceof Array===false) photoIDs = [photoIDs]; - ids.forEach(function(id, index, array) { + photoIDs.forEach(function(id, index, array) { // Change reference for the next and previous photo if (album.json.content[id].nextPhoto!==""||album.json.content[id].previousPhoto!=="") { @@ -191,7 +191,7 @@ photo = { }); - params = "setAlbum&ids=" + ids + "&albumID=" + albumID; + params = "setAlbum&photoIDs=" + photoIDs + "&albumID=" + albumID; lychee.api(params, function(data) { if (data!==true) lychee.error(null, params, data); @@ -200,22 +200,22 @@ photo = { }, - setStar: function(ids) { + setStar: function(photoIDs) { var params; - if (!ids) return false; + if (!photoIDs) return false; if (visible.photo()) { photo.json.star = (photo.json.star==0) ? 1 : 0; view.photo.star(); } - ids.forEach(function(id, index, array) { + photoIDs.forEach(function(id, index, array) { album.json.content[id].star = (album.json.content[id].star==0) ? 1 : 0; view.album.content.star(id); }); - params = "setPhotoStar&ids=" + ids; + params = "setPhotoStar&photoIDs=" + photoIDs; lychee.api(params, function(data) { if (data!==true) lychee.error(null, params, data); diff --git a/php/api.php b/php/api.php index f57a237..cff6b6f 100755 --- a/php/api.php +++ b/php/api.php @@ -110,20 +110,20 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { echo json_encode(getPhoto($_POST['photoID'], $_POST['albumID'])); break; - case 'deletePhoto': if (isset($_POST['ids'])) - echo deletePhoto($_POST['ids']); + case 'deletePhoto': if (isset($_POST['photoIDs'])) + echo deletePhoto($_POST['photoIDs']); break; - case 'setAlbum': if (isset($_POST['ids'])&&isset($_POST['albumID'])) - echo setAlbum($_POST['ids'], $_POST['albumID']); + case 'setAlbum': if (isset($_POST['photoIDs'])&&isset($_POST['albumID'])) + echo setAlbum($_POST['photoIDs'], $_POST['albumID']); break; - case 'setPhotoTitle': if (isset($_POST['ids'])&&isset($_POST['title'])) - echo setPhotoTitle($_POST['ids'], $_POST['title']); + case 'setPhotoTitle': if (isset($_POST['photoIDs'])&&isset($_POST['title'])) + echo setPhotoTitle($_POST['photoIDs'], $_POST['title']); break; - case 'setPhotoStar': if (isset($_POST['ids'])) - echo setPhotoStar($_POST['ids']); + case 'setPhotoStar': if (isset($_POST['photoIDs'])) + echo setPhotoStar($_POST['photoIDs']); break; case 'setPhotoPublic': if (isset($_POST['photoID'])&&isset($_POST['url'])) diff --git a/php/modules/photo.php b/php/modules/photo.php index d78a20c..40f4d2a 100755 --- a/php/modules/photo.php +++ b/php/modules/photo.php @@ -71,12 +71,12 @@ function setPhotoPublic($photoID, $url) { } -function setPhotoStar($ids) { +function setPhotoStar($photoIDs) { global $database; $error = false; - $result = $database->query("SELECT id, star FROM lychee_photos WHERE id IN ($ids);"); + $result = $database->query("SELECT id, star FROM lychee_photos WHERE id IN ($photoIDs);"); while ($row = $result->fetch_object()) { @@ -93,23 +93,23 @@ function setPhotoStar($ids) { } -function setAlbum($ids, $albumID) { +function setAlbum($photoIDs, $albumID) { global $database; - $result = $database->query("UPDATE lychee_photos SET album = '$albumID' WHERE id IN ($ids);"); + $result = $database->query("UPDATE lychee_photos SET album = '$albumID' WHERE id IN ($photoIDs);"); if (!$result) return false; return true; } -function setPhotoTitle($ids, $title) { +function setPhotoTitle($photoIDs, $title) { global $database; if (strlen($title)>30) return false; - $result = $database->query("UPDATE lychee_photos SET title = '$title' WHERE id IN ($ids);"); + $result = $database->query("UPDATE lychee_photos SET title = '$title' WHERE id IN ($photoIDs);"); if (!$result) return false; return true; @@ -129,11 +129,11 @@ function setPhotoDescription($photoID, $description) { } -function deletePhoto($ids) { +function deletePhoto($photoIDs) { global $database; - $result = $database->query("SELECT * FROM lychee_photos WHERE id IN ($ids);"); + $result = $database->query("SELECT * FROM lychee_photos WHERE id IN ($photoIDs);"); while ($row = $result->fetch_object()) { From b4b50be73260b4265720ce9dd280d7a19da582f8 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 31 Jan 2014 21:22:25 +0100 Subject: [PATCH 07/87] Delete all and rename all albums --- assets/js/modules/album.js | 78 ++++++++++++++++++++++---------- assets/js/modules/contextMenu.js | 22 +++++++++ assets/js/modules/multiselect.js | 21 ++++++--- assets/js/modules/photo.js | 57 ++++++++++++++--------- assets/js/modules/view.js | 4 +- php/api.php | 8 ++-- php/modules/album.php | 54 +++++++++++----------- 7 files changed, 157 insertions(+), 87 deletions(-) diff --git a/assets/js/modules/album.js b/assets/js/modules/album.js index 738fe20..4e41375 100644 --- a/assets/js/modules/album.js +++ b/assets/js/modules/album.js @@ -121,21 +121,28 @@ album = { }, - delete: function(albumID) { + delete: function(albumIDs) { var params, buttons, albumTitle; + + if (!albumIDs) return false; + if (albumIDs instanceof Array===false) albumIDs = [albumIDs]; buttons = [ - ["Delete Album and Photos", function() { + ["", function() { - params = "deleteAlbum&albumID=" + albumID; + params = "deleteAlbum&albumIDs=" + albumIDs; lychee.api(params, function(data) { if (visible.albums()) { - albums.json.num--; - view.albums.content.delete(albumID); + + albumIDs.forEach(function(id, index, array) { + albums.json.num--; + view.albums.content.delete(id); + }); + } else lychee.goto(""); if (data!==true) lychee.error(null, params, data); @@ -143,69 +150,90 @@ album = { }); }], - ["Keep Album", function() {}] + ["", function() {}] ]; - if (albumID==="0") { + if (albumIDs==="0") { buttons[0][0] = "Clear Unsorted"; + buttons[1][0] = "Keep Unsorted"; + modal.show("Clear Unsorted", "Are you sure you want to delete all photos from 'Unsorted'?
This action can't be undone!", buttons) - } else { - + } else if (albumIDs.length===1) { + + buttons[0][0] = "Delete Album and Photos"; + buttons[1][0] = "Keep Album"; + + // Get title if (album.json) albumTitle = album.json.title; - else if (albums.json) albumTitle = albums.json.content[albumID].title; + else if (albums.json) albumTitle = albums.json.content[albumIDs].title; + modal.show("Delete Album", "Are you sure you want to delete the album '" + albumTitle + "' and all of the photos it contains? This action can't be undone!", buttons); + } else { + + buttons[0][0] = "Delete Albums and Photos"; + buttons[1][0] = "Keep Albums"; + + modal.show("Delete Albums", "Are you sure you want to delete all " + albumIDs.length + " selected albums and all of the photos they contain? This action can't be undone!", buttons); + } }, - setTitle: function(albumID) { + setTitle: function(albumIDs) { var oldTitle = "", newTitle, params, buttons; - if (!albumID) return false; - if (album.json) oldTitle = album.json.title; - else if (albums.json) oldTitle = albums.json.content[albumID].title; + if (!albumIDs) return false; + if (albumIDs instanceof Array===false) albumIDs = [albumIDs]; + + if (albumIDs.length===1) { + // Get old title if only one album is selected + if (album.json) oldTitle = album.json.title; + else if (albums.json) oldTitle = albums.json.content[albumIDs].title; + } buttons = [ ["Set Title", function() { - newTitle = $(".message input.text").val(); + newTitle = ($(".message input.text").val()==="") ? "Untitled" : $(".message input.text").val(); - if (newTitle==="") newTitle = "Untitled"; - - if (albumID!==""&&albumID!=null&&albumID&&newTitle.length<31) { + if (newTitle.length<31) { if (visible.album()) { album.json.title = newTitle; - view.album.title(oldTitle); + view.album.title(); } else if (visible.albums()) { - - albums.json.content[albumID].title = newTitle; - view.albums.content.title(albumID); + + albumIDs.forEach(function(id, index, array) { + albums.json.content[id].title = newTitle; + view.albums.content.title(id); + }); } - params = "setAlbumTitle&albumID=" + albumID + "&title=" + escape(encodeURI(newTitle)); + params = "setAlbumTitle&albumIDs=" + albumIDs + "&title=" + escape(encodeURI(newTitle)); lychee.api(params, function(data) { if (data!==true) lychee.error(null, params, data); }); - } else if (newTitle.length>0) loadingBar.show("error", "New title too short or too long. Please try again!"); + } else if (newTitle.length>30) loadingBar.show("error", "New title too long. Please try another one!"); }], ["Cancel", function() {}] ]; - modal.show("Set Title", "Please enter a new title for this album: ", buttons); + + if (albumIDs.length===1) modal.show("Set Title", "Please enter a new title for this album: ", buttons); + else modal.show("Set Titles", "Please enter a title for all " + albumIDs.length + " selected album: ", buttons); }, diff --git a/assets/js/modules/contextMenu.js b/assets/js/modules/contextMenu.js index 7ca5c30..443eeb8 100644 --- a/assets/js/modules/contextMenu.js +++ b/assets/js/modules/contextMenu.js @@ -112,6 +112,28 @@ contextMenu = { $(".album[data-id='" + albumID + "']").addClass("active"); }, + + albumMulti: function(albumIDs, e) { + + var mouse_x = e.pageX, + mouse_y = e.pageY - $(document).scrollTop(), + items; + + multiselect.stopResize(); + + contextMenu.fns = [ + function() { album.setTitle(albumIDs) }, + function() { album.delete(albumIDs) }, + ]; + + items = [ + [" Rename All", 0], + [" Delete All", 1] + ]; + + contextMenu.show(items, mouse_x, mouse_y, "right"); + + }, photo: function(photoID, e) { diff --git a/assets/js/modules/multiselect.js b/assets/js/modules/multiselect.js index 8f9cd31..d589249 100644 --- a/assets/js/modules/multiselect.js +++ b/assets/js/modules/multiselect.js @@ -112,7 +112,8 @@ multiselect = { getSelection: function(e) { - var photoIDs = [], + var id, + ids = [], offset, size = multiselect.getSize(); @@ -127,14 +128,22 @@ multiselect = { offset.left>=size.left&& (offset.top+206)<=(size.top+size.height)&& (offset.left+206)<=(size.left+size.width)) { - photoIDs.push($(this).data('id')); - $(this).addClass('active'); + + id = $(this).data('id'); + + if (id!=="0"&&id!==0&&id!=="f"&&id!=="s"&&id!==null&id!==undefined) { + + ids.push(id); + $(this).addClass('active'); + + } + } }); - - if (photoIDs.length!=0&&visible.album()) contextMenu.photoMulti(photoIDs, e); - else if (photoIDs.length!=0&&visible.albums()) contextMenu.albumMulti(photoIDs, e); + + if (ids.length!=0&&visible.album()) contextMenu.photoMulti(ids, e); + else if (ids.length!=0&&visible.albums()) contextMenu.albumMulti(ids, e); else multiselect.close(); }, diff --git a/assets/js/modules/photo.js b/assets/js/modules/photo.js index 3e0a5e9..2bf4fbd 100644 --- a/assets/js/modules/photo.js +++ b/assets/js/modules/photo.js @@ -73,24 +73,24 @@ photo = { } buttons = [ - ["Delete", function() { - + ["", function() { + photoIDs.forEach(function(id, index, array) { // Change reference for the next and previous photo if (album.json.content[id].nextPhoto!==""||album.json.content[id].previousPhoto!=="") { - + nextPhoto = album.json.content[id].nextPhoto; previousPhoto = album.json.content[id].previousPhoto; - + album.json.content[previousPhoto].nextPhoto = nextPhoto; album.json.content[nextPhoto].previousPhoto = previousPhoto; - + } - + album.json.content[id] = null; view.album.content.delete(id); - + }); // Only when search is not active @@ -104,16 +104,29 @@ photo = { }); }], - ["Cancel", function() {}] + ["", function() {}] ]; - - if (photoIDs.length===1) modal.show("Delete Photo", "Are you sure you want to delete the photo '" + photoTitle + "'?
This action can't be undone!", buttons); - else modal.show("Delete Photos", "Are you sure you want to delete all " + photoIDs.length + " selected photo?
This action can't be undone!", buttons); + + if (photoIDs.length===1) { + + buttons[0][0] = "Delete Photo"; + buttons[1][0] = "Keep Photo"; + + modal.show("Delete Photo", "Are you sure you want to delete the photo '" + photoTitle + "'?
This action can't be undone!", buttons); + + } else { + + buttons[0][0] = "Delete Photos"; + buttons[1][0] = "Keep Photos"; + + modal.show("Delete Photos", "Are you sure you want to delete all " + photoIDs.length + " selected photo?
This action can't be undone!", buttons); + + } }, setTitle: function(photoIDs) { - + var oldTitle = "", newTitle, params, @@ -121,7 +134,7 @@ photo = { if (!photoIDs) return false; if (photoIDs instanceof Array===false) photoIDs = [photoIDs]; - + if (photoIDs.length===1) { // Get old title if only one photo is selected if (photo.json) oldTitle = photo.json.title; @@ -134,12 +147,12 @@ photo = { newTitle = $(".message input.text").val(); if (newTitle.length<31) { - + if (visible.photo()) { photo.json.title = (newTitle==="") ? "Untitled" : newTitle; - view.photo.title(oldTitle); + view.photo.title(); } - + photoIDs.forEach(function(id, index, array) { album.json.content[id].title = newTitle; view.album.content.title(id); @@ -157,9 +170,9 @@ photo = { }], ["Cancel", function() {}] ]; - + if (photoIDs.length===1) modal.show("Set Title", "Please enter a new title for this photo: ", buttons); - else modal.show("Set Titles", "Please enter a title for all selected photos: ", buttons); + else modal.show("Set Titles", "Please enter a title for all " + photoIDs.length + " selected photos: ", buttons); }, @@ -168,11 +181,11 @@ photo = { var params, nextPhoto, previousPhoto; - + if (!photoIDs) return false; if (visible.photo) lychee.goto(album.getID()); if (photoIDs instanceof Array===false) photoIDs = [photoIDs]; - + photoIDs.forEach(function(id, index, array) { // Change reference for the next and previous photo @@ -185,10 +198,10 @@ photo = { album.json.content[nextPhoto].previousPhoto = previousPhoto; } - + album.json.content[id] = null; view.album.content.delete(id); - + }); params = "setAlbum&photoIDs=" + photoIDs + "&albumID=" + albumID; diff --git a/assets/js/modules/view.js b/assets/js/modules/view.js index 1175abc..4febc2d 100644 --- a/assets/js/modules/view.js +++ b/assets/js/modules/view.js @@ -214,7 +214,7 @@ view = { }, - title: function(oldTitle) { + title: function() { if ((visible.album()||!album.json.init)&&!visible.photo()) { @@ -404,7 +404,7 @@ view = { }, - title: function(oldTitle) { + title: function() { if (photo.json.init) $("#infobox .attr_name").html(photo.json.title + " " + build.editIcon("edit_title")); lychee.setTitle(photo.json.title, true); diff --git a/php/api.php b/php/api.php index cff6b6f..7097c2f 100755 --- a/php/api.php +++ b/php/api.php @@ -83,8 +83,8 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { echo addAlbum($_POST['title']); break; - case 'setAlbumTitle': if (isset($_POST['albumID'])&&isset($_POST['title'])) - echo setAlbumTitle($_POST['albumID'], $_POST['title']); + case 'setAlbumTitle': if (isset($_POST['albumIDs'])&&isset($_POST['title'])) + echo setAlbumTitle($_POST['albumIDs'], $_POST['title']); break; case 'setAlbumDescription': if (isset($_POST['albumID'])&&isset($_POST['description'])) @@ -100,8 +100,8 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { echo setAlbumPassword($_POST['albumID'], $_POST['password']); break; - case 'deleteAlbum': if (isset($_POST['albumID'])) - echo deleteAlbum($_POST['albumID']); + case 'deleteAlbum': if (isset($_POST['albumIDs'])) + echo deleteAlbum($_POST['albumIDs']); break; // Photo Functions diff --git a/php/modules/album.php b/php/modules/album.php index 294ddf8..dcae268 100755 --- a/php/modules/album.php +++ b/php/modules/album.php @@ -189,14 +189,14 @@ function getAlbum($albumID) { } -function setAlbumTitle($albumID, $title) { +function setAlbumTitle($albumIDs, $title) { global $database; if (strlen($title)<1||strlen($title)>30) return false; - $result = $database->query("UPDATE lychee_albums SET title = '$title' WHERE id = '$albumID';"); + $result = $database->query("UPDATE lychee_albums SET title = '$title' WHERE id IN ($albumIDs);"); + if (!$result) return false; - return true; } @@ -204,34 +204,32 @@ function setAlbumTitle($albumID, $title) { function setAlbumDescription($albumID, $description) { global $database; - + $description = htmlentities($description); - if (strlen($description)>800) return false; - $result = $database->query("UPDATE lychee_albums SET description = '$description' WHERE id = '$albumID';"); - - if (!$result) return false; - return true; + if (strlen($description)>800) return false; + $result = $database->query("UPDATE lychee_albums SET description = '$description' WHERE id = '$albumID';"); + + if (!$result) return false; + return true; } -function deleteAlbum($albumID) { +function deleteAlbum($albumIDs) { global $database; - + $error = false; - - $result = $database->query("SELECT id FROM lychee_photos WHERE album = '$albumID';"); - while ($row = $result->fetch_object()) { - if (!deletePhoto($row->id)) $error = true; - } - - if ($albumID!=0) { - $result = $database->query("DELETE FROM lychee_albums WHERE id = '$albumID';"); - if (!$result) return false; - } - - if ($error) return false; - return true; + $result = $database->query("SELECT id FROM lychee_photos WHERE album IN ($albumIDs);"); + + // Delete photos + while ($row = $result->fetch_object()) + if (!deletePhoto($row->id)) $error = true; + + // Delete album + $result = $database->query("DELETE FROM lychee_albums WHERE id IN ($albumIDs);"); + + if ($error||!$result) return false; + return true; } @@ -308,7 +306,7 @@ function setAlbumPublic($albumID, $password) { } if (strlen($password)>0) return setAlbumPassword($albumID, $password); - else return true; + return true; } @@ -329,10 +327,10 @@ function checkAlbumPassword($albumID, $password) { $result = $database->query("SELECT password FROM lychee_albums WHERE id = '$albumID';"); $row = $result->fetch_object(); + if ($row->password=="") return true; - else if ($row->password==$password) return true; - else return false; + return false; } @@ -344,7 +342,7 @@ function isAlbumPublic($albumID) { $row = $result->fetch_object(); if ($row->public==1) return true; - else return false; + return false; } From 3ad59279b39add68761ebaa2f9c4fe047fb1e7f3 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 31 Jan 2014 22:26:51 +0100 Subject: [PATCH 08/87] Enable multiselect for the whole screen --- assets/css/modules/content.css | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/css/modules/content.css b/assets/css/modules/content.css index e886839..0d3d148 100644 --- a/assets/css/modules/content.css +++ b/assets/css/modules/content.css @@ -26,6 +26,7 @@ position: absolute; padding: 50px 0px 33px 0px; width: 100%; + min-height: calc(100% - 90px); -webkit-overflow-scrolling: touch; } From 6f09515c20ece82798a366dafab5e62f4a0fe96d Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 31 Jan 2014 22:27:58 +0100 Subject: [PATCH 09/87] ContextMenu should never leave the screen again --- assets/js/modules/contextMenu.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/assets/js/modules/contextMenu.js b/assets/js/modules/contextMenu.js index 443eeb8..3a28927 100644 --- a/assets/js/modules/contextMenu.js +++ b/assets/js/modules/contextMenu.js @@ -21,11 +21,21 @@ contextMenu = { if ((mouse_x+$(".contextmenu").outerWidth(true))>$("html").width()) orientation = "left"; if ((mouse_y+$(".contextmenu").outerHeight(true))>$("html").height()) mouse_y -= (mouse_y+$(".contextmenu").outerHeight(true)-$("html").height()) + if (mouse_x>$(document).width()) mouse_x = $(document).width(); + if (mouse_x<0) mouse_x = 0; + if (mouse_y>$(document).height()) mouse_y = $(document).height(); + if (mouse_y<0) mouse_y = 0; + if (orientation==="left") mouse_x -= $(".contextmenu").outerWidth(true); - if (!mouse_x||!mouse_y) { - mouse_x = "10px"; - mouse_y = "10px"; + if (mouse_x===null|| + mouse_x===undefined|| + mouse_x===NaN|| + mouse_y===null|| + mouse_y===undefined|| + mouse_y===NaN) { + mouse_x = "10px"; + mouse_y = "10px"; } $(".contextmenu").css({ @@ -95,7 +105,7 @@ contextMenu = { mouse_y = e.pageY - $(document).scrollTop(), items; - if (albumID==="0"||albumID==="f"||albumID==="s") return false; + if (albumID==="0"||albumID==="f"||albumID==="s") return false; contextMenu.fns = [ function() { album.setTitle(albumID) }, From 60affcdb64a23924dceffd42d0e4e9a57a239ef1 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 31 Jan 2014 22:28:16 +0100 Subject: [PATCH 10/87] Disable multiselect on mobile browsers --- assets/js/modules/multiselect.js | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/js/modules/multiselect.js b/assets/js/modules/multiselect.js index d589249..30bb292 100644 --- a/assets/js/modules/multiselect.js +++ b/assets/js/modules/multiselect.js @@ -18,6 +18,7 @@ multiselect = { show: function(e) { + if (mobileBrowser()) return false; if ($('.album:hover, .photo:hover').length!=0) return false; if (visible.multiselect()) $('#multiselect').remove(); From cba9bd2a7dc5fcb7ade34953ffb5ec915eefec60 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 31 Jan 2014 22:29:45 +0100 Subject: [PATCH 11/87] Validate parameters --- php/api.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/php/api.php b/php/api.php index 7097c2f..0a1c3f4 100755 --- a/php/api.php +++ b/php/api.php @@ -54,13 +54,17 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { // Get Settings $settings = getSettings(); - - // Security - if (isset($_POST['albumID'])&&($_POST['albumID']==''||$_POST['albumID']<0||$_POST['albumID']>10000)) exit('Error: Wrong parameter type for albumID!'); - if (isset($_POST['photoID'])&&$_POST['photoID']=='') exit('Error: Wrong parameter type for photoID!'); + + // Escape foreach(array_keys($_POST) as $key) $_POST[$key] = mysqli_real_escape_string($database, urldecode($_POST[$key])); foreach(array_keys($_GET) as $key) $_GET[$key] = mysqli_real_escape_string($database, urldecode($_GET[$key])); + // Validate parameters + if (isset($_POST['albumIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['albumIDs'])!==1) exit('Error: Wrong parameter type for albumIDs!'); + if (isset($_POST['photoIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['photoIDs'])!==1) exit('Error: Wrong parameter type for photoIDs!'); + if (isset($_POST['albumID'])&&preg_match('/^[0-9sf]{1,}$/', $_POST['albumID'])!==1) exit('Error: Wrong parameter type for albumID!'); + if (isset($_POST['photoID'])&&preg_match('/^[0-9]{14}$/', $_POST['photoID'])!==1) exit('Error: Wrong parameter type for photoID!'); + if (isset($_SESSION['login'])&&$_SESSION['login']==true) { /** From 38ae4662ff7fd3a660054544f0f9d499c89c4336 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 31 Jan 2014 23:55:16 +0100 Subject: [PATCH 12/87] Import filename and upload improvements --- docs/md/Settings.md | 8 +++++++- php/modules/db.php | 9 +++++---- php/modules/misc.php | 15 +++++++++------ php/modules/upload.php | 40 +++++++++++++++++++++++----------------- 4 files changed, 44 insertions(+), 28 deletions(-) diff --git a/docs/md/Settings.md b/docs/md/Settings.md index de49d2d..381dfba 100644 --- a/docs/md/Settings.md +++ b/docs/md/Settings.md @@ -38,4 +38,10 @@ If `1`, Lychee will check if you are using the latest version. The notice will b sorting = ORDER BY [row] [ASC|DESC] -A typical part of an MySQL statement. This string will be appended to mostly every MySQL query. \ No newline at end of file +A typical part of an MySQL statement. This string will be appended to mostly every MySQL query. + +#### Import Filename + + importFilename = [0|1] + +If `1`, Lychee will import the filename of the upload file. \ No newline at end of file diff --git a/php/modules/db.php b/php/modules/db.php index 439ecf3..d4ecce6 100755 --- a/php/modules/db.php +++ b/php/modules/db.php @@ -93,7 +93,7 @@ function createDatabase($dbName, $database) { function createTables($database) { - if (!$database->query("SELECT * FROM lychee_settings;")) { + if (!$database->query("SELECT * FROM lychee_settings LIMIT 1;")) { $query = " @@ -114,7 +114,8 @@ function createTables($database) { ('password',''), ('thumbQuality','90'), ('checkForUpdates','1'), - ('sorting','ORDER BY id DESC'); + ('sorting','ORDER BY id DESC'), + ('importFilename','1'); "; @@ -122,7 +123,7 @@ function createTables($database) { } - if (!$database->query("SELECT * FROM lychee_albums;")) { + if (!$database->query("SELECT * FROM lychee_albums LIMIT 1;")) { $query = " @@ -142,7 +143,7 @@ function createTables($database) { } - if (!$database->query("SELECT * FROM lychee_photos;")) { + if (!$database->query("SELECT * FROM lychee_photos LIMIT 1;")) { $query = " diff --git a/php/modules/misc.php b/php/modules/misc.php index 62852ba..a8b6dd5 100755 --- a/php/modules/misc.php +++ b/php/modules/misc.php @@ -79,14 +79,17 @@ function update() { global $database; - if(!$database->query("SELECT `public` FROM `lychee_albums`;")) $database->query("ALTER TABLE `lychee_albums` ADD `public` TINYINT( 1 ) NOT NULL DEFAULT '0'"); - if(!$database->query("SELECT `password` FROM `lychee_albums`;")) $database->query("ALTER TABLE `lychee_albums` ADD `password` VARCHAR( 100 ) NULL DEFAULT ''"); - if(!$database->query("SELECT `description` FROM `lychee_albums`;")) $database->query("ALTER TABLE `lychee_albums` ADD `description` VARCHAR( 1000 ) NULL DEFAULT ''"); - if($database->query("SELECT `password` FROM `lychee_albums`;")) $database->query("ALTER TABLE `lychee_albums` CHANGE `password` `password` VARCHAR( 100 ) NULL DEFAULT ''"); + if(!$database->query("SELECT `public` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `public` TINYINT( 1 ) NOT NULL DEFAULT '0'"); + if(!$database->query("SELECT `password` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `password` VARCHAR( 100 ) NULL DEFAULT ''"); + if(!$database->query("SELECT `description` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `description` VARCHAR( 1000 ) NULL DEFAULT ''"); + 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`;")) $database->query("ALTER TABLE `lychee_photos` CHANGE `description` `description` VARCHAR( 1000 ) NULL DEFAULT ''"); - if($database->query("SELECT `shortlink` FROM `lychee_photos`;")) $database->query("ALTER TABLE `lychee_photos` DROP `shortlink`"); + 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`"); $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;"); + if ($result->fetch_object()!==true) $database->query("INSERT INTO `lychee_settings` (`key`, `value`) VALUES ('importFilename', '1')"); return true; diff --git a/php/modules/upload.php b/php/modules/upload.php index 4b97430..14493c4 100755 --- a/php/modules/upload.php +++ b/php/modules/upload.php @@ -11,7 +11,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); function upload($files, $albumID) { - global $database; + global $database, $settings; switch($albumID) { // s for public (share) @@ -32,35 +32,41 @@ function upload($files, $albumID) { } foreach ($files as $file) { - + + if ($file['type']!=='image/jpeg'&& + $file['type']!=='image/png'&& + $file['type']!=='image/gif') + return false; + $id = str_replace('.', '', microtime(true)); while(strlen($id)<14) $id .= 0; - - $tmp_name = $file["tmp_name"]; - - $type = getimagesize($tmp_name); - if (($type[2]!=1)&&($type[2]!=2)&&($type[2]!=3)) return false; - $data = array_reverse(explode('.', $file["name"])); - $data = $data[0]; - - $photo_name = md5($id) . ".$data"; + + $tmp_name = $file['tmp_name']; + $extension = array_reverse(explode('.', $file['name'])); + $extension = $extension[0]; + $photo_name = md5($id) . ".$extension"; // Import if not uploaded via web if (!is_uploaded_file($tmp_name)) { - if (copy($tmp_name, "../uploads/big/" . $photo_name)) { + if (copy($tmp_name, '../uploads/big/' . $photo_name)) { unlink($tmp_name); $import_name = $tmp_name; } } else { - move_uploaded_file($tmp_name, "../uploads/big/" . $photo_name); - $import_name = ""; + move_uploaded_file($tmp_name, '../uploads/big/' . $photo_name); + $import_name = ''; } // Read infos $info = getInfo($photo_name); + // Use title of file if IPTC title missing + if ($info['title']===''&& + $settings['importFilename']==='1') + $info['title'] = mysqli_real_escape_string($database, substr(str_replace(".$extension", '', $file['name']), 0, 30)); + // Set orientation based on EXIF data - if (isset($info['orientation'])&&isset($info['width'])&&isset($info['height'])) { + if ($file['type']==='image/jpeg'&&isset($info['orientation'])&&isset($info['width'])&&isset($info['height'])) { if ($info['orientation']==3||$info['orientation']==6||$info['orientation']==8) { @@ -259,8 +265,8 @@ function createThumb($filename, $width = 200, $height = 200) { $info = getimagesize($url); $photoName = explode(".", $filename); - $newUrl = "../uploads/thumb/".$photoName[0].".jpeg"; - $newUrl2x = "../uploads/thumb/".$photoName[0]."@2x.jpeg"; + $newUrl = "../uploads/thumb/$photoName[0].jpeg"; + $newUrl2x = "../uploads/thumb/$photoName[0]@2x.jpeg"; // Set position and size $thumb = imagecreatetruecolor($width, $height); From d8428de0c43ae2d11338056d37145b75ce6093a5 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 1 Feb 2014 00:08:13 +0100 Subject: [PATCH 13/87] Donate menu --- assets/js/modules/contextMenu.js | 4 +++- assets/js/modules/lychee.js | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/assets/js/modules/contextMenu.js b/assets/js/modules/contextMenu.js index 3a28927..dbaa03f 100644 --- a/assets/js/modules/contextMenu.js +++ b/assets/js/modules/contextMenu.js @@ -84,6 +84,7 @@ contextMenu = { function() { settings.setLogin() }, function() { settings.setSorting() }, function() { window.open(lychee.website,"_newtab"); }, + function() { window.open(lychee.website_donate,"_newtab"); }, function() { lychee.logout() } ]; @@ -91,8 +92,9 @@ contextMenu = { [" Change Login", 0], [" Change Sorting", 1], [" About Lychee", 2], + [" Donate", 3], ["separator", -1], - [" Sign Out", 3] + [" Sign Out", 4] ]; contextMenu.show(items, mouse_x, mouse_y, "right"); diff --git a/assets/js/modules/lychee.js b/assets/js/modules/lychee.js index 6ca485a..de5508e 100644 --- a/assets/js/modules/lychee.js +++ b/assets/js/modules/lychee.js @@ -13,6 +13,7 @@ var lychee = { update_path: "http://lychee.electerious.com/version/index.php", updateURL: "https://github.com/electerious/Lychee", website: "http://lychee.electerious.com", + website_donate: "http://lychee.electerious.com#donate", upload_path_thumb: "uploads/thumb/", upload_path_big: "uploads/big/", From 447d1298b93c2536b99134df19f56d4e9be10ca5 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 1 Feb 2014 00:09:05 +0100 Subject: [PATCH 14/87] Version push --- assets/js/modules/lychee.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/modules/lychee.js b/assets/js/modules/lychee.js index de5508e..feacb24 100644 --- a/assets/js/modules/lychee.js +++ b/assets/js/modules/lychee.js @@ -7,7 +7,7 @@ var lychee = { - version: "2.0.2", + version: "2.1", api_path: "php/api.php", update_path: "http://lychee.electerious.com/version/index.php", From c980157ecaf964d164193c9604b90c7ce2876c03 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 1 Feb 2014 20:27:25 +0100 Subject: [PATCH 15/87] Fixed wrong login or password annotation (#71) --- assets/js/modules/lychee.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/modules/lychee.js b/assets/js/modules/lychee.js index feacb24..462ab03 100644 --- a/assets/js/modules/lychee.js +++ b/assets/js/modules/lychee.js @@ -116,7 +116,7 @@ var lychee = { localStorage.setItem("username", user); window.location.reload(); } else { - $("#password").val("").addClass("error"); + $("#password").val("").addClass("error").focus(); $(".message .button.active").removeClass("pressed"); } }); From d14a3dbf8b016a731e5e3c599a8378a4ff5ff6fd Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 1 Feb 2014 21:50:36 +0100 Subject: [PATCH 16/87] Tolerance for multiselect --- assets/js/modules/multiselect.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/assets/js/modules/multiselect.js b/assets/js/modules/multiselect.js index 30bb292..57df893 100644 --- a/assets/js/modules/multiselect.js +++ b/assets/js/modules/multiselect.js @@ -113,7 +113,8 @@ multiselect = { getSelection: function(e) { - var id, + var tolerance = 150, + id, ids = [], offset, size = multiselect.getSize(); @@ -124,11 +125,11 @@ multiselect = { $('.photo, .album').each(function() { offset = $(this).offset(); - - if (offset.top>=size.top&& - offset.left>=size.left&& - (offset.top+206)<=(size.top+size.height)&& - (offset.left+206)<=(size.left+size.width)) { + + if (offset.top>=(size.top-tolerance)&& + offset.left>=(size.left-tolerance)&& + (offset.top+206)<=(size.top+size.height+tolerance)&& + (offset.left+206)<=(size.left+size.width+tolerance)) { id = $(this).data('id'); From be404366bcdf21be08b7a1bde2b6e519aea94e72 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 2 Feb 2014 15:11:46 +0100 Subject: [PATCH 17/87] Basic implementation for tags - Edit Tags - Delete Tags - Search Tags Multiselect: - Only when logged in --- assets/css/modules/infobox.css | 7 +++- assets/js/modules/build.js | 42 +++++++++++++++++----- assets/js/modules/contextMenu.js | 4 +-- assets/js/modules/init.js | 10 +++--- assets/js/modules/multiselect.js | 5 +-- assets/js/modules/photo.js | 62 ++++++++++++++++++++++++++++++++ assets/js/modules/view.js | 6 ++++ php/api.php | 11 ++++++ php/modules/album.php | 2 +- php/modules/db.php | 1 + php/modules/misc.php | 6 ++-- php/modules/tags.php | 38 ++++++++++++++++++++ 12 files changed, 172 insertions(+), 22 deletions(-) create mode 100644 php/modules/tags.php diff --git a/assets/css/modules/infobox.css b/assets/css/modules/infobox.css index 8584387..8233e89 100644 --- a/assets/css/modules/infobox.css +++ b/assets/css/modules/infobox.css @@ -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; diff --git a/assets/js/modules/build.js b/assets/js/modules/build.js index b1ef207..ffb937e 100644 --- a/assets/js/modules/build.js +++ b/assets/js/modules/build.js @@ -18,11 +18,11 @@ build = { return "
"; }, - + multiselect: function(top, left) { - + return "
"; - + }, 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 += "" + tag + ""; + + }); + + } else { + + editTagsHTML = (forView===true||lychee.publicMode) ? "" : " " + build.editIcon("edit_tags"); + html = "
No Tags" + editTagsHTML + "
"; + + } + + 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", "AbstractColorsPhotoshopSomethingLycheeTags"] 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 += ""; infobox += "

" + infos[index][0] + "

"; - infobox += ""; - infobox += "
" + infos[index][1] + "
"; - infobox += ""; + infobox += "
" + infos[index][1] + "
"; break; default: // Item diff --git a/assets/js/modules/contextMenu.js b/assets/js/modules/contextMenu.js index dbaa03f..4430420 100644 --- a/assets/js/modules/contextMenu.js +++ b/assets/js/modules/contextMenu.js @@ -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 = [ diff --git a/assets/js/modules/init.js b/assets/js/modules/init.js index 88c1877..72d2d16 100755 --- a/assets/js/modules/init.js +++ b/assets/js/modules/init.js @@ -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? ", [["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 */ diff --git a/assets/js/modules/multiselect.js b/assets/js/modules/multiselect.js index 57df893..52355d2 100644 --- a/assets/js/modules/multiselect.js +++ b/assets/js/modules/multiselect.js @@ -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); diff --git a/assets/js/modules/photo.js b/assets/js/modules/photo.js index 2bf4fbd..22a1dc0 100644 --- a/assets/js/modules/photo.js +++ b/assets/js/modules/photo.js @@ -302,7 +302,69 @@ photo = { modal.show("Set Description", "Please enter a description for this photo: ", 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: ", 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 = "", diff --git a/assets/js/modules/view.js b/assets/js/modules/view.js index 4febc2d..122ed89 100644 --- a/assets/js/modules/view.js +++ b/assets/js/modules/view.js @@ -447,6 +447,12 @@ view = { } }, + + tags: function() { + + $("#infobox #tags").html(build.tags(photo.json.tags)); + + }, photo: function() { diff --git a/php/api.php b/php/api.php index 0a1c3f4..444f79f 100755 --- a/php/api.php +++ b/php/api.php @@ -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 diff --git a/php/modules/album.php b/php/modules/album.php index dcae268..f4cff60 100755 --- a/php/modules/album.php +++ b/php/modules/album.php @@ -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; } diff --git a/php/modules/db.php b/php/modules/db.php index d4ecce6..d0ba1fd 100755 --- a/php/modules/db.php +++ b/php/modules/db.php @@ -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, diff --git a/php/modules/misc.php b/php/modules/misc.php index a8b6dd5..eb161e1 100755 --- a/php/modules/misc.php +++ b/php/modules/misc.php @@ -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;"); diff --git a/php/modules/tags.php b/php/modules/tags.php new file mode 100644 index 0000000..f0faf9f --- /dev/null +++ b/php/modules/tags.php @@ -0,0 +1,38 @@ +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; + +} \ No newline at end of file From 9cd3f050cd8fa57c1c67851bf8664927b5518a93 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 2 Feb 2014 23:22:06 +0100 Subject: [PATCH 18/87] Better parsing for tags --- assets/js/modules/photo.js | 22 +++++++++++----------- php/modules/tags.php | 10 ++++------ 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/assets/js/modules/photo.js b/assets/js/modules/photo.js index 22a1dc0..8673f38 100644 --- a/assets/js/modules/photo.js +++ b/assets/js/modules/photo.js @@ -316,16 +316,8 @@ photo = { 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!"); + if (tags.length<800) photo.setTags(photoIDs, tags) + else loadingBar.show("error", "Description too long. Please try again!"); }], ["Cancel", function() {}] @@ -341,6 +333,15 @@ photo = { if (!photoIDs) return false; if (photoIDs instanceof Array===false) photoIDs = [photoIDs]; + // Parse tags + tags = tags.replace(/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/g, ','); + tags = tags.replace(/,$|^,/g, ''); + + if (visible.photo()) { + photo.json.tags = tags; + view.photo.tags(); + } + params = "setTags&photoIDs=" + photoIDs + "&tags=" + tags; lychee.api(params, function(data) { @@ -360,7 +361,6 @@ photo = { // Save photo.json.tags = tags.toString(); - view.photo.tags(); photo.setTags([photoID], photo.json.tags); }, diff --git a/php/modules/tags.php b/php/modules/tags.php index f0faf9f..d5887ed 100644 --- a/php/modules/tags.php +++ b/php/modules/tags.php @@ -23,12 +23,10 @@ function getTags($photoID) { 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); + + // Parse tags + $tags = preg_replace('/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/', ',', $tags); + $tags = preg_replace('/,$|^,/', ',', $tags); $result = $database->query("UPDATE lychee_photos SET tags = '$tags' WHERE id IN ($photoIDs);"); From 88c8108035c9014942fc672dd184cb2b345bfd92 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 2 Feb 2014 23:55:18 +0100 Subject: [PATCH 19/87] Smaller delete button --- assets/css/modules/infobox.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/css/modules/infobox.css b/assets/css/modules/infobox.css index 8233e89..86118f8 100644 --- a/assets/css/modules/infobox.css +++ b/assets/css/modules/infobox.css @@ -161,7 +161,7 @@ padding: 0px; margin: 0px 0px -2px 0px; color: red; - font-size: 12px; + font-size: 11px; cursor: pointer; overflow: hidden; -webkit-transform: scale(0); From 62c26b9153b474635127f74774235e7cce2db21f Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 2 Feb 2014 23:56:20 +0100 Subject: [PATCH 20/87] Maxlength for inputs --- assets/js/modules/album.js | 10 +++++----- assets/js/modules/photo.js | 8 ++++---- php/modules/album.php | 6 +++--- php/modules/photo.php | 4 ++-- php/modules/tags.php | 2 ++ 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/assets/js/modules/album.js b/assets/js/modules/album.js index 4e41375..b61efc6 100644 --- a/assets/js/modules/album.js +++ b/assets/js/modules/album.js @@ -117,7 +117,7 @@ album = { }], ["Cancel", function() {}] ]; - modal.show("New Album", "Please enter a title for this album: ", buttons); + modal.show("New Album", "Please enter a title for this album: ", buttons); }, @@ -232,8 +232,8 @@ album = { ["Cancel", function() {}] ]; - if (albumIDs.length===1) modal.show("Set Title", "Please enter a new title for this album: ", buttons); - else modal.show("Set Titles", "Please enter a title for all " + albumIDs.length + " selected album: ", buttons); + if (albumIDs.length===1) modal.show("Set Title", "Please enter a new title for this album: ", buttons); + else modal.show("Set Titles", "Please enter a title for all " + albumIDs.length + " selected album: ", buttons); }, @@ -249,7 +249,7 @@ album = { description = $(".message input.text").val(); - if (description.length<800) { + if (description.length<801) { if (visible.album()) { album.json.description = description; @@ -268,7 +268,7 @@ album = { }], ["Cancel", function() {}] ]; - modal.show("Set Description", "Please enter a description for this album: ", buttons); + modal.show("Set Description", "Please enter a description for this album: ", buttons); }, diff --git a/assets/js/modules/photo.js b/assets/js/modules/photo.js index 8673f38..ab4351d 100644 --- a/assets/js/modules/photo.js +++ b/assets/js/modules/photo.js @@ -171,8 +171,8 @@ photo = { ["Cancel", function() {}] ]; - if (photoIDs.length===1) modal.show("Set Title", "Please enter a new title for this photo: ", buttons); - else modal.show("Set Titles", "Please enter a title for all " + photoIDs.length + " selected photos: ", buttons); + if (photoIDs.length===1) modal.show("Set Title", "Please enter a new title for this photo: ", buttons); + else modal.show("Set Titles", "Please enter a title for all " + photoIDs.length + " selected photos: ", buttons); }, @@ -299,7 +299,7 @@ photo = { }], ["Cancel", function() {}] ]; - modal.show("Set Description", "Please enter a description for this photo: ", buttons); + modal.show("Set Description", "Please enter a description for this photo: ", buttons); }, @@ -322,7 +322,7 @@ photo = { }], ["Cancel", function() {}] ]; - modal.show("Set Tags", "Please enter your tags for this photo. You can add multiple tags by separating them with a comma: ", buttons); + modal.show("Set Tags", "Please enter your tags for this photo. You can add multiple tags by separating them with a comma: ", buttons); }, diff --git a/php/modules/album.php b/php/modules/album.php index f4cff60..57d3240 100755 --- a/php/modules/album.php +++ b/php/modules/album.php @@ -13,7 +13,7 @@ function addAlbum($title) { global $database; - if (strlen($title)<1||strlen($title)>30) return false; + if (strlen($title)<1||strlen($title)>50) return false; $sysdate = date("d.m.Y"); $result = $database->query("INSERT INTO lychee_albums (title, sysdate) VALUES ('$title', '$sysdate');"); @@ -193,7 +193,7 @@ function setAlbumTitle($albumIDs, $title) { global $database; - if (strlen($title)<1||strlen($title)>30) return false; + if (strlen($title)<1||strlen($title)>50) return false; $result = $database->query("UPDATE lychee_albums SET title = '$title' WHERE id IN ($albumIDs);"); if (!$result) return false; @@ -206,7 +206,7 @@ function setAlbumDescription($albumID, $description) { global $database; $description = htmlentities($description); - if (strlen($description)>800) return false; + if (strlen($description)>1000) return false; $result = $database->query("UPDATE lychee_albums SET description = '$description' WHERE id = '$albumID';"); if (!$result) return false; diff --git a/php/modules/photo.php b/php/modules/photo.php index 40f4d2a..566c98b 100755 --- a/php/modules/photo.php +++ b/php/modules/photo.php @@ -108,7 +108,7 @@ function setPhotoTitle($photoIDs, $title) { global $database; - if (strlen($title)>30) return false; + if (strlen($title)>50) return false; $result = $database->query("UPDATE lychee_photos SET title = '$title' WHERE id IN ($photoIDs);"); if (!$result) return false; @@ -121,7 +121,7 @@ function setPhotoDescription($photoID, $description) { global $database; $description = htmlentities($description); - if (strlen($description)>800) return false; + if (strlen($description)>1000) return false; $result = $database->query("UPDATE lychee_photos SET description = '$description' WHERE id = '$photoID';"); if (!$result) return false; diff --git a/php/modules/tags.php b/php/modules/tags.php index d5887ed..129225e 100644 --- a/php/modules/tags.php +++ b/php/modules/tags.php @@ -27,6 +27,8 @@ function setTags($photoIDs, $tags) { // Parse tags $tags = preg_replace('/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/', ',', $tags); $tags = preg_replace('/,$|^,/', ',', $tags); + + if (strlen($tags)>1000) return false; $result = $database->query("UPDATE lychee_photos SET tags = '$tags' WHERE id IN ($photoIDs);"); From 53fac7a8c2447dd41b5bfa6a08cdb589425bfb4d Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 4 Feb 2014 21:38:01 +0100 Subject: [PATCH 21/87] Improved tag editing --- assets/js/modules/photo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/modules/photo.js b/assets/js/modules/photo.js index ab4351d..e506fe1 100644 --- a/assets/js/modules/photo.js +++ b/assets/js/modules/photo.js @@ -309,7 +309,7 @@ photo = { if (!photoIDs) return false; if (photoIDs instanceof Array===false) photoIDs = [photoIDs]; - if (visible.photo()) oldTags = photo.json.tags; + if (visible.photo()) oldTags = photo.json.tags.replace(/,/g, ', '); buttons = [ ["Set Tags", function() { From c4ba5ea64eb5bf7273f1bb80d943c71adaa36ca5 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 4 Feb 2014 21:39:17 +0100 Subject: [PATCH 22/87] Show edit icon on tags --- assets/js/modules/build.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/assets/js/modules/build.js b/assets/js/modules/build.js index ffb937e..e396823 100644 --- a/assets/js/modules/build.js +++ b/assets/js/modules/build.js @@ -244,7 +244,7 @@ build = { tags: function(tags, forView) { var html = "", - editTagsHTML; + editTagsHTML = (forView===true||lychee.publicMode) ? "" : " " + build.editIcon("edit_tags"); if (tags!=="") { @@ -255,10 +255,12 @@ build = { html += "" + tag + ""; }); + + html += editTagsHTML; } else { - editTagsHTML = (forView===true||lychee.publicMode) ? "" : " " + build.editIcon("edit_tags"); + html = "
No Tags" + editTagsHTML + "
"; } From c91b2829e68c24abaa742b2f2448d2a012f75136 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 7 Feb 2014 23:34:04 +0100 Subject: [PATCH 23/87] New data/ folder --- data/.gitignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 data/.gitignore diff --git a/data/.gitignore b/data/.gitignore new file mode 100644 index 0000000..86d0cb2 --- /dev/null +++ b/data/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file From 4fd302f3d0b68d30160011568ea802594b8882bd Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 8 Feb 2014 00:08:18 +0100 Subject: [PATCH 24/87] Config in data/ --- data/.gitignore | 0 docs/md/Installation.md | 12 ++++- php/api.php | 12 ++--- php/modules/album.php | 97 +++++++++++++++++++++-------------------- php/modules/db.php | 5 ++- php/modules/tags.php | 0 plugins/check.php | 6 +-- readme.md | 4 +- view.php | 2 +- 9 files changed, 75 insertions(+), 63 deletions(-) mode change 100644 => 100755 data/.gitignore mode change 100644 => 100755 php/modules/tags.php diff --git a/data/.gitignore b/data/.gitignore old mode 100644 new mode 100755 diff --git a/docs/md/Installation.md b/docs/md/Installation.md index 50bac52..d79ce7e 100644 --- a/docs/md/Installation.md +++ b/docs/md/Installation.md @@ -16,12 +16,20 @@ To use Lychee without restrictions, we recommend to increase the values of the f upload_max_size = 200M upload_max_filesize = 20M max_file_uploads = 100 + +### Download Lychee + +The easiest way to download Lychee is with git: + + git clone https://github.com/electerious/Lychee.git + +You can also use the [direct download](https://github.com/electerious/Lychee/archive/master.zip). ### Folder permissions -Change the permissions of `uploads/` and `php/` to 777, including all subfolders: +Change the permissions of `uploads/` and `data/` to 777, including all subfolders: - chmod -R 777 uploads/ php/ + chmod -R 777 uploads/ data/ ### Lychee installation diff --git a/php/api.php b/php/api.php index 444f79f..54b5196 100755 --- a/php/api.php +++ b/php/api.php @@ -27,7 +27,7 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { require('modules/tags.php'); require('modules/misc.php'); - if (file_exists('config.php')) require('config.php'); + if (file_exists('../data/config.php')) require('../data/config.php'); else { /** @@ -55,7 +55,7 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { // Get Settings $settings = getSettings(); - + // Escape foreach(array_keys($_POST) as $key) $_POST[$key] = mysqli_real_escape_string($database, urldecode($_POST[$key])); foreach(array_keys($_GET) as $key) $_GET[$key] = mysqli_real_escape_string($database, urldecode($_GET[$key])); @@ -64,7 +64,7 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { if (isset($_POST['albumIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['albumIDs'])!==1) exit('Error: Wrong parameter type for albumIDs!'); if (isset($_POST['photoIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['photoIDs'])!==1) exit('Error: Wrong parameter type for photoIDs!'); if (isset($_POST['albumID'])&&preg_match('/^[0-9sf]{1,}$/', $_POST['albumID'])!==1) exit('Error: Wrong parameter type for albumID!'); - if (isset($_POST['photoID'])&&preg_match('/^[0-9]{14}$/', $_POST['photoID'])!==1) exit('Error: Wrong parameter type for photoID!'); + if (isset($_POST['photoID'])&&preg_match('/^[0-9]{14}$/', $_POST['photoID'])!==1) exit('Error: Wrong parameter type for photoID!'); if (isset($_SESSION['login'])&&$_SESSION['login']==true) { @@ -158,13 +158,13 @@ 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; diff --git a/php/modules/album.php b/php/modules/album.php index 57d3240..67e3e6b 100755 --- a/php/modules/album.php +++ b/php/modules/album.php @@ -236,54 +236,55 @@ function deleteAlbum($albumIDs) { function getAlbumArchive($albumID) { global $database; - - switch($albumID) { - case 's': - $query = "SELECT * FROM lychee_photos WHERE public = '1';"; - $zipTitle = "Public"; - break; - case 'f': - $query = "SELECT * FROM lychee_photos WHERE star = '1';"; - $zipTitle = "Starred"; - break; - default: - $query = "SELECT * FROM lychee_photos WHERE album = '$albumID';"; - $zipTitle = "Unsorted"; - } - - $result = $database->query($query); - $files = array(); - $i=0; - while($row = $result->fetch_object()) { - $files[$i] = "../uploads/big/".$row->url; - $i++; - } - $result = $database->query("SELECT * FROM lychee_albums WHERE id = '$albumID';"); - $row = $result->fetch_object(); - if ($albumID!=0&&is_numeric($albumID))$zipTitle = $row->title; - $filename = "../uploads/".$zipTitle.".zip"; - - $zip = new ZipArchive(); - - if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) { - return false; - } - - foreach($files AS $zipFile) { - $newFile = explode("/",$zipFile); - $newFile = array_reverse($newFile); - $zip->addFile($zipFile, $zipTitle."/".$newFile[0]); - } - - $zip->close(); - - header("Content-Type: application/zip"); - header("Content-Disposition: attachment; filename=\"$zipTitle.zip\""); - header("Content-Length: ".filesize($filename)); - readfile($filename); - unlink($filename); - - return true; + + switch($albumID) { + case 's': + $query = "SELECT * FROM lychee_photos WHERE public = '1';"; + $zipTitle = "Public"; + break; + case 'f': + $query = "SELECT * FROM lychee_photos WHERE star = '1';"; + $zipTitle = "Starred"; + break; + default: + $query = "SELECT * FROM lychee_photos WHERE album = '$albumID';"; + $zipTitle = "Unsorted"; + } + + $zip = new ZipArchive(); + $result = $database->query($query); + $files = array(); + $i=0; + + while($row = $result->fetch_object()) { + $files[$i] = "../uploads/big/".$row->url; + $i++; + } + + $result = $database->query("SELECT * FROM lychee_albums WHERE id = '$albumID';"); + $row = $result->fetch_object(); + if ($albumID!=0&&is_numeric($albumID)) $zipTitle = $row->title; + $filename = "../data/$zipTitle.zip"; + + if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) { + return false; + } + + foreach($files AS $zipFile) { + $newFile = explode("/",$zipFile); + $newFile = array_reverse($newFile); + $zip->addFile($zipFile, $zipTitle."/".$newFile[0]); + } + + $zip->close(); + + header("Content-Type: application/zip"); + header("Content-Disposition: attachment; filename=\"$zipTitle.zip\""); + header("Content-Length: ".filesize($filename)); + readfile($filename); + unlink($filename); + + return true; } diff --git a/php/modules/db.php b/php/modules/db.php index d0ba1fd..2453996 100755 --- a/php/modules/db.php +++ b/php/modules/db.php @@ -61,6 +61,9 @@ $config = ""; - if (file_put_contents("config.php", $config)===false) return "Warning: Could not create file!"; + if (file_put_contents("../data/config.php", $config)===false) return "Warning: Could not create file!"; else { $_SESSION['login'] = true; diff --git a/php/modules/tags.php b/php/modules/tags.php old mode 100644 new mode 100755 diff --git a/plugins/check.php b/plugins/check.php index 407059d..4ba09dd 100644 --- a/plugins/check.php +++ b/plugins/check.php @@ -16,8 +16,8 @@ header('content-type: text/plain'); $error = ''; // Include -if (!file_exists('../php/config.php')) exit('Error 001: Configuration not found. Please install Lychee first.'); -require('../php/config.php'); +if (!file_exists('../data/config.php')) exit('Error 001: Configuration not found. Please install Lychee first.'); +require('../data/config.php'); require('../php/modules/settings.php'); // Database @@ -54,7 +54,7 @@ if (substr(sprintf('%o', @fileperms('../uploads/big/')), -4)!='0777') $error .= if (substr(sprintf('%o', @fileperms('../uploads/thumb/')), -4)!='0777') $error .= ('Error 501: Wrong permissions for \'uploads/thumb\' (777 required)' . PHP_EOL); if (substr(sprintf('%o', @fileperms('../uploads/import/')), -4)!='0777') $error .= ('Error 502: Wrong permissions for \'uploads/import\' (777 required)' . PHP_EOL); if (substr(sprintf('%o', @fileperms('../uploads/')), -4)!='0777') $error .= ('Error 503: Wrong permissions for \'uploads/\' (777 required)' . PHP_EOL); -if (substr(sprintf('%o', @fileperms('../php/')), -4)!='0777') $error .= ('Error 504: Wrong permissions for \'php/\' (777 required)' . PHP_EOL); +if (substr(sprintf('%o', @fileperms('../data/')), -4)!='0777') $error .= ('Error 504: Wrong permissions for \'data/\' (777 required)' . PHP_EOL); if ($error=='') echo('Lychee is ready. Lets rock!' . PHP_EOL . PHP_EOL); else echo $error; diff --git a/readme.md b/readme.md index 7746c34..20ca641 100644 --- a/readme.md +++ b/readme.md @@ -17,11 +17,11 @@ You can use Lychee right after the installation. Here are some advanced features ### Settings -Sign in and click the gear on the top left corner to change your settings. If you want to edit them manually: MySQL details are stored in `php/config.php`. Other options and settings are stored directly in the database. [Settings »](docs/md/Settings.md) +Sign in and click the gear on the top left corner to change your settings. If you want to edit them manually: MySQL details are stored in `data/config.php`. Other options and settings are stored directly in the database. [Settings »](docs/md/Settings.md) ### Update -1. Replace all files, excluding `uploads/` +1. Replace all files, excluding `uploads/` and `data/` 2. Open Lychee and enter your database details ### FTP Upload diff --git a/view.php b/view.php index fb08e01..62dbf61 100644 --- a/view.php +++ b/view.php @@ -24,7 +24,7 @@ define("LYCHEE", true); - require("php/config.php"); + require("data/config.php"); require("php/modules/db.php"); require("php/modules/misc.php"); From 6693f0aa6072b64606df2efa0a2a37b56eeb3033 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 8 Feb 2014 00:10:50 +0100 Subject: [PATCH 25/87] Removed php/config.php --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index 1645fb6..f8d8c70 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,5 @@ *.esproj -php/config.php - uploads/import/* uploads/big/* uploads/thumb/* From 652f8559988d16470ee94d34686123a6004337c6 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 8 Feb 2014 00:11:57 +0100 Subject: [PATCH 26/87] Ignore all configs --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index f8d8c70..db6c242 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ *.esproj +php/config.php +data/config.php + uploads/import/* uploads/big/* uploads/thumb/* From f671077c260b0ebc79e68196296274e4eec7569b Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 8 Feb 2014 17:28:11 +0100 Subject: [PATCH 27/87] Better function naming in db.php --- assets/js/modules/settings.js | 2 +- php/api.php | 4 +-- php/modules/db.php | 48 +++++++++++++++++++---------------- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/assets/js/modules/settings.js b/assets/js/modules/settings.js index fec2be9..52e51ad 100644 --- a/assets/js/modules/settings.js +++ b/assets/js/modules/settings.js @@ -26,7 +26,7 @@ var settings = { if (dbHost.length<1) dbHost = "localhost"; if (dbName.length<1) dbName = "lychee"; - params = "createConfig&dbName=" + escape(dbName) + "&dbUser=" + escape(dbUser) + "&dbPassword=" + escape(dbPassword) + "&dbHost=" + escape(dbHost); + params = "dbCreateConfig&dbName=" + escape(dbName) + "&dbUser=" + escape(dbUser) + "&dbPassword=" + escape(dbPassword) + "&dbHost=" + escape(dbHost); lychee.api(params, function(data) { if (data!==true) { diff --git a/php/api.php b/php/api.php index 54b5196..350deb0 100755 --- a/php/api.php +++ b/php/api.php @@ -37,8 +37,8 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { switch ($_POST['function']) { - case 'createConfig': if (isset($_POST['dbHost'])&&isset($_POST['dbUser'])&&isset($_POST['dbPassword'])&&isset($_POST['dbName'])) - echo createConfig($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName']); + case 'dbCreateConfig': if (isset($_POST['dbHost'])&&isset($_POST['dbUser'])&&isset($_POST['dbPassword'])&&isset($_POST['dbName'])) + echo dbCreateConfig($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName']); break; default: echo 'Warning: No configuration!'; diff --git a/php/modules/db.php b/php/modules/db.php index 2453996..5c99f8c 100755 --- a/php/modules/db.php +++ b/php/modules/db.php @@ -15,39 +15,33 @@ function dbConnect() { $database = new mysqli($dbHost, $dbUser, $dbPassword); - if (mysqli_connect_errno()) { - echo mysqli_connect_errno().': '.mysqli_connect_error(); - return false; - } + if ($database->connect_errno) exit('Error: ' . $database->connect_error); + + // Avoid sql injection on older MySQL versions + if ($database->server_version<50500) $database->set_charset('GBK'); if (!$database->select_db($dbName)) - if (!createDatabase($dbName, $database)) exit('Error: Could not create database!'); - if (!$database->query("SELECT * FROM lychee_photos, lychee_albums, lychee_settings LIMIT 1;")) - if (!createTables($database)) exit('Error: Could not create tables!'); - - // Avoid sql injection on older MySQL versions - if ($database->server_version<50500) $database->set_charset('GBK'); + if (!dbCreate($dbName, $database)) exit('Error: Could not create database!'); + + dbCheck($database); return $database; } -function dbClose() { - - global $database; - - if (!$database->close()) exit("Error: Closing the connection failed!"); - - return true; - +function dbCheck($database) { + + if (!$database->query("SELECT * FROM lychee_photos, lychee_albums, lychee_settings LIMIT 1;")) + if (!dbCreateTables($database)) exit('Error: Could not create tables!'); + } -function createConfig($dbHost = 'localhost', $dbUser, $dbPassword, $dbName = 'lychee') { +function dbCreateConfig($dbHost = 'localhost', $dbUser, $dbPassword, $dbName = 'lychee') { $dbPassword = urldecode($dbPassword); $database = new mysqli($dbHost, $dbUser, $dbPassword); - if (mysqli_connect_errno()||$dbUser=="") return "Warning: Connection failed!"; + if ($database->connect_errno) return "Warning: Connection failed!"; else { $config = "query("CREATE DATABASE IF NOT EXISTS $dbName;"); $database->select_db($dbName); @@ -94,7 +88,7 @@ function createDatabase($dbName, $database) { } -function createTables($database) { +function dbCreateTables($database) { if (!$database->query("SELECT * FROM lychee_settings LIMIT 1;")) { @@ -188,4 +182,14 @@ function createTables($database) { } +function dbClose() { + + global $database; + + if (!$database->close()) exit("Error: Closing the connection failed!"); + + return true; + +} + ?> From 96bd4a5e90bcaab188ae56a8a9e553ead81dbdb2 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 8 Feb 2014 17:52:38 +0100 Subject: [PATCH 28/87] Typewriter apostrophe --- php/api.php | 1 - php/modules/db.php | 23 ++++++++--------------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/php/api.php b/php/api.php index 350deb0..542e747 100755 --- a/php/api.php +++ b/php/api.php @@ -2,7 +2,6 @@ /** * @name API - * @author Philipp Maurer * @author Tobias Reich * @copyright 2014 by Philipp Maurer, Tobias Reich */ diff --git a/php/modules/db.php b/php/modules/db.php index 5c99f8c..ddfd78a 100755 --- a/php/modules/db.php +++ b/php/modules/db.php @@ -23,32 +23,25 @@ function dbConnect() { if (!$database->select_db($dbName)) if (!dbCreate($dbName, $database)) exit('Error: Could not create database!'); - dbCheck($database); + if (!$database->query('SELECT * FROM lychee_photos, lychee_albums, lychee_settings LIMIT 0;')) + if (!dbCreateTables($database)) exit('Error: Could not create tables!'); return $database; } -function dbCheck($database) { - - if (!$database->query("SELECT * FROM lychee_photos, lychee_albums, lychee_settings LIMIT 1;")) - if (!dbCreateTables($database)) exit('Error: Could not create tables!'); - -} - function dbCreateConfig($dbHost = 'localhost', $dbUser, $dbPassword, $dbName = 'lychee') { $dbPassword = urldecode($dbPassword); $database = new mysqli($dbHost, $dbUser, $dbPassword); - if ($database->connect_errno) return "Warning: Connection failed!"; + if ($database->connect_errno) return 'Warning: Connection failed!'; else { $config = ""; - if (file_put_contents("../data/config.php", $config)===false) return "Warning: Could not create file!"; + if (file_put_contents('../data/config.php', $config)===false) return 'Warning: Could not create file!'; else { $_SESSION['login'] = true; @@ -90,7 +83,7 @@ function dbCreate($dbName, $database) { function dbCreateTables($database) { - if (!$database->query("SELECT * FROM lychee_settings LIMIT 1;")) { + if (!$database->query('SELECT * FROM lychee_settings LIMIT 0;')) { $query = " @@ -120,7 +113,7 @@ function dbCreateTables($database) { } - if (!$database->query("SELECT * FROM lychee_albums LIMIT 1;")) { + if (!$database->query('SELECT * FROM lychee_albums LIMIT 0;')) { $query = " @@ -140,7 +133,7 @@ function dbCreateTables($database) { } - if (!$database->query("SELECT * FROM lychee_photos LIMIT 1;")) { + if (!$database->query('SELECT * FROM lychee_photos LIMIT 0;')) { $query = " @@ -186,7 +179,7 @@ function dbClose() { global $database; - if (!$database->close()) exit("Error: Closing the connection failed!"); + if (!$database->close()) exit('Error: Closing the connection failed!'); return true; From a4c111eebc79787e599781af56e1099b4e69326f Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 8 Feb 2014 18:40:40 +0100 Subject: [PATCH 29/87] Fixed typos and updated readme --- docs/md/FAQ.md | 2 +- docs/md/FTP Upload.md | 2 +- docs/md/Installation.md | 2 +- docs/md/Settings.md | 10 +++++----- readme.md | 8 ++++++-- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/md/FAQ.md b/docs/md/FAQ.md index 18824a3..bc428ec 100644 --- a/docs/md/FAQ.md +++ b/docs/md/FAQ.md @@ -18,7 +18,7 @@ If possible, change these settings directly in your `php.ini`. We recommend to i Lychee supports the latest versions of Google Chrome, Apple Safari, Mozilla Firefox and Opera. Photos you share with others can be viewed from every browser. #### How can I set thumbnails for my albums? -Thumbnails are chosen automatically by the photos you have starred and in the order you uploaded them. Star a photo inside a album to set it as an thumbnail. +Thumbnails are chosen automatically by the photos you have starred and in the order you uploaded them. Star a photo inside an album to set it as a thumbnail. #### What is new? Take a look at the [Changelog](Changelog.md) to see whats new. diff --git a/docs/md/FTP Upload.md b/docs/md/FTP Upload.md index ca8a70d..c4b1746 100644 --- a/docs/md/FTP Upload.md +++ b/docs/md/FTP Upload.md @@ -10,4 +10,4 @@ You can upload photos directly with every FTP client into Lychee. This feature h 2. Navigate your browser to the place where Lychee is located (e.g. `http://example.com/view.php?p=filename.png`). `filename.png` must be replaced with the filename of your uploaded file. 3. Share the link. -Lychee will import the file as an public image, delete the original (unused) file and display it in the browser. [Sample FTP configuration](http://l.electerious.com/view.php?p=13657692738813). \ No newline at end of file +Lychee will import the file as a public image, delete the original (unused) file and display it in the browser. [Sample FTP configuration »](http://l.electerious.com/view.php?p=13657692738813) \ No newline at end of file diff --git a/docs/md/Installation.md b/docs/md/Installation.md index d79ce7e..1e14e40 100644 --- a/docs/md/Installation.md +++ b/docs/md/Installation.md @@ -19,7 +19,7 @@ To use Lychee without restrictions, we recommend to increase the values of the f ### Download Lychee -The easiest way to download Lychee is with git: +The easiest way to download Lychee is with `git`: git clone https://github.com/electerious/Lychee.git diff --git a/docs/md/Settings.md b/docs/md/Settings.md index 381dfba..3b7adb4 100644 --- a/docs/md/Settings.md +++ b/docs/md/Settings.md @@ -1,6 +1,6 @@ ### Database Details -Your MySQL details are stored in `php/config.php`. This file doesn't exist until you installed Lychee. If you need to change your connection details, you can edit this file manually. +Your MySQL details are stored in `data/config.php`. This file doesn't exist until you installed Lychee. If you need to change your connection details, you can edit this file manually. @@ -13,20 +13,20 @@ Fill these properties with your MySQL information. Lychee will create the databa ### Settings -All settings are stored in the database. You can change the properties manually, but we recommend to use the menu in Lychee. You can find this menu on the top left corner after you signed in. +All settings are stored in the database. You can change the properties manually, but we recommend to use the menu in Lychee. You can find this menu on the top left corner after you signed in. Some of these settings are only changeable directly in the database. #### Login username = Username for Lychee password = Password for Lychee, saved as an md5 hash -Your photos and albums are protected by a username and password you need to set. If both rows are empty, Lychee will prompt you to set them. +Your photos and albums are protected by an username and password you need to set. If both rows are empty, Lychee will prompt you to set them. #### Thumb Quality thumbQuality = [0-100] -Less means a inferiority quality of your thumbs, but faster loading. More means a better quality of your thumbs, but slower loading. The default value is 90. The allowed values are between 0 and 100. +Less means an inferiority quality of your thumbs, but faster loading. More means a better quality of your thumbs, but slower loading. The default value is 90. The allowed values are between 0 and 100. #### Check For Updates @@ -38,7 +38,7 @@ If `1`, Lychee will check if you are using the latest version. The notice will b sorting = ORDER BY [row] [ASC|DESC] -A typical part of an MySQL statement. This string will be appended to mostly every MySQL query. +A typical part of a MySQL statement. This string will be appended to mostly every MySQL query. #### Import Filename diff --git a/readme.md b/readme.md index 20ca641..58ef447 100644 --- a/readme.md +++ b/readme.md @@ -17,7 +17,7 @@ You can use Lychee right after the installation. Here are some advanced features ### Settings -Sign in and click the gear on the top left corner to change your settings. If you want to edit them manually: MySQL details are stored in `data/config.php`. Other options and settings are stored directly in the database. [Settings »](docs/md/Settings.md) +Sign in and click the gear on the top left corner to change your settings. If you want to edit them manually: MySQL details are stored in `data/config.php`. Other options and hidden settings are stored directly in the database. [Settings »](docs/md/Settings.md) ### Update @@ -52,7 +52,11 @@ Take a look at the [FAQ](docs/md/FAQ.md) if you have problems. | 1.2, 1.3, 2.x | [Tobias Reich](http://electerious.com)| | 1.0, 1.1 | [Tobias Reich](http://electerious.com)
[Philipp Maurer](http://phinal.net) | -##License +## Donate + +I am working hard on continuously developing and maintaining Lychee. Please consider making a donation via [Flattr](https://flattr.com/submit/auto?user_id=electerious&url=http%3A%2F%2Flychee.electerious.com&title=Lychee&category=software) or PayPal (from [our site](http://lychee.electerious.com/)) to keep the project going strong and me motivated. + +## License (MIT License) From 1f8f6dfead90b0877033d3d4e75375e57ddb99a9 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 8 Feb 2014 21:19:19 +0100 Subject: [PATCH 30/87] - Edit tags via contextMenu - Dialog improvements --- assets/js/modules/album.js | 86 ++++++++++++++------------------ assets/js/modules/contextMenu.js | 16 +++--- assets/js/modules/photo.js | 85 ++++++++++++++++++------------- php/modules/album.php | 9 ++-- 4 files changed, 102 insertions(+), 94 deletions(-) diff --git a/assets/js/modules/album.js b/assets/js/modules/album.js index b61efc6..adb1108 100644 --- a/assets/js/modules/album.js +++ b/assets/js/modules/album.js @@ -96,28 +96,25 @@ album = { title = $(".message input.text").val(); - if (title==="") title = "Untitled"; + if (title.length===0) title = "Untitled"; - if (title.length>0&&title.length<31) { + modal.close(); - modal.close(); + params = "addAlbum&title=" + escape(encodeURI(title)); + lychee.api(params, function(data) { - params = "addAlbum&title=" + escape(encodeURI(title)); - lychee.api(params, function(data) { + if (data!==false) { + if (data===true) data = 1; // Avoid first album to be true + lychee.goto(data); + } else lychee.error(null, params, data); - if (data!==false) { - if (data===true) data = 1; // Avoid first album to be true - lychee.goto(data); - } else lychee.error(null, params, data); - - }); - - } else loadingBar.show("error", "Title too short or too long. Please try again!"); + }); }], ["Cancel", function() {}] ]; - modal.show("New Album", "Please enter a title for this album: ", buttons); + + modal.show("New Album", "Enter a title for this album: ", buttons); }, @@ -203,37 +200,33 @@ album = { newTitle = ($(".message input.text").val()==="") ? "Untitled" : $(".message input.text").val(); - if (newTitle.length<31) { + if (visible.album()) { - if (visible.album()) { - - album.json.title = newTitle; - view.album.title(); - - } else if (visible.albums()) { - - albumIDs.forEach(function(id, index, array) { - albums.json.content[id].title = newTitle; - view.albums.content.title(id); - }); - - } - - params = "setAlbumTitle&albumIDs=" + albumIDs + "&title=" + escape(encodeURI(newTitle)); - lychee.api(params, function(data) { - - if (data!==true) lychee.error(null, params, data); + album.json.title = newTitle; + view.album.title(); + } else if (visible.albums()) { + + albumIDs.forEach(function(id, index, array) { + albums.json.content[id].title = newTitle; + view.albums.content.title(id); }); - } else if (newTitle.length>30) loadingBar.show("error", "New title too long. Please try another one!"); + } + + params = "setAlbumTitle&albumIDs=" + albumIDs + "&title=" + escape(encodeURI(newTitle)); + lychee.api(params, function(data) { + + if (data!==true) lychee.error(null, params, data); + + }); }], ["Cancel", function() {}] ]; - if (albumIDs.length===1) modal.show("Set Title", "Please enter a new title for this album: ", buttons); - else modal.show("Set Titles", "Please enter a title for all " + albumIDs.length + " selected album: ", buttons); + if (albumIDs.length===1) modal.show("Set Title", "Enter a new title for this album: ", buttons); + else modal.show("Set Titles", "Enter a title for all " + albumIDs.length + " selected album: ", buttons); }, @@ -249,25 +242,22 @@ album = { description = $(".message input.text").val(); - if (description.length<801) { + if (visible.album()) { + album.json.description = description; + view.album.description(); + } - if (visible.album()) { - album.json.description = description; - view.album.description(); - } + params = "setAlbumDescription&albumID=" + photoID + "&description=" + escape(description); + lychee.api(params, function(data) { - params = "setAlbumDescription&albumID=" + photoID + "&description=" + escape(description); - lychee.api(params, function(data) { + if (data!==true) lychee.error(null, params, data); - if (data!==true) lychee.error(null, params, data); - - }); - - } else loadingBar.show("error", "Description too long. Please try again!"); + }); }], ["Cancel", function() {}] ]; + modal.show("Set Description", "Please enter a description for this album: ", buttons); }, diff --git a/assets/js/modules/contextMenu.js b/assets/js/modules/contextMenu.js index e180935..34091e6 100644 --- a/assets/js/modules/contextMenu.js +++ b/assets/js/modules/contextMenu.js @@ -157,6 +157,7 @@ contextMenu = { contextMenu.fns = [ function() { photo.setStar([photoID]) }, + function() { photo.editTags([photoID]) }, function() { photo.setTitle([photoID]) }, function() { contextMenu.move([photoID], e, "right") }, function() { photo.delete([photoID]) } @@ -164,10 +165,11 @@ contextMenu = { items = [ [" Star", 0], + [" Tags", 1], ["separator", -1], - [" Rename", 1], - [" Move", 2], - [" Delete", 3] + [" Rename", 2], + [" Move", 3], + [" Delete", 4] ]; contextMenu.show(items, mouse_x, mouse_y, "right"); @@ -186,6 +188,7 @@ contextMenu = { contextMenu.fns = [ function() { photo.setStar(photoIDs) }, + function() { photo.editTags(photoIDs) }, function() { photo.setTitle(photoIDs) }, function() { contextMenu.move(photoIDs, e, "right") }, function() { photo.delete(photoIDs) } @@ -193,10 +196,11 @@ contextMenu = { items = [ [" Star All", 0], + [" Tag All", 1], ["separator", -1], - [" Rename All", 1], - [" Move All", 2], - [" Delete All", 3] + [" Rename All", 2], + [" Move All", 3], + [" Delete All", 4] ]; contextMenu.show(items, mouse_x, mouse_y, "right"); diff --git a/assets/js/modules/photo.js b/assets/js/modules/photo.js index e506fe1..2d05847 100644 --- a/assets/js/modules/photo.js +++ b/assets/js/modules/photo.js @@ -146,33 +146,29 @@ photo = { newTitle = $(".message input.text").val(); - if (newTitle.length<31) { + if (visible.photo()) { + photo.json.title = (newTitle==="") ? "Untitled" : newTitle; + view.photo.title(); + } - if (visible.photo()) { - photo.json.title = (newTitle==="") ? "Untitled" : newTitle; - view.photo.title(); - } + photoIDs.forEach(function(id, index, array) { + album.json.content[id].title = newTitle; + view.album.content.title(id); + }); - photoIDs.forEach(function(id, index, array) { - album.json.content[id].title = newTitle; - view.album.content.title(id); - }); + params = "setPhotoTitle&photoIDs=" + photoIDs + "&title=" + escape(encodeURI(newTitle)); + lychee.api(params, function(data) { - params = "setPhotoTitle&photoIDs=" + photoIDs + "&title=" + escape(encodeURI(newTitle)); - lychee.api(params, function(data) { + if (data!==true) lychee.error(null, params, data); - if (data!==true) lychee.error(null, params, data); - - }); - - } else if (newTitle.length>30) loadingBar.show("error", "New title too long. Please try another one!"); + }); }], ["Cancel", function() {}] ]; - if (photoIDs.length===1) modal.show("Set Title", "Please enter a new title for this photo: ", buttons); - else modal.show("Set Titles", "Please enter a title for all " + photoIDs.length + " selected photos: ", buttons); + if (photoIDs.length===1) modal.show("Set Title", "Enter a new title for this photo: ", buttons); + else modal.show("Set Titles", "Enter a title for all " + photoIDs.length + " selected photos: ", buttons); }, @@ -280,49 +276,62 @@ photo = { description = $(".message input.text").val(); - if (description.length<800) { + if (visible.photo()) { + photo.json.description = description; + view.photo.description(); + } - if (visible.photo()) { - photo.json.description = description; - view.photo.description(); - } + params = "setPhotoDescription&photoID=" + photoID + "&description=" + escape(description); + lychee.api(params, function(data) { - params = "setPhotoDescription&photoID=" + photoID + "&description=" + escape(description); - lychee.api(params, function(data) { + if (data!==true) lychee.error(null, params, data); - if (data!==true) lychee.error(null, params, data); - - }); - - } else loadingBar.show("error", "Description too long. Please try again!"); + }); }], ["Cancel", function() {}] ]; - modal.show("Set Description", "Please enter a description for this photo: ", buttons); + + modal.show("Set Description", "Enter a description for this photo: ", buttons); }, editTags: function(photoIDs) { - var oldTags = ""; + var oldTags = "", + tags = ""; if (!photoIDs) return false; if (photoIDs instanceof Array===false) photoIDs = [photoIDs]; - if (visible.photo()) oldTags = photo.json.tags.replace(/,/g, ', '); + + // Get tags + if (visible.photo()) oldTags = photo.json.tags; + if (visible.album()&&photoIDs.length===1) oldTags = album.json.content[photoIDs].tags; + if (visible.album()&&photoIDs.length>1) { + var same = true; + photoIDs.forEach(function(id, index, array) { + if(album.json.content[id].tags===album.json.content[photoIDs[0]].tags&&same===true) same = true; + else same = false; + }); + if (same) oldTags = album.json.content[photoIDs[0]].tags; + } + + // Improve tags + oldTags = oldTags.replace(/,/g, ', '); buttons = [ ["Set Tags", function() { tags = $(".message input.text").val(); - if (tags.length<800) photo.setTags(photoIDs, tags) - else loadingBar.show("error", "Description too long. Please try again!"); + photo.setTags(photoIDs, tags); }], ["Cancel", function() {}] ]; - modal.show("Set Tags", "Please enter your tags for this photo. You can add multiple tags by separating them with a comma: ", buttons); + + if (photoIDs.length===1) modal.show("Set Tags", "Enter your tags for this photo. You can add multiple tags by separating them with a comma: ", buttons); + else modal.show("Set Tags", "Enter your tags for all " + photoIDs.length + " selected photos. Existing tags will be overwritten. You can add multiple tags by separating them with a comma: ", buttons); }, @@ -342,6 +351,10 @@ photo = { view.photo.tags(); } + photoIDs.forEach(function(id, index, array) { + album.json.content[id].tags = tags; + }); + params = "setTags&photoIDs=" + photoIDs + "&tags=" + tags; lychee.api(params, function(data) { diff --git a/php/modules/album.php b/php/modules/album.php index 67e3e6b..133d247 100755 --- a/php/modules/album.php +++ b/php/modules/album.php @@ -115,15 +115,15 @@ function getAlbum($albumID) { switch($albumID) { case "f": $return['public'] = false; - $query = "SELECT id, title, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE star = 1 " . $settings['sorting']; + $query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE star = 1 " . $settings['sorting']; break; case "s": $return['public'] = false; - $query = "SELECT id, title, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE public = 1 " . $settings['sorting']; + $query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE public = 1 " . $settings['sorting']; break; case "0": $return['public'] = false; - $query = "SELECT id, title, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE album = 0 " . $settings['sorting']; + $query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE album = 0 " . $settings['sorting']; break; default: $result = $database->query("SELECT * FROM lychee_albums WHERE id = '$albumID';"); @@ -134,7 +134,7 @@ function getAlbum($albumID) { $return['public'] = $row->public; if ($row->password=="") $return['password'] = false; else $return['password'] = true; - $query = "SELECT id, title, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE album = '$albumID' " . $settings['sorting']; + $query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE album = '$albumID' " . $settings['sorting']; break; } @@ -150,6 +150,7 @@ function getAlbum($albumID) { $return['content'][$row['id']]['sysdate'] = date('d F Y', strtotime($row['sysdate'])); $return['content'][$row['id']]['public'] = $row['public']; $return['content'][$row['id']]['star'] = $row['star']; + $return['content'][$row['id']]['tags'] = $row['tags']; $return['content'][$row['id']]['album'] = $row['album']; $return['content'][$row['id']]['thumbUrl'] = $row['thumbUrl']; From 1e34ce4d09f18f9da3fd76952cda3e52b3cec592 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 8 Feb 2014 21:19:33 +0100 Subject: [PATCH 31/87] Improved overlay for photos --- assets/css/modules/content.css | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/assets/css/modules/content.css b/assets/css/modules/content.css index 0d3d148..13a791d 100644 --- a/assets/css/modules/content.css +++ b/assets/css/modules/content.css @@ -115,8 +115,11 @@ background: -ms-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,0) 20%,rgba(0,0,0,0.9) 100%); /* IE10+ */ background: linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,0) 20%,rgba(0,0,0,0.9) 100%); /* W3C */ } - .photo .overlay { - background: rgba(0, 0, 0, .6); + .photo .overlay { + background: -moz-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.5) 80%, rgba(0,0,0,0.9) 100%); /* FF3.6+ */ + background: -webkit-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.5) 80%, rgba(0,0,0,0.9) 100%); /* Chrome10+,Safari5.1+ */ + background: -ms-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.5) 80%, rgba(0,0,0,0.9) 100%); /* IE10+ */ + background: linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.5) 80%, rgba(0,0,0,0.9) 100%); /* W3C */ opacity: 0; } .photo:hover .overlay, From b24f120955d9a15caf8b4db9827d788d028302b1 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 8 Feb 2014 21:43:37 +0100 Subject: [PATCH 32/87] No text selection for Firefox --- assets/css/modules/content.css | 1 + assets/css/modules/infobox.css | 8 ++++---- assets/css/modules/misc.css | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/assets/css/modules/content.css b/assets/css/modules/content.css index 13a791d..c72af27 100644 --- a/assets/css/modules/content.css +++ b/assets/css/modules/content.css @@ -4,6 +4,7 @@ * @copyright 2014 by Tobias Reich */ +/* Gradient ------------------------------------------------*/ #content::before { content: ""; position: absolute; diff --git a/assets/css/modules/infobox.css b/assets/css/modules/infobox.css index 86118f8..96bf44b 100644 --- a/assets/css/modules/infobox.css +++ b/assets/css/modules/infobox.css @@ -27,10 +27,6 @@ -moz-transform: translateX(320px); transform: translateX(320px); - -webkit-user-select: text; - -moz-user-select: text; - user-select: text; - -webkit-transition: -webkit-transform .5s cubic-bezier(.225,.5,.165,1); -moz-transition: -moz-transform .5s cubic-bezier(.225,.5,.165,1); transition: transform .5s cubic-bezier(.225,.5,.165,1); @@ -121,6 +117,10 @@ color: #fff; font-size: 14px; line-height: 19px; + + -webkit-user-select: text; + -moz-user-select: text; + user-select: text; } #infobox table tr td:first-child { width: 110px; diff --git a/assets/css/modules/misc.css b/assets/css/modules/misc.css index a44002f..70e3ee7 100755 --- a/assets/css/modules/misc.css +++ b/assets/css/modules/misc.css @@ -7,9 +7,6 @@ html, body { min-height: 100%; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; } body { background-color: #222; @@ -29,6 +26,9 @@ body.view { top:50%; } * { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; -webkit-transition: color .3s, opacity .3s ease-out, -webkit-transform .3s ease-out, box-shadow .3s; -moz-transition: opacity .3s ease-out, -moz-transform .3s ease-out, box-shadow .3s; transition: color .3s, opacity .3s ease-out, transform .3s ease-out, box-shadow .3s; From 69741b7d33c49eecd4bb8ea5904b4e07a9b4ceac Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 8 Feb 2014 22:11:01 +0100 Subject: [PATCH 33/87] Better selecting --- assets/css/modules/misc.css | 5 +++++ assets/css/modules/multiselect.css | 4 ++-- assets/js/modules/contextMenu.js | 4 ++-- assets/js/modules/modal.js | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/assets/css/modules/misc.css b/assets/css/modules/misc.css index 70e3ee7..9ae7d34 100755 --- a/assets/css/modules/misc.css +++ b/assets/css/modules/misc.css @@ -32,4 +32,9 @@ body.view { -webkit-transition: color .3s, opacity .3s ease-out, -webkit-transform .3s ease-out, box-shadow .3s; -moz-transition: opacity .3s ease-out, -moz-transform .3s ease-out, box-shadow .3s; transition: color .3s, opacity .3s ease-out, transform .3s ease-out, box-shadow .3s; +} +input { + -webkit-user-select: text !important; + -moz-user-select: text !important; + user-select: text !important; } \ No newline at end of file diff --git a/assets/css/modules/multiselect.css b/assets/css/modules/multiselect.css index 7acc7a3..fd60f81 100644 --- a/assets/css/modules/multiselect.css +++ b/assets/css/modules/multiselect.css @@ -6,8 +6,8 @@ #multiselect { position: absolute; - background-color: RGBA(0, 94, 204, .3); - border: 1px solid RGBA(0, 94, 204, 1); + background-color: rgba(0, 94, 204, .3); + border: 1px solid rgba(0, 94, 204, 1); border-radius: 3px; z-index: 3; } \ No newline at end of file diff --git a/assets/js/modules/contextMenu.js b/assets/js/modules/contextMenu.js index 34091e6..cf7a7c2 100644 --- a/assets/js/modules/contextMenu.js +++ b/assets/js/modules/contextMenu.js @@ -272,7 +272,7 @@ contextMenu = { ]; contextMenu.show(items, mouse_x, mouse_y, "left"); - $(".contextmenu input").focus(); + $(".contextmenu input").focus().select(); }, @@ -307,7 +307,7 @@ contextMenu = { if (album.json.password==true) items[3] = [" Remove Password", 5]; contextMenu.show(items, mouse_x, mouse_y, "left"); - $(".contextmenu input").focus(); + $(".contextmenu input").focus().select(); }, diff --git a/assets/js/modules/modal.js b/assets/js/modules/modal.js index bc2969e..7086280 100644 --- a/assets/js/modules/modal.js +++ b/assets/js/modules/modal.js @@ -20,7 +20,7 @@ modal = { modal.fns = [buttons[0][1], buttons[1][1]]; $("body").append(build.modal(title, text, buttons, marginTop, closeButton)); - $(".message input:first-child").focus(); + $(".message input:first-child").focus().select(); }, From 7fd4fd5c04629b9d07b9e9aeae9ccfbf3c445e03 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 8 Feb 2014 22:29:44 +0100 Subject: [PATCH 34/87] Added FeedWriter source --- .gitmodules | 3 +++ php/FeedWriter | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 php/FeedWriter diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..38f3f00 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "php/FeedWriter"] + path = php/FeedWriter + url = git@github.com:mibe/FeedWriter.git diff --git a/php/FeedWriter b/php/FeedWriter new file mode 160000 index 0000000..8b801e9 --- /dev/null +++ b/php/FeedWriter @@ -0,0 +1 @@ +Subproject commit 8b801e96326606d0360c0549f913f099df10ed67 From 2a745b5304e79dba472cd7d0a9823298005b2e93 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 9 Feb 2014 00:34:31 +0100 Subject: [PATCH 35/87] Do not show tags in public mode --- assets/js/modules/build.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/assets/js/modules/build.js b/assets/js/modules/build.js index e396823..b7e9ff5 100644 --- a/assets/js/modules/build.js +++ b/assets/js/modules/build.js @@ -345,9 +345,11 @@ build = { break; case "Tags": // Tags - infobox += ""; - infobox += "

" + infos[index][0] + "

"; - infobox += "
" + infos[index][1] + "
"; + if (forView!==true&&!lychee.publicMode) { + infobox += ""; + infobox += "

" + infos[index][0] + "

"; + infobox += "
" + infos[index][1] + "
"; + } break; default: // Item From e0b8375e28b34ffc9d7894ed828899c0501dd4ba Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 9 Feb 2014 00:34:49 +0100 Subject: [PATCH 36/87] Get current URL in php --- php/modules/misc.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/php/modules/misc.php b/php/modules/misc.php index eb161e1..a953c76 100755 --- a/php/modules/misc.php +++ b/php/modules/misc.php @@ -95,4 +95,17 @@ function update() { } +function pageURL() { + + $pageURL = 'http'; + if (isset($_SERVER["HTTPS"])&&$_SERVER["HTTPS"]==="on") $pageURL .= "s"; + $pageURL .= "://"; + + if ($_SERVER["SERVER_PORT"]!="80") $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER['SCRIPT_NAME']; + else $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER['SCRIPT_NAME']; + + return $pageURL; + +} + ?> From ec196c52d3c13ace63b624564bb65ffc8e2ccbeb Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 9 Feb 2014 19:21:55 +0100 Subject: [PATCH 37/87] API separated into areas --- .gitmodules | 3 - assets/js/modules/photo.js | 4 +- php/FeedWriter | 1 - php/access/admin.php | 155 +++++++++++++++++++ php/access/guest.php | 126 ++++++++++++++++ php/access/installation.php | 23 +++ php/api.php | 294 ++++-------------------------------- php/modules/photo.php | 19 ++- php/modules/tags.php | 38 ----- 9 files changed, 353 insertions(+), 310 deletions(-) delete mode 100644 .gitmodules delete mode 160000 php/FeedWriter create mode 100644 php/access/admin.php create mode 100644 php/access/guest.php create mode 100644 php/access/installation.php delete mode 100755 php/modules/tags.php diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 38f3f00..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "php/FeedWriter"] - path = php/FeedWriter - url = git@github.com:mibe/FeedWriter.git diff --git a/assets/js/modules/photo.js b/assets/js/modules/photo.js index 2d05847..6165df5 100644 --- a/assets/js/modules/photo.js +++ b/assets/js/modules/photo.js @@ -200,7 +200,7 @@ photo = { }); - params = "setAlbum&photoIDs=" + photoIDs + "&albumID=" + albumID; + params = "setPhotoAlbum&photoIDs=" + photoIDs + "&albumID=" + albumID; lychee.api(params, function(data) { if (data!==true) lychee.error(null, params, data); @@ -355,7 +355,7 @@ photo = { album.json.content[id].tags = tags; }); - params = "setTags&photoIDs=" + photoIDs + "&tags=" + tags; + params = "setPhotoTags&photoIDs=" + photoIDs + "&tags=" + tags; lychee.api(params, function(data) { if (data!==true) lychee.error(null, params, data); diff --git a/php/FeedWriter b/php/FeedWriter deleted file mode 160000 index 8b801e9..0000000 --- a/php/FeedWriter +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8b801e96326606d0360c0549f913f099df10ed67 diff --git a/php/access/admin.php b/php/access/admin.php new file mode 100644 index 0000000..f4ed528 --- /dev/null +++ b/php/access/admin.php @@ -0,0 +1,155 @@ + \ No newline at end of file diff --git a/php/access/guest.php b/php/access/guest.php new file mode 100644 index 0000000..483c610 --- /dev/null +++ b/php/access/guest.php @@ -0,0 +1,126 @@ + \ No newline at end of file diff --git a/php/access/installation.php b/php/access/installation.php new file mode 100644 index 0000000..ffd7440 --- /dev/null +++ b/php/access/installation.php @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/php/api.php b/php/api.php index 542e747..3e1ec94 100755 --- a/php/api.php +++ b/php/api.php @@ -3,7 +3,7 @@ /** * @name API * @author Tobias Reich - * @copyright 2014 by Philipp Maurer, Tobias Reich + * @copyright 2014 by Tobias Reich */ @ini_set('max_execution_time', '200'); @@ -16,305 +16,69 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { session_start(); define('LYCHEE', true); + date_default_timezone_set('UTC'); + // Load modules + require('modules/album.php'); require('modules/db.php'); + require('modules/feed.php'); + require('modules/misc.php'); + require('modules/photo.php'); require('modules/session.php'); require('modules/settings.php'); require('modules/upload.php'); - require('modules/album.php'); - require('modules/photo.php'); - require('modules/tags.php'); - require('modules/misc.php'); - + if (file_exists('../data/config.php')) require('../data/config.php'); else { /** - * Installation Mode + * Installation Access * Limited access to configure Lychee. Only available when the config.php file is missing. */ - switch ($_POST['function']) { - - case 'dbCreateConfig': if (isset($_POST['dbHost'])&&isset($_POST['dbUser'])&&isset($_POST['dbPassword'])&&isset($_POST['dbName'])) - echo dbCreateConfig($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName']); - break; - - default: echo 'Warning: No configuration!'; - break; - - } - + define('LYCHEE_ACCESS_INSTALLATION', true); + require('access/installation.php'); exit(); } - // Connect to DB + // Connect and get settings $database = dbConnect(); - - // Get Settings $settings = getSettings(); // Escape - foreach(array_keys($_POST) as $key) $_POST[$key] = mysqli_real_escape_string($database, urldecode($_POST[$key])); - foreach(array_keys($_GET) as $key) $_GET[$key] = mysqli_real_escape_string($database, urldecode($_GET[$key])); + foreach(array_keys($_POST) as $key) $_POST[$key] = mysqli_real_escape_string($database, urldecode($_POST[$key])); + foreach(array_keys($_GET) as $key) $_GET[$key] = mysqli_real_escape_string($database, urldecode($_GET[$key])); // Validate parameters - if (isset($_POST['albumIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['albumIDs'])!==1) exit('Error: Wrong parameter type for albumIDs!'); - if (isset($_POST['photoIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['photoIDs'])!==1) exit('Error: Wrong parameter type for photoIDs!'); - if (isset($_POST['albumID'])&&preg_match('/^[0-9sf]{1,}$/', $_POST['albumID'])!==1) exit('Error: Wrong parameter type for albumID!'); - if (isset($_POST['photoID'])&&preg_match('/^[0-9]{14}$/', $_POST['photoID'])!==1) exit('Error: Wrong parameter type for photoID!'); + if (isset($_POST['albumIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['albumIDs'])!==1) exit('Error: Wrong parameter type for albumIDs!'); + if (isset($_POST['photoIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['photoIDs'])!==1) exit('Error: Wrong parameter type for photoIDs!'); + if (isset($_POST['albumID'])&&preg_match('/^[0-9sf]{1,}$/', $_POST['albumID'])!==1) exit('Error: Wrong parameter type for albumID!'); + if (isset($_POST['photoID'])&&preg_match('/^[0-9]{14}$/', $_POST['photoID'])!==1) exit('Error: Wrong parameter type for photoID!'); + + // Fallback for switch statement + if (!isset($_POST['function'])) $_POST['function'] = ''; + if (!isset($_GET['function'])) $_GET['function'] = ''; if (isset($_SESSION['login'])&&$_SESSION['login']==true) { /** - * Admin Mode + * Admin Access * Full access to Lychee. Only with correct password/session. */ - - switch ($_POST['function']) { - - // Album Functions - - case 'getAlbums': echo json_encode(getAlbums(false)); - break; - - case 'getAlbum': if (isset($_POST['albumID'])) - echo json_encode(getAlbum($_POST['albumID'])); - break; - - case 'addAlbum': if (isset($_POST['title'])) - echo addAlbum($_POST['title']); - break; - - case 'setAlbumTitle': if (isset($_POST['albumIDs'])&&isset($_POST['title'])) - echo setAlbumTitle($_POST['albumIDs'], $_POST['title']); - break; - - case 'setAlbumDescription': if (isset($_POST['albumID'])&&isset($_POST['description'])) - echo setAlbumDescription($_POST['albumID'], $_POST['description']); - break; - - case 'setAlbumPublic': if (isset($_POST['albumID'])) - if (!isset($_POST['password'])) $_POST['password'] = ''; - echo setAlbumPublic($_POST['albumID'], $_POST['password']); - break; - - case 'setAlbumPassword':if (isset($_POST['albumID'])&&isset($_POST['password'])) - echo setAlbumPassword($_POST['albumID'], $_POST['password']); - break; - - case 'deleteAlbum': if (isset($_POST['albumIDs'])) - echo deleteAlbum($_POST['albumIDs']); - break; - - // Photo Functions - - case 'getPhoto': if (isset($_POST['photoID'])&&isset($_POST['albumID'])) - echo json_encode(getPhoto($_POST['photoID'], $_POST['albumID'])); - break; - - case 'deletePhoto': if (isset($_POST['photoIDs'])) - echo deletePhoto($_POST['photoIDs']); - break; - - case 'setAlbum': if (isset($_POST['photoIDs'])&&isset($_POST['albumID'])) - echo setAlbum($_POST['photoIDs'], $_POST['albumID']); - break; - - case 'setPhotoTitle': if (isset($_POST['photoIDs'])&&isset($_POST['title'])) - echo setPhotoTitle($_POST['photoIDs'], $_POST['title']); - break; - - case 'setPhotoStar': if (isset($_POST['photoIDs'])) - echo setPhotoStar($_POST['photoIDs']); - break; - - case 'setPhotoPublic': if (isset($_POST['photoID'])&&isset($_POST['url'])) - echo setPhotoPublic($_POST['photoID'], $_POST['url']); - break; - - case 'setPhotoDescription': if (isset($_POST['photoID'])&&isset($_POST['description'])) - echo setPhotoDescription($_POST['photoID'], $_POST['description']); - break; - - // Add Functions - - case 'upload': if (isset($_FILES)&&isset($_POST['albumID'])) - echo upload($_FILES, $_POST['albumID']); - break; - - case 'importUrl': if (isset($_POST['url'])&&isset($_POST['albumID'])) - echo importUrl($_POST['url'], $_POST['albumID']); - break; - - case 'importServer': if (isset($_POST['albumID'])) - echo importServer($_POST['albumID']); - break; - - // Search 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 - - case 'init': echo json_encode(init('admin')); - break; - - case 'login': if (isset($_POST['user'])&&isset($_POST['password'])) - echo login($_POST['user'], $_POST['password']); - break; - - case 'logout': logout(); - break; - - // Settings - - case 'setLogin': if (isset($_POST['username'])&&isset($_POST['password'])) - if (!isset($_POST['oldPassword'])) $_POST['oldPassword'] = ''; - echo setLogin($_POST['oldPassword'], $_POST['username'], $_POST['password']); - break; - - case 'setSorting': if (isset($_POST['type'])&&isset($_POST['order'])) - echo setSorting($_POST['type'], $_POST['order']); - break; - - // Miscellaneous - - case 'update': echo update(); - - default: if (isset($_GET['function'])&&$_GET['function']=='getAlbumArchive'&&isset($_GET['albumID'])) - - // Album Download - getAlbumArchive($_GET['albumID']); - - else if (isset($_GET['function'])&&$_GET['function']=='getPhotoArchive'&&isset($_GET['photoID'])) - - // Photo Download - getPhotoArchive($_GET['photoID']); - - else if (isset($_GET['function'])&&$_GET['function']=='update') - - // Update Lychee - echo update(); - - else - - // Function unknown - exit('Error: Function not found! Please check the spelling of the called function.'); - - break; - - } + + define('LYCHEE_ACCESS_ADMIN', true); + require('access/admin.php'); } else { /** - * Public Mode + * Guest Access * Access to view all public folders and photos in Lychee. */ - switch ($_POST['function']) { - - // Album Functions - - case 'getAlbums': echo json_encode(getAlbums(true)); - break; - - case 'getAlbum': if (isset($_POST['albumID'])&&isset($_POST['password'])) { - if (isAlbumPublic($_POST['albumID'])) { - // Album Public - if (checkAlbumPassword($_POST['albumID'], $_POST['password'])) - echo json_encode(getAlbum($_POST['albumID'])); - else - echo 'Warning: Wrong password!'; - } else { - // Album Private - echo 'Warning: Album private!'; - } - } - break; - - case 'checkAlbumAccess':if (isset($_POST['albumID'])&&isset($_POST['password'])) { - if (isAlbumPublic($_POST['albumID'])) { - // Album Public - if (checkAlbumPassword($_POST['albumID'], $_POST['password'])) - echo true; - else - echo false; - } else { - // Album Private - echo false; - } - } - break; - - // Photo Functions - - case 'getPhoto': if (isset($_POST['photoID'])&&isset($_POST['albumID'])&&isset($_POST['password'])) { - if (isPhotoPublic($_POST['photoID'], $_POST['password'])) - echo json_encode(getPhoto($_POST['photoID'], $_POST['albumID'])); - else - echo 'Warning: Wrong password!'; - } - break; - - // Session Functions - - case 'init': echo json_encode(init('public')); - break; - - case 'login': if (isset($_POST['user'])&&isset($_POST['password'])) - echo login($_POST['user'], $_POST['password']); - break; - - // Miscellaneous - - default: if (isset($_GET['function'])&&$_GET['function']=='getAlbumArchive'&&isset($_GET['albumID'])&&isset($_GET['password'])) { - - // Album Download - if (isAlbumPublic($_GET['albumID'])) { - // Album Public - if (checkAlbumPassword($_GET['albumID'], $_GET['password'])) - getAlbumArchive($_GET['albumID']); - else - exit('Warning: Wrong password!'); - } else { - // Album Private - exit('Warning: Album private or not downloadable!'); - } - - } else if (isset($_GET['function'])&&$_GET['function']=='getPhotoArchive'&&isset($_GET['photoID'])&&isset($_GET['password'])) { - - // Photo Download - if (isPhotoPublic($_GET['photoID'], $_GET['password'])) - // Photo Public - getPhotoArchive($_GET['photoID']); - else - // Photo Private - exit('Warning: Photo private or not downloadable!'); - - } else { - - // Function unknown - exit('Error: Function not found! Please check the spelling of the called function.'); - - } - break; - - } + define('LYCHEE_ACCESS_GUEST', true); + require('access/guest.php'); } diff --git a/php/modules/photo.php b/php/modules/photo.php index 566c98b..e7ab28d 100755 --- a/php/modules/photo.php +++ b/php/modules/photo.php @@ -93,7 +93,7 @@ function setPhotoStar($photoIDs) { } -function setAlbum($photoIDs, $albumID) { +function setPhotoAlbum($photoIDs, $albumID) { global $database; @@ -129,6 +129,23 @@ function setPhotoDescription($photoID, $description) { } +function setPhotoTags($photoIDs, $tags) { + + global $database; + + // Parse tags + $tags = preg_replace('/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/', ',', $tags); + $tags = preg_replace('/,$|^,/', ',', $tags); + + if (strlen($tags)>1000) return false; + + $result = $database->query("UPDATE lychee_photos SET tags = '$tags' WHERE id IN ($photoIDs);"); + + if (!$result) return false; + return true; + +} + function deletePhoto($photoIDs) { global $database; diff --git a/php/modules/tags.php b/php/modules/tags.php deleted file mode 100755 index 129225e..0000000 --- a/php/modules/tags.php +++ /dev/null @@ -1,38 +0,0 @@ -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; - - // Parse tags - $tags = preg_replace('/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/', ',', $tags); - $tags = preg_replace('/,$|^,/', ',', $tags); - - if (strlen($tags)>1000) return false; - - $result = $database->query("UPDATE lychee_photos SET tags = '$tags' WHERE id IN ($photoIDs);"); - - if (!$result) return false; - return true; - -} \ No newline at end of file From d9342c51e2858ac793565d7c2b9808ea16d78251 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 9 Feb 2014 19:28:31 +0100 Subject: [PATCH 38/87] Removed feed --- php/api.php | 1 - 1 file changed, 1 deletion(-) diff --git a/php/api.php b/php/api.php index 3e1ec94..f78ec3e 100755 --- a/php/api.php +++ b/php/api.php @@ -21,7 +21,6 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { // Load modules require('modules/album.php'); require('modules/db.php'); - require('modules/feed.php'); require('modules/misc.php'); require('modules/photo.php'); require('modules/session.php'); From e648281dcd68e9c43b64e1a96dbef8b831ef99ae Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 9 Feb 2014 22:22:36 +0100 Subject: [PATCH 39/87] Removed FTP docs --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 58ef447..a2ce1e6 100644 --- a/readme.md +++ b/readme.md @@ -26,7 +26,7 @@ Sign in and click the gear on the top left corner to change your settings. If yo ### FTP Upload -You can import photos from your server or upload photos directly with every FTP client into Lychee. [FTP Upload »](docs/md/FTP Upload.md) +To import photos and albums located in `uploads/import/` (photos you have uploaded via FTP or else), sign in and click the add-icon on the top right. Then choose 'Import from Server'. ### Keyboard Shortcuts From f46f63b764de039796672d9fce499bae2c5c29aa Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 9 Feb 2014 22:23:09 +0100 Subject: [PATCH 40/87] Disable multiselect when searching --- assets/js/modules/multiselect.js | 1 + assets/js/modules/visible.js | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/assets/js/modules/multiselect.js b/assets/js/modules/multiselect.js index 52355d2..da71b20 100644 --- a/assets/js/modules/multiselect.js +++ b/assets/js/modules/multiselect.js @@ -20,6 +20,7 @@ multiselect = { if (mobileBrowser()) return false; if (lychee.publicMode) return false; + if (visible.search()) return false; if ($('.album:hover, .photo:hover').length!=0) return false; if (visible.multiselect()) $('#multiselect').remove(); diff --git a/assets/js/modules/visible.js b/assets/js/modules/visible.js index 505e5c8..4afaab7 100755 --- a/assets/js/modules/visible.js +++ b/assets/js/modules/visible.js @@ -8,47 +8,52 @@ visible = { albums: function() { - if ($("#tools_albums").css("display")==="block") return true; + if ($('#tools_albums').css('display')==='block') return true; else return false; }, album: function() { - if ($("#tools_album").css("display")==="block") return true; + if ($('#tools_album').css('display')==='block') return true; else return false; }, photo: function() { - if ($("#imageview.fadeIn").length>0) return true; + if ($('#imageview.fadeIn').length>0) return true; + else return false; + }, + + search: function() { + if (search.code!==null&&search.code!=='') return true; else return false; }, infobox: function() { - if ($("#infobox.active").length>0) return true; + if ($('#infobox.active').length>0) return true; else return false; }, controls: function() { - if (lychee.loadingBar.css("opacity")<1) return false; + if (lychee.loadingBar.css('opacity')<1) return false; else return true; }, message: function() { - if ($(".message").length>0) return true; + if ($('.message').length>0) return true; else return false; }, signin: function() { - if ($(".message .sign_in").length>0) return true; + if ($('.message .sign_in').length>0) return true; else return false; }, contextMenu: function() { - if ($(".contextmenu").length>0) return true; + if ($('.contextmenu').length>0) return true; else return false; }, multiselect: function() { - if ($("#multiselect").length>0) return true; + if ($('#multiselect').length>0) return true; else return false; } From 753c14d85ff34eb82e1a06f401828be700cffd43 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 9 Feb 2014 22:23:24 +0100 Subject: [PATCH 41/87] Removed FTP docs --- docs/md/FTP Upload.md | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 docs/md/FTP Upload.md diff --git a/docs/md/FTP Upload.md b/docs/md/FTP Upload.md deleted file mode 100644 index c4b1746..0000000 --- a/docs/md/FTP Upload.md +++ /dev/null @@ -1,13 +0,0 @@ -### Import from server - -To import photos from your server (photos you have uploaded via FTP to your server), sign in and click the add-icon on the top right. Then choose 'Import from Server'. - -### Upload and share single photos - -You can upload photos directly with every FTP client into Lychee. This feature helps you to share single images quickly with others. - -1. Upload an image to `uploads/import/` -2. Navigate your browser to the place where Lychee is located (e.g. `http://example.com/view.php?p=filename.png`). `filename.png` must be replaced with the filename of your uploaded file. -3. Share the link. - -Lychee will import the file as a public image, delete the original (unused) file and display it in the browser. [Sample FTP configuration »](http://l.electerious.com/view.php?p=13657692738813) \ No newline at end of file From 88a5810e0cfd7a06e028c497a6813ae29f687acf Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 9 Feb 2014 22:30:16 +0100 Subject: [PATCH 42/87] - Multi-Folder import from server - Improved upload - Tidied up .php files - Removed import of single files via view.php?p=filename --- assets/js/modules/contextMenu.js | 2 +- assets/js/modules/upload.js | 13 ++- php/modules/album.php | 115 ++++++++++---------- php/modules/db.php | 13 +-- php/modules/misc.php | 81 +++++++------- php/modules/photo.php | 64 ++++------- php/modules/upload.php | 180 +++++++++++++++++-------------- 7 files changed, 231 insertions(+), 237 deletions(-) diff --git a/assets/js/modules/contextMenu.js b/assets/js/modules/contextMenu.js index cf7a7c2..8bd9572 100644 --- a/assets/js/modules/contextMenu.js +++ b/assets/js/modules/contextMenu.js @@ -224,7 +224,7 @@ contextMenu = { lychee.api("getAlbums", function(data) { - if (!data.albums) { + if (data.num===0) { items = [["New Album", 0, "album.add()"]]; } else { $.each(data.content, function(index) { diff --git a/assets/js/modules/upload.js b/assets/js/modules/upload.js index d183acc..4082470 100755 --- a/assets/js/modules/upload.js +++ b/assets/js/modules/upload.js @@ -170,6 +170,7 @@ upload = { }], ["Cancel", function() {}] ]; + modal.show("Import from Link", "Please enter the direct link to a photo to import it: ", buttons); }, @@ -194,10 +195,15 @@ upload = { upload.close(); upload.notify("Import complete"); - if (album.getID()===false) lychee.goto("0"); + if (data==="Notice: Import only contains albums!") { + if (visible.albums()) lychee.load(); + else lychee.goto(""); + } + else if (album.getID()===false) lychee.goto("0"); else album.load(albumID); - if (data==="Warning: Folder empty!") lychee.error("Folder empty. No photos imported!", params, data); + if (data==="Notice: Import only contains albums!") return true; + else if (data==="Warning: Folder empty!") lychee.error("Folder empty. No photos imported!", params, data); else if (data!==true) lychee.error(null, params, data); }); @@ -205,7 +211,8 @@ upload = { }], ["Cancel", function() {}] ]; - modal.show("Import from Server", "This action will import all photos which are located in 'uploads/import/' of your Lychee installation.", buttons); + + modal.show("Import from Server", "This action will import all photos and albums which are located in 'uploads/import/' of your Lychee installation.", buttons); }, diff --git a/php/modules/album.php b/php/modules/album.php index 133d247..a522172 100755 --- a/php/modules/album.php +++ b/php/modules/album.php @@ -14,8 +14,9 @@ function addAlbum($title) { global $database; if (strlen($title)<1||strlen($title)>50) return false; - $sysdate = date("d.m.Y"); - $result = $database->query("INSERT INTO lychee_albums (title, sysdate) VALUES ('$title', '$sysdate');"); + + $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; @@ -32,8 +33,10 @@ function getAlbums($public) { // Albums if ($public) $query = "SELECT * FROM lychee_albums WHERE public = 1"; else $query = "SELECT * FROM lychee_albums"; - $result = $database->query($query) OR exit("Error: $result
".$database->error); - $i = 0; + + $result = $database->query($query) OR exit("Error: $result
".$database->error); + $i = 0; + while($row = $result->fetch_object()) { // Info @@ -41,11 +44,14 @@ function getAlbums($public) { $return["content"][$row->id]['title'] = $row->title; $return["content"][$row->id]['public'] = $row->public; $return["content"][$row->id]['sysdate'] = date('F Y', strtotime($row->sysdate)); + + // Password if ($row->password=="") $return["content"][$row->id]['password'] = false; else $return["content"][$row->id]['password'] = true; // Thumbs if (($public&&$row->password=="")||(!$public)) { + $albumID = $row->id; $result2 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE album = '$albumID' ORDER BY star DESC, " . substr($settings['sorting'], 9) . " LIMIT 0, 3"); $k = 0; @@ -56,6 +62,7 @@ function getAlbums($public) { if (!isset($return["content"][$row->id]["thumb0"])) $return["content"][$row->id]["thumb0"] = ""; if (!isset($return["content"][$row->id]["thumb1"])) $return["content"][$row->id]["thumb1"] = ""; if (!isset($return["content"][$row->id]["thumb2"])) $return["content"][$row->id]["thumb2"] = ""; + } // Album count @@ -65,9 +72,6 @@ function getAlbums($public) { $return["num"] = $i; - if ($i==0) $return["albums"] = false; - else $return["albums"] = true; - return $return; } @@ -77,8 +81,8 @@ function getSmartInfo() { global $database, $settings; // Unsorted - $result = $database->query("SELECT thumbUrl FROM lychee_photos WHERE album = 0 " . $settings['sorting']); - $i = 0; + $result = $database->query("SELECT thumbUrl FROM lychee_photos WHERE album = 0 " . $settings['sorting']); + $i = 0; while($row = $result->fetch_object()) { if ($i<3) $return["unsortedThumb$i"] = $row->thumbUrl; $i++; @@ -86,8 +90,8 @@ function getSmartInfo() { $return['unsortedNum'] = $i; // Public - $result2 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE public = 1 " . $settings['sorting']); - $i = 0; + $result2 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE public = 1 " . $settings['sorting']); + $i = 0; while($row2 = $result2->fetch_object()) { if ($i<3) $return["publicThumb$i"] = $row2->thumbUrl; $i++; @@ -95,8 +99,8 @@ function getSmartInfo() { $return['publicNum'] = $i; // Starred - $result3 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE star = 1 " . $settings['sorting']); - $i = 0; + $result3 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE star = 1 " . $settings['sorting']); + $i = 0; while($row3 = $result3->fetch_object()) { if ($i<3) $return["starredThumb$i"] = $row3->thumbUrl; $i++; @@ -128,34 +132,33 @@ function getAlbum($albumID) { default: $result = $database->query("SELECT * FROM lychee_albums WHERE id = '$albumID';"); $row = $result->fetch_object(); - $return['title'] = $row->title; - $return['description'] = $row->description; - $return['sysdate'] = date('d M. Y', strtotime($row->sysdate)); - $return['public'] = $row->public; - if ($row->password=="") $return['password'] = false; - else $return['password'] = true; + $return['title'] = $row->title; + $return['description'] = $row->description; + $return['sysdate'] = date('d M. Y', strtotime($row->sysdate)); + $return['public'] = $row->public; + $return['password'] = ($row->password=="" ? false : true); $query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE album = '$albumID' " . $settings['sorting']; break; } // Get photos - $result = $database->query($query); - $previousPhotoID = ""; - $i = 0; + $result = $database->query($query); + $previousPhotoID = ""; + $i = 0; while($row = $result->fetch_array()) { - $return['content'][$row['id']]['id'] = $row['id']; - $return['content'][$row['id']]['title'] = $row['title']; - $return['content'][$row['id']]['sysdate'] = date('d F Y', strtotime($row['sysdate'])); - $return['content'][$row['id']]['public'] = $row['public']; - $return['content'][$row['id']]['star'] = $row['star']; - $return['content'][$row['id']]['tags'] = $row['tags']; - $return['content'][$row['id']]['album'] = $row['album']; - $return['content'][$row['id']]['thumbUrl'] = $row['thumbUrl']; + $return['content'][$row['id']]['id'] = $row['id']; + $return['content'][$row['id']]['title'] = $row['title']; + $return['content'][$row['id']]['sysdate'] = date('d F Y', strtotime($row['sysdate'])); + $return['content'][$row['id']]['public'] = $row['public']; + $return['content'][$row['id']]['star'] = $row['star']; + $return['content'][$row['id']]['tags'] = $row['tags']; + $return['content'][$row['id']]['album'] = $row['album']; + $return['content'][$row['id']]['thumbUrl'] = $row['thumbUrl']; - $return['content'][$row['id']]['previousPhoto'] = $previousPhotoID; - $return['content'][$row['id']]['nextPhoto'] = ""; + $return['content'][$row['id']]['previousPhoto'] = $previousPhotoID; + $return['content'][$row['id']]['nextPhoto'] = ""; if ($previousPhotoID!="") $return['content'][$previousPhotoID]['nextPhoto'] = $row['id']; $previousPhotoID = $row['id']; @@ -171,20 +174,20 @@ function getAlbum($albumID) { } else { // Enable next and previous for the first and last photo - $lastElement = end($return['content']); - $lastElementId = $lastElement['id']; - $firstElement = reset($return['content']); - $firstElementId = $firstElement['id']; + $lastElement = end($return['content']); + $lastElementId = $lastElement['id']; + $firstElement = reset($return['content']); + $firstElementId = $firstElement['id']; if ($lastElementId!==$firstElementId) { - $return['content'][$lastElementId]['nextPhoto'] = $firstElementId; - $return['content'][$firstElementId]['previousPhoto'] = $lastElementId; + $return['content'][$lastElementId]['nextPhoto'] = $firstElementId; + $return['content'][$firstElementId]['previousPhoto'] = $lastElementId; } } - $return['id'] = $albumID; - $return['num'] = $i; + $return['id'] = $albumID; + $return['num'] = $i; return $return; @@ -219,8 +222,8 @@ function deleteAlbum($albumIDs) { global $database; - $error = false; - $result = $database->query("SELECT id FROM lychee_photos WHERE album IN ($albumIDs);"); + $error = false; + $result = $database->query("SELECT id FROM lychee_photos WHERE album IN ($albumIDs);"); // Delete photos while ($row = $result->fetch_object()) @@ -252,10 +255,10 @@ function getAlbumArchive($albumID) { $zipTitle = "Unsorted"; } - $zip = new ZipArchive(); - $result = $database->query($query); - $files = array(); - $i=0; + $zip = new ZipArchive(); + $result = $database->query($query); + $files = array(); + $i = 0; while($row = $result->fetch_object()) { $files[$i] = "../uploads/big/".$row->url; @@ -293,15 +296,13 @@ function setAlbumPublic($albumID, $password) { global $database; - $result = $database->query("SELECT public FROM lychee_albums WHERE id = '$albumID';"); - $row = $result->fetch_object(); - if ($row->public == 0){ - $public = 1; - } else { - $public = 0; - } + $result = $database->query("SELECT public FROM lychee_albums WHERE id = '$albumID';"); + $row = $result->fetch_object(); + $public = ($row->public===0 ? 1 : 0); + $result = $database->query("UPDATE lychee_albums SET public = '$public', password = NULL WHERE id = '$albumID';"); if (!$result) return false; + if ($public==1) { $result = $database->query("UPDATE lychee_photos SET public = 0 WHERE album = '$albumID';"); if (!$result) return false; @@ -327,8 +328,8 @@ function checkAlbumPassword($albumID, $password) { global $database; - $result = $database->query("SELECT password FROM lychee_albums WHERE id = '$albumID';"); - $row = $result->fetch_object(); + $result = $database->query("SELECT password FROM lychee_albums WHERE id = '$albumID';"); + $row = $result->fetch_object(); if ($row->password=="") return true; else if ($row->password==$password) return true; @@ -340,8 +341,8 @@ function isAlbumPublic($albumID) { global $database; - $result = $database->query("SELECT public FROM lychee_albums WHERE id = '$albumID';"); - $row = $result->fetch_object(); + $result = $database->query("SELECT public FROM lychee_albums WHERE id = '$albumID';"); + $row = $result->fetch_object(); if ($row->public==1) return true; return false; diff --git a/php/modules/db.php b/php/modules/db.php index ddfd78a..fb80b7a 100755 --- a/php/modules/db.php +++ b/php/modules/db.php @@ -32,8 +32,8 @@ function dbConnect() { function dbCreateConfig($dbHost = 'localhost', $dbUser, $dbPassword, $dbName = 'lychee') { - $dbPassword = urldecode($dbPassword); - $database = new mysqli($dbHost, $dbUser, $dbPassword); + $dbPassword = urldecode($dbPassword); + $database = new mysqli($dbHost, $dbUser, $dbPassword); if ($database->connect_errno) return 'Warning: Connection failed!'; else { @@ -60,12 +60,9 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); ?>"; if (file_put_contents('../data/config.php', $config)===false) return 'Warning: Could not create file!'; - else { - - $_SESSION['login'] = true; - return true; - - } + + $_SESSION['login'] = true; + return true; } diff --git a/php/modules/misc.php b/php/modules/misc.php index a953c76..7991bd8 100755 --- a/php/modules/misc.php +++ b/php/modules/misc.php @@ -12,29 +12,31 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); function openGraphHeader($photoID) { global $database; - - if (!is_numeric($photoID)) return false; - $result = $database->query("SELECT * FROM lychee_photos WHERE id = '$photoID';"); - $row = $result->fetch_object(); - - $parseUrl = parse_url("http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); - $picture = $parseUrl['scheme']."://".$parseUrl['host'].$parseUrl['path']."/../uploads/big/".$row->url; - + + $photoID = mysqli_real_escape_string($database, $photoID); + if (!is_numeric($photoID)) return false; + + $result = $database->query("SELECT * FROM lychee_photos WHERE id = '$photoID';"); + $row = $result->fetch_object(); + + $parseUrl = parse_url("http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); + $picture = $parseUrl['scheme']."://".$parseUrl['host'].$parseUrl['path']."/../uploads/big/".$row->url; + $return = ''; $return .= ''; $return .= ''; $return .= ''; - + $return .= ''; $return .= ''; $return .= ''; $return .= ''; - + $return .= ''; $return .= ''; $return .= ''; - - return $return; + + return $return; } @@ -42,31 +44,35 @@ function search($term) { global $database, $settings; - $return["albums"] = ""; + $return['albums'] = ''; - $result = $database->query("SELECT * FROM lychee_photos WHERE title like '%$term%' OR description like '%$term%' OR tags like '%$term%';"); + // Photos + $result = $database->query("SELECT id, title, tags, sysdate, public, star, album, thumbUrl 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'])); + $return['photos'][$row['id']] = $row; + $return['photos'][$row['id']]['sysdate'] = date('d F Y', strtotime($row['sysdate'])); } + // Albums $result = $database->query("SELECT * FROM lychee_albums WHERE title like '%$term%' OR description like '%$term%';"); - $i=0; + $i = 0; while($row = $result->fetch_object()) { - $return["albums"][$row->id]['id'] = $row->id; - $return["albums"][$row->id]['title'] = $row->title; - $return["albums"][$row->id]['public'] = $row->public; - $return["albums"][$row->id]['sysdate'] = date('F Y', strtotime($row->sysdate)); - if ($row->password=="") $return["albums"][$row->id]['password'] = false; - else $return["albums"][$row->id]['password'] = true; + // Info + $return['albums'][$row->id]['id'] = $row->id; + $return['albums'][$row->id]['title'] = $row->title; + $return['albums'][$row->id]['public'] = $row->public; + $return['albums'][$row->id]['sysdate'] = date('F Y', strtotime($row->sysdate)); + $return['albums'][$row->id]['password'] = ($row->password=='' ? false : true); - $result2 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE album = '" . $row->id . "' " . $settings['sorting'] . " LIMIT 0, 3;"); - $k = 0; + // Thumbs + $result2 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE album = '" . $row->id . "' " . $settings['sorting'] . " LIMIT 0, 3;"); + $k = 0; while($row2 = $result2->fetch_object()){ $return['albums'][$row->id]["thumb$k"] = $row2->thumbUrl; $k++; } + $i++; } @@ -79,13 +85,13 @@ function update() { global $database; - if(!$database->query("SELECT `public` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `public` TINYINT( 1 ) NOT NULL DEFAULT '0'"); - if(!$database->query("SELECT `password` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `password` VARCHAR( 100 ) NULL DEFAULT ''"); - if(!$database->query("SELECT `description` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `description` VARCHAR( 1000 ) NULL DEFAULT ''"); - 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 `public` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `public` TINYINT( 1 ) NOT NULL DEFAULT '0'"); + if(!$database->query("SELECT `password` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `password` VARCHAR( 100 ) NULL DEFAULT ''"); + if(!$database->query("SELECT `description` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `description` VARCHAR( 1000 ) NULL DEFAULT ''"); + 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 `tags` FROM `lychee_photos` LIMIT 1;")) $database->query("ALTER TABLE `lychee_photos` ADD `tags` VARCHAR( 1000 ) 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 `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;"); @@ -95,17 +101,4 @@ function update() { } -function pageURL() { - - $pageURL = 'http'; - if (isset($_SERVER["HTTPS"])&&$_SERVER["HTTPS"]==="on") $pageURL .= "s"; - $pageURL .= "://"; - - if ($_SERVER["SERVER_PORT"]!="80") $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER['SCRIPT_NAME']; - else $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER['SCRIPT_NAME']; - - return $pageURL; - -} - ?> diff --git a/php/modules/photo.php b/php/modules/photo.php index e7ab28d..47b5f36 100755 --- a/php/modules/photo.php +++ b/php/modules/photo.php @@ -13,20 +13,7 @@ function getPhoto($photoID, $albumID) { global $database; - if (!is_numeric($photoID)) { - $result = $database->query("SELECT COUNT(*) AS quantity FROM lychee_photos WHERE import_name = '../uploads/import/$photoID';"); - $row = $result->fetch_object(); - if ($row->quantity == 0) { - importPhoto($photoID, 's'); - } - if (is_file("../uploads/import/$photoID")) { - importPhoto($photoID, 's'); - } - $query = "SELECT * FROM lychee_photos WHERE import_name = '../uploads/import/$photoID' ORDER BY ID DESC;"; - } else { - $query = "SELECT * FROM lychee_photos WHERE id = '$photoID';"; - } - + $query = "SELECT * FROM lychee_photos WHERE id = '$photoID';"; $result = $database->query($query); $return = $result->fetch_array(); @@ -40,9 +27,9 @@ function getPhoto($photoID, $albumID) { } - $return['original_album'] = $return['album']; - $return['album'] = $albumID; - $return['sysdate'] = date('d M. Y', strtotime($return['sysdate'])); + $return['original_album'] = $return['album']; + $return['album'] = $albumID; + $return['sysdate'] = date('d M. Y', strtotime($return['sysdate'])); if (strlen($return['takedate'])>0) $return['takedate'] = date('d M. Y', strtotime($return['takedate'])); } @@ -57,13 +44,9 @@ function setPhotoPublic($photoID, $url) { global $database; - $result = $database->query("SELECT public FROM lychee_photos WHERE id = '$photoID';"); - $row = $result->fetch_object(); - if ($row->public == 0){ - $public = 1; - } else { - $public = 0; - } + $result = $database->query("SELECT public FROM lychee_photos WHERE id = '$photoID';"); + $row = $result->fetch_object(); + $public = ($row->public==0 ? 1 : 0); $result = $database->query("UPDATE lychee_photos SET public = '$public' WHERE id = '$photoID';"); if (!$result) return false; @@ -75,14 +58,12 @@ function setPhotoStar($photoIDs) { global $database; - $error = false; - $result = $database->query("SELECT id, star FROM lychee_photos WHERE id IN ($photoIDs);"); + $error = false; + $result = $database->query("SELECT id, star FROM lychee_photos WHERE id IN ($photoIDs);"); while ($row = $result->fetch_object()) { - if ($row->star==0) $star = 1; - else $star = 0; - + $star = ($row->star==0 ? 1 : 0); $star = $database->query("UPDATE lychee_photos SET star = '$star' WHERE id = '$row->id';"); if (!$star) $error = true; @@ -122,6 +103,7 @@ function setPhotoDescription($photoID, $description) { $description = htmlentities($description); if (strlen($description)>1000) return false; + $result = $database->query("UPDATE lychee_photos SET description = '$description' WHERE id = '$photoID';"); if (!$result) return false; @@ -159,9 +141,9 @@ function deletePhoto($photoIDs) { $thumbUrl2x = $thumbUrl2x[0] . '@2x.' . $thumbUrl2x[1]; // Delete files - if (!unlink('../uploads/big/' . $row->url)) return false; - if (!unlink('../uploads/thumb/' . $row->thumbUrl)) return false; - if (!unlink('../uploads/thumb/' . $thumbUrl2x)) return false; + if (!unlink('../uploads/big/' . $row->url)) return false; + if (!unlink('../uploads/thumb/' . $row->thumbUrl)) return false; + if (!unlink('../uploads/thumb/' . $thumbUrl2x)) return false; // Delete db entry $delete = $database->query("DELETE FROM lychee_photos WHERE id = $row->id;"); @@ -178,20 +160,18 @@ function isPhotoPublic($photoID, $password) { global $database; - if (is_numeric($photoID)) { - $query = "SELECT * FROM lychee_photos WHERE id = '$photoID';"; - } else { - $query = "SELECT * FROM lychee_photos WHERE import_name = '../uploads/import/$photoID';"; - } - $result = $database->query($query); - $row = $result->fetch_object(); + $query = "SELECT * FROM lychee_photos WHERE id = '$photoID';"; + + $result = $database->query($query); + $row = $result->fetch_object(); + if (!is_numeric($photoID)&&!$row) return true; if ($row->public==1) return true; else { $cAP = checkAlbumPassword($row->album, $password); $iAP = isAlbumPublic($row->album); if ($iAP&&$cAP) return true; - else return false; + return false; } } @@ -200,8 +180,8 @@ function getPhotoArchive($photoID) { global $database; - $result = $database->query("SELECT * FROM lychee_photos WHERE id = '$photoID';"); - $row = $result->fetch_object(); + $result = $database->query("SELECT * FROM lychee_photos WHERE id = '$photoID';"); + $row = $result->fetch_object(); $extension = array_reverse(explode('.', $row->url)); diff --git a/php/modules/upload.php b/php/modules/upload.php index 14493c4..7ca5462 100755 --- a/php/modules/upload.php +++ b/php/modules/upload.php @@ -16,19 +16,19 @@ function upload($files, $albumID) { switch($albumID) { // s for public (share) case 's': - $public = 1; - $star = 0; - $albumID = 0; + $public = 1; + $star = 0; + $albumID = 0; break; // f for starred (fav) case 'f': - $star = 1; - $public = 0; - $albumID = 0; + $star = 1; + $public = 0; + $albumID = 0; break; default: - $star = 0; - $public = 0; + $star = 0; + $public = 0; } foreach ($files as $file) { @@ -41,15 +41,15 @@ function upload($files, $albumID) { $id = str_replace('.', '', microtime(true)); while(strlen($id)<14) $id .= 0; - $tmp_name = $file['tmp_name']; - $extension = array_reverse(explode('.', $file['name'])); - $extension = $extension[0]; - $photo_name = md5($id) . ".$extension"; + $tmp_name = $file['tmp_name']; + $extension = array_reverse(explode('.', $file['name'])); + $extension = $extension[0]; + $photo_name = md5($id) . ".$extension"; // Import if not uploaded via web if (!is_uploaded_file($tmp_name)) { if (copy($tmp_name, '../uploads/big/' . $photo_name)) { - unlink($tmp_name); + @unlink($tmp_name); $import_name = $tmp_name; } } else { @@ -63,7 +63,7 @@ function upload($files, $albumID) { // Use title of file if IPTC title missing if ($info['title']===''&& $settings['importFilename']==='1') - $info['title'] = mysqli_real_escape_string($database, substr(str_replace(".$extension", '', $file['name']), 0, 30)); + $info['title'] = mysqli_real_escape_string($database, substr(basename($file['name'], ".$extension"), 0, 30)); // Set orientation based on EXIF data if ($file['type']==='image/jpeg'&&isset($info['orientation'])&&isset($info['width'])&&isset($info['height'])) { @@ -167,16 +167,16 @@ function getInfo($filename) { global $database; - $url = '../uploads/big/' . $filename; - $iptcArray = array(); - $info = getimagesize($url, $iptcArray); + $url = '../uploads/big/' . $filename; + $iptcArray = array(); + $info = getimagesize($url, $iptcArray); // General information - $return['type'] = $info['mime']; - $return['width'] = $info[0]; - $return['height'] = $info[1]; - $return['date'] = date('d.m.Y', filectime($url)); - $return['time'] = date('H:i:s', filectime($url)); + $return['type'] = $info['mime']; + $return['width'] = $info[0]; + $return['height'] = $info[1]; + $return['date'] = date('d.m.Y', filectime($url)); + $return['time'] = date('H:i:s', filectime($url)); // Size $size = filesize($url)/1024; @@ -184,8 +184,8 @@ function getInfo($filename) { else $return['size'] = round($size, 1) . ' KB'; // IPTC Metadata Fallback - $return['title'] = ''; - $return['description'] = ''; + $return['title'] = ''; + $return['description'] = ''; // IPTC Metadata if(isset($iptcArray['APP13'])) { @@ -193,10 +193,10 @@ function getInfo($filename) { $iptcInfo = iptcparse($iptcArray['APP13']); if (is_array($iptcInfo)) { - $temp = $iptcInfo['2#105'][0]; + $temp = @$iptcInfo['2#105'][0]; if (isset($temp)&&strlen($temp)>0) $return['title'] = $temp; - $temp = $iptcInfo['2#120'][0]; + $temp = @$iptcInfo['2#120'][0]; if (isset($temp)&&strlen($temp)>0) $return['description'] = $temp; } @@ -204,46 +204,48 @@ function getInfo($filename) { } // EXIF Metadata Fallback - $return['orientation'] = ''; - $return['iso'] = ''; - $return['aperture'] = ''; - $return['make'] = ''; - $return['model'] = ''; - $return['shutter'] = ''; - $return['focal'] = ''; - $return['takeDate'] = ''; - $return['takeTime'] = ''; + $return['orientation'] = ''; + $return['iso'] = ''; + $return['aperture'] = ''; + $return['make'] = ''; + $return['model'] = ''; + $return['shutter'] = ''; + $return['focal'] = ''; + $return['takeDate'] = ''; + $return['takeTime'] = ''; + + // Read EXIF + if ($info['mime']=='image/jpeg') $exif = exif_read_data($url, 'EXIF', 0); + else $exif = false; // EXIF Metadata - if ($info['mime']=='image/jpeg'&&function_exists('exif_read_data')&&@exif_read_data($url, 'EXIF', 0)) { + if ($exif!==false) { - $exif = exif_read_data($url, 'EXIF', 0); - - $temp = $exif['Orientation']; + $temp = @$exif['Orientation']; if (isset($temp)) $return['orientation'] = $temp; - $temp = $exif['ISOSpeedRatings']; + $temp = @$exif['ISOSpeedRatings']; if (isset($temp)) $return['iso'] = $temp; - $temp = $exif['COMPUTED']['ApertureFNumber']; + $temp = @$exif['COMPUTED']['ApertureFNumber']; if (isset($temp)) $return['aperture'] = $temp; - $temp = $exif['Make']; + $temp = @$exif['Make']; if (isset($temp)) $return['make'] = $exif['Make']; - $temp = $exif['Model']; + $temp = @$exif['Model']; if (isset($temp)) $return['model'] = $temp; - $temp = $exif['ExposureTime']; + $temp = @$exif['ExposureTime']; if (isset($temp)) $return['shutter'] = $exif['ExposureTime'] . ' Sec.'; - $temp = $exif['FocalLength']; + $temp = @$exif['FocalLength']; if (isset($temp)) $return['focal'] = ($temp/1) . ' mm'; - $temp = $exif['DateTimeOriginal']; + $temp = @$exif['DateTimeOriginal']; if (isset($temp)) { - $exifDate = explode(' ', $temp); - $date = explode(':', $exifDate[0]); + $exifDate = explode(' ', $temp); + $date = explode(':', $exifDate[0]); $return['takeDate'] = $date[2].'.'.$date[1].'.'.$date[0]; $return['takeTime'] = $exifDate[1]; } @@ -261,24 +263,24 @@ function createThumb($filename, $width = 200, $height = 200) { global $settings; - $url = "../uploads/big/$filename"; - $info = getimagesize($url); + $url = "../uploads/big/$filename"; + $info = getimagesize($url); - $photoName = explode(".", $filename); - $newUrl = "../uploads/thumb/$photoName[0].jpeg"; - $newUrl2x = "../uploads/thumb/$photoName[0]@2x.jpeg"; + $photoName = explode(".", $filename); + $newUrl = "../uploads/thumb/$photoName[0].jpeg"; + $newUrl2x = "../uploads/thumb/$photoName[0]@2x.jpeg"; // Set position and size $thumb = imagecreatetruecolor($width, $height); $thumb2x = imagecreatetruecolor($width*2, $height*2); if ($info[0]<$info[1]) { - $newSize = $info[0]; - $startWidth = 0; - $startHeight = $info[1]/2 - $info[0]/2; + $newSize = $info[0]; + $startWidth = 0; + $startHeight = $info[1]/2 - $info[0]/2; } else { - $newSize = $info[1]; - $startWidth = $info[0]/2 - $info[1]/2; - $startHeight = 0; + $newSize = $info[1]; + $startWidth = $info[0]/2 - $info[1]/2; + $startHeight = 0; } // Fallback for older version @@ -286,10 +288,10 @@ function createThumb($filename, $width = 200, $height = 200) { // Create new image switch($info['mime']) { - case 'image/jpeg': $sourceImg = imagecreatefromjpeg($url); break; - case 'image/png': $sourceImg = imagecreatefrompng($url); break; - case 'image/gif': $sourceImg = imagecreatefromgif($url); break; - case 'image/webp': $sourceImg = imagecreatefromwebp($url); break; + case 'image/jpeg': $sourceImg = imagecreatefromjpeg($url); break; + case 'image/png': $sourceImg = imagecreatefrompng($url); break; + case 'image/gif': $sourceImg = imagecreatefromgif($url); break; + case 'image/webp': $sourceImg = imagecreatefromwebp($url); break; default: return false; } @@ -303,21 +305,19 @@ function createThumb($filename, $width = 200, $height = 200) { } -function importPhoto($name, $albumID = 0) { +function importPhoto($path, $albumID = 0) { - $tmp_name = "../uploads/import/$name"; - $info = getimagesize($tmp_name); - $size = filesize($tmp_name); - $nameFile = array(array()); - $nameFile[0]['name'] = $name; - $nameFile[0]['type'] = $info['mime']; - $nameFile[0]['tmp_name'] = $tmp_name; - $nameFile[0]['error'] = 0; - $nameFile[0]['size'] = $size; + $info = getimagesize($path); + $size = filesize($path); + + $nameFile = array(array()); + $nameFile[0]['name'] = $path; + $nameFile[0]['type'] = $info['mime']; + $nameFile[0]['tmp_name'] = $path; + $nameFile[0]['error'] = 0; + $nameFile[0]['size'] = $size; - if (upload($nameFile, $albumID)) return true; - - return false; + return upload($nameFile, $albumID); } @@ -338,6 +338,7 @@ function importUrl($url, $albumID = 0) { $pathinfo = pathinfo($key); $filename = $pathinfo['filename'].".".$pathinfo['extension']; $tmp_name = "../uploads/import/$filename"; + copy($key, $tmp_name); } @@ -357,7 +358,9 @@ function importUrl($url, $albumID = 0) { $pathinfo = pathinfo($url); $filename = $pathinfo['filename'].".".$pathinfo['extension']; $tmp_name = "../uploads/import/$filename"; + copy($url, $tmp_name); + return importPhoto($filename, $albumID); } @@ -368,23 +371,36 @@ function importUrl($url, $albumID = 0) { } -function importServer($albumID = 0) { +function importServer($albumID = 0, $path = '../uploads/import/') { global $database; - $i = 0; - $files = glob('../uploads/import/*'); + $files = glob($path . '*'); + $contains['photos'] = false; + $contains['albums'] = false; foreach ($files as $file) { if (@getimagesize($file)) { - if (!importPhoto(basename($file), $albumID)) return false; - $i++; + + // Photo + if (!importPhoto($file, $albumID)) return false; + $contains['photos'] = true; + + } else if (is_dir($file)) { + + $name = mysqli_real_escape_string($database, basename($file)); + $newAlbumID = addAlbum('[Import] ' . $name); + + if ($newAlbumID!==false) importServer($newAlbumID, $file . '/'); + $contains['albums'] = true; + } } - if ($i===0) return "Warning: Folder empty!"; + if ($contains['photos']===false&&$contains['albums']===false) return "Warning: Folder empty!"; + if ($contains['photos']===false&&$contains['albums']===true) return "Notice: Import only contains albums!"; return true; } From fda195f6fdf209ad14eab4cb27377fcdda35fb56 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 9 Feb 2014 22:39:12 +0100 Subject: [PATCH 43/87] Version push --- assets/js/modules/lychee.js | 2 +- assets/js/modules/settings.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/modules/lychee.js b/assets/js/modules/lychee.js index 462ab03..8e6ffa1 100644 --- a/assets/js/modules/lychee.js +++ b/assets/js/modules/lychee.js @@ -7,7 +7,7 @@ var lychee = { - version: "2.1", + version: "2.1 b1", api_path: "php/api.php", update_path: "http://lychee.electerious.com/version/index.php", diff --git a/assets/js/modules/settings.js b/assets/js/modules/settings.js index 52e51ad..48716ca 100644 --- a/assets/js/modules/settings.js +++ b/assets/js/modules/settings.js @@ -53,7 +53,7 @@ var settings = { ["Retry", function() { setTimeout(settings.createConfig, 400) }], ["", function() {}] ]; - modal.show("Saving Failed", "Unable to save this configuration. Permission denied in 'php/'. Please set the read, write and execute rights for others in 'php/' and 'uploads/'. Take a look the readme for more information.", buttons, null, false); + modal.show("Saving Failed", "Unable to save this configuration. Permission denied in 'data/'. Please set the read, write and execute rights for others in 'data/' and 'uploads/'. Take a look the readme for more information.", buttons, null, false); return false; } From 759ce874e724147d49b3ad5afd13183f721e5d0e Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Mon, 10 Feb 2014 18:04:34 +0100 Subject: [PATCH 44/87] MySQL select performance (#79) --- php/modules/album.php | 12 ++++++------ php/modules/misc.php | 4 ++-- php/modules/photo.php | 7 +++---- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/php/modules/album.php b/php/modules/album.php index a522172..66c6639 100755 --- a/php/modules/album.php +++ b/php/modules/album.php @@ -31,8 +31,8 @@ function getAlbums($public) { if (!$public) $return = getSmartInfo(); // Albums - if ($public) $query = "SELECT * FROM lychee_albums WHERE public = 1"; - else $query = "SELECT * FROM lychee_albums"; + if ($public) $query = "SELECT id, title, public, sysdate, password FROM lychee_albums WHERE public = 1"; + else $query = "SELECT id, title, public, sysdate, password FROM lychee_albums"; $result = $database->query($query) OR exit("Error: $result
".$database->error); $i = 0; @@ -243,15 +243,15 @@ function getAlbumArchive($albumID) { switch($albumID) { case 's': - $query = "SELECT * FROM lychee_photos WHERE public = '1';"; + $query = "SELECT url FROM lychee_photos WHERE public = '1';"; $zipTitle = "Public"; break; case 'f': - $query = "SELECT * FROM lychee_photos WHERE star = '1';"; + $query = "SELECT url FROM lychee_photos WHERE star = '1';"; $zipTitle = "Starred"; break; default: - $query = "SELECT * FROM lychee_photos WHERE album = '$albumID';"; + $query = "SELECT url FROM lychee_photos WHERE album = '$albumID';"; $zipTitle = "Unsorted"; } @@ -265,7 +265,7 @@ function getAlbumArchive($albumID) { $i++; } - $result = $database->query("SELECT * FROM lychee_albums WHERE id = '$albumID';"); + $result = $database->query("SELECT title FROM lychee_albums WHERE id = '$albumID' LIMIT 1;"); $row = $result->fetch_object(); if ($albumID!=0&&is_numeric($albumID)) $zipTitle = $row->title; $filename = "../data/$zipTitle.zip"; diff --git a/php/modules/misc.php b/php/modules/misc.php index 7991bd8..41768d7 100755 --- a/php/modules/misc.php +++ b/php/modules/misc.php @@ -16,7 +16,7 @@ function openGraphHeader($photoID) { $photoID = mysqli_real_escape_string($database, $photoID); if (!is_numeric($photoID)) return false; - $result = $database->query("SELECT * FROM lychee_photos WHERE id = '$photoID';"); + $result = $database->query("SELECT title, description, url FROM lychee_photos WHERE id = '$photoID';"); $row = $result->fetch_object(); $parseUrl = parse_url("http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); @@ -54,7 +54,7 @@ function search($term) { } // Albums - $result = $database->query("SELECT * FROM lychee_albums WHERE title like '%$term%' OR description like '%$term%';"); + $result = $database->query("SELECT id, title, public, sysdate, password FROM lychee_albums WHERE title like '%$term%' OR description like '%$term%';"); $i = 0; while($row = $result->fetch_object()) { diff --git a/php/modules/photo.php b/php/modules/photo.php index 47b5f36..dd2af21 100755 --- a/php/modules/photo.php +++ b/php/modules/photo.php @@ -132,7 +132,7 @@ function deletePhoto($photoIDs) { global $database; - $result = $database->query("SELECT * FROM lychee_photos WHERE id IN ($photoIDs);"); + $result = $database->query("SELECT id, url, thumbUrl FROM lychee_photos WHERE id IN ($photoIDs);"); while ($row = $result->fetch_object()) { @@ -160,12 +160,11 @@ function isPhotoPublic($photoID, $password) { global $database; - $query = "SELECT * FROM lychee_photos WHERE id = '$photoID';"; + $query = "SELECT public, album FROM lychee_photos WHERE id = '$photoID';"; $result = $database->query($query); $row = $result->fetch_object(); - if (!is_numeric($photoID)&&!$row) return true; if ($row->public==1) return true; else { $cAP = checkAlbumPassword($row->album, $password); @@ -180,7 +179,7 @@ function getPhotoArchive($photoID) { global $database; - $result = $database->query("SELECT * FROM lychee_photos WHERE id = '$photoID';"); + $result = $database->query("SELECT title, url FROM lychee_photos WHERE id = '$photoID';"); $row = $result->fetch_object(); $extension = array_reverse(explode('.', $row->url)); From 7c0c000880ec9391cf6fb477285595b5c01d4643 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 11 Feb 2014 12:36:06 +0100 Subject: [PATCH 45/87] Can not make albums public (#80) --- php/modules/album.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/modules/album.php b/php/modules/album.php index 66c6639..05a87f0 100755 --- a/php/modules/album.php +++ b/php/modules/album.php @@ -298,7 +298,7 @@ function setAlbumPublic($albumID, $password) { $result = $database->query("SELECT public FROM lychee_albums WHERE id = '$albumID';"); $row = $result->fetch_object(); - $public = ($row->public===0 ? 1 : 0); + $public = ($row->public=='0' ? 1 : 0); $result = $database->query("UPDATE lychee_albums SET public = '$public', password = NULL WHERE id = '$albumID';"); if (!$result) return false; From 8c9b97236b1d9131285c973032eb122b72ac7b91 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 14 Feb 2014 12:33:21 +0100 Subject: [PATCH 46/87] Check if JSON extension is activated (#81) --- plugins/check.php | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/check.php b/plugins/check.php index 4ba09dd..2455589 100644 --- a/plugins/check.php +++ b/plugins/check.php @@ -35,6 +35,7 @@ if (!extension_loaded('exif')) $error .= ('Error 300: PHP exif extension not act if (!extension_loaded('mbstring')) $error .= ('Error 301: PHP mbstring extension not activated' . PHP_EOL); if (!extension_loaded('gd')) $error .= ('Error 302: PHP gd extension not activated' . PHP_EOL); if (!extension_loaded('mysqli')) $error .= ('Error 303: PHP mysqli extension not activated' . PHP_EOL); +if (!extension_loaded('json')) $error .= ('Error 304: PHP json extension not activated' . PHP_EOL); // Config if (!isset($dbName)||$dbName=='') $error .= ('Error 400: No property for $dbName in config.php' . PHP_EOL); From bd5394024ba204777ba0ca0a8dd9ee450df6db76 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 14 Feb 2014 18:58:21 +0100 Subject: [PATCH 47/87] Return false for smart albums --- php/modules/album.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/php/modules/album.php b/php/modules/album.php index 05a87f0..8ff43bb 100755 --- a/php/modules/album.php +++ b/php/modules/album.php @@ -340,10 +340,11 @@ function checkAlbumPassword($albumID, $password) { function isAlbumPublic($albumID) { global $database; - + $result = $database->query("SELECT public FROM lychee_albums WHERE id = '$albumID';"); $row = $result->fetch_object(); + if ($albumID==='0'||$albumID==='s'||$albumID==='f') return false; if ($row->public==1) return true; return false; From 75d175b9ccb37ecdd1fd4aa767a0be6132f10c98 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 14 Feb 2014 19:03:26 +0100 Subject: [PATCH 48/87] Fixed an error when try to visit non-public albums --- assets/js/modules/album.js | 9 ++++++++- assets/js/modules/lychee.js | 1 + assets/js/modules/view.js | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/assets/js/modules/album.js b/assets/js/modules/album.js index adb1108..2fea995 100644 --- a/assets/js/modules/album.js +++ b/assets/js/modules/album.js @@ -46,7 +46,14 @@ album = { lychee.api(params, function(data) { if (data==="Warning: Album private!") { - lychee.setMode("view"); + if (document.location.hash.replace("#", "").split("/")[1]!=undefined) { + // Display photo only + lychee.setMode("view"); + } else { + // Album not public + lychee.content.show(); + lychee.goto(""); + } return false; } diff --git a/assets/js/modules/lychee.js b/assets/js/modules/lychee.js index 8e6ffa1..f611fea 100644 --- a/assets/js/modules/lychee.js +++ b/assets/js/modules/lychee.js @@ -257,6 +257,7 @@ var lychee = { Mousetrap.unbind('esc'); $("#button_back, a#next, a#previous").remove(); + $(".no_content").remove(); lychee.publicMode = true; lychee.viewMode = true; diff --git a/assets/js/modules/view.js b/assets/js/modules/view.js index 122ed89..fd498a3 100644 --- a/assets/js/modules/view.js +++ b/assets/js/modules/view.js @@ -458,8 +458,8 @@ view = { lychee.imageview.html(build.imageview(photo.json, photo.isSmall(), visible.controls())); - if ((album.json&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].nextPhoto==="")||lychee.viewMode) $("a#next").hide(); - if ((album.json&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].previousPhoto==="")||lychee.viewMode) $("a#previous").hide(); + if ((album.json&&album.json.content&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].nextPhoto==="")||lychee.viewMode) $("a#next").hide(); + if ((album.json&&album.json.content&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].previousPhoto==="")||lychee.viewMode) $("a#previous").hide(); }, From a06bc1786a8aea5b583571925c1484631d9a9786 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 14 Feb 2014 19:04:02 +0100 Subject: [PATCH 49/87] Improved position of the edit icon for tags --- assets/css/modules/infobox.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/assets/css/modules/infobox.css b/assets/css/modules/infobox.css index 96bf44b..8965464 100644 --- a/assets/css/modules/infobox.css +++ b/assets/css/modules/infobox.css @@ -140,6 +140,15 @@ font-size: 14px; margin-bottom: 8px; } + + #infobox #tags .edit { + display: inline-block; + } + + #infobox #tags .empty .edit { + display: inline; + } + #infobox .tag { float: left; padding: 4px 7px; From 49fd3967b6e27952e594bf97f3352b281e5b3b8e Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 14 Feb 2014 19:08:07 +0100 Subject: [PATCH 50/87] Removed importFilename setting --- docs/md/Settings.md | 8 +------- php/modules/db.php | 3 +-- php/modules/misc.php | 3 --- php/modules/upload.php | 5 ++--- 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/docs/md/Settings.md b/docs/md/Settings.md index 3b7adb4..adc4c58 100644 --- a/docs/md/Settings.md +++ b/docs/md/Settings.md @@ -38,10 +38,4 @@ If `1`, Lychee will check if you are using the latest version. The notice will b sorting = ORDER BY [row] [ASC|DESC] -A typical part of a MySQL statement. This string will be appended to mostly every MySQL query. - -#### Import Filename - - importFilename = [0|1] - -If `1`, Lychee will import the filename of the upload file. \ No newline at end of file +A typical part of a MySQL statement. This string will be appended to mostly every MySQL query. \ No newline at end of file diff --git a/php/modules/db.php b/php/modules/db.php index fb80b7a..7680fc9 100755 --- a/php/modules/db.php +++ b/php/modules/db.php @@ -101,8 +101,7 @@ function dbCreateTables($database) { ('password',''), ('thumbQuality','90'), ('checkForUpdates','1'), - ('sorting','ORDER BY id DESC'), - ('importFilename','1'); + ('sorting','ORDER BY id DESC'); "; diff --git a/php/modules/misc.php b/php/modules/misc.php index 41768d7..0678fce 100755 --- a/php/modules/misc.php +++ b/php/modules/misc.php @@ -93,9 +93,6 @@ function update() { 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 `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;"); - if ($result->fetch_object()!==true) $database->query("INSERT INTO `lychee_settings` (`key`, `value`) VALUES ('importFilename', '1')"); return true; diff --git a/php/modules/upload.php b/php/modules/upload.php index 7ca5462..3cda662 100755 --- a/php/modules/upload.php +++ b/php/modules/upload.php @@ -61,9 +61,8 @@ function upload($files, $albumID) { $info = getInfo($photo_name); // Use title of file if IPTC title missing - if ($info['title']===''&& - $settings['importFilename']==='1') - $info['title'] = mysqli_real_escape_string($database, substr(basename($file['name'], ".$extension"), 0, 30)); + if ($info['title']==='') + $info['title'] = mysqli_real_escape_string($database, substr(basename($file['name'], ".$extension"), 0, 30)); // Set orientation based on EXIF data if ($file['type']==='image/jpeg'&&isset($info['orientation'])&&isset($info['width'])&&isset($info['height'])) { From 191544080713a7c2688ab42857a9e95ea8b1fec8 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 14 Feb 2014 19:08:33 +0100 Subject: [PATCH 51/87] Version push --- assets/js/modules/lychee.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/modules/lychee.js b/assets/js/modules/lychee.js index f611fea..6429ff2 100644 --- a/assets/js/modules/lychee.js +++ b/assets/js/modules/lychee.js @@ -7,7 +7,7 @@ var lychee = { - version: "2.1 b1", + version: "2.1 b2", api_path: "php/api.php", update_path: "http://lychee.electerious.com/version/index.php", From 61ec06e3f8daa39aecaf7e1412e9d6bc5414d737 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 14 Feb 2014 20:02:07 +0100 Subject: [PATCH 52/87] Added Update.md --- docs/md/Update.md | 11 +++++++++++ readme.md | 3 +-- 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 docs/md/Update.md diff --git a/docs/md/Update.md b/docs/md/Update.md new file mode 100644 index 0000000..98d8190 --- /dev/null +++ b/docs/md/Update.md @@ -0,0 +1,11 @@ +### Update with `git` + +The easiest way to update Lychee is with `git`: + + git pull + +### Update manually + +1. Download the [newest Version](https://github.com/electerious/Lychee/archive/master.zip) +2. Replace all existing files, excluding `uploads/` and `data/` +3. Open Lychee (and enter your database details) \ No newline at end of file diff --git a/readme.md b/readme.md index a2ce1e6..1fdf47a 100644 --- a/readme.md +++ b/readme.md @@ -21,8 +21,7 @@ Sign in and click the gear on the top left corner to change your settings. If yo ### Update -1. Replace all files, excluding `uploads/` and `data/` -2. Open Lychee and enter your database details +Updating is as easy as it should be. [Update »](docs/md/Update.md) ### FTP Upload From ebce9ec649a65a21a4e9c9a1510d811b41315f59 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 14 Feb 2014 20:02:36 +0100 Subject: [PATCH 53/87] Removed unused file --- docs/install.sh | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 docs/install.sh diff --git a/docs/install.sh b/docs/install.sh deleted file mode 100644 index c9efd35..0000000 --- a/docs/install.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh - -VERSION='2.0' - -echo 'Press ENTER to continue or any other key to abort' -read -s -n 1 key - -if [[ "$key" = "" ]] -then - - if [ -e Lychee-$VERSION ] - then - - echo "The folder 'Lychee-$VERSION' already exists. Please delete it before you try to install Lychee." - exit 1 - - fi - - if [ -e lychee ] - then - - echo "The folder 'lychee' already exists. Please delete it before you try to install Lychee." - exit 1 - - fi - - echo 'Downloading and installing Lychee...' && \ - curl -sS https://codeload.github.com/electerious/Lychee/zip/v$VERSION > lychee.zip && \ - echo 'Downloaded.' && \ - echo 'Unzipping...' && \ - unzip lychee.zip && \ - rm lychee.zip && \ - mv Lychee-$VERSION lychee && \ - cd lychee && \ - echo 'The required directories will be made writable and executable for others. Please enter your password if prompted to do so.' && \ - sudo chmod -R 777 uploads php && \ - echo 'Installation successful!' && \ - exit 0 - -fi \ No newline at end of file From ad4f80d76add08995757cd1a3f93c32f45885648 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Fri, 14 Feb 2014 20:02:58 +0100 Subject: [PATCH 54/87] Improved Installation.md --- docs/md/Installation.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/md/Installation.md b/docs/md/Installation.md index 1e14e40..b9f57e7 100644 --- a/docs/md/Installation.md +++ b/docs/md/Installation.md @@ -1,7 +1,7 @@ -### Requirements +### 1. Requirements Everything you need is a web-server with PHP 5.3 or later and a MySQL-Database. -### PHP configuration `php.ini` +### 2. PHP configuration `php.ini` The following extensions must be activated: @@ -17,7 +17,7 @@ To use Lychee without restrictions, we recommend to increase the values of the f upload_max_filesize = 20M max_file_uploads = 100 -### Download Lychee +### 3. Download The easiest way to download Lychee is with `git`: @@ -25,13 +25,13 @@ The easiest way to download Lychee is with `git`: You can also use the [direct download](https://github.com/electerious/Lychee/archive/master.zip). -### Folder permissions +### 4. Permissions Change the permissions of `uploads/` and `data/` to 777, including all subfolders: chmod -R 777 uploads/ data/ -### Lychee installation +### 5. Finish Open Lychee in your browser and follow the given steps. If you have trouble, take a look at the [FAQ](FAQ.md). \ No newline at end of file From 48158f0d23e5af0b3b07e9c2c62833766b4dd638 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 15 Feb 2014 21:30:29 +0100 Subject: [PATCH 55/87] Compressed files --- assets/css/min/main.css | 2 +- assets/js/min/main.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/assets/css/min/main.css b/assets/css/min/main.css index 31702ad..f95629c 100644 --- a/assets/css/min/main.css +++ b/assets/css/min/main.css @@ -1 +1 @@ -.fadeIn{-webkit-animation-name:fadeIn;-moz-animation-name:fadeIn;animation-name:fadeIn}.fadeIn,.fadeOut{-webkit-animation-duration:.3s;-webkit-animation-fill-mode:forwards;-moz-animation-duration:.3s;-moz-animation-fill-mode:forwards;animation-duration:.3s;animation-fill-mode:forwards}.fadeOut{-webkit-animation-name:fadeOut;-moz-animation-name:fadeOut;animation-name:fadeOut}.contentZoomIn{-webkit-animation-name:zoomIn;-moz-animation-name:zoomIn;animation-name:zoomIn}.contentZoomIn,.contentZoomOut{-webkit-animation-duration:.2s;-webkit-animation-fill-mode:forwards;-moz-animation-duration:.2s;-moz-animation-fill-mode:forwards;animation-duration:.2s;animation-fill-mode:forwards}.contentZoomOut{-webkit-animation-name:zoomOut;-moz-animation-name:zoomOut;animation-name:zoomOut}@-webkit-keyframes moveUp{0%{-webkit-transform:translateY(30px);opacity:0}100%{-webkit-transform:translateY(0);opacity:1}}@-moz-keyframes moveUp{0%{opacity:0}100%{opacity:1}}@keyframes moveUp{0%{transform:translateY(30px);opacity:0}100%{transform:translateY(0);opacity:1}}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-moz-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-moz-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-webkit-keyframes moveBackground{0%{background-position-x:0}100%{background-position-x:-100px}}@-moz-keyframes moveBackground{0%{background-position-x:0}100%{background-position-x:-100px}}@keyframes moveBackground{0%{background-position-x:0}100%{background-position-x:-100px}}@-webkit-keyframes zoomIn{0%{opacity:0;-webkit-transform:scale(.8)}100%{opacity:1;-webkit-transform:scale(1)}}@-moz-keyframes zoomIn{0%{opacity:0}100%{opacity:1}}@keyframes zoomIn{0%{opacity:0;transform:scale(.8)}100%{opacity:1;transform:scale(1)}}@-webkit-keyframes zoomOut{0%{opacity:1;-webkit-transform:scale(1)}100%{opacity:0;-webkit-transform:scale(.8)}}@-moz-keyframes zoomOut{0%{opacity:1}100%{opacity:0}}@keyframes zoomOut{0%{opacity:1;transform:scale(1)}100%{opacity:0;transform:scale(.8)}}@-webkit-keyframes popIn{0%{opacity:0;-webkit-transform:scale(0)}100%{opacity:1;-webkit-transform:scale(1)}}@-moz-keyframes popIn{0%{opacity:0;-moz-transform:scale(0)}100%{opacity:1;-moz-transform:scale(1)}}@keyframes popIn{0%{opacity:0;transform:scale(0)}100%{opacity:1;transform:scale(1)}}@-webkit-keyframes pulse{0%{opacity:1}50%{opacity:.3}100%{opacity:1}}@-moz-keyframes pulse{0%{opacity:1}50%{opacity:.8}100%{opacity:1}}@keyframes pulse{0%{opacity:1}50%{opacity:.8}100%{opacity:1}}#content::before{content:"";position:absolute;left:0;width:100%;height:20px;background-image:-webkit-linear-gradient(top,#262626,#222);background-image:-moz-linear-gradient(top,#262626,#222);background-image:-ms-linear-gradient(top,#262626,#222);background-image:linear-gradient(top,#262626,#222);border-top:1px solid #333}#content.view::before{display:none}#content{position:absolute;padding:50px 0 33px;width:100%;-webkit-overflow-scrolling:touch}.photo{float:left;display:inline-block;width:206px;height:206px;margin:30px 0 0 30px;cursor:pointer}.photo img{position:absolute;width:200px;height:200px;background-color:#222;border-radius:2px;border:2px solid #ccc}.photo:hover img,.photo.active img{box-shadow:0 0 5px #005ecc}.photo:active{-webkit-transition-duration:.1s;-webkit-transform:scale(.98);-moz-transition-duration:.1s;-moz-transform:scale(.98);transition-duration:.1s;transform:scale(.98)}.album{float:left;display:inline-block;width:204px;height:204px;margin:30px 0 0 30px;cursor:pointer}.album img:first-child,.album img:nth-child(2){-webkit-transform:rotate(0)translateY(0)translateX(0);-moz-transform:rotate(0)translateY(0)translateX(0);transform:rotate(0)translateY(0)translateX(0);opacity:0}.album:hover img:first-child{-webkit-transform:rotate(-2deg)translateY(10px)translateX(-12px);-moz-transform:rotate(-2deg)translateY(10px)translateX(-12px);transform:rotate(-2deg)translateY(10px)translateX(-12px);opacity:1}.album:hover img:nth-child(2){-webkit-transform:rotate(5deg)translateY(-8px)translateX(12px);-moz-transform:rotate(5deg)translateY(-8px)translateX(12px);transform:rotate(5deg)translateY(-8px)translateX(12px);opacity:1}.album img{position:absolute;width:200px;height:200px;background-color:#222;border-radius:2px;border:2px solid #ccc}.album:hover img,.album.active img{box-shadow:0 0 5px #005ecc}.album .overlay,.photo .overlay{position:absolute;width:200px;height:200px;margin:2px}.album .overlay{background:-moz-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%);background:-webkit-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%);background:-ms-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%);background:linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%)}.photo .overlay{background:rgba(0,0,0,.6);opacity:0}.photo:hover .overlay,.photo.active .overlay{opacity:1}.album .overlay h1,.photo .overlay h1{min-height:19px;width:190px;margin:153px 0 3px 15px;color:#fff;font-size:16px;font-weight:700;overflow:hidden}.album .overlay a,.photo .overlay a{font-size:11px;color:#aaa}.album .overlay a{margin-left:15px}.photo .overlay a{margin:155px 0 5px 15px}.album .badge,.photo .badge{position:absolute;margin-top:-1px;margin-left:12px;padding:12px 7px 3px;box-shadow:0 0 3px #000;border-radius:0 0 3px 3px;border:1px solid #fff;border-top:none;color:#fff;font-size:24px;text-shadow:0 1px 0 #000;opacity:.9}.album .badge.icon-star,.photo .badge.icon-star{padding:12px 8px 3px}.album .badge.icon-share,.photo .badge.icon-share{padding:12px 6px 3px 8px}.album .badge::after,.photo .badge::after{content:"";position:absolute;margin-top:-12px;margin-left:-26px;width:38px;height:5px;background:-moz-linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);background:-webkit-linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);background:-ms-linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);background:linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);opacity:.4}.album .badge.icon-star::after,.photo .badge.icon-star::after{margin-left:-29px}.album .badge.icon-share::after,.photo .badge.icon-share::after{margin-left:-31px}.album .badge.icon-reorder::after{margin-left:-30px}.album .badge:nth-child(2n),.photo .badge:nth-child(2n){margin-left:57px}.album .badge.red,.photo .badge.red{background:#d64b4b;background:-webkit-linear-gradient(top,#d64b4b,#ab2c2c);background:-moz-linear-gradient(top,#d64b4b,#ab2c2c);background:-ms-linear-gradient(top,#d64b4b,#ab2c2c)}.album .badge.blue,.photo .badge.blue{background:#d64b4b;background:-webkit-linear-gradient(top,#347cd6,#2945ab);background:-moz-linear-gradient(top,#347cd6,#2945ab);background:-ms-linear-gradient(top,#347cd6,#2945ab)}.divider{float:left;width:100%;margin-top:50px;opacity:0;border-top:1px solid #2E2E2E;box-shadow:0 -1px 0 #151515}.divider:first-child{margin-top:0;border-top:none}.divider h1{float:left;margin:20px 0 0 30px;color:#fff;font-size:14px;font-weight:700;text-shadow:0 -1px 0 #000}.no_content{position:absolute;top:50%;left:50%;height:160px;width:180px;margin-top:-80px;margin-left:-90px;padding-top:20px;color:rgba(20,20,20,1);text-shadow:0 1px 0 rgba(255,255,255,.05);text-align:center}.no_content .icon{font-size:120px}.no_content p{font-size:18px}.contextmenu_bg{position:fixed;height:100%;width:100%;z-index:1000}.contextmenu{position:fixed;top:0;left:0;padding:5px 0 6px;background-color:#393939;background-image:-webkit-linear-gradient(top,#444,#2d2d2d);background-image:-moz-linear-gradient(top,#393939,#2d2d2d);background-image:-ms-linear-gradient(top,#393939,#2d2d2d);background-image:linear-gradient(top,#393939,#2d2d2d);border:1px solid rgba(0,0,0,.7);border-bottom:1px solid rgba(0,0,0,.9);border-radius:5px;box-shadow:0 4px 5px rgba(0,0,0,.3),inset 0 1px 0 rgba(255,255,255,.15),inset 1px 0 0 rgba(255,255,255,.05),inset -1px 0 0 rgba(255,255,255,.05);opacity:0;z-index:1001;-webkit-transition:none;-moz-transition:none;transition:none}.contextmenu tr{font-size:14px;color:#eee;text-shadow:0 -1px 0 rgba(0,0,0,.6);cursor:pointer}.contextmenu tr:hover{background-color:#6a84f2;background-image:-webkit-linear-gradient(top,#6a84f2,#3959ef);background-image:-moz-linear-gradient(top,#6a84f2,#3959ef);background-image:-ms-linear-gradient(top,#6a84f2,#3959ef);background-image:linear-gradient(top,#6a84f2,#3959ef)}.contextmenu tr.no_hover:hover{cursor:inherit;background-color:inherit;background-image:none}.contextmenu tr.separator{float:left;height:1px;width:100%;background-color:#1c1c1c;border-bottom:1px solid #4a4a4a;margin:5px 0;cursor:inherit}.contextmenu tr.separator:hover{background-color:#222;background-image:none}.contextmenu tr td{padding:7px 30px 6px 12px;white-space:nowrap;-webkit-transition:none;-moz-transition:none;transition:none}.contextmenu tr:hover td{color:#fff;box-shadow:inset 0 1px 0 rgba(255,255,255,.05);text-shadow:0 -1px 0 rgba(0,0,0,.4)}.contextmenu tr.no_hover:hover td{box-shadow:none}.contextmenu tr a{float:left;width:10px;margin-right:10px;text-align:center}.contextmenu #link{float:right;width:140px;margin:0 -17px -1px 0;padding:4px 6px 5px;background-color:#444;color:#fff;border:1px solid #111;box-shadow:0 1px 0 rgba(255,255,255,.1);outline:none;border-radius:5px}.contextmenu tr a#link_icon{padding-top:4px}@font-face{font-family:'FontAwesome';src:url('../../font/fontawesome-webfont.eot');src:url('../../font/fontawesome-webfont.eot?#iefix') format('eot'),url('../../font/fontawesome-webfont.woff') format('woff'),url('../../font/fontawesome-webfont.ttf') format('truetype'),url('../../font/fontawesome-webfont.svg#FontAwesome') format('svg');font-weight:400;font-style:normal}[class^="icon-"]:before,[class*=" icon-"]:before{font-family:FontAwesome;font-weight:400;font-style:normal;display:inline-block;text-decoration:inherit}a [class^="icon-"],a [class*=" icon-"]{display:inline-block;text-decoration:inherit}.icon-large:before{vertical-align:top;font-size:1.3333333333333333em}.btn [class^="icon-"],.btn [class*=" icon-"]{line-height:.9em}li [class^="icon-"],li [class*=" icon-"]{display:inline-block;width:1.25em;text-align:center}li .icon-large[class^="icon-"],li .icon-large[class*=" icon-"]{width:1.875em}li[class^="icon-"],li[class*=" icon-"]{margin-left:0;list-style-type:none}li[class^="icon-"]:before,li[class*=" icon-"]:before{text-indent:-2em;text-align:center}li[class^="icon-"].icon-large:before,li[class*=" icon-"].icon-large:before{text-indent:-1.3333333333333333em}.icon-glass:before{content:"\f000"}.icon-music:before{content:"\f001"}.icon-search:before{content:"\f002"}.icon-envelope:before{content:"\f003"}.icon-heart:before{content:"\f004"}.icon-star:before{content:"\f005"}.icon-star-empty:before{content:"\f006"}.icon-user:before{content:"\f007"}.icon-film:before{content:"\f008"}.icon-th-large:before{content:"\f009"}.icon-th:before{content:"\f00a"}.icon-th-list:before{content:"\f00b"}.icon-ok:before{content:"\f00c"}.icon-remove:before{content:"\f00d"}.icon-zoom-in:before{content:"\f00e"}.icon-zoom-out:before{content:"\f010"}.icon-off:before{content:"\f011"}.icon-signal:before{content:"\f012"}.icon-cog:before{content:"\f013"}.icon-trash:before{content:"\f014"}.icon-home:before{content:"\f015"}.icon-file:before{content:"\f016"}.icon-time:before{content:"\f017"}.icon-road:before{content:"\f018"}.icon-download-alt:before{content:"\f019"}.icon-download:before{content:"\f01a"}.icon-upload:before{content:"\f01b"}.icon-inbox:before{content:"\f01c"}.icon-play-circle:before{content:"\f01d"}.icon-repeat:before{content:"\f01e"}.icon-refresh:before{content:"\f021"}.icon-list-alt:before{content:"\f022"}.icon-lock:before{content:"\f023"}.icon-flag:before{content:"\f024"}.icon-headphones:before{content:"\f025"}.icon-volume-off:before{content:"\f026"}.icon-volume-down:before{content:"\f027"}.icon-volume-up:before{content:"\f028"}.icon-qrcode:before{content:"\f029"}.icon-barcode:before{content:"\f02a"}.icon-tag:before{content:"\f02b"}.icon-tags:before{content:"\f02c"}.icon-book:before{content:"\f02d"}.icon-bookmark:before{content:"\f02e"}.icon-print:before{content:"\f02f"}.icon-camera:before{content:"\f030"}.icon-font:before{content:"\f031"}.icon-bold:before{content:"\f032"}.icon-italic:before{content:"\f033"}.icon-text-height:before{content:"\f034"}.icon-text-width:before{content:"\f035"}.icon-align-left:before{content:"\f036"}.icon-align-center:before{content:"\f037"}.icon-align-right:before{content:"\f038"}.icon-align-justify:before{content:"\f039"}.icon-list:before{content:"\f03a"}.icon-indent-left:before{content:"\f03b"}.icon-indent-right:before{content:"\f03c"}.icon-facetime-video:before{content:"\f03d"}.icon-picture:before{content:"\f03e"}.icon-pencil:before{content:"\f040"}.icon-map-marker:before{content:"\f041"}.icon-adjust:before{content:"\f042"}.icon-tint:before{content:"\f043"}.icon-edit:before{content:"\f044"}.icon-share:before{content:"\f045"}.icon-check:before{content:"\f046"}.icon-move:before{content:"\f047"}.icon-step-backward:before{content:"\f048"}.icon-fast-backward:before{content:"\f049"}.icon-backward:before{content:"\f04a"}.icon-play:before{content:"\f04b"}.icon-pause:before{content:"\f04c"}.icon-stop:before{content:"\f04d"}.icon-forward:before{content:"\f04e"}.icon-fast-forward:before{content:"\f050"}.icon-step-forward:before{content:"\f051"}.icon-eject:before{content:"\f052"}.icon-chevron-left:before{content:"\f053"}.icon-chevron-right:before{content:"\f054"}.icon-plus-sign:before{content:"\f055"}.icon-minus-sign:before{content:"\f056"}.icon-remove-sign:before{content:"\f057"}.icon-ok-sign:before{content:"\f058"}.icon-question-sign:before{content:"\f059"}.icon-info-sign:before{content:"\f05a"}.icon-screenshot:before{content:"\f05b"}.icon-remove-circle:before{content:"\f05c"}.icon-ok-circle:before{content:"\f05d"}.icon-ban-circle:before{content:"\f05e"}.icon-arrow-left:before{content:"\f060"}.icon-arrow-right:before{content:"\f061"}.icon-arrow-up:before{content:"\f062"}.icon-arrow-down:before{content:"\f063"}.icon-share-alt:before{content:"\f064"}.icon-resize-full:before{content:"\f065"}.icon-resize-small:before{content:"\f066"}.icon-plus:before{content:"\f067"}.icon-minus:before{content:"\f068"}.icon-asterisk:before{content:"\f069"}.icon-exclamation-sign:before{content:"\f06a"}.icon-gift:before{content:"\f06b"}.icon-leaf:before{content:"\f06c"}.icon-fire:before{content:"\f06d"}.icon-eye-open:before{content:"\f06e"}.icon-eye-close:before{content:"\f070"}.icon-warning-sign:before{content:"\f071"}.icon-plane:before{content:"\f072"}.icon-calendar:before{content:"\f073"}.icon-random:before{content:"\f074"}.icon-comment:before{content:"\f075"}.icon-magnet:before{content:"\f076"}.icon-chevron-up:before{content:"\f077"}.icon-chevron-down:before{content:"\f078"}.icon-retweet:before{content:"\f079"}.icon-shopping-cart:before{content:"\f07a"}.icon-folder-close:before{content:"\f07b"}.icon-folder-open:before{content:"\f07c"}.icon-resize-vertical:before{content:"\f07d"}.icon-resize-horizontal:before{content:"\f07e"}.icon-bar-chart:before{content:"\f080"}.icon-twitter-sign:before{content:"\f081"}.icon-facebook-sign:before{content:"\f082"}.icon-camera-retro:before{content:"\f083"}.icon-key:before{content:"\f084"}.icon-cogs:before{content:"\f085"}.icon-comments:before{content:"\f086"}.icon-thumbs-up:before{content:"\f087"}.icon-thumbs-down:before{content:"\f088"}.icon-star-half:before{content:"\f089"}.icon-heart-empty:before{content:"\f08a"}.icon-signout:before{content:"\f08b"}.icon-linkedin-sign:before{content:"\f08c"}.icon-pushpin:before{content:"\f08d"}.icon-external-link:before{content:"\f08e"}.icon-signin:before{content:"\f090"}.icon-trophy:before{content:"\f091"}.icon-github-sign:before{content:"\f092"}.icon-upload-alt:before{content:"\f093"}.icon-lemon:before{content:"\f094"}.icon-phone:before{content:"\f095"}.icon-check-empty:before{content:"\f096"}.icon-bookmark-empty:before{content:"\f097"}.icon-phone-sign:before{content:"\f098"}.icon-twitter:before{content:"\f099"}.icon-facebook:before{content:"\f09a"}.icon-github:before{content:"\f09b"}.icon-unlock:before{content:"\f09c"}.icon-credit-card:before{content:"\f09d"}.icon-rss:before{content:"\f09e"}.icon-hdd:before{content:"\f0a0"}.icon-bullhorn:before{content:"\f0a1"}.icon-bell:before{content:"\f0a2"}.icon-certificate:before{content:"\f0a3"}.icon-hand-right:before{content:"\f0a4"}.icon-hand-left:before{content:"\f0a5"}.icon-hand-up:before{content:"\f0a6"}.icon-hand-down:before{content:"\f0a7"}.icon-circle-arrow-left:before{content:"\f0a8"}.icon-circle-arrow-right:before{content:"\f0a9"}.icon-circle-arrow-up:before{content:"\f0aa"}.icon-circle-arrow-down:before{content:"\f0ab"}.icon-globe:before{content:"\f0ac"}.icon-wrench:before{content:"\f0ad"}.icon-tasks:before{content:"\f0ae"}.icon-filter:before{content:"\f0b0"}.icon-briefcase:before{content:"\f0b1"}.icon-fullscreen:before{content:"\f0b2"}.icon-group:before{content:"\f0c0"}.icon-link:before{content:"\f0c1"}.icon-cloud:before{content:"\f0c2"}.icon-beaker:before{content:"\f0c3"}.icon-cut:before{content:"\f0c4"}.icon-copy:before{content:"\f0c5"}.icon-paper-clip:before{content:"\f0c6"}.icon-save:before{content:"\f0c7"}.icon-sign-blank:before{content:"\f0c8"}.icon-reorder:before{content:"\f0c9"}.icon-list-ul:before{content:"\f0ca"}.icon-list-ol:before{content:"\f0cb"}.icon-strikethrough:before{content:"\f0cc"}.icon-underline:before{content:"\f0cd"}.icon-table:before{content:"\f0ce"}.icon-magic:before{content:"\f0d0"}.icon-truck:before{content:"\f0d1"}.icon-pinterest:before{content:"\f0d2"}.icon-pinterest-sign:before{content:"\f0d3"}.icon-google-plus-sign:before{content:"\f0d4"}.icon-google-plus:before{content:"\f0d5"}.icon-money:before{content:"\f0d6"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.icon-columns:before{content:"\f0db"}.icon-sort:before{content:"\f0dc"}.icon-sort-down:before{content:"\f0dd"}.icon-sort-up:before{content:"\f0de"}.icon-envelope-alt:before{content:"\f0e0"}.icon-linkedin:before{content:"\f0e1"}.icon-undo:before{content:"\f0e2"}.icon-legal:before{content:"\f0e3"}.icon-dashboard:before{content:"\f0e4"}.icon-comment-alt:before{content:"\f0e5"}.icon-comments-alt:before{content:"\f0e6"}.icon-bolt:before{content:"\f0e7"}.icon-sitemap:before{content:"\f0e8"}.icon-umbrella:before{content:"\f0e9"}.icon-paste:before{content:"\f0ea"}.icon-user-md:before{content:"\f200"}header{position:fixed;height:49px;width:100%;background-image:-webkit-linear-gradient(top,#3E3E3E,#282828);background-image:-moz-linear-gradient(top,#3E3E3E,#282828);background-image:-ms-linear-gradient(top,#3E3E3E,#282828);background-image:linear-gradient(top,#3E3E3E,#282828);border-bottom:1px solid #161616;z-index:1;-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;transition:transform .3s ease-out}header.hidden{-webkit-transform:translateY(-60px);-moz-transform:translateY(-60px);transform:translateY(-60px)}header.loading{-webkit-transform:translateY(2px);-moz-transform:translateY(2px);transform:translateY(2px)}header.error{-webkit-transform:translateY(40px);-moz-transform:translateY(40px);transform:translateY(40px)}header.view.error{background-color:rgba(10,10,10,.99)}header.view{background-image:none;border-bottom:none}header.view .button,header.view #title,header.view .tools{text-shadow:none!important}header #title{position:absolute;margin:0 30%;width:40%;padding:15px 0;color:#fff;font-size:16px;font-weight:700;text-align:center;text-shadow:0 -1px 0 #222}header #title.editable{cursor:pointer}header .button{color:#888;font-family:'FontAwesome';font-size:21px;font-weight:700;text-decoration:none!important;cursor:pointer;text-shadow:0 -1px 0 #222}header .button.left{float:left;position:absolute;padding:16px 10px 8px 18px}header .button.right{float:right;position:relative;padding:16px 19px 13px 11px}header .button:hover{color:#fff}header #tools_albums,header #tools_album,header #tools_photo,header #button_signin{display:none}header .button_divider{float:right;position:relative;width:14px;height:50px}header #search{float:right;width:80px;margin:12px 12px 0 0;padding:5px 12px 6px;background-color:#383838;color:#fff;border:1px solid #131313;box-shadow:0 1px 0 rgba(255,255,255,.1);outline:none;border-radius:50px;opacity:.6;-webkit-transition:opacity .3s ease-out,-webkit-transform .3s ease-out,box-shadow .3s,width .2s ease-out;-moz-transition:opacity .3s ease-out,-moz-transform .3s ease-out,box-shadow .3s,width .2s ease-out;transition:opacity .3s ease-out,transform .3s ease-out,box-shadow .3s,width .2s ease-out}header #search:focus{width:140px}header #search:focus~#clearSearch{opacity:1}header #clearSearch{position:absolute;top:15px;right:81px;padding:0;font-size:20px;opacity:0;-webkit-transition:opacity .2s ease-out;-moz-transition:opacity .2s ease-out;transition:opacity .2s ease-out}header #clearSearch:hover{opacity:1}header .tools:first-of-type{margin-right:6px}header .tools{float:right;padding:14px 8px;color:#888;font-size:21px;text-shadow:0 -1px 0 #222;cursor:pointer}header .tools:hover a{color:#fff}header .tools .icon-star{color:#f0ef77}header .tools .icon-share.active{color:#ff9737}header #hostedwith{float:right;padding:5px 10px;margin:13px 9px;color:#888;font-size:13px;text-shadow:0 -1px 0 #222;display:none;cursor:pointer}header #hostedwith:hover{background-color:rgba(0,0,0,.2);border-radius:100px}#imageview{position:fixed;display:none;width:100%;min-height:100%;background-color:rgba(10,10,10,.99);-webkit-transition:background-color .3s}#imageview.view{background-color:inherit}#imageview.full{background-color:#040404}#imageview #image{position:absolute;top:60px;right:30px;bottom:30px;left:30px;background-repeat:no-repeat;background-position:50% 50%;background-size:contain;-webkit-transition:top .3s,bottom .3s,margin-top .3s;-webkit-animation-name:zoomIn;-webkit-animation-duration:.3s;-moz-animation-name:zoomIn;-moz-animation-duration:.3s;animation-name:zoomIn;animation-duration:.3s}#imageview #image.small{top:50%;right:auto;bottom:auto;left:50%}#imageview .arrow_wrapper{position:fixed;width:20%;height:calc(100% - 60px);top:60px;z-index:1}#imageview .arrow_wrapper.previous{left:0}#imageview .arrow_wrapper.next{right:0}#imageview .arrow_wrapper a{position:fixed;top:50%;margin-top:-10px;color:#fff;font-size:50px;text-shadow:0 1px 2px #000;cursor:pointer;opacity:0;z-index:2;-webkit-transition:opacity .2s;-moz-transition:opacity .2s;transition:opacity .2s}#imageview .arrow_wrapper:hover a{opacity:.2}#imageview .arrow_wrapper a#previous{left:20px}#imageview .arrow_wrapper a#next{right:20px}#infobox_overlay{z-index:3;position:fixed;width:100%;height:100%;top:0;left:0;background-color:rgba(0,0,0,.85)}#infobox{z-index:4;position:fixed;right:0;width:300px;height:100%;background-color:rgba(20,20,20,.98);box-shadow:-1px 0 2px rgba(0,0,0,.8);display:none;-webkit-transform:translateX(320px);-moz-transform:translateX(320px);transform:translateX(320px);-webkit-user-select:text;-moz-user-select:text;user-select:text;-webkit-transition:-webkit-transform .5s cubic-bezier(.225,.5,.165,1);-moz-transition:-moz-transform .5s cubic-bezier(.225,.5,.165,1);transition:transform .5s cubic-bezier(.225,.5,.165,1)}#infobox.active{-webkit-transform:translateX(0);-moz-transform:translateX(0);transform:translateX(0)}#infobox .wrapper{float:left;height:100%;overflow:scroll}#infobox .edit{display:inline;margin-left:3px;width:20px;height:5px;cursor:pointer}#infobox .bumper{float:left;width:100%;height:50px}#infobox .header{float:left;height:49px;width:100%;background-color:#1d1d1d;background-image:-webkit-linear-gradient(top,#2A2A2A,#131313);background-image:-moz-linear-gradient(top,#2A2A2A,#131313);background-image:-ms-linear-gradient(top,#2A2A2A,#131313);background-image:linear-gradient(top,#2A2A2A,#131313);border-bottom:1px solid #000}#infobox .header h1{position:absolute;margin:15px 30%;width:40%;font-size:16px;text-align:center}#infobox .header h1,#infobox .header a{color:#fff;font-weight:700;text-shadow:0 -1px 0 #000}#infobox .header a{float:right;padding:15px;font-size:20px;opacity:.5;cursor:pointer}#infobox .header a:hover{opacity:1}#infobox .separator{float:left;width:100%;border-top:1px solid rgba(255,255,255,.04);box-shadow:0 -1px 0 #000}#infobox .separator h1{margin:20px 0 5px 20px;color:#fff;font-size:14px;font-weight:700;text-shadow:0 -1px 0 #000}#infobox table{float:left;margin:10px 0 15px 20px}#infobox table tr td{padding:5px 0;color:#fff;font-size:14px;line-height:19px}#infobox table tr td:first-child{width:110px}#infobox table tr td:last-child{padding-right:10px}#infobox #tags{margin:20px 20px 15px;color:#fff;display:inline-block}#infobox .tag{float:left;padding:4px 7px;margin:0 6px 8px 0;background-color:rgba(0,0,0,.5);border:2px solid rgba(255,255,255,.3);border-radius:100px;font-size:12px;-webkit-transition:border .3s;-moz-transition:border .3s;transition:border .3s}#infobox .tag:hover{border:2px solid #aaa}#infobox .tag span{float:right;width:0;padding:0;margin:0 0 -2px;color:red;font-size:12px;cursor:pointer;overflow:hidden;-webkit-transform:scale(0);transform:scale(0);-webkit-transition:width .3s,margin .3s,-webkit-transform .3s;-moz-transition:width .3s,margin .3s;transition:width .3s,margin .3s,transform .3s}#infobox .tag:hover span{width:10px;margin:0 0 -2px 6px;-webkit-transform:scale(1);transform:scale(1)}#loading{position:fixed;width:100%;height:3px;background-size:100px 3px;background-repeat:repeat-x;border-bottom:1px solid rgba(0,0,0,.3);display:none;-webkit-animation-name:moveBackground;-webkit-animation-duration:.3s;-webkit-animation-iteration-count:infinite;-webkit-animation-timing-function:linear;-moz-animation-name:moveBackground;-moz-animation-duration:.3s;-moz-animation-iteration-count:infinite;-moz-animation-timing-function:linear;animation-name:moveBackground;animation-duration:.3s;animation-iteration-count:infinite;animation-timing-function:linear}#loading.loading{background-image:-webkit-linear-gradient(left,#153674 0%,#153674 47%,#2651AE 53%,#2651AE 100%);background-image:-moz-linear-gradient(left,#153674 0%,#153674 47%,#2651AE 53%,#2651AE 100%);background-image:linear-gradient(left right,#153674 0%,#153674 47%,#2651AE 53%,#2651AE 100%);z-index:2}#loading.error{background-color:#2f0d0e;background-image:-webkit-linear-gradient(left,#451317 0%,#451317 47%,#AA3039 53%,#AA3039 100%);background-image:-moz-linear-gradient(left,#451317 0%,#451317 47%,#AA3039 53%,#AA3039 100%);background-image:linear-gradient(left right,#451317 0%,#451317 47%,#AA3039 53%,#AA3039 100%);z-index:1}#loading h1{margin:13px;color:#ddd;font-size:14px;font-weight:700;text-shadow:0 1px 0 #000;text-transform:capitalize}#loading h1 span{margin-left:10px;font-weight:400;text-transform:none}@media only screen and (max-width:900px){#title{width:40%!important}#title,#title.view{margin:0 20%!important}#title.view{width:60%!important}#title span{display:none!important}}@media only screen and (max-width:640px){#title{display:none!important}#title.view{display:block!important;width:70%!important;margin:0 20% 0 10%!important}#button_move,#button_archive{display:none!important}.center{top:0!important;left:0!important}.album,.photo{margin:40px 0 0 50px!important}.message{position:fixed!important;width:100%!important;height:100%!important;margin:1px 0 0!important;border-radius:0!important;-webkit-animation:moveUp .3s!important;-moz-animation:moveUp .3s!important;animation:moveUp .3s!important}.upload_message{top:50%!important;left:50%!important}}.message_overlay{position:fixed;width:100%;height:100%;top:0;left:0;background-color:rgba(0,0,0,.85);z-index:1000}.message{position:absolute;display:inline-block;width:500px;margin-left:-250px;margin-top:-95px;background-color:#444;background-image:-webkit-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-moz-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-ms-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:linear-gradient(top,#4b4b4b ,#2d2d2d);border-radius:5px;box-shadow:0 0 5px #000,inset 0 1px 0 rgba(255,255,255,.08),inset 1px 0 0 rgba(255,255,255,.03),inset -1px 0 0 rgba(255,255,255,.03);-webkit-animation-name:moveUp;-webkit-animation-duration:.3s;-webkit-animation-timing-function:ease-out;-moz-animation-name:moveUp;-moz-animation-duration:.3s;-moz-animation-timing-function:ease-out;animation-name:moveUp;animation-duration:.3s;animation-timing-function:ease-out}.message h1{float:left;width:100%;padding:12px 0;color:#fff;font-size:16px;font-weight:700;text-shadow:0 -1px 0 #222;text-align:center}.message .close{position:absolute;top:0;right:0;padding:12px 14px 6px 7px;color:#aaa;font-size:20px;text-shadow:0 -1px 0 #222;cursor:pointer}.message .close:hover{color:#fff}.message p{float:left;width:90%;margin-top:1px;padding:12px 5% 15px;color:#eee;font-size:14px;text-shadow:0 -1px 0 #222;line-height:20px}.message p b{font-weight:700}.message p a{color:#eee;text-decoration:none;border-bottom:1px dashed #888}.message .button{float:right;margin:15px 15px 15px 0;padding:6px 10px 8px;background-color:#4e4e4e;background-image:-webkit-linear-gradient(top,#3c3c3c ,#2d2d2d);background-image:-moz-linear-gradient(top,#3c3c3c ,#2d2d2d);background-image:-ms-linear-gradient(top,#3c3c3c ,#2d2d2d);background-image:linear-gradient(top,#3c3c3c ,#2d2d2d);color:#ccc;font-size:14px;font-weight:700;text-align:center;text-shadow:0 -1px 0 #222;border-radius:5px;border:1px solid #191919;box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);cursor:pointer}.message .button:first-of-type{margin:15px 5% 18px 0!important}.message .button.active{color:#fff;box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1),0 0 4px #005ecc}.message .button:hover{background-color:#565757;background-image:-webkit-linear-gradient(top,#505050 ,#393939);background-image:-moz-linear-gradient(top,#505050 ,#393939);background-image:-ms-linear-gradient(top,#505050 ,#393939);background-image:linear-gradient(top,#505050 ,#393939)}.message .button:active,.message .button.pressed{background-color:#393939;background-image:-webkit-linear-gradient(top,#393939 ,#464646);background-image:-moz-linear-gradient(top,#393939 ,#464646);background-image:-ms-linear-gradient(top,#393939 ,#464646);background-image:linear-gradient(top,#393939 ,#464646)}.sign_in{width:100%;margin-top:1px;padding:5px 0;color:#eee;font-size:14px;line-height:20px}.sign_in,.sign_in input{float:left;text-shadow:0 -1px 0 #222}.sign_in input{width:88%;padding:7px 1% 9px;margin:0 5%;background-color:transparent;color:#fff;border:none;border-bottom:1px solid #222;box-shadow:0 1px 0 rgba(255,255,255,.1);border-radius:0;outline:none}.sign_in input:first-of-type{margin-bottom:10px}.sign_in input.error:focus{box-shadow:0 1px 0 rgba(204,0,7,.6)}.message #version{display:inline-block;margin-top:23px;margin-left:5%;color:#888;text-shadow:0 -1px 0 #111}.message #version span{display:none}.message #version span a{color:#888}.message input.text{float:left;width:calc(100% - 10px);padding:17px 5px 9px;margin-top:10px;background-color:transparent;color:#fff;text-shadow:0 -1px 0 #222;border:none;box-shadow:0 1px 0 rgba(255,255,255,.1);border-bottom:1px solid #222;border-radius:0;outline:none}.message input.less{margin-bottom:-10px}.message input.more{margin-bottom:30px}.message .copylink{margin-bottom:20px}html,body{min-height:100%;-webkit-user-select:none;-moz-user-select:none;user-select:none}body{background-color:#222;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:12px;-webkit-font-smoothing:antialiased;-moz-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-smoothing:antialiased}body.view{background-color:#0f0f0f}.center{position:absolute;left:50%;top:50%}*{-webkit-transition:color .3s,opacity .3s ease-out,-webkit-transform .3s ease-out,box-shadow .3s;-moz-transition:opacity .3s ease-out,-moz-transform .3s ease-out,box-shadow .3s;transition:color .3s,opacity .3s ease-out,transform .3s ease-out,box-shadow .3s}.tipsy{padding:4px;font-size:12px;position:absolute;z-index:100000;-webkit-animation-name:fadeIn;-webkit-animation-duration:.3s;-moz-animation-name:fadeIn;-moz-animation-duration:.3s;animation-name:fadeIn;animation-duration:.3s}.tipsy-inner{padding:8px 10px 7px;color:#fff;max-width:200px;text-align:center;background:rgba(0,0,0,.8);border-radius:25px}.tipsy-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed rgba(0,0,0,.8)}.tipsy-arrow-n{border-bottom-color:rgba(0,0,0,.8)}.tipsy-arrow-s{border-top-color:rgba(0,0,0,.8)}.tipsy-arrow-e{border-left-color:rgba(0,0,0,.8)}.tipsy-arrow-w{border-right-color:rgba(0,0,0,.8)}.tipsy-n .tipsy-arrow{left:50%;margin-left:-5px}.tipsy-n .tipsy-arrow,.tipsy-nw .tipsy-arrow{top:0;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.tipsy-nw .tipsy-arrow{left:10px}.tipsy-ne .tipsy-arrow{top:0;right:10px;border-bottom-style:solid;border-top:none}.tipsy-ne .tipsy-arrow,.tipsy-s .tipsy-arrow{border-left-color:transparent;border-right-color:transparent}.tipsy-s .tipsy-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:none}.tipsy-sw .tipsy-arrow{left:10px}.tipsy-sw .tipsy-arrow,.tipsy-se .tipsy-arrow{bottom:0;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.tipsy-se .tipsy-arrow{right:10px}.tipsy-e .tipsy-arrow{right:0;border-left-style:solid;border-right:none}.tipsy-e .tipsy-arrow,.tipsy-w .tipsy-arrow{top:50%;margin-top:-5px;border-top-color:transparent;border-bottom-color:transparent}.tipsy-w .tipsy-arrow{left:0;border-right-style:solid;border-left:none}#upload{display:none}.upload_overlay{position:fixed;width:100%;height:100%;top:0;left:0;background-color:rgba(0,0,0,.85);z-index:1000}.upload_message{position:absolute;display:inline-block;width:200px;margin-left:-100px;margin-top:-85px;background-color:#444;background-image:-webkit-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-moz-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-ms-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:linear-gradient(top,#4b4b4b ,#2d2d2d);border-radius:5px;box-shadow:0 0 5px #000,inset 0 1px 0 rgba(255,255,255,.08),inset 1px 0 0 rgba(255,255,255,.03),inset -1px 0 0 rgba(255,255,255,.03);-webkit-animation-name:moveUp;-webkit-animation-duration:.3s;-webkit-animation-timing-function:ease-out;-moz-animation-name:moveUp;-moz-animation-duration:.3s;-moz-animation-timing-function:ease-out;animation-name:moveUp;animation-duration:.3s;animation-timing-function:ease-out}.upload_message a{margin:35px 0 5px;font-size:70px;text-shadow:0 1px 2px rgba(0,0,0,.5);-webkit-animation-name:pulse;-webkit-animation-duration:2s;-webkit-animation-timing-function:ease-in-out;-webkit-animation-iteration-count:infinite;-moz-animation-name:pulse;-moz-animation-duration:2s;-moz-animation-timing-function:ease-in-out;-moz-animation-iteration-count:infinite;animation-name:pulse;animation-duration:2s;animation-timing-function:ease-in-out;animation-iteration-count:infinite}.upload_message a,.upload_message p{float:left;width:100%;color:#fff;text-align:center}.upload_message p{margin:10px 0 35px;font-size:14px;text-shadow:0 -1px 0 rgba(0,0,0,.5)}.upload_message .progressbar{float:left;width:170px;height:25px;margin:15px;background-size:50px 25px;background-repeat:repeat-x;background-image:-webkit-linear-gradient(left,#191919 0%,#191919 47%,#1D1D1D 53%,#1D1D1D 100%);background-image:-moz-linear-gradient(left,#191919 0%,#191919 47%,#1D1D1D 53%,#1D1D1D 100%);background-image:linear-gradient(left right,#191919 0%,#191919 47%,#1D1D1D 53%,#1D1D1D 100%);border:1px solid #090909;box-shadow:0 1px 0 rgba(255,255,255,.06),inset 0 0 2px #222;border-radius:50px;-webkit-animation-name:moveBackground;-webkit-animation-duration:1s;-webkit-animation-timing-function:linear;-webkit-animation-iteration-count:infinite;-moz-animation-name:moveBackground;-moz-animation-duration:1s;-moz-animation-timing-function:linear;-moz-animation-iteration-count:infinite;animation-name:moveBackground;animation-duration:1s;animation-timing-function:linear;animation-iteration-count:infinite}.upload_message .progressbar div{float:left;width:0%;height:100%;box-shadow:0 1px 0 #000,1px 0 2px #000;background-color:#f5f2f7;background-image:-webkit-linear-gradient(top,#f5f2f7,#c7c6c8);background-image:-moz-linear-gradient(top,#f5f2f7,#c7c6c8);background-image:-ms-linear-gradient(top,#f5f2f7,#c7c6c8);background-image:linear-gradient(top,#f5f2f7,#c7c6c8);border-radius:50px;-webkit-transition:width .2s,opacity .5;-moz-transition:width .2s,opacity .5;transition:width .2s,opacity .5} \ No newline at end of file +.fadeIn{-webkit-animation-name:fadeIn;-moz-animation-name:fadeIn;animation-name:fadeIn}.fadeIn,.fadeOut{-webkit-animation-duration:.3s;-webkit-animation-fill-mode:forwards;-moz-animation-duration:.3s;-moz-animation-fill-mode:forwards;animation-duration:.3s;animation-fill-mode:forwards}.fadeOut{-webkit-animation-name:fadeOut;-moz-animation-name:fadeOut;animation-name:fadeOut}.contentZoomIn{-webkit-animation-name:zoomIn;-moz-animation-name:zoomIn;animation-name:zoomIn}.contentZoomIn,.contentZoomOut{-webkit-animation-duration:.2s;-webkit-animation-fill-mode:forwards;-moz-animation-duration:.2s;-moz-animation-fill-mode:forwards;animation-duration:.2s;animation-fill-mode:forwards}.contentZoomOut{-webkit-animation-name:zoomOut;-moz-animation-name:zoomOut;animation-name:zoomOut}@-webkit-keyframes moveUp{0%{-webkit-transform:translateY(30px);opacity:0}100%{-webkit-transform:translateY(0);opacity:1}}@-moz-keyframes moveUp{0%{opacity:0}100%{opacity:1}}@keyframes moveUp{0%{transform:translateY(30px);opacity:0}100%{transform:translateY(0);opacity:1}}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-moz-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-moz-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-webkit-keyframes moveBackground{0%{background-position-x:0}100%{background-position-x:-100px}}@-moz-keyframes moveBackground{0%{background-position-x:0}100%{background-position-x:-100px}}@keyframes moveBackground{0%{background-position-x:0}100%{background-position-x:-100px}}@-webkit-keyframes zoomIn{0%{opacity:0;-webkit-transform:scale(.8)}100%{opacity:1;-webkit-transform:scale(1)}}@-moz-keyframes zoomIn{0%{opacity:0}100%{opacity:1}}@keyframes zoomIn{0%{opacity:0;transform:scale(.8)}100%{opacity:1;transform:scale(1)}}@-webkit-keyframes zoomOut{0%{opacity:1;-webkit-transform:scale(1)}100%{opacity:0;-webkit-transform:scale(.8)}}@-moz-keyframes zoomOut{0%{opacity:1}100%{opacity:0}}@keyframes zoomOut{0%{opacity:1;transform:scale(1)}100%{opacity:0;transform:scale(.8)}}@-webkit-keyframes popIn{0%{opacity:0;-webkit-transform:scale(0)}100%{opacity:1;-webkit-transform:scale(1)}}@-moz-keyframes popIn{0%{opacity:0;-moz-transform:scale(0)}100%{opacity:1;-moz-transform:scale(1)}}@keyframes popIn{0%{opacity:0;transform:scale(0)}100%{opacity:1;transform:scale(1)}}@-webkit-keyframes pulse{0%{opacity:1}50%{opacity:.3}100%{opacity:1}}@-moz-keyframes pulse{0%{opacity:1}50%{opacity:.8}100%{opacity:1}}@keyframes pulse{0%{opacity:1}50%{opacity:.8}100%{opacity:1}}#content::before{content:"";position:absolute;left:0;width:100%;height:20px;background-image:-webkit-linear-gradient(top,#262626,#222);background-image:-moz-linear-gradient(top,#262626,#222);background-image:-ms-linear-gradient(top,#262626,#222);background-image:linear-gradient(top,#262626,#222);border-top:1px solid #333}#content.view::before{display:none}#content{position:absolute;padding:50px 0 33px;width:100%;min-height:calc(100% - 90px);-webkit-overflow-scrolling:touch}.photo{float:left;display:inline-block;width:206px;height:206px;margin:30px 0 0 30px;cursor:pointer}.photo img{position:absolute;width:200px;height:200px;background-color:#222;border-radius:2px;border:2px solid #ccc}.photo:hover img,.photo.active img{box-shadow:0 0 5px #005ecc}.photo:active{-webkit-transition-duration:.1s;-webkit-transform:scale(.98);-moz-transition-duration:.1s;-moz-transform:scale(.98);transition-duration:.1s;transform:scale(.98)}.album{float:left;display:inline-block;width:204px;height:204px;margin:30px 0 0 30px;cursor:pointer}.album img:first-child,.album img:nth-child(2){-webkit-transform:rotate(0)translateY(0)translateX(0);-moz-transform:rotate(0)translateY(0)translateX(0);transform:rotate(0)translateY(0)translateX(0);opacity:0}.album:hover img:first-child{-webkit-transform:rotate(-2deg)translateY(10px)translateX(-12px);-moz-transform:rotate(-2deg)translateY(10px)translateX(-12px);transform:rotate(-2deg)translateY(10px)translateX(-12px);opacity:1}.album:hover img:nth-child(2){-webkit-transform:rotate(5deg)translateY(-8px)translateX(12px);-moz-transform:rotate(5deg)translateY(-8px)translateX(12px);transform:rotate(5deg)translateY(-8px)translateX(12px);opacity:1}.album img{position:absolute;width:200px;height:200px;background-color:#222;border-radius:2px;border:2px solid #ccc}.album:hover img,.album.active img{box-shadow:0 0 5px #005ecc}.album .overlay,.photo .overlay{position:absolute;width:200px;height:200px;margin:2px}.album .overlay{background:-moz-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%);background:-webkit-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%);background:-ms-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%);background:linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%)}.photo .overlay{background:-moz-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)60%,rgba(0,0,0,.5)80%,rgba(0,0,0,.9)100%);background:-webkit-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)60%,rgba(0,0,0,.5)80%,rgba(0,0,0,.9)100%);background:-ms-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)60%,rgba(0,0,0,.5)80%,rgba(0,0,0,.9)100%);background:linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)60%,rgba(0,0,0,.5)80%,rgba(0,0,0,.9)100%);opacity:0}.photo:hover .overlay,.photo.active .overlay{opacity:1}.album .overlay h1,.photo .overlay h1{min-height:19px;width:190px;margin:153px 0 3px 15px;color:#fff;font-size:16px;font-weight:700;overflow:hidden}.album .overlay a,.photo .overlay a{font-size:11px;color:#aaa}.album .overlay a{margin-left:15px}.photo .overlay a{margin:155px 0 5px 15px}.album .badge,.photo .badge{position:absolute;margin-top:-1px;margin-left:12px;padding:12px 7px 3px;box-shadow:0 0 3px #000;border-radius:0 0 3px 3px;border:1px solid #fff;border-top:none;color:#fff;font-size:24px;text-shadow:0 1px 0 #000;opacity:.9}.album .badge.icon-star,.photo .badge.icon-star{padding:12px 8px 3px}.album .badge.icon-share,.photo .badge.icon-share{padding:12px 6px 3px 8px}.album .badge::after,.photo .badge::after{content:"";position:absolute;margin-top:-12px;margin-left:-26px;width:38px;height:5px;background:-moz-linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);background:-webkit-linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);background:-ms-linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);background:linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);opacity:.4}.album .badge.icon-star::after,.photo .badge.icon-star::after{margin-left:-29px}.album .badge.icon-share::after,.photo .badge.icon-share::after{margin-left:-31px}.album .badge.icon-reorder::after{margin-left:-30px}.album .badge:nth-child(2n),.photo .badge:nth-child(2n){margin-left:57px}.album .badge.red,.photo .badge.red{background:#d64b4b;background:-webkit-linear-gradient(top,#d64b4b,#ab2c2c);background:-moz-linear-gradient(top,#d64b4b,#ab2c2c);background:-ms-linear-gradient(top,#d64b4b,#ab2c2c)}.album .badge.blue,.photo .badge.blue{background:#d64b4b;background:-webkit-linear-gradient(top,#347cd6,#2945ab);background:-moz-linear-gradient(top,#347cd6,#2945ab);background:-ms-linear-gradient(top,#347cd6,#2945ab)}.divider{float:left;width:100%;margin-top:50px;opacity:0;border-top:1px solid #2E2E2E;box-shadow:0 -1px 0 #151515}.divider:first-child{margin-top:0;border-top:none}.divider h1{float:left;margin:20px 0 0 30px;color:#fff;font-size:14px;font-weight:700;text-shadow:0 -1px 0 #000}.no_content{position:absolute;top:50%;left:50%;height:160px;width:180px;margin-top:-80px;margin-left:-90px;padding-top:20px;color:rgba(20,20,20,1);text-shadow:0 1px 0 rgba(255,255,255,.05);text-align:center}.no_content .icon{font-size:120px}.no_content p{font-size:18px}.contextmenu_bg{position:fixed;height:100%;width:100%;z-index:1000}.contextmenu{position:fixed;top:0;left:0;padding:5px 0 6px;background-color:#393939;background-image:-webkit-linear-gradient(top,#444,#2d2d2d);background-image:-moz-linear-gradient(top,#393939,#2d2d2d);background-image:-ms-linear-gradient(top,#393939,#2d2d2d);background-image:linear-gradient(top,#393939,#2d2d2d);border:1px solid rgba(0,0,0,.7);border-bottom:1px solid rgba(0,0,0,.9);border-radius:5px;box-shadow:0 4px 5px rgba(0,0,0,.3),inset 0 1px 0 rgba(255,255,255,.15),inset 1px 0 0 rgba(255,255,255,.05),inset -1px 0 0 rgba(255,255,255,.05);opacity:0;z-index:1001;-webkit-transition:none;-moz-transition:none;transition:none}.contextmenu tr{font-size:14px;color:#eee;text-shadow:0 -1px 0 rgba(0,0,0,.6);cursor:pointer}.contextmenu tr:hover{background-color:#6a84f2;background-image:-webkit-linear-gradient(top,#6a84f2,#3959ef);background-image:-moz-linear-gradient(top,#6a84f2,#3959ef);background-image:-ms-linear-gradient(top,#6a84f2,#3959ef);background-image:linear-gradient(top,#6a84f2,#3959ef)}.contextmenu tr.no_hover:hover{cursor:inherit;background-color:inherit;background-image:none}.contextmenu tr.separator{float:left;height:1px;width:100%;background-color:#1c1c1c;border-bottom:1px solid #4a4a4a;margin:5px 0;cursor:inherit}.contextmenu tr.separator:hover{background-color:#222;background-image:none}.contextmenu tr td{padding:7px 30px 6px 12px;white-space:nowrap;-webkit-transition:none;-moz-transition:none;transition:none}.contextmenu tr:hover td{color:#fff;box-shadow:inset 0 1px 0 rgba(255,255,255,.05);text-shadow:0 -1px 0 rgba(0,0,0,.4)}.contextmenu tr.no_hover:hover td{box-shadow:none}.contextmenu tr a{float:left;width:10px;margin-right:10px;text-align:center}.contextmenu #link{float:right;width:140px;margin:0 -17px -1px 0;padding:4px 6px 5px;background-color:#444;color:#fff;border:1px solid #111;box-shadow:0 1px 0 rgba(255,255,255,.1);outline:none;border-radius:5px}.contextmenu tr a#link_icon{padding-top:4px}@font-face{font-family:'FontAwesome';src:url('../../font/fontawesome-webfont.eot');src:url('../../font/fontawesome-webfont.eot?#iefix') format('eot'),url('../../font/fontawesome-webfont.woff') format('woff'),url('../../font/fontawesome-webfont.ttf') format('truetype'),url('../../font/fontawesome-webfont.svg#FontAwesome') format('svg');font-weight:400;font-style:normal}[class^="icon-"]:before,[class*=" icon-"]:before{font-family:FontAwesome;font-weight:400;font-style:normal;display:inline-block;text-decoration:inherit}a [class^="icon-"],a [class*=" icon-"]{display:inline-block;text-decoration:inherit}.icon-large:before{vertical-align:top;font-size:1.3333333333333333em}.btn [class^="icon-"],.btn [class*=" icon-"]{line-height:.9em}li [class^="icon-"],li [class*=" icon-"]{display:inline-block;width:1.25em;text-align:center}li .icon-large[class^="icon-"],li .icon-large[class*=" icon-"]{width:1.875em}li[class^="icon-"],li[class*=" icon-"]{margin-left:0;list-style-type:none}li[class^="icon-"]:before,li[class*=" icon-"]:before{text-indent:-2em;text-align:center}li[class^="icon-"].icon-large:before,li[class*=" icon-"].icon-large:before{text-indent:-1.3333333333333333em}.icon-glass:before{content:"\f000"}.icon-music:before{content:"\f001"}.icon-search:before{content:"\f002"}.icon-envelope:before{content:"\f003"}.icon-heart:before{content:"\f004"}.icon-star:before{content:"\f005"}.icon-star-empty:before{content:"\f006"}.icon-user:before{content:"\f007"}.icon-film:before{content:"\f008"}.icon-th-large:before{content:"\f009"}.icon-th:before{content:"\f00a"}.icon-th-list:before{content:"\f00b"}.icon-ok:before{content:"\f00c"}.icon-remove:before{content:"\f00d"}.icon-zoom-in:before{content:"\f00e"}.icon-zoom-out:before{content:"\f010"}.icon-off:before{content:"\f011"}.icon-signal:before{content:"\f012"}.icon-cog:before{content:"\f013"}.icon-trash:before{content:"\f014"}.icon-home:before{content:"\f015"}.icon-file:before{content:"\f016"}.icon-time:before{content:"\f017"}.icon-road:before{content:"\f018"}.icon-download-alt:before{content:"\f019"}.icon-download:before{content:"\f01a"}.icon-upload:before{content:"\f01b"}.icon-inbox:before{content:"\f01c"}.icon-play-circle:before{content:"\f01d"}.icon-repeat:before{content:"\f01e"}.icon-refresh:before{content:"\f021"}.icon-list-alt:before{content:"\f022"}.icon-lock:before{content:"\f023"}.icon-flag:before{content:"\f024"}.icon-headphones:before{content:"\f025"}.icon-volume-off:before{content:"\f026"}.icon-volume-down:before{content:"\f027"}.icon-volume-up:before{content:"\f028"}.icon-qrcode:before{content:"\f029"}.icon-barcode:before{content:"\f02a"}.icon-tag:before{content:"\f02b"}.icon-tags:before{content:"\f02c"}.icon-book:before{content:"\f02d"}.icon-bookmark:before{content:"\f02e"}.icon-print:before{content:"\f02f"}.icon-camera:before{content:"\f030"}.icon-font:before{content:"\f031"}.icon-bold:before{content:"\f032"}.icon-italic:before{content:"\f033"}.icon-text-height:before{content:"\f034"}.icon-text-width:before{content:"\f035"}.icon-align-left:before{content:"\f036"}.icon-align-center:before{content:"\f037"}.icon-align-right:before{content:"\f038"}.icon-align-justify:before{content:"\f039"}.icon-list:before{content:"\f03a"}.icon-indent-left:before{content:"\f03b"}.icon-indent-right:before{content:"\f03c"}.icon-facetime-video:before{content:"\f03d"}.icon-picture:before{content:"\f03e"}.icon-pencil:before{content:"\f040"}.icon-map-marker:before{content:"\f041"}.icon-adjust:before{content:"\f042"}.icon-tint:before{content:"\f043"}.icon-edit:before{content:"\f044"}.icon-share:before{content:"\f045"}.icon-check:before{content:"\f046"}.icon-move:before{content:"\f047"}.icon-step-backward:before{content:"\f048"}.icon-fast-backward:before{content:"\f049"}.icon-backward:before{content:"\f04a"}.icon-play:before{content:"\f04b"}.icon-pause:before{content:"\f04c"}.icon-stop:before{content:"\f04d"}.icon-forward:before{content:"\f04e"}.icon-fast-forward:before{content:"\f050"}.icon-step-forward:before{content:"\f051"}.icon-eject:before{content:"\f052"}.icon-chevron-left:before{content:"\f053"}.icon-chevron-right:before{content:"\f054"}.icon-plus-sign:before{content:"\f055"}.icon-minus-sign:before{content:"\f056"}.icon-remove-sign:before{content:"\f057"}.icon-ok-sign:before{content:"\f058"}.icon-question-sign:before{content:"\f059"}.icon-info-sign:before{content:"\f05a"}.icon-screenshot:before{content:"\f05b"}.icon-remove-circle:before{content:"\f05c"}.icon-ok-circle:before{content:"\f05d"}.icon-ban-circle:before{content:"\f05e"}.icon-arrow-left:before{content:"\f060"}.icon-arrow-right:before{content:"\f061"}.icon-arrow-up:before{content:"\f062"}.icon-arrow-down:before{content:"\f063"}.icon-share-alt:before{content:"\f064"}.icon-resize-full:before{content:"\f065"}.icon-resize-small:before{content:"\f066"}.icon-plus:before{content:"\f067"}.icon-minus:before{content:"\f068"}.icon-asterisk:before{content:"\f069"}.icon-exclamation-sign:before{content:"\f06a"}.icon-gift:before{content:"\f06b"}.icon-leaf:before{content:"\f06c"}.icon-fire:before{content:"\f06d"}.icon-eye-open:before{content:"\f06e"}.icon-eye-close:before{content:"\f070"}.icon-warning-sign:before{content:"\f071"}.icon-plane:before{content:"\f072"}.icon-calendar:before{content:"\f073"}.icon-random:before{content:"\f074"}.icon-comment:before{content:"\f075"}.icon-magnet:before{content:"\f076"}.icon-chevron-up:before{content:"\f077"}.icon-chevron-down:before{content:"\f078"}.icon-retweet:before{content:"\f079"}.icon-shopping-cart:before{content:"\f07a"}.icon-folder-close:before{content:"\f07b"}.icon-folder-open:before{content:"\f07c"}.icon-resize-vertical:before{content:"\f07d"}.icon-resize-horizontal:before{content:"\f07e"}.icon-bar-chart:before{content:"\f080"}.icon-twitter-sign:before{content:"\f081"}.icon-facebook-sign:before{content:"\f082"}.icon-camera-retro:before{content:"\f083"}.icon-key:before{content:"\f084"}.icon-cogs:before{content:"\f085"}.icon-comments:before{content:"\f086"}.icon-thumbs-up:before{content:"\f087"}.icon-thumbs-down:before{content:"\f088"}.icon-star-half:before{content:"\f089"}.icon-heart-empty:before{content:"\f08a"}.icon-signout:before{content:"\f08b"}.icon-linkedin-sign:before{content:"\f08c"}.icon-pushpin:before{content:"\f08d"}.icon-external-link:before{content:"\f08e"}.icon-signin:before{content:"\f090"}.icon-trophy:before{content:"\f091"}.icon-github-sign:before{content:"\f092"}.icon-upload-alt:before{content:"\f093"}.icon-lemon:before{content:"\f094"}.icon-phone:before{content:"\f095"}.icon-check-empty:before{content:"\f096"}.icon-bookmark-empty:before{content:"\f097"}.icon-phone-sign:before{content:"\f098"}.icon-twitter:before{content:"\f099"}.icon-facebook:before{content:"\f09a"}.icon-github:before{content:"\f09b"}.icon-unlock:before{content:"\f09c"}.icon-credit-card:before{content:"\f09d"}.icon-rss:before{content:"\f09e"}.icon-hdd:before{content:"\f0a0"}.icon-bullhorn:before{content:"\f0a1"}.icon-bell:before{content:"\f0a2"}.icon-certificate:before{content:"\f0a3"}.icon-hand-right:before{content:"\f0a4"}.icon-hand-left:before{content:"\f0a5"}.icon-hand-up:before{content:"\f0a6"}.icon-hand-down:before{content:"\f0a7"}.icon-circle-arrow-left:before{content:"\f0a8"}.icon-circle-arrow-right:before{content:"\f0a9"}.icon-circle-arrow-up:before{content:"\f0aa"}.icon-circle-arrow-down:before{content:"\f0ab"}.icon-globe:before{content:"\f0ac"}.icon-wrench:before{content:"\f0ad"}.icon-tasks:before{content:"\f0ae"}.icon-filter:before{content:"\f0b0"}.icon-briefcase:before{content:"\f0b1"}.icon-fullscreen:before{content:"\f0b2"}.icon-group:before{content:"\f0c0"}.icon-link:before{content:"\f0c1"}.icon-cloud:before{content:"\f0c2"}.icon-beaker:before{content:"\f0c3"}.icon-cut:before{content:"\f0c4"}.icon-copy:before{content:"\f0c5"}.icon-paper-clip:before{content:"\f0c6"}.icon-save:before{content:"\f0c7"}.icon-sign-blank:before{content:"\f0c8"}.icon-reorder:before{content:"\f0c9"}.icon-list-ul:before{content:"\f0ca"}.icon-list-ol:before{content:"\f0cb"}.icon-strikethrough:before{content:"\f0cc"}.icon-underline:before{content:"\f0cd"}.icon-table:before{content:"\f0ce"}.icon-magic:before{content:"\f0d0"}.icon-truck:before{content:"\f0d1"}.icon-pinterest:before{content:"\f0d2"}.icon-pinterest-sign:before{content:"\f0d3"}.icon-google-plus-sign:before{content:"\f0d4"}.icon-google-plus:before{content:"\f0d5"}.icon-money:before{content:"\f0d6"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.icon-columns:before{content:"\f0db"}.icon-sort:before{content:"\f0dc"}.icon-sort-down:before{content:"\f0dd"}.icon-sort-up:before{content:"\f0de"}.icon-envelope-alt:before{content:"\f0e0"}.icon-linkedin:before{content:"\f0e1"}.icon-undo:before{content:"\f0e2"}.icon-legal:before{content:"\f0e3"}.icon-dashboard:before{content:"\f0e4"}.icon-comment-alt:before{content:"\f0e5"}.icon-comments-alt:before{content:"\f0e6"}.icon-bolt:before{content:"\f0e7"}.icon-sitemap:before{content:"\f0e8"}.icon-umbrella:before{content:"\f0e9"}.icon-paste:before{content:"\f0ea"}.icon-user-md:before{content:"\f200"}header{position:fixed;height:49px;width:100%;background-image:-webkit-linear-gradient(top,#3E3E3E,#282828);background-image:-moz-linear-gradient(top,#3E3E3E,#282828);background-image:-ms-linear-gradient(top,#3E3E3E,#282828);background-image:linear-gradient(top,#3E3E3E,#282828);border-bottom:1px solid #161616;z-index:1;-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;transition:transform .3s ease-out}header.hidden{-webkit-transform:translateY(-60px);-moz-transform:translateY(-60px);transform:translateY(-60px)}header.loading{-webkit-transform:translateY(2px);-moz-transform:translateY(2px);transform:translateY(2px)}header.error{-webkit-transform:translateY(40px);-moz-transform:translateY(40px);transform:translateY(40px)}header.view.error{background-color:rgba(10,10,10,.99)}header.view{background-image:none;border-bottom:none}header.view .button,header.view #title,header.view .tools{text-shadow:none!important}header #title{position:absolute;margin:0 30%;width:40%;padding:15px 0;color:#fff;font-size:16px;font-weight:700;text-align:center;text-shadow:0 -1px 0 #222}header #title.editable{cursor:pointer}header .button{color:#888;font-family:'FontAwesome';font-size:21px;font-weight:700;text-decoration:none!important;cursor:pointer;text-shadow:0 -1px 0 #222}header .button.left{float:left;position:absolute;padding:16px 10px 8px 18px}header .button.right{float:right;position:relative;padding:16px 19px 13px 11px}header .button:hover{color:#fff}header #tools_albums,header #tools_album,header #tools_photo,header #button_signin{display:none}header .button_divider{float:right;position:relative;width:14px;height:50px}header #search{float:right;width:80px;margin:12px 12px 0 0;padding:5px 12px 6px;background-color:#383838;color:#fff;border:1px solid #131313;box-shadow:0 1px 0 rgba(255,255,255,.1);outline:none;border-radius:50px;opacity:.6;-webkit-transition:opacity .3s ease-out,-webkit-transform .3s ease-out,box-shadow .3s,width .2s ease-out;-moz-transition:opacity .3s ease-out,-moz-transform .3s ease-out,box-shadow .3s,width .2s ease-out;transition:opacity .3s ease-out,transform .3s ease-out,box-shadow .3s,width .2s ease-out}header #search:focus{width:140px}header #search:focus~#clearSearch{opacity:1}header #clearSearch{position:absolute;top:15px;right:81px;padding:0;font-size:20px;opacity:0;-webkit-transition:opacity .2s ease-out;-moz-transition:opacity .2s ease-out;transition:opacity .2s ease-out}header #clearSearch:hover{opacity:1}header .tools:first-of-type{margin-right:6px}header .tools{float:right;padding:14px 8px;color:#888;font-size:21px;text-shadow:0 -1px 0 #222;cursor:pointer}header .tools:hover a{color:#fff}header .tools .icon-star{color:#f0ef77}header .tools .icon-share.active{color:#ff9737}header #hostedwith{float:right;padding:5px 10px;margin:13px 9px;color:#888;font-size:13px;text-shadow:0 -1px 0 #222;display:none;cursor:pointer}header #hostedwith:hover{background-color:rgba(0,0,0,.2);border-radius:100px}#imageview{position:fixed;display:none;width:100%;min-height:100%;background-color:rgba(10,10,10,.99);-webkit-transition:background-color .3s}#imageview.view{background-color:inherit}#imageview.full{background-color:#040404}#imageview #image{position:absolute;top:60px;right:30px;bottom:30px;left:30px;background-repeat:no-repeat;background-position:50% 50%;background-size:contain;-webkit-transition:top .3s,bottom .3s,margin-top .3s;-webkit-animation-name:zoomIn;-webkit-animation-duration:.3s;-moz-animation-name:zoomIn;-moz-animation-duration:.3s;animation-name:zoomIn;animation-duration:.3s}#imageview #image.small{top:50%;right:auto;bottom:auto;left:50%}#imageview .arrow_wrapper{position:fixed;width:20%;height:calc(100% - 60px);top:60px;z-index:1}#imageview .arrow_wrapper.previous{left:0}#imageview .arrow_wrapper.next{right:0}#imageview .arrow_wrapper a{position:fixed;top:50%;margin-top:-10px;color:#fff;font-size:50px;text-shadow:0 1px 2px #000;cursor:pointer;opacity:0;z-index:2;-webkit-transition:opacity .2s;-moz-transition:opacity .2s;transition:opacity .2s}#imageview .arrow_wrapper:hover a{opacity:.2}#imageview .arrow_wrapper a#previous{left:20px}#imageview .arrow_wrapper a#next{right:20px}#infobox_overlay{z-index:3;position:fixed;width:100%;height:100%;top:0;left:0;background-color:rgba(0,0,0,.85)}#infobox{z-index:4;position:fixed;right:0;width:300px;height:100%;background-color:rgba(20,20,20,.98);box-shadow:-1px 0 2px rgba(0,0,0,.8);display:none;-webkit-transform:translateX(320px);-moz-transform:translateX(320px);transform:translateX(320px);-webkit-transition:-webkit-transform .5s cubic-bezier(.225,.5,.165,1);-moz-transition:-moz-transform .5s cubic-bezier(.225,.5,.165,1);transition:transform .5s cubic-bezier(.225,.5,.165,1)}#infobox.active{-webkit-transform:translateX(0);-moz-transform:translateX(0);transform:translateX(0)}#infobox .wrapper{float:left;height:100%;overflow:scroll}#infobox .edit{display:inline;margin-left:3px;width:20px;height:5px;cursor:pointer}#infobox .bumper{float:left;width:100%;height:50px}#infobox .header{float:left;height:49px;width:100%;background-color:#1d1d1d;background-image:-webkit-linear-gradient(top,#2A2A2A,#131313);background-image:-moz-linear-gradient(top,#2A2A2A,#131313);background-image:-ms-linear-gradient(top,#2A2A2A,#131313);background-image:linear-gradient(top,#2A2A2A,#131313);border-bottom:1px solid #000}#infobox .header h1{position:absolute;margin:15px 30%;width:40%;font-size:16px;text-align:center}#infobox .header h1,#infobox .header a{color:#fff;font-weight:700;text-shadow:0 -1px 0 #000}#infobox .header a{float:right;padding:15px;font-size:20px;opacity:.5;cursor:pointer}#infobox .header a:hover{opacity:1}#infobox .separator{float:left;width:100%;border-top:1px solid rgba(255,255,255,.04);box-shadow:0 -1px 0 #000}#infobox .separator h1{margin:20px 0 5px 20px;color:#fff;font-size:14px;font-weight:700;text-shadow:0 -1px 0 #000}#infobox table{float:left;margin:10px 0 15px 20px}#infobox table tr td{padding:5px 0;color:#fff;font-size:14px;line-height:19px;-webkit-user-select:text;-moz-user-select:text;user-select:text}#infobox table tr td:first-child{width:110px}#infobox table tr td:last-child{padding-right:10px}#infobox #tags{width:calc(100% - 40px);margin:16px 20px 12px;color:#fff;display:inline-block}#infobox #tags .empty{font-size:14px;margin-bottom:8px}#infobox #tags .edit{display:inline-block}#infobox #tags .empty .edit{display:inline}#infobox .tag{float:left;padding:4px 7px;margin:0 6px 8px 0;background-color:rgba(0,0,0,.5);border:2px solid rgba(255,255,255,.3);border-radius:100px;font-size:12px;-webkit-transition:border .3s;-moz-transition:border .3s;transition:border .3s}#infobox .tag:hover{border:2px solid #aaa}#infobox .tag span{float:right;width:0;padding:0;margin:0 0 -2px;color:red;font-size:11px;cursor:pointer;overflow:hidden;-webkit-transform:scale(0);transform:scale(0);-webkit-transition:width .3s,margin .3s,-webkit-transform .3s;-moz-transition:width .3s,margin .3s;transition:width .3s,margin .3s,transform .3s}#infobox .tag:hover span{width:10px;margin:0 0 -2px 6px;-webkit-transform:scale(1);transform:scale(1)}#loading{position:fixed;width:100%;height:3px;background-size:100px 3px;background-repeat:repeat-x;border-bottom:1px solid rgba(0,0,0,.3);display:none;-webkit-animation-name:moveBackground;-webkit-animation-duration:.3s;-webkit-animation-iteration-count:infinite;-webkit-animation-timing-function:linear;-moz-animation-name:moveBackground;-moz-animation-duration:.3s;-moz-animation-iteration-count:infinite;-moz-animation-timing-function:linear;animation-name:moveBackground;animation-duration:.3s;animation-iteration-count:infinite;animation-timing-function:linear}#loading.loading{background-image:-webkit-linear-gradient(left,#153674 0%,#153674 47%,#2651AE 53%,#2651AE 100%);background-image:-moz-linear-gradient(left,#153674 0%,#153674 47%,#2651AE 53%,#2651AE 100%);background-image:linear-gradient(left right,#153674 0%,#153674 47%,#2651AE 53%,#2651AE 100%);z-index:2}#loading.error{background-color:#2f0d0e;background-image:-webkit-linear-gradient(left,#451317 0%,#451317 47%,#AA3039 53%,#AA3039 100%);background-image:-moz-linear-gradient(left,#451317 0%,#451317 47%,#AA3039 53%,#AA3039 100%);background-image:linear-gradient(left right,#451317 0%,#451317 47%,#AA3039 53%,#AA3039 100%);z-index:1}#loading h1{margin:13px;color:#ddd;font-size:14px;font-weight:700;text-shadow:0 1px 0 #000;text-transform:capitalize}#loading h1 span{margin-left:10px;font-weight:400;text-transform:none}@media only screen and (max-width:900px){#title{width:40%!important}#title,#title.view{margin:0 20%!important}#title.view{width:60%!important}#title span{display:none!important}}@media only screen and (max-width:640px){#title{display:none!important}#title.view{display:block!important;width:70%!important;margin:0 20% 0 10%!important}#button_move,#button_archive{display:none!important}.center{top:0!important;left:0!important}.album,.photo{margin:40px 0 0 50px!important}.message{position:fixed!important;width:100%!important;height:100%!important;margin:1px 0 0!important;border-radius:0!important;-webkit-animation:moveUp .3s!important;-moz-animation:moveUp .3s!important;animation:moveUp .3s!important}.upload_message{top:50%!important;left:50%!important}}.message_overlay{position:fixed;width:100%;height:100%;top:0;left:0;background-color:rgba(0,0,0,.85);z-index:1000}.message{position:absolute;display:inline-block;width:500px;margin-left:-250px;margin-top:-95px;background-color:#444;background-image:-webkit-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-moz-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-ms-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:linear-gradient(top,#4b4b4b ,#2d2d2d);border-radius:5px;box-shadow:0 0 5px #000,inset 0 1px 0 rgba(255,255,255,.08),inset 1px 0 0 rgba(255,255,255,.03),inset -1px 0 0 rgba(255,255,255,.03);-webkit-animation-name:moveUp;-webkit-animation-duration:.3s;-webkit-animation-timing-function:ease-out;-moz-animation-name:moveUp;-moz-animation-duration:.3s;-moz-animation-timing-function:ease-out;animation-name:moveUp;animation-duration:.3s;animation-timing-function:ease-out}.message h1{float:left;width:100%;padding:12px 0;color:#fff;font-size:16px;font-weight:700;text-shadow:0 -1px 0 #222;text-align:center}.message .close{position:absolute;top:0;right:0;padding:12px 14px 6px 7px;color:#aaa;font-size:20px;text-shadow:0 -1px 0 #222;cursor:pointer}.message .close:hover{color:#fff}.message p{float:left;width:90%;margin-top:1px;padding:12px 5% 15px;color:#eee;font-size:14px;text-shadow:0 -1px 0 #222;line-height:20px}.message p b{font-weight:700}.message p a{color:#eee;text-decoration:none;border-bottom:1px dashed #888}.message .button{float:right;margin:15px 15px 15px 0;padding:6px 10px 8px;background-color:#4e4e4e;background-image:-webkit-linear-gradient(top,#3c3c3c ,#2d2d2d);background-image:-moz-linear-gradient(top,#3c3c3c ,#2d2d2d);background-image:-ms-linear-gradient(top,#3c3c3c ,#2d2d2d);background-image:linear-gradient(top,#3c3c3c ,#2d2d2d);color:#ccc;font-size:14px;font-weight:700;text-align:center;text-shadow:0 -1px 0 #222;border-radius:5px;border:1px solid #191919;box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);cursor:pointer}.message .button:first-of-type{margin:15px 5% 18px 0!important}.message .button.active{color:#fff;box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1),0 0 4px #005ecc}.message .button:hover{background-color:#565757;background-image:-webkit-linear-gradient(top,#505050 ,#393939);background-image:-moz-linear-gradient(top,#505050 ,#393939);background-image:-ms-linear-gradient(top,#505050 ,#393939);background-image:linear-gradient(top,#505050 ,#393939)}.message .button:active,.message .button.pressed{background-color:#393939;background-image:-webkit-linear-gradient(top,#393939 ,#464646);background-image:-moz-linear-gradient(top,#393939 ,#464646);background-image:-ms-linear-gradient(top,#393939 ,#464646);background-image:linear-gradient(top,#393939 ,#464646)}.sign_in{width:100%;margin-top:1px;padding:5px 0;color:#eee;font-size:14px;line-height:20px}.sign_in,.sign_in input{float:left;text-shadow:0 -1px 0 #222}.sign_in input{width:88%;padding:7px 1% 9px;margin:0 5%;background-color:transparent;color:#fff;border:none;border-bottom:1px solid #222;box-shadow:0 1px 0 rgba(255,255,255,.1);border-radius:0;outline:none}.sign_in input:first-of-type{margin-bottom:10px}.sign_in input.error:focus{box-shadow:0 1px 0 rgba(204,0,7,.6)}.message #version{display:inline-block;margin-top:23px;margin-left:5%;color:#888;text-shadow:0 -1px 0 #111}.message #version span{display:none}.message #version span a{color:#888}.message input.text{float:left;width:calc(100% - 10px);padding:17px 5px 9px;margin-top:10px;background-color:transparent;color:#fff;text-shadow:0 -1px 0 #222;border:none;box-shadow:0 1px 0 rgba(255,255,255,.1);border-bottom:1px solid #222;border-radius:0;outline:none}.message input.less{margin-bottom:-10px}.message input.more{margin-bottom:30px}.message .copylink{margin-bottom:20px}html,body{min-height:100%}body{background-color:#222;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:12px;-webkit-font-smoothing:antialiased;-moz-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-smoothing:antialiased}body.view{background-color:#0f0f0f}.center{position:absolute;left:50%;top:50%}*{-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-transition:color .3s,opacity .3s ease-out,-webkit-transform .3s ease-out,box-shadow .3s;-moz-transition:opacity .3s ease-out,-moz-transform .3s ease-out,box-shadow .3s;transition:color .3s,opacity .3s ease-out,transform .3s ease-out,box-shadow .3s}input{-webkit-user-select:text!important;-moz-user-select:text!important;user-select:text!important}#multiselect{position:absolute;background-color:rgba(0,94,204,.3);border:1px solid rgba(0,94,204,1);border-radius:3px;z-index:3}.tipsy{padding:4px;font-size:12px;position:absolute;z-index:100000;-webkit-animation-name:fadeIn;-webkit-animation-duration:.3s;-moz-animation-name:fadeIn;-moz-animation-duration:.3s;animation-name:fadeIn;animation-duration:.3s}.tipsy-inner{padding:8px 10px 7px;color:#fff;max-width:200px;text-align:center;background:rgba(0,0,0,.8);border-radius:25px}.tipsy-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed rgba(0,0,0,.8)}.tipsy-arrow-n{border-bottom-color:rgba(0,0,0,.8)}.tipsy-arrow-s{border-top-color:rgba(0,0,0,.8)}.tipsy-arrow-e{border-left-color:rgba(0,0,0,.8)}.tipsy-arrow-w{border-right-color:rgba(0,0,0,.8)}.tipsy-n .tipsy-arrow{left:50%;margin-left:-5px}.tipsy-n .tipsy-arrow,.tipsy-nw .tipsy-arrow{top:0;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.tipsy-nw .tipsy-arrow{left:10px}.tipsy-ne .tipsy-arrow{top:0;right:10px;border-bottom-style:solid;border-top:none}.tipsy-ne .tipsy-arrow,.tipsy-s .tipsy-arrow{border-left-color:transparent;border-right-color:transparent}.tipsy-s .tipsy-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:none}.tipsy-sw .tipsy-arrow{left:10px}.tipsy-sw .tipsy-arrow,.tipsy-se .tipsy-arrow{bottom:0;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.tipsy-se .tipsy-arrow{right:10px}.tipsy-e .tipsy-arrow{right:0;border-left-style:solid;border-right:none}.tipsy-e .tipsy-arrow,.tipsy-w .tipsy-arrow{top:50%;margin-top:-5px;border-top-color:transparent;border-bottom-color:transparent}.tipsy-w .tipsy-arrow{left:0;border-right-style:solid;border-left:none}#upload{display:none}.upload_overlay{position:fixed;width:100%;height:100%;top:0;left:0;background-color:rgba(0,0,0,.85);z-index:1000}.upload_message{position:absolute;display:inline-block;width:200px;margin-left:-100px;margin-top:-85px;background-color:#444;background-image:-webkit-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-moz-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-ms-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:linear-gradient(top,#4b4b4b ,#2d2d2d);border-radius:5px;box-shadow:0 0 5px #000,inset 0 1px 0 rgba(255,255,255,.08),inset 1px 0 0 rgba(255,255,255,.03),inset -1px 0 0 rgba(255,255,255,.03);-webkit-animation-name:moveUp;-webkit-animation-duration:.3s;-webkit-animation-timing-function:ease-out;-moz-animation-name:moveUp;-moz-animation-duration:.3s;-moz-animation-timing-function:ease-out;animation-name:moveUp;animation-duration:.3s;animation-timing-function:ease-out}.upload_message a{margin:35px 0 5px;font-size:70px;text-shadow:0 1px 2px rgba(0,0,0,.5);-webkit-animation-name:pulse;-webkit-animation-duration:2s;-webkit-animation-timing-function:ease-in-out;-webkit-animation-iteration-count:infinite;-moz-animation-name:pulse;-moz-animation-duration:2s;-moz-animation-timing-function:ease-in-out;-moz-animation-iteration-count:infinite;animation-name:pulse;animation-duration:2s;animation-timing-function:ease-in-out;animation-iteration-count:infinite}.upload_message a,.upload_message p{float:left;width:100%;color:#fff;text-align:center}.upload_message p{margin:10px 0 35px;font-size:14px;text-shadow:0 -1px 0 rgba(0,0,0,.5)}.upload_message .progressbar{float:left;width:170px;height:25px;margin:15px;background-size:50px 25px;background-repeat:repeat-x;background-image:-webkit-linear-gradient(left,#191919 0%,#191919 47%,#1D1D1D 53%,#1D1D1D 100%);background-image:-moz-linear-gradient(left,#191919 0%,#191919 47%,#1D1D1D 53%,#1D1D1D 100%);background-image:linear-gradient(left right,#191919 0%,#191919 47%,#1D1D1D 53%,#1D1D1D 100%);border:1px solid #090909;box-shadow:0 1px 0 rgba(255,255,255,.06),inset 0 0 2px #222;border-radius:50px;-webkit-animation-name:moveBackground;-webkit-animation-duration:1s;-webkit-animation-timing-function:linear;-webkit-animation-iteration-count:infinite;-moz-animation-name:moveBackground;-moz-animation-duration:1s;-moz-animation-timing-function:linear;-moz-animation-iteration-count:infinite;animation-name:moveBackground;animation-duration:1s;animation-timing-function:linear;animation-iteration-count:infinite}.upload_message .progressbar div{float:left;width:0%;height:100%;box-shadow:0 1px 0 #000,1px 0 2px #000;background-color:#f5f2f7;background-image:-webkit-linear-gradient(top,#f5f2f7,#c7c6c8);background-image:-moz-linear-gradient(top,#f5f2f7,#c7c6c8);background-image:-ms-linear-gradient(top,#f5f2f7,#c7c6c8);background-image:linear-gradient(top,#f5f2f7,#c7c6c8);border-radius:50px;-webkit-transition:width .2s,opacity .5;-moz-transition:width .2s,opacity .5;transition:width .2s,opacity .5} \ No newline at end of file diff --git a/assets/js/min/main.js b/assets/js/min/main.js index 7168068..fcabcab 100755 --- a/assets/js/min/main.js +++ b/assets/js/min/main.js @@ -1,2 +1,3 @@ -album={json:null,getID:function(){var id;if(photo.json)id=photo.json.album;else if(album.json)id=album.json.id;else id=$(".album:hover, .album.active").attr("data-id");if(!id)id=$(".photo:hover, .photo.active").attr("data-album-id");if(id)return id;else return false},load:function(albumID,refresh){var startTime,params,durationTime,waitTime;password.get(albumID,function(){if(!refresh){loadingBar.show();lychee.animate(".album, .photo","contentZoomOut");lychee.animate(".divider","fadeOut")}startTime=(new Date).getTime();params="getAlbum&albumID="+albumID+"&password="+password.value;lychee.api(params,function(data){if(data==="Warning: Album private!"){lychee.setMode("view");return false}if(data==="Warning: Wrong password!"){album.load(albumID,refresh);return false}album.json=data;durationTime=(new Date).getTime()-startTime;if(durationTime>300)waitTime=0;else if(refresh)waitTime=0;else waitTime=300-durationTime;if(!visible.albums()&&!visible.photo()&&!visible.album())waitTime=0;setTimeout(function(){view.album.init();if(!refresh){lychee.animate(".album, .photo","contentZoomIn");view.header.mode("album")}},waitTime)})})},parse:function(photo){if(photo&&photo.thumbUrl)photo.thumbUrl=lychee.upload_path_thumb+photo.thumbUrl;else if(!album.json.title)album.json.title="Untitled"},add:function(){var title,params,buttons;buttons=[["Create Album",function(){title=$(".message input.text").val();if(title==="")title="Untitled";if(title.length>0&&title.length<31){modal.close();params="addAlbum&title="+escape(encodeURI(title));lychee.api(params,function(data){if(data!==false){if(data===true)data=1;lychee.goto(data)}else lychee.error(null,params,data)})}else loadingBar.show("error","Title too short or too long. Please try again!")}],["Cancel",function(){}]];modal.show("New Album","Please enter a title for this album: ",buttons)},"delete":function(albumID){var params,buttons,albumTitle;buttons=[["Delete Album and Photos",function(){params="deleteAlbum&albumID="+albumID;lychee.api(params,function(data){if(visible.albums()){albums.json.num--;view.albums.content.delete(albumID)}else lychee.goto("");if(data!==true)lychee.error(null,params,data)})}],["Keep Album",function(){}]];if(albumID==="0"){buttons[0][0]="Clear Unsorted";modal.show("Clear Unsorted","Are you sure you want to delete all photos from 'Unsorted'?
This action can't be undone!",buttons)}else{if(album.json)albumTitle=album.json.title;else if(albums.json)albumTitle=albums.json.content[albumID].title;modal.show("Delete Album","Are you sure you want to delete the album '"+albumTitle+"' and all of the photos it contains? This action can't be undone!",buttons)}},setTitle:function(albumID){var oldTitle="",newTitle,params,buttons;if(!albumID)return false;if(album.json)oldTitle=album.json.title;else if(albums.json)oldTitle=albums.json.content[albumID].title;buttons=[["Set Title",function(){newTitle=$(".message input.text").val();if(newTitle==="")newTitle="Untitled";if(albumID!==""&&albumID!=null&&albumID&&newTitle.length<31){if(visible.album()){album.json.title=newTitle;view.album.title(oldTitle)}else if(visible.albums()){albums.json.content[albumID].title=newTitle;view.albums.content.title(albumID)}params="setAlbumTitle&albumID="+albumID+"&title="+escape(encodeURI(newTitle));lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}else if(newTitle.length>0)loadingBar.show("error","New title too short or too long. Please try again!")}],["Cancel",function(){}]];modal.show("Set Title","Please enter a new title for this album: ",buttons)},setDescription:function(photoID){var oldDescription=album.json.description,description,params,buttons;buttons=[["Set Description",function(){description=$(".message input.text").val();if(description.length<800){if(visible.album()){album.json.description=description;view.album.description()}params="setAlbumDescription&albumID="+photoID+"&description="+escape(description);lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}else loadingBar.show("error","Description too long. Please try again!")}],["Cancel",function(){}]];modal.show("Set Description","Please enter a description for this album: ",buttons)},setPublic:function(albumID,e){var params;if($(".message input.text").length>0&&$(".message input.text").val().length>0){params="setAlbumPublic&albumID="+albumID+"&password="+hex_md5($(".message input.text").val());album.json.password=true}else{params="setAlbumPublic&albumID="+albumID;album.json.password=false}if(visible.album()){album.json.public=album.json.public==0?1:0;view.album.public();view.album.password();if(album.json.public==1)contextMenu.shareAlbum(albumID,e)}lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})},share:function(service){var link="",url=location.href;switch(service){case 0:link="https://twitter.com/share?url="+encodeURI(url);break;case 1:link="http://www.facebook.com/sharer.php?u="+encodeURI(url)+"&t="+encodeURI(album.json.title);break;case 2:link="mailto:?subject="+encodeURI(album.json.title)+"&body="+encodeURI("Hi! Check this out: "+url);break;default:link="";break}if(link.length>5)location.href=link},getArchive:function(albumID){var link;if(location.href.indexOf("index.html")>0)link=location.href.replace(location.hash,"").replace("index.html","php/api.php?function=getAlbumArchive&albumID="+albumID);else link=location.href.replace(location.hash,"")+"php/api.php?function=getAlbumArchive&albumID="+albumID;if(lychee.publicMode)link+="&password="+password.value;location.href=link}};albums={json:null,load:function(){var startTime,durationTime,waitTime;lychee.animate(".album, .photo","contentZoomOut");lychee.animate(".divider","fadeOut");startTime=(new Date).getTime();lychee.api("getAlbums",function(data){data.unsortedAlbum={id:0,title:"Unsorted",sysdate:data.unsortedNum+" photos",unsorted:1,thumb0:data.unsortedThumb0,thumb1:data.unsortedThumb1,thumb2:data.unsortedThumb2};data.starredAlbum={id:"f",title:"Starred",sysdate:data.starredNum+" photos",star:1,thumb0:data.starredThumb0,thumb1:data.starredThumb1,thumb2:data.starredThumb2};data.publicAlbum={id:"s",title:"Public",sysdate:data.publicNum+" photos","public":1,thumb0:data.publicThumb0,thumb1:data.publicThumb1,thumb2:data.publicThumb2};albums.json=data;durationTime=(new Date).getTime()-startTime;if(durationTime>300)waitTime=0;else waitTime=300-durationTime;if(!visible.albums()&&!visible.photo()&&!visible.album())waitTime=0;setTimeout(function(){view.header.mode("albums");view.albums.init();lychee.animate(".album, .photo","contentZoomIn")},waitTime)})},parse:function(album){if(album.password&&lychee.publicMode){album.thumb0="assets/img/password.svg";album.thumb1="assets/img/password.svg";album.thumb2="assets/img/password.svg"}else{if(album.thumb0)album.thumb0=lychee.upload_path_thumb+album.thumb0;else album.thumb0="assets/img/no_images.svg";if(album.thumb1)album.thumb1=lychee.upload_path_thumb+album.thumb1;else album.thumb1="assets/img/no_images.svg";if(album.thumb2)album.thumb2=lychee.upload_path_thumb+album.thumb2;else album.thumb2="assets/img/no_images.svg"}}};build={divider:function(title){return"

"+title+"

"},editIcon:function(id){return"
"},album:function(albumJSON){if(!albumJSON)return"";var album="",longTitle="",title=albumJSON.title;if(title.length>18){title=albumJSON.title.substr(0,18)+"...";longTitle=albumJSON.title}typeThumb0=albumJSON.thumb0.split(".").pop();typeThumb1=albumJSON.thumb1.split(".").pop();typeThumb2=albumJSON.thumb2.split(".").pop();album+="
";album+="thumb";album+="thumb";album+="thumb";album+="
";if(albumJSON.password&&!lychee.publicMode)album+="

"+title+"

";else album+="

"+title+"

";album+=""+albumJSON.sysdate+"";album+="
";if(!lychee.publicMode&&albumJSON.star==1)album+="";if(!lychee.publicMode&&albumJSON.public==1)album+="";if(!lychee.publicMode&&albumJSON.unsorted==1)album+="";album+="
";return album},photo:function(photoJSON){if(!photoJSON)return"";var photo="",longTitle="",title=photoJSON.title;if(title.length>18){title=photoJSON.title.substr(0,18)+"...";longTitle=photoJSON.title}photo+="
";photo+="thumb";photo+="
";photo+="

"+title+"

";photo+=""+photoJSON.sysdate+"";photo+="
";if(photoJSON.star==1)photo+="";if(!lychee.publicMode&&photoJSON.public==1&&album.json.public!=1)photo+="";photo+="
";return photo},imageview:function(photoJSON,isSmall,visibleControls){if(!photoJSON)return"";var view="";view+="";view+="";if(isSmall){if(visibleControls)view+="
";else view+="
"}else{if(visibleControls)view+="
";else view+="
"}return view},no_content:function(typ){var no_content="";no_content+="
";no_content+="";if(typ==="search")no_content+="

No results

";else if(typ==="picture")no_content+="

No public albums

";else if(typ==="cog")no_content+="

No Configuration!

";no_content+="
";return no_content},modal:function(title,text,button,marginTop,closeButton){var modal="",custom_style="";if(marginTop)custom_style="style='margin-top: "+marginTop+"px;'";modal+="
";modal+="
";modal+="

"+title+"

";if(closeButton!=false){modal+=""}modal+="

"+text+"

";$.each(button,function(index){if(this[0]!=""){if(index===0)modal+=""+this[0]+"";else modal+=""+this[0]+""}});modal+="
";modal+="
";return modal},signInModal:function(){var modal="";modal+="
";modal+="
";modal+="

Sign In

";modal+="";modal+="";modal+="
Version "+lychee.version+"Update available!
";modal+="Sign in";modal+="
";modal+="
";return modal},uploadModal:function(icon,text){var modal="";modal+="
";modal+="
";modal+="";if(text!==undefined)modal+="

"+text+"

";else modal+="
";modal+="
";modal+="
";return modal},contextMenu:function(items){var menu="";menu+="
";menu+="
";menu+="";menu+="";$.each(items,function(index){if(items[index][0]==="separator"&&items[index][1]===-1)menu+="";else if(items[index][1]===-1)menu+="";else if(items[index][2]!=undefined)menu+="";else menu+=""});menu+="";menu+="
"+items[index][0]+"
"+items[index][0]+"
"+items[index][0]+"
";menu+="
";return menu},infoboxPhoto:function(photoJSON,forView){if(!photoJSON)return"";var infobox="",public,editTitleHTML,editDescriptionHTML,infos;infobox+="

About

";infobox+="
";switch(photoJSON.public){case"0":public="Private";break;case"1":public="Public";break;case"2":public="Public (Album)";break;default:public="-";break}editTitleHTML=forView===true||lychee.publicMode?"":" "+build.editIcon("edit_title");editDescriptionHTML=forView===true||lychee.publicMode?"":" "+build.editIcon("edit_description");infos=[["","Basics"],["Name",photoJSON.title+editTitleHTML],["Uploaded",photoJSON.sysdate],["Description",photoJSON.description+editDescriptionHTML],["","Image"],["Size",photoJSON.size],["Format",photoJSON.type],["Resolution",photoJSON.width+" x "+photoJSON.height]];if(photoJSON.takedate+photoJSON.make+photoJSON.model+photoJSON.shutter+photoJSON.aperture+photoJSON.focal+photoJSON.iso!=""){infos=infos.concat([["","Camera"],["Captured",photoJSON.takedate],["Make",photoJSON.make],["Type/Model",photoJSON.model],["Shutter Speed",photoJSON.shutter],["Aperture",photoJSON.aperture],["Focal Length",photoJSON.focal],["ISO",photoJSON.iso]])}infos=infos.concat([["","Share"],["Visibility",public]]);$.each(infos,function(index){if(infos[index][1]===""||infos[index][1]==undefined||infos[index][1]==null)infos[index][1]="-";switch(infos[index][0]){case"":infobox+="";infobox+="

"+infos[index][1]+"

";infobox+="";break;case"Tags":infobox+="
";infobox+="

"+infos[index][0]+"

";infobox+="";infobox+="
"+infos[index][1]+"
";infobox+="";break;default:infobox+="";infobox+=""+infos[index][0]+"";infobox+=""+infos[index][1]+"";infobox+="";break}});infobox+="";infobox+="
";infobox+="
";return infobox},infoboxAlbum:function(albumJSON,forView){if(!albumJSON)return"";var infobox="",public,password,editTitleHTML,editDescriptionHTML,infos;infobox+="

About

";infobox+="
";switch(albumJSON.public){case"0":public="Private";break;case"1":public="Public";break;default:public="-";break}switch(albumJSON.password){case false:password="No";break;case true:password="Yes";break;default:password="-";break}editTitleHTML=forView===true||lychee.publicMode?"":" "+build.editIcon("edit_title_album");editDescriptionHTML=forView===true||lychee.publicMode?"":" "+build.editIcon("edit_description_album");infos=[["","Basics"],["Name",albumJSON.title+editTitleHTML],["Description",albumJSON.description+editDescriptionHTML],["","Album"],["Created",albumJSON.sysdate],["Images",albumJSON.num],["","Share"],["Visibility",public],["Password",password]];$.each(infos,function(index){if(infos[index][1]===""||infos[index][1]==undefined||infos[index][1]==null)infos[index][1]="-";if(infos[index][0]===""){infobox+="";infobox+="

"+infos[index][1]+"

";infobox+=""}else{infobox+="";infobox+="";infobox+="";infobox+=""}});infobox+="
"+infos[index][0]+""+infos[index][1]+"
";infobox+="
";infobox+="
";return infobox}};contextMenu={fns:null,show:function(items,mouse_x,mouse_y,orientation){if(visible.contextMenu())contextMenu.close();$("body").css("overflow","hidden").append(build.contextMenu(items));if(mouse_x+$(".contextmenu").outerWidth(true)>$("html").width())orientation="left";if(mouse_y+$(".contextmenu").outerHeight(true)>$("html").height())mouse_y-=mouse_y+$(".contextmenu").outerHeight(true)-$("html").height();if(orientation==="left")mouse_x-=$(".contextmenu").outerWidth(true);if(!mouse_x||!mouse_y){mouse_x="10px";mouse_y="10px"}$(".contextmenu").css({top:mouse_y,left:mouse_x,opacity:.98})},add:function(e){var mouse_x=e.pageX,mouse_y=e.pageY,items;mouse_y-=$(document).scrollTop();upload.notify();contextMenu.fns=[function(){$("#upload_files").click()},function(){upload.start.url()},function(){upload.start.dropbox()},function(){upload.start.server()},function(){album.add()}];items=[[" Upload Photo",0],["separator",-1],[" Import from Link",1],[" Import from Dropbox",2],[" Import from Server",3],["separator",-1],[" New Album",4]];contextMenu.show(items,mouse_x,mouse_y,"left")},settings:function(e){var mouse_x=e.pageX,mouse_y=e.pageY,items;mouse_y-=$(document).scrollTop();contextMenu.fns=[function(){settings.setLogin()},function(){settings.setSorting()},function(){window.open(lychee.website,"_newtab")},function(){lychee.logout()}];items=[[" Change Login",0],[" Change Sorting",1],[" About Lychee",2],["separator",-1],[" Sign Out",3]];contextMenu.show(items,mouse_x,mouse_y,"right")},album:function(albumID,e){var mouse_x=e.pageX,mouse_y=e.pageY,items;if(albumID==="0"||albumID==="f"||albumID==="s")return false;mouse_y-=$(document).scrollTop();contextMenu.fns=[function(){album.setTitle(albumID)},function(){album.delete(albumID)}];items=[[" Rename",0],[" Delete",1]];contextMenu.show(items,mouse_x,mouse_y,"right");$(".album[data-id='"+albumID+"']").addClass("active")},photo:function(photoID,e){var mouse_x=e.pageX,mouse_y=e.pageY,items;mouse_y-=$(document).scrollTop();contextMenu.fns=[function(){photo.setStar(photoID)},function(){photo.setTitle(photoID)},function(){contextMenu.move(photoID,e,"right")},function(){photo.delete(photoID)}];items=[[" Star",0],["separator",-1],[" Rename",1],[" Move",2],[" Delete",3]];contextMenu.show(items,mouse_x,mouse_y,"right");$(".photo[data-id='"+photoID+"']").addClass("active")},move:function(photoID,e,orientation){var mouse_x=e.pageX,mouse_y=e.pageY,items=[];contextMenu.fns=[];if(album.getID()!=="0"){items=[["Unsorted",0,"photo.setAlbum(0, "+photoID+")"],["separator",-1]]}lychee.api("getAlbums",function(data){if(!data.albums){items=[["New Album",0,"album.add()"]]}else{$.each(data.content,function(index){if(this.id!=album.getID())items.push([this.title,0,"photo.setAlbum("+this.id+", "+photoID+")"])})}contextMenu.close();$(".photo[data-id='"+photoID+"']").addClass("active");if(!visible.photo())contextMenu.show(items,mouse_x,mouse_y,"right");else contextMenu.show(items,mouse_x,mouse_y,"left")})},sharePhoto:function(photoID,e){var mouse_x=e.pageX,mouse_y=e.pageY,items;mouse_y-=$(document).scrollTop();contextMenu.fns=[function(){photo.setPublic(photoID)},function(){photo.share(photoID,0)},function(){photo.share(photoID,1)},function(){photo.share(photoID,2)},function(){photo.share(photoID,3)},function(){window.open(photo.getDirectLink(),"_newtab")}];link=photo.getViewLink(photoID);if(photo.json.public==="2")link=location.href;items=[["",-1],["separator",-1],[" Make Private",0],["separator",-1],[" Twitter",1],[" Facebook",2],[" Mail",3],[" Dropbox",4],[" Direct Link",5]];contextMenu.show(items,mouse_x,mouse_y,"left");$(".contextmenu input").focus()},shareAlbum:function(albumID,e){var mouse_x=e.pageX,mouse_y=e.pageY,items;mouse_y-=$(document).scrollTop();contextMenu.fns=[function(){album.setPublic(albumID)},function(){password.set(albumID)},function(){album.share(0)},function(){album.share(1)},function(){album.share(2)},function(){password.remove(albumID)}];items=[["",-1],["separator",-1],[" Make Private",0],[" Set Password",1],["separator",-1],[" Twitter",2],[" Facebook",3],[" Mail",4]];if(album.json.password==true)items[3]=[" Remove Password",5];contextMenu.show(items,mouse_x,mouse_y,"left");$(".contextmenu input").focus()},close:function(){contextMenu.js=null;$(".contextmenu_bg, .contextmenu").remove();$(".photo.active, .album.active").removeClass("active");$("body").css("overflow","auto")}};$(document).ready(function(){var event_name=mobileBrowser()?"touchend":"click";$(document).bind("contextmenu",function(e){e.preventDefault()});if(!mobileBrowser())$(".tools").tipsy({gravity:"n",fade:false,delayIn:0,opacity:1});$("#hostedwith").on(event_name,function(){window.open(lychee.website,"_newtab")});$("#button_signin").on(event_name,lychee.loginDialog);$("#button_settings").on(event_name,contextMenu.settings);$("#button_share").on(event_name,function(e){if(photo.json.public==1||photo.json.public==2)contextMenu.sharePhoto(photo.getID(),e);else photo.setPublic(photo.getID(),e)});$("#button_share_album").on(event_name,function(e){if(album.json.public==1)contextMenu.shareAlbum(album.getID(),e);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? ",[["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_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()});$("#button_info").on(event_name,function(){view.infobox.show()});$("#button_archive").on(event_name,function(){album.getArchive(album.getID())});$("#button_star").on(event_name,function(){photo.setStar(photo.getID())});$("#search").on("keyup click",function(){search.find($(this).val())});$("#clearSearch").on(event_name,function(){$("#search").focus();search.reset()});$("#button_back_home").on(event_name,function(){lychee.goto("")});$("#button_back").on(event_name,function(){lychee.goto(album.getID())});lychee.imageview.on(event_name,".arrow_wrapper.previous",function(){if(album.json&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].previousPhoto!=="")lychee.goto(album.getID()+"/"+album.json.content[photo.getID()].previousPhoto)}).on(event_name,".arrow_wrapper.next",function(){if(album.json&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].nextPhoto!=="")lychee.goto(album.getID()+"/"+album.json.content[photo.getID()].nextPhoto)});$("#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_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())});Mousetrap.bind("u",function(){$("#upload_files").click()}).bind("s",function(){if(visible.photo())$("#button_star").click()}).bind("command+backspace",function(){if(visible.photo()&&!visible.message())photo.delete(photo.getID())}).bind("left",function(){if(visible.photo())$("#imageview a#previous").click()}).bind("right",function(){if(visible.photo())$("#imageview a#next").click()}).bind("i",function(){if(visible.infobox())view.infobox.hide();else if(!visible.albums())view.infobox.show()});Mousetrap.bindGlobal("enter",function(){if($(".message .button.active").length)$(".message .button.active").addClass("pressed").click()});Mousetrap.bindGlobal(["esc","command+up"],function(e){e.preventDefault();if(visible.message()&&$(".message .close").length>0)modal.close();else if(visible.contextMenu())contextMenu.close();else if(visible.infobox())view.infobox.hide();else if(visible.photo())lychee.goto(album.getID());else if(visible.album())lychee.goto("");else if(visible.albums()&&$("#search").val().length!==0)search.reset()});$(document).on("keyup","#password",function(){if($(this).val().length>0)$(this).removeClass("error")}).on(event_name,"#title.editable",function(){if(visible.photo())photo.setTitle(photo.getID());else album.setTitle(album.getID())}).on("click",".album",function(){lychee.goto($(this).attr("data-id"))}).on("click",".photo",function(){lychee.goto(album.getID()+"/"+$(this).attr("data-id"))}).on(event_name,".message .close",modal.close).on(event_name,".message .button:first",function(){if(modal.fns!=null)modal.fns[0]();if(!visible.signin())modal.close()}).on(event_name,".message .button:last",function(){if(modal.fns!=null)modal.fns[1]();if(!visible.signin())modal.close()}).on(event_name,".button_add",function(e){contextMenu.add(e)}).on("change","#upload_files",function(){modal.close();upload.start.local(this.files)}).on("contextmenu",".photo",function(e){contextMenu.photo(photo.getID(),e)}).on("contextmenu",".album",function(e){contextMenu.album(album.getID(),e)}).on(event_name,".contextmenu_bg",contextMenu.close).on("contextmenu",".contextmenu_bg",contextMenu.close).on(event_name,"#infobox_overlay",view.infobox.hide).on("dragover",function(e){e.preventDefault()},false).on("drop",function(e){e.stopPropagation();e.preventDefault();if(e.originalEvent.dataTransfer.files.length>0)upload.start.local(e.originalEvent.dataTransfer.files);else if(e.originalEvent.dataTransfer.getData("Text").length>3)upload.start.url(e.originalEvent.dataTransfer.getData("Text"));return true});lychee.init()});loadingBar={status:null,show:function(status,errorText){if(status==="error"){loadingBar.status="error";if(!errorText)errorText="Whoops, it looks like something went wrong. Please reload the site and try again!";lychee.loadingBar.removeClass("loading uploading error").addClass(status).html("

Error: "+errorText+"

").show().css("height","40px");if(visible.controls())lychee.header.addClass("error");clearTimeout(lychee.loadingBar.data("timeout"));lychee.loadingBar.data("timeout",setTimeout(function(){loadingBar.hide(true)},3e3))}else if(loadingBar.status==null){loadingBar.status="loading";clearTimeout(lychee.loadingBar.data("timeout"));lychee.loadingBar.data("timeout",setTimeout(function(){lychee.loadingBar.show().removeClass("loading uploading error").addClass("loading");if(visible.controls())lychee.header.addClass("loading")},1e3))}},hide:function(force_hide){if(loadingBar.status!=="error"&&loadingBar.status!=null||force_hide){loadingBar.status=null;clearTimeout(lychee.loadingBar.data("timeout"));lychee.loadingBar.html("").css("height","3px");if(visible.controls())lychee.header.removeClass("error loading");setTimeout(function(){lychee.loadingBar.hide()},300)}}};var lychee={version:"2.0.2",api_path:"php/api.php",update_path:"http://lychee.electerious.com/version/index.php",updateURL:"https://github.com/electerious/Lychee",website:"http://lychee.electerious.com",upload_path_thumb:"uploads/thumb/",upload_path_big:"uploads/big/",publicMode:false,viewMode:false,debugMode:false,username:"",checkForUpdates:false,sorting:"",dropbox:false,loadingBar:$("#loading"),header:$("header"),content:$("#content"),imageview:$("#imageview"),infobox:$("#infobox"),init:function(){lychee.api("init",function(data){if(data.loggedIn!==true){lychee.setMode("public")}else{lychee.username=data.config.username;lychee.sorting=data.config.sorting}if(data==="Warning: No configuration!"){lychee.header.hide();lychee.content.hide();$("body").append(build.no_content("cog"));settings.createConfig();return true}if(data.config.login===false){settings.createLogin()}lychee.checkForUpdates=data.config.checkForUpdates;$(window).bind("popstate",lychee.load);lychee.load()})},api:function(params,callback,loading){if(loading==undefined)loadingBar.show();$.ajax({type:"POST",url:lychee.api_path,data:"function="+params,dataType:"text",success:function(data){setTimeout(function(){loadingBar.hide()},100);if(typeof data==="string"&&data.substring(0,7)==="Error: "){lychee.error(data.substring(7,data.length),params,data);return false}if(data==="1")data=true;else if(data==="")data=false;if(typeof data==="string"&&data.substring(0,1)==="{"&&data.substring(data.length-1,data.length)==="}")data=$.parseJSON(data);if(lychee.debugMode)console.log(data);callback(data)},error:function(jqXHR,textStatus,errorThrown){lychee.error("Server error or API not found.",params,errorThrown)}})},login:function(){var user=$("input#username").val(),password=hex_md5($("input#password").val()),params;params="login&user="+user+"&password="+password;lychee.api(params,function(data){if(data===true){localStorage.setItem("username",user);window.location.reload()}else{$("#password").val("").addClass("error");$(".message .button.active").removeClass("pressed")}})},loginDialog:function(){var local_username;$("body").append(build.signInModal());$("#username").focus();if(localStorage){local_username=localStorage.getItem("username");if(local_username!=null){if(local_username.length>0)$("#username").val(local_username);$("#password").focus()}}if(lychee.checkForUpdates==="1")lychee.getUpdate()},logout:function(){lychee.api("logout",function(data){window.location.reload()})},"goto":function(url){if(url==undefined)url="";document.location.hash=url},load:function(){var albumID="",photoID="",hash=document.location.hash.replace("#","").split("/");contextMenu.close();if(hash[0]!==undefined)albumID=hash[0];if(hash[1]!==undefined)photoID=hash[1];if(albumID&&photoID){albums.json=null;photo.json=null;if(lychee.content.html()===""||$("#search").length&&$("#search").val().length!==0){lychee.content.hide();album.load(albumID,true)}photo.load(photoID,albumID)}else if(albumID){albums.json=null;photo.json=null;if(visible.photo())view.photo.hide();if(album.json&&albumID==album.json.id)view.album.title();else album.load(albumID)}else{albums.json=null;album.json=null;photo.json=null;search.code="";if(visible.album())view.album.hide();if(visible.photo())view.photo.hide();albums.load()}},getUpdate:function(){$.ajax({url:lychee.update_path,success:function(data){if(data!=lychee.version)$("#version span").show()}})},setTitle:function(title,editable){if(title==="Albums")document.title="Lychee";else document.title="Lychee - "+title;if(editable)$("#title").addClass("editable"); -else $("#title").removeClass("editable");$("#title").html(title)},setMode:function(mode){$("#button_settings, #button_settings, #button_search, #search, #button_trash_album, #button_share_album, .button_add, .button_divider").remove();$("#button_trash, #button_move, #button_share, #button_star").remove();$(document).on("mouseenter","#title.editable",function(){$(this).removeClass("editable")}).off("click","#title.editable").off("touchend","#title.editable").off("contextmenu",".photo").off("contextmenu",".album").off("drop");Mousetrap.unbind("n").unbind("u").unbind("s").unbind("backspace");if(mode==="public"){$("header #button_signin, header #hostedwith").show();lychee.publicMode=true}else if(mode==="view"){Mousetrap.unbind("esc");$("#button_back, a#next, a#previous").remove();lychee.publicMode=true;lychee.viewMode=true}},animate:function(obj,animation){var animations=[["fadeIn","fadeOut"],["contentZoomIn","contentZoomOut"]];if(!obj.jQuery)obj=$(obj);for(var i=0;i",buttons)},get:function(albumID,callback){var passwd=$(".message input.text").val(),params;if(!lychee.publicMode)callback();else if(album.json&&album.json.password==false)callback();else if(albums.json&&albums.json.content[albumID].password==false)callback();else if(!albums.json&&!album.json){album.json={password:true};callback("")}else if(passwd==undefined){password.getDialog(albumID,callback)}else{params="checkAlbumAccess&albumID="+albumID+"&password="+hex_md5(passwd);lychee.api(params,function(data){if(data===true){password.value=hex_md5(passwd);callback()}else{lychee.goto("");loadingBar.show("error","Access denied. Wrong password!")}})}},getDialog:function(albumID,callback){var buttons;buttons=[["Enter",function(){password.get(albumID,callback)}],["Cancel",lychee.goto]];modal.show(" Enter Password","This album is protected by a password. Enter the password below to view the photos of this album: ",buttons,-110,false)},remove:function(albumID){var params;if(visible.album()){album.json.password=false;view.album.password()}params="setAlbumPassword&albumID="+albumID+"&password=";lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}};photo={json:null,getID:function(){var id;if(photo.json)id=photo.json.id;else id=$(".photo:hover, .photo.active").attr("data-id");if(id)return id;else return false},load:function(photoID,albumID){var params,checkPasswd;params="getPhoto&photoID="+photoID+"&albumID="+albumID+"&password="+password.value;lychee.api(params,function(data){if(data==="Warning: Wrong password!"){checkPasswd=function(){if(password.value!=="")photo.load(photoID,albumID);else setTimeout(checkPasswd,250)};checkPasswd();return false}photo.json=data;if(!visible.photo())view.photo.show();view.photo.init();lychee.imageview.show();setTimeout(function(){lychee.content.show()},300)})},parse:function(){if(!photo.json.title)photo.json.title="Untitled";photo.json.url=lychee.upload_path_big+photo.json.url},"delete":function(photoID){var params,buttons,photoTitle;if(!photoID)return false;if(visible.photo())photoTitle=photo.json.title;else photoTitle=album.json.content[photoID].title;if(photoTitle=="")photoTitle="Untitled";buttons=[["Delete Photo",function(){if(album.json.content[photoID].nextPhoto!==""||album.json.content[photoID].previousPhoto!==""){nextPhoto=album.json.content[photoID].nextPhoto;previousPhoto=album.json.content[photoID].previousPhoto;album.json.content[previousPhoto].nextPhoto=nextPhoto;album.json.content[nextPhoto].previousPhoto=previousPhoto}album.json.content[photoID]=null;view.album.content.delete(photoID);if(!visible.albums())lychee.goto(album.getID());params="deletePhoto&photoID="+photoID;lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["Keep Photo",function(){}]];modal.show("Delete Photo","Are you sure you want to delete the photo '"+photoTitle+"'?
This action can't be undone!",buttons)},setTitle:function(photoID){var oldTitle="",newTitle,params,buttons;if(!photoID)return false;if(photo.json)oldTitle=photo.json.title;else if(album.json)oldTitle=album.json.content[photoID].title;buttons=[["Set Title",function(){newTitle=$(".message input.text").val();if(photoID!=null&&photoID&&newTitle.length<31){if(visible.photo()){photo.json.title=newTitle===""?"Untitled":newTitle;view.photo.title(oldTitle)}album.json.content[photoID].title=newTitle;view.album.content.title(photoID);params="setPhotoTitle&photoID="+photoID+"&title="+escape(encodeURI(newTitle));lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}else if(newTitle.length>0)loadingBar.show("error","New title to short or too long. Please try another one!")}],["Cancel",function(){}]];modal.show("Set Title","Please enter a new title for this photo: ",buttons)},setAlbum:function(albumID,photoID){var params;if(albumID>=0){if(album.json.content[photoID].nextPhoto!==""||album.json.content[photoID].previousPhoto!==""){nextPhoto=album.json.content[photoID].nextPhoto;previousPhoto=album.json.content[photoID].previousPhoto;album.json.content[previousPhoto].nextPhoto=nextPhoto;album.json.content[nextPhoto].previousPhoto=previousPhoto}if(visible.photo)lychee.goto(album.getID());album.json.content[photoID]=null;view.album.content.delete(photoID);params="setAlbum&photoID="+photoID+"&albumID="+albumID;lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}},setStar:function(photoID){var params;if(visible.photo()){photo.json.star=photo.json.star==0?1:0;view.photo.star()}album.json.content[photoID].star=album.json.content[photoID].star==0?1:0;view.album.content.star(photoID);params="setPhotoStar&photoID="+photoID;lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})},setPublic:function(photoID,e){var params;if(photo.json.public==2){modal.show("Public Album","This photo is located in a public album. To make this photo private or public, edit the visibility of the associated album.",[["Show Album",function(){lychee.goto(photo.json.original_album)}],["Close",function(){}]]);return false}if(visible.photo()){photo.json.public=photo.json.public==0?1:0;view.photo.public();if(photo.json.public==1)contextMenu.sharePhoto(photoID,e)}album.json.content[photoID].public=album.json.content[photoID].public==0?1:0;view.album.content.public(photoID);params="setPhotoPublic&photoID="+photoID+"&url="+photo.getViewLink(photoID);lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})},setDescription:function(photoID){var oldDescription=photo.json.description,description,params,buttons;buttons=[["Set Description",function(){description=$(".message input.text").val();if(description.length<800){if(visible.photo()){photo.json.description=description;view.photo.description()}params="setPhotoDescription&photoID="+photoID+"&description="+escape(description);lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}else loadingBar.show("error","Description too long. Please try again!")}],["Cancel",function(){}]];modal.show("Set Description","Please enter a description for this photo: ",buttons)},share:function(photoID,service){var link="",url=photo.getViewLink(photoID),filename="unknown";switch(service){case 0:link="https://twitter.com/share?url="+encodeURI(url);break;case 1:link="http://www.facebook.com/sharer.php?u="+encodeURI(url)+"&t="+encodeURI(photo.json.title);break;case 2:link="mailto:?subject="+encodeURI(photo.json.title)+"&body="+encodeURI(url);break;case 3:lychee.loadDropbox(function(){filename=photo.json.title+"."+photo.getDirectLink().split(".").pop();Dropbox.save(photo.getDirectLink(),filename)});break;default:link="";break}if(link.length>5)location.href=link},isSmall:function(){var size=[["width",false],["height",false]];if(photo.json.width<$(window).width()-60)size["width"]=true;if(photo.json.height<$(window).height()-100)size["height"]=true;if(size["width"]&&size["height"])return true;else return false},getArchive:function(photoID){var link;if(location.href.indexOf("index.html")>0)link=location.href.replace(location.hash,"").replace("index.html","php/api.php?function=getPhotoArchive&photoID="+photoID);else link=location.href.replace(location.hash,"")+"php/api.php?function=getPhotoArchive&photoID="+photoID;if(lychee.publicMode)link+="&password="+password.value;location.href=link},getDirectLink:function(){return $("#imageview #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/gi,"")},getViewLink:function(photoID){if(location.href.indexOf("index.html")>0)return location.href.replace("index.html"+location.hash,"view.php?p="+photoID);else return location.href.replace(location.hash,"view.php?p="+photoID)}};search={code:null,find:function(term){var params,albumsData="",photosData="",code;clearTimeout($(window).data("timeout"));$(window).data("timeout",setTimeout(function(){if($("#search").val().length!==0){params="search&term="+term;lychee.api(params,function(data){if(data&&data.albums){albums.json={content:data.albums};$.each(albums.json.content,function(){albums.parse(this);albumsData+=build.album(this)})}if(data&&data.photos){album.json={content:data.photos};$.each(album.json.content,function(){album.parse(this);photosData+=build.photo(this)})}if(albumsData===""&&photosData==="")code="error";else if(albumsData==="")code=build.divider("Photos")+photosData;else if(photosData==="")code=build.divider("Albums")+albumsData;else code=build.divider("Photos")+photosData+build.divider("Albums")+albumsData;if(search.code!==hex_md5(code)){$(".no_content").remove();lychee.animate(".album, .photo","contentZoomOut");lychee.animate(".divider","fadeOut");search.code=hex_md5(code);setTimeout(function(){if(code==="error")$("body").append(build.no_content("search"));else{lychee.content.html(code);lychee.animate(".album, .photo","contentZoomIn");$("img[data-type!='svg']").retina()}},300)}})}else search.reset()},250))},reset:function(){$("#search").val("");$(".no_content").remove();if(search.code!==""){search.code="";lychee.animate(".divider","fadeOut");albums.load()}}};var settings={createConfig:function(){var dbName,dbUser,dbPassword,dbHost,buttons;buttons=[["Connect",function(){dbHost=$(".message input.text#dbHost").val();dbUser=$(".message input.text#dbUser").val();dbPassword=$(".message input.text#dbPassword").val();dbName=$(".message input.text#dbName").val();if(dbHost.length<1)dbHost="localhost";if(dbName.length<1)dbName="lychee";params="createConfig&dbName="+escape(dbName)+"&dbUser="+escape(dbUser)+"&dbPassword="+escape(dbPassword)+"&dbHost="+escape(dbHost);lychee.api(params,function(data){if(data!==true){setTimeout(function(){if(data.indexOf("Warning: Connection failed!")!==-1){buttons=[["Retry",function(){setTimeout(settings.createConfig,400)}],["",function(){}]];modal.show("Connection Failed","Unable to connect to host database because access was denied. Double-check your host, username and password and ensure that access from your current location is permitted.",buttons,null,false);return false}if(data.indexOf("Warning: Could not create file!")!==-1){buttons=[["Retry",function(){setTimeout(settings.createConfig,400)}],["",function(){}]];modal.show("Saving Failed","Unable to save this configuration. Permission denied in 'php/'. Please set the read, write and execute rights for others in 'php/' and 'uploads/'. Take a look the readme for more information.",buttons,null,false);return false}buttons=[["Retry",function(){setTimeout(settings.createConfig,400)}],["",function(){}]];modal.show("Configuration Failed","Something unexpected happened. Please try again and check your installation and server. Take a look the readme for more information.",buttons,null,false);return false},400)}else{lychee.api("update",function(data){window.location.reload()})}})}],["",function(){}]];modal.show("Configuration","Enter your database connection details below:
Lychee will create its own database. If required, you can enter the name of an existing database instead:",buttons,-215,false)},createLogin:function(){var username,password,params,buttons;buttons=[["Create Login",function(){username=$(".message input.text#username").val();password=$(".message input.text#password").val();if(username.length<1||password.length<1){setTimeout(function(){buttons=[["Retry",function(){setTimeout(settings.createLogin,400)}],["",function(){}]];modal.show("Wrong Input","The username or password you entered is not long enough. Please try again with another username and password!",buttons,null,false);return false},400)}else{params="setLogin&username="+escape(username)+"&password="+hex_md5(password);lychee.api(params,function(data){if(data!==true){setTimeout(function(){buttons=[["Retry",function(){setTimeout(settings.createLogin,400)}],["",function(){}]];modal.show("Creation Failed","Unable to save login. Please try again with another username and password!",buttons,null,false);return false},400)}})}}],["",function(){}]];modal.show("Create Login","Enter a username and password for your installation: ",buttons,-122,false)},setLogin:function(){var old_password,username,password,params,buttons;buttons=[["Change Login",function(){old_password=$(".message input.text#old_password").val();username=$(".message input.text#username").val();password=$(".message input.text#password").val();if(old_password.length<1){loadingBar.show("error","Your old password was entered incorrectly. Please try again!");return false}if(username.length<1){loadingBar.show("error","Your new username was entered incorrectly. Please try again!");return false}if(password.length<1){loadingBar.show("error","Your new password was entered incorrectly. Please try again!");return false}params="setLogin&oldPassword="+hex_md5(old_password)+"&username="+escape(username)+"&password="+hex_md5(password);lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("Change Login","Enter your current password:
Your username and password will be changed to the following: ",buttons,-171)},setSorting:function(){var buttons,sorting;buttons=[["Change Sorting",function(){sorting[0]=$("select#settings_type").val();sorting[1]=$("select#settings_order").val();params="setSorting&type="+sorting[0]+"&order="+sorting[1];lychee.api(params,function(data){if(data===true){lychee.sorting="ORDER BY "+sorting[0]+" "+sorting[1];lychee.load()}else lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("Change Sorting","Sort photos by in an order. ",buttons);if(lychee.sorting!=""){sorting=lychee.sorting.replace("ORDER BY ","").replace(" ",";").split(";");$("select#settings_type").val(sorting[0]);$("select#settings_order").val(sorting[1])}}};upload={show:function(icon,text){if(icon===undefined)icon="upload";upload.close(true);$("body").append(build.uploadModal(icon,text))},setIcon:function(icon){$(".upload_message a").remove();$(".upload_message").prepend("")},setProgress:function(progress){$(".progressbar div").css("width",progress+"%")},setText:function(text){$(".progressbar").remove();$(".upload_message").append("

"+text+"

")},notify:function(title){var popup;if(!window.webkitNotifications)return false;if(window.webkitNotifications.checkPermission()!=0)window.webkitNotifications.requestPermission();if(window.webkitNotifications.checkPermission()==0&&title){popup=window.webkitNotifications.createNotification("",title,"You can now manage your new photo(s).");popup.show()}},start:{local:function(files){var pre_progress=0,formData=new FormData,xhr=new XMLHttpRequest,albumID=album.getID(),popup,progress;if(files.length<=0)return false;if(albumID===false)albumID=0;formData.append("function","upload");formData.append("albumID",albumID);for(var i=0;ipre_progress){upload.setProgress(progress);pre_progress=progress}if(progress>=100){upload.setIcon("cog");upload.setText("Processing photos")}}};$("#upload_files").val("");xhr.send(formData)},url:function(){var albumID=album.getID(),params,extension,buttons;if(albumID===false)albumID=0;buttons=[["Import",function(){link=$(".message input.text").val();if(link&&link.length>3){extension=link.split(".").pop();if(extension!=="jpeg"&&extension!=="jpg"&&extension!=="png"&&extension!=="gif"&&extension!=="webp"){loadingBar.show("error","The file format of this link is not supported.");return false}modal.close();upload.show("cog","Importing from URL");params="importUrl&url="+escape(encodeURI(link))+"&albumID="+albumID;lychee.api(params,function(data){upload.close();upload.notify("Import complete");if(album.getID()===false)lychee.goto("0");else album.load(albumID);if(data!==true)lychee.error(null,params,data)})}else loadingBar.show("error","Link to short or too long. Please try another one!")}],["Cancel",function(){}]];modal.show("Import from Link","Please enter the direct link to a photo to import it: ",buttons)},server:function(){var albumID=album.getID(),params,buttons;if(albumID===false)albumID=0;buttons=[["Import",function(){modal.close();upload.show("cog","Importing photos");params="importServer&albumID="+albumID;lychee.api(params,function(data){upload.close();upload.notify("Import complete");if(album.getID()===false)lychee.goto("0");else album.load(albumID);if(data==="Warning: Folder empty!")lychee.error("Folder empty. No photos imported!",params,data);else if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("Import from Server","This action will import all photos which are located in 'uploads/import/' of your Lychee installation.",buttons)},dropbox:function(){var albumID=album.getID(),params;if(albumID===false)albumID=0;lychee.loadDropbox(function(){Dropbox.choose({linkType:"direct",multiselect:true,success:function(files){if(files.length>1){for(var i=0;i0){$("#imageview #image").css({marginTop:-1*($("#imageview #image").height()/2)+20})}else{$("#imageview #image").css({top:60,right:30,bottom:30,left:30})}}},hide:function(){if(visible.photo()&&!visible.infobox()&&!visible.contextMenu()&&!visible.message()){clearTimeout($(window).data("timeout"));$(window).data("timeout",setTimeout(function(){lychee.imageview.addClass("full");lychee.loadingBar.css("opacity",0);lychee.header.addClass("hidden");if($("#imageview #image.small").length>0){$("#imageview #image").css({marginTop:-1*($("#imageview #image").height()/2)})}else{$("#imageview #image").css({top:0,right:0,bottom:0,left:0})}},500))}},mode:function(mode){var albumID=album.getID();switch(mode){case"albums":lychee.header.removeClass("view");$("#tools_album, #tools_photo").hide();$("#tools_albums").show();break;case"album":lychee.header.removeClass("view");$("#tools_albums, #tools_photo").hide();$("#tools_album").show();album.json.content===false?$("#button_archive").hide():$("#button_archive").show();if(albumID==="s"||albumID==="f"){$("#button_info_album, #button_trash_album, #button_share_album").hide()}else if(albumID==="0"){$("#button_info_album, #button_share_album").hide();$("#button_trash_album").show()}else{$("#button_info_album, #button_trash_album, #button_share_album").show()}break;case"photo":lychee.header.addClass("view");$("#tools_albums, #tools_album").hide();$("#tools_photo").show();break}}},infobox:{show:function(){if(!visible.infobox())$("body").append("
");lychee.infobox.addClass("active")},hide:function(){lychee.animate("#infobox_overlay","fadeOut");setTimeout(function(){$("#infobox_overlay").remove()},300);lychee.infobox.removeClass("active")}},albums:{init:function(){view.albums.title();view.albums.content.init()},title:function(){lychee.setTitle("Albums",false)},content:{init:function(){var smartData="",albumsData="";albums.parse(albums.json.unsortedAlbum);albums.parse(albums.json.publicAlbum);albums.parse(albums.json.starredAlbum);if(!lychee.publicMode)smartData=build.divider("Smart Albums")+build.album(albums.json.unsortedAlbum)+build.album(albums.json.starredAlbum)+build.album(albums.json.publicAlbum);if(albums.json.content){if(!lychee.publicMode)albumsData=build.divider("Albums");$.each(albums.json.content,function(){albums.parse(this);albumsData+=build.album(this)})}if(smartData===""&&albumsData==="")$("body").append(build.no_content("picture"));else lychee.content.html(smartData+albumsData);$("img[data-type!='svg']").retina()},title:function(albumID){var prefix="",longTitle="",title=albums.json.content[albumID].title;if(albums.json.content[albumID].password)prefix=" ";if(title.length>18){longTitle=title;title=title.substr(0,18)+"..."}$(".album[data-id='"+albumID+"'] .overlay h1").html(prefix+title).attr("title",longTitle)},"delete":function(albumID){$(".album[data-id='"+albumID+"']").css("opacity",0).animate({width:0,marginLeft:0},300,function(){$(this).remove();if(albums.json.num<=0)lychee.animate(".divider:last-of-type","fadeOut")})}}},album:{init:function(){album.parse();view.album.infobox();view.album.title();view.album.public();view.album.content.init();album.json.init=1},hide:function(){view.infobox.hide()},title:function(oldTitle){if((visible.album()||!album.json.init)&&!visible.photo()){switch(album.getID()){case"f":lychee.setTitle("Starred",false);break;case"s":lychee.setTitle("Public",false);break;case"0":lychee.setTitle("Unsorted",false);break;default:if(album.json.init)$("#infobox .attr_name").html(album.json.title+" "+build.editIcon("edit_title_album"));lychee.setTitle(album.json.title,true);break}}},description:function(){$("#infobox .attr_description").html(album.json.description+" "+build.editIcon("edit_description_album"))},content:{init:function(){var photosData="";$.each(album.json.content,function(){album.parse(this);photosData+=build.photo(this)});lychee.content.html(photosData);$("img[data-type!='svg']").retina()},title:function(photoID){var longTitle="",title=album.json.content[photoID].title;if(title.length>18){longTitle=title;title=title.substr(0,18)+"..."}$(".photo[data-id='"+photoID+"'] .overlay h1").html(title).attr("title",longTitle)},star:function(photoID){$(".photo[data-id='"+photoID+"'] .icon-star").remove();if(album.json.content[photoID].star==1)$(".photo[data-id='"+photoID+"']").append("")},"public":function(photoID){$(".photo[data-id='"+photoID+"'] .icon-share").remove();if(album.json.content[photoID].public==1)$(".photo[data-id='"+photoID+"']").append("")},"delete":function(photoID){$(".photo[data-id='"+photoID+"']").css("opacity",0).animate({width:0,marginLeft:0},300,function(){$(this).remove();if(!visible.albums()){album.json.num--;view.album.num();view.album.title()}})}},num:function(){$("#infobox .attr_images").html(album.json.num)},"public":function(){if(album.json.public==1){$("#button_share_album a").addClass("active");$("#button_share_album").attr("title","Share Album");$(".photo .icon-share").remove();if(album.json.init)$("#infobox .attr_visibility").html("Public")}else{$("#button_share_album a").removeClass("active");$("#button_share_album").attr("title","Make Public");if(album.json.init)$("#infobox .attr_visibility").html("Private")}},password:function(){if(album.json.password==1)$("#infobox .attr_password").html("Yes");else $("#infobox .attr_password").html("No")},infobox:function(){if((visible.album()||!album.json.init)&&!visible.photo())lychee.infobox.html(build.infoboxAlbum(album.json)).show()}},photo:{init:function(){photo.parse();view.photo.infobox();view.photo.title();view.photo.star();view.photo.public();view.photo.photo();photo.json.init=1},show:function(){lychee.content.addClass("view");view.header.mode("photo");$("body").css("overflow","hidden");$(document).bind("mouseenter",view.header.show).bind("mouseleave",view.header.hide);lychee.animate(lychee.imageview,"fadeIn")},hide:function(){if(!visible.controls())view.header.show();if(visible.infobox)view.infobox.hide();lychee.content.removeClass("view");view.header.mode("album");$("body").css("overflow","auto");$(document).unbind("mouseenter").unbind("mouseleave");lychee.animate(lychee.imageview,"fadeOut");setTimeout(function(){lychee.imageview.hide();view.album.infobox()},300)},title:function(oldTitle){if(photo.json.init)$("#infobox .attr_name").html(photo.json.title+" "+build.editIcon("edit_title"));lychee.setTitle(photo.json.title,true)},description:function(){if(photo.json.init)$("#infobox .attr_description").html(photo.json.description+" "+build.editIcon("edit_description"))},star:function(){$("#button_star a").removeClass("icon-star-empty icon-star");if(photo.json.star==1){$("#button_star a").addClass("icon-star");$("#button_star").attr("title","Unstar Photo")}else{$("#button_star a").addClass("icon-star-empty");$("#button_star").attr("title","Star Photo")}},"public":function(){if(photo.json.public==1||photo.json.public==2){$("#button_share a").addClass("active");$("#button_share").attr("title","Share Photo");if(photo.json.init)$("#infobox .attr_visibility").html("Public")}else{$("#button_share a").removeClass("active");$("#button_share").attr("title","Make Public");if(photo.json.init)$("#infobox .attr_visibility").html("Private")}},photo:function(){lychee.imageview.html(build.imageview(photo.json,photo.isSmall(),visible.controls()));if(album.json&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].nextPhoto===""||lychee.viewMode)$("a#next").hide();if(album.json&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].previousPhoto===""||lychee.viewMode)$("a#previous").hide()},infobox:function(){lychee.infobox.html(build.infoboxPhoto(photo.json)).show()}}};visible={albums:function(){if($("#tools_albums").css("display")==="block")return true;else return false},album:function(){if($("#tools_album").css("display")==="block")return true;else return false},photo:function(){if($("#imageview.fadeIn").length>0)return true;else return false},infobox:function(){if($("#infobox.active").length>0)return true;else return false},controls:function(){if(lychee.loadingBar.css("opacity")<1)return false;else return true},message:function(){if($(".message").length>0)return true;else return false},signin:function(){if($(".message .sign_in").length>0)return true;else return false},contextMenu:function(){if($(".contextmenu").length>0)return true;else return false}}; \ No newline at end of file +album={json:null,getID:function(){var id;if(photo.json)id=photo.json.album;else if(album.json)id=album.json.id;else id=$(".album:hover, .album.active").attr("data-id");if(!id)id=$(".photo:hover, .photo.active").attr("data-album-id");if(id)return id;else return false},load:function(albumID,refresh){var startTime,params,durationTime,waitTime;password.get(albumID,function(){if(!refresh){loadingBar.show();lychee.animate(".album, .photo","contentZoomOut");lychee.animate(".divider","fadeOut")}startTime=(new Date).getTime();params="getAlbum&albumID="+albumID+"&password="+password.value;lychee.api(params,function(data){if(data==="Warning: Album private!"){if(document.location.hash.replace("#","").split("/")[1]!=undefined){lychee.setMode("view")}else{lychee.content.show();lychee.goto("")}return false}if(data==="Warning: Wrong password!"){album.load(albumID,refresh);return false}album.json=data;durationTime=(new Date).getTime()-startTime;if(durationTime>300)waitTime=0;else if(refresh)waitTime=0;else waitTime=300-durationTime;if(!visible.albums()&&!visible.photo()&&!visible.album())waitTime=0;setTimeout(function(){view.album.init();if(!refresh){lychee.animate(".album, .photo","contentZoomIn");view.header.mode("album")}},waitTime)})})},parse:function(photo){if(photo&&photo.thumbUrl)photo.thumbUrl=lychee.upload_path_thumb+photo.thumbUrl;else if(!album.json.title)album.json.title="Untitled"},add:function(){var title,params,buttons;buttons=[["Create Album",function(){title=$(".message input.text").val();if(title.length===0)title="Untitled";modal.close();params="addAlbum&title="+escape(encodeURI(title));lychee.api(params,function(data){if(data!==false){if(data===true)data=1;lychee.goto(data)}else lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("New Album","Enter a title for this album: ",buttons)},"delete":function(albumIDs){var params,buttons,albumTitle;if(!albumIDs)return false;if(albumIDs instanceof Array===false)albumIDs=[albumIDs];buttons=[["",function(){params="deleteAlbum&albumIDs="+albumIDs;lychee.api(params,function(data){if(visible.albums()){albumIDs.forEach(function(id,index,array){albums.json.num--;view.albums.content.delete(id)})}else lychee.goto("");if(data!==true)lychee.error(null,params,data)})}],["",function(){}]];if(albumIDs==="0"){buttons[0][0]="Clear Unsorted";buttons[1][0]="Keep Unsorted";modal.show("Clear Unsorted","Are you sure you want to delete all photos from 'Unsorted'?
This action can't be undone!",buttons)}else if(albumIDs.length===1){buttons[0][0]="Delete Album and Photos";buttons[1][0]="Keep Album";if(album.json)albumTitle=album.json.title;else if(albums.json)albumTitle=albums.json.content[albumIDs].title;modal.show("Delete Album","Are you sure you want to delete the album '"+albumTitle+"' and all of the photos it contains? This action can't be undone!",buttons)}else{buttons[0][0]="Delete Albums and Photos";buttons[1][0]="Keep Albums";modal.show("Delete Albums","Are you sure you want to delete all "+albumIDs.length+" selected albums and all of the photos they contain? This action can't be undone!",buttons)}},setTitle:function(albumIDs){var oldTitle="",newTitle,params,buttons;if(!albumIDs)return false;if(albumIDs instanceof Array===false)albumIDs=[albumIDs];if(albumIDs.length===1){if(album.json)oldTitle=album.json.title;else if(albums.json)oldTitle=albums.json.content[albumIDs].title}buttons=[["Set Title",function(){newTitle=$(".message input.text").val()===""?"Untitled":$(".message input.text").val();if(visible.album()){album.json.title=newTitle;view.album.title()}else if(visible.albums()){albumIDs.forEach(function(id,index,array){albums.json.content[id].title=newTitle;view.albums.content.title(id)})}params="setAlbumTitle&albumIDs="+albumIDs+"&title="+escape(encodeURI(newTitle));lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];if(albumIDs.length===1)modal.show("Set Title","Enter a new title for this album: ",buttons);else modal.show("Set Titles","Enter a title for all "+albumIDs.length+" selected album: ",buttons)},setDescription:function(photoID){var oldDescription=album.json.description,description,params,buttons;buttons=[["Set Description",function(){description=$(".message input.text").val();if(visible.album()){album.json.description=description;view.album.description()}params="setAlbumDescription&albumID="+photoID+"&description="+escape(description);lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("Set Description","Please enter a description for this album: ",buttons)},setPublic:function(albumID,e){var params;if($(".message input.text").length>0&&$(".message input.text").val().length>0){params="setAlbumPublic&albumID="+albumID+"&password="+hex_md5($(".message input.text").val());album.json.password=true}else{params="setAlbumPublic&albumID="+albumID;album.json.password=false}if(visible.album()){album.json.public=album.json.public==0?1:0;view.album.public();view.album.password();if(album.json.public==1)contextMenu.shareAlbum(albumID,e)}lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})},share:function(service){var link="",url=location.href;switch(service){case 0:link="https://twitter.com/share?url="+encodeURI(url);break;case 1:link="http://www.facebook.com/sharer.php?u="+encodeURI(url)+"&t="+encodeURI(album.json.title);break;case 2:link="mailto:?subject="+encodeURI(album.json.title)+"&body="+encodeURI("Hi! Check this out: "+url);break;default:link="";break}if(link.length>5)location.href=link},getArchive:function(albumID){var link;if(location.href.indexOf("index.html")>0)link=location.href.replace(location.hash,"").replace("index.html","php/api.php?function=getAlbumArchive&albumID="+albumID);else link=location.href.replace(location.hash,"")+"php/api.php?function=getAlbumArchive&albumID="+albumID;if(lychee.publicMode)link+="&password="+password.value;location.href=link}};albums={json:null,load:function(){var startTime,durationTime,waitTime;lychee.animate(".album, .photo","contentZoomOut");lychee.animate(".divider","fadeOut");startTime=(new Date).getTime();lychee.api("getAlbums",function(data){data.unsortedAlbum={id:0,title:"Unsorted",sysdate:data.unsortedNum+" photos",unsorted:1,thumb0:data.unsortedThumb0,thumb1:data.unsortedThumb1,thumb2:data.unsortedThumb2};data.starredAlbum={id:"f",title:"Starred",sysdate:data.starredNum+" photos",star:1,thumb0:data.starredThumb0,thumb1:data.starredThumb1,thumb2:data.starredThumb2};data.publicAlbum={id:"s",title:"Public",sysdate:data.publicNum+" photos","public":1,thumb0:data.publicThumb0,thumb1:data.publicThumb1,thumb2:data.publicThumb2};albums.json=data;durationTime=(new Date).getTime()-startTime;if(durationTime>300)waitTime=0;else waitTime=300-durationTime;if(!visible.albums()&&!visible.photo()&&!visible.album())waitTime=0;setTimeout(function(){view.header.mode("albums");view.albums.init();lychee.animate(".album, .photo","contentZoomIn")},waitTime)})},parse:function(album){if(album.password&&lychee.publicMode){album.thumb0="assets/img/password.svg";album.thumb1="assets/img/password.svg";album.thumb2="assets/img/password.svg"}else{if(album.thumb0)album.thumb0=lychee.upload_path_thumb+album.thumb0;else album.thumb0="assets/img/no_images.svg";if(album.thumb1)album.thumb1=lychee.upload_path_thumb+album.thumb1;else album.thumb1="assets/img/no_images.svg";if(album.thumb2)album.thumb2=lychee.upload_path_thumb+album.thumb2;else album.thumb2="assets/img/no_images.svg"}}};build={divider:function(title){return"

"+title+"

"},editIcon:function(id){return"
"},multiselect:function(top,left){return"
"},album:function(albumJSON){if(!albumJSON)return"";var album="",longTitle="",title=albumJSON.title;if(title.length>18){title=albumJSON.title.substr(0,18)+"...";longTitle=albumJSON.title}typeThumb0=albumJSON.thumb0.split(".").pop();typeThumb1=albumJSON.thumb1.split(".").pop();typeThumb2=albumJSON.thumb2.split(".").pop();album+="
";album+="thumb";album+="thumb";album+="thumb";album+="
";if(albumJSON.password&&!lychee.publicMode)album+="

"+title+"

";else album+="

"+title+"

";album+=""+albumJSON.sysdate+"";album+="
";if(!lychee.publicMode&&albumJSON.star==1)album+="";if(!lychee.publicMode&&albumJSON.public==1)album+="";if(!lychee.publicMode&&albumJSON.unsorted==1)album+="";album+="
";return album},photo:function(photoJSON){if(!photoJSON)return"";var photo="",longTitle="",title=photoJSON.title;if(title.length>18){title=photoJSON.title.substr(0,18)+"...";longTitle=photoJSON.title}photo+="
";photo+="thumb";photo+="
";photo+="

"+title+"

";photo+=""+photoJSON.sysdate+"";photo+="
";if(photoJSON.star==1)photo+="";if(!lychee.publicMode&&photoJSON.public==1&&album.json.public!=1)photo+="";photo+="
";return photo},imageview:function(photoJSON,isSmall,visibleControls){if(!photoJSON)return"";var view="";view+="";view+="";if(isSmall){if(visibleControls)view+="
";else view+="
"}else{if(visibleControls)view+="
";else view+="
"}return view},no_content:function(typ){var no_content="";no_content+="
";no_content+="";if(typ==="search")no_content+="

No results

";else if(typ==="picture")no_content+="

No public albums

";else if(typ==="cog")no_content+="

No Configuration!

";no_content+="
";return no_content},modal:function(title,text,button,marginTop,closeButton){var modal="",custom_style="";if(marginTop)custom_style="style='margin-top: "+marginTop+"px;'";modal+="
";modal+="
";modal+="

"+title+"

";if(closeButton!=false){modal+=""}modal+="

"+text+"

";$.each(button,function(index){if(this[0]!=""){if(index===0)modal+=""+this[0]+"";else modal+=""+this[0]+""}});modal+="
";modal+="
";return modal},signInModal:function(){var modal="";modal+="
";modal+="
";modal+="

Sign In

";modal+="";modal+="";modal+="
Version "+lychee.version+"Update available!
";modal+="Sign in";modal+="
";modal+="
";return modal},uploadModal:function(icon,text){var modal="";modal+="
";modal+="
";modal+="";if(text!==undefined)modal+="

"+text+"

";else modal+="
";modal+="
";modal+="
";return modal},contextMenu:function(items){var menu="";menu+="
";menu+="
";menu+="";menu+="";$.each(items,function(index){if(items[index][0]==="separator"&&items[index][1]===-1)menu+="";else if(items[index][1]===-1)menu+="";else if(items[index][2]!=undefined)menu+="";else menu+=""});menu+="";menu+="
"+items[index][0]+"
"+items[index][0]+"
"+items[index][0]+"
";menu+="
";return menu},tags:function(tags,forView){var html="",editTagsHTML=forView===true||lychee.publicMode?"":" "+build.editIcon("edit_tags");if(tags!==""){tags=tags.split(",");tags.forEach(function(tag,index,array){html+=""+tag+""});html+=editTagsHTML}else{html="
No Tags"+editTagsHTML+"
"}return html},infoboxPhoto:function(photoJSON,forView){if(!photoJSON)return"";var infobox="",public,editTitleHTML,editDescriptionHTML,infos;infobox+="

About

";infobox+="
";switch(photoJSON.public){case"0":public="Private";break;case"1":public="Public";break;case"2":public="Public (Album)";break;default:public="-";break}editTitleHTML=forView===true||lychee.publicMode?"":" "+build.editIcon("edit_title");editDescriptionHTML=forView===true||lychee.publicMode?"":" "+build.editIcon("edit_description");infos=[["","Basics"],["Name",photoJSON.title+editTitleHTML],["Uploaded",photoJSON.sysdate],["Description",photoJSON.description+editDescriptionHTML],["","Image"],["Size",photoJSON.size],["Format",photoJSON.type],["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!=""){infos=infos.concat([["","Camera"],["Captured",photoJSON.takedate],["Make",photoJSON.make],["Type/Model",photoJSON.model],["Shutter Speed",photoJSON.shutter],["Aperture",photoJSON.aperture],["Focal Length",photoJSON.focal],["ISO",photoJSON.iso]])}infos=infos.concat([["","Share"],["Visibility",public]]);$.each(infos,function(index){if(infos[index][1]===""||infos[index][1]==undefined||infos[index][1]==null)infos[index][1]="-";switch(infos[index][0]){case"":infobox+="";infobox+="

"+infos[index][1]+"

";infobox+="";break;case"Tags":if(forView!==true&&!lychee.publicMode){infobox+="
";infobox+="

"+infos[index][0]+"

";infobox+="
"+infos[index][1]+"
"}break;default:infobox+="";infobox+=""+infos[index][0]+"";infobox+=""+infos[index][1]+"";infobox+="";break}});infobox+="";infobox+="
";infobox+="
";return infobox},infoboxAlbum:function(albumJSON,forView){if(!albumJSON)return"";var infobox="",public,password,editTitleHTML,editDescriptionHTML,infos;infobox+="

About

";infobox+="
";switch(albumJSON.public){case"0":public="Private";break;case"1":public="Public";break;default:public="-";break}switch(albumJSON.password){case false:password="No";break;case true:password="Yes";break;default:password="-";break}editTitleHTML=forView===true||lychee.publicMode?"":" "+build.editIcon("edit_title_album");editDescriptionHTML=forView===true||lychee.publicMode?"":" "+build.editIcon("edit_description_album");infos=[["","Basics"],["Name",albumJSON.title+editTitleHTML],["Description",albumJSON.description+editDescriptionHTML],["","Album"],["Created",albumJSON.sysdate],["Images",albumJSON.num],["","Share"],["Visibility",public],["Password",password]];$.each(infos,function(index){if(infos[index][1]===""||infos[index][1]==undefined||infos[index][1]==null)infos[index][1]="-";if(infos[index][0]===""){infobox+="";infobox+="

"+infos[index][1]+"

";infobox+=""}else{infobox+="";infobox+="";infobox+="";infobox+=""}});infobox+="
"+infos[index][0]+""+infos[index][1]+"
";infobox+="
";infobox+="
";return infobox}};contextMenu={fns:null,show:function(items,mouse_x,mouse_y,orientation){contextMenu.close();$("body").css("overflow","hidden").append(build.contextMenu(items));if(mouse_x+$(".contextmenu").outerWidth(true)>$("html").width())orientation="left";if(mouse_y+$(".contextmenu").outerHeight(true)>$("html").height())mouse_y-=mouse_y+$(".contextmenu").outerHeight(true)-$("html").height();if(mouse_x>$(document).width())mouse_x=$(document).width();if(mouse_x<0)mouse_x=0;if(mouse_y>$(document).height())mouse_y=$(document).height();if(mouse_y<0)mouse_y=0;if(orientation==="left")mouse_x-=$(".contextmenu").outerWidth(true);if(mouse_x===null||mouse_x===undefined||mouse_x===NaN||mouse_y===null||mouse_y===undefined||mouse_y===NaN){mouse_x="10px";mouse_y="10px"}$(".contextmenu").css({top:mouse_y,left:mouse_x,opacity:.98})},add:function(e){var mouse_x=e.pageX,mouse_y=e.pageY-$(document).scrollTop(),items;upload.notify();contextMenu.fns=[function(){$("#upload_files").click()},function(){upload.start.url()},function(){upload.start.dropbox()},function(){upload.start.server()},function(){album.add()}];items=[[" Upload Photo",0],["separator",-1],[" Import from Link",1],[" Import from Dropbox",2],[" Import from Server",3],["separator",-1],[" New Album",4]];contextMenu.show(items,mouse_x,mouse_y,"left")},settings:function(e){var mouse_x=e.pageX,mouse_y=e.pageY-$(document).scrollTop(),items;contextMenu.fns=[function(){settings.setLogin()},function(){settings.setSorting()},function(){window.open(lychee.website,"_newtab")},function(){window.open(lychee.website_donate,"_newtab")},function(){lychee.logout()}];items=[[" Change Login",0],[" Change Sorting",1],[" About Lychee",2],[" Donate",3],["separator",-1],[" Sign Out",4]];contextMenu.show(items,mouse_x,mouse_y,"right")},album:function(albumID,e){var mouse_x=e.pageX,mouse_y=e.pageY-$(document).scrollTop(),items;if(albumID==="0"||albumID==="f"||albumID==="s")return false;contextMenu.fns=[function(){album.setTitle([albumID])},function(){album.delete([albumID])}];items=[[" Rename",0],[" Delete",1]];contextMenu.show(items,mouse_x,mouse_y,"right");$(".album[data-id='"+albumID+"']").addClass("active")},albumMulti:function(albumIDs,e){var mouse_x=e.pageX,mouse_y=e.pageY-$(document).scrollTop(),items;multiselect.stopResize();contextMenu.fns=[function(){album.setTitle(albumIDs)},function(){album.delete(albumIDs)}];items=[[" Rename All",0],[" Delete All",1]];contextMenu.show(items,mouse_x,mouse_y,"right")},photo:function(photoID,e){var mouse_x=e.pageX,mouse_y=e.pageY-$(document).scrollTop(),items;contextMenu.fns=[function(){photo.setStar([photoID])},function(){photo.editTags([photoID])},function(){photo.setTitle([photoID])},function(){contextMenu.move([photoID],e,"right")},function(){photo.delete([photoID])}];items=[[" Star",0],[" Tags",1],["separator",-1],[" Rename",2],[" Move",3],[" Delete",4]];contextMenu.show(items,mouse_x,mouse_y,"right");$(".photo[data-id='"+photoID+"']").addClass("active")},photoMulti:function(photoIDs,e){var mouse_x=e.pageX,mouse_y=e.pageY-$(document).scrollTop(),items;multiselect.stopResize();contextMenu.fns=[function(){photo.setStar(photoIDs)},function(){photo.editTags(photoIDs)},function(){photo.setTitle(photoIDs)},function(){contextMenu.move(photoIDs,e,"right")},function(){photo.delete(photoIDs)}];items=[[" Star All",0],[" Tag All",1],["separator",-1],[" Rename All",2],[" Move All",3],[" Delete All",4]];contextMenu.show(items,mouse_x,mouse_y,"right")},move:function(photoIDs,e,orientation){var mouse_x=e.pageX,mouse_y=e.pageY-$(document).scrollTop(),items=[];contextMenu.close(true);if(album.getID()!=="0"){items=[["Unsorted",0,"photo.setAlbum(["+photoIDs+"], 0)"],["separator",-1]]}lychee.api("getAlbums",function(data){if(data.num===0){items=[["New Album",0,"album.add()"]]}else{$.each(data.content,function(index){if(this.id!=album.getID())items.push([this.title,0,"photo.setAlbum(["+photoIDs+"], "+this.id+")"])})}if(!visible.photo())contextMenu.show(items,mouse_x,mouse_y,"right");else contextMenu.show(items,mouse_x,mouse_y,"left")})},sharePhoto:function(photoID,e){var mouse_x=e.pageX,mouse_y=e.pageY,items;mouse_y-=$(document).scrollTop();contextMenu.fns=[function(){photo.setPublic(photoID)},function(){photo.share(photoID,0)},function(){photo.share(photoID,1)},function(){photo.share(photoID,2)},function(){photo.share(photoID,3)},function(){window.open(photo.getDirectLink(),"_newtab")}];link=photo.getViewLink(photoID);if(photo.json.public==="2")link=location.href;items=[["",-1],["separator",-1],[" Make Private",0],["separator",-1],[" Twitter",1],[" Facebook",2],[" Mail",3],[" Dropbox",4],[" Direct Link",5]];contextMenu.show(items,mouse_x,mouse_y,"left");$(".contextmenu input").focus().select()},shareAlbum:function(albumID,e){var mouse_x=e.pageX,mouse_y=e.pageY,items;mouse_y-=$(document).scrollTop();contextMenu.fns=[function(){album.setPublic(albumID)},function(){password.set(albumID)},function(){album.share(0)},function(){album.share(1)},function(){album.share(2)},function(){password.remove(albumID)}];items=[["",-1],["separator",-1],[" Make Private",0],[" Set Password",1],["separator",-1],[" Twitter",2],[" Facebook",3],[" Mail",4]];if(album.json.password==true)items[3]=[" Remove Password",5];contextMenu.show(items,mouse_x,mouse_y,"left");$(".contextmenu input").focus().select()},close:function(leaveSelection){if(!visible.contextMenu())return false;contextMenu.fns=[];$(".contextmenu_bg, .contextmenu").remove();$("body").css("overflow","auto");if(leaveSelection!==true){$(".photo.active, .album.active").removeClass("active");if(visible.multiselect())multiselect.close()}}};$(document).ready(function(){var event_name=mobileBrowser()?"touchend":"click";$(document).bind("contextmenu",function(e){e.preventDefault()});if(!mobileBrowser())$(".tools").tipsy({gravity:"n",fade:false,delayIn:0,opacity:1});$("#content").on("mousedown",multiselect.show);$(document).on("mouseup",multiselect.getSelection);$("#hostedwith").on(event_name,function(){window.open(lychee.website,"_newtab")});$("#button_signin").on(event_name,lychee.loginDialog);$("#button_settings").on(event_name,contextMenu.settings);$("#button_share").on(event_name,function(e){if(photo.json.public==1||photo.json.public==2)contextMenu.sharePhoto(photo.getID(),e);else photo.setPublic(photo.getID(),e)});$("#button_share_album").on(event_name,function(e){if(album.json.public==1)contextMenu.shareAlbum(album.getID(),e);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? ",[["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_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()});$("#button_info").on(event_name,function(){view.infobox.show()});$("#button_archive").on(event_name,function(){album.getArchive(album.getID())});$("#button_star").on(event_name,function(){photo.setStar([photo.getID()])});$("#search").on("keyup click",function(){search.find($(this).val())});$("#clearSearch").on(event_name,function(){$("#search").focus();search.reset()});$("#button_back_home").on(event_name,function(){lychee.goto("")});$("#button_back").on(event_name,function(){lychee.goto(album.getID())});lychee.imageview.on(event_name,".arrow_wrapper.previous",function(){if(album.json&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].previousPhoto!=="")lychee.goto(album.getID()+"/"+album.json.content[photo.getID()].previousPhoto)}).on(event_name,".arrow_wrapper.next",function(){if(album.json&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].nextPhoto!=="")lychee.goto(album.getID()+"/"+album.json.content[photo.getID()].nextPhoto)});$("#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_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_tags",function(){photo.editTags([photo.getID()])}).on(event_name,"#tags .tag span",function(){photo.deleteTag(photo.getID(),$(this).data("index"))});Mousetrap.bind("u",function(){$("#upload_files").click()}).bind("s",function(){if(visible.photo())$("#button_star").click()}).bind("command+backspace",function(){if(visible.photo()&&!visible.message())photo.delete([photo.getID()])}).bind("left",function(){if(visible.photo())$("#imageview a#previous").click()}).bind("right",function(){if(visible.photo())$("#imageview a#next").click()}).bind("i",function(){if(visible.infobox())view.infobox.hide();else if(!visible.albums())view.infobox.show()});Mousetrap.bindGlobal("enter",function(){if($(".message .button.active").length)$(".message .button.active").addClass("pressed").click()});Mousetrap.bindGlobal(["esc","command+up"],function(e){e.preventDefault();if(visible.message()&&$(".message .close").length>0)modal.close();else if(visible.contextMenu())contextMenu.close();else if(visible.infobox())view.infobox.hide();else if(visible.photo())lychee.goto(album.getID());else if(visible.album())lychee.goto("");else if(visible.albums()&&$("#search").val().length!==0)search.reset()});$(document).on("keyup","#password",function(){if($(this).val().length>0)$(this).removeClass("error")}).on(event_name,"#title.editable",function(){if(visible.photo())photo.setTitle([photo.getID()]);else album.setTitle([album.getID()])}).on("click",".album",function(){lychee.goto($(this).attr("data-id"))}).on("click",".photo",function(){lychee.goto(album.getID()+"/"+$(this).attr("data-id"))}).on(event_name,".message .close",modal.close).on(event_name,".message .button:first",function(){if(modal.fns!=null)modal.fns[0]();if(!visible.signin())modal.close()}).on(event_name,".message .button:last",function(){if(modal.fns!=null)modal.fns[1]();if(!visible.signin())modal.close()}).on(event_name,".button_add",function(e){contextMenu.add(e)}).on("change","#upload_files",function(){modal.close();upload.start.local(this.files)}).on("contextmenu",".photo",function(e){contextMenu.photo(photo.getID(),e)}).on("contextmenu",".album",function(e){contextMenu.album(album.getID(),e)}).on(event_name,".contextmenu_bg",contextMenu.close).on("contextmenu",".contextmenu_bg",contextMenu.close).on(event_name,"#infobox_overlay",view.infobox.hide).on("dragover",function(e){e.preventDefault()},false).on("drop",function(e){e.stopPropagation();e.preventDefault();if(e.originalEvent.dataTransfer.files.length>0)upload.start.local(e.originalEvent.dataTransfer.files);else if(e.originalEvent.dataTransfer.getData("Text").length>3)upload.start.url(e.originalEvent.dataTransfer.getData("Text"));return true});lychee.init()});loadingBar={status:null,show:function(status,errorText){if(status==="error"){loadingBar.status="error";if(!errorText)errorText="Whoops, it looks like something went wrong. Please reload the site and try again!";lychee.loadingBar.removeClass("loading uploading error").addClass(status).html("

Error: "+errorText+"

").show().css("height","40px");if(visible.controls())lychee.header.addClass("error");clearTimeout(lychee.loadingBar.data("timeout"));lychee.loadingBar.data("timeout",setTimeout(function(){loadingBar.hide(true)},3e3))}else if(loadingBar.status==null){loadingBar.status="loading";clearTimeout(lychee.loadingBar.data("timeout"));lychee.loadingBar.data("timeout",setTimeout(function(){lychee.loadingBar.show().removeClass("loading uploading error").addClass("loading");if(visible.controls())lychee.header.addClass("loading")},1e3))}},hide:function(force_hide){if(loadingBar.status!=="error"&&loadingBar.status!=null||force_hide){loadingBar.status=null;clearTimeout(lychee.loadingBar.data("timeout"));lychee.loadingBar.html("").css("height","3px");if(visible.controls())lychee.header.removeClass("error loading");setTimeout(function(){lychee.loadingBar.hide()},300)}}};var lychee={version:"2.1 b2",api_path:"php/api.php",update_path:"http://lychee.electerious.com/version/index.php",updateURL:"https://github.com/electerious/Lychee",website:"http://lychee.electerious.com",website_donate:"http://lychee.electerious.com#donate",upload_path_thumb:"uploads/thumb/",upload_path_big:"uploads/big/",publicMode:false,viewMode:false,debugMode:false,username:"",checkForUpdates:false,sorting:"",dropbox:false,loadingBar:$("#loading"),header:$("header"),content:$("#content"),imageview:$("#imageview"),infobox:$("#infobox"),init:function(){lychee.api("init",function(data){if(data.loggedIn!==true){lychee.setMode("public")}else{lychee.username=data.config.username;lychee.sorting=data.config.sorting +}if(data==="Warning: No configuration!"){lychee.header.hide();lychee.content.hide();$("body").append(build.no_content("cog"));settings.createConfig();return true}if(data.config.login===false){settings.createLogin()}lychee.checkForUpdates=data.config.checkForUpdates;$(window).bind("popstate",lychee.load);lychee.load()})},api:function(params,callback,loading){if(loading==undefined)loadingBar.show();$.ajax({type:"POST",url:lychee.api_path,data:"function="+params,dataType:"text",success:function(data){setTimeout(function(){loadingBar.hide()},100);if(typeof data==="string"&&data.substring(0,7)==="Error: "){lychee.error(data.substring(7,data.length),params,data);return false}if(data==="1")data=true;else if(data==="")data=false;if(typeof data==="string"&&data.substring(0,1)==="{"&&data.substring(data.length-1,data.length)==="}")data=$.parseJSON(data);if(lychee.debugMode)console.log(data);callback(data)},error:function(jqXHR,textStatus,errorThrown){lychee.error("Server error or API not found.",params,errorThrown)}})},login:function(){var user=$("input#username").val(),password=hex_md5($("input#password").val()),params;params="login&user="+user+"&password="+password;lychee.api(params,function(data){if(data===true){localStorage.setItem("username",user);window.location.reload()}else{$("#password").val("").addClass("error").focus();$(".message .button.active").removeClass("pressed")}})},loginDialog:function(){var local_username;$("body").append(build.signInModal());$("#username").focus();if(localStorage){local_username=localStorage.getItem("username");if(local_username!=null){if(local_username.length>0)$("#username").val(local_username);$("#password").focus()}}if(lychee.checkForUpdates==="1")lychee.getUpdate()},logout:function(){lychee.api("logout",function(data){window.location.reload()})},"goto":function(url){if(url==undefined)url="";document.location.hash=url},load:function(){var albumID="",photoID="",hash=document.location.hash.replace("#","").split("/");contextMenu.close();multiselect.close();if(hash[0]!==undefined)albumID=hash[0];if(hash[1]!==undefined)photoID=hash[1];if(albumID&&photoID){albums.json=null;photo.json=null;if(lychee.content.html()===""||$("#search").length&&$("#search").val().length!==0){lychee.content.hide();album.load(albumID,true)}photo.load(photoID,albumID)}else if(albumID){albums.json=null;photo.json=null;if(visible.photo())view.photo.hide();if(album.json&&albumID==album.json.id)view.album.title();else album.load(albumID)}else{albums.json=null;album.json=null;photo.json=null;search.code="";if(visible.album())view.album.hide();if(visible.photo())view.photo.hide();albums.load()}},getUpdate:function(){$.ajax({url:lychee.update_path,success:function(data){if(data!=lychee.version)$("#version span").show()}})},setTitle:function(title,editable){if(title==="Albums")document.title="Lychee";else document.title="Lychee - "+title;if(editable)$("#title").addClass("editable");else $("#title").removeClass("editable");$("#title").html(title)},setMode:function(mode){$("#button_settings, #button_settings, #button_search, #search, #button_trash_album, #button_share_album, .button_add, .button_divider").remove();$("#button_trash, #button_move, #button_share, #button_star").remove();$(document).on("mouseenter","#title.editable",function(){$(this).removeClass("editable")}).off("click","#title.editable").off("touchend","#title.editable").off("contextmenu",".photo").off("contextmenu",".album").off("drop");Mousetrap.unbind("n").unbind("u").unbind("s").unbind("backspace");if(mode==="public"){$("header #button_signin, header #hostedwith").show();lychee.publicMode=true}else if(mode==="view"){Mousetrap.unbind("esc");$("#button_back, a#next, a#previous").remove();$(".no_content").remove();lychee.publicMode=true;lychee.viewMode=true}},animate:function(obj,animation){var animations=[["fadeIn","fadeOut"],["contentZoomIn","contentZoomOut"]];if(!obj.jQuery)obj=$(obj);for(var i=0;i=multiselect.position.top){newHeight=e.pageY-multiselect.position.top;if(multiselect.position.top+newHeight>=$(document).height())newHeight-=multiselect.position.top+newHeight-$(document).height()+2;$("#multiselect").css({top:multiselect.position.top,bottom:"inherit",height:newHeight})}else{$("#multiselect").css({top:"inherit",bottom:multiselect.position.bottom,height:multiselect.position.top-e.pageY})}if(mouse_x>=multiselect.position.left){newWidth=e.pageX-multiselect.position.left;if(multiselect.position.left+newWidth>=$(document).width())newWidth-=multiselect.position.left+newWidth-$(document).width()+2;$("#multiselect").css({right:"inherit",left:multiselect.position.left,width:newWidth})}else{$("#multiselect").css({right:multiselect.position.right,left:"inherit",width:multiselect.position.left-e.pageX})}},stopResize:function(){$(document).off("mousemove")},getSize:function(){if(!visible.multiselect())return false;return{top:$("#multiselect").offset().top,left:$("#multiselect").offset().left,width:parseInt($("#multiselect").css("width").replace("px","")),height:parseInt($("#multiselect").css("height").replace("px",""))}},getSelection:function(e){var tolerance=150,id,ids=[],offset,size=multiselect.getSize();if(visible.contextMenu())return false;if(!visible.multiselect())return false;$(".photo, .album").each(function(){offset=$(this).offset();if(offset.top>=size.top-tolerance&&offset.left>=size.left-tolerance&&offset.top+206<=size.top+size.height+tolerance&&offset.left+206<=size.left+size.width+tolerance){id=$(this).data("id");if(id!=="0"&&id!==0&&id!=="f"&&id!=="s"&&id!==null&id!==undefined){ids.push(id);$(this).addClass("active")}}});if(ids.length!=0&&visible.album())contextMenu.photoMulti(ids,e);else if(ids.length!=0&&visible.albums())contextMenu.albumMulti(ids,e);else multiselect.close()},close:function(){multiselect.stopResize();multiselect.position.top=null;multiselect.position.right=null;multiselect.position.bottom=null;multiselect.position.left=null;lychee.animate("#multiselect","fadeOut");setTimeout(function(){$("#multiselect").remove()},300)}};password={value:"",set:function(albumID){var buttons,params;buttons=[["Set Password",function(){if(visible.album()){album.json.password=true;view.album.password()}params="setAlbumPassword&albumID="+albumID+"&password="+hex_md5($(".message input.text").val());lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("Set Password","Set a password to protect '"+album.json.title+"' from unauthorized viewers. Only people with this password can view this album. ",buttons)},get:function(albumID,callback){var passwd=$(".message input.text").val(),params;if(!lychee.publicMode)callback();else if(album.json&&album.json.password==false)callback();else if(albums.json&&albums.json.content[albumID].password==false)callback();else if(!albums.json&&!album.json){album.json={password:true};callback("")}else if(passwd==undefined){password.getDialog(albumID,callback)}else{params="checkAlbumAccess&albumID="+albumID+"&password="+hex_md5(passwd);lychee.api(params,function(data){if(data===true){password.value=hex_md5(passwd);callback()}else{lychee.goto("");loadingBar.show("error","Access denied. Wrong password!")}})}},getDialog:function(albumID,callback){var buttons;buttons=[["Enter",function(){password.get(albumID,callback)}],["Cancel",lychee.goto]];modal.show(" Enter Password","This album is protected by a password. Enter the password below to view the photos of this album: ",buttons,-110,false)},remove:function(albumID){var params;if(visible.album()){album.json.password=false;view.album.password()}params="setAlbumPassword&albumID="+albumID+"&password=";lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}};photo={json:null,getID:function(){var id;if(photo.json)id=photo.json.id;else id=$(".photo:hover, .photo.active").attr("data-id");if(id)return id;else return false},load:function(photoID,albumID){var params,checkPasswd;params="getPhoto&photoID="+photoID+"&albumID="+albumID+"&password="+password.value;lychee.api(params,function(data){if(data==="Warning: Wrong password!"){checkPasswd=function(){if(password.value!=="")photo.load(photoID,albumID);else setTimeout(checkPasswd,250)};checkPasswd();return false}photo.json=data;if(!visible.photo())view.photo.show();view.photo.init();lychee.imageview.show();setTimeout(function(){lychee.content.show()},300)})},parse:function(){if(!photo.json.title)photo.json.title="Untitled";photo.json.url=lychee.upload_path_big+photo.json.url},"delete":function(photoIDs){var params,buttons,photoTitle;if(!photoIDs)return false;if(photoIDs instanceof Array===false)photoIDs=[photoIDs];if(photoIDs.length===1){if(visible.photo())photoTitle=photo.json.title;else photoTitle=album.json.content[photoIDs].title;if(photoTitle=="")photoTitle="Untitled"}buttons=[["",function(){photoIDs.forEach(function(id,index,array){if(album.json.content[id].nextPhoto!==""||album.json.content[id].previousPhoto!==""){nextPhoto=album.json.content[id].nextPhoto;previousPhoto=album.json.content[id].previousPhoto;album.json.content[previousPhoto].nextPhoto=nextPhoto;album.json.content[nextPhoto].previousPhoto=previousPhoto}album.json.content[id]=null;view.album.content.delete(id)});if(!visible.albums())lychee.goto(album.getID());params="deletePhoto&photoIDs="+photoIDs;lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["",function(){}]];if(photoIDs.length===1){buttons[0][0]="Delete Photo";buttons[1][0]="Keep Photo";modal.show("Delete Photo","Are you sure you want to delete the photo '"+photoTitle+"'?
This action can't be undone!",buttons)}else{buttons[0][0]="Delete Photos";buttons[1][0]="Keep Photos";modal.show("Delete Photos","Are you sure you want to delete all "+photoIDs.length+" selected photo?
This action can't be undone!",buttons)}},setTitle:function(photoIDs){var oldTitle="",newTitle,params,buttons;if(!photoIDs)return false;if(photoIDs instanceof Array===false)photoIDs=[photoIDs];if(photoIDs.length===1){if(photo.json)oldTitle=photo.json.title;else if(album.json)oldTitle=album.json.content[photoIDs].title}buttons=[["Set Title",function(){newTitle=$(".message input.text").val();if(visible.photo()){photo.json.title=newTitle===""?"Untitled":newTitle;view.photo.title()}photoIDs.forEach(function(id,index,array){album.json.content[id].title=newTitle;view.album.content.title(id)});params="setPhotoTitle&photoIDs="+photoIDs+"&title="+escape(encodeURI(newTitle));lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];if(photoIDs.length===1)modal.show("Set Title","Enter a new title for this photo: ",buttons);else modal.show("Set Titles","Enter a title for all "+photoIDs.length+" selected photos: ",buttons)},setAlbum:function(photoIDs,albumID){var params,nextPhoto,previousPhoto;if(!photoIDs)return false;if(visible.photo)lychee.goto(album.getID());if(photoIDs instanceof Array===false)photoIDs=[photoIDs];photoIDs.forEach(function(id,index,array){if(album.json.content[id].nextPhoto!==""||album.json.content[id].previousPhoto!==""){nextPhoto=album.json.content[id].nextPhoto;previousPhoto=album.json.content[id].previousPhoto;album.json.content[previousPhoto].nextPhoto=nextPhoto;album.json.content[nextPhoto].previousPhoto=previousPhoto}album.json.content[id]=null;view.album.content.delete(id)});params="setPhotoAlbum&photoIDs="+photoIDs+"&albumID="+albumID;lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})},setStar:function(photoIDs){var params;if(!photoIDs)return false;if(visible.photo()){photo.json.star=photo.json.star==0?1:0;view.photo.star()}photoIDs.forEach(function(id,index,array){album.json.content[id].star=album.json.content[id].star==0?1:0;view.album.content.star(id)});params="setPhotoStar&photoIDs="+photoIDs;lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})},setPublic:function(photoID,e){var params;if(photo.json.public==2){modal.show("Public Album","This photo is located in a public album. To make this photo private or public, edit the visibility of the associated album.",[["Show Album",function(){lychee.goto(photo.json.original_album)}],["Close",function(){}]]);return false}if(visible.photo()){photo.json.public=photo.json.public==0?1:0;view.photo.public();if(photo.json.public==1)contextMenu.sharePhoto(photoID,e)}album.json.content[photoID].public=album.json.content[photoID].public==0?1:0;view.album.content.public(photoID);params="setPhotoPublic&photoID="+photoID+"&url="+photo.getViewLink(photoID);lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})},setDescription:function(photoID){var oldDescription=photo.json.description,description,params,buttons;buttons=[["Set Description",function(){description=$(".message input.text").val();if(visible.photo()){photo.json.description=description;view.photo.description()}params="setPhotoDescription&photoID="+photoID+"&description="+escape(description);lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("Set Description","Enter a description for this photo: ",buttons)},editTags:function(photoIDs){var oldTags="",tags="";if(!photoIDs)return false;if(photoIDs instanceof Array===false)photoIDs=[photoIDs];if(visible.photo())oldTags=photo.json.tags;if(visible.album()&&photoIDs.length===1)oldTags=album.json.content[photoIDs].tags;if(visible.album()&&photoIDs.length>1){var same=true;photoIDs.forEach(function(id,index,array){if(album.json.content[id].tags===album.json.content[photoIDs[0]].tags&&same===true)same=true;else same=false});if(same)oldTags=album.json.content[photoIDs[0]].tags}oldTags=oldTags.replace(/,/g,", ");buttons=[["Set Tags",function(){tags=$(".message input.text").val();photo.setTags(photoIDs,tags)}],["Cancel",function(){}]];if(photoIDs.length===1)modal.show("Set Tags","Enter your tags for this photo. You can add multiple tags by separating them with a comma: ",buttons);else modal.show("Set Tags","Enter your tags for all "+photoIDs.length+" selected photos. Existing tags will be overwritten. You can add multiple tags by separating them with a comma: ",buttons)},setTags:function(photoIDs,tags){var params;if(!photoIDs)return false;if(photoIDs instanceof Array===false)photoIDs=[photoIDs];tags=tags.replace(/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/g,",");tags=tags.replace(/,$|^,/g,"");if(visible.photo()){photo.json.tags=tags;view.photo.tags()}photoIDs.forEach(function(id,index,array){album.json.content[id].tags=tags});params="setPhotoTags&photoIDs="+photoIDs+"&tags="+tags;lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})},deleteTag:function(photoID,index){var tags;tags=photo.json.tags.split(",");tags.splice(index,1);photo.json.tags=tags.toString();photo.setTags([photoID],photo.json.tags)},share:function(photoID,service){var link="",url=photo.getViewLink(photoID),filename="unknown";switch(service){case 0:link="https://twitter.com/share?url="+encodeURI(url);break;case 1:link="http://www.facebook.com/sharer.php?u="+encodeURI(url)+"&t="+encodeURI(photo.json.title);break;case 2:link="mailto:?subject="+encodeURI(photo.json.title)+"&body="+encodeURI(url);break;case 3:lychee.loadDropbox(function(){filename=photo.json.title+"."+photo.getDirectLink().split(".").pop();Dropbox.save(photo.getDirectLink(),filename)});break;default:link="";break}if(link.length>5)location.href=link},isSmall:function(){var size=[["width",false],["height",false]];if(photo.json.width<$(window).width()-60)size["width"]=true;if(photo.json.height<$(window).height()-100)size["height"]=true;if(size["width"]&&size["height"])return true;else return false},getArchive:function(photoID){var link;if(location.href.indexOf("index.html")>0)link=location.href.replace(location.hash,"").replace("index.html","php/api.php?function=getPhotoArchive&photoID="+photoID);else link=location.href.replace(location.hash,"")+"php/api.php?function=getPhotoArchive&photoID="+photoID;if(lychee.publicMode)link+="&password="+password.value;location.href=link},getDirectLink:function(){return $("#imageview #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/gi,"")},getViewLink:function(photoID){if(location.href.indexOf("index.html")>0)return location.href.replace("index.html"+location.hash,"view.php?p="+photoID);else return location.href.replace(location.hash,"view.php?p="+photoID)}};search={code:null,find:function(term){var params,albumsData="",photosData="",code;clearTimeout($(window).data("timeout"));$(window).data("timeout",setTimeout(function(){if($("#search").val().length!==0){params="search&term="+term;lychee.api(params,function(data){if(data&&data.albums){albums.json={content:data.albums};$.each(albums.json.content,function(){albums.parse(this);albumsData+=build.album(this)})}if(data&&data.photos){album.json={content:data.photos};$.each(album.json.content,function(){album.parse(this);photosData+=build.photo(this)})}if(albumsData===""&&photosData==="")code="error";else if(albumsData==="")code=build.divider("Photos")+photosData;else if(photosData==="")code=build.divider("Albums")+albumsData;else code=build.divider("Photos")+photosData+build.divider("Albums")+albumsData;if(search.code!==hex_md5(code)){$(".no_content").remove();lychee.animate(".album, .photo","contentZoomOut");lychee.animate(".divider","fadeOut");search.code=hex_md5(code);setTimeout(function(){if(code==="error")$("body").append(build.no_content("search"));else{lychee.content.html(code);lychee.animate(".album, .photo","contentZoomIn");$("img[data-type!='svg']").retina()}},300)}})}else search.reset()},250))},reset:function(){$("#search").val("");$(".no_content").remove();if(search.code!==""){search.code="";lychee.animate(".divider","fadeOut");albums.load()}}};var settings={createConfig:function(){var dbName,dbUser,dbPassword,dbHost,buttons;buttons=[["Connect",function(){dbHost=$(".message input.text#dbHost").val();dbUser=$(".message input.text#dbUser").val();dbPassword=$(".message input.text#dbPassword").val();dbName=$(".message input.text#dbName").val();if(dbHost.length<1)dbHost="localhost";if(dbName.length<1)dbName="lychee";params="dbCreateConfig&dbName="+escape(dbName)+"&dbUser="+escape(dbUser)+"&dbPassword="+escape(dbPassword)+"&dbHost="+escape(dbHost);lychee.api(params,function(data){if(data!==true){setTimeout(function(){if(data.indexOf("Warning: Connection failed!")!==-1){buttons=[["Retry",function(){setTimeout(settings.createConfig,400)}],["",function(){}]];modal.show("Connection Failed","Unable to connect to host database because access was denied. Double-check your host, username and password and ensure that access from your current location is permitted.",buttons,null,false);return false}if(data.indexOf("Warning: Could not create file!")!==-1){buttons=[["Retry",function(){setTimeout(settings.createConfig,400)}],["",function(){}]];modal.show("Saving Failed","Unable to save this configuration. Permission denied in 'data/'. Please set the read, write and execute rights for others in 'data/' and 'uploads/'. Take a look the readme for more information.",buttons,null,false);return false}buttons=[["Retry",function(){setTimeout(settings.createConfig,400)}],["",function(){}]];modal.show("Configuration Failed","Something unexpected happened. Please try again and check your installation and server. Take a look the readme for more information.",buttons,null,false);return false},400)}else{lychee.api("update",function(data){window.location.reload()})}})}],["",function(){}]];modal.show("Configuration","Enter your database connection details below:
Lychee will create its own database. If required, you can enter the name of an existing database instead:",buttons,-215,false)},createLogin:function(){var username,password,params,buttons;buttons=[["Create Login",function(){username=$(".message input.text#username").val();password=$(".message input.text#password").val();if(username.length<1||password.length<1){setTimeout(function(){buttons=[["Retry",function(){setTimeout(settings.createLogin,400)}],["",function(){}]];modal.show("Wrong Input","The username or password you entered is not long enough. Please try again with another username and password!",buttons,null,false);return false},400)}else{params="setLogin&username="+escape(username)+"&password="+hex_md5(password);lychee.api(params,function(data){if(data!==true){setTimeout(function(){buttons=[["Retry",function(){setTimeout(settings.createLogin,400)}],["",function(){}]];modal.show("Creation Failed","Unable to save login. Please try again with another username and password!",buttons,null,false);return false},400)}})}}],["",function(){}]];modal.show("Create Login","Enter a username and password for your installation: ",buttons,-122,false)},setLogin:function(){var old_password,username,password,params,buttons;buttons=[["Change Login",function(){old_password=$(".message input.text#old_password").val();username=$(".message input.text#username").val();password=$(".message input.text#password").val();if(old_password.length<1){loadingBar.show("error","Your old password was entered incorrectly. Please try again!");return false}if(username.length<1){loadingBar.show("error","Your new username was entered incorrectly. Please try again!");return false}if(password.length<1){loadingBar.show("error","Your new password was entered incorrectly. Please try again!");return false}params="setLogin&oldPassword="+hex_md5(old_password)+"&username="+escape(username)+"&password="+hex_md5(password);lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("Change Login","Enter your current password:
Your username and password will be changed to the following: ",buttons,-171)},setSorting:function(){var buttons,sorting;buttons=[["Change Sorting",function(){sorting[0]=$("select#settings_type").val();sorting[1]=$("select#settings_order").val();params="setSorting&type="+sorting[0]+"&order="+sorting[1];lychee.api(params,function(data){if(data===true){lychee.sorting="ORDER BY "+sorting[0]+" "+sorting[1];lychee.load()}else lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("Change Sorting","Sort photos by in an order. ",buttons);if(lychee.sorting!=""){sorting=lychee.sorting.replace("ORDER BY ","").replace(" ",";").split(";");$("select#settings_type").val(sorting[0]);$("select#settings_order").val(sorting[1])}}};upload={show:function(icon,text){if(icon===undefined)icon="upload";upload.close(true);$("body").append(build.uploadModal(icon,text))},setIcon:function(icon){$(".upload_message a").remove();$(".upload_message").prepend("")},setProgress:function(progress){$(".progressbar div").css("width",progress+"%")},setText:function(text){$(".progressbar").remove();$(".upload_message").append("

"+text+"

")},notify:function(title){var popup;if(!window.webkitNotifications)return false;if(window.webkitNotifications.checkPermission()!=0)window.webkitNotifications.requestPermission();if(window.webkitNotifications.checkPermission()==0&&title){popup=window.webkitNotifications.createNotification("",title,"You can now manage your new photo(s).");popup.show()}},start:{local:function(files){var pre_progress=0,formData=new FormData,xhr=new XMLHttpRequest,albumID=album.getID(),popup,progress;if(files.length<=0)return false;if(albumID===false)albumID=0;formData.append("function","upload");formData.append("albumID",albumID);for(var i=0;ipre_progress){upload.setProgress(progress);pre_progress=progress}if(progress>=100){upload.setIcon("cog");upload.setText("Processing photos")}}};$("#upload_files").val("");xhr.send(formData)},url:function(){var albumID=album.getID(),params,extension,buttons;if(albumID===false)albumID=0;buttons=[["Import",function(){link=$(".message input.text").val();if(link&&link.length>3){extension=link.split(".").pop();if(extension!=="jpeg"&&extension!=="jpg"&&extension!=="png"&&extension!=="gif"&&extension!=="webp"){loadingBar.show("error","The file format of this link is not supported.");return false}modal.close();upload.show("cog","Importing from URL");params="importUrl&url="+escape(encodeURI(link))+"&albumID="+albumID;lychee.api(params,function(data){upload.close();upload.notify("Import complete");if(album.getID()===false)lychee.goto("0");else album.load(albumID);if(data!==true)lychee.error(null,params,data)})}else loadingBar.show("error","Link to short or too long. Please try another one!")}],["Cancel",function(){}]];modal.show("Import from Link","Please enter the direct link to a photo to import it: ",buttons)},server:function(){var albumID=album.getID(),params,buttons;if(albumID===false)albumID=0;buttons=[["Import",function(){modal.close();upload.show("cog","Importing photos");params="importServer&albumID="+albumID;lychee.api(params,function(data){upload.close();upload.notify("Import complete");if(data==="Notice: Import only contains albums!"){if(visible.albums())lychee.load();else lychee.goto("")}else if(album.getID()===false)lychee.goto("0");else album.load(albumID);if(data==="Notice: Import only contains albums!")return true;else if(data==="Warning: Folder empty!")lychee.error("Folder empty. No photos imported!",params,data);else if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("Import from Server","This action will import all photos and albums which are located in 'uploads/import/' of your Lychee installation.",buttons)},dropbox:function(){var albumID=album.getID(),params;if(albumID===false)albumID=0;lychee.loadDropbox(function(){Dropbox.choose({linkType:"direct",multiselect:true,success:function(files){if(files.length>1){for(var i=0;i0){$("#imageview #image").css({marginTop:-1*($("#imageview #image").height()/2)+20})}else{$("#imageview #image").css({top:60,right:30,bottom:30,left:30})}}},hide:function(){if(visible.photo()&&!visible.infobox()&&!visible.contextMenu()&&!visible.message()){clearTimeout($(window).data("timeout"));$(window).data("timeout",setTimeout(function(){lychee.imageview.addClass("full");lychee.loadingBar.css("opacity",0);lychee.header.addClass("hidden");if($("#imageview #image.small").length>0){$("#imageview #image").css({marginTop:-1*($("#imageview #image").height()/2)})}else{$("#imageview #image").css({top:0,right:0,bottom:0,left:0}) +}},500))}},mode:function(mode){var albumID=album.getID();switch(mode){case"albums":lychee.header.removeClass("view");$("#tools_album, #tools_photo").hide();$("#tools_albums").show();break;case"album":lychee.header.removeClass("view");$("#tools_albums, #tools_photo").hide();$("#tools_album").show();album.json.content===false?$("#button_archive").hide():$("#button_archive").show();if(albumID==="s"||albumID==="f"){$("#button_info_album, #button_trash_album, #button_share_album").hide()}else if(albumID==="0"){$("#button_info_album, #button_share_album").hide();$("#button_trash_album").show()}else{$("#button_info_album, #button_trash_album, #button_share_album").show()}break;case"photo":lychee.header.addClass("view");$("#tools_albums, #tools_album").hide();$("#tools_photo").show();break}}},infobox:{show:function(){if(!visible.infobox())$("body").append("
");lychee.infobox.addClass("active")},hide:function(){lychee.animate("#infobox_overlay","fadeOut");setTimeout(function(){$("#infobox_overlay").remove()},300);lychee.infobox.removeClass("active")}},albums:{init:function(){view.albums.title();view.albums.content.init()},title:function(){lychee.setTitle("Albums",false)},content:{init:function(){var smartData="",albumsData="";albums.parse(albums.json.unsortedAlbum);albums.parse(albums.json.publicAlbum);albums.parse(albums.json.starredAlbum);if(!lychee.publicMode)smartData=build.divider("Smart Albums")+build.album(albums.json.unsortedAlbum)+build.album(albums.json.starredAlbum)+build.album(albums.json.publicAlbum);if(albums.json.content){if(!lychee.publicMode)albumsData=build.divider("Albums");$.each(albums.json.content,function(){albums.parse(this);albumsData+=build.album(this)})}if(smartData===""&&albumsData==="")$("body").append(build.no_content("picture"));else lychee.content.html(smartData+albumsData);$("img[data-type!='svg']").retina()},title:function(albumID){var prefix="",longTitle="",title=albums.json.content[albumID].title;if(albums.json.content[albumID].password)prefix=" ";if(title.length>18){longTitle=title;title=title.substr(0,18)+"..."}$(".album[data-id='"+albumID+"'] .overlay h1").html(prefix+title).attr("title",longTitle)},"delete":function(albumID){$(".album[data-id='"+albumID+"']").css("opacity",0).animate({width:0,marginLeft:0},300,function(){$(this).remove();if(albums.json.num<=0)lychee.animate(".divider:last-of-type","fadeOut")})}}},album:{init:function(){album.parse();view.album.infobox();view.album.title();view.album.public();view.album.content.init();album.json.init=1},hide:function(){view.infobox.hide()},title:function(){if((visible.album()||!album.json.init)&&!visible.photo()){switch(album.getID()){case"f":lychee.setTitle("Starred",false);break;case"s":lychee.setTitle("Public",false);break;case"0":lychee.setTitle("Unsorted",false);break;default:if(album.json.init)$("#infobox .attr_name").html(album.json.title+" "+build.editIcon("edit_title_album"));lychee.setTitle(album.json.title,true);break}}},description:function(){$("#infobox .attr_description").html(album.json.description+" "+build.editIcon("edit_description_album"))},content:{init:function(){var photosData="";$.each(album.json.content,function(){album.parse(this);photosData+=build.photo(this)});lychee.content.html(photosData);$("img[data-type!='svg']").retina()},title:function(photoID){var longTitle="",title=album.json.content[photoID].title;if(title.length>18){longTitle=title;title=title.substr(0,18)+"..."}$(".photo[data-id='"+photoID+"'] .overlay h1").html(title).attr("title",longTitle)},star:function(photoID){$(".photo[data-id='"+photoID+"'] .icon-star").remove();if(album.json.content[photoID].star==1)$(".photo[data-id='"+photoID+"']").append("")},"public":function(photoID){$(".photo[data-id='"+photoID+"'] .icon-share").remove();if(album.json.content[photoID].public==1)$(".photo[data-id='"+photoID+"']").append("")},"delete":function(photoID){$(".photo[data-id='"+photoID+"']").css("opacity",0).animate({width:0,marginLeft:0},300,function(){$(this).remove();if(!visible.albums()){album.json.num--;view.album.num();view.album.title()}})}},num:function(){$("#infobox .attr_images").html(album.json.num)},"public":function(){if(album.json.public==1){$("#button_share_album a").addClass("active");$("#button_share_album").attr("title","Share Album");$(".photo .icon-share").remove();if(album.json.init)$("#infobox .attr_visibility").html("Public")}else{$("#button_share_album a").removeClass("active");$("#button_share_album").attr("title","Make Public");if(album.json.init)$("#infobox .attr_visibility").html("Private")}},password:function(){if(album.json.password==1)$("#infobox .attr_password").html("Yes");else $("#infobox .attr_password").html("No")},infobox:function(){if((visible.album()||!album.json.init)&&!visible.photo())lychee.infobox.html(build.infoboxAlbum(album.json)).show()}},photo:{init:function(){photo.parse();view.photo.infobox();view.photo.title();view.photo.star();view.photo.public();view.photo.photo();photo.json.init=1},show:function(){lychee.content.addClass("view");view.header.mode("photo");$("body").css("overflow","hidden");$(document).bind("mouseenter",view.header.show).bind("mouseleave",view.header.hide);lychee.animate(lychee.imageview,"fadeIn")},hide:function(){if(!visible.controls())view.header.show();if(visible.infobox)view.infobox.hide();lychee.content.removeClass("view");view.header.mode("album");$("body").css("overflow","auto");$(document).unbind("mouseenter").unbind("mouseleave");lychee.animate(lychee.imageview,"fadeOut");setTimeout(function(){lychee.imageview.hide();view.album.infobox()},300)},title:function(){if(photo.json.init)$("#infobox .attr_name").html(photo.json.title+" "+build.editIcon("edit_title"));lychee.setTitle(photo.json.title,true)},description:function(){if(photo.json.init)$("#infobox .attr_description").html(photo.json.description+" "+build.editIcon("edit_description"))},star:function(){$("#button_star a").removeClass("icon-star-empty icon-star");if(photo.json.star==1){$("#button_star a").addClass("icon-star");$("#button_star").attr("title","Unstar Photo")}else{$("#button_star a").addClass("icon-star-empty");$("#button_star").attr("title","Star Photo")}},"public":function(){if(photo.json.public==1||photo.json.public==2){$("#button_share a").addClass("active");$("#button_share").attr("title","Share Photo");if(photo.json.init)$("#infobox .attr_visibility").html("Public")}else{$("#button_share a").removeClass("active");$("#button_share").attr("title","Make Public");if(photo.json.init)$("#infobox .attr_visibility").html("Private")}},tags:function(){$("#infobox #tags").html(build.tags(photo.json.tags))},photo:function(){lychee.imageview.html(build.imageview(photo.json,photo.isSmall(),visible.controls()));if(album.json&&album.json.content&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].nextPhoto===""||lychee.viewMode)$("a#next").hide();if(album.json&&album.json.content&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].previousPhoto===""||lychee.viewMode)$("a#previous").hide()},infobox:function(){lychee.infobox.html(build.infoboxPhoto(photo.json)).show()}}};visible={albums:function(){if($("#tools_albums").css("display")==="block")return true;else return false},album:function(){if($("#tools_album").css("display")==="block")return true;else return false},photo:function(){if($("#imageview.fadeIn").length>0)return true;else return false},search:function(){if(search.code!==null&&search.code!=="")return true;else return false},infobox:function(){if($("#infobox.active").length>0)return true;else return false},controls:function(){if(lychee.loadingBar.css("opacity")<1)return false;else return true},message:function(){if($(".message").length>0)return true;else return false},signin:function(){if($(".message .sign_in").length>0)return true;else return false},contextMenu:function(){if($(".contextmenu").length>0)return true;else return false},multiselect:function(){if($("#multiselect").length>0)return true;else return false}}; \ No newline at end of file From 10a24c277088ef425a734d7774abc1cb6d88e44b Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sat, 15 Feb 2014 21:30:59 +0100 Subject: [PATCH 56/87] Moved favicon to the root --- assets/img/favicon.ico => favicon.ico | Bin index.html | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename assets/img/favicon.ico => favicon.ico (100%) diff --git a/assets/img/favicon.ico b/favicon.ico similarity index 100% rename from assets/img/favicon.ico rename to favicon.ico diff --git a/index.html b/index.html index 84793b5..3fbc0ec 100644 --- a/index.html +++ b/index.html @@ -31,7 +31,7 @@ - + From 132942d0e5889405e0b3743d2360f042573b7812 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Mon, 17 Feb 2014 16:21:04 +0100 Subject: [PATCH 57/87] Shorten text --- docs/md/FAQ.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/md/FAQ.md b/docs/md/FAQ.md index bc428ec..c75a87c 100644 --- a/docs/md/FAQ.md +++ b/docs/md/FAQ.md @@ -1,5 +1,5 @@ #### Lychee is not working -If Lychee is not working properly, try to open `plugins/check.php`. This script will display all errors it can find. Everything should work if you can see the message "Lychee is ready. Lets rock!". +If Lychee is not working properly, try to open `plugins/check.php`. This script will display all errors it can find. #### What do I need to run Lychee on my server? To run Lychee, everything you need is a web-server with PHP 5.3 or later and a MySQL-Database. From 5a6da5423f3cee496adf9a803ec82b1443ae918d Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Mon, 17 Feb 2014 16:22:01 +0100 Subject: [PATCH 58/87] Added check.php to the settings menu --- assets/js/modules/contextMenu.js | 32 ++++++++++++++++---------------- plugins/check.php | 10 ++++------ 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/assets/js/modules/contextMenu.js b/assets/js/modules/contextMenu.js index 8bd9572..83114a0 100644 --- a/assets/js/modules/contextMenu.js +++ b/assets/js/modules/contextMenu.js @@ -24,8 +24,8 @@ contextMenu = { if (mouse_x>$(document).width()) mouse_x = $(document).width(); if (mouse_x<0) mouse_x = 0; if (mouse_y>$(document).height()) mouse_y = $(document).height(); - if (mouse_y<0) mouse_y = 0; - + if (mouse_y<0) mouse_y = 0; + if (orientation==="left") mouse_x -= $(".contextmenu").outerWidth(true); if (mouse_x===null|| @@ -51,7 +51,7 @@ contextMenu = { var mouse_x = e.pageX, mouse_y = e.pageY - $(document).scrollTop(), items; - + upload.notify(); contextMenu.fns = [ @@ -85,8 +85,8 @@ contextMenu = { contextMenu.fns = [ function() { settings.setLogin() }, function() { settings.setSorting() }, - function() { window.open(lychee.website,"_newtab"); }, - function() { window.open(lychee.website_donate,"_newtab"); }, + function() { window.open(lychee.website, "_newtab"); }, + function() { window.open("plugins/check.php", "_newtab"); }, function() { lychee.logout() } ]; @@ -94,7 +94,7 @@ contextMenu = { [" Change Login", 0], [" Change Sorting", 1], [" About Lychee", 2], - [" Donate", 3], + [" Diagnostics", 3], ["separator", -1], [" Sign Out", 4] ]; @@ -109,7 +109,7 @@ contextMenu = { mouse_y = e.pageY - $(document).scrollTop(), items; - if (albumID==="0"||albumID==="f"||albumID==="s") return false; + if (albumID==="0"||albumID==="f"||albumID==="s") return false; contextMenu.fns = [ function() { album.setTitle([albumID]) }, @@ -126,9 +126,9 @@ contextMenu = { $(".album[data-id='" + albumID + "']").addClass("active"); }, - + albumMulti: function(albumIDs, e) { - + var mouse_x = e.pageX, mouse_y = e.pageY - $(document).scrollTop(), items; @@ -177,9 +177,9 @@ contextMenu = { $(".photo[data-id='" + photoID + "']").addClass("active"); }, - + photoMulti: function(photoIDs, e) { - + var mouse_x = e.pageX, mouse_y = e.pageY - $(document).scrollTop(), items; @@ -255,7 +255,7 @@ contextMenu = { function() { photo.share(photoID, 3) }, function() { window.open(photo.getDirectLink(),"_newtab") } ]; - + link = photo.getViewLink(photoID); if (photo.json.public==="2") link = location.href; @@ -312,14 +312,14 @@ contextMenu = { }, close: function(leaveSelection) { - + if (!visible.contextMenu()) return false; - + contextMenu.fns = []; - + $(".contextmenu_bg, .contextmenu").remove(); $("body").css("overflow", "auto"); - + if (leaveSelection!==true) { $(".photo.active, .album.active").removeClass("active"); if (visible.multiselect()) multiselect.close(); diff --git a/plugins/check.php b/plugins/check.php index 2455589..b6d5b99 100644 --- a/plugins/check.php +++ b/plugins/check.php @@ -1,12 +1,10 @@ Date: Mon, 17 Feb 2014 16:22:53 +0100 Subject: [PATCH 59/87] Trim whitespace --- assets/js/modules/album.js | 30 +++++----- assets/js/modules/build.js | 4 +- assets/js/modules/lychee.js | 1 - assets/js/modules/multiselect.js | 94 ++++++++++++++++---------------- assets/js/modules/photo.js | 46 ++++++++-------- assets/js/modules/upload.js | 18 +++--- assets/js/modules/view.js | 8 +-- assets/js/modules/visible.js | 4 +- 8 files changed, 102 insertions(+), 103 deletions(-) diff --git a/assets/js/modules/album.js b/assets/js/modules/album.js index 2fea995..232b971 100644 --- a/assets/js/modules/album.js +++ b/assets/js/modules/album.js @@ -120,7 +120,7 @@ album = { }], ["Cancel", function() {}] ]; - + modal.show("New Album", "Enter a title for this album: ", buttons); }, @@ -130,7 +130,7 @@ album = { var params, buttons, albumTitle; - + if (!albumIDs) return false; if (albumIDs instanceof Array===false) albumIDs = [albumIDs]; @@ -141,12 +141,12 @@ album = { lychee.api(params, function(data) { if (visible.albums()) { - + albumIDs.forEach(function(id, index, array) { albums.json.num--; view.albums.content.delete(id); }); - + } else lychee.goto(""); if (data!==true) lychee.error(null, params, data); @@ -161,27 +161,27 @@ album = { buttons[0][0] = "Clear Unsorted"; buttons[1][0] = "Keep Unsorted"; - + modal.show("Clear Unsorted", "Are you sure you want to delete all photos from 'Unsorted'?
This action can't be undone!", buttons) } else if (albumIDs.length===1) { - + buttons[0][0] = "Delete Album and Photos"; buttons[1][0] = "Keep Album"; - + // Get title if (album.json) albumTitle = album.json.title; else if (albums.json) albumTitle = albums.json.content[albumIDs].title; - + modal.show("Delete Album", "Are you sure you want to delete the album '" + albumTitle + "' and all of the photos it contains? This action can't be undone!", buttons); } else { - + buttons[0][0] = "Delete Albums and Photos"; buttons[1][0] = "Keep Albums"; - + modal.show("Delete Albums", "Are you sure you want to delete all " + albumIDs.length + " selected albums and all of the photos they contain? This action can't be undone!", buttons); - + } }, @@ -195,7 +195,7 @@ album = { if (!albumIDs) return false; if (albumIDs instanceof Array===false) albumIDs = [albumIDs]; - + if (albumIDs.length===1) { // Get old title if only one album is selected if (album.json) oldTitle = album.json.title; @@ -213,7 +213,7 @@ album = { view.album.title(); } else if (visible.albums()) { - + albumIDs.forEach(function(id, index, array) { albums.json.content[id].title = newTitle; view.albums.content.title(id); @@ -231,7 +231,7 @@ album = { }], ["Cancel", function() {}] ]; - + if (albumIDs.length===1) modal.show("Set Title", "Enter a new title for this album: ", buttons); else modal.show("Set Titles", "Enter a title for all " + albumIDs.length + " selected album: ", buttons); @@ -264,7 +264,7 @@ album = { }], ["Cancel", function() {}] ]; - + modal.show("Set Description", "Please enter a description for this album: ", buttons); }, diff --git a/assets/js/modules/build.js b/assets/js/modules/build.js index b7e9ff5..e662d09 100644 --- a/assets/js/modules/build.js +++ b/assets/js/modules/build.js @@ -255,12 +255,12 @@ build = { html += "" + tag + ""; }); - + html += editTagsHTML; } else { - + html = "
No Tags" + editTagsHTML + "
"; } diff --git a/assets/js/modules/lychee.js b/assets/js/modules/lychee.js index 6429ff2..f61ac2f 100644 --- a/assets/js/modules/lychee.js +++ b/assets/js/modules/lychee.js @@ -13,7 +13,6 @@ var lychee = { update_path: "http://lychee.electerious.com/version/index.php", updateURL: "https://github.com/electerious/Lychee", website: "http://lychee.electerious.com", - website_donate: "http://lychee.electerious.com#donate", upload_path_thumb: "uploads/thumb/", upload_path_big: "uploads/big/", diff --git a/assets/js/modules/multiselect.js b/assets/js/modules/multiselect.js index da71b20..e24b9bd 100644 --- a/assets/js/modules/multiselect.js +++ b/assets/js/modules/multiselect.js @@ -8,164 +8,164 @@ multiselect = { position: { - + top: null, right: null, bottom: null, left: null - + }, show: function(e) { - + if (mobileBrowser()) return false; if (lychee.publicMode) return false; if (visible.search()) return false; if ($('.album:hover, .photo:hover').length!=0) return false; if (visible.multiselect()) $('#multiselect').remove(); - + multiselect.position.top = e.pageY; multiselect.position.right = -1 * (e.pageX - $(document).width()); multiselect.position.bottom = -1 * (multiselect.position.top - $(window).height()); multiselect.position.left = e.pageX; - + $('body').append(build.multiselect(multiselect.position.top, multiselect.position.left)); $(document).on('mousemove', multiselect.resize); - + }, - + resize: function(e) { - + var mouse_x = e.pageX, mouse_y = e.pageY, newHeight, newWidth; - + if (multiselect.position.top===null|| multiselect.position.right===null|| multiselect.position.bottom===null|| multiselect.position.left===null) return false; - + if (mouse_y>=multiselect.position.top) { - + // Do not leave the screen newHeight = e.pageY - multiselect.position.top; if ((multiselect.position.top+newHeight)>=$(document).height()) newHeight -= (multiselect.position.top + newHeight) - $(document).height() + 2; - + $('#multiselect').css({ top: multiselect.position.top, bottom: 'inherit', height: newHeight }); - + } else { - + $('#multiselect').css({ top: 'inherit', bottom: multiselect.position.bottom, height: multiselect.position.top - e.pageY }); - + } - + if (mouse_x>=multiselect.position.left) { - + // Do not leave the screen newWidth = e.pageX - multiselect.position.left; if ((multiselect.position.left+newWidth)>=$(document).width()) newWidth -= (multiselect.position.left + newWidth) - $(document).width() + 2; - + $('#multiselect').css({ right: 'inherit', left: multiselect.position.left, width: newWidth }); - + } else { - + $('#multiselect').css({ right: multiselect.position.right, left: 'inherit', width: multiselect.position.left - e.pageX }); - + } - + }, - + stopResize: function() { - + $(document).off('mousemove'); - + }, - + getSize: function() { - + if (!visible.multiselect()) return false; - + return { top: $('#multiselect').offset().top, left: $('#multiselect').offset().left, width: parseInt($('#multiselect').css('width').replace('px', '')), height: parseInt($('#multiselect').css('height').replace('px', '')) } - + }, - + getSelection: function(e) { - + var tolerance = 150, id, ids = [], offset, size = multiselect.getSize(); - + if (visible.contextMenu()) return false; if (!visible.multiselect()) return false; - + $('.photo, .album').each(function() { - + offset = $(this).offset(); - + if (offset.top>=(size.top-tolerance)&& offset.left>=(size.left-tolerance)&& (offset.top+206)<=(size.top+size.height+tolerance)&& (offset.left+206)<=(size.left+size.width+tolerance)) { - + id = $(this).data('id'); - + if (id!=='0'&&id!==0&&id!=='f'&&id!=='s'&&id!==null&id!==undefined) { - + ids.push(id); $(this).addClass('active'); - + } - + } }); - + if (ids.length!=0&&visible.album()) contextMenu.photoMulti(ids, e); else if (ids.length!=0&&visible.albums()) contextMenu.albumMulti(ids, e); else multiselect.close(); - + }, - + close: function() { - + multiselect.stopResize(); - + multiselect.position.top = null; multiselect.position.right = null; multiselect.position.bottom = null; multiselect.position.left = null; - + lychee.animate('#multiselect', 'fadeOut'); setTimeout(function() { $('#multiselect').remove(); }, 300); - + } } \ No newline at end of file diff --git a/assets/js/modules/photo.js b/assets/js/modules/photo.js index 6165df5..74200d4 100644 --- a/assets/js/modules/photo.js +++ b/assets/js/modules/photo.js @@ -291,19 +291,19 @@ photo = { }], ["Cancel", function() {}] ]; - + modal.show("Set Description", "Enter a description for this photo: ", buttons); }, - + editTags: function(photoIDs) { - + var oldTags = "", tags = ""; - + if (!photoIDs) return false; if (photoIDs instanceof Array===false) photoIDs = [photoIDs]; - + // Get tags if (visible.photo()) oldTags = photo.json.tags; if (visible.album()&&photoIDs.length===1) oldTags = album.json.content[photoIDs].tags; @@ -315,10 +315,10 @@ photo = { }); if (same) oldTags = album.json.content[photoIDs[0]].tags; } - + // Improve tags oldTags = oldTags.replace(/,/g, ', '); - + buttons = [ ["Set Tags", function() { @@ -329,55 +329,55 @@ photo = { }], ["Cancel", function() {}] ]; - + if (photoIDs.length===1) modal.show("Set Tags", "Enter your tags for this photo. You can add multiple tags by separating them with a comma: ", buttons); else modal.show("Set Tags", "Enter your tags for all " + photoIDs.length + " selected photos. Existing tags will be overwritten. You can add multiple tags by separating them with a comma: ", buttons); - + }, - + setTags: function(photoIDs, tags) { - + var params; - + if (!photoIDs) return false; if (photoIDs instanceof Array===false) photoIDs = [photoIDs]; - + // Parse tags tags = tags.replace(/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/g, ','); tags = tags.replace(/,$|^,/g, ''); - + if (visible.photo()) { photo.json.tags = tags; view.photo.tags(); } - + photoIDs.forEach(function(id, index, array) { album.json.content[id].tags = tags; }); - + params = "setPhotoTags&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(); photo.setTags([photoID], photo.json.tags); - + }, - + share: function(photoID, service) { var link = "", diff --git a/assets/js/modules/upload.js b/assets/js/modules/upload.js index 4082470..917a46d 100755 --- a/assets/js/modules/upload.js +++ b/assets/js/modules/upload.js @@ -35,20 +35,20 @@ upload = { $(".upload_message").append("

" + text + "

"); }, - + notify: function(title) { - + var popup; - + if (!window.webkitNotifications) return false; - + if (window.webkitNotifications.checkPermission()!=0) window.webkitNotifications.requestPermission(); - + if (window.webkitNotifications.checkPermission()==0&&title) { popup = window.webkitNotifications.createNotification("", title, "You can now manage your new photo(s)."); popup.show(); } - + }, start: { @@ -64,7 +64,7 @@ upload = { if (files.length<=0) return false; if (albumID===false) albumID = 0; - + formData.append("function", "upload"); formData.append("albumID", albumID); @@ -170,7 +170,7 @@ upload = { }], ["Cancel", function() {}] ]; - + modal.show("Import from Link", "Please enter the direct link to a photo to import it: ", buttons); }, @@ -211,7 +211,7 @@ upload = { }], ["Cancel", function() {}] ]; - + modal.show("Import from Server", "This action will import all photos and albums which are located in 'uploads/import/' of your Lychee installation.", buttons); }, diff --git a/assets/js/modules/view.js b/assets/js/modules/view.js index fd498a3..c646189 100644 --- a/assets/js/modules/view.js +++ b/assets/js/modules/view.js @@ -59,7 +59,7 @@ view = { }, mode: function(mode) { - + var albumID = album.getID(); switch (mode) { @@ -447,11 +447,11 @@ view = { } }, - + tags: function() { - + $("#infobox #tags").html(build.tags(photo.json.tags)); - + }, photo: function() { diff --git a/assets/js/modules/visible.js b/assets/js/modules/visible.js index 4afaab7..867424b 100755 --- a/assets/js/modules/visible.js +++ b/assets/js/modules/visible.js @@ -21,7 +21,7 @@ visible = { if ($('#imageview.fadeIn').length>0) return true; else return false; }, - + search: function() { if (search.code!==null&&search.code!=='') return true; else return false; @@ -51,7 +51,7 @@ visible = { if ($('.contextmenu').length>0) return true; else return false; }, - + multiselect: function() { if ($('#multiselect').length>0) return true; else return false; From 9b8f626836a2440ef8729658d69cebebe2bd4935 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Mon, 17 Feb 2014 17:00:22 +0100 Subject: [PATCH 60/87] Ignore plugins --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index db6c242..58d934e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,9 @@ data/config.php uploads/import/* uploads/big/* uploads/thumb/* +plugins/* !uploads/import/index.html !uploads/big/index.html -!uploads/thumb/index.html \ No newline at end of file +!uploads/thumb/index.html +!plugins/check.php \ No newline at end of file From 05543793b0ae92551ef9c4a042fb54b346a1283b Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Mon, 17 Feb 2014 17:01:46 +0100 Subject: [PATCH 61/87] Trim whitespace and spaces to tabs --- php/access/admin.php | 20 +-- php/access/guest.php | 32 ++-- php/access/installation.php | 6 +- php/api.php | 12 +- php/modules/album.php | 290 +++++++++++++++---------------- php/modules/db.php | 44 ++--- php/modules/misc.php | 84 ++++----- php/modules/photo.php | 136 +++++++-------- php/modules/session.php | 30 ++-- php/modules/settings.php | 8 +- php/modules/upload.php | 330 ++++++++++++++++++------------------ 11 files changed, 496 insertions(+), 496 deletions(-) diff --git a/php/access/admin.php b/php/access/admin.php index f4ed528..c2b1ebe 100644 --- a/php/access/admin.php +++ b/php/access/admin.php @@ -1,9 +1,9 @@ 50) 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; + if (strlen($title)<1||strlen($title)>50) 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; } @@ -27,52 +27,52 @@ function getAlbums($public) { global $database, $settings; - // Smart Albums - if (!$public) $return = getSmartInfo(); + // Smart Albums + if (!$public) $return = getSmartInfo(); - // Albums - if ($public) $query = "SELECT id, title, public, sysdate, password FROM lychee_albums WHERE public = 1"; - else $query = "SELECT id, title, public, sysdate, password FROM lychee_albums"; - - $result = $database->query($query) OR exit("Error: $result
".$database->error); - $i = 0; - - while($row = $result->fetch_object()) { + // Albums + if ($public) $query = "SELECT id, title, public, sysdate, password FROM lychee_albums WHERE public = 1"; + else $query = "SELECT id, title, public, sysdate, password FROM lychee_albums"; - // Info - $return["content"][$row->id]['id'] = $row->id; - $return["content"][$row->id]['title'] = $row->title; - $return["content"][$row->id]['public'] = $row->public; - $return["content"][$row->id]['sysdate'] = date('F Y', strtotime($row->sysdate)); - - // Password - if ($row->password=="") $return["content"][$row->id]['password'] = false; - else $return["content"][$row->id]['password'] = true; + $result = $database->query($query) OR exit("Error: $result
".$database->error); + $i = 0; - // Thumbs - if (($public&&$row->password=="")||(!$public)) { - - $albumID = $row->id; - $result2 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE album = '$albumID' ORDER BY star DESC, " . substr($settings['sorting'], 9) . " LIMIT 0, 3"); - $k = 0; - while($row2 = $result2->fetch_object()){ - $return["content"][$row->id]["thumb$k"] = $row2->thumbUrl; - $k++; - } - if (!isset($return["content"][$row->id]["thumb0"])) $return["content"][$row->id]["thumb0"] = ""; - if (!isset($return["content"][$row->id]["thumb1"])) $return["content"][$row->id]["thumb1"] = ""; - if (!isset($return["content"][$row->id]["thumb2"])) $return["content"][$row->id]["thumb2"] = ""; - - } + while($row = $result->fetch_object()) { - // Album count - $i++; + // Info + $return["content"][$row->id]['id'] = $row->id; + $return["content"][$row->id]['title'] = $row->title; + $return["content"][$row->id]['public'] = $row->public; + $return["content"][$row->id]['sysdate'] = date('F Y', strtotime($row->sysdate)); - } + // Password + if ($row->password=="") $return["content"][$row->id]['password'] = false; + else $return["content"][$row->id]['password'] = true; - $return["num"] = $i; + // Thumbs + if (($public&&$row->password=="")||(!$public)) { - return $return; + $albumID = $row->id; + $result2 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE album = '$albumID' ORDER BY star DESC, " . substr($settings['sorting'], 9) . " LIMIT 0, 3"); + $k = 0; + while($row2 = $result2->fetch_object()){ + $return["content"][$row->id]["thumb$k"] = $row2->thumbUrl; + $k++; + } + if (!isset($return["content"][$row->id]["thumb0"])) $return["content"][$row->id]["thumb0"] = ""; + if (!isset($return["content"][$row->id]["thumb1"])) $return["content"][$row->id]["thumb1"] = ""; + if (!isset($return["content"][$row->id]["thumb2"])) $return["content"][$row->id]["thumb2"] = ""; + + } + + // Album count + $i++; + + } + + $return["num"] = $i; + + return $return; } @@ -81,33 +81,33 @@ function getSmartInfo() { global $database, $settings; // Unsorted - $result = $database->query("SELECT thumbUrl FROM lychee_photos WHERE album = 0 " . $settings['sorting']); - $i = 0; - while($row = $result->fetch_object()) { - if ($i<3) $return["unsortedThumb$i"] = $row->thumbUrl; - $i++; - } - $return['unsortedNum'] = $i; + $result = $database->query("SELECT thumbUrl FROM lychee_photos WHERE album = 0 " . $settings['sorting']); + $i = 0; + while($row = $result->fetch_object()) { + if ($i<3) $return["unsortedThumb$i"] = $row->thumbUrl; + $i++; + } + $return['unsortedNum'] = $i; // Public - $result2 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE public = 1 " . $settings['sorting']); - $i = 0; - while($row2 = $result2->fetch_object()) { - if ($i<3) $return["publicThumb$i"] = $row2->thumbUrl; - $i++; - } - $return['publicNum'] = $i; + $result2 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE public = 1 " . $settings['sorting']); + $i = 0; + while($row2 = $result2->fetch_object()) { + if ($i<3) $return["publicThumb$i"] = $row2->thumbUrl; + $i++; + } + $return['publicNum'] = $i; // Starred - $result3 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE star = 1 " . $settings['sorting']); - $i = 0; - while($row3 = $result3->fetch_object()) { - if ($i<3) $return["starredThumb$i"] = $row3->thumbUrl; - $i++; - } - $return['starredNum'] = $i; + $result3 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE star = 1 " . $settings['sorting']); + $i = 0; + while($row3 = $result3->fetch_object()) { + if ($i<3) $return["starredThumb$i"] = $row3->thumbUrl; + $i++; + } + $return['starredNum'] = $i; - return $return; + return $return; } @@ -118,27 +118,27 @@ function getAlbum($albumID) { // Get album information switch($albumID) { - case "f": $return['public'] = false; - $query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE star = 1 " . $settings['sorting']; - break; - - case "s": $return['public'] = false; - $query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE public = 1 " . $settings['sorting']; - break; - - case "0": $return['public'] = false; - $query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE album = 0 " . $settings['sorting']; + case "f": $return['public'] = false; + $query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE star = 1 " . $settings['sorting']; break; - default: $result = $database->query("SELECT * FROM lychee_albums WHERE id = '$albumID';"); - $row = $result->fetch_object(); - $return['title'] = $row->title; - $return['description'] = $row->description; - $return['sysdate'] = date('d M. Y', strtotime($row->sysdate)); - $return['public'] = $row->public; - $return['password'] = ($row->password=="" ? false : true); - $query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE album = '$albumID' " . $settings['sorting']; - break; + case "s": $return['public'] = false; + $query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE public = 1 " . $settings['sorting']; + break; + + case "0": $return['public'] = false; + $query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE album = 0 " . $settings['sorting']; + break; + + default: $result = $database->query("SELECT * FROM lychee_albums WHERE id = '$albumID';"); + $row = $result->fetch_object(); + $return['title'] = $row->title; + $return['description'] = $row->description; + $return['sysdate'] = date('d M. Y', strtotime($row->sysdate)); + $return['public'] = $row->public; + $return['password'] = ($row->password=="" ? false : true); + $query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE album = '$albumID' " . $settings['sorting']; + break; } @@ -148,21 +148,21 @@ function getAlbum($albumID) { $i = 0; while($row = $result->fetch_array()) { - $return['content'][$row['id']]['id'] = $row['id']; - $return['content'][$row['id']]['title'] = $row['title']; - $return['content'][$row['id']]['sysdate'] = date('d F Y', strtotime($row['sysdate'])); - $return['content'][$row['id']]['public'] = $row['public']; - $return['content'][$row['id']]['star'] = $row['star']; - $return['content'][$row['id']]['tags'] = $row['tags']; - $return['content'][$row['id']]['album'] = $row['album']; - $return['content'][$row['id']]['thumbUrl'] = $row['thumbUrl']; + $return['content'][$row['id']]['id'] = $row['id']; + $return['content'][$row['id']]['title'] = $row['title']; + $return['content'][$row['id']]['sysdate'] = date('d F Y', strtotime($row['sysdate'])); + $return['content'][$row['id']]['public'] = $row['public']; + $return['content'][$row['id']]['star'] = $row['star']; + $return['content'][$row['id']]['tags'] = $row['tags']; + $return['content'][$row['id']]['album'] = $row['album']; + $return['content'][$row['id']]['thumbUrl'] = $row['thumbUrl']; - $return['content'][$row['id']]['previousPhoto'] = $previousPhotoID; - $return['content'][$row['id']]['nextPhoto'] = ""; - if ($previousPhotoID!="") $return['content'][$previousPhotoID]['nextPhoto'] = $row['id']; + $return['content'][$row['id']]['previousPhoto'] = $previousPhotoID; + $return['content'][$row['id']]['nextPhoto'] = ""; + if ($previousPhotoID!="") $return['content'][$previousPhotoID]['nextPhoto'] = $row['id']; - $previousPhotoID = $row['id']; - $i++; + $previousPhotoID = $row['id']; + $i++; } @@ -197,22 +197,22 @@ function setAlbumTitle($albumIDs, $title) { global $database; - if (strlen($title)<1||strlen($title)>50) return false; - $result = $database->query("UPDATE lychee_albums SET title = '$title' WHERE id IN ($albumIDs);"); - - if (!$result) return false; - return true; + if (strlen($title)<1||strlen($title)>50) return false; + $result = $database->query("UPDATE lychee_albums SET title = '$title' WHERE id IN ($albumIDs);"); + + if (!$result) return false; + return true; } function setAlbumDescription($albumID, $description) { global $database; - + $description = htmlentities($description); if (strlen($description)>1000) return false; $result = $database->query("UPDATE lychee_albums SET description = '$description' WHERE id = '$albumID';"); - + if (!$result) return false; return true; @@ -221,17 +221,17 @@ function setAlbumDescription($albumID, $description) { function deleteAlbum($albumIDs) { global $database; - + $error = false; $result = $database->query("SELECT id FROM lychee_photos WHERE album IN ($albumIDs);"); - + // Delete photos while ($row = $result->fetch_object()) if (!deletePhoto($row->id)) $error = true; - + // Delete album $result = $database->query("DELETE FROM lychee_albums WHERE id IN ($albumIDs);"); - + if ($error||!$result) return false; return true; @@ -240,54 +240,54 @@ function deleteAlbum($albumIDs) { function getAlbumArchive($albumID) { global $database; - + switch($albumID) { - case 's': - $query = "SELECT url FROM lychee_photos WHERE public = '1';"; - $zipTitle = "Public"; - break; - case 'f': - $query = "SELECT url FROM lychee_photos WHERE star = '1';"; - $zipTitle = "Starred"; - break; - default: - $query = "SELECT url FROM lychee_photos WHERE album = '$albumID';"; - $zipTitle = "Unsorted"; + case 's': + $query = "SELECT url FROM lychee_photos WHERE public = '1';"; + $zipTitle = "Public"; + break; + case 'f': + $query = "SELECT url FROM lychee_photos WHERE star = '1';"; + $zipTitle = "Starred"; + break; + default: + $query = "SELECT url FROM lychee_photos WHERE album = '$albumID';"; + $zipTitle = "Unsorted"; } - + $zip = new ZipArchive(); $result = $database->query($query); $files = array(); $i = 0; - + while($row = $result->fetch_object()) { - $files[$i] = "../uploads/big/".$row->url; - $i++; + $files[$i] = "../uploads/big/".$row->url; + $i++; } - + $result = $database->query("SELECT title FROM lychee_albums WHERE id = '$albumID' LIMIT 1;"); $row = $result->fetch_object(); if ($albumID!=0&&is_numeric($albumID)) $zipTitle = $row->title; $filename = "../data/$zipTitle.zip"; - + if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) { - return false; + return false; } - + foreach($files AS $zipFile) { - $newFile = explode("/",$zipFile); - $newFile = array_reverse($newFile); - $zip->addFile($zipFile, $zipTitle."/".$newFile[0]); + $newFile = explode("/",$zipFile); + $newFile = array_reverse($newFile); + $zip->addFile($zipFile, $zipTitle."/".$newFile[0]); } - + $zip->close(); - + header("Content-Type: application/zip"); header("Content-Disposition: attachment; filename=\"$zipTitle.zip\""); header("Content-Length: ".filesize($filename)); readfile($filename); unlink($filename); - + return true; } @@ -299,10 +299,10 @@ function setAlbumPublic($albumID, $password) { $result = $database->query("SELECT public FROM lychee_albums WHERE id = '$albumID';"); $row = $result->fetch_object(); $public = ($row->public=='0' ? 1 : 0); - + $result = $database->query("UPDATE lychee_albums SET public = '$public', password = NULL WHERE id = '$albumID';"); if (!$result) return false; - + if ($public==1) { $result = $database->query("UPDATE lychee_photos SET public = 0 WHERE album = '$albumID';"); if (!$result) return false; @@ -330,7 +330,7 @@ function checkAlbumPassword($albumID, $password) { $result = $database->query("SELECT password FROM lychee_albums WHERE id = '$albumID';"); $row = $result->fetch_object(); - + if ($row->password=="") return true; else if ($row->password==$password) return true; return false; @@ -340,7 +340,7 @@ function checkAlbumPassword($albumID, $password) { function isAlbumPublic($albumID) { global $database; - + $result = $database->query("SELECT public FROM lychee_albums WHERE id = '$albumID';"); $row = $result->fetch_object(); diff --git a/php/modules/db.php b/php/modules/db.php index 7680fc9..0c9b264 100755 --- a/php/modules/db.php +++ b/php/modules/db.php @@ -1,32 +1,32 @@ connect_errno) exit('Error: ' . $database->connect_error); - if ($database->connect_errno) exit('Error: ' . $database->connect_error); - // Avoid sql injection on older MySQL versions if ($database->server_version<50500) $database->set_charset('GBK'); if (!$database->select_db($dbName)) if (!dbCreate($dbName, $database)) exit('Error: Could not create database!'); - + if (!$database->query('SELECT * FROM lychee_photos, lychee_albums, lychee_settings LIMIT 0;')) if (!dbCreateTables($database)) exit('Error: Could not create tables!'); - return $database; + return $database; } @@ -41,9 +41,9 @@ function dbCreateConfig($dbHost = 'localhost', $dbUser, $dbPassword, $dbName = ' $config = ""; if (file_put_contents('../data/config.php', $config)===false) return 'Warning: Could not create file!'; - + $_SESSION['login'] = true; return true; @@ -125,11 +125,11 @@ function dbCreateTables($database) { "; - if (!$database->query($query)) return false; + if (!$database->query($query)) return false; - } + } - if (!$database->query('SELECT * FROM lychee_photos LIMIT 0;')) { + if (!$database->query('SELECT * FROM lychee_photos LIMIT 0;')) { $query = " @@ -163,11 +163,11 @@ function dbCreateTables($database) { "; - if (!$database->query($query)) return false; + if (!$database->query($query)) return false; - } + } - return true; + return true; } @@ -175,9 +175,9 @@ function dbClose() { global $database; - if (!$database->close()) exit('Error: Closing the connection failed!'); + if (!$database->close()) exit('Error: Closing the connection failed!'); - return true; + return true; } diff --git a/php/modules/misc.php b/php/modules/misc.php index 0678fce..23445ef 100755 --- a/php/modules/misc.php +++ b/php/modules/misc.php @@ -1,10 +1,10 @@ query("SELECT title, description, url FROM lychee_photos WHERE id = '$photoID';"); $row = $result->fetch_object(); - + $parseUrl = parse_url("http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); $picture = $parseUrl['scheme']."://".$parseUrl['host'].$parseUrl['path']."/../uploads/big/".$row->url; - - $return = ''; + + $return = ''; $return .= ''; $return .= ''; - $return .= ''; - + $return .= ''; + $return .= ''; $return .= ''; $return .= ''; $return .= ''; - + $return .= ''; $return .= ''; $return .= ''; - + return $return; } @@ -47,37 +47,37 @@ function search($term) { $return['albums'] = ''; // Photos - $result = $database->query("SELECT id, title, tags, sysdate, public, star, album, thumbUrl 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 id, title, tags, sysdate, public, star, album, thumbUrl 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'])); + } // Albums - $result = $database->query("SELECT id, title, public, sysdate, password FROM lychee_albums WHERE title like '%$term%' OR description like '%$term%';"); - $i = 0; - while($row = $result->fetch_object()) { + $result = $database->query("SELECT id, title, public, sysdate, password FROM lychee_albums WHERE title like '%$term%' OR description like '%$term%';"); + $i = 0; + while($row = $result->fetch_object()) { // Info - $return['albums'][$row->id]['id'] = $row->id; - $return['albums'][$row->id]['title'] = $row->title; - $return['albums'][$row->id]['public'] = $row->public; - $return['albums'][$row->id]['sysdate'] = date('F Y', strtotime($row->sysdate)); - $return['albums'][$row->id]['password'] = ($row->password=='' ? false : true); + $return['albums'][$row->id]['id'] = $row->id; + $return['albums'][$row->id]['title'] = $row->title; + $return['albums'][$row->id]['public'] = $row->public; + $return['albums'][$row->id]['sysdate'] = date('F Y', strtotime($row->sysdate)); + $return['albums'][$row->id]['password'] = ($row->password=='' ? false : true); // Thumbs - $result2 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE album = '" . $row->id . "' " . $settings['sorting'] . " LIMIT 0, 3;"); - $k = 0; - while($row2 = $result2->fetch_object()){ - $return['albums'][$row->id]["thumb$k"] = $row2->thumbUrl; - $k++; - } - - $i++; + $result2 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE album = '" . $row->id . "' " . $settings['sorting'] . " LIMIT 0, 3;"); + $k = 0; + while($row2 = $result2->fetch_object()){ + $return['albums'][$row->id]["thumb$k"] = $row2->thumbUrl; + $k++; + } - } + $i++; - return $return; + } + + return $return; } @@ -85,13 +85,13 @@ function update() { global $database; - if(!$database->query("SELECT `public` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `public` TINYINT( 1 ) NOT NULL DEFAULT '0'"); - if(!$database->query("SELECT `password` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `password` VARCHAR( 100 ) NULL DEFAULT ''"); - if(!$database->query("SELECT `description` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `description` VARCHAR( 1000 ) NULL DEFAULT ''"); - 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 `public` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `public` TINYINT( 1 ) NOT NULL DEFAULT '0'"); + if(!$database->query("SELECT `password` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `password` VARCHAR( 100 ) NULL DEFAULT ''"); + if(!$database->query("SELECT `description` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `description` VARCHAR( 1000 ) NULL DEFAULT ''"); + 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 `tags` FROM `lychee_photos` LIMIT 1;")) $database->query("ALTER TABLE `lychee_photos` ADD `tags` VARCHAR( 1000 ) 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 `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/', '')"); return true; diff --git a/php/modules/photo.php b/php/modules/photo.php index dd2af21..7e4e4f9 100755 --- a/php/modules/photo.php +++ b/php/modules/photo.php @@ -1,10 +1,10 @@ query($query); - $return = $result->fetch_array(); + $result = $database->query($query); + $return = $result->fetch_array(); - if ($albumID!='false') { + if ($albumID!='false') { - if ($return['album']!=0) { + if ($return['album']!=0) { - $result = $database->query("SELECT public FROM lychee_albums WHERE id = '" . $return['album'] . "';"); - $return_album = $result->fetch_array(); - if ($return_album['public']=="1") $return['public'] = "2"; + $result = $database->query("SELECT public FROM lychee_albums WHERE id = '" . $return['album'] . "';"); + $return_album = $result->fetch_array(); + if ($return_album['public']=="1") $return['public'] = "2"; - } + } - $return['original_album'] = $return['album']; - $return['album'] = $albumID; - $return['sysdate'] = date('d M. Y', strtotime($return['sysdate'])); - if (strlen($return['takedate'])>0) $return['takedate'] = date('d M. Y', strtotime($return['takedate'])); + $return['original_album'] = $return['album']; + $return['album'] = $albumID; + $return['sysdate'] = date('d M. Y', strtotime($return['sysdate'])); + if (strlen($return['takedate'])>0) $return['takedate'] = date('d M. Y', strtotime($return['takedate'])); } unset($return['album_public']); - return $return; + return $return; } @@ -44,33 +44,33 @@ function setPhotoPublic($photoID, $url) { global $database; - $result = $database->query("SELECT public FROM lychee_photos WHERE id = '$photoID';"); - $row = $result->fetch_object(); - $public = ($row->public==0 ? 1 : 0); - $result = $database->query("UPDATE lychee_photos SET public = '$public' WHERE id = '$photoID';"); + $result = $database->query("SELECT public FROM lychee_photos WHERE id = '$photoID';"); + $row = $result->fetch_object(); + $public = ($row->public==0 ? 1 : 0); + $result = $database->query("UPDATE lychee_photos SET public = '$public' WHERE id = '$photoID';"); - if (!$result) return false; - return true; + if (!$result) return false; + return true; } function setPhotoStar($photoIDs) { global $database; - + $error = false; - $result = $database->query("SELECT id, star FROM lychee_photos WHERE id IN ($photoIDs);"); - - while ($row = $result->fetch_object()) { - - $star = ($row->star==0 ? 1 : 0); - $star = $database->query("UPDATE lychee_photos SET star = '$star' WHERE id = '$row->id';"); - if (!$star) $error = true; - - } - - if ($error) return false; - return true; + $result = $database->query("SELECT id, star FROM lychee_photos WHERE id IN ($photoIDs);"); + + while ($row = $result->fetch_object()) { + + $star = ($row->star==0 ? 1 : 0); + $star = $database->query("UPDATE lychee_photos SET star = '$star' WHERE id = '$row->id';"); + if (!$star) $error = true; + + } + + if ($error) return false; + return true; } @@ -78,10 +78,10 @@ function setPhotoAlbum($photoIDs, $albumID) { global $database; - $result = $database->query("UPDATE lychee_photos SET album = '$albumID' WHERE id IN ($photoIDs);"); + $result = $database->query("UPDATE lychee_photos SET album = '$albumID' WHERE id IN ($photoIDs);"); - if (!$result) return false; - return true; + if (!$result) return false; + return true; } @@ -89,11 +89,11 @@ function setPhotoTitle($photoIDs, $title) { global $database; - if (strlen($title)>50) return false; - $result = $database->query("UPDATE lychee_photos SET title = '$title' WHERE id IN ($photoIDs);"); + if (strlen($title)>50) return false; + $result = $database->query("UPDATE lychee_photos SET title = '$title' WHERE id IN ($photoIDs);"); - if (!$result) return false; - return true; + if (!$result) return false; + return true; } @@ -101,24 +101,24 @@ function setPhotoDescription($photoID, $description) { global $database; - $description = htmlentities($description); - if (strlen($description)>1000) return false; - - $result = $database->query("UPDATE lychee_photos SET description = '$description' WHERE id = '$photoID';"); + $description = htmlentities($description); + if (strlen($description)>1000) return false; - if (!$result) return false; - return true; + $result = $database->query("UPDATE lychee_photos SET description = '$description' WHERE id = '$photoID';"); + + if (!$result) return false; + return true; } function setPhotoTags($photoIDs, $tags) { global $database; - + // Parse tags $tags = preg_replace('/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/', ',', $tags); $tags = preg_replace('/,$|^,/', ',', $tags); - + if (strlen($tags)>1000) return false; $result = $database->query("UPDATE lychee_photos SET tags = '$tags' WHERE id IN ($photoIDs);"); @@ -131,26 +131,26 @@ function setPhotoTags($photoIDs, $tags) { function deletePhoto($photoIDs) { global $database; - + $result = $database->query("SELECT id, url, thumbUrl FROM lychee_photos WHERE id IN ($photoIDs);"); - + while ($row = $result->fetch_object()) { - + // Get retina thumb url $thumbUrl2x = explode(".", $row->thumbUrl); $thumbUrl2x = $thumbUrl2x[0] . '@2x.' . $thumbUrl2x[1]; - + // Delete files if (!unlink('../uploads/big/' . $row->url)) return false; if (!unlink('../uploads/thumb/' . $row->thumbUrl)) return false; if (!unlink('../uploads/thumb/' . $thumbUrl2x)) return false; - + // Delete db entry $delete = $database->query("DELETE FROM lychee_photos WHERE id = $row->id;"); if (!$delete) return false; - + } - + if (!$result) return false; return true; @@ -162,16 +162,16 @@ function isPhotoPublic($photoID, $password) { $query = "SELECT public, album FROM lychee_photos WHERE id = '$photoID';"; - $result = $database->query($query); - $row = $result->fetch_object(); - - if ($row->public==1) return true; - else { - $cAP = checkAlbumPassword($row->album, $password); - $iAP = isAlbumPublic($row->album); - if ($iAP&&$cAP) return true; - return false; - } + $result = $database->query($query); + $row = $result->fetch_object(); + + if ($row->public==1) return true; + else { + $cAP = checkAlbumPassword($row->album, $password); + $iAP = isAlbumPublic($row->album); + if ($iAP&&$cAP) return true; + return false; + } } diff --git a/php/modules/session.php b/php/modules/session.php index ae42083..d86cff0 100755 --- a/php/modules/session.php +++ b/php/modules/session.php @@ -1,10 +1,10 @@ query('SELECT * FROM lychee_settings;'); while($row = $result->fetch_object()) { - $return[$row->key] = $row->value; + $return[$row->key] = $row->value; } return $return; diff --git a/php/modules/upload.php b/php/modules/upload.php index 3cda662..fa92dfb 100755 --- a/php/modules/upload.php +++ b/php/modules/upload.php @@ -1,10 +1,10 @@ query($query); + // Save to DB + $query = "INSERT INTO lychee_photos (id, title, url, description, type, width, height, size, sysdate, systime, iso, aperture, make, model, shutter, focal, takedate, taketime, thumbUrl, album, public, star, import_name) + VALUES ( + '" . $id . "', + '" . $info['title'] . "', + '" . $photo_name . "', + '" . $info['description'] . "', + '" . $info['type'] . "', + '" . $info['width'] . "', + '" . $info['height'] . "', + '" . $info['size'] . "', + '" . $info['date'] . "', + '" . $info['time'] . "', + '" . $info['iso'] . "', + '" . $info['aperture'] . "', + '" . $info['make'] . "', + '" . $info['model'] . "', + '" . $info['shutter'] . "', + '" . $info['focal'] . "', + '" . $info['takeDate'] . "', + '" . $info['takeTime'] . "', + '" . md5($id) . ".jpeg', + '" . $albumID . "', + '" . $public . "', + '" . $star . "', + '" . $import_name . "');"; + $result = $database->query($query); - if (!$result) return false; + if (!$result) return false; - } + } - return true; + return true; } @@ -188,18 +188,18 @@ function getInfo($filename) { // IPTC Metadata if(isset($iptcArray['APP13'])) { - + $iptcInfo = iptcparse($iptcArray['APP13']); if (is_array($iptcInfo)) { - + $temp = @$iptcInfo['2#105'][0]; if (isset($temp)&&strlen($temp)>0) $return['title'] = $temp; - + $temp = @$iptcInfo['2#120'][0]; if (isset($temp)&&strlen($temp)>0) $return['description'] = $temp; - + } - + } // EXIF Metadata Fallback @@ -212,49 +212,49 @@ function getInfo($filename) { $return['focal'] = ''; $return['takeDate'] = ''; $return['takeTime'] = ''; - + // Read EXIF if ($info['mime']=='image/jpeg') $exif = exif_read_data($url, 'EXIF', 0); else $exif = false; // EXIF Metadata - if ($exif!==false) { + if ($exif!==false) { - $temp = @$exif['Orientation']; - if (isset($temp)) $return['orientation'] = $temp; + $temp = @$exif['Orientation']; + if (isset($temp)) $return['orientation'] = $temp; - $temp = @$exif['ISOSpeedRatings']; - if (isset($temp)) $return['iso'] = $temp; + $temp = @$exif['ISOSpeedRatings']; + if (isset($temp)) $return['iso'] = $temp; - $temp = @$exif['COMPUTED']['ApertureFNumber']; - if (isset($temp)) $return['aperture'] = $temp; + $temp = @$exif['COMPUTED']['ApertureFNumber']; + if (isset($temp)) $return['aperture'] = $temp; - $temp = @$exif['Make']; - if (isset($temp)) $return['make'] = $exif['Make']; + $temp = @$exif['Make']; + if (isset($temp)) $return['make'] = $exif['Make']; - $temp = @$exif['Model']; - if (isset($temp)) $return['model'] = $temp; + $temp = @$exif['Model']; + if (isset($temp)) $return['model'] = $temp; - $temp = @$exif['ExposureTime']; - if (isset($temp)) $return['shutter'] = $exif['ExposureTime'] . ' Sec.'; + $temp = @$exif['ExposureTime']; + if (isset($temp)) $return['shutter'] = $exif['ExposureTime'] . ' Sec.'; - $temp = @$exif['FocalLength']; - if (isset($temp)) $return['focal'] = ($temp/1) . ' mm'; + $temp = @$exif['FocalLength']; + if (isset($temp)) $return['focal'] = ($temp/1) . ' mm'; - $temp = @$exif['DateTimeOriginal']; - if (isset($temp)) { - $exifDate = explode(' ', $temp); - $date = explode(':', $exifDate[0]); - $return['takeDate'] = $date[2].'.'.$date[1].'.'.$date[0]; - $return['takeTime'] = $exifDate[1]; - } + $temp = @$exif['DateTimeOriginal']; + if (isset($temp)) { + $exifDate = explode(' ', $temp); + $date = explode(':', $exifDate[0]); + $return['takeDate'] = $date[2].'.'.$date[1].'.'.$date[0]; + $return['takeTime'] = $exifDate[1]; + } - } + } // Security foreach(array_keys($return) as $key) $return[$key] = mysqli_real_escape_string($database, $return[$key]); - return $return; + return $return; } @@ -262,45 +262,45 @@ function createThumb($filename, $width = 200, $height = 200) { global $settings; - $url = "../uploads/big/$filename"; - $info = getimagesize($url); + $url = "../uploads/big/$filename"; + $info = getimagesize($url); - $photoName = explode(".", $filename); - $newUrl = "../uploads/thumb/$photoName[0].jpeg"; - $newUrl2x = "../uploads/thumb/$photoName[0]@2x.jpeg"; + $photoName = explode(".", $filename); + $newUrl = "../uploads/thumb/$photoName[0].jpeg"; + $newUrl2x = "../uploads/thumb/$photoName[0]@2x.jpeg"; - // Set position and size - $thumb = imagecreatetruecolor($width, $height); - $thumb2x = imagecreatetruecolor($width*2, $height*2); - if ($info[0]<$info[1]) { - $newSize = $info[0]; - $startWidth = 0; - $startHeight = $info[1]/2 - $info[0]/2; - } else { - $newSize = $info[1]; - $startWidth = $info[0]/2 - $info[1]/2; - $startHeight = 0; - } - - // Fallback for older version - if ($info['mime']==='image/webp'&&floatval(phpversion())<5.5) return false; + // Set position and size + $thumb = imagecreatetruecolor($width, $height); + $thumb2x = imagecreatetruecolor($width*2, $height*2); + if ($info[0]<$info[1]) { + $newSize = $info[0]; + $startWidth = 0; + $startHeight = $info[1]/2 - $info[0]/2; + } else { + $newSize = $info[1]; + $startWidth = $info[0]/2 - $info[1]/2; + $startHeight = 0; + } - // Create new image - switch($info['mime']) { - case 'image/jpeg': $sourceImg = imagecreatefromjpeg($url); break; - case 'image/png': $sourceImg = imagecreatefrompng($url); break; - case 'image/gif': $sourceImg = imagecreatefromgif($url); break; - case 'image/webp': $sourceImg = imagecreatefromwebp($url); break; - default: return false; - } + // Fallback for older version + if ($info['mime']==='image/webp'&&floatval(phpversion())<5.5) return false; - imagecopyresampled($thumb,$sourceImg,0,0,$startWidth,$startHeight,$width,$height,$newSize,$newSize); - imagecopyresampled($thumb2x,$sourceImg,0,0,$startWidth,$startHeight,$width*2,$height*2,$newSize,$newSize); + // Create new image + switch($info['mime']) { + case 'image/jpeg': $sourceImg = imagecreatefromjpeg($url); break; + case 'image/png': $sourceImg = imagecreatefrompng($url); break; + case 'image/gif': $sourceImg = imagecreatefromgif($url); break; + case 'image/webp': $sourceImg = imagecreatefromwebp($url); break; + default: return false; + } - imagejpeg($thumb,$newUrl,$settings['thumbQuality']); - imagejpeg($thumb2x,$newUrl2x,$settings['thumbQuality']); + imagecopyresampled($thumb,$sourceImg,0,0,$startWidth,$startHeight,$width,$height,$newSize,$newSize); + imagecopyresampled($thumb2x,$sourceImg,0,0,$startWidth,$startHeight,$width*2,$height*2,$newSize,$newSize); - return true; + imagejpeg($thumb,$newUrl,$settings['thumbQuality']); + imagejpeg($thumb2x,$newUrl2x,$settings['thumbQuality']); + + return true; } @@ -308,7 +308,7 @@ function importPhoto($path, $albumID = 0) { $info = getimagesize($path); $size = filesize($path); - + $nameFile = array(array()); $nameFile[0]['name'] = $path; $nameFile[0]['type'] = $info['mime']; @@ -337,7 +337,7 @@ function importUrl($url, $albumID = 0) { $pathinfo = pathinfo($key); $filename = $pathinfo['filename'].".".$pathinfo['extension']; $tmp_name = "../uploads/import/$filename"; - + copy($key, $tmp_name); } @@ -357,9 +357,9 @@ function importUrl($url, $albumID = 0) { $pathinfo = pathinfo($url); $filename = $pathinfo['filename'].".".$pathinfo['extension']; $tmp_name = "../uploads/import/$filename"; - + copy($url, $tmp_name); - + return importPhoto($filename, $albumID); } @@ -381,19 +381,19 @@ function importServer($albumID = 0, $path = '../uploads/import/') { foreach ($files as $file) { if (@getimagesize($file)) { - + // Photo if (!importPhoto($file, $albumID)) return false; $contains['photos'] = true; - + } else if (is_dir($file)) { - + $name = mysqli_real_escape_string($database, basename($file)); $newAlbumID = addAlbum('[Import] ' . $name); - + if ($newAlbumID!==false) importServer($newAlbumID, $file . '/'); $contains['albums'] = true; - + } } From 6cf4ba7f1b0d478b4e2c0e6c499507c5a21fef10 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Thu, 20 Feb 2014 20:17:06 +0100 Subject: [PATCH 62/87] License changes --- readme.md | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/readme.md b/readme.md index 1fdf47a..12bc480 100644 --- a/readme.md +++ b/readme.md @@ -23,10 +23,6 @@ Sign in and click the gear on the top left corner to change your settings. If yo Updating is as easy as it should be. [Update »](docs/md/Update.md) -### FTP Upload - -To import photos and albums located in `uploads/import/` (photos you have uploaded via FTP or else), sign in and click the add-icon on the top right. Then choose 'Import from Server'. - ### Keyboard Shortcuts These shortcuts will help you to use Lychee even faster. [Keyboard Shortcuts »](docs/md/Keyboard Shortcuts.md) @@ -57,13 +53,11 @@ I am working hard on continuously developing and maintaining Lychee. Please cons ## License -(MIT License) +Copyright © 2014 [Tobias Reich](http://electerious.com) +Copyright © 2013 [Philipp Maurer](http://phinal.net) -Copyright (C) 2014 [Tobias Reich](http://electerious.com) -Copyright (C) 2013 [Philipp Maurer](http://phinal.net) +[![license](http://i.creativecommons.org/l/by-nc-sa/4.0/80x15.png)](http://creativecommons.org/licenses/by-nc-sa/4.0/deed.en_US) -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +[Lychee](http://purl.org/dc/terms/) by [Tobias Reich](http://electerious.com) is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-nc-sa/4.0/deed.en_US). Based on a work at [https://github.com/electerious/Lychee](https://github.com/electerious/Lychee). -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +You are allowed to use Lychee for personal/non-commercial purposes. You are not allowed to commercially use Lychee 2.1 or higher without a valid license from [our website](http://lychee.electerious.com). \ No newline at end of file From 5ffae46e1555b87bb0f0a32737bd4bf34696d60e Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 23 Feb 2014 15:58:39 +0100 Subject: [PATCH 63/87] Visual code adjustments --- plugins/check.php | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/plugins/check.php b/plugins/check.php index b6d5b99..5026c8b 100644 --- a/plugins/check.php +++ b/plugins/check.php @@ -1,7 +1,7 @@ Date: Sun, 23 Feb 2014 16:02:01 +0100 Subject: [PATCH 64/87] Makefile --- assets/css/{min/reset.css => _reset.css} | 0 assets/css/{modules => }/animations.css | 0 assets/css/{modules => }/content.css | 0 assets/css/{modules => }/contextmenu.css | 0 assets/css/{modules => }/font.css | 4 +- assets/css/{modules => }/header.css | 0 assets/css/{modules => }/imageview.css | 0 assets/css/{modules => }/infobox.css | 0 assets/css/{modules => }/loading.css | 0 assets/css/{modules => }/mediaquery.css | 0 assets/css/{modules => }/message.css | 0 assets/css/min/main.css | 1 - assets/css/{modules => }/misc.css | 0 assets/css/{modules => }/multiselect.css | 0 assets/css/{modules => }/tooltip.css | 0 assets/css/{modules => }/upload.css | 0 .../js/{min/frameworks.js => _frameworks.js} | 0 assets/js/{modules => }/album.js | 0 assets/js/{modules => }/albums.js | 0 assets/js/{modules => }/build.js | 0 assets/js/{modules => }/contextMenu.js | 0 assets/js/{modules => }/init.js | 0 assets/js/{modules => }/loadingBar.js | 0 assets/js/{modules => }/lychee.js | 0 assets/js/min/main.js | 3 - assets/js/{modules => }/modal.js | 0 assets/js/modules/view.js | 474 ---------------- assets/js/{modules => }/multiselect.js | 0 assets/js/{modules => }/password.js | 0 assets/js/{modules => }/photo.js | 0 assets/js/{modules => }/search.js | 0 assets/js/{modules => }/settings.js | 0 assets/js/{modules => }/upload.js | 0 assets/js/view.js | 504 +++++++++++++++--- assets/js/view/view.js | 112 ++++ assets/js/{modules => }/visible.js | 0 docs/Makefile | 35 ++ docs/compile.sh | 32 -- index.html | 80 ++- 39 files changed, 620 insertions(+), 625 deletions(-) rename assets/css/{min/reset.css => _reset.css} (100%) rename assets/css/{modules => }/animations.css (100%) rename assets/css/{modules => }/content.css (100%) rename assets/css/{modules => }/contextmenu.css (100%) rename assets/css/{modules => }/font.css (97%) rename assets/css/{modules => }/header.css (100%) rename assets/css/{modules => }/imageview.css (100%) rename assets/css/{modules => }/infobox.css (100%) rename assets/css/{modules => }/loading.css (100%) rename assets/css/{modules => }/mediaquery.css (100%) rename assets/css/{modules => }/message.css (100%) delete mode 100644 assets/css/min/main.css rename assets/css/{modules => }/misc.css (100%) rename assets/css/{modules => }/multiselect.css (100%) rename assets/css/{modules => }/tooltip.css (100%) rename assets/css/{modules => }/upload.css (100%) rename assets/js/{min/frameworks.js => _frameworks.js} (100%) rename assets/js/{modules => }/album.js (100%) rename assets/js/{modules => }/albums.js (100%) rename assets/js/{modules => }/build.js (100%) rename assets/js/{modules => }/contextMenu.js (100%) rename assets/js/{modules => }/init.js (100%) rename assets/js/{modules => }/loadingBar.js (100%) rename assets/js/{modules => }/lychee.js (100%) delete mode 100755 assets/js/min/main.js rename assets/js/{modules => }/modal.js (100%) delete mode 100644 assets/js/modules/view.js rename assets/js/{modules => }/multiselect.js (100%) rename assets/js/{modules => }/password.js (100%) rename assets/js/{modules => }/photo.js (100%) rename assets/js/{modules => }/search.js (100%) rename assets/js/{modules => }/settings.js (100%) rename assets/js/{modules => }/upload.js (100%) create mode 100644 assets/js/view/view.js rename assets/js/{modules => }/visible.js (100%) create mode 100644 docs/Makefile delete mode 100644 docs/compile.sh diff --git a/assets/css/min/reset.css b/assets/css/_reset.css similarity index 100% rename from assets/css/min/reset.css rename to assets/css/_reset.css diff --git a/assets/css/modules/animations.css b/assets/css/animations.css similarity index 100% rename from assets/css/modules/animations.css rename to assets/css/animations.css diff --git a/assets/css/modules/content.css b/assets/css/content.css similarity index 100% rename from assets/css/modules/content.css rename to assets/css/content.css diff --git a/assets/css/modules/contextmenu.css b/assets/css/contextmenu.css similarity index 100% rename from assets/css/modules/contextmenu.css rename to assets/css/contextmenu.css diff --git a/assets/css/modules/font.css b/assets/css/font.css similarity index 97% rename from assets/css/modules/font.css rename to assets/css/font.css index 3517a48..53f2a2b 100755 --- a/assets/css/modules/font.css +++ b/assets/css/font.css @@ -23,8 +23,8 @@ */ @font-face { font-family: 'FontAwesome'; - src: url('../../font/fontawesome-webfont.eot'); - src: url('../../font/fontawesome-webfont.eot?#iefix') format('eot'), url('../../font/fontawesome-webfont.woff') format('woff'), url('../../font/fontawesome-webfont.ttf') format('truetype'), url('../../font/fontawesome-webfont.svg#FontAwesome') format('svg'); + src: url('../font/fontawesome-webfont.eot'); + src: url('../font/fontawesome-webfont.eot?#iefix') format('eot'), url('../font/fontawesome-webfont.woff') format('woff'), url('../font/fontawesome-webfont.ttf') format('truetype'), url('../font/fontawesome-webfont.svg#FontAwesome') format('svg'); font-weight: normal; font-style: normal; } diff --git a/assets/css/modules/header.css b/assets/css/header.css similarity index 100% rename from assets/css/modules/header.css rename to assets/css/header.css diff --git a/assets/css/modules/imageview.css b/assets/css/imageview.css similarity index 100% rename from assets/css/modules/imageview.css rename to assets/css/imageview.css diff --git a/assets/css/modules/infobox.css b/assets/css/infobox.css similarity index 100% rename from assets/css/modules/infobox.css rename to assets/css/infobox.css diff --git a/assets/css/modules/loading.css b/assets/css/loading.css similarity index 100% rename from assets/css/modules/loading.css rename to assets/css/loading.css diff --git a/assets/css/modules/mediaquery.css b/assets/css/mediaquery.css similarity index 100% rename from assets/css/modules/mediaquery.css rename to assets/css/mediaquery.css diff --git a/assets/css/modules/message.css b/assets/css/message.css similarity index 100% rename from assets/css/modules/message.css rename to assets/css/message.css diff --git a/assets/css/min/main.css b/assets/css/min/main.css deleted file mode 100644 index f95629c..0000000 --- a/assets/css/min/main.css +++ /dev/null @@ -1 +0,0 @@ -.fadeIn{-webkit-animation-name:fadeIn;-moz-animation-name:fadeIn;animation-name:fadeIn}.fadeIn,.fadeOut{-webkit-animation-duration:.3s;-webkit-animation-fill-mode:forwards;-moz-animation-duration:.3s;-moz-animation-fill-mode:forwards;animation-duration:.3s;animation-fill-mode:forwards}.fadeOut{-webkit-animation-name:fadeOut;-moz-animation-name:fadeOut;animation-name:fadeOut}.contentZoomIn{-webkit-animation-name:zoomIn;-moz-animation-name:zoomIn;animation-name:zoomIn}.contentZoomIn,.contentZoomOut{-webkit-animation-duration:.2s;-webkit-animation-fill-mode:forwards;-moz-animation-duration:.2s;-moz-animation-fill-mode:forwards;animation-duration:.2s;animation-fill-mode:forwards}.contentZoomOut{-webkit-animation-name:zoomOut;-moz-animation-name:zoomOut;animation-name:zoomOut}@-webkit-keyframes moveUp{0%{-webkit-transform:translateY(30px);opacity:0}100%{-webkit-transform:translateY(0);opacity:1}}@-moz-keyframes moveUp{0%{opacity:0}100%{opacity:1}}@keyframes moveUp{0%{transform:translateY(30px);opacity:0}100%{transform:translateY(0);opacity:1}}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-moz-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-moz-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-webkit-keyframes moveBackground{0%{background-position-x:0}100%{background-position-x:-100px}}@-moz-keyframes moveBackground{0%{background-position-x:0}100%{background-position-x:-100px}}@keyframes moveBackground{0%{background-position-x:0}100%{background-position-x:-100px}}@-webkit-keyframes zoomIn{0%{opacity:0;-webkit-transform:scale(.8)}100%{opacity:1;-webkit-transform:scale(1)}}@-moz-keyframes zoomIn{0%{opacity:0}100%{opacity:1}}@keyframes zoomIn{0%{opacity:0;transform:scale(.8)}100%{opacity:1;transform:scale(1)}}@-webkit-keyframes zoomOut{0%{opacity:1;-webkit-transform:scale(1)}100%{opacity:0;-webkit-transform:scale(.8)}}@-moz-keyframes zoomOut{0%{opacity:1}100%{opacity:0}}@keyframes zoomOut{0%{opacity:1;transform:scale(1)}100%{opacity:0;transform:scale(.8)}}@-webkit-keyframes popIn{0%{opacity:0;-webkit-transform:scale(0)}100%{opacity:1;-webkit-transform:scale(1)}}@-moz-keyframes popIn{0%{opacity:0;-moz-transform:scale(0)}100%{opacity:1;-moz-transform:scale(1)}}@keyframes popIn{0%{opacity:0;transform:scale(0)}100%{opacity:1;transform:scale(1)}}@-webkit-keyframes pulse{0%{opacity:1}50%{opacity:.3}100%{opacity:1}}@-moz-keyframes pulse{0%{opacity:1}50%{opacity:.8}100%{opacity:1}}@keyframes pulse{0%{opacity:1}50%{opacity:.8}100%{opacity:1}}#content::before{content:"";position:absolute;left:0;width:100%;height:20px;background-image:-webkit-linear-gradient(top,#262626,#222);background-image:-moz-linear-gradient(top,#262626,#222);background-image:-ms-linear-gradient(top,#262626,#222);background-image:linear-gradient(top,#262626,#222);border-top:1px solid #333}#content.view::before{display:none}#content{position:absolute;padding:50px 0 33px;width:100%;min-height:calc(100% - 90px);-webkit-overflow-scrolling:touch}.photo{float:left;display:inline-block;width:206px;height:206px;margin:30px 0 0 30px;cursor:pointer}.photo img{position:absolute;width:200px;height:200px;background-color:#222;border-radius:2px;border:2px solid #ccc}.photo:hover img,.photo.active img{box-shadow:0 0 5px #005ecc}.photo:active{-webkit-transition-duration:.1s;-webkit-transform:scale(.98);-moz-transition-duration:.1s;-moz-transform:scale(.98);transition-duration:.1s;transform:scale(.98)}.album{float:left;display:inline-block;width:204px;height:204px;margin:30px 0 0 30px;cursor:pointer}.album img:first-child,.album img:nth-child(2){-webkit-transform:rotate(0)translateY(0)translateX(0);-moz-transform:rotate(0)translateY(0)translateX(0);transform:rotate(0)translateY(0)translateX(0);opacity:0}.album:hover img:first-child{-webkit-transform:rotate(-2deg)translateY(10px)translateX(-12px);-moz-transform:rotate(-2deg)translateY(10px)translateX(-12px);transform:rotate(-2deg)translateY(10px)translateX(-12px);opacity:1}.album:hover img:nth-child(2){-webkit-transform:rotate(5deg)translateY(-8px)translateX(12px);-moz-transform:rotate(5deg)translateY(-8px)translateX(12px);transform:rotate(5deg)translateY(-8px)translateX(12px);opacity:1}.album img{position:absolute;width:200px;height:200px;background-color:#222;border-radius:2px;border:2px solid #ccc}.album:hover img,.album.active img{box-shadow:0 0 5px #005ecc}.album .overlay,.photo .overlay{position:absolute;width:200px;height:200px;margin:2px}.album .overlay{background:-moz-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%);background:-webkit-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%);background:-ms-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%);background:linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%)}.photo .overlay{background:-moz-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)60%,rgba(0,0,0,.5)80%,rgba(0,0,0,.9)100%);background:-webkit-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)60%,rgba(0,0,0,.5)80%,rgba(0,0,0,.9)100%);background:-ms-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)60%,rgba(0,0,0,.5)80%,rgba(0,0,0,.9)100%);background:linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)60%,rgba(0,0,0,.5)80%,rgba(0,0,0,.9)100%);opacity:0}.photo:hover .overlay,.photo.active .overlay{opacity:1}.album .overlay h1,.photo .overlay h1{min-height:19px;width:190px;margin:153px 0 3px 15px;color:#fff;font-size:16px;font-weight:700;overflow:hidden}.album .overlay a,.photo .overlay a{font-size:11px;color:#aaa}.album .overlay a{margin-left:15px}.photo .overlay a{margin:155px 0 5px 15px}.album .badge,.photo .badge{position:absolute;margin-top:-1px;margin-left:12px;padding:12px 7px 3px;box-shadow:0 0 3px #000;border-radius:0 0 3px 3px;border:1px solid #fff;border-top:none;color:#fff;font-size:24px;text-shadow:0 1px 0 #000;opacity:.9}.album .badge.icon-star,.photo .badge.icon-star{padding:12px 8px 3px}.album .badge.icon-share,.photo .badge.icon-share{padding:12px 6px 3px 8px}.album .badge::after,.photo .badge::after{content:"";position:absolute;margin-top:-12px;margin-left:-26px;width:38px;height:5px;background:-moz-linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);background:-webkit-linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);background:-ms-linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);background:linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);opacity:.4}.album .badge.icon-star::after,.photo .badge.icon-star::after{margin-left:-29px}.album .badge.icon-share::after,.photo .badge.icon-share::after{margin-left:-31px}.album .badge.icon-reorder::after{margin-left:-30px}.album .badge:nth-child(2n),.photo .badge:nth-child(2n){margin-left:57px}.album .badge.red,.photo .badge.red{background:#d64b4b;background:-webkit-linear-gradient(top,#d64b4b,#ab2c2c);background:-moz-linear-gradient(top,#d64b4b,#ab2c2c);background:-ms-linear-gradient(top,#d64b4b,#ab2c2c)}.album .badge.blue,.photo .badge.blue{background:#d64b4b;background:-webkit-linear-gradient(top,#347cd6,#2945ab);background:-moz-linear-gradient(top,#347cd6,#2945ab);background:-ms-linear-gradient(top,#347cd6,#2945ab)}.divider{float:left;width:100%;margin-top:50px;opacity:0;border-top:1px solid #2E2E2E;box-shadow:0 -1px 0 #151515}.divider:first-child{margin-top:0;border-top:none}.divider h1{float:left;margin:20px 0 0 30px;color:#fff;font-size:14px;font-weight:700;text-shadow:0 -1px 0 #000}.no_content{position:absolute;top:50%;left:50%;height:160px;width:180px;margin-top:-80px;margin-left:-90px;padding-top:20px;color:rgba(20,20,20,1);text-shadow:0 1px 0 rgba(255,255,255,.05);text-align:center}.no_content .icon{font-size:120px}.no_content p{font-size:18px}.contextmenu_bg{position:fixed;height:100%;width:100%;z-index:1000}.contextmenu{position:fixed;top:0;left:0;padding:5px 0 6px;background-color:#393939;background-image:-webkit-linear-gradient(top,#444,#2d2d2d);background-image:-moz-linear-gradient(top,#393939,#2d2d2d);background-image:-ms-linear-gradient(top,#393939,#2d2d2d);background-image:linear-gradient(top,#393939,#2d2d2d);border:1px solid rgba(0,0,0,.7);border-bottom:1px solid rgba(0,0,0,.9);border-radius:5px;box-shadow:0 4px 5px rgba(0,0,0,.3),inset 0 1px 0 rgba(255,255,255,.15),inset 1px 0 0 rgba(255,255,255,.05),inset -1px 0 0 rgba(255,255,255,.05);opacity:0;z-index:1001;-webkit-transition:none;-moz-transition:none;transition:none}.contextmenu tr{font-size:14px;color:#eee;text-shadow:0 -1px 0 rgba(0,0,0,.6);cursor:pointer}.contextmenu tr:hover{background-color:#6a84f2;background-image:-webkit-linear-gradient(top,#6a84f2,#3959ef);background-image:-moz-linear-gradient(top,#6a84f2,#3959ef);background-image:-ms-linear-gradient(top,#6a84f2,#3959ef);background-image:linear-gradient(top,#6a84f2,#3959ef)}.contextmenu tr.no_hover:hover{cursor:inherit;background-color:inherit;background-image:none}.contextmenu tr.separator{float:left;height:1px;width:100%;background-color:#1c1c1c;border-bottom:1px solid #4a4a4a;margin:5px 0;cursor:inherit}.contextmenu tr.separator:hover{background-color:#222;background-image:none}.contextmenu tr td{padding:7px 30px 6px 12px;white-space:nowrap;-webkit-transition:none;-moz-transition:none;transition:none}.contextmenu tr:hover td{color:#fff;box-shadow:inset 0 1px 0 rgba(255,255,255,.05);text-shadow:0 -1px 0 rgba(0,0,0,.4)}.contextmenu tr.no_hover:hover td{box-shadow:none}.contextmenu tr a{float:left;width:10px;margin-right:10px;text-align:center}.contextmenu #link{float:right;width:140px;margin:0 -17px -1px 0;padding:4px 6px 5px;background-color:#444;color:#fff;border:1px solid #111;box-shadow:0 1px 0 rgba(255,255,255,.1);outline:none;border-radius:5px}.contextmenu tr a#link_icon{padding-top:4px}@font-face{font-family:'FontAwesome';src:url('../../font/fontawesome-webfont.eot');src:url('../../font/fontawesome-webfont.eot?#iefix') format('eot'),url('../../font/fontawesome-webfont.woff') format('woff'),url('../../font/fontawesome-webfont.ttf') format('truetype'),url('../../font/fontawesome-webfont.svg#FontAwesome') format('svg');font-weight:400;font-style:normal}[class^="icon-"]:before,[class*=" icon-"]:before{font-family:FontAwesome;font-weight:400;font-style:normal;display:inline-block;text-decoration:inherit}a [class^="icon-"],a [class*=" icon-"]{display:inline-block;text-decoration:inherit}.icon-large:before{vertical-align:top;font-size:1.3333333333333333em}.btn [class^="icon-"],.btn [class*=" icon-"]{line-height:.9em}li [class^="icon-"],li [class*=" icon-"]{display:inline-block;width:1.25em;text-align:center}li .icon-large[class^="icon-"],li .icon-large[class*=" icon-"]{width:1.875em}li[class^="icon-"],li[class*=" icon-"]{margin-left:0;list-style-type:none}li[class^="icon-"]:before,li[class*=" icon-"]:before{text-indent:-2em;text-align:center}li[class^="icon-"].icon-large:before,li[class*=" icon-"].icon-large:before{text-indent:-1.3333333333333333em}.icon-glass:before{content:"\f000"}.icon-music:before{content:"\f001"}.icon-search:before{content:"\f002"}.icon-envelope:before{content:"\f003"}.icon-heart:before{content:"\f004"}.icon-star:before{content:"\f005"}.icon-star-empty:before{content:"\f006"}.icon-user:before{content:"\f007"}.icon-film:before{content:"\f008"}.icon-th-large:before{content:"\f009"}.icon-th:before{content:"\f00a"}.icon-th-list:before{content:"\f00b"}.icon-ok:before{content:"\f00c"}.icon-remove:before{content:"\f00d"}.icon-zoom-in:before{content:"\f00e"}.icon-zoom-out:before{content:"\f010"}.icon-off:before{content:"\f011"}.icon-signal:before{content:"\f012"}.icon-cog:before{content:"\f013"}.icon-trash:before{content:"\f014"}.icon-home:before{content:"\f015"}.icon-file:before{content:"\f016"}.icon-time:before{content:"\f017"}.icon-road:before{content:"\f018"}.icon-download-alt:before{content:"\f019"}.icon-download:before{content:"\f01a"}.icon-upload:before{content:"\f01b"}.icon-inbox:before{content:"\f01c"}.icon-play-circle:before{content:"\f01d"}.icon-repeat:before{content:"\f01e"}.icon-refresh:before{content:"\f021"}.icon-list-alt:before{content:"\f022"}.icon-lock:before{content:"\f023"}.icon-flag:before{content:"\f024"}.icon-headphones:before{content:"\f025"}.icon-volume-off:before{content:"\f026"}.icon-volume-down:before{content:"\f027"}.icon-volume-up:before{content:"\f028"}.icon-qrcode:before{content:"\f029"}.icon-barcode:before{content:"\f02a"}.icon-tag:before{content:"\f02b"}.icon-tags:before{content:"\f02c"}.icon-book:before{content:"\f02d"}.icon-bookmark:before{content:"\f02e"}.icon-print:before{content:"\f02f"}.icon-camera:before{content:"\f030"}.icon-font:before{content:"\f031"}.icon-bold:before{content:"\f032"}.icon-italic:before{content:"\f033"}.icon-text-height:before{content:"\f034"}.icon-text-width:before{content:"\f035"}.icon-align-left:before{content:"\f036"}.icon-align-center:before{content:"\f037"}.icon-align-right:before{content:"\f038"}.icon-align-justify:before{content:"\f039"}.icon-list:before{content:"\f03a"}.icon-indent-left:before{content:"\f03b"}.icon-indent-right:before{content:"\f03c"}.icon-facetime-video:before{content:"\f03d"}.icon-picture:before{content:"\f03e"}.icon-pencil:before{content:"\f040"}.icon-map-marker:before{content:"\f041"}.icon-adjust:before{content:"\f042"}.icon-tint:before{content:"\f043"}.icon-edit:before{content:"\f044"}.icon-share:before{content:"\f045"}.icon-check:before{content:"\f046"}.icon-move:before{content:"\f047"}.icon-step-backward:before{content:"\f048"}.icon-fast-backward:before{content:"\f049"}.icon-backward:before{content:"\f04a"}.icon-play:before{content:"\f04b"}.icon-pause:before{content:"\f04c"}.icon-stop:before{content:"\f04d"}.icon-forward:before{content:"\f04e"}.icon-fast-forward:before{content:"\f050"}.icon-step-forward:before{content:"\f051"}.icon-eject:before{content:"\f052"}.icon-chevron-left:before{content:"\f053"}.icon-chevron-right:before{content:"\f054"}.icon-plus-sign:before{content:"\f055"}.icon-minus-sign:before{content:"\f056"}.icon-remove-sign:before{content:"\f057"}.icon-ok-sign:before{content:"\f058"}.icon-question-sign:before{content:"\f059"}.icon-info-sign:before{content:"\f05a"}.icon-screenshot:before{content:"\f05b"}.icon-remove-circle:before{content:"\f05c"}.icon-ok-circle:before{content:"\f05d"}.icon-ban-circle:before{content:"\f05e"}.icon-arrow-left:before{content:"\f060"}.icon-arrow-right:before{content:"\f061"}.icon-arrow-up:before{content:"\f062"}.icon-arrow-down:before{content:"\f063"}.icon-share-alt:before{content:"\f064"}.icon-resize-full:before{content:"\f065"}.icon-resize-small:before{content:"\f066"}.icon-plus:before{content:"\f067"}.icon-minus:before{content:"\f068"}.icon-asterisk:before{content:"\f069"}.icon-exclamation-sign:before{content:"\f06a"}.icon-gift:before{content:"\f06b"}.icon-leaf:before{content:"\f06c"}.icon-fire:before{content:"\f06d"}.icon-eye-open:before{content:"\f06e"}.icon-eye-close:before{content:"\f070"}.icon-warning-sign:before{content:"\f071"}.icon-plane:before{content:"\f072"}.icon-calendar:before{content:"\f073"}.icon-random:before{content:"\f074"}.icon-comment:before{content:"\f075"}.icon-magnet:before{content:"\f076"}.icon-chevron-up:before{content:"\f077"}.icon-chevron-down:before{content:"\f078"}.icon-retweet:before{content:"\f079"}.icon-shopping-cart:before{content:"\f07a"}.icon-folder-close:before{content:"\f07b"}.icon-folder-open:before{content:"\f07c"}.icon-resize-vertical:before{content:"\f07d"}.icon-resize-horizontal:before{content:"\f07e"}.icon-bar-chart:before{content:"\f080"}.icon-twitter-sign:before{content:"\f081"}.icon-facebook-sign:before{content:"\f082"}.icon-camera-retro:before{content:"\f083"}.icon-key:before{content:"\f084"}.icon-cogs:before{content:"\f085"}.icon-comments:before{content:"\f086"}.icon-thumbs-up:before{content:"\f087"}.icon-thumbs-down:before{content:"\f088"}.icon-star-half:before{content:"\f089"}.icon-heart-empty:before{content:"\f08a"}.icon-signout:before{content:"\f08b"}.icon-linkedin-sign:before{content:"\f08c"}.icon-pushpin:before{content:"\f08d"}.icon-external-link:before{content:"\f08e"}.icon-signin:before{content:"\f090"}.icon-trophy:before{content:"\f091"}.icon-github-sign:before{content:"\f092"}.icon-upload-alt:before{content:"\f093"}.icon-lemon:before{content:"\f094"}.icon-phone:before{content:"\f095"}.icon-check-empty:before{content:"\f096"}.icon-bookmark-empty:before{content:"\f097"}.icon-phone-sign:before{content:"\f098"}.icon-twitter:before{content:"\f099"}.icon-facebook:before{content:"\f09a"}.icon-github:before{content:"\f09b"}.icon-unlock:before{content:"\f09c"}.icon-credit-card:before{content:"\f09d"}.icon-rss:before{content:"\f09e"}.icon-hdd:before{content:"\f0a0"}.icon-bullhorn:before{content:"\f0a1"}.icon-bell:before{content:"\f0a2"}.icon-certificate:before{content:"\f0a3"}.icon-hand-right:before{content:"\f0a4"}.icon-hand-left:before{content:"\f0a5"}.icon-hand-up:before{content:"\f0a6"}.icon-hand-down:before{content:"\f0a7"}.icon-circle-arrow-left:before{content:"\f0a8"}.icon-circle-arrow-right:before{content:"\f0a9"}.icon-circle-arrow-up:before{content:"\f0aa"}.icon-circle-arrow-down:before{content:"\f0ab"}.icon-globe:before{content:"\f0ac"}.icon-wrench:before{content:"\f0ad"}.icon-tasks:before{content:"\f0ae"}.icon-filter:before{content:"\f0b0"}.icon-briefcase:before{content:"\f0b1"}.icon-fullscreen:before{content:"\f0b2"}.icon-group:before{content:"\f0c0"}.icon-link:before{content:"\f0c1"}.icon-cloud:before{content:"\f0c2"}.icon-beaker:before{content:"\f0c3"}.icon-cut:before{content:"\f0c4"}.icon-copy:before{content:"\f0c5"}.icon-paper-clip:before{content:"\f0c6"}.icon-save:before{content:"\f0c7"}.icon-sign-blank:before{content:"\f0c8"}.icon-reorder:before{content:"\f0c9"}.icon-list-ul:before{content:"\f0ca"}.icon-list-ol:before{content:"\f0cb"}.icon-strikethrough:before{content:"\f0cc"}.icon-underline:before{content:"\f0cd"}.icon-table:before{content:"\f0ce"}.icon-magic:before{content:"\f0d0"}.icon-truck:before{content:"\f0d1"}.icon-pinterest:before{content:"\f0d2"}.icon-pinterest-sign:before{content:"\f0d3"}.icon-google-plus-sign:before{content:"\f0d4"}.icon-google-plus:before{content:"\f0d5"}.icon-money:before{content:"\f0d6"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.icon-columns:before{content:"\f0db"}.icon-sort:before{content:"\f0dc"}.icon-sort-down:before{content:"\f0dd"}.icon-sort-up:before{content:"\f0de"}.icon-envelope-alt:before{content:"\f0e0"}.icon-linkedin:before{content:"\f0e1"}.icon-undo:before{content:"\f0e2"}.icon-legal:before{content:"\f0e3"}.icon-dashboard:before{content:"\f0e4"}.icon-comment-alt:before{content:"\f0e5"}.icon-comments-alt:before{content:"\f0e6"}.icon-bolt:before{content:"\f0e7"}.icon-sitemap:before{content:"\f0e8"}.icon-umbrella:before{content:"\f0e9"}.icon-paste:before{content:"\f0ea"}.icon-user-md:before{content:"\f200"}header{position:fixed;height:49px;width:100%;background-image:-webkit-linear-gradient(top,#3E3E3E,#282828);background-image:-moz-linear-gradient(top,#3E3E3E,#282828);background-image:-ms-linear-gradient(top,#3E3E3E,#282828);background-image:linear-gradient(top,#3E3E3E,#282828);border-bottom:1px solid #161616;z-index:1;-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;transition:transform .3s ease-out}header.hidden{-webkit-transform:translateY(-60px);-moz-transform:translateY(-60px);transform:translateY(-60px)}header.loading{-webkit-transform:translateY(2px);-moz-transform:translateY(2px);transform:translateY(2px)}header.error{-webkit-transform:translateY(40px);-moz-transform:translateY(40px);transform:translateY(40px)}header.view.error{background-color:rgba(10,10,10,.99)}header.view{background-image:none;border-bottom:none}header.view .button,header.view #title,header.view .tools{text-shadow:none!important}header #title{position:absolute;margin:0 30%;width:40%;padding:15px 0;color:#fff;font-size:16px;font-weight:700;text-align:center;text-shadow:0 -1px 0 #222}header #title.editable{cursor:pointer}header .button{color:#888;font-family:'FontAwesome';font-size:21px;font-weight:700;text-decoration:none!important;cursor:pointer;text-shadow:0 -1px 0 #222}header .button.left{float:left;position:absolute;padding:16px 10px 8px 18px}header .button.right{float:right;position:relative;padding:16px 19px 13px 11px}header .button:hover{color:#fff}header #tools_albums,header #tools_album,header #tools_photo,header #button_signin{display:none}header .button_divider{float:right;position:relative;width:14px;height:50px}header #search{float:right;width:80px;margin:12px 12px 0 0;padding:5px 12px 6px;background-color:#383838;color:#fff;border:1px solid #131313;box-shadow:0 1px 0 rgba(255,255,255,.1);outline:none;border-radius:50px;opacity:.6;-webkit-transition:opacity .3s ease-out,-webkit-transform .3s ease-out,box-shadow .3s,width .2s ease-out;-moz-transition:opacity .3s ease-out,-moz-transform .3s ease-out,box-shadow .3s,width .2s ease-out;transition:opacity .3s ease-out,transform .3s ease-out,box-shadow .3s,width .2s ease-out}header #search:focus{width:140px}header #search:focus~#clearSearch{opacity:1}header #clearSearch{position:absolute;top:15px;right:81px;padding:0;font-size:20px;opacity:0;-webkit-transition:opacity .2s ease-out;-moz-transition:opacity .2s ease-out;transition:opacity .2s ease-out}header #clearSearch:hover{opacity:1}header .tools:first-of-type{margin-right:6px}header .tools{float:right;padding:14px 8px;color:#888;font-size:21px;text-shadow:0 -1px 0 #222;cursor:pointer}header .tools:hover a{color:#fff}header .tools .icon-star{color:#f0ef77}header .tools .icon-share.active{color:#ff9737}header #hostedwith{float:right;padding:5px 10px;margin:13px 9px;color:#888;font-size:13px;text-shadow:0 -1px 0 #222;display:none;cursor:pointer}header #hostedwith:hover{background-color:rgba(0,0,0,.2);border-radius:100px}#imageview{position:fixed;display:none;width:100%;min-height:100%;background-color:rgba(10,10,10,.99);-webkit-transition:background-color .3s}#imageview.view{background-color:inherit}#imageview.full{background-color:#040404}#imageview #image{position:absolute;top:60px;right:30px;bottom:30px;left:30px;background-repeat:no-repeat;background-position:50% 50%;background-size:contain;-webkit-transition:top .3s,bottom .3s,margin-top .3s;-webkit-animation-name:zoomIn;-webkit-animation-duration:.3s;-moz-animation-name:zoomIn;-moz-animation-duration:.3s;animation-name:zoomIn;animation-duration:.3s}#imageview #image.small{top:50%;right:auto;bottom:auto;left:50%}#imageview .arrow_wrapper{position:fixed;width:20%;height:calc(100% - 60px);top:60px;z-index:1}#imageview .arrow_wrapper.previous{left:0}#imageview .arrow_wrapper.next{right:0}#imageview .arrow_wrapper a{position:fixed;top:50%;margin-top:-10px;color:#fff;font-size:50px;text-shadow:0 1px 2px #000;cursor:pointer;opacity:0;z-index:2;-webkit-transition:opacity .2s;-moz-transition:opacity .2s;transition:opacity .2s}#imageview .arrow_wrapper:hover a{opacity:.2}#imageview .arrow_wrapper a#previous{left:20px}#imageview .arrow_wrapper a#next{right:20px}#infobox_overlay{z-index:3;position:fixed;width:100%;height:100%;top:0;left:0;background-color:rgba(0,0,0,.85)}#infobox{z-index:4;position:fixed;right:0;width:300px;height:100%;background-color:rgba(20,20,20,.98);box-shadow:-1px 0 2px rgba(0,0,0,.8);display:none;-webkit-transform:translateX(320px);-moz-transform:translateX(320px);transform:translateX(320px);-webkit-transition:-webkit-transform .5s cubic-bezier(.225,.5,.165,1);-moz-transition:-moz-transform .5s cubic-bezier(.225,.5,.165,1);transition:transform .5s cubic-bezier(.225,.5,.165,1)}#infobox.active{-webkit-transform:translateX(0);-moz-transform:translateX(0);transform:translateX(0)}#infobox .wrapper{float:left;height:100%;overflow:scroll}#infobox .edit{display:inline;margin-left:3px;width:20px;height:5px;cursor:pointer}#infobox .bumper{float:left;width:100%;height:50px}#infobox .header{float:left;height:49px;width:100%;background-color:#1d1d1d;background-image:-webkit-linear-gradient(top,#2A2A2A,#131313);background-image:-moz-linear-gradient(top,#2A2A2A,#131313);background-image:-ms-linear-gradient(top,#2A2A2A,#131313);background-image:linear-gradient(top,#2A2A2A,#131313);border-bottom:1px solid #000}#infobox .header h1{position:absolute;margin:15px 30%;width:40%;font-size:16px;text-align:center}#infobox .header h1,#infobox .header a{color:#fff;font-weight:700;text-shadow:0 -1px 0 #000}#infobox .header a{float:right;padding:15px;font-size:20px;opacity:.5;cursor:pointer}#infobox .header a:hover{opacity:1}#infobox .separator{float:left;width:100%;border-top:1px solid rgba(255,255,255,.04);box-shadow:0 -1px 0 #000}#infobox .separator h1{margin:20px 0 5px 20px;color:#fff;font-size:14px;font-weight:700;text-shadow:0 -1px 0 #000}#infobox table{float:left;margin:10px 0 15px 20px}#infobox table tr td{padding:5px 0;color:#fff;font-size:14px;line-height:19px;-webkit-user-select:text;-moz-user-select:text;user-select:text}#infobox table tr td:first-child{width:110px}#infobox table tr td:last-child{padding-right:10px}#infobox #tags{width:calc(100% - 40px);margin:16px 20px 12px;color:#fff;display:inline-block}#infobox #tags .empty{font-size:14px;margin-bottom:8px}#infobox #tags .edit{display:inline-block}#infobox #tags .empty .edit{display:inline}#infobox .tag{float:left;padding:4px 7px;margin:0 6px 8px 0;background-color:rgba(0,0,0,.5);border:2px solid rgba(255,255,255,.3);border-radius:100px;font-size:12px;-webkit-transition:border .3s;-moz-transition:border .3s;transition:border .3s}#infobox .tag:hover{border:2px solid #aaa}#infobox .tag span{float:right;width:0;padding:0;margin:0 0 -2px;color:red;font-size:11px;cursor:pointer;overflow:hidden;-webkit-transform:scale(0);transform:scale(0);-webkit-transition:width .3s,margin .3s,-webkit-transform .3s;-moz-transition:width .3s,margin .3s;transition:width .3s,margin .3s,transform .3s}#infobox .tag:hover span{width:10px;margin:0 0 -2px 6px;-webkit-transform:scale(1);transform:scale(1)}#loading{position:fixed;width:100%;height:3px;background-size:100px 3px;background-repeat:repeat-x;border-bottom:1px solid rgba(0,0,0,.3);display:none;-webkit-animation-name:moveBackground;-webkit-animation-duration:.3s;-webkit-animation-iteration-count:infinite;-webkit-animation-timing-function:linear;-moz-animation-name:moveBackground;-moz-animation-duration:.3s;-moz-animation-iteration-count:infinite;-moz-animation-timing-function:linear;animation-name:moveBackground;animation-duration:.3s;animation-iteration-count:infinite;animation-timing-function:linear}#loading.loading{background-image:-webkit-linear-gradient(left,#153674 0%,#153674 47%,#2651AE 53%,#2651AE 100%);background-image:-moz-linear-gradient(left,#153674 0%,#153674 47%,#2651AE 53%,#2651AE 100%);background-image:linear-gradient(left right,#153674 0%,#153674 47%,#2651AE 53%,#2651AE 100%);z-index:2}#loading.error{background-color:#2f0d0e;background-image:-webkit-linear-gradient(left,#451317 0%,#451317 47%,#AA3039 53%,#AA3039 100%);background-image:-moz-linear-gradient(left,#451317 0%,#451317 47%,#AA3039 53%,#AA3039 100%);background-image:linear-gradient(left right,#451317 0%,#451317 47%,#AA3039 53%,#AA3039 100%);z-index:1}#loading h1{margin:13px;color:#ddd;font-size:14px;font-weight:700;text-shadow:0 1px 0 #000;text-transform:capitalize}#loading h1 span{margin-left:10px;font-weight:400;text-transform:none}@media only screen and (max-width:900px){#title{width:40%!important}#title,#title.view{margin:0 20%!important}#title.view{width:60%!important}#title span{display:none!important}}@media only screen and (max-width:640px){#title{display:none!important}#title.view{display:block!important;width:70%!important;margin:0 20% 0 10%!important}#button_move,#button_archive{display:none!important}.center{top:0!important;left:0!important}.album,.photo{margin:40px 0 0 50px!important}.message{position:fixed!important;width:100%!important;height:100%!important;margin:1px 0 0!important;border-radius:0!important;-webkit-animation:moveUp .3s!important;-moz-animation:moveUp .3s!important;animation:moveUp .3s!important}.upload_message{top:50%!important;left:50%!important}}.message_overlay{position:fixed;width:100%;height:100%;top:0;left:0;background-color:rgba(0,0,0,.85);z-index:1000}.message{position:absolute;display:inline-block;width:500px;margin-left:-250px;margin-top:-95px;background-color:#444;background-image:-webkit-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-moz-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-ms-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:linear-gradient(top,#4b4b4b ,#2d2d2d);border-radius:5px;box-shadow:0 0 5px #000,inset 0 1px 0 rgba(255,255,255,.08),inset 1px 0 0 rgba(255,255,255,.03),inset -1px 0 0 rgba(255,255,255,.03);-webkit-animation-name:moveUp;-webkit-animation-duration:.3s;-webkit-animation-timing-function:ease-out;-moz-animation-name:moveUp;-moz-animation-duration:.3s;-moz-animation-timing-function:ease-out;animation-name:moveUp;animation-duration:.3s;animation-timing-function:ease-out}.message h1{float:left;width:100%;padding:12px 0;color:#fff;font-size:16px;font-weight:700;text-shadow:0 -1px 0 #222;text-align:center}.message .close{position:absolute;top:0;right:0;padding:12px 14px 6px 7px;color:#aaa;font-size:20px;text-shadow:0 -1px 0 #222;cursor:pointer}.message .close:hover{color:#fff}.message p{float:left;width:90%;margin-top:1px;padding:12px 5% 15px;color:#eee;font-size:14px;text-shadow:0 -1px 0 #222;line-height:20px}.message p b{font-weight:700}.message p a{color:#eee;text-decoration:none;border-bottom:1px dashed #888}.message .button{float:right;margin:15px 15px 15px 0;padding:6px 10px 8px;background-color:#4e4e4e;background-image:-webkit-linear-gradient(top,#3c3c3c ,#2d2d2d);background-image:-moz-linear-gradient(top,#3c3c3c ,#2d2d2d);background-image:-ms-linear-gradient(top,#3c3c3c ,#2d2d2d);background-image:linear-gradient(top,#3c3c3c ,#2d2d2d);color:#ccc;font-size:14px;font-weight:700;text-align:center;text-shadow:0 -1px 0 #222;border-radius:5px;border:1px solid #191919;box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);cursor:pointer}.message .button:first-of-type{margin:15px 5% 18px 0!important}.message .button.active{color:#fff;box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1),0 0 4px #005ecc}.message .button:hover{background-color:#565757;background-image:-webkit-linear-gradient(top,#505050 ,#393939);background-image:-moz-linear-gradient(top,#505050 ,#393939);background-image:-ms-linear-gradient(top,#505050 ,#393939);background-image:linear-gradient(top,#505050 ,#393939)}.message .button:active,.message .button.pressed{background-color:#393939;background-image:-webkit-linear-gradient(top,#393939 ,#464646);background-image:-moz-linear-gradient(top,#393939 ,#464646);background-image:-ms-linear-gradient(top,#393939 ,#464646);background-image:linear-gradient(top,#393939 ,#464646)}.sign_in{width:100%;margin-top:1px;padding:5px 0;color:#eee;font-size:14px;line-height:20px}.sign_in,.sign_in input{float:left;text-shadow:0 -1px 0 #222}.sign_in input{width:88%;padding:7px 1% 9px;margin:0 5%;background-color:transparent;color:#fff;border:none;border-bottom:1px solid #222;box-shadow:0 1px 0 rgba(255,255,255,.1);border-radius:0;outline:none}.sign_in input:first-of-type{margin-bottom:10px}.sign_in input.error:focus{box-shadow:0 1px 0 rgba(204,0,7,.6)}.message #version{display:inline-block;margin-top:23px;margin-left:5%;color:#888;text-shadow:0 -1px 0 #111}.message #version span{display:none}.message #version span a{color:#888}.message input.text{float:left;width:calc(100% - 10px);padding:17px 5px 9px;margin-top:10px;background-color:transparent;color:#fff;text-shadow:0 -1px 0 #222;border:none;box-shadow:0 1px 0 rgba(255,255,255,.1);border-bottom:1px solid #222;border-radius:0;outline:none}.message input.less{margin-bottom:-10px}.message input.more{margin-bottom:30px}.message .copylink{margin-bottom:20px}html,body{min-height:100%}body{background-color:#222;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:12px;-webkit-font-smoothing:antialiased;-moz-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-smoothing:antialiased}body.view{background-color:#0f0f0f}.center{position:absolute;left:50%;top:50%}*{-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-transition:color .3s,opacity .3s ease-out,-webkit-transform .3s ease-out,box-shadow .3s;-moz-transition:opacity .3s ease-out,-moz-transform .3s ease-out,box-shadow .3s;transition:color .3s,opacity .3s ease-out,transform .3s ease-out,box-shadow .3s}input{-webkit-user-select:text!important;-moz-user-select:text!important;user-select:text!important}#multiselect{position:absolute;background-color:rgba(0,94,204,.3);border:1px solid rgba(0,94,204,1);border-radius:3px;z-index:3}.tipsy{padding:4px;font-size:12px;position:absolute;z-index:100000;-webkit-animation-name:fadeIn;-webkit-animation-duration:.3s;-moz-animation-name:fadeIn;-moz-animation-duration:.3s;animation-name:fadeIn;animation-duration:.3s}.tipsy-inner{padding:8px 10px 7px;color:#fff;max-width:200px;text-align:center;background:rgba(0,0,0,.8);border-radius:25px}.tipsy-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed rgba(0,0,0,.8)}.tipsy-arrow-n{border-bottom-color:rgba(0,0,0,.8)}.tipsy-arrow-s{border-top-color:rgba(0,0,0,.8)}.tipsy-arrow-e{border-left-color:rgba(0,0,0,.8)}.tipsy-arrow-w{border-right-color:rgba(0,0,0,.8)}.tipsy-n .tipsy-arrow{left:50%;margin-left:-5px}.tipsy-n .tipsy-arrow,.tipsy-nw .tipsy-arrow{top:0;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.tipsy-nw .tipsy-arrow{left:10px}.tipsy-ne .tipsy-arrow{top:0;right:10px;border-bottom-style:solid;border-top:none}.tipsy-ne .tipsy-arrow,.tipsy-s .tipsy-arrow{border-left-color:transparent;border-right-color:transparent}.tipsy-s .tipsy-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:none}.tipsy-sw .tipsy-arrow{left:10px}.tipsy-sw .tipsy-arrow,.tipsy-se .tipsy-arrow{bottom:0;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.tipsy-se .tipsy-arrow{right:10px}.tipsy-e .tipsy-arrow{right:0;border-left-style:solid;border-right:none}.tipsy-e .tipsy-arrow,.tipsy-w .tipsy-arrow{top:50%;margin-top:-5px;border-top-color:transparent;border-bottom-color:transparent}.tipsy-w .tipsy-arrow{left:0;border-right-style:solid;border-left:none}#upload{display:none}.upload_overlay{position:fixed;width:100%;height:100%;top:0;left:0;background-color:rgba(0,0,0,.85);z-index:1000}.upload_message{position:absolute;display:inline-block;width:200px;margin-left:-100px;margin-top:-85px;background-color:#444;background-image:-webkit-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-moz-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-ms-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:linear-gradient(top,#4b4b4b ,#2d2d2d);border-radius:5px;box-shadow:0 0 5px #000,inset 0 1px 0 rgba(255,255,255,.08),inset 1px 0 0 rgba(255,255,255,.03),inset -1px 0 0 rgba(255,255,255,.03);-webkit-animation-name:moveUp;-webkit-animation-duration:.3s;-webkit-animation-timing-function:ease-out;-moz-animation-name:moveUp;-moz-animation-duration:.3s;-moz-animation-timing-function:ease-out;animation-name:moveUp;animation-duration:.3s;animation-timing-function:ease-out}.upload_message a{margin:35px 0 5px;font-size:70px;text-shadow:0 1px 2px rgba(0,0,0,.5);-webkit-animation-name:pulse;-webkit-animation-duration:2s;-webkit-animation-timing-function:ease-in-out;-webkit-animation-iteration-count:infinite;-moz-animation-name:pulse;-moz-animation-duration:2s;-moz-animation-timing-function:ease-in-out;-moz-animation-iteration-count:infinite;animation-name:pulse;animation-duration:2s;animation-timing-function:ease-in-out;animation-iteration-count:infinite}.upload_message a,.upload_message p{float:left;width:100%;color:#fff;text-align:center}.upload_message p{margin:10px 0 35px;font-size:14px;text-shadow:0 -1px 0 rgba(0,0,0,.5)}.upload_message .progressbar{float:left;width:170px;height:25px;margin:15px;background-size:50px 25px;background-repeat:repeat-x;background-image:-webkit-linear-gradient(left,#191919 0%,#191919 47%,#1D1D1D 53%,#1D1D1D 100%);background-image:-moz-linear-gradient(left,#191919 0%,#191919 47%,#1D1D1D 53%,#1D1D1D 100%);background-image:linear-gradient(left right,#191919 0%,#191919 47%,#1D1D1D 53%,#1D1D1D 100%);border:1px solid #090909;box-shadow:0 1px 0 rgba(255,255,255,.06),inset 0 0 2px #222;border-radius:50px;-webkit-animation-name:moveBackground;-webkit-animation-duration:1s;-webkit-animation-timing-function:linear;-webkit-animation-iteration-count:infinite;-moz-animation-name:moveBackground;-moz-animation-duration:1s;-moz-animation-timing-function:linear;-moz-animation-iteration-count:infinite;animation-name:moveBackground;animation-duration:1s;animation-timing-function:linear;animation-iteration-count:infinite}.upload_message .progressbar div{float:left;width:0%;height:100%;box-shadow:0 1px 0 #000,1px 0 2px #000;background-color:#f5f2f7;background-image:-webkit-linear-gradient(top,#f5f2f7,#c7c6c8);background-image:-moz-linear-gradient(top,#f5f2f7,#c7c6c8);background-image:-ms-linear-gradient(top,#f5f2f7,#c7c6c8);background-image:linear-gradient(top,#f5f2f7,#c7c6c8);border-radius:50px;-webkit-transition:width .2s,opacity .5;-moz-transition:width .2s,opacity .5;transition:width .2s,opacity .5} \ No newline at end of file diff --git a/assets/css/modules/misc.css b/assets/css/misc.css similarity index 100% rename from assets/css/modules/misc.css rename to assets/css/misc.css diff --git a/assets/css/modules/multiselect.css b/assets/css/multiselect.css similarity index 100% rename from assets/css/modules/multiselect.css rename to assets/css/multiselect.css diff --git a/assets/css/modules/tooltip.css b/assets/css/tooltip.css similarity index 100% rename from assets/css/modules/tooltip.css rename to assets/css/tooltip.css diff --git a/assets/css/modules/upload.css b/assets/css/upload.css similarity index 100% rename from assets/css/modules/upload.css rename to assets/css/upload.css diff --git a/assets/js/min/frameworks.js b/assets/js/_frameworks.js similarity index 100% rename from assets/js/min/frameworks.js rename to assets/js/_frameworks.js diff --git a/assets/js/modules/album.js b/assets/js/album.js similarity index 100% rename from assets/js/modules/album.js rename to assets/js/album.js diff --git a/assets/js/modules/albums.js b/assets/js/albums.js similarity index 100% rename from assets/js/modules/albums.js rename to assets/js/albums.js diff --git a/assets/js/modules/build.js b/assets/js/build.js similarity index 100% rename from assets/js/modules/build.js rename to assets/js/build.js diff --git a/assets/js/modules/contextMenu.js b/assets/js/contextMenu.js similarity index 100% rename from assets/js/modules/contextMenu.js rename to assets/js/contextMenu.js diff --git a/assets/js/modules/init.js b/assets/js/init.js similarity index 100% rename from assets/js/modules/init.js rename to assets/js/init.js diff --git a/assets/js/modules/loadingBar.js b/assets/js/loadingBar.js similarity index 100% rename from assets/js/modules/loadingBar.js rename to assets/js/loadingBar.js diff --git a/assets/js/modules/lychee.js b/assets/js/lychee.js similarity index 100% rename from assets/js/modules/lychee.js rename to assets/js/lychee.js diff --git a/assets/js/min/main.js b/assets/js/min/main.js deleted file mode 100755 index fcabcab..0000000 --- a/assets/js/min/main.js +++ /dev/null @@ -1,3 +0,0 @@ -album={json:null,getID:function(){var id;if(photo.json)id=photo.json.album;else if(album.json)id=album.json.id;else id=$(".album:hover, .album.active").attr("data-id");if(!id)id=$(".photo:hover, .photo.active").attr("data-album-id");if(id)return id;else return false},load:function(albumID,refresh){var startTime,params,durationTime,waitTime;password.get(albumID,function(){if(!refresh){loadingBar.show();lychee.animate(".album, .photo","contentZoomOut");lychee.animate(".divider","fadeOut")}startTime=(new Date).getTime();params="getAlbum&albumID="+albumID+"&password="+password.value;lychee.api(params,function(data){if(data==="Warning: Album private!"){if(document.location.hash.replace("#","").split("/")[1]!=undefined){lychee.setMode("view")}else{lychee.content.show();lychee.goto("")}return false}if(data==="Warning: Wrong password!"){album.load(albumID,refresh);return false}album.json=data;durationTime=(new Date).getTime()-startTime;if(durationTime>300)waitTime=0;else if(refresh)waitTime=0;else waitTime=300-durationTime;if(!visible.albums()&&!visible.photo()&&!visible.album())waitTime=0;setTimeout(function(){view.album.init();if(!refresh){lychee.animate(".album, .photo","contentZoomIn");view.header.mode("album")}},waitTime)})})},parse:function(photo){if(photo&&photo.thumbUrl)photo.thumbUrl=lychee.upload_path_thumb+photo.thumbUrl;else if(!album.json.title)album.json.title="Untitled"},add:function(){var title,params,buttons;buttons=[["Create Album",function(){title=$(".message input.text").val();if(title.length===0)title="Untitled";modal.close();params="addAlbum&title="+escape(encodeURI(title));lychee.api(params,function(data){if(data!==false){if(data===true)data=1;lychee.goto(data)}else lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("New Album","Enter a title for this album: ",buttons)},"delete":function(albumIDs){var params,buttons,albumTitle;if(!albumIDs)return false;if(albumIDs instanceof Array===false)albumIDs=[albumIDs];buttons=[["",function(){params="deleteAlbum&albumIDs="+albumIDs;lychee.api(params,function(data){if(visible.albums()){albumIDs.forEach(function(id,index,array){albums.json.num--;view.albums.content.delete(id)})}else lychee.goto("");if(data!==true)lychee.error(null,params,data)})}],["",function(){}]];if(albumIDs==="0"){buttons[0][0]="Clear Unsorted";buttons[1][0]="Keep Unsorted";modal.show("Clear Unsorted","Are you sure you want to delete all photos from 'Unsorted'?
This action can't be undone!",buttons)}else if(albumIDs.length===1){buttons[0][0]="Delete Album and Photos";buttons[1][0]="Keep Album";if(album.json)albumTitle=album.json.title;else if(albums.json)albumTitle=albums.json.content[albumIDs].title;modal.show("Delete Album","Are you sure you want to delete the album '"+albumTitle+"' and all of the photos it contains? This action can't be undone!",buttons)}else{buttons[0][0]="Delete Albums and Photos";buttons[1][0]="Keep Albums";modal.show("Delete Albums","Are you sure you want to delete all "+albumIDs.length+" selected albums and all of the photos they contain? This action can't be undone!",buttons)}},setTitle:function(albumIDs){var oldTitle="",newTitle,params,buttons;if(!albumIDs)return false;if(albumIDs instanceof Array===false)albumIDs=[albumIDs];if(albumIDs.length===1){if(album.json)oldTitle=album.json.title;else if(albums.json)oldTitle=albums.json.content[albumIDs].title}buttons=[["Set Title",function(){newTitle=$(".message input.text").val()===""?"Untitled":$(".message input.text").val();if(visible.album()){album.json.title=newTitle;view.album.title()}else if(visible.albums()){albumIDs.forEach(function(id,index,array){albums.json.content[id].title=newTitle;view.albums.content.title(id)})}params="setAlbumTitle&albumIDs="+albumIDs+"&title="+escape(encodeURI(newTitle));lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];if(albumIDs.length===1)modal.show("Set Title","Enter a new title for this album: ",buttons);else modal.show("Set Titles","Enter a title for all "+albumIDs.length+" selected album: ",buttons)},setDescription:function(photoID){var oldDescription=album.json.description,description,params,buttons;buttons=[["Set Description",function(){description=$(".message input.text").val();if(visible.album()){album.json.description=description;view.album.description()}params="setAlbumDescription&albumID="+photoID+"&description="+escape(description);lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("Set Description","Please enter a description for this album: ",buttons)},setPublic:function(albumID,e){var params;if($(".message input.text").length>0&&$(".message input.text").val().length>0){params="setAlbumPublic&albumID="+albumID+"&password="+hex_md5($(".message input.text").val());album.json.password=true}else{params="setAlbumPublic&albumID="+albumID;album.json.password=false}if(visible.album()){album.json.public=album.json.public==0?1:0;view.album.public();view.album.password();if(album.json.public==1)contextMenu.shareAlbum(albumID,e)}lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})},share:function(service){var link="",url=location.href;switch(service){case 0:link="https://twitter.com/share?url="+encodeURI(url);break;case 1:link="http://www.facebook.com/sharer.php?u="+encodeURI(url)+"&t="+encodeURI(album.json.title);break;case 2:link="mailto:?subject="+encodeURI(album.json.title)+"&body="+encodeURI("Hi! Check this out: "+url);break;default:link="";break}if(link.length>5)location.href=link},getArchive:function(albumID){var link;if(location.href.indexOf("index.html")>0)link=location.href.replace(location.hash,"").replace("index.html","php/api.php?function=getAlbumArchive&albumID="+albumID);else link=location.href.replace(location.hash,"")+"php/api.php?function=getAlbumArchive&albumID="+albumID;if(lychee.publicMode)link+="&password="+password.value;location.href=link}};albums={json:null,load:function(){var startTime,durationTime,waitTime;lychee.animate(".album, .photo","contentZoomOut");lychee.animate(".divider","fadeOut");startTime=(new Date).getTime();lychee.api("getAlbums",function(data){data.unsortedAlbum={id:0,title:"Unsorted",sysdate:data.unsortedNum+" photos",unsorted:1,thumb0:data.unsortedThumb0,thumb1:data.unsortedThumb1,thumb2:data.unsortedThumb2};data.starredAlbum={id:"f",title:"Starred",sysdate:data.starredNum+" photos",star:1,thumb0:data.starredThumb0,thumb1:data.starredThumb1,thumb2:data.starredThumb2};data.publicAlbum={id:"s",title:"Public",sysdate:data.publicNum+" photos","public":1,thumb0:data.publicThumb0,thumb1:data.publicThumb1,thumb2:data.publicThumb2};albums.json=data;durationTime=(new Date).getTime()-startTime;if(durationTime>300)waitTime=0;else waitTime=300-durationTime;if(!visible.albums()&&!visible.photo()&&!visible.album())waitTime=0;setTimeout(function(){view.header.mode("albums");view.albums.init();lychee.animate(".album, .photo","contentZoomIn")},waitTime)})},parse:function(album){if(album.password&&lychee.publicMode){album.thumb0="assets/img/password.svg";album.thumb1="assets/img/password.svg";album.thumb2="assets/img/password.svg"}else{if(album.thumb0)album.thumb0=lychee.upload_path_thumb+album.thumb0;else album.thumb0="assets/img/no_images.svg";if(album.thumb1)album.thumb1=lychee.upload_path_thumb+album.thumb1;else album.thumb1="assets/img/no_images.svg";if(album.thumb2)album.thumb2=lychee.upload_path_thumb+album.thumb2;else album.thumb2="assets/img/no_images.svg"}}};build={divider:function(title){return"

"+title+"

"},editIcon:function(id){return"
"},multiselect:function(top,left){return"
"},album:function(albumJSON){if(!albumJSON)return"";var album="",longTitle="",title=albumJSON.title;if(title.length>18){title=albumJSON.title.substr(0,18)+"...";longTitle=albumJSON.title}typeThumb0=albumJSON.thumb0.split(".").pop();typeThumb1=albumJSON.thumb1.split(".").pop();typeThumb2=albumJSON.thumb2.split(".").pop();album+="
";album+="thumb";album+="thumb";album+="thumb";album+="
";if(albumJSON.password&&!lychee.publicMode)album+="

"+title+"

";else album+="

"+title+"

";album+=""+albumJSON.sysdate+"";album+="
";if(!lychee.publicMode&&albumJSON.star==1)album+="";if(!lychee.publicMode&&albumJSON.public==1)album+="";if(!lychee.publicMode&&albumJSON.unsorted==1)album+="";album+="
";return album},photo:function(photoJSON){if(!photoJSON)return"";var photo="",longTitle="",title=photoJSON.title;if(title.length>18){title=photoJSON.title.substr(0,18)+"...";longTitle=photoJSON.title}photo+="
";photo+="thumb";photo+="
";photo+="

"+title+"

";photo+=""+photoJSON.sysdate+"";photo+="
";if(photoJSON.star==1)photo+="";if(!lychee.publicMode&&photoJSON.public==1&&album.json.public!=1)photo+="";photo+="
";return photo},imageview:function(photoJSON,isSmall,visibleControls){if(!photoJSON)return"";var view="";view+="";view+="";if(isSmall){if(visibleControls)view+="
";else view+="
"}else{if(visibleControls)view+="
";else view+="
"}return view},no_content:function(typ){var no_content="";no_content+="
";no_content+="";if(typ==="search")no_content+="

No results

";else if(typ==="picture")no_content+="

No public albums

";else if(typ==="cog")no_content+="

No Configuration!

";no_content+="
";return no_content},modal:function(title,text,button,marginTop,closeButton){var modal="",custom_style="";if(marginTop)custom_style="style='margin-top: "+marginTop+"px;'";modal+="
";modal+="
";modal+="

"+title+"

";if(closeButton!=false){modal+=""}modal+="

"+text+"

";$.each(button,function(index){if(this[0]!=""){if(index===0)modal+=""+this[0]+"";else modal+=""+this[0]+""}});modal+="
";modal+="
";return modal},signInModal:function(){var modal="";modal+="
";modal+="
";modal+="

Sign In

";modal+="";modal+="";modal+="
Version "+lychee.version+"Update available!
";modal+="Sign in";modal+="
";modal+="
";return modal},uploadModal:function(icon,text){var modal="";modal+="
";modal+="
";modal+="";if(text!==undefined)modal+="

"+text+"

";else modal+="
";modal+="
";modal+="
";return modal},contextMenu:function(items){var menu="";menu+="
";menu+="
";menu+="";menu+="";$.each(items,function(index){if(items[index][0]==="separator"&&items[index][1]===-1)menu+="";else if(items[index][1]===-1)menu+="";else if(items[index][2]!=undefined)menu+="";else menu+=""});menu+="";menu+="
"+items[index][0]+"
"+items[index][0]+"
"+items[index][0]+"
";menu+="
";return menu},tags:function(tags,forView){var html="",editTagsHTML=forView===true||lychee.publicMode?"":" "+build.editIcon("edit_tags");if(tags!==""){tags=tags.split(",");tags.forEach(function(tag,index,array){html+=""+tag+""});html+=editTagsHTML}else{html="
No Tags"+editTagsHTML+"
"}return html},infoboxPhoto:function(photoJSON,forView){if(!photoJSON)return"";var infobox="",public,editTitleHTML,editDescriptionHTML,infos;infobox+="

About

";infobox+="
";switch(photoJSON.public){case"0":public="Private";break;case"1":public="Public";break;case"2":public="Public (Album)";break;default:public="-";break}editTitleHTML=forView===true||lychee.publicMode?"":" "+build.editIcon("edit_title");editDescriptionHTML=forView===true||lychee.publicMode?"":" "+build.editIcon("edit_description");infos=[["","Basics"],["Name",photoJSON.title+editTitleHTML],["Uploaded",photoJSON.sysdate],["Description",photoJSON.description+editDescriptionHTML],["","Image"],["Size",photoJSON.size],["Format",photoJSON.type],["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!=""){infos=infos.concat([["","Camera"],["Captured",photoJSON.takedate],["Make",photoJSON.make],["Type/Model",photoJSON.model],["Shutter Speed",photoJSON.shutter],["Aperture",photoJSON.aperture],["Focal Length",photoJSON.focal],["ISO",photoJSON.iso]])}infos=infos.concat([["","Share"],["Visibility",public]]);$.each(infos,function(index){if(infos[index][1]===""||infos[index][1]==undefined||infos[index][1]==null)infos[index][1]="-";switch(infos[index][0]){case"":infobox+="";infobox+="

"+infos[index][1]+"

";infobox+="";break;case"Tags":if(forView!==true&&!lychee.publicMode){infobox+="
";infobox+="

"+infos[index][0]+"

";infobox+="
"+infos[index][1]+"
"}break;default:infobox+="";infobox+=""+infos[index][0]+"";infobox+=""+infos[index][1]+"";infobox+="";break}});infobox+="";infobox+="
";infobox+="
";return infobox},infoboxAlbum:function(albumJSON,forView){if(!albumJSON)return"";var infobox="",public,password,editTitleHTML,editDescriptionHTML,infos;infobox+="

About

";infobox+="
";switch(albumJSON.public){case"0":public="Private";break;case"1":public="Public";break;default:public="-";break}switch(albumJSON.password){case false:password="No";break;case true:password="Yes";break;default:password="-";break}editTitleHTML=forView===true||lychee.publicMode?"":" "+build.editIcon("edit_title_album");editDescriptionHTML=forView===true||lychee.publicMode?"":" "+build.editIcon("edit_description_album");infos=[["","Basics"],["Name",albumJSON.title+editTitleHTML],["Description",albumJSON.description+editDescriptionHTML],["","Album"],["Created",albumJSON.sysdate],["Images",albumJSON.num],["","Share"],["Visibility",public],["Password",password]];$.each(infos,function(index){if(infos[index][1]===""||infos[index][1]==undefined||infos[index][1]==null)infos[index][1]="-";if(infos[index][0]===""){infobox+="";infobox+="

"+infos[index][1]+"

";infobox+=""}else{infobox+="";infobox+="";infobox+="";infobox+=""}});infobox+="
"+infos[index][0]+""+infos[index][1]+"
";infobox+="
";infobox+="
";return infobox}};contextMenu={fns:null,show:function(items,mouse_x,mouse_y,orientation){contextMenu.close();$("body").css("overflow","hidden").append(build.contextMenu(items));if(mouse_x+$(".contextmenu").outerWidth(true)>$("html").width())orientation="left";if(mouse_y+$(".contextmenu").outerHeight(true)>$("html").height())mouse_y-=mouse_y+$(".contextmenu").outerHeight(true)-$("html").height();if(mouse_x>$(document).width())mouse_x=$(document).width();if(mouse_x<0)mouse_x=0;if(mouse_y>$(document).height())mouse_y=$(document).height();if(mouse_y<0)mouse_y=0;if(orientation==="left")mouse_x-=$(".contextmenu").outerWidth(true);if(mouse_x===null||mouse_x===undefined||mouse_x===NaN||mouse_y===null||mouse_y===undefined||mouse_y===NaN){mouse_x="10px";mouse_y="10px"}$(".contextmenu").css({top:mouse_y,left:mouse_x,opacity:.98})},add:function(e){var mouse_x=e.pageX,mouse_y=e.pageY-$(document).scrollTop(),items;upload.notify();contextMenu.fns=[function(){$("#upload_files").click()},function(){upload.start.url()},function(){upload.start.dropbox()},function(){upload.start.server()},function(){album.add()}];items=[[" Upload Photo",0],["separator",-1],[" Import from Link",1],[" Import from Dropbox",2],[" Import from Server",3],["separator",-1],[" New Album",4]];contextMenu.show(items,mouse_x,mouse_y,"left")},settings:function(e){var mouse_x=e.pageX,mouse_y=e.pageY-$(document).scrollTop(),items;contextMenu.fns=[function(){settings.setLogin()},function(){settings.setSorting()},function(){window.open(lychee.website,"_newtab")},function(){window.open(lychee.website_donate,"_newtab")},function(){lychee.logout()}];items=[[" Change Login",0],[" Change Sorting",1],[" About Lychee",2],[" Donate",3],["separator",-1],[" Sign Out",4]];contextMenu.show(items,mouse_x,mouse_y,"right")},album:function(albumID,e){var mouse_x=e.pageX,mouse_y=e.pageY-$(document).scrollTop(),items;if(albumID==="0"||albumID==="f"||albumID==="s")return false;contextMenu.fns=[function(){album.setTitle([albumID])},function(){album.delete([albumID])}];items=[[" Rename",0],[" Delete",1]];contextMenu.show(items,mouse_x,mouse_y,"right");$(".album[data-id='"+albumID+"']").addClass("active")},albumMulti:function(albumIDs,e){var mouse_x=e.pageX,mouse_y=e.pageY-$(document).scrollTop(),items;multiselect.stopResize();contextMenu.fns=[function(){album.setTitle(albumIDs)},function(){album.delete(albumIDs)}];items=[[" Rename All",0],[" Delete All",1]];contextMenu.show(items,mouse_x,mouse_y,"right")},photo:function(photoID,e){var mouse_x=e.pageX,mouse_y=e.pageY-$(document).scrollTop(),items;contextMenu.fns=[function(){photo.setStar([photoID])},function(){photo.editTags([photoID])},function(){photo.setTitle([photoID])},function(){contextMenu.move([photoID],e,"right")},function(){photo.delete([photoID])}];items=[[" Star",0],[" Tags",1],["separator",-1],[" Rename",2],[" Move",3],[" Delete",4]];contextMenu.show(items,mouse_x,mouse_y,"right");$(".photo[data-id='"+photoID+"']").addClass("active")},photoMulti:function(photoIDs,e){var mouse_x=e.pageX,mouse_y=e.pageY-$(document).scrollTop(),items;multiselect.stopResize();contextMenu.fns=[function(){photo.setStar(photoIDs)},function(){photo.editTags(photoIDs)},function(){photo.setTitle(photoIDs)},function(){contextMenu.move(photoIDs,e,"right")},function(){photo.delete(photoIDs)}];items=[[" Star All",0],[" Tag All",1],["separator",-1],[" Rename All",2],[" Move All",3],[" Delete All",4]];contextMenu.show(items,mouse_x,mouse_y,"right")},move:function(photoIDs,e,orientation){var mouse_x=e.pageX,mouse_y=e.pageY-$(document).scrollTop(),items=[];contextMenu.close(true);if(album.getID()!=="0"){items=[["Unsorted",0,"photo.setAlbum(["+photoIDs+"], 0)"],["separator",-1]]}lychee.api("getAlbums",function(data){if(data.num===0){items=[["New Album",0,"album.add()"]]}else{$.each(data.content,function(index){if(this.id!=album.getID())items.push([this.title,0,"photo.setAlbum(["+photoIDs+"], "+this.id+")"])})}if(!visible.photo())contextMenu.show(items,mouse_x,mouse_y,"right");else contextMenu.show(items,mouse_x,mouse_y,"left")})},sharePhoto:function(photoID,e){var mouse_x=e.pageX,mouse_y=e.pageY,items;mouse_y-=$(document).scrollTop();contextMenu.fns=[function(){photo.setPublic(photoID)},function(){photo.share(photoID,0)},function(){photo.share(photoID,1)},function(){photo.share(photoID,2)},function(){photo.share(photoID,3)},function(){window.open(photo.getDirectLink(),"_newtab")}];link=photo.getViewLink(photoID);if(photo.json.public==="2")link=location.href;items=[["",-1],["separator",-1],[" Make Private",0],["separator",-1],[" Twitter",1],[" Facebook",2],[" Mail",3],[" Dropbox",4],[" Direct Link",5]];contextMenu.show(items,mouse_x,mouse_y,"left");$(".contextmenu input").focus().select()},shareAlbum:function(albumID,e){var mouse_x=e.pageX,mouse_y=e.pageY,items;mouse_y-=$(document).scrollTop();contextMenu.fns=[function(){album.setPublic(albumID)},function(){password.set(albumID)},function(){album.share(0)},function(){album.share(1)},function(){album.share(2)},function(){password.remove(albumID)}];items=[["",-1],["separator",-1],[" Make Private",0],[" Set Password",1],["separator",-1],[" Twitter",2],[" Facebook",3],[" Mail",4]];if(album.json.password==true)items[3]=[" Remove Password",5];contextMenu.show(items,mouse_x,mouse_y,"left");$(".contextmenu input").focus().select()},close:function(leaveSelection){if(!visible.contextMenu())return false;contextMenu.fns=[];$(".contextmenu_bg, .contextmenu").remove();$("body").css("overflow","auto");if(leaveSelection!==true){$(".photo.active, .album.active").removeClass("active");if(visible.multiselect())multiselect.close()}}};$(document).ready(function(){var event_name=mobileBrowser()?"touchend":"click";$(document).bind("contextmenu",function(e){e.preventDefault()});if(!mobileBrowser())$(".tools").tipsy({gravity:"n",fade:false,delayIn:0,opacity:1});$("#content").on("mousedown",multiselect.show);$(document).on("mouseup",multiselect.getSelection);$("#hostedwith").on(event_name,function(){window.open(lychee.website,"_newtab")});$("#button_signin").on(event_name,lychee.loginDialog);$("#button_settings").on(event_name,contextMenu.settings);$("#button_share").on(event_name,function(e){if(photo.json.public==1||photo.json.public==2)contextMenu.sharePhoto(photo.getID(),e);else photo.setPublic(photo.getID(),e)});$("#button_share_album").on(event_name,function(e){if(album.json.public==1)contextMenu.shareAlbum(album.getID(),e);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? ",[["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_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()});$("#button_info").on(event_name,function(){view.infobox.show()});$("#button_archive").on(event_name,function(){album.getArchive(album.getID())});$("#button_star").on(event_name,function(){photo.setStar([photo.getID()])});$("#search").on("keyup click",function(){search.find($(this).val())});$("#clearSearch").on(event_name,function(){$("#search").focus();search.reset()});$("#button_back_home").on(event_name,function(){lychee.goto("")});$("#button_back").on(event_name,function(){lychee.goto(album.getID())});lychee.imageview.on(event_name,".arrow_wrapper.previous",function(){if(album.json&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].previousPhoto!=="")lychee.goto(album.getID()+"/"+album.json.content[photo.getID()].previousPhoto)}).on(event_name,".arrow_wrapper.next",function(){if(album.json&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].nextPhoto!=="")lychee.goto(album.getID()+"/"+album.json.content[photo.getID()].nextPhoto)});$("#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_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_tags",function(){photo.editTags([photo.getID()])}).on(event_name,"#tags .tag span",function(){photo.deleteTag(photo.getID(),$(this).data("index"))});Mousetrap.bind("u",function(){$("#upload_files").click()}).bind("s",function(){if(visible.photo())$("#button_star").click()}).bind("command+backspace",function(){if(visible.photo()&&!visible.message())photo.delete([photo.getID()])}).bind("left",function(){if(visible.photo())$("#imageview a#previous").click()}).bind("right",function(){if(visible.photo())$("#imageview a#next").click()}).bind("i",function(){if(visible.infobox())view.infobox.hide();else if(!visible.albums())view.infobox.show()});Mousetrap.bindGlobal("enter",function(){if($(".message .button.active").length)$(".message .button.active").addClass("pressed").click()});Mousetrap.bindGlobal(["esc","command+up"],function(e){e.preventDefault();if(visible.message()&&$(".message .close").length>0)modal.close();else if(visible.contextMenu())contextMenu.close();else if(visible.infobox())view.infobox.hide();else if(visible.photo())lychee.goto(album.getID());else if(visible.album())lychee.goto("");else if(visible.albums()&&$("#search").val().length!==0)search.reset()});$(document).on("keyup","#password",function(){if($(this).val().length>0)$(this).removeClass("error")}).on(event_name,"#title.editable",function(){if(visible.photo())photo.setTitle([photo.getID()]);else album.setTitle([album.getID()])}).on("click",".album",function(){lychee.goto($(this).attr("data-id"))}).on("click",".photo",function(){lychee.goto(album.getID()+"/"+$(this).attr("data-id"))}).on(event_name,".message .close",modal.close).on(event_name,".message .button:first",function(){if(modal.fns!=null)modal.fns[0]();if(!visible.signin())modal.close()}).on(event_name,".message .button:last",function(){if(modal.fns!=null)modal.fns[1]();if(!visible.signin())modal.close()}).on(event_name,".button_add",function(e){contextMenu.add(e)}).on("change","#upload_files",function(){modal.close();upload.start.local(this.files)}).on("contextmenu",".photo",function(e){contextMenu.photo(photo.getID(),e)}).on("contextmenu",".album",function(e){contextMenu.album(album.getID(),e)}).on(event_name,".contextmenu_bg",contextMenu.close).on("contextmenu",".contextmenu_bg",contextMenu.close).on(event_name,"#infobox_overlay",view.infobox.hide).on("dragover",function(e){e.preventDefault()},false).on("drop",function(e){e.stopPropagation();e.preventDefault();if(e.originalEvent.dataTransfer.files.length>0)upload.start.local(e.originalEvent.dataTransfer.files);else if(e.originalEvent.dataTransfer.getData("Text").length>3)upload.start.url(e.originalEvent.dataTransfer.getData("Text"));return true});lychee.init()});loadingBar={status:null,show:function(status,errorText){if(status==="error"){loadingBar.status="error";if(!errorText)errorText="Whoops, it looks like something went wrong. Please reload the site and try again!";lychee.loadingBar.removeClass("loading uploading error").addClass(status).html("

Error: "+errorText+"

").show().css("height","40px");if(visible.controls())lychee.header.addClass("error");clearTimeout(lychee.loadingBar.data("timeout"));lychee.loadingBar.data("timeout",setTimeout(function(){loadingBar.hide(true)},3e3))}else if(loadingBar.status==null){loadingBar.status="loading";clearTimeout(lychee.loadingBar.data("timeout"));lychee.loadingBar.data("timeout",setTimeout(function(){lychee.loadingBar.show().removeClass("loading uploading error").addClass("loading");if(visible.controls())lychee.header.addClass("loading")},1e3))}},hide:function(force_hide){if(loadingBar.status!=="error"&&loadingBar.status!=null||force_hide){loadingBar.status=null;clearTimeout(lychee.loadingBar.data("timeout"));lychee.loadingBar.html("").css("height","3px");if(visible.controls())lychee.header.removeClass("error loading");setTimeout(function(){lychee.loadingBar.hide()},300)}}};var lychee={version:"2.1 b2",api_path:"php/api.php",update_path:"http://lychee.electerious.com/version/index.php",updateURL:"https://github.com/electerious/Lychee",website:"http://lychee.electerious.com",website_donate:"http://lychee.electerious.com#donate",upload_path_thumb:"uploads/thumb/",upload_path_big:"uploads/big/",publicMode:false,viewMode:false,debugMode:false,username:"",checkForUpdates:false,sorting:"",dropbox:false,loadingBar:$("#loading"),header:$("header"),content:$("#content"),imageview:$("#imageview"),infobox:$("#infobox"),init:function(){lychee.api("init",function(data){if(data.loggedIn!==true){lychee.setMode("public")}else{lychee.username=data.config.username;lychee.sorting=data.config.sorting -}if(data==="Warning: No configuration!"){lychee.header.hide();lychee.content.hide();$("body").append(build.no_content("cog"));settings.createConfig();return true}if(data.config.login===false){settings.createLogin()}lychee.checkForUpdates=data.config.checkForUpdates;$(window).bind("popstate",lychee.load);lychee.load()})},api:function(params,callback,loading){if(loading==undefined)loadingBar.show();$.ajax({type:"POST",url:lychee.api_path,data:"function="+params,dataType:"text",success:function(data){setTimeout(function(){loadingBar.hide()},100);if(typeof data==="string"&&data.substring(0,7)==="Error: "){lychee.error(data.substring(7,data.length),params,data);return false}if(data==="1")data=true;else if(data==="")data=false;if(typeof data==="string"&&data.substring(0,1)==="{"&&data.substring(data.length-1,data.length)==="}")data=$.parseJSON(data);if(lychee.debugMode)console.log(data);callback(data)},error:function(jqXHR,textStatus,errorThrown){lychee.error("Server error or API not found.",params,errorThrown)}})},login:function(){var user=$("input#username").val(),password=hex_md5($("input#password").val()),params;params="login&user="+user+"&password="+password;lychee.api(params,function(data){if(data===true){localStorage.setItem("username",user);window.location.reload()}else{$("#password").val("").addClass("error").focus();$(".message .button.active").removeClass("pressed")}})},loginDialog:function(){var local_username;$("body").append(build.signInModal());$("#username").focus();if(localStorage){local_username=localStorage.getItem("username");if(local_username!=null){if(local_username.length>0)$("#username").val(local_username);$("#password").focus()}}if(lychee.checkForUpdates==="1")lychee.getUpdate()},logout:function(){lychee.api("logout",function(data){window.location.reload()})},"goto":function(url){if(url==undefined)url="";document.location.hash=url},load:function(){var albumID="",photoID="",hash=document.location.hash.replace("#","").split("/");contextMenu.close();multiselect.close();if(hash[0]!==undefined)albumID=hash[0];if(hash[1]!==undefined)photoID=hash[1];if(albumID&&photoID){albums.json=null;photo.json=null;if(lychee.content.html()===""||$("#search").length&&$("#search").val().length!==0){lychee.content.hide();album.load(albumID,true)}photo.load(photoID,albumID)}else if(albumID){albums.json=null;photo.json=null;if(visible.photo())view.photo.hide();if(album.json&&albumID==album.json.id)view.album.title();else album.load(albumID)}else{albums.json=null;album.json=null;photo.json=null;search.code="";if(visible.album())view.album.hide();if(visible.photo())view.photo.hide();albums.load()}},getUpdate:function(){$.ajax({url:lychee.update_path,success:function(data){if(data!=lychee.version)$("#version span").show()}})},setTitle:function(title,editable){if(title==="Albums")document.title="Lychee";else document.title="Lychee - "+title;if(editable)$("#title").addClass("editable");else $("#title").removeClass("editable");$("#title").html(title)},setMode:function(mode){$("#button_settings, #button_settings, #button_search, #search, #button_trash_album, #button_share_album, .button_add, .button_divider").remove();$("#button_trash, #button_move, #button_share, #button_star").remove();$(document).on("mouseenter","#title.editable",function(){$(this).removeClass("editable")}).off("click","#title.editable").off("touchend","#title.editable").off("contextmenu",".photo").off("contextmenu",".album").off("drop");Mousetrap.unbind("n").unbind("u").unbind("s").unbind("backspace");if(mode==="public"){$("header #button_signin, header #hostedwith").show();lychee.publicMode=true}else if(mode==="view"){Mousetrap.unbind("esc");$("#button_back, a#next, a#previous").remove();$(".no_content").remove();lychee.publicMode=true;lychee.viewMode=true}},animate:function(obj,animation){var animations=[["fadeIn","fadeOut"],["contentZoomIn","contentZoomOut"]];if(!obj.jQuery)obj=$(obj);for(var i=0;i=multiselect.position.top){newHeight=e.pageY-multiselect.position.top;if(multiselect.position.top+newHeight>=$(document).height())newHeight-=multiselect.position.top+newHeight-$(document).height()+2;$("#multiselect").css({top:multiselect.position.top,bottom:"inherit",height:newHeight})}else{$("#multiselect").css({top:"inherit",bottom:multiselect.position.bottom,height:multiselect.position.top-e.pageY})}if(mouse_x>=multiselect.position.left){newWidth=e.pageX-multiselect.position.left;if(multiselect.position.left+newWidth>=$(document).width())newWidth-=multiselect.position.left+newWidth-$(document).width()+2;$("#multiselect").css({right:"inherit",left:multiselect.position.left,width:newWidth})}else{$("#multiselect").css({right:multiselect.position.right,left:"inherit",width:multiselect.position.left-e.pageX})}},stopResize:function(){$(document).off("mousemove")},getSize:function(){if(!visible.multiselect())return false;return{top:$("#multiselect").offset().top,left:$("#multiselect").offset().left,width:parseInt($("#multiselect").css("width").replace("px","")),height:parseInt($("#multiselect").css("height").replace("px",""))}},getSelection:function(e){var tolerance=150,id,ids=[],offset,size=multiselect.getSize();if(visible.contextMenu())return false;if(!visible.multiselect())return false;$(".photo, .album").each(function(){offset=$(this).offset();if(offset.top>=size.top-tolerance&&offset.left>=size.left-tolerance&&offset.top+206<=size.top+size.height+tolerance&&offset.left+206<=size.left+size.width+tolerance){id=$(this).data("id");if(id!=="0"&&id!==0&&id!=="f"&&id!=="s"&&id!==null&id!==undefined){ids.push(id);$(this).addClass("active")}}});if(ids.length!=0&&visible.album())contextMenu.photoMulti(ids,e);else if(ids.length!=0&&visible.albums())contextMenu.albumMulti(ids,e);else multiselect.close()},close:function(){multiselect.stopResize();multiselect.position.top=null;multiselect.position.right=null;multiselect.position.bottom=null;multiselect.position.left=null;lychee.animate("#multiselect","fadeOut");setTimeout(function(){$("#multiselect").remove()},300)}};password={value:"",set:function(albumID){var buttons,params;buttons=[["Set Password",function(){if(visible.album()){album.json.password=true;view.album.password()}params="setAlbumPassword&albumID="+albumID+"&password="+hex_md5($(".message input.text").val());lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("Set Password","Set a password to protect '"+album.json.title+"' from unauthorized viewers. Only people with this password can view this album. ",buttons)},get:function(albumID,callback){var passwd=$(".message input.text").val(),params;if(!lychee.publicMode)callback();else if(album.json&&album.json.password==false)callback();else if(albums.json&&albums.json.content[albumID].password==false)callback();else if(!albums.json&&!album.json){album.json={password:true};callback("")}else if(passwd==undefined){password.getDialog(albumID,callback)}else{params="checkAlbumAccess&albumID="+albumID+"&password="+hex_md5(passwd);lychee.api(params,function(data){if(data===true){password.value=hex_md5(passwd);callback()}else{lychee.goto("");loadingBar.show("error","Access denied. Wrong password!")}})}},getDialog:function(albumID,callback){var buttons;buttons=[["Enter",function(){password.get(albumID,callback)}],["Cancel",lychee.goto]];modal.show(" Enter Password","This album is protected by a password. Enter the password below to view the photos of this album: ",buttons,-110,false)},remove:function(albumID){var params;if(visible.album()){album.json.password=false;view.album.password()}params="setAlbumPassword&albumID="+albumID+"&password=";lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}};photo={json:null,getID:function(){var id;if(photo.json)id=photo.json.id;else id=$(".photo:hover, .photo.active").attr("data-id");if(id)return id;else return false},load:function(photoID,albumID){var params,checkPasswd;params="getPhoto&photoID="+photoID+"&albumID="+albumID+"&password="+password.value;lychee.api(params,function(data){if(data==="Warning: Wrong password!"){checkPasswd=function(){if(password.value!=="")photo.load(photoID,albumID);else setTimeout(checkPasswd,250)};checkPasswd();return false}photo.json=data;if(!visible.photo())view.photo.show();view.photo.init();lychee.imageview.show();setTimeout(function(){lychee.content.show()},300)})},parse:function(){if(!photo.json.title)photo.json.title="Untitled";photo.json.url=lychee.upload_path_big+photo.json.url},"delete":function(photoIDs){var params,buttons,photoTitle;if(!photoIDs)return false;if(photoIDs instanceof Array===false)photoIDs=[photoIDs];if(photoIDs.length===1){if(visible.photo())photoTitle=photo.json.title;else photoTitle=album.json.content[photoIDs].title;if(photoTitle=="")photoTitle="Untitled"}buttons=[["",function(){photoIDs.forEach(function(id,index,array){if(album.json.content[id].nextPhoto!==""||album.json.content[id].previousPhoto!==""){nextPhoto=album.json.content[id].nextPhoto;previousPhoto=album.json.content[id].previousPhoto;album.json.content[previousPhoto].nextPhoto=nextPhoto;album.json.content[nextPhoto].previousPhoto=previousPhoto}album.json.content[id]=null;view.album.content.delete(id)});if(!visible.albums())lychee.goto(album.getID());params="deletePhoto&photoIDs="+photoIDs;lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["",function(){}]];if(photoIDs.length===1){buttons[0][0]="Delete Photo";buttons[1][0]="Keep Photo";modal.show("Delete Photo","Are you sure you want to delete the photo '"+photoTitle+"'?
This action can't be undone!",buttons)}else{buttons[0][0]="Delete Photos";buttons[1][0]="Keep Photos";modal.show("Delete Photos","Are you sure you want to delete all "+photoIDs.length+" selected photo?
This action can't be undone!",buttons)}},setTitle:function(photoIDs){var oldTitle="",newTitle,params,buttons;if(!photoIDs)return false;if(photoIDs instanceof Array===false)photoIDs=[photoIDs];if(photoIDs.length===1){if(photo.json)oldTitle=photo.json.title;else if(album.json)oldTitle=album.json.content[photoIDs].title}buttons=[["Set Title",function(){newTitle=$(".message input.text").val();if(visible.photo()){photo.json.title=newTitle===""?"Untitled":newTitle;view.photo.title()}photoIDs.forEach(function(id,index,array){album.json.content[id].title=newTitle;view.album.content.title(id)});params="setPhotoTitle&photoIDs="+photoIDs+"&title="+escape(encodeURI(newTitle));lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];if(photoIDs.length===1)modal.show("Set Title","Enter a new title for this photo: ",buttons);else modal.show("Set Titles","Enter a title for all "+photoIDs.length+" selected photos: ",buttons)},setAlbum:function(photoIDs,albumID){var params,nextPhoto,previousPhoto;if(!photoIDs)return false;if(visible.photo)lychee.goto(album.getID());if(photoIDs instanceof Array===false)photoIDs=[photoIDs];photoIDs.forEach(function(id,index,array){if(album.json.content[id].nextPhoto!==""||album.json.content[id].previousPhoto!==""){nextPhoto=album.json.content[id].nextPhoto;previousPhoto=album.json.content[id].previousPhoto;album.json.content[previousPhoto].nextPhoto=nextPhoto;album.json.content[nextPhoto].previousPhoto=previousPhoto}album.json.content[id]=null;view.album.content.delete(id)});params="setPhotoAlbum&photoIDs="+photoIDs+"&albumID="+albumID;lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})},setStar:function(photoIDs){var params;if(!photoIDs)return false;if(visible.photo()){photo.json.star=photo.json.star==0?1:0;view.photo.star()}photoIDs.forEach(function(id,index,array){album.json.content[id].star=album.json.content[id].star==0?1:0;view.album.content.star(id)});params="setPhotoStar&photoIDs="+photoIDs;lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})},setPublic:function(photoID,e){var params;if(photo.json.public==2){modal.show("Public Album","This photo is located in a public album. To make this photo private or public, edit the visibility of the associated album.",[["Show Album",function(){lychee.goto(photo.json.original_album)}],["Close",function(){}]]);return false}if(visible.photo()){photo.json.public=photo.json.public==0?1:0;view.photo.public();if(photo.json.public==1)contextMenu.sharePhoto(photoID,e)}album.json.content[photoID].public=album.json.content[photoID].public==0?1:0;view.album.content.public(photoID);params="setPhotoPublic&photoID="+photoID+"&url="+photo.getViewLink(photoID);lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})},setDescription:function(photoID){var oldDescription=photo.json.description,description,params,buttons;buttons=[["Set Description",function(){description=$(".message input.text").val();if(visible.photo()){photo.json.description=description;view.photo.description()}params="setPhotoDescription&photoID="+photoID+"&description="+escape(description);lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("Set Description","Enter a description for this photo: ",buttons)},editTags:function(photoIDs){var oldTags="",tags="";if(!photoIDs)return false;if(photoIDs instanceof Array===false)photoIDs=[photoIDs];if(visible.photo())oldTags=photo.json.tags;if(visible.album()&&photoIDs.length===1)oldTags=album.json.content[photoIDs].tags;if(visible.album()&&photoIDs.length>1){var same=true;photoIDs.forEach(function(id,index,array){if(album.json.content[id].tags===album.json.content[photoIDs[0]].tags&&same===true)same=true;else same=false});if(same)oldTags=album.json.content[photoIDs[0]].tags}oldTags=oldTags.replace(/,/g,", ");buttons=[["Set Tags",function(){tags=$(".message input.text").val();photo.setTags(photoIDs,tags)}],["Cancel",function(){}]];if(photoIDs.length===1)modal.show("Set Tags","Enter your tags for this photo. You can add multiple tags by separating them with a comma: ",buttons);else modal.show("Set Tags","Enter your tags for all "+photoIDs.length+" selected photos. Existing tags will be overwritten. You can add multiple tags by separating them with a comma: ",buttons)},setTags:function(photoIDs,tags){var params;if(!photoIDs)return false;if(photoIDs instanceof Array===false)photoIDs=[photoIDs];tags=tags.replace(/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/g,",");tags=tags.replace(/,$|^,/g,"");if(visible.photo()){photo.json.tags=tags;view.photo.tags()}photoIDs.forEach(function(id,index,array){album.json.content[id].tags=tags});params="setPhotoTags&photoIDs="+photoIDs+"&tags="+tags;lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})},deleteTag:function(photoID,index){var tags;tags=photo.json.tags.split(",");tags.splice(index,1);photo.json.tags=tags.toString();photo.setTags([photoID],photo.json.tags)},share:function(photoID,service){var link="",url=photo.getViewLink(photoID),filename="unknown";switch(service){case 0:link="https://twitter.com/share?url="+encodeURI(url);break;case 1:link="http://www.facebook.com/sharer.php?u="+encodeURI(url)+"&t="+encodeURI(photo.json.title);break;case 2:link="mailto:?subject="+encodeURI(photo.json.title)+"&body="+encodeURI(url);break;case 3:lychee.loadDropbox(function(){filename=photo.json.title+"."+photo.getDirectLink().split(".").pop();Dropbox.save(photo.getDirectLink(),filename)});break;default:link="";break}if(link.length>5)location.href=link},isSmall:function(){var size=[["width",false],["height",false]];if(photo.json.width<$(window).width()-60)size["width"]=true;if(photo.json.height<$(window).height()-100)size["height"]=true;if(size["width"]&&size["height"])return true;else return false},getArchive:function(photoID){var link;if(location.href.indexOf("index.html")>0)link=location.href.replace(location.hash,"").replace("index.html","php/api.php?function=getPhotoArchive&photoID="+photoID);else link=location.href.replace(location.hash,"")+"php/api.php?function=getPhotoArchive&photoID="+photoID;if(lychee.publicMode)link+="&password="+password.value;location.href=link},getDirectLink:function(){return $("#imageview #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/gi,"")},getViewLink:function(photoID){if(location.href.indexOf("index.html")>0)return location.href.replace("index.html"+location.hash,"view.php?p="+photoID);else return location.href.replace(location.hash,"view.php?p="+photoID)}};search={code:null,find:function(term){var params,albumsData="",photosData="",code;clearTimeout($(window).data("timeout"));$(window).data("timeout",setTimeout(function(){if($("#search").val().length!==0){params="search&term="+term;lychee.api(params,function(data){if(data&&data.albums){albums.json={content:data.albums};$.each(albums.json.content,function(){albums.parse(this);albumsData+=build.album(this)})}if(data&&data.photos){album.json={content:data.photos};$.each(album.json.content,function(){album.parse(this);photosData+=build.photo(this)})}if(albumsData===""&&photosData==="")code="error";else if(albumsData==="")code=build.divider("Photos")+photosData;else if(photosData==="")code=build.divider("Albums")+albumsData;else code=build.divider("Photos")+photosData+build.divider("Albums")+albumsData;if(search.code!==hex_md5(code)){$(".no_content").remove();lychee.animate(".album, .photo","contentZoomOut");lychee.animate(".divider","fadeOut");search.code=hex_md5(code);setTimeout(function(){if(code==="error")$("body").append(build.no_content("search"));else{lychee.content.html(code);lychee.animate(".album, .photo","contentZoomIn");$("img[data-type!='svg']").retina()}},300)}})}else search.reset()},250))},reset:function(){$("#search").val("");$(".no_content").remove();if(search.code!==""){search.code="";lychee.animate(".divider","fadeOut");albums.load()}}};var settings={createConfig:function(){var dbName,dbUser,dbPassword,dbHost,buttons;buttons=[["Connect",function(){dbHost=$(".message input.text#dbHost").val();dbUser=$(".message input.text#dbUser").val();dbPassword=$(".message input.text#dbPassword").val();dbName=$(".message input.text#dbName").val();if(dbHost.length<1)dbHost="localhost";if(dbName.length<1)dbName="lychee";params="dbCreateConfig&dbName="+escape(dbName)+"&dbUser="+escape(dbUser)+"&dbPassword="+escape(dbPassword)+"&dbHost="+escape(dbHost);lychee.api(params,function(data){if(data!==true){setTimeout(function(){if(data.indexOf("Warning: Connection failed!")!==-1){buttons=[["Retry",function(){setTimeout(settings.createConfig,400)}],["",function(){}]];modal.show("Connection Failed","Unable to connect to host database because access was denied. Double-check your host, username and password and ensure that access from your current location is permitted.",buttons,null,false);return false}if(data.indexOf("Warning: Could not create file!")!==-1){buttons=[["Retry",function(){setTimeout(settings.createConfig,400)}],["",function(){}]];modal.show("Saving Failed","Unable to save this configuration. Permission denied in 'data/'. Please set the read, write and execute rights for others in 'data/' and 'uploads/'. Take a look the readme for more information.",buttons,null,false);return false}buttons=[["Retry",function(){setTimeout(settings.createConfig,400)}],["",function(){}]];modal.show("Configuration Failed","Something unexpected happened. Please try again and check your installation and server. Take a look the readme for more information.",buttons,null,false);return false},400)}else{lychee.api("update",function(data){window.location.reload()})}})}],["",function(){}]];modal.show("Configuration","Enter your database connection details below:
Lychee will create its own database. If required, you can enter the name of an existing database instead:",buttons,-215,false)},createLogin:function(){var username,password,params,buttons;buttons=[["Create Login",function(){username=$(".message input.text#username").val();password=$(".message input.text#password").val();if(username.length<1||password.length<1){setTimeout(function(){buttons=[["Retry",function(){setTimeout(settings.createLogin,400)}],["",function(){}]];modal.show("Wrong Input","The username or password you entered is not long enough. Please try again with another username and password!",buttons,null,false);return false},400)}else{params="setLogin&username="+escape(username)+"&password="+hex_md5(password);lychee.api(params,function(data){if(data!==true){setTimeout(function(){buttons=[["Retry",function(){setTimeout(settings.createLogin,400)}],["",function(){}]];modal.show("Creation Failed","Unable to save login. Please try again with another username and password!",buttons,null,false);return false},400)}})}}],["",function(){}]];modal.show("Create Login","Enter a username and password for your installation: ",buttons,-122,false)},setLogin:function(){var old_password,username,password,params,buttons;buttons=[["Change Login",function(){old_password=$(".message input.text#old_password").val();username=$(".message input.text#username").val();password=$(".message input.text#password").val();if(old_password.length<1){loadingBar.show("error","Your old password was entered incorrectly. Please try again!");return false}if(username.length<1){loadingBar.show("error","Your new username was entered incorrectly. Please try again!");return false}if(password.length<1){loadingBar.show("error","Your new password was entered incorrectly. Please try again!");return false}params="setLogin&oldPassword="+hex_md5(old_password)+"&username="+escape(username)+"&password="+hex_md5(password);lychee.api(params,function(data){if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("Change Login","Enter your current password:
Your username and password will be changed to the following: ",buttons,-171)},setSorting:function(){var buttons,sorting;buttons=[["Change Sorting",function(){sorting[0]=$("select#settings_type").val();sorting[1]=$("select#settings_order").val();params="setSorting&type="+sorting[0]+"&order="+sorting[1];lychee.api(params,function(data){if(data===true){lychee.sorting="ORDER BY "+sorting[0]+" "+sorting[1];lychee.load()}else lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("Change Sorting","Sort photos by in an order. ",buttons);if(lychee.sorting!=""){sorting=lychee.sorting.replace("ORDER BY ","").replace(" ",";").split(";");$("select#settings_type").val(sorting[0]);$("select#settings_order").val(sorting[1])}}};upload={show:function(icon,text){if(icon===undefined)icon="upload";upload.close(true);$("body").append(build.uploadModal(icon,text))},setIcon:function(icon){$(".upload_message a").remove();$(".upload_message").prepend("")},setProgress:function(progress){$(".progressbar div").css("width",progress+"%")},setText:function(text){$(".progressbar").remove();$(".upload_message").append("

"+text+"

")},notify:function(title){var popup;if(!window.webkitNotifications)return false;if(window.webkitNotifications.checkPermission()!=0)window.webkitNotifications.requestPermission();if(window.webkitNotifications.checkPermission()==0&&title){popup=window.webkitNotifications.createNotification("",title,"You can now manage your new photo(s).");popup.show()}},start:{local:function(files){var pre_progress=0,formData=new FormData,xhr=new XMLHttpRequest,albumID=album.getID(),popup,progress;if(files.length<=0)return false;if(albumID===false)albumID=0;formData.append("function","upload");formData.append("albumID",albumID);for(var i=0;ipre_progress){upload.setProgress(progress);pre_progress=progress}if(progress>=100){upload.setIcon("cog");upload.setText("Processing photos")}}};$("#upload_files").val("");xhr.send(formData)},url:function(){var albumID=album.getID(),params,extension,buttons;if(albumID===false)albumID=0;buttons=[["Import",function(){link=$(".message input.text").val();if(link&&link.length>3){extension=link.split(".").pop();if(extension!=="jpeg"&&extension!=="jpg"&&extension!=="png"&&extension!=="gif"&&extension!=="webp"){loadingBar.show("error","The file format of this link is not supported.");return false}modal.close();upload.show("cog","Importing from URL");params="importUrl&url="+escape(encodeURI(link))+"&albumID="+albumID;lychee.api(params,function(data){upload.close();upload.notify("Import complete");if(album.getID()===false)lychee.goto("0");else album.load(albumID);if(data!==true)lychee.error(null,params,data)})}else loadingBar.show("error","Link to short or too long. Please try another one!")}],["Cancel",function(){}]];modal.show("Import from Link","Please enter the direct link to a photo to import it: ",buttons)},server:function(){var albumID=album.getID(),params,buttons;if(albumID===false)albumID=0;buttons=[["Import",function(){modal.close();upload.show("cog","Importing photos");params="importServer&albumID="+albumID;lychee.api(params,function(data){upload.close();upload.notify("Import complete");if(data==="Notice: Import only contains albums!"){if(visible.albums())lychee.load();else lychee.goto("")}else if(album.getID()===false)lychee.goto("0");else album.load(albumID);if(data==="Notice: Import only contains albums!")return true;else if(data==="Warning: Folder empty!")lychee.error("Folder empty. No photos imported!",params,data);else if(data!==true)lychee.error(null,params,data)})}],["Cancel",function(){}]];modal.show("Import from Server","This action will import all photos and albums which are located in 'uploads/import/' of your Lychee installation.",buttons)},dropbox:function(){var albumID=album.getID(),params;if(albumID===false)albumID=0;lychee.loadDropbox(function(){Dropbox.choose({linkType:"direct",multiselect:true,success:function(files){if(files.length>1){for(var i=0;i0){$("#imageview #image").css({marginTop:-1*($("#imageview #image").height()/2)+20})}else{$("#imageview #image").css({top:60,right:30,bottom:30,left:30})}}},hide:function(){if(visible.photo()&&!visible.infobox()&&!visible.contextMenu()&&!visible.message()){clearTimeout($(window).data("timeout"));$(window).data("timeout",setTimeout(function(){lychee.imageview.addClass("full");lychee.loadingBar.css("opacity",0);lychee.header.addClass("hidden");if($("#imageview #image.small").length>0){$("#imageview #image").css({marginTop:-1*($("#imageview #image").height()/2)})}else{$("#imageview #image").css({top:0,right:0,bottom:0,left:0}) -}},500))}},mode:function(mode){var albumID=album.getID();switch(mode){case"albums":lychee.header.removeClass("view");$("#tools_album, #tools_photo").hide();$("#tools_albums").show();break;case"album":lychee.header.removeClass("view");$("#tools_albums, #tools_photo").hide();$("#tools_album").show();album.json.content===false?$("#button_archive").hide():$("#button_archive").show();if(albumID==="s"||albumID==="f"){$("#button_info_album, #button_trash_album, #button_share_album").hide()}else if(albumID==="0"){$("#button_info_album, #button_share_album").hide();$("#button_trash_album").show()}else{$("#button_info_album, #button_trash_album, #button_share_album").show()}break;case"photo":lychee.header.addClass("view");$("#tools_albums, #tools_album").hide();$("#tools_photo").show();break}}},infobox:{show:function(){if(!visible.infobox())$("body").append("
");lychee.infobox.addClass("active")},hide:function(){lychee.animate("#infobox_overlay","fadeOut");setTimeout(function(){$("#infobox_overlay").remove()},300);lychee.infobox.removeClass("active")}},albums:{init:function(){view.albums.title();view.albums.content.init()},title:function(){lychee.setTitle("Albums",false)},content:{init:function(){var smartData="",albumsData="";albums.parse(albums.json.unsortedAlbum);albums.parse(albums.json.publicAlbum);albums.parse(albums.json.starredAlbum);if(!lychee.publicMode)smartData=build.divider("Smart Albums")+build.album(albums.json.unsortedAlbum)+build.album(albums.json.starredAlbum)+build.album(albums.json.publicAlbum);if(albums.json.content){if(!lychee.publicMode)albumsData=build.divider("Albums");$.each(albums.json.content,function(){albums.parse(this);albumsData+=build.album(this)})}if(smartData===""&&albumsData==="")$("body").append(build.no_content("picture"));else lychee.content.html(smartData+albumsData);$("img[data-type!='svg']").retina()},title:function(albumID){var prefix="",longTitle="",title=albums.json.content[albumID].title;if(albums.json.content[albumID].password)prefix=" ";if(title.length>18){longTitle=title;title=title.substr(0,18)+"..."}$(".album[data-id='"+albumID+"'] .overlay h1").html(prefix+title).attr("title",longTitle)},"delete":function(albumID){$(".album[data-id='"+albumID+"']").css("opacity",0).animate({width:0,marginLeft:0},300,function(){$(this).remove();if(albums.json.num<=0)lychee.animate(".divider:last-of-type","fadeOut")})}}},album:{init:function(){album.parse();view.album.infobox();view.album.title();view.album.public();view.album.content.init();album.json.init=1},hide:function(){view.infobox.hide()},title:function(){if((visible.album()||!album.json.init)&&!visible.photo()){switch(album.getID()){case"f":lychee.setTitle("Starred",false);break;case"s":lychee.setTitle("Public",false);break;case"0":lychee.setTitle("Unsorted",false);break;default:if(album.json.init)$("#infobox .attr_name").html(album.json.title+" "+build.editIcon("edit_title_album"));lychee.setTitle(album.json.title,true);break}}},description:function(){$("#infobox .attr_description").html(album.json.description+" "+build.editIcon("edit_description_album"))},content:{init:function(){var photosData="";$.each(album.json.content,function(){album.parse(this);photosData+=build.photo(this)});lychee.content.html(photosData);$("img[data-type!='svg']").retina()},title:function(photoID){var longTitle="",title=album.json.content[photoID].title;if(title.length>18){longTitle=title;title=title.substr(0,18)+"..."}$(".photo[data-id='"+photoID+"'] .overlay h1").html(title).attr("title",longTitle)},star:function(photoID){$(".photo[data-id='"+photoID+"'] .icon-star").remove();if(album.json.content[photoID].star==1)$(".photo[data-id='"+photoID+"']").append("")},"public":function(photoID){$(".photo[data-id='"+photoID+"'] .icon-share").remove();if(album.json.content[photoID].public==1)$(".photo[data-id='"+photoID+"']").append("")},"delete":function(photoID){$(".photo[data-id='"+photoID+"']").css("opacity",0).animate({width:0,marginLeft:0},300,function(){$(this).remove();if(!visible.albums()){album.json.num--;view.album.num();view.album.title()}})}},num:function(){$("#infobox .attr_images").html(album.json.num)},"public":function(){if(album.json.public==1){$("#button_share_album a").addClass("active");$("#button_share_album").attr("title","Share Album");$(".photo .icon-share").remove();if(album.json.init)$("#infobox .attr_visibility").html("Public")}else{$("#button_share_album a").removeClass("active");$("#button_share_album").attr("title","Make Public");if(album.json.init)$("#infobox .attr_visibility").html("Private")}},password:function(){if(album.json.password==1)$("#infobox .attr_password").html("Yes");else $("#infobox .attr_password").html("No")},infobox:function(){if((visible.album()||!album.json.init)&&!visible.photo())lychee.infobox.html(build.infoboxAlbum(album.json)).show()}},photo:{init:function(){photo.parse();view.photo.infobox();view.photo.title();view.photo.star();view.photo.public();view.photo.photo();photo.json.init=1},show:function(){lychee.content.addClass("view");view.header.mode("photo");$("body").css("overflow","hidden");$(document).bind("mouseenter",view.header.show).bind("mouseleave",view.header.hide);lychee.animate(lychee.imageview,"fadeIn")},hide:function(){if(!visible.controls())view.header.show();if(visible.infobox)view.infobox.hide();lychee.content.removeClass("view");view.header.mode("album");$("body").css("overflow","auto");$(document).unbind("mouseenter").unbind("mouseleave");lychee.animate(lychee.imageview,"fadeOut");setTimeout(function(){lychee.imageview.hide();view.album.infobox()},300)},title:function(){if(photo.json.init)$("#infobox .attr_name").html(photo.json.title+" "+build.editIcon("edit_title"));lychee.setTitle(photo.json.title,true)},description:function(){if(photo.json.init)$("#infobox .attr_description").html(photo.json.description+" "+build.editIcon("edit_description"))},star:function(){$("#button_star a").removeClass("icon-star-empty icon-star");if(photo.json.star==1){$("#button_star a").addClass("icon-star");$("#button_star").attr("title","Unstar Photo")}else{$("#button_star a").addClass("icon-star-empty");$("#button_star").attr("title","Star Photo")}},"public":function(){if(photo.json.public==1||photo.json.public==2){$("#button_share a").addClass("active");$("#button_share").attr("title","Share Photo");if(photo.json.init)$("#infobox .attr_visibility").html("Public")}else{$("#button_share a").removeClass("active");$("#button_share").attr("title","Make Public");if(photo.json.init)$("#infobox .attr_visibility").html("Private")}},tags:function(){$("#infobox #tags").html(build.tags(photo.json.tags))},photo:function(){lychee.imageview.html(build.imageview(photo.json,photo.isSmall(),visible.controls()));if(album.json&&album.json.content&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].nextPhoto===""||lychee.viewMode)$("a#next").hide();if(album.json&&album.json.content&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].previousPhoto===""||lychee.viewMode)$("a#previous").hide()},infobox:function(){lychee.infobox.html(build.infoboxPhoto(photo.json)).show()}}};visible={albums:function(){if($("#tools_albums").css("display")==="block")return true;else return false},album:function(){if($("#tools_album").css("display")==="block")return true;else return false},photo:function(){if($("#imageview.fadeIn").length>0)return true;else return false},search:function(){if(search.code!==null&&search.code!=="")return true;else return false},infobox:function(){if($("#infobox.active").length>0)return true;else return false},controls:function(){if(lychee.loadingBar.css("opacity")<1)return false;else return true},message:function(){if($(".message").length>0)return true;else return false},signin:function(){if($(".message .sign_in").length>0)return true;else return false},contextMenu:function(){if($(".contextmenu").length>0)return true;else return false},multiselect:function(){if($("#multiselect").length>0)return true;else return false}}; \ No newline at end of file diff --git a/assets/js/modules/modal.js b/assets/js/modal.js similarity index 100% rename from assets/js/modules/modal.js rename to assets/js/modal.js diff --git a/assets/js/modules/view.js b/assets/js/modules/view.js deleted file mode 100644 index c646189..0000000 --- a/assets/js/modules/view.js +++ /dev/null @@ -1,474 +0,0 @@ -/** - * @name UI View - * @description Responsible to reflect data changes to the UI. - * @author Tobias Reich - * @copyright 2014 by Tobias Reich - */ - -view = { - - header: { - - show: function() { - - clearTimeout($(window).data("timeout")); - - if (visible.photo()) { - lychee.imageview.removeClass("full"); - lychee.loadingBar.css("opacity", 1); - lychee.header.removeClass("hidden"); - if ($("#imageview #image.small").length>0) { - $("#imageview #image").css({ - marginTop: -1*($("#imageview #image").height()/2)+20 - }); - } else { - $("#imageview #image").css({ - top: 60, - right: 30, - bottom: 30, - left: 30 - }); - } - } - - }, - - hide: function() { - - if (visible.photo()&&!visible.infobox()&&!visible.contextMenu()&&!visible.message()) { - clearTimeout($(window).data("timeout")); - $(window).data("timeout", setTimeout(function() { - lychee.imageview.addClass("full"); - lychee.loadingBar.css("opacity", 0); - lychee.header.addClass("hidden"); - if ($("#imageview #image.small").length>0) { - $("#imageview #image").css({ - marginTop: -1*($("#imageview #image").height()/2) - }); - } else { - $("#imageview #image").css({ - top: 0, - right: 0, - bottom: 0, - left: 0 - }); - } - }, 500)); - } - - }, - - mode: function(mode) { - - var albumID = album.getID(); - - switch (mode) { - case "albums": - lychee.header.removeClass("view"); - $("#tools_album, #tools_photo").hide(); - $("#tools_albums").show(); - break; - case "album": - lychee.header.removeClass("view"); - $("#tools_albums, #tools_photo").hide(); - $("#tools_album").show(); - album.json.content === false ? $("#button_archive").hide() : $("#button_archive").show(); - if (albumID==="s"||albumID==="f") { - $("#button_info_album, #button_trash_album, #button_share_album").hide(); - } else if (albumID==="0") { - $("#button_info_album, #button_share_album").hide(); - $("#button_trash_album").show(); - } else { - $("#button_info_album, #button_trash_album, #button_share_album").show(); - } - break; - case "photo": - lychee.header.addClass("view"); - $("#tools_albums, #tools_album").hide(); - $("#tools_photo").show(); - break; - - } - - } - - }, - - infobox: { - - show: function() { - - if (!visible.infobox()) $("body").append("
"); - lychee.infobox.addClass("active"); - - }, - - hide: function() { - - lychee.animate("#infobox_overlay", "fadeOut"); - setTimeout(function() { $("#infobox_overlay").remove() }, 300); - lychee.infobox.removeClass("active"); - - } - - }, - - albums: { - - init: function() { - - view.albums.title(); - view.albums.content.init(); - - }, - - title: function() { - - lychee.setTitle("Albums", false); - - }, - - content: { - - init: function() { - - var smartData = "", - albumsData = ""; - - /* Smart Albums */ - albums.parse(albums.json.unsortedAlbum); - albums.parse(albums.json.publicAlbum); - albums.parse(albums.json.starredAlbum); - if (!lychee.publicMode) smartData = build.divider("Smart Albums") + build.album(albums.json.unsortedAlbum) + build.album(albums.json.starredAlbum) + build.album(albums.json.publicAlbum); - - /* Albums */ - if (albums.json.content) { - - if (!lychee.publicMode) albumsData = build.divider("Albums"); - $.each(albums.json.content, function() { - albums.parse(this); - albumsData += build.album(this); - }); - - } - - if (smartData===""&&albumsData==="") $("body").append(build.no_content("picture")); - else lychee.content.html(smartData + albumsData); - - $("img[data-type!='svg']").retina(); - - }, - - title: function(albumID) { - - var prefix = "", - longTitle = "", - title = albums.json.content[albumID].title; - - if (albums.json.content[albumID].password) prefix = " "; - if (title.length>18) { - longTitle = title; - title = title.substr(0, 18) + "..."; - } - - $(".album[data-id='" + albumID + "'] .overlay h1") - .html(prefix + title) - .attr("title", longTitle); - - }, - - delete: function(albumID) { - - $(".album[data-id='" + albumID + "']").css("opacity", 0).animate({ - width: 0, - marginLeft: 0 - }, 300, function() { - $(this).remove(); - if (albums.json.num<=0) lychee.animate(".divider:last-of-type", "fadeOut"); - }); - - } - - } - - }, - - album: { - - init: function() { - - album.parse(); - - view.album.infobox(); - view.album.title(); - view.album.public(); - view.album.content.init(); - - album.json.init = 1; - - }, - - hide: function() { - - view.infobox.hide(); - - }, - - title: function() { - - if ((visible.album()||!album.json.init)&&!visible.photo()) { - - switch (album.getID()) { - case "f": - lychee.setTitle("Starred", false); - break; - case "s": - lychee.setTitle("Public", false); - break; - case "0": - lychee.setTitle("Unsorted", false); - break; - default: - if (album.json.init) $("#infobox .attr_name").html(album.json.title + " " + build.editIcon("edit_title_album")); - lychee.setTitle(album.json.title, true); - break; - } - - } - - }, - - description: function() { - - $("#infobox .attr_description").html(album.json.description + " " + build.editIcon("edit_description_album")); - - }, - - content: { - - init: function() { - - var photosData = ""; - - $.each(album.json.content, function() { - album.parse(this); - photosData += build.photo(this); - }); - lychee.content.html(photosData); - - $("img[data-type!='svg']").retina(); - - }, - - title: function(photoID) { - - var longTitle = "", - title = album.json.content[photoID].title; - - if (title.length>18) { - longTitle = title; - title = title.substr(0, 18) + "..."; - } - - $(".photo[data-id='" + photoID + "'] .overlay h1") - .html(title) - .attr("title", longTitle); - - }, - - star: function(photoID) { - - $(".photo[data-id='" + photoID + "'] .icon-star").remove(); - if (album.json.content[photoID].star==1) $(".photo[data-id='" + photoID + "']").append(""); - - }, - - public: function(photoID) { - - $(".photo[data-id='" + photoID + "'] .icon-share").remove(); - if (album.json.content[photoID].public==1) $(".photo[data-id='" + photoID + "']").append(""); - - }, - - delete: function(photoID) { - - $(".photo[data-id='" + photoID + "']").css("opacity", 0).animate({ - width: 0, - marginLeft: 0 - }, 300, function() { - $(this).remove(); - // Only when search is not active - if (!visible.albums()) { - album.json.num--; - view.album.num(); - view.album.title(); - } - }); - - } - - }, - - num: function() { - - $("#infobox .attr_images").html(album.json.num); - - }, - - public: function() { - - if (album.json.public==1) { - $("#button_share_album a").addClass("active"); - $("#button_share_album").attr("title", "Share Album"); - $(".photo .icon-share").remove(); - if (album.json.init) $("#infobox .attr_visibility").html("Public"); - } else { - $("#button_share_album a").removeClass("active"); - $("#button_share_album").attr("title", "Make Public"); - if (album.json.init) $("#infobox .attr_visibility").html("Private"); - } - - }, - - password: function() { - - if (album.json.password==1) $("#infobox .attr_password").html("Yes"); - else $("#infobox .attr_password").html("No"); - - }, - - infobox: function() { - - if ((visible.album()||!album.json.init)&&!visible.photo()) lychee.infobox.html(build.infoboxAlbum(album.json)).show(); - - } - - }, - - photo: { - - init: function() { - - photo.parse(); - - view.photo.infobox(); - view.photo.title(); - view.photo.star(); - view.photo.public(); - view.photo.photo(); - - photo.json.init = 1; - - }, - - show: function() { - - // Change header - lychee.content.addClass("view"); - view.header.mode("photo"); - - // Make body not scrollable - $("body").css("overflow", "hidden"); - - // Fullscreen - $(document) - .bind("mouseenter", view.header.show) - .bind("mouseleave", view.header.hide); - - lychee.animate(lychee.imageview, "fadeIn"); - - }, - - hide: function() { - - if (!visible.controls()) view.header.show(); - if (visible.infobox) view.infobox.hide(); - - lychee.content.removeClass("view"); - view.header.mode("album"); - - // Make body scrollable - $("body").css("overflow", "auto"); - - // Disable Fullscreen - $(document) - .unbind("mouseenter") - .unbind("mouseleave"); - - // Hide Photo - lychee.animate(lychee.imageview, "fadeOut"); - setTimeout(function() { - lychee.imageview.hide(); - view.album.infobox(); - }, 300); - - }, - - title: function() { - - if (photo.json.init) $("#infobox .attr_name").html(photo.json.title + " " + build.editIcon("edit_title")); - lychee.setTitle(photo.json.title, true); - - }, - - description: function() { - - if (photo.json.init) $("#infobox .attr_description").html(photo.json.description + " " + build.editIcon("edit_description")); - - }, - - star: function() { - - $("#button_star a").removeClass("icon-star-empty icon-star"); - if (photo.json.star==1) { - // Starred - $("#button_star a").addClass("icon-star"); - $("#button_star").attr("title", "Unstar Photo"); - } else { - // Unstarred - $("#button_star a").addClass("icon-star-empty"); - $("#button_star").attr("title", "Star Photo"); - } - - }, - - public: function() { - - if (photo.json.public==1||photo.json.public==2) { - // Photo public - $("#button_share a").addClass("active"); - $("#button_share").attr("title", "Share Photo"); - if (photo.json.init) $("#infobox .attr_visibility").html("Public"); - } else { - // Photo private - $("#button_share a").removeClass("active"); - $("#button_share").attr("title", "Make Public"); - if (photo.json.init) $("#infobox .attr_visibility").html("Private"); - } - - }, - - tags: function() { - - $("#infobox #tags").html(build.tags(photo.json.tags)); - - }, - - photo: function() { - - lychee.imageview.html(build.imageview(photo.json, photo.isSmall(), visible.controls())); - - if ((album.json&&album.json.content&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].nextPhoto==="")||lychee.viewMode) $("a#next").hide(); - if ((album.json&&album.json.content&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].previousPhoto==="")||lychee.viewMode) $("a#previous").hide(); - - }, - - infobox: function() { - - lychee.infobox.html(build.infoboxPhoto(photo.json)).show(); - - } - - } - -} \ No newline at end of file diff --git a/assets/js/modules/multiselect.js b/assets/js/multiselect.js similarity index 100% rename from assets/js/modules/multiselect.js rename to assets/js/multiselect.js diff --git a/assets/js/modules/password.js b/assets/js/password.js similarity index 100% rename from assets/js/modules/password.js rename to assets/js/password.js diff --git a/assets/js/modules/photo.js b/assets/js/photo.js similarity index 100% rename from assets/js/modules/photo.js rename to assets/js/photo.js diff --git a/assets/js/modules/search.js b/assets/js/search.js similarity index 100% rename from assets/js/modules/search.js rename to assets/js/search.js diff --git a/assets/js/modules/settings.js b/assets/js/settings.js similarity index 100% rename from assets/js/modules/settings.js rename to assets/js/settings.js diff --git a/assets/js/modules/upload.js b/assets/js/upload.js similarity index 100% rename from assets/js/modules/upload.js rename to assets/js/upload.js diff --git a/assets/js/view.js b/assets/js/view.js index 7d6aa8e..c646189 100644 --- a/assets/js/view.js +++ b/assets/js/view.js @@ -1,112 +1,474 @@ /** - * @name View - * @description Used to view single photos with view.php - * @author Tobias Reich - * @copyright 2014 by Tobias Reich + * @name UI View + * @description Responsible to reflect data changes to the UI. + * @author Tobias Reich + * @copyright 2014 by Tobias Reich */ -var header = $("header"), - headerTitle = $("#title"), - imageview = $("#imageview"), - api_path = "php/api.php", - infobox = $("#infobox"); +view = { -$(document).ready(function(){ + header: { - /* Event Name */ - if (mobileBrowser()) event_name = "touchend"; - else event_name = "click"; + show: function() { - /* Window */ - $(window).keydown(key); + clearTimeout($(window).data("timeout")); - /* Infobox */ - $(document).on(event_name, "#infobox .header a", function() { hideInfobox() }); - $(document).on(event_name, "#infobox_overlay", function() { hideInfobox() }); - $("#button_info").on(event_name, function() { showInfobox() }); + if (visible.photo()) { + lychee.imageview.removeClass("full"); + lychee.loadingBar.css("opacity", 1); + lychee.header.removeClass("hidden"); + if ($("#imageview #image.small").length>0) { + $("#imageview #image").css({ + marginTop: -1*($("#imageview #image").height()/2)+20 + }); + } else { + $("#imageview #image").css({ + top: 60, + right: 30, + bottom: 30, + left: 30 + }); + } + } - /* Direct Link */ - $("#button_direct").on(event_name, function() { + }, - link = $("#imageview #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/ig, ""); - window.open(link,"_newtab"); + hide: function() { - }); + if (visible.photo()&&!visible.infobox()&&!visible.contextMenu()&&!visible.message()) { + clearTimeout($(window).data("timeout")); + $(window).data("timeout", setTimeout(function() { + lychee.imageview.addClass("full"); + lychee.loadingBar.css("opacity", 0); + lychee.header.addClass("hidden"); + if ($("#imageview #image.small").length>0) { + $("#imageview #image").css({ + marginTop: -1*($("#imageview #image").height()/2) + }); + } else { + $("#imageview #image").css({ + top: 0, + right: 0, + bottom: 0, + left: 0 + }); + } + }, 500)); + } - loadPhotoInfo(gup("p")); + }, -}); + mode: function(mode) { -function key(e) { + var albumID = album.getID(); - code = (e.keyCode ? e.keyCode : e.which); - if (code===27&&visibleInfobox()) { hideInfobox(); e.preventDefault(); } + switch (mode) { + case "albums": + lychee.header.removeClass("view"); + $("#tools_album, #tools_photo").hide(); + $("#tools_albums").show(); + break; + case "album": + lychee.header.removeClass("view"); + $("#tools_albums, #tools_photo").hide(); + $("#tools_album").show(); + album.json.content === false ? $("#button_archive").hide() : $("#button_archive").show(); + if (albumID==="s"||albumID==="f") { + $("#button_info_album, #button_trash_album, #button_share_album").hide(); + } else if (albumID==="0") { + $("#button_info_album, #button_share_album").hide(); + $("#button_trash_album").show(); + } else { + $("#button_info_album, #button_trash_album, #button_share_album").show(); + } + break; + case "photo": + lychee.header.addClass("view"); + $("#tools_albums, #tools_album").hide(); + $("#tools_photo").show(); + break; -} + } -function visibleInfobox() { + } - if (parseInt(infobox.css("right").replace("px", ""))<0) return false; - else return true; + }, -} + infobox: { -function isPhotoSmall(photo) { + show: function() { - size = [ - ["width", false], - ["height", false] - ]; + if (!visible.infobox()) $("body").append("
"); + lychee.infobox.addClass("active"); - if (photo.width<$(window).width()-60) size["width"] = true; - if (photo.height<$(window).height()-100) size["height"] = true; + }, - if (size["width"]&&size["height"]) return true; - else return false; + hide: function() { -} + lychee.animate("#infobox_overlay", "fadeOut"); + setTimeout(function() { $("#infobox_overlay").remove() }, 300); + lychee.infobox.removeClass("active"); -function showInfobox() { + } - $("body").append("
"); - infobox.addClass("active"); + }, -} + albums: { -function hideInfobox() { + init: function() { - $("#infobox_overlay").removeClass("fadeIn").addClass("fadeOut"); - setTimeout(function() { $("#infobox_overlay").remove() }, 300); - infobox.removeClass("active"); + view.albums.title(); + view.albums.content.init(); -} + }, -function loadPhotoInfo(photoID) { + title: function() { - params = "function=getPhoto&photoID=" + photoID + "&albumID=0&password=''"; - $.ajax({type: "POST", url: api_path, data: params, dataType: "json", success: function(data) { + lychee.setTitle("Albums", false); - if (!data.title) data.title = "Untitled"; - document.title = "Lychee - " + data.title; - headerTitle.html(data.title); + }, - data.url = "uploads/big/" + data.url; + content: { - imageview.attr("data-id", photoID); - if (isPhotoSmall(data)) imageview.html("
"); - else imageview.html("
"); - imageview.removeClass("fadeOut").addClass("fadeIn").show(); + init: function() { - infobox.html(build.infoboxPhoto(data, true)).show(); + var smartData = "", + albumsData = ""; - }, error: ajaxError }); + /* Smart Albums */ + albums.parse(albums.json.unsortedAlbum); + albums.parse(albums.json.publicAlbum); + albums.parse(albums.json.starredAlbum); + if (!lychee.publicMode) smartData = build.divider("Smart Albums") + build.album(albums.json.unsortedAlbum) + build.album(albums.json.starredAlbum) + build.album(albums.json.publicAlbum); -} + /* Albums */ + if (albums.json.content) { -function ajaxError(jqXHR, textStatus, errorThrown) { + if (!lychee.publicMode) albumsData = build.divider("Albums"); + $.each(albums.json.content, function() { + albums.parse(this); + albumsData += build.album(this); + }); - console.log(jqXHR); - console.log(textStatus); - console.log(errorThrown); + } + + if (smartData===""&&albumsData==="") $("body").append(build.no_content("picture")); + else lychee.content.html(smartData + albumsData); + + $("img[data-type!='svg']").retina(); + + }, + + title: function(albumID) { + + var prefix = "", + longTitle = "", + title = albums.json.content[albumID].title; + + if (albums.json.content[albumID].password) prefix = " "; + if (title.length>18) { + longTitle = title; + title = title.substr(0, 18) + "..."; + } + + $(".album[data-id='" + albumID + "'] .overlay h1") + .html(prefix + title) + .attr("title", longTitle); + + }, + + delete: function(albumID) { + + $(".album[data-id='" + albumID + "']").css("opacity", 0).animate({ + width: 0, + marginLeft: 0 + }, 300, function() { + $(this).remove(); + if (albums.json.num<=0) lychee.animate(".divider:last-of-type", "fadeOut"); + }); + + } + + } + + }, + + album: { + + init: function() { + + album.parse(); + + view.album.infobox(); + view.album.title(); + view.album.public(); + view.album.content.init(); + + album.json.init = 1; + + }, + + hide: function() { + + view.infobox.hide(); + + }, + + title: function() { + + if ((visible.album()||!album.json.init)&&!visible.photo()) { + + switch (album.getID()) { + case "f": + lychee.setTitle("Starred", false); + break; + case "s": + lychee.setTitle("Public", false); + break; + case "0": + lychee.setTitle("Unsorted", false); + break; + default: + if (album.json.init) $("#infobox .attr_name").html(album.json.title + " " + build.editIcon("edit_title_album")); + lychee.setTitle(album.json.title, true); + break; + } + + } + + }, + + description: function() { + + $("#infobox .attr_description").html(album.json.description + " " + build.editIcon("edit_description_album")); + + }, + + content: { + + init: function() { + + var photosData = ""; + + $.each(album.json.content, function() { + album.parse(this); + photosData += build.photo(this); + }); + lychee.content.html(photosData); + + $("img[data-type!='svg']").retina(); + + }, + + title: function(photoID) { + + var longTitle = "", + title = album.json.content[photoID].title; + + if (title.length>18) { + longTitle = title; + title = title.substr(0, 18) + "..."; + } + + $(".photo[data-id='" + photoID + "'] .overlay h1") + .html(title) + .attr("title", longTitle); + + }, + + star: function(photoID) { + + $(".photo[data-id='" + photoID + "'] .icon-star").remove(); + if (album.json.content[photoID].star==1) $(".photo[data-id='" + photoID + "']").append(""); + + }, + + public: function(photoID) { + + $(".photo[data-id='" + photoID + "'] .icon-share").remove(); + if (album.json.content[photoID].public==1) $(".photo[data-id='" + photoID + "']").append(""); + + }, + + delete: function(photoID) { + + $(".photo[data-id='" + photoID + "']").css("opacity", 0).animate({ + width: 0, + marginLeft: 0 + }, 300, function() { + $(this).remove(); + // Only when search is not active + if (!visible.albums()) { + album.json.num--; + view.album.num(); + view.album.title(); + } + }); + + } + + }, + + num: function() { + + $("#infobox .attr_images").html(album.json.num); + + }, + + public: function() { + + if (album.json.public==1) { + $("#button_share_album a").addClass("active"); + $("#button_share_album").attr("title", "Share Album"); + $(".photo .icon-share").remove(); + if (album.json.init) $("#infobox .attr_visibility").html("Public"); + } else { + $("#button_share_album a").removeClass("active"); + $("#button_share_album").attr("title", "Make Public"); + if (album.json.init) $("#infobox .attr_visibility").html("Private"); + } + + }, + + password: function() { + + if (album.json.password==1) $("#infobox .attr_password").html("Yes"); + else $("#infobox .attr_password").html("No"); + + }, + + infobox: function() { + + if ((visible.album()||!album.json.init)&&!visible.photo()) lychee.infobox.html(build.infoboxAlbum(album.json)).show(); + + } + + }, + + photo: { + + init: function() { + + photo.parse(); + + view.photo.infobox(); + view.photo.title(); + view.photo.star(); + view.photo.public(); + view.photo.photo(); + + photo.json.init = 1; + + }, + + show: function() { + + // Change header + lychee.content.addClass("view"); + view.header.mode("photo"); + + // Make body not scrollable + $("body").css("overflow", "hidden"); + + // Fullscreen + $(document) + .bind("mouseenter", view.header.show) + .bind("mouseleave", view.header.hide); + + lychee.animate(lychee.imageview, "fadeIn"); + + }, + + hide: function() { + + if (!visible.controls()) view.header.show(); + if (visible.infobox) view.infobox.hide(); + + lychee.content.removeClass("view"); + view.header.mode("album"); + + // Make body scrollable + $("body").css("overflow", "auto"); + + // Disable Fullscreen + $(document) + .unbind("mouseenter") + .unbind("mouseleave"); + + // Hide Photo + lychee.animate(lychee.imageview, "fadeOut"); + setTimeout(function() { + lychee.imageview.hide(); + view.album.infobox(); + }, 300); + + }, + + title: function() { + + if (photo.json.init) $("#infobox .attr_name").html(photo.json.title + " " + build.editIcon("edit_title")); + lychee.setTitle(photo.json.title, true); + + }, + + description: function() { + + if (photo.json.init) $("#infobox .attr_description").html(photo.json.description + " " + build.editIcon("edit_description")); + + }, + + star: function() { + + $("#button_star a").removeClass("icon-star-empty icon-star"); + if (photo.json.star==1) { + // Starred + $("#button_star a").addClass("icon-star"); + $("#button_star").attr("title", "Unstar Photo"); + } else { + // Unstarred + $("#button_star a").addClass("icon-star-empty"); + $("#button_star").attr("title", "Star Photo"); + } + + }, + + public: function() { + + if (photo.json.public==1||photo.json.public==2) { + // Photo public + $("#button_share a").addClass("active"); + $("#button_share").attr("title", "Share Photo"); + if (photo.json.init) $("#infobox .attr_visibility").html("Public"); + } else { + // Photo private + $("#button_share a").removeClass("active"); + $("#button_share").attr("title", "Make Public"); + if (photo.json.init) $("#infobox .attr_visibility").html("Private"); + } + + }, + + tags: function() { + + $("#infobox #tags").html(build.tags(photo.json.tags)); + + }, + + photo: function() { + + lychee.imageview.html(build.imageview(photo.json, photo.isSmall(), visible.controls())); + + if ((album.json&&album.json.content&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].nextPhoto==="")||lychee.viewMode) $("a#next").hide(); + if ((album.json&&album.json.content&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].previousPhoto==="")||lychee.viewMode) $("a#previous").hide(); + + }, + + infobox: function() { + + lychee.infobox.html(build.infoboxPhoto(photo.json)).show(); + + } + + } } \ No newline at end of file diff --git a/assets/js/view/view.js b/assets/js/view/view.js new file mode 100644 index 0000000..7d6aa8e --- /dev/null +++ b/assets/js/view/view.js @@ -0,0 +1,112 @@ +/** + * @name View + * @description Used to view single photos with view.php + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +var header = $("header"), + headerTitle = $("#title"), + imageview = $("#imageview"), + api_path = "php/api.php", + infobox = $("#infobox"); + +$(document).ready(function(){ + + /* Event Name */ + if (mobileBrowser()) event_name = "touchend"; + else event_name = "click"; + + /* Window */ + $(window).keydown(key); + + /* Infobox */ + $(document).on(event_name, "#infobox .header a", function() { hideInfobox() }); + $(document).on(event_name, "#infobox_overlay", function() { hideInfobox() }); + $("#button_info").on(event_name, function() { showInfobox() }); + + /* Direct Link */ + $("#button_direct").on(event_name, function() { + + link = $("#imageview #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/ig, ""); + window.open(link,"_newtab"); + + }); + + loadPhotoInfo(gup("p")); + +}); + +function key(e) { + + code = (e.keyCode ? e.keyCode : e.which); + if (code===27&&visibleInfobox()) { hideInfobox(); e.preventDefault(); } + +} + +function visibleInfobox() { + + if (parseInt(infobox.css("right").replace("px", ""))<0) return false; + else return true; + +} + +function isPhotoSmall(photo) { + + size = [ + ["width", false], + ["height", false] + ]; + + if (photo.width<$(window).width()-60) size["width"] = true; + if (photo.height<$(window).height()-100) size["height"] = true; + + if (size["width"]&&size["height"]) return true; + else return false; + +} + +function showInfobox() { + + $("body").append("
"); + infobox.addClass("active"); + +} + +function hideInfobox() { + + $("#infobox_overlay").removeClass("fadeIn").addClass("fadeOut"); + setTimeout(function() { $("#infobox_overlay").remove() }, 300); + infobox.removeClass("active"); + +} + +function loadPhotoInfo(photoID) { + + params = "function=getPhoto&photoID=" + photoID + "&albumID=0&password=''"; + $.ajax({type: "POST", url: api_path, data: params, dataType: "json", success: function(data) { + + if (!data.title) data.title = "Untitled"; + document.title = "Lychee - " + data.title; + headerTitle.html(data.title); + + data.url = "uploads/big/" + data.url; + + imageview.attr("data-id", photoID); + if (isPhotoSmall(data)) imageview.html("
"); + else imageview.html("
"); + imageview.removeClass("fadeOut").addClass("fadeIn").show(); + + infobox.html(build.infoboxPhoto(data, true)).show(); + + }, error: ajaxError }); + +} + +function ajaxError(jqXHR, textStatus, errorThrown) { + + console.log(jqXHR); + console.log(textStatus); + console.log(errorThrown); + +} \ No newline at end of file diff --git a/assets/js/modules/visible.js b/assets/js/visible.js similarity index 100% rename from assets/js/modules/visible.js rename to assets/js/visible.js diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..8636adb --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,35 @@ +NO_COLOR=\x1b[0m +OK_COLOR=\x1b[32;01m +ERROR_COLOR=\x1b[31;01m +WARN_COLOR=\x1b[33;01m + +OK_STRING=$(OK_COLOR)[OK]$(NO_COLOR) +ERROR_STRING=$(ERROR_COLOR)[ERRORS]$(NO_COLOR) +RUN_STRING=$(WARN_COLOR)[RUN]$(NO_COLOR) + +ROOT = . +CSS = '$(ROOT)/assets/css' +JS = '$(ROOT)/assets/js' +BUILD = '$(ROOT)/assets/build' + +all: clean create css js + +clean: + rm -f -R $(BUILD) + @echo "$(OK_STRING) Clean build" + +create: clean + mkdir $(BUILD) + @echo "$(OK_STRING) Create build" + +css: create + @echo "$(RUN_STRING) Compiling CSS" + awk 'FNR==1{print ""}1' $(CSS)/*.css > $(BUILD)/main.css + csso $(BUILD)/main.css $(BUILD)/main.css + @echo "$(OK_STRING) CSS compiled" + +js: create + @echo "$(RUN_STRING) Compiling JS" + awk 'FNR==1{print ""}1' $(JS)/*.js > $(BUILD)/main.js + uglifyjs $(BUILD)/main.js -o $(BUILD)/main.js + @echo "$(OK_STRING) JS compiled" \ No newline at end of file diff --git a/docs/compile.sh b/docs/compile.sh deleted file mode 100644 index 5c30e6c..0000000 --- a/docs/compile.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -folderCSS="../assets/css" -folderJS="../assets/js" - -if [ -e "$folderCSS/modules/" ] -then - - echo "Compiling CSS ..." - awk 'FNR==1{print ""}1' $folderCSS/modules/*.css > $folderCSS/min/main.css - csso $folderCSS/min/main.css $folderCSS/min/main.css - echo "CSS compiled!" - -else - - echo "CSS files not found in $folderCSS" - -fi - -if [ -e "$folderJS/modules/" ] -then - - echo "Compiling JS ..." - awk 'FNR==1{print ""}1' $folderJS/modules/*.js > $folderJS/min/main.js - uglifyjs $folderJS/min/main.js -o $folderJS/min/main.js - echo "JS compiled!" - -else - - echo "JS files not found in $folderJS" - -fi \ No newline at end of file diff --git a/index.html b/index.html index 3fbc0ec..fc89321 100644 --- a/index.html +++ b/index.html @@ -9,27 +9,25 @@ - - + - - - - - - - - - - - - - - - - - + + @@ -97,29 +95,27 @@ - - + - - - - - - - - - - - - - - - - - - - + + \ No newline at end of file From 0c4f23108e238d6c6731a77943785d15bde41710 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 23 Feb 2014 16:12:53 +0100 Subject: [PATCH 65/87] Path adjustments --- assets/js/view/{view.js => main.js} | 6 +++--- view.php | 12 +++++------- 2 files changed, 8 insertions(+), 10 deletions(-) rename assets/js/view/{view.js => main.js} (96%) diff --git a/assets/js/view/view.js b/assets/js/view/main.js similarity index 96% rename from assets/js/view/view.js rename to assets/js/view/main.js index 7d6aa8e..1fb584f 100644 --- a/assets/js/view/view.js +++ b/assets/js/view/main.js @@ -1,8 +1,8 @@ /** - * @name View + * @name Main * @description Used to view single photos with view.php - * @author Tobias Reich - * @copyright 2014 by Tobias Reich + * @author Tobias Reich + * @copyright 2014 by Tobias Reich */ var header = $("header"), diff --git a/view.php b/view.php index 62dbf61..a091fa9 100644 --- a/view.php +++ b/view.php @@ -9,10 +9,9 @@ - - + - + @@ -57,10 +56,9 @@
- - - - + + + \ No newline at end of file From faf230a96f5934b0b0c55a49c7533c82120309a3 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 23 Feb 2014 16:59:45 +0100 Subject: [PATCH 66/87] How to build Lychee --- docs/md/Build.md | 20 ++++++++++++++++++++ readme.md | 4 ++++ 2 files changed, 24 insertions(+) create mode 100644 docs/md/Build.md diff --git a/docs/md/Build.md b/docs/md/Build.md new file mode 100644 index 0000000..7fe7d91 --- /dev/null +++ b/docs/md/Build.md @@ -0,0 +1,20 @@ +### Dependencies + +First you have to install the following dependencies: + +- [CSS Optimizer](https://github.com/css/csso) `csso` +- [UglifyJS](https://github.com/mishoo/UglifyJS2) `uglifyjs` + +These dependencies can be installed using `npm`: + + npm install csso uglify-js -g; + +### Build + +The Makefile is located in `docs/` and can be easily executed, using the following command. Make sure your run this from the root of Lychee: + + make -f docs/Makefile + +### Use uncompressed files + +While developing, you might want to use the uncompressed files. This is possible by editing the `index.html`. Simply change the linked CSS and JS files. There are already out-commented link-tags for development and production. \ No newline at end of file diff --git a/readme.md b/readme.md index 12bc480..98b9702 100644 --- a/readme.md +++ b/readme.md @@ -23,6 +23,10 @@ Sign in and click the gear on the top left corner to change your settings. If yo Updating is as easy as it should be. [Update »](docs/md/Update.md) +### Build + +Lychee is ready to use, right out of the box. If you want to contribute and edit CSS or JS files, you need to rebuild Lychee. [Build »](docs/md/Build.md) + ### Keyboard Shortcuts These shortcuts will help you to use Lychee even faster. [Keyboard Shortcuts »](docs/md/Keyboard Shortcuts.md) From 259a623eebe32ad93cadca48dbca1ee712baf6b2 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 23 Feb 2014 17:00:04 +0100 Subject: [PATCH 67/87] Beta-version push (Beta 3) --- assets/js/lychee.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/lychee.js b/assets/js/lychee.js index f61ac2f..0d11ae4 100644 --- a/assets/js/lychee.js +++ b/assets/js/lychee.js @@ -7,7 +7,7 @@ var lychee = { - version: "2.1 b2", + version: "2.1 b3", api_path: "php/api.php", update_path: "http://lychee.electerious.com/version/index.php", From b48321b04e8c3907a5acff4b309bf68aa3396961 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 23 Feb 2014 19:33:00 +0100 Subject: [PATCH 68/87] Development mode --- index.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/index.html b/index.html index fc89321..70a8b65 100644 --- a/index.html +++ b/index.html @@ -9,7 +9,7 @@ - @@ -24,7 +24,7 @@ - --> + @@ -95,7 +95,7 @@ - @@ -112,10 +112,10 @@ - --> + - - + \ No newline at end of file From f0065bbebc0e29ca9551c81ef72805681d63b6aa Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 23 Feb 2014 19:41:12 +0100 Subject: [PATCH 69/87] Improved updating mechanism --- assets/js/lychee.js | 11 ++++++++--- assets/js/settings.js | 4 ++-- php/access/admin.php | 4 +--- php/access/guest.php | 2 +- php/access/installation.php | 4 ++-- php/api.php | 2 +- php/modules/db.php | 9 +++++---- php/modules/misc.php | 17 +++++++++++++++-- php/modules/session.php | 8 ++++++-- 9 files changed, 41 insertions(+), 20 deletions(-) diff --git a/assets/js/lychee.js b/assets/js/lychee.js index 0d11ae4..0ca6d5d 100644 --- a/assets/js/lychee.js +++ b/assets/js/lychee.js @@ -7,7 +7,7 @@ var lychee = { - version: "2.1 b3", + version: "2.1 b4", api_path: "php/api.php", update_path: "http://lychee.electerious.com/version/index.php", @@ -26,6 +26,7 @@ var lychee = { sorting: "", dropbox: false, + dropboxKey: '', loadingBar: $("#loading"), header: $("header"), @@ -35,13 +36,17 @@ var lychee = { init: function() { - lychee.api("init", function(data) { + var params; + + params = "init&version=" + escape(lychee.version); + lychee.api(params, function(data) { if (data.loggedIn!==true) { lychee.setMode("public"); } else { lychee.username = data.config.username; lychee.sorting = data.config.sorting; + lychee.dropboxKey = data.config.dropboxKey; } // No configuration @@ -300,7 +305,7 @@ var lychee = { g.id = "dropboxjs"; g.type = "text/javascript"; g.async = "true"; - g.setAttribute("data-app-key", "iq7lioj9wu0ieqs"); + g.setAttribute("data-app-key", lychee.dropboxKey); g.onload = g.onreadystatechange = function() { var rs = this.readyState; if (rs&&rs!=="complete"&&rs!=="loaded") return; diff --git a/assets/js/settings.js b/assets/js/settings.js index 48716ca..34d0f01 100644 --- a/assets/js/settings.js +++ b/assets/js/settings.js @@ -26,7 +26,7 @@ var settings = { if (dbHost.length<1) dbHost = "localhost"; if (dbName.length<1) dbName = "lychee"; - params = "dbCreateConfig&dbName=" + escape(dbName) + "&dbUser=" + escape(dbUser) + "&dbPassword=" + escape(dbPassword) + "&dbHost=" + escape(dbHost); + params = "dbCreateConfig&dbName=" + escape(dbName) + "&dbUser=" + escape(dbUser) + "&dbPassword=" + escape(dbPassword) + "&dbHost=" + escape(dbHost) + "&version=" + escape(lychee.version); lychee.api(params, function(data) { if (data!==true) { @@ -71,7 +71,7 @@ var settings = { } else { // Configuration successful - lychee.api("update", function(data) { window.location.reload() }); + window.location.reload(); } diff --git a/php/access/admin.php b/php/access/admin.php index c2b1ebe..b1e418f 100644 --- a/php/access/admin.php +++ b/php/access/admin.php @@ -101,7 +101,7 @@ switch ($_POST['function']) { // Session Function - case 'init': echo json_encode(init('admin')); + case 'init': echo json_encode(init('admin', $_POST['version'])); break; case 'login': if (isset($_POST['user'])&&isset($_POST['password'])) @@ -124,8 +124,6 @@ switch ($_POST['function']) { // Miscellaneous - case 'update': echo update(); - default: switch ($_GET['function']) { case 'getFeed': if (isset($_GET['albumID'])) diff --git a/php/access/guest.php b/php/access/guest.php index 6c44b0f..f2acc6a 100644 --- a/php/access/guest.php +++ b/php/access/guest.php @@ -56,7 +56,7 @@ switch ($_POST['function']) { // Session Functions - case 'init': echo json_encode(init('public')); + case 'init': echo json_encode(init('public', $_POST['version'])); break; case 'login': if (isset($_POST['user'])&&isset($_POST['password'])) diff --git a/php/access/installation.php b/php/access/installation.php index 0777972..664c8ab 100644 --- a/php/access/installation.php +++ b/php/access/installation.php @@ -11,8 +11,8 @@ if (!defined('LYCHEE_ACCESS_INSTALLATION')) exit('Error: You are not allowed to switch ($_POST['function']) { - case 'dbCreateConfig': if (isset($_POST['dbHost'])&&isset($_POST['dbUser'])&&isset($_POST['dbPassword'])&&isset($_POST['dbName'])) - echo dbCreateConfig($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName']); + case 'dbCreateConfig': if (isset($_POST['dbHost'])&&isset($_POST['dbUser'])&&isset($_POST['dbPassword'])&&isset($_POST['dbName'])&&isset($_POST['version'])) + echo dbCreateConfig($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['version']); break; default: echo 'Warning: No configuration!'; diff --git a/php/api.php b/php/api.php index cfdfa08..9fefa3a 100755 --- a/php/api.php +++ b/php/api.php @@ -58,7 +58,7 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { // Fallback for switch statement if (!isset($_POST['function'])) $_POST['function'] = ''; if (!isset($_GET['function'])) $_GET['function'] = ''; - + if (isset($_SESSION['login'])&&$_SESSION['login']==true) { /** diff --git a/php/modules/db.php b/php/modules/db.php index 0c9b264..1c2d32c 100755 --- a/php/modules/db.php +++ b/php/modules/db.php @@ -30,7 +30,7 @@ function dbConnect() { } -function dbCreateConfig($dbHost = 'localhost', $dbUser, $dbPassword, $dbName = 'lychee') { +function dbCreateConfig($dbHost = 'localhost', $dbUser, $dbPassword, $dbName = 'lychee', $version) { $dbPassword = urldecode($dbPassword); $database = new mysqli($dbHost, $dbUser, $dbPassword); @@ -43,13 +43,13 @@ $config = "query("SELECT `public` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `public` TINYINT( 1 ) NOT NULL DEFAULT '0'"); if(!$database->query("SELECT `password` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `password` VARCHAR( 100 ) NULL DEFAULT ''"); if(!$database->query("SELECT `description` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `description` VARCHAR( 1000 ) NULL DEFAULT ''"); if($database->query("SELECT `password` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` CHANGE `password` `password` VARCHAR( 100 ) NULL DEFAULT ''"); + // Photos 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 `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/', '')"); + // Settings + $result = $database->query("SELECT `key` FROM `lychee_settings` WHERE `key` = 'dropboxKey' LIMIT 1;"); + if ($result->num_rows===0) $database->query("INSERT INTO `lychee_settings` (`key`, `value`) VALUES ('dropboxKey', '')"); + + // Config + if ($version!==''&&$configVersion!==$version) { + $data = file_get_contents('../data/config.php'); + $data = preg_replace('/\$configVersion = \'[\w. ]*\';/', "\$configVersion = '$version';", $data); + file_put_contents('../data/config.php', $data); + } + return true; } diff --git a/php/modules/session.php b/php/modules/session.php index d86cff0..a8f0498 100755 --- a/php/modules/session.php +++ b/php/modules/session.php @@ -9,9 +9,13 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!'); -function init($mode) { +function init($mode, $version) { - global $settings; + global $settings, $configVersion; + + // Update + if ($configVersion!==$version) + if (!update($version)) exit('Error: Updating the database failed!'); $return['config'] = $settings; unset($return['config']['password']); From 11cfb939b56cd50ee7c9e1e54e973b4b99e14f1f Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Sun, 23 Feb 2014 22:42:15 +0100 Subject: [PATCH 70/87] Edit the Dropbox key (#84) --- assets/js/contextMenu.js | 9 ++++++--- assets/js/lychee.js | 20 ++++++++++++++------ assets/js/settings.js | 32 ++++++++++++++++++++++++++++++++ docs/md/Settings.md | 8 +++++++- php/access/admin.php | 4 ++++ php/api.php | 2 +- php/modules/settings.php | 12 ++++-------- readme.md | 4 ++++ 8 files changed, 72 insertions(+), 19 deletions(-) diff --git a/assets/js/contextMenu.js b/assets/js/contextMenu.js index 83114a0..b98f333 100644 --- a/assets/js/contextMenu.js +++ b/assets/js/contextMenu.js @@ -85,6 +85,7 @@ contextMenu = { contextMenu.fns = [ function() { settings.setLogin() }, function() { settings.setSorting() }, + function() { settings.setDropboxKey() }, function() { window.open(lychee.website, "_newtab"); }, function() { window.open("plugins/check.php", "_newtab"); }, function() { lychee.logout() } @@ -93,10 +94,12 @@ contextMenu = { items = [ [" Change Login", 0], [" Change Sorting", 1], - [" About Lychee", 2], - [" Diagnostics", 3], + [" Set Dropbox", 2], ["separator", -1], - [" Sign Out", 4] + [" About Lychee", 3], + [" Diagnostics", 4], + ["separator", -1], + [" Sign Out", 5] ]; contextMenu.show(items, mouse_x, mouse_y, "right"); diff --git a/assets/js/lychee.js b/assets/js/lychee.js index 0ca6d5d..5fc25b3 100644 --- a/assets/js/lychee.js +++ b/assets/js/lychee.js @@ -7,7 +7,7 @@ var lychee = { - version: "2.1 b4", + version: "2.1 b3", api_path: "php/api.php", update_path: "http://lychee.electerious.com/version/index.php", @@ -44,9 +44,9 @@ var lychee = { if (data.loggedIn!==true) { lychee.setMode("public"); } else { - lychee.username = data.config.username; - lychee.sorting = data.config.sorting; - lychee.dropboxKey = data.config.dropboxKey; + lychee.username = data.config.username || ''; + lychee.sorting = data.config.sorting || ''; + lychee.dropboxKey = data.config.dropboxKey || ''; } // No configuration @@ -294,7 +294,7 @@ var lychee = { loadDropbox: function(callback) { - if (!lychee.dropbox) { + if (!lychee.dropbox&&lychee.dropboxKey) { loadingBar.show(); @@ -315,7 +315,15 @@ var lychee = { }; s.parentNode.insertBefore(g, s); - } else callback(); + } else if (lychee.dropbox&&lychee.dropboxKey) { + + callback(); + + } else { + + settings.setDropboxKey(callback); + + }; }, diff --git a/assets/js/settings.js b/assets/js/settings.js index 34d0f01..7e97a5e 100644 --- a/assets/js/settings.js +++ b/assets/js/settings.js @@ -80,6 +80,7 @@ var settings = { }], ["", function() {}] ]; + modal.show("Configuration", "Enter your database connection details below:
Lychee will create its own database. If required, you can enter the name of an existing database instead:", buttons, -215, false); }, @@ -137,6 +138,7 @@ var settings = { }], ["", function() {}] ]; + modal.show("Create Login", "Enter a username and password for your installation: ", buttons, -122, false); }, @@ -181,6 +183,7 @@ var settings = { }], ["Cancel", function() {}] ]; + modal.show("Change Login", "Enter your current password:
Your username and password will be changed to the following: ", buttons, -171); }, @@ -233,6 +236,35 @@ var settings = { $("select#settings_order").val(sorting[1]); } + }, + + setDropboxKey: function(callback) { + + var buttons, + params, + key; + + buttons = [ + ["Set Key", function() { + + key = $(".message input.text#key").val(); + + params = "setDropboxKey&key=" + key; + lychee.api(params, function(data) { + + if (data===true) { + lychee.dropboxKey = key; + if (callback) lychee.loadDropbox(callback); + } else lychee.error(null, params, data); + + }); + + }], + ["Cancel", function() {}] + ]; + + modal.show("Set Dropbox Key", "In order to import photos from your Dropbox, you need a valid drop-ins app key from their website. Generate yourself a personal key and enter it below: ", buttons); + } } \ No newline at end of file diff --git a/docs/md/Settings.md b/docs/md/Settings.md index adc4c58..5c49c43 100644 --- a/docs/md/Settings.md +++ b/docs/md/Settings.md @@ -38,4 +38,10 @@ If `1`, Lychee will check if you are using the latest version. The notice will b sorting = ORDER BY [row] [ASC|DESC] -A typical part of a MySQL statement. This string will be appended to mostly every MySQL query. \ No newline at end of file +A typical part of a MySQL statement. This string will be appended to mostly every MySQL query. + +#### Dropbox Key + +This key is required to use the Dropbox import feature from your server. Lychee will ask you for this key, the first time you try to use the import. You can get your personal drop-ins app key from [their website](https://www.dropbox.com/developers/apps/create). + + dropboxKey = Your personal App Key \ No newline at end of file diff --git a/php/access/admin.php b/php/access/admin.php index b1e418f..b58536c 100644 --- a/php/access/admin.php +++ b/php/access/admin.php @@ -122,6 +122,10 @@ switch ($_POST['function']) { echo setSorting($_POST['type'], $_POST['order']); break; + case 'setDropboxKey': if (isset($_POST['key'])) + echo setDropboxKey($_POST['key']); + break; + // Miscellaneous default: switch ($_GET['function']) { diff --git a/php/api.php b/php/api.php index 9fefa3a..cfdfa08 100755 --- a/php/api.php +++ b/php/api.php @@ -58,7 +58,7 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) { // Fallback for switch statement if (!isset($_POST['function'])) $_POST['function'] = ''; if (!isset($_GET['function'])) $_GET['function'] = ''; - + if (isset($_SESSION['login'])&&$_SESSION['login']==true) { /** diff --git a/php/modules/settings.php b/php/modules/settings.php index e969ac6..dd8f8cf 100755 --- a/php/modules/settings.php +++ b/php/modules/settings.php @@ -66,22 +66,18 @@ function setPassword($password) { } -/*function setCheckForUpdates() { +function setDropboxKey($key) { global $database; - $result = $database->query("SELECT value FROM lychee_settings WHERE `key` = 'checkForUpdates';"); - $row = $result->fetch_object(); + if (strlen($key)<1||strlen($key)>50) return false; - if ($row->value==0) $checkForUpdates = 1; - else $checkForUpdates = 0; - - $result = $database->query("UPDATE lychee_settings SET value = '$checkForUpdates' WHERE `key` = 'checkForUpdates';"); + $result = $database->query("UPDATE lychee_settings SET value = '$key' WHERE `key` = 'dropboxKey';"); if (!$result) return false; return true; -}*/ +} function setSorting($type, $order) { diff --git a/readme.md b/readme.md index 98b9702..b27cb01 100644 --- a/readme.md +++ b/readme.md @@ -31,6 +31,10 @@ Lychee is ready to use, right out of the box. If you want to contribute and edit These shortcuts will help you to use Lychee even faster. [Keyboard Shortcuts »](docs/md/Keyboard Shortcuts.md) +### Dropbox import + +In order to use the Dropbox import from your server, you need a valid drop-ins app key from [their website](https://www.dropbox.com/developers/apps/create). Lychee will ask you for this key, the first time you try to use the import. Want to change your code? Take a loot at [the settings](docs/md/Settings.md) of Lychee. + ### Twitter Cards Lychee supports [Twitter Cards](https://dev.twitter.com/docs/cards) and [Open Graph](http://opengraphprotocol.org) for shared images (not albums). In order to use Twitter Cards you need to request an approval for your domain. Simply share an image with Lychee, copy its link and paste it in [Twitters Card Validator](https://dev.twitter.com/docs/cards/validation/validator). From f94d3b2eab5338ad0ed62123344653f3dd71006a Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Tue, 25 Feb 2014 18:05:53 +0100 Subject: [PATCH 71/87] Prebuild --- assets/build/main.css | 1 + assets/build/main.js | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 assets/build/main.css create mode 100644 assets/build/main.js diff --git a/assets/build/main.css b/assets/build/main.css new file mode 100644 index 0000000..4babeb5 --- /dev/null +++ b/assets/build/main.css @@ -0,0 +1 @@ +html{font-size:100%}html,body{margin:0;padding:0;border:0;font:inherit;vertical-align:baseline}div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}table{border-collapse:collapse;border-spacing:0}.fadeIn{-webkit-animation-name:fadeIn;-moz-animation-name:fadeIn;animation-name:fadeIn}.fadeIn,.fadeOut{-webkit-animation-duration:.3s;-webkit-animation-fill-mode:forwards;-moz-animation-duration:.3s;-moz-animation-fill-mode:forwards;animation-duration:.3s;animation-fill-mode:forwards}.fadeOut{-webkit-animation-name:fadeOut;-moz-animation-name:fadeOut;animation-name:fadeOut}.contentZoomIn{-webkit-animation-name:zoomIn;-moz-animation-name:zoomIn;animation-name:zoomIn}.contentZoomIn,.contentZoomOut{-webkit-animation-duration:.2s;-webkit-animation-fill-mode:forwards;-moz-animation-duration:.2s;-moz-animation-fill-mode:forwards;animation-duration:.2s;animation-fill-mode:forwards}.contentZoomOut{-webkit-animation-name:zoomOut;-moz-animation-name:zoomOut;animation-name:zoomOut}@-webkit-keyframes moveUp{0%{-webkit-transform:translateY(30px);opacity:0}100%{-webkit-transform:translateY(0);opacity:1}}@-moz-keyframes moveUp{0%{opacity:0}100%{opacity:1}}@keyframes moveUp{0%{transform:translateY(30px);opacity:0}100%{transform:translateY(0);opacity:1}}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-moz-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-moz-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-webkit-keyframes moveBackground{0%{background-position-x:0}100%{background-position-x:-100px}}@-moz-keyframes moveBackground{0%{background-position-x:0}100%{background-position-x:-100px}}@keyframes moveBackground{0%{background-position-x:0}100%{background-position-x:-100px}}@-webkit-keyframes zoomIn{0%{opacity:0;-webkit-transform:scale(.8)}100%{opacity:1;-webkit-transform:scale(1)}}@-moz-keyframes zoomIn{0%{opacity:0}100%{opacity:1}}@keyframes zoomIn{0%{opacity:0;transform:scale(.8)}100%{opacity:1;transform:scale(1)}}@-webkit-keyframes zoomOut{0%{opacity:1;-webkit-transform:scale(1)}100%{opacity:0;-webkit-transform:scale(.8)}}@-moz-keyframes zoomOut{0%{opacity:1}100%{opacity:0}}@keyframes zoomOut{0%{opacity:1;transform:scale(1)}100%{opacity:0;transform:scale(.8)}}@-webkit-keyframes popIn{0%{opacity:0;-webkit-transform:scale(0)}100%{opacity:1;-webkit-transform:scale(1)}}@-moz-keyframes popIn{0%{opacity:0;-moz-transform:scale(0)}100%{opacity:1;-moz-transform:scale(1)}}@keyframes popIn{0%{opacity:0;transform:scale(0)}100%{opacity:1;transform:scale(1)}}@-webkit-keyframes pulse{0%{opacity:1}50%{opacity:.3}100%{opacity:1}}@-moz-keyframes pulse{0%{opacity:1}50%{opacity:.8}100%{opacity:1}}@keyframes pulse{0%{opacity:1}50%{opacity:.8}100%{opacity:1}}#content::before{content:"";position:absolute;left:0;width:100%;height:20px;background-image:-webkit-linear-gradient(top,#262626,#222);background-image:-moz-linear-gradient(top,#262626,#222);background-image:-ms-linear-gradient(top,#262626,#222);background-image:linear-gradient(top,#262626,#222);border-top:1px solid #333}#content.view::before{display:none}#content{position:absolute;padding:50px 0 33px;width:100%;min-height:calc(100% - 90px);-webkit-overflow-scrolling:touch}.photo{float:left;display:inline-block;width:206px;height:206px;margin:30px 0 0 30px;cursor:pointer}.photo img{position:absolute;width:200px;height:200px;background-color:#222;border-radius:2px;border:2px solid #ccc}.photo:hover img,.photo.active img{box-shadow:0 0 5px #005ecc}.photo:active{-webkit-transition-duration:.1s;-webkit-transform:scale(.98);-moz-transition-duration:.1s;-moz-transform:scale(.98);transition-duration:.1s;transform:scale(.98)}.album{float:left;display:inline-block;width:204px;height:204px;margin:30px 0 0 30px;cursor:pointer}.album img:first-child,.album img:nth-child(2){-webkit-transform:rotate(0)translateY(0)translateX(0);-moz-transform:rotate(0)translateY(0)translateX(0);transform:rotate(0)translateY(0)translateX(0);opacity:0}.album:hover img:first-child{-webkit-transform:rotate(-2deg)translateY(10px)translateX(-12px);-moz-transform:rotate(-2deg)translateY(10px)translateX(-12px);transform:rotate(-2deg)translateY(10px)translateX(-12px);opacity:1}.album:hover img:nth-child(2){-webkit-transform:rotate(5deg)translateY(-8px)translateX(12px);-moz-transform:rotate(5deg)translateY(-8px)translateX(12px);transform:rotate(5deg)translateY(-8px)translateX(12px);opacity:1}.album img{position:absolute;width:200px;height:200px;background-color:#222;border-radius:2px;border:2px solid #ccc}.album:hover img,.album.active img{box-shadow:0 0 5px #005ecc}.album .overlay,.photo .overlay{position:absolute;width:200px;height:200px;margin:2px}.album .overlay{background:-moz-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%);background:-webkit-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%);background:-ms-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%);background:linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)20%,rgba(0,0,0,.9)100%)}.photo .overlay{background:-moz-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)60%,rgba(0,0,0,.5)80%,rgba(0,0,0,.9)100%);background:-webkit-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)60%,rgba(0,0,0,.5)80%,rgba(0,0,0,.9)100%);background:-ms-linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)60%,rgba(0,0,0,.5)80%,rgba(0,0,0,.9)100%);background:linear-gradient(top,rgba(0,0,0,0)0%,rgba(0,0,0,0)60%,rgba(0,0,0,.5)80%,rgba(0,0,0,.9)100%);opacity:0}.photo:hover .overlay,.photo.active .overlay{opacity:1}.album .overlay h1,.photo .overlay h1{min-height:19px;width:190px;margin:153px 0 3px 15px;color:#fff;font-size:16px;font-weight:700;overflow:hidden}.album .overlay a,.photo .overlay a{font-size:11px;color:#aaa}.album .overlay a{margin-left:15px}.photo .overlay a{margin:155px 0 5px 15px}.album .badge,.photo .badge{position:absolute;margin-top:-1px;margin-left:12px;padding:12px 7px 3px;box-shadow:0 0 3px #000;border-radius:0 0 3px 3px;border:1px solid #fff;border-top:none;color:#fff;font-size:24px;text-shadow:0 1px 0 #000;opacity:.9}.album .badge.icon-star,.photo .badge.icon-star{padding:12px 8px 3px}.album .badge.icon-share,.photo .badge.icon-share{padding:12px 6px 3px 8px}.album .badge::after,.photo .badge::after{content:"";position:absolute;margin-top:-12px;margin-left:-26px;width:38px;height:5px;background:-moz-linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);background:-webkit-linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);background:-ms-linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);background:linear-gradient(top,rgba(0,0,0,1)0%,rgba(0,0,0,0)100%);opacity:.4}.album .badge.icon-star::after,.photo .badge.icon-star::after{margin-left:-29px}.album .badge.icon-share::after,.photo .badge.icon-share::after{margin-left:-31px}.album .badge.icon-reorder::after{margin-left:-30px}.album .badge:nth-child(2n),.photo .badge:nth-child(2n){margin-left:57px}.album .badge.red,.photo .badge.red{background:#d64b4b;background:-webkit-linear-gradient(top,#d64b4b,#ab2c2c);background:-moz-linear-gradient(top,#d64b4b,#ab2c2c);background:-ms-linear-gradient(top,#d64b4b,#ab2c2c)}.album .badge.blue,.photo .badge.blue{background:#d64b4b;background:-webkit-linear-gradient(top,#347cd6,#2945ab);background:-moz-linear-gradient(top,#347cd6,#2945ab);background:-ms-linear-gradient(top,#347cd6,#2945ab)}.divider{float:left;width:100%;margin-top:50px;opacity:0;border-top:1px solid #2E2E2E;box-shadow:0 -1px 0 #151515}.divider:first-child{margin-top:0;border-top:none}.divider h1{float:left;margin:20px 0 0 30px;color:#fff;font-size:14px;font-weight:700;text-shadow:0 -1px 0 #000}.no_content{position:absolute;top:50%;left:50%;height:160px;width:180px;margin-top:-80px;margin-left:-90px;padding-top:20px;color:rgba(20,20,20,1);text-shadow:0 1px 0 rgba(255,255,255,.05);text-align:center}.no_content .icon{font-size:120px}.no_content p{font-size:18px}.contextmenu_bg{position:fixed;height:100%;width:100%;z-index:1000}.contextmenu{position:fixed;top:0;left:0;padding:5px 0 6px;background-color:#393939;background-image:-webkit-linear-gradient(top,#444,#2d2d2d);background-image:-moz-linear-gradient(top,#393939,#2d2d2d);background-image:-ms-linear-gradient(top,#393939,#2d2d2d);background-image:linear-gradient(top,#393939,#2d2d2d);border:1px solid rgba(0,0,0,.7);border-bottom:1px solid rgba(0,0,0,.9);border-radius:5px;box-shadow:0 4px 5px rgba(0,0,0,.3),inset 0 1px 0 rgba(255,255,255,.15),inset 1px 0 0 rgba(255,255,255,.05),inset -1px 0 0 rgba(255,255,255,.05);opacity:0;z-index:1001;-webkit-transition:none;-moz-transition:none;transition:none}.contextmenu tr{font-size:14px;color:#eee;text-shadow:0 -1px 0 rgba(0,0,0,.6);cursor:pointer}.contextmenu tr:hover{background-color:#6a84f2;background-image:-webkit-linear-gradient(top,#6a84f2,#3959ef);background-image:-moz-linear-gradient(top,#6a84f2,#3959ef);background-image:-ms-linear-gradient(top,#6a84f2,#3959ef);background-image:linear-gradient(top,#6a84f2,#3959ef)}.contextmenu tr.no_hover:hover{cursor:inherit;background-color:inherit;background-image:none}.contextmenu tr.separator{float:left;height:1px;width:100%;background-color:#1c1c1c;border-bottom:1px solid #4a4a4a;margin:5px 0;cursor:inherit}.contextmenu tr.separator:hover{background-color:#222;background-image:none}.contextmenu tr td{padding:7px 30px 6px 12px;white-space:nowrap;-webkit-transition:none;-moz-transition:none;transition:none}.contextmenu tr:hover td{color:#fff;box-shadow:inset 0 1px 0 rgba(255,255,255,.05);text-shadow:0 -1px 0 rgba(0,0,0,.4)}.contextmenu tr.no_hover:hover td{box-shadow:none}.contextmenu tr a{float:left;width:10px;margin-right:10px;text-align:center}.contextmenu #link{float:right;width:140px;margin:0 -17px -1px 0;padding:4px 6px 5px;background-color:#444;color:#fff;border:1px solid #111;box-shadow:0 1px 0 rgba(255,255,255,.1);outline:none;border-radius:5px}.contextmenu tr a#link_icon{padding-top:4px}@font-face{font-family:'FontAwesome';src:url('../font/fontawesome-webfont.eot');src:url('../font/fontawesome-webfont.eot?#iefix') format('eot'),url('../font/fontawesome-webfont.woff') format('woff'),url('../font/fontawesome-webfont.ttf') format('truetype'),url('../font/fontawesome-webfont.svg#FontAwesome') format('svg');font-weight:400;font-style:normal}[class^="icon-"]:before,[class*=" icon-"]:before{font-family:FontAwesome;font-weight:400;font-style:normal;display:inline-block;text-decoration:inherit}a [class^="icon-"],a [class*=" icon-"]{display:inline-block;text-decoration:inherit}.icon-large:before{vertical-align:top;font-size:1.3333333333333333em}.btn [class^="icon-"],.btn [class*=" icon-"]{line-height:.9em}li [class^="icon-"],li [class*=" icon-"]{display:inline-block;width:1.25em;text-align:center}li .icon-large[class^="icon-"],li .icon-large[class*=" icon-"]{width:1.875em}li[class^="icon-"],li[class*=" icon-"]{margin-left:0;list-style-type:none}li[class^="icon-"]:before,li[class*=" icon-"]:before{text-indent:-2em;text-align:center}li[class^="icon-"].icon-large:before,li[class*=" icon-"].icon-large:before{text-indent:-1.3333333333333333em}.icon-glass:before{content:"\f000"}.icon-music:before{content:"\f001"}.icon-search:before{content:"\f002"}.icon-envelope:before{content:"\f003"}.icon-heart:before{content:"\f004"}.icon-star:before{content:"\f005"}.icon-star-empty:before{content:"\f006"}.icon-user:before{content:"\f007"}.icon-film:before{content:"\f008"}.icon-th-large:before{content:"\f009"}.icon-th:before{content:"\f00a"}.icon-th-list:before{content:"\f00b"}.icon-ok:before{content:"\f00c"}.icon-remove:before{content:"\f00d"}.icon-zoom-in:before{content:"\f00e"}.icon-zoom-out:before{content:"\f010"}.icon-off:before{content:"\f011"}.icon-signal:before{content:"\f012"}.icon-cog:before{content:"\f013"}.icon-trash:before{content:"\f014"}.icon-home:before{content:"\f015"}.icon-file:before{content:"\f016"}.icon-time:before{content:"\f017"}.icon-road:before{content:"\f018"}.icon-download-alt:before{content:"\f019"}.icon-download:before{content:"\f01a"}.icon-upload:before{content:"\f01b"}.icon-inbox:before{content:"\f01c"}.icon-play-circle:before{content:"\f01d"}.icon-repeat:before{content:"\f01e"}.icon-refresh:before{content:"\f021"}.icon-list-alt:before{content:"\f022"}.icon-lock:before{content:"\f023"}.icon-flag:before{content:"\f024"}.icon-headphones:before{content:"\f025"}.icon-volume-off:before{content:"\f026"}.icon-volume-down:before{content:"\f027"}.icon-volume-up:before{content:"\f028"}.icon-qrcode:before{content:"\f029"}.icon-barcode:before{content:"\f02a"}.icon-tag:before{content:"\f02b"}.icon-tags:before{content:"\f02c"}.icon-book:before{content:"\f02d"}.icon-bookmark:before{content:"\f02e"}.icon-print:before{content:"\f02f"}.icon-camera:before{content:"\f030"}.icon-font:before{content:"\f031"}.icon-bold:before{content:"\f032"}.icon-italic:before{content:"\f033"}.icon-text-height:before{content:"\f034"}.icon-text-width:before{content:"\f035"}.icon-align-left:before{content:"\f036"}.icon-align-center:before{content:"\f037"}.icon-align-right:before{content:"\f038"}.icon-align-justify:before{content:"\f039"}.icon-list:before{content:"\f03a"}.icon-indent-left:before{content:"\f03b"}.icon-indent-right:before{content:"\f03c"}.icon-facetime-video:before{content:"\f03d"}.icon-picture:before{content:"\f03e"}.icon-pencil:before{content:"\f040"}.icon-map-marker:before{content:"\f041"}.icon-adjust:before{content:"\f042"}.icon-tint:before{content:"\f043"}.icon-edit:before{content:"\f044"}.icon-share:before{content:"\f045"}.icon-check:before{content:"\f046"}.icon-move:before{content:"\f047"}.icon-step-backward:before{content:"\f048"}.icon-fast-backward:before{content:"\f049"}.icon-backward:before{content:"\f04a"}.icon-play:before{content:"\f04b"}.icon-pause:before{content:"\f04c"}.icon-stop:before{content:"\f04d"}.icon-forward:before{content:"\f04e"}.icon-fast-forward:before{content:"\f050"}.icon-step-forward:before{content:"\f051"}.icon-eject:before{content:"\f052"}.icon-chevron-left:before{content:"\f053"}.icon-chevron-right:before{content:"\f054"}.icon-plus-sign:before{content:"\f055"}.icon-minus-sign:before{content:"\f056"}.icon-remove-sign:before{content:"\f057"}.icon-ok-sign:before{content:"\f058"}.icon-question-sign:before{content:"\f059"}.icon-info-sign:before{content:"\f05a"}.icon-screenshot:before{content:"\f05b"}.icon-remove-circle:before{content:"\f05c"}.icon-ok-circle:before{content:"\f05d"}.icon-ban-circle:before{content:"\f05e"}.icon-arrow-left:before{content:"\f060"}.icon-arrow-right:before{content:"\f061"}.icon-arrow-up:before{content:"\f062"}.icon-arrow-down:before{content:"\f063"}.icon-share-alt:before{content:"\f064"}.icon-resize-full:before{content:"\f065"}.icon-resize-small:before{content:"\f066"}.icon-plus:before{content:"\f067"}.icon-minus:before{content:"\f068"}.icon-asterisk:before{content:"\f069"}.icon-exclamation-sign:before{content:"\f06a"}.icon-gift:before{content:"\f06b"}.icon-leaf:before{content:"\f06c"}.icon-fire:before{content:"\f06d"}.icon-eye-open:before{content:"\f06e"}.icon-eye-close:before{content:"\f070"}.icon-warning-sign:before{content:"\f071"}.icon-plane:before{content:"\f072"}.icon-calendar:before{content:"\f073"}.icon-random:before{content:"\f074"}.icon-comment:before{content:"\f075"}.icon-magnet:before{content:"\f076"}.icon-chevron-up:before{content:"\f077"}.icon-chevron-down:before{content:"\f078"}.icon-retweet:before{content:"\f079"}.icon-shopping-cart:before{content:"\f07a"}.icon-folder-close:before{content:"\f07b"}.icon-folder-open:before{content:"\f07c"}.icon-resize-vertical:before{content:"\f07d"}.icon-resize-horizontal:before{content:"\f07e"}.icon-bar-chart:before{content:"\f080"}.icon-twitter-sign:before{content:"\f081"}.icon-facebook-sign:before{content:"\f082"}.icon-camera-retro:before{content:"\f083"}.icon-key:before{content:"\f084"}.icon-cogs:before{content:"\f085"}.icon-comments:before{content:"\f086"}.icon-thumbs-up:before{content:"\f087"}.icon-thumbs-down:before{content:"\f088"}.icon-star-half:before{content:"\f089"}.icon-heart-empty:before{content:"\f08a"}.icon-signout:before{content:"\f08b"}.icon-linkedin-sign:before{content:"\f08c"}.icon-pushpin:before{content:"\f08d"}.icon-external-link:before{content:"\f08e"}.icon-signin:before{content:"\f090"}.icon-trophy:before{content:"\f091"}.icon-github-sign:before{content:"\f092"}.icon-upload-alt:before{content:"\f093"}.icon-lemon:before{content:"\f094"}.icon-phone:before{content:"\f095"}.icon-check-empty:before{content:"\f096"}.icon-bookmark-empty:before{content:"\f097"}.icon-phone-sign:before{content:"\f098"}.icon-twitter:before{content:"\f099"}.icon-facebook:before{content:"\f09a"}.icon-github:before{content:"\f09b"}.icon-unlock:before{content:"\f09c"}.icon-credit-card:before{content:"\f09d"}.icon-rss:before{content:"\f09e"}.icon-hdd:before{content:"\f0a0"}.icon-bullhorn:before{content:"\f0a1"}.icon-bell:before{content:"\f0a2"}.icon-certificate:before{content:"\f0a3"}.icon-hand-right:before{content:"\f0a4"}.icon-hand-left:before{content:"\f0a5"}.icon-hand-up:before{content:"\f0a6"}.icon-hand-down:before{content:"\f0a7"}.icon-circle-arrow-left:before{content:"\f0a8"}.icon-circle-arrow-right:before{content:"\f0a9"}.icon-circle-arrow-up:before{content:"\f0aa"}.icon-circle-arrow-down:before{content:"\f0ab"}.icon-globe:before{content:"\f0ac"}.icon-wrench:before{content:"\f0ad"}.icon-tasks:before{content:"\f0ae"}.icon-filter:before{content:"\f0b0"}.icon-briefcase:before{content:"\f0b1"}.icon-fullscreen:before{content:"\f0b2"}.icon-group:before{content:"\f0c0"}.icon-link:before{content:"\f0c1"}.icon-cloud:before{content:"\f0c2"}.icon-beaker:before{content:"\f0c3"}.icon-cut:before{content:"\f0c4"}.icon-copy:before{content:"\f0c5"}.icon-paper-clip:before{content:"\f0c6"}.icon-save:before{content:"\f0c7"}.icon-sign-blank:before{content:"\f0c8"}.icon-reorder:before{content:"\f0c9"}.icon-list-ul:before{content:"\f0ca"}.icon-list-ol:before{content:"\f0cb"}.icon-strikethrough:before{content:"\f0cc"}.icon-underline:before{content:"\f0cd"}.icon-table:before{content:"\f0ce"}.icon-magic:before{content:"\f0d0"}.icon-truck:before{content:"\f0d1"}.icon-pinterest:before{content:"\f0d2"}.icon-pinterest-sign:before{content:"\f0d3"}.icon-google-plus-sign:before{content:"\f0d4"}.icon-google-plus:before{content:"\f0d5"}.icon-money:before{content:"\f0d6"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.icon-columns:before{content:"\f0db"}.icon-sort:before{content:"\f0dc"}.icon-sort-down:before{content:"\f0dd"}.icon-sort-up:before{content:"\f0de"}.icon-envelope-alt:before{content:"\f0e0"}.icon-linkedin:before{content:"\f0e1"}.icon-undo:before{content:"\f0e2"}.icon-legal:before{content:"\f0e3"}.icon-dashboard:before{content:"\f0e4"}.icon-comment-alt:before{content:"\f0e5"}.icon-comments-alt:before{content:"\f0e6"}.icon-bolt:before{content:"\f0e7"}.icon-sitemap:before{content:"\f0e8"}.icon-umbrella:before{content:"\f0e9"}.icon-paste:before{content:"\f0ea"}.icon-user-md:before{content:"\f200"}header{position:fixed;height:49px;width:100%;background-image:-webkit-linear-gradient(top,#3E3E3E,#282828);background-image:-moz-linear-gradient(top,#3E3E3E,#282828);background-image:-ms-linear-gradient(top,#3E3E3E,#282828);background-image:linear-gradient(top,#3E3E3E,#282828);border-bottom:1px solid #161616;z-index:1;-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;transition:transform .3s ease-out}header.hidden{-webkit-transform:translateY(-60px);-moz-transform:translateY(-60px);transform:translateY(-60px)}header.loading{-webkit-transform:translateY(2px);-moz-transform:translateY(2px);transform:translateY(2px)}header.error{-webkit-transform:translateY(40px);-moz-transform:translateY(40px);transform:translateY(40px)}header.view.error{background-color:rgba(10,10,10,.99)}header.view{background-image:none;border-bottom:none}header.view .button,header.view #title,header.view .tools{text-shadow:none!important}header #title{position:absolute;margin:0 30%;width:40%;padding:15px 0;color:#fff;font-size:16px;font-weight:700;text-align:center;text-shadow:0 -1px 0 #222}header #title.editable{cursor:pointer}header .button{color:#888;font-family:'FontAwesome';font-size:21px;font-weight:700;text-decoration:none!important;cursor:pointer;text-shadow:0 -1px 0 #222}header .button.left{float:left;position:absolute;padding:16px 10px 8px 18px}header .button.right{float:right;position:relative;padding:16px 19px 13px 11px}header .button:hover{color:#fff}header #tools_albums,header #tools_album,header #tools_photo,header #button_signin{display:none}header .button_divider{float:right;position:relative;width:14px;height:50px}header #search{float:right;width:80px;margin:12px 12px 0 0;padding:5px 12px 6px;background-color:#383838;color:#fff;border:1px solid #131313;box-shadow:0 1px 0 rgba(255,255,255,.1);outline:none;border-radius:50px;opacity:.6;-webkit-transition:opacity .3s ease-out,-webkit-transform .3s ease-out,box-shadow .3s,width .2s ease-out;-moz-transition:opacity .3s ease-out,-moz-transform .3s ease-out,box-shadow .3s,width .2s ease-out;transition:opacity .3s ease-out,transform .3s ease-out,box-shadow .3s,width .2s ease-out}header #search:focus{width:140px}header #search:focus~#clearSearch{opacity:1}header #clearSearch{position:absolute;top:15px;right:81px;padding:0;font-size:20px;opacity:0;-webkit-transition:opacity .2s ease-out;-moz-transition:opacity .2s ease-out;transition:opacity .2s ease-out}header #clearSearch:hover{opacity:1}header .tools:first-of-type{margin-right:6px}header .tools{float:right;padding:14px 8px;color:#888;font-size:21px;text-shadow:0 -1px 0 #222;cursor:pointer}header .tools:hover a{color:#fff}header .tools .icon-star{color:#f0ef77}header .tools .icon-share.active{color:#ff9737}header #hostedwith{float:right;padding:5px 10px;margin:13px 9px;color:#888;font-size:13px;text-shadow:0 -1px 0 #222;display:none;cursor:pointer}header #hostedwith:hover{background-color:rgba(0,0,0,.2);border-radius:100px}#imageview{position:fixed;display:none;width:100%;min-height:100%;background-color:rgba(10,10,10,.99);-webkit-transition:background-color .3s}#imageview.view{background-color:inherit}#imageview.full{background-color:#040404}#imageview #image{position:absolute;top:60px;right:30px;bottom:30px;left:30px;background-repeat:no-repeat;background-position:50% 50%;background-size:contain;-webkit-transition:top .3s,bottom .3s,margin-top .3s;-webkit-animation-name:zoomIn;-webkit-animation-duration:.3s;-moz-animation-name:zoomIn;-moz-animation-duration:.3s;animation-name:zoomIn;animation-duration:.3s}#imageview #image.small{top:50%;right:auto;bottom:auto;left:50%}#imageview .arrow_wrapper{position:fixed;width:20%;height:calc(100% - 60px);top:60px;z-index:1}#imageview .arrow_wrapper.previous{left:0}#imageview .arrow_wrapper.next{right:0}#imageview .arrow_wrapper a{position:fixed;top:50%;margin-top:-10px;color:#fff;font-size:50px;text-shadow:0 1px 2px #000;cursor:pointer;opacity:0;z-index:2;-webkit-transition:opacity .2s;-moz-transition:opacity .2s;transition:opacity .2s}#imageview .arrow_wrapper:hover a{opacity:.2}#imageview .arrow_wrapper a#previous{left:20px}#imageview .arrow_wrapper a#next{right:20px}#infobox_overlay{z-index:3;position:fixed;width:100%;height:100%;top:0;left:0;background-color:rgba(0,0,0,.85)}#infobox{z-index:4;position:fixed;right:0;width:300px;height:100%;background-color:rgba(20,20,20,.98);box-shadow:-1px 0 2px rgba(0,0,0,.8);display:none;-webkit-transform:translateX(320px);-moz-transform:translateX(320px);transform:translateX(320px);-webkit-transition:-webkit-transform .5s cubic-bezier(.225,.5,.165,1);-moz-transition:-moz-transform .5s cubic-bezier(.225,.5,.165,1);transition:transform .5s cubic-bezier(.225,.5,.165,1)}#infobox.active{-webkit-transform:translateX(0);-moz-transform:translateX(0);transform:translateX(0)}#infobox .wrapper{float:left;height:100%;overflow:scroll}#infobox .edit{display:inline;margin-left:3px;width:20px;height:5px;cursor:pointer}#infobox .bumper{float:left;width:100%;height:50px}#infobox .header{float:left;height:49px;width:100%;background-color:#1d1d1d;background-image:-webkit-linear-gradient(top,#2A2A2A,#131313);background-image:-moz-linear-gradient(top,#2A2A2A,#131313);background-image:-ms-linear-gradient(top,#2A2A2A,#131313);background-image:linear-gradient(top,#2A2A2A,#131313);border-bottom:1px solid #000}#infobox .header h1{position:absolute;margin:15px 30%;width:40%;font-size:16px;text-align:center}#infobox .header h1,#infobox .header a{color:#fff;font-weight:700;text-shadow:0 -1px 0 #000}#infobox .header a{float:right;padding:15px;font-size:20px;opacity:.5;cursor:pointer}#infobox .header a:hover{opacity:1}#infobox .separator{float:left;width:100%;border-top:1px solid rgba(255,255,255,.04);box-shadow:0 -1px 0 #000}#infobox .separator h1{margin:20px 0 5px 20px;color:#fff;font-size:14px;font-weight:700;text-shadow:0 -1px 0 #000}#infobox table{float:left;margin:10px 0 15px 20px}#infobox table tr td{padding:5px 0;color:#fff;font-size:14px;line-height:19px;-webkit-user-select:text;-moz-user-select:text;user-select:text}#infobox table tr td:first-child{width:110px}#infobox table tr td:last-child{padding-right:10px}#infobox #tags{width:calc(100% - 40px);margin:16px 20px 12px;color:#fff;display:inline-block}#infobox #tags .empty{font-size:14px;margin-bottom:8px}#infobox #tags .edit{display:inline-block}#infobox #tags .empty .edit{display:inline}#infobox .tag{float:left;padding:4px 7px;margin:0 6px 8px 0;background-color:rgba(0,0,0,.5);border:2px solid rgba(255,255,255,.3);border-radius:100px;font-size:12px;-webkit-transition:border .3s;-moz-transition:border .3s;transition:border .3s}#infobox .tag:hover{border:2px solid #aaa}#infobox .tag span{float:right;width:0;padding:0;margin:0 0 -2px;color:red;font-size:11px;cursor:pointer;overflow:hidden;-webkit-transform:scale(0);transform:scale(0);-webkit-transition:width .3s,margin .3s,-webkit-transform .3s;-moz-transition:width .3s,margin .3s;transition:width .3s,margin .3s,transform .3s}#infobox .tag:hover span{width:10px;margin:0 0 -2px 6px;-webkit-transform:scale(1);transform:scale(1)}#loading{position:fixed;width:100%;height:3px;background-size:100px 3px;background-repeat:repeat-x;border-bottom:1px solid rgba(0,0,0,.3);display:none;-webkit-animation-name:moveBackground;-webkit-animation-duration:.3s;-webkit-animation-iteration-count:infinite;-webkit-animation-timing-function:linear;-moz-animation-name:moveBackground;-moz-animation-duration:.3s;-moz-animation-iteration-count:infinite;-moz-animation-timing-function:linear;animation-name:moveBackground;animation-duration:.3s;animation-iteration-count:infinite;animation-timing-function:linear}#loading.loading{background-image:-webkit-linear-gradient(left,#153674 0%,#153674 47%,#2651AE 53%,#2651AE 100%);background-image:-moz-linear-gradient(left,#153674 0%,#153674 47%,#2651AE 53%,#2651AE 100%);background-image:linear-gradient(left right,#153674 0%,#153674 47%,#2651AE 53%,#2651AE 100%);z-index:2}#loading.error{background-color:#2f0d0e;background-image:-webkit-linear-gradient(left,#451317 0%,#451317 47%,#AA3039 53%,#AA3039 100%);background-image:-moz-linear-gradient(left,#451317 0%,#451317 47%,#AA3039 53%,#AA3039 100%);background-image:linear-gradient(left right,#451317 0%,#451317 47%,#AA3039 53%,#AA3039 100%);z-index:1}#loading h1{margin:13px;color:#ddd;font-size:14px;font-weight:700;text-shadow:0 1px 0 #000;text-transform:capitalize}#loading h1 span{margin-left:10px;font-weight:400;text-transform:none}@media only screen and (max-width:900px){#title{width:40%!important}#title,#title.view{margin:0 20%!important}#title.view{width:60%!important}#title span{display:none!important}}@media only screen and (max-width:640px){#title{display:none!important}#title.view{display:block!important;width:70%!important;margin:0 20% 0 10%!important}#button_move,#button_archive{display:none!important}.center{top:0!important;left:0!important}.album,.photo{margin:40px 0 0 50px!important}.message{position:fixed!important;width:100%!important;height:100%!important;margin:1px 0 0!important;border-radius:0!important;-webkit-animation:moveUp .3s!important;-moz-animation:moveUp .3s!important;animation:moveUp .3s!important}.upload_message{top:50%!important;left:50%!important}}.message_overlay{position:fixed;width:100%;height:100%;top:0;left:0;background-color:rgba(0,0,0,.85);z-index:1000}.message{position:absolute;display:inline-block;width:500px;margin-left:-250px;margin-top:-95px;background-color:#444;background-image:-webkit-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-moz-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-ms-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:linear-gradient(top,#4b4b4b ,#2d2d2d);border-radius:5px;box-shadow:0 0 5px #000,inset 0 1px 0 rgba(255,255,255,.08),inset 1px 0 0 rgba(255,255,255,.03),inset -1px 0 0 rgba(255,255,255,.03);-webkit-animation-name:moveUp;-webkit-animation-duration:.3s;-webkit-animation-timing-function:ease-out;-moz-animation-name:moveUp;-moz-animation-duration:.3s;-moz-animation-timing-function:ease-out;animation-name:moveUp;animation-duration:.3s;animation-timing-function:ease-out}.message h1{float:left;width:100%;padding:12px 0;color:#fff;font-size:16px;font-weight:700;text-shadow:0 -1px 0 #222;text-align:center}.message .close{position:absolute;top:0;right:0;padding:12px 14px 6px 7px;color:#aaa;font-size:20px;text-shadow:0 -1px 0 #222;cursor:pointer}.message .close:hover{color:#fff}.message p{float:left;width:90%;margin-top:1px;padding:12px 5% 15px;color:#eee;font-size:14px;text-shadow:0 -1px 0 #222;line-height:20px}.message p b{font-weight:700}.message p a{color:#eee;text-decoration:none;border-bottom:1px dashed #888}.message .button{float:right;margin:15px 15px 15px 0;padding:6px 10px 8px;background-color:#4e4e4e;background-image:-webkit-linear-gradient(top,#3c3c3c ,#2d2d2d);background-image:-moz-linear-gradient(top,#3c3c3c ,#2d2d2d);background-image:-ms-linear-gradient(top,#3c3c3c ,#2d2d2d);background-image:linear-gradient(top,#3c3c3c ,#2d2d2d);color:#ccc;font-size:14px;font-weight:700;text-align:center;text-shadow:0 -1px 0 #222;border-radius:5px;border:1px solid #191919;box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);cursor:pointer}.message .button:first-of-type{margin:15px 5% 18px 0!important}.message .button.active{color:#fff;box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1),0 0 4px #005ecc}.message .button:hover{background-color:#565757;background-image:-webkit-linear-gradient(top,#505050 ,#393939);background-image:-moz-linear-gradient(top,#505050 ,#393939);background-image:-ms-linear-gradient(top,#505050 ,#393939);background-image:linear-gradient(top,#505050 ,#393939)}.message .button:active,.message .button.pressed{background-color:#393939;background-image:-webkit-linear-gradient(top,#393939 ,#464646);background-image:-moz-linear-gradient(top,#393939 ,#464646);background-image:-ms-linear-gradient(top,#393939 ,#464646);background-image:linear-gradient(top,#393939 ,#464646)}.sign_in{width:100%;margin-top:1px;padding:5px 0;color:#eee;font-size:14px;line-height:20px}.sign_in,.sign_in input{float:left;text-shadow:0 -1px 0 #222}.sign_in input{width:88%;padding:7px 1% 9px;margin:0 5%;background-color:transparent;color:#fff;border:none;border-bottom:1px solid #222;box-shadow:0 1px 0 rgba(255,255,255,.1);border-radius:0;outline:none}.sign_in input:first-of-type{margin-bottom:10px}.sign_in input.error:focus{box-shadow:0 1px 0 rgba(204,0,7,.6)}.message #version{display:inline-block;margin-top:23px;margin-left:5%;color:#888;text-shadow:0 -1px 0 #111}.message #version span{display:none}.message #version span a{color:#888}.message input.text{float:left;width:calc(100% - 10px);padding:17px 5px 9px;margin-top:10px;background-color:transparent;color:#fff;text-shadow:0 -1px 0 #222;border:none;box-shadow:0 1px 0 rgba(255,255,255,.1);border-bottom:1px solid #222;border-radius:0;outline:none}.message input.less{margin-bottom:-10px}.message input.more{margin-bottom:30px}.message .copylink{margin-bottom:20px}html,body{min-height:100%}body{background-color:#222;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:12px;-webkit-font-smoothing:antialiased;-moz-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-smoothing:antialiased}body.view{background-color:#0f0f0f}.center{position:absolute;left:50%;top:50%}*{-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-transition:color .3s,opacity .3s ease-out,-webkit-transform .3s ease-out,box-shadow .3s;-moz-transition:opacity .3s ease-out,-moz-transform .3s ease-out,box-shadow .3s;transition:color .3s,opacity .3s ease-out,transform .3s ease-out,box-shadow .3s}input{-webkit-user-select:text!important;-moz-user-select:text!important;user-select:text!important}#multiselect{position:absolute;background-color:rgba(0,94,204,.3);border:1px solid rgba(0,94,204,1);border-radius:3px;z-index:3}.tipsy{padding:4px;font-size:12px;position:absolute;z-index:100000;-webkit-animation-name:fadeIn;-webkit-animation-duration:.3s;-moz-animation-name:fadeIn;-moz-animation-duration:.3s;animation-name:fadeIn;animation-duration:.3s}.tipsy-inner{padding:8px 10px 7px;color:#fff;max-width:200px;text-align:center;background:rgba(0,0,0,.8);border-radius:25px}.tipsy-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed rgba(0,0,0,.8)}.tipsy-arrow-n{border-bottom-color:rgba(0,0,0,.8)}.tipsy-arrow-s{border-top-color:rgba(0,0,0,.8)}.tipsy-arrow-e{border-left-color:rgba(0,0,0,.8)}.tipsy-arrow-w{border-right-color:rgba(0,0,0,.8)}.tipsy-n .tipsy-arrow{left:50%;margin-left:-5px}.tipsy-n .tipsy-arrow,.tipsy-nw .tipsy-arrow{top:0;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.tipsy-nw .tipsy-arrow{left:10px}.tipsy-ne .tipsy-arrow{top:0;right:10px;border-bottom-style:solid;border-top:none}.tipsy-ne .tipsy-arrow,.tipsy-s .tipsy-arrow{border-left-color:transparent;border-right-color:transparent}.tipsy-s .tipsy-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:none}.tipsy-sw .tipsy-arrow{left:10px}.tipsy-sw .tipsy-arrow,.tipsy-se .tipsy-arrow{bottom:0;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.tipsy-se .tipsy-arrow{right:10px}.tipsy-e .tipsy-arrow{right:0;border-left-style:solid;border-right:none}.tipsy-e .tipsy-arrow,.tipsy-w .tipsy-arrow{top:50%;margin-top:-5px;border-top-color:transparent;border-bottom-color:transparent}.tipsy-w .tipsy-arrow{left:0;border-right-style:solid;border-left:none}#upload{display:none}.upload_overlay{position:fixed;width:100%;height:100%;top:0;left:0;background-color:rgba(0,0,0,.85);z-index:1000}.upload_message{position:absolute;display:inline-block;width:200px;margin-left:-100px;margin-top:-85px;background-color:#444;background-image:-webkit-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-moz-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:-ms-linear-gradient(top,#4b4b4b ,#2d2d2d);background-image:linear-gradient(top,#4b4b4b ,#2d2d2d);border-radius:5px;box-shadow:0 0 5px #000,inset 0 1px 0 rgba(255,255,255,.08),inset 1px 0 0 rgba(255,255,255,.03),inset -1px 0 0 rgba(255,255,255,.03);-webkit-animation-name:moveUp;-webkit-animation-duration:.3s;-webkit-animation-timing-function:ease-out;-moz-animation-name:moveUp;-moz-animation-duration:.3s;-moz-animation-timing-function:ease-out;animation-name:moveUp;animation-duration:.3s;animation-timing-function:ease-out}.upload_message a{margin:35px 0 5px;font-size:70px;text-shadow:0 1px 2px rgba(0,0,0,.5);-webkit-animation-name:pulse;-webkit-animation-duration:2s;-webkit-animation-timing-function:ease-in-out;-webkit-animation-iteration-count:infinite;-moz-animation-name:pulse;-moz-animation-duration:2s;-moz-animation-timing-function:ease-in-out;-moz-animation-iteration-count:infinite;animation-name:pulse;animation-duration:2s;animation-timing-function:ease-in-out;animation-iteration-count:infinite}.upload_message a,.upload_message p{float:left;width:100%;color:#fff;text-align:center}.upload_message p{margin:10px 0 35px;font-size:14px;text-shadow:0 -1px 0 rgba(0,0,0,.5)}.upload_message .progressbar{float:left;width:170px;height:25px;margin:15px;background-size:50px 25px;background-repeat:repeat-x;background-image:-webkit-linear-gradient(left,#191919 0%,#191919 47%,#1D1D1D 53%,#1D1D1D 100%);background-image:-moz-linear-gradient(left,#191919 0%,#191919 47%,#1D1D1D 53%,#1D1D1D 100%);background-image:linear-gradient(left right,#191919 0%,#191919 47%,#1D1D1D 53%,#1D1D1D 100%);border:1px solid #090909;box-shadow:0 1px 0 rgba(255,255,255,.06),inset 0 0 2px #222;border-radius:50px;-webkit-animation-name:moveBackground;-webkit-animation-duration:1s;-webkit-animation-timing-function:linear;-webkit-animation-iteration-count:infinite;-moz-animation-name:moveBackground;-moz-animation-duration:1s;-moz-animation-timing-function:linear;-moz-animation-iteration-count:infinite;animation-name:moveBackground;animation-duration:1s;animation-timing-function:linear;animation-iteration-count:infinite}.upload_message .progressbar div{float:left;width:0%;height:100%;box-shadow:0 1px 0 #000,1px 0 2px #000;background-color:#f5f2f7;background-image:-webkit-linear-gradient(top,#f5f2f7,#c7c6c8);background-image:-moz-linear-gradient(top,#f5f2f7,#c7c6c8);background-image:-ms-linear-gradient(top,#f5f2f7,#c7c6c8);background-image:linear-gradient(top,#f5f2f7,#c7c6c8);border-radius:50px;-webkit-transition:width .2s,opacity .5;-moz-transition:width .2s,opacity .5;transition:width .2s,opacity .5} \ No newline at end of file diff --git a/assets/build/main.js b/assets/build/main.js new file mode 100644 index 0000000..24415e3 --- /dev/null +++ b/assets/build/main.js @@ -0,0 +1,6 @@ +(function(e,undefined){var t,n,r=typeof undefined,i=e.location,o=e.document,s=o.documentElement,a=e.jQuery,u=e.$,l={},c=[],p="2.0.3",f=c.concat,h=c.push,d=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,x=function(e,n){return new x.fn.init(e,n,t)},b=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^-ms-/,N=/-([\da-z])/gi,E=function(e,t){return t.toUpperCase()},S=function(){o.removeEventListener("DOMContentLoaded",S,!1),e.removeEventListener("load",S,!1),x.ready()};x.fn=x.prototype={jquery:p,constructor:x,init:function(e,t,n){var r,i;if(!e)return this;if("string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:T.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof x?t[0]:t,x.merge(this,x.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:o,!0)),C.test(r[1])&&x.isPlainObject(t))for(r in t)x.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=o.getElementById(r[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?n.ready(e):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return d.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,t,n,r,i,o,s=arguments[0]||{},a=1,u=arguments.length,l=!1;for("boolean"==typeof s&&(l=s,s=arguments[1]||{},a=2),"object"==typeof s||x.isFunction(s)||(s={}),u===a&&(s=this,--a);u>a;a++)if(null!=(e=arguments[a]))for(t in e)n=s[t],r=e[t],s!==r&&(l&&r&&(x.isPlainObject(r)||(i=x.isArray(r)))?(i?(i=!1,o=n&&x.isArray(n)?n:[]):o=n&&x.isPlainObject(n)?n:{},s[t]=x.extend(l,o,r)):r!==undefined&&(s[t]=r));return s},x.extend({expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=a),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){(e===!0?--x.readyWait:x.isReady)||(x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(o,[x]),x.fn.trigger&&x(o).trigger("ready").off("ready")))},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray,isWindow:function(e){return null!=e&&e===e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if("object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}return!0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:JSON.parse,parseXML:function(e){var t,n;if(!e||"string"!=typeof e)return null;try{n=new DOMParser,t=n.parseFromString(e,"text/xml")}catch(r){t=undefined}return(!t||t.getElementsByTagName("parsererror").length)&&x.error("Invalid XML: "+e),t},noop:function(){},globalEval:function(e){var t,n=eval;e=x.trim(e),e&&(1===e.indexOf("use strict")?(t=o.createElement("script"),t.text=e,o.head.appendChild(t).parentNode.removeChild(t)):n(e))},camelCase:function(e){return e.replace(k,"ms-").replace(N,E)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,s=j(e);if(n){if(s){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(s){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:function(e){return null==e?"":v.call(e)},makeArray:function(e,t){var n=t||[];return null!=e&&(j(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:g.call(t,e,n)},merge:function(e,t){var n=t.length,r=e.length,i=0;if("number"==typeof n)for(;n>i;i++)e[r++]=t[i];else while(t[i]!==undefined)e[r++]=t[i++];return e.length=r,e},grep:function(e,t,n){var r,i=[],o=0,s=e.length;for(n=!!n;s>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,s=j(e),a=[];if(s)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(a[a.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(a[a.length]=r);return f.apply([],a)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(n=e[t],t=e,e=n),x.isFunction(e)?(r=d.call(arguments,2),i=function(){return e.apply(t||this,r.concat(d.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):undefined},access:function(e,t,n,r,i,o,s){var a=0,u=e.length,l=null==n;if("object"===x.type(n)){i=!0;for(a in n)x.access(e,t,a,n[a],!0,o,s)}else if(r!==undefined&&(i=!0,x.isFunction(r)||(s=!0),l&&(s?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(x(e),n)})),t))for(;u>a;a++)t(e[a],n,s?r:r.call(e[a],a,t(e[a],n)));return i?e:l?t.call(e):u?t(e[0],n):o},now:Date.now,swap:function(e,t,n,r){var i,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=s[o];return i}}),x.ready.promise=function(t){return n||(n=x.Deferred(),"complete"===o.readyState?setTimeout(x.ready):(o.addEventListener("DOMContentLoaded",S,!1),e.addEventListener("load",S,!1))),n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function j(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}t=x(o),function(e,undefined){var t,n,r,i,o,s,a,u,l,c,p,f,h,d,g,m,y,v="sizzle"+-new Date,b=e.document,w=0,T=0,C=st(),k=st(),N=st(),E=!1,S=function(e,t){return e===t?(E=!0,0):0},j=typeof undefined,D=1<<31,A={}.hasOwnProperty,L=[],q=L.pop,H=L.push,O=L.push,F=L.slice,P=L.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",W="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",$=W.replace("w","w#"),B="\\["+M+"*("+W+")"+M+"*(?:([*^$|!~]?=)"+M+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+$+")|)|)"+M+"*\\]",I=":("+W+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+B.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=RegExp("^"+M+"*,"+M+"*"),X=RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=RegExp(M+"*[+~]"),Y=RegExp("="+M+"*([^\\]'\"]*)"+M+"*\\]","g"),V=RegExp(I),G=RegExp("^"+$+"$"),J={ID:RegExp("^#("+W+")"),CLASS:RegExp("^\\.("+W+")"),TAG:RegExp("^("+W.replace("w","w*")+")"),ATTR:RegExp("^"+B),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:RegExp("^(?:"+R+")$","i"),needsContext:RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Q=/^[^{]+\{\s*\[native \w/,K=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,Z=/^(?:input|select|textarea|button)$/i,et=/^h\d$/i,tt=/'|\\/g,nt=RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),rt=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{O.apply(L=F.call(b.childNodes),b.childNodes),L[b.childNodes.length].nodeType}catch(it){O={apply:L.length?function(e,t){H.apply(e,F.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function ot(e,t,r,i){var o,s,a,u,l,f,g,m,x,w;if((t?t.ownerDocument||t:b)!==p&&c(t),t=t||p,r=r||[],!e||"string"!=typeof e)return r;if(1!==(u=t.nodeType)&&9!==u)return[];if(h&&!i){if(o=K.exec(e))if(a=o[1]){if(9===u){if(s=t.getElementById(a),!s||!s.parentNode)return r;if(s.id===a)return r.push(s),r}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(a))&&y(t,s)&&s.id===a)return r.push(s),r}else{if(o[2])return O.apply(r,t.getElementsByTagName(e)),r;if((a=o[3])&&n.getElementsByClassName&&t.getElementsByClassName)return O.apply(r,t.getElementsByClassName(a)),r}if(n.qsa&&(!d||!d.test(e))){if(m=g=v,x=t,w=9===u&&e,1===u&&"object"!==t.nodeName.toLowerCase()){f=gt(e),(g=t.getAttribute("id"))?m=g.replace(tt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",l=f.length;while(l--)f[l]=m+mt(f[l]);x=U.test(e)&&t.parentNode||t,w=f.join(",")}if(w)try{return O.apply(r,x.querySelectorAll(w)),r}catch(T){}finally{g||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,r,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>i.cacheLength&&delete t[e.shift()],t[n]=r}return t}function at(e){return e[v]=!0,e}function ut(e){var t=p.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function lt(e,t){var n=e.split("|"),r=e.length;while(r--)i.attrHandle[n[r]]=t}function ct(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function pt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return at(function(t){return t=+t,at(function(n,r){var i,o=e([],n.length,t),s=o.length;while(s--)n[i=o[s]]&&(n[i]=!(r[i]=n[i]))})})}s=ot.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},n=ot.support={},c=ot.setDocument=function(e){var t=e?e.ownerDocument||e:b,r=t.defaultView;return t!==p&&9===t.nodeType&&t.documentElement?(p=t,f=t.documentElement,h=!s(t),r&&r.attachEvent&&r!==r.top&&r.attachEvent("onbeforeunload",function(){c()}),n.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ut(function(e){return e.appendChild(t.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=ut(function(e){return e.innerHTML="
",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),n.getById=ut(function(e){return f.appendChild(e).id=v,!t.getElementsByName||!t.getElementsByName(v).length}),n.getById?(i.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){return e.getAttribute("id")===t}}):(delete i.find.ID,i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=n.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==j?t.getElementsByTagName(e):undefined}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.CLASS=n.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==j&&h?t.getElementsByClassName(e):undefined},g=[],d=[],(n.qsa=Q.test(t.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll(":checked").length||d.push(":checked")}),ut(function(e){var n=t.createElement("input");n.setAttribute("type","hidden"),e.appendChild(n).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&d.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||d.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),d.push(",.*:")})),(n.matchesSelector=Q.test(m=f.webkitMatchesSelector||f.mozMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&ut(function(e){n.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",I)}),d=d.length&&RegExp(d.join("|")),g=g.length&&RegExp(g.join("|")),y=Q.test(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},S=f.compareDocumentPosition?function(e,r){if(e===r)return E=!0,0;var i=r.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(r);return i?1&i||!n.sortDetached&&r.compareDocumentPosition(e)===i?e===t||y(b,e)?-1:r===t||y(b,r)?1:l?P.call(l,e)-P.call(l,r):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,n){var r,i=0,o=e.parentNode,s=n.parentNode,a=[e],u=[n];if(e===n)return E=!0,0;if(!o||!s)return e===t?-1:n===t?1:o?-1:s?1:l?P.call(l,e)-P.call(l,n):0;if(o===s)return ct(e,n);r=e;while(r=r.parentNode)a.unshift(r);r=n;while(r=r.parentNode)u.unshift(r);while(a[i]===u[i])i++;return i?ct(a[i],u[i]):a[i]===b?-1:u[i]===b?1:0},t):p},ot.matches=function(e,t){return ot(e,null,null,t)},ot.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Y,"='$1']"),!(!n.matchesSelector||!h||g&&g.test(t)||d&&d.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return ot(t,p,null,[e]).length>0},ot.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},ot.attr=function(e,t){(e.ownerDocument||e)!==p&&c(e);var r=i.attrHandle[t.toLowerCase()],o=r&&A.call(i.attrHandle,t.toLowerCase())?r(e,t,!h):undefined;return o===undefined?n.attributes||!h?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null:o},ot.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},ot.uniqueSort=function(e){var t,r=[],i=0,o=0;if(E=!n.detectDuplicates,l=!n.sortStable&&e.slice(0),e.sort(S),E){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return e},o=ot.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=ot.selectors={cacheLength:50,createPseudo:at,match:J,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(nt,rt),e[3]=(e[4]||e[5]||"").replace(nt,rt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ot.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ot.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return J.CHILD.test(e[0])?null:(e[3]&&e[4]!==undefined?e[2]=e[4]:n&&V.test(n)&&(t=gt(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(nt,rt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=C[e+" "];return t||(t=RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&C(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ot.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,h,d,g=o!==s?"nextSibling":"previousSibling",m=t.parentNode,y=a&&t.nodeName.toLowerCase(),x=!u&&!a;if(m){if(o){while(g){p=t;while(p=p[g])if(a?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;d=g="only"===e&&!d&&"nextSibling"}return!0}if(d=[s?m.firstChild:m.lastChild],s&&x){c=m[v]||(m[v]={}),l=c[e]||[],h=l[0]===w&&l[1],f=l[0]===w&&l[2],p=h&&m.childNodes[h];while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[w,h,f];break}}else if(x&&(l=(t[v]||(t[v]={}))[e])&&l[0]===w)f=l[1];else while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if((a?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(x&&((p[v]||(p[v]={}))[e]=[w,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||ot.error("unsupported pseudo: "+e);return r[v]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?at(function(e,n){var i,o=r(e,t),s=o.length;while(s--)i=P.call(e,o[s]),e[i]=!(n[i]=o[s])}):function(e){return r(e,0,n)}):r}},pseudos:{not:at(function(e){var t=[],n=[],r=a(e.replace(z,"$1"));return r[v]?at(function(e,t,n,i){var o,s=r(e,null,i,[]),a=e.length;while(a--)(o=s[a])&&(e[a]=!(t[a]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:at(function(e){return function(t){return ot(e,t).length>0}}),contains:at(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:at(function(e){return G.test(e||"")||ot.error("unsupported lang: "+e),e=e.replace(nt,rt).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return et.test(e.nodeName)},input:function(e){return Z.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},i.pseudos.nth=i.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[t]=pt(t);for(t in{submit:!0,reset:!0})i.pseudos[t]=ft(t);function dt(){}dt.prototype=i.filters=i.pseudos,i.setFilters=new dt;function gt(e,t){var n,r,o,s,a,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);a=e,u=[],l=i.preFilter;while(a){(!n||(r=_.exec(a)))&&(r&&(a=a.slice(r[0].length)||a),u.push(o=[])),n=!1,(r=X.exec(a))&&(n=r.shift(),o.push({value:n,type:r[0].replace(z," ")}),a=a.slice(n.length));for(s in i.filter)!(r=J[s].exec(a))||l[s]&&!(r=l[s](r))||(n=r.shift(),o.push({value:n,type:s,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?ot.error(e):k(e,u).slice(0)}function mt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function yt(e,t,n){var i=t.dir,o=n&&"parentNode"===i,s=T++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,a){var u,l,c,p=w+" "+s;if(a){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,a))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[v]||(t[v]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,a)||r,l[1]===!0)return!0}}function vt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,s=[],a=0,u=e.length,l=null!=t;for(;u>a;a++)(o=e[a])&&(!n||n(o,r,i))&&(s.push(o),l&&t.push(a));return s}function bt(e,t,n,r,i,o){return r&&!r[v]&&(r=bt(r)),i&&!i[v]&&(i=bt(i,o)),at(function(o,s,a,u){var l,c,p,f=[],h=[],d=s.length,g=o||Ct(t||"*",a.nodeType?[a]:a,[]),m=!e||!o&&t?g:xt(g,f,e,a,u),y=n?i||(o?e:d||r)?[]:s:m;if(n&&n(m,y,a,u),r){l=xt(y,h),r(l,[],a,u),c=l.length;while(c--)(p=l[c])&&(y[h[c]]=!(m[h[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?P.call(o,p):f[c])>-1&&(o[l]=!(s[l]=p))}}else y=xt(y===s?y.splice(d,y.length):y),i?i(null,s,y,u):O.apply(s,y)})}function wt(e){var t,n,r,o=e.length,s=i.relative[e[0].type],a=s||i.relative[" "],l=s?1:0,c=yt(function(e){return e===t},a,!0),p=yt(function(e){return P.call(t,e)>-1},a,!0),f=[function(e,n,r){return!s&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>l;l++)if(n=i.relative[e[l].type])f=[yt(vt(f),n)];else{if(n=i.filter[e[l].type].apply(null,e[l].matches),n[v]){for(r=++l;o>r;r++)if(i.relative[e[r].type])break;return bt(l>1&&vt(f),l>1&&mt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&wt(e.slice(l,r)),o>r&&wt(e=e.slice(r)),o>r&&mt(e))}f.push(n)}return vt(f)}function Tt(e,t){var n=0,o=t.length>0,s=e.length>0,a=function(a,l,c,f,h){var d,g,m,y=[],v=0,x="0",b=a&&[],T=null!=h,C=u,k=a||s&&i.find.TAG("*",h&&l.parentNode||l),N=w+=null==C?1:Math.random()||.1;for(T&&(u=l!==p&&l,r=n);null!=(d=k[x]);x++){if(s&&d){g=0;while(m=e[g++])if(m(d,l,c)){f.push(d);break}T&&(w=N,r=++n)}o&&((d=!m&&d)&&v--,a&&b.push(d))}if(v+=x,o&&x!==v){g=0;while(m=t[g++])m(b,y,l,c);if(a){if(v>0)while(x--)b[x]||y[x]||(y[x]=q.call(f));y=xt(y)}O.apply(f,y),T&&!a&&y.length>0&&v+t.length>1&&ot.uniqueSort(f)}return T&&(w=N,u=C),b};return o?at(a):a}a=ot.compile=function(e,t){var n,r=[],i=[],o=N[e+" "];if(!o){t||(t=gt(e)),n=t.length;while(n--)o=wt(t[n]),o[v]?r.push(o):i.push(o);o=N(e,Tt(i,r))}return o};function Ct(e,t,n){var r=0,i=t.length;for(;i>r;r++)ot(e,t[r],n);return n}function kt(e,t,r,o){var s,u,l,c,p,f=gt(e);if(!o&&1===f.length){if(u=f[0]=f[0].slice(0),u.length>2&&"ID"===(l=u[0]).type&&n.getById&&9===t.nodeType&&h&&i.relative[u[1].type]){if(t=(i.find.ID(l.matches[0].replace(nt,rt),t)||[])[0],!t)return r;e=e.slice(u.shift().value.length)}s=J.needsContext.test(e)?0:u.length;while(s--){if(l=u[s],i.relative[c=l.type])break;if((p=i.find[c])&&(o=p(l.matches[0].replace(nt,rt),U.test(u[0].type)&&t.parentNode||t))){if(u.splice(s,1),e=o.length&&mt(u),!e)return O.apply(r,o),r;break}}}return a(e,f)(o,t,!h,r,U.test(e)),r}n.sortStable=v.split("").sort(S).join("")===v,n.detectDuplicates=E,c(),n.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(p.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||lt("type|href|height|width",function(e,t,n){return n?undefined:e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||lt("value",function(e,t,n){return n||"input"!==e.nodeName.toLowerCase()?undefined:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||lt(R,function(e,t,n){var r;return n?undefined:(r=e.getAttributeNode(t))&&r.specified?r.value:e[t]===!0?t.toLowerCase():null}),x.find=ot,x.expr=ot.selectors,x.expr[":"]=x.expr.pseudos,x.unique=ot.uniqueSort,x.text=ot.getText,x.isXMLDoc=ot.isXML,x.contains=ot.contains}(e);var D={};function A(e){var t=D[e]={};return x.each(e.match(w)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?D[e]||A(e):x.extend({},e);var t,n,r,i,o,s,a=[],u=!e.once&&[],l=function(p){for(t=e.memory&&p,n=!0,s=i||0,i=0,o=a.length,r=!0;a&&o>s;s++)if(a[s].apply(p[0],p[1])===!1&&e.stopOnFalse){t=!1;break}r=!1,a&&(u?u.length&&l(u.shift()):t?a=[]:c.disable())},c={add:function(){if(a){var n=a.length;(function s(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&c.has(n)||a.push(n):n&&n.length&&"string"!==r&&s(n)})})(arguments),r?o=a.length:t&&(i=n,l(t))}return this},remove:function(){return a&&x.each(arguments,function(e,t){var n;while((n=x.inArray(t,a,n))>-1)a.splice(n,1),r&&(o>=n&&o--,s>=n&&s--)}),this},has:function(e){return e?x.inArray(e,a)>-1:!(!a||!a.length)},empty:function(){return a=[],o=0,this},disable:function(){return a=u=t=undefined,this},disabled:function(){return!a},lock:function(){return u=undefined,t||c.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!a||n&&!u||(t=t||[],t=[e,t.slice?t.slice():t],r?u.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var s=o[0],a=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var s=o[2],a=o[3];r[o[1]]=s.add,a&&s.add(function(){n=a},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=s.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=d.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),s=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?d.call(arguments):r,n===a?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},a,u,l;if(r>1)for(a=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(s(t,l,n)).fail(o.reject).progress(s(t,u,a)):--i;return i||o.resolveWith(l,n),o.promise()}}),x.support=function(t){var n=o.createElement("input"),r=o.createDocumentFragment(),i=o.createElement("div"),s=o.createElement("select"),a=s.appendChild(o.createElement("option"));return n.type?(n.type="checkbox",t.checkOn=""!==n.value,t.optSelected=a.selected,t.reliableMarginRight=!0,t.boxSizingReliable=!0,t.pixelPosition=!1,n.checked=!0,t.noCloneChecked=n.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!a.disabled,n=o.createElement("input"),n.value="t",n.type="radio",t.radioValue="t"===n.value,n.setAttribute("checked","t"),n.setAttribute("name","t"),r.appendChild(n),t.checkClone=r.cloneNode(!0).cloneNode(!0).lastChild.checked,t.focusinBubbles="onfocusin"in e,i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===i.style.backgroundClip,x(function(){var n,r,s="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",a=o.getElementsByTagName("body")[0];a&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",a.appendChild(n).appendChild(i),i.innerHTML="",i.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",x.swap(a,null!=a.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===i.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(i,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(i,null)||{width:"4px"}).width,r=i.appendChild(o.createElement("div")),r.style.cssText=i.style.cssText=s,r.style.marginRight=r.style.width="0",i.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),a.removeChild(n))}),t):t}({});var L,q,H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,O=/([A-Z])/g;function F(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=x.expando+Math.random()}F.uid=1,F.accepts=function(e){return e.nodeType?1===e.nodeType||9===e.nodeType:!0},F.prototype={key:function(e){if(!F.accepts(e))return 0;var t={},n=e[this.expando];if(!n){n=F.uid++;try{t[this.expando]={value:n},Object.defineProperties(e,t)}catch(r){t[this.expando]=n,x.extend(e,t)}}return this.cache[n]||(this.cache[n]={}),n},set:function(e,t,n){var r,i=this.key(e),o=this.cache[i];if("string"==typeof t)o[t]=n;else if(x.isEmptyObject(o))x.extend(this.cache[i],t);else for(r in t)o[r]=t[r];return o},get:function(e,t){var n=this.cache[this.key(e)];return t===undefined?n:n[t]},access:function(e,t,n){var r;return t===undefined||t&&"string"==typeof t&&n===undefined?(r=this.get(e,t),r!==undefined?r:this.get(e,x.camelCase(t))):(this.set(e,t,n),n!==undefined?n:t)},remove:function(e,t){var n,r,i,o=this.key(e),s=this.cache[o];if(t===undefined)this.cache[o]={};else{x.isArray(t)?r=t.concat(t.map(x.camelCase)):(i=x.camelCase(t),t in s?r=[t,i]:(r=i,r=r in s?[r]:r.match(w)||[])),n=r.length;while(n--)delete s[r[n]]}},hasData:function(e){return!x.isEmptyObject(this.cache[e[this.expando]]||{})},discard:function(e){e[this.expando]&&delete this.cache[e[this.expando]]}},L=new F,q=new F,x.extend({acceptData:F.accepts,hasData:function(e){return L.hasData(e)||q.hasData(e)},data:function(e,t,n){return L.access(e,t,n)},removeData:function(e,t){L.remove(e,t)},_data:function(e,t,n){return q.access(e,t,n)},_removeData:function(e,t){q.remove(e,t)}}),x.fn.extend({data:function(e,t){var n,r,i=this[0],o=0,s=null;if(e===undefined){if(this.length&&(s=L.get(i),1===i.nodeType&&!q.get(i,"hasDataAttrs"))){for(n=i.attributes;n.length>o;o++)r=n[o].name,0===r.indexOf("data-")&&(r=x.camelCase(r.slice(5)),P(i,r,s[r]));q.set(i,"hasDataAttrs",!0)}return s}return"object"==typeof e?this.each(function(){L.set(this,e)}):x.access(this,function(t){var n,r=x.camelCase(e);if(i&&t===undefined){if(n=L.get(i,e),n!==undefined)return n;if(n=L.get(i,r),n!==undefined)return n;if(n=P(i,r,undefined),n!==undefined)return n}else this.each(function(){var n=L.get(this,r);L.set(this,r,t),-1!==e.indexOf("-")&&n!==undefined&&L.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){L.remove(this,e)})}});function P(e,t,n){var r;if(n===undefined&&1===e.nodeType)if(r="data-"+t.replace(O,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:H.test(n)?JSON.parse(n):n}catch(i){}L.set(e,t,n)}else n=undefined;return n}x.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=q.get(e,t),n&&(!r||x.isArray(n)?r=q.access(e,t,x.makeArray(n)):r.push(n)),r||[]):undefined},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),s=function(){x.dequeue(e,t) +};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,s,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return q.get(e,n)||q.access(e,n,{empty:x.Callbacks("once memory").add(function(){q.remove(e,[t+"queue",n])})})}}),x.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),n>arguments.length?x.queue(this[0],e):t===undefined?this:this.each(function(){var n=x.queue(this,e,t);x._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=x.Deferred(),o=this,s=this.length,a=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=undefined),e=e||"fx";while(s--)n=q.get(o[s],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(a));return a(),i.promise(t)}});var R,M,W=/[\t\r\n\f]/g,$=/\r/g,B=/^(?:input|select|textarea|button)$/i;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[x.propFix[e]||e]})},addClass:function(e){var t,n,r,i,o,s=0,a=this.length,u="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,s=0,a=this.length,u=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,i=0,o=x(this),s=e.match(w)||[];while(t=s[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===r||"boolean"===n)&&(this.className&&q.set(this,"__className__",this.className),this.className=this.className||e===!1?"":q.get(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(W," ").indexOf(t)>=0)return!0;return!1},val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=x.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,x(this).val()):e,null==i?i="":"number"==typeof i?i+="":x.isArray(i)&&(i=x.map(i,function(e){return null==e?"":e+""})),t=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&t.set(this,i,"value")!==undefined||(this.value=i))});if(i)return t=x.valHooks[i.type]||x.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&(n=t.get(i,"value"))!==undefined?n:(n=i.value,"string"==typeof n?n.replace($,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,s=o?null:[],a=o?i+1:r.length,u=0>i?a:o?i:0;for(;a>u;u++)if(n=r[u],!(!n.selected&&u!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),s=i.length;while(s--)r=i[s],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,t,n){var i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===r?x.prop(e,t,n):(1===s&&x.isXMLDoc(e)||(t=t.toLowerCase(),i=x.attrHooks[t]||(x.expr.match.bool.test(t)?M:R)),n===undefined?i&&"get"in i&&null!==(o=i.get(e,t))?o:(o=x.find.attr(e,t),null==o?undefined:o):null!==n?i&&"set"in i&&(o=i.set(e,n,t))!==undefined?o:(e.setAttribute(t,n+""),n):(x.removeAttr(e,t),undefined))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)&&(e[r]=!1),e.removeAttribute(n)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return o=1!==s||!x.isXMLDoc(e),o&&(t=x.propFix[t]||t,i=x.propHooks[t]),n!==undefined?i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){return e.hasAttribute("tabindex")||B.test(e.nodeName)||e.href?e.tabIndex:-1}}}}),M={set:function(e,t,n){return t===!1?x.removeAttr(e,n):e.setAttribute(n,n),n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,t){var n=x.expr.attrHandle[t]||x.find.attr;x.expr.attrHandle[t]=function(e,t,r){var i=x.expr.attrHandle[t],o=r?undefined:(x.expr.attrHandle[t]=undefined)!=n(e,t,r)?t.toLowerCase():null;return x.expr.attrHandle[t]=i,o}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,t){return x.isArray(t)?e.checked=x.inArray(x(e).val(),t)>=0:undefined}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var I=/^key/,z=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,X=/^([^.]*)(?:\.(.+)|)$/;function U(){return!0}function Y(){return!1}function V(){try{return o.activeElement}catch(e){}}x.event={global:{},add:function(e,t,n,i,o){var s,a,u,l,c,p,f,h,d,g,m,y=q.get(e);if(y){n.handler&&(s=n,n=s.handler,o=s.selector),n.guid||(n.guid=x.guid++),(l=y.events)||(l=y.events={}),(a=y.handle)||(a=y.handle=function(e){return typeof x===r||e&&x.event.triggered===e.type?undefined:x.event.dispatch.apply(a.elem,arguments)},a.elem=e),t=(t||"").match(w)||[""],c=t.length;while(c--)u=X.exec(t[c])||[],d=m=u[1],g=(u[2]||"").split(".").sort(),d&&(f=x.event.special[d]||{},d=(o?f.delegateType:f.bindType)||d,f=x.event.special[d]||{},p=x.extend({type:d,origType:m,data:i,handler:n,guid:n.guid,selector:o,needsContext:o&&x.expr.match.needsContext.test(o),namespace:g.join(".")},s),(h=l[d])||(h=l[d]=[],h.delegateCount=0,f.setup&&f.setup.call(e,i,g,a)!==!1||e.addEventListener&&e.addEventListener(d,a,!1)),f.add&&(f.add.call(e,p),p.handler.guid||(p.handler.guid=n.guid)),o?h.splice(h.delegateCount++,0,p):h.push(p),x.event.global[d]=!0);e=null}},remove:function(e,t,n,r,i){var o,s,a,u,l,c,p,f,h,d,g,m=q.hasData(e)&&q.get(e);if(m&&(u=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(a=X.exec(t[l])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){p=x.event.special[h]||{},h=(r?p.delegateType:p.bindType)||h,f=u[h]||[],a=a[2]&&RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=f.length;while(o--)c=f[o],!i&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(f.splice(o,1),c.selector&&f.delegateCount--,p.remove&&p.remove.call(e,c));s&&!f.length&&(p.teardown&&p.teardown.call(e,d,m.handle)!==!1||x.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)x.event.remove(e,h+t[l],n,r,!0);x.isEmptyObject(u)&&(delete m.handle,q.remove(e,"events"))}},trigger:function(t,n,r,i){var s,a,u,l,c,p,f,h=[r||o],d=y.call(t,"type")?t.type:t,g=y.call(t,"namespace")?t.namespace.split("."):[];if(a=u=r=r||o,3!==r.nodeType&&8!==r.nodeType&&!_.test(d+x.event.triggered)&&(d.indexOf(".")>=0&&(g=d.split("."),d=g.shift(),g.sort()),c=0>d.indexOf(":")&&"on"+d,t=t[x.expando]?t:new x.Event(d,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=g.join("."),t.namespace_re=t.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=undefined,t.target||(t.target=r),n=null==n?[t]:x.makeArray(n,[t]),f=x.event.special[d]||{},i||!f.trigger||f.trigger.apply(r,n)!==!1)){if(!i&&!f.noBubble&&!x.isWindow(r)){for(l=f.delegateType||d,_.test(l+d)||(a=a.parentNode);a;a=a.parentNode)h.push(a),u=a;u===(r.ownerDocument||o)&&h.push(u.defaultView||u.parentWindow||e)}s=0;while((a=h[s++])&&!t.isPropagationStopped())t.type=s>1?l:f.bindType||d,p=(q.get(a,"events")||{})[t.type]&&q.get(a,"handle"),p&&p.apply(a,n),p=c&&a[c],p&&x.acceptData(a)&&p.apply&&p.apply(a,n)===!1&&t.preventDefault();return t.type=d,i||t.isDefaultPrevented()||f._default&&f._default.apply(h.pop(),n)!==!1||!x.acceptData(r)||c&&x.isFunction(r[d])&&!x.isWindow(r)&&(u=r[c],u&&(r[c]=null),x.event.triggered=d,r[d](),x.event.triggered=undefined,u&&(r[c]=u)),t.result}},dispatch:function(e){e=x.event.fix(e);var t,n,r,i,o,s=[],a=d.call(arguments),u=(q.get(this,"events")||{})[e.type]||[],l=x.event.special[e.type]||{};if(a[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),t=0;while((i=s[t++])&&!e.isPropagationStopped()){e.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(o.namespace))&&(e.handleObj=o,e.data=o.data,r=((x.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,a),r!==undefined&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,s=[],a=t.delegateCount,u=e.target;if(a&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!==this;u=u.parentNode||this)if(u.disabled!==!0||"click"!==e.type){for(r=[],n=0;a>n;n++)o=t[n],i=o.selector+" ",r[i]===undefined&&(r[i]=o.needsContext?x(i,this).index(u)>=0:x.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&s.push({elem:u,handlers:r})}return t.length>a&&s.push({elem:this,handlers:t.slice(a)}),s},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,s=t.button;return null==e.pageX&&null!=t.clientX&&(n=e.target.ownerDocument||o,r=n.documentElement,i=n.body,e.pageX=t.clientX+(r&&r.scrollLeft||i&&i.scrollLeft||0)-(r&&r.clientLeft||i&&i.clientLeft||0),e.pageY=t.clientY+(r&&r.scrollTop||i&&i.scrollTop||0)-(r&&r.clientTop||i&&i.clientTop||0)),e.which||s===undefined||(e.which=1&s?1:2&s?3:4&s?2:0),e}},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,s=e,a=this.fixHooks[i];a||(this.fixHooks[i]=a=z.test(i)?this.mouseHooks:I.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new x.Event(s),t=r.length;while(t--)n=r[t],e[n]=s[n];return e.target||(e.target=o),3===e.target.nodeType&&(e.target=e.target.parentNode),a.filter?a.filter(e,s):e},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==V()&&this.focus?(this.focus(),!1):undefined},delegateType:"focusin"},blur:{trigger:function(){return this===V()&&this.blur?(this.blur(),!1):undefined},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&x.nodeName(this,"input")?(this.click(),!1):undefined},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==undefined&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)},x.Event=function(e,t){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.getPreventDefault&&e.getPreventDefault()?U:Y):this.type=e,t&&x.extend(this,t),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,undefined):new x.Event(e,t)},x.Event.prototype={isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=U,e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=U,e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=U,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,t,n,r,i){var o,s;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=undefined);for(s in e)this.on(s,t,n,e[s],i);return this}if(null==n&&null==r?(r=t,n=t=undefined):null==r&&("string"==typeof t?(r=n,n=undefined):(r=n,n=t,t=undefined)),r===!1)r=Y;else if(!r)return this;return 1===i&&(o=r,r=function(e){return x().off(e),o.apply(this,arguments)},r.guid=o.guid||(o.guid=x.guid++)),this.each(function(){x.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,x(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=undefined),n===!1&&(n=Y),this.each(function(){x.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?x.event.trigger(e,t,n,!0):undefined}});var G=/^.[^:#\[\.,]*$/,J=/^(?:parents|prev(?:Until|All))/,Q=x.expr.match.needsContext,K={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t=x(e,this),n=t.length;return this.filter(function(){var e=0;for(;n>e;e++)if(x.contains(this,t[e]))return!0})},not:function(e){return this.pushStack(et(this,e||[],!0))},filter:function(e){return this.pushStack(et(this,e||[],!1))},is:function(e){return!!et(this,"string"==typeof e&&Q.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],s=Q.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(s?s.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?g.call(x(e),this[0]):g.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function Z(e,t){while((e=e[t])&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return Z(e,"nextSibling")},prev:function(e){return Z(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return e.contentDocument||x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(K[e]||x.unique(i),J.test(e)&&i.reverse()),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,t,n){var r=[],i=n!==undefined;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&x(e).is(n))break;r.push(e)}return r},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function et(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(G.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return g.call(t,e)>=0!==n})}var tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,nt=/<([\w:]+)/,rt=/<|&#?\w+;/,it=/<(?:script|style|link)/i,ot=/^(?:checkbox|radio)$/i,st=/checked\s*(?:[^=]|=\s*.checked.)/i,at=/^$|\/(?:java|ecma)script/i,ut=/^true\/(.*)/,lt=/^\s*\s*$/g,ct={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ct.optgroup=ct.option,ct.tbody=ct.tfoot=ct.colgroup=ct.caption=ct.thead,ct.th=ct.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===undefined?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(mt(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&dt(mt(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++)1===e.nodeType&&(x.cleanData(mt(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!it.test(e)&&!ct[(nt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(tt,"<$1>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(x.cleanData(mt(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=f.apply([],e);var r,i,o,s,a,u,l=0,c=this.length,p=this,h=c-1,d=e[0],g=x.isFunction(d);if(g||!(1>=c||"string"!=typeof d||x.support.checkClone)&&st.test(d))return this.each(function(r){var i=p.eq(r);g&&(e[0]=d.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(r=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),i=r.firstChild,1===r.childNodes.length&&(r=i),i)){for(o=x.map(mt(r,"script"),ft),s=o.length;c>l;l++)a=r,l!==h&&(a=x.clone(a,!0,!0),s&&x.merge(o,mt(a,"script"))),t.call(this[l],a,l);if(s)for(u=o[o.length-1].ownerDocument,x.map(o,ht),l=0;s>l;l++)a=o[l],at.test(a.type||"")&&!q.access(a,"globalEval")&&x.contains(u,a)&&(a.src?x._evalUrl(a.src):x.globalEval(a.textContent.replace(lt,"")))}return this}}),x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=[],i=x(e),o=i.length-1,s=0;for(;o>=s;s++)n=s===o?this:this.clone(!0),x(i[s])[t](n),h.apply(r,n.get());return this.pushStack(r)}}),x.extend({clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),u=x.contains(e.ownerDocument,e);if(!(x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(s=mt(a),o=mt(e),r=0,i=o.length;i>r;r++)yt(o[r],s[r]);if(t)if(n)for(o=o||mt(e),s=s||mt(a),r=0,i=o.length;i>r;r++)gt(o[r],s[r]);else gt(e,a);return s=mt(a,"script"),s.length>0&&dt(s,!u&&mt(e,"script")),a},buildFragment:function(e,t,n,r){var i,o,s,a,u,l,c=0,p=e.length,f=t.createDocumentFragment(),h=[];for(;p>c;c++)if(i=e[c],i||0===i)if("object"===x.type(i))x.merge(h,i.nodeType?[i]:i);else if(rt.test(i)){o=o||f.appendChild(t.createElement("div")),s=(nt.exec(i)||["",""])[1].toLowerCase(),a=ct[s]||ct._default,o.innerHTML=a[1]+i.replace(tt,"<$1>")+a[2],l=a[0];while(l--)o=o.lastChild;x.merge(h,o.childNodes),o=f.firstChild,o.textContent=""}else h.push(t.createTextNode(i));f.textContent="",c=0;while(i=h[c++])if((!r||-1===x.inArray(i,r))&&(u=x.contains(i.ownerDocument,i),o=mt(f.appendChild(i),"script"),u&&dt(o),n)){l=0;while(i=o[l++])at.test(i.type||"")&&n.push(i)}return f},cleanData:function(e){var t,n,r,i,o,s,a=x.event.special,u=0;for(;(n=e[u])!==undefined;u++){if(F.accepts(n)&&(o=n[q.expando],o&&(t=q.cache[o]))){if(r=Object.keys(t.events||{}),r.length)for(s=0;(i=r[s])!==undefined;s++)a[i]?x.event.remove(n,i):x.removeEvent(n,i,t.handle);q.cache[o]&&delete q.cache[o]}delete L.cache[n[L.expando]]}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}});function pt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function ft(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function ht(e){var t=ut.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function dt(e,t){var n=e.length,r=0;for(;n>r;r++)q.set(e[r],"globalEval",!t||q.get(t[r],"globalEval"))}function gt(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(q.hasData(e)&&(o=q.access(e),s=q.set(t,o),l=o.events)){delete s.handle,s.events={};for(i in l)for(n=0,r=l[i].length;r>n;n++)x.event.add(t,i,l[i][n])}L.hasData(e)&&(a=L.access(e),u=x.extend({},a),L.set(t,u))}}function mt(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return t===undefined||t&&x.nodeName(e,t)?x.merge([e],n):n}function yt(e,t){var n=t.nodeName.toLowerCase();"input"===n&&ot.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}x.fn.extend({wrapAll:function(e){var t;return x.isFunction(e)?this.each(function(t){x(this).wrapAll(e.call(this,t))}):(this[0]&&(t=x(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var vt,xt,bt=/^(none|table(?!-c[ea]).+)/,wt=/^margin/,Tt=RegExp("^("+b+")(.*)$","i"),Ct=RegExp("^("+b+")(?!px)[a-z%]+$","i"),kt=RegExp("^([+-])=("+b+")","i"),Nt={BODY:"block"},Et={position:"absolute",visibility:"hidden",display:"block"},St={letterSpacing:0,fontWeight:400},jt=["Top","Right","Bottom","Left"],Dt=["Webkit","O","Moz","ms"];function At(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Dt.length;while(i--)if(t=Dt[i]+n,t in e)return t;return r}function Lt(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function qt(t){return e.getComputedStyle(t,null)}function Ht(e,t){var n,r,i,o=[],s=0,a=e.length;for(;a>s;s++)r=e[s],r.style&&(o[s]=q.get(r,"olddisplay"),n=r.style.display,t?(o[s]||"none"!==n||(r.style.display=""),""===r.style.display&&Lt(r)&&(o[s]=q.access(r,"olddisplay",Rt(r.nodeName)))):o[s]||(i=Lt(r),(n&&"none"!==n||!i)&&q.set(r,"olddisplay",i?n:x.css(r,"display"))));for(s=0;a>s;s++)r=e[s],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[s]||"":"none"));return e}x.fn.extend({css:function(e,t){return x.access(this,function(e,t,n){var r,i,o={},s=0;if(x.isArray(t)){for(r=qt(e),i=t.length;i>s;s++)o[t[s]]=x.css(e,t[s],!1,r);return o}return n!==undefined?x.style(e,t,n):x.css(e,t)},e,t,arguments.length>1)},show:function(){return Ht(this,!0)},hide:function(){return Ht(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){Lt(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=vt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,s,a=x.camelCase(t),u=e.style;return t=x.cssProps[a]||(x.cssProps[a]=At(u,a)),s=x.cssHooks[t]||x.cssHooks[a],n===undefined?s&&"get"in s&&(i=s.get(e,!1,r))!==undefined?i:u[t]:(o=typeof n,"string"===o&&(i=kt.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(x.css(e,t)),o="number"),null==n||"number"===o&&isNaN(n)||("number"!==o||x.cssNumber[a]||(n+="px"),x.support.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),s&&"set"in s&&(n=s.set(e,n,r))===undefined||(u[t]=n)),undefined)}},css:function(e,t,n,r){var i,o,s,a=x.camelCase(t);return t=x.cssProps[a]||(x.cssProps[a]=At(e.style,a)),s=x.cssHooks[t]||x.cssHooks[a],s&&"get"in s&&(i=s.get(e,!0,n)),i===undefined&&(i=vt(e,t,r)),"normal"===i&&t in St&&(i=St[t]),""===n||n?(o=parseFloat(i),n===!0||x.isNumeric(o)?o||0:i):i}}),vt=function(e,t,n){var r,i,o,s=n||qt(e),a=s?s.getPropertyValue(t)||s[t]:undefined,u=e.style;return s&&(""!==a||x.contains(e.ownerDocument,e)||(a=x.style(e,t)),Ct.test(a)&&wt.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=s.width,u.width=r,u.minWidth=i,u.maxWidth=o)),a};function Ot(e,t,n){var r=Tt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function Ft(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,s=0;for(;4>o;o+=2)"margin"===n&&(s+=x.css(e,n+jt[o],!0,i)),r?("content"===n&&(s-=x.css(e,"padding"+jt[o],!0,i)),"margin"!==n&&(s-=x.css(e,"border"+jt[o]+"Width",!0,i))):(s+=x.css(e,"padding"+jt[o],!0,i),"padding"!==n&&(s+=x.css(e,"border"+jt[o]+"Width",!0,i)));return s}function Pt(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=qt(e),s=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=vt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Ct.test(i))return i;r=s&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+Ft(e,t,n||(s?"border":"content"),r,o)+"px"}function Rt(e){var t=o,n=Nt[e];return n||(n=Mt(e,t),"none"!==n&&n||(xt=(xt||x("