{"barcodes":[{"referrers":[-1],"id":1,"name":"EAN_13 1","createdAt":"0000-00-00 00:00:00","updatedAt":"2017-04-07 12:20:03","type":"GTIN_13","code":"4250489631226"}],"defaultCategories":[{"id":1003,"right":"all","sitemap":true,"parentCategoryId":986,"level":4,"linklist":true,"type":"item","updatedAt":"2021-12-27T17:07:39+01:00","manually":true,"plentyId":22632}],"filter":{"hasManufacturer":true,"isSalable":true,"isSalableAndActive":true,"hasActiveChildren":false},"images":{"all":[{"names":{"imageId":29195,"lang":"de","name":"Klassische silberfarbene extrakurze Krawattennadel","alternate":"Sch\u00f6ne silberne extrakurze Krawattennadel"},"path":"S3:8572:teroon-krawattennadel-kurz1.jpg","position":0,"url":"https:\/\/cdn02.plentyone.com\/f2d5nd8wf1gh\/item\/images\/8572\/full\/teroon-krawattennadel-kurz1.jpg","urlMiddle":"https:\/\/cdn02.plentyone.com\/f2d5nd8wf1gh\/item\/images\/8572\/middle\/teroon-krawattennadel-kurz1.jpg","urlPreview":"https:\/\/cdn02.plentyone.com\/f2d5nd8wf1gh\/item\/images\/8572\/preview\/teroon-krawattennadel-kurz1.jpg","urlSecondPreview":"https:\/\/cdn02.plentyone.com\/f2d5nd8wf1gh\/item\/images\/8572\/secondPreview\/teroon-krawattennadel-kurz1.jpg","cleanImageName":"teroon-krawattennadel-kurz1.jpg"},{"names":{"imageId":41467,"lang":"de","name":"Hochwertiges Krawattennadel Etui","alternate":"Robustes Krawattennadel Etui"},"path":"S3:8572:Teroon-etui-1023.jpg","position":1,"url":"https:\/\/cdn02.plentyone.com\/f2d5nd8wf1gh\/item\/images\/8572\/full\/Teroon-etui-1023.jpg","urlMiddle":"https:\/\/cdn02.plentyone.com\/f2d5nd8wf1gh\/item\/images\/8572\/middle\/Teroon-etui-1023.jpg","urlPreview":"https:\/\/cdn02.plentyone.com\/f2d5nd8wf1gh\/item\/images\/8572\/preview\/Teroon-etui-1023.jpg","urlSecondPreview":"https:\/\/cdn02.plentyone.com\/f2d5nd8wf1gh\/item\/images\/8572\/secondPreview\/Teroon-etui-1023.jpg","cleanImageName":"Teroon-etui-1023.jpg"}],"variation":[]},"item":{"id":8572,"add_cms_page":0,"condition":{"id":0,"names":{"lang":"de","name":"Neu"}},"free2":"100160T2","free20":0,"storeSpecial":{"id":2,"names":{"lang":"de","name":"Neuheit"}},"manufacturerId":26,"producingCountryId":1,"revenueAccount":0,"conditionApi":{"id":0,"names":{"lang":"de","name":"Neu"}},"ageRestriction":0,"itemType":"default","customsTariffNumber":"","producingCountry":{"names":{"name":" Deutschland","lang":"de"},"active":1,"shippingDestinationId":101,"name":"Germany","isCountryStateMandatory":null,"storehouseId":0,"id":1,"lang":"de","isoCode2":"DE","isoCode3":"DEU"},"manufacturer":{"id":26,"name":"TEROON","legalName":"Grom Schmuck","logo":"\/images\/gallery\/producer\/teroon.jpg","url":"","contactUrl":"","street":"Siemensstr.","email":"info@grom-schmuck.de","position":0,"responsibleName":"Torsten Grom","responsibleStreet":"Siemensstr.","responsibleHouseNo":"42","responsiblePostCode":"75217","responsibleTown":"Birkenfeld","responsibleCountry":1,"responsibleEmail":"info@grom-schmuck.de","responsibleContactUrl":"Torsten Grom","responsiblePhoneNo":"+49 (0)7231 7833570","pixmaniaBrandId":0,"neckermannBrandId":0,"externalName":"TEROON","neckermannAtEpBrandId":0,"postcode":"75217","houseNo":"42","town":"Birkenfeld","countryId":1,"phoneNumber":"+49 (0)7231 7833570","faxNumber":"","laRedouteBrandId":0,"comment":"","updatedAt":"2024-12-12T16:30:53+01:00","nameExternal":"TEROON","countryObject":{"names":[{"language":"de","id":1,"name":" Deutschland","country_id":1},{"country_id":1,"id":250,"name":"Germany","language":"en"}],"active":1,"shippingDestinationId":101,"name":" Deutschland","isCountryStateMandatory":null,"storehouseId":0,"id":1,"lang":"de","isoCode2":"DE","isoCode3":"DEU"},"responsibleCountryObject":{"names":[{"language":"de","id":1,"name":" Deutschland","country_id":1},{"country_id":1,"id":250,"name":"Germany","language":"en"}],"active":1,"shippingDestinationId":101,"name":" Deutschland","isCountryStateMandatory":null,"storehouseId":0,"id":1,"lang":"de","isoCode2":"DE","isoCode3":"DEU"}},"rebate":0,"salableVariationCount":1},"properties":[{"propertySelection":[],"propertyId":11,"propertySelectionId":null,"surcharge":0,"property":{"id":11,"position":0,"names":{"lang":"de","name":"Besonderheit","description":"","propertyId":11},"valueType":"text","isOderProperty":false,"isShownOnItemPage":true,"isShownOnItemList":false,"isShownAtCheckout":false,"surcharge":0},"group":{"id":18,"names":{"lang":"de","name":"Shop-Merkmale","description":"","propertyGroupId":18},"backendName":"Shop-Merkmale","orderPropertyGroupingType":"none","isSurchargePercental":false,"ottoComponent":0,"updatedAt":"2019-10-02T13:04:11+02:00"}},{"propertySelection":[],"propertyId":17,"propertySelectionId":null,"surcharge":0,"property":{"id":17,"position":0,"names":{"lang":"de","name":"Farbe","description":"","propertyId":17},"valueType":"text","isOderProperty":false,"isShownOnItemPage":true,"isShownOnItemList":true,"isShownAtCheckout":false,"surcharge":0},"group":{"id":18,"names":{"lang":"de","name":"Shop-Merkmale","description":"","propertyGroupId":18},"backendName":"Shop-Merkmale","orderPropertyGroupingType":"none","isSurchargePercental":false,"ottoComponent":0,"updatedAt":"2019-10-02T13:04:11+02:00"}},{"propertySelection":[],"propertyId":146,"propertySelectionId":null,"surcharge":0,"property":{"id":146,"position":3000,"names":{"lang":"de","name":"Gravur-Bild","description":"","propertyId":146},"valueType":"file","isOderProperty":true,"isShownOnItemPage":true,"isShownOnItemList":false,"isShownAtCheckout":true,"surcharge":0},"group":{"id":19,"names":{"lang":"de","name":"Gravur","description":"","propertyGroupId":19},"backendName":"Gravur","orderPropertyGroupingType":"none","isSurchargePercental":false,"ottoComponent":0,"updatedAt":"2016-04-27T18:30:38+02:00"}}],"texts":{"id":10626,"lang":"de","name2":"TEROON Krawattenklammer EXTRAKURZ","name3":"","description":"<p><li><b>Marke:<\/b> TEROON<\/p><\/li> <p><li><b>Oberfl\u00e4che:<\/b> Rhodium veredelt (silberfarben)<\/p><\/li> <p><li><b>Mechanik:<\/b> hochwertige und verschlei\u00dfarme Alligatorklemme<\/p><\/li> <p><li><b>Besonderheiten:<\/b> glanz-polierte Oberfl\u00e4che<\/p><\/li> <p><li><b>Farbe:<\/b> Silber<\/p><\/li> <p><li><b>Ma\u00dfe:<\/b> ca. 45 mm x 68 mm<\/p><\/li> <p><li><b>Gewicht:<\/b> ca. 8 g<\/p><\/li> <p><b>Im Lieferumfang ist das hochwertige Geschenk-Etui des Designers TEROON enthalten.<\/b><\/p>","title":"","itemId":8572,"metaDescription":"Glanz-polierte Oberfl\u00e4che und hochwertige Alligatorklemme \u2713 schneller Versand \u2713 \u00fcber 10.000 zufriedene Kunden \u279c Jetzt online bestellen","technicalData":"<p>TEROON ist eine Marke von Grom Schmuck aus der Goldstadt Pforzheim | Hochwertiges Geschenketui<\/p>\n<ul>\t<li>| | Rhodium veredelt (Farbton Silber) | hochwertige und verschlei\u00dfarme Alligatorklemme<\/li>\t<li>glanz-polierte Oberfl\u00e4che<\/li><\/ul>","urlPath":"krawattennadeln\/rhodium-silbern\/klassisch-dezent\/teroon-krawattenklammer-krawattennadel","name1":"TEROON Krawattenklammer EXTRAKURZ","shortDescription":"","keywords":""},"unit":{"names":{"unitId":1,"lang":"de","name":"St\u00fcck"},"unitOfMeasurement":"C62","content":1},"variation":{"position":0,"number":"631226","model":"631226","externalId":"100160T2","availabilityId":1,"estimatedAvailableAt":null,"maximumOrderQuantity":null,"minimumOrderQuantity":1,"intervalOrderQuantity":0,"availableUntil":null,"releasedAt":null,"name":"","weightG":100,"weightNetG":8,"widthMM":21,"lengthMM":45,"heightMM":6,"unitsContained":1,"bundleType":null,"mayShowUnitPrice":true,"availabilityUpdatedAt":"2019-03-20T02:45:05+01:00","availability":{"id":1,"icon":"av1.jpg","averageDays":1,"createdAt":"2019-08-07 11:02:36","updatedAt":"2019-08-07 11:02:36","names":{"id":22,"availabilityId":1,"lang":"de","name":"Sofort lieferbar","createdAt":"2021-10-25 11:55:10","updatedAt":"2021-10-25 11:55:10"},"iconPath":"\/tpl\/availability\/av1.jpg","mappedAvailability":"http:\/\/schema.org\/InStock"},"id":5874,"unitCombinationId":1},"hasOrderProperties":true,"hasRequiredOrderProperty":false,"hasOnlyRequiredAndPreselected":false,"prices":{"default":{"price":{"value":25,"formatted":"25,00\u00a0\u20ac"},"unitPrice":{"value":25,"formatted":"25,00\u00a0\u20ac"},"basePrice":"25,00\u00a0\u20ac \/ St\u00fcck","baseLot":1,"baseUnit":"C62","baseSinglePrice":25,"minimumOrderQuantity":1,"contactClassDiscount":{"percent":0,"amount":0},"categoryDiscount":{"percent":0,"amount":0},"currency":"EUR","lowestPrice":{"value":null,"formatted":""},"vat":{"id":0,"value":19},"isNet":false,"data":{"salesPriceId":1,"price":25,"priceNet":21.008403361345,"basePrice":25,"basePriceNet":21.008403361345,"unitPrice":25,"unitPriceNet":21.008403361345,"lowestPrice":null,"lowestPriceNet":null,"customerClassDiscountPercent":0,"customerClassDiscount":0,"customerClassDiscountNet":0,"categoryDiscountPercent":0,"categoryDiscount":0,"categoryDiscountNet":0,"vatId":0,"vatValue":19,"currency":"EUR","interval":"none","conversionFactor":1,"minimumOrderQuantity":"1.00","updatedAt":"2023-03-14 18:09:20","type":"default","pricePosition":1}},"rrp":{"price":{"value":0,"formatted":"0,00\u00a0\u20ac"},"unitPrice":{"value":0,"formatted":"0,00\u00a0\u20ac"},"basePrice":"0,00\u00a0\u20ac \/ St\u00fcck","baseLot":1,"baseUnit":"C62","baseSinglePrice":0,"minimumOrderQuantity":1,"contactClassDiscount":{"percent":0,"amount":0},"categoryDiscount":{"percent":0,"amount":0},"currency":"EUR","lowestPrice":{"value":null,"formatted":""},"vat":{"id":0,"value":19},"isNet":false,"data":{"salesPriceId":40,"price":0,"priceNet":0,"basePrice":0,"basePriceNet":0,"unitPrice":0,"unitPriceNet":0,"lowestPrice":null,"lowestPriceNet":null,"customerClassDiscountPercent":0,"customerClassDiscount":0,"customerClassDiscountNet":0,"categoryDiscountPercent":0,"categoryDiscount":0,"categoryDiscountNet":0,"vatId":0,"vatValue":19,"currency":"EUR","interval":"none","conversionFactor":1,"minimumOrderQuantity":"1.00","updatedAt":"2017-02-02 09:03:26","type":"rrp","pricePosition":2}},"set":null,"specialOffer":null,"graduatedPrices":[{"price":{"value":25,"formatted":"25,00\u00a0\u20ac"},"unitPrice":{"value":25,"formatted":"25,00\u00a0\u20ac"},"basePrice":"25,00\u00a0\u20ac \/ St\u00fcck","baseLot":1,"baseUnit":"C62","baseSinglePrice":25,"minimumOrderQuantity":1,"contactClassDiscount":{"percent":0,"amount":0},"categoryDiscount":{"percent":0,"amount":0},"currency":"EUR","lowestPrice":{"value":null,"formatted":""},"vat":{"id":0,"value":19},"isNet":false,"data":{"salesPriceId":1,"price":25,"priceNet":21.008403361345,"basePrice":25,"basePriceNet":21.008403361345,"unitPrice":25,"unitPriceNet":21.008403361345,"lowestPrice":null,"lowestPriceNet":null,"customerClassDiscountPercent":0,"customerClassDiscount":0,"customerClassDiscountNet":0,"categoryDiscountPercent":0,"categoryDiscount":0,"categoryDiscountNet":0,"vatId":0,"vatValue":19,"currency":"EUR","interval":"none","conversionFactor":1,"minimumOrderQuantity":"1.00","updatedAt":"2023-03-14 18:09:20","type":"default","pricePosition":1}}]},"facets":[],"attributes":[]}
3dView
$(document).ready(function () { setTimeout(function () { let cloned = $('#thumb-carousel .owl-item.active:last-child').clone(); $(cloned).attr('data-toggle', 'modal'); $(cloned).attr('href', '#modal-360'); $(cloned).attr('data-target', '#modal-360'); $(cloned).find('picture').attr('data-iesrc', 'https://www.pro-manschettenknoepfe.de/layout/promanschettenknoepfe/img/360grad_icon.jpg').attr('data-picture-class', 'https://www.pro-manschettenknoepfe.de/layout/promanschettenknoepfe/img/360grad_icon.jpg'); $(cloned).find('source').attr('srcset', 'https://www.pro-manschettenknoepfe.de/layout/promanschettenknoepfe/img/360grad_icon.jpg'); $(cloned).find('img').attr('src', 'https://www.pro-manschettenknoepfe.de/layout/promanschettenknoepfe/img/360grad_icon.jpg'); $(cloned).appendTo('#thumb-carousel .owl-stage'); }, 1000); });

