553 lines
17 KiB
JavaScript
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");
|
|
} |