//ver 1
class WiseHubJson2Form extends HTMLElement {
//system keeps here somme data - like uploaded files
#attachments;
constructor() {
super();
this.uniqId = this.generateCode(64);
this.#attachments = {};
try {
this.user = getUserFromStorage();
} catch (ex) {
this.user = null;
}
}
connectedCallback() {
this.endPoint = this.getAttribute("endpoint");
this.guid = this.getAttribute("guid");
var tmp = this.getAttribute("save-dispatch");
if (tmp && (tmp.toLowerCase() == "true" || tmp.toLowerCase() == "1" || tmp.toLowerCase() == "yes")) this.saveDispatch = true; else this.saveDispatch = false;
if (this.endPoint) this.loadData();
}
addToAttachments(key, value) {
if (key.startsWith("ATTACHMENT_FOR_FIELD_")) key = key.replace("ATTACHMENT_FOR_FIELD_", "");
this.#attachments[key] = value;
this.redrawAttachments();
}
removeFromAttachments(key) {
delete this.#attachments[key];
this.redrawAttachments();
//this.#attachments[key] = null;
}
getAttachment(key) {
var tmp = this.#attachments[key];
return tmp;
}
getConfirmationCaption(v) {
if (v == null || v == "") {
return "Kliknij, aby potwierdzić";
} else {
return "Potwierdzone: " + v;
}
}
redrawAttachments() {
console.log("redrawing attachemnts")
const redraw=(key, obj) => {
console.log(key, obj);
};
document.querySelectorAll(`.attachment-container`).forEach(x=>{
x.style.display = "none";
});
Object.keys(this.#attachments).forEach(key => {
console.log("key", key);
document.querySelectorAll(`.${this.uniqId}-file-info`).forEach(x=>{
redraw(key, x);
});
document.querySelectorAll(`.${this.uniqId}-file-action`).forEach(x=>{
if (x.getAttribute("data-ref")==key) {
x.style.display = "inline";
}
});
});
}
loadData() {
var url = this.endPoint;
if (url.includes("?")) url += "&"; else url += "?";
url += "action=load&code=" + this.guid;
fetch(url)
.then((response) => response.json())
.then((data) => {
//console.log(data);
this.formData = JSON.parse(data.data[0].frd_definition);
var loaded = data.data[0].data;
if (loaded == null || loaded == "") loaded = "[]";
loaded = loaded.replace(/\n/g, '\\n');
this.formLoaded = JSON.parse(loaded);
this.render();
this.setLoaded();
this.redrawAttachments();
})
.catch((ex) => {
console.log('Error:', ex);
});
}
setData(formDefinition, formUserData) {
this.formLoaded = formUserData;
this.formData = formDefinition;
this.render();
this.setLoaded();
}
getUniqId() {
return this.uniqId;
}
getData() {
let response = { "guid": this.guid };
let formResponse = [];
let error = false;
let errorInfo = "";
var parent = document.querySelector(`#${this.uniqId}`);
this.formData.sections.forEach(section => {
section.fields.forEach(field => {
var fid = field.id;
if (fid == null || fid == "") {
fid = field.name;
}
var fieldDom = parent.querySelector(`#${fid}`);
if (fieldDom==null) {
console.log("Trying to find (failed) dom id=" + fid);
}
this.removeClass(fieldDom, 'border-danger');
if (fid != null && fid != "") {
field.value = fieldDom.value;
}
if (field.required == 1 && field.value == "" && fieldDom.style.display != 'none') {
error = true;
console.log("error field",field, fieldDom);
errorInfo += field.caption + "(" + field.id + "); ";
this.addClass(fieldDom, 'border-danger');
}
//console.log(fieldDom);
formResponse.push({ "id": fid, "value": field.value });
});
});
Object.keys(this.#attachments).forEach(key => {
formResponse.push({ "id": "ATTACHMENT_FOR_FIELD_" + key, "value": this.#attachments[key] });
});
this.error = error;
this.errorInfo = errorInfo;
response["questions"] = this.formFlat;
response["answers"] = formResponse;
return response;
}
save() {
var response = this.getData();
if (this.saveDispatch == false) {
var postUrl = this.endPoint + "?action=save&code=" + this.guid;
fetch(postUrl, {
method: 'POST', // or 'PUT'
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(response),
})
.then((res) => res.json())
.then((data) => {
//if (success != null) success(data);
})
.catch((ex) => {
console.error('Error:', ex);
//if (error != null) error(ex);
});
} else {
response["id"] = this.uniqId;
response["error"] = this.error;
response["errorInfo"] = this.errorInfo;
let event = new CustomEvent("json2form", { bubbles: true, composed: false, detail: response }); // (2)
this.dispatchEvent(event);
}
}
render() {
var form = this.formData;
this.formFlat = [];
var html = `
${form['title']}
${form['lead']}
`;
var sectionId = "";
for (var s = 0; s < form['sections'].length; s++) {
var section = form['sections'][s];
sectionId = section["id"];
var cap = section['title'];
html += "" + cap + " ";//
for (var a = 0; a < section['fields'].length; a++) {
var o = section['fields'][a];
var id = o['id'];
var css = o['domClass'];
var cap = o["caption"];
var name = o["name"];
var hint = o["hint"];
if (css == "") {
css = "w-100";
}
var info = "";
if (o["required"] == 1) {
info = " * ";
}
var type = o["type"];
if (type == "header") {
html += "" + cap + " ";
} else if (type != "section") {
var bold = "";
if (type == "label") bold = "fw-bold font-weight-bold";
html += "" + cap + " " + info + "
";
if (hint != null && hint != "") {
html += "" + hint + "
";
}
if (type == "select") {
html += "";
for (var b = 0; b < o["selectValues"].length; b++) {
var o2 = o["selectValues"][b];
this.formFlat.push({ "id:": id, "question": cap, "possibleId": o2["id"], "possibleTxt": o2["value"] });
if (o2["value"] == "-- wybierz --") o2["value"] = "--";
html += "" + o2["value"] + " ";
}
html += " ";
} else if (type == "wh-confirmation") {
html += ` `;
html += ` `;
this.formFlat.push({ "id:": id, "question": cap, "possibleId": "", "possibleTxt": "" });
} else if (type == 'textarea') {
//field.value - previus
html += ``;
this.formFlat.push({ "id:": id, "question": cap, "possibleId": "", "possibleTxt": "" });
} else if (type == 'label') {
html += ` `;
this.formFlat.push({ "id:": id, "question": cap, "possibleId": "", "possibleTxt": "" });
} else if (type == 'file') {
var oldId = id;
//id = id+"xx";
html += " ";
html += " ";
html += "";
html += "
pobierz ";
html += "
usuń ";
html += "
";
html += " ";
//html += " ";
} else {
html += " ";
this.formFlat.push({ "id:": id, "question": cap, "possibleId": "", "possibleTxt": "" });
}
}
}
html += " ";
}
html += " ";
html += "";
html += ` `;
html += "
";
this.innerHTML = html;
this.redrawAttachments();
//binfing confiormation
document.querySelectorAll(`.${this.uniqId}-btn-confirmation`).forEach(confirmBtn => {
confirmBtn.addEventListener("click", btn => {
if (this.user != null) {
$(`#${this.uniqId}`).find(`#${confirmBtn.getAttribute("data-ref")}`).val(this.user.userSymbol);
confirmBtn.value = this.getConfirmationCaption(this.user.userSymbol);
} else {
showPopup("Użytkownik nie jest zalogowany", false)
}
});
});
//binding file
document.querySelectorAll(`.${this.uniqId}-file-action`).forEach(btnInput => {
btnInput.addEventListener("click", (b) => {
var ref = b.target.getAttribute("data-ref");
var action = b.target.getAttribute("data-action");
var att = this.getAttachment(ref);
if (att == null) {
alert('Nie wgrano załącznika');
} else {
if (action == "delete") {
this.removeFromAttachments(ref);
document.getElementById(ref).value = "wybierz";
} else {
const byteCharacters = atob(this.getAttachment(ref));
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += 512) {
const slice = byteCharacters.slice(offset, offset + 512);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, { type: 'application/octet-stream' });
// Create temporary anchor element
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = document.getElementById(ref).value;
// Trigger the download
a.click();
}
}
console.log(this.#attachments);
});
});
document.querySelectorAll(`.${this.uniqId}-file-upload-button`).forEach(btnInput => {
btnInput.addEventListener("click", (b) => {
console.log(b.target.getAttribute("data-ref"));
var ref = b.target.getAttribute("data-ref");
document.getElementById(ref).click();
});
});
document.querySelectorAll(`.${this.uniqId}-file`).forEach(fileInput => {
fileInput.addEventListener('change', (event) => {
// Get the file from the input element
const file = event.target.files[0];
const parentId = fileInput.getAttribute("data-ref");
if (file) {
// Create a new FileReader instance
const reader = new FileReader();
var that = this;
// Define the onload callback function
reader.onload = function (e) {
// The file's content will be available as a Base64 encoded string in e.target.result
const base64String = e.target.result.split(',')[1]; // Remove the data URL prefix
console.log('File Name:', file.name);
document.getElementById(parentId).value = file.name;
that.addToAttachments(parentId, base64String);
// You can now use the file.name and base64String variables as needed
};
// Read the file content as a Data URL (Base64 encoded string)
reader.readAsDataURL(file);
}
});
});
//bingind save button
document.querySelector(`#${this.uniqId}-save`).onclick = () => {
this.save();
};
this.prepareVisibility(form);
this.dispatchReady();
}
dispatchReady() {
let event = new CustomEvent("wh-json-form-ready", { bubbles: true, composed: false, detail: { "status": "ready", "uniqId": this.uniqId } }); // (2)
document.dispatchEvent(event);
}
prepareVisibility(form) {
this.conds = [];
for (var a = 0; a < form['visibility'].length; a++) {
var vis = form['visibility'][a];
var ifArr = vis["if"].split(":");
var show = vis["show"];
if (ifArr.length > 1) {
this.conds.push({ 'if': ifArr[0], 'eq': ifArr[1], 'show': show });
this.formsSetVisibilityItems(show, 'none');
}
}
var items = document.querySelector(`#${this.uniqId}`).querySelectorAll(`select`);
items.forEach(i => {
var that = this;
i.addEventListener('change', function () {
that.conds.forEach(item => {//hide all
that.formsSetVisibilityItems(item.show, 'none');
});
that.conds.forEach(item => {//show if equal
var obj = document.getElementById(item['if'])
if (obj != null && obj.value != null && item.eq == obj.value) {
//console.log("if", item['if'], "==", obj.value, ' show', item['show']);
that.formsSetVisibilityItems(item.show, 'block');
}
});
});
});
}
setLoaded() {
let changeEvent = new Event('change');
this.formLoaded.forEach(l => {
if (!l.id.startsWith("ATTACHMENT_FOR_FIELD_")) {
var item = document.querySelector(`#${this.uniqId}`).querySelector(`#${l.id}`);
if (item) {
item.value = l.value;
item.dispatchEvent(changeEvent);
}
} else {//convert fields with attachments as this.#attachment
this.addToAttachments(l.id, l.value);
}
});
document.querySelectorAll(`.${this.uniqId}-btn-confirmation`).forEach(x => {
var l = $(`#${this.uniqId}`).find(`#${x.getAttribute("data-ref")}`).val();
x.value = this.getConfirmationCaption(l);
});
}
formsSetVisibilityItems(elementId, display) {
var field = document.getElementById(elementId);
if (field != null) field.style.display = display;
var divsToHide = document.getElementsByClassName(elementId); //divsToHide is an array
for (var i = 0; i < divsToHide.length; i++) {
divsToHide[i].style.display = display;
}
}
generateCode(len) {
var c = "qwertyuiopasdfhgjhkjlzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
var s = "";
for (var a = 0; a < len; a++) {
var idx = Math.floor(Math.random() * c.length);
s = s + c[idx];
}
return s;
}
addClass(element, className) {
if (element && !element.classList.contains(className)) {
element.classList.add(className);
}
}
removeClass(element, className) {
if (element && element.classList.contains(className)) {
element.classList.remove(className);
}
}
}
customElements.define("wh-json2form", WiseHubJson2Form);