TEROON Krawattenklammer EXTRAKURZ

Art.-Nr.: 631226

Art.-Nr.: 631226


function styleArticlePrice() { document.querySelectorAll('.widget-item-price').forEach(function(widget) { /* Erst alles zurücksetzen – wichtig bei Variantenwechsel */ widget.style.removeProperty('position'); widget.style.removeProperty('top'); const nextWidget = widget.nextElementSibling; if (nextWidget && nextWidget.classList.contains('vat')) { nextWidget.style.removeProperty('position'); nextWidget.style.removeProperty('top'); } const priceElements = Array.from(widget.querySelectorAll('*')).filter(function(el) { const text = el.textContent .replace(/\u00a0/g, ' ') .trim(); const isPurePrice = /^[0-9.,\s]+€$/.test(text); const hasPriceChild = Array.from(el.children).some(function(child) { const childText = child.textContent .replace(/\u00a0/g, ' ') .trim(); return /^[0-9.,\s]+€$/.test(childText); }); return isPurePrice && !hasPriceChild; }); if (priceElements.length === 0) { return; } let strikePrice = null; let currentPrice = null; priceElements.forEach(function(el) { const styles = window.getComputedStyle(el); const isStrike = el.tagName === 'DEL' || el.tagName === 'S' || el.tagName === 'STRIKE' || styles.textDecorationLine.indexOf('line-through') !== -1 || styles.textDecoration.indexOf('line-through') !== -1; if (isStrike) { strikePrice = el; } }); const normalPrices = priceElements.filter(function(el) { return el !== strikePrice; }); if (normalPrices.length > 0) { currentPrice = normalPrices.reduce(function(largest, el) { if (!largest) { return el; } const currentSize = parseFloat(window.getComputedStyle(el).fontSize); const largestSize = parseFloat(window.getComputedStyle(largest).fontSize); return currentSize > largestSize ? el : largest; }, null); } /* Aktuellen Verkaufspreis fett */ if (currentPrice) { currentPrice.style.setProperty('font-weight', '700', 'important'); } /* Nur bei vorhandenem Streichpreis */ if (strikePrice && currentPrice) { /* Abstand Streichpreis → aktueller Preis kompakter */ strikePrice.style.setProperty('margin-bottom', '0', 'important'); strikePrice.style.setProperty('line-height', '1', 'important'); currentPrice.style.setProperty('margin-top', '0', 'important'); currentPrice.style.setProperty('line-height', '1.1', 'important'); /* Gesamten Preisblock 14 px nach oben */ widget.style.setProperty('position', 'relative', 'important'); widget.style.setProperty('top', '-14px', 'important'); /* MwSt.-Zeile ebenfalls mit hochziehen */ if (nextWidget && nextWidget.classList.contains('vat')) { nextWidget.style.setProperty('position', 'relative', 'important'); nextWidget.style.setProperty('top', '-14px', 'important'); } } }); } styleArticlePrice(); setTimeout(styleArticlePrice, 200); setTimeout(styleArticlePrice, 800); document.addEventListener("onVariationChanged", function() { setTimeout(styleArticlePrice, 100); setTimeout(styleArticlePrice, 500); });
25,00 € *
Inhalt 1 Stück
Grundpreis 25,00 € / Stück
inkl. ges. MwSt. zzgl. 3,99 € Versandkosten
${ $store.getters.currentItemVariation.variation.availability.names.name }
function reloadAvailability() { if (ceresStore.getters.currentItemVariation.variation.availability.id < 3) { let shipToday = true; let shipTomorrow = true; const cutoffHours = 16; const todayStringWithTimeZoneEuropeBerlin = new Date().toLocaleString("en-US", {timeZone: "Europe/Berlin"}) const todayEuropeBerlin = new Date(Date.parse(todayStringWithTimeZoneEuropeBerlin)); let tomorrowEuropeBerlin = new Date(Number(todayEuropeBerlin)); tomorrowEuropeBerlin.setDate(todayEuropeBerlin.getDate() + 1); const dayOfWeekEuropeBerlin = todayEuropeBerlin.getDay(); var dd = String(todayEuropeBerlin.getDate()).padStart(2, '0'); var mm = String(todayEuropeBerlin.getMonth() + 1).padStart(2, '0'); var yyyy = todayEuropeBerlin.getFullYear(); var hh = todayEuropeBerlin.getHours(); var ii = todayEuropeBerlin.getMinutes(); const todayStringEuropeBerlin = yyyy + '-' + mm + '-' + dd; const tomorrowStringEuropeBerlin = tomorrowEuropeBerlin.getFullYear() + '-' + String(tomorrowEuropeBerlin.getMonth() + 1).padStart(2, '0') + '-' + String(tomorrowEuropeBerlin.getDate()).padStart(2, '0'); if (dayOfWeekEuropeBerlin === 0 || dayOfWeekEuropeBerlin === 6) { shipToday = false; } else if (hh > cutoffHours) { shipToday = false; } else { $.getJSON("https://feiertage-api.de/api/?jahr=2020&nur_land=BW", function (json) { $.each(json, function (i, item) { if (todayStringEuropeBerlin === item.datum) { shipToday = false; } if (tomorrowStringEuropeBerlin === item.datum) { shipTomorrow = false; } }); }); } if (!shipToday) { console.log(dayOfWeekEuropeBerlin + 1); if (dayOfWeekEuropeBerlin === 5 || dayOfWeekEuropeBerlin === 6) { shipTomorrow = false; } if (dd === '31' && mm === '12') { shipTomorrow = false; } } let displayHours; if ((cutoffHours - (hh + 1)) < 0) { displayHours = 0; } else { displayHours = cutoffHours - (hh + 1); } setTimeout(function () { if (shipToday) { var countdownText = ''; if (displayHours === 0) { countdownText = (60 - ii) + ' Min.'; } else if (displayHours === 1) { countdownText = '1 Std. ' + (60 - ii) + ' Min.'; } else { countdownText = displayHours + ' Std. ' + (60 - ii) + ' Min.'; } $('#shipping-countdown').html('Versand noch heute bei Bestellung innerhalb von ' + countdownText + '.'); } else { if (shipTomorrow) { $('#shipping-countdown').html('Wenn Sie noch heute bestellen, verlässt die Ware bereits morgen unser Lager.'); } else { $('#shipping-countdown').html('Ihre Bestellung wird vorbereitet, gepackt & schon am nächsten Werktag (Mo-Fr) an Sie versandt!'); } } }, 100); $('#shipping-countdown').css('display', 'block'); } else { $('#shipping-countdown').html(' '); } } document.addEventListener("onVariationChanged", () => { reloadAvailability(); }); reloadAvailability();
WhatsApp
Fragen? Direkt per WhatsApp
pro-manschettenknoepfe.de
(function () { 'use strict'; /* ========================================================= GROM – Live-Gravurvorschau v4.1 (v4.1: Vorschau verschwindet, wenn Gravurtext/Schriftart ausgeblendet werden) Gravurtext: Merkmal 109 Schriftart: Merkmal 110 Anmerkungen: Merkmal 120 (optional) Änderungen gegenüber v3: - Schutz gegen doppelte Einbindung - Keine veraltete Vorschau mehr bei schnellem Tippen (Render-Token) - Kurzes Debounce bei Eingabe - Canvas-Höhe passt exakt in die Box, keine Mindestbreite mehr (Mobil) - Lange Texte werden bei Web-Fonts nicht mehr abgeschnitten - Keine Browser-Ersatzschrift, falls ein Font nicht lädt - Platzhalter-Kästchen in den Sprites werden ausgefiltert - Vorschau funktioniert auch ohne "Anmerkungen"-Feld - Ungenutzter Code entfernt ========================================================= */ if (window.__gromGravurLiveInit) return; window.__gromGravurLiveInit = true; const PREVIEW_H = 52; /* Innenhöhe der Box: 62px - 2 * 5px Padding */ const BASE_SOURCE_PX = 180; const MAX_TEMP_W = 6000; const WEB_FONTS = { "AZURE": { family: "GromAzure", url: "https://cdn02.plentyone.com/f2d5nd8wf1gh/frontend/gravur-fonts/AZURE.otf", format: "opentype" }, "Baby Script 42": { family: "GromBabyScript42", url: "https://cdn02.plentyone.com/f2d5nd8wf1gh/frontend/gravur-fonts/Baby_Script_42.otf", format: "opentype" }, "Optima 3L": { family: "GromOptima3L", url: "https://cdn02.plentyone.com/f2d5nd8wf1gh/frontend/gravur-fonts/Optima_3L.TTF", format: "truetype" }, "Script 4L": { family: "GromScript4L", url: "https://cdn02.plentyone.com/f2d5nd8wf1gh/frontend/gravur-fonts/Script_4L.otf", format: "opentype" } }; const CFG = { "Script Rund 1L": { sprite: "https://cdn02.plentyone.com/f2d5nd8wf1gh/frontend/gravur-fonts/script-rund-1l-sprite-v3.png", /* Diese Slots enthalten nur Platzhalter-Kästchen (identische bbox) */ blocked: [91, 93, 94, 95, 96, 123, 124, 125], metrics: {"cellW":192,"cellH":160,"cols":16,"firstCodepoint":32,"metrics":{"32":{"advance":52,"bbox":null},"33":{"advance":40,"bbox":[82,27,114,114]},"34":{"advance":44,"bbox":[79,26,115,41]},"35":{"advance":61,"bbox":[71,27,124,71]},"36":{"advance":79,"bbox":[61,21,132,121]},"37":{"advance":74,"bbox":[65,27,131,114]},"38":{"advance":76,"bbox":[62,35,130,115]},"39":{"advance":28,"bbox":[90,27,104,42]},"40":{"advance":41,"bbox":[80,27,113,114]},"41":{"advance":41,"bbox":[81,28,114,114]},"42":{"advance":46,"bbox":[78,27,116,63]},"43":{"advance":60,"bbox":[71,46,123,95]},"44":{"advance":28,"bbox":[90,106,104,120]},"45":{"advance":50,"bbox":[76,89,118,92]},"46":{"advance":28,"bbox":[95,107,99,114]},"47":{"advance":66,"bbox":[71,27,129,114]},"48":{"advance":77,"bbox":[62,26,131,115]},"49":{"advance":40,"bbox":[82,27,114,114]},"50":{"advance":79,"bbox":[62,26,133,114]},"51":{"advance":78,"bbox":[63,27,133,115]},"52":{"advance":68,"bbox":[67,28,127,114]},"53":{"advance":78,"bbox":[63,27,133,115]},"54":{"advance":77,"bbox":[62,27,131,115]},"55":{"advance":73,"bbox":[65,26,130,114]},"56":{"advance":79,"bbox":[61,26,132,114]},"57":{"advance":77,"bbox":[63,26,132,115]},"58":{"advance":28,"bbox":[88,69,106,114]},"59":{"advance":36,"bbox":[83,69,111,120]},"60":{"advance":80,"bbox":[61,44,133,114]},"61":{"advance":60,"bbox":[70,58,122,82]},"62":{"advance":80,"bbox":[61,44,133,114]},"63":{"advance":54,"bbox":[74,26,120,114]},"64":{"advance":83,"bbox":[59,35,134,106]},"65":{"advance":94,"bbox":[57,26,143,115]},"66":{"advance":96,"bbox":[53,27,141,115]},"67":{"advance":81,"bbox":[61,27,134,114]},"68":{"advance":92,"bbox":[55,28,139,115]},"69":{"advance":76,"bbox":[64,27,132,115]},"70":{"advance":93,"bbox":[54,27,139,115]},"71":{"advance":93,"bbox":[54,27,139,117]},"72":{"advance":117,"bbox":[42,27,151,116]},"73":{"advance":83,"bbox":[60,26,135,115]},"74":{"advance":99,"bbox":[51,27,142,139]},"75":{"advance":120,"bbox":[41,27,153,115]},"76":{"advance":94,"bbox":[54,27,140,116]},"77":{"advance":140,"bbox":[30,27,162,115]},"78":{"advance":122,"bbox":[40,27,154,115]},"79":{"advance":84,"bbox":[58,27,134,116]},"80":{"advance":97,"bbox":[53,27,142,115]},"81":{"advance":87,"bbox":[58,27,137,116]},"82":{"advance":96,"bbox":[53,27,141,115]},"83":{"advance":78,"bbox":[65,26,135,116]},"84":{"advance":95,"bbox":[53,27,140,116]},"85":{"advance":107,"bbox":[48,27,147,116]},"86":{"advance":76,"bbox":[63,25,131,113]},"87":{"advance":98,"bbox":[53,25,143,113]},"88":{"advance":118,"bbox":[42,25,152,113]},"89":{"advance":113,"bbox":[45,26,150,142]},"90":{"advance":117,"bbox":[42,25,151,114]},"91":{"advance":81,"bbox":[61,43,134,113]},"92":{"advance":32,"bbox":[84,26,108,113]},"93":{"advance":80,"bbox":[61,43,133,113]},"94":{"advance":80,"bbox":[61,43,133,113]},"95":{"advance":80,"bbox":[61,43,133,113]},"96":{"advance":80,"bbox":[61,43,133,113]},"97":{"advance":70,"bbox":[65,54,127,114]},"98":{"advance":72,"bbox":[65,26,129,114]},"99":{"advance":62,"bbox":[70,54,124,114]},"100":{"advance":84,"bbox":[59,27,135,114]},"101":{"advance":62,"bbox":[73,53,127,113]},"102":{"advance":56,"bbox":[72,25,120,113]},"103":{"advance":81,"bbox":[61,54,134,142]},"104":{"advance":70,"bbox":[66,27,128,114]},"105":{"advance":41,"bbox":[81,26,114,114]},"106":{"advance":59,"bbox":[72,26,123,142]},"107":{"advance":70,"bbox":[67,27,129,114]},"108":{"advance":43,"bbox":[78,26,113,114]},"109":{"advance":89,"bbox":[57,53,138,114]},"110":{"advance":69,"bbox":[66,54,127,114]},"111":{"advance":62,"bbox":[70,54,124,115]},"112":{"advance":81,"bbox":[61,54,134,141]},"113":{"advance":66,"bbox":[68,55,126,141]},"114":{"advance":51,"bbox":[75,54,118,114]},"115":{"advance":63,"bbox":[69,53,124,114]},"116":{"advance":39,"bbox":[81,34,112,114]},"117":{"advance":66,"bbox":[68,54,126,114]},"118":{"advance":69,"bbox":[66,54,127,114]},"119":{"advance":89,"bbox":[59,54,140,115]},"120":{"advance":81,"bbox":[60,55,133,114]},"121":{"advance":76,"bbox":[63,55,131,143]},"122":{"advance":74,"bbox":[64,55,130,114]},"123":{"advance":80,"bbox":[62,43,134,114]},"124":{"advance":80,"bbox":[61,43,133,114]},"125":{"advance":81,"bbox":[61,43,134,114]},"126":{"advance":45,"bbox":[78,65,115,75]}}} }, "US Block 1L": { sprite: "https://cdn02.plentyone.com/f2d5nd8wf1gh/frontend/gravur-fonts/us-block-1l-sprite-v3.png", /* Diese Slots enthalten nur Platzhalter-Kästchen (identische bbox) */ blocked: [94, 96, 124], metrics: {"cellW":192,"cellH":160,"cols":16,"firstCodepoint":32,"metrics":{"32":{"advance":52,"bbox":null},"33":{"advance":28,"bbox":[93,27,103,114]},"34":{"advance":37,"bbox":[84,26,110,43]},"35":{"advance":72,"bbox":[67,27,128,86]},"36":{"advance":59,"bbox":[73,27,121,114]},"37":{"advance":87,"bbox":[60,26,136,115]},"38":{"advance":83,"bbox":[60,26,132,116]},"39":{"advance":28,"bbox":[92,24,102,42]},"40":{"advance":28,"bbox":[92,28,102,114]},"41":{"advance":28,"bbox":[92,27,102,114]},"42":{"advance":31,"bbox":[87,26,107,50]},"43":{"advance":78,"bbox":[63,37,130,103]},"44":{"advance":28,"bbox":[90,105,104,121]},"45":{"advance":67,"bbox":[69,81,125,84]},"46":{"advance":28,"bbox":[92,105,102,114]},"47":{"advance":63,"bbox":[74,26,126,114]},"48":{"advance":80,"bbox":[62,26,131,115]},"49":{"advance":31,"bbox":[88,26,108,114]},"50":{"advance":71,"bbox":[67,26,127,114]},"51":{"advance":74,"bbox":[67,26,130,115]},"52":{"advance":80,"bbox":[62,26,131,114]},"53":{"advance":73,"bbox":[67,26,129,115]},"54":{"advance":75,"bbox":[65,26,129,115]},"55":{"advance":72,"bbox":[67,26,128,114]},"56":{"advance":74,"bbox":[65,26,128,116]},"57":{"advance":75,"bbox":[65,26,129,115]},"58":{"advance":28,"bbox":[92,62,102,114]},"59":{"advance":28,"bbox":[91,62,104,119]},"60":{"advance":45,"bbox":[80,38,114,103]},"61":{"advance":52,"bbox":[76,60,117,80]},"62":{"advance":45,"bbox":[80,38,114,103]},"63":{"advance":62,"bbox":[72,25,123,114]},"64":{"advance":83,"bbox":[61,33,133,108]},"65":{"advance":79,"bbox":[66,26,134,114]},"66":{"advance":71,"bbox":[67,26,127,114]},"67":{"advance":72,"bbox":[67,25,128,115]},"68":{"advance":71,"bbox":[67,27,127,115]},"69":{"advance":70,"bbox":[68,27,127,115]},"70":{"advance":68,"bbox":[68,27,125,114]},"71":{"advance":72,"bbox":[67,26,128,116]},"72":{"advance":74,"bbox":[65,27,128,114]},"73":{"advance":28,"bbox":[96,27,99,114]},"74":{"advance":55,"bbox":[74,27,118,115]},"75":{"advance":72,"bbox":[67,27,128,114]},"76":{"advance":73,"bbox":[66,28,128,115]},"77":{"advance":87,"bbox":[59,27,135,114]},"78":{"advance":73,"bbox":[66,26,128,115]},"79":{"advance":78,"bbox":[63,26,130,116]},"80":{"advance":70,"bbox":[68,27,127,114]},"81":{"advance":84,"bbox":[60,26,133,121]},"82":{"advance":73,"bbox":[66,26,128,114]},"83":{"advance":75,"bbox":[68,26,132,116]},"84":{"advance":78,"bbox":[63,27,130,114]},"85":{"advance":72,"bbox":[67,27,128,116]},"86":{"advance":77,"bbox":[64,25,130,113]},"87":{"advance":109,"bbox":[49,25,147,113]},"88":{"advance":75,"bbox":[65,25,129,113]},"89":{"advance":76,"bbox":[65,25,130,113]},"90":{"advance":72,"bbox":[66,25,127,113]},"91":{"advance":28,"bbox":[90,25,105,113]},"92":{"advance":62,"bbox":[71,25,122,113]},"93":{"advance":28,"bbox":[90,25,105,113]},"94":{"advance":83,"bbox":[61,43,133,113]},"95":{"advance":57,"bbox":[74,123,120,126]},"96":{"advance":83,"bbox":[61,43,133,113]},"97":{"advance":68,"bbox":[68,48,125,115]},"98":{"advance":65,"bbox":[70,26,124,115]},"99":{"advance":63,"bbox":[71,48,123,115]},"100":{"advance":65,"bbox":[70,27,124,115]},"101":{"advance":68,"bbox":[72,48,129,115]},"102":{"advance":28,"bbox":[88,25,105,113]},"103":{"advance":67,"bbox":[70,48,126,138]},"104":{"advance":58,"bbox":[74,28,121,113]},"105":{"advance":28,"bbox":[97,27,100,113]},"106":{"advance":28,"bbox":[92,28,102,131]},"107":{"advance":61,"bbox":[73,27,123,113]},"108":{"advance":28,"bbox":[95,26,98,113]},"109":{"advance":98,"bbox":[54,48,141,113]},"110":{"advance":58,"bbox":[73,48,120,113]},"111":{"advance":70,"bbox":[68,48,127,115]},"112":{"advance":67,"bbox":[69,49,125,132]},"113":{"advance":67,"bbox":[69,49,125,133]},"114":{"advance":36,"bbox":[84,50,109,113]},"115":{"advance":58,"bbox":[73,47,120,115]},"116":{"advance":28,"bbox":[89,36,106,114]},"117":{"advance":57,"bbox":[74,51,120,116]},"118":{"advance":65,"bbox":[70,50,124,113]},"119":{"advance":93,"bbox":[59,50,141,113]},"120":{"advance":63,"bbox":[71,50,123,113]},"121":{"advance":56,"bbox":[75,51,120,135]},"122":{"advance":58,"bbox":[74,50,121,114]},"123":{"advance":41,"bbox":[83,26,113,114]},"124":{"advance":83,"bbox":[61,43,133,114]},"125":{"advance":40,"bbox":[83,26,112,114]},"126":{"advance":48,"bbox":[78,65,115,75]}}} } }; Object.keys(CFG).forEach(function (name) { CFG[name].blockedSet = new Set(CFG[name].blocked || []); }); /* Alle sechs Vorschauen werden auf dieselbe sichtbare Höhe normalisiert. Dünne Schriften werden nur leicht angeglichen – die echte Charakteristik bleibt erhalten. */ const VISUAL = { "AZURE": { height: 34, sourceStroke: 0.8 }, "Baby Script 42": { height: 34, sourceStroke: 1.6 }, "Optima 3L": { height: 34, sourceStroke: 0.0 }, "Script 4L": { height: 34, sourceStroke: 1.7 }, "Script Rund 1L": { height: 34, thicken: 0.22 }, "US Block 1L": { height: 34, thicken: 0.28 } }; /* Hinweis: Die Werte 128–159 stammen aus der Font-Kodierung (Windows-1252-Positionen) und lassen sich über die Tastatur praktisch nicht eingeben. Ein eingetipptes "€" (Unicode 8364) wird daher bei diesen Schriften weiterhin ausgelassen. */ const WEB_SUPPORTED = {"AZURE":[32,38,45,48,49,50,51,52,53,54,55,56,57,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],"Baby Script 42":[32,34,35,38,39,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,61,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,128,133,134,138,154,159,161,167,176,196,214,220,223,228,246,252],"Optima 3L":[32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,338,339,352,353,376,402],"Script 4L":[32,33,34,35,37,39,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,61,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,128,133,134,138,154,159,161,176,196,214,220,228,246,252]}; const WEB_SUPPORTED_SETS = {}; Object.keys(WEB_SUPPORTED).forEach(function (name) { WEB_SUPPORTED_SETS[name] = new Set(WEB_SUPPORTED[name]); }); const imageCache = {}; const measureCtx = document.createElement('canvas').getContext('2d'); let renderToken = 0; let debounceTimer = null; /* ---------- Fonts ---------- */ function installWebFonts() { if (document.getElementById('grom-gravur-live-fonts')) return; const style = document.createElement('style'); style.id = 'grom-gravur-live-fonts'; let css = ''; Object.keys(WEB_FONTS).forEach(function (name) { const f = WEB_FONTS[name]; css += '@font-face{' + 'font-family:"' + f.family + '";' + 'src:url("' + f.url + '") format("' + f.format + '");' + 'font-style:normal;' + 'font-weight:400;' + 'font-display:swap;' + '}'; }); style.textContent = css; document.head.appendChild(style); } /* true = Font ist geladen; false = Laden fehlgeschlagen (dann wird NICHT in einer Ersatzschrift gezeichnet). */ async function ensureFontLoaded(cfg, sample) { if (!document.fonts || !document.fonts.load) return true; try { const faces = await document.fonts.load('400 40px "' + cfg.family + '"', sample); if (!faces || !faces.length) return false; return faces.every(function (f) { return f.status === 'loaded'; }); } catch (e) { return false; } } /* ---------- DOM ---------- */ function getTextInput() { return document.querySelector( '#order-property-input-container_109 input, ' + '#order-property-input-container_109 textarea' ); } function getFontSelect() { return document.querySelector('#order-property-input-select_110'); } function getSelectedFontName() { const select = getFontSelect(); if (!select || select.selectedIndex < 0) return ''; const opt = select.options[select.selectedIndex]; return opt ? opt.text.trim() : ''; } function findNotesContainer() { /* Im echten Plenty-DOM ist Anmerkungen Merkmal 120. */ const direct = document.getElementById('order-property-input-container_120'); if (direct) return direct; /* Fallback, falls Plenty die ID irgendwann ändert. */ const containers = document.querySelectorAll('[id^="order-property-input-container_"]'); for (const container of containers) { const labels = container.querySelectorAll('label'); for (const label of labels) { if ((label.textContent || '').trim() === 'Anmerkungen') return container; } } return null; } function getNotesLabel(notesContainer) { if (!notesContainer) return null; const labels = notesContainer.querySelectorAll('label'); for (const label of labels) { if ((label.textContent || '').trim() === 'Anmerkungen') return label; } return null; } function setPreviewState(previewVisible) { const notesContainer = findNotesContainer(); const notesLabel = getNotesLabel(notesContainer); const customNotesLabel = document.getElementById('grom-live-notes-label'); /* Eigenes Label nur zeigen, wenn wir das Plenty-Label tatsächlich ersetzen. */ if (customNotesLabel) { customNotesLabel.style.display = (previewVisible && notesLabel) ? 'block' : 'none'; } if (!notesContainer) return; if (previewVisible) { /* Das absolut positionierte Plenty-Label würde die Vorschau überlagern. */ notesContainer.style.setProperty('padding-top', '0px', 'important'); if (notesLabel) notesLabel.style.setProperty('display', 'none', 'important'); } else { /* Geschlossener Zustand: native Plenty-Beschriftung + 9 px Abstand. */ notesContainer.style.setProperty('padding-top', '9px', 'important'); notesContainer.style.setProperty('box-sizing', 'border-box', 'important'); if (notesLabel) notesLabel.style.removeProperty('display'); } } function ensurePreview() { const input = getTextInput(); const textContainer = document.getElementById('order-property-input-container_109'); if (!input || !textContainer) return null; let wrap = document.getElementById('grom-live-engraving-preview'); if (!wrap) { wrap = document.createElement('div'); wrap.id = 'grom-live-engraving-preview'; wrap.style.cssText = 'display:none;' + 'width:100%;' + 'margin:9px 0 0 0;' + 'padding:0;' + 'box-sizing:border-box;' + 'clear:both;'; const label = document.createElement('div'); label.textContent = 'Gravurvorschau'; label.style.cssText = 'font-size:11px;' + 'font-family:inherit;' + 'font-weight:400;' + 'line-height:1.15;' + 'color:#333;' + 'margin:0 0 4px 0;' + 'padding:0;' + 'text-align:left;'; const box = document.createElement('div'); box.id = 'grom-live-engraving-box'; box.style.cssText = 'width:100%;' + 'height:62px;' + 'padding:5px 8px;' + 'border:0;' + 'background:#f7f7f7;' + 'box-sizing:border-box;' + 'display:flex;' + 'align-items:center;' + 'justify-content:center;' + 'overflow:hidden;'; const canvas = document.createElement('canvas'); canvas.id = 'grom-live-engraving-canvas'; canvas.style.cssText = 'display:block;' + 'width:100%;' + 'height:' + PREVIEW_H + 'px;' + 'margin:0;' + 'padding:0;'; const customNotesLabel = document.createElement('div'); customNotesLabel.id = 'grom-live-notes-label'; customNotesLabel.textContent = 'Anmerkungen'; customNotesLabel.style.cssText = 'display:none;' + 'font-size:11px;' + 'font-family:inherit;' + 'font-weight:400;' + 'line-height:1.15;' + 'color:#333;' + 'margin:10px 0 4px 0;' + 'padding:0;' + 'text-align:left;'; box.appendChild(canvas); wrap.appendChild(label); wrap.appendChild(box); wrap.appendChild(customNotesLabel); textContainer.insertAdjacentElement('afterend', wrap); } else if (wrap.previousElementSibling !== textContainer) { textContainer.insertAdjacentElement('afterend', wrap); } return wrap; } function showPreview(wrap) { wrap.style.display = 'block'; setPreviewState(true); } function hidePreview(wrap) { if (wrap) wrap.style.display = 'none'; setPreviewState(false); } /* ---------- Canvas ---------- */ function loadImage(url) { if (imageCache[url]) return imageCache[url]; imageCache[url] = new Promise(function (resolve, reject) { const im = new Image(); im.onload = function () { resolve(im); }; im.onerror = function (e) { delete imageCache[url]; /* späterer neuer Versuch möglich */ reject(e); }; im.src = url; }); return imageCache[url]; } function setupCanvas(canvas) { const box = document.getElementById('grom-live-engraving-box'); if (!box) return null; const dpr = Math.min(window.devicePixelRatio || 1, 2); const cssW = Math.max(1, box.clientWidth - 16); /* 2 * 8px Padding */ const cssH = PREVIEW_H; canvas.width = Math.round(cssW * dpr); canvas.height = Math.round(cssH * dpr); canvas.style.width = cssW + 'px'; canvas.style.height = cssH + 'px'; const ctx = canvas.getContext('2d'); ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.imageSmoothingEnabled = true; ctx.imageSmoothingQuality = 'high'; return { ctx: ctx, dpr: dpr, width: canvas.width, height: canvas.height }; } function findInkBounds(ctx, w, h) { const a = ctx.getImageData(0, 0, w, h).data; let minX = w, minY = h, maxX = -1, maxY = -1; for (let y = 0; y < h; y++) { const row = y * w * 4; for (let x = 0; x < w; x++) { if (a[row + x * 4 + 3] > 8) { if (x < minX) minX = x; if (x > maxX) maxX = x; if (y < minY) minY = y; if (y > maxY) maxY = y; } } } if (maxX < 0) return null; return { x: minX, y: minY, w: maxX - minX + 1, h: maxY - minY + 1 }; } /* ---------- Web-Fonts ---------- */ function sanitizeWebText(text, fontName) { let value = text; /* AZURE: nur Großbuchstaben. Umlaute/ß auf vorhandene Zeichen abbilden. */ if (fontName === 'AZURE') { value = value .toUpperCase() .replace(/Ä/g, 'A') .replace(/Ö/g, 'O') .replace(/Ü/g, 'U') .replace(/ẞ/g, 'SS') .replace(/ß/g, 'SS'); } /* Script 4L hat echte ÄÖÜ/äöü, aber kein ß. */ if (fontName === 'Script 4L') { value = value.replace(/ẞ/g, 'SS').replace(/ß/g, 'ss'); } /* Bei den anderen Fonts ẞ auf SS abbilden, da nur ß vorhanden ist. */ if (fontName === 'Baby Script 42' || fontName === 'Optima 3L') { value = value.replace(/ẞ/g, 'SS'); } const set = WEB_SUPPORTED_SETS[fontName] || new Set(); /* Nicht vorhandene Zeichen werden ausgelassen – keine Browser-Ersatzschrift. */ return Array.from(value).filter(function (ch) { return set.has(ch.codePointAt(0)); }).join(''); } /* Rückgabe: false = Font konnte nicht geladen werden, sonst true. */ async function renderWebFont(text, fontName, token) { const canvas = document.getElementById('grom-live-engraving-canvas'); const cfg = WEB_FONTS[fontName]; const visual = VISUAL[fontName] || { height: 34, sourceStroke: 0 }; if (!canvas || !cfg) return true; const previewText = sanitizeWebText(text, fontName); if (!previewText) { setupCanvas(canvas); /* leeren */ return true; } const loaded = await ensureFontLoaded(cfg, previewText); if (token !== renderToken) return true; /* inzwischen neuere Eingabe */ if (!loaded) return false; /* Ab hier kein await mehr – alles läuft synchron mit dem aktuellen Text. */ let sourcePx = BASE_SOURCE_PX; let pad = Math.round(sourcePx * 0.28); measureCtx.font = '400 ' + sourcePx + 'px "' + cfg.family + '"'; let measured = Math.max(1, Math.ceil(measureCtx.measureText(previewText).width)); /* Lange Texte: Quellgröße verkleinern statt abschneiden. */ if (measured + pad * 2 > MAX_TEMP_W) { sourcePx = Math.max(24, Math.floor(sourcePx * (MAX_TEMP_W - pad * 2) / measured)); pad = Math.round(sourcePx * 0.28); measureCtx.font = '400 ' + sourcePx + 'px "' + cfg.family + '"'; measured = Math.max(1, Math.ceil(measureCtx.measureText(previewText).width)); } const temp = document.createElement('canvas'); temp.width = Math.min(MAX_TEMP_W, measured + pad * 2); temp.height = Math.ceil(sourcePx * 1.78); const t = temp.getContext('2d', { willReadFrequently: true }); t.font = '400 ' + sourcePx + 'px "' + cfg.family + '"'; t.textAlign = 'left'; t.textBaseline = 'alphabetic'; t.lineJoin = 'round'; t.lineCap = 'round'; t.fillStyle = '#111'; t.strokeStyle = '#111'; const baseline = Math.round(sourcePx * 1.25); if (visual.sourceStroke > 0) { t.lineWidth = visual.sourceStroke * (sourcePx / BASE_SOURCE_PX); t.strokeText(previewText, pad, baseline); } t.fillText(previewText, pad, baseline); /* Sichtbare Pixel suchen – so bekommen alle Schriften dieselbe sichtbare Höhe. */ const b = findInkBounds(t, temp.width, temp.height); const state = setupCanvas(canvas); if (!state || !b) return true; const out = state.ctx; const W = state.width; const H = state.height; const targetH = visual.height * state.dpr; const availableW = W - (20 * state.dpr); let scale = targetH / b.h; if ((b.w * scale) > availableW) scale = availableW / b.w; const dw = b.w * scale; const dh = b.h * scale; const dx = (W - dw) / 2; const dy = (H - dh) / 2; out.drawImage(temp, b.x, b.y, b.w, b.h, dx, dy, dw, dh); return true; } /* ---------- Sprite-Fonts ---------- */ function getSpriteGlyph(ch, cfg) { const M = cfg.metrics; const cp = ch.codePointAt(0); if (cfg.blockedSet.has(cp)) return null; if (cp >= 32 && cp <= 126 && M.metrics[String(cp)]) { const mm = M.metrics[String(cp)]; return { index: cp - M.firstCodepoint, advance: mm.advance, bbox: mm.bbox, diaeresis: false }; } return null; } function expandSpriteText(text, cfg) { const out = []; const umlautMap = { 'ä': 'a', 'ö': 'o', 'ü': 'u', 'Ä': 'A', 'Ö': 'O', 'Ü': 'U' }; Array.from(text).forEach(function (ch) { /* ß ist in den Sprites nicht als eigener Slot vorhanden → ss / SS. */ if (ch === 'ß') { out.push({ ch: 's', diaeresis: false }); out.push({ ch: 's', diaeresis: false }); return; } if (ch === 'ẞ') { out.push({ ch: 'S', diaeresis: false }); out.push({ ch: 'S', diaeresis: false }); return; } if (umlautMap[ch]) { out.push({ ch: umlautMap[ch], diaeresis: true }); return; } if (getSpriteGlyph(ch, cfg)) { out.push({ ch: ch, diaeresis: false }); } /* Nicht vorhandene Zeichen werden bewusst ausgelassen. */ }); return out; } /* Rückgabe: false = Sprite konnte nicht geladen werden, sonst true. */ async function renderSprite(text, fontName, token) { const canvas = document.getElementById('grom-live-engraving-canvas'); const cfg = CFG[fontName]; const visual = VISUAL[fontName] || { height: 34, thicken: 0 }; if (!canvas || !cfg) return true; let im; try { im = await loadImage(cfg.sprite); } catch (e) { if (token !== renderToken) return true; return false; } if (token !== renderToken) return true; /* inzwischen neuere Eingabe */ /* Ab hier kein await mehr. */ const state = setupCanvas(canvas); if (!state) return true; const ctx = state.ctx; const dpr = state.dpr; const W = state.width; const H = state.height; const M = cfg.metrics; const glyphs = []; expandSpriteText(text, cfg).forEach(function (item) { const g = getSpriteGlyph(item.ch, cfg); if (g) { g.diaeresis = item.diaeresis; glyphs.push(g); } }); if (!glyphs.length) return true; let minTop = 999; let maxBottom = 0; glyphs.forEach(function (g) { if (g.bbox) { let top = g.bbox[1]; if (g.diaeresis) top -= 14; minTop = Math.min(minTop, top); maxBottom = Math.max(maxBottom, g.bbox[3]); } }); if (minTop === 999) { minTop = 25; maxBottom = 116; } const sourceVisualH = Math.max(1, maxBottom - minTop); let sc = (visual.height * dpr) / sourceVisualH; let totalW = 0; glyphs.forEach(function (g) { totalW += g.advance * sc; }); const availableW = W - (20 * dpr); if (totalW > availableW && totalW > 0) { sc *= availableW / totalW; totalW = availableW; } const sourceBaseline = 116; const centerOffset = (((minTop + maxBottom) / 2) - sourceBaseline) * sc; const baseline = (H / 2) - centerOffset; let x = (W - totalW) / 2; const th = (visual.thicken || 0) * dpr; function drawGlyph(g, dx, dy) { const idx = g.index; const sx = (idx % M.cols) * M.cellW; const sy = Math.floor(idx / M.cols) * M.cellH; const dw = M.cellW * sc; const dh = M.cellH * sc; const adv = g.advance * sc; const drawX = x - (dw / 2) + (adv / 2) + dx; const drawY = baseline - (sourceBaseline * sc) + dy; ctx.drawImage(im, sx, sy, M.cellW, M.cellH, drawX, drawY, dw, dh); } glyphs.forEach(function (g) { if (th > 0) { drawGlyph(g, -th, 0); drawGlyph(g, th, 0); drawGlyph(g, 0, -th); drawGlyph(g, 0, th); } drawGlyph(g, 0, 0); if (g.diaeresis) { const adv = g.advance * sc; const cx = x + (adv / 2); const topY = baseline - (sourceBaseline * sc) + ((g.bbox ? g.bbox[1] : 50) * sc); const dotY = topY - (7 * sc); const dotOffset = Math.max(3.0 * dpr, 7.5 * sc); const r = Math.max(1.15 * dpr, 2.7 * sc); ctx.fillStyle = '#111'; ctx.beginPath(); ctx.arc(cx - dotOffset, dotY, r, 0, Math.PI * 2); ctx.fill(); ctx.beginPath(); ctx.arc(cx + dotOffset, dotY, r, 0, Math.PI * 2); ctx.fill(); } x += g.advance * sc; }); /* Sprite-Dateien sind blau; alle Vorschauen sollen gleich schwarz aussehen. */ ctx.globalCompositeOperation = 'source-in'; ctx.fillStyle = '#111'; ctx.fillRect(0, 0, W, H); ctx.globalCompositeOperation = 'source-over'; return true; } /* ---------- Steuerung ---------- */ /* true, wenn das Element im DOM hängt und tatsächlich angezeigt wird. */ function isVisible(el) { if (!el || !el.isConnected) return false; if (!el.getClientRects().length) return false; return window.getComputedStyle(el).visibility !== 'hidden'; } async function renderPreview() { const token = ++renderToken; installWebFonts(); const input = getTextInput(); const select = getFontSelect(); const textContainer = document.getElementById('order-property-input-container_109'); /* BUGFIX v4.1: Blendet Plenty Gravurtext oder Schriftart aus (z. B. bei "Lasergravur: Bild/Logo/Wappen"), muss auch die Vorschau verschwinden – sonst bleibt der alte Text stehen. */ if (!input || !select || !isVisible(textContainer) || !isVisible(select)) { hidePreview(document.getElementById('grom-live-engraving-preview')); return; } const wrap = ensurePreview(); if (!wrap) return; const text = input.value || ''; const fontName = getSelectedFontName(); const isWeb = !!WEB_FONTS[fontName]; const isSprite = !!CFG[fontName]; if (!text.trim() || (!isWeb && !isSprite)) { hidePreview(wrap); return; } /* Erst sichtbar machen, damit die Box eine Breite hat. */ showPreview(wrap); let ok = true; try { ok = isWeb ? await renderWebFont(text, fontName, token) : await renderSprite(text, fontName, token); } catch (e) { ok = false; } if (token !== renderToken) return; /* neuere Eingabe übernimmt */ if (!ok) hidePreview(wrap); /* Font/Sprite nicht ladbar → lieber keine Vorschau */ } function scheduleRender(delay) { clearTimeout(debounceTimer); debounceTimer = setTimeout(renderPreview, delay || 0); } document.addEventListener('input', function (e) { if (e.target && e.target.closest && e.target.closest('#order-property-input-container_109')) { scheduleRender(60); } }); document.addEventListener('change', function (e) { if (e.target && e.target.id === 'order-property-input-select_110') { scheduleRender(0); return; } /* BUGFIX v4.1: Jede andere Merkmal-Auswahl (z. B. Gravurart) kann Felder ein- oder ausblenden. Plenty baut das DOM danach neu auf → mehrfach prüfen. */ if (e.target && e.target.closest && e.target.closest('[id^="order-property-input-container_"]')) { scheduleRender(0); setTimeout(renderPreview, 250); setTimeout(renderPreview, 700); } }); document.addEventListener('click', function (e) { if (e.target && e.target.closest && e.target.closest('.properties-toggle')) { setTimeout(renderPreview, 150); setTimeout(renderPreview, 400); } }); document.addEventListener('onVariationChanged', function () { setTimeout(renderPreview, 250); setTimeout(renderPreview, 600); }); window.addEventListener('resize', function () { scheduleRender(120); }); installWebFonts(); setPreviewState(false); setTimeout(renderPreview, 300); setTimeout(renderPreview, 900); })();
(function () { function fixDuplicateFontPreview() { var container = document.getElementById('order-property-input-container_110'); if (!container) { return; } var images = container.querySelectorAll('img.font-img'); var seenSources = {}; images.forEach(function (img) { var src = img.getAttribute('src'); if (!src) { return; } if (seenSources[src]) { img.style.display = 'none'; } else { img.style.display = 'block'; seenSources[src] = true; } }); } /* Beim Laden */ setTimeout(fixDuplicateFontPreview, 200); setTimeout(fixDuplicateFontPreview, 600); setTimeout(fixDuplicateFontPreview, 1200); /* Beim Öffnen/Schließen der Gravur */ document.addEventListener('click', function (event) { if ( event.target.closest && event.target.closest('.properties-toggle') ) { setTimeout(fixDuplicateFontPreview, 100); setTimeout(fixDuplicateFontPreview, 400); } }); /* Beim Wechsel der Schriftart */ document.addEventListener('change', function (event) { if ( event.target && event.target.id === 'order-property-input-select_110' ) { setTimeout(fixDuplicateFontPreview, 100); setTimeout(fixDuplicateFontPreview, 400); } }); /* Beim Variantenwechsel */ document.addEventListener('onVariationChanged', function () { setTimeout(fixDuplicateFontPreview, 200); setTimeout(fixDuplicateFontPreview, 600); }); })();

