// 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 { alert("Ugyanezt képet már korábban feltöltötték!"); } } }; 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 (!isNaN(Number(resp))) { // ha szám a válasz, akkor biztosan 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; } pup_slide(-1); // visszalépés } else { // ha kaptunk UID-t image_uid = resp; pup_slide(1); // előrelé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 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++) { // 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 = `${line_entries[i].width * line_entries[i].scale_factor}px`; container_section.style.height = img.style.height = `${line_entries[i].height * line_entries[i].scale_factor}px`; img.src = `ARTWORKS/thumbnails/${line_entries[i].Image_FileName}`; img.addEventListener("load", (e) => { img.style.opacity = "100%"; }, 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='100%' 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"); }