Błąd "Element X not allowed as child of element Y in this context" to jeden z najczęstszych problemów podczas walidacji kodu HTML. Pojawia się, gdy próbujemy zagnieździć element w innym elemencie w sposób niezgodny ze standardami HTML. W tym przewodniku dowiesz się, jakie są przyczyny tego błędu, jakie są najczęstsze przypadki jego występowania oraz jak skutecznie go naprawić, aby Twoja strona była zgodna ze standardami W3C.

⚡ Ekspresowe Podsumowanie:

  1. Przyczyna błędu: Błąd pojawia się, gdy umieszczasz element HTML wewnątrz innego elementu, który zgodnie ze specyfikacją nie może go zawierać.
  2. Typowe przypadki: Umieszczanie elementów blokowych wewnątrz elementów liniowych, nieprawidłowa struktura list, tabeli lub formularzy.
  3. Rozwiązania: Zastosowanie prawidłowej struktury zagnieżdżenia zgodnej ze specyfikacją HTML5.
  4. Narzędzia pomocnicze: Walidator W3C, narzędzia deweloperskie przeglądarek, edytory z podpowiedziami składni.

🗺️ Spis Treści - Twoja Mapa Drogowa


📚 Zrozumienie błędu zagnieżdżenia elementów

Błąd "Element X not allowed as child of element Y in this context" (Element X nie jest dozwolony jako dziecko elementu Y w tym kontekście) jest stosunkowo prosty do zrozumienia, ale może być trudny do zidentyfikowania i naprawienia, szczególnie w bardziej złożonych strukturach HTML.

Co dokładnie oznacza ten błąd?

Ten komunikat wskazuje, że próbujesz umieścić element HTML (oznaczony jako X) wewnątrz innego elementu (oznaczonego jako Y), ale specyfikacja HTML nie pozwala na takie zagnieżdżenie. Każdy element HTML ma ściśle określone reguły dotyczące tego, jakie inne elementy mogą być jego "dziećmi" (czyli elementami zagnieżdżonymi).

Dlaczego to jest ważne?

Przestrzeganie prawidłowej struktury zagnieżdżania elementów jest kluczowe z kilku powodów:

  1. Zgodność ze standardami: Strony zgodne ze standardami W3C mają większą szansę na poprawne wyświetlanie we wszystkich przeglądarkach.
  2. Dostępność: Prawidłowa struktura HTML jest kluczowa dla czytników ekranu i innych technologii wspomagających.
  3. SEO: Wyszukiwarki lepiej interpretują i indeksują strony z poprawnym, semantycznym kodem HTML.
  4. Utrzymanie kodu: Czysty, zgodny ze standardami kod jest łatwiejszy do utrzymania i modyfikowania.

Podstawowe zasady zagnieżdżania elementów

W HTML istnieją pewne fundamentalne zasady, które warto znać:

  1. Elementy blokowe vs liniowe: Elementy blokowe (np. <div>, <p>, <h1>) mogą zawierać inne elementy blokowe i liniowe, ale elementy liniowe (np. <span>, <a>, <strong>) mogą zawierać tylko inne elementy liniowe.

  2. Elementy strukturalne: Niektóre elementy wymagają konkretnej struktury zagnieżdżenia, np. w <ul> lub <ol> można umieszczać tylko elementy <li>.

  3. Kontekst paragrafu: Niektóre elementy, jak <p>, mają ograniczony zestaw potomków i nie mogą zawierać innych elementów blokowych.

  4. Elementy puste: Niektóre elementy (np. <img>, <input>, <br>) są elementami pustymi i nie mogą zawierać innych elementów.

💡 Najczęstsze przypadki błędu i ich rozwiązania

Przyjrzyjmy się najczęściej spotykanym przypadkom tego błędu i sposobom ich rozwiązania:

1. Elementy blokowe wewnątrz elementów liniowych

Problem:

<span>
    <div>Ten kod generuje błąd</div>
</span>

Błąd: "Element div not allowed as child of element span in this context"

Rozwiązanie:

<!-- Opcja 1: Zamień element liniowy na blokowy -->
<div>
    <div>Ten kod jest poprawny</div>
</div>

<!-- Opcja 2: Zamień element blokowy na liniowy -->
<span>
    <span>Ten kod również jest poprawny</span>
</span>

2. Błędna struktura list

Problem:

<ul>
    Niepoprawny tekst bezpośrednio w liście
    <div>Niepoprawny element div w liście</div>
</ul>

Błąd: "Element div not allowed as child of element ul in this context"

Rozwiązanie:

<ul>
    <li>Tekst powinien być w elemencie li</li>
    <li><div>Teraz div jest poprawnie umieszczony w li</div></li>
</ul>

3. Elementy blokowe wewnątrz paragrafów

Problem:

<p>
    Początek paragrafu
    <div>Ten div powoduje błąd</div>
    Koniec paragrafu
</p>

Błąd: "Element div not allowed as child of element p in this context"

Rozwiązanie:

<p>Początek paragrafu</p>
<div>Ten div jest teraz poza paragrafem</div>
<p>Koniec paragrafu</p>

4. Nieprawidłowa struktura tabeli

Problem:

<table>
    <tr>
        <td>Komórka 1</td>
    </tr>
    <div>Ten div nie może być tutaj</div>
</table>

Błąd: "Element div not allowed as child of element table in this context"

Rozwiązanie:

<table>
    <tbody>
        <tr>
            <td>Komórka 1</td>
        </tr>
        <tr>
            <td>
                <div>Div może być wewnątrz komórki</div>
            </td>
        </tr>
    </tbody>
</table>

5. Błędy w formularzach

Problem:

<form>
    <label>Etykieta</label>
    <input type="text">
    <div>
        <button>Przycisk w div</button>
    </div>
    <p>Paragraf w formularzu</p>
</form>

Ten kod jest poprawny w HTML5, ale wcześniej mógł powodować problemy. Warto pamiętać, że formularze mają elastyczną strukturę i mogą zawierać większość elementów poza innymi formularzami.

✨ Pro Tip: W przypadku złożonych formularzy, dobrą praktyką jest grupowanie powiązanych elementów za pomocą <fieldset> z odpowiednim <legend>, co poprawia dostępność i semantykę:

<form>
    <fieldset>
        <legend>Dane osobowe</legend>
        <label for="name">Imię:</label>
        <input type="text" id="name">
    </fieldset>
    <button type="submit">Wyślij</button>
</form>

🔍 Jak zidentyfikować i naprawić błędy zagnieżdżenia

Aby skutecznie identyfikować i naprawiać błędy zagnieżdżenia, warto korzystać z odpowiednich narzędzi i technik:

1. Walidator W3C

Najprostszym sposobem sprawdzenia, czy Twój kod HTML zawiera błędy zagnieżdżenia, jest skorzystanie z oficjalnego walidatora W3C:

  1. Odwiedź stronę validator.w3.org
  2. Wprowadź adres URL swojej strony, prześlij plik HTML lub wklej bezpośrednio kod
  3. Analizuj otrzymane wyniki, zwracając szczególną uwagę na komunikaty o błędach zagnieżdżenia

Walidator W3C wskaże dokładnie, które elementy są nieprawidłowo zagnieżdżone, i często sugeruje rozwiązania.

2. Narzędzia deweloperskie przeglądarek

Nowoczesne przeglądarki oferują zaawansowane narzędzia deweloperskie, które pomagają identyfikować problemy z kodem HTML:

  1. Otwórz narzędzia deweloperskie (zazwyczaj F12 lub Ctrl+Shift+I)
  2. Przejdź do zakładki "Elements" (Chrome) lub "Inspector" (Firefox)
  3. Przeszukaj DOM (Document Object Model) w poszukiwaniu nieprawidłowych struktur
  4. Zwróć uwagę na ostrzeżenia wyświetlane przez przeglądarkę

3. Edytory kodu z podpowiedziami składni

Korzystaj z edytorów kodu, które oferują podpowiedzi składni i walidację w czasie rzeczywistym:

  • Visual Studio Code z rozszerzeniami takimi jak HTML Hint czy HTMLHint
  • PhpStorm lub WebStorm z wbudowaną obsługą walidacji HTML
  • Sublime Text z pluginem SublimeLinter

Takie narzędzia często podkreślają problematyczne fragmenty kodu jeszcze przed zapisaniem pliku.

4. Podejście systematyczne

Przy naprawianiu błędów zagnieżdżenia warto zastosować systematyczne podejście:

  1. Izoluj problem: Wyodrębnij fragment kodu, który powoduje błąd
  2. Zrozum ograniczenia: Sprawdź w dokumentacji, jakie elementy mogą być zagnieżdżane w elemencie nadrzędnym
  3. Przeorganizuj strukturę: Zmień strukturę HTML, zachowując jednocześnie zamierzony wygląd i funkcjonalność
  4. Testuj inkrementalnie: Po każdej zmianie waliduj kod, aby upewnić się, że błąd został rozwiązany i nie wprowadzono nowych problemów

Uwaga: Pamiętaj, że niektóre frameworki i biblioteki mogą generować HTML, który wygląda niepoprawnie, ale działa prawidłowo w kontekście danego narzędzia. Zawsze sprawdzaj dokumentację używanych technologii.

🛠️ Przewodnik po dozwolonych zagnieżdżeniach elementów HTML5

Poniżej prezentujemy przewodnik po najczęściej używanych elementach HTML5 i ich dozwolonych "dzieciach", który pomoże Ci unikać błędów zagnieżdżenia:

