Added basic subalbum support.

That is, albums can now contain other albums, which are shown at
the top of the album view. This required some changes to album.js
and the contextMenu.js, because this view contains now both
photos and albums.

The contextMenu on this view has been kept simple by requiring
the user to select either only albums or only photos, but not
a mixture of both.

This feature required a database change, so that the version
has been updated to 3.1.3.

At the moment, album and photo operations (make public, download,
delete, merge) are still "flat", i.e. don't respect the album
hierarchy.
pull/581/head
Nils Asmussen 8 years ago
parent 6d4df5f6b7
commit ef9040870a

@ -72,8 +72,10 @@ final class Admin extends Access {
private static function getAlbumsAction() { private static function getAlbumsAction() {
Validator::required(isset($_POST['parent']), __METHOD__);
$albums = new Albums(); $albums = new Albums();
Response::json($albums->get(false)); Response::json($albums->get(false, $_POST['parent']));
} }
@ -90,10 +92,10 @@ final class Admin extends Access {
private static function addAlbumAction() { private static function addAlbumAction() {
Validator::required(isset($_POST['title']), __METHOD__); Validator::required(isset($_POST['title'], $_POST['parent']), __METHOD__);
$album = new Album(null); $album = new Album(null);
Response::json($album->add($_POST['title']), JSON_NUMERIC_CHECK); Response::json($album->add($_POST['title'], $_POST['parent']), JSON_NUMERIC_CHECK);
} }

@ -44,8 +44,10 @@ final class Guest extends Access {
private static function getAlbumsAction() { private static function getAlbumsAction() {
Validator::required(isset($_POST['parent']), __METHOD__);
$albums = new Albums(); $albums = new Albums();
Response::json($albums->get(true)); Response::json($albums->get(true, $_POST['parent']));
} }

@ -23,7 +23,7 @@ final class Album {
/** /**
* @return string|false ID of the created album. * @return string|false ID of the created album.
*/ */
public function add($title = 'Untitled') { public function add($title = 'Untitled', $parent = 0) {
// Call plugins // Call plugins
Plugins::get()->activate(__METHOD__, 0, func_get_args()); Plugins::get()->activate(__METHOD__, 0, func_get_args());
@ -35,7 +35,7 @@ final class Album {
$visible = 1; $visible = 1;
// Database // Database
$query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, sysstamp, public, visible) VALUES ('?', '?', '?', '?', '?')", array(LYCHEE_TABLE_ALBUMS, $id, $title, $sysstamp, $public, $visible)); $query = Database::prepare(Database::get(), "INSERT INTO ? (id, title, sysstamp, public, visible, parent) VALUES ('?', '?', '?', '?', '?', '?')", array(LYCHEE_TABLE_ALBUMS, $id, $title, $sysstamp, $public, $visible, $parent));
$result = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $result = Database::execute(Database::get(), $query, __METHOD__, __LINE__);
// Call plugins // Call plugins
@ -79,6 +79,8 @@ final class Album {
// Parse thumbs or set default value // Parse thumbs or set default value
$album['thumbs'] = (isset($data['thumbs']) ? explode(',', $data['thumbs']) : array()); $album['thumbs'] = (isset($data['thumbs']) ? explode(',', $data['thumbs']) : array());
$album['parent'] = $data['parent'];
return $album; return $album;
} }

@ -16,7 +16,7 @@ final class Albums {
/** /**
* @return array|false Returns an array of albums or false on failure. * @return array|false Returns an array of albums or false on failure.
*/ */
public function get($public = true) { public function get($public = true, $parent = 0) {
// Call plugins // Call plugins
Plugins::get()->activate(__METHOD__, 0, func_get_args()); Plugins::get()->activate(__METHOD__, 0, func_get_args());
@ -32,8 +32,8 @@ final class Albums {
if ($public===false) $return['smartalbums'] = $this->getSmartAlbums(); if ($public===false) $return['smartalbums'] = $this->getSmartAlbums();
// Albums query // Albums query
if ($public===false) $query = Database::prepare(Database::get(), 'SELECT id, title, public, sysstamp, password FROM ? ' . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS)); if ($public===false) $query = Database::prepare(Database::get(), "SELECT id, title, public, sysstamp, password, parent FROM ? " . ($parent != -1 ? "WHERE parent = '?' " : "") . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS, $parent));
else $query = Database::prepare(Database::get(), 'SELECT id, title, public, sysstamp, password FROM ? WHERE public = 1 AND visible <> 0 ' . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS)); else $query = Database::prepare(Database::get(), "SELECT id, title, public, sysstamp, password, parent FROM ? " . ($parent != -1 ? "WHERE parent = '?' " : "") . " AND public = 1 AND visible <> 0 " . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS, $parent));
// Execute query // Execute query
$albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__);

@ -15,7 +15,8 @@ final class Database {
'030001', // 3.0.1 '030001', // 3.0.1
'030003', // 3.0.3 '030003', // 3.0.3
'030100', // 3.1.0 '030100', // 3.1.0
'030102' // 3.1.2 '030102', // 3.1.2
'030103' // 3.1.3
); );
/** /**

@ -0,0 +1,24 @@
<?php
/**
* Update to version 3.1.3
*/
use Lychee\Modules\Database;
use Lychee\Modules\Response;
// Add parent field to albums
$query = Database::prepare($connection, "SELECT `parent` FROM `?` LIMIT 1", array(LYCHEE_TABLE_ALBUMS));
if (!Database::execute($connection, $query, "update_030103", __LINE__)) {
$query = Database::prepare($connection, "ALTER TABLE `?` ADD `parent` BIGINT(14) NOT NULL DEFAULT 0", array(LYCHEE_TABLE_ALBUMS));
$result = Database::execute($connection, $query, "update_030103", __LINE__);
if (!$result) {
Log::error($database, 'update_030103', __LINE__, 'Could not update database (' . $database->error . ')');
return false;
}
}
// Set version
if (Database::setVersion($connection, '030103')===false) Response::error('Could not update version of database!');
?>

@ -1,6 +1,6 @@
{ {
"name": "Lychee", "name": "Lychee",
"version": "3.1.2", "version": "3.1.3",
"description": "Self-hosted photo-management done right.", "description": "Self-hosted photo-management done right.",
"authors": "Tobias Reich <tobias@electerious.com>", "authors": "Tobias Reich <tobias@electerious.com>",
"license": "MIT", "license": "MIT",

@ -5,7 +5,8 @@
album = { album = {
json: null json: null,
subjson: null
} }
@ -24,18 +25,32 @@ album.getID = function() {
return $.isNumeric(id) return $.isNumeric(id)
} }
if (photo.json) id = photo.json.album
else if (album.json) id = album.json.id
// Search // Search
if (isID(id)===false) id = $('.album:hover, .album.active').attr('data-id') if (isID(id)===false) id = $('.album:hover, .album.active').attr('data-id')
if (isID(id)===false) id = $('.photo:hover, .photo.active').attr('data-album-id') if (isID(id)===false) id = $('.photo:hover, .photo.active').attr('data-album-id')
if (isID(id)===false) {
if (photo.json) id = photo.json.album
else if (album.json) id = album.json.id
}
if (isID(id)===true) return id if (isID(id)===true) return id
else return false else return false
} }
album.getParent = function () {
let id = album.json.id;
if (album.isSmartID(id) || album.json.parent==0) {
return ''
} else {
return album.json.parent
}
}
album.load = function(albumID, refresh = false) { album.load = function(albumID, refresh = false) {
password.get(albumID, function() { password.get(albumID, function() {
@ -96,6 +111,28 @@ album.load = function(albumID, refresh = false) {
}) })
if (!album.isSmartID(albumID)) {
params = {
parent: albumID
}
api.post('Albums::get', params, function(data) {
let waitTime = 0
album.subjson = data
// Calculate delay
let durationTime = (new Date().getTime() - startTime)
if (durationTime>300) waitTime = 0
else waitTime = 300 - durationTime
setTimeout(() => {
view.album.init()
}, waitTime)
})
}
}) })
} }
@ -106,18 +143,35 @@ album.parse = function() {
} }
album.add = function() { function buildAlbumOptions(albums, select, parent = 0, layer = 0) {
var cmbxOptions = ''
for (i in albums) {
if (albums[i].parent == parent) {
let title = (layer > 0 ? "&nbsp;&nbsp;".repeat(layer - 1) + "└ " : "") + albums[i].title
cmbxOptions += `<option `;
if (select == albums[i].id)
cmbxOptions += `selected="selected" `
cmbxOptions += `value='` + albums[i].id + `'>` + title + `</option>`
cmbxOptions += buildAlbumOptions(albums, select, albums[i].id, layer + 1)
}
}
return cmbxOptions
}
album.add = function(albumID = 0) {
const action = function(data) { const action = function(data) {
let title = data.title let title = data.title
let parent = data.parent
const isNumber = (n) => (!isNaN(parseFloat(n)) && isFinite(n)) const isNumber = (n) => (!isNaN(parseFloat(n)) && isFinite(n))
basicModal.close() basicModal.close()
let params = { let params = {
title title,
parent
} }
api.post('Album::add', params, function(data) { api.post('Album::add', params, function(data) {
@ -133,18 +187,28 @@ album.add = function() {
} }
basicModal.show({ api.post('Albums::get', {
body: `<p>Enter a title for the new album: <input class='text' name='title' type='text' maxlength='50' placeholder='Title' value='Untitled'></p>`, parent: -1
buttons: { }, function (data) {
action: { var cmbxOptions = `<select name='parent'>`
title: 'Create Album', cmbxOptions += `<option value='0'>- None -</option>`
fn: action cmbxOptions += buildAlbumOptions(data.albums, albumID)
}, cmbxOptions += '</select>'
cancel: {
title: 'Cancel', basicModal.show({
fn: basicModal.close body: `<p>Enter a title for the new album: <input class='text' name='title' type='text' maxlength='50' placeholder='Title' value='Untitled'></p>`
+ `<p>Select the parent album:<br/>` + cmbxOptions + `</p>`,
buttons: {
action: {
title: 'Create Album',
fn: action
},
cancel: {
title: 'Cancel',
fn: basicModal.close
}
} }
} })
}) })
} }
@ -204,8 +268,8 @@ album.delete = function(albumIDs) {
cancel.title = 'Keep Album' cancel.title = 'Keep Album'
// Get title // Get title
if (album.json) albumTitle = album.json.title if (album.json && album.json.id == albumIDs[0]) albumTitle = album.json.title
else if (albums.json) albumTitle = albums.getByID(albumIDs).title else if (albums.json || album.subjson) albumTitle = albums.getByID(albumIDs).title
// Fallback for album without a title // Fallback for album without a title
if (albumTitle==='') albumTitle = 'Untitled' if (albumTitle==='') albumTitle = 'Untitled'
@ -249,8 +313,8 @@ album.setTitle = function(albumIDs) {
if (albumIDs.length===1) { if (albumIDs.length===1) {
// Get old title if only one album is selected // Get old title if only one album is selected
if (album.json) oldTitle = album.json.title if (album.json && album.json.id == albumIDs[0]) oldTitle = album.json.title
else if (albums.json) oldTitle = albums.getByID(albumIDs).title else if (albums.json || album.subjson) oldTitle = albums.getByID(albumIDs).title
} }
@ -264,10 +328,17 @@ album.setTitle = function(albumIDs) {
// Rename only one album // Rename only one album
album.json.title = newTitle if (album.json.id == albumIDs[0]) {
view.album.title() album.json.title = newTitle
view.album.title()
}
if (albums.json) albums.getByID(albumIDs[0]).title = newTitle if (albums.json || album.subjson) {
albumIDs.forEach(function(id) {
albums.getByID(id).title = newTitle
view.album.content.title(id)
})
}
} else if (visible.albums()) { } else if (visible.albums()) {
@ -545,7 +616,7 @@ album.getArchive = function(albumID) {
} }
album.merge = function(albumIDs) { album.merge = function(albumIDs, titles = []) {
let title = '' let title = ''
let sTitle = '' let sTitle = ''
@ -555,7 +626,8 @@ album.merge = function(albumIDs) {
if (albumIDs instanceof Array===false) albumIDs = [ albumIDs ] if (albumIDs instanceof Array===false) albumIDs = [ albumIDs ]
// Get title of first album // Get title of first album
if (albums.json) title = albums.getByID(albumIDs[0]).title if (titles.length > 0) title = titles[0]
else if (albums.json || album.subjson) title = albums.getByID(albumIDs[0]).title
// Fallback for first album without a title // Fallback for first album without a title
if (title==='') title = 'Untitled' if (title==='') title = 'Untitled'
@ -563,7 +635,8 @@ album.merge = function(albumIDs) {
if (albumIDs.length===2) { if (albumIDs.length===2) {
// Get title of second album // Get title of second album
if (albums.json) sTitle = albums.getByID(albumIDs[1]).title if (titles.length > 1) sTitle = titles[1]
else if (albums.json || album.subjson) sTitle = albums.getByID(albumIDs[1]).title
// Fallback for second album without a title // Fallback for second album without a title
if (sTitle==='') sTitle = 'Untitled' if (sTitle==='') sTitle = 'Untitled'

@ -17,7 +17,11 @@ albums.load = function() {
if (albums.json===null) { if (albums.json===null) {
api.post('Albums::get', {}, function(data) { params = {
parent: 0
}
api.post('Albums::get', params, function(data) {
let waitTime = 0 let waitTime = 0
@ -109,18 +113,21 @@ albums.getByID = function(albumID) {
// Function returns the JSON of an album // Function returns the JSON of an album
if (albumID==null) return undefined if (albumID==null) return undefined
if (!albums.json) return undefined if (albumID instanceof Array)
if (!albums.json.albums) return undefined albumID = albumID[0]
let json = undefined let json = undefined
$.each(albums.json.albums, function(i) { let func = function() {
if (this.id==albumID) json = this
let elem = albums.json.albums[i] }
if (elem.id==albumID) json = elem
}) if (albums.json && albums.json.albums) {
$.each(albums.json.albums, func)
}
else if (album.subjson && album.subjson.albums) {
$.each(album.subjson.albums, func)
}
return json return json

@ -3,9 +3,47 @@
* @copyright 2015 by Tobias Reich * @copyright 2015 by Tobias Reich
*/ */
function buildAlbumList(albums, albumID, action, parent = 0, layer = 0) {
let items = []
for (i in albums) {
if ((layer == 0 && !albums[i].parent) || albums[i].parent == parent) {
let album = albums[i]
let thumb = 'src/images/no_cover.svg'
if (album.thumbs && album.thumbs[0])
thumb = album.thumbs[0]
else if(album.thumbUrl)
thumb = album.thumbUrl
if (album.title==='') album.title = 'Untitled'
let prefix = layer > 0 ? "&nbsp;&nbsp;".repeat(layer - 1) + "└ " : ""
let html = prefix + lychee.html`<img class='cover' width='16' height='16' src='$${ thumb }'><div class='title'>$${ album.title }</div>`
if (album.id!=albumID) {
items.push({
title: html,
fn: () => action(album)
})
}
else {
html = "<div class='disabled'>" + html + "</div>"
items.push({
title: html,
fn: () => {}
})
}
items = items.concat(buildAlbumList(albums, albumID, action, album.id, layer + 1))
}
}
return items
}
contextMenu = {} contextMenu = {}
contextMenu.add = function(e) { contextMenu.add = function(albumID, e) {
let items = [ let items = [
{ title: build.iconic('image') + 'Upload Photo', fn: () => $('#upload_files').click() }, { title: build.iconic('image') + 'Upload Photo', fn: () => $('#upload_files').click() },
@ -14,7 +52,7 @@ contextMenu.add = function(e) {
{ title: build.iconic('dropbox', 'ionicons') + 'Import from Dropbox', fn: upload.start.dropbox }, { title: build.iconic('dropbox', 'ionicons') + 'Import from Dropbox', fn: upload.start.dropbox },
{ title: build.iconic('terminal') + 'Import from Server', fn: upload.start.server }, { title: build.iconic('terminal') + 'Import from Server', fn: upload.start.server },
{ }, { },
{ title: build.iconic('folder') + 'New Album', fn: album.add } { title: build.iconic('folder') + 'New Album', fn: () => album.add(albumID) }
] ]
basicContext.show(items, e.originalEvent) basicContext.show(items, e.originalEvent)
@ -90,26 +128,13 @@ contextMenu.albumMulti = function(albumIDs, e) {
contextMenu.albumTitle = function(albumID, e) { contextMenu.albumTitle = function(albumID, e) {
api.post('Albums::get', {}, function(data) { api.post('Albums::get', { parent: -1 }, function(data) {
let items = [] let items = []
if (data.albums && data.num>1) { if (data.albums && data.num>1) {
// Generate list of albums items = buildAlbumList(data.albums, albumID, (a) => lychee.goto(a.id))
$.each(data.albums, function() {
if (!this.thumbs[0]) this.thumbs[0] = 'src/images/no_cover.svg'
if (this.title==='') this.title = 'Untitled'
let html = lychee.html`<img class='cover' width='16' height='16' src='$${ this.thumbs[0] }'><div class='title'>$${ this.title }</div>`
if (this.id!=albumID) items.push({
title: html,
fn: () => lychee.goto(this.id)
})
})
items.unshift({ }) items.unshift({ })
@ -125,25 +150,15 @@ contextMenu.albumTitle = function(albumID, e) {
contextMenu.mergeAlbum = function(albumID, e) { contextMenu.mergeAlbum = function(albumID, e) {
api.post('Albums::get', {}, function(data) { api.post('Albums::get', { parent: -1 }, function(data) {
let items = [] let items = []
if (data.albums && data.num>1) { if (data.albums && data.num>1) {
$.each(data.albums, function() { let title = albums.getByID(albumID).title
if (!this.thumbs[0]) this.thumbs[0] = 'src/images/no_cover.svg' items = buildAlbumList(data.albums, albumID, (a) => album.merge([ albumID, a.id ], [title, a.title]))
if (this.title==='') this.title = 'Untitled'
let html = lychee.html`<img class='cover' width='16' height='16' src='$${ this.thumbs[0] }'><div class='title'>$${ this.title }</div>`
if (this.id!=albumID) items.push({
title: html,
fn: () => album.merge([ albumID, this.id ])
})
})
} }
@ -177,14 +192,41 @@ contextMenu.photo = function(photoID, e) {
} }
function countSubAlbums(photoIDs) {
let count = 0
for (i in photoIDs) {
for (j in album.subjson.albums) {
if (album.subjson.albums[j].id == photoIDs[i]) {
count++
break
}
}
}
return count
}
contextMenu.photoMulti = function(photoIDs, e) { contextMenu.photoMulti = function(photoIDs, e) {
let subcount = countSubAlbums(photoIDs)
let photocount = photoIDs.length - subcount
if (subcount && photocount) {
$('.photo.active, .album.active').removeClass('active')
multiselect.close()
lychee.error("Please select either albums or photos!")
return
}
if (subcount) {
contextMenu.albumMulti(photoIDs, e)
return
}
multiselect.stopResize()
// Notice for 'Move All': // Notice for 'Move All':
// fn must call basicContext.close() first, // fn must call basicContext.close() first,
// in order to keep the selection and multiselect // in order to keep the selection and multiselect
multiselect.stopResize()
let items = [ let items = [
{ title: build.iconic('star') + 'Star All', fn: () => photo.setStar(photoIDs) }, { title: build.iconic('star') + 'Star All', fn: () => photo.setStar(photoIDs) },
{ title: build.iconic('tag') + 'Tag All', fn: () => photo.editTags(photoIDs) }, { title: build.iconic('tag') + 'Tag All', fn: () => photo.editTags(photoIDs) },
@ -211,19 +253,7 @@ contextMenu.photoTitle = function(albumID, photoID, e) {
items.push({ }) items.push({ })
// Generate list of albums items = items.concat(buildAlbumList(data.content, photoID, (a) => lychee.goto(albumID + '/' + a.id)))
$.each(data.content, function(index) {
if (this.title==='') this.title = 'Untitled'
let html = lychee.html`<img class='cover' width='16' height='16' src='$${ this.thumbUrl }'><div class='title'>$${ this.title }</div>`
if (this.id!=photoID) items.push({
title: html,
fn: () => lychee.goto(albumID + '/' + this.id)
})
})
} }
@ -251,7 +281,7 @@ contextMenu.move = function(photoIDs, e) {
let items = [] let items = []
api.post('Albums::get', {}, function(data) { api.post('Albums::get', { parent: -1 }, function(data) {
if (data.num===0) { if (data.num===0) {
@ -262,20 +292,7 @@ contextMenu.move = function(photoIDs, e) {
} else { } else {
// Generate list of albums items = buildAlbumList(data.albums, album.getID(), (a) => photo.setAlbum(photoIDs, a.id))
$.each(data.albums, function() {
if (!this.thumbs[0]) this.thumbs[0] = 'src/images/no_cover.svg'
if (this.title==='') this.title = 'Untitled'
let html = lychee.html`<img class='cover' width='16' height='16' src='$${ this.thumbs[0] }'><div class='title'>$${ this.title }</div>`
if (this.id!=album.getID()) items.push({
title: html,
fn: () => photo.setAlbum(photoIDs, this.id)
})
})
// Show Unsorted when unsorted is not the current album // Show Unsorted when unsorted is not the current album
if (album.getID()!=='0') { if (album.getID()!=='0') {

@ -44,7 +44,7 @@ header.bind = function() {
header.dom('#button_settings') .on(eventName, contextMenu.settings) header.dom('#button_settings') .on(eventName, contextMenu.settings)
header.dom('#button_info_album') .on(eventName, sidebar.toggle) header.dom('#button_info_album') .on(eventName, sidebar.toggle)
header.dom('#button_info') .on(eventName, sidebar.toggle) header.dom('#button_info') .on(eventName, sidebar.toggle)
header.dom('.button_add') .on(eventName, contextMenu.add) header.dom('.button_add') .on(eventName, function(e) { contextMenu.add(album.getID(), e) })
header.dom('#button_more') .on(eventName, function(e) { contextMenu.photoMore(photo.getID(), e) }) header.dom('#button_more') .on(eventName, function(e) { contextMenu.photoMore(photo.getID(), e) })
header.dom('#button_move') .on(eventName, function(e) { contextMenu.move([ photo.getID() ], e) }) header.dom('#button_move') .on(eventName, function(e) { contextMenu.move([ photo.getID() ], e) })
header.dom('.header__hostedwith') .on(eventName, function() { window.open(lychee.website) }) header.dom('.header__hostedwith') .on(eventName, function() { window.open(lychee.website) })
@ -52,7 +52,7 @@ header.bind = function() {
header.dom('#button_trash') .on(eventName, function() { photo.delete([ photo.getID() ]) }) header.dom('#button_trash') .on(eventName, function() { photo.delete([ photo.getID() ]) })
header.dom('#button_archive') .on(eventName, function() { album.getArchive(album.getID()) }) header.dom('#button_archive') .on(eventName, function() { album.getArchive(album.getID()) })
header.dom('#button_star') .on(eventName, function() { photo.setStar([ photo.getID() ]) }) header.dom('#button_star') .on(eventName, function() { photo.setStar([ photo.getID() ]) })
header.dom('#button_back_home') .on(eventName, function() { lychee.goto() }) header.dom('#button_back_home') .on(eventName, function() { lychee.goto(album.getParent()) })
header.dom('#button_back') .on(eventName, function() { lychee.goto(album.getID()) }) header.dom('#button_back') .on(eventName, function() { lychee.goto(album.getID()) })
header.dom('.header__search').on('keyup click', function() { search.find($(this).val()) }) header.dom('.header__search').on('keyup click', function() { search.find($(this).val()) })

@ -6,8 +6,8 @@
lychee = { lychee = {
title : document.title, title : document.title,
version : '3.1.2', version : '3.1.3',
versionCode : '030102', versionCode : '030103',
updatePath : '//update.electerious.com/index.json', updatePath : '//update.electerious.com/index.json',
updateURL : 'https://github.com/electerious/Lychee', updateURL : 'https://github.com/electerious/Lychee',
@ -170,6 +170,7 @@ lychee.load = function() {
// Trash data // Trash data
photo.json = null photo.json = null
albums.json = null
// Show Photo // Show Photo
if (lychee.content.html()==='' || (header.dom('.header__search').length && header.dom('.header__search').val().length!==0)) { if (lychee.content.html()==='' || (header.dom('.header__search').length && header.dom('.header__search').val().length!==0)) {
@ -182,6 +183,7 @@ lychee.load = function() {
// Trash data // Trash data
photo.json = null photo.json = null
albums.json = null
// Show Album // Show Album
if (visible.photo()) view.photo.hide() if (visible.photo()) view.photo.hide()
@ -197,6 +199,7 @@ lychee.load = function() {
} }
// Trash data // Trash data
album.subjson = null
album.json = null album.json = null
photo.json = null photo.json = null

@ -144,8 +144,22 @@ view.album = {
let photosData = '' let photosData = ''
// Sub albums
if (album.subjson && album.subjson.albums && album.subjson.num!==0) {
photosData = build.divider('Albums')
$.each(album.subjson.albums, function() {
albums.parse(this)
photosData += build.album(this)
})
}
if (album.json.content && album.json.content!==false) { if (album.json.content && album.json.content!==false) {
photosData += build.divider('Photos')
// Build photos // Build photos
$.each(album.json.content, function() { $.each(album.json.content, function() {
photosData += build.photo(this) photosData += build.photo(this)
@ -164,13 +178,25 @@ view.album = {
title: function(photoID) { title: function(photoID) {
let title = album.json.content[photoID].title if (album.json.content[photoID]) {
ntitle = album.json.content[photoID].title
prefix = '.photo'
}
else {
for (i in album.subjson.albums) {
if (album.subjson.albums[i].id == photoID) {
ntitle = album.subjson.albums[i].title
break
}
}
prefix = '.album'
}
title = lychee.escapeHTML(title) ntitle = lychee.escapeHTML(ntitle)
$('.photo[data-id="' + photoID + '"] .overlay h1') $(prefix + '[data-id="' + photoID + '"] .overlay h1')
.html(title) .html(ntitle)
.attr('title', title) .attr('title', ntitle)
}, },

@ -8,6 +8,10 @@
box-shadow: 0 0 0 1px black(.5); box-shadow: 0 0 0 1px black(.5);
} }
&__data .disabled {
opacity: 0.5;
}
&__data .title { &__data .title {
display: inline-block; display: inline-block;
margin: 0 0 3px 26px; margin: 0 0 3px 26px;

Loading…
Cancel
Save