From dd2f6ebc77854244a37c002db5e582d7be618e48 Mon Sep 17 00:00:00 2001 From: Tobias Reich Date: Wed, 22 Jan 2014 11:12:51 +0100 Subject: [PATCH] V2.0 - All new redefined interface - Faster animations and transitions - Import from Dropbox - Import from Server - Download public albums - Several sorting options - Installation assistent - Infobox and description for albums - Faster loading and improved performance - Better file handling and upload - Album covers are chosen intelligent - Prettier URLs - Massive changes under the hood - IPTC support (Headline and Caption) - EXIF Orientation support How to update: 1. Replace all files, excluding `uploads/` 2. Open Lychee and enter your database details --- .htaccess | 8 +- .user.ini | 10 +- assets/css/min/main.css | 1 + assets/css/min/reset.css | 11 + assets/css/modules/animations.css | 311 ++++ assets/css/modules/content.css | 256 +++ assets/css/modules/contextmenu.css | 101 ++ .../css/modules/font.css | 6 +- assets/css/modules/header.css | 165 ++ assets/css/modules/imageview.css | 88 ++ assets/css/modules/infobox.css | 173 ++ assets/css/modules/loading.css | 59 + assets/css/modules/mediaquery.css | 61 + assets/css/modules/message.css | 198 +++ assets/css/modules/misc.css | 35 + assets/css/modules/tooltip.css | 39 + assets/css/modules/upload.css | 123 ++ {css => assets}/font/fontawesome-webfont.eot | Bin {css => assets}/font/fontawesome-webfont.svg | 0 {css => assets}/font/fontawesome-webfont.ttf | Bin {css => assets}/font/fontawesome-webfont.woff | Bin assets/img/apple-touch-icon-ipad.png | Bin 0 -> 6033 bytes assets/img/apple-touch-icon-iphone.png | Bin 0 -> 5396 bytes assets/img/favicon.ico | Bin 0 -> 6518 bytes assets/img/no_images.svg | 1 + assets/img/password.svg | 1 + {js => assets/js/min}/frameworks.js | 0 assets/js/min/main.js | 2 + {js => assets/js}/modules/album.js | 173 +- {js => assets/js}/modules/albums.js | 31 +- assets/js/modules/build.js | 410 +++++ {js => assets/js}/modules/contextMenu.js | 232 +-- assets/js/modules/init.js | 138 ++ {js => assets/js}/modules/loadingBar.js | 26 +- {js => assets/js}/modules/lychee.js | 155 +- assets/js/modules/modal.js | 35 + {js => assets/js}/modules/password.js | 41 +- assets/js/modules/photo.js | 315 ++++ {js => assets/js}/modules/search.js | 27 +- assets/js/modules/settings.js | 238 +++ assets/js/modules/upload.js | 253 +++ {js => assets/js}/modules/view.js | 158 +- {js => assets/js}/modules/visible.js | 24 +- {js => assets/js}/view.js | 21 +- css/animations.css | 485 ------ css/style.css | 1398 ----------------- docs/assets/favicon.sketch/Data | Bin 0 -> 23304 bytes .../favicon.sketch/QuickLook/Preview.png | Bin 0 -> 2055 bytes .../favicon.sketch/QuickLook/Thumbnail.png | Bin 0 -> 80665 bytes docs/assets/favicon.sketch/fonts | 1 + docs/assets/favicon.sketch/metadata | 14 + docs/assets/favicon.sketch/version | 1 + docs/assets/thumbs.sketch/Data | Bin 0 -> 26647 bytes .../thumbs.sketch/QuickLook/Preview.png | Bin 0 -> 5266 bytes .../thumbs.sketch/QuickLook/Thumbnail.png | Bin 0 -> 9584 bytes docs/assets/thumbs.sketch/fonts | 0 docs/assets/thumbs.sketch/metadata | 14 + docs/assets/thumbs.sketch/version | 1 + docs/compile.sh | 32 + docs/install.sh | 40 + docs/md/Changelog.md | 16 + docs/md/FAQ.md | 44 + docs/md/FTP Upload.md | 13 + docs/md/Installation.md | 29 + docs/md/Keyboard Shortcuts.md | 17 + docs/md/Settings.md | 41 + img/apple-touch-icon.png | Bin 10871 -> 0 bytes img/background.jpg | Bin 3151 -> 0 bytes img/bar/error.png | Bin 184 -> 0 bytes img/bar/loading.png | Bin 3287 -> 0 bytes img/checks.png | Bin 113 -> 0 bytes img/favicon.png | Bin 3380 -> 0 bytes img/no_images.png | Bin 3420 -> 0 bytes img/no_images@2x.png | Bin 4130 -> 0 bytes img/password.png | Bin 3688 -> 0 bytes img/password@2x.png | Bin 4477 -> 0 bytes index.html | 88 +- js/functions.js | 1 - js/main.js | 147 -- js/modules/build.js | 288 ---- js/modules/modal.js | 37 - js/modules/photo.js | 403 ----- js/modules/photos.js | 431 ----- lychee.sql | 48 - php/api.php | 395 +++-- php/check.php | 45 - php/config.php | 27 - php/functions.php | 801 ---------- php/modules/album.php | 354 +++++ php/modules/db.php | 183 +++ php/modules/misc.php | 95 ++ php/modules/photo.php | 167 ++ php/modules/session.php | 64 + php/modules/settings.php | 137 ++ php/modules/upload.php | 378 +++++ php/update.php | 17 - plugins/check.php | 65 + readme.md | 61 +- uploads/big/index.html | 0 uploads/import/index.html | 0 uploads/thumb/index.html | 0 view.php | 29 +- 102 files changed, 5634 insertions(+), 4699 deletions(-) create mode 100644 assets/css/min/main.css create mode 100644 assets/css/min/reset.css create mode 100755 assets/css/modules/animations.css create mode 100644 assets/css/modules/content.css create mode 100644 assets/css/modules/contextmenu.css rename css/font-awesome.css => assets/css/modules/font.css (97%) create mode 100644 assets/css/modules/header.css create mode 100644 assets/css/modules/imageview.css create mode 100644 assets/css/modules/infobox.css create mode 100644 assets/css/modules/loading.css create mode 100644 assets/css/modules/mediaquery.css create mode 100644 assets/css/modules/message.css create mode 100755 assets/css/modules/misc.css create mode 100644 assets/css/modules/tooltip.css create mode 100644 assets/css/modules/upload.css rename {css => assets}/font/fontawesome-webfont.eot (100%) rename {css => assets}/font/fontawesome-webfont.svg (100%) rename {css => assets}/font/fontawesome-webfont.ttf (100%) rename {css => assets}/font/fontawesome-webfont.woff (100%) create mode 100644 assets/img/apple-touch-icon-ipad.png create mode 100644 assets/img/apple-touch-icon-iphone.png create mode 100644 assets/img/favicon.ico create mode 100644 assets/img/no_images.svg create mode 100644 assets/img/password.svg rename {js => assets/js/min}/frameworks.js (100%) create mode 100644 assets/js/min/main.js rename {js => assets/js}/modules/album.js (52%) rename {js => assets/js}/modules/albums.js (71%) create mode 100755 assets/js/modules/build.js rename {js => assets/js}/modules/contextMenu.js (50%) create mode 100755 assets/js/modules/init.js rename {js => assets/js}/modules/loadingBar.js (59%) rename {js => assets/js}/modules/lychee.js (55%) create mode 100644 assets/js/modules/modal.js rename {js => assets/js}/modules/password.js (60%) create mode 100644 assets/js/modules/photo.js rename {js => assets/js}/modules/search.js (67%) create mode 100644 assets/js/modules/settings.js create mode 100644 assets/js/modules/upload.js rename {js => assets/js}/modules/view.js (64%) rename {js => assets/js}/modules/visible.js (53%) rename {js => assets/js}/view.js (81%) mode change 100755 => 100644 delete mode 100755 css/animations.css delete mode 100755 css/style.css create mode 100644 docs/assets/favicon.sketch/Data create mode 100644 docs/assets/favicon.sketch/QuickLook/Preview.png create mode 100644 docs/assets/favicon.sketch/QuickLook/Thumbnail.png create mode 100644 docs/assets/favicon.sketch/fonts create mode 100644 docs/assets/favicon.sketch/metadata create mode 100644 docs/assets/favicon.sketch/version create mode 100644 docs/assets/thumbs.sketch/Data create mode 100644 docs/assets/thumbs.sketch/QuickLook/Preview.png create mode 100644 docs/assets/thumbs.sketch/QuickLook/Thumbnail.png create mode 100644 docs/assets/thumbs.sketch/fonts create mode 100644 docs/assets/thumbs.sketch/metadata create mode 100644 docs/assets/thumbs.sketch/version create mode 100644 docs/compile.sh create mode 100644 docs/install.sh create mode 100644 docs/md/Changelog.md create mode 100644 docs/md/FAQ.md create mode 100644 docs/md/FTP Upload.md create mode 100644 docs/md/Installation.md create mode 100644 docs/md/Keyboard Shortcuts.md create mode 100644 docs/md/Settings.md delete mode 100755 img/apple-touch-icon.png delete mode 100755 img/background.jpg delete mode 100755 img/bar/error.png delete mode 100755 img/bar/loading.png delete mode 100755 img/checks.png delete mode 100755 img/favicon.png delete mode 100755 img/no_images.png delete mode 100755 img/no_images@2x.png delete mode 100755 img/password.png delete mode 100755 img/password@2x.png delete mode 100644 js/functions.js delete mode 100755 js/main.js delete mode 100755 js/modules/build.js delete mode 100644 js/modules/modal.js delete mode 100644 js/modules/photo.js delete mode 100755 js/modules/photos.js delete mode 100755 lychee.sql mode change 100755 => 100644 php/api.php delete mode 100644 php/check.php delete mode 100755 php/config.php delete mode 100644 php/functions.php create mode 100755 php/modules/album.php create mode 100755 php/modules/db.php create mode 100755 php/modules/misc.php create mode 100755 php/modules/photo.php create mode 100755 php/modules/session.php create mode 100755 php/modules/settings.php create mode 100755 php/modules/upload.php delete mode 100644 php/update.php create mode 100644 plugins/check.php mode change 100644 => 100755 uploads/big/index.html mode change 100644 => 100755 uploads/import/index.html mode change 100644 => 100755 uploads/thumb/index.html mode change 100755 => 100644 view.php diff --git a/.htaccess b/.htaccess index b2cfacd..4eaa634 100644 --- a/.htaccess +++ b/.htaccess @@ -2,9 +2,9 @@ IndexIgnore * # Uncomment these lines to change PHP parameters if you are using the PHP Apache module # -# php_value max_execution_time 300 -# php_value post_max_size 100M -# php_value upload_max_size 100M -# php_value upload_max_filesize 5M +# php_value max_execution_time 200 +# php_value post_max_size 200M +# php_value upload_max_size 200M +# php_value upload_max_filesize 20M # php_value max_file_uploads 100 # diff --git a/.user.ini b/.user.ini index f6bf2b8..e2273cf 100644 --- a/.user.ini +++ b/.user.ini @@ -1,8 +1,8 @@ ; Uncomment these lines to change PHP parameters if you are using PHP with CGI or FastCGI. Only works with PHP starting from 5.3.0. ; Note that with FastCGI, you might also want to set FcgidBusyTimeout, FcgidIOTimeout and FcgidMaxRequestLen in your Apache config -;max_execution_time = 60 -;post_max_size = 100M -;upload_max_size = 100M -;upload_max_filesize = 5M -;max_file_uploads = 100 +;max_execution_time = 200 +;post_max_size = 200M +;upload_max_size = 200M +;upload_max_filesize = 20M +;max_file_uploads = 200 diff --git a/assets/css/min/main.css b/assets/css/min/main.css new file mode 100644 index 0000000..37ef7f7 --- /dev/null +++ b/assets/css/min/main.css @@ -0,0 +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:110%;left:110%;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:.98;z-index:1001}.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 .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}}.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 diff --git a/assets/css/min/reset.css b/assets/css/min/reset.css new file mode 100644 index 0000000..36081f8 --- /dev/null +++ b/assets/css/min/reset.css @@ -0,0 +1,11 @@ +/** + * @name reset.css + */ + +html,body,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; } \ No newline at end of file diff --git a/assets/css/modules/animations.css b/assets/css/modules/animations.css new file mode 100755 index 0000000..47e1e48 --- /dev/null +++ b/assets/css/modules/animations.css @@ -0,0 +1,311 @@ +/** + * @name animations.css + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +/* Animation Setter ------------------------------------------------*/ +.fadeIn { + -webkit-animation-name: fadeIn; + -webkit-animation-duration: .3s; + -webkit-animation-fill-mode: forwards; + -moz-animation-name: fadeIn; + -moz-animation-duration: .3s; + -moz-animation-fill-mode: forwards; + animation-name: fadeIn; + animation-duration: .3s; + animation-fill-mode: forwards; } + +.fadeOut { + -webkit-animation-name: fadeOut; + -webkit-animation-duration: .3s; + -webkit-animation-fill-mode: forwards; + -moz-animation-name: fadeOut; + -moz-animation-duration: .3s; + -moz-animation-fill-mode: forwards; + animation-name: fadeOut; + animation-duration: .3s; + animation-fill-mode: forwards; } + +.contentZoomIn { + -webkit-animation-name: zoomIn; + -webkit-animation-duration: .2s; + -webkit-animation-fill-mode: forwards; + -moz-animation-name: zoomIn; + -moz-animation-duration: .2s; + -moz-animation-fill-mode: forwards; + animation-name: zoomIn; + animation-duration: .2s; + animation-fill-mode: forwards; } + +.contentZoomOut { + -webkit-animation-name: zoomOut; + -webkit-animation-duration: .2s; + -webkit-animation-fill-mode: forwards; + -moz-animation-name: zoomOut; + -moz-animation-duration: .2s; + -moz-animation-fill-mode: forwards; + animation-name: zoomOut; + animation-duration: .2s; + animation-fill-mode: forwards; } + +/* moveUp ------------------------------------------------*/ +@-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; + } +} + +/* fadeIn ------------------------------------------------*/ +@-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; + } +} + +/* fadeOut ------------------------------------------------*/ +@-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; + } +} + +/* moveBackground ------------------------------------------------*/ +@-webkit-keyframes moveBackground { + 0% { + background-position-x: 0px; + } + 100% { + background-position-x: -100px; + } +} +@-moz-keyframes moveBackground { + 0% { + background-position-x: 0px; + } + 100% { + background-position-x: -100px; + } +} +@keyframes moveBackground { + 0% { + background-position-x: 0px; + } + 100% { + background-position-x: -100px; + } +} + +/* zoomIn ------------------------------------------------*/ +@-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); + } +} + +/* zoomOut ------------------------------------------------*/ +@-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); + } +} + +/* popIn ------------------------------------------------*/ +@-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); + } +} + +/* pulse ------------------------------------------------*/ +@-webkit-keyframes pulse { + 0% { + opacity: 1; + } + 50% { + opacity: 0.3; + } + 100% { + opacity: 1; + } +} +@-moz-keyframes pulse { + 0% { + opacity: 1; + } + 50% { + opacity: 0.8; + } + 100% { + opacity: 1; + } +} +@keyframes pulse { + 0% { + opacity: 1; + } + 50% { + opacity: 0.8; + } + 100% { + opacity: 1; + } +} + +/* rotate ------------------------------------------------ +@-webkit-keyframes rotate { + 0% { + -webkit-transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + } +} +@-moz-keyframes rotate { + 0% { + -moz-transform: rotate(0deg); + } + 100% { + -moz-transform: rotate(360deg); + } +} +@keyframes rotate { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} */ \ No newline at end of file diff --git a/assets/css/modules/content.css b/assets/css/modules/content.css new file mode 100644 index 0000000..e886839 --- /dev/null +++ b/assets/css/modules/content.css @@ -0,0 +1,256 @@ +/** + * @name content.css + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +#content::before { + content: ""; + position: absolute; + left: 0px; + 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; +} + + /* Modes ------------------------------------------------*/ + #content.view::before { + display: none; + } + +#content { + position: absolute; + padding: 50px 0px 33px 0px; + width: 100%; + -webkit-overflow-scrolling: touch; +} + + /* Photo ------------------------------------------------*/ + .photo { + float: left; + display: inline-block; + width: 206px; + height: 206px; + margin: 30px 0px 0px 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: 0px 0px 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 ------------------------------------------------*/ + .album { + float: left; + display: inline-block; + width: 204px; + height: 204px; + margin: 30px 0px 0px 30px; + cursor: pointer; + } + .album img:first-child, + .album img:nth-child(2) { + -webkit-transform: rotate(0deg) translateY(0px) translateX(0px); + -moz-transform: rotate(0deg) translateY(0px) translateX(0px); + transform: rotate(0deg) translateY(0px) translateX(0px); + 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: 0px 0px 5px #005ecc; + } + + /* Album/Photo Overlay ------------------------------------------------*/ + .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,0.9) 100%); /* FF3.6+ */ + background: -webkit-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,0) 20%,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) 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); + opacity: 0; + } + .photo:hover .overlay, + .photo.active .overlay { + opacity: 1; + } + .album .overlay h1, + .photo .overlay h1 { + min-height: 19px; + width: 190px; + margin: 153px 0px 3px 15px; + color: #fff; + font-size: 16px; + font-weight: bold; + overflow: hidden; + } + .album .overlay a, + .photo .overlay a { + font-size: 11px; + color: #aaa; + } + .album .overlay a { + margin-left: 15px; + } + .photo .overlay a { + margin: 155px 0px 5px 15px; + } + + /* Badges ------------------------------------------------*/ + .album .badge, + .photo .badge { + position: absolute; + margin-top: -1px; + margin-left: 12px; + padding: 12px 7px 3px 7px; + box-shadow: 0px 0px 3px #000; + border-radius: 0px 0px 3px 3px; + border: 1px solid #fff; + border-top: none; + color: #fff; + font-size: 24px; + text-shadow: 0px 1px 0px #000; + opacity: .9; + } + .album .badge.icon-star, + .photo .badge.icon-star { + padding: 12px 8px 3px 8px; + } + .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%); /* FF3.6+ */ + background: -webkit-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0) 100%); /* Chrome10+,Safari5.1+ */ + background: -ms-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0) 100%); /* IE10+ */ + background: linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0) 100%); /* W3C */ + 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 ------------------------------------------------*/ + .divider { + float: left; + width: 100%; + margin-top: 50px; + opacity: 0; + border-top: 1px solid #2E2E2E; + box-shadow: 0px -1px 0px #151515; + } + .divider:first-child { + margin-top: 0px; + border-top: none; + } + .divider h1 { + float: left; + margin: 20px 0px 0px 30px; + color: #fff; + font-size: 14px; + font-weight: bold; + text-shadow: 0px -1px 0px #000; + } + + /* No Content ------------------------------------------------*/ + .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: 0px 1px 0px rgba(255, 255, 255, .05); + text-align: center; + } + .no_content .icon { + font-size: 120px; + } + .no_content p { + font-size: 18px; + } \ No newline at end of file diff --git a/assets/css/modules/contextmenu.css b/assets/css/modules/contextmenu.css new file mode 100644 index 0000000..fa6d60e --- /dev/null +++ b/assets/css/modules/contextmenu.css @@ -0,0 +1,101 @@ +/** + * @name contextmenu.css + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +.contextmenu_bg { + position: fixed; + height: 100%; + width: 100%; + z-index: 1000; +} +.contextmenu { + position: fixed; + top: 110%; + left: 110%; + padding: 5px 0px 6px 0px; + 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,0.7); + border-bottom: 1px solid rgba(0,0,0,.9); + border-radius: 5px; + box-shadow: 0px 4px 5px rgba(0,0,0,0.3), inset 0px 1px 0px rgba(255,255,255,0.15), inset 1px 0px 0px rgba(255,255,255,0.05), inset -1px 0px 0px rgba(255,255,255,0.05); + opacity: .98; + z-index: 1001; +} + + /* Items ------------------------------------------------*/ + .contextmenu tr { + font-size: 14px; + color: #eee; + text-shadow: 0px -1px 0px 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 0px; + 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 0px 1px 0px rgba(255,255,255,.05); + text-shadow: 0px -1px 0px 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; + } + + /* Direct Link Input ------------------------------------------------*/ + .contextmenu #link { + float: right; + width: 140px; + margin: 0px -17px -1px 0px; + padding: 4px 6px 5px 6px; + background-color: #444; + color: #fff; + border: none; + border: 1px solid #111; + box-shadow: 0px 1px 0px rgba(255,255,255,.1); + outline: none; + border-radius: 5px; + } + .contextmenu tr a#link_icon { + padding-top: 4px; + } \ No newline at end of file diff --git a/css/font-awesome.css b/assets/css/modules/font.css similarity index 97% rename from css/font-awesome.css rename to assets/css/modules/font.css index f1b1458..3517a48 100755 --- a/css/font-awesome.css +++ b/assets/css/modules/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; } @@ -300,4 +300,4 @@ li[class^="icon-"].icon-large:before, li[class*=" icon-"].icon-large:before { .icon-umbrella:before { content: "\f0e9"; } .icon-paste:before { content: "\f0ea"; } -.icon-user-md:before { content: "\f200"; } +.icon-user-md:before { content: "\f200"; } \ No newline at end of file diff --git a/assets/css/modules/header.css b/assets/css/modules/header.css new file mode 100644 index 0000000..2e6ee7c --- /dev/null +++ b/assets/css/modules/header.css @@ -0,0 +1,165 @@ +/** + * @name _header.css + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +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; +} + + /* Modes ------------------------------------------------*/ + 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; + } + + /* Title ------------------------------------------------*/ + header #title { + position: absolute; + margin: 0px 30%; + width: 40%; + padding: 15px 0px; + color: #fff; + font-size: 16px; + font-weight: bold; + text-align: center; + text-shadow: 0px -1px 0px #222; + } + header #title.editable { + cursor: pointer; + } + + /* Button ------------------------------------------------*/ + header .button { + color: #888; + font-family: 'FontAwesome'; + font-size: 21px; + font-weight: bold; + text-decoration: none !important; + cursor: pointer; + text-shadow: 0px -1px 0px #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; + } + + /* Button Divider ------------------------------------------------*/ + header .button_divider { + float: right; + position: relative; + width: 14px; + height: 50px; + } + + /* Search ------------------------------------------------*/ + header #search { + float: right; + width: 80px; + margin: 12px 12px 0px 0px; + padding: 5px 12px 6px 12px; + background-color: #383838; + color: #fff; + border: none; + border: 1px solid #131313; + box-shadow: 0px 1px 0px 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; + } + + /* Tools ------------------------------------------------*/ + header .tools:first-of-type { + margin-right: 6px; + } + header .tools { + float: right; + padding: 14px 8px; + color: #888; + font-size: 21px; + text-shadow: 0px -1px 0px #222; + cursor: pointer; + } + header .tools:hover a { + color: #fff; + } + header .tools .icon-star { + color: #f0ef77; + } + header .tools .icon-share.active { + color: #ff9737; + } + + /* Hosted with Lychee ------------------------------------------------*/ + header #hostedwith { + float: right; + padding: 5px 10px; + margin: 13px 9px; + color: #888; + font-size: 13px; + text-shadow: 0px -1px 0px #222; + display: none; + cursor: pointer; + } + header #hostedwith:hover { + background-color: rgba(0, 0, 0, .2); + border-radius: 100px; + } \ No newline at end of file diff --git a/assets/css/modules/imageview.css b/assets/css/modules/imageview.css new file mode 100644 index 0000000..db910a2 --- /dev/null +++ b/assets/css/modules/imageview.css @@ -0,0 +1,88 @@ +/** + * @name imageview.css + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +#imageview { + position: fixed; + display: none; + width: 100%; + min-height: 100%; + background-color: rgba(10,10,10,.99); + + -webkit-transition: background-color .3s; +} + + /* Modes ------------------------------------------------*/ + #imageview.view { + background-color: inherit; + } + #imageview.full { + background-color: #040404; + } + + /* ImageView ------------------------------------------------*/ + #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%; + } + + /* Previous/Next Buttons ------------------------------------------------*/ + #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: 0px 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; + } \ No newline at end of file diff --git a/assets/css/modules/infobox.css b/assets/css/modules/infobox.css new file mode 100644 index 0000000..8584387 --- /dev/null +++ b/assets/css/modules/infobox.css @@ -0,0 +1,173 @@ +/** + * @name infobox.css + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +#infobox_overlay { + z-index: 3; + position: fixed; + width: 100%; + height: 100%; + top: 0px; + left: 0px; + background-color: rgba(0,0,0,.85); +} +#infobox { + z-index: 4; + position: fixed; + right: 0px; + width: 300px; + height: 100%; + background-color: rgba(20,20,20,0.98); + box-shadow: -1px 0px 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(0px); + -moz-transform: translateX(0px); + transform: translateX(0px); +} + + /* Misc ------------------------------------------------*/ + #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; + } + + /* Header ------------------------------------------------*/ + #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%; + color: #fff; + font-size: 16px; + font-weight: bold; + text-align: center; + text-shadow: 0px -1px 0px #000; + } + #infobox .header a { + float: right; + padding: 15px 15px; + color: #fff; + font-size: 20px; + font-weight: bold; + text-shadow: 0px -1px 0px #000; + opacity: .5; + cursor: pointer; + } + #infobox .header a:hover { + opacity: 1; + } + + /* Seperator ------------------------------------------------*/ + #infobox .separator { + float: left; + width: 100%; + border-top: 1px solid rgba(255,255,255,.04); + box-shadow: 0px -1px 0px #000; + } + #infobox .separator h1 { + margin: 20px 0px 5px 20px; + color: #fff; + font-size: 14px; + font-weight: bold; + text-shadow: 0px -1px 0px #000; + } + + /* Table ------------------------------------------------*/ + #infobox table { + float: left; + margin: 10px 0px 15px 20px; + } + #infobox table tr td { + padding: 5px 0px; + 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; + } + + /* Tags ------------------------------------------------*/ + #infobox #tags { + margin: 20px 20px 15px 20px; + color: #fff; + display: inline-block; + } + #infobox .tag { + float: left; + padding: 4px 7px; + margin: 0px 6px 8px 0px; + 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: 0px; + padding: 0px; + margin: 0px 0px -2px 0px; + 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: 0px 0px -2px 6px; + -webkit-transform: scale(1); + transform: scale(1); + } \ No newline at end of file diff --git a/assets/css/modules/loading.css b/assets/css/modules/loading.css new file mode 100644 index 0000000..eb49536 --- /dev/null +++ b/assets/css/modules/loading.css @@ -0,0 +1,59 @@ +/** + * @name loading.css + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +#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; + + /* Animation */ + -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; +} + + /* Modes ------------------------------------------------*/ + #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; + } + + /* Content ------------------------------------------------*/ + #loading h1 { + margin: 13px; + color: #ddd; + font-size: 14px; + font-weight: bold; + text-shadow: 0px 1px 0px #000; + text-transform: capitalize; + } + #loading h1 span { + margin-left: 10px; + font-weight: normal; + text-transform: none; + } \ No newline at end of file diff --git a/assets/css/modules/mediaquery.css b/assets/css/modules/mediaquery.css new file mode 100644 index 0000000..f9a193d --- /dev/null +++ b/assets/css/modules/mediaquery.css @@ -0,0 +1,61 @@ +/** + * @name mediaquery.css + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +@media only screen and (max-width: 900px) { + + #title { + margin: 0px 20% !important; + width: 40% !important; + } + #title.view { + margin: 0px 20% !important; + 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: 0px 20% 0px 10% !important; + } + #button_move { + display: none !important; + } + #button_archive { + display: none !important; + } + + .center { + top: 0px !important; + left: 0px !important; + } + + .album, .photo { + margin: 40px 0px 0px 50px !important; + } + + .message { + position: fixed !important; + width: 100% !important; + height: 100% !important; + margin: 1px 0px 0px 0px !important; + border-radius: 0px !important; + + /* Animation */ + -webkit-animation: moveUp .3s !important; + -moz-animation: moveUp .3s !important; + animation: moveUp .3s !important; + } + +} \ No newline at end of file diff --git a/assets/css/modules/message.css b/assets/css/modules/message.css new file mode 100644 index 0000000..a28dbe5 --- /dev/null +++ b/assets/css/modules/message.css @@ -0,0 +1,198 @@ +/** + * @name message.css + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +.message_overlay { + position: fixed; + width: 100%; + height: 100%; + top: 0px; + left: 0px; + 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, rgb(75, 75, 75), rgb(45, 45, 45)); + background-image: -moz-linear-gradient(top, rgb(75, 75, 75), rgb(45, 45, 45)); + background-image: -ms-linear-gradient(top, rgb(75, 75, 75), rgb(45, 45, 45)); + background-image: linear-gradient(top, rgb(75, 75, 75), rgb(45, 45, 45)); + border-radius: 5px; + box-shadow: 0px 0px 5px #000, inset 0px 1px 0px rgba(255,255,255,.08), inset 1px 0px 0px rgba(255,255,255,.03), inset -1px 0px 0px rgba(255,255,255,.03); + + /* Animation */ + -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; +} + + /* Header ------------------------------------------------*/ + .message h1 { + float: left; + width: 100%; + padding: 12px 0px; + color: #fff; + font-size: 16px; + font-weight: bold; + text-shadow: 0px -1px 0px #222; + text-align: center; + } + .message .close { + position: absolute; + top: 0px; + right: 0px; + padding: 12px 14px 6px 7px; + color: #aaa; + font-size: 20px; + text-shadow: 0px -1px 0px #222; + cursor: pointer; + } + .message .close:hover { + color: #fff; + } + + /* Text ------------------------------------------------*/ + .message p { + float: left; + width: 90%; + margin-top: 1px; + padding: 12px 5% 15px 5%; + color: #eee; + font-size: 14px; + text-shadow: 0px -1px 0px #222; + line-height: 20px; + } + .message p b { + font-weight: bold; + } + .message p a { + color: #eee; + text-decoration: none; + border-bottom: 1px dashed #888; + } + + /* Button ------------------------------------------------*/ + .message .button { + float: right; + margin: 15px 15px 15px 0px; + padding: 6px 10px 8px 10px; + background-color: #4e4e4e; + background-image: -webkit-linear-gradient(top, rgb(60, 60, 60), rgb(45, 45, 45)); + background-image: -moz-linear-gradient(top, rgb(60, 60, 60), rgb(45, 45, 45)); + background-image: -ms-linear-gradient(top, rgb(60, 60, 60), rgb(45, 45, 45)); + background-image: linear-gradient(top, rgb(60, 60, 60), rgb(45, 45, 45)); + color: #ccc; + font-size: 14px; + font-weight: bold; + text-align: center; + text-shadow: 0px -1px 0px #222; + border-radius: 5px; + border: 1px solid #191919; + box-shadow: inset 0px 1px 0px rgba(255,255,255,.1), 0px 1px 0px rgba(255,255,255,.1); + cursor: pointer; + } + .message .button:first-of-type { + margin: 15px 5% 18px 0px !important; + } + .message .button.active { + color: #fff; + box-shadow: inset 0px 1px 0px rgba(255,255,255,.1), 0px 1px 0px rgba(255,255,255,.1), 0px 0px 4px #005ecc; + } + .message .button:hover { + background-color: #565757; + background-image: -webkit-linear-gradient(top, rgb(80, 80, 80), rgb(57, 57, 57)); + background-image: -moz-linear-gradient(top, rgb(80, 80, 80), rgb(57, 57, 57)); + background-image: -ms-linear-gradient(top, rgb(80, 80, 80), rgb(57, 57, 57)); + background-image: linear-gradient(top, rgb(80, 80, 80), rgb(57, 57, 57)); + } + .message .button:active, + .message .button.pressed { + background-color: #393939; + background-image: -webkit-linear-gradient(top, rgb(57, 57, 57), rgb(70, 70, 70)); + background-image: -moz-linear-gradient(top, rgb(57, 57, 57), rgb(70, 70, 70)); + background-image: -ms-linear-gradient(top, rgb(57, 57, 57), rgb(70, 70, 70)); + background-image: linear-gradient(top, rgb(57, 57, 57), rgb(70, 70, 70)); + } + + /* Sign in ------------------------------------------------*/ + .sign_in { + float: left; + width: 100%; + margin-top: 1px; + padding: 5px 0px; + color: #eee; + font-size: 14px; + text-shadow: 0px -1px 0px #222; + line-height: 20px; + } + .sign_in input { + float: left; + width: 88%; + padding: 7px 1% 9px 1%; + margin: 0px 5%; + background-color: transparent; + color: #fff; + text-shadow: 0px -1px 0px #222; + border: none; + border-bottom: 1px solid #222; + box-shadow: 0px 1px 0px rgba(255,255,255,.1); + border-radius: 0px; + outline: none; + } + .sign_in input:first-of-type { + margin-bottom: 10px; + } + .sign_in input.error:focus { + box-shadow: 0px 1px 0px rgba(204, 0, 7, 0.6); + } + .message #version { + display: inline-block; + margin-top: 23px; + margin-left: 5%; + color: #888; + text-shadow: 0px -1px 0px #111; + } + .message #version span { + display: none; + } + .message #version span a { + color: #888; + } + + /* Input Misc ------------------------------------------------*/ + .message input.text { + float: left; + width: calc(100% - 10px); + padding: 17px 5px 9px 5px; + margin-top: 10px; + background-color: transparent; + color: #fff; + text-shadow: 0px -1px 0px #222; + border: none; + box-shadow: 0px 1px 0px rgba(255,255,255,.1); + border-bottom: 1px solid #222; + border-radius: 0px; + outline: none; + } + .message input.less { + margin-bottom: -10px; + } + .message input.more { + margin-bottom: 30px; + } + .message .copylink { + margin-bottom: 20px; + } \ No newline at end of file diff --git a/assets/css/modules/misc.css b/assets/css/modules/misc.css new file mode 100755 index 0000000..a44002f --- /dev/null +++ b/assets/css/modules/misc.css @@ -0,0 +1,35 @@ +/** + * @name misc.css + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +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; +} \ No newline at end of file diff --git a/assets/css/modules/tooltip.css b/assets/css/modules/tooltip.css new file mode 100644 index 0000000..8958666 --- /dev/null +++ b/assets/css/modules/tooltip.css @@ -0,0 +1,39 @@ +/** + * @name tooltip.css + */ + +.tipsy { + padding: 4px; + font-size: 12px; + position: absolute; + z-index: 100000; + + /* Animation */ + -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 { top: 0px; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; } +.tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;} +.tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none; 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; border-left-color: transparent; border-right-color: transparent; } +.tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } +.tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } +.tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; } +.tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; } \ No newline at end of file diff --git a/assets/css/modules/upload.css b/assets/css/modules/upload.css new file mode 100644 index 0000000..32d9b1b --- /dev/null +++ b/assets/css/modules/upload.css @@ -0,0 +1,123 @@ +/** + * @name upload.css + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +#upload { + display: none; +} +.upload_overlay { + position: fixed; + width: 100%; + height: 100%; + top: 0px; + left: 0px; + 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, rgb(75, 75, 75), rgb(45, 45, 45)); + background-image: -moz-linear-gradient(top, rgb(75, 75, 75), rgb(45, 45, 45)); + background-image: -ms-linear-gradient(top, rgb(75, 75, 75), rgb(45, 45, 45)); + background-image: linear-gradient(top, rgb(75, 75, 75), rgb(45, 45, 45)); + border-radius: 5px; + box-shadow: 0px 0px 5px #000, inset 0px 1px 0px rgba(255,255,255,.08), inset 1px 0px 0px rgba(255,255,255,.03), inset -1px 0px 0px rgba(255,255,255,.03); + + /* Animation */ + -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; +} + + /* Icon ------------------------------------------------*/ + .upload_message a { + float: left; + width: 100%; + margin: 35px 0px 5px 0px; + color: #fff; + font-size: 70px; + text-shadow: 0px 1px 2px rgba(0,0,0,.5); + text-align: center; + + -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; + } + + /* Text ------------------------------------------------*/ + .upload_message p { + float: left; + width: 100%; + margin: 10px 0px 35px 0px; + color: #fff; + font-size: 14px; + text-align: center; + text-shadow: 0px -1px 0px rgba(0,0,0,.5); + } + + /* Progress ------------------------------------------------*/ + .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 0px 0px 2px #222; + border-radius: 50px; + + /* Animation */ + -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 0px 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/css/font/fontawesome-webfont.eot b/assets/font/fontawesome-webfont.eot similarity index 100% rename from css/font/fontawesome-webfont.eot rename to assets/font/fontawesome-webfont.eot diff --git a/css/font/fontawesome-webfont.svg b/assets/font/fontawesome-webfont.svg similarity index 100% rename from css/font/fontawesome-webfont.svg rename to assets/font/fontawesome-webfont.svg diff --git a/css/font/fontawesome-webfont.ttf b/assets/font/fontawesome-webfont.ttf similarity index 100% rename from css/font/fontawesome-webfont.ttf rename to assets/font/fontawesome-webfont.ttf diff --git a/css/font/fontawesome-webfont.woff b/assets/font/fontawesome-webfont.woff similarity index 100% rename from css/font/fontawesome-webfont.woff rename to assets/font/fontawesome-webfont.woff diff --git a/assets/img/apple-touch-icon-ipad.png b/assets/img/apple-touch-icon-ipad.png new file mode 100644 index 0000000000000000000000000000000000000000..4e552b3b275d9914731866848a064516742b8cc3 GIT binary patch literal 6033 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 zM?x<;@v-7no_images \ No newline at end of file diff --git a/assets/img/password.svg b/assets/img/password.svg new file mode 100644 index 0000000..34bca5b --- /dev/null +++ b/assets/img/password.svg @@ -0,0 +1 @@ +password \ No newline at end of file diff --git a/js/frameworks.js b/assets/js/min/frameworks.js similarity index 100% rename from js/frameworks.js rename to assets/js/min/frameworks.js diff --git a/assets/js/min/main.js b/assets/js/min/main.js new file mode 100644 index 0000000..95fec77 --- /dev/null +++ b/assets/js/min/main.js @@ -0,0 +1,2 @@ +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)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+"&delAll=true";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="",title=albumJSON.title;if(title.length>18)title=albumJSON.title.substr(0,18)+"...";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="",title=photoJSON.title;if(title.length>18)title=photoJSON.title.substr(0,18)+"...";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,orientation){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){contextMenu.close();$("body").css("overflow","hidden").append(build.contextMenu(items,orientation));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})},add:function(e){var mouse_x=e.pageX,mouse_y=e.pageY,items;mouse_y-=$(document).scrollTop();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){e.preventDefault();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){e.preventDefault();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=[];mouse_y-=$(document).scrollTop();if(orientation===undefined)orientation="left";if(!mouse_x||!mouse_y){mouse_x="10px";mouse_y="10px"}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");$("body").css("overflow","hidden").append(build.contextMenu(items,orientation));if(!visible.photo())mouse_x+=$(".contextmenu").width();$(".contextmenu").css({top:mouse_y,left:mouse_x-$(".contextmenu").width()})})},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)}];items=[["",-1],["separator",-1],[" Make Private",0],["separator",-1],[" Twitter",1],[" Facebook",2],[" Mail",3],[" Dropbox",4]];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","scroll")}};$(document).ready(function(){var event_name=mobileBrowser()?"touchend":"click";if(window.webkitNotifications)window.webkitNotifications.requestPermission();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(){window.open(photo.getDirectLink(),"_newtab")});$("#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())});$("#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("f",function(){if(visible.photo())$("#button_download").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(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",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(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},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")}},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+"

