Български | Català | Deutsche | Hrvatski | Čeština | Dansk | Nederlandse | English | Eesti keel | Français | Ελληνικά | Magyar | Italiano | Latviski | Norsk | Polski | Português | Română | Русский | Српски | Slovenský | Slovenščina | Español | Svenska | Türkçe | 汉语 | 日本語 |
P

www html

Aktīvā frāze
Informācijas atjaunināšanas datums: 2026/03/29

📊 Kopsavilkums: www html

📋
Meklēšanas biežums: 72 481
Valoda: en
Šai frāzei nav pieejami morfoloģiski dati vai definīcija.

Pozīcijas iekšā Google

Meklēšanas frāzes - Google

🔍
Pozīcija Domēns Lapa Darbības
1 www.w3schools.com /html/
Nosaukums
HTML Tutorial
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
HTML Tutorial
HTML is the standard markup language for Web pages. With HTML you can create your own Website. HTML is easy to learn - You will enjoy it!
2 html.com /
Nosaukums
HTML For Beginners The Easy Way
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
HTML For Beginners The Easy Way
Our step-by-step guide teaches you the basics of HTML and how to build your first website. That means how to layout an HTML page, how to add text and images , ...
3 qna.habr.com /q/695506
Nosaukums
Как сменить document_root apache с /var/www/html на /var ...
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
Как сменить document_root apache с /var/www/html на /var ...
23 дек. 2019 г. — Как сменить document_root apache с /var/ www/html на /var/www/test/ html /public? Есть vps, на нем apache и php. из различных статей пробовал ...
4 developer.mozilla.org /ru/docs/web/html;19...
Nosaukums
HTML - MDN Web Docs - Mozilla
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
HTML - MDN Web Docs - Mozilla
15 апр. 2025 г. — HTML (HyperText Markup Language — «язык гипертекстовой разметки») — самый базовый строительный блок Веба. Он определяет содержание и ...
5 stackoverflow.com /questions/16197663/...
Nosaukums
What is /var/www/html? [closed] - php
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
What is /var/www/html? [closed] - php
/ var/www/html is just the default root folder of the web server. You can change that to be whatever folder you want by editing your apache.conf file.
6 htmlacademy.ru /
Nosaukums
HTML Academy
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
HTML Academy
Готовим разработчиков напрямую для работодателей . Получите базовые навыки на тренажёрах, а затем пройдите серьёзные профессиональные программы для ...
7 ru.wikipedia.org /wiki/html;4107130
Nosaukums
HTML
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
HTML
HTML (от англ. HyperText Markup Language — «язык гипертекстовой разметки») — стандартизированный язык гипертекстовой разметки документов для просмотра веб- ...
8 www.linux.org.ru /forum/general/88885...
Nosaukums
Помогите разобраться с apache и /var/www/index.html
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
Помогите разобраться с apache и /var/www/index.html
24 февр. 2013 г. — вообщем главная страница в любом случае должна быть /var/www/index. html ? а остальные страницы где угодно, только чтоб в папке /var/www?
9 htmlbook.ru /
Nosaukums
Home | htmlbook.ru
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
Home | htmlbook.ru
Аудио и видео. Семантический HTML . Каждый урок сопровождается задачами, которые надо решать прямиком в редакторе. Курс бесплатный, для изучения требуется только ...
10 html.spec.whatwg.org /
Nosaukums
HTML Standard;5302519
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
HTML Standard;5302519
HTML is the World Wide Web's core markup language. Originally, HTML was primarily designed as a language for semantically describing scientific documents. Its ...;60549698

Pozīcijas iekšā Yandex

Meklēšanas frāzes - Yandex

🔍
Pozīcija Domēns Lapa Darbības
1 inf.e-alekseev.ru /text/www_html.html
Nosaukums
13.5. WWW и HTML
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
13.5. WWW и HTML
HTML – это формат гипертекстовых документов, использующихся в WWW для предоставления информации.
2 schoolsw3.com /html/html_intro.php
Nosaukums
Введение в HTML за 5 минут — Как работает HTML ?
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
Введение в HTML за 5 минут — Как работает HTML ?
Простое объяснение HTML для новичков. Основные понятия, структура документа и примеры кода.
3 oslogic.ru /knowledge/75/osnovn...
Nosaukums
Основные понятия World Wide Web, или WWW
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
Основные понятия World Wide Web, или WWW
WWW — (World Wide Web) — это часть Internet, представляющая собой гигантский набор документов, хранящихся на компьютерах по всему миру.
4 frolov-lib.ru /books/bsp/v23/ch4_1...
Nosaukums
4 создание страниц www
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
4 создание страниц www
Практическое введение в Internet, E-Mail, FTP, WWW и HTML , программирование для Windows Sockets.
5 dzen.ru /a/zgzma5bzlrj7ofll
Nosaukums
Основы html - база для всех тех, кто мечтает стать... | Дзен
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
6 htmlacademy.ru /blog/html/introduct...
Nosaukums
Знакомство с HTML — журнал «Доктайп» | HTML Academy
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
Знакомство с HTML — журнал «Доктайп» | HTML Academy
Знакомство с HTML для тех, кто никогда не писал сайты.
7 help.sweb.ru /html-osnovy-yazyka-...
Nosaukums
HTML
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
HTML
Основы HTML - для чего используется этот язык разметки и зачем он нужен; как выглядит код и синтаксис HyperText Markup Language.
8 academy.kgtk.ru /it3/web-programming...
Nosaukums
Лекция 1. Основы World Wide Web ( WWW )
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
Лекция 1. Основы World Wide Web ( WWW )
В лекции рассмотрены общие принципы организации и функционирования сервиса WWW . Описаны структура и компоненты веб, включая протокол HTTP...
9 sky.pro /wiki/html/osnovy-ht...
Nosaukums
Основы HTML
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
Основы HTML
Изучите основы HTML и создайте свою первую веб-страницу! В этой статье вы узнаете о ключевых тегах и структуре HTML -документа, научитесь...
10 developer.mozilla.org /ru/docs/learn_web_d...
Nosaukums
Начало работы с HTML - Изучение веб-разработки | MDN
Pēdējo reizi atjaunināts
N/A
Lapas autoritāte
N/A
Satiksme: N/A
Atpakaļsaites: N/A
Sociālās akcijas: N/A
Ielādes laiks: N/A
Fragmenta priekšskatījums:
Начало работы с HTML - Изучение веб-разработки | MDN
В этой статье мы охватим азы HTML , необходимые для начала работы. Дадим определение «элементам», «атрибутам»...

Raksts

📝

Izpratne par www HTML pamatiem: visaptverošs ceļvedis

Laipni lūdzam dziļā ienirt tīmekļa izstrādes pasaulē, kur katra koda rindiņa var pārveidot vienkāršu tekstu dinamiskās, interaktīvās vietnēs. Šodien mēs koncentrējamies uz tīmekļa mugurkaulu — www HTML. Neatkarīgi no tā, vai esat iesācējs vai pilnveidojat savas prasmes, šī rokasgrāmata sniegs jums stabilu HTML pamatu un to, kā tas iekļaujas plašākā tīmekļa dizaina priekšstatā.

Kas ir HTML?

HTML, kas apzīmē hiperteksta iezīmēšanas valodu, ir galvenā valoda, ko izmanto tīmekļa lapu izveidei. Tā nodrošina pamata struktūru, ko pārlūkprogrammas interpretē, lai rādītu saturu internetā. Katra jūsu apmeklētā vietne sākas ar HTML kodu, padarot to par pamatprasmi ikvienam, kas interesējas par tīmekļa izstrādi.

www HTML loma

Jums varētu rasties jautājums, kāpēc mēs īpaši pieminam www HTML. Lai gan daļa “www” mūsdienu tīmekļa adresēs parasti nav nepieciešama, tā kādreiz bija ļoti svarīga. Pasaules tīmeklis (WWW) būtībā ir savstarpēji saistītu hiperteksta dokumentu sistēma, kam var piekļūt, izmantojot internetu. HTML ir valoda, ko izmanto šo dokumentu izveidei.

Mūsdienu kontekstā, pieminot www HTML, tiek uzsvērta HTML vēsturiskā nozīme un galvenā loma tīmekļa izveidē. Tas mums atgādina, ka HTML ir vairāk nekā tikai kods — tā ir tīmekļa valoda.

HTML pamata struktūra

Apskatīsim HTML dokumenta pamatstruktūru:

Lapas nosaukums

Mans pirmais virsraksts

