PageSourceSearch

https://www.felcosit.com/assets/contact-modal.js?v=20260904-1

js felcosit.com collected 2026-10-07 07:16:06 UTC 7,206 bytes, 161 lines download raw bytes

1(() => {
2  if (window.felcosContactModalReady) return;
3
4  const triggers = document.querySelectorAll('[data-contact-modal]');
5  if (!triggers.length) return;
6  window.felcosContactModalReady = true;
7
8  const config = {
9    endpoint: 'contact.php',
10    email: '[email protected]',
11    phone: '+49 (621) 159 69 107',
12    phoneHref: 'tel:+4962115969107',
13    privacyUrl: '/datenschutz'
14  };
15
16  const modal = document.createElement('div');
17  modal.className = 'contact-modal';
18  modal.hidden = true;
19  modal.innerHTML = `
20    <div class="contact-modal__dialog" role="dialog" aria-modal="true" aria-labelledby="contact-modal-title">
21      <div class="contact-modal__header">
22        <div>
23          <span class="contact-modal__kicker">FelCos IT Kontakt</span>
24          <h2 id="contact-modal-title">Beratung oder Demo</h2>
25          <p>Schick uns kurz die wichtigsten Eckdaten. Direkte Kontaktwege stehen hier ebenfalls bereit.</p>
26        </div>
27        <button class="contact-modal__close" type="button" aria-label="Kontaktformular schließen">&times;</button>
28      </div>
29      <div class="contact-modal__body">
30        <aside class="contact-modal__direct" aria-label="Direkte Kontaktdaten">
31          <h3>Direkt erreichbar</h3>
32          <p>Für schnelle Rückfragen oder eine konkrete Terminabstimmung.</p>
33          <a class="contact-modal__contact-link" href="${config.phoneHref}"><span>&#9742;</span><span>${config.phone}</span></a>
34          <a class="contact-modal__contact-link" href="mailto:${config.email}"><span>@</span><span>${config.email}</span></a>
35          <div class="contact-modal__hub-note" aria-label="HuB Web-ERP Hinweis">
36            <img src="assets/img/hub-logo-header.svg" alt="HuB - The essentials. Nothing more.">
37            <strong>HuB – Web-ERP für wachsende KMU.</strong>
38            <span>Vom Team bis Company. Alle Module des aktuellen Releases. Ohne unnötigen Ballast.</span>
39            <ul class="contact-modal__facts" aria-label="FelCos IT Keyfacts">
40              <li>Über 25 Jahre ERP-Erfahrung</li>
41              <li>Beratung, Programmierung &amp; Prozessoptimierung</li>
42              <li>Direkter persönlicher Ansprechpartner</li>
43            </ul>
44          </div>
45        </aside>
46        <form class="contact-modal__form" action="${config.endpoint}" method="post">
47          <h3>Anfrage vorbereiten</h3>
48          <label class="contact-modal__website">Website<input name="website" tabindex="-1" autocomplete="off"></label>
49          <div class="contact-modal__grid">
50            <label>Name<input name="name" autocomplete="name" required></label>
51            <label>Firma<input name="company" autocomplete="organization"></label>
52          </div>
53          <div class="contact-modal__grid">
54            <label>E-Mail<input name="email" type="email" autocomplete="email" required></label>
55            <label>Telefon<input name="phone" autocomplete="tel"></label>
56          </div>
57          <label>Thema
58            <select name="topic">
59              <option>HuB Demo</option>
60              <option>HuB Beratung</option>
61              <option>Lexware Office Integration</option>
62              <option>caniasERP Anfrage</option>
63              <option>Förderung</option>
64              <option>Vereins-Aktion 2026</option>
65              <option>Web-Applikation</option>
66              <option>Allgemeine Anfrage</option>
67            </select>
68          </label>
69          <label>Nachricht<textarea name="message" maxlength="2500" placeholder="Worum geht es und wann passt ein Rückruf?"></textarea></label>
70          <label class="contact-modal__consent"><input name="privacy" type="checkbox" required><span>Ich stimme zu, dass FelCos IT meine Angaben zur Bearbeitung der Anfrage verarbeitet. Hinweise stehen in der <a href="${config.privacyUrl}">Datenschutzerklärung</a>.</span></label>
71          <div class="contact-modal__actions">
72            <button class="contact-modal__submit" type="submit">Kontaktanfrage senden</button>
73            <a class="contact-modal__fallback" href="mailto:${config.email}">Oder direkt mailen</a>
74          </div>
75          <p class="contact-modal__status" role="status" aria-live="polite"></p>
76        </form>
77      </div>
78    </div>`;
79  document.body.append(modal);
80
81  const form = modal.querySelector('form');
82  const topic = modal.querySelector('select[name="topic"]');
83  const closeButton = modal.querySelector('.contact-modal__close');
84  const submitButton = modal.querySelector('.contact-modal__submit');
85  const status = modal.querySelector('.contact-modal__status');
86  let previousFocus = null;
87
88  const setStatus = (message = '', type = '') => {
89    status.textContent = message;
90    status.dataset.status = type;
91  };
92
93  const openModal = (event) => {
94    event.preventDefault();
95    const trigger = event.currentTarget;
96    previousFocus = document.activeElement;
97    if (trigger.dataset.contactTopic) topic.value = trigger.dataset.contactTopic;
98    setStatus();
99    modal.hidden = false;
100    document.body.classList.add('contact-modal-open');
101    closeButton.focus();
102  };
103
104  const closeModal = () => {
105    modal.hidden = true;
106    document.body.classList.remove('contact-modal-open');
107    previousFocus?.focus();
108  };
109
110  form.addEventListener('submit', async (event) => {
111    event.preventDefault();
112    if (!form.reportValidity()) return;
113
114    if (window.location.protocol === 'file:') {
115      setStatus('Bitte öffne die Seite über den Webspace oder einen lokalen PHP-Webserver. Direkt als Datei kann contact.php nicht ausgeführt werden.', 'error');
116      return;
117    }
118
119    const formData = new FormData(form);
120    const payload = Object.fromEntries(formData.entries());
121    payload.privacy = formData.get('privacy') === 'on';
122
123    submitButton.disabled = true;
124    submitButton.textContent = 'Wird gesendet...';
125    setStatus('Anfrage wird sicher übermittelt.', 'pending');
126
127    try {
128      const response = await fetch(config.endpoint, {
129        method: 'POST',
130        headers: {
131          Accept: 'application/json',
132          'Content-Type': 'application/json'
133        },
134        body: JSON.stringify(payload)
135      });
136      const result = await response.json().catch(() => ({}));
137      if (!response.ok || !result.ok) {
138        throw new Error(result.message || 'Die Anfrage konnte gerade nicht gesendet werden.');
139      }
140
141      window.felcosTrack?.('contact_submit', { topic: payload.topic || 'unknown' });
142      form.reset();
143      topic.value = payload.topic || 'HuB Demo';
144      setStatus(result.message || 'Danke, deine Anfrage wurde gesendet.', 'success');
145    } catch (error) {
146      setStatus(error.message || 'Die Anfrage konnte gerade nicht gesendet werden. Bitte nutze E-Mail oder Telefon.', 'error');
147    } finally {
148      submitButton.disabled = false;
149      submitButton.textContent = 'Kontaktanfrage senden';
150    }
151  });
152
153  triggers.forEach((trigger) => trigger.addEventListener('click', openModal));
154  closeButton.addEventListener('click', closeModal);
155  modal.addEventListener('click', (event) => {
156    if (event.target === modal) closeModal();
157  });
158  document.addEventListener('keydown', (event) => {
159    if (event.key === 'Escape' && !modal.hidden) closeModal();
160  });
161})();

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.