AlkantarClanX12
Current Path : /proc/self/root/home/thanudqk/siamfreetour.com/wp-content/plugins/hd-quiz/hdfields/ |
Current File : //proc/self/root/home/thanudqk/siamfreetour.com/wp-content/plugins/hd-quiz/hdfields/script.js |
const _hd = { v: 0.3, data: { fields: {}, }, options: { tabAutoScroll: "", // null (default), or px count wrapper: document.body, }, init: function () { console.log("HDFields init v" + _hd.v); _hd.tabs.init(); // set tab navigation _hd.radio.init(); // set radio listeners _hd.images.init(); // if any image or gallery inputs _hd.colour.init(); // colour inputs _hd.image_toggle.init(); // image toggles _hd.search_list.init(); // searchable lists _hd.editor.init(); // tinyMCE editors _hd.kb.init(); // keyboard click navigation let save_el = document.getElementById("hd_save"); if (save_el) { save_el.addEventListener("click", _hd.save); } }, tabs: { // currently only compatible with one tabbed container per page init: function () { const tab_nav_items = document.getElementsByClassName("hd_tab_nav_item"); for (let i = 0; i < tab_nav_items.length; i++) { tab_nav_items[i].addEventListener("click", _hd.tabs.switch); } // set tab_id for each and every element for (let i = 0; i < tab_nav_items.length; i++) { let id = tab_nav_items[i].getAttribute("data-id"); let tab = document.getElementById("hd_tab_content_" + id); let fields = tab.getElementsByClassName("hderp"); for (let ii = 0; ii < fields.length; ii++) { fields[ii].setAttribute("data-tab", id); } } if (window.innerWidth < 740) { const tabWrapper = document.getElementsByClassName("hd_content_tabs"); for (let i = 0; i < tabWrapper.length; i++) { if (!tabWrapper[i].classList.contains("hd_content_tabs_horizintal")) { tabWrapper[i].classList.add("hd_content_tabs_horizontal"); } } } }, switch: async function () { if (this.classList.contains("hd_tab_nav_item_active")) { return; } let id = this.getAttribute("data-id"); await _hd.tabs.set(this, "hd_tab_nav_item_active"); let el = document.getElementById("hd_tab_content_" + id); await _hd.tabs.set(el, "hd_tab_content_section_active"); console.log(_hd.options.tabAutoScroll); if (_hd.options.tabAutoScroll === "") { document.getElementsByClassName("hd_tabs_anchor")[0].scrollIntoView({ behavior: "smooth", block: "start", inline: "nearest", }); } else { document.documentElement.scrollTop = _hd.options.tabAutoScroll; } }, set: async function (el, className = "") { let active = document.getElementsByClassName(className); while (active.length > 0) { active[0].classList.remove(className); } el.classList.add(className); }, }, kb: { init: function () { const items = document.getElementsByClassName("hd_kb"); for (let i = 0; i < items.length; i++) { items[i].addEventListener("keyup", function (ev) { if (ev.which == 32) { this.click(); } }); } }, }, sortable: { init: function (parentEL) { Array.prototype.map.call(parentEL, (list) => { _hd.sortable.enableDragList(list); }); }, enableDragList: function (list) { Array.prototype.map.call(list.children, (item) => { _hd.sortable.enableDragItem(item); }); }, enableDragItem: function (item) { item.setAttribute("draggable", true); item.ondrag = _hd.sortable.handleDrag; item.ondragend = _hd.sortable.handleDrop; }, handleDrag: function (item) { const selectedItem = item.target, list = selectedItem.parentNode, x = event.clientX, y = event.clientY; selectedItem.classList.add("drag-sort-active"); let swapItem = document.elementFromPoint(x, y) === null ? selectedItem : document.elementFromPoint(x, y); if (list === swapItem.parentNode) { swapItem = swapItem !== selectedItem.nextSibling ? swapItem : swapItem.nextSibling; list.insertBefore(selectedItem, swapItem); } }, handleDrop: function (item) { item.target.classList.remove("drag-sort-active"); }, }, radio: { init: function () { let radio = document.getElementsByClassName("hd_input_radio"); for (let i = 0; i < radio.length; i++) { let input = radio[i].getElementsByClassName("hd_radio_input"); for (let x = 0; x < input.length; x++) { input[x].addEventListener("change", function () { _hd.radio.change(input[x], radio[i]); }); } } }, change: function (input, radio) { // once a radio option has been selected, radio value canot be unset let inputs = radio.getElementsByClassName("hd_radio_input"); let hasSelection = false; for (let i = 0; i < inputs.length; i++) { if (inputs[i].checked == true) { hasSelection = true; } } if (!hasSelection) { if (inputs.length > 1) { input.checked = true; return; } } // now we ensure that only the current is checked if (input.checked != true) { return; } for (let i = 0; i < inputs.length; i++) { if (inputs[i] !== input) { inputs[i].checked = false; } } }, }, colour: { init: function () { const colours = document.getElementsByClassName("hd_colour"); for (let i = 0; i < colours.length; i++) { colours[i].addEventListener("change", _hd.colour.change); } }, change: function () { let value = this.value; value = value.toUpperCase(); if (value.length >= 4 && value[0] === "#") { if (value.length !== 4 && value.length !== 7) { return; } this.nextSibling.style.backgroundColor = value; this.value = value; } }, }, image_toggle: { init: function () { const toggleItems = document.getElementsByClassName("hd_image_toggle_item"); for (let i = 0; i < toggleItems.length; i++) { toggleItems[i].addEventListener("click", _hd.image_toggle.change); } const toggles = document.getElementsByClassName("hd_image_toggle"); for (let i = 0; i < toggles.length; i++) { let sortable = toggles[i].getAttribute("data-sortable"); if (sortable == 1) { console.log(toggles[i].getElementsByClassName("hd_image_toggle_items")); _hd.sortable.init(toggles[i].getElementsByClassName("hd_image_toggle_items")); } } }, change: async function () { const item = this; const field = item.parentElement.parentElement; const multi = parseInt(field.getAttribute("data-multiple")); const required = field.getAttribute("data-required"); let active = field.getElementsByClassName("active"); let wasActive = false; if (item.classList.contains("active")) { wasActive = true; } if (multi) { await changeMulti(); _hd.image_toggle.setContent(field); } else { await changeSingle(); _hd.image_toggle.setContent(field); } async function changeMulti() { if (required) { if (wasActive && active.length > 1) { item.classList.toggle("active"); } else if (!wasActive) { item.classList.toggle("active"); } } else { item.classList.toggle("active"); } } async function changeSingle() { while (active.length > 0) { active[0].classList.remove("active"); } if (required) { if (!wasActive) { item.classList.add("active"); } } else { if (!wasActive) { item.classList.add("active"); } } } }, setContent: function (field) { const activeContent = field.querySelectorAll(".hd_image_toggle_content.active"); for (let i = 0; i < activeContent.length; i++) { activeContent[i].classList.remove("active"); } const active = field.getElementsByClassName("hd_image_toggle_items")[0].getElementsByClassName("active"); let value = []; for (let i = 0; i < active.length; i++) { value.push(active[i].getAttribute("data-id")); let content = field.querySelector('.hd_image_toggle_content[data-id = "' + active[i].getAttribute("data-id") + '"]'); content.classList.add("active"); } field.setAttribute("data-value", JSON.stringify(value)); }, }, images: { // NOTE: This handles gallery too init: function () { const images = document.getElementsByClassName("hd_image"); for (let i = 0; i < images.length; i++) { let set = images[i].getAttribute("data-event-loaded"); if (set === "loaded") { continue; } images[i].setAttribute("data-event-loaded", "loaded"); images[i].addEventListener("click", function () { let options = { title: this.getAttribute("data-title"), button: this.getAttribute("data-button"), multiple: this.getAttribute("data-multiple"), }; _hd.images.load(this, options); }); } // sortable const els = document.getElementsByClassName("hd_gallery_content"); _hd.sortable.init(els); }, load: function (el, options) { let type = el.getAttribute("data-type"); let frame = (wp.media.frames.file_frame = wp.media({ title: options.title, button: { text: options.button, }, multiple: options.multiple, })); // When an image is selected, run a callback. frame.on("select", function () { let attachment = frame.state().get("selection"); if (type === "image") { setImage(el, attachment); } else if (type === "gallery") { setGallery(el, attachment); } else { console.log(attachment); } }); frame.open(); function setImage(el, attachment) { let id = el.getAttribute("id"); attachment = attachment.first().toJSON(); el.setAttribute("data-value", attachment.id); let image = attachment.sizes.full.url; if (attachment.sizes.medium) { image = attachment.sizes.medium.url; } el.innerHTML = `<img src = "${image}" alt = ""/>`; let remove = el.nextElementSibling.classList.add("active"); } function setGallery(el, attachment) { attachment = attachment.toJSON(); let id = el.getAttribute("data-id"); for (let i = 0; i < attachment.length; i++) { let iid = attachment[i].id; let image = attachment[i].sizes.thumbnail.url; let html = `<div class = "hd_gallery_image" data-id = "${id}" data-type = "gallery" onClick = "_hd.images.remove(this)" data-value = "${iid}" role = "button" title = "click to delete, drag and drop to reorder"><img src = "${image}" alt = ""/></div>`; el.nextElementSibling.insertAdjacentHTML("beforeend", html); } const els = document.getElementsByClassName("hd_gallery_content"); _hd.sortable.init(els); } }, remove: function (target) { let id = target.getAttribute("data-id"); let type = target.getAttribute("data-type"); if (type === "image") { removeImage(target, id); } else if (type === "gallery") { removeGallery(target, id); } function removeImage(target, id) { target.classList.remove("active"); let el = document.getElementById(id); el.innerHTML = "upload image"; el.setAttribute("data-value", 0); } function removeGallery(target, id) { let el = document.getElementById(id); target.remove(); } }, }, search_list: { init: function () { const items = document.getElementsByClassName("hd_search_list"); for (let i = 0; i < items.length; i++) { let input = items[i].getElementsByClassName("hd_input")[0]; input.addEventListener("keyup", function () { _hd.search_list.check(this, items[i]); }); input.addEventListener("focus", function () { items[i].classList.add("active"); }); input.addEventListener("blur", function () { setTimeout(function () { items[i].classList.remove("active"); }, 100); }); } }, check: async function (el, parent) { let value = el.value; let dropdown = parent.getElementsByClassName("hd_search_list_open")[0]; if (value.length < 3) { dropdown.innerText = "Enter " + (3 - value.length) + " or more characters"; return; } dropdown.innerHTML = ""; let options = el.getAttribute("data-list"); options = JSON.parse(options); let results = []; let valueCompare = value.toUpperCase(); for (let i = 0; i < options.length; i++) { let option = options[i].label.toUpperCase(); if (option.includes(valueCompare)) { results.push(options[i]); } } if (results.length == 0) { dropdown.innerText = "No results found"; return; } let html = ""; for (let i = 0; i < results.length; i++) { html += `<div class = "hd_search_list_result_item" onClick = "_hd.search_list.add(this)" data-id = "${parent.getAttribute("id")}" data-value = "${results[i]["value"]}">${results[i]["label"]}</div>`; } dropdown.innerHTML = html; }, add: function (item) { let value = item.getAttribute("data-value"); let label = item.innerText; let id = item.getAttribute("data-id"); const list = document.getElementById(id).getElementsByClassName("hd_search_list_wrapper")[0]; const html = `<span onClick = "_hd.search_list.remove(this)" class = "hd_search_list_item" data-value = "${value}">${label}</span>`; list.insertAdjacentHTML("beforeend", html); const input = document.getElementById(id).getElementsByClassName("hd_input")[0]; const dropdown = document.getElementById(id).getElementsByClassName("hd_search_list_open")[0]; dropdown.innerText = "Enter 3 or more characters"; input.value = ""; }, remove: function (item) { item.remove(); }, }, editor: { init: function () { const el = document.getElementsByClassName("hd_editor_input"); for (let i = 0; i < el.length; i++) { el[i].setAttribute("data-type", "editor"); if (el[i].classList.contains("hd_editor_required")) { el[i].setAttribute("data-required", "required"); } } }, }, saveLocal: async function (wrapper) { _hd.options.wrapper = wrapper; return await _hd.validate.init(); }, save: async function (ev, wrapper = null) { if (this.classList.contains("disabled")) { return; } this.classList.add("disabled"); let label = this.innerHTML; this.innerHTML = "..."; let action = this.getAttribute("data-action"); if (wrapper === null && this.getAttribute("data-wrapper")) { if (wrapper === null) { _hd.options.wrapper = document.getElementById(this.getAttribute("data-wrapper")); } else { _hd.options.wrapper = wrapper; } } let valid = await _hd.validate.init(); if (!valid) { this.innerHTML = label; this.classList.remove("disabled"); // find the first invalid let firstInvalid = document.getElementsByClassName("hd_error"); if (firstInvalid.length > 0) { firstInvalid = firstInvalid[0]; let tab = firstInvalid.getAttribute("data-tab"); if (tab) { let tabEl = document.querySelector('.hd_tab_nav_item[data-id = "' + tab + '"]'); if (tabEl) { tabEl.click(); } } } } else { await _hd.ajax(action, _hd.data.fields, this); } }, validate: { init: async function () { // get all fields _hd.data.fields = {}; let valid = true; let fields = _hd.options.wrapper.getElementsByClassName("hderp"); for (let i = 0; i < fields.length; i++) { let type = fields[i].getAttribute("data-type"); if (!_hd.validate.field[type]) { console.error("Field type " + type + " does not have a validation function"); return; } let v = await _hd.validate.field[type](fields[i]); v = await _hd.validate.required(fields[i], v); if (!v.status) { valid = false; fields[i].classList.add("hd_error"); } else { fields[i].classList.remove("hd_error"); } v.id = fields[i].getAttribute("id"); v.type = type; _hd.data.fields[v.id] = { id: v.id, type: v.type, value: v.value, }; } return valid; }, required: async function (el, v) { let required = el.getAttribute("data-required"); if (required === "required") { if (v.value === "") { v.status = false; } } return v; }, field: { text: async function (field) { let v = { value: field.value, status: true, }; return v; }, hidden: async function (field) { let v = { value: field.value, status: true, }; return v; }, textarea: async function (field) { let v = { value: field.value, status: true, }; return v; }, textarea_code: async function (field) { let v = { value: field.value, status: true, }; return v; }, email: async function (field) { let v = { value: field.value, status: await isEmail(field.value), }; return v; async function isEmail(email) { if (email == "") { return true; } let re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return re.test(String(email).toLowerCase()); } }, website: async function (field) { let v = { value: field.value, status: await isWebsite(field.value), }; return v; async function isWebsite(website = "") { if (website === "localhost" || website === "") { return true; } try { website = new URL(website); return true; } catch (error) { return false; } } }, integer: async function (field) { let v = { value: field.value, status: true, }; if (v.value !== "") { v.value = parseInt(field.value); } return v; }, float: async function (field) { let v = { value: field.value, status: true, }; if (v.value !== "") { v.value = parseFloat(field.value); } return v; }, currency: async function (field) { let v = { value: field.value, status: true, }; if (v.value !== "") { v.value = parseFloat(field.value).toFixed(2); } return v; }, colour: async function (field) { let v = { value: field.value, status: true, }; return v; }, image: async function (field) { let v = { value: parseInt(field.getAttribute("data-value")), status: true, }; return v; }, gallery: async function (field) { let v = { value: [], status: true, }; let items = field.nextElementSibling.getElementsByClassName("hd_gallery_image"); for (let i = 0; i < items.length; i++) { v.value.push(parseInt(items[i].getAttribute("data-value"))); } return v; }, select: async function (field) { let v = { value: field.value, status: true, }; return v; }, radio: async function (field) { let v = { value: "", status: false, }; let data = ""; let radios = field.getElementsByClassName("hd_radio_input"); for (let i = 0; i < radios.length; i++) { if (radios[i].checked) { data = radios[i].value; break; } } if (data.length === 0) { data = "hd_null"; // allow for overwriting of default if saved as null } v = { value: data, status: true, }; return v; }, image_toggle: async function (field) { let v = { value: [], status: true, }; const items = field.getElementsByClassName("hd_image_toggle_items")[0].getElementsByClassName("active"); for (let i = 0; i < items.length; i++) { v.value.push(items[i].getAttribute("data-id")); } return v; }, checkbox: async function (field) { let v = { value: "", status: false, }; let data = []; let checkboxes = field.getElementsByClassName("hd_check_input"); for (let i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { data.push(checkboxes[i].value); } } // if user selects nothing we don't want field `default` to override that if (data.length === 0) { data = ["hd_null"]; } v = { value: data, status: true, }; return v; }, date: async function (field) { let v = { value: field.value, status: true, }; return v; }, editor: async function (field) { await tinyMCE.triggerSave(); let v = { value: field.value, status: true, }; return v; }, search_list: async function (field) { let v = { value: [], status: true, }; const items = field.getElementsByClassName("hd_search_list_item"); for (let i = 0; i < items.length; i++) { v.value.push(parseInt(items[i].getAttribute("data-value"))); } return v; }, }, }, ajax: async function (action = "", data, el = null, callback = null) { if (action == "") { console.warn("HD.ajax: No action was provided"); return; } let label = ""; if (el !== null) { label = el.innerText; if (el.getAttribute("data-label") != "") { label = el.getAttribute("data-label"); } el.classList.add("disabled"); el.innerText = "..."; } const formdata = new FormData(); formdata.append("action", action); formdata.append("data", JSON.stringify(data)); const nonce = document.getElementById("hd_wpnonce").value; formdata.append("HD_NONCE", nonce); let res = await fetch(ajaxurl, { method: "POST", credentials: "same-origin", body: formdata, }); res = await res.json(); if (el !== null) { el.classList.remove("disabled"); el.innerText = label; } if (res.status !== "success") { console.error(res); console.log("Failed running action " + action); _hd.error.show(res); return; } if (el !== null) { el.classList.remove("disabled"); el.innerText = label; } console.log(res); if (res.action && res.action != "") { console.log("Running action " + res.action.name); console.log(res); let f = res.action.name; f = getF(f); // we will limit to only three parameters for brevity let args = []; if (res.action.data) { args.push(res.action.data); } if (res.action.data2) { args.push(res.action.data2); } if (res.action.data3) { args.push(res.action.data3); } f(...args); // run the custom action function getF(f) { let scope = window; let scopeSplit = f.split("."); for (i = 0; i < scopeSplit.length - 1; i++) { scope = scope[scopeSplit[i]]; if (scope == undefined) { return; } } return scope[scopeSplit[scopeSplit.length - 1]]; } } }, error: { show: function (res) { const el = document.getElementById("hdfields_error_log"); if (el === null) { return; } el.innerHTML = res.message; el.classList.add("active"); setTimeout(function () { el.classList.remove("active"); }, 6000); }, }, }; _hd.init();