Für die Gravur benötigen wir 1-3 Werktage.

Bei Manschettenknöpfen zählen die Zeichen beider Gravuren zusammen (2x GROM = 8 Zeichen). Unterschiedliche Gravuren sind möglich.

Gravur:

Anzahl:
PayPal Klarna Apple Pay Kreditkarten
100 Tage Rückgaberecht

  • Marke: TEROON

  • Oberfläche: Rhodium veredelt (silberfarben)

  • Mechanik: hochwertige und verschleißarme Alligatorklemme

  • Besonderheiten: glanz-polierte Oberfläche

  • Farbe: Silber

  • Maße: ca. 45 mm x 68 mm

  • Gewicht: ca. 8 g

  • Im Lieferumfang ist das hochwertige Geschenk-Etui des Designers TEROON enthalten.

    Per whatsapp:     pro-manschettenknoepfe.de

    Oder per Kontaktformular:

    document.querySelector("form > input[data-mail='subject']").value = "Anfrage zu Artikelnummer: ${ $store.getters.currentItemVariation.variation.number }";

    Sie wollen eine größere Anzahl dieses Artikels bestellen?
    Gerne erstellen wir Ihnen eine individuelles Angebot!

    Für Juweliere, Herrenaustatter, Werbemittelhändler und alle anderen gewerblichen Interessenten haben wir in unserem Händlerbereich Informationen (z.B. zu Themen wie individuellen Gravuren, Drucken und Neuproduktionen, sowie Referenzen und Projektbeispiele) bereit gestellt.

    Für den Zugang zu unseren Händler-Preisen legen Sie sich einfach ein Kundenkonto an und senden uns bitte im Anschluß Ihre Gewerbeanmeldung oder Ihren Handelsregisterauszug an b2b@pro-manschettenknoepfe.de.
    Wir werden Ihr Kundenkonto umgehend als Händlerkonto (ohne Mindestbestellwert) freischalten.
    Es werden Ihnen dann alle Artikel zum Händler-Einkaufspreis angezeigt.

    Für weitere Informationen stehen wir Ihnen gerne zur Verfügung:

    • per eMail: b2b@pro-manschettenknoepfe.de
    • per Telefon: +49 (0)7231 7833570
    TEROON Produktsicherheitsverordnung (GPSR) Verantwortung
    Grom Schmuck
    Siemensstr. 42
    75217 Birkenfeld
    info@grom-schmuck.de
    +49 (0)7231 7833570

    Weitere Informationen finden Sie hier.

    EMPFEHLUNGEN