// ==UserScript== // @name Platesmania Lookup Toolbox // @version 1.9.1 // @description Shows lookup buttons on Platesmania upload pages. // @match https://platesmania.com/*/add* // @grant GM_setValue // @grant GM_xmlhttpRequest // @connect opendata.rdw.nl // @connect motonet.fi // @license MIT // @namespace https://greasyfork.org/users/976031 // @downloadURL none // ==/UserScript== (function () { 'use strict'; const lookupSites = { nl: [ { name: 'Finnik', base: 'https://finnik.nl/kenteken/' }, { name: 'Autoweek', base: 'https://www.autoweek.nl/kentekencheck/' }, { name: 'voertuig.net', base: 'https://voertuig.net/kenteken/' }, { name: 'Centraal Beheer', base: 'https://centraalbeheer.finnik.nl/kenteken/' }, { name: 'Kentekencheck.info', base: 'https://www.kentekencheck.info/kenteken/' }, { name: 'Kentekencheck.nu', base: 'https://www.kentekencheck.nu/kenteken/' }, { name: 'Qenteken', base: 'https://www.qenteken.nl/kentekencheck/' }, { name: 'RDW (Website)', base: 'https://www.rdwdata.nl/kenteken/' }, ], se: [ { name: 'car.info', base: 'https://www.car.info/?s=' }, { name: 'biluppgifter.se', base: 'https://biluppgifter.se/fordon/' }, { name: 'transportstyrelsen', base: 'https://fordon-fu-regnr.transportstyrelsen.se/?ts-regnr-sok=' }, ], ua: [ { name: 'carplates.app', base: 'https://ua.carplates.app/en/number/' }, { name: 'baza-gai.com.ua', base: 'https://baza-gai.com.ua/nomer/' }, { name: 'auto-inform.com.ua', base: 'https://auto-inform.com.ua/search/' }, ], uk: [ { name: 'checkcardetails.co.uk', base: 'https://www.checkcardetails.co.uk/cardetails/' }, { name: 'totalcarcheck.co.uk', base: 'https://totalcarcheck.co.uk/FreeCheck?regno=' }, { name: 'checkhistory.co.uk', base: 'https://checkhistory.uk/vehicle/' }, ], dk: [ { name: 'digitalservicebog.dk', base: 'https://app.digitalservicebog.dk/search?country=dk&Registration=' }, { name: 'esyn.dk', base: 'https://findsynsrapport.esyn.dk/result?registration=' }, ], no: [{ name: 'vegvesen.no', base: 'https://www.vegvesen.no/en/vehicles/buy-and-sell/vehicle-information/check-vehicle-information/?registreringsnummer=' }], fr: [ { name: 'immatriculation-auto.info', base: 'https://immatriculation-auto.info/vehicle/' }, { name: 'carter-cash.com', base: 'https://www.carter-cash.com/?plate=', needsHyphen: true }, ], es: [ { name: 'carter-cash.es', base: 'https://www.carter-cash.es/piezas-auto/?plate=' }, ], fi: [{ name: 'motonet.fi (API)', base: 'https://www.motonet.fi/api/vehicleInfo/registrationNumber/FI?locale=fi®istrationNumber=' }], cz: [{ name: 'uniqa.cz', base: 'https://www.uniqa.cz/online/pojisteni-vozidla/#ecvId=' }], sk: [{ name: 'overenie.digital', base: 'https://overenie.digital/over/sk/ecv/' }], }; const url = window.location.href; const is = (code) => url.includes(`platesmania.com/${code}/add`); const supportedCodes = ['nl','ua','no','dk','fr','uk','fi','pl','lt','cz','se','es', 'sk']; // --- Helpers --- function selectedText(id) { const el = document.getElementById(id); if (!el || !el.options || el.selectedIndex < 0) return ''; return el.options[el.selectedIndex].text; } function areFieldsFilled() { if (is('nl')) return document.getElementById('nomer').value !== ''; if (is('ua')) { const region = document.getElementById('region1').value; const digits = document.getElementById('digit1').value; return region !== '' && digits !== ''; } if (is('no') || is('dk') || is('se')) return document.getElementById('let').value !== '' && document.getElementById('digit').value !== ''; if (is('fr')) { const b1 = document.getElementById('b1').value; const d2 = document.getElementById('digit2').value; const b2 = document.getElementById('b2').value; return b1 !== '' && d2 !== '' && b2 !== ''; } if (is('es')) { const ctype = document.getElementById('ctype')?.value; if (!ctype) return false; if (ctype === '1') { return document.getElementById('digit1').value !== '' && document.getElementById('let').value !== ''; } if (ctype === '2') { return selectedText('dip') !== '' && selectedText('region') !== '' && document.getElementById('digit1').value !== ''; } if (ctype === '3') { return selectedText('region') !== '' && document.getElementById('digit1').value !== '' && document.getElementById('let').value !== ''; } if (ctype === '4') { return selectedText('region') !== '' && document.getElementById('digit2').value !== '' && document.getElementById('let').value !== ''; } if (ctype === '5') { return selectedText('region') !== '' && document.getElementById('digit1').value !== '' && document.getElementById('let').value !== ''; } if (ctype === '7') { return selectedText('region') !== '' && document.getElementById('digit2').value !== ''; } return false; } if (is('de') || is('ch')) return document.getElementById('digit').value !== ''; if (is('pl') || is('uk')) { const nomerpl = document.getElementById('nomerpl').value; const dip = document.getElementById('dip').value; return nomerpl !== '' || dip !== ''; } if (is('fi')) return document.getElementById('digit').value !== ''; if (is('lt')) return document.getElementById('digit2').value !== ''; if (is('cz')) { const d1 = document.getElementById('digit1').value; const d2 = document.getElementById('digit2').value; const d3 = document.getElementById('digit3').value; const nomer = document.getElementById('nomer').value; return d1 !== '' || d2 !== '' || d3 !== '' || nomer !== ''; } if (is('sk')) { const digit = document.getElementById('digit').value; const nomerpl = document.getElementById('nomerpl').value; const police = document.getElementById('police').value; return digit !== '' || nomerpl !== '' || police !== ''; } return false; } function buildPlateForCurrentPage() { if (is('nl')) return document.getElementById('nomer').value; if (is('ua')) { const region = document.getElementById('region1').value; const digits = document.getElementById('digit1').value; const b1 = document.getElementById('b1').value; const b2 = document.getElementById('b2').value; return `${region}${digits}${b1}${b2}`; } if (is('no') || is('dk') || is('se')) { const letField = document.getElementById('let').value; const digitField = document.getElementById('digit').value; return `${letField}${digitField}`; } if (is('fr')) { const b1 = document.getElementById('b1').value; const digit2 = document.getElementById('digit2').value; const b2 = document.getElementById('b2').value; return `${b1}${digit2}${b2}`; } if (is('es')) { const ctype = document.getElementById('ctype')?.value; const q = (id) => document.getElementById(id)?.value || ''; if (ctype === '1') { return q('digit1') + q('let'); } if (ctype === '2') { return selectedText('dip') + selectedText('region') + q('digit1'); } if (ctype === '3') { return selectedText('region') + q('digit1') + q('let'); } if (ctype === '4') { return selectedText('region') + q('digit2') + q('let'); } if (ctype === '5') { return selectedText('region') + q('digit1') + q('let'); } if (ctype === '7') { return selectedText('region') + q('digit2'); } return ''; } if (is('fi')) { const letField = document.getElementById('let1').value; const digitField = document.getElementById('digit').value; return `${letField}-${digitField}`; } if (is('uk')) { return document.getElementById('nomerpl').value; } if (is('pl')) { const ctype = document.getElementById('ctype')?.value; const q = (id) => document.getElementById(id)?.value || ''; switch (ctype) { case '1': case '2': case '3': case '4': case '5': case '9': case '10': case '11': return selectedText('region') + q('nomerpl'); case '6': case '7': case '8': return selectedText('region') + q('b1') + q('nomerpl'); case '12': return selectedText('dip') + selectedText('region') + q('digit'); default: return ''; } } if (is('lt')) { const b1 = document.getElementById('b1'); const b2 = document.getElementById('b2'); const b3 = document.getElementById('b3'); const d1 = document.getElementById('digit1'); const d2 = document.getElementById('digit2'); const d3 = document.getElementById('digit3'); const vanity = document.getElementById('nomer'); const ctype = document.getElementById('ctype').value; if (ctype === '1') return b1.value + b2.value + b3.value + d2.value; if (ctype === '2') return d1.value + b1.value + b2.value; if (ctype === '3') return b1.value + b2.value + d2.value; if (ctype === '4') return d1.value + b1.value + b2.value + b3.value; if (['5','6','7','9'].includes(ctype)) return vanity.value; if (ctype === '8') return d3.value + b1.value + b2.value; return ''; } if (is('cz')) { const q = (id) => document.getElementById(id)?.value || ''; const category = q('ctype'); const regionField = document.getElementById('region'); const selectedRegionText = regionField.options[regionField.selectedIndex].text; const b1 = q('b1'), b2 = q('b2'), b3 = q('b3'); const d1 = q('digit1'), d2 = q('digit2'), d3 = q('digit3'); const nomer = q('nomer'), el = q('el'); switch (category) { case '1': return `${b1}${selectedRegionText}${b2}${d1}`; case '2': return `${b1}${selectedRegionText}${d1}`; case '4': return `${selectedRegionText}${b2}${d1}`; case '5': return `${selectedRegionText}${b2}${d1}`; case '6': return `${selectedRegionText}${b2}${d1}`; case '7': return `${selectedRegionText}${b2}${d2}`; case '8': return `${selectedRegionText}${b2}${d2}`; case '9': return `${selectedRegionText}${b2}${d2}`; case '10': return `${selectedRegionText}${b2}${d2}`; case '11': return nomer; case '3': return nomer; case '12': return `${el}${b3}${d3}`; case '13': return `${d1}${d3}`; default: return ''; } } if (is('sk')) { const ctype = document.getElementById('ctype')?.value; const q = (id) => document.getElementById(id)?.value || ''; switch (ctype) { case '1': case '2': case '12': return selectedText('region') + q('digit') + q('let2'); case '3': case '4': case '5': case '6': case '7': case '8': return selectedText('region') + q('let1') + q('digit'); case '9': return q('let2') + q('nomerpl'); case '10': return q('let1') + q('police'); case '11': return q('digit') + q('police'); case '13': return selectedText('dip') + q('police'); default: return ''; } } return ''; } // For Google Images button we historically insert spaces between chunks on some countries. function buildPlateForSearchDisplay() { if (is('nl')) return document.getElementById('nomer').value; if (is('ua')) { const region = document.getElementById('region1').value; const digits = document.getElementById('digit1').value; const b1 = document.getElementById('b1').value; const b2 = document.getElementById('b2').value; return `${region} ${digits} ${b1}${b2}`; } if (is('no') || is('dk') || is('se')) { return document.getElementById('let').value + ' ' + document.getElementById('digit').value; } if (is('fr')) { const b1 = document.getElementById('b1').value; const d2 = document.getElementById('digit2').value; const b2 = document.getElementById('b2').value; return `${b1} ${d2} ${b2}`; } if (is('es')) { return buildPlateForCurrentPage(); } if (is('de')) { const regionField = document.getElementById('region').value; const letField = document.getElementById('b1').value; const letField2 = document.getElementById('b2').value; const digitField = document.getElementById('digit').value; return `${regionField} ${letField} ${digitField}${letField2}`; } if (is('ch')) { const regionField = document.getElementById('region').value; const digitField = document.getElementById('digit').value; return `${regionField} ${digitField}`; } if (is('fi')) { return document.getElementById('let1').value + '-' + document.getElementById('digit').value; } if (is('pl')) { const regionField = document.getElementById('region'); const selectedRegionText = regionField.options[regionField.selectedIndex].text; const digitField = document.getElementById('nomerpl').value; return selectedRegionText + ' ' + digitField; } if (is('uk')) { return document.getElementById('nomerpl').value; } if (is('lt') || is('cz') || is('sk')) { return buildPlateForCurrentPage(); } return ''; } function frWithHyphens(s) { return s.replace(/^([A-Z]{2})(\d{3})([A-Z]{2})$/i, '$1-$2-$3'); } function onlyYearFromDate(s) { if (!s) return ''; const m = String(s).match(/(\d{4})/); return m ? m[1] : ''; } function showFIWindow(info) { const existing = document.getElementById('fiFloatWin'); if (existing) existing.remove(); const wrap = document.createElement('div'); wrap.id = 'fiFloatWin'; wrap.style.position = 'fixed'; wrap.style.top = '80px'; wrap.style.right = '40px'; wrap.style.zIndex = '99999'; wrap.style.background = '#fff'; wrap.style.border = '1px solid #ccc'; wrap.style.borderRadius = '6px'; wrap.style.boxShadow = '0 6px 18px rgba(0,0,0,0.18)'; wrap.style.minWidth = '260px'; wrap.style.maxWidth = '420px'; wrap.style.fontFamily = 'system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif'; const header = document.createElement('div'); header.style.padding = '10px 12px'; header.style.borderBottom = '1px solid #eee'; header.style.display = 'flex'; header.style.alignItems = 'center'; header.style.justifyContent = 'space-between'; header.style.background = '#f8f9fa'; const makeModel = `${info.manufacturerName || ''} ${info.model || ''}`.trim().replace(/\s+/g, ' '); const makeModelSpanHTML = `${escHtml(makeModel)}`; const y = onlyYearFromDate(info.registrationDate); const title = document.createElement('div'); title.innerHTML = `${makeModelSpanHTML}${y ? ` (${escHtml(y)})` : ''}`; title.style.fontWeight = '600'; const close = document.createElement('div'); close.textContent = '×'; close.title = 'Close'; close.style.cursor = 'pointer'; close.style.fontSize = '18px'; close.style.lineHeight = '18px'; close.style.marginLeft = '10px'; close.onclick = () => wrap.remove(); header.appendChild(title); header.appendChild(close); const body = document.createElement('div'); body.style.padding = '10px 12px'; body.style.fontSize = '14px'; const rows = [ ['Manufacturer', info.manufacturerName], ['Model', info.model], ['Type', info.type], ['VIN', info.VIN], ['Registration date', info.registrationDate], ['Fuel', info.fuel], ['Power', (info.powerKw || info.powerHp) ? `${info.powerKw ?? ''}${info.powerKw ? ' kW' : ''}${(info.powerKw && info.powerHp) ? ' / ' : ''}${info.powerHp ?? ''}${info.powerHp ? ' hp' : ''}` : ''], ].filter(([, v]) => v); for (const [label, value] of rows) { const row = document.createElement('div'); row.style.display = 'flex'; row.style.alignItems = 'center'; row.style.margin = '6px 0'; const text = document.createElement('div'); text.textContent = `${label}: ${value}`; text.style.flex = '1 1 auto'; const img = document.createElement('img'); img.src = 'https://i.imgur.com/RjmoRpu.png'; img.alt = 'Copy'; img.title = 'Copy'; img.style.height = '1em'; img.style.cursor = 'pointer'; img.style.marginLeft = '8px'; img.onclick = () => copyToClipboard(String(value)); row.appendChild(text); row.appendChild(img); body.appendChild(row); } wrap.appendChild(header); wrap.appendChild(body); document.body.appendChild(wrap); makeDraggable(wrap, header); } async function fetchMotonetData(fiPlateRaw) { const plate = String(fiPlateRaw || '').trim().toUpperCase(); if (!plate) throw new Error('Empty plate'); const url = `https://www.motonet.fi/api/vehicleInfo/registrationNumber/FI?locale=fi®istrationNumber=${encodeURIComponent(plate)}`; const data = await httpGet(url).catch(() => ({})); return data && typeof data === 'object' ? data : {}; } // --- Utils for RDW API + Floating Window --- function httpGet(url) { return new Promise((resolve, reject) => { if (typeof GM_xmlhttpRequest === 'function') { GM_xmlhttpRequest({ method: 'GET', url, headers: { 'Accept': 'application/json' }, onload: (res) => { try { resolve(JSON.parse(res.responseText)); } catch (e) { reject(e); } }, onerror: (e) => reject(e), }); } else { fetch(url).then(r => r.json()).then(resolve).catch(reject); } }); } function onlyYear(yyyymmdd) { if (!yyyymmdd || typeof yyyymmdd !== 'string') return 'unknown'; if (/^\d{8}$/.test(yyyymmdd)) return yyyymmdd.slice(0,4); return 'unknown'; } function copyToClipboard(text) { const doFallback = () => { const ta = document.createElement('textarea'); ta.value = text; document.body.appendChild(ta); ta.select(); try { document.execCommand('copy'); } catch {} document.body.removeChild(ta); }; if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(text).catch(doFallback); } else { doFallback(); } } function escHtml(s) { return String(s).replace(/[&<>"']/g, (c) => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); } function escAttr(s) { return String(s).replace(/['"]/g, (c) => ({ "'": "\\'", '"': '\\"' }[c])); } function makeDraggable(win, handle) { let ox=0, oy=0, dragging=false; handle.style.cursor = 'move'; handle.addEventListener('mousedown', (e) => { dragging = true; ox = e.clientX - win.offsetLeft; oy = e.clientY - win.offsetTop; document.addEventListener('mousemove', move); document.addEventListener('mouseup', up); e.preventDefault(); }); function move(e) { if (!dragging) return; win.style.left = (e.clientX - ox) + 'px'; win.style.top = (e.clientY - oy) + 'px'; } function up() { dragging = false; document.removeEventListener('mousemove', move); document.removeEventListener('mouseup', up); } } function showRDWWindow(info) { const existing = document.getElementById('rdwFloatWin'); if (existing) existing.remove(); const wrap = document.createElement('div'); wrap.id = 'rdwFloatWin'; wrap.style.position = 'fixed'; wrap.style.top = '80px'; wrap.style.right = '40px'; wrap.style.zIndex = '99999'; wrap.style.background = '#fff'; wrap.style.border = '1px solid #ccc'; wrap.style.borderRadius = '6px'; wrap.style.boxShadow = '0 6px 18px rgba(0,0,0,0.18)'; wrap.style.minWidth = '260px'; wrap.style.maxWidth = '380px'; wrap.style.fontFamily = 'system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif'; const header = document.createElement('div'); header.style.padding = '10px 12px'; header.style.borderBottom = '1px solid #eee'; header.style.display = 'flex'; header.style.alignItems = 'center'; header.style.justifyContent = 'space-between'; header.style.background = '#f8f9fa'; const makeModel = `${info.make} ${info.model}`.trim().replace(/\s+/g,' '); const makeModelSpanHTML = `${escHtml(makeModel)}`; const y = info.yFirst && info.yFirst !== 'unknown' ? ` (${escHtml(info.yFirst)})` : ''; const title = document.createElement('div'); title.innerHTML = `${makeModelSpanHTML}${y}`; title.style.fontWeight = '600'; const close = document.createElement('div'); close.textContent = '×'; close.title = 'Close'; close.style.cursor = 'pointer'; close.style.fontSize = '18px'; close.style.lineHeight = '18px'; close.style.marginLeft = '10px'; close.onclick = () => wrap.remove(); header.appendChild(title); header.appendChild(close); const body = document.createElement('div'); body.style.padding = '10px 12px'; body.style.fontSize = '14px'; const rows = [ ['Make', info.make], ['Model', info.model], ['Variant', info.variant], ['First registration', info.yFirst], ['First registration in NL', info.yNL], ['Fuel', info.fuel], ['Doors', info.doors], ['Color', info.color], ]; for (const [label, value] of rows) { const row = document.createElement('div'); row.style.display = 'flex'; row.style.alignItems = 'center'; row.style.margin = '6px 0'; const text = document.createElement('div'); text.textContent = `${label}: ${value}`; text.style.flex = '1 1 auto'; const img = document.createElement('img'); img.src = 'https://i.imgur.com/RjmoRpu.png'; img.alt = 'Copy'; img.title = 'Copy'; img.style.height = '1em'; img.style.cursor = 'pointer'; img.style.marginLeft = '8px'; img.onclick = () => copyToClipboard(String(value)); row.appendChild(text); row.appendChild(img); body.appendChild(row); } wrap.appendChild(header); wrap.appendChild(body); document.body.appendChild(wrap); makeDraggable(wrap, header); } async function fetchRDWData(kentekenRaw) { const plate = String(kentekenRaw || '').trim().replace(/[\s-]+/g, '').toUpperCase(); if (!plate) throw new Error('Empty plate'); const baseUrl = 'https://opendata.rdw.nl/resource/m9d7-ebf2.json'; const fuelUrl = 'https://opendata.rdw.nl/resource/8ys7-d773.json'; const qBase = `${baseUrl}?kenteken=${encodeURIComponent(plate)}`; const qFuel = `${fuelUrl}?kenteken=${encodeURIComponent(plate)}`; const [base, fuel] = await Promise.all([ httpGet(qBase).catch(() => []), httpGet(qFuel).catch(() => []), ]); const primary = Array.isArray(base) && base.length ? base[0] : {}; const fuelTypes = (Array.isArray(fuel) ? fuel : []) .map(x => x.brandstof_omschrijving || x.brandstof_omschrijving_ || x.brandstof || '') .filter(Boolean); const info = { make: primary.merk || 'unknown', model: primary.handelsbenaming || 'unknown', variant: primary.variant || 'unknown', yFirst: onlyYear(primary.datum_eerste_toelating), yNL: onlyYear(primary.datum_eerste_tenaamstelling_in_nederland), fuel: fuelTypes.length ? fuelTypes.join('/') : 'unknown', doors: primary.aantal_deuren || 'unknown', color: primary.eerste_kleur || 'unknown', }; return info; } // --- UI Button Factory (now supports optional left icon) --- function makeBtn(label, disabled, onclick, iconUrl) { const btn = document.createElement('button'); btn.disabled = !!disabled; btn.style.marginBottom = '0'; btn.style.width = '100%'; btn.style.backgroundColor = disabled ? '#95a5a6' : '#3498db'; btn.style.color = '#ffffff'; btn.style.border = 'none'; btn.style.cursor = disabled ? 'default' : 'pointer'; btn.style.height = '23px'; btn.style.borderRadius = '4px'; btn.style.display = 'flex'; btn.style.alignItems = 'center'; btn.style.justifyContent = 'center'; btn.style.gap = '6px'; btn.style.padding = '0 8px'; if (iconUrl) { const img = document.createElement('img'); img.src = iconUrl; img.alt = ''; img.style.maxHeight = (23 - 2) + 'px'; img.style.display = 'inline-block'; img.style.verticalAlign = 'middle'; btn.appendChild(img); } const span = document.createElement('span'); span.innerText = label; btn.appendChild(span); if (onclick && !disabled) btn.onclick = onclick; return btn; } // --- Buttons (Lookup / Google Images / Autogespot) --- function createOrUpdateLookupButtons() { const host = document.getElementById('zoomimgid'); if (!host) return; // Always ensure a grid container exists (even if there are no site lookups) let container = document.getElementById('lookupButtonsContainer'); if (!container) { container = document.createElement('div'); container.id = 'lookupButtonsContainer'; container.style.display = 'grid'; container.style.gap = '6px'; host.parentNode.insertBefore(container, host); } else { container.innerHTML = ''; } const fieldsOk = areFieldsFilled(); const code = supportedCodes.find(is); const sites = lookupSites[code] || []; // Optional helper label only when there are site buttons if (sites.length > 0) { const label = document.createElement('div'); label.textContent = '(Ctrl+Click buttons to open in background)'; label.style.fontSize = '9px'; label.style.fontWeight = 'bold'; label.style.marginBottom = '2px'; label.style.textAlign = 'center'; container.appendChild(label); } // Countries with special flows const specialPL = is('pl'); const specialLT = is('lt'); if (specialPL) { const btn = makeBtn('Lookup', !fieldsOk, () => { const plateNumber = buildPlateForCurrentPage(); const targetUrl = `https://moj.gov.pl/nforms/engine/ng/index?nfWidReset=true&xFormsAppName=NormaEuro&xFormsOrigin=EXTERNAL&plateNumber=${encodeURIComponent(plateNumber)}#/search`; window.open(targetUrl, '_blank'); }); container.appendChild(btn); // keep going; Google/Autogespot will also append into this same container } else if (specialLT) { const btn = makeBtn('Lookup', !fieldsOk, () => { const plateNumber = buildPlateForCurrentPage(); let form = document.createElement('form'); form.action = 'https://www.cab.lt/draustumo-patikra/'; form.method = 'POST'; form.target = '_blank'; let inputCountry = document.createElement('input'); inputCountry.type = 'hidden'; inputCountry.name = 'country'; inputCountry.value = 'LT'; let inputPlate = document.createElement('input'); inputPlate.type = 'hidden'; inputPlate.name = 'plate'; inputPlate.value = plateNumber; form.appendChild(inputCountry); form.appendChild(inputPlate); document.body.appendChild(form); form.submit(); document.body.removeChild(form); }); container.appendChild(btn); } // Standard flow: add site buttons if present if (sites.length === 1) { const only = sites[0]; const btn = makeBtn('Lookup', !fieldsOk, () => { const raw = buildPlateForCurrentPage(); if (!raw) return; const finalPlate = (is('fr') && only.needsHyphen) ? frWithHyphens(raw) : raw; window.open(only.base + finalPlate, '_blank'); }); container.appendChild(btn); } else if (sites.length > 1) { for (const site of sites) { const btn = makeBtn(site.name, !fieldsOk, () => { const raw = buildPlateForCurrentPage(); if (!raw) return; const finalPlate = (is('fr') && site.needsHyphen) ? frWithHyphens(raw) : raw; window.open(site.base + finalPlate, '_blank'); }); container.appendChild(btn); } } // --- NL: RDW API lookup button that opens floating window --- if (is('nl')) { const rdwBtn = makeBtn('RDW (API)', !fieldsOk, async () => { const plate = buildPlateForCurrentPage(); if (!plate) return; rdwBtn.disabled = true; rdwBtn.style.opacity = '0.7'; try { const info = await fetchRDWData(plate); showRDWWindow(info); } catch (e) { showRDWWindow({ make: 'unknown', model: 'unknown', variant: 'unknown', yFirst: 'unknown', yNL: 'unknown', fuel: 'unknown', doors: 'unknown', color: 'unknown', }); } finally { rdwBtn.disabled = false; rdwBtn.style.opacity = '1'; } }); container.appendChild(rdwBtn); } // --- FI: Motonet API lookup button that opens floating window --- if (is('fi')) { const fiBtn = makeBtn('Motonet (API)', !fieldsOk, async () => { const plate = buildPlateForCurrentPage(); // returns "AAA-123" if (!plate) return; fiBtn.disabled = true; fiBtn.style.opacity = '0.7'; try { const info = await fetchMotonetData(plate); showFIWindow(info && Object.keys(info).length ? info : {}); } catch (e) { showFIWindow({}); } finally { fiBtn.disabled = false; fiBtn.style.opacity = '1'; } }); container.appendChild(fiBtn); } } function createOrUpdateGoogleImagesButton() { const host = document.getElementById('zoomimgid'); if (!host) return; let googleBtn = document.getElementById('googleImagesButton'); if (!googleBtn) { googleBtn = makeBtn('Google Images (search plate)', true, null, 'https://i.imgur.com/5x00UaD.png'); googleBtn.id = 'googleImagesButton'; const container = document.getElementById('lookupButtonsContainer'); if (container) { container.appendChild(googleBtn); } else { host.parentNode.insertBefore(googleBtn, host); // fallback (shouldn’t happen now) } } const fieldsOk = areFieldsFilled(); googleBtn.disabled = !fieldsOk; googleBtn.onclick = !fieldsOk ? null : function () { const plateNumber = buildPlateForSearchDisplay(); if (!plateNumber) return; window.open('https://www.google.com/search?tbm=isch&q="' + plateNumber + '"', '_blank'); }; } function createOrUpdateAutogespotButton() { const host = document.getElementById('zoomimgid'); if (!host) return; let agBtn = document.getElementById('autogespotButton'); if (!agBtn) { agBtn = makeBtn('Search on Autogespot', true, null, 'https://i.imgur.com/X8HxriW.png'); agBtn.id = 'autogespotButton'; const container = document.getElementById('lookupButtonsContainer'); if (container) { container.appendChild(agBtn); } else { host.parentNode.insertBefore(agBtn, host); // fallback (shouldn’t happen now) } } const fieldsOk = areFieldsFilled(); agBtn.disabled = !fieldsOk; agBtn.style.marginBottom = '6px'; agBtn.onclick = !fieldsOk ? null : function () { let plateCompact = buildPlateForCurrentPage(); if (!plateCompact) { const display = buildPlateForSearchDisplay(); plateCompact = (display || '').replace(/\s+/g, ''); } if (!plateCompact) return; const target = `https://www.autogespot.com/spots?licenseplate=${encodeURIComponent(plateCompact)}`; window.open(target, '_blank'); }; } // --- Initial render + live updates --- function render() { createOrUpdateLookupButtons(); createOrUpdateGoogleImagesButton(); createOrUpdateAutogespotButton(); } render(); setInterval(render, 1000); })();