")},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"){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();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();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()){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();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").retina()},title:function(albumID){var prefix="",title=albums.json.content[albumID].title;if(albums.json.content[albumID].password)prefix=" ";if(title.length>18)title=title.substr(0,18)+"...";$(".album[data-id='"+albumID+"'] .overlay h1").html(prefix+title)},"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").retina()},title:function(photoID){var title=album.json.content[photoID].title;if(title.length>18)title=title.substr(0,18)+"...";$(".photo[data-id='"+photoID+"'] .overlay h1").html(title)},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","scroll");$(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 diff --git a/js/modules/album.js b/assets/js/modules/album.js similarity index 52% rename from js/modules/album.js rename to assets/js/modules/album.js index 85fd938..142b3b9 100644 --- a/js/modules/album.js +++ b/assets/js/modules/album.js @@ -1,11 +1,8 @@ /** - * @name album.js - * @author Philipp Maurer - * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - * - * Album Module - * Takes care of every action an album can handle and execute. + * @name Album Module + * @description Takes care of every action an album can handle and execute. + * @author Tobias Reich + * @copyright 2014 by Tobias Reich */ album = { @@ -33,8 +30,7 @@ album = { var startTime, params, durationTime, - waitTime, - photosData = ""; + waitTime; password.get(albumID, function() { @@ -47,14 +43,14 @@ album = { startTime = new Date().getTime(); params = "getAlbum&albumID=" + albumID + "&password=" + password.value; - lychee.api(params, "json", function(data) { + lychee.api(params, function(data) { - if (data=="HTTP/1.1 403 Album private!") { + if (data==="Warning: Album private!") { lychee.setMode("view"); return false; } - if (data=="HTTP/1.1 403 Wrong password!") { + if (data==="Warning: Wrong password!") { album.load(albumID, refresh); return false; } @@ -66,14 +62,14 @@ album = { 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); }); @@ -91,22 +87,35 @@ album = { add: function() { - var title = prompt("Please enter a title for this album:", "Untitled"), - params; + var title, + params, + buttons; - if (title.length>0&&title.length<31) { + buttons = [ + ["Create Album", function() { - modal.close(); + title = $(".message input.text").val(); - params = "addAlbum&title=" + escape(encodeURI(title)); - lychee.api(params, "text", function(data) { + if (title==="") title = "Untitled"; - if (data) lychee.goto("a" + data); - else loadingBar.show("error"); + if (title.length>0&&title.length<31) { - }); + modal.close(); - } else if (title.length>0) loadingBar.show("error", "Error", "Title to short or too long. Please try another one!"); + params = "addAlbum&title=" + escape(encodeURI(title)); + lychee.api(params, function(data) { + + if (data!==false) 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); }, @@ -120,12 +129,14 @@ album = { ["Delete Album and Photos", function() { params = "deleteAlbum&albumID=" + albumID + "&delAll=true"; - lychee.api(params, "text", function(data) { + lychee.api(params, function(data) { - if (visible.albums()) view.albums.content.delete(albumID); - else lychee.goto(""); + if (visible.albums()) { + albums.json.num--; + view.albums.content.delete(albumID); + } else lychee.goto(""); - if (!data) loadingBar.show("error"); + if (data!==true) lychee.error(null, params, data); }); @@ -133,7 +144,7 @@ album = { ["Keep Album", function() {}] ]; - if (albumID==0) { + 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) @@ -152,66 +163,113 @@ album = { var oldTitle = "", newTitle, - params; + params, + buttons; - if (!albumID) albumID = album.getID(); + if (!albumID) return false; if (album.json) oldTitle = album.json.title; else if (albums.json) oldTitle = albums.json.content[albumID].title; - newTitle = prompt("Please enter a new title for this album:", oldTitle); + buttons = [ + ["Set Title", function() { - if (albumID!=""&&albumID!=null&&albumID&&newTitle.length>0&&newTitle.length<31) { + newTitle = $(".message input.text").val(); - if (visible.album()) { + if (newTitle==="") newTitle = "Untitled"; - album.json.title = newTitle; - view.album.title(); + if (albumID!==""&&albumID!=null&&albumID&&newTitle.length<31) { - } else if (visible.albums()) { + if (visible.album()) { - albums.json.content[albumID].title = newTitle; - view.albums.content.title(albumID); + album.json.title = newTitle; + view.album.title(oldTitle); - } + } else if (visible.albums()) { - params = "setAlbumTitle&albumID=" + albumID + "&title=" + escape(encodeURI(newTitle)); - lychee.api(params, "text", function(data) { + albums.json.content[albumID].title = newTitle; + view.albums.content.title(albumID); - if (!data) loadingBar.show("error"); + } - }); + 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 if (newTitle.length>0) loadingBar.show("error", "Error", "New title to short or too long. Please try another one!"); + }); + + } 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 ($("input.password").length>0&&$("input.password").val().length>0) { - - params = "setAlbumPublic&albumID=" + albumID + "&password=" + hex_md5($("input.password").val()); + + 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, "text", function(data) { - if (!data) loadingBar.show("error"); + lychee.api(params, function(data) { + + if (data!==true) lychee.error(null, params, data); }); @@ -247,6 +305,9 @@ album = { 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; } diff --git a/js/modules/albums.js b/assets/js/modules/albums.js similarity index 71% rename from js/modules/albums.js rename to assets/js/modules/albums.js index 73179db..11f1652 100644 --- a/js/modules/albums.js +++ b/assets/js/modules/albums.js @@ -1,11 +1,8 @@ /** - * @name albums.js - * @author Philipp Maurer - * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - * - * Albums Module - * Takes care of every action albums can handle and execute. + * @name Albums Module + * @description Takes care of every action albums can handle and execute. + * @author Tobias Reich + * @copyright 2014 by Tobias Reich */ albums = { @@ -16,18 +13,14 @@ albums = { var startTime, durationTime, - unsortedAlbum, - starredAlbum, - publicAlbum, - smartData = "", - albumsData = ""; + waitTime; lychee.animate(".album, .photo", "contentZoomOut"); lychee.animate(".divider", "fadeOut"); startTime = new Date().getTime(); - lychee.api("getAlbums", "json", function(data) { + lychee.api("getAlbums", function(data) { /* Smart Albums */ data.unsortedAlbum = { @@ -81,13 +74,13 @@ albums = { parse: function(album) { if (album.password&&lychee.publicMode) { - album.thumb0 = "img/password.png"; - album.thumb1 = "img/password.png"; - album.thumb2 = "img/password.png"; + 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 = "img/no_images.png"; - if (album.thumb1) album.thumb1 = lychee.upload_path_thumb + album.thumb1; else album.thumb1 = "img/no_images.png"; - if (album.thumb2) album.thumb2 = lychee.upload_path_thumb + album.thumb2; else album.thumb2 = "img/no_images.png"; + 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"; } } diff --git a/assets/js/modules/build.js b/assets/js/modules/build.js new file mode 100755 index 0000000..860765a --- /dev/null +++ b/assets/js/modules/build.js @@ -0,0 +1,410 @@ +/** + * @name Build Module + * @description This module is used to generate HTML-Code. + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +build = { + + divider: function(title) { + + return "

" + title + "

"; + + }, + + editIcon: function(id) { + + return "
"; + + }, + + album: function(albumJSON) { + + if (!albumJSON) return ""; + + var album = "", + title = albumJSON.title; + + if (title.length>18) title = albumJSON.title.substr(0, 18) + "..."; + + 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 = "", + title = photoJSON.title; + + if (title.length>18) title = photoJSON.title.substr(0, 18) + "..."; + + 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, orientation) { + + 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"); + + //["Tags", "AbstractColorsPhotoshopSomethingLycheeTags"] + 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 "": // Separator + infobox += ""; + infobox += "

" + infos[index][1] + "

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

" + infos[index][0] + "

"; + infobox += ""; + infobox += "
" + infos[index][1] + "
"; + infobox += ""; + break; + + default: // Item + 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; + + } + +} \ No newline at end of file diff --git a/js/modules/contextMenu.js b/assets/js/modules/contextMenu.js similarity index 50% rename from js/modules/contextMenu.js rename to assets/js/modules/contextMenu.js index e2f2c96..8f88c89 100644 --- a/js/modules/contextMenu.js +++ b/assets/js/modules/contextMenu.js @@ -1,26 +1,101 @@ /** - * @name contextMenu.js - * @author Philipp Maurer - * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - * - * ContextMenu Module - * This module is used for the context menu. + * @name ContextMenu Module + * @description This module is used for the context menu. + * @author Tobias Reich + * @copyright 2014 by Tobias Reich */ contextMenu = { fns: null, - album: function(e) { + show: function(items, mouse_x, mouse_y, orientation) { + + contextMenu.close(); + + $("body") + .css("overflow", "hidden") + .append(build.contextMenu(items, orientation)); + + 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 + }); + + }, + + add: function(e) { + + var mouse_x = e.pageX, + mouse_y = e.pageY, + items; + + mouse_y -= $(document).scrollTop(); + + 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) { e.preventDefault(); var mouse_x = e.pageX, mouse_y = e.pageY, - albumID = album.getID(), items; - if (albumID=="0"||albumID=="f"||albumID=="s") return false; + if (albumID==="0"||albumID==="f"||albumID==="s") return false; mouse_y -= $(document).scrollTop(); @@ -34,24 +109,17 @@ contextMenu = { [" Delete", 1] ]; - contextMenu.close(); + contextMenu.show(items, mouse_x, mouse_y, "right"); + $(".album[data-id='" + albumID + "']").addClass("active"); - $("body") - .css("overflow", "hidden") - .append(build.contextMenu(items)); - $(".contextmenu").css({ - "top": mouse_y, - "left": mouse_x - }); }, - photo: function(e) { + photo: function(photoID, e) { e.preventDefault(); var mouse_x = e.pageX, mouse_y = e.pageY, - photoID = photo.getID(), items; mouse_y -= $(document).scrollTop(); @@ -59,7 +127,7 @@ contextMenu = { contextMenu.fns = [ function() { photo.setStar(photoID) }, function() { photo.setTitle(photoID) }, - function() { contextMenu.move(photoID, e) }, + function() { contextMenu.move(photoID, e, "right") }, function() { photo.delete(photoID) } ]; @@ -71,41 +139,36 @@ contextMenu = { [" Delete", 3] ]; - contextMenu.close(); + contextMenu.show(items, mouse_x, mouse_y, "right"); + $(".photo[data-id='" + photoID + "']").addClass("active"); - $("body") - .css("overflow", "hidden") - .append(build.contextMenu(items)); - $(".contextmenu").css({ - "top": mouse_y, - "left": mouse_x - }); }, - move: function(photoID, e) { + move: function(photoID, e, orientation) { var mouse_x = e.pageX, mouse_y = e.pageY, - items = [], - albumID; + items = []; contextMenu.fns = []; mouse_y -= $(document).scrollTop(); + if (orientation===undefined) orientation = "left"; + if (!mouse_x||!mouse_y) { mouse_x = "10px"; mouse_y = "10px"; } - if (album.getID()!=0) { + if (album.getID()!=="0") { items = [ ["Unsorted", 0, "photo.setAlbum(0, " + photoID + ")"], ["separator", -1] ]; } - lychee.api("getAlbums", "json", function(data) { + lychee.api("getAlbums", function(data) { if (!data.albums) { items = [["New Album", 0, "album.add()"]]; @@ -119,7 +182,7 @@ contextMenu = { $(".photo[data-id='" + photoID + "']").addClass("active"); $("body") .css("overflow", "hidden") - .append(build.contextMenu(items)); + .append(build.contextMenu(items, orientation)); if (!visible.photo()) mouse_x += $(".contextmenu").width(); $(".contextmenu").css({ "top": mouse_y, @@ -138,11 +201,6 @@ contextMenu = { mouse_y -= $(document).scrollTop(); - if (!mouse_x||!mouse_y) { - mouse_x = "10px"; - mouse_y = "10px"; - } - contextMenu.fns = [ function() { photo.setPublic(photoID) }, function() { photo.share(photoID, 0) }, @@ -151,40 +209,18 @@ contextMenu = { function() { photo.share(photoID, 3) } ]; - if (document.location.hostname!="localhost") { - - items = [ - ["", -1], - ["separator", -1], - [" Make Private", 0], - ["separator", -1], - [" Twitter", 1], - [" Facebook", 2], - [" Mail", 3], - [" Dropbox", 4] - ]; - - } else { - - items = [ - ["", -1], - ["separator", -1], - [" Make Private", 0], - ["separator", -1], - [" Mail", 3] - ]; - - } - - contextMenu.close(); - $("body") - .css("overflow", "hidden") - .append(build.contextMenu(items)); - $(".contextmenu").css({ - "top": mouse_y, - "left": mouse_x+20-$(".contextmenu").width() - }); + items = [ + ["", -1], + ["separator", -1], + [" Make Private", 0], + ["separator", -1], + [" Twitter", 1], + [" Facebook", 2], + [" Mail", 3], + [" Dropbox", 4] + ]; + contextMenu.show(items, mouse_x, mouse_y, "left"); $(".contextmenu input").focus(); }, @@ -197,11 +233,6 @@ contextMenu = { mouse_y -= $(document).scrollTop(); - if (!mouse_x||!mouse_y) { - mouse_x = "10px"; - mouse_y = "10px"; - } - contextMenu.fns = [ function() { album.setPublic(albumID) }, function() { password.set(albumID) }, @@ -211,43 +242,20 @@ contextMenu = { function() { password.remove(albumID) } ]; - if (document.location.hostname!="localhost") { - - items = [ - ["", -1], - ["separator", -1], - [" Make Private", 0], - [" Set Password", 1], - ["separator", -1], - [" Twitter", 2], - [" Facebook", 3], - [" Mail", 4], - ]; - - } else { - - items = [ - ["", -1], - ["separator", -1], - [" Make Private", 0], - [" Set Password", 1], - ["separator", -1], - [" Mail", 4], - ]; - - } + 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.close(); - $("body") - .css("overflow", "hidden") - .append(build.contextMenu(items)); - $(".contextmenu").css({ - "top": mouse_y, - "left": mouse_x+20-$(".contextmenu").width() - }); - + contextMenu.show(items, mouse_x, mouse_y, "left"); $(".contextmenu input").focus(); }, diff --git a/assets/js/modules/init.js b/assets/js/modules/init.js new file mode 100755 index 0000000..9a11ef3 --- /dev/null +++ b/assets/js/modules/init.js @@ -0,0 +1,138 @@ +/** + * @name Init Module + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +$(document).ready(function(){ + + /* Event Name */ + var event_name = (mobileBrowser()) ? "touchend" : "click"; + + /* Notifications */ + if (window.webkitNotifications) window.webkitNotifications.requestPermission(); + + /* Tooltips */ + if (!mobileBrowser()) $(".tools").tipsy({gravity: 'n', fade: false, delayIn: 0, opacity: 1}); + + /* Header */ + $("#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() { window.open(photo.getDirectLink(),"_newtab") }); + $("#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 */ + $("#search").on("keyup click", function() { search.find($(this).val()) }); + + /* Back Buttons */ + $("#button_back_home").on(event_name, function() { lychee.goto("") }); + $("#button_back").on(event_name, function() { lychee.goto(album.getID()) }); + + /* Image View */ + 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 */ + $("#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()) }); + + /* Keyboard */ + Mousetrap + .bind('u', function() { $("#upload_files").click() }) + .bind('s', function() { if (visible.photo()) $("#button_star").click() }) + .bind('f', function() { if (visible.photo()) $("#button_download").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 */ + $(document) + + /* Login */ + .on("keyup", "#password", function() { if ($(this).val().length>0) $(this).removeClass("error") }) + + /* Header */ + .on(event_name, "#title.editable", 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")) }) + + /* Modal */ + .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() }) + + /* Add Dialog */ + .on(event_name, ".button_add", function(e) { contextMenu.add(e) }) + + /* Upload */ + .on("change", "#upload_files", function() { modal.close(); upload.start.local(this.files) }) + + /* Context Menu */ + .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) + + /* Infobox */ + .on(event_name, "#infobox_overlay", view.infobox.hide) + + /* Upload */ + .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; + }); + + /* Init */ + lychee.init(); + +}); \ No newline at end of file diff --git a/js/modules/loadingBar.js b/assets/js/modules/loadingBar.js similarity index 59% rename from js/modules/loadingBar.js rename to assets/js/modules/loadingBar.js index 60c5c80..bfba305 100755 --- a/js/modules/loadingBar.js +++ b/assets/js/modules/loadingBar.js @@ -1,33 +1,29 @@ /** - * @name loadingBar.js - * @author Philipp Maurer - * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - * - * LoadingBar Module - * This module is used to show and hide the loading bar. + * @name LoadingBar Module + * @description This module is used to show and hide the loading bar. + * @author Tobias Reich + * @copyright 2014 by Tobias Reich */ loadingBar = { status: null, - show: function(status, errorTitle, errorText) { + show: function(status, errorText) { - if (status=="error") { + if (status==="error") { loadingBar.status = "error"; - if (!errorTitle) errorTitle = "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("

" + errorTitle + ": " + errorText + "

") + .html("

Error: " + errorText + "

") .show() .css("height", "40px"); - if (visible.controls()) lychee.header.css("margin-Top", "40px"); + if (visible.controls()) lychee.header.addClass("error"); clearTimeout(lychee.loadingBar.data("timeout")); lychee.loadingBar.data("timeout", setTimeout(function() { loadingBar.hide(true) }, 3000)); @@ -42,7 +38,7 @@ loadingBar = { .show() .removeClass("loading uploading error") .addClass("loading"); - if (visible.controls()) lychee.header.css("margin-Top", "3px"); + if (visible.controls()) lychee.header.addClass("loading"); }, 1000)); } @@ -51,12 +47,12 @@ loadingBar = { hide: function(force_hide) { - if ((loadingBar.status!="error"&&loadingBar.status!=null)||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.css("marginTop", "0px"); + if (visible.controls()) lychee.header.removeClass("error loading"); setTimeout(function() { lychee.loadingBar.hide() }, 300); } diff --git a/js/modules/lychee.js b/assets/js/modules/lychee.js similarity index 55% rename from js/modules/lychee.js rename to assets/js/modules/lychee.js index caf3913..96bc064 100644 --- a/js/modules/lychee.js +++ b/assets/js/modules/lychee.js @@ -1,52 +1,72 @@ /** - * @name lychee.js - * @author Philipp Maurer - * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - * - * Lychee Module - * This module provides the basic functions of Lychee. + * @name Lychee Module + * @description This module provides the basic functions of Lychee. + * @author Tobias Reich + * @copyright 2014 by Tobias Reich */ var lychee = { - init: function() { + version: "2.0", - this.version = "1.3.2"; - this.api_path = "php/api.php"; - this.update_path = "http://lychee.electerious.com/version/index.php"; - this.updateURL = "https://github.com/electerious/Lychee"; + 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", - this.upload_path_thumb = "uploads/thumb/"; - this.upload_path_big = "uploads/big/"; + upload_path_thumb: "uploads/thumb/", + upload_path_big: "uploads/big/", - this.publicMode = false; - this.viewMode = false; + publicMode: false, + viewMode: false, + debugMode: false, - this.checkForUpdates = false; + username: "", + checkForUpdates: false, + sorting: "", - this.dropbox = false; + dropbox: false, - this.loadingBar = $("#loading"); - this.header = $("header"); - this.content = $("#content"); - this.imageview = $("#imageview"); - this.infobox = $("#infobox"); + 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; + } + + // No configuration + if (data==="Warning: No configuration!") { + lychee.header.hide(); + lychee.content.hide(); + $("body").append(build.no_content("cog")); + settings.createConfig(); + return true; + } - run: function() { + // No login + if (data.config.login===false) { + settings.createLogin(); + } - lychee.api("init", "json", function(data) { lychee.checkForUpdates = data.config.checkForUpdates; - if (!data.loggedIn) lychee.setMode("public"); $(window).bind("popstate", lychee.load); lychee.load(); + }); }, - api: function(params, type, callback, loading) { + api: function(params, callback, loading) { if (loading==undefined) loadingBar.show(); @@ -54,13 +74,31 @@ var lychee = { type: "POST", url: lychee.api_path, data: "function=" + params, - dataType: type, - success: - function(data) { - setTimeout(function() { loadingBar.hide() }, 100); - callback(data); - }, - error: lychee.error + 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); + + } }); }, @@ -72,8 +110,8 @@ var lychee = { params; params = "login&user=" + user + "&password=" + password; - lychee.api(params, "text", function(data) { - if (data) { + lychee.api(params, function(data) { + if (data===true) { localStorage.setItem("username", user); window.location.reload(); } else { @@ -86,6 +124,8 @@ var lychee = { loginDialog: function() { + var local_username; + $("body").append(build.signInModal()); $("#username").focus(); if (localStorage) { @@ -95,13 +135,13 @@ var lychee = { $("#password").focus(); } } - if (lychee.checkForUpdates) lychee.getUpdate(); + if (lychee.checkForUpdates==="1") lychee.getUpdate(); }, logout: function() { - lychee.api("logout", "text", function(data) { + lychee.api("logout", function(data) { window.location.reload(); }); @@ -118,12 +158,12 @@ var lychee = { var albumID = "", photoID = "", - hash = document.location.hash.replace("#", ""); + hash = document.location.hash.replace("#", "").split("/"); contextMenu.close(); - if (hash.indexOf("a")!=-1) albumID = hash.split("p")[0].replace("a", ""); - if (hash.indexOf("p")!=-1) photoID = hash.split("p")[1]; + if (hash[0]!==undefined) albumID = hash[0]; + if (hash[1]!==undefined) photoID = hash[1]; if (albumID&&photoID) { @@ -132,11 +172,10 @@ var lychee = { photo.json = null; // Show Photo - if (lychee.content.html()==""||($("#search").length&&$("#search").val().length!=0)) { + if (lychee.content.html()===""||($("#search").length&&$("#search").val().length!==0)) { lychee.content.hide(); album.load(albumID, true); } - if (!visible.photo()) view.photo.show(); photo.load(photoID, albumID); } else if (albumID) { @@ -159,6 +198,7 @@ var lychee = { search.code = ""; // Show Albums + if (visible.album()) view.album.hide(); if (visible.photo()) view.photo.hide(); albums.load(); @@ -175,12 +215,11 @@ var lychee = { }, - setTitle: function(title, count, editable) { + setTitle: function(title, editable) { - if (title=="Albums") document.title = "Lychee"; + if (title==="Albums") document.title = "Lychee"; else document.title = "Lychee - " + title; - if (count) title += " - " + count + " photos"; if (editable) $("#title").addClass("editable"); else $("#title").removeClass("editable"); @@ -190,8 +229,8 @@ var lychee = { setMode: function(mode) { - $("#button_signout, #search, #button_trash_album, #button_share_album, #button_edit_album, .button_add, #button_archive, .button_divider").remove(); - $("#button_trash, #button_move, #button_edit, #button_share, #button_star").remove(); + $("#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") }) @@ -207,12 +246,12 @@ var lychee = { .unbind('s') .unbind('backspace'); - if (mode=="public") { + if (mode==="public") { - $("#button_signin").show(); + $("header #button_signin, header #hostedwith").show(); lychee.publicMode = true; - } else if (mode=="view") { + } else if (mode==="view") { Mousetrap.unbind('esc'); $("#button_back, a#next, a#previous").remove(); @@ -262,7 +301,7 @@ var lychee = { g.setAttribute("data-app-key", "iq7lioj9wu0ieqs"); g.onload = g.onreadystatechange = function() { var rs = this.readyState; - if (rs&&rs!="complete"&&rs!="loaded") return; + if (rs&&rs!=="complete"&&rs!=="loaded") return; lychee.dropbox = true; loadingBar.hide(); callback(); @@ -273,12 +312,12 @@ var lychee = { }, - error: function(jqXHR, textStatus, errorThrown) { + error: function(errorThrown, params, data) { - console.log(jqXHR); - console.log(textStatus); - console.log(errorThrown); - loadingBar.show("error", textStatus, errorThrown); + console.log("Error Description: " + errorThrown); + console.log("Error Params: " + params); + console.log("Server Response: " + data); + loadingBar.show("error", errorThrown); } diff --git a/assets/js/modules/modal.js b/assets/js/modules/modal.js new file mode 100644 index 0000000..bc2969e --- /dev/null +++ b/assets/js/modules/modal.js @@ -0,0 +1,35 @@ +/** + * @name Modal Module + * @description Build, show and hide a modal. + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +modal = { + + fns: null, + + show: function(title, text, buttons, marginTop, closeButton) { + + if (!buttons) { + var buttons = [ + ["", function() {}], + ["", function() {}] + ]; + } + + modal.fns = [buttons[0][1], buttons[1][1]]; + $("body").append(build.modal(title, text, buttons, marginTop, closeButton)); + $(".message input:first-child").focus(); + + }, + + close: function() { + + modal.fns = null; + $(".message_overlay").removeClass("fadeIn").css("opacity", 0); + setTimeout(function() { $(".message_overlay").remove() }, 300); + + } + +} \ No newline at end of file diff --git a/js/modules/password.js b/assets/js/modules/password.js similarity index 60% rename from js/modules/password.js rename to assets/js/modules/password.js index ed4ea0b..9253f2c 100644 --- a/js/modules/password.js +++ b/assets/js/modules/password.js @@ -1,11 +1,8 @@ /** - * @name password.js - * @author Philipp Maurer + * @name Password Module + * @description Controls the access to password-protected albums and photos. * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - * - * Password Module - * Controls the access to password-protected albums and photos. + * @copyright 2014 by Tobias Reich */ password = { @@ -20,25 +17,28 @@ password = { buttons = [ ["Set Password", function() { - if (visible.album()) album.json.password = true; + if (visible.album()) { + album.json.password = true; + view.album.password(); + } - params = "setAlbumPassword&albumID=" + albumID + "&password=" + hex_md5($("input.password").val()); - lychee.api(params, "text", function(data) { + params = "setAlbumPassword&albumID=" + albumID + "&password=" + hex_md5($(".message input.text").val()); + lychee.api(params, function(data) { - if (!data) loadingBar.show("error"); + 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); + 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 = $("input.password").val(), + var passwd = $(".message input.text").val(), params; if (!lychee.publicMode) callback(); @@ -59,14 +59,14 @@ password = { // Check password params = "checkAlbumAccess&albumID=" + albumID + "&password=" + hex_md5(passwd); - lychee.api(params, "text", function(data) { + lychee.api(params, function(data) { - if (data) { + if (data===true) { password.value = hex_md5(passwd); callback(); } else { lychee.goto(""); - loadingBar.show("error", "Error", "Access denied. Wrong password!"); + loadingBar.show("error", "Access denied. Wrong password!"); } }); @@ -83,7 +83,7 @@ password = { ["Enter", function() { password.get(albumID, callback) }], ["Cancel", lychee.goto] ]; - modal.show(" Enter Password", "This album is protected with a password. Enter the password below to view the photos of this album: ", buttons); + 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); }, @@ -91,12 +91,15 @@ password = { var params; - if (visible.album()) album.json.password = false; + if (visible.album()) { + album.json.password = false; + view.album.password(); + } params = "setAlbumPassword&albumID=" + albumID + "&password="; - lychee.api(params, "text", function(data) { + lychee.api(params, function(data) { - if (!data) loadingBar.show("error"); + if (data!==true) lychee.error(null, params, data); }); diff --git a/assets/js/modules/photo.js b/assets/js/modules/photo.js new file mode 100644 index 0000000..b944ef1 --- /dev/null +++ b/assets/js/modules/photo.js @@ -0,0 +1,315 @@ +/** + * @name Photo Module + * @description Takes care of every action a photo can handle and execute. + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +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() { + + // 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); + + // Only when search is not active + 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 (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; + + }, + + getDirectLink: function() { + + return $("#imageview #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/ig, ""); + + }, + + 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); + + } + +} \ No newline at end of file diff --git a/js/modules/search.js b/assets/js/modules/search.js similarity index 67% rename from js/modules/search.js rename to assets/js/modules/search.js index b07da4d..cae7b67 100755 --- a/js/modules/search.js +++ b/assets/js/modules/search.js @@ -1,11 +1,8 @@ /** - * @name search.js - * @author Philipp Maurer - * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - * - * Search Module - * Searches through your photos and albums. + * @name Search Module + * @description Searches through your photos and albums. + * @author Tobias Reich + * @copyright 2014 by Tobias Reich */ search = { @@ -22,10 +19,10 @@ search = { clearTimeout($(window).data("timeout")); $(window).data("timeout", setTimeout(function() { - if ($("#search").val().length!=0) { + if ($("#search").val().length!==0) { params = "search&term=" + term; - lychee.api(params, "json", function(data) { + lychee.api(params, function(data) { if (data&&data.albums) { albums.json = { content: data.albums }; @@ -43,12 +40,12 @@ search = { }); } - if (albumsData==""&&photosData=="") code = "error"; - else if (albumsData=="") code = build.divider("Photos")+photosData; - else if (photosData=="") code = build.divider("Albums")+albumsData; + 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)) { + if (search.code!==hex_md5(code)) { $(".no_content").remove(); @@ -59,7 +56,7 @@ search = { setTimeout(function() { - if (code=="error") $("body").append(build.no_content("search")); + if (code==="error") $("body").append(build.no_content("search")); else { lychee.content.html(code); lychee.animate(".album, .photo", "contentZoomIn"); @@ -82,7 +79,7 @@ search = { $("#search").val(""); $(".no_content").remove(); - if (search.code!="") { + if (search.code!=="") { search.code = ""; lychee.animate(".divider", "fadeOut"); diff --git a/assets/js/modules/settings.js b/assets/js/modules/settings.js new file mode 100644 index 0000000..fec2be9 --- /dev/null +++ b/assets/js/modules/settings.js @@ -0,0 +1,238 @@ +/** + * @name Settings Module + * @description Lets you change settings. + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +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) { + + // Configuration failed + setTimeout(function() { + + // Connection failed + 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; + + } + + // Could not create file + 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; + + } + + // Something went wrong + 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 { + + // Configuration successful + 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]); + } + + } + +} \ No newline at end of file diff --git a/assets/js/modules/upload.js b/assets/js/modules/upload.js new file mode 100644 index 0000000..3289235 --- /dev/null +++ b/assets/js/modules/upload.js @@ -0,0 +1,253 @@ +/** + * @name Album Module + * @description Takes care of every action an album can handle and execute. + * @author Tobias Reich + * @copyright 2014 by Tobias Reich + */ + +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 + "

"); + + }, + + 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; i < files.length; i++) { + + if (files[i].type!=="image/jpeg"&&files[i].type!=="image/jpg"&&files[i].type!=="image/png"&&files[i].type!=="image/gif") { + loadingBar.show("error", "The file format of " + files[i].name + " is not supported."); + return false; + } else { + formData.append(i, files[i]); + } + + } + + upload.show(); + + window.onbeforeunload = function() { return "Lychee is currently uploading!"; }; + + xhr.open("POST", lychee.api_path); + + xhr.onload = function() { + + if (xhr.status===200) { + + upload.close(); + + // WebKit Notification + if (window.webkitNotifications&&BrowserDetect.browser==="Safari") { + popup = window.webkitNotifications.createNotification("", "Upload complete", "You can now manage your new photo."); + popup.show(); + } + + window.onbeforeunload = null; + + if (album.getID()===false) lychee.goto("0"); + else album.load(albumID); + + } + + }; + + xhr.upload.onprogress = function(e) { + + if (e.lengthComputable) { + + progress = (e.loaded / e.total * 100 | 0); + + if (progress>pre_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") { + 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(); + + 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(); + + 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; i < files.length; i++) files[i] = files[i].link; + + } else files = files[0].link; + + upload.show("cog", "Importing photos"); + + params = "importUrl&url=" + escape(files) + "&albumID=" + albumID; + lychee.api(params, function(data) { + + upload.close(); + + if (album.getID()===false) lychee.goto("0"); + else album.load(albumID); + + if (data!==true) lychee.error(null, params, data); + + }); + + } + }); + }); + + } + + }, + + close: function(force) { + + if (force===true) { + $(".upload_overlay").remove(); + } else { + upload.setProgress(100); + $(".upload_overlay").removeClass("fadeIn").css("opacity", 0); + setTimeout(function() { $(".upload_overlay").remove() }, 300); + } + + } + +} \ No newline at end of file diff --git a/js/modules/view.js b/assets/js/modules/view.js similarity index 64% rename from js/modules/view.js rename to assets/js/modules/view.js index 6ecb6d8..8dc23ca 100644 --- a/js/modules/view.js +++ b/assets/js/modules/view.js @@ -1,11 +1,8 @@ /** - * @name view.js - * @author Philipp Maurer - * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - * - * UI View - * Responsible to reflect data changes to the UI. + * @name UI View + * @description Responsible to reflect data changes to the UI. + * @author Tobias Reich + * @copyright 2014 by Tobias Reich */ view = { @@ -19,14 +16,14 @@ view = { if (visible.photo()) { lychee.imageview.removeClass("full"); lychee.loadingBar.css("opacity", 1); - lychee.header.css("margin-Top", "0px"); + 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: 70, + top: 60, right: 30, bottom: 30, left: 30 @@ -43,7 +40,7 @@ view = { $(window).data("timeout", setTimeout(function() { lychee.imageview.addClass("full"); lychee.loadingBar.css("opacity", 0); - lychee.header.css("margin-Top", "-45px"); + lychee.header.addClass("hidden"); if ($("#imageview #image.small").length>0) { $("#imageview #image").css({ marginTop: -1*($("#imageview #image").height()/2) @@ -63,31 +60,58 @@ view = { mode: function(mode) { - var albumID; + 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(); - albumID = album.getID(); - if (albumID=="s"||albumID=="f") $("#button_edit_album, #button_trash_album, #button_share_album").hide(); - else if (albumID==0) $("#button_edit_album, #button_share_album").hide(); - else $("#button_edit_album, #button_trash_album, #button_share_album").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() { @@ -99,7 +123,7 @@ view = { title: function() { - lychee.setTitle("Albums", null, false); + lychee.setTitle("Albums", false); }, @@ -127,7 +151,7 @@ view = { } - if (smartData==""&&albumsData=="") $("body").append(build.no_content("picture")); + if (smartData===""&&albumsData==="") $("body").append(build.no_content("picture")); else lychee.content.html(smartData + albumsData); $("img").retina(); @@ -153,6 +177,7 @@ view = { marginLeft: 0 }, 300, function() { $(this).remove(); + if (albums.json.num<=0) lychee.animate(".divider:last-of-type", "fadeOut"); }); } @@ -167,6 +192,7 @@ view = { album.parse(); + view.album.infobox(); view.album.title(); view.album.public(); view.album.content.init(); @@ -175,22 +201,29 @@ view = { }, - title: function() { + hide: function() { + + view.infobox.hide(); + + }, + + title: function(oldTitle) { if ((visible.album()||!album.json.init)&&!visible.photo()) { switch (album.getID()) { case "f": - lychee.setTitle("Starred", album.json.num, false); + lychee.setTitle("Starred", false); break; case "s": - lychee.setTitle("Public", album.json.num, false); + lychee.setTitle("Public", false); break; case "0": - lychee.setTitle("Unsorted", album.json.num, false); + lychee.setTitle("Unsorted", false); break; default: - lychee.setTitle(album.json.title, album.json.num, true); + if (album.json.init) $("#infobox .attr_name").html(album.json.title + " " + build.editIcon("edit_title_album")); + lychee.setTitle(album.json.title, true); break; } @@ -198,6 +231,12 @@ view = { }, + description: function() { + + $("#infobox .attr_description").html(album.json.description + " " + build.editIcon("edit_description_album")); + + }, + content: { init: function() { @@ -248,6 +287,7 @@ view = { // Only when search is not active if (!visible.albums()) { album.json.num--; + view.album.num(); view.album.title(); } }); @@ -256,17 +296,38 @@ view = { }, + 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(); + } }, @@ -289,11 +350,18 @@ view = { 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"); }, @@ -301,43 +369,38 @@ view = { hide: function() { if (!visible.controls()) view.header.show(); - if (visible.infobox) view.photo.hideInfobox(); + if (visible.infobox) view.infobox.hide(); + lychee.content.removeClass("view"); view.header.mode("album"); // Make body scrollable $("body").css("overflow", "scroll"); + // Disable Fullscreen + $(document) + .unbind("mouseenter") + .unbind("mouseleave"); + // Hide Photo lychee.animate(lychee.imageview, "fadeOut"); - setTimeout(function() { lychee.imageview.hide() }, 300); - - }, - - showInfobox: function() { - - if (!visible.infobox()) $("body").append("
"); - lychee.infobox.css("right", "0px"); - - }, - - hideInfobox: function() { - - $("#infobox_overlay").remove(); - lychee.infobox.css("right", "-320px"); + setTimeout(function() { + lychee.imageview.hide(); + view.album.infobox(); + }, 300); }, title: function(oldTitle) { - if (photo.json.init) $("#infobox .attr_name").html($("#infobox .attr_name").html().replace(oldTitle, photo.json.title)); - lychee.setTitle(photo.json.title, null, true); + if (photo.json.init) $("#infobox .attr_name").html(photo.json.title + " " + build.editIcon("edit_title")); + lychee.setTitle(photo.json.title, true); }, - description: function(oldDescription) { + description: function() { - if (photo.json.init) $("#infobox .attr_description").html($("#infobox .attr_description").html().replace(oldDescription, photo.json.description)); + if (photo.json.init) $("#infobox .attr_description").html(photo.json.description + " " + build.editIcon("edit_description")); }, @@ -374,19 +437,16 @@ view = { photo: function() { - if (visible.controls()&&photo.isSmall()) lychee.imageview.html("
"); - else if (visible.controls()) lychee.imageview.html("
"); - else if (photo.isSmall()) lychee.imageview.html("
"); - else lychee.imageview.html("
"); + lychee.imageview.html(build.imageview(photo.json, photo.isSmall(), visible.controls())); - if (!photo.json.nextPhoto||lychee.viewMode) $("a#next").hide(); - if (!photo.json.previousPhoto||lychee.viewMode) $("a#previous").hide(); + 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.infobox(photo.json)).show(); + lychee.infobox.html(build.infoboxPhoto(photo.json)).show(); } diff --git a/js/modules/visible.js b/assets/js/modules/visible.js similarity index 53% rename from js/modules/visible.js rename to assets/js/modules/visible.js index 8ece3a1..2855354 100755 --- a/js/modules/visible.js +++ b/assets/js/modules/visible.js @@ -1,22 +1,19 @@ /** - * @name visible.js - * @author Philipp Maurer - * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - * - * Visible Module - * This module is used to check if elements are visible or not. + * @name Visible Module + * @description This module is used to check if elements are visible or not. + * @author Tobias Reich + * @copyright 2014 by Tobias Reich */ 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; }, @@ -26,8 +23,8 @@ visible = { }, infobox: function() { - if (parseInt(lychee.infobox.css("right").replace("px", ""))==-320) return false; - else return true; + if ($("#infobox.active").length>0) return true; + else return false; }, controls: function() { @@ -40,6 +37,11 @@ visible = { 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; diff --git a/js/view.js b/assets/js/view.js old mode 100755 new mode 100644 similarity index 81% rename from js/view.js rename to assets/js/view.js index d542f68..00ed53f --- a/js/view.js +++ b/assets/js/view.js @@ -1,8 +1,8 @@ /** - * @name view.js - * @author Philipp Maurer + * @name View + * @description Used to view single photos with view.php * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich + * @copyright 2014 by Tobias Reich */ var header = $("header"), @@ -38,7 +38,7 @@ $(document).ready(function(){ function key(e) { code = (e.keyCode ? e.keyCode : e.which); - if (code==27&&visibleInfobox()) { hideInfobox(); e.preventDefault(); } + if (code===27&&visibleInfobox()) { hideInfobox(); e.preventDefault(); } } @@ -66,15 +66,16 @@ function isPhotoSmall(photo) { function showInfobox() { - $("body").append("
"); - infobox.css("right", "0px"); + $("body").append("
"); + infobox.addClass("active"); } function hideInfobox() { - $("#infobox_overlay").remove(); - infobox.css("right", "-320px"); + $("#infobox_overlay").removeClass("fadeIn").addClass("fadeOut"); + setTimeout(function() { $("#infobox_overlay").remove() }, 300); + infobox.removeClass("active"); } @@ -91,10 +92,10 @@ function loadPhotoInfo(photoID) { imageview.attr("data-id", photoID); if (isPhotoSmall(data)) imageview.html("
"); - else imageview.html("
"); + else imageview.html("
"); imageview.removeClass("fadeOut").addClass("fadeIn").show(); - infobox.html(build.infobox(data, true)).show(); + infobox.html(build.infoboxPhoto(data, true)).show(); }, error: ajaxError }); diff --git a/css/animations.css b/css/animations.css deleted file mode 100755 index e45fc77..0000000 --- a/css/animations.css +++ /dev/null @@ -1,485 +0,0 @@ -/** - * @name animations.css - * @author Philipp Maurer - * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - */ - -/* bounceInDown ------------------------------------------------*/ -@-webkit-keyframes bounceInDown { - 0% { - -webkit-transform: translateY(-2000px); - } - 60% { - -webkit-transform: translateY(30px); - } - 80% { - -webkit-transform: translateY(-10px); - } - 100% { - -webkit-transform: translateY(0); - } -} -@-moz-keyframes bounceInDown { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -@-ms-keyframes bounceInDown { - 0% { - -ms-transform: translateY(-2000px); - } - 60% { - -ms-transform: translateY(30px); - } - 80% { - -ms-transform: translateY(-10px); - } - 100% { - -ms-transform: translateY(0); - } -} -@-o-keyframes bounceInDown { - 0% { - -o-transform: translateY(-2000px); - } - 60% { - -o-transform: translateY(30px); - } - 80% { - -o-transform: translateY(-10px); - } - 100% { - -o-transform: translateY(0); - } -} -@keyframes bounceInDown { - 0% { - transform: translateY(-2000px); - } - 60% { - transform: translateY(30px); - } - 80% { - transform: translateY(-10px); - } - 100% { - transform: translateY(0); - } -} - -/* bounceOutUp ------------------------------------------------*/ -@-webkit-keyframes bounceOutUp { - 0% { - -webkit-transform: translateY(0); - } - 20% { - -webkit-transform: translateY(20px); - } - 100% { - -webkit-transform: translateY(-2000px); - } -} -@-moz-keyframes bounceOutUp { - 0% { - opacity: 1; - } - 100% { - opacity: 0; - } -} -@-ms-keyframes bounceOutUp { - 0% { - -ms-transform: translateY(0); - } - 20% { - -ms-transform: translateY(20px); - } - 100% { - -ms-transform: translateY(-2000px); - } -} -@-o-keyframes bounceOutUp { - 0% { - -o-transform: translateY(0); - } - 20% { - -o-transform: translateY(20px); - } - 100% { - -o-transform: translateY(-2000px); - } -} -@keyframes bounceOutUp { - 0% { - transform: translateY(0); - } - 20% { - transform: translateY(20px); - } - 100% { - transform: translateY(-2000px); - } -} - -/* moveUp ------------------------------------------------*/ -@-webkit-keyframes moveUp { - 0% { - -webkit-transform: translateY(1000px); - } - 100% { - -webkit-transform: translateY(0px); - } -} -@-moz-keyframes moveUp { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -@-ms-keyframes moveUp { - 0% { - -ms-transform: translateY(1000px); - } - 100% { - -ms-transform: translateY(0px); - } -} -@-o-keyframes moveUp { - 0% { - -o-transform: translateY(1000px); - } - 100% { - -o-transform: translateY(0px); - } -} -@keyframes moveUp { - 0% { - transform: translateY(1000px); - } - 100% { - transform: translateY(0px); - } -} - -/* moveDown ------------------------------------------------*/ -@-webkit-keyframes moveDown { - 0% { - -webkit-transform: translateY(-100px); - } - 100% { - -webkit-transform: translateY(0); - } -} -@-moz-keyframes moveDown { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -@-ms-keyframes moveDown { - 0% { - -ms-transform: translateY(-100px); - } - 100% { - -ms-transform: translateY(0); - } -} -@-o-keyframes moveDown { - 0% { - -o-transform: translateY(-100px); - } - 100% { - -o-transform: translateY(0); - } -} -@keyframes moveDown { - 0% { - transform: translateY(-100px); - } - 100% { - transform: translateY(0); - } -} - -/* fadeIn ------------------------------------------------*/ -@-webkit-keyframes fadeIn { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -@-moz-keyframes fadeIn { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -@-ms-keyframes fadeIn { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -@-o-keyframes fadeIn { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -@keyframes fadeIn { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} - -/* fadeOut ------------------------------------------------*/ -@-webkit-keyframes fadeOut { - 0% { - opacity: 1; - } - 100% { - opacity: 0; - } -} -@-moz-keyframes fadeOut { - 0% { - opacity: 1; - } - 100% { - opacity: 0; - } -} -@-ms-keyframes fadeOut { - 0% { - opacity: 1; - } - 100% { - opacity: 0; - } -} -@-o-keyframes fadeOut { - 0% { - opacity: 1; - } - 100% { - opacity: 0; - } -} -@keyframes fadeOut { - 0% { - opacity: 1; - } - 100% { - opacity: 0; - } -} - -/* moveBackground ------------------------------------------------*/ -@-webkit-keyframes moveBackground { - 0% { - background-position-x: 0px; - } - 100% { - background-position-x: -33px; - } -} -@-moz-keyframes moveBackground { - 0% { - background-position-x: 0px; - } - 100% { - background-position-x: -33px; - } -} -@-ms-keyframes moveBackground { - 0% { - background-position-x: 0px; - } - 100% { - background-position-x: -33px; - } -} -@-o-keyframes moveBackground { - 0% { - background-position-x: 0px; - } - 100% { - background-position-x: -33px; - } -} -@keyframes moveBackground { - 0% { - background-position-x: 0px; - } - 100% { - background-position-x: -33px; - } -} - -/* zoomOut ------------------------------------------------*/ -@-webkit-keyframes zoomOut { - 0% { - opacity: 1; - -webkit-transform: scale(1); - } - 100% { - opacity: 0; - -webkit-transform: scale(.5); - } -} -@-moz-keyframes zoomOut { - 0% { - opacity: 1; - } - 100% { - opacity: 0; - } -} -@-ms-keyframes zoomOut { - 0% { - opacity: 1; - } - 100% { - opacity: 0; - } -} -@-o-keyframes zoomOut { - 0% { - opacity: 1; - } - 100% { - opacity: 0; - } -} -@keyframes zoomOut { - 0% { - opacity: 1; - transform: scale(1); - } - 100% { - opacity: 0; - transform: scale(.5); - } -} - -/* zoomIn ------------------------------------------------*/ -@-webkit-keyframes zoomIn { - 0% { - opacity: 0; - -webkit-transform: scale(.5); - } - 100% { - opacity: 1; - -webkit-transform: scale(1); - } -} -@-moz-keyframes zoomIn { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -@-ms-keyframes zoomIn { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -@-o-keyframes zoomIn { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -@keyframes zoomIn { - 0% { - opacity: 0; - transform: scale(.5); - } - 100% { - opacity: 1; - transform: scale(1); - } -} - -/* pulse ------------------------------------------------*/ -@-webkit-keyframes pulse { - 0% { - opacity: 1; - } - 50% { - opacity: 0.3; - } - 100% { - opacity: 1; - } -} -@-moz-keyframes pulse { - 0% { - opacity: 1; - } - 50% { - opacity: 0.8; - } - 100% { - opacity: 1; - } -} -@-ms-keyframes pulse { - 0% { - opacity: 1; - } - 50% { - opacity: 0.8; - } - 100% { - opacity: 1; - } -} -@-o-keyframes pulse { - 0% { - opacity: 1; - } - 50% { - opacity: 0.8; - } - 100% { - opacity: 1; - } -} -@keyframes pulse { - 0% { - opacity: 1; - } - 50% { - opacity: 0.8; - } - 100% { - opacity: 1; - } -} \ No newline at end of file diff --git a/css/style.css b/css/style.css deleted file mode 100755 index ef10a09..0000000 --- a/css/style.css +++ /dev/null @@ -1,1398 +0,0 @@ -/** - * @name style.css - * @author Philipp Maurer - * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - */ - -/* Reset -------------------------------------------------*/ -html,body,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; } - -/* Basics -------------------------------------------------*/ -html, body { - min-height: 100%; - -webkit-user-select: none; - -moz-user-select: none; - -o-user-select: none; - user-select: none; -} -body { background-color: #222; background-image: url(../img/background.jpg); font-family:'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; -webkit-font-smoothing: antialiased; } -.center { left: 50%; top:50%; position: absolute; } -* { - -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; - -o-transition: opacity .3s ease-out, -o-transform .3s ease-out, box-shadow .3s; - transition: color .3s, opacity .3s ease-out, transform .3s ease-out, box-shadow .3s; -} - -/* Tooltip ------------------------------------------------*/ -.tipsy { - padding: 4px; - font-size: 12px; - position: absolute; - z-index: 100000; - - /* Animation */ - -webkit-animation-name: fadeIn; - -webkit-animation-duration: .3s; - -webkit-animation-fill-mode: forwards; - -moz-animation-name: fadeIn; - -moz-animation-duration: .3s; - -moz-animation-fill-mode: forwards; - -o-animation-name: fadeIn; - -o-animation-duration: .3s; - -o-animation-fill-mode: forwards; - animation-name: fadeIn; - animation-duration: .3s; - animation-fill-mode: forwards; -} -.tipsy-inner { - padding: 7px 10px 6px 10px; - color: white; - max-width: 200px; - text-align: center; - text-shadow: 0 -1px 0 #000; - background: #000; - box-shadow: 0 1px 2px hsla(0, 0%, 0%, .25); - border-radius: 3px; -} -.tipsy-arrow { position: absolute; width: 0; height: 0; line-height: 0; border: 5px dashed #000; } -.tipsy-arrow-n { border-bottom-color: #000; } -.tipsy-arrow-s { border-top-color: #000; } -.tipsy-arrow-e { border-left-color: #000; } -.tipsy-arrow-w { border-right-color: #000; } -.tipsy-n .tipsy-arrow { top: 0px; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; } -.tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;} -.tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none; 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; border-left-color: transparent; border-right-color: transparent; } -.tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } -.tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } -.tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; } -.tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; } - -/* Animations ------------------------------------------------*/ -.fadeIn { - -webkit-animation-name: fadeIn; - -webkit-animation-duration: .3s; - -webkit-animation-fill-mode: forwards; - -moz-animation-name: fadeIn; - -moz-animation-duration: .3s; - -moz-animation-fill-mode: forwards; - -o-animation-name: fadeIn; - -o-animation-duration: .3s; - -o-animation-fill-mode: forwards; - animation-name: fadeIn; - animation-duration: .3s; - animation-fill-mode: forwards; -} -.fadeOut { - -webkit-animation-name: fadeOut; - -webkit-animation-duration: .3s; - -webkit-animation-fill-mode: forwards; - -moz-animation-name: fadeOut; - -moz-animation-duration: .3s; - -moz-animation-fill-mode: forwards; - -o-animation-name: fadeOut; - -o-animation-duration: .3s; - -o-animation-fill-mode: forwards; - animation-name: fadeOut; - animation-duration: .3s; - animation-fill-mode: forwards; -} -.contentFadeIn { - -webkit-animation-name: bounceInDown; - -webkit-animation-duration: 1s; - -webkit-animation-timing-function: ease-out; - -webkit-animation-fill-mode: forwards; - -moz-animation-name: bounceInDown; - -moz-animation-duration: .3s; - -moz-animation-fill-mode: forwards; - -o-animation-name: bounceInDown; - -o-animation-duration: 1s; - -o-animation-timing-function: ease-out; - -o-animation-fill-mode: forwards; - animation-name: bounceInDown; - animation-duration: 1s; - animation-timing-function: ease-out; - animation-fill-mode: forwards; -} -.contentFadeOut { - -webkit-animation-name: bounceOutUp; - -webkit-animation-duration: 1s; - -webkit-animation-timing-function: ease-out; - -webkit-animation-fill-mode: forwards; - -moz-animation-name: bounceOutUp; - -moz-animation-duration: .3s; - -moz-animation-fill-mode: forwards; - -o-animation-name: bounceOutUp; - -o-animation-duration: 1s; - -o-animation-timing-function: ease-out; - -o-animation-fill-mode: forwards; - animation-name: bounceOutUp; - animation-duration: 1s; - animation-timing-function: ease-out; - animation-fill-mode: forwards; -} -.contentZoomOut { - -webkit-animation-name: zoomOut; - -webkit-animation-duration: .3s; - -webkit-animation-fill-mode: forwards; - -moz-animation-name: zoomOut; - -moz-animation-duration: .3s; - -moz-animation-fill-mode: forwards; - -o-animation-name: zoomOut; - -o-animation-duration: .3s; - -o-animation-fill-mode: forwards; - animation-name: zoomOut; - animation-duration: .3s; - animation-fill-mode: forwards; -} -.contentZoomIn { - -webkit-animation-name: zoomIn; - -webkit-animation-duration: .3s; - -webkit-animation-fill-mode: forwards; - -moz-animation-name: zoomIn; - -moz-animation-duration: .3s; - -moz-animation-fill-mode: forwards; - -o-animation-name: zoomIn; - -o-animation-duration: .3s; - -o-animation-fill-mode: forwards; - animation-name: zoomIn; - animation-duration: .3s; - animation-fill-mode: forwards; -} - -/* Loading ------------------------------------------------*/ -#loading { - position: fixed; - width: 100%; - height: 2px; - background-color: #2f0d0e; - background-repeat: repeat-x; - z-index: 1; - display: none; - - /* Animation */ - -webkit-animation-name: moveBackground; - -webkit-animation-duration: .2s; - -webkit-animation-timing-function: linear; - -webkit-animation-iteration-count: infinite; - -moz-animation-name: moveBackground; - -moz-animation-duration: .2s; - -moz-animation-timing-function: linear; - -moz-animation-iteration-count: infinite; - -o-animation-name: moveBackground; - -o-animation-duration: .2s; - -o-animation-timing-function: linear; - -o-animation-iteration-count: infinite; - animation-name: moveBackground; - animation-duration: .2s; - animation-timing-function: linear; - animation-iteration-count: infinite; -} -#loading h1 { - margin: 13px; - color: #ddd; - font-size: 14px; - font-weight: bold; - text-shadow: 0px 1px 0px #000; - text-transform: capitalize; -} -#loading h1 span { - margin-left: 10px; - font-weight: normal; - text-transform: none; -} -#loading.loading { - background-image: url(../img/bar/loading.png); -} -#loading.error { - background-image: url(../img/bar/error.png); -} - -/* Header ------------------------------------------------*/ -header { - position: fixed; - height: 41px; - width: 100%; - - background-color: #333; - background-image: -webkit-gradient(linear, left top, left bottom, from(#555), to(#333)); - background-image: -webkit-linear-gradient(top, #555, #333); - background-image: -moz-linear-gradient(top, #555, #333); - background-image: -o-linear-gradient(top, #555, #333); - background-image: -ms-linear-gradient(top, #555, #333); - background-image: linear-gradient(top, #555, #333); - - box-shadow: inset 0px 1px 0px #666, inset 0px -1px 0px #393939, 0px 0px 3px #000; - border-top: 1px solid #222; - z-index: 1; - - -webkit-transition: opacity .3s ease-out, -webkit-transform .3s ease-out, box-shadow .3s, margin-top .3s; - -moz-transition: opacity .3s ease-out, -moz-transform .3s ease-out, box-shadow .3s, margin-top .3s; - -o-transition: opacity .3s ease-out, -o-transform .3s ease-out, box-shadow .3s, margin-top .3s; - transition: opacity .3s ease-out, transform .3s ease-out, box-shadow .3s, margin-top .3s; - - /* Animation */ - -webkit-animation-name: moveDown; - -webkit-animation-duration: .3s; - -webkit-animation-timing-function: ease-out; - -webkit-animation-fill-mode: forwards; - -moz-animation-name: moveDown; - -moz-animation-duration: .3s; - -moz-animation-timing-function: ease-out; - -moz-animation-fill-mode: forwards; - -o-animation-name: moveDown; - -o-animation-duration: .3s; - -o-animation-timing-function: ease-out; - -o-animation-fill-mode: forwards; - animation-name: moveDown; - animation-duration: .3s; - animation-timing-function: ease-out; - animation-fill-mode: forwards; -} - - /* Title ------------------------------------------------*/ - #title { - position: absolute; - margin: 0px 30%; - width: 40%; - padding: 11px 0px; - color: #fff; - font-size: 16px; - font-weight: bold; - text-align: center; - text-shadow: 0px -1px 0px #000; - } - #title.editable { - cursor: pointer; - } - #title span { - color: #aaa; - font-size: 16px; - font-weight: normal; - } - - /* Button ------------------------------------------------*/ - header .button { - float: left; - position: absolute; - padding: 7px 10px 8px 10px; - margin: 6px 0px 0px 8px; - font-size: 12px; - font-weight: bold; - color: #fff; - text-shadow: 0px -1px 0px #000; - text-decoration: none !important; - - background: #555; - background-image: -webkit-gradient(linear, left bottom, left top, color-stop(1, #555), color-stop(0, #333)); - background-image: -webkit-linear-gradient(top, #555 0%, #333 100%); - background-image: -moz-linear-gradient(top, #555 0%, #333 100%); - background-image: -o-linear-gradient(top, #555 0%, #333 100%); - background: linear-gradient(top, #555 0%, #333 100%); - - border: 1px solid #222; - border-radius: 3px; - box-shadow: inset 0 1px 0 rgba(255,255,255,0.1), 0px 1px 0px #444; - cursor: pointer; - } - header .button:hover { - background-color: #5c5c5c; - background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(92, 92, 92)), to(rgb(57, 57, 57))); - background-image: -webkit-linear-gradient(top, rgb(92, 92, 92), rgb(57, 57, 57)); - background-image: -moz-linear-gradient(top, rgb(92, 92, 92), rgb(57, 57, 57)); - background-image: -o-linear-gradient(top, rgb(92, 92, 92), rgb(57, 57, 57)); - background-image: -ms-linear-gradient(top, rgb(92, 92, 92), rgb(57, 57, 57)); - background-image: linear-gradient(top, rgb(92, 92, 92), rgb(57, 57, 57)); - } - header .button:active { - background-color: #393939; - background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(57, 57, 57)), to(rgb(68, 68, 68))); - background-image: -webkit-linear-gradient(top, rgb(57, 57, 57), rgb(68, 68, 68)); - background-image: -moz-linear-gradient(top, rgb(57, 57, 57), rgb(68, 68, 68)); - background-image: -o-linear-gradient(top, rgb(57, 57, 57), rgb(68, 68, 68)); - background-image: -ms-linear-gradient(top, rgb(57, 57, 57), rgb(68, 68, 68)); - background-image: linear-gradient(top, rgb(57, 57, 57), rgb(68, 68, 68)); - } - header .button.icon { - float: right; - position: relative; - padding: 7px 11px 4px 11px; - margin: 6px 8px 0px 0px; - font-family: 'FontAwesome'; - font-size: 16px; - } - #tools_albums, #tools_album, #tools_photo, #button_signin { - display: none; - } - - /* Button Divider ------------------------------------------------*/ - header .button_divider { - float: right; - position: relative; - margin: 1px 12px 0px 0px; - width: 1px; - height: 40px; - background-color: transparent; - background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(68, 68, 68)), to(rgb(37, 37, 37))); - background-image: -webkit-linear-gradient(top, rgba(68, 68, 68, 0), rgb(25, 25, 25)); - background-image: -moz-linear-gradient(top, rgb(68, 68, 68), rgb(37, 37, 37)); - background-image: -o-linear-gradient(top, rgb(68, 68, 68), rgb(37, 37, 37)); - background-image: -ms-linear-gradient(top, rgb(68, 68, 68), rgb(37, 37, 37)); - background-image: linear-gradient(top, rgb(68, 68, 68), rgb(37, 37, 37)); - border-right: 1px solid #555; - } - header .button_divider.less { - margin: 1px 6px 0px 6px; - } - - - /* Search ------------------------------------------------*/ - #search { - float: right; - width: 80px; - margin: 7px 12px 0px 0px; - padding: 5px 10px 7px 10px; - background-color: #444; - color: #fff; - border: none; - border: 1px solid #111; - box-shadow: 0px 1px 0px #555; - outline: none; - border-radius: 5px; - 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; - -o-transition: opacity .3s ease-out, -o-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; - } - #search:focus { - box-shadow: 0px 1px 0px #555, inset 0px 0px 2px #333; - opacity: 1; - width: 140px; - } - - /* Tools ------------------------------------------------*/ - .tools:first-of-type { - margin-right: 6px; - } - .tools { - float: right; - padding: 10px 8px; - color: #aaa; - font-size: 21px; - text-shadow: 0px -1px 0px #222; - cursor: pointer; - } - .tools:hover a { - color: #fff; - } - .tools .icon-star { - color: #f0ef77; - } - .tools .icon-share.active { - color: #ff9737; - } - - -/* Content ------------------------------------------------*/ -#content { - position: absolute; - padding: 41px 0px 33px 0px; - width: 100%; - -webkit-overflow-scrolling: touch; -} - - /* Photo ------------------------------------------------*/ - .photo { - float: left; - display: inline-block; - width: 206px; - height: 206px; - margin: 30px 0px 0px 30px; - cursor: pointer; - } - .photo img { - position: absolute; - width: 200px; - height: 200px; - background-color: #222; - border-radius: 3px; - box-shadow: 0px 1px 5px #111; - border: 3px solid #ccc; - } - .photo:hover img, .photo.active img { - box-shadow: 0px 0px 10px #005ecc; - } - - /* Album ------------------------------------------------*/ - .album { - float: left; - display: inline-block; - width: 206px; - height: 206px; - margin: 30px 0px 0px 30px; - cursor: pointer; - } - .album img:first-child, .album img:nth-child(2) { - -webkit-transform: rotate(0deg) translateY(0px) translateX(0px); - -moz-transform: rotate(0deg) translateY(0px) translateX(0px); - -o-transform: rotate(0deg) translateY(0px) translateX(0px); - transform: rotate(0deg) translateY(0px) translateX(0px); - opacity: 0; - } - .album:hover img:first-child { - -webkit-transform: rotate(-2deg) translateY(10px) translateX(-12px); - -moz-transform: rotate(-2deg) translateY(10px) translateX(-12px); - -o-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); - -o-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: 3px; - box-shadow: 0px 1px 5px #111; - border: 3px solid #ccc; - } - .album:hover img, .album.active img { - box-shadow: 0px 0px 10px #005ecc; - } - - /* Album/Photo Overlay ------------------------------------------------*/ - .album .overlay, .photo .overlay { - position: absolute; - width: 200px; - height: 200px; - margin: 3px; - background: -moz-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 20%, rgba(0,0,0,0.9) 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,0)), color-stop(20%,rgba(0,0,0,0)), color-stop(100%,rgba(0,0,0,0.9))); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,0) 20%,rgba(0,0,0,0.9) 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,0) 20%,rgba(0,0,0,0.9) 100%); /* Opera 11.10+ */ - 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 { - opacity: 0; - } - .photo:hover .overlay, .photo.active .overlay { - opacity: 1; - } - .album .overlay h1, .photo .overlay h1 { - min-height: 19px; - width: 190px; - margin: 153px 0px 3px 15px; - color: #fff; - font-size: 16px; - font-weight: bold; - text-shadow: 0px 1px 0px #000; - overflow: hidden; - } - .album .overlay a { - margin-left: 15px; - font-size: 11px; - color: #aaa; - text-shadow: 0px 1px 0px #000; - } - .photo .overlay a { - margin: 155px 0px 5px 15px; - font-size: 11px; - color: #aaa; - text-shadow: 0px 1px 0px #000; - } - - /* Badges ------------------------------------------------*/ - .album .badge, .photo .badge { - position: absolute; - margin-top: -1px; - margin-left: 12px; - padding: 12px 7px 3px 7px; - box-shadow: 0px 0px 3px #000; - border-radius: 0px 0px 3px 3px; - border: 1px solid #fff; - border-top: none; - color: #fff; - font-size: 24px; - text-shadow: 0px 1px 0px #000; - opacity: .9; - } - .album .badge.icon-star, .photo .badge.icon-star { - padding: 12px 8px 3px 8px; - } - .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: 34px; - height: 5px; - background: -moz-linear-gradient(top, rgba(0,0,0,1) 0%, rgba(0,0,0,0) 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,1)), color-stop(100%,rgba(0,0,0,0))); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0) 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0) 100%); /* Opera 11.10+ */ - background: -ms-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0) 100%); /* IE10+ */ - background: linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0) 100%); /* W3C */ - opacity: .4; - } - .album .badge.icon-star::after { - margin-left: -28px; - width: 36px; - } - .album .badge.icon-share::after, .photo .badge.icon-share::after { - margin-left: -30px; - width: 38px; - } - .album .badge.icon-reorder::after { - margin-left: -30px; - width: 38px; - } - .album .badge:nth-child(2n), .photo .badge:nth-child(2n) { - margin-left: 57px; - } - .album .badge.red, .photo .badge.red { - background: #d64b4b; - background: -webkit-gradient(linear, left top, left bottom, from(#d64b4b), to(#ab2c2c)); - background: -webkit-linear-gradient(top, #d64b4b, #ab2c2c); - background: -moz-linear-gradient(top, #d64b4b, #ab2c2c); - background: -ms-linear-gradient(top, #d64b4b, #ab2c2c); - background: -o-linear-gradient(top, #d64b4b, #ab2c2c); - } - .album .badge.blue, .photo .badge.blue { - background: #d64b4b; - background: -webkit-gradient(linear, left top, left bottom, from(#347cd6), to(#2945ab)); - background: -webkit-linear-gradient(top, #347cd6, #2945ab); - background: -moz-linear-gradient(top, #347cd6, #2945ab); - background: -ms-linear-gradient(top, #347cd6, #2945ab); - background: -o-linear-gradient(top, #347cd6, #2945ab); - } - - /* Divider ------------------------------------------------*/ - .divider { - float: left; - width: 100%; - height: 32px; - margin-top: 50px; - opacity: 0; - - background-color: #2b2b2b; - background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(43, 43, 43)), to(rgb(35, 35, 35))); - background-image: -webkit-linear-gradient(top, rgb(43, 43, 43), rgb(35, 35, 35)); - background-image: -moz-linear-gradient(top, rgb(43, 43, 43), rgb(35, 35, 35)); - background-image: -o-linear-gradient(top, rgb(43, 43, 43), rgb(35, 35, 35)); - background-image: -ms-linear-gradient(top, rgb(43, 43, 43), rgb(35, 35, 35)); - background-image: linear-gradient(top, rgb(43, 43, 43), rgb(35, 35, 35)); - - box-shadow: 0px 1px 0px #111, inset 0px 1px 0px rgba(255, 255, 255, .1); - } - .divider:first-child { - margin-top: 2px; - } - .divider h1 { - float: left; - margin: 8px 0px 0px 30px; - color: #fff; - font-size: 14px; - font-weight: bold; - text-shadow: 0px -1px 0px #000; - } - - /* No Content ------------------------------------------------*/ - .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: 0px 1px 0px rgba(255, 255, 255, .05); - text-align: center; - } - - .no_content .icon { - font-size: 120px; - } - - .no_content p { - font-size: 18px; - } - -/* Overlay ------------------------------------------------*/ -.message_overlay { - position: fixed; - width: 100%; - height: 100%; - top: 0px; - left: 0px; - background-color: rgba(0,0,0,.3); - background-image: -webkit-gradient(radial, 50% 50%,0,50% 50%,200, from(rgba(0, 0, 0, 0.85)), to(rgba(0, 0, 0, 0.50))); - background-image: -webkit-radial-gradient(50% 50%, rgba(0, 0, 0, 0.50), rgba(0, 0, 0, 0.85)); - background-image: -moz-radial-gradient(50% 50%, rgba(0, 0, 0, 0.50), rgba(0, 0, 0, 0.85)); - background-image: -o-radial-gradient(50% 50%, rgba(0, 0, 0, 0.50), rgba(0, 0, 0, 0.85)); - background-image: -ms-radial-gradient(50% 50%, rgba(0, 0, 0, 0.50), rgba(0, 0, 0, 0.85)); - background-image: radial-gradient(50% 50%, rgba(0, 0, 0, 0.50), rgba(0, 0, 0, 0.85)); - z-index: 1000; -} - - .message { - position: absolute; - display: inline-block; - width: 500px; - margin-left: -250px; - margin-top: -85px; - background-color: #505050; - background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(80, 80, 80)), to(rgb(43, 42, 42))); - background-image: -webkit-linear-gradient(top, rgb(80, 80, 80), rgb(43, 42, 42)); - background-image: -moz-linear-gradient(top, rgb(80, 80, 80), rgb(43, 42, 42)); - background-image: -o-linear-gradient(top, rgb(80, 80, 80), rgb(43, 42, 42)); - background-image: -ms-linear-gradient(top, rgb(80, 80, 80), rgb(43, 42, 42)); - background-image: linear-gradient(top, rgb(80, 80, 80), rgb(43, 42, 42)); - border-radius: 5px; - border-bottom: 1px solid #000; - box-shadow: 0px 0px 5px #000, inset 0px 1px 0px rgba(255,255,255,.2), inset 1px 0px 0px rgba(255,255,255,.05), inset -1px 0px 0px rgba(255,255,255,.05); - - /* Animation */ - -webkit-animation-name: bounceInDown; - -webkit-animation-duration: 1s; - -webkit-animation-timing-function: ease-out; - -webkit-animation-fill-mode: forwards; - -moz-animation-name: bounceInDown; - -moz-animation-duration: 1s; - -moz-animation-timing-function: ease-out; - -moz-animation-fill-mode: forwards; - -o-animation-name: bounceInDown; - -o-animation-duration: 1s; - -o-animation-timing-function: ease-out; - -o-animation-fill-mode: forwards; - animation-name: bounceInDown; - animation-duration: 1s; - animation-timing-function: ease-out; - animation-fill-mode: forwards; - } - .message h1 { - float: left; - width: 100%; - padding: 12px 0px; - color: #fff; - font-size: 16px; - font-weight: bold; - text-shadow: 0px -1px 0px #000; - text-align: center; - } - .message .close { - position: absolute; - top: 0px; - right: 0px; - padding: 12px 14px 6px 7px; - color: #aaa; - font-size: 20px; - text-shadow: 0px -1px 0px #111; - cursor: pointer; - } - .message .close:hover { - color: #fff; - } - .message p { - float: left; - width: 90%; - margin-top: 1px; - padding: 12px 5% 15px 5%; - color: #eee; - font-size: 14px; - text-shadow: 0px -1px 0px #222; - line-height: 20px; - } - .message p b { - font-weight: bold; - } - .message .button { - float: right; - margin: 15px 15px 15px 0px; - padding: 6px 10px 8px 10px; - background-color: #4e4e4e; - background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(78, 78, 78)), to(rgb(45, 45, 45))); - background-image: -webkit-linear-gradient(top, rgb(78, 78, 78), rgb(45, 45, 45)); - background-image: -moz-linear-gradient(top, rgb(78, 78, 78), rgb(45, 45, 45)); - background-image: -o-linear-gradient(top, rgb(78, 78, 78), rgb(45, 45, 45)); - background-image: -ms-linear-gradient(top, rgb(78, 78, 78), rgb(45, 45, 45)); - background-image: linear-gradient(top, rgb(78, 78, 78), rgb(45, 45, 45)); - - color: #ccc; - font-size: 14px; - font-weight: bold; - text-align: center; - text-shadow: 0px -1px 0px #000; - border-radius: 5px; - border: 1px solid #111; - box-shadow: inset 0px 1px 0px rgba(255,255,255,.2), 0px 1px 0px rgba(255,255,255,.1); - cursor: pointer; - } - .message .button:first-of-type { - margin: 15px 5% 18px 0px !important; - } - .message .button.active { - color: #fff; - box-shadow: inset 0px 1px 0px rgba(255,255,255,.2), 0px 1px 0px rgba(255,255,255,.1), 0px 0px 5px #005ecc; - } - .message .button:hover { - background-color: #565757; - background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(86, 87, 87)), to(rgb(57, 57, 57))); - background-image: -webkit-linear-gradient(top, rgb(86, 87, 87), rgb(57, 57, 57)); - background-image: -moz-linear-gradient(top, rgb(86, 87, 87), rgb(57, 57, 57)); - background-image: -o-linear-gradient(top, rgb(86, 87, 87), rgb(57, 57, 57)); - background-image: -ms-linear-gradient(top, rgb(86, 87, 87), rgb(57, 57, 57)); - background-image: linear-gradient(top, rgb(86, 87, 87), rgb(57, 57, 57)); - } - .message .button:active, .message .button.pressed { - background-color: #393939; - background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(57, 57, 57)), to(rgb(75, 76, 76))); - background-image: -webkit-linear-gradient(top, rgb(57, 57, 57), rgb(75, 76, 76)); - background-image: -moz-linear-gradient(top, rgb(57, 57, 57), rgb(75, 76, 76)); - background-image: -o-linear-gradient(top, rgb(57, 57, 57), rgb(75, 76, 76)); - background-image: -ms-linear-gradient(top, rgb(57, 57, 57), rgb(75, 76, 76)); - background-image: linear-gradient(top, rgb(57, 57, 57), rgb(75, 76, 76)); - } - - /* Add Album ------------------------------------------------*/ - .message.add { - width: 588px; - margin-top: -152px; - margin-left: -294px; - } - .add_album { - float: left; - display: inline-block; - width: 150px; - height: 200px; - margin: 30px 0px 30px 30px; - border-radius: 3px; - border: 3px dashed #777; - cursor: pointer; - text-align: center; - -webkit-transition: border .3s; - -moz-transition: border .3s; - -o-transition: border .3s; - transition: border .3s; - } - .add_album:hover { - border: 3px dashed #fff; - } - .add_album .icon { - margin-top: 55px; - color: #777; - font-family: 'FontAwesome'; - font-size: 80px; - text-shadow: 0px 1px 2px #000; - } - .add_album:hover .icon { - color: #fff; - } - .add_album a { - float: left; - width: 100%; - color: #777; - font-size: 14px; - font-weight: bold; - text-shadow: 0px 1px 0px #000; - } - .add_album:hover a { - color: #fff; - } - - /* Sign in ------------------------------------------------*/ - .sign_in { - float: left; - width: 100%; - margin-top: 1px; - padding: 5px 0px; - color: #eee; - font-size: 14px; - text-shadow: 0px -1px 0px #222; - line-height: 20px; - } - .sign_in input { - float: left; - width: 86%; - padding: 7px 2% 9px 2%; - margin: 0px 5%; - background-color: #444; - color: #fff; - text-shadow: 0px 1px 0px #222; - border: none; - border: 1px solid #111; - box-shadow: 0px 1px 0px #555; - outline: none; - border-radius: 5px; - } - .sign_in input:first-of-type { - margin-bottom: 10px; - } - .sign_in input:focus { - box-shadow: 0px 1px 0px #666, inset 0px 0px 3px #333, 0px 0px 5px #005ecc; - } - .sign_in input.error:focus { - box-shadow: 0px 1px 0px #666, inset 0px 0px 3px #333, 0px 0px 5px #cc0007; - } - .message #version { - display: inline-block; - margin-top: 23px; - margin-left: 5%; - color: #888; - text-shadow: 0px -1px 0px #111; - } - .message #version span { - display: none; - } - .message #version span a { - color: #888; - } - - /* Copy Link, Password ------------------------------------------------*/ - .message .copylink, .message .password { - float: left; - width: 95%; - padding: 7px 10px 9px 10px; - margin-top: 20px; - background-color: #444; - color: #fff; - text-shadow: 0px 1px 0px #222; - border: none; - border: 1px solid #111; - box-shadow: 0px 1px 0px #666, inset 0px 0px 3px #333, 0px 0px 5px #005ecc; - outline: none; - border-radius: 5px; - } - .message .copylink { - margin-bottom: 20px; - } - -/* Image View ------------------------------------------------*/ -#imageview { - position: fixed; - display: none; - width: 100%; - min-height: 100%; - background-color: rgba(30,30,30,.99); - box-shadow: 0px 2px 4px #000; - -webkit-transition: background-color .3s; -} -#imageview.full { - background-color: #111; -} - -#imageview #image { - position: absolute; - top: 70px; - 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; - -webkit-animation-fill-mode: forwards; - -moz-animation-name: zoomIn; - -moz-animation-duration: .3s; - -moz-animation-fill-mode: forwards; - -o-animation-name: zoomIn; - -o-animation-duration: .3s; - -o-animation-fill-mode: forwards; - animation-name: zoomIn; - animation-duration: .3s; - animation-fill-mode: forwards; -} -#imageview #image.small { - top: 50%; - right: auto; - bottom: auto; - left: 50%; -} - - /* Previous/Next Buttons ------------------------------------------------*/ - #imageview a { - position: fixed; - top: 50%; - margin-top: -10px; - color: #fff; - font-size: 50px; - text-shadow: 0px 1px 2px #000; - cursor: pointer; - opacity: .1; - z-index: 1; - } - #imageview a:hover { - opacity: .9; - } - #imageview a#previous { - left: 20px; - -webkit-transition: left .3s; - } - #imageview.full a#previous { - left: -50px; - } - #imageview a#next { - right: 20px; - -webkit-transition: right .3s - } - #imageview.full a#next { - right: -50px; - } - - /* InfoBox ------------------------------------------------*/ - #infobox_overlay { - z-index: 2; - position: fixed; - width: 100%; - height: 100%; - top: 0px; - left: 0px; - background-color: rgba(0,0,0,.7); - -webkit-animation-name: fadeIn; - -webkit-animation-duration: .5s; - -webkit-animation-fill-mode: forwards; - -moz-animation-name: fadeIn; - -moz-animation-duration: .5s; - -moz-animation-fill-mode: forwards; - -o-animation-name: fadeIn; - -o-animation-duration: .5s; - -o-animation-fill-mode: forwards; - animation-name: fadeIn; - animation-duration: .5s; - animation-fill-mode: forwards; - } - #infobox { - z-index: 3; - position: fixed; - right: -320px; - width: 300px; - height: 100%; - background-color: rgba(20,20,20,0.98); - box-shadow: -1px 0px 2px #000; - display: none; - - -webkit-user-select: text; - -moz-user-select: text; - -o-user-select: text; - user-select: text; - - -webkit-transition: right .5s ease-out; - -moz-transition: right .5s; - -o-transition: right .5s; - transition: right .5s; - } - #infobox .wrapper { - float: left; - height: 100%; - overflow: scroll; - } - #infobox .header { - float: left; - height: 41px; - width: 100%; - - background-color: #1d1d1d; - background-image: -webkit-gradient(linear, left top, left bottom, from(#1d1d1d), to(#050505)); - background-image: -webkit-linear-gradient(top, #1d1d1d, #050505); - background-image: -moz-linear-gradient(top, #1d1d1d, #050505); - background-image: -o-linear-gradient(top, #1d1d1d, #050505); - background-image: -ms-linear-gradient(top, #1d1d1d, #050505); - background-image: linear-gradient(top, #1d1d1d, #050505); - - box-shadow: inset 0px 1px 0px #111, inset 0px -1px 0px #000; - border-top: 1px solid #000; - } - #infobox .header h1 { - position: absolute; - margin: 0px 30%; - width: 40%; - margin-top: 11px; - color: #fff; - font-size: 16px; - font-weight: bold; - text-align: center; - text-shadow: 0px -1px 0px #000; - } - #infobox .header a { - float: right; - padding: 10px 15px; - color: #fff; - font-size: 21px; - font-weight: bold; - text-shadow: 0px -1px 0px #000; - opacity: .5; - cursor: pointer; - } - #infobox .header a:hover { - opacity: 1; - } - #infobox .separater { - float: left; - width: 100%; - height: 27px; - - background-color: #2b2b2b; - background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(43, 43, 43)), to(rgb(35, 35, 35))); - background-image: -webkit-linear-gradient(top, rgb(43, 43, 43), rgb(35, 35, 35)); - background-image: -moz-linear-gradient(top, rgb(43, 43, 43), rgb(35, 35, 35)); - background-image: -o-linear-gradient(top, rgb(43, 43, 43), rgb(35, 35, 35)); - background-image: -ms-linear-gradient(top, rgb(43, 43, 43), rgb(35, 35, 35)); - background-image: linear-gradient(top, rgb(43, 43, 43), rgb(35, 35, 35)); - - box-shadow: 0px 1px 0px #000, inset 0px 1px 0px rgba(255, 255, 255, .1); - } - #infobox .separater h1 { - margin: 5px 0px 0px 15px; - color: #fff; - font-size: 14px; - font-weight: bold; - text-shadow: 0px -1px 0px #000; - } - #infobox table { - float: left; - margin: 10px 0px 15px 15px; - } - #infobox table tr td { - padding: 5px 0px; - 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 .bumper { - float: left; - width: 100%; - height: 35px; - } - #infobox #edit_title, - #infobox #edit_description { - display: inline; - margin-left: 3px; - width: 20px; - height: 5px; - cursor: pointer; - } - -/* ContextMenu ------------------------------------------------*/ -.contextmenu_bg { - position: fixed; - height: 100%; - width: 100%; - z-index: 1000; -} -.contextmenu { - position: fixed; - top: 110%; - left: 110%; - padding: 5px 0px; - background-color: #393939; - background-image: -webkit-gradient(linear, left top, left bottom, from(#393939), to(#2d2d2d)); - background-image: -webkit-linear-gradient(top, #444, #2d2d2d); - background-image: -moz-linear-gradient(top, #393939, #2d2d2d); - background-image: -o-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,0.7); - border-bottom: 1px solid rgba(0,0,0,.9); - border-radius: 5px; - box-shadow: 0px 3px 5px rgba(0,0,0,0.4), inset 0px 1px 0px rgba(255,255,255,0.2), inset 1px 0px 0px rgba(255,255,255,0.05), inset -1px 0px 0px rgba(255,255,255,0.05); - opacity: .98; - z-index: 1001; -} - - /* Items ------------------------------------------------*/ - .contextmenu tr { - font-size: 14px; - color: #eee; - text-shadow: 0px -1px 0px rgba(0,0,0,.7); - cursor: pointer; - } - .contextmenu tr:hover { - background-color: #6a84f2; - background-image: -webkit-gradient(linear, left top, left bottom, from(#6a84f2), to(#3959ef)); - background-image: -webkit-linear-gradient(top, #6a84f2, #3959ef); - background-image: -moz-linear-gradient(top, #6a84f2, #3959ef); - background-image: -o-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: #222; - box-shadow: 0px 1px 0px #555; - margin: 4px 0px 5px 0px; - cursor: inherit; - } - .contextmenu tr.separator:hover { - background-color: #222; - background-image: none; - } - .contextmenu tr td { - padding: 5px 20px 5px 10px; - -webkit-transition: none; - -moz-transition: none; - -o-transition: none; - transition: none; - } - .contextmenu tr:hover td { - color: #fff; - box-shadow: inset 0px 1px 0px rgba(255,255,255,.1); - text-shadow: 0px -1px 0px rgba(0,0,0,.7); - } - .contextmenu tr.no_hover:hover td { - box-shadow: none; - } - .contextmenu tr a { - float: left; - width: 10px; - margin-right: 10px; - text-align: center; - } - - /* Direct Link Input ------------------------------------------------*/ - .contextmenu #link { - float: right; - width: 140px; - margin: 0px -10px -1px 0px; - padding: 4px 6px 5px 6px; - background-color: #444; - color: #fff; - border: none; - border: 1px solid #111; - box-shadow: 0px 1px 0px rgba(255,255,255,.1); - outline: none; - border-radius: 5px; - } - .contextmenu tr a#link_icon { - padding-top: 4px; - } - -/* Upload ------------------------------------------------*/ -#upload { - display: none; -} -.upload_overlay { - position: fixed; - width: 100%; - height: 100%; - background-color: rgba(0,0,0,.3); - background-image: -webkit-gradient(radial, 50% 50%,0,50% 50%,200, from(rgba(0, 0, 0, 0.85)), to(rgba(0, 0, 0, 0.50))); - background-image: -webkit-radial-gradient(50% 50%, rgba(0, 0, 0, 0.50), rgba(0, 0, 0, 0.85)); - background-image: -moz-radial-gradient(50% 50%, rgba(0, 0, 0, 0.50), rgba(0, 0, 0, 0.85)); - background-image: -o-radial-gradient(50% 50%, rgba(0, 0, 0, 0.50), rgba(0, 0, 0, 0.85)); - background-image: -ms-radial-gradient(50% 50%, rgba(0, 0, 0, 0.50), rgba(0, 0, 0, 0.85)); - background-image: radial-gradient(50% 50%, rgba(0, 0, 0, 0.50), rgba(0, 0, 0, 0.85)); - z-index: 1000; -} -.upload_message { - position: absolute; - display: inline-block; - width: 200px; - margin-left: -100px; - margin-top: -85px; - background-color: #505050; - background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(80, 80, 80)), to(rgb(43, 42, 42))); - background-image: -webkit-linear-gradient(top, rgb(80, 80, 80), rgb(43, 42, 42)); - background-image: -moz-linear-gradient(top, rgb(80, 80, 80), rgb(43, 42, 42)); - background-image: -o-linear-gradient(top, rgb(80, 80, 80), rgb(43, 42, 42)); - background-image: -ms-linear-gradient(top, rgb(80, 80, 80), rgb(43, 42, 42)); - background-image: linear-gradient(top, rgb(80, 80, 80), rgb(43, 42, 42)); - border-radius: 5px; - border-bottom: 1px solid #000; - box-shadow: 0px 0px 5px #000, inset 0px 1px 0px rgba(255,255,255,.2), inset 1px 0px 0px rgba(255,255,255,.05), inset -1px 0px 0px rgba(255,255,255,.05); - - /* Animation */ - -webkit-animation-name: bounceInDown; - -webkit-animation-duration: 1s; - -webkit-animation-timing-function: ease-out; - -webkit-animation-fill-mode: forwards; - -moz-animation-name: bounceInDown; - -moz-animation-duration: 1s; - -moz-animation-timing-function: ease-out; - -moz-animation-fill-mode: forwards; - -o-animation-name: bounceInDown; - -o-animation-duration: 1s; - -o-animation-timing-function: ease-out; - -o-animation-fill-mode: forwards; - animation-name: bounceInDown; - animation-duration: 1s; - animation-timing-function: ease-out; - animation-fill-mode: forwards; -} -.upload_message a { - float: left; - margin: 35px 69px 5px 69px; - color: #fff; - font-size: 80px; - text-shadow: 0px 1px 2px #000; - z-index: 2; - - /* Animation */ - -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; - -o-animation-name: pulse; - -o-animation-duration: 2s; - -o-animation-timing-function: ease-in-out; - -o-animation-iteration-count: infinite; - animation-name: pulse; - animation-duration: 2s; - animation-timing-function: ease-in-out; - animation-iteration-count: infinite; -} -.upload_message p { - float: left; - width: 200px; - margin: 10px 0px; - color: #fff; - font-size: 14px; - text-align: center; - text-shadow: 0px -1px 0px #000; -} -.upload_message .progressbar { - float: left; - width: 170px; - height: 25px; - margin: 15px; - background-image: url(data:image/png;base64,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bj4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT4xPC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4yNTwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgogICAgICAgICA8ZGM6c3ViamVjdD4KICAgICAgICAgICAgPHJkZjpCYWcvPgogICAgICAgICA8L2RjOnN1YmplY3Q+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxMi0wOS0yOFQxNDowOTozMDwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAyLjEuMTwveG1wOkNyZWF0b3JUb29sPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KhsXwcAAAABJQTFRFAAAA////////////////////PlKtOgAAAAZ0Uk5TAAECAwQF749peAAAAF1JREFUGNNjYIAA11AICIDyGZigAqEGMBFWmAhMgMEUKhAEFwlFN4YZJqIAExGFCoTgNoYRpskBJsICExHAbQzMC4EYxhjgNkYVKhCM2xhiQgLTGCJCgpWckMAwBgAeZ0aFTqsxyQAAAABJRU5ErkJggg==), #101010; - background-image: url(data:image/png;base64,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bj4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT4xPC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4yNTwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgogICAgICAgICA8ZGM6c3ViamVjdD4KICAgICAgICAgICAgPHJkZjpCYWcvPgogICAgICAgICA8L2RjOnN1YmplY3Q+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxMi0wOS0yOFQxNDowOTozMDwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAyLjEuMTwveG1wOkNyZWF0b3JUb29sPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KhsXwcAAAABJQTFRFAAAA////////////////////PlKtOgAAAAZ0Uk5TAAECAwQF749peAAAAF1JREFUGNNjYIAA11AICIDyGZigAqEGMBFWmAhMgMEUKhAEFwlFN4YZJqIAExGFCoTgNoYRpskBJsICExHAbQzMC4EYxhjgNkYVKhCM2xhiQgLTGCJCgpWckMAwBgAeZ0aFTqsxyQAAAABJRU5ErkJggg==), -webkit-linear-gradient(top, #101010, #1f1f1f); - background-image: url(data:image/png;base64,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bj4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT4xPC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4yNTwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgogICAgICAgICA8ZGM6c3ViamVjdD4KICAgICAgICAgICAgPHJkZjpCYWcvPgogICAgICAgICA8L2RjOnN1YmplY3Q+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxMi0wOS0yOFQxNDowOTozMDwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAyLjEuMTwveG1wOkNyZWF0b3JUb29sPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KhsXwcAAAABJQTFRFAAAA////////////////////PlKtOgAAAAZ0Uk5TAAECAwQF749peAAAAF1JREFUGNNjYIAA11AICIDyGZigAqEGMBFWmAhMgMEUKhAEFwlFN4YZJqIAExGFCoTgNoYRpskBJsICExHAbQzMC4EYxhjgNkYVKhCM2xhiQgLTGCJCgpWckMAwBgAeZ0aFTqsxyQAAAABJRU5ErkJggg==), -moz-linear-gradient(top, #101010, #1f1f1f); - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAZBAMAAABN41qcAAAEJGlDQ1BJQ0MgUHJvZmlsZQAAOBGFVd9v21QUPolvUqQWPyBYR4eKxa9VU1u5GxqtxgZJk6XtShal6dgqJOQ6N4mpGwfb6baqT3uBNwb8AUDZAw9IPCENBmJ72fbAtElThyqqSUh76MQPISbtBVXhu3ZiJ1PEXPX6yznfOec7517bRD1fabWaGVWIlquunc8klZOnFpSeTYrSs9RLA9Sr6U4tkcvNEi7BFffO6+EdigjL7ZHu/k72I796i9zRiSJPwG4VHX0Z+AxRzNRrtksUvwf7+Gm3BtzzHPDTNgQCqwKXfZwSeNHHJz1OIT8JjtAq6xWtCLwGPLzYZi+3YV8DGMiT4VVuG7oiZpGzrZJhcs/hL49xtzH/Dy6bdfTsXYNY+5yluWO4D4neK/ZUvok/17X0HPBLsF+vuUlhfwX4j/rSfAJ4H1H0qZJ9dN7nR19frRTeBt4Fe9FwpwtN+2p1MXscGLHR9SXrmMgjONd1ZxKzpBeA71b4tNhj6JGoyFNp4GHgwUp9qplfmnFW5oTdy7NamcwCI49kv6fN5IAHgD+0rbyoBc3SOjczohbyS1drbq6pQdqumllRC/0ymTtej8gpbbuVwpQfyw66dqEZyxZKxtHpJn+tZnpnEdrYBbueF9qQn93S7HQGGHnYP7w6L+YGHNtd1FJitqPAR+hERCNOFi1i1alKO6RQnjKUxL1GNjwlMsiEhcPLYTEiT9ISbN15OY/jx4SMshe9LaJRpTvHr3C/ybFYP1PZAfwfYrPsMBtnE6SwN9ib7AhLwTrBDgUKcm06FSrTfSj187xPdVQWOk5Q8vxAfSiIUc7Z7xr6zY/+hpqwSyv0I0/QMTRb7RMgBxNodTfSPqdraz/sDjzKBrv4zu2+a2t0/HHzjd2Lbcc2sG7GtsL42K+xLfxtUgI7YHqKlqHK8HbCCXgjHT1cAdMlDetv4FnQ2lLasaOl6vmB0CMmwT/IPszSueHQqv6i/qluqF+oF9TfO2qEGTumJH0qfSv9KH0nfS/9TIp0Wboi/SRdlb6RLgU5u++9nyXYe69fYRPdil1o1WufNSdTTsp75BfllPy8/LI8G7AUuV8ek6fkvfDsCfbNDP0dvRh0CrNqTbV7LfEEGDQPJQadBtfGVMWEq3QWWdufk6ZSNsjG2PQjp3ZcnOWWing6noonSInvi0/Ex+IzAreevPhe+CawpgP1/pMTMDo64G0sTCXIM+KdOnFWRfQKdJvQzV1+Bt8OokmrdtY2yhVX2a+qrykJfMq4Ml3VR4cVzTQVz+UoNne4vcKLoyS+gyKO6EHe+75Fdt0Mbe5bRIf/wjvrVmhbqBN97RD1vxrahvBOfOYzoosH9bq94uejSOQGkVM6sN/7HelL4t10t9F4gPdVzydEOx83Gv+uNxo7XyL/FtFl8z9ZAHF4bBsrEwAAAAlwSFlzAAAuIwAALiMBeKU/dgAABOBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuMS4yIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4xPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8dGlmZjpDb21wcmVzc2lvbj41PC90aWZmOkNvbXByZXNzaW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4zMDA8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjMwMDwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjMzPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT4xPC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4yNTwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgogICAgICAgICA8ZGM6c3ViamVjdD4KICAgICAgICAgICAgPHJkZjpCYWcvPgogICAgICAgICA8L2RjOnN1YmplY3Q+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxMi0wOS0yOFQxNDowOTozMDwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAyLjEuMTwveG1wOkNyZWF0b3JUb29sPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KhsXwcAAAABJQTFRFAAAA////////////////////PlKtOgAAAAZ0Uk5TAAECAwQF749peAAAAF1JREFUGNNjYIAA11AICIDyGZigAqEGMBFWmAhMgMEUKhAEFwlFN4YZJqIAExGFCoTgNoYRpskBJsICExHAbQzMC4EYxhjgNkYVKhCM2xhiQgLTGCJCgpWckMAwBgAeZ0aFTqsxyQAAAABJRU5ErkJggg==), -o-linear-gradient(top, #101010, #1f1f1f); - background-image: url(data:image/png;base64,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bj4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT4xPC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4yNTwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgogICAgICAgICA8ZGM6c3ViamVjdD4KICAgICAgICAgICAgPHJkZjpCYWcvPgogICAgICAgICA8L2RjOnN1YmplY3Q+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxMi0wOS0yOFQxNDowOTozMDwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAyLjEuMTwveG1wOkNyZWF0b3JUb29sPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KhsXwcAAAABJQTFRFAAAA////////////////////PlKtOgAAAAZ0Uk5TAAECAwQF749peAAAAF1JREFUGNNjYIAA11AICIDyGZigAqEGMBFWmAhMgMEUKhAEFwlFN4YZJqIAExGFCoTgNoYRpskBJsICExHAbQzMC4EYxhjgNkYVKhCM2xhiQgLTGCJCgpWckMAwBgAeZ0aFTqsxyQAAAABJRU5ErkJggg==), -ms-linear-gradient(top, #101010, #1f1f1f); - background-image: url(data:image/png;base64,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bj4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT4xPC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4yNTwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgogICAgICAgICA8ZGM6c3ViamVjdD4KICAgICAgICAgICAgPHJkZjpCYWcvPgogICAgICAgICA8L2RjOnN1YmplY3Q+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxMi0wOS0yOFQxNDowOTozMDwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAyLjEuMTwveG1wOkNyZWF0b3JUb29sPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KhsXwcAAAABJQTFRFAAAA////////////////////PlKtOgAAAAZ0Uk5TAAECAwQF749peAAAAF1JREFUGNNjYIAA11AICIDyGZigAqEGMBFWmAhMgMEUKhAEFwlFN4YZJqIAExGFCoTgNoYRpskBJsICExHAbQzMC4EYxhjgNkYVKhCM2xhiQgLTGCJCgpWckMAwBgAeZ0aFTqsxyQAAAABJRU5ErkJggg==), linear-gradient(top, #101010, #1f1f1f); - border: 1px solid #000; - box-shadow: 0 1px 0 rgba(255,255,255,.2), inset 0px 0px 2px #111; - border-radius: 5px; - - /* Animation */ - -webkit-animation-name: moveBackground; - -webkit-animation-duration: .6s; - -webkit-animation-timing-function: linear; - -webkit-animation-iteration-count: infinite; - -moz-animation-name: moveBackground; - -moz-animation-duration: .6s; - -moz-animation-timing-function: linear; - -moz-animation-iteration-count: infinite; - -o-animation-name: moveBackground; - -o-animation-duration: .6s; - -o-animation-timing-function: linear; - -o-animation-iteration-count: infinite; - animation-name: moveBackground; - animation-duration: .6s; - 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 0px 2px #000; - background-color: #f5f2f7; - background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f2f7), to(#c7c6c8)); - background-image: -webkit-linear-gradient(top, #f5f2f7, #c7c6c8); - background-image: -moz-linear-gradient(top, #f5f2f7, #c7c6c8); - background-image: -o-linear-gradient(top, #f5f2f7, #c7c6c8); - background-image: -ms-linear-gradient(top, #f5f2f7, #c7c6c8); - background-image: linear-gradient(top, #f5f2f7, #c7c6c8); - border-radius: 5px; - -webkit-transition: width .2s, opacity .5; - -moz-transition: width .2s, opacity .5; - -o-transition: width .2s, opacity .5; - transition: width .2s, opacity .5; -} - -/* Screen behavior -------------------------------------------------*/ -@media only screen and (max-width: 900px) { - - #title { margin: 0px 20%; width: 40%; } - #title.view { margin: 11px 20% 0px 20%; width: 60%; } - #title span { display: none; } - -} -@media only screen and (max-width: 640px) { - - #title { display: none; } - #title.view { display: block; margin: 11px 20% 0px 15%; width: 65%; } - #button_move { display: none; } - #button_archive { display: none; } - - .center { top: 0px; left: 0px; } - - .album { margin: 40px 0px 0px 50px; } - .photo { margin: 40px 0px 0px 50px; } - - .message { - position: fixed; - width: 100%; - height: 100%; - margin: 1px 0px 0px 0px !important; - border-radius: 0px; - - /* Animation */ - -webkit-animation-name: moveUp; - -webkit-animation-duration: .3s; - -moz-animation-name: moveUp; - -moz-animation-duration: .3s; - -o-animation-name: moveUp; - -o-animation-duration: .3s; - animation-name: moveUp; - animation-duration: .3s; - } - - .message.add { - width: 100%; - margin-top: 0px; - } - - .add_album { - width: 88%; - height: 100px; - margin: 30px 5% -10px 5%; - } - - .add_album .icon { - margin-top: 18px; - font-size: 50px; - } - -} \ No newline at end of file diff --git a/docs/assets/favicon.sketch/Data b/docs/assets/favicon.sketch/Data new file mode 100644 index 0000000000000000000000000000000000000000..781092e0f36e7cc041f16d2ea7eb9589b7361b38 GIT binary patch literal 23304 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 literal 0 HcmV?d00001 diff --git a/docs/assets/favicon.sketch/QuickLook/Preview.png b/docs/assets/favicon.sketch/QuickLook/Preview.png new file mode 100644 index 0000000000000000000000000000000000000000..8a594068cf2b827279cd98ead26b9dd069767a16 GIT binary patch literal 2055 zcmV+i2>ADjP)4Tx05}naRo`#hR1`jmZ&IWdKOk5~hl<6oRa0BJ8yc;~21%2p?MfD<>DVeH z9(p*dx19w`~g7O0}n_%Aq@s%d)fBDv`JHkDym6Hd+5XuAtvnwRpGmK zVkc9?T=n|PIo~X-eVh__(Z?q}P9Z-Dj?gOW6|D%o20XmjW-qs4UjrD(li^iv8@eK9k+ZFm zVRFymFOPAzG5-%Pn|1W;U4vNroTa&AxDScmEA~{ri9gr1^c?U@uwSpaNnw8l_>cP1 zd;)kMQS_;jeRSUEM_*s96y65j1$)tOrwdK{YIQMt92l|D^(E_=$Rjw{b!QT@q!)ni zR`|5oW9X5n$Wv+HVc@|^eX5yXnsHX8PF3UX~a6)MwxDE0HaPjyrlI!;jX{6Kvuh*8ej?;85ekN$?5uuCiS zBTvvVG+XTxAO{m@bvM#Jr)z6J><&E22D|vq?Y?Vkbo_DijopiF$2PET#mZ8eu=y$(ArYkv7@Ex`GL?QCc!_*KFrd&;n1r7 zqW-CFs9&fT)ZaU5gc&=gBz-DaCw(vdOp0__x+47~U6sC(E(JNe@4cTT*n6*E zVH4eoU1-&7pEV~_PRe`a7v+@vy!^5}8?Y3)UmlaER000A?Nkl+x@LdL*=Kj=aw zg)}5JBQ;PVQKOIoQ>0C}Fv(ff;AX%@Gq|Xf5HXB?q#9ksxG)qMtze*ptlb2esWtwg zGoph|?_9mF`}|!DgbR(KP!csX(=%9`qRp_7!>HK~_ zT3cH&Fff3*xw(VvnLZ{a21P|hXlQ6aNJxmvCs;hKUaxQN>FL4B%8CkjzXjQjkB?(% zX$iTxxhhku)rw&7q=JHiz{0`;1EniTk|gZ7ngV*9j9kLZvZM-5m7>auR9IMu1Mx%$ zK_)y6wP|BxgFTc8$;9c2J6nN!wr3dpGz`aED`Gb`_ql#{c2Su z-73T4ZpG)aPBC1Mg3)jc{@KrX{l?f_HY~0kq^D0UauFUqoZ8KIO(L+)KsNqxBK2B!)Zrs%?-qbPG6Ug9#9LoqM{;s9EEWq3-qh5Dl#~?3y1Kd=a)(q& zu^CbL0LGG5JS~weWV_m`#!Vq4ktHiPLOB(Ih{O}p zYPGQ0Y^*h+e!HBMl!UsvI<&R5F-#qmSVi6$eEH=;;)w(#gsC*Z+A2I#Kk&!9IU78< zXvOhNCKGaUazxdhGR>01;egxihLo9^8JM4+-_v+M1+~QGa;Z$Rva%2io~F3CSSdf9 zj!rEOrYLhAae7KhsHbWQ7EddG9GmI;Gchs2zW5YqFXB3?Ol4&y%w{uaRz#vtL@;=g l9Axhd#7O^1K6L-W{sjj;hhI0NJMI7g002ovPDHLkV1nmf>5KpX literal 0 HcmV?d00001 diff --git a/docs/assets/favicon.sketch/QuickLook/Thumbnail.png b/docs/assets/favicon.sketch/QuickLook/Thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..bc37a48db78f458af51c46a38bcd8420c8d91651 GIT binary patch literal 80665 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 N?IGLhzxnpmKL9I;+i3s* literal 0 HcmV?d00001 diff --git a/docs/assets/favicon.sketch/fonts b/docs/assets/favicon.sketch/fonts new file mode 100644 index 0000000..2114530 --- /dev/null +++ b/docs/assets/favicon.sketch/fonts @@ -0,0 +1 @@ +Entypo \ No newline at end of file diff --git a/docs/assets/favicon.sketch/metadata b/docs/assets/favicon.sketch/metadata new file mode 100644 index 0000000..1491bff --- /dev/null +++ b/docs/assets/favicon.sketch/metadata @@ -0,0 +1,14 @@ + + + + + app + com.bohemiancoding.sketch + build + 5302 + commit + 9460a4bc62af5e9ba50dd4143578fd9401710ce5 + version + 18 + + diff --git a/docs/assets/favicon.sketch/version b/docs/assets/favicon.sketch/version new file mode 100644 index 0000000..25bf17f --- /dev/null +++ b/docs/assets/favicon.sketch/version @@ -0,0 +1 @@ +18 \ No newline at end of file diff --git a/docs/assets/thumbs.sketch/Data b/docs/assets/thumbs.sketch/Data new file mode 100644 index 0000000000000000000000000000000000000000..5cb73285efaf8c155afd3207f17d03273b4b1083 GIT binary patch literal 26647 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 literal 0 HcmV?d00001 diff --git a/docs/assets/thumbs.sketch/QuickLook/Preview.png b/docs/assets/thumbs.sketch/QuickLook/Preview.png new file mode 100644 index 0000000000000000000000000000000000000000..9dc91d08e0a640648027e328a07f34aeba6c66eb GIT binary patch literal 5266 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 literal 0 HcmV?d00001 diff --git a/docs/assets/thumbs.sketch/QuickLook/Thumbnail.png b/docs/assets/thumbs.sketch/QuickLook/Thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..ee7febe8bc715875011febfbb49602323bd778cd GIT binary patch literal 9584 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 c3 + + + + app + com.bohemiancoding.sketch + build + 5302 + commit + 9460a4bc62af5e9ba50dd4143578fd9401710ce5 + version + 18 + + diff --git a/docs/assets/thumbs.sketch/version b/docs/assets/thumbs.sketch/version new file mode 100644 index 0000000..25bf17f --- /dev/null +++ b/docs/assets/thumbs.sketch/version @@ -0,0 +1 @@ +18 \ No newline at end of file diff --git a/docs/compile.sh b/docs/compile.sh new file mode 100644 index 0000000..5c30e6c --- /dev/null +++ b/docs/compile.sh @@ -0,0 +1,32 @@ +#!/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/docs/install.sh b/docs/install.sh new file mode 100644 index 0000000..f0ad8cc --- /dev/null +++ b/docs/install.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +VERSION='1.3.2' + +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 diff --git a/docs/md/Changelog.md b/docs/md/Changelog.md new file mode 100644 index 0000000..b36ea12 --- /dev/null +++ b/docs/md/Changelog.md @@ -0,0 +1,16 @@ +### v2.0 +- All new redefined interface +- Faster animations and transitions +- Import from Dropbox +- Import from Server +- Download public albums +- Several sorting options +- Installation assistent +- Infobox and description for albums +- Faster loading and improved performance +- Better file handling and upload +- Album covers are chosen intelligent +- Prettier URLs +- Massive changes under the hood +- IPTC support (Headline and Caption) +- EXIF Orientation support \ No newline at end of file diff --git a/docs/md/FAQ.md b/docs/md/FAQ.md new file mode 100644 index 0000000..e5df297 --- /dev/null +++ b/docs/md/FAQ.md @@ -0,0 +1,44 @@ +#### 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!". + +#### 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. + +#### I can't upload multiple photos at once +If you experience problems uploading large amounts of photos, you might want to change the PHP parameters in `.htaccess` (if you are using the PHP Apache module) or in `.user.ini` (if you are using PHP >= 5.3 with CGI or FastCGI). +If possible, change these settings directly in your `php.ini`. We recommend to increase the values of the following properties: + + max_execution_time = 200 + post_max_size = 200M + upload_max_size = 200M + upload_max_filesize = 20M + max_file_uploads = 100 + +#### Which browsers are supported? +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 choosen 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. + +#### What is new? +Take a look at the [Changelog](Changelog.md) to see whats new. + +#### How can I backup my installation? +To backup your Lychee installation you need to do the following steps: + +1. Create a copy of the whole Lychee folder +2. Run the following MySQL Queries: + - CREATE TABLE lychee_albums_backup LIKE lychee_albums; + - INSERT INTO lychee_albums_backup SELECT * FROM lychee_albums; + - CREATE TABLE lychee_photos_backup LIKE lychee_photos; + - INSERT INTO lychee_photos_backup SELECT * FROM lychee_photos; + - CREATE TABLE lychee_settings_backup LIKE lychee_settings; + - INSERT INTO lychee_settings_backup SELECT * FROM lychee_settings; + +#### How to update? + +1. Replace all files, excluding `uploads/` +2. Open Lychee and enter your database details + +#### Can I upload videos? +No. Video support is not planned. \ No newline at end of file diff --git a/docs/md/FTP Upload.md b/docs/md/FTP Upload.md new file mode 100644 index 0000000..ca8a70d --- /dev/null +++ b/docs/md/FTP Upload.md @@ -0,0 +1,13 @@ +### 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 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 diff --git a/docs/md/Installation.md b/docs/md/Installation.md new file mode 100644 index 0000000..50bac52 --- /dev/null +++ b/docs/md/Installation.md @@ -0,0 +1,29 @@ +### Requirements +Everything you need is a web-server with PHP 5.3 or later and a MySQL-Database. + +### PHP configuration `php.ini` + +The following extensions must be activated: + + extension = php_mbstring.dll + extension = php_exif.dll + extension = php_gd2.dll + +To use Lychee without restrictions, we recommend to increase the values of the following properties: + + max_execution_time = 200 + post_max_size = 200M + upload_max_size = 200M + upload_max_filesize = 20M + max_file_uploads = 100 + +### Folder permissions + +Change the permissions of `uploads/` and `php/` to 777, including all subfolders: + + chmod -R 777 uploads/ php/ + +### Lychee installation + +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 diff --git a/docs/md/Keyboard Shortcuts.md b/docs/md/Keyboard Shortcuts.md new file mode 100644 index 0000000..a4ea4c7 --- /dev/null +++ b/docs/md/Keyboard Shortcuts.md @@ -0,0 +1,17 @@ +### Everywhere +| Key | Action | +|:-----------|:------------| +| `enter` | Confirm Dialog | +| `u` | Upload photo | +| `esc` | Close/Back | +| `cmd`+`up` | Close/Back | + +### Photoview +| Key | Action | +|:-----------|:------------| +| `s` | Star photo | +| `i` | Show information | +| `f` | Show photo in new tab +| `cmd`+`backspace` | Delete photo +| `left` | Previous photo +| `right` | Next photo \ No newline at end of file diff --git a/docs/md/Settings.md b/docs/md/Settings.md new file mode 100644 index 0000000..de49d2d --- /dev/null +++ b/docs/md/Settings.md @@ -0,0 +1,41 @@ +### 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. + + + + $dbHost = Your MySQL host (in most cases you can use localhost) + $dbUser = Your MySQL username + $dbPassword = Your MySQL password + $dbName = The name of the database you want to use + +Fill these properties with your MySQL information. Lychee will create the database and tables for you, if they doesn't exist. + +### 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. + +#### 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. + +#### 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. + +#### Check For Updates + + checkForUpdates = [0|1] + +If `1`, Lychee will check if you are using the latest version. The notice will be displayed beside the version-number when you sign in. + +#### Sorting + + 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 diff --git a/img/apple-touch-icon.png b/img/apple-touch-icon.png deleted file mode 100755 index bd3b738c4c6bded6febfeb3cf1a74e27bc771943..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10871 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 alBB;n{HN@$gpa{N@ys1j)FT7SJ^utpz34~) diff --git a/img/bar/error.png b/img/bar/error.png deleted file mode 100755 index ea61be07630164bb95fd93ae9e115f8deb7280a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^ia^ZF!VDzeud7Z3Qk(@Ik;M!Q+`=Ht$S`Y;1W-^t zz$e7jT}0GVL@ZcBGF(C`LQ*P9QaV#kK3h&oD})~WED??LYcW*4pRnv)8x3{q24JoJ30tBOoI$BLDyZni%U_U7SJ}Mnz3^ zv2Rz0xd8x-k9_p>EKT(E1TArBq>mp005DE`m`P`8y}{Mr5%z&kESlb!p^X>~pk#n^ z=)k7wP3V>4wOLu!@5$5_CnUHUWL7RX0vs;6cQr_UZ`a}C404v8wj}cf-#I|ejph)M z7F+1i+`s4X?X&1r7C>{p43}4@G{7?nC(1@Km)vwnO}i!32@n>fy5-urg1ARsTohUm zSnl=*3>K(VtvH^~9=PZ|1P`oI0OCY)d)}@hgu|%^q51Y1RDh(o@s!M!gq1f&_U186 z37GucIBO^IwNj}$1u{G5Vyt{|tOUOKvJjy3TIuM(3IiK|29ujQo0cs#fQNiFc-N{a zLD@kw))u*HrN%Anm-!71dwu@S%*q?rtV?s_E0iaAe%udBt8#v>k$TSmi0AzVab4JC z)FO>3b2~ZL;ab`zx7vslrNw~aJ$$Q3xth{l_OkVKTEiQ4if|HqWWzL;^R&1$#EtRP zui%ak$T%@6582*1g(iuaig28go6{o|PBr(+)l&F4G)J5UKY{*`9iUIhex&9EsgU%@ zchB-n>?k(653fU8T(>EVNoUa>EBO5Ow=XgbxnpnXZ+c%ZWlO@dCKPj$!mDeR{B%SI z=!83|ihjTJLWh|ZV3H~bHqvZ;YlUqWwaw1xb`??4cI{nA2v)XZqEio}6YRKQ9W|wX z^a&olo`poov{Jb8YbV`8qMi>Nf8VCkei~VhtYrjz)&ao!f~`!pY=Cm->GReIPhIm* zzVg(_PF_`j*8;PBCku77JS)vom%Ha@j{6Lvt~`>|zS)syJ12##l9WkzFAE8Y z#*|tLy=0b-lP=`-29GnHQu4=I=y4ZOtY1^4Ptisff#n&+yHT~wev~t>&9Z@X-M{S! z+tYh>(O}qG*{b6=7fvyB;k@lk^D&4W(_khVOHmH~va}b5kl!>P%iB;&^N8s@(|=f4 zX&Llb*+!+3C5TE)uT3|?&|^$dk;*@XU_@73GNuv86)N_M$vHMamst3=7+pv=RBDt3i*hY*tcyE|F|qe0R_a?9(?OE54W0C=#2eV&vI$(CPd65& z%8>EVlzRA*WMd99ex=PT8X;~y$mJ=ptNY?XYx=D5me9ONM~S7RI0u(lbcP<;*rzWUw?P(`13K$HX=1NIW#}?*%3n!55Iv*5q_QL8}3Nx$p0wI0aiC% zM_s4<29*;OF=>=S=9L9T8zvgI^vR`wNlfNiBY`6$q&!mE%Xf}kj(hc)K40I%D)vzg zfBGGeTghT|EF*Iie%8y<3&jGkv=tJ7U$~q~E5~rro9v z-z)Qk5yu>hoT&!G28Ma!y@nmY^G|XT3XYUX3bdHt zPH8QX1Uz9FtN!VGR!e=@tFU{=d(Gu|8vN!ObI6ro4E%fOfCf)~Vt$wg;`Y&Pry5v| zgsdJ{!9-_hpR!lQ^Mg8XXv4(r3+wg?H*g)Q60%06U-{))bWZP>`L!a>bjvTt1Bw>u?XXBxt{s% z?q2d*;%ZQQw7kW1X06d;`J%&O$7ug3OM#2}xzC*leK&m!>gD3r%jv@!Mi2 z8Kz}~GTSnj;b25o zmKSkj3mj&3F#D0Owy|Wiv>GKqaM^0F*oW*#XemSm1iV8@`X5e8q8=z2DCYSSd;$W- z0;JG!x5}Q09CL4V5IPUEZ{`He%n?GvHgqtSp*y|c#Ew}_j_}6^@_U#Wwq+6Z)c2{G zf!h3k^OxjF<-Mprtd923=?`uB*phaJ+Vfq;o-Wr*jNf=rAet`=Q^Qs+jN7L*txfnW zZWPUlwXux$_Yt{hSptMp5{q zuihQ_sD9h5r_NJOH9;(I_*FwbZXRv$wX2NIf0}I#_nmtdJu}w0J?9W?M97Ld_`5AR z4865BClFP8B(&-_DDu$AHmzP@>NMaitmTaZ!TlX^XXuXs36}U^J@EO!+43f4%zEfU zrB~=%Qh~aLmgbTc?rU!hcQ?2f-0#A9@lb22Q^=aMlis7vA@AAs9lpVw#74xn;=EFO z!CpI2HvG$9ci*rq3z%y9M52z~oXj4GeIKs-3*mxwdD`(PYV+*c$?2m0YR{c)nMDgn z3XTj64hlf?Q55!2X}8bD-sqzLKx24EeaETlClnMk11 zLE$#JdMRs5N`%ij$%CoP){dS%6Ku@AI2 zH-mYg{XuS?Xm;C{1E|xcrXM60skVu$kp)lfZ>DOQ3#K~pSpk1{cJ$j%?tdm zum<@5(Hh_%ivFeWpZ0%7FZ$PH)ByjQr6%Kw7EtG6yb_jXHU?5sQqt1W^78T!2m}g+ zDkvyuXlTIUa7RZ+S65e0Pfr8_;p^**(XE=eNKrA-*Ri3W^02g1hBDYG6PO7QWvDU~ zi*r@QufEy9Nv>1inB}V+>rqfDDiIMXDk{GFZ72%BHxh@W*Q68d$E%tcSm;;ly2ktm DTs+fC diff --git a/img/checks.png b/img/checks.png deleted file mode 100755 index 8556378d65deffd08737802925759276e9afb5ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 113 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 KMNUMnLSTYRH7OC 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 diff --git a/img/no_images@2x.png b/img/no_images@2x.png deleted file mode 100755 index 15bef9fd206a858f2a2bda52edff9dc1ae85c6e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4130 zcma)rkRrVV0+^#T z0Vz_1k4Ogz;z@a*eFIHYsmOKQruUES&#RW#C-?j_Y8YDBBi~VMmLR zj_&+KygS=Qh4RnIjH6Dosqw{{(Q)UE;L&=J;bAzq^@%A1Rw>t%cYUSB;`EuG_Fcxa zJPcf>4DY9%oWO`Z9mb))u;5()4_y)tt z46*6_cyO-83$bs``9Um>jmG*Jp!wa)gM)jSw?J~dMC;x~@m!A>1zldj^_VS25Nm3? z>bu8War>$+*&x3n=ebyLjJ{pbsnHj%^WVFi4mK(G_U+`QQrm7%NBiBPZUZM1o8qg~YIjoT%v?FT% z@;s%9U;+X>PiW3hm!mcype<$)Fq!%D!gCKReEZDFOB`{ls~$cKIqtGj->=eg!o5E> zKUdu)_N>$HUoR5S2>VN)Ptj3#zNon9rcQ6~Nv?FN!_h9!@$7q5*T1{lq%(8g3v537 zZesL3l`S&HrQz9)FjJhY1AAoX@O0?eE0i6|6&sL z(gaPtqRN-a% zpdEwb!E5e+5-&L`8Bvz2ZK$^W*At<7R?CQkS1g|(N+*sOf+J78U>vmN90R?@j#ph5 zW<|92eADsc%VZIF|7F^smS3H#rd442+z*iSGwaqAR?RL}rhYwB)^nRWS~ycthEo^a zlc5ESrMek7u7Y!Q3CQF}b4(|qa&2Fn`EKwwD_jqJIP7jjd1Q3pC5KX7n|5ag+nh)C5d!2U&67OgWbcqFQ!36Jw%Op zgjg3@k0MXCDj9{9pq@aV^Z2)0*hy3;j=|sQ3ya@L;njaGDsWd+f(V2e>$^cM#nr?c zFQ#-~b3i;kYo=+1B8%ogti`zT8iuKt#d%Q%!n#`HcT^4PH2pRGwF~cZmUs=Bmc6LY zGDkJ)1RDgy5Gji3KhtNsD^f_w?u3=}KrvM6XgVg{S~lmB^~F$w-$jSDj7BY*E%(Cm ztM2FOO#`iJ&-8UO@(6a(b{Tdtb`dkmAB@D_;luDXr%|PvOH~76g%^di1`GWMYJuCp zwa<>9<<29n7SIM$mOgBYd~e)la};w#&tIMwo)?;@e7t+2RnBHl@vdNDd`f&ne9}*) zg*xgi^~;q?SF7W95`=w8FUcSRl;A{QAS9LDGVvbf9nLEAEJF>+xrw{kx{bThhGj_! z)M6?oo0?^3mU8zG^FvBaOJ7Yd$QK=Jf zG3R&#HlH_Nd}Ad?Ag=csJBd-^RC6oHYsE7C>ID-dwF>(Zim7w{9ZKIBOS~-lD!j&` z<{m~1brWU^v#vDS$W=GWsmLj4Ml_>CKfeD2`D_yhf7w!!8=Ko~n{AsvZU0wUGO1rO z-#q_%hl>5%N3omgvuN?Em@Iv~enR){dt*bB#y0g-fO^t>!9`q&q}A(^v}`yWl$3O`Pkb&!p>_IsE+Wb%bD zYrb;OdwVot(YM{RePT>){HT^D#eI`I84=f+TAZ>dMCGuGPOp5B{GhT1ziYSQwo$Bp zO+7|ELH$gVZxbmPwr6|9c;tI9@pJUY;=w2l1y%us2I{8k-b^=@Hlxhx#hb@Niq!Z;&hZ6``aUk*9hkToHM=^) zKD#cfXpu%){rvdNd}$ArjI(Yrdn9?`oXGhpp5vG^t)=s~$lKO+n0fGMN<$P4zt|zQ zn6PQN=XjV5PLF&Y*{_q{ZW&{*PuAztpJhbB-+X)e+IlN&t~3>wnlGVP+F$y&Yb3A- z3~Gtl##TvLDym&-gtaN<%W2ntbRAwdIg_W^pM2}GkC{`$i^Sizej(#UUy4PTaZub| zPdXzUb3PjNo?6(R%b4@(Ip6)Wn--$%q>Op$+~oWF`C*Ilx;t0Jvk|hzm%2L`%a;1- zUrj4Xo)Ayu_>UgFo&?8pQ(m!?Lq@NRs+w$EC>skMT6J1R(~UBHXfBTr9(*2a6Hb&0 zw=d~XtNvehJu|U0D6y~jl_|5}2m2GfJCSRRg*$~b%r{?F%-4yf`k$smJ2R{CPvmcw z74yAYd0RCN4_2G*+oB)YaJwcsBmoK~uNw_2-4MgY%LU6}LP;45jmv>GYgwN=zl=6d zd4>)$BrttoQNO?|{4TU>*U-HJ?)ky?>vVY=btP}PzS%j{I#g#3xtUBwJVO+AwkACt zzCJX1wd88*mDU7&NA>KZPVb{{zqA9-kd_P;^XvA&Di>8ZXFB&pHnLCN82672E?c^E zl(X~plXvv(EROm(h569JC$3L(HIjbiPSV?&HgRshWcc z+0yEGwiy>A5OwXr6ZLvvZXkEMPd_k@Zy0b4K}$`A3UFUoOO;V?!>{mY*XN|)mOEp z;K`$YmQrpjjotv2BbOul)!DpD>?q0XGL4F(;k{9((#Gx8SEDvmO0;v*^IC1#F=4+F z)y7OMrAp}mddr9k1T}s?ej=cH`@@f(`1HZqXU!77-|iCnNjV`HTBEaFcl!_b{uQEz z!DLC3>cPm4=c2>+xj~HUMp1F>B&kVbC+sMfX20E;ytIniLlJTkG%!JIhg*K)o=yu> zyOBR>3fIg+=qJlo!&}C>&_BSSP!%W?4uvA2P!lK=4Tai3VJc7<91252VKz_|G!#x3 zZz$Xcigbh`F_$l2mXMI3hrvuDVCX2AO&mR51?8yXmZ+(zNlyek7 z3WapUBE1PnA0i40MbR-qqtK2h?q8#H2-H=c>6S!Mqi5s3SB=4w9Z@MOse2`EdOb`YM#WDk z6h4oHCj$g;IKdl9h{6y`00Idhl7Y-1lgv1u%tW8eLQ-Zmkb_0%5EFC$ke34hc@gM5 zVq6{>$OC{vIwj;n04ORdD#?s0sRl@RHxj{{M2sK-0GWs(13+~Swwhd6O(s{7FEM1^~c&eYXGvV(Qb^fgAgM zUYl6N80(&WZyU{Pv>ba{-y#jfZ>*Ur%O8#PSdF!8VH^Y9hL~1MN9QrN9)%u3L|!j{ zm67vd@z17q`}<5zjZ?-md%wC4((fGq1;4!)zShVWah|(+0~kwdP!1kM=mw>$hxV2= zyxxj~Ca1W2HspsD$32l%cb-1q>z9vQ_LPE!()=VmlV-N0(ySK3pl^Qejs=XZZqC7D zQRQl@)7xsX9PX=Xdx^ijnBlQkWz-$|OC`gD95*lalzlhKJpXndTe$YpEn(O@PQK{A z_uHcQ{ik(*vv|0!$oEHIEtQuSi++IYO7W~r((5%!NP}dl$txoj*UO6_Y9|C^ue&30 z7b1pc`pVb_>~Ujl;8Qw0@PCvf$KyWhKnm;DI3I$GRy-gb4vB`aLRrIE!~fU(nJM(L zdgSeZVH@~`;qK@66Dl|p5U4Pv85aX2wXHKe+azv7qVC6*1xsVONbpt$ko__w2bGsHyDv~guPbo{C`a`K;L_z#u*Q!)78UY4=X zBqNB-rJd)D1?Y|1Z=O(QrZ?y=I+Ce(6Q>@|o01%>B+d>$V8ef(ZeL9M67=3hENSC+ zNcG<=H@-9M`qv#5ONI*rdpM%VgHN*qUUA%?&EdGgNv&3|^C*$Ir|z&vn5_#_W&x#* zF@c%Z_KSrlvh_dD)*#B?rTonn7&NOLAi&?0a=BB4iuT2<2Tl8JCq-+7)OY4F{1<=E e|L0PB@re1(kuERz^cLxlkG}359kP~9_`d)K$(bzx diff --git a/img/password.png b/img/password.png deleted file mode 100755 index 4d47becec5a649b092e7efe590f8248f3abd44f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3688 zcmZu!X*|?l7avU7mr7*km*p=)wx}#)$&wnfgt0T0LCTa-wy{LE!7yoTlYJNl`BgFv z*@?#_TPh@5vZZ93rs#c6 z>30{+PeN^yEwI+Ci3##yCPyv{9#eGiv3t#8mIQd43UbHCd5v@a5U}oUvoSH9pG*tn zT(8yoIhD8H<1{_7_+os*Z#`?pXl+~#upM1SWt>nQ;iK1Y_< zGrqo1vmF!Gk>7MZB9Uy~-MF=;g7u+&RBpAFM~@xEWC7=mWsgF*Oh>gZMav7%v*y?~ zc8RDTK;LW<6x9>YsS6czmec^VopnK5l?zI=zQ?)pbH$=ggCegqi_&P;Q+aYTrD@P& zm&bCS{YoR*k#swYJjnd^Kf}X21y&F>L8AM>qI_{svbw3D$XfCbRtQHElyW+*&O8jaVr+suI5lBxUC1L-7CEP2 zqJP$Et@!Gy)7XOlZtKLfWVG$RUhjRT{f7JsqX?E(|bL# zT&xf_h&^p_QUhr^Ur||c#bjWBhcB1mv%f8HF#B3J;6HsG$_1p?!W$31+S`21;Y>*O zr#-k7>zJwH!<7&-IumnBTY+69x-d}C|E@bE>Vd9xlLdQkh#tiFG@I;AgZr#e%LsvU zT)i!?{A;u7&>8CY|19oFal544oUwudwhLQ489t$MCCVbD(+NRstj9Ci?>ynsj8#!% zRrcT&$7C9WLmvM5Y0N!x- ztvvbEnfU5rV{5(5(|1IhIb7rSp0K}_);zk;5|wc5G3&4=?|aB|>_q)VaSpTg{?8`i zCkxnxUw@pjY!cGvd(kdDBlaDl{J_0Eo5S$%mkeEY~aV1 zjQmFUt20xA>v8;T=gDwK3aB?D8$D0J66 znERddt-d+=e$yW6SI0NKZ`q=GqAj8#qV}S>n%!C=c{lU=^5*jvHG4pRXYOZE=XvMF zXKrc);@W_nuUuoQZgDMjweswce%T~NuhyH~=;&8^t#R;#D_#Y09`?fJg)PPienr($ z)xFMUy;$FdR7)yrHETu0ym|dr`h!O*EWeFhoKoECS>#zd<9)h1i!yYk)VcIxw~qJo z+bJ9Rvk3Y6d0>je`}F3(sn+ z&Q6E5u0~zVbFH5gqFtjgw)nOHrabc;yIxXw5}j}R{hhFXXbDlH$Ckg&G!1T~&9W;* zC^QUPR8AK<4Jr=u4wiEB2!9tIIeRK}==MyLcxaZ2k4l<*_^sj*`;UZK=jFYDtK;d5 zVV%L9lkfE=_M4bW{8#w1%u;)DDzg_w8Qg9UbL(zo-Kcwk-}YKZtyk(_&`;J+*FVt` z)kjgF z7Bn~EX~K|6Zl`Oqw*}SWq{S>N9QN$<-KXw9V&|%IGIL55HL8ZH{u7V@?tsHaa-J#m zO0F7u3Ut*D%~Cbv<~ISOYxXBf42QC;{y{tW(jMdfSp70jlg*clcj9hDJ)QD1Lz3Ru z3>;h7oXeZL*)P%evyU0A<*S9c>(>(YC-HZi)>A@(YM zH-mxuI{W_n-Yc^u3S96rMb!qi`=dMKzE$+il_%pKjK+t48Hr8Cst1JKI(WwsMioQp zGI;r$S*;l(Z8vT5e#2(h_x`lp;n@eRihrJO6NV_HXbh9?=hfHwJ#c85Xka--ZqeNv z+X`Ov`8qd@30SYFOqrsz7;MGv7c;##d$N{R;5%>vDct}Q$@%+7xO}kh!t{2+Pp0|> zr)UU-<(0LSohk4assNw^05AYB2LL#rsspIP096E_>H+B313E}R2LB%8w#a5N5%A;KdI>;b^uT*n>`vp)m^iBJU)FaTk1 zj_^PtJVHEF0S_e7BP0o_10X%@ksg0%$iG0LU;qk*M1^2bn0OSHfWnbObbt^T5E73^ z!vM57fDS>TF<3N_f+kWi2pxQHDF5`;xWkhNOXK8CZ0%+ zFKI}M$0n6Gq(&lBvFKDB9v5Pc!=iCy5Jv&=C>S1%#N$%&1R}nm98Ye*lR-QMB%sX+ zkq817MZh2K5D8R}h=CtQ;vpKqf=K&<0#ZRarGN^O4zqF!2?R^x5hY0;C5LDL%P9?H z5`kP&Kn6hyA%sForIZ&?K#)pAQ^_S%5Nse}8^FIDusjJYPX)<1kcv5xT8Qv-8e*eQ^K&*U#(%46xM~F@^>tVpIaFMnI@%NXZr0Dzh;L56mYeipmt8_4 zODU|aP)6#F``sWp8|E7Ye&522Qmbn%S514pXj5~=t^CSgIdrA>jRS$AUtQ(r=4$bh z>XQB0nNXPo0sOd37hOgyyfe{i)Z8tGNV@*A;}6f~&z&%XC#Yp5ro{Z9(De3xHE;eA zw{p@sl@^KYu(Nl^bed(9e5wMIKuS&Npv*!xS);5=Pxe@@;JdH?(>CHbJmCMjhuxVm zP2O5EOE|)fbxC#L+sp)VP3DE%-SDg{R0-quB43;~?QSG4qTK{V^Cg|TWj{AOUtZ}u zs(uSysNk^FcfLa-d1n%R^_Hn6Y`0~2+pUHB*WSkb>E)Aun7seGvwx+3QVrH!ubgpF ROK<;MEGWj6g^p5WKQ=kJ{NyzhCh^LegwU7z#0mOt+MIp>bHx?v_NEGG;CfkZ9L zjclf_r#OnN#Bq2qX;kGBUEVFfvlK^24}$`M7~V=AxO;aW=R5q@%c;i<~e2 z0E)`Xa!-U5zv`Mxfvux02v+=&5i0)1drc)JPTqF4dCzAS1-O_+SPc2=x-VP~ zR*@OwPq|gnAbV~X{Arnd@?7NEbJE#Dv^T(LeUZ;f-uUUNmb6rrU)geqcG+sptk^26 z!F1)}oLF$SeVX!5j~u*!8^^{X9W=IjqO)@?!xE$+NpWnOP|5a*K4&5+J0JarA0(Jk zuT$-JfVi&XnFR{S_4pM7j<#^lmFP|L8k=l(-&icUweEcObjru;!_NXNxyx*kcnujs z5$3rGpEAOi;+Zs8C_guc=o$B1uk9N;8hmS8uldO)d{JeVn+1){LJaxLzJYM0K`Tmj zFOHPdkl`S<@4hQz!*5^B)=F#&Yv=uNk+si5y7fx^AzE?~cCL@%r5IQ7wb|US{#> zB;0y3MJOWLv+C*PP}@XxSK)||?%|L_7gPmggEPG)Js&xOf}ZMFm0JijWAs2q$M-1R zGkC%uG=mgBE8JXD?OB*qgiSd2WM^VSVZVLMy3oAY~J0l$Unf8!m&v)}mq!_oIaU7=6D zfNz9dxWCUHeCNIB{rw^Yvn#@pb=Nfb21C6B!+wiP(V(vrrC*6r412^6+X+54f?8=y z?rAWJP826yS^uJvf9O>B>ue({z2)N%ULCH8Gf#T(YtO!@Y^StC(v7mCQHa=K=i5#_&Q~?M(_GSSTgr@I za2G!xx*kS%?q=oMs=hJs7rG$vBJNE6ZBzmZS)9t+^UY~iSN=fLd)X2B`@!Xh?9biP zVuH)WdSj~yGap5VRTcxPPYp^ggo)K*e>>xk)d+{kha4SBP-v`GO%$>Ndxwb~d#gRC_7I2^e_U_xe3BLa4O(p>uW}<<(jrnx=BCm~3Om%s0u4B* z=&5jyCAVC1HS;@!xN;Z9RH7<6DvOZ}tWr*>NW!kln;7=p(79T1U0-sG9oKxJ4;Zz?X;QJt#lcr4`VPVQDYzjfV} zx?7<+#kaFfhuI(Wo?4is)5y-xoYS47ox?}88myJ8Nui{&e_#byri#BR(~rp+cG4ez zEoWb6U;6I$UE_$^#aEl1$x{u>3X_~=Ava|={e&Qar3yiEN-Tw=I*bpsOjR$=qKeH=)WJQ^`?{M(&cL8WaZ#;shW*ivg!BIThhnU zCp4Sbo_707!FFSI6Qy@G$dvgu8+YXrqE2=pb1v^phyJSphF+mdeu=F|&W)1xgAOEh zy+h`GwgEw zbrPfFRE}MaZlku#y9Y6g`lCpd;^<5Zl0{t0^;_S%25nH4TsBw4d)!k+lc81BL@WM* zK)f;Sd8za9ax*^X@r(7-`}K&n#7yY{X-Bm=wOeOq)D#dW5qoWY+0(@vAHUb9dpo!U zHASLFT}s+>2gXYa3(gGr*Ukm$raKf5NLSsc;;tN60X9`O&kE>81w?TUtbTjwf1)ZP zs9R!Ya=5&GF?LiyHBgn+X^}USiD*CBF4~^6Uqt4&OxKx1ejN{n%jNx&)LqqM9Ru!X zcftF~qjobJZP$C_Cj9Gt>j%E+^=+4Lo))_%mSje3O36!}kmK&Z`z*ESPSTyCGSaH^ z0(v1&|B`;Rew_Zn8vhzb5M<41n}6GXV_>QG_ryl;CJd|%ej_v~{0eLezAd1?|D4c2 zdmn*6*74Oj@gd3Ddj57Mr5Bw3!oBHXLe;&&|nn#U@= zP!31zFG0T@^e}UyezIA%sJDJJmAyd zBjqzU;9gRQ?oS2ocKmg29f=u%DgPkN3?YK?7KV?;SW@~OcAs?W`yb@d!*yr-!a;_Gk&ARiZUrmR~C8UpYrUT37 zGQT(V_tp;ihII19?P(CuKPo9-9n!pNk;A@VmxQQn8Y=E zYDRDRknpHmx2yMJ{>79FAL2-jtkDNenC+i`jRFrcrmW8ARIGuukLfIqG_5HtWQknv zdmIz=dP;Shy7KOeU5s6J&ySwycdssZ1zH9UO%XaXkF*~-WAI`ZzZ|ErWN@W2Xe@p=^Y9+xzKwbH zn!w$=KlG-82Ddu|3dHUjv^~+@_S|-v9i^!X!%k(rHYnWgUh8!);4II+>_u@)o_Qoh zmK#BK$?HY1k9)ZV+|#CP(`mCpGj8m9?7$P&a>MV|*woI^r?n?{-mQ{57}Q|gCdb3M zrT({f#|*{b>R^72&PLCQ?}Y2*uTGrTLT+BnAfv`$C3HJ`(`C6SX=)a>1|w7B3~+d% ztv>-OzV72gs}W0^=Pn_FK_LD&R+csm^l)KLZY!qG!BU;BMDR#1VF*fQAoHO8tX=+yT$X6 zkJbjzPymgBqtR|?3i^Jh@gm4^%frmlx7!;mBz=ucS!{hPs8F&&6pTQ)+Ap{hZfWr{*cmgk_ zvci#&@Nhyn&*I5ZNJvyTAu65{MQ0OH+C&VTn2}GUvxxcZcsFP~#yp-xis!`)HVF+S zVW1=;fk%+Y8Kew4iNPjgpk$0W8IL3r+{i=%IX;|BB9imjWG0(}HK*WUlyD4%h^J68 zC_IM6&cMSncnO_BB_OFhqtU2LHkHMug(GQEC>kZ6_Af`HM2y9?s47CaPJ~z-CCD{s~nmw zYc&#BiQ%jcHVg(XIIsvD@8U)|q|NN!t6scM zJjQ!p{U6Kwv3u}tzi2?$JrhJ_Rgz**o-Ol`5k^FG-6?EN zn1%5ClKk%U2LPif=i2T%BZW%+QjF*!Zi3dQ3uO~(SDZGeyQQhyG)@@)aes=|jvniM z{lTp3I?G|(z<_hmJIt;N!`^=J8)OEl;n8aIMC@yz^`D>VQq=Fc2n`S2JGSd(4yQBi zC)zufsOUc7J2l>6n0)9lggUW4i+ zr&4h$)zsq7aPK7`;L~rf$VZyTn-zkwN}rpV?qH!*gnq;K>r>X-Sk`XgVwfQCO!0qn zVgIT4&!YdQU~58T!RKnC*K-)__tNLdvmS59IxW$ri3op4H}*EyrYf)hcyMCsn=GeE zGAj^&v1gi6G}Ae{k~U|sz;s>|a9&w+4r^d|>7KNUA4Gn3AS#OmC>h4p+)3~)dsO)R zba~4UIR>&q?RwXVTL-oFd2|#)0`zJREja2n^vBmB?~hpba<}mJ&(s7j#drFPABVLv zOSc1ijlN-iNLsZy*0n6WT A=>Px# diff --git a/index.html b/index.html index f123005..1fe1fff 100644 --- a/index.html +++ b/index.html @@ -5,16 +5,35 @@ Lychee - + - - - - + + + + + + + + + + + - @@ -30,30 +49,30 @@
- Back - + +
-
+
- Back +
-
-
- +
+
- +
@@ -74,31 +93,30 @@
-
-
- + + + + + + + + + + + + + + + + --> - - - + \ No newline at end of file diff --git a/js/functions.js b/js/functions.js deleted file mode 100644 index f22d3bd..0000000 --- a/js/functions.js +++ /dev/null @@ -1 +0,0 @@ -album={json:null,getID:function(){var e;if(photo.json)e=photo.json.album;else if(album.json)e=album.json.id;else e=$(".album:hover, .album.active").attr("data-id");if(!e)e=$(".photo:hover, .photo.active").attr("data-album-id");if(e)return e;else return false},load:function(e,t){var n,r,i,s,o="";password.get(e,function(){if(!t){loadingBar.show();lychee.animate(".album, .photo","contentZoomOut");lychee.animate(".divider","fadeOut")}n=(new Date).getTime();r="getAlbum&albumID="+e+"&password="+password.value;lychee.api(r,"json",function(r){if(r=="HTTP/1.1 403 Album private!"){lychee.setMode("view");return false}if(r=="HTTP/1.1 403 Wrong password!"){album.load(e,t);return false}album.json=r;i=(new Date).getTime()-n;if(i>300)s=0;else if(t)s=0;else s=300-i;if(!visible.albums()&&!visible.photo()&&!visible.album())s=0;setTimeout(function(){view.album.init();if(!t){lychee.animate(".album, .photo","contentZoomIn");view.header.mode("album")}},s)})})},parse:function(e){if(e&&e.thumbUrl)e.thumbUrl=lychee.upload_path_thumb+e.thumbUrl;else if(!album.json.title)album.json.title="Untitled"},add:function(){var e=prompt("Please enter a title for this album:","Untitled"),t;if(e.length>0&&e.length<31){modal.close();t="addAlbum&title="+escape(encodeURI(e));lychee.api(t,"text",function(e){if(e)lychee.goto("a"+e);else loadingBar.show("error")})}else if(e.length>0)loadingBar.show("error","Error","Title to short or too long. Please try another one!")},"delete":function(e){var t,n,r;n=[["Delete Album and Photos",function(){t="deleteAlbum&albumID="+e+"&delAll=true";lychee.api(t,"text",function(t){if(visible.albums())view.albums.content.delete(e);else lychee.goto("");if(!t)loadingBar.show("error")})}],["Keep Album",function(){}]];if(e==0){n[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!",n)}else{if(album.json)r=album.json.title;else if(albums.json)r=albums.json.content[e].title;modal.show("Delete Album","Are you sure you want to delete the album '"+r+"' and all of the photos it contains? This action can't be undone!",n)}},setTitle:function(e){var t="",n,r;if(!e)e=album.getID();if(album.json)t=album.json.title;else if(albums.json)t=albums.json.content[e].title;n=prompt("Please enter a new title for this album:",t);if(e!=""&&e!=null&&e&&n.length>0&&n.length<31){if(visible.album()){album.json.title=n;view.album.title()}else if(visible.albums()){albums.json.content[e].title=n;view.albums.content.title(e)}r="setAlbumTitle&albumID="+e+"&title="+escape(encodeURI(n));lychee.api(r,"text",function(e){if(!e)loadingBar.show("error")})}else if(n.length>0)loadingBar.show("error","Error","New title to short or too long. Please try another one!")},setPublic:function(e,t){var n;if($("input.password").length>0&&$("input.password").val().length>0){n="setAlbumPublic&albumID="+e+"&password="+hex_md5($("input.password").val());album.json.password=true}else{n="setAlbumPublic&albumID="+e;album.json.password=false}if(visible.album()){album.json.public=album.json.public==0?1:0;view.album.public();if(album.json.public==1)contextMenu.shareAlbum(e,t)}lychee.api(n,"text",function(e){if(!e)loadingBar.show("error")})},share:function(e){var t="",n=location.href;switch(e){case 0:t="https://twitter.com/share?url="+encodeURI(n);break;case 1:t="http://www.facebook.com/sharer.php?u="+encodeURI(n)+"&t="+encodeURI(album.json.title);break;case 2:t="mailto:?subject="+encodeURI(album.json.title)+"&body="+encodeURI("Hi! Check this out: "+n);break;default:t="";break}if(t.length>5)location.href=t},getArchive:function(e){var t;if(location.href.indexOf("index.html")>0)t=location.href.replace(location.hash,"").replace("index.html","php/api.php?function=getAlbumArchive&albumID="+e);else t=location.href.replace(location.hash,"")+"php/api.php?function=getAlbumArchive&albumID="+e;location.href=t}};albums={json:null,load:function(){var e,t,n,r,i,s="",o="";lychee.animate(".album, .photo","contentZoomOut");lychee.animate(".divider","fadeOut");e=(new Date).getTime();lychee.api("getAlbums","json",function(n){n.unsortedAlbum={id:0,title:"Unsorted",sysdate:n.unsortedNum+" photos",unsorted:1,thumb0:n.unsortedThumb0,thumb1:n.unsortedThumb1,thumb2:n.unsortedThumb2};n.starredAlbum={id:"f",title:"Starred",sysdate:n.starredNum+" photos",star:1,thumb0:n.starredThumb0,thumb1:n.starredThumb1,thumb2:n.starredThumb2};n.publicAlbum={id:"s",title:"Public",sysdate:n.publicNum+" photos","public":1,thumb0:n.publicThumb0,thumb1:n.publicThumb1,thumb2:n.publicThumb2};albums.json=n;t=(new Date).getTime()-e;if(t>300)waitTime=0;else waitTime=300-t;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(e){if(e.password&&lychee.publicMode){e.thumb0="img/password.png";e.thumb1="img/password.png";e.thumb2="img/password.png"}else{if(e.thumb0)e.thumb0=lychee.upload_path_thumb+e.thumb0;else e.thumb0="img/no_images.png";if(e.thumb1)e.thumb1=lychee.upload_path_thumb+e.thumb1;else e.thumb1="img/no_images.png";if(e.thumb2)e.thumb2=lychee.upload_path_thumb+e.thumb2;else e.thumb2="img/no_images.png"}}};build={divider:function(e){return"

"+e+"

"},album:function(e){if(!e)return"";var t="";title=e.title;if(title.length>18)title=e.title.substr(0,18)+"...";t+="
";t+="thumb";t+="thumb";t+="thumb";t+="
";if(e.password&&!lychee.publicMode)t+="

"+title+"

";else t+="

"+title+"

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

"+n+"

";t+=""+e.sysdate+"";t+="
";if(e.star==1)t+="";if(!lychee.publicMode&&e.public==1&&album.json.public!=1)t+="";t+="
";return t},no_content:function(e){var t="";t+="
";t+="";if(e=="search")t+="

No results

";else if(e=="picture")t+="

No public albums

";t+="
";return t},modal:function(e,t,n){var r="";r+="
";r+="
";r+="

"+e+"

";r+="";r+="

"+t+"

";$.each(n,function(e){if(this[0]!=""){if(e==0)r+=""+this[0]+"";else r+=""+this[0]+""}});r+="
";r+="
";return r},addModal:function(){var e="";e+="
";e+="
";e+="

Add Album or Photo

";e+="";e+="
";e+="
";e+="New Album";e+="
";e+="";e+="
";e+="
";e+="Upload Photo";e+="
";e+="
";e+="
";return e},signInModal:function(){var e="";e+="
";e+="
";e+="

Sign In

";e+="";e+="
Version "+lychee.version+"Update available!
";e+="Sign in";e+="
";e+="
";return e},uploadModal:function(){var e="";e+="
";e+="
";e+="";e+="
";e+="
";e+="
";return e},contextMenu:function(e){var t="";t+="
";t+="
";t+="";t+="";$.each(e,function(n){if(e[n][0]=="separator"&&e[n][1]==-1)t+="";else if(e[n][1]==-1)t+="";else if(e[n][2]!=undefined)t+="";else t+=""});t+="";t+="
"+e[n][0]+"
"+e[n][0]+"
"+e[n][0]+"
";t+="
";return t},infobox:function(e,t){if(!e)return"";var n="",r,i,s,o;n+="

About

";n+="
";switch(e.public){case"0":r="Private";break;case"1":r="Public";break;case"2":r="Public (Album)";break;default:r="-";break}i=t==true||lychee.publicMode?"":"
";s=t==true||lychee.publicMode?"":"
";o=[["","Basics"],["Name",e.title+i],["Uploaded",e.sysdate],["Description",e.description+s],["","Image"],["Size",e.size],["Format",e.type],["Resolution",e.width+" x "+e.height],["","Camera"],["Captured",e.takedate],["Make",e.make],["Type/Model",e.model],["Shutter Speed",e.shutter],["Aperture",e.aperture],["Focal Length",e.focal],["ISO",e.iso],["","Share"],["Visibility",r]];$.each(o,function(e){if(o[e][1]==""||o[e][1]==undefined||o[e][1]==null)o[e][1]="-";if(o[e][0]==""){n+="";n+="

"+o[e][1]+"

";n+=""}else{n+="";n+="";n+="";n+=""}});n+="
"+o[e][0]+""+o[e][1]+"
";n+="
";n+="
";return n}};contextMenu={fns:null,album:function(e){e.preventDefault();var t=e.pageX,n=e.pageY,r=album.getID(),i;if(r=="0"||r=="f"||r=="s")return false;n-=$(document).scrollTop();contextMenu.fns=[function(){album.setTitle(r)},function(){album.delete(r)}];i=[[" Rename",0],[" Delete",1]];contextMenu.close();$(".album[data-id='"+r+"']").addClass("active");$("body").css("overflow","hidden").append(build.contextMenu(i));$(".contextmenu").css({top:n,left:t})},photo:function(e){e.preventDefault();var t=e.pageX,n=e.pageY,r=photo.getID(),i;n-=$(document).scrollTop();contextMenu.fns=[function(){photo.setStar(r)},function(){photo.setTitle(r)},function(){contextMenu.move(r,e)},function(){photo.delete(r)}];i=[[" Star",0],["separator",-1],[" Rename",1],[" Move",2],[" Delete",3]];contextMenu.close();$(".photo[data-id='"+r+"']").addClass("active");$("body").css("overflow","hidden").append(build.contextMenu(i));$(".contextmenu").css({top:n,left:t})},move:function(e,t){var n=t.pageX,r=t.pageY,i=[],s;contextMenu.fns=[];r-=$(document).scrollTop();if(!n||!r){n="10px";r="10px"}if(album.getID()!=0){i=[["Unsorted",0,"photo.setAlbum(0, "+e+")"],["separator",-1]]}lychee.api("getAlbums","json",function(t){if(!t.albums){i=[["New Album",0,"album.add()"]]}else{$.each(t.content,function(t){if(this.id!=album.getID())i.push([this.title,0,"photo.setAlbum("+this.id+", "+e+")"])})}contextMenu.close();$(".photo[data-id='"+e+"']").addClass("active");$("body").css("overflow","hidden").append(build.contextMenu(i));if(!visible.photo())n+=$(".contextmenu").width();$(".contextmenu").css({top:r,left:n-$(".contextmenu").width()})})},sharePhoto:function(e,t){var n=t.pageX,r=t.pageY,i;r-=$(document).scrollTop();if(!n||!r){n="10px";r="10px"}contextMenu.fns=[function(){photo.setPublic(e)},function(){photo.share(e,0)},function(){photo.share(e,1)},function(){photo.share(e,2)},function(){photo.share(e,3)}];if(document.location.hostname!="localhost"){i=[["",-1],["separator",-1],[" Make Private",0],["separator",-1],[" Twitter",1],[" Facebook",2],[" Mail",3],[" Dropbox",4]]}else{i=[["",-1],["separator",-1],[" Make Private",0],["separator",-1],[" Mail",3]]}contextMenu.close();$("body").css("overflow","hidden").append(build.contextMenu(i));$(".contextmenu").css({top:r,left:n+20-$(".contextmenu").width()});$(".contextmenu input").focus()},shareAlbum:function(e,t){var n=t.pageX,r=t.pageY,i;r-=$(document).scrollTop();if(!n||!r){n="10px";r="10px"}contextMenu.fns=[function(){album.setPublic(e)},function(){password.set(e)},function(){album.share(0)},function(){album.share(1)},function(){album.share(2)},function(){password.remove(e)}];if(document.location.hostname!="localhost"){i=[["",-1],["separator",-1],[" Make Private",0],[" Set Password",1],["separator",-1],[" Twitter",2],[" Facebook",3],[" Mail",4]]}else{i=[["",-1],["separator",-1],[" Make Private",0],[" Set Password",1],["separator",-1],[" Mail",4]]}if(album.json.password==true)i[3]=[" Remove Password",5];contextMenu.close();$("body").css("overflow","hidden").append(build.contextMenu(i));$(".contextmenu").css({top:r,left:n+20-$(".contextmenu").width()});$(".contextmenu input").focus()},close:function(){contextMenu.js=null;$(".contextmenu_bg, .contextmenu").remove();$(".photo.active, .album.active").removeClass("active");$("body").css("overflow","scroll")}};loadingBar={status:null,show:function(e,t,n){if(e=="error"){loadingBar.status="error";if(!t)t="Error";if(!n)n="Whoops, it looks like something went wrong. Please reload the site and try again!";lychee.loadingBar.removeClass("loading uploading error").addClass(e).html("

"+t+": "+n+"

").show().css("height","40px");if(visible.controls())lychee.header.css("margin-Top","40px");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.css("margin-Top","3px")},1e3))}},hide:function(e){if(loadingBar.status!="error"&&loadingBar.status!=null||e){loadingBar.status=null;clearTimeout(lychee.loadingBar.data("timeout"));lychee.loadingBar.html("").css("height","3px");if(visible.controls())lychee.header.css("marginTop","0px");setTimeout(function(){lychee.loadingBar.hide()},300)}}};var lychee={init:function(){this.version="1.3.2";this.api_path="php/api.php";this.update_path="http://lychee.electerious.com/version/index.php";this.updateURL="https://github.com/electerious/Lychee";this.upload_path_thumb="uploads/thumb/";this.upload_path_big="uploads/big/";this.publicMode=false;this.viewMode=false;this.checkForUpdates=false;this.dropbox=false;this.loadingBar=$("#loading");this.header=$("header");this.content=$("#content");this.imageview=$("#imageview");this.infobox=$("#infobox")},run:function(){lychee.api("init","json",function(e){lychee.checkForUpdates=e.config.checkForUpdates;if(!e.loggedIn)lychee.setMode("public");$(window).bind("popstate",lychee.load);lychee.load()})},api:function(e,t,n,r){if(r==undefined)loadingBar.show();$.ajax({type:"POST",url:lychee.api_path,data:"function="+e,dataType:t,success:function(e){setTimeout(function(){loadingBar.hide()},100);n(e)},error:lychee.error})},login:function(){var e=$("input#username").val(),t=hex_md5($("input#password").val()),n;n="login&user="+e+"&password="+t;lychee.api(n,"text",function(t){if(t){localStorage.setItem("username",e);window.location.reload()}else{$("#password").val("").addClass("error");$(".message .button.active").removeClass("pressed")}})},loginDialog:function(){$("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)lychee.getUpdate()},logout:function(){lychee.api("logout","text",function(e){window.location.reload()})},"goto":function(e){if(e==undefined)e="";document.location.hash=e},load:function(){var e="",t="",n=document.location.hash.replace("#","");contextMenu.close();if(n.indexOf("a")!=-1)e=n.split("p")[0].replace("a","");if(n.indexOf("p")!=-1)t=n.split("p")[1];if(e&&t){albums.json=null;photo.json=null;if(lychee.content.html()==""||$("#search").length&&$("#search").val().length!=0){lychee.content.hide();album.load(e,true)}if(!visible.photo())view.photo.show();photo.load(t,e)}else if(e){albums.json=null;photo.json=null;if(visible.photo())view.photo.hide();if(album.json&&e==album.json.id)view.album.title();else album.load(e)}else{albums.json=null;album.json=null;photo.json=null;search.code="";if(visible.photo())view.photo.hide();albums.load()}},getUpdate:function(){$.ajax({url:lychee.update_path,success:function(e){if(e!=lychee.version)$("#version span").show()}})},setTitle:function(e,t,n){if(e=="Albums")document.title="Lychee";else document.title="Lychee - "+e;if(t)e+=" - "+t+" photos";if(n)$("#title").addClass("editable");else $("#title").removeClass("editable");$("#title").html(e)},setMode:function(e){$("#button_signout, #search, #button_trash_album, #button_share_album, #button_edit_album, .button_add, #button_archive, .button_divider").remove();$("#button_trash, #button_move, #button_edit, #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(e=="public"){$("#button_signin").show();lychee.publicMode=true}else if(e=="view"){Mousetrap.unbind("esc");$("#button_back, a#next, a#previous").remove();lychee.publicMode=true;lychee.viewMode=true}},animate:function(e,t){var n=[["fadeIn","fadeOut"],["contentZoomIn","contentZoomOut"]];if(!e.jQuery)e=$(e);for(var r=0;r",t)},get:function(e,t){var n=$("input.password").val(),r;if(!lychee.publicMode)t();else if(album.json&&album.json.password==false)t();else if(albums.json&&albums.json.content[e].password==false)t();else if(!albums.json&&!album.json){album.json={password:true};t("")}else if(n==undefined){password.getDialog(e,t)}else{r="checkAlbumAccess&albumID="+e+"&password="+hex_md5(n);lychee.api(r,"text",function(e){if(e){password.value=hex_md5(n);t()}else{lychee.goto("");loadingBar.show("error","Error","Access denied. Wrong password!")}})}},getDialog:function(e,t){var n;n=[["Enter",function(){password.get(e,t)}],["Cancel",lychee.goto]];modal.show(" Enter Password","This album is protected with a password. Enter the password below to view the photos of this album: ",n)},remove:function(e){var t;if(visible.album())album.json.password=false;t="setAlbumPassword&albumID="+e+"&password=";lychee.api(t,"text",function(e){if(!e)loadingBar.show("error")})}};photo={json:null,getID:function(){var e;if(photo.json)e=photo.json.id;else e=$(".photo:hover, .photo.active").attr("data-id");if(e)return e;else return false},load:function(e,t){var n,r;n="getPhoto&photoID="+e+"&albumID="+t+"&password="+password.value;lychee.api(n,"json",function(n){if(n=="HTTP/1.1 403 Wrong password!"){r=function(){if(password.value!="")photo.load(e,t);else setTimeout(r,250)};r();return false}photo.json=n;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},add:{files:function(e){var t=0,n=new FormData,r=new XMLHttpRequest,i,s;$(".upload_overlay").remove();$("body").append(build.uploadModal());window.onbeforeunload=function(){return"Lychee is currently uploading!"};for(var o=0;ot){$(".progressbar div").css("width",s+"%");t=s}if(s>=100)$(".progressbar div").css("opacity",.2)}};$("#upload_files").val("");r.send(n)},url:function(e){var t=album.getID();if(!e)e=prompt("Please enter the direct link to a photo to import it:","");if(album.getID()=="")t=0;if(e&&e.length>3){modal.close();$(".upload_overlay").remove();$("body").append(build.uploadModal());$(".progressbar div").css({opacity:.2,width:"100%"});params="importUrl&url="+escape(e)+"&albumID="+t;lychee.api(params,"text",function(e){$(".upload_overlay").removeClass("fadeIn").css("opacity",0);setTimeout(function(){$(".upload_overlay").remove()},300);if(e){if(album.getID()=="")lychee.goto("a0");else album.load(album.getID())}else loadingBar.show("error")})}else if(e.length>0)loadingBar.show("error","Error","Link to short or too long. Please try another one!")},dropbox:function(){lychee.loadDropbox(function(){Dropbox.choose({linkType:"direct",multiselect:false,success:function(e){photo.add.url(e[0].link)}})})}},"delete":function(e){var t,n,r;if(!e)e=photo.getID();if(visible.photo())r=photo.json.title;else r=album.json.content[e].title;if(r=="")r="Untitled";n=[["Delete Photo",function(){album.json.content[e]=null;view.album.content.delete(e);if(!visible.albums())lychee.goto("a"+album.getID());t="deletePhoto&photoID="+e;lychee.api(t,"text",function(e){if(!e)loadingBar.show("error")})}],["Keep Photo",function(){}]];modal.show("Delete Photo","Are you sure you want to delete the photo '"+r+"'?
This action can't be undone!",n)},setTitle:function(e){var t="",n,r;if(!e)e=photo.getID();if(photo.json)t=photo.json.title;else if(album.json)t=album.json.content[e].title;n=prompt("Please enter a new title for this photo:",t);if(e!=null&&e&&n.length<31){if(visible.photo()){photo.json.title=n==""?"Untitled":n;view.photo.title(t)}album.json.content[e].title=n;view.album.content.title(e);r="setPhotoTitle&photoID="+e+"&title="+escape(encodeURI(n));lychee.api(r,"text",function(e){if(!e)loadingBar.show("error")})}else if(n.length>0)loadingBar.show("error","Error","New title to short or too long. Please try another one!")},setAlbum:function(e,t){var n;if(e>=0){if(visible.photo)lychee.goto("a"+album.getID());album.json.content[t]=null;view.album.content.delete(t);n="setAlbum&photoID="+t+"&albumID="+e;lychee.api(n,"text",function(e){if(!e)loadingBar.show("error")})}},setStar:function(e){var t;if(visible.photo()){photo.json.star=photo.json.star==0?1:0;view.photo.star()}album.json.content[e].star=album.json.content[e].star==0?1:0;view.album.content.star(e);t="setPhotoStar&photoID="+e;lychee.api(t,"text",function(e){if(!e)loadingBar.show("error")})},setPublic:function(e,t){var n;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("a"+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(e,t)}album.json.content[e].public=album.json.content[e].public==0?1:0;view.album.content.public(e);n="setPhotoPublic&photoID="+e+"&url="+photo.getViewLink(e);lychee.api(n,"text",function(e){if(!e)loadingBar.show("error")})},setDescription:function(e){var t=photo.json.description,n=prompt("Please enter a description for this photo:",t),r;if(n.length>0&&n.length<160){if(visible.photo()){photo.json.description=n;view.photo.description(t)}r="setPhotoDescription&photoID="+e+"&description="+escape(n);lychee.api(r,"text",function(e){if(!e)loadingBar.show("error")})}else if(n.length>0)loadingBar.show("error","Error","Description to short or too long. Please try another one!")},share:function(e,t){var n="",r=photo.getViewLink(e),i,s="unknown";switch(t){case 0:n="https://twitter.com/share?url="+encodeURI(r);break;case 1:n="http://www.facebook.com/sharer.php?u="+encodeURI(r)+"&t="+encodeURI(photo.json.title);break;case 2:n="mailto:?subject="+encodeURI(photo.json.title)+"&body="+encodeURI(r);break;case 3:lychee.loadDropbox(function(){s=photo.json.title+"."+photo.getDirectLink().split(".").pop();Dropbox.save(photo.getDirectLink(),s)});break;default:n="";break}if(n.length>5)location.href=n},isSmall:function(){var e=[["width",false],["height",false]];if(photo.json.width<$(window).width()-60)e["width"]=true;if(photo.json.height<$(window).height()-100)e["height"]=true;if(e["width"]&&e["height"])return true;else return false},getDirectLink:function(){return $("#imageview #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/ig,"")},getViewLink:function(e){if(location.href.indexOf("index.html")>0)return location.href.replace("index.html"+location.hash,"view.php?p="+e);else return location.href.replace(location.hash,"view.php?p="+e)}};search={code:null,find:function(e){var t,n="",r="",i;clearTimeout($(window).data("timeout"));$(window).data("timeout",setTimeout(function(){if($("#search").val().length!=0){t="search&term="+e;lychee.api(t,"json",function(e){if(e&&e.albums){albums.json={content:e.albums};$.each(albums.json.content,function(){albums.parse(this);n+=build.album(this)})}if(e&&e.photos){album.json={content:e.photos};$.each(album.json.content,function(){album.parse(this);r+=build.photo(this)})}if(n==""&&r=="")i="error";else if(n=="")i=build.divider("Photos")+r;else if(r=="")i=build.divider("Albums")+n;else i=build.divider("Photos")+r+build.divider("Albums")+n;if(search.code!=hex_md5(i)){$(".no_content").remove();lychee.animate(".album, .photo","contentZoomOut");lychee.animate(".divider","fadeOut");search.code=hex_md5(i);setTimeout(function(){if(i=="error")$("body").append(build.no_content("search"));else{lychee.content.html(i);lychee.animate(".album, .photo","contentZoomIn")}},300)}})}else search.reset()},250))},reset:function(){$("#search").val("");$(".no_content").remove();if(search.code!=""){search.code="";lychee.animate(".divider","fadeOut");albums.load()}}};view={header:{show:function(){clearTimeout($(window).data("timeout"));if(visible.photo()){lychee.imageview.removeClass("full");lychee.loadingBar.css("opacity",1);lychee.header.css("margin-Top","0px");if($("#imageview #image.small").length>0){$("#imageview #image").css({marginTop:-1*($("#imageview #image").height()/2)+20})}else{$("#imageview #image").css({top:70,right:30,bottom:30,left:30})}}},hide:function(){if(visible.photo()&&!visible.infobox()){clearTimeout($(window).data("timeout"));$(window).data("timeout",setTimeout(function(){lychee.imageview.addClass("full");lychee.loadingBar.css("opacity",0);lychee.header.css("margin-Top","-45px");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(e){var t;switch(e){case"albums":$("#tools_album, #tools_photo").hide();$("#tools_albums").show();break;case"album":$("#tools_albums, #tools_photo").hide();$("#tools_album").show();t=album.getID();if(t=="s"||t=="f")$("#button_edit_album, #button_trash_album, #button_share_album").hide();else if(t==0)$("#button_edit_album, #button_share_album").hide();else $("#button_edit_album, #button_trash_album, #button_share_album").show();break;case"photo":$("#tools_albums, #tools_album").hide();$("#tools_photo").show();break}}},albums:{init:function(){view.albums.title();view.albums.content.init()},title:function(){lychee.setTitle("Albums",null,false)},content:{init:function(){var e="",t="";albums.parse(albums.json.unsortedAlbum);albums.parse(albums.json.publicAlbum);albums.parse(albums.json.starredAlbum);if(!lychee.publicMode)e=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)t=build.divider("Albums");$.each(albums.json.content,function(){albums.parse(this);t+=build.album(this)})}if(e==""&&t=="")$("body").append(build.no_content("picture"));else lychee.content.html(e+t);$("img").retina()},title:function(e){var t="",n=albums.json.content[e].title;if(albums.json.content[e].password)t=" ";if(n.length>18)n=n.substr(0,18)+"...";$(".album[data-id='"+e+"'] .overlay h1").html(t+n)},"delete":function(e){$(".album[data-id='"+e+"']").css("opacity",0).animate({width:0,marginLeft:0},300,function(){$(this).remove()})}}},album:{init:function(){album.parse();view.album.title();view.album.public();view.album.content.init();album.json.init=1},title:function(){if((visible.album()||!album.json.init)&&!visible.photo()){switch(album.getID()){case"f":lychee.setTitle("Starred",album.json.num,false);break;case"s":lychee.setTitle("Public",album.json.num,false);break;case"0":lychee.setTitle("Unsorted",album.json.num,false);break;default:lychee.setTitle(album.json.title,album.json.num,true);break}}},content:{init:function(){var e="";$.each(album.json.content,function(){album.parse(this);e+=build.photo(this)});lychee.content.html(e);$("img").retina()},title:function(e){var t=album.json.content[e].title;if(t.length>18)t=t.substr(0,18)+"...";$(".photo[data-id='"+e+"'] .overlay h1").html(t)},star:function(e){$(".photo[data-id='"+e+"'] .icon-star").remove();if(album.json.content[e].star==1)$(".photo[data-id='"+e+"']").append("")},"public":function(e){$(".photo[data-id='"+e+"'] .icon-share").remove();if(album.json.content[e].public==1)$(".photo[data-id='"+e+"']").append("")},"delete":function(e){$(".photo[data-id='"+e+"']").css("opacity",0).animate({width:0,marginLeft:0},300,function(){$(this).remove();if(!visible.albums()){album.json.num--;view.album.title()}})}},"public":function(){if(album.json.public==1){$("#button_share_album a").addClass("active");$("#button_share_album").attr("title","Share Album");$(".photo .icon-share").remove()}else{$("#button_share_album a").removeClass("active");$("#button_share_album").attr("title","Make Public")}}},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(){view.header.mode("photo");$("body").css("overflow","hidden");lychee.animate(lychee.imageview,"fadeIn")},hide:function(){if(!visible.controls())view.header.show();if(visible.infobox)view.photo.hideInfobox();view.header.mode("album");$("body").css("overflow","scroll");lychee.animate(lychee.imageview,"fadeOut");setTimeout(function(){lychee.imageview.hide()},300)},showInfobox:function(){if(!visible.infobox())$("body").append("
");lychee.infobox.css("right","0px")},hideInfobox:function(){$("#infobox_overlay").remove();lychee.infobox.css("right","-320px")},title:function(e){if(photo.json.init)$("#infobox .attr_name").html($("#infobox .attr_name").html().replace(e,photo.json.title));lychee.setTitle(photo.json.title,null,true)},description:function(e){if(photo.json.init)$("#infobox .attr_description").html($("#infobox .attr_description").html().replace(e,photo.json.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(){if(visible.controls()&&photo.isSmall())lychee.imageview.html("
");else if(visible.controls())lychee.imageview.html("
");else if(photo.isSmall())lychee.imageview.html("
");else lychee.imageview.html("
");if(!photo.json.nextPhoto||lychee.viewMode)$("a#next").hide();if(!photo.json.previousPhoto||lychee.viewMode)$("a#previous").hide()},infobox:function(){lychee.infobox.html(build.infobox(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(parseInt(lychee.infobox.css("right").replace("px",""))==-320)return false;else return true},controls:function(){if(lychee.loadingBar.css("opacity")<1)return false;else return true},message:function(){if($(".message").length>0)return true;else return false},contextMenu:function(){if($(".contextmenu").length>0)return true;else return false}} \ No newline at end of file diff --git a/js/main.js b/js/main.js deleted file mode 100755 index 8cf4aed..0000000 --- a/js/main.js +++ /dev/null @@ -1,147 +0,0 @@ -/** - * @name main.js - * @author Philipp Maurer - * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - */ - -$(document).ready(function(){ - - /* Init */ - lychee.init(); - - /* Event Name */ - var event_name = (mobileBrowser()) ? "touchend" : "click"; - - /* Notifications */ - if (window.webkitNotifications) window.webkitNotifications.requestPermission(); - - /* Tooltips */ - if (!mobileBrowser()) $(".tools").tipsy({gravity: 'n'}); - - /* Header */ - $("#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_signout").on(event_name, lychee.logout); - $("#button_download").on(event_name, function() { window.open(photo.getDirectLink(),"_newtab") }); - $("#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() }); - $("#button_edit_album").on(event_name, function() { album.setTitle() }); - $("#button_edit").on(event_name, function() { photo.setTitle(photo.getID()) }); - $("#button_info").on(event_name, function() { view.photo.showInfobox() }); - $("#button_archive").on(event_name, function() { album.getArchive(album.getID()) }); - $("#button_star").on(event_name, function() { photo.setStar(photo.getID()) }); - - /* Search */ - $("#search").on("keyup click", function() { search.find($(this).val()) }); - - /* Back Buttons */ - $("#button_back_home").on(event_name, function() { lychee.goto("") }); - $("#button_back").on(event_name, function() { lychee.goto("a" + album.getID()) }); - - /* Image View */ - lychee.imageview - .on(event_name, "a#previous", function() { - if (photo.json&&photo.json.previousPhoto) lychee.goto("a" + album.getID() + "p" + photo.json.previousPhoto) - }) - .on(event_name, "a#next", function() { - if (photo.json&&photo.json.nextPhoto) lychee.goto("a" + album.getID() + "p" + photo.json.nextPhoto) - }); - - /* Infobox */ - $("#infobox") - .on(event_name, ".header a", function() { view.photo.hideInfobox() }) - .on(event_name, "#edit_title", function() { photo.setTitle(photo.getID()) }) - .on(event_name, "#edit_description", function() { photo.setDescription(photo.getID()) }); - - /* Keyboard */ - Mousetrap - .bind('n', function(e) { if (!visible.message()) $("body").append(build.addModal) }) - .bind('u', function(e) { $("#auswahl").html(""); $("#upload_files").click() }) - .bind('s', function(e) { if (visible.photo()) $("#button_star").click() }) - .bind('f', function(e) { if (visible.photo()) $("#button_download").click() }) - .bind('command+backspace', function(e) { if (visible.photo()&&!visible.message()) photo.delete() }) - .bind('left', function(e) { if (visible.photo()) $("#imageview a#previous").click() }) - .bind('right', function(e) { if (visible.photo()) $("#imageview a#next").click() }) - .bind('i', function(e) { - if (visible.infobox()) view.photo.hideInfobox(); - else if (visible.photo()) view.photo.showInfobox(); - }); - - Mousetrap.bindGlobal('enter', function(e) { - if ($(".message .button.active").length) $(".message .button.active").addClass("pressed").click() - }); - - Mousetrap.bindGlobal(['esc', 'command+up'], function(e) { - e.preventDefault(); - if (visible.message()) modal.close(); - else if (visible.contextMenu()) contextMenu.close(); - else if (visible.infobox()) view.photo.hideInfobox(); - else if (visible.photo()) lychee.goto("a" + album.getID()); - else if (visible.album()) lychee.goto(""); - else if (visible.albums()&&$("#search").val().length!=0) search.reset(); - }); - - /* Document */ - $(document) - - /* Login */ - .on(event_name, "#button_signin", function() { lychee.loginDialog() }) - .on("keyup", "#password", function() { if ($(this).val().length>0) $(this).removeClass("error") }) - - /* Header */ - .on(event_name, "#title.editable", function() { - if (visible.photo()) photo.setTitle(photo.getID()); - else album.setTitle(); - }) - - /* Navigation */ - .on("click", ".album", function() { lychee.goto("a" + $(this).attr("data-id")) }) - .on("click", ".photo", function() { lychee.goto("a" + album.getID() + "p" + $(this).attr("data-id")) }) - - /* Modal */ - .on(event_name, ".message .close", modal.close) - .on(event_name, ".message .button:first", function() { modal.fns[0](); modal.close(); }) - .on(event_name, ".message .button:last", function() { modal.fns[1](); modal.close(); }) - - /* Add Dialog */ - .on(event_name, ".button_add", function() { $("body").append(build.addModal) }) - .on(event_name, "#add_album", album.add) - .on(event_name, "#add_link", function() { photo.add.url() }) - .on(event_name, "#add_photo", function() { $("#auswahl").html(""); $("#upload_files").click() }) - - /* Upload */ - .on("change", "#upload_files", function() { modal.close(); photo.add.files(this.files); }) - - /* Context Menu */ - .on("contextmenu", ".photo", contextMenu.photo) - .on("contextmenu", ".album", contextMenu.album) - .on(event_name, ".contextmenu_bg", contextMenu.close) - - /* Infobox */ - .on(event_name, "#infobox_overlay", function() { view.photo.hideInfobox() }) - - /* Controls */ - .bind("mouseenter", view.header.show) - .bind("mouseleave", view.header.hide) - - /* Upload */ - .on("dragover", function(e) { e.preventDefault(); }, false) - .on("drop", function(e) { - e.stopPropagation(); - e.preventDefault(); - photo.add.files(e.originalEvent.dataTransfer.files); - return true; - }); - - /* Run */ - lychee.run(); - -}); \ No newline at end of file diff --git a/js/modules/build.js b/js/modules/build.js deleted file mode 100755 index 4040c3a..0000000 --- a/js/modules/build.js +++ /dev/null @@ -1,288 +0,0 @@ -/** - * @name build.js - * @author Philipp Maurer - * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - * - * Build Module - * This module is used to generate HTML-Code. - */ - -build = { - - divider: function(title) { - - return "

" + title + "

"; - - }, - - album: function(albumJSON) { - - if (!albumJSON) return ""; - - var album = "" - title = albumJSON.title; - - if (title.length>18) title = albumJSON.title.substr(0, 18) + "..."; - - 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 = "", - title = photoJSON.title; - - if (title.length>18) title = photoJSON.title.substr(0, 18) + "..."; - - 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; - - }, - - 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

"; - - no_content += "
"; - - return no_content; - - }, - - modal: function(title, text, button) { - - var modal = ""; - - modal += "
"; - modal += "
"; - modal += "

" + title + "

"; - modal += ""; - modal += "

" + text + "

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

Add Album or Photo

"; - modal += ""; - modal += "
"; - modal += "
"; - modal += "New Album"; - modal += "
"; - modal += ""; - modal += "
"; - modal += "
"; - modal += "Upload Photo"; - modal += "
"; - modal += "
"; - modal += "
"; - - return modal; - - }, - - signInModal: function() { - - var modal = ""; - - modal += "
"; - modal += "
"; - modal += "

Sign In

"; - modal += ""; - modal += "
Version " + lychee.version + "Update available!
"; - modal += "Sign in"; - modal += "
"; - modal += "
"; - - return modal; - - }, - - uploadModal: function() { - - var modal = ""; - - modal += "
"; - modal += "
"; - modal += ""; - 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; - - }, - - infobox: 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) ? "" : "
"; - editDescriptionHTML = (forView==true||lychee.publicMode) ? "" : "
"; - - 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], - ["", "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], - ["", "Share"], - ["Visibility", public] - ]; - - $.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; - - } - -} \ No newline at end of file diff --git a/js/modules/modal.js b/js/modules/modal.js deleted file mode 100644 index aeaf385..0000000 --- a/js/modules/modal.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @name modal.js - * @author Philipp Maurer - * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - * - * Modal Module - * Build, show and hide a modal. - */ - -modal = { - - fns: null, - - show: function(title, text, buttons) { - - if (!buttons) { - var buttons = []; - buttons[0] = ["", function() {}]; - buttons[1] = ["", function() {}]; - } - - modal.fns = [buttons[0][1], buttons[1][1]]; - $("body").append(build.modal(title, text, buttons)); - $(".message input").focus(); - - }, - - close: function() { - - modal.fns = null; - $(".message_overlay").removeClass("fadeIn").css("opacity", 0); - setTimeout(function() { $(".message_overlay").remove() }, 300); - - } - -} \ No newline at end of file diff --git a/js/modules/photo.js b/js/modules/photo.js deleted file mode 100644 index 4deb588..0000000 --- a/js/modules/photo.js +++ /dev/null @@ -1,403 +0,0 @@ -/** - * @name photo.js - * @author Philipp Maurer - * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - * - * Photo Module - * Takes care of every action a photo can handle and execute. - */ - -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, "json", function(data) { - - if (data=="HTTP/1.1 403 Wrong password!") { - checkPasswd = function() { - if (password.value!="") photo.load(photoID, albumID); - else setTimeout(checkPasswd, 250); - } - checkPasswd(); - return false; - } - - photo.json = data; - 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; - - }, - - add: { - - files: function(files) { - - var pre_progress = 0, - formData = new FormData(), - xhr = new XMLHttpRequest(), - popup, - progress; - - $(".upload_overlay").remove(); - $("body").append(build.uploadModal()); - - window.onbeforeunload = function() { return "Lychee is currently uploading!"; }; - - for (var i = 0; i < files.length; i++) formData.append(i, files[i]); - - formData.append("function", "upload"); - - if (album.getID()=="") formData.append("albumID", 0); - else formData.append("albumID", album.getID()); - - xhr.open('POST', lychee.api_path); - xhr.onload = function() { - - if (xhr.status===200) { - - $(".progressbar div").css("width", "100%"); - $(".upload_overlay").removeClass("fadeIn").css("opacity", 0); - setTimeout(function() { $(".upload_overlay").remove() }, 300); - - if (window.webkitNotifications&&BrowserDetect.browser=="Safari") { - popup = window.webkitNotifications.createNotification("", "Upload complete", "You can now manage your new photo."); - popup.show(); - } - - window.onbeforeunload = null; - - if (album.getID()=="") lychee.goto("a0"); - else album.load(album.getID()); - - } - - }; - - xhr.upload.onprogress = function(event) { - - if (event.lengthComputable) { - - progress = (event.loaded / event.total * 100 | 0); - - if (progress>pre_progress) { - $(".progressbar div").css("width", progress + "%"); - pre_progress = progress; - } - - if (progress>=100) $(".progressbar div").css("opacity", 0.2); - - } - - }; - - $("#upload_files").val(""); - - xhr.send(formData); - - }, - - url: function(link) { - - var albumID = album.getID(); - - if (!link) link = prompt("Please enter the direct link to a photo to import it:", ""); - if (album.getID()=="") albumID = 0; - - if (link&&link.length>3) { - - modal.close(); - - $(".upload_overlay").remove(); - $("body").append(build.uploadModal()); - $(".progressbar div").css({ - "opacity": 0.2, - "width": "100%" - }); - - params = "importUrl&url=" + escape(link) + "&albumID=" + albumID; - lychee.api(params, "text", function(data) { - - $(".upload_overlay").removeClass("fadeIn").css("opacity", 0); - setTimeout(function() { $(".upload_overlay").remove() }, 300); - - if (data) { - if (album.getID()=="") lychee.goto("a0"); - else album.load(album.getID()); - } else loadingBar.show("error"); - - }); - - } else if (link.length>0) loadingBar.show("error", "Error", "Link to short or too long. Please try another one!"); - - }, - - dropbox: function() { - - lychee.loadDropbox(function() { - Dropbox.choose({ - linkType: "direct", - multiselect: false, - success: function(files) { photo.add.url(files[0].link) } - }); - }); - - } - - }, - - delete: function(photoID) { - - var params, - buttons, - photoTitle; - - if (!photoID) photoID = photo.getID(); - - if (visible.photo()) photoTitle = photo.json.title; - else photoTitle = album.json.content[photoID].title; - if (photoTitle=="") photoTitle = "Untitled"; - - buttons = [ - ["Delete Photo", function() { - - album.json.content[photoID] = null; - view.album.content.delete(photoID); - - // Only when search is not active - if (!visible.albums()) lychee.goto("a" + album.getID()); - - params = "deletePhoto&photoID=" + photoID; - lychee.api(params, "text", function(data) { - - if (!data) loadingBar.show("error"); - - }); - - }], - ["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; - - if (!photoID) photoID = photo.getID(); - if (photo.json) oldTitle = photo.json.title; - else if (album.json) oldTitle = album.json.content[photoID].title; - - newTitle = prompt("Please enter a new title for this photo:", oldTitle); - - 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, "text", function(data) { - - if (!data) loadingBar.show("error"); - - }); - - } else if (newTitle.length>0) loadingBar.show("error", "Error", "New title to short or too long. Please try another one!"); - - }, - - setAlbum: function(albumID, photoID) { - - var params; - - if (albumID>=0) { - - if (visible.photo) lychee.goto("a" + album.getID()); - album.json.content[photoID] = null; - view.album.content.delete(photoID); - - params = "setAlbum&photoID=" + photoID + "&albumID=" + albumID; - lychee.api(params, "text", function(data) { - - if (!data) loadingBar.show("error"); - - }); - - } - - }, - - 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, "text", function(data) { - - if (!data) loadingBar.show("error"); - - }); - - }, - - 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("a" + 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, "text", function(data) { - - if (!data) loadingBar.show("error"); - - }); - - }, - - setDescription: function(photoID) { - - var oldDescription = photo.json.description, - description = prompt("Please enter a description for this photo:", oldDescription), - params; - - if (description.length>0&&description.length<160) { - - if (visible.photo()) { - photo.json.description = description; - view.photo.description(oldDescription); - } - - params = "setPhotoDescription&photoID=" + photoID + "&description=" + escape(description); - lychee.api(params, "text", function(data) { - - if (!data) loadingBar.show("error"); - - }); - - } else if (description.length>0) loadingBar.show("error", "Error", "Description to short or too long. Please try another one!"); - - }, - - share: function(photoID, service) { - - var link = "", - url = photo.getViewLink(photoID), - params, - 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; - - }, - - getDirectLink: function() { - - return $("#imageview #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/ig, ""); - - }, - - 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); - - } - -} \ No newline at end of file diff --git a/js/modules/photos.js b/js/modules/photos.js deleted file mode 100755 index 473744f..0000000 --- a/js/modules/photos.js +++ /dev/null @@ -1,431 +0,0 @@ -/** - * @name photos.js - * @author Philipp Maurer - * @author Tobias Reich - * @copyright 2013 by Philipp Maurer, Tobias Reich - * - * Photos Module - * Takes care of every action photos can handle and execute. - */ - -photos = { - - load: function(albumID, refresh) { - - // If refresh is true the function will only refresh the content and not change the toolbar buttons either the title - - /*password = localStorage.getItem("album" + albumID); - if (password==null) { - if (lychee.publicMode) password = prompt("Please enter a password for this album:", ""); else password = ""; - if (password!="") password = hex_md5(password); - localStorage.setItem("album" + albumID, password); - }*/ - - password = ""; - - if (!refresh) { - loadingBar.show(); - if (visible.imageview()) photos.hideView(); - lychee.animate(".album, .photo", "contentZoomOut"); - lychee.animate(".divider", "fadeOut"); - } - - startTime = new Date().getTime(); - - params = "getPhotos&albumID=" + albumID + "&password=" + password; - lychee.api(params, "json", function(data) { - - if (data=="HTTP/1.1 403 Wrong password!") { - localStorage.removeItem("album" + albumID); - photos.load(albumID, refresh); - return false; - } - - durationTime = (new Date().getTime() - startTime); - if (durationTime>300) waitTime = 0; else if (refresh) waitTime = 0; else waitTime = 300 - durationTime; - - $.timer(waitTime,function(){ - - photosData = ""; - $.each(data, function() { photosData += build.photo(this); }); - lychee.content.html(photosData); - - if (!refresh) { - - lychee.animate(".album, .photo", "contentZoomIn"); - $("#tools_albums, #tools_photo").hide(); - $("#tools_album").show(); - $("img").retina(); - - albums.loadInfo(albumID, password); - - } - - }, false); - - }); - - }, - - loadInfo: function(photoID, albumID) { - - /*password = localStorage.getItem("album" + albumID); - if (password==null) { - if (lychee.publicMode) password = prompt("Please enter a password for this album:", ""); else password = ""; - if (password!="") password = hex_md5(password); - localStorage.setItem("album" + albumID, password); - }*/ - - password = ""; - - photos.showView(); - - params = "getPhotoInfo&photoID=" + photoID + "&password=" + password; - lychee.api(params, "json", function(data) { - - if (data=="HTTP/1.1 403 Wrong password!") { - localStorage.removeItem("album" + albumID); - photos.loadInfo(photoID, albumID); - return false; - } - - if (!data.title) data.title = "Untitled"; - - document.title = "Lychee - " + data.title; - lychee.headerTitle.html(data.title).addClass("editable"); - - $("#button_star a").removeClass("icon-star-empty icon-star"); - if (data.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"); - } - - if (data.public=="1") { - $("#button_share a").addClass("active"); - $("#button_share").attr("title", "Share Photo"); - } else { - $("#button_share a").removeClass("active"); - $("#button_share").attr("title", "Make Public"); - } - - data.url = lychee.upload_path + data.url; - - if (visible.controls()&&photos.isSmall(data)) lychee.image_view.html("
"); - else if (visible.controls()) lychee.image_view.html("
"); - else if (photos.isSmall(data)) lychee.image_view.html("
"); - else lychee.image_view.html("
"); - - lychee.animate(image_view, "fadeIn"); - lychee.image_view.show(); - - if (!visible.controls()) lychee.hideControls(); - - lychee.infobox.html(build.infobox(data)).show(); - - $.timer(300,function(){ lychee.content.show(); }); - - }); - - }, - - isSmall: function(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; - - }, - - showView: function() { - - // Change toolbar-buttons - $("#tools_albums, #tools_album").hide(); - $("#tools_photo").show(); - - // Make body not scrollable - $("body").css("overflow", "hidden"); - - }, - - hideView: function() { - - // Change toolbar-buttons - $("#tools_photo, #tools_albums").hide(); - $("#tools_album").show(); - - // Make body scrollable - $("body").css("overflow", "scroll"); - - // Change website title and url by using albums.loadInfo - albums.loadInfo(lychee.content.attr("data-id")); - - // Hide ImageViewer - lychee.animate(image_view, "fadeOut"); - $.timer(300,function(){ lychee.image_view.hide() }); - - }, - - showInfobox: function() { - - if (!visible.infobox()) $("body").append("
"); - lychee.infobox.css("right", "0px"); - - }, - - hideInfobox: function() { - - $("#infobox_overlay").remove(); - lychee.infobox.css("right", "-320px"); - - }, - - hide: function(photoID) { - - $(".photo[data-id='" + photoID + "']").css("opacity", 0).animate({ - width: 0, - marginLeft: 0 - }, 300, function() { - $(this).remove(); - if (!visible.imageview()) { - imgNum = parseInt($("#title span").html().replace("- ", "").replace(" photos", ""))-1; - $("#title span").html(" - " + imgNum + " photos"); - } - }); - - }, - - delete: function(photoID) { - - params = "deletePhoto&photoID=" + photoID; - lychee.api(params, "text", function(data) { - - if (data) { - - photos.hide(photoID); - lychee.goto("a" + lychee.content.attr("data-id")); - - } else loadingBar.show("error"); - - }); - - }, - - deleteDialog: function(photoID) { - - if (!photoID) photoID = lychee.image_view.attr("data-id"); - - if (visible.imageview()) photoTitle = lychee.title(); - else photoTitle = $(".photo[data-id='" + photoID + "'] .overlay h1").html(); - if (photoTitle=="") photoTitle = "Untitled"; - - f1 = "photos.delete(" + photoID + ");"; - f2 = ""; - modal = build.modal("Delete Photo", "Are you sure you want to delete the photo '" + photoTitle + "'?
This action can't be undone!", ["Delete Photo", "Keep Photo"], [f1, f2]); - $("body").append(modal); - - }, - - setTitle: function(photoID) { - - if (!photoID) oldTitle = lychee.title(); else oldTitle = ""; - if (!photoID) photoID = lychee.image_view.attr("data-id"); - - newTitle = prompt("Please enter a new title for this photo:", oldTitle); - - if (photoID!=null&&photoID&&newTitle.length<31) { - - if (newTitle=="") newTitle = "Untitled"; - - params = "setPhotoTitle&photoID=" + photoID + "&title=" + encodeURI(newTitle); - lychee.api(params, "text", function(data) { - - if (data) { - if (visible.imageview()) { - $("#infobox .attr_name").html($("#infobox .attr_name").html().replace(lychee.title(), newTitle)); - lychee.headerTitle.html(newTitle); - document.title = "Lychee - " + newTitle; - } - $(".photo[data-id='" + photoID + "'] .overlay h1").html(newTitle); - } else loadingBar.show("error"); - - }); - - } else if (newTitle.length>0) loadingBar.show("error", "Error", "New title to short or too long. Please try another one!"); - - }, - - setAlbum: function(photoID, albumID) { - - if (albumID>=0) { - - params = "setAlbum&photoID=" + photoID + "&albumID=" + albumID; - lychee.api(params, "text", function(data) { - - if (data) { - photos.hide(photoID); - lychee.goto("a" + lychee.content.attr("data-id")); - } else loadingBar.show("error"); - - }); - - } - - }, - - setStar: function() { - - photoID = lychee.image_view.attr("data-id"); - - params = "setPhotoStar&photoID=" + photoID; - lychee.api(params, "text", function(data) { - - if (data) { - - if ($("#button_star a.icon-star-empty").length) { - $("#button_star a").removeClass("icon-star-empty icon-star").addClass("icon-star"); - $("#button_star").attr("title", "Unstar Photo"); - } else { - $("#button_star a").removeClass("icon-star-empty icon-star").addClass("icon-star-empty"); - $("#button_star").attr("title", "Star Photo"); - } - - photos.load(lychee.content.attr("data-id"), true); - - } else loadingBar.show("error"); - - }); - - }, - - setPublic: function(e) { - - photoID = lychee.image_view.attr("data-id"); - - params = "setPhotoPublic&photoID=" + photoID + "&url=" + photos.getViewLink(photoID); - lychee.api(params, "text", function(data) { - - if (data) { - - if ($("#button_share a.active").length) { - $("#button_share a").removeClass("active"); - $("#button_share").attr("title", "Make Public"); - $("#infobox .attr_visibility").html("Private"); - } else { - $("#button_share a").addClass("active"); - $("#button_share").attr("title", "Share Photo"); - $("#infobox .attr_visibility").html("Public"); - contextMenu.share(photoID, e.pageX, e.pageY); - } - - photos.load(lychee.content.attr("data-id"), true); - - } else loadingBar.show("error"); - - }); - - }, - - setDescription: function() { - - description = prompt("Please enter a description for this photo:", ""); - photoID = lychee.image_view.attr("data-id"); - - if (description.length>0&&description.length<160) { - - params = "setPhotoDescription&photoID=" + photoID + "&description=" + escape(description); - lychee.api(params, "text", function(data) { - - if (data) { - $("#infobox .attr_description").html(description + "
"); - } else loadingBar.show("error"); - - }); - - } else if (description.length>0) loadingBar.show("error", "Error", "Description to short or too long. Please try another one!"); - - }, - - share: function(service, photoID) { - - link = ""; - url = photos.getViewLink(photoID); - - 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(lychee.title()); - break; - case 2: - link = "mailto:?subject=" + encodeURI(lychee.title()) + "&body=" + encodeURI("Hi! Check this out: " + url); - break; - case 3: - modal = build.modal("Copy Link", "Everyone can view your public photos, but only you can edit them. Use this link to share your photo with others: ", ["Close"], [""]); - $("body").append(modal); - $(".copylink").focus(); - break; - case 4: - params = "getShortlink&photoID=" + photoID; - lychee.api(params, "text", function(data) { - if (data=="") data = "Something went wrong!"; - modal = build.modal("Copy Shortlink", "Everyone can view your public photos, but only you can edit them. Use this link to share your photo with others: ", ["Close"], [""]); - $("body").append(modal); - $(".copylink").focus(); - }); - break; - default: - link = ""; - break; - } - - if (link.length>5) location.href = link; - - }, - - 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); - - }, - - previous: function() { - - albumID = lychee.content.attr("data-id"); - photoID = lychee.image_view.attr("data-id"); - - params = "previousPhoto&photoID=" + photoID + "&albumID=" + albumID; - lychee.api(params, "json", function(data) { - - if (data!=false) lychee.goto("a" + albumID + "p" + data.id); - - }); - - }, - - next: function() { - - albumID = lychee.content.attr("data-id"); - photoID = lychee.image_view.attr("data-id"); - - params = "nextPhoto&photoID=" + photoID + "&albumID=" + albumID; - lychee.api(params, "json", function(data) { - - if (data) lychee.goto("a" + albumID + "p" + data.id); - - }); - - } - -} \ No newline at end of file diff --git a/lychee.sql b/lychee.sql deleted file mode 100755 index 7e5e6b0..0000000 --- a/lychee.sql +++ /dev/null @@ -1,48 +0,0 @@ -SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; -SET time_zone = "+00:00"; - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; - -CREATE TABLE IF NOT EXISTS `lychee_albums` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `title` varchar(50) NOT NULL, - `sysdate` varchar(10) NOT NULL, - `public` TINYINT(1) DEFAULT '0', - `password` VARCHAR(100), - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; - -CREATE TABLE IF NOT EXISTS `lychee_photos` ( - `id` bigint(14) NOT NULL, - `title` varchar(50) NOT NULL, - `description` varchar(160) NOT NULL, - `url` varchar(100) NOT NULL, - `public` tinyint(1) NOT NULL, - `shortlink` varchar(20) NOT NULL, - `type` varchar(10) NOT NULL, - `width` int(11) NOT NULL, - `height` int(11) NOT NULL, - `size` varchar(10) NOT NULL, - `sysdate` varchar(10) NOT NULL, - `systime` varchar(8) NOT NULL, - `iso` varchar(15) NOT NULL, - `aperture` varchar(10) NOT NULL, - `make` varchar(20) NOT NULL, - `model` varchar(50) NOT NULL, - `shutter` varchar(10) NOT NULL, - `focal` varchar(10) NOT NULL, - `takedate` varchar(10) NOT NULL, - `taketime` varchar(8) NOT NULL, - `star` tinyint(1) NOT NULL, - `thumbUrl` varchar(50) NOT NULL, - `album` varchar(30) NOT NULL DEFAULT '0', - `import_name` varchar(100) DEFAULT '', - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/php/api.php b/php/api.php old mode 100755 new mode 100644 index 7f108cf..a15579e --- a/php/api.php +++ b/php/api.php @@ -1,115 +1,282 @@ - \ No newline at end of file diff --git a/php/check.php b/php/check.php deleted file mode 100644 index bf06453..0000000 --- a/php/check.php +++ /dev/null @@ -1,45 +0,0 @@ -\n'); - - // Extensions - if (!extension_loaded('exif')) $error .= ('Error 200: PHP exif extension not activated.
\n'); - if (!extension_loaded('mbstring')) $error .= ('Error 201: PHP mbstring extension not activated.
\n'); - if (!extension_loaded('gd')) $error .= ('Error 202: PHP gd extension not activated.
\n'); - if (!extension_loaded('mysqli')) $error .= ('Error 203: PHP mysqli extension not activated.
\n'); - - // Config - if (!$db||$db=='') $error .= ('Error 300: No property for \$db in config.php.
\n'); - if (!$dbUser||$dbUser=='') $error .= ('Error 301: No property for \$dbUser in config.php.
\n'); - if (!$dbPassword||$dbPassword=='') $error .= ('Error 302: No property for \$dbPassword in config.php.
\n'); - if (!$dbHost||$dbHost=='') $error .= ('Error 303: No property for \$dbHost in config.php.
\n'); - if (!$user||$user=='') $error .= ('Error 304: No property for \$user in config.php.
\n'); - if (!$password||$password=='') $error .= ('Error 305: No property for \$password in config.php.
\n'); - - // Additional Config - //if ($checkForUpdates!=true&&heckForUpdates!=false) $error .= ('Error 306: No property for \$checkForUpdates in config.php.
\n'); - if (!is_numeric($thumbQuality)||$thumbQuality<=0||$thumbQuality>=100) $error .= ('Error 307: Wrong property for \$thumbQuality in config.php.
\n'); - if ($sorting!='ASC'&&$sorting!='DESC') $error .= ('Error 308: Wrong property for \$sorting in config.php.
\n'); - - // Database - $database = new mysqli($dbHost, $dbUser, $dbPassword, $db); - if (mysqli_connect_errno()!=0) $error .= ('Error 400: ' . mysqli_connect_errno() . ': ' . mysqli_connect_error() . '
\n'); - - // Permissions - if (substr(sprintf('%o', fileperms('../uploads/big/')), -4)!='0777') $error .= ('Error 500: Wrong permissions for \'/uploads/big\' (777 required).
\n'); - if (substr(sprintf('%o', fileperms('../uploads/thumb/')), -4)!='0777') $error .= ('Error 501: Wrong permissions for \'/uploads/thumb\' (777 required).
\n'); - if (substr(sprintf('%o', fileperms('../uploads/import/')), -4)!='0777') $error .= ('Error 502: Wrong permissions for \'/uploads/import\' (777 required).
\n'); - if (substr(sprintf('%o', fileperms('../uploads/')), -4)!='0777') $error .= ('Error 503: Wrong permissions for \'/uploads\' (777 required).
\n'); - - if ($error=='') echo('Lychee is ready!'); else echo $error; - -?> \ No newline at end of file diff --git a/php/config.php b/php/config.php deleted file mode 100755 index 789bf44..0000000 --- a/php/config.php +++ /dev/null @@ -1,27 +0,0 @@ - \ No newline at end of file diff --git a/php/functions.php b/php/functions.php deleted file mode 100644 index 87eeb25..0000000 --- a/php/functions.php +++ /dev/null @@ -1,801 +0,0 @@ -select_db($db)) { - createDatabase($db, $database); - } - $query = "SELECT * FROM lychee_photos, lychee_albums;"; - if (!$database->query($query)) createTables($database); - return $database; -} -function dbClose() { - global $database; - if (!$database->close()) { - echo "Closing the connection failed!"; - return false; - } - return true; -} -function createDatabase($db, $database) { - $result = $database->query("CREATE DATABASE IF NOT EXISTS $db;"); - $database->select_db($db); - if (!$result) return false; - return true; -} -function createTables($database) { - $query = "CREATE TABLE IF NOT EXISTS `lychee_albums` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `title` varchar(50) NOT NULL, - `sysdate` varchar(10) NOT NULL, - `public` TINYINT(1) DEFAULT '0', - `password` VARCHAR(100), - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;"; - $result = $database->query($query); - if (!$result) return false; - - $query = "CREATE TABLE `lychee_photos` ( - `id` bigint(14) NOT NULL, - `title` varchar(50) NOT NULL, - `description` varchar(160) NOT NULL, - `url` varchar(100) NOT NULL, - `public` tinyint(1) NOT NULL, - `type` varchar(10) NOT NULL, - `width` int(11) NOT NULL, - `height` int(11) NOT NULL, - `size` varchar(10) NOT NULL, - `sysdate` varchar(10) NOT NULL, - `systime` varchar(8) NOT NULL, - `iso` varchar(15) NOT NULL, - `aperture` varchar(10) NOT NULL, - `make` varchar(20) NOT NULL, - `model` varchar(50) NOT NULL, - `shutter` varchar(20) NOT NULL, - `focal` varchar(10) NOT NULL, - `takedate` varchar(10) NOT NULL, - `taketime` varchar(8) NOT NULL, - `star` tinyint(1) NOT NULL, - `thumbUrl` varchar(50) NOT NULL, - `album` varchar(30) NOT NULL DEFAULT '0', - `import_name` varchar(100) DEFAULT '', - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1;"; - $result = $database->query($query); - if (!$result) return false; - return true; -} - -// Upload Functions -function upload($files, $albumID) { - - global $database; - - switch($albumID) { - // s for public (share) - case 's': - $public = 1; - $star = 0; - $albumID = 0; - break; - // f for starred (fav) - case 'f': - $star = 1; - $public = 0; - $albumID = 0; - break; - default: - $star = 0; - $public = 0; - } - - foreach ($files as $file) { - - $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 = $file["name"]; - $data = explode('.',$data); - $data = array_reverse ($data); - $data = $data[0]; - - // Import if not uploaded via web - if (!is_uploaded_file($file)) { - if (copy($tmp_name, "../uploads/big/" . md5($id) . ".$data")) { - unlink($tmp_name); - $import_name = $tmp_name; - } - } else { - move_uploaded_file($tmp_name, "../uploads/big/" . md5($id) . ".$data"); - $import_name = ""; - } - - // Create Thumb - createThumb(md5($id).".".$data); - - // Read infos - $info = getCamera(md5($id).".".$data); - $title = ""; - if (isset($info['type'])){$type=$info['type'];} else {$type="";} - if (isset($info['width'])){$width=$info['width'];} else {$width="";} - if (isset($info['height'])){$height=$info['height'] OR "";} else {$height="";} - if (isset($info['size'])){$size=$info['size'] OR "";} else {$size="";} - if (isset($info['date'])){$sysdate=$info['date'];} else {$sysdate="";} - if (isset($info['time'])){$systime=$info['time'];} else {$systime="";} - if (isset($info['iso'])){$iso=$info['iso'];} else {$iso="";} - if (isset($info['aperture'])){$aperture=$info['aperture'];} else {$aperture="";} - if (isset($info['make'])){$make=$info['make'];} else {$make="";} - if (isset($info['model'])){$model=$info['model'] OR "";} else {$model="";} - if (isset($info['shutter'])){$shutter=$info['shutter'];} else {$shutter="";} - if (isset($info['focal'])){$focal=$info['focal'];} else {$focal="";} - if (isset($info['takeDate'])){$takeDate=$info['takeDate'];} else {$takeDate="";} - if (isset($info['takeTime'])){$takeTime=$info['takeTime'];} else {$takeTime="";} - $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', '$title', '" . md5($id) . ".$data', '', '$type', '$width', '$height', '$size', '$sysdate', '$systime', '$iso', '$aperture', '$make', '$model', '$shutter', '$focal', '$takeDate', '$takeTime', '" . md5($id) . ".$data', '$albumID', '$public', '$star', '$import_name');"; - $result = $database->query($query); - - } - - return true; - -} -function getCamera($filename) { - global $database; - $url = "../uploads/big/$filename"; - $type = getimagesize($url); - $type = $type['mime']; - - if (($type == "image/jpeg") && function_exists('exif_read_data') ){ - - $exif = exif_read_data($url, "EXIF", 0); - - // General information - $return['name'] = $exif['FileName']; - $generalInfos = getimagesize($url); - $return['type'] = $generalInfos['mime']; - $return['width'] = $generalInfos[0]; - $return['height'] = $generalInfos[1]; - $size = (filesize($url) / 1024); - if ($size >= 1024){$size=round($size/1024,1)." MB";} else {$size=round($size,1)." KB";} - $return['size'] = $size; - $return['date'] = date("d.m.Y",filectime($url)); - $return['time'] = date("H:i:s",filectime($url)); - - // Camera Information - if (isset($exif['ISOSpeedRatings'])){$return['iso']="ISO-".$exif['ISOSpeedRatings'];} - if (isset($exif['COMPUTED']['ApertureFNumber'])){$return['aperture']=$exif['COMPUTED']['ApertureFNumber'];} - if (isset($exif['Make'])){$return['make']=$exif['Make'];} - if (isset($exif['Model'])){$return['model']=$exif['Model'];} - if (isset($exif['ExposureTime'])){$return['shutter']=$exif['ExposureTime']." Sek.";} - if (isset($exif['FocalLength'])){$return['focal']=($exif['FocalLength']/1)." mm";} - if (isset($exif['Software'])){$return['software']=$exif['Software'];} - if (isset($exif['DateTimeOriginal'])) { - $exifDate = explode(" ",$exif['DateTimeOriginal']); - $date = explode(":", $exifDate[0]); $return['takeDate'] = $date[2].".".$date[1].".".$date[0]; - $return['takeTime'] = $exifDate[1]; - } - - } else { - - $exif = getimagesize($url); - $return['type'] = $exif['mime']; - $return['width'] = $exif[0]; - $return['height'] = $exif[1]; - $size = (filesize($url) / 1024); - if ($size >= 1024){$size=round($size/1024,1)." MB";} else {$size=round($size,1)." KB";} - $return['size'] = $size; - $return['date'] = date("d.m.Y",filectime($url)); - $return['time'] = date("H:i:s",filectime($url)); - - } - return $return; -} -function createThumb($filename, $width = 200, $width2x = 400, $height = 200, $height2x = 400) { - - global $database, $thumbQuality; - $photoUrl = "../uploads/big/$filename"; - $newUrl = "../uploads/thumb/$filename"; - $thumbPhotoName = explode(".", $filename); - $newUrl2x = "../uploads/thumb/".$thumbPhotoName[0]."@2x.".$thumbPhotoName[1]; - $oldImg = getimagesize($photoUrl); - $type = $oldImg['mime']; - - // Set position and size - $thumb = imagecreatetruecolor($width, $height); - $thumb2x = imagecreatetruecolor($width2x, $height2x); - if ($oldImg[0]<$oldImg[1]) { - $newSize = $oldImg[0]; - $startWidth = 0; - $startHeight = $oldImg[1]/2 - $oldImg[0]/2; - } else { - $newSize = $oldImg[1]; - $startWidth = $oldImg[0]/2 - $oldImg[1]/2; - $startHeight = 0; - } - - // Create new image - switch($type) { - case "image/jpeg": $sourceImg = imagecreatefromjpeg($photoUrl); break; - case "image/png": $sourceImg = imagecreatefrompng($photoUrl); break; - case "image/gif": $sourceImg = imagecreatefromgif($photoUrl); break; - default: return false; - } - imagecopyresampled($thumb,$sourceImg,0,0,$startWidth,$startHeight,$width,$height,$newSize,$newSize); - imagecopyresampled($thumb2x,$sourceImg,0,0,$startWidth,$startHeight,$width2x,$height2x,$newSize,$newSize); - switch($type) { - case "image/jpeg": imagejpeg($thumb,$newUrl,$thumbQuality); imagejpeg($thumb2x,$newUrl2x,$thumbQuality); break; - case "image/png": imagepng($thumb,$newUrl); imagepng($thumb2x,$newUrl2x); break; - case "image/gif": imagegif($thumb,$newUrl); imagegif($thumb2x,$newUrl2x); break; - default: return false; - } - - return true; - -} - -// Session Functions -function init($mode) { - global $checkForUpdates; - $return["config"]["checkForUpdates"] = $checkForUpdates; - if ($mode=="admin") $return["loggedIn"] = true; - else $return["loggedIn"] = false; - return $return; -} -function login($loginUser, $loginPassword) { - global $database, $user, $password; - if ($loginUser==$user&&$loginPassword==md5($password)) { - // Admin Login - $_SESSION['login'] = true; - return true; - } else { - return false; - } -} -function logout() { - session_destroy(); - return true; -} - -// Album Functions -function addAlbum($title) { - global $database; - $title = mysqli_real_escape_string($database, urldecode($title)); - if (strlen($title)<1||strlen($title)>30) return false; - $sysdate = date("d.m.Y"); - $query = "INSERT INTO lychee_albums (title, sysdate) VALUES ('$title', '$sysdate');"; - $result = $database->query($query); - if (!$result) return false; - return $database->insert_id; -} -function getAlbums($public) { - global $database, $sorting; - - // Smart Albums - if (!$public) $return = getSmartInfo(); - - // Albums - if ($public) $query = "SELECT * FROM lychee_albums WHERE public = 1 ORDER BY id $sorting;"; - else $query = "SELECT * FROM lychee_albums ORDER BY id $sorting;"; - $result = $database->query($query) OR die("Error: $result
".$database->error); - $i=0; - while($row = $result->fetch_object()) { - $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'] = $row->sysdate; - 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; - $query = "SELECT thumbUrl FROM lychee_photos WHERE album = '$albumID' ORDER BY id $sorting LIMIT 0, 3;"; - $result2 = $database->query($query); - $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"]=""; - } - $i++; - } - if ($i==0) $return["albums"] = false; - else $return["albums"] = true; - return $return; -} -function getAlbum($albumID) { - global $database, $sorting; - switch($albumID) { - case "f": - $return['public'] = false; - $query = "SELECT id, title, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE star = 1 ORDER BY id $sorting;"; - break; - case "s": - $return['public'] = false; - $query = "SELECT id, title, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE public = 1 ORDER BY id $sorting;"; - break; - case 0: - $return['public'] = false; - $query = "SELECT id, title, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE album = 0 ORDER BY id $sorting;"; - default: - $result = $database->query("SELECT title, public, password FROM lychee_albums WHERE id = '$albumID';"); - $row = $result->fetch_object(); - $return['title'] = $row->title; - $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' ORDER BY id $sorting;"; - break; - } - $result = $database->query($query); - $i = 0; - while($row = $result->fetch_array()) { - $return['content'][$row['id']] = $row; - $i++; - } - if ($i==0) $return['content'] = false; - $return['id'] = $albumID; - $return['num'] = $i; - return $return; -} -function getSmartInfo() { - - global $database, $sorting; - - // Unsorted - $query = "SELECT * FROM lychee_photos WHERE album = 0 ORDER BY id $sorting;"; - $result = $database->query($query); - $i = 0; - while($row = $result->fetch_object()) { - if ($i<3) $return["unsortedThumb$i"] = $row->thumbUrl; - $i++; - } - $return['unsortedNum'] = $i; - - // Public - $query2 = "SELECT * FROM lychee_photos WHERE public = 1 ORDER BY id $sorting;"; - $result2 = $database->query($query2); - $i = 0; - while($row2 = $result2->fetch_object()) { - if ($i<3) $return["publicThumb$i"] = $row2->thumbUrl; - $i++; - } - $return['publicNum'] = $i; - - // Starred - $query3 = "SELECT * FROM lychee_photos WHERE star = 1 ORDER BY id $sorting;"; - $result3 = $database->query($query3); - $i = 0; - while($row3 = $result3->fetch_object()) { - if ($i<3) $return["starredThumb$i"] = $row3->thumbUrl; - $i++; - } - $return['starredNum'] = $i; - - return $return; - -} -function setAlbumTitle($albumID, $title) { - global $database; - $title = mysqli_real_escape_string($database, urldecode($title)); - if (strlen($title)<1||strlen($title)>30) return false; - $query = "UPDATE lychee_albums SET title = '$title' WHERE id = '$albumID';"; - $result = $database->query($query); - if (!$result) return false; - return true; -} -function deleteAlbum($albumID, $delAll) { - global $database; - if ($delAll=="true") { - $query = "SELECT id FROM lychee_photos WHERE album = '$albumID';"; - $result = $database->query($query); - $error = false; - while($row = $result->fetch_object()) { - if (!deletePhoto($row->id)) $error = true; - } - } else { - $query = "UPDATE lychee_photos SET album = '0' WHERE album = '$albumID';"; - $result = $database->query($query); - if (!$result) return false; - } - if ($albumID!=0) { - $query = "DELETE FROM lychee_albums WHERE id = '$albumID';"; - $result = $database->query($query); - if (!$result) return false; - } - if ($error) return false; - return true; -} -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++; - } - $query = "SELECT * FROM lychee_albums WHERE id = '$albumID';"; - $result = $database->query($query); - $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; -} -function setAlbumPublic($albumID, $password) { - global $database; - $query = "SELECT public FROM lychee_albums WHERE id = '$albumID';"; - $result = $database->query($query); - $row = $result->fetch_object(); - if ($row->public == 0){ - $public = 1; - } else { - $public = 0; - } - $query = "UPDATE lychee_albums SET public = '$public', password = NULL WHERE id = '$albumID';"; - $result = $database->query($query); - if (!$result) return false; - if ($public==1) { - $query = "UPDATE lychee_photos SET public = 0 WHERE album = '$albumID';"; - $result = $database->query($query); - if (!$result) return false; - } - if (strlen($password)>0) return setAlbumPassword($albumID, $password); - else return true; -} -function setAlbumPassword($albumID, $password) { - global $database; - $query = "UPDATE lychee_albums SET password = '$password' WHERE id = '$albumID';"; - $result = $database->query($query); - if (!$result) return false; - return true; -} -function checkAlbumPassword($albumID, $password) { - global $database; - $query = "SELECT public, password FROM lychee_albums WHERE id = '$albumID';"; - $result = $database->query($query); - $row = $result->fetch_object(); - if ($row->password=="") return true; - else if ($row->password==$password) return true; - else return false; -} -function isAlbumPublic($albumID) { - global $database; - $query = "SELECT public, password FROM lychee_albums WHERE id = '$albumID';"; - $result = $database->query($query); - $row = $result->fetch_object(); - if ($row->public==1) return true; - else return false; -} - -// Photo Functions -function getPhoto($photoID, $albumID) { - global $database; - if (!is_numeric($photoID)) { - $query = "SELECT COUNT(*) AS quantity FROM lychee_photos WHERE import_name = '../uploads/import/$photoID';"; - $result = $database->query($query); - $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';"; - } - $result = $database->query($query); - $return = $result->fetch_array(); - - if ($albumID!='false') { - - 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"; - - } - - $return['original_album'] = $return['album']; - $return['album'] = $albumID; - - $nextPhoto = getNextPhotoID($photoID, $albumID, false); - if ($nextPhoto==$photoID) $return['nextPhoto'] = false; - else $return['nextPhoto'] = $nextPhoto; - - $previousPhoto = getPreviousPhotoID($photoID, $albumID, false); - if ($previousPhoto==$photoID) $return['previousPhoto'] = false; - else $return['previousPhoto'] = $previousPhoto; - - } - - unset($return['album_public']); - - return $return; -} -function setPhotoPublic($photoID, $url) { - global $database; - $query = "SELECT public FROM lychee_photos WHERE id = '$photoID';"; - $result = $database->query($query); - $row = $result->fetch_object(); - if ($row->public == 0){ - $public = 1; - } else { - $public = 0; - } - $query = "UPDATE lychee_photos SET public = '$public' WHERE id = '$photoID';"; - $result = $database->query($query); - if (!$result) return false; - return true; -} -function setPhotoStar($photoID) { - global $database; - $query = "SELECT star FROM lychee_photos WHERE id = '$photoID';"; - $result = $database->query($query); - $row = $result->fetch_object(); - if ($row->star == 0) { - $star = 1; - } else { - $star = 0; - } - $query = "UPDATE lychee_photos SET star = '$star' WHERE id = '$photoID';"; - $result = $database->query($query); - return true; -} -function getNextPhotoID($photoID, $albumID, $innerCall) { - global $database, $sorting; - if (!$innerCall&&$sorting=="ASC") return getPreviousPhotoID($photoID, $albumID, true); - switch($albumID) { - case 'f': $query = "SELECT id FROM lychee_photos WHERE id < '$photoID' AND star = '1' ORDER BY id DESC LIMIT 0, 1;"; - break; - case 's': $query = "SELECT id FROM lychee_photos WHERE id < '$photoID' AND public = '1' ORDER BY id DESC LIMIT 0, 1;"; - break; - default: $query = "SELECT id FROM lychee_photos WHERE id < '$photoID' AND album = '$albumID' ORDER BY id DESC LIMIT 0, 1;"; - } - $result = $database->query($query); - $return = $result->fetch_array(); - if (!$return || ($return==0)) { - switch($albumID) { - case 'f': $query = "SELECT id FROM lychee_photos WHERE star = '1' ORDER BY id DESC LIMIT 0, 1;"; - break; - case 's': $query = "SELECT id FROM lychee_photos WHERE public = '1' ORDER BY id DESC LIMIT 0, 1;"; - break; - default: $query = "SELECT id FROM lychee_photos WHERE album = '$albumID' ORDER BY id DESC LIMIT 0, 1;"; - } - $result = $database->query($query); - $return = $result->fetch_array(); - } - return $return['id']; -} -function getPreviousPhotoID($photoID, $albumID, $innerCall) { - global $database, $sorting; - if (!$innerCall&&$sorting=="ASC") return getNextPhotoID($photoID, $albumID, true); - switch($albumID) { - case 'f': $query = "SELECT id FROM lychee_photos WHERE id > '$photoID' AND star = '1' ORDER BY id LIMIT 0, 1;"; - break; - case 's': $query = "SELECT id FROM lychee_photos WHERE id > '$photoID' AND public = '1' ORDER BY id LIMIT 0, 1;"; - break; - default: $query = "SELECT id FROM lychee_photos WHERE id > '$photoID' AND album = '$albumID' ORDER BY id LIMIT 0, 1;"; - } - $result = $database->query($query); - $return = $result->fetch_array(); - if (!$return || ($return==0)) { - switch($albumID) { - case 'f': $query = "SELECT id FROM lychee_photos WHERE star = '1' ORDER BY id LIMIT 0, 1;"; - break; - case 's': $query = "SELECT id FROM lychee_photos WHERE public = '1' ORDER BY id LIMIT 0, 1;"; - break; - default: $query = "SELECT id FROM lychee_photos WHERE album = '$albumID' ORDER BY id LIMIT 0, 1;"; - } - $result = $database->query($query); - $return = $result->fetch_array(); - } - return $return['id']; -} -function setAlbum($photoID, $newAlbum) { - global $database; - $query = "UPDATE lychee_photos SET album = '$newAlbum' WHERE id = '$photoID';"; - $result = $database->query($query); - if (!$result) return false; - else return true; -} -function setPhotoTitle($photoID, $title) { - global $database; - $title = mysqli_real_escape_string($database, urldecode($title)); - if (strlen($title)>30) return false; - $query = "UPDATE lychee_photos SET title = '$title' WHERE id = '$photoID';"; - $result = $database->query($query); - if (!$result) return false; - else return true; -} -function setPhotoDescription($photoID, $description) { - global $database; - $description = mysqli_real_escape_string($database, htmlentities($description)); - if (strlen($description)>160) return false; - $query = "UPDATE lychee_photos SET description = '$description' WHERE id = '$photoID';"; - $result = $database->query($query); - if (!$result) return false; - return true; -} -function deletePhoto($photoID) { - global $database; - $query = "SELECT * FROM lychee_photos WHERE id = '$photoID';"; - $result = $database->query($query); - 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]); - $query = "DELETE FROM lychee_photos WHERE id = '$photoID';"; - $result = $database->query($query); - if (!$unlink1 || !$unlink2 || !$unlink3) return false; - if (!$result) return false; - return true; -} -function importPhoto($name, $albumID) { - $tmp_name = "../uploads/import/$name"; - $details = getimagesize($tmp_name); - $size = filesize($tmp_name); - $nameFile = array(array()); - $nameFile[0]['name'] = $name; - $nameFile[0]['type'] = $details['mime']; - $nameFile[0]['tmp_name'] = $tmp_name; - $nameFile[0]['error'] = 0; - $nameFile[0]['size'] = $size; - if (!upload($nameFile, $albumID)) return false; - else return true; -} -function importUrl($url, $albumID) { - if (@getimagesize($url)) { - $pathinfo = pathinfo($url); - $filename = $pathinfo['filename'].".".$pathinfo['extension']; - $tmp_name = "../uploads/import/$filename"; - copy($url, $tmp_name); - return importPhoto($filename, $albumID); - } else { - return false; - } -} - -// Share Functions -function facebookHeader($photoID) { - $database = dbConnect(); - if (!is_numeric($photoID)) return false; - $query = "SELECT * FROM lychee_photos WHERE id = '$photoID';"; - $result = $database->query($query); - $row = $result->fetch_object(); - - $parseUrl = parse_url("http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); - $thumb = $parseUrl['scheme']."://".$parseUrl['host'].$parseUrl['path']."/../uploads/big/".$row->thumbUrl; - - $return .= ''; - $return = ''; - $return .= ''; - $return .= ''; - - $return .= ''; - $return .= ''; - $return .= ''; - $return .= ''; - - $return .= ''; - $return .= ''; - $return .= ''; - - return $return; -} -function isPhotoPublic($photoID, $password) { - global $database; - $photoID = mysqli_real_escape_string($database, $photoID); - 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(); - 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; - } -} - -// Search Function -function search($term) { - global $database, $sorting; - $return["albums"] = ""; - $term = mysqli_real_escape_string($database, $term); - - $query = "SELECT * FROM lychee_photos WHERE title like '%$term%' OR description like '%$term%';"; - $result = $database->query($query); - while($row = $result->fetch_array()) { - $return['photos'][$row['id']] = $row; - } - - $query = "SELECT * FROM lychee_albums WHERE title like '%$term%';"; - $result = $database->query($query); - $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'] = $row->sysdate; - if ($row->password=="") $return["albums"][$row->id]['password'] = false; - else $return["albums"][$row->id]['password'] = true; - - $query2 = "SELECT thumbUrl FROM lychee_photos WHERE album = '".$row->id."' ORDER BY id $sorting LIMIT 0, 3;"; - $result2 = $database->query($query2); - $k = 0; - while($row2 = $result2->fetch_object()){ - $return['albums'][$row->id]["thumb$k"] = $row2->thumbUrl; - $k++; - } - $i++; - - } - return $return; -} - -?> diff --git a/php/modules/album.php b/php/modules/album.php new file mode 100755 index 0000000..501f3f1 --- /dev/null +++ b/php/modules/album.php @@ -0,0 +1,354 @@ +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; + +} + +function getAlbums($public) { + + global $database, $settings; + + // Smart Albums + if (!$public) $return = getSmartInfo(); + + // 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; + while($row = $result->fetch_object()) { + + // 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)); + 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; + 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; + + if ($i==0) $return["albums"] = false; + else $return["albums"] = true; + + return $return; + +} + +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; + + // 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; + + // 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; + + return $return; + +} + +function getAlbum($albumID) { + + global $database, $settings; + + // Get album information + switch($albumID) { + + case "f": $return['public'] = false; + $query = "SELECT id, title, 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']; + break; + + case 0: $return['public'] = false; + $query = "SELECT id, title, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE album = 0 " . $settings['sorting']; + + 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; + $query = "SELECT id, title, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE album = '$albumID' " . $settings['sorting']; + break; + + } + + // Get photos + $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']]['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']; + + $previousPhotoID = $row['id']; + $i++; + + } + + if ($i==0) { + + // Empty album + $return['content'] = false; + + } 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']; + + if ($lastElementId!==$firstElementId) { + $return['content'][$lastElementId]['nextPhoto'] = $firstElementId; + $return['content'][$firstElementId]['previousPhoto'] = $lastElementId; + } + + } + + $return['id'] = $albumID; + $return['num'] = $i; + + return $return; + +} + +function setAlbumTitle($albumID, $title) { + + global $database; + + if (strlen($title)<1||strlen($title)>30) return false; + $result = $database->query("UPDATE lychee_albums SET title = '$title' WHERE id = '$albumID';"); + if (!$result) return false; + + return true; + +} + +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; + +} + +function deleteAlbum($albumID, $delAll) { + + global $database; + + if ($delAll=="true") { + $result = $database->query("SELECT id FROM lychee_photos WHERE album = '$albumID';"); + $error = false; + while($row = $result->fetch_object()) { + if (!deletePhoto($row->id)) $error = true; + } + } else { + $result = $database->query("UPDATE lychee_photos SET album = '0' WHERE album = '$albumID';"); + if (!$result) return false; + } + + if ($albumID!=0) { + $result = $database->query("DELETE FROM lychee_albums WHERE id = '$albumID';"); + if (!$result) return false; + } + + if ($error) return false; + return true; + +} + +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; + +} + +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("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; + } + + if (strlen($password)>0) return setAlbumPassword($albumID, $password); + else return true; + +} + +function setAlbumPassword($albumID, $password) { + + global $database; + + $result = $database->query("UPDATE lychee_albums SET password = '$password' WHERE id = '$albumID';"); + + if (!$result) return false; + return true; + +} + +function checkAlbumPassword($albumID, $password) { + + global $database; + + $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; + +} + +function isAlbumPublic($albumID) { + + global $database; + + $result = $database->query("SELECT public FROM lychee_albums WHERE id = '$albumID';"); + $row = $result->fetch_object(); + + if ($row->public==1) return true; + else return false; + +} + +?> \ No newline at end of file diff --git a/php/modules/db.php b/php/modules/db.php new file mode 100755 index 0000000..792e2d6 --- /dev/null +++ b/php/modules/db.php @@ -0,0 +1,183 @@ +select_db($dbName)) + if (!createDatabase($dbName, $database)) exit('Error: Could not create database!'); + if (!$database->query("SELECT * FROM lychee_photos, lychee_albums, lychee_settings;")) + if (!createTables($database)) exit('Error: Could not create tables!'); + + return $database; + +} + +function dbClose() { + + global $database; + + if (!$database->close()) exit("Error: Closing the connection failed!"); + + return true; + +} + +function createConfig($dbHost = 'localhost', $dbUser, $dbPassword, $dbName = 'lychee') { + + $dbPassword = urldecode($dbPassword); + $database = new mysqli($dbHost, $dbUser, $dbPassword); + + if (mysqli_connect_errno()||$dbUser=="") return "Warning: Connection failed!"; + else { + +$config = ""; + + if (file_put_contents("config.php", $config)===false) return "Warning: Could not create file!"; + else { + + $_SESSION['login'] = true; + return true; + + } + + } + +} + +function createDatabase($dbName, $database) { + + $result = $database->query("CREATE DATABASE IF NOT EXISTS $dbName;"); + $database->select_db($dbName); + + if (!$database->select_db($dbName)||!$result) return false; + return true; + +} + +function createTables($database) { + + if (!$database->query("SELECT * FROM lychee_settings;")) { + + $query = " + + CREATE TABLE `lychee_settings` ( + `key` varchar(50) NOT NULL DEFAULT '', + `value` varchar(50) DEFAULT '' + ) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + "; + + if (!$database->query($query)) return false; + + $query = " + + INSERT INTO `lychee_settings` (`key`, `value`) + VALUES + ('username',''), + ('password',''), + ('thumbQuality','90'), + ('checkForUpdates','1'), + ('sorting','ORDER BY id DESC'); + + "; + + if (!$database->query($query)) return false; + + } + + if (!$database->query("SELECT * FROM lychee_albums;")) { + + $query = " + + CREATE TABLE `lychee_albums` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `title` varchar(50) NOT NULL, + `description` varchar(1000) DEFAULT '', + `sysdate` varchar(10) NOT NULL, + `public` tinyint(1) DEFAULT '0', + `password` varchar(100) DEFAULT '', + PRIMARY KEY (`id`) + ) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + "; + + if (!$database->query($query)) return false; + + } + + if (!$database->query("SELECT * FROM lychee_photos;")) { + + $query = " + + CREATE TABLE `lychee_photos` ( + `id` bigint(14) NOT NULL, + `title` varchar(50) NOT NULL, + `description` varchar(1000) NOT NULL DEFAULT '', + `url` varchar(100) NOT NULL, + `public` tinyint(1) NOT NULL, + `type` varchar(10) NOT NULL, + `width` int(11) NOT NULL, + `height` int(11) NOT NULL, + `size` varchar(20) NOT NULL, + `sysdate` varchar(10) NOT NULL, + `systime` varchar(8) NOT NULL, + `iso` varchar(15) NOT NULL, + `aperture` varchar(20) NOT NULL, + `make` varchar(20) NOT NULL, + `model` varchar(50) NOT NULL, + `shutter` varchar(30) NOT NULL, + `focal` varchar(20) NOT NULL, + `takedate` varchar(20) NOT NULL, + `taketime` varchar(8) NOT NULL, + `star` tinyint(1) NOT NULL, + `thumbUrl` varchar(50) NOT NULL, + `album` varchar(30) NOT NULL DEFAULT '0', + `import_name` varchar(100) DEFAULT '', + PRIMARY KEY (`id`) + ) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + "; + + if (!$database->query($query)) return false; + + } + + return true; + +} + +?> \ No newline at end of file diff --git a/php/modules/misc.php b/php/modules/misc.php new file mode 100755 index 0000000..62852ba --- /dev/null +++ b/php/modules/misc.php @@ -0,0 +1,95 @@ +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; + +} + +function search($term) { + + global $database, $settings; + + $return["albums"] = ""; + + $result = $database->query("SELECT * FROM lychee_photos WHERE title like '%$term%' OR description 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%';"); + $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; + + $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; + +} + +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 `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`"); + $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 new file mode 100755 index 0000000..9a21774 --- /dev/null +++ b/php/modules/photo.php @@ -0,0 +1,167 @@ +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';"; + } + + $result = $database->query($query); + $return = $result->fetch_array(); + + if ($albumID!='false') { + + 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"; + + } + + $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; + +} + +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("UPDATE lychee_photos SET public = '$public' WHERE id = '$photoID';"); + + if (!$result) return false; + return true; + +} + +function setPhotoStar($photoID) { + + 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; + } + $result = $database->query("UPDATE lychee_photos SET star = '$star' WHERE id = '$photoID';"); + return true; + +} + +function setAlbum($photoID, $newAlbum) { + + global $database; + + $result = $database->query("UPDATE lychee_photos SET album = '$newAlbum' WHERE id = '$photoID';"); + + if (!$result) return false; + else return true; + +} + +function setPhotoTitle($photoID, $title) { + + global $database; + + if (strlen($title)>30) return false; + $result = $database->query("UPDATE lychee_photos SET title = '$title' WHERE id = '$photoID';"); + + if (!$result) return false; + else return true; + +} + +function setPhotoDescription($photoID, $description) { + + global $database; + + $description = htmlentities($description); + if (strlen($description)>800) return false; + $result = $database->query("UPDATE lychee_photos SET description = '$description' WHERE id = '$photoID';"); + + if (!$result) return false; + return true; + +} + +function deletePhoto($photoID) { + + 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; + +} + +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(); + 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; + } + +} + +?> \ No newline at end of file diff --git a/php/modules/session.php b/php/modules/session.php new file mode 100755 index 0000000..ae42083 --- /dev/null +++ b/php/modules/session.php @@ -0,0 +1,64 @@ + \ No newline at end of file diff --git a/php/modules/settings.php b/php/modules/settings.php new file mode 100755 index 0000000..1c9246a --- /dev/null +++ b/php/modules/settings.php @@ -0,0 +1,137 @@ +query('SELECT * FROM lychee_settings;'); + + while($row = $result->fetch_object()) { + $return[$row->key] = $row->value; + } + + return $return; + +} + +function setLogin($oldPassword = '', $username, $password) { + + global $settings; + + if ($oldPassword==$settings['password']) { + + if (!setUsername($username)) exit('Error: Updating username failed!'); + if (!setPassword($password)) exit('Error: Updating password failed!'); + + return true; + + } + + exit('Error: Current password entered incorrectly!'); + +} + +function setUsername($username) { + + global $database; + + $username = htmlentities($username); + if (strlen($username)>50) return false; + + $result = $database->query("UPDATE lychee_settings SET value = '$username' WHERE `key` = 'username';"); + + if (!$result) return false; + return true; + +} + +function setPassword($password) { + + global $database; + + if (strlen($password)<1||strlen($password)>50) return false; + + $result = $database->query("UPDATE lychee_settings SET value = '$password' WHERE `key` = 'password';"); + + if (!$result) return false; + return true; + +} + +/*function setCheckForUpdates() { + + global $database; + + $result = $database->query("SELECT value FROM lychee_settings WHERE `key` = 'checkForUpdates';"); + $row = $result->fetch_object(); + + if ($row->value==0) $checkForUpdates = 1; + else $checkForUpdates = 0; + + $result = $database->query("UPDATE lychee_settings SET value = '$checkForUpdates' WHERE `key` = 'checkForUpdates';"); + + if (!$result) return false; + return true; + +}*/ + +function setSorting($type, $order) { + + global $database; + + $sorting = 'ORDER BY '; + + switch ($type) { + + case 'id': $sorting .= 'id'; + break; + + case 'title': $sorting .= 'title'; + break; + + case 'description': $sorting .= 'description'; + break; + + case 'public': $sorting .= 'public'; + break; + + case 'type': $sorting .= 'type'; + break; + + case 'star': $sorting .= 'star'; + break; + + default: exit('Error: Unknown type for sorting!'); + + } + + $sorting .= ' '; + + switch ($order) { + + case 'ASC': $sorting .= 'ASC'; + break; + + case 'DESC': $sorting .= 'DESC'; + break; + + default: exit('Error: Unknown order for sorting!'); + + } + + $result = $database->query("UPDATE lychee_settings SET value = '$sorting' WHERE `key` = 'sorting';"); + + if (!$result) return false; + return true; + +} + +?> \ No newline at end of file diff --git a/php/modules/upload.php b/php/modules/upload.php new file mode 100755 index 0000000..699fd05 --- /dev/null +++ b/php/modules/upload.php @@ -0,0 +1,378 @@ +query($query); + + if (!$result) return false; + + } + + return true; + +} + +function getInfo($filename) { + + global $database; + + $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)); + + // Size + $size = filesize($url)/1024; + if ($size>=1024) $return['size'] = round($size/1024, 1) . ' MB'; + else $return['size'] = round($size, 1) . ' KB'; + + // IPTC Metadata Fallback + $return['title'] = ''; + $return['description'] = ''; + + // IPTC Metadata + $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 + $return['orientation'] = ''; + $return['iso'] = ''; + $return['aperture'] = ''; + $return['make'] = ''; + $return['model'] = ''; + $return['shutter'] = ''; + $return['focal'] = ''; + $return['takeDate'] = ''; + $return['takeTime'] = ''; + + // EXIF Metadata + if ($info['mime']=='image/jpeg'&&function_exists('exif_read_data')&&@exif_read_data($url, 'EXIF', 0)) { + + $exif = exif_read_data($url, 'EXIF', 0); + + $temp = $exif['Orientation']; + if (isset($temp)) $return['orientation'] = $temp; + + $temp = $exif['ISOSpeedRatings']; + if (isset($temp)) $return['iso'] = $temp; + + $temp = $exif['COMPUTED']['ApertureFNumber']; + if (isset($temp)) $return['aperture'] = $temp; + + $temp = $exif['Make']; + if (isset($temp)) $return['make'] = $exif['Make']; + + $temp = $exif['Model']; + if (isset($temp)) $return['model'] = $temp; + + $temp = $exif['ExposureTime']; + if (isset($temp)) $return['shutter'] = $exif['ExposureTime'] . ' Sec.'; + + $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]; + } + + } + + // Security + foreach(array_keys($return) as $key) $return[$key] = mysqli_real_escape_string($database, $return[$key]); + + return $return; + +} + +function createThumb($filename, $width = 200, $height = 200) { + + global $settings; + + $url = "../uploads/big/$filename"; + $info = getimagesize($url); + + $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; + } + + // 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; + default: 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); + + imagejpeg($thumb,$newUrl,$settings['thumbQuality']); + imagejpeg($thumb2x,$newUrl2x,$settings['thumbQuality']); + + return true; + +} + +function importPhoto($name, $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; + + if (upload($nameFile, $albumID)) return true; + + return false; + +} + +function importUrl($url, $albumID = 0) { + + if (strpos($url, ',')!==false) { + + // Multiple photos + + $url = explode(',', $url); + + foreach ($url as &$key) { + + $key = str_replace(' ', '%20', $key); + + if (@getimagesize($key)) { + + $pathinfo = pathinfo($key); + $filename = $pathinfo['filename'].".".$pathinfo['extension']; + $tmp_name = "../uploads/import/$filename"; + copy($key, $tmp_name); + + } + + } + + return importServer($albumID); + + } else { + + // One photo + + $url = str_replace(' ', '%20', $url); + + if (@getimagesize($url)) { + + $pathinfo = pathinfo($url); + $filename = $pathinfo['filename'].".".$pathinfo['extension']; + $tmp_name = "../uploads/import/$filename"; + copy($url, $tmp_name); + return importPhoto($filename, $albumID); + + } + + } + + return false; + +} + +function importServer($albumID = 0) { + + global $database; + + $i = 0; + $files = glob('../uploads/import/*'); + + foreach ($files as $file) { + + if (@getimagesize($file)) { + if (!importPhoto(basename($file), $albumID)) return false; + $i++; + } + + } + + if ($i===0) return "Warning: Folder empty!"; + return true; + +} + +?> \ No newline at end of file diff --git a/php/update.php b/php/update.php deleted file mode 100644 index e4fdadd..0000000 --- a/php/update.php +++ /dev/null @@ -1,17 +0,0 @@ -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 NULL"); - $database->query("UPDATE `lychee_photos` SET url = replace(url, 'uploads/big/', ''), thumbUrl = replace(thumbUrl, 'uploads/thumb/', '')"); - echo "\nUpdate complete!"; -} else { - echo "\nCould not Update!"; -} - -?> \ No newline at end of file diff --git a/plugins/check.php b/plugins/check.php new file mode 100644 index 0000000..eb51a5f --- /dev/null +++ b/plugins/check.php @@ -0,0 +1,65 @@ + \ No newline at end of file diff --git a/readme.md b/readme.md index ef6891f..7702ed8 100644 --- a/readme.md +++ b/readme.md @@ -2,71 +2,66 @@ #### A great looking and easy-to-use Photo-Management-System. -![Lychee](http://l.electerious.com/uploads/big/13582806160093.png) -![Lychee](http://l.electerious.com/uploads/big/13582805615704.png) +![Lychee](http://l.electerious.com/uploads/big/136b4779d133a94666d5f0d151b8ea2f.png) +![Lychee](http://l.electerious.com/uploads/big/580f1300f884c330fa34b652decb0571.png) -Lychee is a free, easy to use and great looking photo-management-system you can run on your server to manage and share photos. Just download the source and follow the instructions to install Lychee wherever you want. +Lychee is a free photo-management tool, which runs on your server or web-space. Installing is a matter of seconds. Upload, manage and share photos like from a native application. Lychee comes with everything you need and all your photos are stored securely. ## Installation -To run Lychee, everything you need is a web-server with PHP 5.3 or later and a MySQL-Database. Follow the instructions to install Lychee on your server. [Installation »](https://github.com/electerious/Lychee/wiki/Installation) +To run Lychee, everything you need is a web-server with PHP 5.3 or later and a MySQL-Database. Follow the instructions to install Lychee on your server. [Installation »](docs/md/Installation.md) -## Settings +## How to use -Settings are located inside the `php/config.php`. All settings are optional and doesn't need to be changed. [Settings »](https://github.com/electerious/Lychee/wiki/Settings) +You can use Lychee right after the installation. Here are some advanced features to get the most out of it. -## How to use +### Settings -After the configuration, navigate your browser to the place where Lychee is located. Everything should work now. +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) -#### FTP Upload +### Update -You can upload photos directly with every FTP client into Lychee. This feature helps you to share single images quickly with others. [FTP Upload »](https://github.com/electerious/Lychee/wiki/FTP-Upload) +1. Replace all files, excluding `uploads/` +2. Open Lychee and enter your database details -#### Keyboard Shortcuts +### FTP Upload -This shortcuts will help you to use Lychee even faster. [Keyboard Shortcuts »](https://github.com/electerious/Lychee/wiki/Keyboard-Shortcuts) +You can import photos from your server or upload photos directly with every FTP client into Lychee. [FTP Upload »](docs/md/FTP Upload.md) -#### Twitter Cards +### Keyboard Shortcuts -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). +These shortcuts will help you to use Lychee even faster. [Keyboard Shortcuts »](docs/md/Keyboard Shortcuts.md) -## Browser Support +### Twitter Cards -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. For the best experience we are recommending to use Google Chrome or Apple Safari. +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). -## Update +## Troubleshooting -####From version 1.0/1.1/1.2 to 1.3: -1. Replace all files, excluding `uploads/` -2. Open `php/config.php` and reconfigure your installation -3. Open `php/update.php` in your browser +Take a look at the [FAQ](docs/md/faq.md) if you have problems. ## Extensions | Name | Description | Link | |:-----------|:------------|:------------| -| lycheesync | Command line interface tool to sync lychee with any directory containing photos | https://github.com/GustavePate/lycheesync | - -## Troubleshooting - -If Lychee is not working properly, try to open `php/check.php`. This file will take a look at your configuration and displays all errors it can find. Everything should work if you can see the message "Lychee is ready!". - -If you experience problems uploading large amounts of photos, you might want to change the PHP parameters in `.htaccess` (if you are using the PHP Apache module) or in `.user.ini` (if you are using PHP >= 5.3 with CGI or FastCGI). +| lycheesync | Sync Lychee with any directory containing photos | https://github.com/GustavePate/lycheesync | -## About +## Developer +- [electerious](https://github.com/electerious) / [Tobias Reich](http://electerious.com) -Lychee is made by [Tobias Reich](http://electerious.com) (HTML, CSS, JS, Design, Website Design and Development) with the help of [Philipp Maurer](http://phinal.net) (PHP, MySQL). +## Contributors +- [phinal](https://github.com/phinal) / [Philipp Maurer](http://phinal.net) +- [cdauth](https://github.com/cdauth) ##License (MIT License) -Copyright (C) 2013 [Tobias Reich](http://electerious.com) -Copyright (C) 2013 [Philipp Maurer](http://phinal.net) +Copyright (C) 2014 [Tobias Reich](http://electerious.com) +Copyright (C) 2013 [Philipp Maurer](http://phinal.net) 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: 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.SE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 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. \ No newline at end of file diff --git a/uploads/big/index.html b/uploads/big/index.html old mode 100644 new mode 100755 diff --git a/uploads/import/index.html b/uploads/import/index.html old mode 100644 new mode 100755 diff --git a/uploads/thumb/index.html b/uploads/thumb/index.html old mode 100644 new mode 100755 diff --git a/view.php b/view.php old mode 100755 new mode 100644 index 7d121fe..1a08813 --- a/view.php +++ b/view.php @@ -9,10 +9,10 @@ - - - - + + + + @@ -25,19 +25,22 @@ define("LYCHEE", true); require("php/config.php"); - require("php/functions.php"); + require("php/modules/db.php"); + require("php/modules/misc.php"); + + $database = dbConnect(); - echo facebookHeader($_GET['p']); + echo openGraphHeader($_GET['p']); } ?> - + -
+
@@ -48,16 +51,16 @@
-
+
- - - + + + -> \ No newline at end of file + \ No newline at end of file