const cards = {}; /******************************************************************************/ cards.albums = {}; cards.albums.drag_start = function drag_start(event) { const album_card = event.target.closest(".album_card"); event.dataTransfer.setData("text/plain", album_card.id); } cards.albums.drag_end = function drag_end(event) { } cards.albums.drag_over = function drag_over(event) { event.preventDefault(); } cards.albums.drag_drop = function drag_drop(event) { const child = document.getElementById(event.dataTransfer.getData("text")); const child_id = child.dataset.id; const parent = event.currentTarget; const parent_id = parent.dataset.id; event.dataTransfer.clearData(); if (child_id == parent_id) { return; } let prompt; if (parent_id === "root") { const child_title = child.querySelector('.album_card_title').textContent.trim(); prompt = `Remove child\n${child_title}?`; } else { const child_title = child.querySelector('.album_card_title').textContent.trim(); const parent_title = parent.querySelector('.album_card_title').textContent.trim(); prompt = `Move\n${child_title}\ninto\n${parent_title}?`; } if (! confirm(prompt)) { return; } if (parent_id === "root") { api.albums.remove_child(ALBUM_ID, child_id, common.refresh_or_alert); } else if (ALBUM_ID) { api.albums.add_child(parent_id, child_id, null); api.albums.remove_child(ALBUM_ID, child_id, common.refresh_or_alert); } else { api.albums.add_child(parent_id, child_id, common.refresh_or_alert); } } /******************************************************************************/ cards.bookmarks = {}; cards.bookmarks.create = function create(bookmark, add_author, add_delete_button, add_url_element) { const bookmark_card = document.createElement("div"); bookmark_card.className = "bookmark_card" bookmark_card.dataset.id = bookmark.id; const h2 = document.createElement("h2"); const bookmark_title = document.createElement("a"); bookmark_title.className = "bookmark_title"; bookmark_title.href = bookmark.url; bookmark_title.innerText = bookmark.display_name; h2.appendChild(bookmark_title); bookmark_card.appendChild(h2); // The URL element is always display:none, but its presence is useful in // facilitating the Editor object. If this bookmark will not be editable, // there is no need for it. if (add_url_element) { const bookmark_url = document.createElement("a"); bookmark_url.className = "bookmark_url"; bookmark_url.href = bookmark.url; bookmark_url.innerText = bookmark.url; bookmark_card.appendChild(bookmark_url); } // If more tools are added, this will become an `or`. // I just want to have the structure in place now. if (add_delete_button) { const bookmark_toolbox = document.createElement("div"); bookmark_toolbox.className = "bookmark_toolbox" bookmark_card.appendChild(bookmark_toolbox); if (add_delete_button) { const delete_button = document.createElement("button"); delete_button.className = "red_button button_with_confirm"; delete_button.dataset.onclick = "return delete_bookmark_form(event);"; delete_button.dataset.prompt = "Delete Bookmark?"; delete_button.dataset.cancelClass = "gray_button"; delete_button.innerText = "Delete"; bookmark_toolbox.appendChild(delete_button); common.init_button_with_confirm(delete_button); } } return bookmark_card; } /******************************************************************************/ cards.photos = {}; cards.photos.MIMETYPE_THUMBNAILS = { "svg": "svg", "application/zip": "archive", "application/x-tar": "archive", "archive": "archive", "audio": "audio", "image": "image", "video": "video", "text": "txt", }; cards.photos.file_link = function file_link(photo, short) { if (short) { return `/photo/${photo.id}/download/${photo.id}${photo.dot_extension}`; } const basename = escape(photo.filename); return `/photo/${photo.id}/download/${basename}`; } cards.photos.create = function create(photo, view) { if (view !== "list" && view !== "grid") { view = "grid"; } const photo_card = document.createElement("div"); photo_card.id = `photo_card_${photo.id}`; photo_card.dataset.id = photo.id; photo_card.className = `photo_card photo_card_${view} photo_card_unselected` if (photo.searchhidden) { photo_card.classList.add("photo_card_searchhidden"); } photo_card.ondragstart = "return cards.photos.drag_start(event);"; photo_card.ondragend = "return cards.photos.drag_end(event);"; photo_card.ondragover = "return cards.photos.drag_over(event);"; photo_card.ondrop = "return cards.photos.drag_drop(event);"; photo_card.draggable = true; const photo_card_filename = document.createElement("div"); photo_card_filename.className = "photo_card_filename"; const filename_link = document.createElement("a"); filename_link.href = `/photo/${photo.id}`; filename_link.draggable = false; filename_link.innerText = photo.filename; photo_card_filename.appendChild(filename_link); photo_card.appendChild(photo_card_filename); const photo_card_metadata = document.createElement("span"); photo_card_metadata.className = "photo_card_metadata"; const metadatas = []; if (photo.width) { metadatas.push(`${photo.width}×${photo.height}`); } if (photo.duration) { metadatas.push(`${photo.duration_string}`); } photo_card_metadata.innerHTML = common.join_and_trail(metadatas, ", "); const filesize_file_link = document.createElement("a"); filesize_file_link.href = cards.photos.file_link(photo); filesize_file_link.target = "_blank"; filesize_file_link.draggable = false; filesize_file_link.innerText = photo.bytes_string; photo_card_metadata.append(filesize_file_link); photo_card.appendChild(photo_card_metadata); if (view == "grid") { let thumbnail_src; if (photo.has_thumbnail) { thumbnail_src = `/photo/${photo.id}/thumbnail/${photo.id}.jpg`; } else { thumbnail_src = cards.photos.MIMETYPE_THUMBNAILS[photo.extension] || cards.photos.MIMETYPE_THUMBNAILS[photo.mimetype] || cards.photos.MIMETYPE_THUMBNAILS[photo.simple_mimetype] || "other"; thumbnail_src = `/static/basic_thumbnails/${thumbnail_src}.png`; } const photo_card_thumbnail = document.createElement("a"); photo_card_thumbnail.className = "photo_card_thumbnail"; photo_card_thumbnail.target = "_blank"; photo_card_thumbnail.href = `/photo/${photo.id}`; photo_card_thumbnail.draggable = false; const thumbnail_img = document.createElement("img"); thumbnail_img.loading = "lazy"; thumbnail_img.src = thumbnail_src; thumbnail_img.draggable = false; photo_card_thumbnail.appendChild(thumbnail_img); photo_card.appendChild(photo_card_thumbnail); } let tag_names_title = []; let tag_names_inner = ""; for (const tag of photo.tags) { tag_names_title.push(tag.name); tag_names_inner = "T"; } const photo_card_tags = document.createElement("span"); photo_card_tags.className = "photo_card_tags"; photo_card_tags.title = tag_names_title.join(","); photo_card_tags.innerText = tag_names_inner; photo_card.appendChild(photo_card_tags); if (window.photo_clipboard !== undefined) { const clipboard_checkbox = photo_clipboard.give_checkbox(photo_card); photo_clipboard.apply_check(clipboard_checkbox); } return photo_card; } cards.photos.drag_start = function drag_start(event) { } cards.photos.drag_end = function drag_end(event) { } cards.photos.drag_over = function drag_over(event) { } cards.photos.drag_drop = function drag_drop(event) { } cards.photos.photo_contextmenu = null; cards.photos.set_contextmenu = function set_contextmenu(element, build_function) { element.classList.add("photo_card_contextmenu"); element.classList.add("contextmenu"); element.onclick = "event.stopPropagation(); return;"; cards.photos.photo_contextmenu = element; cards.photos.build_photo_contextmenu = build_function; contextmenus.hide_open_menus(); } cards.photos.right_clicked_photo = null; cards.photos.photo_rightclick = function photo_rightclick(event) { if (["A", "IMG"].includes(event.target.tagName)) { return true; } if (cards.photos.photo_contextmenu === null) { return true; } if (event.ctrlKey || event.shiftKey || event.altKey) { return true; } const photo_card = event.target.closest(".photo_card"); if (! photo_card) { cards.photos.right_clicked_photo = null; contextmenus.hide_open_menus(); return true; } if (contextmenus.menu_is_open()) { contextmenus.hide_open_menus(); } cards.photos.right_clicked_photo = photo_card; const menu = cards.photos.photo_contextmenu; cards.photos.build_photo_contextmenu(photo_card, menu); setTimeout(() => {contextmenus.show_menu(event, menu);}, 0); event.stopPropagation(); event.preventDefault(); return false; } /******************************************************************************/ cards.tags = {};