Elementy dokumentu i sekcji

  • \ - Może zawierać: \, \
  • \ - Może zawierać: \, \<meta>, \<link>, \<style>, \<script>, \<noscript>, \<base></li> <li><strong>\<body></strong> - Może zawierać praktycznie wszystkie elementy widoczne (blokowe i liniowe)</li> <li><strong>\<header></strong>, <strong>\<footer></strong>, <strong>\<main></strong>, <strong>\<section></strong>, <strong>\<article></strong>, <strong>\<aside></strong>, <strong>\<nav></strong> - Elementy strukturalne, mogą zawierać większość elementów blokowych i liniowych, ale nie mogą zawierać \<header> lub \<footer> wewnątrz \<header> lub \<footer></li> </ul> <h3>Elementy blokowe</h3> <ul> <li><strong>\<div></strong> - Może zawierać praktycznie wszystkie elementy (blokowe i liniowe)</li> <li><strong>\<p></strong> - Może zawierać tylko elementy liniowe, NIE może zawierać elementów blokowych</li> <li><strong>\<h1></strong> do <strong>\<h6></strong> - Powinny zawierać głównie tekst i elementy liniowe, unikaj zagnieżdżania elementów blokowych</li> <li><strong>\<blockquote></strong> - Może zawierać elementy blokowe i liniowe</li> <li><strong>\<pre></strong> - Zazwyczaj zawiera tekst i ograniczony zestaw elementów liniowych</li> </ul> <h3>Listy</h3> <ul> <li><strong>\<ul></strong>, <strong>\<ol></strong> - Mogą zawierać TYLKO elementy \<li></li> <li><strong>\<li></strong> - Może zawierać zarówno elementy blokowe, jak i liniowe</li> <li><strong>\<dl></strong> - Może zawierać tylko elementy \<dt> i \<dd></li> <li><strong>\<dt></strong> - Powinien zawierać głównie tekst i elementy liniowe</li> <li><strong>\<dd></strong> - Może zawierać elementy blokowe i liniowe</li> </ul> <h3>Tabele</h3> <ul> <li><strong>\<table></strong> - Może zawierać: \<caption>, \<colgroup>, \<thead>, \<tbody>, \<tfoot>, \<tr></li> <li><strong>\<tr></strong> - Może zawierać tylko \<th> i \<td></li> <li><strong>\<th></strong>, <strong>\<td></strong> - Mogą zawierać zarówno elementy blokowe, jak i liniowe</li> </ul> <h3>Formularze</h3> <ul> <li><strong>\<form></strong> - Może zawierać większość elementów HTML poza innym \<form></li> <li><strong>\<fieldset></strong> - Grupuje powiązane elementy formularza, powinien zawierać \<legend> i elementy formularza</li> <li><strong>\<select></strong> - Może zawierać tylko elementy \<option> i \<optgroup></li> <li><strong>\<optgroup></strong> - Może zawierać tylko elementy \<option></li> <li><strong>\<button></strong> - Może zawierać elementy liniowe (ale nie \<a>, \<button>, \<select>, \<textarea>, \<input>, \<label>)</li> </ul> <h3>Elementy liniowe</h3> <ul> <li><strong>\<a></strong> - Może zawierać większość elementów liniowych i niektóre blokowe w HTML5 (ale nie inne \<a>)</li> <li><strong>\<span></strong>, <strong>\<em></strong>, <strong>\<strong></strong>, <strong>\<code></strong>, <strong>\<i></strong>, <strong>\<b></strong> - Powinny zawierać tylko tekst i inne elementy liniowe</li> <li><strong>\<br></strong>, <strong>\<img></strong>, <strong>\<input></strong> - Elementy puste, nie mogą zawierać żadnych dzieci</li> </ul> <p><strong>✨ Pro Tip:</strong> Jeśli nie jesteś pewien, jakie elementy mogą być zagnieżdżone w konkretnym elemencie, sprawdź oficjalną dokumentację HTML na <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element">MDN Web Docs</a> lub <a href="https://www.w3.org/TR/html52/dom.html#elements">W3C</a>.</p> <h2>🧪 Przykłady przed i po poprawkach</h2> <p>Najlepszym sposobem na zrozumienie, jak naprawiać błędy zagnieżdżenia, jest analiza konkretnych przykładów:</p> <h3>Przykład 1: Menu nawigacyjne</h3> <p><strong>Przed (z błędem):</strong></p> <pre><code class="language-html"><nav> Home <div>O nas</div> <div>Kontakt</div> </nav></code></pre> <p><strong>Błąd:</strong> Tekst i elementy div nie powinny być bezpośrednimi dziećmi nav.</p> <p><strong>Po (poprawione):</strong></p> <pre><code class="language-html"><nav> <ul> <li><a href="/">Home</a></li> <li><a href="/o-nas">O nas</a></li> <li><a href="/kontakt">Kontakt</a></li> </ul> </nav></code></pre> <h3>Przykład 2: Artykuł z obrazkami</h3> <p><strong>Przed (z błędem):</strong></p> <pre><code class="language-html"><article> <h2>Tytuł artykułu</h2> <p> Początek tekstu <div class="image-container"> <img src="obraz.jpg" alt="Opis obrazu"> </div> Dalsza część tekstu. </p> </article></code></pre> <p><strong>Błąd:</strong> Element div nie może być dzieckiem p.</p> <p><strong>Po (poprawione):</strong></p> <pre><code class="language-html"><article> <h2>Tytuł artykułu</h2> <p>Początek tekstu</p> <div class="image-container"> <img src="obraz.jpg" alt="Opis obrazu"> </div> <p>Dalsza część tekstu.</p> </article></code></pre> <h3>Przykład 3: Struktura formularza</h3> <p><strong>Przed (z błędem):</strong></p> <pre><code class="language-html"><form> <label>Imię</label> <label>Email</label> <input type="text"> <input type="email"> <button>Wyślij</button> </form></code></pre> <p><strong>Błąd:</strong> Brak powiązania między labelami i inputami.</p> <p><strong>Po (poprawione):</strong></p> <pre><code class="language-html"><form> <div class="form-group"> <label for="name">Imię</label> <input type="text" id="name"> </div> <div class="form-group"> <label for="email">Email</label> <input type="email" id="email"> </div> <button type="submit">Wyślij</button> </form></code></pre> <h3>Przykład 4: Lista z mieszaną zawartością</h3> <p><strong>Przed (z błędem):</strong></p> <pre><code class="language-html"><ul> <li>Pierwszy element</li> Tekst poza li <div>Element div</div> <li>Ostatni element</li> </ul></code></pre> <p><strong>Błąd:</strong> Tekst i div nie mogą być bezpośrednimi dziećmi ul.</p> <p><strong>Po (poprawione):</strong></p> <pre><code class="language-html"><ul> <li>Pierwszy element</li> <li>Tekst w odpowiednim miejscu</li> <li><div>Element div teraz w li</div></li> <li>Ostatni element</li> </ul></code></pre> <h2>❓ FAQ - Odpowiedzi na Twoje Pytania</h2> <p><strong>Czy wszystkie przeglądarki tak samo interpretują błędy zagnieżdżenia?</strong><br /> Nie. Różne przeglądarki mogą stosować różne strategie naprawy niepoprawnego kodu HTML. Dlatego strona z błędami może wyglądać inaczej w różnych przeglądarkach, co prowadzi do problemów z kompatybilnością.</p> <p><strong>Czy HTML5 jest bardziej elastyczny w kwestii zagnieżdżania niż starsze wersje?</strong><br /> Tak, HTML5 wprowadził pewne złagodzenia w porównaniu do wcześniejszych standardów. Na przykład, w HTML5 element \<a> może zawierać niektóre elementy blokowe, co wcześniej było niedozwolone.</p> <p><strong>Jak sprawdzić, czy mój framework generuje poprawny HTML?</strong><br /> Możesz użyć walidatora W3C na wyrenderowanej stronie (nie na szablonach). Pamiętaj jednak, że niektóre frameworki celowo generują kod, który wygląda na niepoprawny, ale działa poprawnie w kontekście danego narzędzia.</p> <p><strong>Czy błędy zagnieżdżenia wpływają na SEO?</strong><br /> Tak, mogą wpływać. Wyszukiwarki polegają na poprawnym, semantycznym HTML do zrozumienia struktury i treści strony. Poważne błędy mogą utrudnić indeksowanie i potencjalnie wpłynąć na pozycję w wynikach wyszukiwania.</p> <p><strong>Co zrobić, jeśli naprawienie błędu zagnieżdżenia psuje wygląd mojej strony?</strong><br /> Jeśli naprawa struktury HTML wpływa na wygląd strony, prawdopodobnie potrzebujesz także dostosować swój CSS. Zamiast polegać na niepoprawnej strukturze HTML, lepiej jest naprawić zarówno HTML, jak i CSS, aby zachować zgodność ze standardami.</p> <h2>🏁 Podsumowanie - Twórz poprawny, semantyczny HTML</h2> <p>Błędy zagnieżdżenia elementów HTML, choć czasem frustrujące, są stosunkowo łatwe do naprawienia, gdy zrozumiesz podstawowe zasady struktury HTML. Pamiętaj, że tworzenie kodu zgodnego ze standardami nie jest tylko kwestią "czystości" - ma realne zalety w postaci lepszej kompatybilności między przeglądarkami, dostępności i optymalizacji dla wyszukiwarek.</p> <p>Kluczem do unikania i naprawiania błędów zagnieżdżenia jest:</p> <ol> <li><strong>Poznanie zasad:</strong> Zrozumienie, które elementy mogą być zagnieżdżone w innych</li> <li><strong>Regularna walidacja:</strong> Sprawdzanie kodu za pomocą oficjalnego walidatora W3C</li> <li><strong>Właściwe narzędzia:</strong> Korzystanie z edytorów z podpowiedziami składni</li> <li><strong>Myślenie semantyczne:</strong> Używanie elementów HTML zgodnie z ich znaczeniem, a nie tylko wyglądem</li> </ol> <p>Pamiętaj, że poprawny, semantyczny HTML to fundament każdej dobrze działającej strony internetowej.</p> <h3>✅ Twoja Checklista:</h3> <ul> <li>🔍 Regularnie waliduj swój kod HTML</li> <li>🔄 Poznaj ograniczenia zagnieżdżania dla używanych elementów</li> <li>🔒 Stosuj edytory kodu z podpowiedziami składni HTML</li> <li>📝 Myśl o znaczeniu semantycznym każdego elementu</li> <li>📊 Testuj stronę w różnych przeglądarkach</li> </ul> <p><strong>🚀 Potrzebujesz pomocy z kodowaniem strony?</strong></p> <p>W <a href="https://iqhost.pl/oferta">IQHost</a> oferujemy nie tylko niezawodny hosting, ale także wsparcie techniczne, które pomoże Ci rozwiązać problemy z kodem HTML. Nasze serwery są zoptymalizowane do szybkiego działania stron internetowych, a nasz zespół ekspertów służy pomocą w kwestiach technicznych.</p> <p><em>Skontaktuj się z nami już dziś, aby dowiedzieć się, jak możemy pomóc Ci w tworzeniu doskonałych stron internetowych zgodnych ze standardami!</em></p> <!-- Tagi wpisu --> <div class="article-tags"> <h3>Kategorie i tagi</h3> <div class="tag-list"> <a href="https://dev.iqhost.pl/blog?kategoria=Web+Development" class="tag"> <i class="fas fa-tag"></i> Web Development </a> <a href="https://dev.iqhost.pl/blog?kategoria=Rozwi%C4%85zywanie+problem%C3%B3w" class="tag"> <i class="fas fa-tag"></i> Rozwiązywanie problemów </a> </div> </div> <!-- Ocena artykułu --> <div class="article-feedback"> <h3>Czy ten artykuł był pomocny?</h3> <div class="feedback-buttons"> <button class="article-feedback-button positive" data-post-id="jak-poprawic-blad-element-x-not-allowed-as-child-of-element-y-in-this-context" data-helpful="true"> <i class="fas fa-thumbs-up"></i> Tak </button> <button class="article-feedback-button negative" data-post-id="jak-poprawic-blad-element-x-not-allowed-as-child-of-element-y-in-this-context" data-helpful="false"> <i class="fas fa-thumbs-down"></i> Nie </button> </div> <div class="feedback-thank-you mt-4" style="display: none;"> <p>Dziękujemy za Twoją opinię! Twoja ocena pomoże nam ulepszać naszego bloga.</p> </div> </div> <div class="post-navigation"> <a href="https://dev.iqhost.pl/blog" class="btn btn-outline-primary"> <i class="fas fa-arrow-left"></i> Wróć do listy wpisów </a> </div> <!-- Call to Action dla hostingu - skopiowane z article-page.php --> <div class="article-cta"> <h3>Twoja strona WordPress działa wolno?</h3> <p>Sprawdź nasz hosting WordPress z ultraszybkimi dyskami NVMe i konfiguracją serwera zoptymalizowaną pod kątem wydajności. Doświadcz różnicy już dziś!</p> <a href="https://dev.iqhost.pl" class="cta-hosting-button"> <i class="fas fa-rocket"></i> Sprawdź ofertę hostingu </a> <div class="hosting-guarantee"> <i class="fas fa-shield-alt"></i> 30-dniowa gwarancja zwrotu pieniędzy </div> </div> </div> </div> <div class="article-sidebar"> <!-- Spis treści --> <div class="sidebar-section"> <h3 class="sidebar-title"><i class="fas fa-list"></i> Spis treści</h3> <div class="sidebar-toc"> <ul class="simple-toc-list" id="toc-right-menu" role="navigation" aria-label="Spis treści"> <!-- Spis treści zostanie wygenerowany przez JavaScript --> </ul> </div> </div> <!-- Kategorie --> <div class="sidebar-section"> <h3 class="sidebar-title"><i class="fas fa-folder"></i> Kategorie</h3> <ul class="sidebar-categories"> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Bezpiecze%C5%84stwo"> Bezpieczeństwo </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Hosting"> Hosting </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Serwery"> Serwery </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Poradniki"> Poradniki </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=WordPress"> WordPress </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Chmura"> Chmura </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Linux"> Linux </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Administracja"> Administracja </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Infrastruktura"> Infrastruktura </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Wirtualizacja"> Wirtualizacja </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Narz%C4%99dzia"> Narzędzia </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Technologia"> Technologia </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Administracja+Serwerem"> Administracja Serwerem </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Domeny"> Domeny </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Programowanie"> Programowanie </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=DevOps"> DevOps </a> </li> <li class="sidebar-category-item active"> <a href="https://dev.iqhost.pl/blog?kategoria=Rozwi%C4%85zywanie+problem%C3%B3w"> Rozwiązywanie problemów </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Optymalizacja"> Optymalizacja </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Administracja+serwerem"> Administracja serwerem </a> </li> <li class="sidebar-category-item "> <a href="https://dev.iqhost.pl/blog?kategoria=Poczta"> Poczta </a> </li> </ul> </div> <!-- Podobne wpisy (widoczne tylko na dużych ekranach) --> <div class="sidebar-section d-none d-lg-block"> <h3 class="sidebar-title">Podobne artykuły</h3> <div class="sidebar-posts"> <div class="sidebar-post-item"> <a href="https://dev.iqhost.pl/blog/jak-naprawic-blad-pliki-cookie-sa-blokowane-w-wordpressie" class="sidebar-post-link"> <div class="sidebar-post-title">Jak naprawić błąd "Pliki cookie są blokowane" w WordPressie? Kompleksowy poradnik</div> <div class="sidebar-post-meta"> <span class="post-date">03.05.2025</span> </div> </a> </div> <div class="sidebar-post-item"> <a href="https://dev.iqhost.pl/blog/jak-stworzyc-wlasna-skorke-w-wordpress-krok-po-kroku" class="sidebar-post-link"> <div class="sidebar-post-title">Jak stworzyć własną skórkę w WordPress krok po kroku - kompletny przewodnik</div> <div class="sidebar-post-meta"> <span class="post-date">01.05.2025</span> </div> </a> </div> <div class="sidebar-post-item"> <a href="https://dev.iqhost.pl/blog/python-skrypt-do-aplikacji-web-na-hostingu" class="sidebar-post-link"> <div class="sidebar-post-title">Jak stworzyć i wdrożyć skrypt Python dla aplikacji webowej na hostingu</div> <div class="sidebar-post-meta"> <span class="post-date">01.05.2025</span> </div> </a> </div> </div> </div> <!-- Baner promocyjny - skopiowane z post-view.php --> <div class="sidebar-section promo-section"> <div class="promo-banner"> <h4>Hosting WordPress</h4> <p>Błyskawicznie szybki hosting dla Twojej strony</p> <div class="promo-price">Od 39,95 zł/rok</div> <a href="https://dev.iqhost.pl" class="btn">Sprawdź ofertę</a> </div> </div> </div> </div> </div> </section> <!-- CTA --> <section class="cta-section section-padding"> <div class="container"> <div class="cta-wrapper"> <div class="cta-content" data-aos="fade-right"> <h2>Zostań na bieżąco z nowościami na blogu!</h2> <p>Nie przegap najnowszych artykułów, porad i inspiracji ze świata hostingu, domen i technologii. Zapisz się do newslettera lub przeglądaj najnowsze wpisy!</p> <div class="cta-buttons"> <a href="#blog-posts" class="cta-button primary">Przeglądaj artykuły</a> <a href="#newsletter" class="cta-button secondary">Zapisz się do newslettera</a> </div> </div> <div class="cta-image" data-aos="fade-left"> <img src="https://dev.iqhost.pl/assets/images/cta-illustration.svg?v=1767455018" alt="Blog IQHost" width="400" height="300"> </div> </div> </div> </section> <!-- Skrypt do generowania spisu treści - NOWY DESIGN z hierarchią --> <script> document.addEventListener('DOMContentLoaded', function() { // Funkcja do generowania spisu treści - prosta wersja function generateTableOfContents() { const contentDiv = document.querySelector('.article-text'); if (!contentDiv) return; const headings = contentDiv.querySelectorAll('h2, h3'); if (headings.length === 0) { const tocSection = document.querySelector('.sidebar-section'); if (tocSection) tocSection.style.display = 'none'; return; } const tocList = document.getElementById('toc-right-menu'); if (!tocList) return; tocList.innerHTML = ''; // Filtruj nagłówki do pominięcia const skipPatterns = ['spis treści', 'spis tresci', 'table of contents', 'kategorie i tagi', 'czy ten artykuł']; headings.forEach(function(heading, index) { const headingText = heading.textContent.toLowerCase().trim(); // Pomiń nagłówki pasujące do wzorców for (const pattern of skipPatterns) { if (headingText.includes(pattern)) return; } // Dodaj ID do nagłówka jeśli nie ma if (!heading.id) { const slug = heading.textContent .toLowerCase() .replace(/[^\w\s-]/g, '') .replace(/\s+/g, '-') .substring(0, 50); heading.id = slug || ('heading-' + index); } const listItem = document.createElement('li'); listItem.className = 'toc-item toc-' + heading.tagName.toLowerCase(); const link = document.createElement('a'); link.href = '#' + heading.id; link.className = 'toc-link'; // Tekst - usuń emoji i skróć let displayText = heading.textContent.trim(); displayText = displayText.replace(/^[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}⚡📚💻🚀🛠️📦🔐🌐❓🏁✨⚙️✅🗺️👍🔍🛒📈🚫📧🔄🎯]+\s*/gu, ''); if (displayText.length > 40) { link.title = displayText; displayText = displayText.substring(0, 37) + '...'; } link.textContent = displayText; // Smooth scroll link.addEventListener('click', function(e) { e.preventDefault(); const targetElement = document.getElementById(heading.id); if (targetElement) { window.scrollTo({ top: targetElement.offsetTop - 100, behavior: 'smooth' }); document.querySelectorAll('.toc-link').forEach(l => l.classList.remove('active')); this.classList.add('active'); } }); listItem.appendChild(link); tocList.appendChild(listItem); }); } // Funkcja do obsługi przełącznika sidebara function setupSidebarToggle() { console.log('=== setupSidebarToggle START ==='); const sidebarToggle = document.getElementById('sidebar-toggle'); console.log('sidebarToggle element:', sidebarToggle); if (!sidebarToggle) { console.error('ERROR: Sidebar toggle button NOT FOUND!'); return; } const sidebar = document.querySelector('.article-sidebar'); const mainContent = document.querySelector('.article-main'); console.log('sidebar element:', sidebar); console.log('mainContent element:', mainContent); if (!sidebar || !mainContent) { console.error('ERROR: Sidebar or mainContent NOT FOUND!'); return; } let isHidden = false; sidebarToggle.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); console.log('=== CLICK! isHidden before:', isHidden); isHidden = !isHidden; console.log('=== isHidden after toggle:', isHidden); if (isHidden) { // Ukryj sidebar.style.cssText = 'display: none !important; visibility: hidden !important; opacity: 0 !important;'; mainContent.style.cssText = 'grid-column: 1 / -1 !important; max-width: 100% !important;'; console.log('>>> UKRYWAM SIDEBAR'); } else { // Pokaż sidebar.style.cssText = ''; mainContent.style.cssText = ''; console.log('>>> POKAZUJĘ SIDEBAR'); } const textSpan = sidebarToggle.querySelector('.text'); if (textSpan) { textSpan.textContent = isHidden ? 'Pokaż panel boczny' : 'Ukryj panel boczny'; } }); console.log('=== Sidebar toggle INITIALIZED ==='); } // Funkcja do obsługi przycisków oceny artykułu function setupFeedbackButtons() { const feedbackButtons = document.querySelectorAll('.article-feedback-button'); if (feedbackButtons.length === 0) return; feedbackButtons.forEach(function(button) { button.addEventListener('click', function() { // Tutaj można dodać logikę zapisu oceny artykułu, np. przez AJAX // Ukryj przyciski i pokaż podziękowanie const feedbackButtonsContainer = button.closest('.feedback-buttons'); const feedbackThankYou = button.closest('.article-feedback').querySelector('.feedback-thank-you'); if (feedbackButtonsContainer) feedbackButtonsContainer.style.display = 'none'; if (feedbackThankYou) feedbackThankYou.style.display = 'block'; }); }); } // Funkcja do zaznaczania aktywnej sekcji podczas przewijania - prosta wersja function setupScrollSpy() { const headings = document.querySelectorAll('.article-text h2, .article-text h3'); const tocLinks = document.querySelectorAll('.toc-link'); if (headings.length === 0 || tocLinks.length === 0) return; let ticking = false; window.addEventListener('scroll', function() { if (!ticking) { window.requestAnimationFrame(function() { const scrollPosition = window.scrollY; // Znajdź aktywny nagłówek let currentHeading = null; headings.forEach(function(heading) { if (scrollPosition >= heading.offsetTop - 150) { currentHeading = heading; } }); // Zaznacz aktywny link if (currentHeading) { tocLinks.forEach(function(link) { link.classList.remove('active'); if (link.getAttribute('href') === '#' + currentHeading.id) { link.classList.add('active'); } }); } ticking = false; }); ticking = true; } }); } // Inicjalizacja wszystkich funkcji generateTableOfContents(); setupSidebarToggle(); setupFeedbackButtons(); setupScrollSpy(); // Dodatkowa inicjalizacja scrollspy po załadowaniu wszystkich obrazów window.addEventListener('load', function() { setupScrollSpy(); }); }); </script> <!-- Highlight.js tylko dla bloga --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> <script src="https://dev.iqhost.pl/assets/js/blog-article.js"></script> <!-- Skrypt dodający klasy do artykułu --> <script> document.addEventListener('DOMContentLoaded', function() { // Dodaj klasę blog-article-content do treści artykułu const articleContent = document.querySelector('.article-text'); if (articleContent) { articleContent.classList.add('blog-article-content'); } // Ukryj nagłówek "Spis treści" w treści artykułu (bo mamy go w sidebarze) const headings = articleContent ? articleContent.querySelectorAll('h2, h3') : []; headings.forEach(heading => { const text = heading.textContent.toLowerCase(); if (text.includes('spis treści') || text.includes('spis tresci') || text.includes('table of contents') || text.includes('mapa drogowa')) { // Ukryj nagłówek i następny element (jeśli to separator lub pusty element) heading.style.display = 'none'; const nextEl = heading.nextElementSibling; if (nextEl && (nextEl.tagName === 'HR' || nextEl.innerHTML.trim() === '' || nextEl.innerHTML.includes('<!-- '))) { nextEl.style.display = 'none'; } } }); // Ukryj inline TOC - listę z linkami nawigacyjnymi w treści (zachowujemy tylko sidebar TOC) if (articleContent) { const allLists = articleContent.querySelectorAll('ul, ol'); allLists.forEach(list => { const links = list.querySelectorAll('a'); // Sprawdź czy większość linków to anchory wewnętrzne (#) let anchorCount = 0; links.forEach(link => { if (link.href && link.href.includes('#') && !link.href.includes('http')) { anchorCount++; } else if (link.getAttribute('href') && link.getAttribute('href').startsWith('#')) { anchorCount++; } }); // Jeśli lista ma więcej niż 10 linków i większość to anchory - to prawdopodobnie inline TOC if (links.length > 10 && anchorCount > links.length * 0.7) { list.style.display = 'none'; // Ukryj też poprzedni HR jeśli istnieje const prevEl = list.previousElementSibling; if (prevEl && prevEl.tagName === 'HR') { prevEl.style.display = 'none'; } // Ukryj następny HR jeśli istnieje const nextEl = list.nextElementSibling; if (nextEl && nextEl.tagName === 'HR') { nextEl.style.display = 'none'; } } }); } // Dodatkowe usprawnienia dla spisu treści const tocContainer = document.querySelector('.sidebar-toc'); if (tocContainer) { // Usuń wszystkie zbyt długie wcięcia const tocLinks = tocContainer.querySelectorAll('.toc-link'); tocLinks.forEach(link => { // Jeśli tekst jest zbyt długi, przytnij go if (link.textContent.length > 40) { link.title = link.textContent; // Pełna nazwa jako tooltip link.textContent = link.textContent.substring(0, 37) + '...'; } }); } // Naprawa ID nagłówków dla poprawnego działania spisu treści // Mapa dla nagłówków/ID w markdown, dokładnie takich jak w pliku .md const headingIdMap = { '\ud83c\uddf5\ud83c\uddf1 Dlaczego .pl Króluje w Polskim Internecie?': 'dlaczego-pl', '\ud83d\udc4d Krok 1: Nazwa Domeny Idealna - Jak Ją Stworzyć?': 'krok1', '\ud83d\udd0d Krok 2: Dostępność i Sekrety WHOIS': 'krok2', '\ud83d\udeab Najczęstsze Błędy Przy Rejestracji': 'common-mistakes', '\ud83d\uded2 Krok 3: Rejestracja Krok Po Kroku': 'krok3', '\u2705 Twoja Checklista Rejestracji Domeny .pl': 'checklist', '\u2699\ufe0f Krok 4: DNS & DNSSEC - Techniczne Serce Domeny': 'krok4', '\ud83d\udce7 Krok 5: SPF, DKIM, DMARC - Zadbaj o Dostarczalność E-maili': 'krok5', '\ud83d\udd04 Krok 6: Zarządzanie Cyklem Życia': 'krok6', '\ud83d\udcc8 Krok 7: Pro SEO Tricki dla Domeny .pl': 'krok7', '\u2753 FAQ - Odpowiedzi na Twoje Pytania': 'faq', '\ud83c\udfc1 Podsumowanie - Gotowy na Sukces?': 'podsumowanie' }; // Znajdź wszystkie nagłówki h2 w artykule const h2s = document.querySelectorAll('.article-text h2'); h2s.forEach(heading => { const text = heading.textContent.trim(); if (headingIdMap[text]) { heading.id = headingIdMap[text]; console.log('Ustawiono ID:', heading.id, 'dla nagłówka:', text); } }); // Również naprawiamy linki w spisie treści setTimeout(() => { const tocLinks = document.querySelectorAll('.toc-link'); tocLinks.forEach(link => { const text = link.textContent.trim(); Object.entries(headingIdMap).forEach(([headingText, id]) => { // Sprawdź, czy tekst linku jest częścią tekstu nagłówka po usunięciu emoji const cleanHeadingText = headingText.replace(/^[\u{1F300}-\u{1F6FF}\u{2600}-\u{26FF}\s]+/u, '').trim(); if (cleanHeadingText.includes(text)) { link.href = '#' + id; console.log('Naprawiono link:', link.textContent, 'href:', link.href); } }); }); }, 500); }); </script> <!-- Stopka --> <footer class="footer"> <div class="container"> <!-- Social Media na górze --> <div class="footer-social-top"> <a href="https://www.facebook.com/iqhostpl" class="social-icon" target="_blank" rel="noopener noreferrer" aria-label="Facebook"> <i class="fab fa-facebook-f"></i> </a> </div> <!-- 5 kolumn w jednym rzędzie --> <div class="footer-main-grid"> <!-- Kolumna 1: Brand --> <div class="footer-column footer-brand-column"> <img src="https://dev.iqhost.pl/assets/images/logo-full-iqhost-white.png?v=1767455018" alt="IQHost.pl Logo" class="footer-logo" width="140" height="auto"> <p class="footer-tagline">Tworzymy hosting, który szanuje Twój czas i budżet. Stała cena odnowienia i rozliczenie roczne to nasza standardowa praktyka.</p> <div class="footer-badges"> <div class="badge-item"> <i class="fas fa-shield-alt"></i> <span>100% Bezpieczeństwa</span> </div> <div class="badge-item"> <i class="fas fa-headset"></i> <span>Szybki Support</span> </div> <div class="badge-item"> <i class="fas fa-calendar-check"></i> <span>30 dni gwarancji</span> </div> </div> </div> <!-- Kolumna 2: Migracja --> <div class="footer-column"> <h3>Migracja</h3> <ul class="footer-links"> <li><a href="https://dev.iqhost.pl/migracja">Proces migracji</a></li> <li><a href="https://dev.iqhost.pl/migracja#benefits">Korzyści</a></li> <li><a href="https://dev.iqhost.pl/migracja#steps">Jak przebiega migracja</a></li> <li><a href="https://dev.iqhost.pl/migracja#faq">FAQ</a></li> <li><a href="https://dev.iqhost.pl/migracja#explanation">Dlaczego warto</a></li> <li><a href="https://dev.iqhost.pl#plans">Cennik hostingu</a></li> </ul> </div> <!-- Kolumna 3: Usługi --> <div class="footer-column"> <h3>Usługi</h3> <ul class="footer-links"> <li><a href="https://dev.iqhost.pl">Hosting WWW</a></li> <li><a href="https://dev.iqhost.pl#plans">Cennik hostingu</a></li> <li><a href="https://dev.iqhost.pl/domeny">Domeny internetowe</a></li> <li><a href="https://dev.iqhost.pl/migracja">Darmowa migracja</a></li> <li><a href="https://panel.iqgroup.pl">Panel klienta</a></li> <li><a href="https://monitor.iqhs.eu/?route=publicpage&key=QAyt2V7Yi2SRTzqNbY" target="_blank">Monitoring serwerów</a></li> </ul> </div> <!-- Kolumna 4: Wsparcie --> <div class="footer-column"> <h3>Wsparcie</h3> <ul class="footer-links"> <li><a href="https://dev.iqhost.pl/baza-wiedzy">Baza wiedzy</a></li> <li><a href="https://dev.iqhost.pl/blog">Blog</a></li> <li><a href="https://dev.iqhost.pl/pomoc">Centrum pomocy</a></li> <li><a href="https://monitor.iqhs.eu/?route=publicpage&key=QAyt2V7Yi2SRTzqNbY" target="_blank">Status serwerów</a></li> <li><a href="https://dev.iqhost.pl/kontakt">Kontakt</a></li> <li><a href="https://panel.iqgroup.pl/submitticket.php?step=2&deptid=1" target="_blank">Zgłoś problem</a></li> </ul> </div> <!-- Kolumna 5: Firma --> <div class="footer-column"> <h3>Firma</h3> <ul class="footer-links"> <li><a href="https://dev.iqhost.pl/o-nas">O nas</a></li> <li><a href="https://dev.iqhost.pl/kontakt">Kontakt</a></li> <li><a href="https://dev.iqhost.pl/regulamin">Regulamin</a></li> <li><a href="https://dev.iqhost.pl/polityka-prywatnosci">Polityka prywatności</a></li> <li><a href="https://dev.iqhost.pl/polityka-cookies">Polityka cookies</a></li> <li><a href="https://dev.iqhost.pl/dokumenty-prawne">Dokumenty prawne</a></li> </ul> </div> </div> <!-- Newsletter Section --> <div class="footer-newsletter"> <div class="newsletter-content"> <h3>Zostań w kontakcie</h3> <p>Otrzymuj porady dotyczące migracji i ekskluzywne oferty</p> </div> <form class="newsletter-form" id="footer-newsletter-form" action="/newsletter/subscribe.php" method="post"> <input type="email" name="email" placeholder="Twój adres e-mail" aria-label="Adres e-mail do newslettera" required> <button type="submit" class="newsletter-button"> <i class="fas fa-paper-plane"></i> Subskrybuj </button> <input type="hidden" name="consent" value="1"> <input type="hidden" name="g-recaptcha-response" id="newsletter-recaptcha-response"> </form> <small class="newsletter-note">Nie spamujemy. Możesz zrezygnować w każdej chwili.</small> <div id="newsletter-result" class="newsletter-result" style="display: none;"></div> </div> <!-- Dolna część stopki --> <div class="footer-bottom"> <div class="footer-bottom-left"> <p>© 2026 IQhost.pl - Marka Iqgroup.pl <span class="separator">|</span> NIP: 9910389442 <span class="separator">|</span> REGON: 161561682</p> <p class="footer-version">v9554fd4d (2026-01-07 19:59)</p> </div> <div class="footer-bottom-center"> <a href="https://dev.iqhost.pl/regulamin">Regulamin</a> <a href="https://dev.iqhost.pl/polityka-prywatnosci">Polityka prywatności</a> <a href="https://dev.iqhost.pl/polityka-cookies">Polityka cookies</a> <a href="https://dev.iqhost.pl/dokumenty-prawne">RODO</a> <a href="https://dev.iqhost.pl/dokumenty-prawne">Warunki SLA</a> </div> <div class="footer-bottom-right"> <div class="footer-certifications"> <span class="cert-badge"><i class="fas fa-shield-alt"></i> SSL secured</span> <span class="cert-badge"><i class="fas fa-lock"></i> Bezpieczne płatności</span> </div> </div> </div> </div> <!-- Scroll to top button --> <button id="scroll-to-top" class="scroll-to-top" aria-label="Przewiń do góry"> <i class="fas fa-arrow-up"></i> </button> </footer> <script> document.addEventListener('DOMContentLoaded', function() { // Newsletter form const form = document.getElementById('footer-newsletter-form'); const resultBox = document.getElementById('newsletter-result'); const submitBtn = form.querySelector('.newsletter-button'); function showResult(message, success) { resultBox.textContent = message; resultBox.style.display = 'block'; resultBox.className = 'newsletter-result ' + (success ? 'success' : 'error'); setTimeout(() => { resultBox.style.display = 'none'; }, 5000); } form.addEventListener('submit', function(e) { e.preventDefault(); submitBtn.disabled = true; submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Wysyłanie...'; grecaptcha.ready(function() { grecaptcha.execute('6LeaPwsqAAAAALYV9xE_2tC5d1DUUXBC6SxTPOwV', {action: 'newsletter_subscribe'}) .then(function(token) { document.getElementById('newsletter-recaptcha-response').value = token; const formData = new FormData(form); fetch('/newsletter/subscribe.php', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { submitBtn.disabled = false; submitBtn.innerHTML = '<i class="fas fa-paper-plane"></i> Subskrybuj'; showResult(data.message, data.success); if (data.success) form.reset(); }) .catch(error => { submitBtn.disabled = false; submitBtn.innerHTML = '<i class="fas fa-paper-plane"></i> Subskrybuj'; showResult('Wystąpił błąd. Spróbuj ponownie.', false); }); }); }); }); }); </script> <!-- Cookie Consent Banner --> <div class="cookie-consent" id="cookieConsent"> <div class="container"> <div class="cookie-content"> <p>Używamy plików cookie, aby zapewnić najlepsze doświadczenia na naszej stronie. <a href="https://dev.iqhost.pl/cookies">Dowiedz się więcej</a> o naszej polityce cookies.</p> <div class="cookie-buttons"> <button class="cookie-button secondary" id="cookiePreferences">Preferencje</button> <button class="cookie-button primary" id="acceptCookies">Akceptuję</button> </div> </div> </div> </div> <!-- Modal z informacjami o formularzu migracji - styl zgodny z modali strony /pomoc --> <div class="modal" id="migrationModal" style="display: none;" aria-hidden="true"> <div class="modal-overlay" tabindex="-1"> <div class="modal-container" role="dialog" aria-modal="true" aria-labelledby="migration-modal-title"> <header class="modal-header"> <h2 class="modal-title" id="migration-modal-title"> Formularz migracji - informacja </h2> <button class="modal-close-button" id="closeMigrationModal" aria-label="Zamknij okno modalne"> <i class="fas fa-times"></i> </button> </header> <main class="modal-content"> <div class="migration-info-wrapper"> <div class="info-header"> <i class="fas fa-info-circle"></i> <h3>Aby wypełnić formularz migracji:</h3> </div> <ul class="requirements-list"> <li><i class="fas fa-check-circle"></i> Musisz posiadać zarejestrowane konto w IQhost</li> <li><i class="fas fa-check-circle"></i> Musisz mieć zakupiony pakiet hostingowy</li> </ul> <p class="info-note"> Formularz migracji jest dostępny w Panelu Klienta po zalogowaniu. Możemy bezpłatnie przenieść Twoją stronę z dowolnego hostingu! </p> <div class="options-grid"> <div class="option-box"> <div class="option-header"> <div class="option-icon"> <i class="fas fa-shopping-cart"></i> </div> <h4>Nie masz jeszcze pakietu?</h4> </div> <p>Wybierz jeden z naszych pakietów i rozpocznij proces migracji.</p> <a href="https://dev.iqhost.pl" class="cta-button primary">Wybierz pakiet</a> </div> <div class="option-box"> <div class="option-header"> <div class="option-icon"> <i class="fas fa-user-circle"></i> </div> <h4>Masz już konto z pakietem?</h4> </div> <p>Zaloguj się do Panelu Klienta i wypełnij formularz migracji.</p> <a href="https://panel.iqgroup.pl/modules/addons/iq_migration_form/clientarea.php" class="cta-button secondary">Przejdź do formularza migracji</a> </div> </div> <div class="guarantees-section"> <div class="guarantee-item"> <i class="fas fa-clock"></i> <span>Migracja w ciągu 2-3 dni</span> </div> <div class="guarantee-item"> <i class="fas fa-money-bill-wave"></i> <span>Całkowicie za darmo</span> </div> <div class="guarantee-item"> <i class="fas fa-shield-alt"></i> <span>Bezpieczny transfer danych</span> </div> </div> </div> </main> <footer class="modal-footer"> <button class="cta-button secondary small-button close-modal-trigger" id="closeModalButton" aria-label="Zamknij to okno">Zamknij</button> </footer> </div> </div> </div> <style> /* Style dopasowane do modali z /pomoc */ .migration-info-wrapper { color: var(--text-primary, #333); } .migration-info-wrapper .info-header { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; } .migration-info-wrapper .info-header i { font-size: 1.5rem; color: var(--primary-color, #0056b3); } .migration-info-wrapper .info-header h3 { font-size: 1.3rem; font-weight: 600; margin: 0; color: var(--text-primary, #333); } .migration-info-wrapper .requirements-list { margin: 0 0 20px 0; padding: 0; list-style-type: none; } .migration-info-wrapper .requirements-list li { display: flex; align-items: baseline; gap: 10px; padding: 10px 12px; margin-bottom: 10px; background-color: rgba(0, 86, 179, 0.05); border-radius: 8px; } .migration-info-wrapper .requirements-list li i { color: var(--success-color, #28a745); } .migration-info-wrapper .info-note { margin-bottom: 24px; padding: 12px 16px; background-color: rgba(0, 86, 179, 0.05); border-left: 4px solid var(--primary-color, #0056b3); border-radius: 0 4px 4px 0; font-size: 0.95rem; line-height: 1.5; } .migration-info-wrapper .options-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 24px; } .migration-info-wrapper .option-box { padding: 20px; border-radius: 8px; background-color: var(--background-light-primary, #fff); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); transition: transform 0.3s ease, box-shadow 0.3s ease; } .migration-info-wrapper .option-box:hover { transform: translateY(-5px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); } .migration-info-wrapper .option-header { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; } .migration-info-wrapper .option-icon { width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background-color: rgba(0, 86, 179, 0.1); color: var(--primary-color, #0056b3); font-size: 1.2rem; } .migration-info-wrapper .option-header h4 { margin: 0; font-size: 1.1rem; font-weight: 600; color: var(--primary-color, #0056b3); } .migration-info-wrapper .option-box p { font-size: 0.95rem; margin-bottom: 16px; color: var(--text-secondary, #555); line-height: 1.5; } .migration-info-wrapper .guarantees-section { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; background-color: var(--background-light-secondary, #f8f9fa); padding: 16px; border-radius: 8px; } .migration-info-wrapper .guarantee-item { display: flex; align-items: center; gap: 8px; padding: 8px 16px; background-color: var(--background-light-primary, #fff); border-radius: 20px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); font-size: 0.9rem; color: var(--text-secondary, #555); animation: fadeIn 0.5s ease-out forwards; animation-delay: calc(var(--index) * 0.1s); opacity: 0; } .migration-info-wrapper .guarantee-item:nth-child(1) {--index: 0;} .migration-info-wrapper .guarantee-item:nth-child(2) {--index: 1;} .migration-info-wrapper .guarantee-item:nth-child(3) {--index: 2;} .migration-info-wrapper .guarantee-item i { color: var(--primary-color, #0056b3); } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } /* Responsywność */ @media (max-width: 768px) { .migration-info-wrapper .options-grid { grid-template-columns: 1fr; } .migration-info-wrapper .guarantees-section { flex-direction: column; align-items: center; } } /* Dark mode */ body.dark-mode .migration-info-wrapper { color: var(--dm-text-primary, #e0e0e0); } body.dark-mode .migration-info-wrapper .info-header h3 { color: var(--dm-text-primary, #e0e0e0); } body.dark-mode .migration-info-wrapper .requirements-list li { background-color: rgba(0, 119, 230, 0.1); } body.dark-mode .migration-info-wrapper .info-note { background-color: rgba(0, 119, 230, 0.1); border-left-color: var(--dm-primary-color, #0077e6); } body.dark-mode .migration-info-wrapper .option-box { background-color: var(--dm-background-light-primary, #2c3034); } body.dark-mode .migration-info-wrapper .option-header h4 { color: var(--dm-primary-color, #0077e6); } body.dark-mode .migration-info-wrapper .option-icon { background-color: rgba(0, 119, 230, 0.2); color: var(--dm-primary-color, #0077e6); } body.dark-mode .migration-info-wrapper .option-box p { color: var(--dm-text-secondary, #b0b0b0); } body.dark-mode .migration-info-wrapper .guarantees-section { background-color: var(--dm-background-light-secondary, #343a40); } body.dark-mode .migration-info-wrapper .guarantee-item { background-color: var(--dm-background-light-primary, #2c3034); color: var(--dm-text-secondary, #b0b0b0); } body.dark-mode .migration-info-wrapper .guarantee-item i { color: var(--dm-primary-color, #0077e6); } </style> <!-- Quiz Modal Trigger (można umieścić gdziekolwiek) --> <!-- Użycie: <button class="quiz-trigger">Dobierz pakiet</button> --> <!-- Quiz Modal --> <div class="quiz-modal" id="quiz-modal" role="dialog" aria-modal="true" aria-labelledby="quiz-title"> <div class="quiz-overlay"></div> <div class="quiz-container"> <button class="quiz-close" aria-label="Zamknij quiz">×</button> <!-- Progress bar --> <div class="quiz-progress"> <div class="quiz-progress-bar" id="quiz-progress-bar"></div> <div class="quiz-progress-steps"> <span class="step active" data-step="1">1</span> <span class="step" data-step="2">2</span> <span class="step" data-step="3">3</span> </div> </div> <!-- Quiz Content --> <div class="quiz-content"> <!-- Step 1: Project Type --> <div class="quiz-step active" data-step="1"> <h2 id="quiz-title">Co chcesz hostować?</h2> <p class="quiz-subtitle">Wybierz opcję najlepiej opisującą Twój projekt</p> <div class="quiz-options"> <button class="quiz-option" data-value="blog" data-next="2"> <div class="option-icon"><i class="fas fa-pen-fancy"></i></div> <div class="option-content"> <span class="option-title">Blog lub portfolio</span> <span class="option-desc">Osobista strona, CV online, fotografia</span> </div> </button> <button class="quiz-option" data-value="firma" data-next="2"> <div class="option-icon"><i class="fas fa-building"></i></div> <div class="option-content"> <span class="option-title">Strona firmowa</span> <span class="option-desc">Wizytówka firmy, landing page, oferta</span> </div> </button> <button class="quiz-option" data-value="sklep" data-next="2"> <div class="option-icon"><i class="fas fa-shopping-cart"></i></div> <div class="option-content"> <span class="option-title">Sklep internetowy</span> <span class="option-desc">WooCommerce, PrestaShop, własny e-commerce</span> </div> </button> <button class="quiz-option" data-value="agencja" data-next="2"> <div class="option-icon"><i class="fas fa-layer-group"></i></div> <div class="option-content"> <span class="option-title">Wiele stron</span> <span class="option-desc">Agencja, freelancer, projekty klientów</span> </div> </button> </div> </div> <!-- Step 2: Traffic --> <div class="quiz-step" data-step="2"> <h2>Ilu odwiedzających spodziewasz się?</h2> <p class="quiz-subtitle">Miesięczna liczba unikalnych użytkowników</p> <div class="quiz-options"> <button class="quiz-option" data-value="low" data-next="3"> <div class="option-icon"><i class="fas fa-user"></i></div> <div class="option-content"> <span class="option-title">Do 1 000 osób</span> <span class="option-desc">Początkujący projekt, lokalna firma</span> </div> </button> <button class="quiz-option" data-value="medium" data-next="3"> <div class="option-icon"><i class="fas fa-users"></i></div> <div class="option-content"> <span class="option-title">1 000 - 10 000 osób</span> <span class="option-desc">Rozwijający się biznes, aktywny blog</span> </div> </button> <button class="quiz-option" data-value="high" data-next="3"> <div class="option-icon"><i class="fas fa-user-friends"></i></div> <div class="option-content"> <span class="option-title">10 000 - 50 000 osób</span> <span class="option-desc">Popularny serwis, średni sklep</span> </div> </button> <button class="quiz-option" data-value="very-high" data-next="3"> <div class="option-icon"><i class="fas fa-globe"></i></div> <div class="option-content"> <span class="option-title">Ponad 50 000 osób</span> <span class="option-desc">Duży portal, popularny e-commerce</span> </div> </button> </div> <button class="quiz-back" data-back="1"> <i class="fas fa-arrow-left"></i> Wróć </button> </div> <!-- Step 3: Storage --> <div class="quiz-step" data-step="3"> <h2>Ile treści będziesz przechowywać?</h2> <p class="quiz-subtitle">Zdjęcia, pliki, bazy danych, multimedia</p> <div class="quiz-options"> <button class="quiz-option" data-value="small" data-next="result"> <div class="option-icon"><i class="fas fa-file-alt"></i></div> <div class="option-content"> <span class="option-title">Niewiele</span> <span class="option-desc">Głównie teksty i kilka zdjęć</span> </div> </button> <button class="quiz-option" data-value="medium" data-next="result"> <div class="option-icon"><i class="fas fa-images"></i></div> <div class="option-content"> <span class="option-title">Średnio</span> <span class="option-desc">Galerie zdjęć, dokumenty PDF</span> </div> </button> <button class="quiz-option" data-value="large" data-next="result"> <div class="option-icon"><i class="fas fa-photo-video"></i></div> <div class="option-content"> <span class="option-title">Dużo</span> <span class="option-desc">Wideo, duże pliki, archiwa</span> </div> </button> <button class="quiz-option" data-value="very-large" data-next="result"> <div class="option-icon"><i class="fas fa-database"></i></div> <div class="option-content"> <span class="option-title">Bardzo dużo</span> <span class="option-desc">Multimedia, backupy, duże bazy</span> </div> </button> </div> <button class="quiz-back" data-back="2"> <i class="fas fa-arrow-left"></i> Wróć </button> </div> <!-- Result --> <div class="quiz-step quiz-result" data-step="result"> <div class="result-badge"> <i class="fas fa-check-circle"></i> Mamy dla Ciebie idealny pakiet! </div> <div class="result-card"> <div class="result-header"> <h2 class="result-package-name" id="result-package-name">HS25</h2> <div class="result-price"> <span class="price-amount" id="result-price">79,95</span> <span class="price-period">zł/rok</span> </div> <div class="result-guarantee"> <i class="fas fa-lock"></i> Stała cena - bez podwyżek! </div> </div> <div class="result-specs"> <div class="spec-item"> <i class="fas fa-hdd"></i> <span id="result-capacity">25 GB NVMe</span> </div> <div class="spec-item"> <i class="fas fa-globe"></i> <span id="result-domains">20 domen</span> </div> </div> <div class="result-features" id="result-features"> <!-- Filled by JS --> </div> <div class="result-reason"> <h4><i class="fas fa-lightbulb"></i> Dlaczego ten pakiet?</h4> <p id="result-reason-text"> Na podstawie Twoich odpowiedzi... </p> </div> <a href="#" class="result-cta" id="result-cta" target="_blank" rel="noopener"> <i class="fas fa-shopping-cart"></i> Zamów <span id="result-cta-name">HS25</span> teraz </a> <div class="result-alternative"> <a href="#plans" class="quiz-close-link">Zobacz wszystkie pakiety</a> <span class="separator">|</span> <button class="quiz-restart">Wypełnij ponownie</button> </div> </div> </div> </div> </div> </div> <style> /* Quiz Modal - Core Styles */ .quiz-modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 10000; display: flex; align-items: center; justify-content: center; opacity: 0; visibility: hidden; transition: opacity 0.3s ease, visibility 0.3s ease; } .quiz-modal.active { opacity: 1; visibility: visible; } .quiz-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.7); backdrop-filter: blur(4px); } .quiz-container { position: relative; width: 95%; max-width: 600px; max-height: 90vh; background: var(--background-color, #ffffff); border-radius: 20px; box-shadow: 0 25px 80px rgba(0, 0, 0, 0.3); overflow: hidden; transform: scale(0.9) translateY(20px); transition: transform 0.3s ease; } .quiz-modal.active .quiz-container { transform: scale(1) translateY(0); } .quiz-close { position: absolute; top: 16px; right: 16px; width: 40px; height: 40px; border: none; background: rgba(0, 0, 0, 0.05); border-radius: 50%; font-size: 24px; cursor: pointer; z-index: 10; color: var(--text-muted, #666); transition: all 0.2s ease; } .quiz-close:hover { background: rgba(0, 0, 0, 0.1); transform: rotate(90deg); } /* Progress Bar */ .quiz-progress { padding: 24px 32px 16px; } .quiz-progress-bar { display: none; } .quiz-progress-steps { display: flex; justify-content: center; align-items: center; gap: 48px; } .quiz-progress-steps .step { width: 36px; height: 36px; border-radius: 50%; background: transparent; border: 2px solid #ccc; color: #999; font-size: 14px; font-weight: 700; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; } .quiz-progress-steps .step.active { background: var(--primary-color, #0056b3); border-color: var(--primary-color, #0056b3); color: white; } .quiz-progress-steps .step.completed { background: var(--primary-color, #0056b3); border-color: var(--primary-color, #0056b3); color: white; } /* Quiz Content */ .quiz-content { padding: 32px; min-height: 400px; position: relative; overflow: hidden; } .quiz-step { display: none; animation: fadeSlideIn 0.4s ease; } .quiz-step.active { display: block; } @keyframes fadeSlideIn { from { opacity: 0; transform: translateX(30px); } to { opacity: 1; transform: translateX(0); } } .quiz-step h2 { font-size: 1.5rem; font-weight: 700; color: var(--text-color, #1a1a1a); margin-bottom: 8px; text-align: center; } .quiz-subtitle { color: var(--text-muted, #666); text-align: center; margin-bottom: 28px; font-size: 0.9375rem; } /* Quiz Options */ .quiz-options { display: flex; flex-direction: column; gap: 12px; } .quiz-option { display: flex; align-items: center; gap: 16px; padding: 16px 20px; background: var(--background-alt, #f8f9fa); border: 2px solid transparent; border-radius: 12px; cursor: pointer; transition: all 0.2s ease; text-align: left; width: 100%; } .quiz-option:hover { border-color: var(--primary-color, #0056b3); background: rgba(0, 86, 179, 0.05); transform: translateX(4px); } .quiz-option:active { transform: scale(0.98); } .quiz-option.selected { border-color: var(--primary-color, #0056b3); background: rgba(0, 86, 179, 0.1); } .option-icon { width: 48px; height: 48px; background: linear-gradient(135deg, var(--primary-color, #0056b3), #0077cc); border-radius: 12px; display: flex; align-items: center; justify-content: center; color: white; font-size: 1.25rem; flex-shrink: 0; } .option-content { flex: 1; } .option-title { display: block; font-weight: 600; color: var(--text-color, #1a1a1a); font-size: 1rem; margin-bottom: 2px; } .option-desc { display: block; font-size: 0.8125rem; color: var(--text-muted, #666); } /* Back Button */ .quiz-back { display: inline-flex; align-items: center; gap: 8px; margin-top: 20px; padding: 8px 16px; background: none; border: none; color: var(--text-muted, #666); font-size: 0.875rem; cursor: pointer; transition: color 0.2s ease; } .quiz-back:hover { color: var(--primary-color, #0056b3); } /* Result Step */ .quiz-result { text-align: center; } .result-badge { display: inline-flex; align-items: center; gap: 8px; padding: 8px 20px; background: linear-gradient(135deg, #22c55e, #16a34a); color: white; border-radius: 30px; font-weight: 600; font-size: 0.9375rem; margin-bottom: 24px; animation: bounceIn 0.5s ease; } @keyframes bounceIn { 0% { transform: scale(0); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } } .result-card { background: var(--background-alt, #f8f9fa); border-radius: 16px; padding: 28px; border: 2px solid var(--primary-color, #0056b3); } .result-header { margin-bottom: 20px; } .result-package-name { font-size: 2rem; font-weight: 800; color: var(--primary-color, #0056b3); margin-bottom: 8px; } .result-price { display: flex; align-items: baseline; justify-content: center; gap: 4px; } .result-price .price-amount { font-size: 2.5rem; font-weight: 800; color: var(--text-color, #1a1a1a); } .result-price .price-period { font-size: 1rem; color: var(--text-muted, #666); } .result-guarantee { display: inline-flex; align-items: center; gap: 6px; margin-top: 8px; padding: 4px 12px; background: rgba(34, 197, 94, 0.1); color: #16a34a; border-radius: 20px; font-size: 0.8125rem; font-weight: 600; } .result-specs { display: flex; justify-content: center; gap: 32px; margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid var(--border-color, #e0e0e0); } .spec-item { display: flex; align-items: center; gap: 8px; font-weight: 600; color: var(--text-color, #1a1a1a); } .spec-item i { color: var(--primary-color, #0056b3); } .result-features { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-bottom: 20px; } .result-features .feature { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; background: white; border-radius: 20px; font-size: 0.8125rem; color: var(--text-color, #1a1a1a); } .result-features .feature i { color: #22c55e; font-size: 0.75rem; } .result-reason { background: white; border-radius: 12px; padding: 16px; margin-bottom: 20px; text-align: left; } .result-reason h4 { display: flex; align-items: center; gap: 8px; font-size: 0.9375rem; font-weight: 600; color: var(--text-color, #1a1a1a); margin-bottom: 8px; } .result-reason h4 i { color: #f59e0b; } .result-reason p { font-size: 0.875rem; color: var(--text-muted, #666); line-height: 1.6; margin: 0; } .result-cta { display: inline-flex; align-items: center; justify-content: center; gap: 10px; width: 100%; padding: 16px 32px; background: linear-gradient(135deg, #22c55e, #16a34a); color: white; border: none; border-radius: 12px; font-size: 1.125rem; font-weight: 700; text-decoration: none; cursor: pointer; transition: all 0.2s ease; box-shadow: 0 4px 15px rgba(34, 197, 94, 0.3); } .result-cta:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(34, 197, 94, 0.4); color: white; } .result-alternative { margin-top: 16px; font-size: 0.875rem; color: var(--text-muted, #666); } .result-alternative a, .result-alternative button { color: var(--primary-color, #0056b3); background: none; border: none; cursor: pointer; text-decoration: underline; } .result-alternative .separator { margin: 0 12px; color: var(--border-color, #e0e0e0); } /* Dark Mode */ body.dark-mode .quiz-container { background: var(--dark-card, #1e2028); } body.dark-mode .quiz-close { background: rgba(255, 255, 255, 0.1); color: #aaa; } body.dark-mode .quiz-progress-steps .step { background: transparent; border-color: #555; color: #777; } body.dark-mode .quiz-progress-steps .step.active, body.dark-mode .quiz-progress-steps .step.completed { background: var(--primary-light, #5ba3ff); border-color: var(--primary-light, #5ba3ff); color: #0d1f35; } body.dark-mode .quiz-step h2 { color: var(--dark-text, #f0f0f0); } body.dark-mode .quiz-option { background: var(--dark-bg, #151820); border-color: var(--dark-border, #333); } body.dark-mode .quiz-option:hover { background: rgba(0, 86, 179, 0.15); } body.dark-mode .option-title { color: var(--dark-text, #f0f0f0); } body.dark-mode .result-card { background: var(--dark-bg, #151820); } body.dark-mode .result-price .price-amount { color: var(--dark-text, #f0f0f0); } body.dark-mode .spec-item { color: var(--dark-text, #f0f0f0); } body.dark-mode .result-features .feature { background: var(--dark-card, #1e2028); color: var(--dark-text, #f0f0f0); } body.dark-mode .result-reason { background: var(--dark-card, #1e2028); } body.dark-mode .result-reason h4 { color: var(--dark-text, #f0f0f0); } /* Mobile Responsive */ @media (max-width: 640px) { .quiz-container { width: 100%; max-width: none; height: 100%; max-height: 100%; border-radius: 0; } .quiz-content { padding: 24px 20px; } .quiz-step h2 { font-size: 1.25rem; } .quiz-option { padding: 14px 16px; } .option-icon { width: 40px; height: 40px; font-size: 1rem; } .result-price .price-amount { font-size: 2rem; } .result-specs { flex-direction: column; gap: 12px; } .result-cta { font-size: 1rem; padding: 14px 24px; } } </style> <script> (function() { 'use strict'; // Package data var packages = {"hs1":{"name":"STARTER HS1","price":"30,68","capacity":"1 GB","domains":"1 domena","url":"https:\/\/panel.iqgroup.pl\/store\/hosting-www\/hs-1","features":["SSL w cenie","Bazy danych bez limitu","Email bez limitu","Codzienne backupy"],"ideal_for":"Idealny na start - blog, portfolio lub prosta strona wizyt\u00f3wka."},"hs5":{"name":"HS5","price":"39,95","capacity":"5 GB","domains":"5 domen","url":"https:\/\/panel.iqgroup.pl\/cart.php?a=add&pid=1","features":["SSL w cenie","Bazy danych bez limitu","Email bez limitu","Codzienne backupy"],"ideal_for":"\u015awietny dla strony firmowej lub rozbudowanego bloga z galeri\u0105."},"hs25":{"name":"HS25","price":"79,95","capacity":"25 GB","domains":"20 domen","url":"https:\/\/panel.iqgroup.pl\/cart.php?a=add&pid=2","features":["SSL w cenie","SSH\/SFTP","Redis cache","WP-CLI & Composer"],"ideal_for":"Optymalny dla sklepu internetowego lub strony z du\u017c\u0105 ilo\u015bci\u0105 tre\u015bci."},"hs50":{"name":"HS50","price":"129,95","capacity":"50 GB","domains":"Bez limitu","url":"https:\/\/panel.iqgroup.pl\/cart.php?a=add&pid=174","features":["Wszystko z HS25","Wi\u0119cej zasob\u00f3w CPU","Priorytetowy I\/O","D\u0142u\u017csze backupy"],"ideal_for":"Doskona\u0142y dla freelancer\u00f3w i ma\u0142ych agencji z kilkoma projektami."},"hs100":{"name":"HS100","price":"199,95","capacity":"100 GB","domains":"Bez limitu","url":"https:\/\/panel.iqgroup.pl\/cart.php?a=add&pid=3","features":["Wszystko z HS50","Maksymalne zasoby","Priority support","SLA 99.9%"],"ideal_for":"Dla agencji i firm z wieloma stronami o wysokim ruchu."},"hs200":{"name":"HS200","price":"349,95","capacity":"200 GB","domains":"Bez limitu","url":"https:\/\/panel.iqgroup.pl\/cart.php?a=add&pid=4","features":["Wszystko z HS100","Dedykowane zasoby","Account manager","SLA 99.95%"],"ideal_for":"Dla du\u017cych agencji i firm enterprise z wymagaj\u0105cymi projektami."}}; // Quiz state var answers = { projectType: null, traffic: null, storage: null }; // DOM elements var modal = document.getElementById('quiz-modal'); var progressBar = document.getElementById('quiz-progress-bar'); var steps = document.querySelectorAll('.quiz-step'); var progressSteps = document.querySelectorAll('.quiz-progress-steps .step'); // Recommendation logic function getRecommendation() { var scores = { hs1: 0, hs5: 0, hs25: 0, hs50: 0, hs100: 0, hs200: 0 }; // Project type scoring // HS1 tylko dla bloga bez poczty, HS5 dla wizytówki, HS25+ dla firmy z pocztą switch (answers.projectType) { case 'blog': // Blog/portfolio - HS1 możliwy, ale HS5 bezpieczniejszy scores.hs1 += 2; scores.hs5 += 3; break; case 'firma': // Firma = poczta firmowa = minimum HS25, lepiej HS50 scores.hs25 += 3; scores.hs50 += 4; scores.hs5 += 1; break; case 'sklep': // Sklep = duże wymagania scores.hs50 += 4; scores.hs25 += 2; scores.hs100 += 2; break; case 'agencja': // Agencja/wiele stron = duże pakiety scores.hs100 += 4; scores.hs50 += 3; scores.hs200 += 2; break; } // Traffic scoring switch (answers.traffic) { case 'low': // Niski ruch - HS5 domyślnie, HS1 tylko bonus scores.hs5 += 2; scores.hs1 += 1; break; case 'medium': // Średni ruch - HS25/HS50 scores.hs25 += 3; scores.hs50 += 2; break; case 'high': // Wysoki ruch - HS50+ scores.hs50 += 3; scores.hs100 += 2; break; case 'very-high': // Bardzo wysoki - HS100/HS200 scores.hs100 += 4; scores.hs200 += 3; break; } // Storage scoring switch (answers.storage) { case 'small': // Mało treści - HS5 bezpieczny wybór scores.hs5 += 2; scores.hs1 += 1; break; case 'medium': // Średnio - HS25 scores.hs25 += 3; scores.hs5 += 1; break; case 'large': // Dużo - HS50 scores.hs50 += 3; scores.hs25 += 1; break; case 'very-large': // Bardzo dużo - HS100+ scores.hs100 += 3; scores.hs200 += 2; break; } // Find highest score var maxScore = 0; var recommended = 'hs5'; for (var pkg in scores) { if (scores[pkg] > maxScore) { maxScore = scores[pkg]; recommended = pkg; } } return recommended; } // Generate reason text function getReasonText(pkg) { var reasons = []; // Project type reason var projectReasons = { 'blog': 'Dla bloga lub portfolio', 'firma': 'Dla strony firmowej', 'sklep': 'Sklep internetowy wymaga więcej zasobów', 'agencja': 'Wiele projektów wymaga przestrzeni i domen' }; reasons.push(projectReasons[answers.projectType] || ''); // Traffic reason var trafficReasons = { 'low': 'przy niskim ruchu wystarczą podstawowe zasoby.', 'medium': 'średni ruch wymaga stabilnej wydajności.', 'high': 'wysoki ruch wymaga mocniejszych zasobów.', 'very-high': 'bardzo wysoki ruch wymaga maksymalnej wydajności.' }; reasons.push(trafficReasons[answers.traffic] || ''); // Storage reason if (answers.storage === 'large' || answers.storage === 'very-large') { reasons.push('Duża ilość treści wymaga odpowiedniej przestrzeni dyskowej.'); } // Package-specific benefit var pkgBenefits = { 'hs1': 'STARTER HS1 to ekonomiczny wybór na początek.', 'hs5': 'HS5 daje zapas miejsca i domen na rozwój.', 'hs25': 'HS25 oferuje SSH, Redis i zaawansowane funkcje.', 'hs50': 'HS50 to świetny balans ceny i możliwości.', 'hs100': 'HS100 zapewnia maksymalne zasoby dla wymagających projektów.', 'hs200': 'HS200 to rozwiązanie enterprise z dedykowanym wsparciem.' }; reasons.push(pkgBenefits[pkg] || ''); return reasons.filter(function(r) { return r; }).join(' '); } // Show result function showResult() { var recommended = getRecommendation(); var pkg = packages[recommended]; document.getElementById('result-package-name').textContent = pkg.name; document.getElementById('result-price').textContent = pkg.price; document.getElementById('result-capacity').textContent = pkg.capacity + ' NVMe'; document.getElementById('result-domains').textContent = pkg.domains; document.getElementById('result-cta').href = pkg.url; document.getElementById('result-cta-name').textContent = pkg.name; document.getElementById('result-reason-text').textContent = getReasonText(recommended); // Features var featuresHtml = ''; pkg.features.forEach(function(f) { featuresHtml += '<span class="feature"><i class="fas fa-check"></i> ' + f + '</span>'; }); document.getElementById('result-features').innerHTML = featuresHtml; goToStep('result'); } // Navigation function goToStep(step) { steps.forEach(function(s) { s.classList.remove('active'); }); document.querySelector('.quiz-step[data-step="' + step + '"]').classList.add('active'); progressBar.setAttribute('data-progress', step); progressSteps.forEach(function(ps) { var psStep = parseInt(ps.getAttribute('data-step')); var currentStep = step === 'result' ? 4 : parseInt(step); ps.classList.remove('active', 'completed'); if (psStep === currentStep || (step === 'result' && psStep === 3)) { ps.classList.add('active'); } else if (psStep < currentStep) { ps.classList.add('completed'); } }); } // Open/Close modal function openQuiz() { modal.classList.add('active'); document.body.style.overflow = 'hidden'; } function closeQuiz() { modal.classList.remove('active'); document.body.style.overflow = ''; } function resetQuiz() { answers = { projectType: null, traffic: null, storage: null }; goToStep('1'); document.querySelectorAll('.quiz-option').forEach(function(o) { o.classList.remove('selected'); }); } // Event listeners document.querySelectorAll('.quiz-trigger').forEach(function(trigger) { trigger.addEventListener('click', function(e) { e.preventDefault(); resetQuiz(); openQuiz(); }); }); document.querySelectorAll('.quiz-close, .quiz-close-link').forEach(function(el) { el.addEventListener('click', function(e) { e.preventDefault(); closeQuiz(); }); }); document.querySelector('.quiz-overlay').addEventListener('click', closeQuiz); document.querySelectorAll('.quiz-restart').forEach(function(btn) { btn.addEventListener('click', resetQuiz); }); document.querySelectorAll('.quiz-option').forEach(function(option) { option.addEventListener('click', function() { var value = this.getAttribute('data-value'); var next = this.getAttribute('data-next'); var currentStep = this.closest('.quiz-step').getAttribute('data-step'); // Store answer if (currentStep === '1') answers.projectType = value; if (currentStep === '2') answers.traffic = value; if (currentStep === '3') answers.storage = value; // Visual feedback this.closest('.quiz-options').querySelectorAll('.quiz-option').forEach(function(o) { o.classList.remove('selected'); }); this.classList.add('selected'); // Navigate setTimeout(function() { if (next === 'result') { showResult(); } else { goToStep(next); } }, 200); }); }); document.querySelectorAll('.quiz-back').forEach(function(btn) { btn.addEventListener('click', function() { var back = this.getAttribute('data-back'); goToStep(back); }); }); // Keyboard navigation document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && modal.classList.contains('active')) { closeQuiz(); } }); // Result CTA click handler - explicit navigation var resultCta = document.getElementById('result-cta'); if (resultCta) { resultCta.addEventListener('click', function(e) { var url = this.getAttribute('href'); if (url && url !== '#') { // Close quiz and navigate closeQuiz(); window.open(url, '_blank', 'noopener'); } else { e.preventDefault(); console.warn('Quiz: URL pakietu nie został ustawiony'); } }); } // Expose global function window.openPackageQuiz = openQuiz; })(); </script> <!-- Skrypty --> <!-- jQuery - bez defer (dependency dla innych skryptów) --> <script src="https://dev.iqhost.pl/assets/lib/jquery/jquery-3.6.0.min.js?v=1767455019"></script> <!-- Popper i Bootstrap JS - bez defer (dependency) --> <script src="https://dev.iqhost.pl/assets/lib/popper/popper.min.js?v=1767455019"></script> <script src="https://dev.iqhost.pl/assets/lib/bootstrap/bootstrap.min.js?v=1767455019"></script> <!-- AOS - Animate On Scroll Library - BEZ defer (krytyczne dla hero) --> <script src="https://dev.iqhost.pl/assets/lib/aos/aos.js?v=1767455019"></script> <!-- Particles.js dla tła --> <script defer src="https://dev.iqhost.pl/assets/lib/particles-js/particles.min.js?v=1767455019"></script> <!-- Własne skrypty JS --> <script defer src="https://dev.iqhost.pl/assets/js/particles-init.js?v=1767455019"></script> <script defer src="https://dev.iqhost.pl/assets/js/site-stats.js?v=1767601901"></script> <script src="https://dev.iqhost.pl/assets/js/tabs.js?v=1767455019"></script> <script src="https://dev.iqhost.pl/assets/js/components/faq.js?v=1767455019"></script> <script defer src="https://dev.iqhost.pl/assets/js/components/faq-global-fix.js?v=1767455019"></script> <script src="https://dev.iqhost.pl/assets/js/fix-testimonials.js?v=1767455019"></script> <script src="https://dev.iqhost.pl/assets/js/carousel.js?v=1767455019"></script> <script src="https://dev.iqhost.pl/assets/js/modals.js?v=1767455019"></script> <script defer src="https://dev.iqhost.pl/assets/js/migration-modal.js?v=1767455019"></script> <script defer src="https://dev.iqhost.pl/assets/js/notifications.js?v=1767455019"></script> <script src="https://dev.iqhost.pl/assets/js/theme.js?v=1767455019"></script> <script defer src="https://dev.iqhost.pl/assets/js/scroll-top.js?v=1767455019"></script> <script src="https://dev.iqhost.pl/assets/js/pricing.js?v=1767455019"></script> <script defer src="https://dev.iqhost.pl/assets/js/misc.js?v=1767455019"></script> <!-- Menu mobilne musi być załadowane na końcu --> <script src="https://dev.iqhost.pl/assets/js/mobile-menu2.js?v=1767455019"></script> <!-- Menedżer koszyka - globalny --> <script src="https://dev.iqhost.pl/assets/js/cart-manager.js?v=1767459270"></script> <script src="https://dev.iqhost.pl/assets/js/blog-sidebar.js?v=1767455019"></script> <!-- Inicjalizacja wszystkich skryptów - BEZ defer (musi być od razu) --> <script src="https://dev.iqhost.pl/assets/js/init-all.js?v=1767455019"></script> <!-- Google reCAPTCHA v3 --> <script defer src="https://www.google.com/recaptcha/api.js?render=6LeaPwsqAAAAALYV9xE_2tC5d1DUUXBC6SxTPOwV"></script> <script defer src="https://dev.iqhost.pl/assets/js/recaptcha.js?v=1767455019"></script> <!-- Google Analytics, itp. --> <!-- Tutaj można dodać skrypty do śledzenia --> </body> </html>