(function(){ const MIN_SECONDS=3, COOLDOWN_SECONDS=10, MAX_FAILS_BEFORE_COOLDOWN=2, MATH_ENABLED=true, ERROR_FADE_MS=7500; let startedAt=Date.now(), keypressCount=0, focusedCount=0, mouseMoveCount=0, fails=0, cooldownUntil=0, errorFadeTimer=null; function ready(fn){document.readyState!=='loading'?fn():document.addEventListener('DOMContentLoaded',fn);} function el(t,a={},c=[]){const e=document.createElement(t); Object.entries(a).forEach(([k,v])=>{ if(k==='style'&&typeof v==='object'){Object.assign(e.style,v);} else if(k in e){e[k]=v;} else {e.setAttribute(k,v);} }); (c||[]).forEach(x=>e.appendChild(typeof x==='string'?document.createTextNode(x):x)); return e; } const offscreen=()=>({position:'absolute',left:'-10000px',top:'auto',width:'1px',height:'1px',overflow:'hidden'}); const seconds=ts=>Math.floor((Date.now()-ts)/1000); // helpers function findSampleInput(form){ return form.querySelector('input[type="text"], input:not([type]), textarea, select'); } function findSubmit(form){ return form.querySelector('[type="submit"], button[type="submit"]'); } function findFieldLabelForInput(input){ if(!input) return null; const container = input.closest('.form-group, .form__row, .field, .form-group-inline, .row, div'); let lbl = container ? container.querySelector('label') : null; if(lbl) return lbl; if(input.id){ const byFor = input.form?.querySelector(`label[for="${CSS.escape(input.id)}"]`); if(byFor) return byFor; } let n=input.previousElementSibling; while(n){ if(n.tagName==='LABEL') return n; n=n.previousElementSibling; } return null; } function getInvalidSample(form){ return form.querySelector('input[aria-invalid="true"], .is-invalid input, input.error, .has-error input') || null; } function applyBaseInputStyles(fromCS, toEl){ if(!fromCS||!toEl) return; toEl.style.padding = fromCS.padding; toEl.style.border = fromCS.border; toEl.style.borderRadius = fromCS.borderRadius; toEl.style.background = fromCS.backgroundColor; toEl.style.color = fromCS.color; toEl.style.lineHeight = fromCS.lineHeight; toEl.style.fontSize = fromCS.fontSize; toEl.style.fontFamily = fromCS.fontFamily; toEl.style.boxShadow = fromCS.boxShadow; toEl.style.outline = 'none'; } function applyInvalidStyles(invalidCS, toEl){ if(invalidCS){ toEl.style.border = invalidCS.border; toEl.style.boxShadow = invalidCS.boxShadow; const bc = invalidCS.borderColor || ''; if(!bc) toEl.style.borderColor = '#ef4444'; }else{ toEl.style.borderColor = '#ef4444'; toEl.style.boxShadow = '0 0 0 1px rgba(239,68,68,.25)'; } } function clearInvalidStyles(sampleCS, toEl){ applyBaseInputStyles(sampleCS, toEl); } // >>> NOWE: pobieranie koloru gwiazdki jak w innych polach function getRequiredStarColor(form){ // 1) gwiazdka w labelach (span/sup/i z '*') const candidates = form.querySelectorAll('label span, label sup, label i'); for(const el of candidates){ if((el.textContent||'').trim() === '*'){ const c = getComputedStyle(el).color; if(c) return c; } } // 2) kolor z komunikatu błędu (często to ten sam czerwony) const err = form.querySelector('.error, .text-danger, .form-error, .invalid-feedback, .error-message, .help-block'); if(err){ const c = getComputedStyle(err).color; if(c) return c; } // 3) domyślny czerwony (tailwindowy red-500) return '#ef4444'; } ready(function(){ const form=document.querySelector('form'); if(!form) return; const sampleInput=findSampleInput(form); const submitBtn=findSubmit(form); const csInput=sampleInput?getComputedStyle(sampleInput):null; const sampleLabel=findFieldLabelForInput(sampleInput); const csLabel=sampleLabel?getComputedStyle(sampleLabel):null; const invalidSample=getInvalidSample(form); const invalidCS=invalidSample?getComputedStyle(invalidSample):null; // interakcje const inputs=[...form.querySelectorAll('input, textarea, select')]; form.addEventListener('keydown',e=>{if(!['Tab','Shift','Control','Alt','Meta'].includes(e.key)) keypressCount++;},true); inputs.forEach(i=>i.addEventListener('focus',()=>{focusedCount++;},true)); window.addEventListener('mousemove',()=>{mouseMoveCount++;},{passive:true}); // honeypot + meta const hpWrap=el('div',{style:offscreen()}), hp=el('input',{type:'text',name:'website',autocomplete:'off',tabIndex:-1,'aria-hidden':'true',placeholder:'Zostaw puste'}); hpWrap.appendChild(hp); form.appendChild(hpWrap); const meta=el('input',{type:'hidden',name:'anti_spam_meta'}); form.appendChild(meta); // anchor const anchor=submitBtn?.closest('div')||form; // === Sekcja matematyczna === let a=0,b=0, mathInput=null, questionSpan=null, errorText=null; function newEquation(focus=true){ a=Math.floor(2+Math.random()*7); b=Math.floor(2+Math.random()*7); if(questionSpan) questionSpan.textContent=`Ile to ${a} + ${b}?`; if(mathInput){ mathInput.value=''; if(focus) mathInput.focus(); } } function mountMath(){ if(!MATH_ENABLED) return; newEquation(false); const field=el('div',{className:'antispam-math-field',style:{margin:'16px 0'}}); const label=el('label',{htmlFor:'math-proof',style:{ display:'block',marginBottom:'8px', fontWeight: csLabel?csLabel.fontWeight:'600', color: csLabel?csLabel.color:(csInput?csInput.color:'#0f172a'), fontSize: csLabel?csLabel.fontSize:(csInput?csInput.fontSize:'16px'), lineHeight: csLabel?csLabel.lineHeight:(csInput?csInput.lineHeight:'1.4'), fontFamily: csLabel?csLabel.fontFamily:(csInput?csInput.fontFamily:'inherit') }},['Potwierdź, że jesteś człowiekiem']); // GWIAZDKA W TYM SAMYM KOLORZE CO W POLU E-MAIL (albo innym wymaganym) const starColor = getRequiredStarColor(form); const requiredStar = el('span',{style:{color:starColor, marginLeft:'4px', fontWeight: csLabel?csLabel.fontWeight:'600'}},['*']); label.appendChild(requiredStar); const row=el('div',{style:{display:'flex',alignItems:'center',gap:'12px',flexWrap:'wrap'}}); mathInput=el('input',{id:'math-proof',type:'text',inputMode:'numeric',pattern:'[0-9]*',placeholder:'Wpisz wynik (np. 5)'}); applyBaseInputStyles(csInput, mathInput); mathInput.style.width='200px'; questionSpan=el('span',{style:{ whiteSpace:'nowrap', color: csLabel?csLabel.color:(csInput?csInput.color:'#0f172a'), fontSize: csLabel?csLabel.fontSize:(csInput?csInput.fontSize:'16px'), lineHeight: csLabel?csLabel.lineHeight:(csInput?csInput.lineHeight:'1.4'), fontFamily: csLabel?csLabel.fontFamily:(csInput?csInput.fontFamily:'inherit'), fontWeight: csLabel?csLabel.fontWeight:'600' }},[`Ile to ${a} + ${b}?`]); errorText=el('div',{role:'alert','aria-live':'assertive',style:{ marginTop:'6px', color:'#ef4444', fontSize: csLabel?csLabel.fontSize:(csInput?csInput.fontSize:'12px'), lineHeight: csLabel?csLabel.lineHeight:(csInput?csInput.lineHeight:'1.3'), fontFamily: csLabel?csLabel.fontFamily:(csInput?csInput.fontFamily:'inherit'), opacity:0, transition:'opacity 200ms ease' }}); row.appendChild(mathInput); row.appendChild(questionSpan); field.appendChild(label); field.appendChild(row); field.appendChild(errorText); if(anchor?.parentNode){ anchor.parentNode.insertBefore(field,anchor); } else { form.appendChild(field); } } mountMath(); if(document.getElementById('math-proof')) document.getElementById('math-proof').focus(); function showErr(msg){ if(!errorText||!mathInput) return; applyInvalidStyles(invalidCS, mathInput); if(errorFadeTimer){ clearTimeout(errorFadeTimer); errorFadeTimer=null; } errorText.textContent = msg; errorText.style.opacity = 1; errorFadeTimer = setTimeout(()=>{ errorText.style.opacity = 0; setTimeout(()=>{ if(errorText.style.opacity==='0') errorText.textContent=''; }, 300); }, ERROR_FADE_MS); } function clearErr(){ if(!errorText||!mathInput) return; clearTimeout(errorFadeTimer); errorFadeTimer=null; errorText.textContent=''; errorText.style.opacity=0; clearInvalidStyles(csInput, mathInput); } function validate(ev){ clearErr(); const now=Date.now(); if(now=1)&& (keypressCount>=2||mouseMoveCount>=2); if(!interacted){ fails++; if(ev){ev.preventDefault();ev.stopImmediatePropagation();} showErr('Najpierw wypełnij formularz.'); cool(); return false; } if(MATH_ENABLED){ const v=(document.getElementById('math-proof')?.value||'').trim(); if(!/^\d+$/.test(v)){ fails++; if(ev){ev.preventDefault();ev.stopImmediatePropagation();} showErr('Podaj wynik jako liczbę.'); newEquation(); cool(); return false; } if(parseInt(v,10)!==(a+b)){ fails++; if(ev){ev.preventDefault();ev.stopImmediatePropagation();} showErr('Niepoprawny wynik.'); newEquation(); cool(); return false; } } meta.value=btoa(unescape(encodeURIComponent(JSON.stringify({ ttf_s:seconds(startedAt),keys:keypressCount,foci:focusedCount,moves:mouseMoveCount,math_ok:true,math_a:a,math_b:b,fails })))); return true; } function cool(){ if(fails>=MAX_FAILS_BEFORE_COOLDOWN){ cooldownUntil=Date.now()+COOLDOWN_SECONDS*1000; if(submitBtn){ const orig=submitBtn.disabled?null:submitBtn.textContent; submitBtn.disabled=true; let left=COOLDOWN_SECONDS; (function t(){submitBtn.textContent=`Zablokowane (${left}s)`; if(--left<0){submitBtn.disabled=false;if(orig)submitBtn.textContent=orig;} else setTimeout(t,1000); })(); } } } // nasłuchy/patch form.addEventListener('submit',e=>{ if(!validate(e)) return false; },true); form.addEventListener('submit',e=>{ if(!validate(e)) return false; }); if(typeof form.requestSubmit==='function'){ const o=form.requestSubmit.bind(form); form.requestSubmit=function(...a){ if(!validate())return; return o(...a); }; } if(typeof form.submit==='function'){ const o=form.submit.bind(form); form.submit=function(...a){ if(!validate())return; return o(...a); }; } if(submitBtn){ submitBtn.addEventListener('click',e=>{ if(!validate(e)) return false; },true); } }); })(); Senior Shopify Frontend Developer (k/m)

Senior Shopify Frontend Developer (k/m)

outside.tracker.banner.form.text

*
*
* (system.max.size)
*
*
*
ID: 48