1386 lines
54 KiB
Plaintext
1386 lines
54 KiB
Plaintext
{% assign content_type = content_type | default: 'body' %}
|
|
|
|
{% if content_type == 'body' %}
|
|
|
|
{% comment %}
|
|
|
|
<div id="shx-3d-render-input-container">
|
|
<style>.custom.form__label{margin-bottom: 0.6rem}.field.custom{margin-top:0}.custom .field__input{padding-top:0.8rem}</style>
|
|
<label class="form__label custom" for="your-label">Dein Text</label>
|
|
<div class="field custom">
|
|
<input class="field__input" form="{{ 'product-form-' | append: section.id }}" type="text" id="your-label" name="properties[Your label]">
|
|
</div>
|
|
</div>
|
|
|
|
{% endcomment %}
|
|
|
|
<shx-input-forms section_id="{{ section.id }}">
|
|
</shx-input-forms>
|
|
|
|
{% elsif content_type == 'init' %}
|
|
|
|
{% liquid
|
|
capture shx_get_environment
|
|
render "shx-get-environment"
|
|
endcapture %}
|
|
|
|
<style>
|
|
.shx-input-forms-container {
|
|
overflow: hidden;
|
|
}
|
|
|
|
.shx_ifc_renderButton, .shx-ifc-form_label {
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
.shx-threejs-renderer-container {
|
|
margin-top: 1rem;
|
|
border-radius: 10px;
|
|
border: 0;
|
|
width: 100%;
|
|
|
|
position: relative;
|
|
overflow: hidden;
|
|
display: flex;
|
|
}
|
|
|
|
.shx-threejs-renderer {
|
|
border: 0;
|
|
width: 100%;
|
|
|
|
background-color: ##bfb8b5;
|
|
}
|
|
|
|
.shx-ifc-colorselect, .shx-ifc-watchselect {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.shx-ifc-colorselect label {
|
|
cursor: pointer;
|
|
|
|
width: 40px;
|
|
height: 40px;
|
|
margin: 8px;
|
|
border-radius: 2px;
|
|
|
|
position: relative;
|
|
}
|
|
|
|
.shx-ifc-watchselect label {
|
|
cursor: pointer;
|
|
|
|
width: 80px;
|
|
height: 80px;
|
|
margin: 8px;
|
|
border-radius: 2px;
|
|
|
|
position: relative;
|
|
}
|
|
|
|
.shx-ifc-colorselect label::after, .shx-ifc-watchselect label::after {
|
|
content: '';
|
|
display: block;
|
|
position: absolute;
|
|
|
|
top: -4px;
|
|
left: -4px;
|
|
|
|
width: calc(100% + 8px);
|
|
height: calc(100% + 8px);
|
|
border-radius: 4px;
|
|
|
|
border: 1px solid #0003;
|
|
}
|
|
|
|
.shx-ifc-colorselect input[type="radio"]:checked + label::after, .shx-ifc-watchselect input[type="radio"]:checked + label::after{
|
|
border: 1px solid #111;
|
|
}
|
|
|
|
.shx-ifc-colorselect input[type="radio"], .shx-ifc-watchselect input[type="radio"]{
|
|
height: 1px;
|
|
width: 1px;
|
|
position: absolute;
|
|
clip: rect(0, 0, 0, 0);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.shx-mat-container {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
|
|
overflow: hidden;
|
|
}
|
|
|
|
.shx-mat-matte, .shx-mat-silk {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
|
|
transition: all 0.5s;
|
|
}
|
|
|
|
.shx-mat-matte {
|
|
background: linear-gradient(60deg, #fff -20%, transparent 60%);
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.shx-mat-silk {
|
|
background: linear-gradient(60deg, #fff 35%, transparent 35%);
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.shx-ifc-colorselect input[type="radio"]:checked + label .shx-mat-matte,
|
|
.shx-ifc-colorselect input[type="radio"]:checked + label .shx-mat-silk {
|
|
transform: scale(1.8);
|
|
transform-origin: center; /* Ensure scaling is centered */
|
|
opacity: 0.35;
|
|
}
|
|
|
|
.invisibleInput {
|
|
position: absolute;
|
|
pointer-events: none;
|
|
|
|
left: 50%;
|
|
top: 90%;
|
|
|
|
width: 1px;
|
|
height: 1px;
|
|
opacity: 0;
|
|
}
|
|
|
|
#shx-emoji-picker-popup:not(.shown) {
|
|
display: none;
|
|
}
|
|
|
|
.shx-emoji-picker {
|
|
width: 100%;
|
|
--emoji-size: 2.5rem;
|
|
--input-font-size: 14px;
|
|
}
|
|
</style>
|
|
|
|
<script type="module">
|
|
// import "https://cdn.jsdelivr.net/npm/emoji-picker-element@^1/index.js";
|
|
import "{{ 'shx-npm-emoji-picker-element-index.js' | asset_url }}"
|
|
</script>
|
|
|
|
<script type="text/javascript">
|
|
{% comment %}
|
|
code copied from https://cdn.jsdelivr.net/npm/insert-text-at-cursor@0.3.0/index.js to use it in plain javascript instead of es6 module
|
|
{% endcomment %}
|
|
let browserSupportsTextareaTextNodes;
|
|
|
|
function canManipulateViaTextNodes(input) {
|
|
if (input.nodeName !== "TEXTAREA") {
|
|
return false;
|
|
}
|
|
if (typeof browserSupportsTextareaTextNodes === "undefined") {
|
|
const textarea = document.createElement("textarea");
|
|
textarea.value = 1;
|
|
browserSupportsTextareaTextNodes = !!textarea.firstChild;
|
|
}
|
|
return browserSupportsTextareaTextNodes;
|
|
}
|
|
|
|
function insertText(input, text) {
|
|
// Most of the used APIs only work with the field selected
|
|
input.focus();
|
|
|
|
// IE 8-10
|
|
if (document.selection) {
|
|
const ieRange = document.selection.createRange();
|
|
ieRange.text = text;
|
|
|
|
// Move cursor after the inserted text
|
|
ieRange.collapse(false /* to the end */);
|
|
ieRange.select();
|
|
|
|
return;
|
|
}
|
|
|
|
// Webkit + Edge
|
|
const isSuccess = document.execCommand("insertText", false, text);
|
|
if (!isSuccess) {
|
|
const start = input.selectionStart;
|
|
const end = input.selectionEnd;
|
|
// Firefox (non-standard method)
|
|
if (typeof input.setRangeText === "function") {
|
|
input.setRangeText(text);
|
|
} else {
|
|
// To make a change we just need a Range, not a Selection
|
|
const range = document.createRange();
|
|
const textNode = document.createTextNode(text);
|
|
|
|
if (canManipulateViaTextNodes(input)) {
|
|
let node = input.firstChild;
|
|
|
|
// If textarea is empty, just insert the text
|
|
if (!node) {
|
|
input.appendChild(textNode);
|
|
} else {
|
|
// Otherwise we need to find a nodes for start and end
|
|
let offset = 0;
|
|
let startNode = null;
|
|
let endNode = null;
|
|
|
|
while (node && (startNode === null || endNode === null)) {
|
|
const nodeLength = node.nodeValue.length;
|
|
|
|
// if start of the selection falls into current node
|
|
if (start >= offset && start <= offset + nodeLength) {
|
|
range.setStart((startNode = node), start - offset);
|
|
}
|
|
|
|
// if end of the selection falls into current node
|
|
if (end >= offset && end <= offset + nodeLength) {
|
|
range.setEnd((endNode = node), end - offset);
|
|
}
|
|
|
|
offset += nodeLength;
|
|
node = node.nextSibling;
|
|
}
|
|
|
|
// If there is some text selected, remove it as we should replace it
|
|
if (start !== end) {
|
|
range.deleteContents();
|
|
}
|
|
}
|
|
}
|
|
|
|
// If the node is a textarea and the range doesn't span outside the element
|
|
//
|
|
// Get the commonAncestorContainer of the selected range and test its type
|
|
// If the node is of type `#text` it means that we're still working with text nodes within our textarea element
|
|
// otherwise, if it's of type `#document` for example it means our selection spans outside the textarea.
|
|
if (
|
|
canManipulateViaTextNodes(input) &&
|
|
range.commonAncestorContainer.nodeName === "#text"
|
|
) {
|
|
// Finally insert a new node. The browser will automatically split start and end nodes into two if necessary
|
|
range.insertNode(textNode);
|
|
} else {
|
|
// If the node is not a textarea or the range spans outside a textarea the only way is to replace the whole value
|
|
const value = input.value;
|
|
input.value = value.slice(0, start) + text + value.slice(end);
|
|
}
|
|
}
|
|
|
|
// Correct the cursor position to be at the end of the insertion
|
|
input.setSelectionRange(start + text.length, start + text.length);
|
|
|
|
// Notify any possible listeners of the change
|
|
const e = document.createEvent("UIEvent");
|
|
e.initEvent("input", true, false);
|
|
input.dispatchEvent(e);
|
|
}
|
|
}
|
|
|
|
{% comment %}
|
|
end of copied code
|
|
{% endcomment %}
|
|
|
|
const FilamentList = {
|
|
"10": {
|
|
"name": "Schwarz (Matt)",
|
|
"hex": "#000000",
|
|
"matte": true
|
|
},
|
|
"20": {
|
|
"name": "Schwarz (Glänzend)",
|
|
"hex": "#000000",
|
|
"silk": true
|
|
},
|
|
"11": {
|
|
"name": "Weiß (Matt)",
|
|
"hex": "#FFFFFF",
|
|
"matte": true
|
|
},
|
|
"12": {
|
|
"name": "Gold (Glänzend)",
|
|
"hex": "#ba7e14",
|
|
"silk": true,
|
|
"metallic": true
|
|
},
|
|
"13": {
|
|
"name": "Rot (Glänzend)",
|
|
"hex": "#BB0000",
|
|
"silk": true
|
|
},
|
|
"14": {
|
|
"name": "Holz (Matt)",
|
|
"hex": "#78583e",
|
|
"matte": true
|
|
},
|
|
"17": {
|
|
"name": "Blau (Fluoreszierend)",
|
|
"hex": "#1166FF",
|
|
"matte": true
|
|
},
|
|
"18": {
|
|
"name": "Orange (Fluoreszierend)",
|
|
"hex": "#ff5638",
|
|
"matte": true
|
|
},
|
|
"19": {
|
|
"name": "Diamant-Smaragdgrün (Glitzernd)",
|
|
"hex": "#1C2F1C",
|
|
"silk": true
|
|
},
|
|
"21": {
|
|
"name": "Rosa (Matt)",
|
|
"hex": "#FFC0CB",
|
|
"matte": true
|
|
},
|
|
"22": {
|
|
"name": "Hellgrau (Matt)",
|
|
"hex": "#384145",
|
|
"matte": true
|
|
},
|
|
"23": {
|
|
"name": "Schokolade (Matt)",
|
|
"hex": "#401d03",
|
|
"matte": true
|
|
},
|
|
"26": {
|
|
"name": "Beige (Matt)",
|
|
"hex": "#ffdba6",
|
|
"matte": true
|
|
},
|
|
"27": {
|
|
"name": "Marineblau (Matt)",
|
|
"hex": "#101060",
|
|
"matte": true
|
|
},
|
|
"28": {
|
|
"name": "Gelb (Matt)",
|
|
"hex": "#ffd54d",
|
|
"matte": true
|
|
},
|
|
"30": {
|
|
"name": "Hellgrün (Matt)",
|
|
"hex": "#60bf79",
|
|
"matte": true
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Helper function to convert Hex to RGB
|
|
function hexToRgb(hex) {
|
|
let r = 0, g = 0, b = 0;
|
|
// 3 digits
|
|
if (hex.length === 4) {
|
|
r = parseInt(hex[1] + hex[1], 16);
|
|
g = parseInt(hex[2] + hex[2], 16);
|
|
b = parseInt(hex[3] + hex[3], 16);
|
|
}
|
|
// 6 digits
|
|
else if (hex.length === 7) {
|
|
r = parseInt(hex[1] + hex[2], 16);
|
|
g = parseInt(hex[3] + hex[4], 16);
|
|
b = parseInt(hex[5] + hex[6], 16);
|
|
}
|
|
return [r, g, b];
|
|
}
|
|
|
|
// Helper function to convert RGB to HSL
|
|
function rgbToHsl(r, g, b) {
|
|
r /= 255, g /= 255, b /= 255;
|
|
let max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
let h, s, l = (max + min) / 2;
|
|
|
|
if (max === min) {
|
|
h = s = 0; // achromatic
|
|
} else {
|
|
let d = max - min;
|
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
switch (max) {
|
|
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
|
case g: h = (b - r) / d + 2; break;
|
|
case b: h = (r - g) / d + 4; break;
|
|
}
|
|
h /= 6;
|
|
}
|
|
|
|
return [h, s, l];
|
|
}
|
|
|
|
// add id to FilamentList
|
|
for (let key in FilamentList) {
|
|
FilamentList[key].id = key;
|
|
}
|
|
|
|
// Sort FilamentList by HSL
|
|
const sortedFilementIDs = Object.keys(FilamentList).sort((a, b) => {
|
|
let rgbA = hexToRgb(FilamentList[a].hex);
|
|
let hslA = rgbToHsl(...rgbA);
|
|
let rgbB = hexToRgb(FilamentList[b].hex);
|
|
let hslB = rgbToHsl(...rgbB);
|
|
|
|
// Compare by Hue, then Saturation, then Lightness
|
|
for (let i = 0; i < 3; i++) {
|
|
if (hslA[i] !== hslB[i]) {
|
|
return hslA[i] - hslB[i];
|
|
}
|
|
}
|
|
return 0; // identical colors
|
|
});
|
|
|
|
function SHX_getFilamentById(id) {
|
|
let filament = FilamentList[id];
|
|
if(filament) {
|
|
return filament;
|
|
} else {
|
|
console.error("Filament not found in FilamentList", id);
|
|
return {
|
|
|
|
"name": "undefined",
|
|
"hex": "#000000"
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
let globalInputFormsObjValues = {
|
|
"test1": {
|
|
"text1": "test",
|
|
"font": "LT Beverage"
|
|
},
|
|
"test2": {
|
|
"text1": "test1",
|
|
"text2": "test2"
|
|
},
|
|
"84712": {
|
|
"text1": "Paula",
|
|
"font": "LT Beverage",
|
|
"surface_finish": "matte",
|
|
"color": SHX_getFilamentById("10")
|
|
},
|
|
"17200": {
|
|
"text1": "Marie",
|
|
"font": "LT Beverage",
|
|
"surface_finish": "matte",
|
|
"color1": SHX_getFilamentById("17"),
|
|
"color2": SHX_getFilamentById("10")
|
|
},
|
|
"97548": {
|
|
"text1": "Luca",
|
|
"font": "LT Beverage",
|
|
"surface_finish": "matte",
|
|
"color1": SHX_getFilamentById("17"),
|
|
"color2": SHX_getFilamentById("10"),
|
|
"color3": SHX_getFilamentById("17")
|
|
},
|
|
"68859": {
|
|
"text1": "Max",
|
|
"font": "LT Beverage",
|
|
"backgroundType": "padding",
|
|
"color1": SHX_getFilamentById("17"),
|
|
"color2": SHX_getFilamentById("10")
|
|
},
|
|
"49340": {
|
|
"text1": "Lena",
|
|
"font": "LT Beverage",
|
|
"color1": SHX_getFilamentById("11"),
|
|
"color2": SHX_getFilamentById("10"),
|
|
"color3": SHX_getFilamentById("17")
|
|
}
|
|
};
|
|
|
|
let shx_globalValues = {
|
|
"text1": "Marie", // all keys are global values
|
|
"font": "LT Beverage",
|
|
"fontSize": "normal",
|
|
};
|
|
|
|
function SHX_IFC_getCurrentValue(id, key) {
|
|
if(shx_globalValues.hasOwnProperty(key)) {
|
|
if(shx_globalValues[key] !== undefined) {
|
|
for (let key in globalInputFormsObjValues) {
|
|
if (globalInputFormsObjValues[id][key] !== undefined) {
|
|
shx_globalValues[key] = globalInputFormsObjValues[id][key];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
let value = shx_globalValues[key];
|
|
|
|
globalInputFormsObjValues[id][key] = value;
|
|
return value;
|
|
}
|
|
|
|
return globalInputFormsObjValues[id][key];
|
|
}
|
|
|
|
function SHX_IFC_setCurrentValue(id, key, value) {
|
|
if(shx_globalValues.hasOwnProperty(key)) {
|
|
shx_globalValues[key] = value;
|
|
}
|
|
|
|
globalInputFormsObjValues[id][key] = value;
|
|
}
|
|
|
|
// emoji picker element will be created by clicking the emoji
|
|
function onClickEmojiPickerButton() {
|
|
const emojiPickupPopup = document.getElementById("shx-emoji-picker-popup")
|
|
|
|
// checking if emoji picker already exists
|
|
// needs to be created every time the variant was changed because of rerendering all inputs
|
|
if (emojiPickupPopup.childNodes.length === 0) {
|
|
const emojiPicker = document.createElement("emoji-picker");
|
|
emojiPicker.classList = "light shx-emoji-picker";
|
|
|
|
emojiPicker.addEventListener("emoji-click", (e) => {
|
|
insertText(document.querySelector("#shx-text1"), e.detail.unicode);
|
|
});
|
|
|
|
emojiPickupPopup.appendChild(emojiPicker);
|
|
}
|
|
|
|
emojiPickupPopup.classList.toggle('shown')
|
|
}
|
|
|
|
// Regular expression to match emoji characters
|
|
const emojiRegex = /[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F700}-\u{1F77F}]|[\u{1F780}-\u{1F7FF}]|[\u{1F800}-\u{1F8FF}]|[\u{1F900}-\u{1F9FF}]|[\u{1FA00}-\u{1FA6F}]|[\u{1FA70}-\u{1FAFF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|[\u{2B50}-\u{2B55}]|[\u{1F1E6}-\u{1F1FF}]/u;
|
|
|
|
// this function is to show the user a help message if there could be spacing added between emojis and text
|
|
function isEmojiSpacingOk(text) {
|
|
// regex to find emojis followed by a letter or another emoji without a space in between
|
|
let regex = /([\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{1FA70}-\u{1FAFF}])([^\s]|$)/gu;
|
|
|
|
// check if the regex finds a matching pattern
|
|
let match;
|
|
while ((match = regex.exec(text)) !== null) {
|
|
if (match[2] !== ' ' && match[2] !== '') {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function SHX_IFC_genTextInput(inputID, labelText, inputName, inputVal, section_id, maxLength = 24, emojisSupported = false) {
|
|
function handleInputLabel(value) {
|
|
let inputLabel = document.querySelector(`label[for="${inputID}-label"] span`)
|
|
|
|
// create input label if not exists
|
|
if (!inputLabel) {
|
|
const span = document.createElement("span");
|
|
span.style.marginLeft = `10px`
|
|
document.querySelector(`label[for="${inputID}-label"]`).appendChild(span)
|
|
}
|
|
|
|
// get label again from DOM as it might not exist before
|
|
inputLabel = document.querySelector(`label[for="${inputID}-label"] span`)
|
|
|
|
// show current used char length
|
|
inputLabel.style.display = `inline`
|
|
inputLabel.style.color = null;
|
|
inputLabel.textContent = value.length + ' von ' + maxLength + ' Zeichen verwendet';
|
|
|
|
// show error message no text specific
|
|
if (value.length == 0) {
|
|
inputLabel.textContent = 'Bitte gib deinen Text ein';
|
|
inputLabel.style.color = 'red';
|
|
}
|
|
|
|
// show error message no emojis supported on this product variant
|
|
if (value.length > 0) {
|
|
if (!emojisSupported && emojiRegex.test(value)) {
|
|
inputLabel.textContent = 'Emojis werden bei diesem Typ nicht unterstützt. Bitte wechsle zu "Mit Hintergrund"';
|
|
inputLabel.style.color = 'red';
|
|
} else if (!emojisSupported && value.indexOf(" ") !== -1) {
|
|
inputLabel.textContent = 'Leerzeichen werden bei diesem Typ nicht unterstützt. Bitte wechsle zu "Mit Hintergrund"';
|
|
inputLabel.style.color = 'red';
|
|
} else if (emojisSupported && !isEmojiSpacingOk(value)) {
|
|
document.querySelector('#shx-info-text').style.innerHTML = 'red';
|
|
document.querySelector('#shx-info-text').style.color = 'red';
|
|
document.querySelector('#shx-info-text').style.display = 'block';
|
|
|
|
// hide the text after 8 seconds
|
|
setTimeout(() => {
|
|
document.querySelector('#shx-info-text').style.display = 'none';
|
|
}, 8000);
|
|
}
|
|
}
|
|
}
|
|
|
|
setTimeout(() => {
|
|
// init call after text input is created on DOM
|
|
handleInputLabel(document.querySelector(`#${inputID}`).value)
|
|
|
|
document.querySelector(`#${inputID}`).addEventListener('input', (e) => {
|
|
handleInputLabel(e.target.value)
|
|
});
|
|
}, 1000);
|
|
|
|
return `
|
|
<label class="form__label custom shx-ifc-form_label" for="${inputID}-label">${labelText}</label>
|
|
<div class="field custom ">
|
|
<input class="field__input" form="product-form-${section_id}" type="text" id="${inputID}" name="properties[${inputName}]" value="${(inputVal.length > maxLength ? inputVal.substring(0, maxLength) : inputVal)}" oninput="document.querySelector('shx-input-forms').renderView()" required maxlength="${maxLength}" normalMaxLength="${maxLength}">
|
|
|
|
${emojisSupported ? `
|
|
<div id="shx-emoji-picker-button" onclick="onClickEmojiPickerButton()" style="position: absolute; right: 0; padding: 12px 10px 2px 12px; cursor: pointer">
|
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#121212BF"><path d="M620-520q25 0 42.5-17.5T680-580q0-25-17.5-42.5T620-640q-25 0-42.5 17.5T560-580q0 25 17.5 42.5T620-520Zm-280 0q25 0 42.5-17.5T400-580q0-25-17.5-42.5T340-640q-25 0-42.5 17.5T280-580q0 25 17.5 42.5T340-520Zm140 260q68 0 123.5-38.5T684-400h-66q-22 37-58.5 58.5T480-320q-43 0-79.5-21.5T342-400h-66q25 63 80.5 101.5T480-260Zm0 180q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-400Zm0 320q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Z"/></svg>
|
|
</div>` : ``}
|
|
</div>
|
|
|
|
<div id="shx-emoji-picker-popup"></div>
|
|
`;
|
|
}
|
|
|
|
function getCustomEnhancedDropdownItemFontAssetUrl(fontName) {
|
|
const fontAssetName = `shx-texte-font-${fontName.toLowerCase().split(" ").join("-")}.svg`
|
|
|
|
// we use shx-texte-font-arial.svg as dummy to get the asset url and then replace it with the right font asset name
|
|
const assetBaseUrl = "{{ 'shx-texte-font-arial.svg' | asset_url }}";
|
|
const imgSrc = `${assetBaseUrl.replace("shx-texte-font-arial.svg", fontAssetName)}`;
|
|
|
|
return imgSrc
|
|
}
|
|
|
|
function getCustomEnhancedDropdownItemFontAssetAltTag(fontName) {
|
|
return fontName.split(".")[0]
|
|
}
|
|
|
|
function toggleCustomEnhancedDropdownFont() {
|
|
const dropdownContent = document.querySelector("#shx-custom-enhanced-dropdown-font-dropdown-content")
|
|
|
|
dropdownContent.style.display = dropdownContent.style.display === 'block' ? 'none' : 'block';
|
|
}
|
|
|
|
function onFontDropdownItemClick(event) {
|
|
const selectedVariant = event.currentTarget.getAttribute('data-value');
|
|
const customSelectedValue = document.getElementById('shx-custom-enhanced-dropdown-font-select-selected-value')
|
|
|
|
customSelectedValue.src = getCustomEnhancedDropdownItemFontAssetUrl(selectedVariant)
|
|
customSelectedValue.alt = getCustomEnhancedDropdownItemFontAssetAltTag(selectedVariant)
|
|
|
|
const selectElement = document.querySelector('.shx-custom-enhanced-dropdown-font-hide-dummy-select');
|
|
|
|
// Set the selected option in the original select element
|
|
selectElement.value = selectedVariant;
|
|
|
|
// Trigger change event
|
|
const eventChange = new Event('change', { bubbles: true });
|
|
selectElement.dispatchEvent(eventChange);
|
|
|
|
// Remove the selected style from all items
|
|
document.querySelectorAll('#shx-custom-enhanced-dropdown-font-dropdown-content div').forEach(div => {
|
|
div.classList.remove('shx-custom-enhanced-dropdown-variant-selected');
|
|
});
|
|
|
|
// Add the selected style to the clicked item
|
|
event.currentTarget.classList.add('shx-custom-enhanced-dropdown-variant-selected');
|
|
|
|
document.getElementById("shx-custom-enhanced-dropdown-font-dropdown-content").style.display = 'none';
|
|
}
|
|
|
|
function loadCustomEnhancedDropdownDefaultSelectedValue() {
|
|
// timeout is needed because the other elements needs to be added to the dom
|
|
setTimeout(() => {
|
|
const customSelectedValue = document.getElementById('shx-custom-enhanced-dropdown-font-select-selected-value');
|
|
const selectElement = document.querySelector('.shx-custom-enhanced-dropdown-font-hide-dummy-select');
|
|
|
|
customSelectedValue.src = getCustomEnhancedDropdownItemFontAssetUrl(selectElement.value);
|
|
customSelectedValue.alt = getCustomEnhancedDropdownItemFontAssetAltTag(selectElement.value);
|
|
}, 10)
|
|
};
|
|
|
|
// Close the dropdown if the user clicks outside of it
|
|
window.addEventListener('click', function(event) {
|
|
const dropdownContent = document.getElementById('shx-custom-enhanced-dropdown-font-dropdown-content');
|
|
|
|
if (!event.target.matches('#shx-custom-enhanced-dropdown-font-select-button')) {
|
|
if (dropdownContent.style.display === 'block') {
|
|
dropdownContent.style.display = 'none';
|
|
}
|
|
}
|
|
});
|
|
|
|
function SHX_IFC_genDropdownSelect(inputID, labelText, inputName, inputVal, options, section_id) {
|
|
let isInputShxFont = inputID === "shx-font"
|
|
|
|
let html = `
|
|
<label class="form__label custom shx-ifc-form_label" for="${inputID}-label">${labelText}</label>
|
|
<div class="field custom${isInputShxFont ? ' shx-custom-enhanced-dropdown-hide-dummy-select' : ''}">
|
|
<select id="${inputID}" form="product-form-${section_id}" name="properties[${inputName}]" class="field__input shx-custom-enhanced-dropdown-font-hide-dummy-select" style="height: 40px" onchange="document.querySelector('shx-input-forms').renderView(500)">
|
|
`;
|
|
|
|
let customDropdownHtml = "";
|
|
|
|
if (isInputShxFont) {
|
|
customDropdownHtml += `
|
|
<div class="shx-custom-enhanced-dropdown field">
|
|
<button class="shx-custom-enhanced-dropdown-button" onclick="toggleCustomEnhancedDropdownFont()" id="shx-custom-enhanced-dropdown-font-select-button">
|
|
<div style="display: flex; justify-content: space-between; align-items: center; pointer-events: none; height: 40px">
|
|
<div style="position: relative; top: 4px; width: 120px">
|
|
<img id="shx-custom-enhanced-dropdown-font-select-selected-value" alt="lade..." style="height: 28px"></img>
|
|
</div>
|
|
|
|
<div style="display: flex; align-items: center; gap: 8px">
|
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#131213"><path d="M480-344 240-584l56-56 184 184 184-184 56 56-240 240Z"/></svg>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
|
|
<div class="shx-custom-enhanced-dropdown-content" id="shx-custom-enhanced-dropdown-font-dropdown-content">
|
|
`
|
|
}
|
|
|
|
for(let i = 0; i < options.length; i++) {
|
|
let optionDisplayName = "";
|
|
let optionValue = "";
|
|
|
|
if(Array.isArray(options[i])) {
|
|
optionValue = options[i][0];
|
|
optionDisplayName = options[i][1];
|
|
} else {
|
|
optionValue = options[i];
|
|
optionDisplayName = options[i];
|
|
}
|
|
|
|
html += `<option value="${optionValue}" ${inputVal === optionValue ? 'selected' : ''}>${optionDisplayName}</option>`;
|
|
|
|
if (isInputShxFont) {
|
|
customDropdownHtml += `
|
|
<div data-value="${optionValue}" class="${inputVal === optionValue ? 'shx-custom-enhanced-dropdown-variant-selected' : ''}" onclick="onFontDropdownItemClick(event)" style="height: 60px">
|
|
<div style="height: 100%">
|
|
<img src="${getCustomEnhancedDropdownItemFontAssetUrl(optionValue)}" alt="${optionDisplayName}" style="height: 90%; width: 100%" />
|
|
</div>
|
|
</div>
|
|
`
|
|
}
|
|
}
|
|
html += `</select></div>`;
|
|
|
|
if (isInputShxFont) {
|
|
customDropdownHtml += `</div></div>`
|
|
|
|
html += customDropdownHtml
|
|
}
|
|
|
|
loadCustomEnhancedDropdownDefaultSelectedValue()
|
|
|
|
return html;
|
|
}
|
|
|
|
function SHX_IFC_genColorSelect(inputID, labelText, inputName, _inputVal, colorWhiteList, section_id) {
|
|
let options = [];
|
|
|
|
let inputVal = _inputVal;
|
|
|
|
let inputValJson = null;
|
|
|
|
if(typeof _inputVal === 'object') {
|
|
inputVal = _inputVal.id;
|
|
}
|
|
else{
|
|
try {
|
|
inputValJson = JSON.parse(_inputVal);
|
|
} catch(e) {
|
|
inputValJson = null;
|
|
}
|
|
|
|
if(inputValJson) {
|
|
inputVal = inputValJson.id;
|
|
}
|
|
}
|
|
|
|
if(!colorWhiteList || colorWhiteList.length === 0) {
|
|
options = [...sortedFilementIDs];
|
|
} else for(let i = 0; i < colorWhiteList.length; i++) {
|
|
if(FilamentList[colorWhiteList[i]]) {
|
|
options.push(colorWhiteList[i]);
|
|
} else {
|
|
console.error("Color not found in FilamentList", colorWhiteList[i]);
|
|
}
|
|
}
|
|
|
|
|
|
let html = `
|
|
<label class="form__label custom shx-ifc-form_label" for="${inputID}-label">${labelText}: <span class="shx-ifc-form_label_selected shx-ifc-form_label_selected_${inputID}">${SHX_getFilamentById(inputVal).name}</span></label>
|
|
<div id="${inputID}" class="shx-ifc-colorselect">
|
|
`;
|
|
|
|
|
|
// Iterate over the Map
|
|
for (let i = 0; i < options.length; i++) {
|
|
let color = options[i];
|
|
|
|
html += `
|
|
<input type="radio" id="${inputID}-${color}" class="shx-ifc-colorselect-input" form="product-form-${section_id}" name="properties[${inputName}]" value="${FilamentList[color].name} #${color}" ${inputVal === color ? 'checked' : ''}>
|
|
<label for="${inputID}-${color}" style="background-color: ${FilamentList[color].hex};">
|
|
`;
|
|
|
|
|
|
html += `<div class="shx-mat-container">`;
|
|
if(FilamentList[color].matte) {
|
|
html += `<span class="shx-mat-matte"></span>`;
|
|
}
|
|
|
|
if(FilamentList[color].silk) {
|
|
html += `<span class="shx-mat-silk"></span>`;
|
|
}
|
|
html += `</div>`;
|
|
|
|
html += `</label>`;
|
|
}
|
|
|
|
html += `</div>`;
|
|
|
|
return html;
|
|
}
|
|
|
|
function SHX_IFC_genSwatchSelect(inputID, labelText, inputName, inputVal, options, section_id) {
|
|
|
|
//console.log("inputVal", inputVal);
|
|
//console.log("options", options);
|
|
|
|
let html = `
|
|
<label class="form__label custom shx-ifc-form_label" for="${inputID}-label">${labelText}: <span class="shx-ifc-form_label_selected shx-ifc-form_label_selected_${inputID}">${options[inputVal].name}</span></label>
|
|
<div id="${inputID}" class="shx-ifc-watchselect">
|
|
`;
|
|
|
|
// Iterate over the Map
|
|
for (let swatch in options) {
|
|
|
|
setTimeout(() => {
|
|
document.querySelector(`#${inputID}-${swatch}`).addEventListener('change', (event) => {
|
|
document.querySelector('shx-input-forms').updateSelectSwatch(event, inputID, swatch, options);
|
|
});
|
|
}, 500);
|
|
|
|
let swatchObj = options[swatch];
|
|
|
|
//console.log("swatch",swatch);
|
|
|
|
html += `
|
|
<input type="radio" id="${inputID}-${swatch}" class="shx-ifc-swatchselect-input" form="product-form-${section_id}" name="properties[${inputName}]" value="${swatchObj.name}" ${inputVal === swatch ? 'checked' : ''}>
|
|
<label for="${inputID}-${swatch}" style="background-color: #eee; background: url('${swatchObj.imgUrl}'); background-size: cover;">
|
|
`;
|
|
|
|
html += `</label>`;
|
|
}
|
|
|
|
html += `</div>`;
|
|
|
|
return html;
|
|
}
|
|
const defaultStyle = `<style>.custom.form__label{margin-bottom: 0.6rem}.field.custom{margin-top: 0.6rem}.custom .field__input{padding-top:0.8rem}</style>`;
|
|
|
|
let globalInputFormsObj = {
|
|
"test1": {
|
|
"renderHTML": (section_id) => {
|
|
let html = defaultStyle;
|
|
|
|
// elementID, labeltext, shopping cart name, initial value, section_id
|
|
html += SHX_IFC_genTextInput('shx-text1', 'Custom Text 1', 'Text', SHX_IFC_getCurrentValue('test1', 'text1'), section_id);
|
|
html += SHX_IFC_genDropdownSelect('shx-font', 'Schriftart', 'Schriftart', SHX_IFC_getCurrentValue('test1', 'font'), ['LT Beverage', "Rose", 'Arial'], section_id);
|
|
|
|
return html;
|
|
}
|
|
},"test2": {
|
|
"renderHTML": (section_id) => {
|
|
let html = defaultStyle;
|
|
|
|
html += SHX_IFC_genTextInput('custom-text-1', 'Custom Text 1', 'Custom Text 1', SHX_IFC_getCurrentValue('test2', 'text1'), section_id);
|
|
html += SHX_IFC_genTextInput('custom-text-2', 'Custom Text 2', 'Custom Text 2', SHX_IFC_getCurrentValue('test2', 'text2'), section_id);
|
|
|
|
return html;
|
|
}
|
|
}, "84712": {
|
|
"renderHTML": (section_id) => {
|
|
let html = defaultStyle;
|
|
const id = "84712";
|
|
|
|
html += SHX_IFC_genTextInput('shx-text1', 'Text', 'Text', SHX_IFC_getCurrentValue(id, 'text1'), section_id);
|
|
html += SHX_IFC_genDropdownSelect('shx-font', 'Schriftart', 'Schriftart', SHX_IFC_getCurrentValue(id,'font'), ['LT Beverage', "Rose"], section_id);
|
|
html += SHX_IFC_genColorSelect('shx-color', 'Farbe', 'Farbe', SHX_IFC_getCurrentValue(id, 'color'), [], section_id);
|
|
|
|
return html;
|
|
}
|
|
}, "17200": {
|
|
"renderHTML": (section_id) => {
|
|
let html = defaultStyle;
|
|
const id = "17200";
|
|
|
|
html += SHX_IFC_genTextInput('shx-text1', 'Text', 'Text', SHX_IFC_getCurrentValue(id, 'text1'), section_id);
|
|
html += SHX_IFC_genDropdownSelect('shx-font', 'Schriftart', 'Schriftart', SHX_IFC_getCurrentValue(id, 'font'), ['LT Beverage', "Rose"], section_id);
|
|
html += SHX_IFC_genColorSelect('shx-color1', 'Farbe 1', 'Farbe 1', SHX_IFC_getCurrentValue(id, 'color1'), [], section_id);
|
|
html += SHX_IFC_genColorSelect('shx-color2', 'Farbe 2', 'Farbe 2', SHX_IFC_getCurrentValue(id, 'color2'), [], section_id);
|
|
|
|
return html;
|
|
}
|
|
}, "97548": {
|
|
"renderHTML": (section_id) => {
|
|
let html = defaultStyle;
|
|
const id = "97548";
|
|
|
|
html += SHX_IFC_genTextInput('shx-text1', 'Text', 'Text', SHX_IFC_getCurrentValue(id, 'text1'), section_id);
|
|
html += SHX_IFC_genDropdownSelect('shx-font', 'Schriftart', 'Schriftart', SHX_IFC_getCurrentValue(id, 'font'), ['LT Beverage', "Rose"], section_id);
|
|
html += SHX_IFC_genColorSelect('shx-color1', 'Farbe 1', 'Farbe 1', SHX_IFC_getCurrentValue(id, 'color1'), [], section_id);
|
|
html += SHX_IFC_genColorSelect('shx-color2', 'Farbe 2', 'Farbe 2', SHX_IFC_getCurrentValue(id, 'color2'), [], section_id);
|
|
html += SHX_IFC_genColorSelect('shx-color3', 'Farbe 3', 'Farbe 3', SHX_IFC_getCurrentValue(id, 'color3'), [], section_id);
|
|
|
|
return html;
|
|
}
|
|
}, "68859": {
|
|
"renderHTML": (section_id) => {
|
|
let html = defaultStyle;
|
|
const id = "68859";
|
|
|
|
html += SHX_IFC_genTextInput('shx-text1', 'Text', 'Text', SHX_IFC_getCurrentValue(id, 'text1'), section_id, 32, true);
|
|
html += SHX_IFC_genDropdownSelect('shx-font', 'Schriftart', 'Schriftart', SHX_IFC_getCurrentValue(id, 'font'), ['LT Beverage', "Rose", "Arial", "Big Shoulders Stencil", "Cookii", "Monocraft"], section_id);
|
|
html += SHX_IFC_genDropdownSelect('shx-fontSize', 'Schriftgröße', 'Schriftgröße', SHX_IFC_getCurrentValue(id, 'fontSize'), [['Klein #small','Klein'], ["Normal #normal","Normal"], ["Groß #big","Groß"]], section_id);
|
|
html += SHX_IFC_genSwatchSelect('shx-backgroundType', 'Hintergrundtyp', 'Hintergrundtyp', SHX_IFC_getCurrentValue(id, 'backgroundType'), {"roundRect": {name: "Rechteckig abgerundet", imgUrl: "{{ "shx-text-w-bg-rect.png" | asset_url }}"}, "padding": {name: "Angepasst", imgUrl: "{{ "shx-text-w-bg-custom.png" | asset_url }}"}}, section_id);
|
|
html += SHX_IFC_genColorSelect('shx-color1', 'Textfarbe', 'Textfarbe', SHX_IFC_getCurrentValue(id, 'color1'), [], section_id);
|
|
html += SHX_IFC_genColorSelect('shx-color2', 'Hintergrundfarbe', 'Hintergrundfarbe', SHX_IFC_getCurrentValue(id, 'color2'), [], section_id);
|
|
|
|
return html;
|
|
}
|
|
}, "49340": {
|
|
"renderHTML": (section_id) => {
|
|
let html = defaultStyle;
|
|
const id = "49340";
|
|
|
|
html += SHX_IFC_genTextInput('shx-text1', 'Text', 'Text', SHX_IFC_getCurrentValue(id, 'text1'), section_id, 32, true);
|
|
html += SHX_IFC_genDropdownSelect('shx-font', 'Schriftart', 'Schriftart', SHX_IFC_getCurrentValue(id, 'font'), ['LT Beverage', "Rose", "Arial", "Big Shoulders Stencil", "Cookii", "Monocraft"], section_id);
|
|
html += SHX_IFC_genDropdownSelect('shx-fontSize', 'Schriftgröße', 'Schriftgröße', SHX_IFC_getCurrentValue(id, 'fontSize'), [['Klein #small','Klein'], ["Normal #normal","Normal"], ["Groß #big","Groß"]], section_id);
|
|
html += SHX_IFC_genColorSelect('shx-color1', 'Textfarbe', 'Textfarbe', SHX_IFC_getCurrentValue(id, 'color1'), [], section_id);
|
|
html += SHX_IFC_genColorSelect('shx-color2', 'Textumrandungsfarbe', 'Textumrandungsfarbe', SHX_IFC_getCurrentValue(id, 'color2'), [], section_id);
|
|
html += SHX_IFC_genColorSelect('shx-color3', 'Hintergrundfarbe', 'Hintergrundfarbe', SHX_IFC_getCurrentValue(id, 'color3'), [], section_id);
|
|
|
|
return html;
|
|
}
|
|
},
|
|
|
|
};
|
|
|
|
document.addEventListener("DOMContentLoaded", ()=>{
|
|
const forms = document.querySelector("form[novalidate]");
|
|
if(forms){
|
|
forms.removeAttribute("novalidate");
|
|
}
|
|
});
|
|
|
|
// create new html tag called "shx-input-forms"
|
|
class InputFormsElement extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
// element functionality written in here
|
|
this.currentVariant = null;
|
|
this.container = null;
|
|
|
|
this.uuid = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
|
|
|
|
this.section_id = null;
|
|
}
|
|
|
|
enableBuyButton() {
|
|
let buyButton = document.querySelector('.shopify-payment-button__button');
|
|
if(buyButton) {
|
|
buyButton.disabled = false;
|
|
buyButton.style.cursor = 'pointer';
|
|
buyButton.style.opacity = 1;
|
|
buyButton.style.pointerEvents = 'auto';
|
|
}
|
|
|
|
buyButton = document.querySelector('.shopify-payment-button__more-options');
|
|
if(buyButton) {
|
|
buyButton.disabled = false;
|
|
}
|
|
|
|
this.requiredPlaceholder.value = '';
|
|
this.requiredPlaceholder.required = false;
|
|
}
|
|
|
|
disableBuyButton() {
|
|
let buyButton = document.querySelector('.shopify-payment-button__button');
|
|
if(buyButton) {
|
|
buyButton.disabled = true;
|
|
buyButton.style.cursor = 'not-allowed';
|
|
buyButton.style.opacity = 0.5;
|
|
buyButton.style.pointerEvents = 'none';
|
|
}
|
|
|
|
buyButton = document.querySelector('.shopify-payment-button__more-options');
|
|
if(buyButton) {
|
|
buyButton.disabled = true;
|
|
}
|
|
|
|
this.requiredPlaceholder.value = '';
|
|
this.requiredPlaceholder.required = true;
|
|
}
|
|
|
|
showLoadingSpinner() {
|
|
this.loadingSpinner.show();
|
|
this.disableBuyButton();
|
|
}
|
|
|
|
showLoadingSpinnerError() {
|
|
this.loadingSpinner.showError("Hoppla, da ist etwas schief gelaufen. Bitte versuche es später erneut.");
|
|
this.disableBuyButton();
|
|
}
|
|
|
|
showLoadingSpinnerErrorChar() {
|
|
this.loadingSpinner.showErrorCharLottie("Hoppla, der von dir eingegebene Text ist zu lang. Bitte kürze ihn oder wende dich an uns für eine individuelle Lösung.");
|
|
this.disableBuyButton();
|
|
|
|
{%comment %}
|
|
// if font size is not small, set it to small
|
|
// most users are not changing the font size, so we set it for them
|
|
// because they only want to generate the product and not to change the font size
|
|
// so with this we will keep the user flow and the user will not be confused
|
|
{% endcomment %}
|
|
|
|
if(document.querySelector('#shx-fontSize').value !== 'Klein #small') {
|
|
document.querySelector('#shx-fontSize').value = 'Klein #small';
|
|
document.querySelector('#shx-fontSize').dispatchEvent(new Event('change'));
|
|
|
|
// show info text that the text is too long and we set the font size to small
|
|
this.infoText.style.color = 'red';
|
|
this.infoText.innerHTML = 'Text ist zu lang. Wir haben die <span style="font-weight: 600">Schriftgröße</span> auf <span style="font-weight: 600">klein</span> gesetzt. Bitte überprüfe deinen Text.';
|
|
document.querySelector('#shx-info-text').style.display = 'block';
|
|
|
|
// hide the text after 8 seconds
|
|
this.infoTextTimeout = setTimeout(() => {
|
|
document.querySelector('#shx-info-text').style.display = 'none';
|
|
}, 8000);
|
|
}
|
|
}
|
|
|
|
hideLoadingSpinner() {
|
|
this.loadingSpinner.hide();
|
|
this.enableBuyButton();
|
|
}
|
|
|
|
iFrameListener(event) {
|
|
|
|
////console.log("event.origin||", "'"+event.origin+"'", event.origin !== "https://3d-viewer.shinnex.de")
|
|
if(event.origin !== {% if shx_get_environment contains "development" %}"https://3dview.wasgehtsiedasan.shinnex.de"{% else %}"https://3d-viewer.shinnex.de"{% endif %}) return;
|
|
//console.log("event.data||",event.data)
|
|
|
|
if(event.data === undefined) return;
|
|
|
|
let data;
|
|
try {
|
|
data = JSON.parse(event.data)["shx-3d-viewer"];
|
|
} catch(e) {
|
|
return;
|
|
}
|
|
|
|
let uuid =this.uuid;
|
|
//console.log("uuid", uuid);
|
|
if(data.id !== this.uuid) {
|
|
if(data.status === "init" ) {
|
|
const initData = JSON.stringify({"init":{"uuid":uuid}});
|
|
//console.log("initData", initData );
|
|
this.Viewer3D.contentWindow.postMessage(initData, "*");
|
|
|
|
this.showLoadingSpinner();
|
|
this.renderView();
|
|
}
|
|
return;
|
|
};
|
|
|
|
if(data.status === "error") {
|
|
if(data.errorMessage === "TooLong") {
|
|
this.showLoadingSpinnerErrorChar();
|
|
return;
|
|
}
|
|
|
|
this.showLoadingSpinnerError();
|
|
return;
|
|
}
|
|
|
|
//console.log("Message received from the child: ", data); // Message received from child
|
|
|
|
if(data.loaded === true) {
|
|
this.hideLoadingSpinner();
|
|
} else {
|
|
this.showLoadingSpinner();
|
|
}
|
|
|
|
}
|
|
|
|
connectedCallback() {
|
|
|
|
let iFrameListener = this.iFrameListener.bind(this);
|
|
|
|
window.addEventListener('message', function(event) {
|
|
iFrameListener(event);
|
|
});
|
|
|
|
this.section_id = this.getAttribute('section_id');
|
|
|
|
this.innerHTML = '<div class="shx-input-forms-container"><div class="shx-input-forms-content"></div></div>';
|
|
this.container = this.querySelector('.shx-input-forms-container');
|
|
this.container.style.height = '0px';
|
|
|
|
this.content = this.container.querySelector('.shx-input-forms-content');
|
|
|
|
this.Viewer3DContainer = document.createElement('div');
|
|
this.Viewer3DContainer.classList.add('shx-threejs-renderer-container');
|
|
this.Viewer3DContainer.innerHTML = `{% render 'shx-loading-spinner', content_type:"body" %}`;
|
|
this.loadingSpinner = this.Viewer3DContainer.querySelector('shx-loading-spinner');
|
|
this.container.appendChild(this.Viewer3DContainer);
|
|
|
|
|
|
function createIFrame() {
|
|
this.Viewer3D = document.createElement('iframe');
|
|
|
|
const Viewer3D = this.Viewer3D;
|
|
|
|
this.Viewer3D.src = {% if shx_get_environment contains "development" %}"https://3dview.wasgehtsiedasan.shinnex.de/"{% else %}"https://3d-viewer.shinnex.de/"{% endif %};
|
|
this.Viewer3D.classList.add('shx-threejs-renderer');
|
|
this.Viewer3D.style.width = this.container.offsetWidth + 'px';
|
|
this.Viewer3D.style.height = this.container.offsetWidth + 'px';
|
|
|
|
this.Viewer3DContainer.appendChild(this.Viewer3D);
|
|
|
|
this.requiredPlaceholder = document.createElement('input');
|
|
this.requiredPlaceholder.type = 'checkbox';
|
|
this.requiredPlaceholder.classList.add('invisibleInput');
|
|
this.requiredPlaceholder.setAttribute('form', 'product-form-' + this.section_id);
|
|
this.requiredPlaceholder.name = 'properties[Checkbox]';
|
|
this.requiredPlaceholder.required = true;
|
|
this.requiredPlaceholder.checked = false; // Default unchecked
|
|
this.requiredPlaceholder.addEventListener('input', (event) => {
|
|
event.target.checked = false;
|
|
return false;
|
|
});
|
|
|
|
this.Viewer3DContainer.appendChild(this.requiredPlaceholder);
|
|
|
|
this.invisibleProductID = document.createElement('input');
|
|
this.invisibleProductID.type = 'input';
|
|
this.invisibleProductID.classList.add('invisibleInput');
|
|
this.invisibleProductID.setAttribute('form', 'product-form-' + this.section_id);
|
|
this.invisibleProductID.name = 'properties[ID]';
|
|
this.invisibleProductID.required = false;
|
|
this.invisibleProductID.value = this.currentVariant;
|
|
this.invisibleProductID.addEventListener('input', (event) => {
|
|
event.target.checked = false;
|
|
return false;
|
|
});
|
|
|
|
this.Viewer3DContainer.appendChild(this.invisibleProductID);
|
|
|
|
// create text below the iframe for information if the text is too long and we set the font size to small
|
|
|
|
this.infoText = document.createElement('span');
|
|
this.infoText.id = 'shx-info-text';
|
|
this.infoText.style.display = 'none';
|
|
this.container.appendChild(this.infoText);
|
|
}
|
|
|
|
setTimeout(createIFrame.bind(this), 1000);
|
|
}
|
|
|
|
initCurrentVariant(id) {
|
|
this.currentVariant = id;
|
|
|
|
// edit inner html
|
|
this.reloadCurrentVariant(id, true);
|
|
}
|
|
|
|
disconnectedCallback() {
|
|
// Clean up the element when it is removed from the DOM.
|
|
}
|
|
|
|
renderView(debounteTime = 1500) {
|
|
/*let currentTimeout = this.renderViewDebounce;
|
|
if(currentTimeout) {
|
|
clearTimeout(currentTimeout);
|
|
}
|
|
|
|
this.renderViewDebounce = setTimeout(this._renderView.bind(this), debounteTime);*/
|
|
this._renderView();
|
|
}
|
|
|
|
_renderView() {
|
|
// request data from server
|
|
let tJS = this.tJS;
|
|
|
|
// update globalInputFormsObjValues from input fields
|
|
for(let key in globalInputFormsObj) {
|
|
if(key === this.currentVariant) {
|
|
let inputs = this.content.querySelectorAll('input');
|
|
|
|
for(let i = 0; i < inputs.length; i++) {
|
|
let input = inputs[i];
|
|
|
|
if(input.type === 'radio') {
|
|
if(input.checked) {
|
|
|
|
if(input.classList.contains('shx-ifc-colorselect-input')) {
|
|
let _name = input.id.replace('shx-', '');
|
|
let name = _name.slice(0, _name.indexOf('-'));
|
|
|
|
let filamentID = _name.slice(_name.indexOf('-') + 1);
|
|
|
|
//console.log('filamentID', filamentID);
|
|
|
|
let filament = SHX_getFilamentById(filamentID);
|
|
|
|
SHX_IFC_setCurrentValue(key, name, JSON.stringify(filament));
|
|
} else if(input.classList.contains('shx-ifc-swatchselect-input')) {
|
|
let name = input.id.replace('shx-', '');
|
|
|
|
let swatchID = name.slice(0, name.indexOf('-'));
|
|
let swatchValue = name.slice(name.indexOf('-') + 1);
|
|
|
|
SHX_IFC_setCurrentValue(key, swatchID, swatchValue);
|
|
|
|
|
|
|
|
//console.log("swatch selected", key, swatchID, swatchValue );
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
let name = input.id.replace('shx-', '');
|
|
SHX_IFC_setCurrentValue(key, name, input.value);
|
|
}
|
|
}
|
|
|
|
let selects = this.content.querySelectorAll('select');
|
|
for(let i = 0; i < selects.length; i++) {
|
|
let name = selects[i].id.replace('shx-', '');
|
|
let options = selects[i].querySelectorAll('option');
|
|
for(let j = 0; j < options.length; j++) {
|
|
if(options[j].selected) {
|
|
SHX_IFC_setCurrentValue(key, name, options[j].value);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// check if some values are empty ""
|
|
for(let key in globalInputFormsObjValues[this.currentVariant]) {
|
|
if(globalInputFormsObjValues[this.currentVariant][key].replaceAll(" ", "") === "") {
|
|
//console.log("Empty value found", key);
|
|
this.disableBuyButton();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(this.Viewer3D)
|
|
this.Viewer3D.contentWindow.postMessage(JSON.stringify({"changeView":{"currentVariant": this.currentVariant, values: globalInputFormsObjValues[this.currentVariant]}}), "*");
|
|
|
|
//this.showLoadingSpinner();
|
|
}
|
|
|
|
updateSelectColorSwatch(event) {
|
|
let target = event.target;
|
|
|
|
let inputID = target.id.slice(0, target.id.lastIndexOf('-'));
|
|
let filamentID = target.id.slice(target.id.lastIndexOf('-') + 1);
|
|
|
|
|
|
let filament = SHX_getFilamentById(filamentID);
|
|
document.querySelector('.shx-ifc-form_label_selected_' + inputID).innerHTML = filament.name;
|
|
|
|
|
|
this.renderView(200);
|
|
}
|
|
|
|
updateSelectSwatch(event, inputID, swatch, options) {
|
|
let target = event.target;
|
|
|
|
document.querySelector('.shx-ifc-form_label_selected_' + inputID).innerHTML = options[swatch].name;
|
|
|
|
this.renderView(200);
|
|
}
|
|
|
|
reloadCurrentVariant(id, openAnimation = false) {
|
|
this.currentVariant = id;
|
|
let content = this.content;
|
|
let container = this.container;
|
|
|
|
|
|
|
|
// edit inner html
|
|
content.innerHTML = "";
|
|
|
|
|
|
for(let key in globalInputFormsObj) {
|
|
if(key === this.currentVariant) {
|
|
content.innerHTML = globalInputFormsObj[key].renderHTML(this.section_id);
|
|
}
|
|
}
|
|
|
|
const inputs = content.querySelectorAll('input');
|
|
|
|
for(let i = 0; i < inputs.length; i++) {
|
|
if(inputs[i].type === 'radio' && inputs[i].classList.contains('shx-ifc-colorselect-input')) {
|
|
inputs[i].addEventListener('change', this.updateSelectColorSwatch.bind(this));
|
|
}
|
|
}
|
|
|
|
//console.log('reloadCurrentVariant', id, openAnimation);
|
|
|
|
|
|
if(openAnimation) {
|
|
// calculate of this height
|
|
container.style.height = 'auto';
|
|
let height = container.offsetHeight;
|
|
container.style.height = '0px';
|
|
|
|
function animate() {
|
|
anime({
|
|
targets: container,
|
|
height: height,
|
|
duration: 500,
|
|
easing: 'cubicBezier(0.590, 0.190, 0.050, 0.990)',
|
|
complete: function() {
|
|
container.style.height = 'auto';
|
|
container.style.overflow = 'visible';
|
|
}
|
|
});
|
|
}
|
|
|
|
//animejs fade in
|
|
//dom ready
|
|
|
|
if (document.getElementById('animejs-script').readyState === 'complete' || document.getElementById('animejs-script').readyState === 'loaded'){
|
|
animate();
|
|
} else {
|
|
document.getElementById('animejs-script').addEventListener('load', function() {
|
|
animate();
|
|
});
|
|
}
|
|
} else {
|
|
container.style.opacity = 0;
|
|
anime({
|
|
targets: container,
|
|
opacity: 1,
|
|
duration: 500,
|
|
easing: 'cubicBezier(0.590, 0.190, 0.050, 0.990)'
|
|
});
|
|
}
|
|
|
|
this.renderView();
|
|
}
|
|
}
|
|
|
|
customElements.define('shx-input-forms', InputFormsElement);
|
|
|
|
|
|
</script>
|
|
|
|
{% endif %}
|
|
|