553 lines
17 KiB
JavaScript

// megjelenítés / eltüntetés
function show(obj) {
o(obj).setAttribute("shown", "true");
}
function hide(obj) {
o(obj).setAttribute("shown", "false");
}
function toggle_show(obj) {
o(obj).setAttribute("shown", o(obj).getAttribute("shown") === "false");
}
function scroll_enable(on) {
document.body.style.overflowY = on ? "scroll" : "hidden";
}
// -----------------------------------------
var slide_unit = 504;
var slider_id = "pupslider";
var upload_popup_id = "uploadpup";
var publish_btn_id = "publishbtn";
var image_uid = null;
function determine_sliding_unit() {
if (window.innerWidth > 600) { // számítógépes megjelenítés
slide_unit = 504;
} else { // mobilos megjelenítés
slide_unit = ((window.orientation % 90) === 0) ? window.innerWidth : window.innerHeight; // deprecated, de működik...
}
}
function pup_slide(units) {
slider_slide(slider_id, -slide_unit * units);
}
function pup_reset() {
hide(upload_popup_id); // ablak eltüntetése
reset_slider(slider_id); // slider visszaállítása
o(publish_btn_id).innerText = "Mehet!"; // gombfelirat visszaállítása
o("respchkbox").checked = false; // pipa kivétele
// mezők törlése
o("author").value = "";
o("imgtitle").value = "";
o("description").value = "";
}
// kép publikálása
function publish() {
if (image_uid == null) { // csak, ha érvényes...
return;
}
// mezők kinyerése
let author = o("author").value;
let title = o("imgtitle").value;
let desc = o("description").value;
// ha a kötelező mezők nincsenek kitöltve, akkor nem lehet beküldeni
if (author.trim() === "" || title.trim() === "") {
alert("Alkotó és cím megadása kötelező!");
return;
}
// checkbox ellenőrzése
if (!o("respchkbox").checked) {
return;
}
// struktúra összeállítása
let details = {
uid: image_uid,
author: author,
title: title,
desc: desc
}
// küldés
let formData = new FormData();
formData.append("action", "publish");
formData.append("details", JSON.stringify(details));
let req = new XMLHttpRequest();
req.onreadystatechange = state => {
if (req.status === 200 && req.readyState === 4) {
pup_reset(); // popup resetelése
if (Number(req.response) === 0) {
alert("Sikeres feltöltés!");
close_upload_pup();
} else if (Number(req.response) === -1) {
alert("Ugyanezt képet már korábban feltöltötték!");
} else {
alert("Valami nem stimmel!\nHa ismételten nem sikerül, kérlek jelezd a hibát!");
}
}
};
req.open("POST", "interface.php");
req.send(formData);
// UID elfelejtése
image_uid = null;
o(publish_btn_id).innerText = "Türelem..."
}
// feltöltés után kapott válasz feldolgozása
function process_upload_response(resp) {
if (/^[0-9a-zA-Z]+$/.test(resp)) { // ha random string a válasz, akkor kaptunk UID-t
image_uid = resp;
pup_slide(1); // előrelépés
} else { // ha negatív szám a válasz vagy egyébb szöveg, akkor hibás az eredmény
let resp_num = Number(resp);
switch (resp_num) {
case -1:
alert("Hiba a feldolgozás során!");
break;
case -2:
alert("A feltöltött fájl formátuma nem megfelelő, csak JPG- vagy PNG-képek elfogadottak!")
break;
case -3:
alert("Mérethiba: a kép hosszabb oldalának legalább 2000 pixel szélesnek kell lennie!");
break;
default:
alert("Valami nem stimmel!\nHa ismételten nem sikerül, kérlek jelezd a hibát!");
break;
}
pup_slide(-1); // visszalépés
}
}
// fájl feltöltése
function upload_file(f) {
let formData = new FormData();
formData.append("image", f);
formData.append("action", "upload");
let req = new XMLHttpRequest();
req.onreadystatechange = state => {
if (req.status === 200 && req.readyState === 4) {
process_upload_response(req.response);
}
};
req.open("POST", "interface.php");
req.send(formData);
}
// feltöltés eszközről
function upload_from_device() {
let file_selector = o("fileselector");
if (file_selector.files.length > 0) {
pup_slide(1); // görgetés jobbra
upload_file(file_selector.files[0]);
}
}
// feltöltőablak megnyitása
function open_upload_pup() {
show(upload_popup_id);
let display = o("display");
display.style.filter = "blur(10px)";
scroll_enable(false);
}
// feltöltőablak bezárása
function close_upload_pup() {
hide(upload_popup_id);
let display = o("display");
display.style.filter = "";
scroll_enable(true);
pup_reset();
}
// -----------------
function async_req(action, cb, add_data = null) {
xhr = new XMLHttpRequest();
fd = new FormData();
fd.append("action", action);
xhr.onreadystatechange = state => {
if (xhr.status === 200 && xhr.readyState === 4 && cb != null) {
cb(state, xhr.response);
}
};
// további adatok hozzáfűzése a kéréshez
if (add_data != null) {
for (let prop in add_data) {
if (Object.prototype.hasOwnProperty.call(add_data, prop)) {
fd.append(prop, JSON.stringify(add_data[prop]));
}
}
}
xhr.open("POST", "interface.php");
xhr.send(fd)
}
var total_artwork_count = 0; // összes kép alkotás száma
var thumb_largest_side = 400; // a bélyegkép hosszabb oldala 400 pixel
var batch_loading_quantity = 10; // egyszerre betöltött képek mennyisége
var autoload_enabled = false; // automatikus betöltés
var artworks_loaded_n = 0; // ennyi kép van betöltve a megjelenítőbe
var thumbnail_padding = 8; // kép körüli margó
var extra_margin = 0; // extra margó, amire számítani kell a fal generálásakor
var last_uid = ""; // utolsó UID
var wall_height = 0; // a fal magassága, pixelben
var dynamic_load_distance = 200; // ennyi pixellel a fal alja előtt indítja a dinamikus betöltést
var dynamic_loading_under_way = false; // dinamikus töltés folyamatban, ne indítsunk új requestet
var update_interval = 10000; // automatikus frissítés 10 másodpercenként
var max_scaled_size_factor = 1.2; // hányszorosa lehet a nagyított kép az eredetinek
var thumbnails = [];
// fotófal inicializálása
function init_photowall() {
scroll_enable(true);
determine_sliding_unit();
init_drag_and_drop();
req_general_info();
init_dynamic_loading();
init_viewer();
// újrakompozitálás átméretezés esetén
window.addEventListener("resize", () => {
compose_wall();
}, false);
window.addEventListener("orientationchange", (e) => {
determine_sliding_unit();
});
// automatikus frissítés
setInterval(() => {
req_update();
}, 10000);
}
// inicializálási lánc
function req_general_info() {
async_req("general_info", recv_general_info);
}
function recv_general_info(state, resp) {
// általános adatok mentése
let resp_obj = JSON.parse(resp);
total_artwork_count = resp_obj["total_artwork_count"];
thumb_largest_side = resp_obj["thumb_largest_side"];
// első adag képe betöltése
req_batch();
}
// egy adag kép lekérése
function req_batch() {
async_req("batch", recv_batch, {offset: artworks_loaded_n, n: batch_loading_quantity});
}
function recv_batch(state, resp) {
let img_batch = JSON.parse(resp);
// utolsó UID mentése, ha most történt az első letöltés
if (artworks_loaded_n === 0) {
last_uid = img_batch[0].UID;
}
// betöltött művek számának növelése
artworks_loaded_n += img_batch.length;
// ha van még mit letölteni, akkor engedélyezzük az automatikus betöltést
autoload_enabled = total_artwork_count > artworks_loaded_n;
// újonnan kapott képek befűzése a lista ELEJÉRE!
thumbnails = thumbnails.concat(img_batch);
// fotófal összeállítása
compose_wall();
// ha nem töltődött be elég kép... VIGYÁZAT: rekurzív, mint állat!
if (wall_height < window.innerHeight) {
req_batch();
}
// töltés kész
dynamic_loading_under_way = false;
}
// fotófal összeállítása
function compose_wall() {
// görgetési pozíció mentése
let scroll_pos = window.scrollY;
// nézőfelület szélessége és magassága
let display = o("display");
display.innerHTML = ""; // fal törlése
wall_height = 0;
let width = display.clientWidth;
//let height = display.clientHeight;
// bélyegképek méreteinek meghatározása
for (let i = 0; i < thumbnails.length; i++) {
let thumbnail = thumbnails[i];
// ha kell, akkor kiszámoljuk a kép méretét
if (!(thumbnail.hasOwnProperty("width") && thumbnail.hasOwnProperty("height"))) {
let ar = Number(thumbnail["AspectRatio"]);
if (ar >= 1.0) { // a kép fekvő vagy négyzet, ezért a SZÉLESSÉG a nagyobb
thumbnail.width = thumb_largest_side;
thumbnail.height = thumb_largest_side / ar;
} else { // a kép álló, ezért a MAGASSÁG a nagyobb
thumbnail.height = thumb_largest_side;
thumbnail.width = thumb_largest_side * ar;
}
}
}
// sorok előállítása
let processed_n = 0;
while (processed_n < artworks_loaded_n) { // amíg van még kép
// egy sornyi kép összegyűjtése
let total_width = 0;
let max_thumbnail_height = 0; // maximális bélyegkép-magasság
let line_entries = [];
for (let i = processed_n; i < artworks_loaded_n && total_width < width; i++) { // futtatás a lista végéig, vagy amíg be nem telik a sok
line_entries.push(thumbnails[i]); // hozzáadás a listához
// maximális hossz növelése
total_width += thumbnails[i].width;
// (1. lépés) maximális magasság keresése
max_thumbnail_height = thumbnails[i].height > max_thumbnail_height ? thumbnails[i].height : max_thumbnail_height;
}
// 2. lépés: a maximális magasságnál kisebb képek felskálázása
let total_scaled_width = 0;
for (let i = 0; i < line_entries.length; i++) {
let thumbnail = line_entries[i];
// skálafaktor
let K = max_thumbnail_height / thumbnail.height;
thumbnail.scale_factor = K;
// skálázott méret kiszámítása
thumbnail.scaledHeight = thumbnail.height * K;
thumbnail.scaledWidth = thumbnail.width * K;
total_scaled_width += thumbnail.scaledWidth;
}
// 3. lépés: visszaskálázás a sor hosszára
let summed_padding = (line_entries.length + 1) * thumbnail_padding + extra_margin; // sorhossz kiszámítása margókkal együtt
// a képeknek az ablakszélesség-összes margó helyre be kell férni, ezért:
let k = (width - summed_padding) / total_scaled_width;
for (let i = 0; i < line_entries.length; i++) {
line_entries[i].scale_factor *= k;
line_entries[i].scale_factor = Math.round(line_entries[i].scale_factor * 1000) / 1000; // kerekítés ezredekre
}
// képek elhelyzése
for (let i = 0; i < line_entries.length; i++) {
// méret kiszámítása
let thumb_width = line_entries[i].width * line_entries[i].scale_factor;
let thumb_height = line_entries[i].height * line_entries[i].scale_factor;
// ha bármelyik nagyobb, mint max_scaled_size_factor * hosszabb_oldal pixel, akkor visszaskálázzuk;
let bigger_dim = Math.max(thumb_width, thumb_height);
let max_scaled_size = max_scaled_size_factor * thumb_largest_side;
if (bigger_dim > max_scaled_size) {
let s = max_scaled_size / bigger_dim;
thumb_width *= s;
thumb_height *= s;
}
// képet tároló elem
let container_section = document.createElement("section");
container_section.style.backgroundColor = line_entries[i].ColorMean;
container_section.classList.add("thumbnail-container");
// a bélyegkép
let img = document.createElement("img");
img.classList.add("thumbnail");
container_section.style.width = img.style.width = `${thumb_width}px`;
container_section.style.height = img.style.height = `${thumb_height}px`;
img.src = `ARTWORKS/thumbnails/${line_entries[i].Image_FileName}`;
img.addEventListener("load", (e) => {
img.style.opacity = "1";
}, false);
img.details = line_entries[i];
img.addEventListener("click", (e) => {
open_viewer(img.details);
}, false);
// kép címe
let title_span = document.createElement("span");
title_span.classList.add("thumb-title");
title_span.innerText = line_entries[i].Title;
// sáv színének igazítása a kép domináns színéhez
let title_bgcolor = new Color();
title_bgcolor.from_cssrgb(line_entries[i].ColorMean);
//title_bgcolor.mul(0.8);
title_bgcolor.a = 0.6;
title_span.style.backgroundColor = title_bgcolor.to_rgba();
container_section.appendChild(img);
container_section.appendChild(title_span);
display.appendChild(container_section);
}
// falmagasság számítása
wall_height += 2 * thumbnail_padding + max_thumbnail_height * k;
// feldolgozottság léptetése
processed_n += line_entries.length;
}
// görgetés oda, ahol eredetileg álltunk
window.scrollTo(0, scroll_pos);
}
// frissítés lekérése
function req_update() {
async_req("update", recv_update, {last_uid: last_uid});
}
// frissítés fogadása
function recv_update(state, resp) {
let img_update_batch = JSON.parse(resp);
// ha nem volt semmi újabb, akkor kilépünk
if (img_update_batch.length === 0) {
return;
}
// növeljük az összes és a betöltött művek számát
artworks_loaded_n += img_update_batch.length;
total_artwork_count += img_update_batch.length;
// ha van még mit letölteni, akkor engedélyezzük az automatikus betöltést
autoload_enabled = total_artwork_count > artworks_loaded_n;
// újonnan kapott képek befűzése a lista ELEJÉRE!
thumbnails = img_update_batch.concat(thumbnails);
// utolsó UID mentése
last_uid = thumbnails[0].UID;
// fal összeállítása
compose_wall();
}
// DnD inicializálása
function init_drag_and_drop() {
let drop_area = o("uploadtype");
drop_area.addEventListener("dragover", (e) => {
e.stopPropagation();
e.preventDefault();
}, false);
drop_area.addEventListener("drop", (e) => {
e.stopPropagation();
e.preventDefault();
if (e.dataTransfer.files.length > 0) {
pup_slide(1);
upload_file(e.dataTransfer.files[0]);
}
}, false);
}
// dinamikus betöltés inicializálása
function init_dynamic_loading() {
document.addEventListener("scroll", (e) => {
if (autoload_enabled && !dynamic_loading_under_way) { // ha az automatikus töltés engedélyezett
if (window.scrollY + window.innerHeight > wall_height - dynamic_load_distance) {
dynamic_loading_under_way = true;
req_batch();
}
}
}, false);
}
// képnézegető inicializálása
function init_viewer() {
let img = o("viewerimg");
let caption_sect = o("artcaptions");
// betöltéskor a felirat megjelenítése
img.addEventListener("load", (e) => {
img.style.opacity="1";
place_artcaptions();
show(caption_sect);
}, false);
window.addEventListener("resize", (e) => {
setTimeout(() => {
place_artcaptions();
}, 400);
}, false);
// TODO görgetéskor nagyítás
}
// feliratok elhelyezése
function place_artcaptions() {
let img = o("viewerimg");
let caption_sect = o("artcaptions");
let brect = img.getBoundingClientRect();
caption_sect.style.left = brect.x + "px";
caption_sect.style.width = img.clientWidth + "px";
}
// képnézegető megynitása
function open_viewer(details) {
let img = o("viewerimg");
img.style.opacity = "0";
img.src = "ARTWORKS/published/" + details.Image_FileName;
// feliratok kiírása
o("arttitle").innerText = details.Title;
o("artauthor").innerText = details.Author;
o("artdesc").innerText = details.Description;
// feliratcsík háttérszínének meghatározása a domináns szín alapján
/*let captions_bgcolor = new Color();
captions_bgcolor.from_cssrgb(details.ColorMean);
captions_bgcolor.a = 0.6;
o("artcaptions").style.backgroundColor = captions_bgcolor.to_rgba();*/
// ...
scroll_enable(false);
show("viewersect");
}
// képnézegető bezárása
function close_viewer() {
scroll_enable(true);
hide("viewersect");
hide("artcaptions");
}