// 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"; } function blur_page(blur) { if (blur) { show("blurlayer"); o("display").style.filter = "blur(10px)"; scroll_enable(false); } else { hide("blurlayer"); o("display").style.filter = ""; scroll_enable(true); } } // ----------------------------------------- var slide_unit = 604; var slider_id = "pupslider"; var upload_popup_id = "uploadpup"; var publish_btn_id = "publishbtn"; var image_uid = null; var processing_busy = false; // feldolgozás folyamatban function determine_sliding_unit() { if (window.innerWidth > 600) { // számítógépes megjelenítés slide_unit = 604; } 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 o("autocorrchkbox").checked = false; // mezők törlése o("author").value = ""; o("author_group").value = ""; o("imgtitle").value = ""; o("description").value = ""; o("fileselector").value = ""; } // kép publikálása function publish() { if (processing_busy || image_uid == null) { // csak, ha érvényes... return; } // mezők kinyerése let author = o("author").value.trim(); let title = o("imgtitle").value.trim(); let desc = o("description").value.trim(); let autocorr = o("autocorrchkbox").checked; let group = o("author_group").value.trim(); // 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, autocorrect: autocorr, group: group } // 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) { let close_if_needed = true; if (Number(req.response) === 0) { alert("Sikeres feltöltés!"); req_update(); // frissítés kérése } else if (Number(req.response) === -1) { alert("Ugyanezt képet már korábban feltöltötték!"); } else if (Number(req.response) === -2) { alert("A megadott csoport nem létezik!"); close_if_needed = false; // nem kell bezárni, mert valószínűleg csak elírta o("author_group").focus(); // fókuszálás a csoport mezőre } else { alert("Valami nem stimmel!\nHa ismételten nem sikerül, kérlek jelezd a hibát!"); } // bezárás, ha szükséges if (close_if_needed) { // UID elfelejtése image_uid = null; // popup resetelése close_upload_pup(); } processing_busy = false; o(publish_btn_id).innerText = "Mehet!"; } }; req.open("POST", "interface.php"); req.send(formData); // feldolgozás folyamatban processing_busy = true; o(publish_btn_id).innerHTML = "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; case -4: alert("Elérted a feltöltési limitet.\nKérlek próbáld újra később!"); 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); blur_page(true); o("fileselector").value = ""; } // feltöltőablak bezárása function close_upload_pup() { hide(upload_popup_id); blur_page(false); 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(); }, update_interval); } // 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 && total_artwork_count > artworks_loaded_n) { 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; let last_line_height = thumb_largest_side; 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 = []; let not_full_line = false; // nem teljes sor 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; // nem teljes sor jelzése if ((i + 1) === artworks_loaded_n && total_width < width) { not_full_line = true; } } // 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 a sor nem teljes, és a képek az utolsó teljes sor magasságánál nagyobbak lennének, akkor visszaskálázunk if (not_full_line) { if (thumb_height > last_line_height) { let s = last_line_height / thumb_height; 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 let thumbnail_height = max_thumbnail_height * k; wall_height += 2 * thumbnail_padding + thumbnail_height; // feldolgozottság léptetése processed_n += line_entries.length; // falmagasság mentése last_line_height = thumbnail_height; } // görgetés oda, ahol eredetileg álltunk window.scrollTo(0, scroll_pos); } // frissítés folyamatban var update_in_progress = false; // frissítés lekérése function req_update() { if (!update_in_progress) { update_in_progress = true; 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(); // update kész update_in_progress = false; } // 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); } var magnification_sensitivity = 0.05; // nagyítási érzékenység, skálafaktor a görgetés mértékére var touch_magnification_sensitivity = 0.01; // nagyítási érzékenység érintőképernyő esetén var viewer_original_mouse_coords = {x: 0, y: 0}; // egér indulópozíciója a kép mozgatásakor var viewer_original_offset_coords = {x: 0, y: 0}; // mozgatás kezdeti offset var viewer_grabbing = false; // mozgatják épp a képet? var last_touch_distance = 0; // előző érintési távolság // 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.classList.remove("loading"); place_artcaptions(); show(caption_sect); hide("viewerloadanim"); }, false); window.addEventListener("resize", (e) => { change_viewer_magnification(1, true); change_viewer_offset({ x: 0, y: 0 }, true); setTimeout(() => { place_artcaptions(); }, 400); }, false); img.addEventListener("wheel", (e) => { change_viewer_magnification(-e.deltaY * magnification_sensitivity); }, false); // a képre kattintáskor ne záródjon be a nézegető, ha éppen mozgatjuk img.addEventListener("click", (e) => { if (e.clientX !== viewer_original_mouse_coords.x || e.clientY !== viewer_original_mouse_coords.y) { e.preventDefault(); e.stopPropagation(); return false; } }, false); // nézegető billentyű-kombinációk window.addEventListener("keyup", (e) => { switch (e.key) { case "Escape": close_viewer(); break; } }, false); // kép mozgatása img.addEventListener("mousedown", (e) => { viewer_original_offset_coords = img.offset; viewer_original_mouse_coords = {x: e.clientX, y: e.clientY}; viewer_grabbing = true; img.style.cursor = "grabbing"; // ne jelölődjön ki a kép e.preventDefault(); e.stopPropagation(); return false; }, false); img.addEventListener("mousemove", (e) => { if (viewer_grabbing) { let offset = { x: e.clientX - viewer_original_mouse_coords.x + viewer_original_offset_coords.x, y: e.clientY - viewer_original_mouse_coords.y + viewer_original_offset_coords.y }; change_viewer_offset(offset, true); } }, false); let end_grab = (e) => { viewer_grabbing = false; img.style.cursor = "grab"; }; img.addEventListener("mouseup", end_grab, false); img.addEventListener("mouseleave", end_grab, false); img.addEventListener("touchstart", (e) => { let t = e.touches; viewer_original_offset_coords = img.offset; viewer_original_mouse_coords = { x: t[0].screenX, y: t[0].screenY }; viewer_grabbing = true; last_touch_distance = 0; }, false); img.addEventListener("touchmove", (e) => { let t = e.touches; if (t.length >= 2) { let d = Math.sqrt((t[0].screenX - t[1].screenX) * (t[0].screenX - t[1].screenX) + (t[0].screenY - t[1].screenY) * (t[0].screenY - t[1].screenY)); // TODO szűrés let d_filtered = d; // nagyítás if (last_touch_distance !== 0) { change_viewer_magnification(touch_magnification_sensitivity * (d_filtered - last_touch_distance)); } last_touch_distance = d_filtered; } else if (t.length === 1) { if (viewer_grabbing) { let offset = { x: t[0].screenX - viewer_original_mouse_coords.x + viewer_original_offset_coords.x, y: t[0].screenY - viewer_original_mouse_coords.y + viewer_original_offset_coords.y }; change_viewer_offset(offset, true); } } }, false); img.addEventListener("touchend", (e) => { viewer_grabbing = false; }, false); } // 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"; } var viewer_open = false; var group_logo_repository = "https://mkkozi.hu/user/plugins/mkk-groups/logos"; // képnézegető megynitása function open_viewer(details) { let img = o("viewerimg"); img.classList.add("loading"); img.style.left = img.style.top = "0px"; 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();*/ // csoportlogó megjelenítése let glogo = document.createElement("img"); glogo.src = `${group_logo_repository}/${details.AuthorGroup}.png`; glogo.alt = `(${details.AuthorGroup})`; glogo.classList.add("art-author-group"); o("artauthor").appendChild(glogo); // nézegető visszaállítása change_viewer_magnification(1.0, true); change_viewer_offset({x: 0, y: 0}, true); // ... scroll_enable(false); show("viewerloadanim"); show("viewersect"); viewer_open = true; } // képnézegető bezárása function close_viewer() { scroll_enable(true); hide("viewersect"); hide("artcaptions"); // kép eltávolítása let img = o("viewerimg"); img.src = ""; viewer_open = false; } // kép nagyítása a képnézegetőben function change_viewer_magnification(c, absolute = false) { let img = o("viewerimg"); // ha nagyítás mezője a képnek, akkor most létrehozzuk if (!img.hasOwnProperty("magnification")) { img.magnification = 1.0; } // nagyítás értékének meghatározása img.magnification = Math.min(Math.max(1.0, absolute ? c : (img.magnification + c)), 5.0); // visszaírás img.style.transform = `scale(${img.magnification})`; } // kép helyének megváltoztatása function change_viewer_offset(offset, absolute = false) { let img = o("viewerimg"); // ha nincs eltolás mezője a képnek, akkor most létrehozzuk if (!img.hasOwnProperty("offset")) { img.offset = {x: 0, y: 0}; } // az eltolás értékének meghatározása img.offset = absolute ? offset : ({x: img.offset.x + offset.x, y: img.offset.y + offset.y}) // visszaírás img.style.left = img.offset.x + "px"; img.style.top = img.offset.y + "px"; } // üdvözlőüzenet megnyitása function open_welcome_msg() { show("welcomepup"); blur_page(true); } // üdvözlőüzenet eltüntetése function hide_welcome_msg() { hide("welcomepup"); blur_page(false); } // üdvözlőüzenet OK-gomb function confirm_welcome_msg() { hide_welcome_msg(); // süti mentése let d = new Date(); d.setTime(d.getTime() + (7*24*3600*1000)); document.cookie = `phw_welcome_confirmed=1; expires=${d.toUTCString()}; path=/;`; }