Quotation Fill out the form below and our experienced team will provide you with a complementary quotation and are happy to discuss your requirements as needed. If our form options don’t suit please feel free to use our contact page or call on 0141 332 9077. * Indicates required fields CUSTOMER TYPE * Commercial/BusinessPersonalUniversity/SchoolNon Profit Email address * Quote name or reference ADD MATERIALS TO QUOTE * Fill out the specifications below, then hit the 'Add to Quote' button to save this item to your list. Sheet / FilmRodTubeOther MATERIAL NAME * AcrylicLexanPolycarbonatePVCStyrenePolypropylenePolyethyleneNylonAcetalGRPAluminium CompositeMultiwall PolycarbonatePVC FOAMOther Thickness (mm) * Width (mm) * Length (mm) * Number of pieces * Instructions and material details (eg. colour, texture, grade, cutting/fabrication instructions) MATERIAL NAME * AcrylicPolycarbonatePVCNylonAcetalPolyethylene Diameter (mm) * Length (mm) * Number of pieces * Instructions and material details (eg. colour, texture, grade, cutting/fabrication instructions) MATERIAL NAME * AcrylicPolycarbonatePVCNylonAcetal Outside Diameter (mm) * Inside Diameter (mm) * Length (mm) * Number of pieces * Instructions and material details (eg. colour, texture, grade, cutting/fabrication instructions) MATERIAL NAME 5 * AcrylicLexanPolycarbonatePVCStyrenePolypropylenePolyethyleneNylonAcetalGRPAluminium CompositeMultiwall PolycarbonatePVC FOAMOther Number of pieces * Instructions and material details (eg. colour, texture, grade, cutting/fabrication instructions) + Add to Quote You must click this button to add this specific material to your summary before sending. Your selection will appear in the box below once added. INCLUDED QUOTE MATERIALS NEED A FABRICATED PART? YesNo UPLOAD A DRAWING OF PROJECT SPECIFICATIONS Accepted file types: pdf | png | jpg | stp | sld | sldasm | dxf | dwg | xls | xlsx. Max. file size: 10 MB. Tell us about your application (Provide comments or details to help us expedite your request) PROVIDE YOUR CONTACT INFORMATION First Name * Last Name * Company No. of Employees 0-1011-2021-5051-100100+ Job Title Telephone Number * Address * City / Town * Post Code * ⚠️ Please add at least one material to your quote list using the yellow "+ Add to Quote" button above before submitting. function createHiddenInput(name, value) { const input = document.createElement("input"); input.type = "hidden"; input.name = name; input.value = value || ''; return input; } // NEW HELPER: Keeps the hidden validation field in sync with the list count function updateValidationCount() { const totalEntries = document.querySelectorAll('.quote-entry').length; const validationInput = document.getElementById("quote-validation-count"); const errorMsg = document.getElementById("quote-error-msg"); if (totalEntries > 0) { validationInput.value = totalEntries; // Populates field, satisfying CF7 requirement errorMsg.style.display = "none"; // Hides the error message if visible } else { validationInput.value = ""; // Empties field, causing CF7 to reject submission } } function getMaterialDetails() { const type = document.querySelector('input[name="ADD-MATERIALS-TO-QUOTE"]:checked')?.value; if (!type) { alert("Please select a material type"); return null; } let material, quantity, details = "", instructions = ""; let materialSuffix = ""; switch(type) { case "Sheet / Film": materialSuffix = "sheet"; material = document.querySelector(`select[name="Material-${materialSuffix}"]`).value; quantity = document.querySelector(`input[name="Number-of-pieces-${materialSuffix}"]`).value; const thickness = document.querySelector(`input[name="Sheet-Thickness"]`).value; const width = document.querySelector(`input[name="Sheet-Width"]`).value; const length = document.querySelector(`input[name="Sheet-Length"]`).value; instructions = document.querySelector(`textarea[name="instructions-and-materials-${materialSuffix}"]`).value; details = `Thickness: ${thickness}mm, Width: ${width}mm, Length: ${length}mm`; break; case "Rod": materialSuffix = "rod"; material = document.querySelector(`select[name="Material-${materialSuffix}"]`).value; quantity = document.querySelector(`input[name="Number-of-pieces-${materialSuffix}"]`).value; const diameter = document.querySelector(`input[name="Diameter"]`).value; const rodLength = document.querySelector(`input[name="Rod-Length"]`).value; instructions = document.querySelector(`textarea[name="instructions-and-materials-${materialSuffix}"]`).value; details = `Diameter: ${diameter}mm, Length: ${rodLength}mm`; break; case "Tube": materialSuffix = "tube"; material = document.querySelector(`select[name="Material-${materialSuffix}"]`).value; quantity = document.querySelector(`input[name="Number-of-pieces-${materialSuffix}"]`).value; const outsideDiameter = document.querySelector(`input[name="Outside-diameter"]`).value; const insideDiameter = document.querySelector(`input[name="Inside-diameter"]`).value; const tubeLength = document.querySelector(`input[name="Tube-Length"]`).value; instructions = document.querySelector(`textarea[name="instructions-and-materials-${materialSuffix}"]`).value; details = `Outside Diameter: ${outsideDiameter}mm, Inside Diameter: ${insideDiameter}mm, Length: ${tubeLength}mm`; break; case "Other": materialSuffix = "other"; material = document.querySelector(`select[name="Material-${materialSuffix}"]`).value; quantity = document.querySelector(`input[name="Number-of-pieces-${materialSuffix}"]`).value; instructions = document.querySelector(`textarea[name="instructions-and-materials-${materialSuffix}"]`).value; if (instructions) { details = instructions; } break; default: return null; } if (!material || !quantity) { alert("Please fill out all required fields"); return null; } return { type, material, quantity, details, instructions, materialSuffix }; } document.addEventListener("DOMContentLoaded", function () { const addToQuoteButton = document.getElementById("add-to-quote"); const quoteSummary = document.getElementById("quote-summary"); addToQuoteButton.addEventListener("click", function () { const materialData = getMaterialDetails(); if (!materialData) return; const { type, material, quantity, details, instructions, materialSuffix } = materialData; const quoteIndex = document.querySelectorAll('.quote-entry').length + 1; const quoteEntry = document.createElement("div"); quoteEntry.classList.add("quote-entry"); quoteEntry.style.marginBottom = "10px"; quoteEntry.style.borderBottom = "1px solid #ddd"; quoteEntry.style.paddingBottom = "10px"; quoteEntry.innerHTML = ` ${type} - ${material} Quantity: ${quantity} ${details ? `Details: ${details}` : ''} ${instructions ? `Instructions: ${instructions}` : ''} Delete `; quoteSummary.appendChild(quoteEntry); quoteSummary.appendChild(createHiddenInput(`quote_item_${quoteIndex}_type`, `${type} - ${material}`)); quoteSummary.appendChild(createHiddenInput(`quote_item_${quoteIndex}_quantity`, quantity)); if (details) quoteSummary.appendChild(createHiddenInput(`quote_item_${quoteIndex}_details`, details)); if (instructions) quoteSummary.appendChild(createHiddenInput(`quote_item_${quoteIndex}_instructions`, instructions)); quoteSummary.appendChild(createHiddenInput(`quote_item_${quoteIndex}_materialSuffix`, materialSuffix)); // Update validation check after adding an item updateValidationCount(); }); // Handle Delete functionality quoteSummary.addEventListener("click", function(e) { const target = e.target; const entry = target.closest(".quote-entry"); if (!entry) return; if (target.classList.contains("delete-entry")) { const index = Array.from(quoteSummary.querySelectorAll('.quote-entry')).indexOf(entry); const hiddenInputs = quoteSummary.querySelectorAll(`input[name^="quote_item_${index + 1}_"]`); hiddenInputs.forEach(input => input.remove()); entry.remove(); const remainingEntries = quoteSummary.querySelectorAll('.quote-entry'); remainingEntries.forEach((entry, idx) => { const hiddenInputs = quoteSummary.querySelectorAll(`input[name^="quote_item_${idx + 2}_"]`); hiddenInputs.forEach(input => { const parts = input.name.split('_'); parts[2] = idx + 1; input.name = parts.join('_'); }); }); // Update validation check after deleting an item updateValidationCount(); } }); // CATCH BLANK SUBMISSIONS: Intercept the CF7 submit try if count is 0 const formElement = document.querySelector('.wpcf7-form'); if (formElement) { formElement.addEventListener('submit', function(e) { const totalEntries = document.querySelectorAll('.quote-entry').length; if (totalEntries === 0) { e.preventDefault(); // Halt the form submit e.stopImmediatePropagation(); const errorMsg = document.getElementById("quote-error-msg"); errorMsg.style.display = "block"; // Make the red reminder visible // Scroll the window smoothly back up to the material layout card to fix it document.querySelector('.material-builder-card').scrollIntoView({ behavior: 'smooth', block: 'center' }); } }); } });