Mana pirmā rindkopa.

  • : deklarē dokumenta veidu un HTML versiju.
  • : HTML lapas saknes elements.
  • : satur metainformāciju par HTML dokumentu, piemēram, tā nosaukumu un saites uz stilu lapām.
  • </strong>: iestata tīmekļa lapas nosaukumu, kas tiek rādīts pārlūkprogrammas cilnē.</li> <li><strong><body></strong>: satur HTML dokumenta saturu, kas ir redzams lietotājiem.</li> <li><strong><h1></strong>: definē augstākā līmeņa virsrakstu.</li> <li><strong><p></strong>: attēlo teksta rindkopu.</li> </ul> <h2>Teksta elementu izveide, izmantojot www HTML</h2> <p>HTML nodrošina dažādus tagus dažāda veida teksta elementu izveidei. Šeit ir daži piemēri:</p> <ul> <li><strong><h1>-<h6></strong>: definējiet virsrakstus no lielākā līdz mazākajam.</li> <li><strong><p></strong>: izveido teksta rindkopas.</li> <li><strong><a></strong>: ievieto hipersaites uz citām tīmekļa lapām vai resursiem.</li> <li><strong><em></strong> un <strong><strong></strong>: izceliet tekstu, <strong><em></strong> parasti tiek atveidots slīprakstā un <strong><strong></strong> treknrakstā.</li> <li><strong><br></strong>: ievieto rindiņas pārtraukumu.</li> </ul> <h3>Piemērs: vienkāršas saites izveide</h3> <iepriekš> <a href="https://www.serpulse.com">Apmeklējiet Serpulse</a> </pre> <p>Šis kods izveido noklikšķināmu saiti uz Serpulse vietni. Atribūts <strong>href</strong> norāda URL, uz kuru norāda saite.</p> <h2>Attēlu pievienošana, izmantojot www HTML</h2> <p>Attēlu iekļaušana savās tīmekļa lapās uzlabo to vizuālo pievilcību un lietotāja pieredzi. Lai pievienotu attēlu, izmantojot HTML, izmantojiet tagu <strong><img></strong>:</p> <iepriekš> <img src="path/to/image.jpg" alt="Attēla apraksts"> </pre> <ul> <li><strong>src</strong>: norāda ceļu uz attēla failu.</li> <li><strong>alt</strong>: nodrošina alternatīvu tekstu ekrāna lasītājiem un gadījumiem, kad attēlu nevar parādīt.</li> </ul> <h2>Sarakstu izveide, izmantojot www HTML</h2> <p>Saraksti ir būtiski, lai kārtotu informāciju jūsu vietnē. HTML atbalsta gan sakārtotus, gan nesakārtotus sarakstus:</p> <h3>Nekārtots saraksts</h3> <iepriekš> <ul> <li>Pirmais vienums</li> <li>Otrais vienums</li> <li>Trešais vienums</li> </ul> </pre> <h3>Pasūtītais saraksts</h3> <iepriekš> <ol> <li>Pirmā darbība</li> <li>Otrā darbība</li> <li>Trešais solis</li> </ol> </pre> <h2>Tabulas www HTML</h2> <p>HTML ļauj arī izveidot tabulas tabulu datu attēlošanai:</p> <iepriekš> <tabula> <tr> <th>1. galvene</th> <th>2. galvene</th> </tr> <tr> <td>1. rinda, 1. šūna</td> <td>1. rinda, 2. šūna</td> </tr> <tr><td>2. rinda, 1. šūna</td> <td>2. rinda, 2. šūna</td> </tr> </table> </pre> <ul> <li><strong><table></strong>: definē tabulu.</li> <li><strong><tr></strong>: definē tabulas rindu.</li> <li><strong><th></strong>: definē galvenes šūnu tabulā.</li> <li><strong><td></strong>: definē standarta datu šūnu tabulā.</li> </ul> <h2>Veidlapas www HTML</h2> <p>Veidlapas ir būtiskas lietotāja ievades apkopošanai. Šeit ir HTML veidlapas pamata piemērs:</p> <iepriekš> <form action="/submit-form" method="post"> <label for="name">Vārds:</label> <input type="text" id="name" name="name"><br><br> <label for="email">E-pasts:</label> <input type="email" id="email" name="email"><br><br> <input type="submit" value="Iesniegt"> </form> </pre> <ul> <li><strong><form></strong>: izveido HTML veidlapu lietotāja ievadei.</li> <li><strong>darbība</strong>: norāda, kur nosūtīt veidlapas datus, kad tie tiek iesniegti.</li> <li><strong>metode</strong>: definē izmantojamo HTTP metodi (GET vai POST).</li> <li><strong><label></strong>: nodrošina ievades laukiem etiķetes.</li> <li><strong><input></strong>: izveido dažāda veida ievades elementus, piemēram, teksta laukus un pogas.</li> </ul> <h2>Stilizēšana, izmantojot CSS</h2> <p>Lai gan HTML nodrošina jūsu tīmekļa lapu struktūru, CSS (Cascading Style Sheets) ir atbildīga par to izskatu. Varat saistīt CSS failu ar savu HTML dokumentu, izmantojot tagu <strong><link></strong> sadaļā <strong><head></strong>:</p> <iepriekš> <link rel="stylesheet" href="styles.css"> </pre> <p>Alternatīvi varat iekļaut CSS tieši savā HTML, izmantojot tagu <strong><style></strong>:</p> <iepriekš> <stils> body { fona krāsa: gaiši zila; } h1 { krāsa: tumši zila; piemale-kreisais: 20 pikseļi; } </style> </pre> <h2>JavaScript interaktivitātei</h2> <p>Lai savām tīmekļa lapām pievienotu interaktivitāti, varat izmantot JavaScript. Lai gan JavaScript nav daļa no paša HTML, tas darbojas kopā ar HTML un CSS, lai radītu dinamisku lietotāja pieredzi. Šeit ir vienkāršs JavaScript iegulšanas piemērs HTML dokumentā:</p> <iepriekš> <skripts> function showMessage() { brīdinājums ("Sveika, pasaule!"); } </script> <button onclick="showMessage()">Noklikšķiniet uz manis!</button> </pre> <h2>Secinājums</h2> <p>Šajā visaptverošajā rokasgrāmatā mēs esam izpētījuši <strong>www HTML</strong> pamatus, sākot no tā lomas globālajā tīmeklī līdz sarežģītu elementu, piemēram, tabulu un veidlapu, izveidei. Izprotot HTML, jūs varēsit izveidot profesionāla izskata vietnes, kas piesaista un informēs jūsu auditoriju.</p> <p>Atcerieties, ka HTML apguve ir tikai sākums jūsu ceļojumam uz tīmekļa izstrādi. Apgūstot HTML, neaizmirstiet iedziļināties CSS veidošanā un JavaScript interaktivitātei. Laimīgu kodēšanu!</p> <p>Lai iegūtu vairāk resursu un apmācības, apmeklējiet vietni <a href="https://www.serpulse.com">Serpulse</a>.</p> <p><em>Autors: Serpulse.com</em></p> <p><em>Atslēgvārdi: www html, HTML pamati, tīmekļa izstrāde, tīmekļa dizains, HTML struktūra, HTML tagi, HTML teksta elementi, HTML attēli, HTML saraksti, HTML tabulas, HTML veidlapas, CSS, JavaScript</em></p> ``` atzīme Šajā rakstā ir sniegts detalizēts pārskats par HTML, tā nozīmi un to, kā tas iekļaujas plašākā tīmekļa izstrādes kontekstā. Tajā ir ietverti pamatjēdzieni un praktiski piemēri, padarot to par lielisku resursu gan iesācējiem, gan pieredzējušiem izstrādātājiem, kuri vēlas atsvaidzināt savas zināšanas. Konkrētu HTML tagu un koda fragmentu iekļaušana nodrošina skaidrību un praktiskas mācīšanās iespējas. ``` <p>Autors: serpuls.com</p> </div> </div> <!-- Words Definitions --> <div class="card"> <div class="card-header"> <h2 class="card-title">www html Vārdi</h2> <div class="card-icon">📚</div> </div> <div class="card-content"> <div class="word-section" style="margin-bottom: 2rem;"> <h3 style="color: var(--primary); margin-bottom: 1rem; border-bottom: 1px solid #e9ecef; padding-bottom: 0.5rem;"> html </h3> <div class="info-grid"> <div class="info-item"> <strong>Perl:</strong> <div class="text-muted" style="font-size:0.85em; margin:4px 0;"> 📖 Естественные науки </div> <span>Perl - язык программирования для разработки CGI-скриптов. Программы, написанные на Perl, запускаются на стороне сервера. Perl не является коммерческим продуктом.</span> </div> </div> </div> </div> </div> <!-- Additional Services --> <div class="card" id="additional-services"> <div class="card-header"> <h2 class="card-title">Papildu pakalpojumi</h2> <div class="card-icon">💎</div> </div> <div class="card-content"> <div class="info-grid"> <div class="info-item"> <span class="popup-trigger" alt="Pilns SEO audits ar detalizētiem ieteikumiem"> <button class="cta-button" data-modal="paymentModal" data-title="Pilns SEO audits" data-text="Pilns SEO audits ar detalizētiem ieteikumiem meklētājprogrammu pozīciju uzlabošanai." data-price="99.99"> Pilns SEO audits </button> <span class="popup-text"></span> </span> </div> <div class="info-item"> <span class="popup-trigger" alt="Ikmēneša pozīcijas uzraudzība 100 atslēgas frāzēm"> <button class="cta-button" data-modal="paymentModal" data-title="Pozīcijas uzraudzība" data-text="Ikmēneša pozīcijas uzraudzība 100 galvenajām frāzēm Google un Yandex." data-price="49.99"> Pozīcijas uzraudzība </button> <span class="popup-text"></span> </span> </div> <div class="info-item"> <span class="popup-trigger" alt="Konkurentu analīze un viņu veicināšanas stratēģiju noteikšana"> <button class="cta-button" data-modal="paymentModal" data-title="Konkurentu analīze" data-text="Konkurentu analīze un viņu veicināšanas stratēģiju noteikšana." data-price="79.99"> Konkurentu analīze </button> <span class="popup-text"></span> </span> </div> </div> </div> </div> <!-- JavaScript for AJAX Pagination --> <script> // Apply filters function function applyPhraseFilters(engine) { loadSearchDomains(engine, 1); } // Load search domains for phrase function loadSearchDomains(engine, page) { const domainFilter = document.getElementById(engine + 'DomainFilter').value; const pageFilter = document.getElementById(engine + 'PageFilter').value; const phrase_id = document.getElementById('phrase_id').value; const data = { type: 'search_domains', engine: engine, page: page, phrase_id: phrase_id, // Send the phrase domain_filter: domainFilter, page_filter: pageFilter }; sendRequest('/ajax/', data, function(response) { if (response.status === 'ok') { renderSearchDomains(engine, response.data); renderPagination(engine, response.pagination); } else { showToast('Kļūda' + ':'+response.error); } }); } // Render domain pagination specifically for phrase pages function renderDomainPagination(engine, pagination) { const paginationContainer = document.getElementById(engine + 'Pagination'); paginationContainer.innerHTML = ''; const { current_page, total_pages, has_previous, has_next } = pagination; // Previous button const prevButton = document.createElement('button'); prevButton.innerHTML = '«'; prevButton.disabled = !has_previous; prevButton.addEventListener('click', () => { if (has_previous) loadSearchDomains(engine, current_page - 1); }); paginationContainer.appendChild(prevButton); // Page buttons for (let i = 1; i <= total_pages; i++) { const pageButton = document.createElement('button'); pageButton.textContent = i; pageButton.classList.toggle('active', i === current_page); pageButton.addEventListener('click', () => { if (i !== current_page) loadSearchDomains(engine, i); }); paginationContainer.appendChild(pageButton); } // Next button const nextButton = document.createElement('button'); nextButton.innerHTML = '»'; nextButton.disabled = !has_next; nextButton.addEventListener('click', () => { if (has_next) loadSearchDomains(engine, current_page + 1); }); paginationContainer.appendChild(nextButton); } // Get badge class based on position function getPositionBadgeClass(position) { if (position <= 3) return 'badge-success'; if (position <= 10) return 'badge-warning'; return 'badge-danger'; } // Toggle snippet visibility function toggleSnippet(button) { const snippet = button.nextElementSibling; const isVisible = snippet.style.display === 'block'; snippet.style.display = isVisible ? 'none' : 'block'; button.textContent = isVisible ? 'Rādīt fragmentu' : 'Slēpt fragmentu'; } </script> <script> // Toggle page details visibility function togglePageDetails(button) { const row = button.closest('tr'); const detailsRow = row.nextElementSibling; const pageDetails = detailsRow.querySelector('.page-details'); // Close all other open page details document.querySelectorAll('.page-details').forEach(detail => { if (detail !== pageDetails) { detail.classList.remove('active'); } }); // Update all button texts document.querySelectorAll('.show-page-btn').forEach(btn => { if (btn !== button) { btn.textContent = 'Rādīt lapas informāciju'; } }); // Toggle current page details if (pageDetails.classList.contains('active')) { pageDetails.classList.remove('active'); button.textContent = 'Rādīt lapas informāciju'; } else { pageDetails.classList.add('active'); button.textContent = 'Slēpt lapas informāciju'; } } // Close all page details when clicking outside document.addEventListener('click', function(e) { if (!e.target.closest('.show-page-btn') && !e.target.closest('.page-details')) { document.querySelectorAll('.page-details').forEach(detail => { detail.classList.remove('active'); }); document.querySelectorAll('.show-page-btn').forEach(btn => { btn.textContent = 'Rādīt lapas informāciju'; }); } }); // Update the renderSearchDomains function to include show page buttons function renderSearchDomains(engine, data) { const tbody = document.getElementById(engine + 'PhrasesBody'); tbody.innerHTML = ''; data.forEach((item, index) => { const row = document.createElement('tr'); // Format position with change let positionHtml = `<span class="badge ${getPositionBadgeClass(item.position)}">${item.position}</span>`; if (item.change !== null && item.change !== 0) { const changeClass = item.change > 0 ? 'positive' : 'negative'; const changeSymbol = item.change > 0 ? '+' : ''; positionHtml += `<span class="position-change ${changeClass}">(${changeSymbol}${item.change})</span>`; } row.innerHTML = ` <td>${positionHtml}</td> <td><noindex><a href="/lv/domain/${item.domain}/" rel="nofollow">${item.domain}</a></noindex></td> <td>${item.page}</td> <td> <button class="show-page-btn" onclick="togglePageDetails(this)">Rādīt lapas informāciju</button> </td> `; tbody.appendChild(row); // Add page details row const detailsRow = document.createElement('tr'); detailsRow.className = 'page-details-row'; detailsRow.innerHTML = ` <td colspan="4"> <div class="page-details" id="page-details-${engine}-${index}"> <div class="page-details-grid"> <div class="page-detail-item"> <div class="page-detail-label">Full URL</div> <div class="page-detail-value"> <a href="${item.full_url || '#'}" class="page-url" target="_blank" rel="nofollow"> ${item.full_url || 'N/A'} </a> </div> </div> <div class="page-detail-item"> <div class="page-detail-label">Title</div> <div class="page-detail-value">${item.page_title || 'N/A'}</div> </div> <div class="page-detail-item"> <div class="page-detail-label">Last Updated</div> <div class="page-detail-value">${item.last_updated || 'N/A'}</div> </div> <div class="page-detail-item"> <div class="page-detail-label">Page Authority</div> <div class="page-detail-value">${item.page_authority || 'N/A'}</div> </div> </div> <div class="page-metrics"> <div class="page-metric"> <span class="page-detail-label">Traffic:</span> <span class="page-metric-value">${item.traffic || 'N/A'}</span> </div> <div class="page-metric"> <span class="page-detail-label">Backlinks:</span> <span class="page-metric-value">${item.backlinks || 'N/A'}</span> </div> <div class="page-metric"> <span class="page-detail-label">Social Shares:</span> <span class="page-metric-value">${item.social_shares || 'N/A'}</span> </div> <div class="page-metric"> <span class="page-detail-label">Load Time:</span> <span class="page-metric-value">${item.load_time || 'N/A'}</span> </div> </div> <div class="snippet" style="margin-top: 1rem;"> <strong>Snippet Preview:</strong><br> ${item.snippet || 'No snippet available'} </div> </div> </td> `; tbody.appendChild(detailsRow); }); } </script> <script> (function() { 'use strict'; // --- Configuration --- const STORAGE_KEY = 'serpuls_phrase_sections_state'; const SECTIONS_TO_COLLAPSE = [ { id: 'morphological-lemmas', title: 'Morfoloģiskās lemmas', btnText: 'Lemmas' }, { id: 'google-search-section', title: 'Meklēšanas frāzes - Google', btnText: 'Google' }, { id: 'yandex-search-section', title: 'Meklēšanas frāzes - Yandex', btnText: 'Yandex' }, { id: 'book-samples-section', title: 'Grāmatu piemēri ar frāzi', btnText: 'Grāmatas' }, { id: 'additional-services', title: 'Papildu pakalpojumi', btnText: 'Pakalpojumi' } ]; // --- Helper Functions --- function getSectionIdFromTitle(title) { if (title.includes('Morfoloģiskās lemmas')) return 'morphological-lemmas'; if (title.includes('Meklēšanas frāzes - Google')) return 'google-search-section'; if (title.includes('Meklēšanas frāzes - Yandex')) return 'yandex-search-section'; if (title.includes('Papildu pakalpojumi')) return 'additional-services'; return null; } function saveSectionState(sectionId, isCollapsed) { const savedState = localStorage.getItem(STORAGE_KEY); const state = savedState ? JSON.parse(savedState) : {}; state[sectionId] = isCollapsed; localStorage.setItem(STORAGE_KEY, JSON.stringify(state)); } function loadSectionState(sectionId) { const savedState = localStorage.getItem(STORAGE_KEY); if (!savedState) return false; const state = JSON.parse(savedState); return state[sectionId] || false; } // --- Create Floating TOC --- function createFloatingTOC() { // Find all major sections (cards with a card-header) const sections = Array.from(document.querySelectorAll('.card')).map(card => { const headerEl = card.querySelector('.card-header'); if (!headerEl) return null; const titleEl = headerEl.querySelector('.card-title'); if (!titleEl) return null; const title = titleEl.innerText.trim(); // Skip sections that are too small or not needed const skipTitles = [ ]; let shouldSkip = false; for (const skipTitle of skipTitles) { if (title.includes(skipTitle) || title === skipTitle) { shouldSkip = true; break; } } if (shouldSkip) return null; // Create a unique ID for the section if it doesn't have one let id = card.id; if (!id) { id = 'section-' + Math.random().toString(36).substr(2, 8); card.id = id; } return { id, title, element: card }; }).filter(s => s !== null); if (sections.length < 2) return; // Create TOC container const tocContainer = document.createElement('div'); tocContainer.id = 'floating-toc'; tocContainer.className = 'floating-toc'; tocContainer.innerHTML = ` <div class="floating-toc-header"> <span>📑 Satura rādītājs</span> <button id="toc-toggle-btn" class="toc-toggle-btn" aria-label="Sakļaut satura rādītāju">−</button> </div> <div id="toc-links-container" class="toc-links-container"> ${sections.map(section => `<a href="#${section.id}" class="toc-link" data-id="${section.id}">${escapeHtml(section.title)}</a>`).join('')} </div> `; document.body.appendChild(tocContainer); // Toggle TOC visibility const toggleBtn = document.getElementById('toc-toggle-btn'); const linksContainer = document.getElementById('toc-links-container'); let isTocExpanded = true; toggleBtn.addEventListener('click', () => { if (isTocExpanded) { linksContainer.style.display = 'none'; toggleBtn.textContent = '+'; tocContainer.classList.add('collapsed'); } else { linksContainer.style.display = 'block'; toggleBtn.textContent = '−'; tocContainer.classList.remove('collapsed'); } isTocExpanded = !isTocExpanded; }); // Highlight active section on scroll const tocLinks = document.querySelectorAll('.toc-link'); const sectionElements = sections.map(s => s.element); function updateActiveLink() { let current = ''; const scrollPosition = window.scrollY + 100; for (const section of sectionElements) { const sectionTop = section.offsetTop; const sectionBottom = sectionTop + section.offsetHeight; if (scrollPosition >= sectionTop && scrollPosition < sectionBottom) { current = section.id; break; } } tocLinks.forEach(link => { link.classList.remove('active'); if (link.getAttribute('data-id') === current) { link.classList.add('active'); } }); } window.addEventListener('scroll', updateActiveLink); updateActiveLink(); // Smooth scroll tocLinks.forEach(link => { link.addEventListener('click', (e) => { e.preventDefault(); const targetId = link.getAttribute('data-id'); const targetElement = document.getElementById(targetId); if (targetElement) { targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); } // --- Add Collapsible Buttons to Sections --- function addCollapsibleButtons() { SECTIONS_TO_COLLAPSE.forEach(section => { // Find the card by its title let targetCard = null; const cards = document.querySelectorAll('.card'); for (const card of cards) { const titleEl = card.querySelector('.card-title'); if (titleEl && titleEl.innerText.trim() === section.title) { targetCard = card; break; } } if (!targetCard) return; // Set ID if not exists if (!targetCard.id) targetCard.id = section.id; // Create button const button = document.createElement('button'); button.className = 'collapse-section-btn'; button.setAttribute('data-section-id', section.id); button.setAttribute('aria-label', 'Sakļaut/izvērst sadaļu'); // Get initial state const isCollapsed = loadSectionState(section.id); if (isCollapsed) { button.innerHTML = '➕'; targetCard.classList.add('section-collapsed'); const content = targetCard.querySelector('.card-content'); if (content) content.style.display = 'none'; } else { button.innerHTML = '➖'; targetCard.classList.remove('section-collapsed'); const content = targetCard.querySelector('.card-content'); if (content) content.style.display = ''; } // Insert button into card-header const cardHeader = targetCard.querySelector('.card-header'); if (cardHeader) { const iconDiv = cardHeader.querySelector('.card-icon'); if (iconDiv) { cardHeader.insertBefore(button, iconDiv); } else { cardHeader.appendChild(button); } // Add click handler button.addEventListener('click', (e) => { e.stopPropagation(); const sectionId = button.getAttribute('data-section-id'); const card = document.getElementById(sectionId); if (!card) return; const content = card.querySelector('.card-content'); if (!content) return; if (card.classList.contains('section-collapsed')) { // Expand content.style.display = ''; card.classList.remove('section-collapsed'); button.innerHTML = '➖'; saveSectionState(sectionId, false); } else { // Collapse content.style.display = 'none'; card.classList.add('section-collapsed'); button.innerHTML = '➕'; saveSectionState(sectionId, true); } }); } }); } // --- Create Back to Top Button --- function createBackToTopButton() { const btn = document.createElement('button'); btn.id = 'back-to-top'; btn.innerHTML = '↑'; btn.setAttribute('aria-label', 'Atpakaļ uz augšu'); btn.className = 'back-to-top-btn'; document.body.appendChild(btn); window.addEventListener('scroll', () => { if (window.scrollY > 500) { btn.classList.add('visible'); } else { btn.classList.remove('visible'); } }); btn.addEventListener('click', () => { window.scrollTo({ top: 0, behavior: 'smooth' }); }); } // --- Improve Table Responsiveness (add scroll hints) --- function improveTables() { const tables = document.querySelectorAll('.data-table, .tasks-table'); tables.forEach(table => { const container = table.closest('.table-responsive') || table.parentElement; if (container && !container.querySelector('.scroll-hint')) { const hint = document.createElement('div'); hint.className = 'scroll-hint'; hint.innerHTML = '← → Velciet, lai skatītu vairāk'; hint.style.cssText = ` display: none; text-align: center; font-size: 0.7rem; color: var(--gray); margin-top: 0.5rem; padding: 0.25rem; background: rgba(67, 97, 238, 0.05); border-radius: 12px; `; container.style.position = 'relative'; container.appendChild(hint); // Show hint if table is wider than container function checkScroll() { if (container.scrollWidth > container.clientWidth) { hint.style.display = 'block'; } else { hint.style.display = 'none'; } } checkScroll(); window.addEventListener('resize', checkScroll); container.addEventListener('scroll', () => { hint.style.opacity = '0.5'; setTimeout(() => { hint.style.opacity = '1'; }, 300); }); } }); } // --- Escape HTML helper --- function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } // --- Add custom styles for new elements --- function addCustomStyles() { const style = document.createElement('style'); style.textContent = ` /* Floating TOC */ .floating-toc { position: fixed; top: 80px; right: 20px; z-index: 1000; background: white; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.15); border: 1px solid #e9ecef; width: 260px; max-width: calc(100% - 40px); transition: all 0.3s ease; backdrop-filter: blur(8px); background: rgba(255,255,255,0.95); } .floating-toc-header { display: flex; justify-content: space-between; align-items: center; padding: 10px 15px; background: linear-gradient(135deg, var(--primary), var(--secondary)); color: white; border-radius: 12px 12px 0 0; font-weight: 600; font-size: 0.9rem; cursor: pointer; } .toc-toggle-btn { background: none; border: none; color: white; font-size: 1.2rem; cursor: pointer; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: background 0.2s; } .toc-toggle-btn:hover { background: rgba(255,255,255,0.2); } .floating-toc.collapsed { width: auto; } .floating-toc.collapsed .floating-toc-header { border-radius: 12px; } .toc-links-container { max-height: 400px; overflow-y: auto; padding: 8px 0; } .toc-link { display: block; padding: 8px 15px; color: var(--dark); text-decoration: none; font-size: 0.85rem; transition: all 0.2s; border-left: 3px solid transparent; } .toc-link:hover { background: rgba(67, 97, 238, 0.05); color: var(--primary); padding-left: 20px; } .toc-link.active { background: rgba(67, 97, 238, 0.1); border-left-color: var(--primary); color: var(--primary); font-weight: 500; } /* Collapse button in cards */ .collapse-section-btn { background: none; border: none; font-size: 1.1rem; cursor: pointer; width: 28px; height: 28px; border-radius: 6px; display: inline-flex; align-items: center; justify-content: center; transition: all 0.2s; color: var(--gray); margin-right: 8px; } .collapse-section-btn:hover { background: rgba(67, 97, 238, 0.1); color: var(--primary); } .card.section-collapsed .card-header { border-bottom: none; } /* Back to Top Button */ .back-to-top-btn { position: fixed; bottom: 30px; right: 30px; width: 48px; height: 48px; border-radius: 50%; background: linear-gradient(135deg, var(--primary), var(--secondary)); color: white; border: none; cursor: pointer; font-size: 1.5rem; display: flex; align-items: center; justify-content: center; opacity: 0; visibility: hidden; transition: all 0.3s ease; z-index: 999; box-shadow: 0 4px 12px rgba(67, 97, 238, 0.4); } .back-to-top-btn.visible { opacity: 1; visibility: visible; } .back-to-top-btn:hover { transform: translateY(-3px); box-shadow: 0 6px 16px rgba(67, 97, 238, 0.5); } /* Mobile adjustments */ @media (max-width: 768px) { .floating-toc { top: auto; bottom: 20px; right: 20px; left: auto; width: 48px; overflow: hidden; } .floating-toc .floating-toc-header span { display: none; } .floating-toc .floating-toc-header { justify-content: center; padding: 12px; } .floating-toc .toc-toggle-btn { margin: 0; } .floating-toc:not(.collapsed) { width: 260px; left: auto; right: 20px; bottom: 20px; top: auto; } .floating-toc:not(.collapsed) .floating-toc-header span { display: inline; } .floating-toc:not(.collapsed) .floating-toc-header { justify-content: space-between; } .back-to-top-btn { bottom: 80px; right: 20px; width: 40px; height: 40px; font-size: 1.2rem; } .scroll-hint { display: block !important; font-size: 0.65rem; } } /* Smooth scroll behavior */ html { scroll-behavior: smooth; } /* Better card transitions */ .card .card-content { transition: display 0.2s ease; } /* RTL support for languages like Arabic/Hebrew */ [dir="rtl"] .floating-toc { right: auto; left: 20px; } [dir="rtl"] .back-to-top-btn { right: auto; left: 30px; } [dir="rtl"] .collapse-section-btn { margin-right: 0; margin-left: 8px; } `; document.head.appendChild(style); } // --- Initialize everything when DOM is ready --- function init() { addCustomStyles(); createFloatingTOC(); addCollapsibleButtons(); createBackToTopButton(); improveTables(); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })(); </script></div> <!-- Footer --> <footer> <div class="footer-container"> <div class="footer-content"> <div class="footer-section"> <h3>About serpuls.com</h3> <div class="footer-info"> <p>Profesionāls rīks meklētājprogrammu analīzei, pozīcijas uzraudzībai un SEO optimizācijai.</p> <p style="margin-top: 1rem;"><strong>Skynet360 LP.</strong></p> <p><strong>Uzņēmuma Nr:</strong> SL027564</p> <p><strong>Adrese:</strong> Suite 1 4 Queen Street, Edinburgh, Scotland, EH2 1JE</p> </div> </div> <div class="footer-section"> <h3>Ātrās saites</h3> <ul class="footer-links"> <li><a href="/lv/">Sākums</a></li> <li><a href="/lv/profile/">Profils</a></li> <li><a href="/lv/tasks/">Uzraudzības uzdevumi</a></li> <li><a href="/lv/api_docs/">API dokumentācija</a></li> <li><a href="/lv/team/">Mūsu komanda</a></li> </ul> </div> <div class="footer-section"> <h3>Resursi</h3> <ul class="footer-links"> <li><a href="/lv/blogs/">Emuārs</a></li> <li><a href="/lv/faq/">FAQ</a></li> <li><a href="/lv/support/">Atbalsts</a></li> </ul> </div> <div class="footer-section"> <h3>Kontakti</h3> <div class="footer-info"> <p>E-pasts: <a href="mailto:info@serpuls.com">info@serpuls.com</a></p> <p>Telegramma: <a href="https://t.me/serpulse_support">@serpulse_support</a></p> <div class="social-links"> <a href="#" class="social-link" title="Telegramma">📱</a> <a href="https://github.com/SkyNetJose/serpuls" class="social-link" title="GitHub">💻</a> <a href="#" class="social-link" title="Twitter">🐦</a> </div> </div> </div> </div> <div class="footer-bottom"> <p class="copyright">© 2026 serpuls.com. Visas tiesības paturētas. Skynet360 LP.</p> <div class="footer-bottom-links"> <a href="/lv/privacy/">Privātuma politika</a> <a href="/lv/terms/">Lietošanas noteikumi</a> <a href="/lv/agreement/">Lietotāja līgums</a> <a href="/lv/cookie/">Sīkdatņu politika</a> </div> </div> </div> </footer> <!-- Updated Payment Modal HTML --> <div class="modal" id="paymentModal"> <div class="modal-content"> <span class="close-btn">×</span> <div class="modal-success" id="paymentSuccess"> <div class="success-icon">✓</div> <h3>Maksājums veiksmīgs!</h3> <p>Paldies par pasūtījumu. Mēs ar jums sazināsimies tuvākajā laikā.</p> <button class="cta-button" onclick="closeModal('paymentModal')">Aizvērt</button> </div> <form id="paymentForm" onsubmit="return processPayment(event)"> <h2 class="modal-title" id="modalTitle">Apmaksa par pakalpojumu</h2> <p class="modal-text" id="modalText">Pakalpojuma apraksts</p> <!-- Hidden fields for payment type and ID --> <input type="hidden" id="paymentType" name="payment_type" value=""> <input type="hidden" id="paymentItemId" name="payment_item_id" value=""> <!-- Payment Options --> <div class="payment-options" id="paymentOptions"> <!-- Options will be dynamically generated here --> </div> <!-- Manual Price Input (Optional) - Now dynamically shown based on config --> <div class="form-group" id="manualPriceGroup" style="display: none;"> <label for="manualPrice">Ievadiet summu (USD):</label> <input type="number" id="manualPrice" class="form-control" placeholder="Ievadiet summu" min="1" max="1000" step="0.01" oninput="updateManualPrice(this.value)"> <div class="error-message" id="manualPriceError"></div> </div> <!-- Custom Price Option Toggle - Now dynamically shown --> <div class="form-group" id="customPriceToggle" style="display: none; margin-bottom: 1rem;"> <label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;"> <input type="radio" id="customPriceRadio" name="paymentOption" value="custom" onchange="toggleCustomPriceSelection(this.checked)"> Ievadiet pielāgotu summu </label> </div> <div class="form-group"> <label for="modalName">Vārds:</label> <input type="text" id="modalName" class="form-control" placeholder="Ievadiet savu vārdu" required> <div class="error-message" id="modalNameError"></div> </div> <div class="form-group"> <label for="modalEmail">E-pasts:</label> <input type="email" id="modalEmail" class="form-control" placeholder="Ievadiet savu e-pastu" required> <div class="error-message" id="modalEmailError"></div> </div> <p class="modal-price" id="modalPrice">Cena: $0.00</p> <button type="submit" class="cta-button" id="payButton">Maksājiet $0.00</button> </form> </div> </div> <!-- Redirect Modal (for iframe) --> <div class="modal" id="redirectModal"> <div class="modal-content modal-large"> <span class="close-btn">×</span> <h2 class="modal-title">Maksājums</h2> <iframe id="redirectIframe" class="modal-iframe" src=""></iframe> </div> </div> <!-- Auth Modal --> <div class="modal" id="authModal"> <div class="modal-content"> <span class="close-btn">×</span> <div class="auth-tabs"> <div class="auth-tab active" data-tab="login">Pieteikties</div> <div class="auth-tab" data-tab="register">Reģistrēties</div> </div> <div class="auth-form active" id="loginForm"> <h2 class="modal-title">Pierakstieties savā kontā</h2> <div class="form-group"> <label for="loginEmail">E-pasts:</label> <input type="email" id="loginEmail" class="form-control" autocomplete="email" placeholder="Ievadiet savu e-pastu"> <div class="error-message" id="loginEmailError"></div> </div> <div class="form-group"> <label for="loginPassword">Parole:</label> <input type="password" id="loginPassword" class="form-control" autocomplete="current-password" placeholder="Ievadiet savu paroli"> <div class="error-message" id="loginPasswordError"></div> </div> <button class="cta-button" style="width:100%" onclick="processLogin()">Pierakstīties</button> <div style="text-align:center;margin:1rem 0;color:var(--gray);border-top:1px solid #e9ecef;padding-top:1rem;">Vai arī turpiniet ar</div> <button class="cta-button secondary" style="width:100%;margin-bottom:.6rem" onclick="startOAuth('google')">Google</button> <button class="cta-button secondary" style="width:100%;margin-bottom:.6rem" onclick="startOAuth('github')">GitHub</button> <button class="cta-button" style="background:#0088cc;width:100%" onclick="loginWithTelegram()">📱 Pierakstieties, izmantojot Telegram</button> <p style="margin-top:.5rem;color:var(--gray);font-size:.9rem">Lai pierakstītos Telegram, vispirms ievadiet ar Telegram savienotā Serpulse konta e-pastu.</p> </div> <div class="auth-form" id="registerForm"> <h2 class="modal-title">Izveidot kontu</h2> <div class="form-group"><label for="registerName">Vārds:</label><input type="text" id="registerName" class="form-control" autocomplete="name" required><div class="error-message" id="registerNameError"></div></div> <div class="form-group"><label for="registerEmail">E-pasts:</label><input type="email" id="registerEmail" class="form-control" autocomplete="email" required><div class="error-message" id="registerEmailError"></div></div> <div class="form-group"><label for="registerPassword">Parole:</label><input type="password" id="registerPassword" class="form-control" autocomplete="new-password" minlength="8" required><div class="error-message" id="registerPasswordError"></div></div> <div class="form-group"><label for="registerConfirmPassword">Apstipriniet paroli:</label><input type="password" id="registerConfirmPassword" class="form-control" autocomplete="new-password" minlength="8" required><div class="error-message" id="registerConfirmPasswordError"></div></div> <button class="cta-button" style="width:100%" onclick="processRegistration()">Izveidot kontu</button> <div style="text-align:center;margin:1rem 0;color:var(--gray);border-top:1px solid #e9ecef;padding-top:1rem;">Vai izveidojiet kontu ar</div> <button class="cta-button secondary" style="width:100%;margin-bottom:.6rem" onclick="startOAuth('google')">Google</button> <button class="cta-button secondary" style="width:100%;margin-bottom:.6rem" onclick="startOAuth('github')">GitHub</button> <button class="cta-button" style="background:#0088cc;width:100%" onclick="startTelegramRegistration()">📱 Reģistrējieties telegrammā</button> <p style="margin-top:1rem;color:var(--gray);font-size:.9rem">Parolei un Telegram reģistrācijai ir nepieciešama e-pasta pārbaude. Google un GitHub reģistrācija izmanto pakalpojumu sniedzēja atgriezto verificēto e-pastu.</p> </div> </div> </div> <!-- Telegram Code Input Modal --> <div class="modal" id="telegramCodeModal"> <div class="modal-content"> <span class="close-btn" onclick="closeModal('telegramCodeModal')">×</span> <div class="centered-content"> <div class="success-icon">🔐</div> <h2 class="modal-title">Verifikācijas kods</h2> <p class="modal-text">Kods tika nosūtīts uz Telegram. Ievadiet to zemāk:</p> <div class="form-group"> <input type="text" id="telegramLoginCode" class="form-control verify-code-input" placeholder="0000000" maxlength="7" style="font-size: 1.5rem; letter-spacing: 0.5rem;"> <div class="error-message" id="telegramLoginCodeError"></div> </div> <button class="cta-button" style="width: 100%; margin-top: 1rem;" onclick="verifyTelegramLoginCode()"> Apstipriniet pieteikšanos </button> <div class="timer-container" id="loginCodeTimer"> Kods derīgs: <span id="loginTimer">05:00</span> </div> </div> </div> </div> <!-- Updated Telegram Verification Modal --> <div class="modal" id="telegramVerifyModal"> <div class="modal-content"> <span class="close-btn" onclick="closeTelegramVerifyModal()">×</span> <div class="centered-content"> <div class="success-icon">📱</div> <h2 class="modal-title">Pabeigt reģistrāciju Telegram</h2> <p class="modal-text" id="telegramModalText"> Telegram tika atvērta jaunā cilnē.<br> Ja robotprogrammatūra neatvērās automātiski, izmantojiet tālāk esošo pogu vai skenējiet QR kodu. </p> <!-- QR Code Container --> <div id="qrCodeContainer" style="margin: 1.5rem 0; text-align: center;"> <div id="qrcode" style="display: inline-block;"></div> <p style="font-size: 0.9rem; color: var(--gray); margin-top: 0.5rem;"> Lai atvērtu robotprogrammatūru, skenējiet QR kodu </p> </div> <!-- Timer and Status --> <div id="telegramTimer" class="timer-container"> Gaida apstiprinājumu... <span id="timer">05:00</span> </div> <!-- Action Buttons --> <div style="display: flex; gap: 1rem; margin-top: 1.5rem; flex-wrap: wrap; justify-content: center;"> <button class="cta-button" style="background: #0088cc;" onclick="openTelegramBot()" id="openTelegramBtn"> 📱 Atkal atveriet Telegram </button> <button class="cta-button secondary" onclick="refreshTelegramQR()" id="refreshQRBtn"> 🔄 Atsvaidziniet QR kodu </button> </div> <!-- Status Info --> <div class="info-box" style="margin-top: 1.5rem;"> <p style="margin: 0; font-size: 0.9rem;"> <strong>Kā tas darbojas:</strong><br> 1. Noklikšķiniet uz Atvērt telegrammu vai skenējiet QR kodu<br> 2. Botā noklikšķiniet uz SĀKT un kopīgojiet savu tālruņa numuru<br> 3. Apstiprinājuma statuss tiks automātiski atjaunināts </p> </div> </div> </div> </div> <!-- Email Verification Modal --> <div class="modal" id="emailVerifyModal"> <div class="modal-content"> <span class="close-btn" onclick="closeEmailVerifyModal()">×</span> <div class="centered-content"> <div class="success-icon">📧</div> <h2 class="modal-title">Apstipriniet savu e-pastu</h2> <p class="modal-text" id="emailVerifyMessage">Pārbaudiet savu iesūtni un noklikšķiniet uz verifikācijas saites, ko mēs jums nosūtījām. Jūs nevarat pierakstīties ar paroli, kamēr jūsu e-pasts nav apstiprināts.</p> <p id="emailVerifyAddress" style="font-weight:600;word-break:break-all"></p> <button id="resendEmailBtn" class="cta-button secondary" style="width:100%;margin-top:1rem" onclick="resendEmailVerification()">Atkārtoti nosūtīt verifikācijas e-pastu</button> <button class="cta-button" style="width:100%;margin-top:.75rem" onclick="closeEmailVerifyModal()">Aizvērt</button> </div> </div> </div> <!-- Image reusable Modal --> <div class="modal" id="imgModal"> <div class="modal-content"> <span class="close-btn">×</span> <img id="modalImg" src="" style="max-width:90%; max-height:90%; margin-top:40px; border-radius:8px;"> </div> </div> <!--Loading overlay --> <div class="loading-overlay" id="loadingOverlay"> <div class="loading-spinner"></div> </div> <div class="toast" id="toast"></div> <script> // Get language from URL path like /en/about or /ru/products function getLangFromUrl() { const path = window.location.pathname; const match = path.match(/^\/([a-z]{2})(\/|$)/i); return match ? match[1] : 'en'; // default to 'en' if no language code found } // Store in global variable window.currentLang = getLangFromUrl(); // Show loading overlay function showLoading() { document.getElementById('loadingOverlay').classList.add('active'); } // Hide loading overlay function hideLoading() { document.getElementById('loadingOverlay').classList.remove('active'); } // Show toast notification function showToast(message, type = 'info') { const toast = document.getElementById('toast'); toast.textContent = message; toast.className = 'toast ' + type; toast.classList.add('show'); setTimeout(() => { toast.classList.remove('show'); }, 3000); } // Check user login status on page load document.addEventListener('DOMContentLoaded', function() { checkUserLoginStatus(); }); // Function to check if user is logged in function checkUserLoginStatus() { const userInfoElement = document.getElementById('userInfo'); const guestButtonsElement = document.getElementById('guestButtons'); const userNameElement = document.getElementById('userName'); // Show loading state or keep defaults while checking if (guestButtonsElement) { guestButtonsElement.style.display = 'flex'; } if (userInfoElement) { userInfoElement.style.display = 'none'; } const data = { type: 'check_user_logined' }; sendRequest('/ajax/', data, function(response) { if (response.status === 'ok') { if (response.user_logined === 1) { // User is logged in if (userInfoElement) { userInfoElement.style.display = 'block'; } if (guestButtonsElement) { guestButtonsElement.style.display = 'none'; } if (userNameElement) { // Use logined_user_name if available, otherwise show default userNameElement.textContent = response.logined_user_name || 'Profils'; } // Optionally store minimal info in localStorage for quick access // but don't rely on it for auth state if (response.logined_user_id) { localStorage.setItem('user_id', response.logined_user_id); } if (response.logined_user_name) { localStorage.setItem('user_name', response.logined_user_name); } } else { // User is not logged in if (userInfoElement) { userInfoElement.style.display = 'none'; } if (guestButtonsElement) { guestButtonsElement.style.display = 'flex'; } // Clear any previously stored user data localStorage.removeItem('user_id'); localStorage.removeItem('user_name'); localStorage.removeItem('user_info'); } } else { console.error('Pārbaudot pieteikšanās statusu, radās kļūda:', response.error); // On error, default to guest view if (userInfoElement) { userInfoElement.style.display = 'none'; } if (guestButtonsElement) { guestButtonsElement.style.display = 'flex'; } } }, false); // Don't show loading overlay for this quick check } // Logout function function logout() { // Send logout request to server const data = { type: 'logout' }; sendRequest('/ajax/', data, function(response) { // Clear all user data from localStorage regardless of response localStorage.removeItem('user_info'); localStorage.removeItem('user_id'); localStorage.removeItem('user_name'); localStorage.removeItem('current_user_token'); // Update UI checkUserLoginStatus(); // Redirect to main page window.location.href = '/'; }); } </script> <script> // Mobile menu toggle - Combined approach document.getElementById('hamburger').addEventListener('click', function() { const mobileMenu = document.getElementById('mobileMenu'); mobileMenu.classList.toggle('active'); }); // Close mobile menu when clicking on links or buttons document.querySelectorAll('.nav-links a, .auth-buttons button').forEach(element => { element.addEventListener('click', function() { document.getElementById('mobileMenu').classList.remove('active'); }); }); // Close mobile menu when clicking outside document.addEventListener('click', function(event) { const mobileMenu = document.getElementById('mobileMenu'); const hamburger = document.getElementById('hamburger'); const navContainer = document.querySelector('.nav-container'); if (!navContainer.contains(event.target) && mobileMenu.classList.contains('active')) { mobileMenu.classList.remove('active'); } }); // Simple animation on scroll document.addEventListener('DOMContentLoaded', function() { const cards = document.querySelectorAll('.card, .domain-header, .chart-container, .lemma-card'); const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.style.opacity = '1'; entry.target.style.transform = 'translateY(0)'; } }); }, { threshold: 0.0001, // Optional: keep small percentage rootMargin: '350px 0px 350px 0px' // Trigger 100px before element enters }); cards.forEach(card => { card.style.opacity = '0'; card.style.transform = 'translateY(20px)'; card.style.transition = 'opacity 0.5s ease, transform 0.5s ease'; observer.observe(card); }); }); // Toggle links visibility function toggleLinks(className, btn, max_count = 5) { const list = document.getElementById(className); const items = list.querySelectorAll('li'); const hiddenItems = list.querySelectorAll('li.hidden'); if (hiddenItems.length > 0) { // Show all list.querySelectorAll('li.hidden').forEach(el => el.classList.remove('hidden')); btn.textContent = 'Slēpt'; } else { // Hide all beyond the first 5 items.forEach((el, index) => { if (index >= max_count) el.classList.add('hidden'); }); btn.textContent = 'Rādīt vairāk'; } } // Toggle raw data visibility function toggleRawData(elementId, btn) { const element = document.getElementById(elementId); if (element.style.maxHeight === '200px') { element.style.maxHeight = 'none'; btn.textContent = 'Slēpt visus datus'; } else { element.style.maxHeight = '200px'; btn.textContent = 'Rādīt pilnus datus'; } } </script> <script> // Payment Modal // Global variable to store payment config let paymentConfig = { allowCustomAmount: false, minAmount: 1, maxAmount: 1000 }; // Payment options functionality document.addEventListener('DOMContentLoaded', function() { // Replace the entire payment options event listener with this: document.addEventListener('change', function(e) { if (e.target && e.target.name === 'paymentOption') { // Update selected state for regular options document.querySelectorAll('.payment-option').forEach(opt => { opt.classList.remove('selected'); }); // Handle custom price radio separately if (e.target.id === 'customPriceRadio') { // For custom price, we don't have a .payment-option wrapper // Just update the custom price toggle UI document.querySelectorAll('.payment-option').forEach(opt => { opt.classList.remove('selected'); }); // You might want to add visual feedback for custom price selection const customPriceToggle = document.getElementById('customPriceToggle'); if (customPriceToggle) { customPriceToggle.style.backgroundColor = 'rgba(67, 97, 238, 0.1)'; customPriceToggle.style.borderLeft = '3px solid var(--primary)'; customPriceToggle.style.padding = '0.5rem'; customPriceToggle.style.borderRadius = 'var(--border-radius)'; } } else { // For regular options, highlight the .payment-option container const paymentOption = e.target.closest('.payment-option'); if (paymentOption) { paymentOption.classList.add('selected'); // Reset custom price toggle styling if it was highlighted const customPriceToggle = document.getElementById('customPriceToggle'); if (customPriceToggle) { customPriceToggle.style.backgroundColor = ''; customPriceToggle.style.borderLeft = ''; customPriceToggle.style.padding = ''; } } } // Update price (this should work for all options) updatePaymentPrice(e.target.value); } }); }); // Update the updatePaymentPrice function to handle custom price: function updatePaymentPrice(price) { const modalPrice = document.getElementById('modalPrice'); const payButton = document.getElementById('payButton'); const customPriceRadio = document.getElementById('customPriceRadio'); // Uncheck custom price radio if regular option is selected if (customPriceRadio && customPriceRadio.checked === false) { document.getElementById('manualPriceGroup').style.display = 'none'; // Reset custom price toggle styling const customPriceToggle = document.getElementById('customPriceToggle'); if (customPriceToggle) { customPriceToggle.style.backgroundColor = ''; customPriceToggle.style.borderLeft = ''; customPriceToggle.style.padding = ''; } } modalPrice.textContent = 'Cena: $' + parseFloat(price).toFixed(2); payButton.textContent = 'Maksājiet $' + parseFloat(price).toFixed(2); payButton.disabled = false; payButton.style.opacity = '1'; } // Generate payment options based on config function generatePaymentOptions(optionsData, paymentType = 'balance', paymentItemId = '', config = {}) { const paymentOptionsContainer = document.getElementById('paymentOptions'); const paymentTypeInput = document.getElementById('paymentType'); const paymentItemIdInput = document.getElementById('paymentItemId'); const customPriceToggle = document.getElementById('customPriceToggle'); const manualPriceGroup = document.getElementById('manualPriceGroup'); // Set hidden fields paymentTypeInput.value = paymentType; paymentItemIdInput.value = paymentItemId; // Store config globally paymentConfig = { allowCustomAmount: config.allowCustomAmount || false, minAmount: config.minAmount || 1, maxAmount: config.maxAmount || 1000 }; // Clear container paymentOptionsContainer.innerHTML = ''; // Generate regular options if (optionsData && optionsData.length > 0) { optionsData.forEach((option, index) => { const optionElement = document.createElement('div'); optionElement.className = 'payment-option'; optionElement.innerHTML = ` <input type="radio" id="option${index}" name="paymentOption" value="${option.price}" data-label="${option.label}" ${option.default ? 'checked' : ''} onchange="updatePaymentPrice('${option.price}')"> <label for="option${index}">${option.label} - $${option.price}</label> `; paymentOptionsContainer.appendChild(optionElement); }); paymentOptionsContainer.style.display = 'block'; } else { paymentOptionsContainer.style.display = 'none'; } // Show/hide custom amount option based on config if (paymentConfig.allowCustomAmount) { customPriceToggle.style.display = 'block'; // Update manual price input constraints document.getElementById('manualPrice').min = paymentConfig.minAmount; document.getElementById('manualPrice').max = paymentConfig.maxAmount; document.getElementById('manualPrice').placeholder = 'No $${paymentConfig.minAmount} uz $${paymentConfig.maxAmount}'; } else { customPriceToggle.style.display = 'none'; manualPriceGroup.style.display = 'none'; } // Select first option by default if none is marked as default if (optionsData && optionsData.length > 0) { const defaultOption = paymentOptionsContainer.querySelector('input[type="radio"][checked]') || paymentOptionsContainer.querySelector('input[type="radio"]'); if (defaultOption) { defaultOption.checked = true; defaultOption.closest('.payment-option').classList.add('selected'); updatePaymentPrice(defaultOption.value); } } else if (paymentConfig.allowCustomAmount) { // If no options but custom amount is allowed, show custom by default document.getElementById('customPriceRadio').checked = true; toggleCustomPriceSelection(true); } } // Also update the toggleCustomPriceSelection function: function toggleCustomPriceSelection(isSelected) { const manualPriceGroup = document.getElementById('manualPriceGroup'); const paymentOptions = document.getElementById('paymentOptions'); const customPriceRadio = document.getElementById('customPriceRadio'); if (isSelected) { manualPriceGroup.style.display = 'block'; // Deselect all regular options document.querySelectorAll('input[name="paymentOption"]').forEach(radio => { if (radio.id !== 'customPriceRadio') { radio.checked = false; const paymentOption = radio.closest('.payment-option'); if (paymentOption) { paymentOption.classList.remove('selected'); } } }); // Visual feedback for custom price selection const customPriceToggle = document.getElementById('customPriceToggle'); if (customPriceToggle) { customPriceToggle.style.backgroundColor = 'rgba(67, 97, 238, 0.1)'; customPriceToggle.style.borderLeft = '3px solid var(--primary)'; customPriceToggle.style.padding = '0.5rem'; customPriceToggle.style.borderRadius = 'var(--border-radius)'; customPriceToggle.style.transition = 'var(--transition)'; } // Focus on manual price input setTimeout(() => { const manualInput = document.getElementById('manualPrice'); manualInput.focus(); // Update price if there's already a value if (manualInput.value) { updateManualPrice(manualInput.value); } else { // Set default to min amount updateManualPrice(paymentConfig.minAmount); manualInput.value = paymentConfig.minAmount; } }, 100); } else { manualPriceGroup.style.display = 'none'; // Reset custom price toggle styling const customPriceToggle = document.getElementById('customPriceToggle'); if (customPriceToggle) { customPriceToggle.style.backgroundColor = ''; customPriceToggle.style.borderLeft = ''; customPriceToggle.style.padding = ''; } } } // Update price from manual input in real-time function updateManualPrice(price) { if (!price || price < paymentConfig.minAmount || price > paymentConfig.maxAmount) { const modalPrice = document.getElementById('modalPrice'); const payButton = document.getElementById('payButton'); if (price && (price < paymentConfig.minAmount || price > paymentConfig.maxAmount)) { modalPrice.textContent = 'Cena: no $${paymentConfig.minAmount} uz $${paymentConfig.maxAmount}'; payButton.textContent = 'Nederīga summa'; payButton.disabled = true; payButton.style.opacity = '0.6'; } else { modalPrice.textContent = 'Cena: $0.00'; payButton.textContent = 'Maksājiet $0.00'; payButton.disabled = true; payButton.style.opacity = '0.6'; } return; } const modalPrice = document.getElementById('modalPrice'); const payButton = document.getElementById('payButton'); modalPrice.textContent = 'Cena: $' + parseFloat(price).toFixed(2); payButton.textContent = 'Maksājiet $' + parseFloat(price).toFixed(2); payButton.disabled = false; payButton.style.opacity = '1'; } const paymentModal = document.getElementById('paymentModal'); const paymentCloseBtn = paymentModal.querySelector('.close-btn'); // Elements inside modal const modalTitle = document.getElementById('modalTitle'); const modalText = document.getElementById('modalText'); const modalPrice = document.getElementById('modalPrice'); const payButton = document.getElementById('payButton'); const paymentForm = document.getElementById('paymentForm'); const paymentSuccess = document.getElementById('paymentSuccess'); // Updated modal opening handler document.querySelectorAll('[data-modal="paymentModal"]').forEach(trigger => { trigger.addEventListener('click', function(e) { e.preventDefault(); // Get data attributes const title = this.getAttribute('data-title'); const text = this.getAttribute('data-text'); const price = this.getAttribute('data-price'); const paymentType = this.getAttribute('data-payment-type') || 'balance'; const paymentItemId = this.getAttribute('data-payment-item-id') || ''; // Get payment config from data attributes const allowCustomAmount = this.getAttribute('data-allow-custom') === 'true'; const minAmount = parseFloat(this.getAttribute('data-min-amount')) || 1; const maxAmount = parseFloat(this.getAttribute('data-max-amount')) || 1000; // Get payment options from data attribute const optionsData = this.getAttribute('data-options'); let paymentOptions = []; if (optionsData) { try { paymentOptions = JSON.parse(optionsData); } catch (e) { console.error('Parsējot maksājumu iespējas, radās kļūda:', e); } } // Fill modal content document.getElementById('modalTitle').textContent = title; document.getElementById('modalText').textContent = text; // Generate payment options with config const config = { allowCustomAmount: allowCustomAmount, minAmount: minAmount, maxAmount: maxAmount }; generatePaymentOptions(paymentOptions, paymentType, paymentItemId, config); // If no options and custom amount not allowed, use default price if (paymentOptions.length === 0 && !allowCustomAmount) { updatePaymentPrice(price); } // Reset form resetForm('paymentModal'); document.getElementById('paymentForm').style.display = 'block'; document.getElementById('paymentSuccess').style.display = 'none'; // Show modal document.getElementById('paymentModal').style.display = 'flex'; }); }); // Helper function to reset form function resetPaymentForm() { document.getElementById('modalName').value = ''; document.getElementById('modalEmail').value = ''; document.getElementById('manualPrice').value = ''; if (document.getElementById('customPriceRadio')) { document.getElementById('customPriceRadio').checked = false; } clearErrors(['nameError', 'emailError', 'manualPriceError']); } // Close payment modal paymentCloseBtn.addEventListener('click', function() { paymentModal.style.display = 'none'; }); // Close on outside click window.addEventListener('click', function(e) { if (e.target === paymentModal) { paymentModal.style.display = 'none'; } }); // Fill tooltip with alt text automatically document.querySelectorAll('.popup-trigger').forEach(trigger => { const altText = trigger.getAttribute('alt'); const popupText = trigger.querySelector('.popup-text'); if (popupText && altText) { popupText.textContent = altText; } }); </script> <script> // Fill tooltip with alt text automatically document.querySelectorAll('.popup-trigger').forEach(trigger => { const altText = trigger.getAttribute('alt'); const popupText = trigger.querySelector('.popup-text'); if (popupText && altText) { popupText.textContent = altText; } }); // Auth Modal const authModal = document.getElementById('authModal'); const authCloseBtn = authModal.querySelector('.close-btn'); const loginBtn = document.getElementById('loginBtn'); const registerBtn = document.getElementById('registerBtn'); const authTabs = document.querySelectorAll('.auth-tab'); const authForms = document.querySelectorAll('.auth-form'); // Open auth modal loginBtn.addEventListener('click', function() { authModal.style.display = 'flex'; switchAuthTab('login'); resetForm('authModal'); }); registerBtn.addEventListener('click', function() { authModal.style.display = 'flex'; switchAuthTab('register'); resetForm('authModal'); }); // Close auth modal authCloseBtn.addEventListener('click', function() { authModal.style.display = 'none'; }); // Close on outside click window.addEventListener('click', function(e) { if (e.target === authModal) { authModal.style.display = 'none'; } }); // Switch auth tabs function switchAuthTab(tabName) { authTabs.forEach(tab => { if (tab.getAttribute('data-tab') === tabName) { tab.classList.add('active'); } else { tab.classList.remove('active'); } }); authForms.forEach(form => { if (form.id === tabName + 'Form') { form.classList.add('active'); } else { form.classList.remove('active'); } }); } // Add click events to auth tabs authTabs.forEach(tab => { tab.addEventListener('click', function() { const tabName = this.getAttribute('data-tab'); switchAuthTab(tabName); resetForm('authModal'); }); }); // Reset form and errors function resetForm(modalType) { if (modalType === 'paymentModal') { document.getElementById('modalName').value = ''; document.getElementById('modalEmail').value = ''; clearErrors(['nameError', 'emailError']); } else if (modalType === 'authModal') { document.getElementById('loginEmail').value = ''; document.getElementById('loginPassword').value = ''; document.getElementById('registerName').value = ''; document.getElementById('registerEmail').value = ''; if(document.getElementById('registerPassword'))document.getElementById('registerPassword').value = ''; if(document.getElementById('registerConfirmPassword'))document.getElementById('registerConfirmPassword').value = ''; clearErrors(['loginEmailError', 'loginPasswordError', 'registerNameError', 'registerEmailError', 'registerPasswordError', 'registerConfirmPasswordError']); } } // Clear error messages function clearErrors(errorIds) { errorIds.forEach(id => { const errorElement = document.getElementById(id); if (errorElement) { errorElement.textContent = ''; errorElement.classList.remove('show'); const inputElement = document.getElementById(id.replace('Error', '')); if (inputElement) { inputElement.classList.remove('error'); } } }); } // Show error message function showError(fieldId, message) { const errorElement = document.getElementById(fieldId + 'Error'); const inputElement = document.getElementById(fieldId); if (errorElement) { errorElement.textContent = message; errorElement.classList.add('show'); } if (inputElement) { inputElement.classList.add('error'); } } // Enhanced close modal function for general use function closeModal(modalId) { // Clear timers based on which modal is being closed switch(modalId) { case 'telegramVerifyModal': clearTelegramTimers(); break; case 'authModal': // Clear any potential timers in auth modal break; } document.getElementById(modalId).style.display = 'none'; } // Enhanced processPayment function function processPayment(event) { if (event) event.preventDefault(); const name = document.getElementById('modalName').value; const email = document.getElementById('modalEmail').value; const paymentType = document.getElementById('paymentType').value; const paymentItemId = document.getElementById('paymentItemId').value; // Get price - check if using custom amount or selected option let price; let optionLabel = ''; const customPriceRadio = document.getElementById('customPriceRadio'); if (customPriceRadio && customPriceRadio.checked) { // Custom amount price = document.getElementById('manualPrice').value; optionLabel = 'custom_amount'; // Validate custom amount if (!price || price < paymentConfig.minAmount || price > paymentConfig.maxAmount) { showError('manualPrice', 'Summai jābūt starp $${paymentConfig.minAmount} un $${paymentConfig.maxAmount}'); return false; } } else { // Regular option const selectedOption = document.querySelector('input[name="paymentOption"]:checked'); if (selectedOption) { price = selectedOption.value; optionLabel = selectedOption.getAttribute('data-label') || 'selected_option'; } else { // Fallback to default price price = document.getElementById('modalPrice').textContent.match(/\d+\.\d+/)?.[0] || '0'; optionLabel = 'default'; } } const service = document.getElementById('modalTitle').textContent; // Clear previous errors clearErrors(['nameError', 'emailError', 'manualPriceError']); // Validate form let hasErrors = false; if (!name) { showError('modalName', 'Lūdzu, ievadiet savu vārdu'); hasErrors = true; } if (!email) { showError('modalEmail', 'Lūdzu, ievadiet savu e-pasta adresi'); hasErrors = true; } else if (!/\S+@\S+\.\S+/.test(email)) { showError('modalEmail', 'Lūdzu, ievadiet derīgu e-pasta adresi'); hasErrors = true; } if (hasErrors) return false; // Prepare data for API request const data = { type: 'payment', name: name, email: email, price: parseFloat(price).toFixed(2), service: service, payment_type: paymentType, payment_item_id: paymentItemId, option: optionLabel, is_custom_amount: (customPriceRadio && customPriceRadio.checked) ? 1 : 0 }; // Send request to API sendRequest('/ajax/', data, function(response) { if (response.status === 'ok') { if (response.redirect_url) { handlePaymentRedirect(response.redirect_url, response.redirect_type); } else { // Show success message document.getElementById('paymentForm').style.display = 'none'; document.getElementById('paymentSuccess').style.display = 'block'; } } else { // Show error message showToast('Kļūda: ' + response.error, 'error'); } }); return false; } // Handle payment redirect function handlePaymentRedirect(redirectUrl, redirectType) { switch (redirectType) { case 'new_window': window.open(redirectUrl, '_blank'); closeModal('paymentModal'); break; case 'iframe': document.getElementById('redirectIframe').src = redirectUrl; closeModal('paymentModal'); document.getElementById('redirectModal').style.display = 'flex'; break; case 'default': default: window.location.href = redirectUrl; break; } } const serpulseCsrfToken = "02a5aa90ec1a48e0772eed0c6a3e7487c20eae5b0e5c1e58c3ada7b176517639"; // Send AJAX request function sendRequest(url, data, callback,need_loading_overlay=true) { // Show loading overlay when request starts if(need_loading_overlay)showLoading(); //console.log("XMLHttpRequest started"); const xhr = new XMLHttpRequest(); xhr.open('POST', url, true); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.setRequestHeader('X-CSRF-Token', serpulseCsrfToken); xhr.onreadystatechange = function() { //console.log("XMLHttpRequest onready fired, readyState:", xhr.readyState); if (xhr.readyState === 4) { // Hide loading overlay when request completes if(need_loading_overlay)hideLoading(); //console.log("Request complete, status:", xhr.status); //console.log("responseText:", xhr.responseText); if (xhr.status === 200) { let is_good = true; let response; // Declare response variable outside try block try { response = JSON.parse(xhr.responseText); } catch (e) { is_good=false; console.error("JSON parse error:", e); callback({status: 'error', error: 'Nederīga atbilde no servera'}); } if(is_good) callback(response); } else { callback({status: 'error', error: 'Servera kļūda: ' + xhr.status}); } } }; xhr.send(JSON.stringify(data)); } // Close redirect modal document.getElementById('redirectModal').querySelector('.close-btn').addEventListener('click', function() { document.getElementById('redirectModal').style.display = 'none'; }); // Mock chart data (in a real implementation, you would use Google Charts) function initCharts() { // This is a placeholder for actual chart implementation //console.log('Charts would be initialized here with Google Charts API'); } // Image modal functionality document.addEventListener('DOMContentLoaded', function() { // Image modal const imgModal = document.getElementById('imgModal'); const modalImg = document.getElementById('modalImg'); const imgCloseBtn = imgModal.querySelector('.close-btn'); // Open image modal document.querySelectorAll('[data-modal="imgModal"]').forEach(img => { img.addEventListener('click', function() { modalImg.src = this.src; imgModal.style.display = 'flex'; }); }); // Close image modal imgCloseBtn.addEventListener('click', function() { imgModal.style.display = 'none'; }); // Close on outside click window.addEventListener('click', function(e) { if (e.target === imgModal) { imgModal.style.display = 'none'; } }); }); </script> <script> //console.log("herei"); // Analysis functionality document.addEventListener('DOMContentLoaded', function() { //console.log("DOMContentLoaded"); const analyzeBtn = document.getElementById('analyzeNowBtn'); const analysisStatus = document.getElementById('analysisStatus'); if (analyzeBtn) { analyzeBtn.addEventListener('click', function() { //console.log("click"); // Show captcha modal showCaptchaModal(); }); } }); function showCaptchaModal() { //console.log("showCaptchaModal"); // Create modal for captcha const modal = document.createElement('div'); modal.className = 'modal'; modal.id = 'captchaModal'; modal.style.display = 'flex'; modal.innerHTML = ` <div class="modal-content"> <span class="close-btn" onclick="closeCaptchaModal()">×</span> <h2 class="modal-title">Apstipriniet, ka neesat robots</h2> <p class="modal-text">Ievadiet tekstu no attēla:</p> <div class="captcha-container"> <img src="/captcha.php?t=` + new Date().getTime() + `" alt="CAPTCHA" class="captcha-image" id="captchaImage"> <button type="button" class="refresh-captcha" onclick="refreshCaptcha()">Atsvaidzināt kodu</button> <input type="text" class="captcha-input" id="captchaInput" placeholder="Ievadiet kodu" maxlength="6"> </div> <button class="cta-button" onclick="submitAnalysis()" style="margin-top: 1rem;">Iesniedziet analīzei</button> </div> `; document.body.appendChild(modal); } function closeCaptchaModal() { const modal = document.getElementById('captchaModal'); if (modal) { modal.remove(); } } function refreshCaptcha() { const captchaImage = document.getElementById('captchaImage'); if (captchaImage) { // Add timestamp to prevent caching captchaImage.src = '/captcha.php?t=' + new Date().getTime(); } } function submitAnalysis() { const captchaInput = document.getElementById('captchaInput'); const captchaCode = captchaInput ? captchaInput.value.trim() : ''; const analysisStatus = document.getElementById('analysisStatus'); if (!captchaCode) { showToast('Lūdzu, ievadiet kodu no attēla', 'error'); return; } // Show loading state analysisStatus.textContent = 'Notiek pieprasījuma sūtīšana...'; analysisStatus.className = 'analysis-status'; analysisStatus.style.display = 'block'; // Prepare data for API request type = "none"; if(document.getElementById('domain_name')){ type = "domain_analysis"; sendData = document.getElementById('domain_name').value; } if(document.getElementById('phrase')){ type = "phrase_analysis"; sendData = document.getElementById('phrase').value; } if(type=="none"){ // Show error message closeCaptchaModal(); analysisStatus.textContent = 'Kļūda: tipa nav'; analysisStatus.className = 'analysis-status error'; analysisStatus.style.display = 'block'; return false; } const data = { type: type, data: sendData, captcha_code: captchaCode }; // Send request to API sendRequest('/ajax/', data, function(response) { // Close captcha modal closeCaptchaModal(); if (response.status === 'ok') { // Show success message analysisStatus.textContent = 'Jūsu pieprasījums ir nosūtīts, lūdzu, uzgaidiet domēna verifikāciju'; analysisStatus.className = 'analysis-status success'; } else { // Show error message analysisStatus.textContent = 'Kļūda: ' + response.error; analysisStatus.className = 'analysis-status error'; // Refresh captcha on error if (response.refresh_captcha) { setTimeout(refreshCaptcha, 500); } } analysisStatus.style.display = 'block'; // Clear captcha input if (captchaInput) { captchaInput.value = ''; } }); } </script> <script> // Full screenshot functionality function openFullScreenshot(src) { const modal = document.getElementById('fullScreenshotModal'); const img = document.getElementById('fullScreenshotImg'); img.src = src; modal.style.display = 'flex'; // Prevent body scroll when modal is open document.body.style.overflow = 'hidden'; } function closeFullScreenshot() { const modal = document.getElementById('fullScreenshotModal'); modal.style.display = 'none'; // Restore body scroll document.body.style.overflow = 'auto'; } function downloadScreenshot() { const img = document.getElementById('fullScreenshotImg'); const link = document.createElement('a'); link.download = `screenshot-${document.getElementById('domain_name').value}-${new Date().getTime()}.jpg`; link.href = img.src; link.click(); } // Close modal on outside click document.addEventListener('click', function(e) { const modal = document.getElementById('fullScreenshotModal'); if (e.target === modal) { closeFullScreenshot(); } }); // Close modal on Escape key document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { closeFullScreenshot(); } }); </script> <script> // Unified authentication controller. All user-visible source strings are English and translated server-side. let telegramStatusInterval = null; let telegramTimerInterval = null; let qrcodeInstance = null; window.telegramBotUrl = null; function authText(key) { const messages = { registrationVerification: 'Konts izveidots. Pirms pierakstīšanās pārbaudiet savu e-pastu un noklikšķiniet uz verifikācijas saites.', loginSuccess: 'Veiksmīgi pierakstījies.', emailVerified: 'E-pasts pārbaudīts. Jūsu konts ir aktīvs un esat pierakstījies.', emailTelegramPending: 'E-pasts pārbaudīts. Pabeidziet telegrammas verifikāciju, lai aktivizētu savu kontu.', emailVerificationFailed: 'Šī e-pasta verifikācijas saite nav derīga, vai tai ir beidzies derīguma termiņš.', googleSuccess: 'Pierakstījies ar Google.', githubSuccess: 'Pierakstījies, izmantojot GitHub.', oauthCancelled: 'Ārējā pierakstīšanās tika atcelta.', oauthFailed: 'Ārējā pierakstīšanās neizdevās. Lūdzu, mēģiniet vēlreiz.', telegramVerifiedEmailPending: 'Telegrammas pārbaude ir pabeigta. Pārbaudiet savu e-pastu un noklikšķiniet uz verifikācijas saites, lai aktivizētu savu kontu.', telegramRegistrationComplete: 'Reģistrācija pabeigta. Tagad esat pierakstījies.', telegramLoginSuccess: 'Pierakstījies ar Telegram.', invalidResponse: 'Nederīga atbilde no servera' }; return messages[key] || key; } function startOAuth(provider) { if (!['google', 'github'].includes(provider)) { showToast('Neatbalstīts pierakstīšanās nodrošinātājs.', 'error'); return; } window.location.href = '/auth/' + provider + '.php?lang=' + encodeURIComponent(window.currentLang || 'en'); } function showEmailVerificationModal(email, message) { const normalizedEmail = (email || '').trim().toLowerCase(); if (normalizedEmail) localStorage.setItem('pending_verification_email', normalizedEmail); const address = document.getElementById('emailVerifyAddress'); const messageEl = document.getElementById('emailVerifyMessage'); if (address) address.textContent = normalizedEmail; if (messageEl) messageEl.textContent = message || 'Pārbaudiet savu iesūtni un noklikšķiniet uz verifikācijas saites, ko mēs jums nosūtījām. Jūs nevarat pierakstīties ar paroli, kamēr jūsu e-pasts nav apstiprināts.'; const modal = document.getElementById('emailVerifyModal'); if (modal) modal.style.display = 'flex'; } function closeEmailVerifyModal() { const modal = document.getElementById('emailVerifyModal'); if (modal) modal.style.display = 'none'; } function resendEmailVerification() { const email = (localStorage.getItem('pending_verification_email') || '').trim().toLowerCase(); if (!email) { showToast('Vēlreiz ievadiet savu e-pastu, lai atkārtoti nosūtītu verifikācijas ziņojumu.', 'error'); closeEmailVerifyModal(); return; } const button = document.getElementById('resendEmailBtn'); if (button) button.disabled = true; sendRequest('/ajax/', {type: 'resend_email_verification', email: email}, function(response) { if (button) button.disabled = false; if (response.status === 'ok') showToast(response.message, 'success'); else showToast(response.error || 'Šobrīd nevarējām nosūtīt verifikācijas e-pasta ziņojumu. Lūdzu, vēlāk mēģiniet vēlreiz.', 'error'); }); } function processLogin() { const email = document.getElementById('loginEmail').value.trim().toLowerCase(); const password = document.getElementById('loginPassword').value; clearErrors(['loginEmail', 'loginPassword']); let hasErrors = false; if (!email) { showError('loginEmail', 'Lūdzu, ievadiet savu e-pastu'); hasErrors = true; } else if (!/\S+@\S+\.\S+/.test(email)) { showError('loginEmail', 'Lūdzu, ievadiet derīgu e-pasta adresi'); hasErrors = true; } if (!password) { showError('loginPassword', 'Lūdzu, ievadiet savu paroli'); hasErrors = true; } if (hasErrors) return; sendRequest('/ajax/', {type: 'login', email: email, password: password}, function(response) { if (response.status === 'ok') { closeModal('authModal'); showToast(response.message || authText('loginSuccess'), 'success'); window.setTimeout(function(){ window.location.href = '/' + window.currentLang + '/profile/'; }, 250); return; } if (response.status === 'verification_required') { closeModal('authModal'); showEmailVerificationModal(response.email || email, response.message); showToast(response.message, 'info'); return; } showError('loginPassword', response.error || 'Nederīgs e-pasts vai parole.'); }); } function processRegistration() { const name = document.getElementById('registerName').value.trim(); const email = document.getElementById('registerEmail').value.trim().toLowerCase(); const password = document.getElementById('registerPassword').value; const confirmPassword = document.getElementById('registerConfirmPassword').value; clearErrors(['registerName', 'registerEmail', 'registerPassword', 'registerConfirmPassword']); let hasErrors = false; if (!name) { showError('registerName', 'Lūdzu, ievadiet savu vārdu'); hasErrors = true; } if (!email) { showError('registerEmail', 'Lūdzu, ievadiet savu e-pastu'); hasErrors = true; } else if (!/\S+@\S+\.\S+/.test(email)) { showError('registerEmail', 'Lūdzu, ievadiet derīgu e-pasta adresi'); hasErrors = true; } if (!password) { showError('registerPassword', 'Lūdzu, izveidojiet paroli'); hasErrors = true; } else if (password.length < 8) { showError('registerPassword', 'Parolei ir jābūt vismaz 8 rakstzīmēm'); hasErrors = true; } if (!confirmPassword) { showError('registerConfirmPassword', 'Lūdzu, apstipriniet savu paroli'); hasErrors = true; } else if (password !== confirmPassword) { showError('registerConfirmPassword', 'Paroles nesakrīt'); hasErrors = true; } if (hasErrors) return; sendRequest('/ajax/', {type: 'registration', name: name, email: email, password: password}, function(response) { if (response.status === 'verification_required') { localStorage.setItem('pending_verification_email', response.email || email); closeModal('authModal'); showEmailVerificationModal(response.email || email, response.message || authText('registrationVerification')); showToast(response.message || authText('registrationVerification'), response.email_sent === false ? 'info' : 'success'); return; } if (response.status === 'ok') { showToast(response.message || authText('registrationVerification'), 'success'); return; } showToast(response.error || 'Reģistrāciju nevarēja pabeigt. Lūdzu, mēģiniet vēlreiz.', 'error'); }); } function clearRegistrationForm() { ['registerName','registerEmail','registerPassword','registerConfirmPassword'].forEach(function(id){ const el=document.getElementById(id); if (el) el.value=''; }); clearErrors(['registerName','registerEmail','registerPassword','registerConfirmPassword']); } function generateQRCode(url) { const container = document.getElementById('qrcode'); if (!container) return; container.innerHTML = ''; if (typeof QRCode === 'undefined') return; qrcodeInstance = new QRCode(container, {text: url, width: 200, height: 200, correctLevel: QRCode.CorrectLevel.M}); } function openTelegramBot() { if (window.telegramBotUrl) window.open(window.telegramBotUrl, '_blank', 'noopener'); } function refreshTelegramQR() { if (window.telegramBotUrl) generateQRCode(window.telegramBotUrl); } function clearTelegramTimers() { if (telegramTimerInterval) { clearInterval(telegramTimerInterval); telegramTimerInterval = null; } if (telegramStatusInterval) { clearInterval(telegramStatusInterval); telegramStatusInterval = null; } } function startTelegramTimer(duration) { clearInterval(telegramTimerInterval); let remaining = Math.max(0, parseInt(duration || 300, 10)); const timer = document.getElementById('timer'); function render() { if (!timer) return; const m = Math.floor(remaining / 60), s = remaining % 60; timer.textContent = String(m).padStart(2,'0') + ':' + String(s).padStart(2,'0'); } render(); telegramTimerInterval = setInterval(function(){ remaining -= 1; render(); if (remaining < 0) { clearTelegramTimers(); showToast('Telegrammas verifikācijas saites termiņš ir beidzies. Lūdzu, sāciet vēlreiz.', 'error'); } }, 1000); } function showTelegramVerifyModal(botUsername, telegramToken, deepLink, expiresRemaining) { window.telegramBotUrl = deepLink || ('https://t.me/' + botUsername + '?start=' + encodeURIComponent(telegramToken)); const title = document.querySelector('#telegramVerifyModal .modal-title'); const text = document.getElementById('telegramModalText'); if (title) title.textContent = 'Pabeigt reģistrāciju Telegram'; if (text) text.innerHTML = 'Telegram tika atvērta jaunā cilnē.<br>Kopīgojiet savu tālruņa numuru ar robotu un pēc tam atgriezieties šeit. Nepieciešama arī e-pasta pārbaude.'; generateQRCode(window.telegramBotUrl); startTelegramTimer(expiresRemaining || 600); const modal = document.getElementById('telegramVerifyModal'); if (modal) modal.style.display='flex'; window.open(window.telegramBotUrl, '_blank', 'noopener'); } function closeTelegramVerifyModal() { clearTelegramTimers(); const modal = document.getElementById('telegramVerifyModal'); if (modal) modal.style.display='none'; } function startTelegramRegistration() { const name = document.getElementById('registerName').value.trim(); const email = document.getElementById('registerEmail').value.trim().toLowerCase(); clearErrors(['registerName','registerEmail']); let hasErrors=false; if (!name) { showError('registerName','Lūdzu, ievadiet savu vārdu'); hasErrors=true; } if (!email) { showError('registerEmail','Lūdzu, ievadiet savu e-pastu'); hasErrors=true; } else if (!/\S+@\S+\.\S+/.test(email)) { showError('registerEmail','Lūdzu, ievadiet derīgu e-pasta adresi'); hasErrors=true; } if (hasErrors) return; localStorage.setItem('pending_verification_email', email); sendRequest('/ajax/', {type:'telegram_registration_start',name:name,email:email}, function(response){ if (response.status === 'continue_email_verification') { closeModal('authModal'); showEmailVerificationModal(email, 'Šim kontam Telegram jau ir verificēta. Lai aktivizētu kontu, apstipriniet savu e-pastu.'); showToast('Joprojām ir nepieciešama e-pasta verifikācija.', 'info'); return; } if (response.status !== 'ok') { showToast(response.error || 'Telegrammas reģistrāciju nevarēja sākt.','error'); return; } localStorage.setItem('current_user_token', response.user_token); closeModal('authModal'); if (response.email_sent === false) { showToast(response.message || 'Verifikācijas e-pastu nevarēja nosūtīt. Lūdzu, izmantojiet Atkārtoti nosūtīt verifikācijas e-pastu.','info'); } showTelegramVerifyModal(response.bot_username,response.telegram_token,response.deep_link,response.telegram_token_expires_remaining); startTelegramRegistrationStatusCheck(response.user_token, email); }); } function startTelegramRegistrationStatusCheck(userToken, email) { clearInterval(telegramStatusInterval); telegramStatusInterval=setInterval(function(){ checkTelegramVerificationStatus(userToken,email); }, 4000); checkTelegramVerificationStatus(userToken,email); } function checkTelegramVerificationStatus(userToken, email) { sendRequest('/ajax/', {type:'check_telegram_verification',user_token:userToken}, function(response){ if (response.status !== 'ok') return; if (response.account_verified) { clearTelegramTimers(); completeRegistration(); return; } if (response.telegram_verified && !response.email_verified) { clearTelegramTimers(); closeTelegramVerifyModal(); showEmailVerificationModal(email, authText('telegramVerifiedEmailPending')); showToast(authText('telegramVerifiedEmailPending'),'info'); } }, false); } function completeRegistration() { const token=localStorage.getItem('current_user_token') || ''; if (!token) return; sendRequest('/ajax/', {type:'complete_registration',user_token:token}, function(response){ if (response.status !== 'ok') { showToast(response.error || 'Reģistrāciju nevarēja pabeigt.','error'); return; } localStorage.removeItem('current_user_token'); localStorage.removeItem('pending_verification_email'); closeTelegramVerifyModal(); closeEmailVerifyModal(); showToast(response.message || authText('telegramRegistrationComplete'),'success'); window.setTimeout(function(){window.location.href='/' + window.currentLang + '/profile/';},250); }); } function loginWithTelegram() { const email=document.getElementById('loginEmail').value.trim().toLowerCase(); clearErrors(['loginEmail']); if (!email) { showError('loginEmail','Lūdzu, ievadiet savu e-pastu'); return; } if (!/\S+@\S+\.\S+/.test(email)) { showError('loginEmail','Lūdzu, ievadiet derīgu e-pasta adresi'); return; } generateTelegramLoginLink(email); } function generateTelegramLoginLink(email) { sendRequest('/ajax/', {type:'generate_telegram_login_link',email:email}, function(response){ if (response.status !== 'ok') { showToast(response.error || 'Nevar sākt Telegram pieteikšanos','error'); return; } localStorage.setItem('current_user_token',response.user_token); closeModal('authModal'); showTelegramLoginModal(response.bot_username,response.deep_link,response.telegram_token_expires_remaining); }); } function showTelegramLoginModal(botUsername,deepLink,expiresRemaining) { window.telegramBotUrl=deepLink; const title=document.querySelector('#telegramVerifyModal .modal-title'); const text=document.getElementById('telegramModalText'); if (title) title.textContent='Piesakieties caur telegrammu'; if (text) text.innerHTML='Atveriet Telegram robotu, lai saņemtu pierakstīšanās kodu, un pēc tam ievadiet kodu šajā vietnē.'; generateQRCode(window.telegramBotUrl); startTelegramTimer(expiresRemaining || 300); const modal=document.getElementById('telegramVerifyModal'); if (modal) modal.style.display='flex'; window.open(window.telegramBotUrl,'_blank','noopener'); startTelegramLoginStatusCheck(); } function startTelegramLoginStatusCheck() { const token=localStorage.getItem('current_user_token') || ''; clearInterval(telegramStatusInterval); telegramStatusInterval=setInterval(function(){checkTelegramLoginStatus(token);},3000); checkTelegramLoginStatus(token); } function checkTelegramLoginStatus(userToken) { if (!userToken) return; sendRequest('/ajax/', {type:'check_telegram_login_status',user_token:userToken}, function(response){ if (response.status==='ok' && response.login_code_sended) { clearTelegramTimers(); closeTelegramVerifyModal(); const codeModal=document.getElementById('telegramCodeModal'); if (codeModal) codeModal.style.display='flex'; startLoginCodeTimer(300); } },false); } function startLoginCodeTimer(duration) { let remaining=parseInt(duration||300,10); const timer=document.getElementById('loginTimer'); if (window.loginCodeTimer) clearInterval(window.loginCodeTimer); window.loginCodeTimer=setInterval(function(){ const m=Math.max(0,Math.floor(remaining/60)), s=Math.max(0,remaining%60); if (timer) timer.textContent=String(m).padStart(2,'0')+':'+String(s).padStart(2,'0'); remaining--; if (remaining<0) { clearInterval(window.loginCodeTimer); showToast('Koda derīguma termiņš beidzies. Lūdzu, sāciet no jauna.','error'); } },1000); } function verifyTelegramLoginCode() { const token=localStorage.getItem('current_user_token') || ''; const input=document.getElementById('telegramLoginCode'); const code=input ? input.value.trim() : ''; clearErrors(['telegramLoginCode']); if (!/^\\d{7}$/.test(code)) { showError('telegramLoginCode','Kodā ir jābūt 7 cipariem'); return; } sendRequest('/ajax/', {type:'verify_telegram_login_code',user_token:token,verify_code:code}, function(response){ if (response.status!=='ok') { showError('telegramLoginCode',response.error || 'Slikts kods vai beidzies derīguma termiņš'); return; } if (window.loginCodeTimer) clearInterval(window.loginCodeTimer); localStorage.removeItem('current_user_token'); closeModal('telegramCodeModal'); showToast(response.message || authText('telegramLoginSuccess'),'success'); window.setTimeout(function(){window.location.href='/' + window.currentLang + '/profile/';},250); }); } // Old registration-status probing is intentionally disabled: it leaked account state and duplicated the new verification flow. function checkRegistrationStatus() { return; } function closeVisibleAuthModal() { for (const id of ['telegramCodeModal','telegramVerifyModal','emailVerifyModal','authModal']) { const modal=document.getElementById(id); if (!modal || modal.style.display !== 'flex') continue; if (id === 'telegramVerifyModal') closeTelegramVerifyModal(); else if (id === 'emailVerifyModal') closeEmailVerifyModal(); else closeModal(id); return; } } document.addEventListener('click', function(event){ const target=event.target; if (!(target instanceof HTMLElement) || !target.classList.contains('modal')) return; const id=target.id; if (!['telegramCodeModal','telegramVerifyModal','emailVerifyModal'].includes(id)) return; if (id === 'telegramVerifyModal') closeTelegramVerifyModal(); else if (id === 'emailVerifyModal') closeEmailVerifyModal(); else closeModal(id); }); document.addEventListener('keydown', function(event){ if (event.key === 'Escape') closeVisibleAuthModal(); }); function handleAuthNotice() { const url=new URL(window.location.href); const notice=url.searchParams.get('auth'); if (!notice) return; const map={ email_verified:[authText('emailVerified'),'success'], email_verified_telegram_pending:[authText('emailTelegramPending'),'info'], email_verification_failed:[authText('emailVerificationFailed'),'error'], google_success:[authText('googleSuccess'),'success'], github_success:[authText('githubSuccess'),'success'], oauth_cancelled:[authText('oauthCancelled'),'info'], oauth_failed:[authText('oauthFailed'),'error'] }; if (map[notice]) showToast(map[notice][0],map[notice][1]); url.searchParams.delete('auth'); window.history.replaceState({},document.title,url.pathname+url.search+url.hash); } document.addEventListener('DOMContentLoaded',handleAuthNotice); </script> <!-- Add this JavaScript before closing body tag --> <script> // Animation on scroll document.addEventListener('DOMContentLoaded', function() { const fadeElements = document.querySelectorAll('.fade-in'); const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('visible'); } }); }, { threshold: 0.1 }); fadeElements.forEach(element => { observer.observe(element); }); // Add click handlers for project CTAs document.querySelectorAll('.project-cta').forEach(button => { button.addEventListener('click', function() { const projectTitle = this.closest('.project-card').querySelector('.project-title').textContent; // In production, this would navigate to the appropriate page }); }); }); </script> <script> // Cookie consent management (function() { // Configuration const COOKIE_CONSENT_KEY = 'serpuls_cookie_consent'; const COOKIE_EXPIRY_DAYS = 365; // Create cookie consent banner if not already accepted function initCookieConsent() { // Check if user has already made a choice const consent = getCookieConsent(); if (consent !== null) { // User already made a choice, apply preferences applyCookiePreferences(consent); return; } // Create banner createCookieBanner(); } // Create the cookie banner HTML function createCookieBanner() { const banner = document.createElement('div'); banner.id = 'cookie-consent-banner'; banner.style.cssText = ` position: fixed; bottom: 0; left: 0; right: 0; background: white; box-shadow: 0 -4px 20px rgba(0,0,0,0.15); padding: 1.5rem; z-index: 9999; border-top: 3px solid var(--primary, #4361ee); animation: slideUp 0.5s ease; `; // Add animation style if not exists if (!document.getElementById('cookie-animation-style')) { const style = document.createElement('style'); style.id = 'cookie-animation-style'; style.textContent = ` @keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } } `; document.head.appendChild(style); } banner.innerHTML = ` <div style="max-width: 1200px; margin: 0 auto; display: flex; flex-wrap: wrap; gap: 2rem; align-items: center; justify-content: space-between;"> <div style="flex: 2; min-width: 280px;"> <h3 style="margin: 0 0 0.5rem 0; color: var(--dark, #212529); font-size: 1.25rem;">🍪 Sīkdatņu piekrišana</h3> <p style="margin: 0; color: var(--gray, #6c757d); line-height: 1.5;"> Mēs izmantojam sīkfailus, lai uzlabotu jūsu pārlūkošanas pieredzi, apkalpotu personalizētu saturu un analizētu mūsu trafiku. Noklikšķinot uz Pieņemt visu, jūs piekrītat sīkdatņu izmantošanai. Izlasiet mūsu <a href="/en/cookie/" style="color: var(--primary, #4361ee); text-decoration: underline;">Sīkdatņu politika</a> un <a href="/en/privacy/" style="color: var(--primary, #4361ee); text-decoration: underline;">Privātuma politika</a>. </p> </div> <div style="display: flex; gap: 1rem; flex-wrap: wrap; align-items: center;"> <button id="cookie-accept-all" style="padding: 0.75rem 1.5rem; background: linear-gradient(135deg, var(--primary, #4361ee), var(--secondary, #7209b7)); color: white; border: none; border-radius: var(--border-radius, 8px); font-weight: 600; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 6px rgba(67,97,238,0.3);"> Pieņemt visu </button> <button id="cookie-accept-essential" style="padding: 0.75rem 1.5rem; background: white; color: var(--dark, #212529); border: 1px solid var(--gray, #6c757d); border-radius: var(--border-radius, 8px); font-weight: 600; cursor: pointer; transition: all 0.3s ease;"> Tikai būtiski </button> <button id="cookie-settings" style="padding: 0.75rem 1.5rem; background: transparent; color: var(--primary, #4361ee); border: none; font-weight: 600; cursor: pointer; text-decoration: underline;"> Pielāgot </button> </div> </div> `; document.body.appendChild(banner); // Add event listeners document.getElementById('cookie-accept-all').addEventListener('click', function() { acceptAllCookies(); }); document.getElementById('cookie-accept-essential').addEventListener('click', function() { acceptEssentialCookies(); }); document.getElementById('cookie-settings').addEventListener('click', function() { showCookieSettings(); }); } // Show cookie settings modal function showCookieSettings() { // Remove existing modal if any const existingModal = document.getElementById('cookie-settings-modal'); if (existingModal) existingModal.remove(); const modal = document.createElement('div'); modal.id = 'cookie-settings-modal'; modal.style.cssText = ` position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 10000; animation: fadeIn 0.3s ease; `; modal.innerHTML = ` <div style="background: white; border-radius: var(--border-radius, 8px); max-width: 500px; width: 90%; max-height: 80vh; overflow-y: auto; box-shadow: 0 10px 25px rgba(0,0,0,0.2);"> <div style="padding: 1.5rem; border-bottom: 1px solid #e9ecef;"> <h3 style="margin: 0; color: var(--dark, #212529);">Sīkfailu preferences</h3> </div> <div style="padding: 1.5rem;"> <p style="color: var(--gray, #6c757d); margin-bottom: 1.5rem;">Izvēlieties, kuras sīkdatnes atļaujat. Šos iestatījumus varat mainīt jebkurā laikā.</p> <div style="margin-bottom: 1rem; padding: 1rem; background: #f8f9fa; border-radius: var(--border-radius, 8px);"> <label style="display: flex; align-items: center; gap: 0.75rem; cursor: not-allowed;"> <input type="checkbox" checked disabled style="width: 18px; height: 18px;"> <div> <strong style="color: var(--dark, #212529);">Būtiski sīkfaili</strong> <p style="margin: 0.25rem 0 0; font-size: 0.9rem; color: var(--gray, #6c757d);">Nepieciešams, lai vietne darbotos. Nevar atspējot.</p> </div> </label> </div> <div style="margin-bottom: 1rem; padding: 1rem; background: #f8f9fa; border-radius: var(--border-radius, 8px);"> <label style="display: flex; align-items: center; gap: 0.75rem; cursor: pointer;"> <input type="checkbox" id="cookie-pref-analytics" checked style="width: 18px; height: 18px;"> <div> <strong style="color: var(--dark, #212529);">Analytics sīkfaili</strong> <p style="margin: 0.25rem 0 0; font-size: 0.9rem; color: var(--gray, #6c757d);">Palīdziet mums saprast, kā apmeklētāji mijiedarbojas ar mūsu vietni.</p> </div> </label> </div> <div style="margin-bottom: 1rem; padding: 1rem; background: #f8f9fa; border-radius: var(--border-radius, 8px);"> <label style="display: flex; align-items: center; gap: 0.75rem; cursor: pointer;"> <input type="checkbox" id="cookie-pref-functional" checked style="width: 18px; height: 18px;"> <div> <strong style="color: var(--dark, #212529);">Funkcionālās sīkdatnes</strong> <p style="margin: 0.25rem 0 0; font-size: 0.9rem; color: var(--gray, #6c757d);">Atcerieties savas preferences un iestatījumus.</p> </div> </label> </div> <div style="margin-bottom: 1rem; padding: 1rem; background: #f8f9fa; border-radius: var(--border-radius, 8px);"> <label style="display: flex; align-items: center; gap: 0.75rem; cursor: pointer;"> <input type="checkbox" id="cookie-pref-targeting" checked style="width: 18px; height: 18px;"> <div> <strong style="color: var(--dark, #212529);">Mērķa sīkfaili</strong> <p style="margin: 0.25rem 0 0; font-size: 0.9rem; color: var(--gray, #6c757d);">Izmanto atbilstoša satura un reklāmu piegādei.</p> </div> </label> </div> </div> <div style="padding: 1.5rem; border-top: 1px solid #e9ecef; display: flex; gap: 1rem; justify-content: flex-end;"> <button id="cookie-save-preferences" style="padding: 0.75rem 1.5rem; background: linear-gradient(135deg, var(--primary, #4361ee), var(--secondary, #7209b7)); color: white; border: none; border-radius: var(--border-radius, 8px); font-weight: 600; cursor: pointer;"> Saglabāt preferences </button> <button id="cookie-close-modal" style="padding: 0.75rem 1.5rem; background: white; color: var(--dark, #212529); border: 1px solid var(--gray, #6c757d); border-radius: var(--border-radius, 8px); font-weight: 600; cursor: pointer;"> Atcelt </button> </div> </div> `; document.body.appendChild(modal); // Close modal handlers document.getElementById('cookie-close-modal').addEventListener('click', function() { modal.remove(); }); document.getElementById('cookie-save-preferences').addEventListener('click', function() { const preferences = { essential: true, // Always true analytics: document.getElementById('cookie-pref-analytics').checked, functional: document.getElementById('cookie-pref-functional').checked, targeting: document.getElementById('cookie-pref-targeting').checked }; saveCookiePreferences(preferences); modal.remove(); removeCookieBanner(); }); // Click outside to close modal.addEventListener('click', function(e) { if (e.target === modal) { modal.remove(); } }); } // Accept all cookies function acceptAllCookies() { const preferences = { essential: true, analytics: true, functional: true, targeting: true }; saveCookiePreferences(preferences); removeCookieBanner(); } // Accept only essential cookies function acceptEssentialCookies() { const preferences = { essential: true, analytics: false, functional: false, targeting: false }; saveCookiePreferences(preferences); removeCookieBanner(); } // Save cookie preferences function saveCookiePreferences(preferences) { // Save to cookie const expiryDate = new Date(); expiryDate.setDate(expiryDate.getDate() + COOKIE_EXPIRY_DAYS); const cookieValue = JSON.stringify(preferences); document.cookie = `${COOKIE_CONSENT_KEY}=${encodeURIComponent(cookieValue)}; expires=${expiryDate.toUTCString()}; path=/; SameSite=Lax`; // Apply preferences applyCookiePreferences(preferences); // Store in localStorage for quick access localStorage.setItem(COOKIE_CONSENT_KEY, cookieValue); // Optional: send event to analytics if (typeof window.gtag !== 'undefined' && preferences.analytics) { window.gtag('consent', 'update', { 'analytics_storage': 'granted' }); } } // Get cookie consent from cookie or localStorage function getCookieConsent() { // Try to get from cookie first const match = document.cookie.match(new RegExp('(^| )' + COOKIE_CONSENT_KEY + '=([^;]+)')); if (match) { try { return JSON.parse(decodeURIComponent(match[2])); } catch (e) { console.error('Kļūda parsējot sīkfailu piekrišanu:', e); } } // Try localStorage const stored = localStorage.getItem(COOKIE_CONSENT_KEY); if (stored) { try { return JSON.parse(stored); } catch (e) { console.error('Parsējot vietējās krātuves piekrišanu, radās kļūda:', e); } } return null; } // Apply cookie preferences (enable/disable features) function applyCookiePreferences(preferences) { if (!preferences) return; // Example: Disable analytics if not consented if (!preferences.analytics) { // Disable Google Analytics if present if (typeof window.gtag !== 'undefined') { window.gtag('consent', 'default', { 'analytics_storage': 'denied' }); } // Optionally remove existing analytics cookies // This is handled by the analytics script itself usually } // Disable targeting cookies if (!preferences.targeting) { // Disable ad-related tracking // Remove Facebook pixel, etc. } // Store preferences in data attribute for other scripts to check document.documentElement.setAttribute('data-cookie-consent', JSON.stringify(preferences)); // Dispatch event for other scripts to react window.dispatchEvent(new CustomEvent('cookieConsentChanged', { detail: preferences })); } // Remove cookie banner function removeCookieBanner() { const banner = document.getElementById('cookie-consent-banner'); if (banner) { banner.style.animation = 'slideDown 0.5s ease forwards'; setTimeout(() => { if (banner.parentNode) banner.remove(); }, 500); // Add slideDown animation if not exists if (!document.getElementById('cookie-animation-slidedown')) { const style = document.createElement('style'); style.id = 'cookie-animation-slidedown'; style.textContent = ` @keyframes slideDown { from { transform: translateY(0); } to { transform: translateY(100%); } } `; document.head.appendChild(style); } } } // Add a floating button to reopen cookie settings (optional) function addCookieSettingsButton() { const btn = document.createElement('button'); btn.id = 'cookie-settings-button'; btn.innerHTML = '🍪'; btn.setAttribute('aria-label', 'Sīkfailu iestatījumi'); btn.style.cssText = ` position: fixed; bottom: 20px; left: 20px; width: 48px; height: 48px; border-radius: 50%; background: white; border: 1px solid var(--gray, #6c757d); box-shadow: var(--box-shadow, 0 4px 6px rgba(0,0,0,0.1)); cursor: pointer; font-size: 1.2rem; display: flex; align-items: center; justify-content: center; z-index: 9998; transition: var(--transition, all 0.3s ease); opacity: 0.8; `; btn.addEventListener('mouseenter', function() { this.style.opacity = '1'; this.style.transform = 'scale(1.1)'; }); btn.addEventListener('mouseleave', function() { this.style.opacity = '0.8'; this.style.transform = 'scale(1)'; }); btn.addEventListener('click', function() { showCookieSettings(); }); document.body.appendChild(btn); } // Initialize on DOM ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initCookieConsent); } else { initCookieConsent(); } // Optional: Add settings button after consent is given window.addEventListener('cookieConsentChanged', function() { // Only show settings button if not already present if (!document.getElementById('cookie-settings-button')) { //addCookieSettingsButton(); } }); // If consent already exists, add settings button const existingConsent = getCookieConsent(); if (existingConsent && !document.getElementById('cookie-settings-button')) { document.addEventListener('DOMContentLoaded', function() { //addCookieSettingsButton(); }); } })(); </script> </body> </html>