PageSourceSearch

https://intelectsoft.md/assets/app.js?v=56c1ca

js intelectsoft.md collected 2026-10-02 00:02:55 UTC 18,263 bytes, 358 lines download raw bytes

1(function(){
2/* ====== Trimiterea formularului — IDENTIC cu qrl.md ======
3   Același serviciu ESM MailService, același API key, același destinatar.    */
4var ESM_API_URL = 'https://api.eservicii.md/MailService/Send';
5var ESM_API_KEY = '6061a897-0693-4686-be25-6abe73d85c08';
6var ESM_RECIPIENT = '[email protected]';
7
8/* Notificare Telegram (grupul de vânzări) — fire-and-forget, doar la succes;
9   dacă Telegram pică, emailul rămâne neafectat. */
10var TG_BOT_TOKEN = '8139472333:AAFRA28RtdUmJRukjZYtMh8bVFlENTdO9_I';
11var TG_CHAT_ID = '-484860415';
12function _isTg(d){
13  if (!TG_BOT_TOKEN || !TG_CHAT_ID) return;
14  var t = '📥 intelectsoft.md — solicitare nouă\n' + (location.pathname+location.hash) + '\n\n' +
15    [ d.name ? 'Nume: ' + d.name : '',
16      d.company ? 'Companie: ' + d.company : '',
17      d.phone ? 'Telefon: ' + d.phone : '',
18      d.email ? 'Email: ' + d.email : '',
19      d.industry ? 'Domeniu: ' + d.industry : '',
20      d.solution ? 'Soluție: ' + d.solution : '',
21      d.message ? 'Mesaj: ' + d.message : '' ].filter(
21Boolean).join('\n');
22  var u = 'https://api.telegram.org/bot' + TG_BOT_TOKEN + '/sendMessage?disable_web_page_preview=true&chat_id=' +
23    encodeURIComponent(TG_CHAT_ID) + '&text=' + encodeURIComponent(t.slice(0, 3800));
24  try { fetch(u, { mode: 'no-cors' }); } catch (e) {}
25}
26
27"use strict";
28var reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
29
30/* ---------- Header ---------- */
31var header = document.getElementById('header');
32function onScroll(){ header.classList.toggle('scrolled', window.scrollY > 24); }
33window.addEventListener('scroll', onScroll, {passive:true}); onScroll();
34
35var burger = document.getElementById('burger');
36burger.addEventListener('click', function(){
37  var open = header.classList.toggle('menu-open');
38  burger.setAttribute('aria-expanded', open);
39  document.body.style.overflow = open ? 'hidden' : '';
40  if (!open) document.querySelectorAll('.nav > li.open').forEach(function(x){ x.classList.remove('open'); });
41});
42document.querySelectorAll('.nav a').forEach(function(a){
43  a.addEventListener('click', function(e){
44    if (window.innerWidth <= 900){
45      var li = a.closest('li');
46      var hasSub = li && li.querySelector('.mega, .dropdown') && a.classList.contains('nav-link');
47      if (hasSub){
48        e.preventDefault();
49        var wasOpen = li.classList.contains('open');
50        document.querySelectorAll('.nav > li.open').forEach(function(x){ if (x !== li) x.classList.remove('open'); });
51        li.classList.toggle('open', !wasOpen);
52        return;
53      }
54      header.classList.remove('menu-open'); burger.setAttribute('aria-expanded','false'); document.body.style.overflow='';
55      document.querySelectorAll('.nav > li.open').forEach(function(x){ x.classList.remove('open'); });
56    }
57  });
58});
59
60/* ---------- Ceas live (ora Chișinău) — puls EKG, colț pe desktop / inline pe mobil ---------- */
61(function(){
62  var elsT = document.querySelectorAll('.hp-time'), elsD = document.querySelectorAll('.hp-date');
63  if (!elsT.length) return;
64  var CITY = {ro:'Chișinău', ru:'Кишинёв', en:'Chișinău'};
65  function lang(){ return document.documentElement.lang || 'ro'; }
66  function tick(){
67    var now = new Date();
68    var t = new Intl.DateTimeFormat('ro-MD', {timeZone:'Europe/Chisinau', hour:'2-digit', minute:'2-digit', second:'2-digit', hour12:false}).format(now);
69    var lc = lang(), loc = lc === 'ru' ? 'ru-RU' : (lc === 'en' ? 'en-GB' : 'ro-RO');
70    var d = new Intl.DateTimeFormat(loc, {timeZone:'Europe/Chisinau', day:'numeric', month:'long'}).format(now);
71    var label = (CITY[lc] || CITY.ro) + ' · ' + d;
72    for (var i=0;i<elsT.length;i++) elsT[i].textContent = t;
73    for (var i2=0;i2<elsD.length;i2++) elsD[i2].textContent = label;
74  }
75  tick();
76  setInterval(tick, 1000);
77
78  /* „X ani pe piață" — calculat automat (anul curent, ora Chișinău, minus 2008), nu hardcodat */
79  var yearsEl = document.getElementById('heroYears');
80  if (yearsEl){
81    var nowY = +new Intl.DateTimeFormat('en-GB', {timeZone:'Europe/Chisinau', year:'numeric'}).format(new Date());
82    yearsEl.textContent = nowY - 2008;
83  }
84})();
85
86/* ---------- Ecosystem diagram ---------- */
87var ECO_NODES = [
88  {k:'eco.n1',  label:'POS și vânzări',            ic:'<path d="M4 7h16l-1.3 11.2a2 2 0 0 1-2 1.8H7.3a2 2 0 0 1-2-1.8L4 7zM8.5 10V6a3.5 3.5 0 0 1 7 0v4"/>'},
89  {k:'eco.n2',  label:'Fiscalizare electronică',   ic:'<path d="M7 3h10v18l-2-1.4L13 21l-2-1.4L9 21l-2-1.4V3zM10 8h4M10 12h4"/>'},
90  {k:'eco.n3',  label:'Plăți și QR',               ic:'<rect x="4" y="4" width="6.5" height="6.5" rx="1"/><rect x="13.5" y="4" width="6.5" height="6.5" rx="1"/><rect x="4" y="13.5" width="6.5" height="6.5" rx="1"/><path d="M13.5 13.5h3v3h-3zM20 13.5v.01M16.5 20h.01M20 17v3"/>'},
91  {k:'eco.n4',  label:'Facturare și documente',    ic:'<path d="M6 3h9l4 4v14H6V3zM14 3v5h5M9 12h6M9 16h6"/>'},
92  {k:'eco.n5',  label:'Loialitate și CRM',         ic:'<path d="M12 20s-7-4.3-7-9.5A4 4 0 0 1 12 8a4 4 0 0 1 7 2.5C19 15.7 12 20 12 20z"/>'},
93  {k:'eco.n6',  label:'SMS și notificări',         ic:'<path d="M4 5h16v11H9l-5 4V5z"/><path d="M8 9.5h8M8 12.5h5"/>'},
94  {k:'eco.n7',  label:'Business Intelligence',     ic:'<path d="M4 20V10M10 20V4M16 20v-8M21 20H3"/>'},
95  {k:'eco.n8',  label:'Terminale și dispozitive',          ic:'<circle cx="12" cy="17" r="1.6"/><path d="M8.5 13.5a5 5 0 0 1 7 0M5.7 10.6a9 9 0 0 1 12.6 0M3 7.6a13 13 0 0 1 18 0"/>'},
96  {k:'eco.n9',  label:'Aplicații mobile',          ic:'<rect x="7" y="2.5" width="10" height="19" rx="2.5"/><path d="M11 18.5h2"/>'},
97  {k:'eco.n10', label:'API și integrări',          ic:'<path d="M9 8l-4 4 4 4M15 8l4 4-4 4"/>'}
98];
99var diagram = document.getElementById('ecoDiagram');
100var spokes = document.getElementById('ecoSpokes');
101if (diagram && spokes){
102  var C = 300, Rn = 232, Rc = 96;
103  ECO_NODES.forEach(function(n, i){
104    var ang = -Math.PI/2 + i * (2*Math.PI/ECO_NODES.length);
105    var x = C + Rn*Math.cos(ang), y = C + Rn*Math.sin(ang);
106    var x1 = C + Rc*Math.cos(ang), y1 = C + Rc*Math.sin(ang);
107    var x2 = C + (Rn-40)*Math.cos(ang), y2 = C + (Rn-40)*Math.sin(ang);
108    var sp = document.createElementNS('http://www.w3.org/2000/svg','line');
109    sp.setAttribute('x1',x1); sp.setAttribute('y1',y1); sp.setAttribute('x2',x2); sp.setAttribute('y2',y2);
110    sp.setAttribute('class','spoke'); sp.dataset.i = i; spokes.appendChild(sp);
111    if (!reduced){
112      var fl = document.createElementNS('http://www.w3.org/2000/svg','line');
113      fl.setAttribute('x1',x1); fl.setAttribute('y1',y1); fl.setAttribute('x2',x2); fl.setAttribute('y2',y2);
114      fl.setAttribute('class','flow');
115      var len = Math.hypot(x2-x1, y2-y1);
116      fl.style.strokeDasharray = '5 ' + len;
117      fl.style.animation = 'ecoflow 4.8s linear infinite';
118      fl.style.animationDelay = (-i*0.48)+'s';
119      spokes.appendChild(fl);
120    }
121    var node = document.createElement('button');
122    node.type = 'button';
123    node.className = 'eco-node';
124    node.style.left = (x/600*100)+'%';
125    node.style.top  = (y/600*100)+'%';
126    node.style.background = 'none';
127    node.innerHTML = '<span class="eco-node-ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">'+n.ic+'</svg></span><span data-i18n="'+n.k+'">'+n.label+'</span>';
128    node.addEventListener('mouseenter', function(){ hot(i,true); });
129    node.addEventListener('mouseleave', function(){ hot(i,false); });
130    node.addEventListener('focus', function(){ hot(i,true); });
131    node.addEventListener('blur', function(){ hot(i,false); });
132    diagram.appendChild(node);
133  });
134  var style = document.createElement('style');
135  style.textContent = '@keyframes ecoflow{from{stroke-dashoffset:0}to{stroke-dashoffset:-'+(2*Rn)+'}} .eco-svg .flow{opacity:.55}';
136  if (!reduced) document.head.appendChild(style);
137}
138function hot(i, on){
139  var sp = spokes.querySelector('.spoke[data-i="'+i+'"]');
140  if (sp) sp.classList.toggle('hot', on);
141  var nodes = diagram.querySelectorAll('.eco-node');
142  if (nodes[i]) nodes[i].classList.toggle('hot', on);
143}
144
145/* ---------- Reveal on scroll ---------- */
146var io = new IntersectionObserver(function(entries){
147  entries.forEach(function(e){ if (e.isIntersecting){ e.target.classList.add('in'); io.unobserve(e.target); } });
148},{threshold:.12, rootMargin:'0px 0px -40px 0px'});
149document.querySelectorAll('.reveal').forEach(function(el){ io.observe(el); });
150
151/* ---------- Industry tabs ---------- */
152var tabs = document.querySelectorAll('.ind-tab');
153tabs.forEach(function(t){
154  t.addEventListener('click', function(){
155    tabs.forEach(function(x){ x.classList.remove('active'); x.setAttribute('aria-selected','false'); });
156    t.classList.add('active'); t.setAttribute('aria-selected','true');
157    document.querySelectorAll('.ind-content').forEach(function(c){
158      c.classList.toggle('active', c.dataset.ind === t.dataset.ind);
159    });
160  });
161});
162
163/* ---------- Cabinet client (dropdown) ---------- */
164var portal = document.querySelector('.portal');
165if (portal){
166  var pbtn = portal.querySelector('.portal-btn');
167  pbtn.addEventListener('click', function(e){
168    /* Butonul e un <a> cu href spre cabinetul SaaS — href-ul rămâne ca rezervă dacă
169       JS-ul nu rulează. Cu JS, clicul trebuie să DESCHIDĂ meniul, nu să navigheze:
170       fără preventDefault, meniul se deschidea o clipă și browserul pleca imediat
171       la RDWeb, iar celelalte 13 destinații nu erau niciodată accesibile. */
172    e.preventDefault();
173    e.stopPropagation();
174    var open = portal.classList.toggle('open');
175    pbtn.setAttribute('aria-expanded', open);
176  });
177  document.addEventListener('click', function(e){
178    if (!portal.contains(e.target)){ portal.classList.remove('open'); pbtn.setAttribute('aria-expanded','false'); }
179  });
180  document.addEventListener('keydown', function(e){
181    if (e.key === 'Escape'){ portal.classList.remove('open'); pbtn.setAttribute('aria-expanded','false'); }
182  });
183  var mob = document.getElementById('mobPortals');
184  if (mob) mob.innerHTML = portal.querySelector('.portal-menu').innerHTML;
185}
186
187/* ---------- Mega-meniu -> activează tab-ul industriei ---------- */
188document.querySelectorAll('[data-goto-ind]').forEach(function(a){
189  a.addEventListener('click', function(){
190    var t = document.querySelector('.ind-tab[data-ind="' + a.dataset.gotoInd + '"]');
191    if (t) t.click();
192  });
193});
194
195/* ---------- Product catalog filter ---------- */
196var pfBtns = document.querySelectorAll('.pf-btn');
197pfBtns.forEach(function(b){
198  b.addEventListener('click', function(){
199    pfBtns.forEach(function(x){ x.classList.remove('active'); });
200    b.classList.add('active');
201    var f = b.dataset.f;
202    document.querySelectorAll('.prod-item').forEach(function(it){
203      it.classList.toggle('hide', f !== 'all' && it.dataset.c !== f);
204    });
205  });
206});
207
208/* ---------- Counters ---------- */
209var cio = new IntersectionObserver(function(entries){
210  entries.forEach(function(e){
211    if (!e.isIntersecting) return;
212    var el = e.target, to = +el.dataset.to;
213    cio.unobserve(el);
214    if (reduced || to === 2008){ el.textContent = to.toLocaleString('ro-RO'); return; }
215    var t0 = performance.now(), dur = 1400;
216    (function tick(now){
217      var p = Math.min((now-t0)/dur, 1);
218      el.textContent = Math.round(to * (1-Math.pow(1-p,3))).toLocaleString('ro-RO');
219      if (p<1) requestAnimationFrame(tick);
220    })(t0);
221  });
222},{threshold:.6});
223document.querySelectorAll('.count').forEach(function(el){ cio.observe(el); });
224
225/* ---------- Contact form ---------- */
226var form = document.getElementById('contactForm');
227var success = document.getElementById('formSuccess');
228form.addEventListener('submit', function(e){
229  e.preventDefault();
230  var ok = true;
231  form.querySelectorAll('[required]').forEach(function(f){
232    var field = f.closest('.field');
233    var bad = !f.value.trim() || (f.type==='email' && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(f.value)) || (f.type==='checkbox' && !f.checked);
234    if (field){ field.classList.toggle('show-err', bad); f.classList.toggle('err', bad); }
235    else if (f.type==='checkbox' && bad){ f.focus(); }
236    if (bad) ok = false;
237  });
238  if (!ok) return;
239  var btn = document.getElementById('submitBtn');
240  btn.classList.add('btn-loading');
241  btn.innerHTML = '<span class="spinner"></span>';
242  btn.disabled = true;
243  var done = function(){ form.style.display = 'none'; success.classList.add('show'); };
244
245  /* șablonul HTML al e-mailului — stilul site-ului, compatibil cu clienții de e-mail */
246  function esc(s){ return String(s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); }
247  function emailRow(label, value){
248    if (!value) return '';
249    return '<tr>' +
250      '<td style="padding:11px 18px;border-bottom:1px solid #EAE2D3;font:700 11px/1.4 Arial,sans-serif;letter-spacing:1px;text-transform:uppercase;color:#B89B5E;white-space:nowrap;vertical-align:top">' + esc(label) + '</td>' +
251      '<td style="padding:11px 18px;border-bottom:1px solid #EAE2D3;font:400 14px/1.6 Georgia,serif;color:#20231F">' + esc(value) + '</td></tr>';
252  }
253  function buildEmailHtml(d){
254    return '<!DOCTYPE html><html><body style="margin:0;padding:0;background:#F5F1E8">
254' +
255      '<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background:#F5F1E8;padding:28px 12px"><tr><td align="center">' +
256      '<table role="presentation" width="620" cellpadding="0" cellspacing="0" style="max-width:620px;width:100%;background:#FAF8F3;border-radius:14px;overflow:hidden;border:1px solid #EAE2D3">' +
257      '<tr><td style="background:#12372A;padding:26px 30px">' +
258        '<div style="font:700 20px/1 Georgia,serif;color:#F5F1E8">intelect<span style="color:#72B827">soft</span></div>' +
259        '<div style="font:700 10.5px/1 Arial,sans-serif;letter-spacing:2px;text-transform:uppercase;color:#B89B5E;margin-top:9px">Solicitare nou\u0103 de pe intelectsoft.md</div>' +
260      '</td></tr>' +
261      '<tr><td style="padding:26px 30px 10px"><div style="font:600 22px/1.3 Georgia,serif;color:#12372A">' + esc(d.name) + '</div>' +
262        '<div style="font:400 13px/1.5 Arial,sans-serif;color:#666B63;margin-top:4px">' + esc(d.company) + '</div></td></tr>' +
263      '<tr><td style="padding:12px 30px 26px"><table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background:#ffffff;border:1px solid #EAE2D3;border-radius:10px;overflow:hidden">' +
264        emailRow('Telefon', d.phone) +
265        emailRow('E-mail', d.email) +
266        emailRow('Domeniu', d.industry) +
267        emailRow('Solu\u021bie', d.solution) +
268        emailRow('Mesaj', d.message) +
269      '</table></td></tr>' +
270      '<tr><td style="padding:0 30px 28px"><div style="font:400 11.5px/1.6 Arial,sans-serif;color:#666B63;border-top:1px solid #EAE2D3;padding-top:16px">' +
271        'Trimis de pe <a href="https://intelectsoft.md" style="color:#B89B5E;text-decoration:none;font-weight:700">intelectsoft.md</a> \u00b7 IntelectSoft SRL \u00b7 str. Alba Iulia 113, Chi\u0219in\u0103u</div></td></tr>' +
272      '</table></td></tr></table></body></html>';
273  }
274
275  function formLang(){ return document.documentElement.lang || 'ro'; }
276  var FAIL_MSG = {
277    ro: 'Reîncearcă — trimiterea a eșuat. Sau sună-ne: +373 22 835 312',
278    ru: 'Повторите — отправка не удалась. Или позвоните: +373 22 835 312',
279    en: 'Try again — sending failed. Or call us: +373 22 835 312'
280  };
281
282  var fields = {
283    name: document.getElementById('f-name'),
284    company: document.getElementById('f-company'),
285    phone: document.getElementById('f-phone'),
286    email: document.getElementById('f-email'),
287    industry: document.getElementById('f-industry'),
288    solution: document.getElementById('f-solution'),
289    message: document.getElementById('f-msg')
290  };
291  function fieldText(el){
292    if (!el) return '';
293    if (el.tagName === 'SELECT') return el.selectedIndex > 0 ? el.options[el.selectedIndex].text : '';
294    return el.value.trim();
295  }
296
297  var d = {};
298  Object.keys(fields).forEach(function(k){ d[k] = fieldText(fields[k]); });
299
300  /* honeypot anti-spam — identic cu qrl.md */
301  var hp = form.querySelector('[name="_gotcha"]');
302  if (hp && hp.value) { setTimeout(done, 800); return; }
303
304  var subj = {
305    ro: 'Solicitare nouă de pe intelectsoft.md · ' + d.company,
306    ru: 'Новая заявка с intelectsoft.md · ' + d.company,
307    en: 'New request from intelectsoft.md · ' + d.company
308  };
309  var payload = {
310    mail: {
311      to: [ESM_RECIPIENT],
312      noReply: true,
313      replyTo: d.email,
314      subject: subj[formLang()] || subj.ro,
315      body: buildEmailHtml(d),
316      isHtmlBody: true
317    },
318    action: 'request',
319    source: 'intelectsoft.md',
320    sendEmailOnDate: new Date().toISOString(),
321    apiKey: ESM_API_KEY
322  };
323  fetch(ESM_API_URL, {
324    method: 'POST',
325    headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
326    body: JSON.stringify(payload)
327  })
328    .then(function(res){
329      if (res.ok) { _isTg(d); done(); }
330      else { throw new Error('API ' + res.status); }
331    })
332    .catch(function(){
333      btn.disabled = false; btn.classList.remove('btn-loading');
334      btn.textContent = FAIL_MSG[formLang()] || FAIL_MSG.ro;
335    });
336});
337form.querySelectorAll('input,textarea').forEach(function(f){
338  f.addEventListener('input', function(){ var fd=f.closest('.field'); if(fd){fd.classList.remove('show-err'); f.classList.remove('err');} });
339});
340
341/* ---------- Limbă: navigare între versiunile statice /ru/ și /en/ ---------- */
342function pageLang(){ var m = location.pathname.match(/^\/(ru|en)(\/|$)/); return m ? m[1] : 'ro'; }
343function langHref(l){
344  var p = location.pathname.replace(/^\/(ru|en)(?=\/|$)/, '');
345  if (p === '') p = '/';
346  return (l === 'ro' ? '' : '/' + l) + p + location.hash;
347}
348var curLang = pageLang();
349document.querySelectorAll('.lang-btn').forEach(function(b){
350  var on = b.dataset.lang === curLang;
351  b.classList.toggle('active', on);
352  b.setAttribute('aria-pressed', on ? 'true' : 'false');
353  b.addEventListener('click', function(){
354    try { localStorage.setItem('is_lang', b.dataset.lang); } catch(e){}
355    if (b.dataset.lang !== curLang) location.href = langHref(b.dataset.lang);
356  });
357});
358})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.