Compare commits

..

18 Commits

Author SHA1 Message Date
Your Name a89d6e1a63 feat(ui): add new sponsor and quote image
Add a new sponsor link to index and o-nas pages with corresponding logo, and include a new quote image.
2026-06-01 15:56:16 +02:00
Your Name 60a4b82931 feat(ui): add new sponsor and update text content
Add a new sponsor logo and link for NSA to the index and o-nas pages.
Update the header text in o-nas.html to reflect winner status.
2026-05-30 09:33:58 +02:00
Your Name efa35518ab feat(ui): update sponsor logos and links
Replace the alpacar.pl sponsor with kovosteel.cz and gracla.cz in index.html and o-nas.html, and add new sponsor image assets.
2026-05-25 17:41:17 +02:00
Tomas Dvorak cc6841e723 feat(backend): implement fallback API for club data retrieval
Add a fallback mechanism to use an alternative base URL and club ID
when the primary API request fails. This ensures data resilience by
attempting to fetch club details and standings from a secondary source
using a slug-based lookup.

The implementation also updates the logic to use the active club ID
(either primary or fallback) when overriding logo URLs in match
details and table standings.
2026-05-13 12:05:20 +02:00
Tomas Dvorak 4c904a1546 fix(backend): improve video resilience and add blog ordering validation
Implement fallback mechanisms for YouTube video data and add startup
validation for blog post ordering.

- Add `loadVideosJSON` to persist and reload video data from disk.
- Update `refreshVideos` to retain existing local videos if the YouTube
  API returns an empty response.
- Add `validateBlogOrdering` to perform a health check on blog post
  sequence during startup.
- Call video loading and blog validation in `main`.
2026-05-11 15:30:24 +02:00
Tomas Dvorak 76c447a395 fix(ui): add defensive sorting for blog posts
Implement client-side sorting for blog post lists to ensure they are
displayed in descending order by numeric ID. This prevents issues
where API response ordering or file modification timestamps might
cause older posts to appear newer than recent ones.

Also add backend tests to verify blog ordering logic.
2026-05-11 13:03:04 +02:00
Tomas Dvorak a6b47de1a4 refactor(backend): improve blog canonical ID resolution
Refactor the blog listing logic to use a canonical numeric ID when available. This ensures consistent identity and deduplication between numeric and slug-based filenames, and ensures image path resolution uses the correct identifier.
2026-05-11 12:33:26 +02:00
Your Name 2f65bc03e6 rybbit 2026-04-18 14:30:18 +02:00
Your Name ac9930767e new sponsor and fix backend 2026-04-09 15:43:28 +02:00
Tomas Dvorak 4f3164956a Add slug-to-numeric resolution for blog URLs
- Modified blog handler to resolve slugs to numeric files when slug files don't exist
- This allows slug URLs to work without creating duplicate slug files
- Fixes sorting issues while maintaining slug URL compatibility
2026-03-14 11:27:08 +01:00
Tomas Dvorak f8a6abf391 Fix blog sorting to show newest first
- When files have recent timestamps (from setup script), sort by numeric ID
- Higher numeric IDs represent newer blogs
- This ensures proper chronological ordering in admin interface
2026-03-14 11:21:31 +01:00
Tomas Dvorak 45facf7aa0 Fix image paths and remove duplicate slug files
- Remove duplicate slug files that were causing duplicate entries
- Add logic to find corresponding numeric ID for image paths
- This fixes broken images in admin interface for slug-based blogs
2026-03-14 11:19:09 +01:00
Tomas Dvorak c9c322ff95 Fix duplicate blog entries and image paths
- Add deduplication logic to avoid showing same blog twice
- Add extractBlogID function to get correct numeric ID from meta tags
- Use blogID for image paths instead of filename ID
- This fixes duplicate entries in admin interface and broken images
2026-03-14 11:17:49 +01:00
Tomas Dvorak 3a7c1bbcba Fix blog API endpoints and path issues
- Fix listLatestBlogs function to use correct blog directory path
- Add /data/blog-list.json endpoint for frontend blog listing
- Update remoteBlogDir references to use blogDir
- Resolve blog listing and admin interface loading issues
2026-03-14 11:12:40 +01:00
Tomas Dvorak 03b9abd32d fix 2026-03-14 10:52:14 +01:00
Tomas Dvorak 21574a8b30 Add slug support and new admin features 2026-03-14 10:40:04 +01:00
Tomas Dvorak 4773e4cab1 update 2026-02-22 13:09:22 +01:00
Tomas Dvorak 362f55e28a update 2026-02-22 13:01:34 +01:00
99 changed files with 38687 additions and 36056 deletions
+2 -2
View File
@@ -1,3 +1,3 @@
{
"livePreview.defaultPreviewPath": "/ukol.html"
{
"livePreview.defaultPreviewPath": "/ukol.html"
}
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full">
+172
View File
@@ -0,0 +1,172 @@
# Remote Blog Management - Complete Guide
## 🎯 Goal
Remove local blog files and work exclusively with remote server blogs.
## 📋 Options Available
### Option 1: Quick Remove Local Blogs
```bash
# Run this in your bizoni directory
./remove-local-blogs.sh
```
### Option 2: Ubuntu Server Management Script
```bash
# Upload to your Ubuntu server and run
./ubuntu-remote-blogs.sh migrate
```
### Option 3: Backend Configuration (Recommended)
Update backend to work with remote blogs only.
## 🚀 Recommended Deployment Steps
### Step 1: Remove Local Blogs
```bash
cd /home/tdvorak/Desktop/HTML_Projekty/bizoni
./remove-local-blogs.sh
```
### Step 2: Update Backend Configuration
The backend is now configured to work with remote blogs at `/var/www/bizoni/blog`.
You can set the remote path with environment variable:
```bash
export REMOTE_BLOG_DIR="/var/www/bizoni/blog"
```
### Step 3: Deploy Backend to Server
1. Build the updated backend
2. Deploy to your server
3. Set REMOTE_BLOG_DIR environment variable
### Step 4: Run Migration on Server
```bash
# On your Ubuntu server
./ubuntu-remote-blogs.sh migrate
```
## 📁 File Structure After Changes
### Local (Development)
```
bizoni/
├── backend/main.go # Updated for remote blogs
├── admin/new.html # Updated with new fields
├── js/admin-auth.js # Login persistence
├── tools/migrate_slugs.go # Migration tool
├── remove-local-blogs.sh # Local cleanup script
└── ubuntu-remote-blogs.sh # Server management script
```
### Server (Production)
```
/var/www/bizoni/
├── blog/
│ ├── 0000.html # Original numeric files
│ ├── 0001.html
│ ├── jdeme-do-finale.html # New slug files
│ └── 1-zapas-final-score.html
├── img/blog/
│ ├── 0000.png
│ └── 0001.png
└── backend # Updated backend
```
## 🔧 Ubuntu Server Script Usage
### List All Blogs
```bash
./ubuntu-remote-blogs.sh list
```
### Migrate All Blogs to Slugs
```bash
./ubuntu-remote-blogs.sh migrate
```
### Show Blog Info
```bash
./ubuntu-remote-blogs.sh info 0030
```
### Add Slug to Specific Blog
```bash
./ubuntu-remote-blogs.sh add-slug 0030
```
### Create Backup
```bash
./ubuntu-remote-blogs.sh backup
```
## 🌐 URL Structure After Migration
### Before
- `/blog/0030.html`
- `/blog/0001.html`
### After
- `/blog/jdeme-do-finale` (clean URL)
- `/blog/1-zapas-final-score`
- `/blog/0030.html` (still works for backward compatibility)
## ⚠️ Important Notes
1. **Backup First**: Always create backup before migration
2. **Test Locally**: Test backend with REMOTE_BLOG_DIR set to local copy
3. **Deploy Gradually**: Deploy backend first, then run migration
4. **Environment Variables**: Use REMOTE_BLOG_DIR for flexibility
## 🔄 Environment Variables
Set these on your server:
```bash
# Path to remote blog directory
export REMOTE_BLOG_DIR="/var/www/bizoni/blog"
# Port for backend (if needed)
export PORT="8080"
# Static files path
export STATIC_PATH="/var/www/bizoni"
```
## 🚨 Troubleshooting
### Backend Can't Find Blogs
```bash
# Check if directory exists
ls -la /var/www/bizoni/blog
# Set correct path
export REMOTE_BLOG_DIR="/correct/path/to/blogs"
```
### Migration Script Fails
```bash
# Make script executable
chmod +x ubuntu-remote-blogs.sh
# Update paths in script
nano ubuntu-remote-blogs.sh
```
### Permission Issues
```bash
# Fix permissions on server
sudo chown -R www-data:www-data /var/www/bizoni/blog
sudo chmod -R 755 /var/www/bizoni/blog
```
## 📞 Next Steps
1. **Choose your option** (1, 2, or 3)
2. **Remove local blogs** with the provided script
3. **Deploy updated backend** to server
4. **Run migration** on server
5. **Test new URLs** and admin interface
Your blog system will then work entirely with remote server blogs! 🎉
+8 -1
View File
@@ -40,6 +40,7 @@
.kpi .it { background:#f3f4f6; border:1px solid var(--border); border-radius:8px; padding:10px; text-align:center; }
small.code { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; background:#f3f4f6; border:1px solid var(--border); border-radius:6px; padding:2px 6px; }
</style>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="admin-with-sidenav">
<aside class="admin-sidenav">
@@ -233,7 +234,13 @@
s.textContent = 'Načítám…';
const res = await fetch('/api/blog/latest?limit=12');
if (!res.ok) throw new Error('HTTP '+res.status);
const items = await res.json();
let items = await res.json();
// Defensive sort: numeric ID descending ensures newest first regardless of API ordering
items.sort((a,b)=>{
const ai = parseInt(a.id,10); const bi = parseInt(b.id,10);
if (!isNaN(ai) && !isNaN(bi)) return bi-ai;
return (b.id||'').localeCompare(a.id||'');
});
grid.innerHTML='';
if (!Array.isArray(items) || items.length === 0) {
grid.innerHTML = '<div class="muted">Žádné příspěvky.</div>';
+8 -1
View File
@@ -18,6 +18,7 @@
header { display:flex; justify-content: space-between; align-items:center; margin-bottom: 16px; }
.badge { background: #111827; color: #fff; padding: 6px 10px; border-radius: 999px; font-size: 12px; }
</style>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="admin-with-sidenav">
<aside class="admin-sidenav">
@@ -52,7 +53,13 @@
try {
const res = await fetch('/api/blog/latest?limit=12');
if (!res.ok) throw new Error('HTTP '+res.status);
const items = await res.json();
let items = await res.json();
// Defensive sort: numeric ID descending ensures newest first regardless of API ordering
items.sort((a,b)=>{
const ai = parseInt(a.id,10); const bi = parseInt(b.id,10);
if (!isNaN(ai) && !isNaN(bi)) return bi-ai;
return (b.id||'').localeCompare(a.id||'');
});
status.textContent = `Nalezeno: ${items.length}`;
mount.innerHTML = '';
if (!Array.isArray(items) || items.length === 0) {
+114 -4
View File
@@ -32,6 +32,7 @@
<link href="https://cdn.jsdelivr.net/npm/quill@1.3.7/dist/quill.snow.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/quill@1.3.7/dist/quill.min.js"></script>
<script src="../js/admin-auth.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="admin-with-sidenav">
<aside class="admin-sidenav">
@@ -62,6 +63,23 @@
<label for="title">Titulek</label>
<input type="text" id="title" name="title" placeholder="Např. FC Bizoni vyhráli finále" required />
</div>
<div>
<label for="slug">URL slug (použije se v adrese)</label>
<input type="text" id="slug" name="slug" placeholder="napr-fc-bizoni-vyhrali-finale" pattern="[a-z0-9-]+" title="Pouze malá písmena, číslice a pomlčky" />
<div class="muted" style="margin-top:6px">Automaticky se vygeneruje z titulku, pokud nezadáte vlastní.</div>
</div>
<div>
<label for="annotation">Anotace (krátký popis pro SEO a sociální sítě)</label>
<input type="text" id="annotation" name="annotation" placeholder="Krátký popis článku (150-300 znaků)" maxlength="300" />
<div class="muted" style="margin-top:6px">Použije se pro SEO description a při sdílení na sociálních sítích.</div>
</div>
<div>
<label for="content-mode">Způsob zadávání obsahu</label>
<select id="content-mode" name="content-mode" style="width: 100%; padding: 10px; border:1px solid #d1d5db; border-radius: 8px; font-size: 14px;">
<option value="visual">Vizuální editor (Quill)</option>
<option value="html">HTML kód</option>
</select>
</div>
<div>
<label for="categories">Kategorie (oddělené čárkou)</label>
<input type="text" id="categories" name="categories" placeholder="Zápasy, O nás" />
@@ -87,7 +105,12 @@
</div>
<div>
<label for="editor">Obsah (vizuální editor)</label>
<div id="editor"></div>
<div id="visual-editor-wrapper">
<div id="editor"></div>
</div>
<div id="html-editor-wrapper" style="display: none;">
<textarea id="html-content" name="html-content" rows="12" placeholder="Zadejte HTML kód obsahu..." style="width: 100%; padding: 10px; border:1px solid #d1d5db; border-radius: 8px; font-size: 14px; font-family: 'Courier New', monospace;"></textarea>
</div>
<!-- Hidden textarea to submit HTML (kept focusable-safe by moving offscreen) -->
<textarea id="content" name="content" rows="12" style="position:absolute; left:-10000px; width:1px; height:1px; overflow:hidden;"></textarea>
<div class="muted">Obsah bude vložen do sekce <code>&lt;div class="text lte-text-page clearfix"&gt;...&lt;/div&gt;</code> podle šablony <code>blog/0030.html</code>.</div>
@@ -140,6 +163,60 @@
const inputId = document.getElementById('post-id');
const inputTitle = document.getElementById('title');
const inputCats = document.getElementById('categories');
const inputSlug = document.getElementById('slug');
const inputAnnotation = document.getElementById('annotation');
const contentModeSelect = document.getElementById('content-mode');
const visualEditorWrapper = document.getElementById('visual-editor-wrapper');
const htmlEditorWrapper = document.getElementById('html-editor-wrapper');
const htmlContentTextarea = document.getElementById('html-content');
// Content mode switching
contentModeSelect.addEventListener('change', () => {
const mode = contentModeSelect.value;
if (mode === 'visual') {
visualEditorWrapper.style.display = 'block';
htmlEditorWrapper.style.display = 'none';
} else {
visualEditorWrapper.style.display = 'none';
htmlEditorWrapper.style.display = 'block';
// Sync current content to HTML textarea
const currentContent = quill.root.innerHTML;
htmlContentTextarea.value = currentContent;
}
});
// Sync content from HTML to visual when switching back
contentModeSelect.addEventListener('change', () => {
if (contentModeSelect.value === 'visual') {
const htmlContent = htmlContentTextarea.value;
if (htmlContent.trim()) {
quill.root.innerHTML = htmlContent;
}
}
});
// Auto-generate slug from title
function generateSlug(text) {
return text
.toLowerCase()
.trim()
.replace(/[^\w\s-]/g, '') // Remove special characters
.replace(/[\s_-]+/g, '-') // Replace spaces and underscores with hyphen
.replace(/^-+|-+$/g, ''); // Remove leading/trailing hyphens
}
// Update slug when title changes (if slug is empty)
inputTitle.addEventListener('input', () => {
if (!inputSlug.value || inputSlug.dataset.autoGenerated === 'true') {
inputSlug.value = generateSlug(inputTitle.value);
inputSlug.dataset.autoGenerated = 'true';
}
});
// Mark slug as manually edited when user types in it
inputSlug.addEventListener('input', () => {
inputSlug.dataset.autoGenerated = 'false';
});
let pastedBlob = null; // holds clipboard/fetched blob if provided
@@ -209,8 +286,21 @@
const data = await res.json();
inputId.value = data.id || id;
inputTitle.value = data.title || '';
inputSlug.value = data.slug || '';
inputAnnotation.value = data.annotation || '';
inputCats.value = Array.isArray(data.categories) ? data.categories.join(', ') : '';
quill.root.innerHTML = data.content_html || '';
// Set content mode and load content
if (data.content_mode === 'html') {
contentModeSelect.value = 'html';
htmlContentTextarea.value = data.content_html || '';
visualEditorWrapper.style.display = 'none';
htmlEditorWrapper.style.display = 'block';
} else {
contentModeSelect.value = 'visual';
quill.root.innerHTML = data.content_html || '';
}
// show current image preview
preview.style.display = 'flex';
previewImg.src = '/img/blog/' + (data.id || id) + '.png';
@@ -245,10 +335,22 @@
// Move Quill HTML into the hidden textarea
// Merge category checkboxes into text input
reconcileCategories();
const html = quill.root.innerHTML;
// Get content based on mode
let html;
if (contentModeSelect.value === 'html') {
html = htmlContentTextarea.value.trim();
} else {
html = quill.root.innerHTML;
}
document.getElementById('content').value = html;
// Validate content is not empty (avoid browser required on hidden field)
const plain = quill.getText().trim();
const plain = contentModeSelect.value === 'html' ?
html.replace(/<[^>]*>/g, '').trim() : // Strip HTML for validation
quill.getText().trim();
if (!plain) {
result.textContent = 'Vyplňte obsah článku.';
result.classList.add('err');
@@ -256,6 +358,10 @@
return;
}
const fd = new FormData(form);
// Add annotation and content mode to form data
fd.set('annotation', inputAnnotation.value);
fd.set('content_mode', contentModeSelect.value);
// Prefer pasted/fetched blob if present when no file was chosen
if (pastedBlob && !(imageInput.files && imageInput.files[0])) {
const ext = (pastedBlob.type === 'image/jpeg') ? 'jpg' : 'png';
@@ -300,6 +406,10 @@
result.appendChild(a);
form.reset(); preview.style.display = 'none';
quill.setContents([]);
htmlContentTextarea.value = '';
contentModeSelect.value = 'visual';
visualEditorWrapper.style.display = 'block';
htmlEditorWrapper.style.display = 'none';
}
} catch (err) {
result.textContent = 'Chyba: ' + (err.message || err);
+1
View File
@@ -23,6 +23,7 @@
.search { border:1px solid #d1d5db; padding: 6px 10px; border-radius: 8px; min-width: 260px; }
.status { margin: 12px 0; color: #6b7280; }
</style>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="admin-with-sidenav">
<aside class="admin-sidenav">
+119 -119
View File
@@ -1,120 +1,120 @@
Search Clubs
GET /club/search?q=QUERY
Find clubs on fotbal.cz. Supports football and futsal clubs.
Example: https://facr.tdvorak.dev/club/search?q=Sparta
Response shape
{
"query": "Sparta",
"count": 2,
"results": [
{
"name": "AC Sparta Praha",
"club_id": "",
"club_type": "football",
"url": "https://www.fotbal.cz/...",
"logo_url": "https://.../logo.png",
"category": "Muži",
"address": "..."
}
]
}
Club Info + Matches
GET /club/{type}/{id} - id must be provided in the setup of the club
{type}: football
{id}: club UUID from fotbal.cz
Example: https://facr.tdvorak.dev/club/football/00000000-0000-0000-0000-000000000000
Response shape
{
"name": "AC Sparta Praha",
"club_id": "00000000-0000-0000-0000-000000000000",
"club_type": "football",
"club_internal_id": "123456",
"url": "https://www.fotbal.cz/...",
"logo_url": "https://is1.fotbal.cz/media/kluby/.../logo.jpg",
"address": "Milady Horákové 98, 160 00 Praha 6",
"category": "Muži A",
"competitions": [
{
"id": "12345",
"code": "1. LIGA",
"name": "Fortuna Liga",
"team_count": "16",
"matches_link": "https://www.fotbal.cz/...",
"matches": [
{
"date_time": "12.08.2023 18:00",
"home": "AC Sparta Praha",
"home_id": "00000000-0000-0000-0000-000000000000",
"home_logo_url": "https://.../sparta.png",
"away": "SK Slavia Praha",
"away_id": "11111111-1111-1111-1111-111111111111",
"away_logo_url": "https://.../slavia.png",
"score": "2:1",
"venue": "Stadion Letná",
"match_id": "match12345",
"report_url": "https://www.fotbal.cz/..."
}
]
}
]
}
Club Tables (Standings)
GET /club/{type}/{id}/table - id must be provided in the setup of the club
Returns standings (overall table) for each competition of the club.
Example: https://facr.tdvorak.dev/club/football/00000000-0000-0000-0000-000000000000/table
Response shape
{
"name": "AC Sparta Praha",
"club_id": "00000000-0000-0000-0000-000000000000",
"club_type": "football",
"club_internal_id": "123456",
"url": "https://www.fotbal.cz/...",
"logo_url": "https://is1.fotbal.cz/media/kluby/.../logo.jpg",
"competitions": [
{
"id": "12345",
"code": "1. LIGA",
"name": "Fortuna Liga",
"team_count": "16",
"matches_link": "https://www.fotbal.cz/...",
"table": {
"overall": [
{
"rank": "1",
"team": "AC Sparta Praha",
"team_id": "00000000-0000-0000-0000-000000000000",
"team_logo_url": "https://.../sparta.png",
"played": "10",
"wins": "8",
"draws": "2",
"losses": "0",
"score": "25:5",
"points": "26"
},
{
"rank": "2",
"team": "SK Slavia Praha",
"team_id": "11111111-1111-1111-1111-111111111111",
"team_logo_url": "https://.../slavia.png",
"played": "10",
"wins": "7",
"draws": "2",
"losses": "1",
"score": "20:8",
"points": "23"
}
]
}
}
]
Search Clubs
GET /club/search?q=QUERY
Find clubs on fotbal.cz. Supports football and futsal clubs.
Example: https://facr.tdvorak.dev/club/search?q=Sparta
Response shape
{
"query": "Sparta",
"count": 2,
"results": [
{
"name": "AC Sparta Praha",
"club_id": "",
"club_type": "football",
"url": "https://www.fotbal.cz/...",
"logo_url": "https://.../logo.png",
"category": "Muži",
"address": "..."
}
]
}
Club Info + Matches
GET /club/{type}/{id} - id must be provided in the setup of the club
{type}: football
{id}: club UUID from fotbal.cz
Example: https://facr.tdvorak.dev/club/football/00000000-0000-0000-0000-000000000000
Response shape
{
"name": "AC Sparta Praha",
"club_id": "00000000-0000-0000-0000-000000000000",
"club_type": "football",
"club_internal_id": "123456",
"url": "https://www.fotbal.cz/...",
"logo_url": "https://is1.fotbal.cz/media/kluby/.../logo.jpg",
"address": "Milady Horákové 98, 160 00 Praha 6",
"category": "Muži A",
"competitions": [
{
"id": "12345",
"code": "1. LIGA",
"name": "Fortuna Liga",
"team_count": "16",
"matches_link": "https://www.fotbal.cz/...",
"matches": [
{
"date_time": "12.08.2023 18:00",
"home": "AC Sparta Praha",
"home_id": "00000000-0000-0000-0000-000000000000",
"home_logo_url": "https://.../sparta.png",
"away": "SK Slavia Praha",
"away_id": "11111111-1111-1111-1111-111111111111",
"away_logo_url": "https://.../slavia.png",
"score": "2:1",
"venue": "Stadion Letná",
"match_id": "match12345",
"report_url": "https://www.fotbal.cz/..."
}
]
}
]
}
Club Tables (Standings)
GET /club/{type}/{id}/table - id must be provided in the setup of the club
Returns standings (overall table) for each competition of the club.
Example: https://facr.tdvorak.dev/club/football/00000000-0000-0000-0000-000000000000/table
Response shape
{
"name": "AC Sparta Praha",
"club_id": "00000000-0000-0000-0000-000000000000",
"club_type": "football",
"club_internal_id": "123456",
"url": "https://www.fotbal.cz/...",
"logo_url": "https://is1.fotbal.cz/media/kluby/.../logo.jpg",
"competitions": [
{
"id": "12345",
"code": "1. LIGA",
"name": "Fortuna Liga",
"team_count": "16",
"matches_link": "https://www.fotbal.cz/...",
"table": {
"overall": [
{
"rank": "1",
"team": "AC Sparta Praha",
"team_id": "00000000-0000-0000-0000-000000000000",
"team_logo_url": "https://.../sparta.png",
"played": "10",
"wins": "8",
"draws": "2",
"losses": "0",
"score": "25:5",
"points": "26"
},
{
"rank": "2",
"team": "SK Slavia Praha",
"team_id": "11111111-1111-1111-1111-111111111111",
"team_logo_url": "https://.../slavia.png",
"played": "10",
"wins": "7",
"draws": "2",
"losses": "1",
"score": "20:8",
"points": "23"
}
]
}
}
]
}
+15 -15
View File
@@ -1,15 +1,15 @@
FROM golang:1.22-alpine AS build
WORKDIR /app
COPY . .
RUN go build -o server ./main.go
FROM alpine:3.20
WORKDIR /app
# HTTPS for /img/clean proxy requires CA bundle
RUN apk add --no-cache ca-certificates \
&& update-ca-certificates
# Optional: timezone data for precise Prague time
# RUN apk add --no-cache tzdata
COPY --from=build /app/server /app/server
EXPOSE 8080
ENTRYPOINT ["/app/server"]
FROM golang:1.22-alpine AS build
WORKDIR /app
COPY . .
RUN go build -o server ./main.go
FROM alpine:3.20
WORKDIR /app
# HTTPS for /img/clean proxy requires CA bundle
RUN apk add --no-cache ca-certificates \
&& update-ca-certificates
# Optional: timezone data for precise Prague time
# RUN apk add --no-cache tzdata
COPY --from=build /app/server /app/server
EXPOSE 8080
ENTRYPOINT ["/app/server"]
+718 -169
View File
File diff suppressed because it is too large Load Diff
+170
View File
@@ -0,0 +1,170 @@
package main
import (
"fmt"
"os"
"path/filepath"
"sort"
"strconv"
"testing"
"time"
)
// TestListLatestBlogsOrdering verifies that listLatestBlogs returns items
// sorted by numeric ID descending, regardless of file timestamps or order.
func TestListLatestBlogsOrdering(t *testing.T) {
// Create a temp directory structure mimicking the remote server
tmpDir := t.TempDir()
blogDir := filepath.Join(tmpDir, "blog")
imgDir := filepath.Join(tmpDir, "img", "blog")
if err := os.MkdirAll(blogDir, 0755); err != nil {
t.Fatal(err)
}
if err := os.MkdirAll(imgDir, 0755); err != nil {
t.Fatal(err)
}
// Create numeric blog files with IDs spanning a wide range.
// We intentionally create them in non-numeric order and touch
// old IDs with newer timestamps to simulate a migration.
files := []struct {
id string
slug string
title string
}{
{"0031", "vstupujeme-spolecne-do-druhe-ligy", "VSTUPUJEME SPOLEČNĚ DO DRUHÉ LIGY!"},
{"0032", "nova-mise-pred-nami", "NOVÁ MISE PŘED NÁMI!"},
{"0033", "superpohar-divizi-je-zde", "SUPERPOHÁR DIVIZÍ JE ZDE!"},
{"0034", "superpohar-je-nas", "SUPERPOHÁR JE NÁŠ!"},
{"0035", "fotoreport-1", "FOTOREPORT"},
{"0036", "regionalni-finale-je-tady", "REGIONÁLNÍ FINÁLE JE TADY!"},
{"0037", "bizoni-slavi-postup", "BIZONI SLAVÍ POSTUP!"},
{"0038", "fotoreport-2", "FOTOREPORT"},
{"0039", "2-liga-je-tu", "2. LIGA JE TU!"},
{"0040", "pred-startem-sezony-1", "PŘED STARTEM SEZONY"},
{"0041", "pred-startem-sezony-2", "PŘED STARTEM SEZÓNY"},
{"0042", "podpora-futsalu", "Podpora Futsalu"},
{"0169", "stepan-stodulka-fanouskum-3", "Štěpán Stodůlka fanouškům: Budujeme klub, který bude dlouhodobě silný"},
{"0170", "martin-prokes-fanouskum", "Martin Prokeš fanouškům: První futsalová sezóna přinesla cenné zkušenosti"},
{"0171", "andrea-adamikova-fanouskum", "Andrea Adamíková fanouškům: Druhé místo je motivací do další práce"},
{"0172", "stepan-stodulka-fanouskum-2", "Štěpán Stodůlka fanouškům: Bizonky jsou hrdou součástí našeho klubu"},
{"0173", "martin-lapcik-fanouskum", "Martin Lapčík fanouškům: První rok bizoní mládeže nás všechny nadchl"},
{"0174", "marek-stojaspal-fanouskum", "Marek Stojaspal fanouškům: Mládež položila pevné základy budoucnosti"},
{"0175", "stepan-stodulka-fanouskum-1", "Štěpán Stodůlka fanouškům: Mládež ukázala velký potenciál"},
{"0176", "dekujeme-my-jsme-tu-diky-vam", "DĚKUJEME, MY JSME TU DÍKY VÁM!"},
}
for _, f := range files {
// Create numeric HTML file with slug meta tag
htmlContent := fmt.Sprintf(`<!DOCTYPE html>
<html>
<head>
<meta name="slug" content="%s">
</head>
<body>
<h1 class="lte-header">%s</h1>
<div class="text lte-text-page clearfix">content</div>
</body>
</html>`, f.slug, f.title)
numericPath := filepath.Join(blogDir, f.id+".html")
if err := os.WriteFile(numericPath, []byte(htmlContent), 0644); err != nil {
t.Fatal(err)
}
// Create corresponding slug file (duplicate content)
slugPath := filepath.Join(blogDir, f.slug+".html")
if err := os.WriteFile(slugPath, []byte(htmlContent), 0644); err != nil {
t.Fatal(err)
}
// Create a dummy image
imgPath := filepath.Join(imgDir, f.id+".png")
if err := os.WriteFile(imgPath, []byte("fake png"), 0644); err != nil {
t.Fatal(err)
}
}
// Touch some old IDs with a newer timestamp to simulate post-migration
// (this is the exact condition that broke the old sorting).
// We sleep briefly between creation and touch so the timestamp is definitely newer.
importTime := time.Now()
for _, oldID := range []string{"0031", "0032", "0042"} {
fpath := filepath.Join(blogDir, oldID+".html")
if err := os.Chtimes(fpath, importTime, importTime); err != nil {
// ignore errors on Chtimes
}
}
// Call listLatestBlogs
items, err := listLatestBlogs(tmpDir, 12)
if err != nil {
t.Fatalf("listLatestBlogs error: %v", err)
}
if len(items) != 12 {
t.Fatalf("expected 12 items, got %d", len(items))
}
// Verify IDs are sorted descending (newest first)
for i := 0; i < len(items)-1; i++ {
curr, _ := strconv.Atoi(items[i].ID)
next, _ := strconv.Atoi(items[i+1].ID)
if curr <= next {
t.Errorf("IDs not sorted descending at index %d: %s (%d) <= %s (%d)",
i, items[i].ID, curr, items[i+1].ID, next)
}
}
// Verify the first item is the newest (0176)
if items[0].ID != "0176" {
t.Errorf("expected first item ID to be 0176, got %s (title: %s)", items[0].ID, items[0].Title)
}
if items[1].ID != "0175" {
t.Errorf("expected second item ID to be 0175, got %s", items[1].ID)
}
// Verify deduplication: total unique posts should be 20 (not 40)
allItems, err := listLatestBlogs(tmpDir, 0)
if err != nil {
t.Fatalf("listLatestBlogs unlimited error: %v", err)
}
if len(allItems) != 20 {
t.Errorf("expected 20 unique items after dedup, got %d", len(allItems))
}
// Verify all items are sorted descending
sorted := sort.SliceIsSorted(allItems, func(i, j int) bool {
ii, _ := strconv.Atoi(allItems[i].ID)
jj, _ := strconv.Atoi(allItems[j].ID)
return ii > jj
})
if !sorted {
t.Error("allItems are not sorted by numeric ID descending")
}
}
// TestListLatestBlogsNoSlug verifies numeric-only blogs still sort correctly.
func TestListLatestBlogsNoSlug(t *testing.T) {
tmpDir := t.TempDir()
blogDir := filepath.Join(tmpDir, "blog")
imgDir := filepath.Join(tmpDir, "img", "blog")
os.MkdirAll(blogDir, 0755)
os.MkdirAll(imgDir, 0755)
for _, id := range []string{"0001", "0005", "0010", "0002"} {
content := fmt.Sprintf(`<html><head></head><body><h1 class="lte-header">Title %s</h1></body></html>`, id)
os.WriteFile(filepath.Join(blogDir, id+".html"), []byte(content), 0644)
os.WriteFile(filepath.Join(imgDir, id+".png"), []byte("png"), 0644)
}
items, err := listLatestBlogs(tmpDir, 0)
if err != nil {
t.Fatal(err)
}
expected := []string{"0010", "0005", "0002", "0001"}
if len(items) != len(expected) {
t.Fatalf("expected %d items, got %d", len(expected), len(items))
}
for i, exp := range expected {
if items[i].ID != exp {
t.Errorf("index %d: expected %s, got %s", i, exp, items[i].ID)
}
}
}
+149
View File
@@ -0,0 +1,149 @@
//go:build ignore
// Migration script to clean up duplicate blog files
// Run with: go run migrate_blogs.go <blog_directory>
//
// This script:
// 1. Scans all blog HTML files
// 2. Groups numeric files with their slug counterparts
// 3. Removes orphan slug files (slugs without matching numeric files)
// 4. Reports duplicates for manual review
package main
import (
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: go run migrate_blogs.go <blog_directory>")
fmt.Println("Example: go run migrate_blogs.go ../blog")
os.Exit(1)
}
blogDir := os.Args[1]
// Check directory exists
if _, err := os.Stat(blogDir); os.IsNotExist(err) {
fmt.Printf("Error: blog directory not found: %s\n", blogDir)
os.Exit(1)
}
// Read all files
entries, err := os.ReadDir(blogDir)
if err != nil {
fmt.Printf("Error reading directory: %v\n", err)
os.Exit(1)
}
numericRe := regexp.MustCompile(`^\d{4}\.html$`)
slugRe := regexp.MustCompile(`^[a-z0-9-]+\.html$`)
// Map: numeric ID -> slug (extracted from file content)
numericToSlug := make(map[string]string)
// Map: slug -> numeric ID (extracted by matching content)
slugToNumeric := make(map[string]string)
// List of orphan slug files (no matching numeric file)
orphanSlugs := []string{}
// List of numeric files
numericFiles := []string{}
// List of slug files
slugFiles := []string{}
// First pass: categorize files
for _, e := range entries {
name := e.Name()
if numericRe.MatchString(name) {
numericFiles = append(numericFiles, name)
} else if slugRe.MatchString(name) {
slugFiles = append(slugFiles, name)
}
}
fmt.Printf("Found %d numeric files and %d slug files\n", len(numericFiles), len(slugFiles))
// Extract slugs from numeric files
for _, name := range numericFiles {
path := filepath.Join(blogDir, name)
content, err := os.ReadFile(path)
if err != nil {
continue
}
slug := extractSlugFromContent(string(content))
id := strings.TrimSuffix(name, ".html")
if slug != "" {
numericToSlug[id] = slug
}
}
// Check slug files for matches
for _, name := range slugFiles {
slug := strings.TrimSuffix(name, ".html")
foundMatch := false
// Check if any numeric file has this slug
for numericID, numericSlug := range numericToSlug {
if numericSlug == slug {
slugToNumeric[slug] = numericID
foundMatch = true
break
}
}
if !foundMatch {
orphanSlugs = append(orphanSlugs, name)
}
}
// Report findings
fmt.Println("\n=== Blog Migration Report ===")
fmt.Printf("\nNumeric files with slugs:\n")
for id, slug := range numericToSlug {
fmt.Printf(" %s -> %s\n", id, slug)
}
fmt.Printf("\nSlug files with matching numeric:\n")
for slug, id := range slugToNumeric {
fmt.Printf(" %s.html -> %s.html\n", slug, id)
}
if len(orphanSlugs) > 0 {
fmt.Printf("\nOrphan slug files (no matching numeric file):\n")
for _, name := range orphanSlugs {
fmt.Printf(" %s\n", name)
}
fmt.Printf("\nRemove %d orphan slug files? (y/n): ", len(orphanSlugs))
var response string
fmt.Scanln(&response)
if strings.ToLower(response) == "y" {
for _, name := range orphanSlugs {
path := filepath.Join(blogDir, name)
if err := os.Remove(path); err != nil {
fmt.Printf(" Error removing %s: %v\n", name, err)
} else {
fmt.Printf(" Removed: %s\n", name)
}
}
fmt.Println("Migration complete!")
} else {
fmt.Println("Migration cancelled.")
}
} else {
fmt.Println("\nNo orphan slug files found. Blog directory is clean.")
}
}
func extractSlugFromContent(htmlContent string) string {
re := regexp.MustCompile(`(?is)<meta name="slug" content="([^"]+)"`)
m := re.FindStringSubmatch(htmlContent)
if len(m) >= 2 {
return m[1]
}
return ""
}
+24 -3
View File
@@ -31,6 +31,7 @@
<script type="text/javascript" src="js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full">
@@ -63,20 +64,40 @@
</a>
</li>
<li id="menu-item-29540" class="menu-item menu-item-type-post_type menu-item-object-page">
<a href="">
<a href="o-nas.html">
<span>O nás</span>
</a>
</li>
<li id="menu-item-59" class="menu-item menu-item-type-custom">
<a href="">
<a href="blog.html">
<span>Blog</span>
</a>
</li>
<li id="menu-item-13613" class="menu-item menu-item-type-post_type menu-item-object-page">
<a href="">
<a href="kontakt.html">
<span>Kontakt</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="vykonny-vybor.html">
<span>Výkonný výbor</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="index.html#tym">
<span>Tým</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="index.html#sponzori">
<span>Sponzoři</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a target="_blank" href="https://eu.zonerama.com/Fcbizoni/1419417">
<span>Fotogalerie</span>
</a>
</li>
</ul>
</div>
<!-- Mobile Menu Toggle -->
+6
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full">
@@ -78,6 +79,11 @@
<span>Kontakt</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="vykonny-vybor.html">
<span>Výkonný výbor</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="index.html#tym">
<span>Tým</span>
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos e--ua-blink e--ua-edge e--ua-webkit" data-elementor-device-mode="mobile_extra">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full" style=" min-height: 0px;
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
<meta name="category" content="Zápasy">
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
<meta name="category" content="Zápasy">
<meta name="category" content="O nás">
<meta name="category" content="Novinky">
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
<meta name="category" content="Zápasy">
<meta name="category" content="O nás">
<meta name="category" content="Novinky">
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
<meta name="category" content="Zápasy">
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
<meta name="category" content="Zápasy">
<meta name="category" content="Zápasy">
</head>
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
<meta name="category" content="Zápasy">
<meta name="category" content="Fotoreport">
</head>
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
<meta name="category" content="Zápasy">
<meta name="category" content="Zápasy">
</head>
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
<meta name="category" content="Zápasy">
<meta name="category" content="Zápasy">
</head>
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
<meta name="category" content="Zápasy">
<meta name="category" content="Fotoreport">
<meta name="category" content="Zápasy">
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
<meta name="category" content="Zápasy">
<meta name="category" content="Zápasy">
</head>
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
<meta name="category" content="Zápasy">
<meta name="category" content="Zápasy">
</head>
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
<meta name="category" content="Zápasy">
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
<meta name="category" content="Zápasy">
<meta name="category" content="O nás">
</head>
+31231 -31231
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
File diff suppressed because one or more lines are too long
+162 -162
View File
@@ -1,163 +1,163 @@
.lt-custom-popup {
position: fixed;
right: 8px;
top: 50%;
z-index: 1000;
display: none;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
text-align: center;
border-radius: 64px;
box-shadow: 0 0 25px rgba(0,0,0,.08);
padding: 20px 10px 20px 10px;
background-color: #fff;
}
.lt-custom-popup img {
margin-bottom: 12px;
}
.lt-custom-popup .close {
font-size: 14px;
border-radius: 50%;
position: absolute;
top: 0;
right: 0;
font-size: 20px;
color: #CE4F4D;
z-index: 20;
text-align: center;
line-height: 20px;
width: 20px;
height: 20px;
display: block;
opacity: 1;
background-color: #EEEEEE;
transition: all 0.5s ease;
}
.lt-custom-popup.closed {
padding: 15px 8px 6px 10px;
right: 0;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
transition: all 0.25s ease;
}
.lt-custom-popup.closed:hover {
padding-right: 14px;
}
.ltx-font-selector:hover {
cursor: pointer;
}
.lt-custom-popup.closed img:hover {
cursor: pointer;
}
.lt-custom-popup.closed .close {
display: none;
}
.lt-custom-popup.closed div {
display: none;
}
.lt-custom-popup.closed .img {
display: block;
overflow: hidden;
height: 35px;
width: 35px;
text-align: center;
}
.lt-custom-popup.closed .img img {
margin: 0;
}
.lt-custom-popup .close:hover {
opacity: 1;
color: #000;
}
@media (max-width: 991px) {
.lt-custom-popup {
display: none !important;
}
}
.ltx-font-selector div,
.ltx-color-selector div {
border-radius: 50%;
width: 35px;
height: 35px;
border: 4px solid #fff;
display: block;
margin: 4px auto 0;
box-shadow: 0 0 5px rgba(0,0,0,.1);
cursor: pointer;
transition: all 0.5s ease;
}
.ltx-font-selector div:hover,
.ltx-color-selector div:hover {
box-shadow: 0 0 5px rgba(0,0,0,.2);
}
.lt-custom-field {
padding: 0;
border: 0;
width: 20px;
height: 20px;
border-radius: 50%;
margin-bottom: 14px;
margin-left: auto;
margin-right: auto;
cursor: pointer;
display: block;
}
/* FACR upcoming mobile visibility overrides */
@media (max-width: 767px) {
/* Show the Zápasy (x/y) header on phones */
.lte-football-upcoming .lte-header-upcoming {
display: inline-block !important;
font-size: 18px;
line-height: 1.2;
padding: 2px 8px;
}
/* Ensure countdown line is visible and centered */
#facr-countdown.lte-football-date {
display: block !important;
text-align: center !important;
}
.lt-custom-popup {
position: fixed;
right: 8px;
top: 50%;
z-index: 1000;
display: none;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
text-align: center;
border-radius: 64px;
box-shadow: 0 0 25px rgba(0,0,0,.08);
padding: 20px 10px 20px 10px;
background-color: #fff;
}
.lt-custom-popup img {
margin-bottom: 12px;
}
.lt-custom-popup .close {
font-size: 14px;
border-radius: 50%;
position: absolute;
top: 0;
right: 0;
font-size: 20px;
color: #CE4F4D;
z-index: 20;
text-align: center;
line-height: 20px;
width: 20px;
height: 20px;
display: block;
opacity: 1;
background-color: #EEEEEE;
transition: all 0.5s ease;
}
.lt-custom-popup.closed {
padding: 15px 8px 6px 10px;
right: 0;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
transition: all 0.25s ease;
}
.lt-custom-popup.closed:hover {
padding-right: 14px;
}
.ltx-font-selector:hover {
cursor: pointer;
}
.lt-custom-popup.closed img:hover {
cursor: pointer;
}
.lt-custom-popup.closed .close {
display: none;
}
.lt-custom-popup.closed div {
display: none;
}
.lt-custom-popup.closed .img {
display: block;
overflow: hidden;
height: 35px;
width: 35px;
text-align: center;
}
.lt-custom-popup.closed .img img {
margin: 0;
}
.lt-custom-popup .close:hover {
opacity: 1;
color: #000;
}
@media (max-width: 991px) {
.lt-custom-popup {
display: none !important;
}
}
.ltx-font-selector div,
.ltx-color-selector div {
border-radius: 50%;
width: 35px;
height: 35px;
border: 4px solid #fff;
display: block;
margin: 4px auto 0;
box-shadow: 0 0 5px rgba(0,0,0,.1);
cursor: pointer;
transition: all 0.5s ease;
}
.ltx-font-selector div:hover,
.ltx-color-selector div:hover {
box-shadow: 0 0 5px rgba(0,0,0,.2);
}
.lt-custom-field {
padding: 0;
border: 0;
width: 20px;
height: 20px;
border-radius: 50%;
margin-bottom: 14px;
margin-left: auto;
margin-right: auto;
cursor: pointer;
display: block;
}
/* FACR upcoming mobile visibility overrides */
@media (max-width: 767px) {
/* Show the Zápasy (x/y) header on phones */
.lte-football-upcoming .lte-header-upcoming {
display: inline-block !important;
font-size: 18px;
line-height: 1.2;
padding: 2px 8px;
}
/* Ensure countdown line is visible and centered */
#facr-countdown.lte-football-date {
display: block !important;
text-align: center !important;
}
}
+1 -1
View File
File diff suppressed because one or more lines are too long
+145 -145
View File
@@ -1,146 +1,146 @@
.lt-custom-popup {
position: fixed;
right: 8px;
top: 50%;
z-index: 1000;
display: none;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
text-align: center;
border-radius: 64px;
box-shadow: 0 0 25px rgba(0,0,0,.08);
padding: 20px 10px 20px 10px;
background-color: #fff;
}
.lt-custom-popup img {
margin-bottom: 12px;
}
.lt-custom-popup .close {
font-size: 14px;
border-radius: 50%;
position: absolute;
top: 0;
right: 0;
font-size: 20px;
color: #CE4F4D;
z-index: 20;
text-align: center;
line-height: 20px;
width: 20px;
height: 20px;
display: block;
opacity: 1;
background-color: #EEEEEE;
transition: all 0.5s ease;
}
.lt-custom-popup.closed {
padding: 15px 8px 6px 10px;
right: 0;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
transition: all 0.25s ease;
}
.lt-custom-popup.closed:hover {
padding-right: 14px;
}
.ltx-font-selector:hover {
cursor: pointer;
}
.lt-custom-popup.closed img:hover {
cursor: pointer;
}
.lt-custom-popup.closed .close {
display: none;
}
.lt-custom-popup.closed div {
display: none;
}
.lt-custom-popup.closed .img {
display: block;
overflow: hidden;
height: 35px;
width: 35px;
text-align: center;
}
.lt-custom-popup.closed .img img {
margin: 0;
}
.lt-custom-popup .close:hover {
opacity: 1;
color: #000;
}
@media (max-width: 991px) {
.lt-custom-popup {
display: none !important;
}
}
.ltx-font-selector div,
.ltx-color-selector div {
border-radius: 50%;
width: 35px;
height: 35px;
border: 4px solid #fff;
display: block;
margin: 4px auto 0;
box-shadow: 0 0 5px rgba(0,0,0,.1);
cursor: pointer;
transition: all 0.5s ease;
}
.ltx-font-selector div:hover,
.ltx-color-selector div:hover {
box-shadow: 0 0 5px rgba(0,0,0,.2);
}
.lt-custom-field {
padding: 0;
border: 0;
width: 20px;
height: 20px;
border-radius: 50%;
margin-bottom: 14px;
margin-left: auto;
margin-right: auto;
cursor: pointer;
display: block;
.lt-custom-popup {
position: fixed;
right: 8px;
top: 50%;
z-index: 1000;
display: none;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
text-align: center;
border-radius: 64px;
box-shadow: 0 0 25px rgba(0,0,0,.08);
padding: 20px 10px 20px 10px;
background-color: #fff;
}
.lt-custom-popup img {
margin-bottom: 12px;
}
.lt-custom-popup .close {
font-size: 14px;
border-radius: 50%;
position: absolute;
top: 0;
right: 0;
font-size: 20px;
color: #CE4F4D;
z-index: 20;
text-align: center;
line-height: 20px;
width: 20px;
height: 20px;
display: block;
opacity: 1;
background-color: #EEEEEE;
transition: all 0.5s ease;
}
.lt-custom-popup.closed {
padding: 15px 8px 6px 10px;
right: 0;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
transition: all 0.25s ease;
}
.lt-custom-popup.closed:hover {
padding-right: 14px;
}
.ltx-font-selector:hover {
cursor: pointer;
}
.lt-custom-popup.closed img:hover {
cursor: pointer;
}
.lt-custom-popup.closed .close {
display: none;
}
.lt-custom-popup.closed div {
display: none;
}
.lt-custom-popup.closed .img {
display: block;
overflow: hidden;
height: 35px;
width: 35px;
text-align: center;
}
.lt-custom-popup.closed .img img {
margin: 0;
}
.lt-custom-popup .close:hover {
opacity: 1;
color: #000;
}
@media (max-width: 991px) {
.lt-custom-popup {
display: none !important;
}
}
.ltx-font-selector div,
.ltx-color-selector div {
border-radius: 50%;
width: 35px;
height: 35px;
border: 4px solid #fff;
display: block;
margin: 4px auto 0;
box-shadow: 0 0 5px rgba(0,0,0,.1);
cursor: pointer;
transition: all 0.5s ease;
}
.ltx-font-selector div:hover,
.ltx-color-selector div:hover {
box-shadow: 0 0 5px rgba(0,0,0,.2);
}
.lt-custom-field {
padding: 0;
border: 0;
width: 20px;
height: 20px;
border-radius: 50%;
margin-bottom: 14px;
margin-left: auto;
margin-right: auto;
cursor: pointer;
display: block;
}
+1 -1
View File
File diff suppressed because one or more lines are too long
+171 -171
View File
@@ -1,172 +1,172 @@
.wpcf7 .screen-reader-response {
position: absolute;
overflow: hidden;
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
height: 1px;
width: 1px;
margin: -1px;
padding: 0;
border: 0;
word-wrap: normal !important;
}
.wpcf7 form .wpcf7-response-output {
margin: 2em 0.5em 1em;
padding: 0.2em 1em;
border: 2px solid #00a0d2; /* Blue */
}
.wpcf7 form.init .wpcf7-response-output,
.wpcf7 form.resetting .wpcf7-response-output,
.wpcf7 form.submitting .wpcf7-response-output {
display: none;
}
.wpcf7 form.sent .wpcf7-response-output {
border-color: #46b450; /* Green */
}
.wpcf7 form.failed .wpcf7-response-output,
.wpcf7 form.aborted .wpcf7-response-output {
border-color: #dc3232; /* Red */
}
.wpcf7 form.spam .wpcf7-response-output {
border-color: #f56e28; /* Orange */
}
.wpcf7 form.invalid .wpcf7-response-output,
.wpcf7 form.unaccepted .wpcf7-response-output,
.wpcf7 form.payment-required .wpcf7-response-output {
border-color: #ffb900; /* Yellow */
}
.wpcf7-form-control-wrap {
position: relative;
}
.wpcf7-not-valid-tip {
color: #dc3232; /* Red */
font-size: 1em;
font-weight: normal;
display: block;
}
.use-floating-validation-tip .wpcf7-not-valid-tip {
position: relative;
top: -2ex;
left: 1em;
z-index: 100;
border: 1px solid #dc3232;
background: #fff;
padding: .2em .8em;
width: 24em;
}
.wpcf7-list-item {
display: inline-block;
margin: 0 0 0 1em;
}
.wpcf7-list-item-label::before,
.wpcf7-list-item-label::after {
content: " ";
}
.wpcf7-spinner {
visibility: hidden;
display: inline-block;
background-color: #23282d; /* Dark Gray 800 */
opacity: 0.75;
width: 24px;
height: 24px;
border: none;
border-radius: 100%;
padding: 0;
margin: 0 24px;
position: relative;
}
form.submitting .wpcf7-spinner {
visibility: visible;
}
.wpcf7-spinner::before {
content: '';
position: absolute;
background-color: #fbfbfc; /* Light Gray 100 */
top: 4px;
left: 4px;
width: 6px;
height: 6px;
border: none;
border-radius: 100%;
transform-origin: 8px 8px;
animation-name: spin;
animation-duration: 1000ms;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@media (prefers-reduced-motion: reduce) {
.wpcf7-spinner::before {
animation-name: blink;
animation-duration: 2000ms;
}
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes blink {
from {
opacity: 0;
}
50% {
opacity: 1;
}
to {
opacity: 0;
}
}
.wpcf7 [inert] {
opacity: 0.5;
}
.wpcf7 input[type="file"] {
cursor: pointer;
}
.wpcf7 input[type="file"]:disabled {
cursor: default;
}
.wpcf7 .wpcf7-submit:disabled {
cursor: not-allowed;
}
.wpcf7 input[type="url"],
.wpcf7 input[type="email"],
.wpcf7 input[type="tel"] {
direction: ltr;
}
.wpcf7-reflection > output {
display: list-item;
list-style: none;
}
.wpcf7-reflection > output[hidden] {
display: none;
.wpcf7 .screen-reader-response {
position: absolute;
overflow: hidden;
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
height: 1px;
width: 1px;
margin: -1px;
padding: 0;
border: 0;
word-wrap: normal !important;
}
.wpcf7 form .wpcf7-response-output {
margin: 2em 0.5em 1em;
padding: 0.2em 1em;
border: 2px solid #00a0d2; /* Blue */
}
.wpcf7 form.init .wpcf7-response-output,
.wpcf7 form.resetting .wpcf7-response-output,
.wpcf7 form.submitting .wpcf7-response-output {
display: none;
}
.wpcf7 form.sent .wpcf7-response-output {
border-color: #46b450; /* Green */
}
.wpcf7 form.failed .wpcf7-response-output,
.wpcf7 form.aborted .wpcf7-response-output {
border-color: #dc3232; /* Red */
}
.wpcf7 form.spam .wpcf7-response-output {
border-color: #f56e28; /* Orange */
}
.wpcf7 form.invalid .wpcf7-response-output,
.wpcf7 form.unaccepted .wpcf7-response-output,
.wpcf7 form.payment-required .wpcf7-response-output {
border-color: #ffb900; /* Yellow */
}
.wpcf7-form-control-wrap {
position: relative;
}
.wpcf7-not-valid-tip {
color: #dc3232; /* Red */
font-size: 1em;
font-weight: normal;
display: block;
}
.use-floating-validation-tip .wpcf7-not-valid-tip {
position: relative;
top: -2ex;
left: 1em;
z-index: 100;
border: 1px solid #dc3232;
background: #fff;
padding: .2em .8em;
width: 24em;
}
.wpcf7-list-item {
display: inline-block;
margin: 0 0 0 1em;
}
.wpcf7-list-item-label::before,
.wpcf7-list-item-label::after {
content: " ";
}
.wpcf7-spinner {
visibility: hidden;
display: inline-block;
background-color: #23282d; /* Dark Gray 800 */
opacity: 0.75;
width: 24px;
height: 24px;
border: none;
border-radius: 100%;
padding: 0;
margin: 0 24px;
position: relative;
}
form.submitting .wpcf7-spinner {
visibility: visible;
}
.wpcf7-spinner::before {
content: '';
position: absolute;
background-color: #fbfbfc; /* Light Gray 100 */
top: 4px;
left: 4px;
width: 6px;
height: 6px;
border: none;
border-radius: 100%;
transform-origin: 8px 8px;
animation-name: spin;
animation-duration: 1000ms;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@media (prefers-reduced-motion: reduce) {
.wpcf7-spinner::before {
animation-name: blink;
animation-duration: 2000ms;
}
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes blink {
from {
opacity: 0;
}
50% {
opacity: 1;
}
to {
opacity: 0;
}
}
.wpcf7 [inert] {
opacity: 0.5;
}
.wpcf7 input[type="file"] {
cursor: pointer;
}
.wpcf7 input[type="file"]:disabled {
cursor: default;
}
.wpcf7 .wpcf7-submit:disabled {
cursor: not-allowed;
}
.wpcf7 input[type="url"],
.wpcf7 input[type="email"],
.wpcf7 input[type="tel"] {
direction: ltr;
}
.wpcf7-reflection > output {
display: list-item;
list-style: none;
}
.wpcf7-reflection > output[hidden] {
display: none;
}
+531 -531
View File
File diff suppressed because it is too large Load Diff
+219 -219
View File
@@ -1,219 +1,219 @@
<?xml version="1.0" encoding="UTF-8"?>
<team>
<category name="men">
<member>
<name>Janečka Martin</name>
<number>13</number>
<role>Hráč</role>
<image>img/muzi/Janečka_Martin_1.png</image>
</member>
<member>
<name>Hubinka Adam</name>
<number>18</number>
<role>Hráč</role>
<image>img/muzi/Hubinka_Adam_1.png</image>
</member>
<member>
<name>Zapletal Martin</name>
<number>8</number>
<role>Hráč</role>
<image>img/muzi/Zapletal_Martin_1.png</image>
</member>
<member>
<name>Lapčík Martin</name>
<number>5</number>
<role>Hráč</role>
<image>img/muzi/Lapcik_Martin_1.png</image>
</member>
<member>
<name>Drobný Michal</name>
<number>3</number>
<role>Hráč</role>
<image>img/muzi/Drobný_Michal_1.png</image>
</member>
<member>
<name>Janečka Radek</name>
<number>16</number>
<role>Brankář</role>
<image>img/muzi/Janečka_Radek_1.png</image>
</member>
<member>
<name>Mačuda Jakub</name>
<number>33</number>
<role>Hráč</role>
<image>img/muzi/Mačuda_Jakub_1.png</image>
</member>
<member>
<name>Příplata Filip</name>
<number>9</number>
<role>Hráč</role>
<image>img/muzi/Příplata_Filip_1.png</image>
</member>
<member>
<name>Brázdil Petr</name>
<number>12</number>
<role>Hráč</role>
<image>img/muzi/Brázdil_Petr_1.png</image>
</member>
<member>
<name>Svízela Jakub</name>
<number>19</number>
<role>Hráč</role>
<image>img/muzi/Svízela_Jakub_1.png</image>
</member>
<member>
<name>Šipka Jan</name>
<number>14</number>
<role>Hráč</role>
<image>img/muzi/Šipka_Jan_1.png</image>
</member>
<member>
<name>Polák David</name>
<number>11</number>
<role>Hráč</role>
<image>img/muzi/Polák_David_1.png</image>
</member>
<member>
<name>Ohnutek Tomáš</name>
<number>21</number>
<role>Hráč</role>
<image>img/muzi/Tomas_Ohnutek_1.png</image>
</member>
<member>
<name>Kočiš Lukáš</name>
<number>6</number>
<role>Hráč</role>
<image>img/muzi/Kočiš_Lukáš_1.png</image>
</member>
<member>
<name>Malý Lukáš</name>
<number>21</number>
<role>Hráč</role>
<image>img/muzi/Malý_Lukáš_1.png</image>
</member>
<member>
<name>Řičica Jakub</name>
<number></number>
<role>sekretář klubu</role>
<image>img/muzi/Řičica_Jakub_1.png</image>
</member>
<member>
<name>Moravec David</name>
<number>44</number>
<role>místopředseda klubu</role>
<image>img/muzi/Moravec_David_1.png</image>
</member>
<member>
<name>Janečková Vladimíra</name>
<number></number>
<role>vedoucí týmu</role>
<image>img/muzi/Janečková_Vladimíra_1.png</image>
</member>
<member>
<name>Stodůlka Štěpán</name>
<number>96</number>
<role>PR manažer klubu</role>
<image>img/muzi/Stodůlka_Štěpán_1.png</image>
</member>
<member>
<name>Stojaspal Marek</name>
<number></number>
<role>Trenér mládeže</role>
<image>img/muzi/Stojaspal_Marek_1.png</image>
</member>
<member>
<name>Puškáč Lubomír</name>
<number></number>
<role>Vedoucí týmu</role>
<image>img/muzi/Puškáč_Lubomír_1.png</image>
</member>
<member>
<name>Náplava Jaroslav</name>
<number>88</number>
<role>Předseda klubu</role>
<image>img/muzi/Náplava_Jaroslav_1.png</image>
</member>
</category>
<category name="women">
<member>
<name>Šrámková Sára</name>
<number>12</number>
<role>hráč</role>
<image>img/zeny/Šrámková_Sára_1.png</image>
</member>
<member>
<name>Baná Barbora</name>
<number>21</number>
<role>hráč</role>
<image>img/zeny/Baná_Barbora_1.png</image>
</member>
<member>
<name>Majerechová Eliška</name>
<number>69</number>
<role>hráč</role>
<image>img/zeny/Majerechová_Eliška_1.png</image>
</member>
<member>
<name>Maleňáková Adriana</name>
<number>11</number>
<role>hráč</role>
<image>img/zeny/Maleňáková_Adriana_1.png</image>
</member>
<member>
<name>Adamíková Andrea</name>
<number>6</number>
<role>hráč</role>
<image>img/zeny/Adamíková_Andrea_1.png</image>
</member>
<member>
<name>Dufková Martina</name>
<number>17</number>
<role>hráč</role>
<image>img/zeny/Dufková_Martina_1.png</image>
</member>
<member>
<name>Gorčíková Anna</name>
<number>16</number>
<role>hráč</role>
<image>img/zeny/Gorčíková_Anna_1.png</image>
</member>
<member>
<name>Mrázková Denisa</name>
<number>4</number>
<role>hráč</role>
<image>img/zeny/Mrázková_Denisa_1.png</image>
</member>
<member>
<name>Prokešová Terezie</name>
<number>1</number>
<role>hráč</role>
<image>img/zeny/Prokešová_Terezie_1.png</image>
</member>
<member>
<name>Sekaninová Markéta</name>
<number>7</number>
<role>hráč</role>
<image>img/zeny/Sekaninová_Markéta_1.png</image>
</member>
<member>
<name>Chudárková Kristýna</name>
<number></number>
<role>hráč</role>
<image>img/zeny/Chudárková_Kristýna_1.png</image>
</member>
<member>
<name>Štichová Tereza</name>
<number>10</number>
<role>hráč</role>
<image>img/zeny/Štichová_Tereza_1.png</image>
</member>
<member>
<name>Prokeš Martin</name>
<number></number>
<role>Trenér</role>
<image>img/muzi/Prokeš_Martin_1.png</image>
</member>
</category>
</team>
<?xml version="1.0" encoding="UTF-8"?>
<team>
<category name="men">
<member>
<name>Janečka Martin</name>
<number>13</number>
<role>Hráč</role>
<image>img/muzi/Janečka_Martin_1.png</image>
</member>
<member>
<name>Hubinka Adam</name>
<number>18</number>
<role>Hráč</role>
<image>img/muzi/Hubinka_Adam_1.png</image>
</member>
<member>
<name>Zapletal Martin</name>
<number>8</number>
<role>Hráč</role>
<image>img/muzi/Zapletal_Martin_1.png</image>
</member>
<member>
<name>Lapčík Martin</name>
<number>5</number>
<role>Hráč</role>
<image>img/muzi/Lapcik_Martin_1.png</image>
</member>
<member>
<name>Drobný Michal</name>
<number>3</number>
<role>Hráč</role>
<image>img/muzi/Drobný_Michal_1.png</image>
</member>
<member>
<name>Janečka Radek</name>
<number>16</number>
<role>Brankář</role>
<image>img/muzi/Janečka_Radek_1.png</image>
</member>
<member>
<name>Mačuda Jakub</name>
<number>33</number>
<role>Hráč</role>
<image>img/muzi/Mačuda_Jakub_1.png</image>
</member>
<member>
<name>Příplata Filip</name>
<number>9</number>
<role>Hráč</role>
<image>img/muzi/Příplata_Filip_1.png</image>
</member>
<member>
<name>Brázdil Petr</name>
<number>12</number>
<role>Hráč</role>
<image>img/muzi/Brázdil_Petr_1.png</image>
</member>
<member>
<name>Svízela Jakub</name>
<number>19</number>
<role>Hráč</role>
<image>img/muzi/Svízela_Jakub_1.png</image>
</member>
<member>
<name>Šipka Jan</name>
<number>14</number>
<role>Hráč</role>
<image>img/muzi/Šipka_Jan_1.png</image>
</member>
<member>
<name>Polák David</name>
<number>11</number>
<role>Hráč</role>
<image>img/muzi/Polák_David_1.png</image>
</member>
<member>
<name>Ohnutek Tomáš</name>
<number>21</number>
<role>Hráč</role>
<image>img/muzi/Tomas_Ohnutek_1.png</image>
</member>
<member>
<name>Kočiš Lukáš</name>
<number>6</number>
<role>Hráč</role>
<image>img/muzi/Kočiš_Lukáš_1.png</image>
</member>
<member>
<name>Malý Lukáš</name>
<number>21</number>
<role>Hráč</role>
<image>img/muzi/Malý_Lukáš_1.png</image>
</member>
<member>
<name>Řičica Jakub</name>
<number></number>
<role>Člen VV</role>
<image>img/muzi/Řičica_Jakub_1.png</image>
</member>
<member>
<name>Moravec David</name>
<number>44</number>
<role>Místopředseda</role>
<image>img/muzi/Moravec_David_1.png</image>
</member>
<member>
<name>Janečková Vladimíra</name>
<number></number>
<role>vedoucí týmu</role>
<image>img/muzi/Janečková_Vladimíra_1.png</image>
</member>
<member>
<name>Stodůlka Štěpán</name>
<number>96</number>
<role>Předseda</role>
<image>img/muzi/Stodůlka_Štěpán_1.png</image>
</member>
<member>
<name>Stojaspal Marek</name>
<number></number>
<role>Trenér mládeže</role>
<image>img/muzi/Stojaspal_Marek_1.png</image>
</member>
<member>
<name>Puškáč Lubomír</name>
<number></number>
<role>Vedoucí týmu</role>
<image>img/muzi/Puškáč_Lubomír_1.png</image>
</member>
<member>
<name>Náplava Jaroslav</name>
<number>88</number>
<role>Člen VV</role>
<image>img/muzi/Náplava_Jaroslav_1.png</image>
</member>
</category>
<category name="women">
<member>
<name>Šrámková Sára</name>
<number>12</number>
<role>hráč</role>
<image>img/zeny/Šrámková_Sára_1.png</image>
</member>
<member>
<name>Baná Barbora</name>
<number>21</number>
<role>hráč</role>
<image>img/zeny/Baná_Barbora_1.png</image>
</member>
<member>
<name>Majerechová Eliška</name>
<number>69</number>
<role>hráč</role>
<image>img/zeny/Majerechová_Eliška_1.png</image>
</member>
<member>
<name>Maleňáková Adriana</name>
<number>11</number>
<role>hráč</role>
<image>img/zeny/Maleňáková_Adriana_1.png</image>
</member>
<member>
<name>Adamíková Andrea</name>
<number>6</number>
<role>hráč</role>
<image>img/zeny/Adamíková_Andrea_1.png</image>
</member>
<member>
<name>Dufková Martina</name>
<number>17</number>
<role>hráč</role>
<image>img/zeny/Dufková_Martina_1.png</image>
</member>
<member>
<name>Gorčíková Anna</name>
<number>16</number>
<role>hráč</role>
<image>img/zeny/Gorčíková_Anna_1.png</image>
</member>
<member>
<name>Mrázková Denisa</name>
<number>4</number>
<role>hráč</role>
<image>img/zeny/Mrázková_Denisa_1.png</image>
</member>
<member>
<name>Prokešová Terezie</name>
<number>1</number>
<role>hráč</role>
<image>img/zeny/Prokešová_Terezie_1.png</image>
</member>
<member>
<name>Sekaninová Markéta</name>
<number>7</number>
<role>hráč</role>
<image>img/zeny/Sekaninová_Markéta_1.png</image>
</member>
<member>
<name>Chudárková Kristýna</name>
<number></number>
<role>hráč</role>
<image>img/zeny/Chudárková_Kristýna_1.png</image>
</member>
<member>
<name>Štichová Tereza</name>
<number>10</number>
<role>hráč</role>
<image>img/zeny/Štichová_Tereza_1.png</image>
</member>
<member>
<name>Prokeš Martin</name>
<number></number>
<role>Trenér</role>
<image>img/muzi/Prokeš_Martin_1.png</image>
</member>
</category>
</team>
+13 -13
View File
@@ -1,13 +1,13 @@
services:
app:
build: ./backend
container_name: bizoni-app
environment:
- STATIC_PATH=/app/site
- PORT=8080
ports:
- "8080:8080"
volumes:
- ./data:/app/data
- ./:/app/site
restart: unless-stopped
services:
app:
build: ./backend
container_name: bizoni-app
environment:
- STATIC_PATH=/app/site
- PORT=8080
ports:
- "8080:8080"
volumes:
- ./data:/app/data
- ./:/app/site
restart: unless-stopped
+1
View File
@@ -31,6 +31,7 @@
<script type="text/javascript" src="js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full">
+1
View File
@@ -31,6 +31,7 @@
<script type="text/javascript" src="js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full">
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full">
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

+41 -7
View File
@@ -30,6 +30,7 @@
window.si = window.si || function () { (window.siq = window.siq || []).push(arguments); };
</script>
<script defer src="/_vercel/speed-insights/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
<link rel="stylesheet" id="bootstrap-css" href="css/bootstrap.css" type="text/css" media="all" />
<link rel="stylesheet" id="atleticos-theme-style-css" href="css/bizoni.css" type="text/css" media="all" />
<link rel="stylesheet" href="css/overrides.css" type="text/css" media="all" />
@@ -102,6 +103,11 @@
<span>Kontakt</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="vykonny-vybor.html">
<span>Výkonný výbor</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="index.html#tym">
<span>Tým</span>
@@ -1768,13 +1774,6 @@
</a>
</div>
</div>
<div class="col-xl-3 col-lg-3 col-md-6 col-sm-6 col-ms-6 col-xs-12 partners-wrap center-flex">
<div class="partners-item item center-flex">
<a href="https://alpacar.pl/" target="_blank">
<img decoding="async" src="img/sponzor17.png" class="image">
</a>
</div>
</div>
<div class="col-xl-3 col-lg-3 col-md-6 col-sm-6 col-ms-6 col-xs-12 partners-wrap center-flex">
<div class="partners-item item center-flex">
<a href="https://vechra.cz/" target="_blank">
@@ -1852,6 +1851,41 @@
</a>
</div>
</div>
<div class="col-sxl-3 col-lg-3 col-md-6 col-sm-6 col-ms-6 col-xs-12 partners-wrap center-flex">
<div class="partners-item item center-flex">
<a href="https://sbernesurovinyuh.cz/" target="_blank">
<img decoding="async" src="img/sponzor29.png" class="image">
</a>
</div>
</div>
<div class="col-sxl-3 col-lg-3 col-md-6 col-sm-6 col-ms-6 col-xs-12 partners-wrap center-flex">
<div class="partners-item item center-flex">
<a href="https://www.kovosteel.cz/" target="_blank">
<img decoding="async" src="img/sponzor30.png" class="image">
</a>
</div>
</div>
<div class="col-sxl-3 col-lg-3 col-md-6 col-sm-6 col-ms-6 col-xs-12 partners-wrap center-flex">
<div class="partners-item item center-flex">
<a href="http://gracla.cz/" target="_blank">
<img decoding="async" src="img/sponzor31.png" class="image">
</a>
</div>
</div>
<div class="col-sxl-3 col-lg-3 col-md-6 col-sm-6 col-ms-6 col-xs-12 partners-wrap center-flex">
<div class="partners-item item center-flex">
<a href="https://nsa.gov.cz/" target="_blank">
<img decoding="async" src="img/sponzor32.png" class="image">
</a>
</div>
</div>
<div class="col-sxl-3 col-lg-3 col-md-6 col-sm-6 col-ms-6 col-xs-12 partners-wrap center-flex">
<div class="partners-item item center-flex">
<a href="https://zlinskykraj.cz/" target="_blank">
<img decoding="async" src="img/sponzor33.png" class="image">
</a>
</div>
</div>
</div>
</div>
</div>
+6
View File
@@ -51,6 +51,12 @@
const res = await fetch('/api/blog/latest?limit=12', {credentials: 'omit'});
if (!res.ok) throw new Error('HTTP '+res.status);
let items = await res.json();
// Defensive sort: numeric ID descending ensures newest first regardless of API ordering
items.sort((a,b)=>{
const ai = parseInt(a.id,10); const bi = parseInt(b.id,10);
if (!isNaN(ai) && !isNaN(bi)) return bi-ai;
return (b.id||'').localeCompare(a.id||'');
});
if (primary) primary.innerHTML = '';
if (!Array.isArray(items) || items.length === 0) {
if (primary) primary.innerHTML = '<div style="width:100%;text-align:center;padding:12px;color:#888;">Žádné příspěvky zatím nejsou.</div>';
+471 -471
View File
@@ -1,471 +1,471 @@
(function(){
const DATA_URL_JSON = '/data/club.json';
const TZ = 'Europe/Prague';
let state = {
data: null,
compIndex: 0,
matchIndex: 0,
intervalId: null,
upcomingTimerId: null,
};
function parseCZDate(s){
try{
// format: 02.01.2006 15:04
const [d, t] = s.split(' ');
const [day, month, year] = d.split('.').map(Number);
const [hour, minute] = t.split(':').map(Number);
// Interpret as local time (Europe/Prague). Using local constructor avoids UTC offset skew.
const dt = new Date(year, month-1, day, hour, minute);
return dt;
}catch(e){ return null; }
}
// using original logo URLs; no cleaning/proxy
function ensureFacrStyles(){
if(document.getElementById('facr-styles')) return;
const css = `
/* logo background unchanged */
.facr-nav{ background:#ffffff22; border:1px solid #ffffff55; color:#fff; padding:6px 10px; border-radius:6px; cursor:pointer; backdrop-filter: blur(2px); }
.facr-nav:hover{ background:#ffffff40; }
.facr-nav:disabled{ opacity:.5; cursor:default; }
.facr-tab{ padding:6px 10px; margin:4px; border-radius:16px; border:1px solid #c42221; color:#c42221; background:#ffffff; font-weight:600; }
.facr-tab.active{ background:#c42221; color:#ffffff; }
.facr-tab:hover{ background:#c42221cc; color:#ffffff; }
.facr-inline-status{ margin-left:8px; font-weight:700; font-size:14px; white-space:nowrap; color:inherit; display:inline-block; vertical-align:middle; }
/* Default (desktop): show middle only */
#facr-countdown{ display:none !important; }
.facr-inline-status{ display:none !important; }
.facr-mob-center-score{ display:none; font-weight:700; font-size:24px; line-height:1; }
/* Mobile: keep only the bottom countdown by default */
@media (max-width: 767px){
#facr-mid{ display:none !important; }
#facr-countdown{ display:block !important; }
.facr-inline-status{ display:none !important; }
.facr-mob-center-score{ display:inline-block !important; }
/* If finished, hide the bottom countdown */
.facr-finished #facr-countdown{ display:none !important; }
}
@media (max-width: 480px){
#facr-mid{ font-size:28px !important; min-width:100px; }
.facr-tab{ padding:4px 8px; font-size:14px; }
.facr-inline-status{ font-size:12px; margin-left:6px; }
.facr-nav{ padding:4px 8px; }
}
`;
const style = document.createElement('style');
style.id = 'facr-styles';
style.type = 'text/css';
style.appendChild(document.createTextNode(css));
document.head.appendChild(style);
}
function fmtCountdown(ms){
if(ms <= 0) return '0m';
const totalMin = Math.floor(ms/60000);
const d = Math.floor(totalMin/(60*24));
const h = Math.floor((totalMin - d*60*24)/60);
const m = totalMin % 60;
const parts = [];
if(d) parts.push(`${d}d`);
if(h || d) parts.push(`${h}h`);
parts.push(`${m}m`);
return parts.join(' ');
}
function fmtCountdownLong(ms){
if(ms < 0) ms = 0;
const totalSec = Math.floor(ms/1000);
const d = Math.floor(totalSec / (24*3600));
const h = Math.floor((totalSec % (24*3600)) / 3600);
const m = Math.floor((totalSec % 3600) / 60);
const s = totalSec % 60;
const dd = d > 0 ? `${d}d ` : '';
const hh = String(h).padStart(2,'0');
const mm = String(m).padStart(2,'0');
const ss = String(s).padStart(2,'0');
return `${dd}${hh}:${mm}:${ss}`.trim();
}
function todayCZ(){
const now = new Date();
const dd = String(now.getDate()).padStart(2,'0');
const mm = String(now.getMonth()+1).padStart(2,'0');
const yyyy = now.getFullYear();
return `${dd}.${mm}.${yyyy}`;
}
async function fetchData(){
const res = await fetch(DATA_URL_JSON, { cache: 'no-cache' });
if(!res.ok) throw new Error('Failed to fetch data');
const data = await res.json();
state.data = data;
return data;
}
function escapeHTML(s){
if(s == null) return '';
return String(s)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
function truncate(s, max){
const str = s == null ? '' : String(s);
if(max <= 0) return '';
return str.length > max ? str.slice(0, max - 1) + '…' : str;
}
function isWithinMatchWindow(){
if(!state.data) return false;
const now = new Date();
for(const comp of state.data.club_detail.competitions || []){
for(const m of comp.matches || []){
const dt = parseCZDate(m.date_time);
if(!dt) continue;
const diffMs = Math.abs(now - dt);
if(diffMs <= 2*60*60*1000) return true;
}
}
return false;
}
function upcomingMatchesAll(){
const list = [];
if(!state.data) return list;
const now = new Date();
const windowStart = new Date(now.getTime() - 3*24*60*60*1000);
for(const comp of state.data.club_detail.competitions || []){
const candidates = (comp.matches || [])
.map(m=>({ comp, match: m, dt: parseCZDate(m.date_time) }))
.filter(x=> x.dt && x.dt >= windowStart)
.sort((a,b)=> a.dt - b.dt);
if(candidates.length === 0) continue;
// Prefer the latest recently finished match within the 3-day window;
// if none, then choose the next upcoming; if none, fall back to the latest overall in window
let pick = null;
// find latest finished (dt < now) within window
for(let i = candidates.length - 1; i >= 0; i--){
if(candidates[i].dt < now){ pick = candidates[i]; break; }
}
if(!pick){
pick = candidates.find(x=> x.dt >= now) || candidates[candidates.length - 1];
}
list.push(pick);
}
// sort resulting per-competition picks by time ascending for navigation
list.sort((a,b)=> a.dt - b.dt);
return list;
}
function renderUpcoming(){
const root = document.getElementById('facr-upcoming');
if(!root) return;
ensureFacrStyles();
// clear any previous per-second timer
if(state.upcomingTimerId){
clearInterval(state.upcomingTimerId);
state.upcomingTimerId = null;
}
const items = upcomingMatchesAll();
if(items.length === 0){
root.innerHTML = '<div class="lte-football-upcoming"><span class="lte-header lte-header-upcoming">Žádné nadcházející zápasy</span></div>';
return;
}
// Selection policy:
// 1) If there is any finished match within the last 3 days across competitions,
// show the latest such finished match (keep result visible for 3 days)
// 2) Otherwise, show the first future match
// 3) If none, show the latest overall (shouldn't happen as items filtered by 3d window per-comp)
const now = new Date();
const threeDms = 3*24*60*60*1000;
let latestRecentIdx = -1;
let latestRecentTime = -Infinity;
items.forEach((it, i) => {
const dtms = it.dt.getTime();
if(dtms <= now.getTime() && now.getTime() - dtms <= threeDms){
if(dtms > latestRecentTime){ latestRecentTime = dtms; latestRecentIdx = i; }
}
});
let preferredIdx = latestRecentIdx;
if(preferredIdx === -1){
preferredIdx = items.findIndex(it => it.dt >= now);
if(preferredIdx === -1) preferredIdx = items.length - 1;
}
const idx = Math.min(state.matchIndex || preferredIdx, items.length-1);
const { comp, match:m } = items[idx];
const compName = truncate(escapeHTML(comp.name || comp.code || 'Soutěž'), 60);
const homeLogo = m.home_logo_url || 'img/logo.png';
const awayLogo = m.away_logo_url || 'img/logo.png';
const facrLink = m.facr_link || comp.matches_link || state.data.club_detail.url || '#';
const UP_MAX = 24;
const homeName = truncate(escapeHTML(m.home), UP_MAX);
const awayName = truncate(escapeHTML(m.away), UP_MAX);
const dateVenue = truncate(escapeHTML(m.date_time + (m.venue?`, ${m.venue}`:'')), 40);
// Determine if match is today (CZ date) and precompute mid display text
const matchDayCZ = (m.date_time || '').split(' ')[0];
const isToday = matchDayCZ === todayCZ();
const startDt = m.date_time ? parseCZDate(m.date_time) : null;
const diffMsPre = startDt ? (startDt.getTime() - new Date().getTime()) : 0;
const midText = (diffMsPre > 0) ? `Za ${fmtCountdownLong(diffMsPre)}` : (m.score || '-');
// Determine status flags and parse score parts if any
const now2_forTpl = new Date();
const startMs_forTpl = m.date_time ? parseCZDate(m.date_time).getTime() : 0;
const diff_forTpl = startMs_forTpl - now2_forTpl.getTime();
const twoH_forTpl = 2*60*60*1000;
const threeD_forTpl = 3*24*60*60*1000;
const isFuture = diff_forTpl > 0;
const isLive = Math.abs(diff_forTpl) <= twoH_forTpl;
const isRecentFinished = (!isFuture && !isLive && -diff_forTpl < threeD_forTpl);
const scoreStr = m.score || '';
const s1 = scoreStr && scoreStr.includes(':') ? escapeHTML(scoreStr.split(':')[0]) : '';
const s2 = scoreStr && scoreStr.includes(':') ? escapeHTML(scoreStr.split(':')[1]) : '';
// Date/time formatting for display lines
const dtForDisp = startDt || (m.date_time ? parseCZDate(m.date_time) : null);
const dd = dtForDisp ? String(dtForDisp.getDate()).padStart(1,'') : '';
const mm = dtForDisp ? String(dtForDisp.getMonth()+1).padStart(1,'') : '';
const yyyy = dtForDisp ? dtForDisp.getFullYear() : '';
const HH = dtForDisp ? String(dtForDisp.getHours()).padStart(2,'0') : '';
const MM = dtForDisp ? String(dtForDisp.getMinutes()).padStart(2,'0') : '';
const dateOnly = dtForDisp ? `${dd}. ${mm}. ${yyyy}` : '';
const timeToken = (m.date_time || '').split(' ')[1] || '';
const timeOnly = dtForDisp ? `${HH}:${MM}` : '';
const timeDisplay = dtForDisp ? ((timeToken === '' || timeToken === '00:00') ? 'Bude upřesněno' : timeOnly) : '';
const venue = m.venue || '';
const wrapperExtraClass = (isRecentFinished && s1 && s2) ? ' facr-finished' : '';
const headerLabel = isLive ? 'Aktuální zápas' : (isFuture ? 'Nadcházející zápas' : (isRecentFinished ? 'Poslední zápas' : `Zápasy (${idx+1}/${items.length})`));
root.innerHTML = `
<div class="lte-football-upcoming${wrapperExtraClass}">
<div class="facr-comp-title lte-football-date" style="text-align:center; margin-bottom:6px;">${compName}</div>
<div class="facr-upcoming-header">
<button id="facr-prev" class="facr-nav">◀</button>
<span class="lte-header lte-header-upcoming">${headerLabel}</span>
<button id="facr-next" class="facr-nav">▶</button>
</div>
<div class="lte-teams">
<span class="lte-team-name lte-team-1 lte-header" title="${escapeHTML(m.home)}">
<span class="lte-team-logo"><img decoding="async" src="${homeLogo}" alt="${escapeHTML(m.home)}"></span>${homeName}
<span id="facr-inline-status" class="facr-inline-status" aria-live="polite"></span>
${isRecentFinished && s1 ? `<span class="lte-team-count-mob">${s1}</span>` : ''}
</span>
<span class="lte-team-count">
<span id="facr-mid" style="font-size:32px; line-height:1; font-weight:700; display:inline-block; min-width:120px; text-align:center;">${midText}</span>
${isRecentFinished && s1 && s2 ? `<span class="facr-mob-center-score">${s1}<span>:</span>${s2}</span>` : ''}
</span>
<span class="lte-team-name lte-team-2 lte-header" title="${escapeHTML(m.away)}">
${isRecentFinished && s2 ? `<span class=\"lte-team-count-mob\">${s2}</span>` : ''}${awayName}<span class="lte-team-logo"><img decoding="async" src="${awayLogo}" alt="${escapeHTML(m.away)}"></span>
</span>
</div>
<span class="lte-football-date" style="text-align:center;" title="${escapeHTML(m.date_time + (m.venue?`, ${m.venue}`:''))}">${escapeHTML(dateOnly + (venue?`, ${venue}`:''))}</span>
${timeDisplay ? `<span class="lte-football-time" style="display:block; text-align:center;">${escapeHTML(timeDisplay)}</span>` : ''}
<span id="facr-countdown" class="lte-football-date" style="display:block; text-align:center;"></span>
<br>
<a class="lte-football-date" target="_blank" href="${facrLink}" style="text-align:center; background-color:#c42221; color:#ffffff; opacity:1;">Detail na FACR</a>
<span style="display:block; margin-top:6px;"></span>
<a class="lte-football-date" href="#tabulka" style="text-align:center; background-color:#ffffff43; color:#ffffff; opacity:1; width:49%; display:inline-block;">Tabulka bodů</a>
<a class="lte-football-date" href="/zapasy/vsechny.html" style="text-align:center; background-color:#ffffff43; color:#ffffff; opacity:1; width:49%; display:inline-block;">Všechny zápasy</a>
</div>`;
const prev = document.getElementById('facr-prev');
const next = document.getElementById('facr-next');
if(prev) prev.onclick = ()=>{ state.matchIndex = (idx - 1 + items.length) % items.length; renderUpcoming(); };
if(next) next.onclick = ()=>{ state.matchIndex = (idx + 1) % items.length; renderUpcoming(); };
// setup countdown / status text
const cd = document.getElementById('facr-countdown');
const inlineStatus = document.getElementById('facr-inline-status');
if(cd || inlineStatus){
const now2 = new Date();
const startMs = m.date_time ? parseCZDate(m.date_time).getTime() : 0;
const diff = startMs - now2.getTime();
const twoH = 2*60*60*1000;
const threeD = 3*24*60*60*1000;
let text = '';
if(diff > 0){
text = `Začátek za ${fmtCountdown(diff)}`;
}else if(Math.abs(diff) <= twoH){
text = 'Právě probíhá';
}else if(-diff < threeD){
text = (m.score ? `Výsledek: ${m.score}` : 'Ukončeno');
}else{
text = '';
}
if(cd) cd.textContent = text;
if(inlineStatus) inlineStatus.textContent = text;
}
// Live countdown in the middle area when future and not today
const midEl = document.getElementById('facr-mid');
if(midEl){
const startTime = m.date_time ? parseCZDate(m.date_time).getTime() : 0;
function tick(){
const now = Date.now();
const diff = startTime - now;
if(diff > 0){
const longTxt = `Za ${fmtCountdownLong(diff)}`;
midEl.textContent = longTxt;
const inlineEl = document.getElementById('facr-inline-status');
if(inlineEl) inlineEl.textContent = `Začátek za ${fmtCountdown(diff)}`;
const cdEl = document.getElementById('facr-countdown');
if(cdEl) cdEl.textContent = `Začátek za ${fmtCountdown(diff)}`;
}else{
// switch to score at/after kickoff
const scoreTxt = m.score || '-';
midEl.textContent = scoreTxt;
const inlineEl = document.getElementById('facr-inline-status');
if(inlineEl) inlineEl.textContent = (m.score ? `Výsledek: ${m.score}` : 'Ukončeno');
const cdEl = document.getElementById('facr-countdown');
if(cdEl) cdEl.textContent = (m.score ? `Výsledek: ${m.score}` : 'Ukončeno');
if(state.upcomingTimerId){ clearInterval(state.upcomingTimerId); state.upcomingTimerId = null; }
}
}
// Run live countdown for any future match (including today)
if(startTime > Date.now()){
tick();
state.upcomingTimerId = setInterval(tick, 1000);
} else {
// Ensure inline status reflects finished state on initial render
const inlineEl = document.getElementById('facr-inline-status');
if(inlineEl) inlineEl.textContent = (m.score ? `Výsledek: ${m.score}` : 'Ukončeno');
}
}
}
function renderCompetitionTabs(){
const tabs = document.getElementById('facr-comp-tabs');
if(!tabs || !state.data) return;
ensureFacrStyles();
const comps = state.data.club_table.competitions || [];
tabs.innerHTML = comps.map((c,i)=>
`<button class="facr-tab ${i===state.compIndex?'active':''}" data-idx="${i}">${c.name || c.code || 'Soutěž'}</button>`
).join('');
tabs.querySelectorAll('button').forEach(btn=>{
btn.addEventListener('click', ()=>{
state.compIndex = Number(btn.dataset.idx)||0;
renderCompetitionTabs();
renderTable();
});
});
}
function renderTable(){
const tbody = document.getElementById('facr-table-body');
const badge = document.getElementById('facr-comp-badge');
if(!tbody || !state.data) return;
const comps = state.data.club_table.competitions || [];
if(comps.length === 0){ tbody.innerHTML = ''; return; }
const comp = comps[Math.min(state.compIndex, comps.length-1)];
if(badge){ badge.textContent = comp.name || comp.code || 'Soutěž'; }
const rows = comp.table && comp.table.overall ? comp.table.overall : [];
tbody.innerHTML = rows.map(r=>`
<tr>
<td class="lte-row"><span>${r.rank}</span></td>
<td class="lte-club-logo"><img decoding="async" src="${r.team_logo_url || 'img/logo.png'}"></td>
<td class="lte-name">${r.team}</td>
<td class="lte-rate">${r.played}</td>
<td class="lte-rate">${r.wins}</td>
<td class="lte-rate">${r.draws}</td>
<td class="lte-rate">${r.losses}</td>
<td class="lte-rate">${r.score}</td>
<td class="lte-summary">${r.points}</td>
</tr>
`).join('');
}
function renderAllMatches(){
const container = document.getElementById('facr-all-matches');
if(!container || !state.data) return;
const comps = state.data.club_detail.competitions || [];
const sections = [];
for(const comp of comps){
const matches = (comp.matches || [])
.map(m=>({ m, dt: parseCZDate(m.date_time) }))
.filter(x=>!!x.dt)
.sort((a,b)=> b.dt - a.dt);
if(matches.length === 0) continue;
const compName = truncate(escapeHTML(comp.name || comp.code || 'Soutěž'), 40);
const itemsHtml = matches.map(({m})=>{
const homeLogo = m.home_logo_url || '../img/logo.png';
const awayLogo = m.away_logo_url || '../img/logo.png';
const facrLink = m.report_url || comp.matches_link || state.data.club_detail.url || '#';
const score = m.score || '-';
const GRID_MAX = 22;
const home = truncate(escapeHTML(m.home), GRID_MAX);
const away = truncate(escapeHTML(m.away), GRID_MAX);
const dateVenue = truncate(escapeHTML(m.date_time + (m.venue?`, ${m.venue}`:'')), 36);
const s1 = escapeHTML((score.split(':')[0]||'-'));
const s2 = escapeHTML((score.split(':')[1]||'-'));
return `
<a href="${facrLink}" target="_blank" class="lte-item swiper-slide">
<div class="lte-teams lte-match-time-public">
<span class="lte-team-name lte-team-1 lte-header" title="${escapeHTML(m.home)}">
<span class="lte-team-logo"><img src="${homeLogo}" alt="${escapeHTML(m.home)}"></span>${home}</span>
<span class="lte-score-mob lte-score-1">${s1}</span>
<span class="lte-team-count">
<span class="lte-c lte-score-1">${s1}</span>
<span class="lte-d">:</span>
<span class="lte-c lte-score-4">${s2}</span>
</span>
<span class="lte-team-name lte-team-2 lte-header" title="${escapeHTML(m.away)}">${away}
<span class="lte-team-logo"><img src="${awayLogo}" alt="${escapeHTML(m.away)}"></span>
</span>
<span class="lte-score-mob lte-score-4">${s2}</span>
</div>
<div class="lte-footer">
<span class="lte-football-date" title="${escapeHTML(m.date_time + (m.venue?`, ${m.venue}`:''))}">${dateVenue}</span>
</div>
</a>`;
}).join('');
sections.push(`
<div class="lte-section">
<h3 class="lte-header" style="margin: 20px 0 10px;">${compName}</h3>
<div class="lte-football-matches inner-page">${itemsHtml}</div>
</div>
`);
}
container.innerHTML = sections.join('');
}
function schedule(){
if(state.intervalId) clearInterval(state.intervalId);
const intervalMs = isWithinMatchWindow() ? 2*60*1000 : 30*60*1000;
state.intervalId = setInterval(async ()=>{
try{
await fetchData();
renderUpcoming();
renderCompetitionTabs();
renderTable();
renderAllMatches();
schedule(); // reevaluate interval if window changed
}catch(e){ console.warn('refresh failed', e); }
}, intervalMs);
}
async function init(){
try{
await fetchData();
renderUpcoming();
renderCompetitionTabs();
renderTable();
renderAllMatches();
schedule();
}catch(e){
console.error('FACR init failed', e);
}
}
document.addEventListener('DOMContentLoaded', init);
})();
(function(){
const DATA_URL_JSON = '/data/club.json';
const TZ = 'Europe/Prague';
let state = {
data: null,
compIndex: 0,
matchIndex: 0,
intervalId: null,
upcomingTimerId: null,
};
function parseCZDate(s){
try{
// format: 02.01.2006 15:04
const [d, t] = s.split(' ');
const [day, month, year] = d.split('.').map(Number);
const [hour, minute] = t.split(':').map(Number);
// Interpret as local time (Europe/Prague). Using local constructor avoids UTC offset skew.
const dt = new Date(year, month-1, day, hour, minute);
return dt;
}catch(e){ return null; }
}
// using original logo URLs; no cleaning/proxy
function ensureFacrStyles(){
if(document.getElementById('facr-styles')) return;
const css = `
/* logo background unchanged */
.facr-nav{ background:#ffffff22; border:1px solid #ffffff55; color:#fff; padding:6px 10px; border-radius:6px; cursor:pointer; backdrop-filter: blur(2px); }
.facr-nav:hover{ background:#ffffff40; }
.facr-nav:disabled{ opacity:.5; cursor:default; }
.facr-tab{ padding:6px 10px; margin:4px; border-radius:16px; border:1px solid #c42221; color:#c42221; background:#ffffff; font-weight:600; }
.facr-tab.active{ background:#c42221; color:#ffffff; }
.facr-tab:hover{ background:#c42221cc; color:#ffffff; }
.facr-inline-status{ margin-left:8px; font-weight:700; font-size:14px; white-space:nowrap; color:inherit; display:inline-block; vertical-align:middle; }
/* Default (desktop): show middle only */
#facr-countdown{ display:none !important; }
.facr-inline-status{ display:none !important; }
.facr-mob-center-score{ display:none; font-weight:700; font-size:24px; line-height:1; }
/* Mobile: keep only the bottom countdown by default */
@media (max-width: 767px){
#facr-mid{ display:none !important; }
#facr-countdown{ display:block !important; }
.facr-inline-status{ display:none !important; }
.facr-mob-center-score{ display:inline-block !important; }
/* If finished, hide the bottom countdown */
.facr-finished #facr-countdown{ display:none !important; }
}
@media (max-width: 480px){
#facr-mid{ font-size:28px !important; min-width:100px; }
.facr-tab{ padding:4px 8px; font-size:14px; }
.facr-inline-status{ font-size:12px; margin-left:6px; }
.facr-nav{ padding:4px 8px; }
}
`;
const style = document.createElement('style');
style.id = 'facr-styles';
style.type = 'text/css';
style.appendChild(document.createTextNode(css));
document.head.appendChild(style);
}
function fmtCountdown(ms){
if(ms <= 0) return '0m';
const totalMin = Math.floor(ms/60000);
const d = Math.floor(totalMin/(60*24));
const h = Math.floor((totalMin - d*60*24)/60);
const m = totalMin % 60;
const parts = [];
if(d) parts.push(`${d}d`);
if(h || d) parts.push(`${h}h`);
parts.push(`${m}m`);
return parts.join(' ');
}
function fmtCountdownLong(ms){
if(ms < 0) ms = 0;
const totalSec = Math.floor(ms/1000);
const d = Math.floor(totalSec / (24*3600));
const h = Math.floor((totalSec % (24*3600)) / 3600);
const m = Math.floor((totalSec % 3600) / 60);
const s = totalSec % 60;
const dd = d > 0 ? `${d}d ` : '';
const hh = String(h).padStart(2,'0');
const mm = String(m).padStart(2,'0');
const ss = String(s).padStart(2,'0');
return `${dd}${hh}:${mm}:${ss}`.trim();
}
function todayCZ(){
const now = new Date();
const dd = String(now.getDate()).padStart(2,'0');
const mm = String(now.getMonth()+1).padStart(2,'0');
const yyyy = now.getFullYear();
return `${dd}.${mm}.${yyyy}`;
}
async function fetchData(){
const res = await fetch(DATA_URL_JSON, { cache: 'no-cache' });
if(!res.ok) throw new Error('Failed to fetch data');
const data = await res.json();
state.data = data;
return data;
}
function escapeHTML(s){
if(s == null) return '';
return String(s)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
function truncate(s, max){
const str = s == null ? '' : String(s);
if(max <= 0) return '';
return str.length > max ? str.slice(0, max - 1) + '…' : str;
}
function isWithinMatchWindow(){
if(!state.data) return false;
const now = new Date();
for(const comp of state.data.club_detail.competitions || []){
for(const m of comp.matches || []){
const dt = parseCZDate(m.date_time);
if(!dt) continue;
const diffMs = Math.abs(now - dt);
if(diffMs <= 2*60*60*1000) return true;
}
}
return false;
}
function upcomingMatchesAll(){
const list = [];
if(!state.data) return list;
const now = new Date();
const windowStart = new Date(now.getTime() - 3*24*60*60*1000);
for(const comp of state.data.club_detail.competitions || []){
const candidates = (comp.matches || [])
.map(m=>({ comp, match: m, dt: parseCZDate(m.date_time) }))
.filter(x=> x.dt && x.dt >= windowStart)
.sort((a,b)=> a.dt - b.dt);
if(candidates.length === 0) continue;
// Prefer the latest recently finished match within the 3-day window;
// if none, then choose the next upcoming; if none, fall back to the latest overall in window
let pick = null;
// find latest finished (dt < now) within window
for(let i = candidates.length - 1; i >= 0; i--){
if(candidates[i].dt < now){ pick = candidates[i]; break; }
}
if(!pick){
pick = candidates.find(x=> x.dt >= now) || candidates[candidates.length - 1];
}
list.push(pick);
}
// sort resulting per-competition picks by time ascending for navigation
list.sort((a,b)=> a.dt - b.dt);
return list;
}
function renderUpcoming(){
const root = document.getElementById('facr-upcoming');
if(!root) return;
ensureFacrStyles();
// clear any previous per-second timer
if(state.upcomingTimerId){
clearInterval(state.upcomingTimerId);
state.upcomingTimerId = null;
}
const items = upcomingMatchesAll();
if(items.length === 0){
root.innerHTML = '<div class="lte-football-upcoming"><span class="lte-header lte-header-upcoming">Žádné nadcházející zápasy</span></div>';
return;
}
// Selection policy:
// 1) If there is any finished match within the last 3 days across competitions,
// show the latest such finished match (keep result visible for 3 days)
// 2) Otherwise, show the first future match
// 3) If none, show the latest overall (shouldn't happen as items filtered by 3d window per-comp)
const now = new Date();
const threeDms = 3*24*60*60*1000;
let latestRecentIdx = -1;
let latestRecentTime = -Infinity;
items.forEach((it, i) => {
const dtms = it.dt.getTime();
if(dtms <= now.getTime() && now.getTime() - dtms <= threeDms){
if(dtms > latestRecentTime){ latestRecentTime = dtms; latestRecentIdx = i; }
}
});
let preferredIdx = latestRecentIdx;
if(preferredIdx === -1){
preferredIdx = items.findIndex(it => it.dt >= now);
if(preferredIdx === -1) preferredIdx = items.length - 1;
}
const idx = Math.min(state.matchIndex || preferredIdx, items.length-1);
const { comp, match:m } = items[idx];
const compName = truncate(escapeHTML(comp.name || comp.code || 'Soutěž'), 60);
const homeLogo = m.home_logo_url || 'img/logo.png';
const awayLogo = m.away_logo_url || 'img/logo.png';
const facrLink = m.facr_link || comp.matches_link || state.data.club_detail.url || '#';
const UP_MAX = 24;
const homeName = truncate(escapeHTML(m.home), UP_MAX);
const awayName = truncate(escapeHTML(m.away), UP_MAX);
const dateVenue = truncate(escapeHTML(m.date_time + (m.venue?`, ${m.venue}`:'')), 40);
// Determine if match is today (CZ date) and precompute mid display text
const matchDayCZ = (m.date_time || '').split(' ')[0];
const isToday = matchDayCZ === todayCZ();
const startDt = m.date_time ? parseCZDate(m.date_time) : null;
const diffMsPre = startDt ? (startDt.getTime() - new Date().getTime()) : 0;
const midText = (diffMsPre > 0) ? `Za ${fmtCountdownLong(diffMsPre)}` : (m.score || '-');
// Determine status flags and parse score parts if any
const now2_forTpl = new Date();
const startMs_forTpl = m.date_time ? parseCZDate(m.date_time).getTime() : 0;
const diff_forTpl = startMs_forTpl - now2_forTpl.getTime();
const twoH_forTpl = 2*60*60*1000;
const threeD_forTpl = 3*24*60*60*1000;
const isFuture = diff_forTpl > 0;
const isLive = Math.abs(diff_forTpl) <= twoH_forTpl;
const isRecentFinished = (!isFuture && !isLive && -diff_forTpl < threeD_forTpl);
const scoreStr = m.score || '';
const s1 = scoreStr && scoreStr.includes(':') ? escapeHTML(scoreStr.split(':')[0]) : '';
const s2 = scoreStr && scoreStr.includes(':') ? escapeHTML(scoreStr.split(':')[1]) : '';
// Date/time formatting for display lines
const dtForDisp = startDt || (m.date_time ? parseCZDate(m.date_time) : null);
const dd = dtForDisp ? String(dtForDisp.getDate()).padStart(1,'') : '';
const mm = dtForDisp ? String(dtForDisp.getMonth()+1).padStart(1,'') : '';
const yyyy = dtForDisp ? dtForDisp.getFullYear() : '';
const HH = dtForDisp ? String(dtForDisp.getHours()).padStart(2,'0') : '';
const MM = dtForDisp ? String(dtForDisp.getMinutes()).padStart(2,'0') : '';
const dateOnly = dtForDisp ? `${dd}. ${mm}. ${yyyy}` : '';
const timeToken = (m.date_time || '').split(' ')[1] || '';
const timeOnly = dtForDisp ? `${HH}:${MM}` : '';
const timeDisplay = dtForDisp ? ((timeToken === '' || timeToken === '00:00') ? 'Bude upřesněno' : timeOnly) : '';
const venue = m.venue || '';
const wrapperExtraClass = (isRecentFinished && s1 && s2) ? ' facr-finished' : '';
const headerLabel = isLive ? 'Aktuální zápas' : (isFuture ? 'Nadcházející zápas' : (isRecentFinished ? 'Poslední zápas' : `Zápasy (${idx+1}/${items.length})`));
root.innerHTML = `
<div class="lte-football-upcoming${wrapperExtraClass}">
<div class="facr-comp-title lte-football-date" style="text-align:center; margin-bottom:6px;">${compName}</div>
<div class="facr-upcoming-header">
<button id="facr-prev" class="facr-nav">◀</button>
<span class="lte-header lte-header-upcoming">${headerLabel}</span>
<button id="facr-next" class="facr-nav">▶</button>
</div>
<div class="lte-teams">
<span class="lte-team-name lte-team-1 lte-header" title="${escapeHTML(m.home)}">
<span class="lte-team-logo"><img decoding="async" src="${homeLogo}" alt="${escapeHTML(m.home)}"></span>${homeName}
<span id="facr-inline-status" class="facr-inline-status" aria-live="polite"></span>
${isRecentFinished && s1 ? `<span class="lte-team-count-mob">${s1}</span>` : ''}
</span>
<span class="lte-team-count">
<span id="facr-mid" style="font-size:32px; line-height:1; font-weight:700; display:inline-block; min-width:120px; text-align:center;">${midText}</span>
${isRecentFinished && s1 && s2 ? `<span class="facr-mob-center-score">${s1}<span>:</span>${s2}</span>` : ''}
</span>
<span class="lte-team-name lte-team-2 lte-header" title="${escapeHTML(m.away)}">
${isRecentFinished && s2 ? `<span class=\"lte-team-count-mob\">${s2}</span>` : ''}${awayName}<span class="lte-team-logo"><img decoding="async" src="${awayLogo}" alt="${escapeHTML(m.away)}"></span>
</span>
</div>
<span class="lte-football-date" style="text-align:center;" title="${escapeHTML(m.date_time + (m.venue?`, ${m.venue}`:''))}">${escapeHTML(dateOnly + (venue?`, ${venue}`:''))}</span>
${timeDisplay ? `<span class="lte-football-time" style="display:block; text-align:center;">${escapeHTML(timeDisplay)}</span>` : ''}
<span id="facr-countdown" class="lte-football-date" style="display:block; text-align:center;"></span>
<br>
<a class="lte-football-date" target="_blank" href="${facrLink}" style="text-align:center; background-color:#c42221; color:#ffffff; opacity:1;">Detail na FACR</a>
<span style="display:block; margin-top:6px;"></span>
<a class="lte-football-date" href="#tabulka" style="text-align:center; background-color:#ffffff43; color:#ffffff; opacity:1; width:49%; display:inline-block;">Tabulka bodů</a>
<a class="lte-football-date" href="/zapasy/vsechny.html" style="text-align:center; background-color:#ffffff43; color:#ffffff; opacity:1; width:49%; display:inline-block;">Všechny zápasy</a>
</div>`;
const prev = document.getElementById('facr-prev');
const next = document.getElementById('facr-next');
if(prev) prev.onclick = ()=>{ state.matchIndex = (idx - 1 + items.length) % items.length; renderUpcoming(); };
if(next) next.onclick = ()=>{ state.matchIndex = (idx + 1) % items.length; renderUpcoming(); };
// setup countdown / status text
const cd = document.getElementById('facr-countdown');
const inlineStatus = document.getElementById('facr-inline-status');
if(cd || inlineStatus){
const now2 = new Date();
const startMs = m.date_time ? parseCZDate(m.date_time).getTime() : 0;
const diff = startMs - now2.getTime();
const twoH = 2*60*60*1000;
const threeD = 3*24*60*60*1000;
let text = '';
if(diff > 0){
text = `Začátek za ${fmtCountdown(diff)}`;
}else if(Math.abs(diff) <= twoH){
text = 'Právě probíhá';
}else if(-diff < threeD){
text = (m.score ? `Výsledek: ${m.score}` : 'Ukončeno');
}else{
text = '';
}
if(cd) cd.textContent = text;
if(inlineStatus) inlineStatus.textContent = text;
}
// Live countdown in the middle area when future and not today
const midEl = document.getElementById('facr-mid');
if(midEl){
const startTime = m.date_time ? parseCZDate(m.date_time).getTime() : 0;
function tick(){
const now = Date.now();
const diff = startTime - now;
if(diff > 0){
const longTxt = `Za ${fmtCountdownLong(diff)}`;
midEl.textContent = longTxt;
const inlineEl = document.getElementById('facr-inline-status');
if(inlineEl) inlineEl.textContent = `Začátek za ${fmtCountdown(diff)}`;
const cdEl = document.getElementById('facr-countdown');
if(cdEl) cdEl.textContent = `Začátek za ${fmtCountdown(diff)}`;
}else{
// switch to score at/after kickoff
const scoreTxt = m.score || '-';
midEl.textContent = scoreTxt;
const inlineEl = document.getElementById('facr-inline-status');
if(inlineEl) inlineEl.textContent = (m.score ? `Výsledek: ${m.score}` : 'Ukončeno');
const cdEl = document.getElementById('facr-countdown');
if(cdEl) cdEl.textContent = (m.score ? `Výsledek: ${m.score}` : 'Ukončeno');
if(state.upcomingTimerId){ clearInterval(state.upcomingTimerId); state.upcomingTimerId = null; }
}
}
// Run live countdown for any future match (including today)
if(startTime > Date.now()){
tick();
state.upcomingTimerId = setInterval(tick, 1000);
} else {
// Ensure inline status reflects finished state on initial render
const inlineEl = document.getElementById('facr-inline-status');
if(inlineEl) inlineEl.textContent = (m.score ? `Výsledek: ${m.score}` : 'Ukončeno');
}
}
}
function renderCompetitionTabs(){
const tabs = document.getElementById('facr-comp-tabs');
if(!tabs || !state.data) return;
ensureFacrStyles();
const comps = state.data.club_table.competitions || [];
tabs.innerHTML = comps.map((c,i)=>
`<button class="facr-tab ${i===state.compIndex?'active':''}" data-idx="${i}">${c.name || c.code || 'Soutěž'}</button>`
).join('');
tabs.querySelectorAll('button').forEach(btn=>{
btn.addEventListener('click', ()=>{
state.compIndex = Number(btn.dataset.idx)||0;
renderCompetitionTabs();
renderTable();
});
});
}
function renderTable(){
const tbody = document.getElementById('facr-table-body');
const badge = document.getElementById('facr-comp-badge');
if(!tbody || !state.data) return;
const comps = state.data.club_table.competitions || [];
if(comps.length === 0){ tbody.innerHTML = ''; return; }
const comp = comps[Math.min(state.compIndex, comps.length-1)];
if(badge){ badge.textContent = comp.name || comp.code || 'Soutěž'; }
const rows = comp.table && comp.table.overall ? comp.table.overall : [];
tbody.innerHTML = rows.map(r=>`
<tr>
<td class="lte-row"><span>${r.rank}</span></td>
<td class="lte-club-logo"><img decoding="async" src="${r.team_logo_url || 'img/logo.png'}"></td>
<td class="lte-name">${r.team}</td>
<td class="lte-rate">${r.played}</td>
<td class="lte-rate">${r.wins}</td>
<td class="lte-rate">${r.draws}</td>
<td class="lte-rate">${r.losses}</td>
<td class="lte-rate">${r.score}</td>
<td class="lte-summary">${r.points}</td>
</tr>
`).join('');
}
function renderAllMatches(){
const container = document.getElementById('facr-all-matches');
if(!container || !state.data) return;
const comps = state.data.club_detail.competitions || [];
const sections = [];
for(const comp of comps){
const matches = (comp.matches || [])
.map(m=>({ m, dt: parseCZDate(m.date_time) }))
.filter(x=>!!x.dt)
.sort((a,b)=> b.dt - a.dt);
if(matches.length === 0) continue;
const compName = truncate(escapeHTML(comp.name || comp.code || 'Soutěž'), 40);
const itemsHtml = matches.map(({m})=>{
const homeLogo = m.home_logo_url || '../img/logo.png';
const awayLogo = m.away_logo_url || '../img/logo.png';
const facrLink = m.report_url || comp.matches_link || state.data.club_detail.url || '#';
const score = m.score || '-';
const GRID_MAX = 22;
const home = truncate(escapeHTML(m.home), GRID_MAX);
const away = truncate(escapeHTML(m.away), GRID_MAX);
const dateVenue = truncate(escapeHTML(m.date_time + (m.venue?`, ${m.venue}`:'')), 36);
const s1 = escapeHTML((score.split(':')[0]||'-'));
const s2 = escapeHTML((score.split(':')[1]||'-'));
return `
<a href="${facrLink}" target="_blank" class="lte-item swiper-slide">
<div class="lte-teams lte-match-time-public">
<span class="lte-team-name lte-team-1 lte-header" title="${escapeHTML(m.home)}">
<span class="lte-team-logo"><img src="${homeLogo}" alt="${escapeHTML(m.home)}"></span>${home}</span>
<span class="lte-score-mob lte-score-1">${s1}</span>
<span class="lte-team-count">
<span class="lte-c lte-score-1">${s1}</span>
<span class="lte-d">:</span>
<span class="lte-c lte-score-4">${s2}</span>
</span>
<span class="lte-team-name lte-team-2 lte-header" title="${escapeHTML(m.away)}">${away}
<span class="lte-team-logo"><img src="${awayLogo}" alt="${escapeHTML(m.away)}"></span>
</span>
<span class="lte-score-mob lte-score-4">${s2}</span>
</div>
<div class="lte-footer">
<span class="lte-football-date" title="${escapeHTML(m.date_time + (m.venue?`, ${m.venue}`:''))}">${dateVenue}</span>
</div>
</a>`;
}).join('');
sections.push(`
<div class="lte-section">
<h3 class="lte-header" style="margin: 20px 0 10px;">${compName}</h3>
<div class="lte-football-matches inner-page">${itemsHtml}</div>
</div>
`);
}
container.innerHTML = sections.join('');
}
function schedule(){
if(state.intervalId) clearInterval(state.intervalId);
const intervalMs = isWithinMatchWindow() ? 2*60*1000 : 30*60*1000;
state.intervalId = setInterval(async ()=>{
try{
await fetchData();
renderUpcoming();
renderCompetitionTabs();
renderTable();
renderAllMatches();
schedule(); // reevaluate interval if window changed
}catch(e){ console.warn('refresh failed', e); }
}, intervalMs);
}
async function init(){
try{
await fetchData();
renderUpcoming();
renderCompetitionTabs();
renderTable();
renderAllMatches();
schedule();
}catch(e){
console.error('FACR init failed', e);
}
}
document.addEventListener('DOMContentLoaded', init);
})();
+552 -552
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -6,6 +6,12 @@
if (!res.ok) throw new Error('HTTP '+res.status);
let items = await res.json();
if (!Array.isArray(items) || items.length === 0) items = [];
// Defensive sort: numeric ID descending ensures newest first regardless of API ordering
items.sort((a,b)=>{
const ai = parseInt(a.id,10); const bi = parseInt(b.id,10);
if (!isNaN(ai) && !isNaN(bi)) return bi-ai;
return (b.id||'').localeCompare(a.id||'');
});
// Update background images of zoom slider slides if present
const slides = document.querySelectorAll('.lte-slider-zoom .zs-slides .zs-slide');
+237 -237
View File
@@ -1,238 +1,238 @@
/**
* jQuery plugin paroller.js v1.4.7
* https://github.com/tgomilar/paroller.js
* preview: https://tgomilar.github.io/paroller/
* author: Tanja Gomilar
**/
(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
define('parollerjs', ['jquery'], factory);
} else if (typeof module === 'object' && typeof module.exports === 'object') {
module.exports = factory(require('jquery'));
}
else {
factory(jQuery);
}
})(function ($) {
'use strict';
var working = false;
var scrollAction = function() {
working = false;
};
var setDirection = {
bgVertical: function (elem, bgOffset) {
return elem.css({'background-position': 'center ' + -bgOffset + 'px'});
},
bgHorizontal: function (elem, bgOffset) {
return elem.css({'background-position': -bgOffset + 'px' + ' center'});
},
vertical: function (elem, elemOffset, transition, oldTransform) {
(oldTransform === 'none' ? oldTransform = '' : true);
return elem.css({
'-webkit-transform': 'translateY(' + elemOffset + 'px)' + oldTransform,
'-moz-transform': 'translateY(' + elemOffset + 'px)' + oldTransform,
'transform': 'translateY(' + elemOffset + 'px)' + oldTransform,
'transition': transition,
'will-change': 'transform'
});
},
horizontal: function (elem, elemOffset, transition, oldTransform) {
(oldTransform === 'none' ? oldTransform = '' : true);
return elem.css({
'-webkit-transform': 'translateX(' + elemOffset + 'px)' + oldTransform,
'-moz-transform': 'translateX(' + elemOffset + 'px)' + oldTransform,
'transform': 'translateX(' + elemOffset + 'px)' + oldTransform,
'transition': transition,
'will-change': 'transform'
});
}
};
var setMovement = {
factor: function (elem, width, options) {
var dataFactor = elem.data('paroller-factor');
var factor = (dataFactor) ? dataFactor : options.factor;
if (width < 576) {
var dataFactorXs = elem.data('paroller-factor-xs');
var factorXs = (dataFactorXs) ? dataFactorXs : options.factorXs;
return (factorXs) ? factorXs : factor;
}
else if (width <= 768) {
var dataFactorSm = elem.data('paroller-factor-sm');
var factorSm = (dataFactorSm) ? dataFactorSm : options.factorSm;
return (factorSm) ? factorSm : factor;
}
else if (width <= 1024) {
var dataFactorMd = elem.data('paroller-factor-md');
var factorMd = (dataFactorMd) ? dataFactorMd : options.factorMd;
return (factorMd) ? factorMd : factor;
}
else if (width <= 1200) {
var dataFactorLg = elem.data('paroller-factor-lg');
var factorLg = (dataFactorLg) ? dataFactorLg : options.factorLg;
return (factorLg) ? factorLg : factor;
} else if (width <= 1920) {
var dataFactorXl = elem.data('paroller-factor-xl');
var factorXl = (dataFactorXl) ? dataFactorXl : options.factorXl;
return (factorXl) ? factorXl : factor;
} else {
return factor;
}
},
bgOffset: function (offset, factor) {
return Math.round(offset * factor);
},
transform: function (offset, factor, windowHeight, height) {
return Math.round((offset - (windowHeight / 2) + height) * factor);
}
};
var clearPositions = {
background: function (elem) {
return elem.css({'background-position': 'unset'});
},
foreground: function (elem) {
return elem.css({
'transform' : 'unset',
'transition' : 'unset'
});
}
};
$.fn.paroller = function (options) {
var windowHeight = $(window).height();
var documentHeight = $(document).height();
// default options
var options = $.extend({
factor: 0, // - to +
factorXs: 0, // - to +
factorSm: 0, // - to +
factorMd: 0, // - to +
factorLg: 0, // - to +
factorXl: 0, // - to +
transition: 'translate 0.1s ease', // CSS transition
type: 'background', // foreground
direction: 'vertical', // horizontal
offsetVal : 0, // horizontal
}, options);
return this.each(function () {
var $this = $(this);
var width = $(window).width();
var offset = $this.offset().top;
var height = $this.outerHeight();
var dataType = $this.data('paroller-type');
var dataDirection = $this.data('paroller-direction');
var dataTransition = $this.data('paroller-transition');
var oldTransform = $this.css('transform');
var offsetVal = parseInt($this.data('offset'));
var transition = (dataTransition) ? dataTransition : options.transition;
var type = (dataType) ? dataType : options.type;
var direction = (dataDirection) ? dataDirection : options.direction;
var factor = 0;
var bgOffset = setMovement.bgOffset(offset, factor);
var transform = setMovement.transform(offset, factor, windowHeight, height);
if (type === 'background') {
if (direction === 'vertical') {
setDirection.bgVertical($this, bgOffset);
}
else if (direction === 'horizontal') {
setDirection.bgHorizontal($this, bgOffset);
}
}
else if (type === 'foreground') {
if (direction === 'vertical') {
setDirection.vertical($this, transform, transition, oldTransform);
}
else if (direction === 'horizontal') {
setDirection.horizontal($this, transform, transition, oldTransform);
}
}
$(window).on('resize', function () {
var scrolling = $(this).scrollTop();
width = $(window).width();
offset = $this.offset().top;
height = $this.outerHeight();
factor = setMovement.factor($this, width, options);
bgOffset = Math.round(offset * factor);
transform = Math.round((offset - (windowHeight / 2) + height) * factor);
/*if ( offsetVal != 0 )*/
offset = offset - 400;
if (! working) {
window.requestAnimationFrame(scrollAction);
working = true;
}
if (type === 'background') {
clearPositions.background($this);
if (direction === 'vertical') {
setDirection.bgVertical($this, bgOffset);
}
else if (direction === 'horizontal') {
setDirection.bgHorizontal($this, bgOffset);
}
}
else if ((type === 'foreground') && (scrolling <= documentHeight)) {
clearPositions.foreground($this);
if (direction === 'vertical') {
setDirection.vertical($this, transform, transition);
}
else if (direction === 'horizontal') {
setDirection.horizontal($this, transform, transition);
}
}
});
$(window).on('scroll', function () {
var scrolling = $(this).scrollTop();
var scrollTop = $(document).scrollTop();
if (scrollTop === 0) {
factor = 0;
} else {
factor = setMovement.factor($this, width, options);
}
bgOffset = Math.round((offset - scrolling) * factor);
transform = Math.round(((offset - (windowHeight / 2) + height) - scrolling) * factor);
if (! working) {
window.requestAnimationFrame(scrollAction);
working = true;
}
if (type === 'background') {
if (direction === 'vertical') {
setDirection.bgVertical($this, bgOffset);
}
else if (direction === 'horizontal') {
setDirection.bgHorizontal($this, bgOffset);
}
}
else if ((type === 'foreground') && (scrolling <= documentHeight)) {
if (direction === 'vertical') {
setDirection.vertical($this, transform, transition, oldTransform);
}
else if (direction === 'horizontal') {
setDirection.horizontal($this, transform, transition, oldTransform);
}
}
});
});
};
/**
* jQuery plugin paroller.js v1.4.7
* https://github.com/tgomilar/paroller.js
* preview: https://tgomilar.github.io/paroller/
* author: Tanja Gomilar
**/
(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
define('parollerjs', ['jquery'], factory);
} else if (typeof module === 'object' && typeof module.exports === 'object') {
module.exports = factory(require('jquery'));
}
else {
factory(jQuery);
}
})(function ($) {
'use strict';
var working = false;
var scrollAction = function() {
working = false;
};
var setDirection = {
bgVertical: function (elem, bgOffset) {
return elem.css({'background-position': 'center ' + -bgOffset + 'px'});
},
bgHorizontal: function (elem, bgOffset) {
return elem.css({'background-position': -bgOffset + 'px' + ' center'});
},
vertical: function (elem, elemOffset, transition, oldTransform) {
(oldTransform === 'none' ? oldTransform = '' : true);
return elem.css({
'-webkit-transform': 'translateY(' + elemOffset + 'px)' + oldTransform,
'-moz-transform': 'translateY(' + elemOffset + 'px)' + oldTransform,
'transform': 'translateY(' + elemOffset + 'px)' + oldTransform,
'transition': transition,
'will-change': 'transform'
});
},
horizontal: function (elem, elemOffset, transition, oldTransform) {
(oldTransform === 'none' ? oldTransform = '' : true);
return elem.css({
'-webkit-transform': 'translateX(' + elemOffset + 'px)' + oldTransform,
'-moz-transform': 'translateX(' + elemOffset + 'px)' + oldTransform,
'transform': 'translateX(' + elemOffset + 'px)' + oldTransform,
'transition': transition,
'will-change': 'transform'
});
}
};
var setMovement = {
factor: function (elem, width, options) {
var dataFactor = elem.data('paroller-factor');
var factor = (dataFactor) ? dataFactor : options.factor;
if (width < 576) {
var dataFactorXs = elem.data('paroller-factor-xs');
var factorXs = (dataFactorXs) ? dataFactorXs : options.factorXs;
return (factorXs) ? factorXs : factor;
}
else if (width <= 768) {
var dataFactorSm = elem.data('paroller-factor-sm');
var factorSm = (dataFactorSm) ? dataFactorSm : options.factorSm;
return (factorSm) ? factorSm : factor;
}
else if (width <= 1024) {
var dataFactorMd = elem.data('paroller-factor-md');
var factorMd = (dataFactorMd) ? dataFactorMd : options.factorMd;
return (factorMd) ? factorMd : factor;
}
else if (width <= 1200) {
var dataFactorLg = elem.data('paroller-factor-lg');
var factorLg = (dataFactorLg) ? dataFactorLg : options.factorLg;
return (factorLg) ? factorLg : factor;
} else if (width <= 1920) {
var dataFactorXl = elem.data('paroller-factor-xl');
var factorXl = (dataFactorXl) ? dataFactorXl : options.factorXl;
return (factorXl) ? factorXl : factor;
} else {
return factor;
}
},
bgOffset: function (offset, factor) {
return Math.round(offset * factor);
},
transform: function (offset, factor, windowHeight, height) {
return Math.round((offset - (windowHeight / 2) + height) * factor);
}
};
var clearPositions = {
background: function (elem) {
return elem.css({'background-position': 'unset'});
},
foreground: function (elem) {
return elem.css({
'transform' : 'unset',
'transition' : 'unset'
});
}
};
$.fn.paroller = function (options) {
var windowHeight = $(window).height();
var documentHeight = $(document).height();
// default options
var options = $.extend({
factor: 0, // - to +
factorXs: 0, // - to +
factorSm: 0, // - to +
factorMd: 0, // - to +
factorLg: 0, // - to +
factorXl: 0, // - to +
transition: 'translate 0.1s ease', // CSS transition
type: 'background', // foreground
direction: 'vertical', // horizontal
offsetVal : 0, // horizontal
}, options);
return this.each(function () {
var $this = $(this);
var width = $(window).width();
var offset = $this.offset().top;
var height = $this.outerHeight();
var dataType = $this.data('paroller-type');
var dataDirection = $this.data('paroller-direction');
var dataTransition = $this.data('paroller-transition');
var oldTransform = $this.css('transform');
var offsetVal = parseInt($this.data('offset'));
var transition = (dataTransition) ? dataTransition : options.transition;
var type = (dataType) ? dataType : options.type;
var direction = (dataDirection) ? dataDirection : options.direction;
var factor = 0;
var bgOffset = setMovement.bgOffset(offset, factor);
var transform = setMovement.transform(offset, factor, windowHeight, height);
if (type === 'background') {
if (direction === 'vertical') {
setDirection.bgVertical($this, bgOffset);
}
else if (direction === 'horizontal') {
setDirection.bgHorizontal($this, bgOffset);
}
}
else if (type === 'foreground') {
if (direction === 'vertical') {
setDirection.vertical($this, transform, transition, oldTransform);
}
else if (direction === 'horizontal') {
setDirection.horizontal($this, transform, transition, oldTransform);
}
}
$(window).on('resize', function () {
var scrolling = $(this).scrollTop();
width = $(window).width();
offset = $this.offset().top;
height = $this.outerHeight();
factor = setMovement.factor($this, width, options);
bgOffset = Math.round(offset * factor);
transform = Math.round((offset - (windowHeight / 2) + height) * factor);
/*if ( offsetVal != 0 )*/
offset = offset - 400;
if (! working) {
window.requestAnimationFrame(scrollAction);
working = true;
}
if (type === 'background') {
clearPositions.background($this);
if (direction === 'vertical') {
setDirection.bgVertical($this, bgOffset);
}
else if (direction === 'horizontal') {
setDirection.bgHorizontal($this, bgOffset);
}
}
else if ((type === 'foreground') && (scrolling <= documentHeight)) {
clearPositions.foreground($this);
if (direction === 'vertical') {
setDirection.vertical($this, transform, transition);
}
else if (direction === 'horizontal') {
setDirection.horizontal($this, transform, transition);
}
}
});
$(window).on('scroll', function () {
var scrolling = $(this).scrollTop();
var scrollTop = $(document).scrollTop();
if (scrollTop === 0) {
factor = 0;
} else {
factor = setMovement.factor($this, width, options);
}
bgOffset = Math.round((offset - scrolling) * factor);
transform = Math.round(((offset - (windowHeight / 2) + height) - scrolling) * factor);
if (! working) {
window.requestAnimationFrame(scrollAction);
working = true;
}
if (type === 'background') {
if (direction === 'vertical') {
setDirection.bgVertical($this, bgOffset);
}
else if (direction === 'horizontal') {
setDirection.bgHorizontal($this, bgOffset);
}
}
else if ((type === 'foreground') && (scrolling <= documentHeight)) {
if (direction === 'vertical') {
setDirection.vertical($this, transform, transition, oldTransform);
}
else if (direction === 'horizontal') {
setDirection.horizontal($this, transform, transition, oldTransform);
}
}
});
});
};
});
+409 -409
View File
@@ -1,409 +1,409 @@
/*
* zoomSlider - v1.0.2 Fork
* CSS3 background zoom slideshow
* http://mingthings.com
*
* Made by Ming Yeung
* Under MIT License
*/
;(function ( $, window, document, undefined ) {
var pluginName = "zoomSlider",
defaults = {
src: null,
src2: null,
speed: 8000,
initzoom: 1.2,
switchSpeed: 1000,
interval: 4600,
autoplay: true,
bullets: true,
overlay: 'plain' // false, plain, dots
};
// The actual plugin constructor
function Plugin ( element, options ) {
this.element = element;
this.$el = $(element);
this._defaults = defaults;
this._name = pluginName;
var elData = this.$el.data();
var elDataObj = {};
for (var key in elData) {
if ( elData.hasOwnProperty(key) ) {
if ( key.match(/zs[A-Z]/) ) {
var keyName = key.substr(2);
keyName = keyName.charAt(0).toLowerCase() + keyName.slice(1);
elDataObj[keyName] = elData[key]
}
}
}
this.settings = $.extend( {}, defaults, elDataObj, options );
if ( this.settings.src == null || this.settings.src.length < 1 ) {
console.log('ZoomSlider terminated - invalid input.');
return;
}
this.init();
}
// Avoid Plugin.prototype conflicts
$.extend(Plugin.prototype, {
init: function () {
// Place initialization logic here
// You already have access to the DOM element and
// the options via the instance, e.g. this.element
// and this.settings
// you can add more functions like the one below and
// call them like so: this.yourOtherFunction(this.element, this.settings).
// make sure src is an Array
if ($.isArray(this.settings.src) == false) {
this.settings.src = [this.settings.src];
}
if ($.isArray(this.settings.src2) == false) {
this.settings.src2 = [this.settings.src2];
}
// https://github.com/twitter/bootstrap/issues/2870
this.transEndEventNames = {
'WebkitTransition' : 'webkitTransitionEnd',
'MozTransition' : 'transitionend',
'OTransition' : 'oTransitionEnd',
'msTransition' : 'MSTransitionEnd',
'transition' : 'transitionend'
};
this.transEndEventName = this.transEndEventNames[ Modernizr.prefixed( 'transition' ) ];
// suport for css transforms and css transitions
this.support = Modernizr.csstransitions && Modernizr.csstransforms;
// set inline CSS3 transition properties
var transformPrefixed = Modernizr.prefixed('transform');
transformPrefixed = transformPrefixed.replace(/([A-Z])/g, function(transformPrefixed,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
this.transitionProp = {
'transition': transformPrefixed+' '+this.settings.speed+'ms ease-out, opacity '+this.settings.switchSpeed+'ms'
};
this.numSlides = this.settings.src.length;
// make sure the container is not [position: static]
switch(this.$el.css('position')) {
case 'relative':
case 'absolute':
case 'fixed':
break;
default:
this.$el.css('position', 'relative');
break;
}
// make sure the first image has been loaded.
var self = this;
var $img = $('<img />');
//$img.load( function() {
if (self.numSlides == 1) {
self.initSingle();
} else {
self.initSlideshow();
}
//});
$img.attr('src', this.settings.src[0]);
},
initSlideshow: function () {
var self = this;
var $slideshow = $('<div class="zs-slideshow"></div>'),
$slidesWrap = $('<div class="zs-slides"></div>'),
$arrowsWrap = $('<div class="zs-arrows"></div>'),
$zslayer = $('<div class="zs-layer"></div>'),
$bulletsWrap = $('<div class="zs-bullets"></div>'),
$ww = $(window).width();
for (i = 0; i < this.numSlides; i++) {
var $slide = $('<div class="zs-slide zs-slide-' + i + '"></div>');
if ( $ww <= 767 && this.settings.src2[i].length ) {
$slide.css({ 'background-image': "url('" + this.settings.src2[i] + "')" }).appendTo( $slidesWrap );
}
else {
$slide.css({ 'background-image': "url('" + this.settings.src[i] + "')" }).appendTo( $slidesWrap );
}
var $bullet = $('<div class="zs-bullet zs-bullet-' + i + '"></div>')
$bullet.appendTo( $bulletsWrap );
if (i == 0) {
$slide.addClass('active').css('opacity', 1);
$bullet.addClass('active');
$('.zs-enabled .lte-zs-slider-inner.lte-zs-slide-' + i).addClass('visible');
}
}
self._promoteChildren();
$slideshow.append( $zslayer );
$slideshow.append( $slidesWrap ).prependTo( this.$el );
if ( this.settings.bullets != false || this.settings.bullets == 'outside' ) {
if ( this.settings.bullets == 'outside' ) {
$slideshow.after( $bulletsWrap );
}
else {
$slideshow.append( $bulletsWrap );
}
$slideshow.on('click', '.zs-bullet', function(e){
self.jump( $(this).index() );
});
}
if ( this.settings.arrows == true || this.settings.arrows == 'right' || this.settings.arrows == 'bottom' ) {
var container_class = '';
if ( this.settings.arrows == 'bottom' ) {
container_class = 'container';
}
$('<div class="'+container_class+'"><span class="lte-arrow-left">'+this.settings.prev+'</span><span class="lte-arrow-right">'+this.settings.next+'</span></div>').appendTo( $arrowsWrap );
this.$el.append( $arrowsWrap );
this.$el.on('click', '.lte-arrow-left', function(e){
self.prev();
});
this.$el.on('click', '.lte-arrow-right', function(e){
self.next() ;
});
}
this.pos = 0;
this.pending = null;
this.switching = false;
this.$slideshow = $slideshow;
this.$slides = $slidesWrap.children( '.zs-slide' );
this.$bullets = $bulletsWrap.children( '.zs-bullet' );
this.$el.addClass('zs-enabled');
var $firstBlock = $('.zs-enabled .lte-zs-slider-inner');
$('.zs-enabled .lte-zs-slider-inner').css('opacity', '');
var minHeight = 0;
$('.lte-zs-slider-inner').each(function(i, el) {
if ( $(el).height() > minHeight ) {
minHeight = $(el).height();
}
});
if (this.support) {
var $firstSlide = this.$slides.eq(0);
var $initzoom = this.settings.initzoom;
$firstSlide.css('opacity', 0).css( this.transitionProp );
$('.lte-zs-slider-wrapper').css('min-height', (minHeight ) + 'px' );
$('.zs-slideshow').css('min-height', (minHeight - 2 ) + 'px' );
jQuery(window).on('resize', function(){
var minHeight = 0;
$('.lte-zs-slider-inner').each(function(i, el) {
if ( $(el).height() > minHeight ) {
minHeight = $(el).height();
}
});
$('.lte-zs-slider-wrapper').css('min-height', (minHeight ) + 'px' );
$('.zs-slideshow').css('min-height', (minHeight - 2 ) + 'px' );
});
setTimeout(function(){
$firstSlide.css( { 'opacity': 1.0, 'transform': 'scale('+ $initzoom +', '+ $initzoom +')', 'z-index': 2 } );
}, 50);
}
if (this.settings.autoplay == true) {
this.play();
}
},
initSingle: function() {
var self = this;
var $slideshow = $('<div class="zs-slideshow"></div>'),
$slidesWrap = $('<div class="zs-slides"></div>'),
$slide = $('<div class="zs-slide zs-slide-0"></div>');
$slide.css({ 'background-image': "url('" + this.settings.src[0] + "')" }).appendTo( $slidesWrap );
$slide.addClass('active').css('opacity', 1);
$('.zs-enabled .lte-zs-slider-inner.lte-zs-slide-0').addClass('visible').addClass('single');
self._promoteChildren();
$slideshow.append( $slidesWrap ).prependTo( this.$el );
this.$el.addClass('zs-enabled');
if (this.settings.overlay == 'dots') {
this.$el.addClass('overlay-dots');
} else if (this.settings.overlay == 'plain') {
this.$el.addClass('overlay-plain')
}
if (this.support) {
$slide.css('opacity', 1).css( this.transitionProp );
if (this.settings) {
setTimeout(function(){
$slide.css( { 'opacity': 1.0, 'transform': 'scale(1)', 'z-index': 2 } )
}, 50);
}
}
},
_promoteChildren: function() {
// make sure every children have high enough z-index
this.$el.children().each(function(index){
$this = $(this);
if ($this.css('z-index') == 'auto') {
$this.css('z-index', 2);
}
if ($this.css('position') == 'static') {
$this.css('position', 'relative');
}
});
},
jump: function( pos ) {
if ( pos >= this.numSlides ) {
console.log('ZoomSlider: jump(pos) aborted. supplied index out of range.');
return;
}
if ( this.pos == pos ) return;
if ( this.switching ) {
this.pending = pos;
return;
}
var self = this;
var $lastSlide = this.$slides.eq( this.pos );
var $nowSlide = this.$slides.eq( pos );
$('.zs-enabled .lte-zoompages .current').html(pos + 1);
$('.zs-enabled .lte-zs-slider-inner.visible').removeClass('visible');
$('.zs-enabled .lte-zs-slider-inner.lte-zs-slide-' + pos).addClass('visible');
if ( this.support ) {
this.switching = true;
$lastSlide.css('z-index', 1);
$nowSlide.addClass('active')
.css( this.transitionProp )
.css( { 'opacity': 1.0, 'transform': 'scale('+this.settings.initzoom+', '+this.settings.initzoom+')', 'z-index': 2 } )
.on( this.transEndEventName, function(e) {
if (e.originalEvent.propertyName == 'opacity') {
lastSlideBg = $lastSlide.css('background-image');
$lastSlide.removeClass('active')
.removeAttr('style')
.css('background-image', lastSlideBg);
$nowSlide.off( self.transEndEventName );
self.switching = false;
if ( self.pending != null ) {
setTimeout(function(){
var newPos = self.pending;
self.pending = null;
self.$bullets.eq(newPos).click();
}, 30)
}
}
});
} else {
$lastSlide.removeClass('active');
$nowSlide.addClass('active');
}
this.$bullets.eq(this.pos).removeClass('active');
this.$bullets.eq(pos).addClass('active');
this.pos = pos;
if (this.settings.autoplay) {
this.play();
}
},
prev: function() {
var posPrev = this.pos - 1;
if (posPrev < 0) posPrev = this.numSlides - 1;
this.jump( posPrev );
},
next: function() {
var posNext = this.pos + 1;
if (posNext >= this.numSlides) posNext = 0;
this.jump( posNext );
},
play: function() {
// clear any existing timer
if (this.timer != null) {
clearInterval(this.timer);
}
var self = this;
this.settings.autoplay = true;
// add timer
this.timer = setInterval( function(){
self.next();
}, this.settings.interval );
},
stop: function() {
this.settings.autoplay = false;
clearInterval(this.timer);
this.timer = null;
}
});
// A really lightweight plugin wrapper around the constructor,
// preventing against multiple instantiations
$.fn[ pluginName ] = function ( options ) {
return this.each(function() {
if ( !$.data( this, "plugin_" + pluginName ) ) {
$.data( this, "plugin_" + pluginName, new Plugin( this, options ) );
}
});
};
var WidgetZoomsliderHandler = function ($scope, $) {
// auto create slideshow on [data-zs-enabled] instances.
var $instances = $('[data-zs-src]');
if ($instances.length > 0) {
$instances.each( function(index) {
var $this = $(this);
$this.zoomSlider();
});
}
};
$(window).on('elementor/frontend/init', function () {
elementorFrontend.hooks.addAction('frontend/element_ready/lte-zoomslider.default', WidgetZoomsliderHandler);
});
})( jQuery, window, document );
/*
* zoomSlider - v1.0.2 Fork
* CSS3 background zoom slideshow
* http://mingthings.com
*
* Made by Ming Yeung
* Under MIT License
*/
;(function ( $, window, document, undefined ) {
var pluginName = "zoomSlider",
defaults = {
src: null,
src2: null,
speed: 8000,
initzoom: 1.2,
switchSpeed: 1000,
interval: 4600,
autoplay: true,
bullets: true,
overlay: 'plain' // false, plain, dots
};
// The actual plugin constructor
function Plugin ( element, options ) {
this.element = element;
this.$el = $(element);
this._defaults = defaults;
this._name = pluginName;
var elData = this.$el.data();
var elDataObj = {};
for (var key in elData) {
if ( elData.hasOwnProperty(key) ) {
if ( key.match(/zs[A-Z]/) ) {
var keyName = key.substr(2);
keyName = keyName.charAt(0).toLowerCase() + keyName.slice(1);
elDataObj[keyName] = elData[key]
}
}
}
this.settings = $.extend( {}, defaults, elDataObj, options );
if ( this.settings.src == null || this.settings.src.length < 1 ) {
console.log('ZoomSlider terminated - invalid input.');
return;
}
this.init();
}
// Avoid Plugin.prototype conflicts
$.extend(Plugin.prototype, {
init: function () {
// Place initialization logic here
// You already have access to the DOM element and
// the options via the instance, e.g. this.element
// and this.settings
// you can add more functions like the one below and
// call them like so: this.yourOtherFunction(this.element, this.settings).
// make sure src is an Array
if ($.isArray(this.settings.src) == false) {
this.settings.src = [this.settings.src];
}
if ($.isArray(this.settings.src2) == false) {
this.settings.src2 = [this.settings.src2];
}
// https://github.com/twitter/bootstrap/issues/2870
this.transEndEventNames = {
'WebkitTransition' : 'webkitTransitionEnd',
'MozTransition' : 'transitionend',
'OTransition' : 'oTransitionEnd',
'msTransition' : 'MSTransitionEnd',
'transition' : 'transitionend'
};
this.transEndEventName = this.transEndEventNames[ Modernizr.prefixed( 'transition' ) ];
// suport for css transforms and css transitions
this.support = Modernizr.csstransitions && Modernizr.csstransforms;
// set inline CSS3 transition properties
var transformPrefixed = Modernizr.prefixed('transform');
transformPrefixed = transformPrefixed.replace(/([A-Z])/g, function(transformPrefixed,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
this.transitionProp = {
'transition': transformPrefixed+' '+this.settings.speed+'ms ease-out, opacity '+this.settings.switchSpeed+'ms'
};
this.numSlides = this.settings.src.length;
// make sure the container is not [position: static]
switch(this.$el.css('position')) {
case 'relative':
case 'absolute':
case 'fixed':
break;
default:
this.$el.css('position', 'relative');
break;
}
// make sure the first image has been loaded.
var self = this;
var $img = $('<img />');
//$img.load( function() {
if (self.numSlides == 1) {
self.initSingle();
} else {
self.initSlideshow();
}
//});
$img.attr('src', this.settings.src[0]);
},
initSlideshow: function () {
var self = this;
var $slideshow = $('<div class="zs-slideshow"></div>'),
$slidesWrap = $('<div class="zs-slides"></div>'),
$arrowsWrap = $('<div class="zs-arrows"></div>'),
$zslayer = $('<div class="zs-layer"></div>'),
$bulletsWrap = $('<div class="zs-bullets"></div>'),
$ww = $(window).width();
for (i = 0; i < this.numSlides; i++) {
var $slide = $('<div class="zs-slide zs-slide-' + i + '"></div>');
if ( $ww <= 767 && this.settings.src2[i].length ) {
$slide.css({ 'background-image': "url('" + this.settings.src2[i] + "')" }).appendTo( $slidesWrap );
}
else {
$slide.css({ 'background-image': "url('" + this.settings.src[i] + "')" }).appendTo( $slidesWrap );
}
var $bullet = $('<div class="zs-bullet zs-bullet-' + i + '"></div>')
$bullet.appendTo( $bulletsWrap );
if (i == 0) {
$slide.addClass('active').css('opacity', 1);
$bullet.addClass('active');
$('.zs-enabled .lte-zs-slider-inner.lte-zs-slide-' + i).addClass('visible');
}
}
self._promoteChildren();
$slideshow.append( $zslayer );
$slideshow.append( $slidesWrap ).prependTo( this.$el );
if ( this.settings.bullets != false || this.settings.bullets == 'outside' ) {
if ( this.settings.bullets == 'outside' ) {
$slideshow.after( $bulletsWrap );
}
else {
$slideshow.append( $bulletsWrap );
}
$slideshow.on('click', '.zs-bullet', function(e){
self.jump( $(this).index() );
});
}
if ( this.settings.arrows == true || this.settings.arrows == 'right' || this.settings.arrows == 'bottom' ) {
var container_class = '';
if ( this.settings.arrows == 'bottom' ) {
container_class = 'container';
}
$('<div class="'+container_class+'"><span class="lte-arrow-left">'+this.settings.prev+'</span><span class="lte-arrow-right">'+this.settings.next+'</span></div>').appendTo( $arrowsWrap );
this.$el.append( $arrowsWrap );
this.$el.on('click', '.lte-arrow-left', function(e){
self.prev();
});
this.$el.on('click', '.lte-arrow-right', function(e){
self.next() ;
});
}
this.pos = 0;
this.pending = null;
this.switching = false;
this.$slideshow = $slideshow;
this.$slides = $slidesWrap.children( '.zs-slide' );
this.$bullets = $bulletsWrap.children( '.zs-bullet' );
this.$el.addClass('zs-enabled');
var $firstBlock = $('.zs-enabled .lte-zs-slider-inner');
$('.zs-enabled .lte-zs-slider-inner').css('opacity', '');
var minHeight = 0;
$('.lte-zs-slider-inner').each(function(i, el) {
if ( $(el).height() > minHeight ) {
minHeight = $(el).height();
}
});
if (this.support) {
var $firstSlide = this.$slides.eq(0);
var $initzoom = this.settings.initzoom;
$firstSlide.css('opacity', 0).css( this.transitionProp );
$('.lte-zs-slider-wrapper').css('min-height', (minHeight ) + 'px' );
$('.zs-slideshow').css('min-height', (minHeight - 2 ) + 'px' );
jQuery(window).on('resize', function(){
var minHeight = 0;
$('.lte-zs-slider-inner').each(function(i, el) {
if ( $(el).height() > minHeight ) {
minHeight = $(el).height();
}
});
$('.lte-zs-slider-wrapper').css('min-height', (minHeight ) + 'px' );
$('.zs-slideshow').css('min-height', (minHeight - 2 ) + 'px' );
});
setTimeout(function(){
$firstSlide.css( { 'opacity': 1.0, 'transform': 'scale('+ $initzoom +', '+ $initzoom +')', 'z-index': 2 } );
}, 50);
}
if (this.settings.autoplay == true) {
this.play();
}
},
initSingle: function() {
var self = this;
var $slideshow = $('<div class="zs-slideshow"></div>'),
$slidesWrap = $('<div class="zs-slides"></div>'),
$slide = $('<div class="zs-slide zs-slide-0"></div>');
$slide.css({ 'background-image': "url('" + this.settings.src[0] + "')" }).appendTo( $slidesWrap );
$slide.addClass('active').css('opacity', 1);
$('.zs-enabled .lte-zs-slider-inner.lte-zs-slide-0').addClass('visible').addClass('single');
self._promoteChildren();
$slideshow.append( $slidesWrap ).prependTo( this.$el );
this.$el.addClass('zs-enabled');
if (this.settings.overlay == 'dots') {
this.$el.addClass('overlay-dots');
} else if (this.settings.overlay == 'plain') {
this.$el.addClass('overlay-plain')
}
if (this.support) {
$slide.css('opacity', 1).css( this.transitionProp );
if (this.settings) {
setTimeout(function(){
$slide.css( { 'opacity': 1.0, 'transform': 'scale(1)', 'z-index': 2 } )
}, 50);
}
}
},
_promoteChildren: function() {
// make sure every children have high enough z-index
this.$el.children().each(function(index){
$this = $(this);
if ($this.css('z-index') == 'auto') {
$this.css('z-index', 2);
}
if ($this.css('position') == 'static') {
$this.css('position', 'relative');
}
});
},
jump: function( pos ) {
if ( pos >= this.numSlides ) {
console.log('ZoomSlider: jump(pos) aborted. supplied index out of range.');
return;
}
if ( this.pos == pos ) return;
if ( this.switching ) {
this.pending = pos;
return;
}
var self = this;
var $lastSlide = this.$slides.eq( this.pos );
var $nowSlide = this.$slides.eq( pos );
$('.zs-enabled .lte-zoompages .current').html(pos + 1);
$('.zs-enabled .lte-zs-slider-inner.visible').removeClass('visible');
$('.zs-enabled .lte-zs-slider-inner.lte-zs-slide-' + pos).addClass('visible');
if ( this.support ) {
this.switching = true;
$lastSlide.css('z-index', 1);
$nowSlide.addClass('active')
.css( this.transitionProp )
.css( { 'opacity': 1.0, 'transform': 'scale('+this.settings.initzoom+', '+this.settings.initzoom+')', 'z-index': 2 } )
.on( this.transEndEventName, function(e) {
if (e.originalEvent.propertyName == 'opacity') {
lastSlideBg = $lastSlide.css('background-image');
$lastSlide.removeClass('active')
.removeAttr('style')
.css('background-image', lastSlideBg);
$nowSlide.off( self.transEndEventName );
self.switching = false;
if ( self.pending != null ) {
setTimeout(function(){
var newPos = self.pending;
self.pending = null;
self.$bullets.eq(newPos).click();
}, 30)
}
}
});
} else {
$lastSlide.removeClass('active');
$nowSlide.addClass('active');
}
this.$bullets.eq(this.pos).removeClass('active');
this.$bullets.eq(pos).addClass('active');
this.pos = pos;
if (this.settings.autoplay) {
this.play();
}
},
prev: function() {
var posPrev = this.pos - 1;
if (posPrev < 0) posPrev = this.numSlides - 1;
this.jump( posPrev );
},
next: function() {
var posNext = this.pos + 1;
if (posNext >= this.numSlides) posNext = 0;
this.jump( posNext );
},
play: function() {
// clear any existing timer
if (this.timer != null) {
clearInterval(this.timer);
}
var self = this;
this.settings.autoplay = true;
// add timer
this.timer = setInterval( function(){
self.next();
}, this.settings.interval );
},
stop: function() {
this.settings.autoplay = false;
clearInterval(this.timer);
this.timer = null;
}
});
// A really lightweight plugin wrapper around the constructor,
// preventing against multiple instantiations
$.fn[ pluginName ] = function ( options ) {
return this.each(function() {
if ( !$.data( this, "plugin_" + pluginName ) ) {
$.data( this, "plugin_" + pluginName, new Plugin( this, options ) );
}
});
};
var WidgetZoomsliderHandler = function ($scope, $) {
// auto create slideshow on [data-zs-enabled] instances.
var $instances = $('[data-zs-src]');
if ($instances.length > 0) {
$instances.each( function(index) {
var $this = $(this);
$this.zoomSlider();
});
}
};
$(window).on('elementor/frontend/init', function () {
elementorFrontend.hooks.addAction('frontend/element_ready/lte-zoomslider.default', WidgetZoomsliderHandler);
});
})( jQuery, window, document );
+40 -40
View File
@@ -1,41 +1,41 @@
document.addEventListener("DOMContentLoaded", function() {
// Get the buttons and the navbar element
const openButton = document.getElementById('open-button');
const closeButton = document.getElementById('close-button');
const navbar = document.getElementById('navbar');
// Log to check if elements exist
console.log('Open button:', openButton);
console.log('Close button:', closeButton);
console.log('Navbar:', navbar);
// Ensure that buttons and navbar exist
if (openButton && closeButton && navbar) {
console.log('Elements found and event listeners ready.');
// Add event listener to the open button to remove the collapse class
openButton.addEventListener('click', function() {
console.log('Open button clicked');
if (navbar.classList.contains('collapse')) {
navbar.classList.remove('collapse');
console.log('Collapse class removed');
} else {
console.log('Navbar is already open (no collapse class).');
}
});
// Add event listener to the close button to add the collapse class
closeButton.addEventListener('click', function() {
console.log('Close button clicked');
if (!navbar.classList.contains('collapse')) {
navbar.classList.add('collapse');
console.log('Collapse class added');
} else {
console.log('Navbar is already collapsed (collapse class exists).');
}
});
} else {
console.error('Error: Buttons or navbar element not found.');
}
document.addEventListener("DOMContentLoaded", function() {
// Get the buttons and the navbar element
const openButton = document.getElementById('open-button');
const closeButton = document.getElementById('close-button');
const navbar = document.getElementById('navbar');
// Log to check if elements exist
console.log('Open button:', openButton);
console.log('Close button:', closeButton);
console.log('Navbar:', navbar);
// Ensure that buttons and navbar exist
if (openButton && closeButton && navbar) {
console.log('Elements found and event listeners ready.');
// Add event listener to the open button to remove the collapse class
openButton.addEventListener('click', function() {
console.log('Open button clicked');
if (navbar.classList.contains('collapse')) {
navbar.classList.remove('collapse');
console.log('Collapse class removed');
} else {
console.log('Navbar is already open (no collapse class).');
}
});
// Add event listener to the close button to add the collapse class
closeButton.addEventListener('click', function() {
console.log('Close button clicked');
if (!navbar.classList.contains('collapse')) {
navbar.classList.add('collapse');
console.log('Collapse class added');
} else {
console.log('Navbar is already collapsed (collapse class exists).');
}
});
} else {
console.error('Error: Buttons or navbar element not found.');
}
});
+12 -12
View File
File diff suppressed because one or more lines are too long
+328 -328
View File
@@ -1,328 +1,328 @@
// team-switcher.js
// Loads team data from XML and populates the team slider. Adds a men/women switcher.
(function () {
const XML_URL = 'data/team.xml';
const SWITCHER_ID = 'gender-switcher';
const WRAPPER_ID = 'team-swiper-wrapper-1';
const PRELOADER_ID = 'team-preloader-1';
const SECTION_ID = 'team-section-1';
let teamData = null; // cached parsed XML data
let currentGender = 'men';
// Autoscroll timers
let autoTimer = null;
let resumeTimer = null;
const AUTO_DELAY = 3500; // 5s
const RESUME_AFTER = 10000; // resume 10s after user interaction
function qs(sel, root = document) { return root.querySelector(sel); }
function qsa(sel, root = document) { return Array.from(root.querySelectorAll(sel)); }
async function loadXML() {
if (teamData) return teamData;
const res = await fetch(XML_URL, { cache: 'no-cache' });
if (!res.ok) throw new Error('Failed to fetch team.xml');
const text = await res.text();
const parser = new DOMParser();
const xml = parser.parseFromString(text, 'application/xml');
const parseError = xml.querySelector('parsererror');
if (parseError) throw new Error('Invalid XML in team.xml');
teamData = xml;
return xml;
}
function getMembersByCategory(xml, categoryName) {
const cat = Array.from(xml.querySelectorAll('team > category'))
.find(c => (c.getAttribute('name') || '').toLowerCase() === categoryName);
if (!cat) return [];
return Array.from(cat.querySelectorAll('member')).map(m => ({
name: (m.querySelector('name')?.textContent || '').trim(),
number: (m.querySelector('number')?.textContent || '').trim(),
role: (m.querySelector('role')?.textContent || '').trim(),
image: (m.querySelector('image')?.textContent || '').trim(),
}));
}
function slideHTML(member) {
const numHTML = member.number ? `<div class="lte-num">${member.number}</div>` : '<div class="lte-num"></div>';
const safeImg = member.image || '';
return (
`<div class="lte-item swiper-slide">
<div class="lte-team-item">
<a class="lte-image" style="background-image: url()">
<img loading="lazy" decoding="async" width="800" height="1200" src="${safeImg}" class="attachment-full size-full" />
</a>
<div class="lte-descr">
${numHTML}
<a href="${safeImg}" target="_blank">
<h4 class="lte-header">${member.name}</h4>
</a>
<p class="lte-subheader" style="color: #c42221">${member.role}
</p>
</div>
</div>
</div>`
);
}
function renderMembers(members) {
const wrapper = document.getElementById(WRAPPER_ID);
if (!wrapper) return;
const swiperEl = wrapper.closest('.swiper-container');
const swiper = swiperEl && swiperEl.swiper;
// Use DOM-based rendering to match theme's slider expectations
wrapper.innerHTML = members.map(slideHTML).join('');
// Strong refresh
if (swiper) {
try {
if (typeof swiper.updateSlides === 'function') swiper.updateSlides();
if (typeof swiper.updateSize === 'function') swiper.updateSize();
if (typeof swiper.updateAutoHeight === 'function') swiper.updateAutoHeight(0);
if (typeof swiper.slideTo === 'function') swiper.slideTo(0, 0, false);
if (typeof swiper.update === 'function') swiper.update();
} catch (e) {}
}
// Ask the theme to re-init this slider completely so arrows/loop/order are consistent
const sliderContainer = wrapper.closest('.lte-swiper-slider');
if (sliderContainer) sliderContainer.classList.remove('lte-inited');
if (typeof window.initSwiperWrappers === 'function') {
try { window.initSwiperWrappers(); } catch (_) {}
}
// Remove any duplicate arrow bars the theme may have added on re-init
cleanupDuplicateArrows();
setTimeout(() => window.dispatchEvent(new Event('resize')), 0);
// Ensure arrows exist and are bound; manual endless wrap
setupEndlessNavigation(swiperEl);
setupDragWrap(swiper);
// Restart autoscroll on fresh render
stopAutoScroll();
startAutoScroll();
}
// Keep only one arrows bar; prefer the one whose anchors already have our data-ts-bound
function cleanupDuplicateArrows() {
const wrapper = document.getElementById(WRAPPER_ID);
if (!wrapper) return;
const slider = wrapper.closest('.lte-swiper-slider');
if (!slider) return;
// Arrows can be siblings of slider or children inside slider depending on theme config
const candidates = [];
const parent = slider.parentElement;
if (parent) {
Array.from(parent.children).forEach((el) => { if (el.classList && el.classList.contains('lte-arrows')) candidates.push(el); });
}
Array.from(slider.children).forEach((el) => { if (el.classList && el.classList.contains('lte-arrows')) candidates.push(el); });
if (candidates.length <= 1) return;
// Prefer the one that already has data-ts-bound anchors
const hasBound = candidates.find(a => a.querySelector('a[data-ts-bound="1"]'));
const keep = hasBound || candidates[0];
candidates.forEach((a) => { if (a !== keep && a.parentElement) a.parentElement.removeChild(a); });
}
async function switchGender(gender) {
currentGender = gender;
try {
showPreloader();
const xml = await loadXML();
// Keep the order as in XML so the first visible is the first listed (e.g., Janečka Martin)
const list = getMembersByCategory(xml, gender);
renderMembers(list);
updateActiveButton();
markReady();
hidePreloader();
} catch (e) {
console.error(e);
hidePreloader();
}
}
function updateActiveButton() {
const container = document.getElementById(SWITCHER_ID);
if (!container) return;
qsa('button[data-gender]', container).forEach(btn => {
btn.classList.toggle('active', btn.dataset.gender === currentGender);
});
}
function bindUI() {
const container = document.getElementById(SWITCHER_ID);
if (!container) return;
container.addEventListener('click', (e) => {
const btn = e.target.closest('button[data-gender]');
if (!btn) return;
const gender = btn.dataset.gender;
if (gender && gender !== currentGender) switchGender(gender);
});
}
function ensureBasicStyles() {
const css = `
#${SWITCHER_ID}{display:flex;gap:.5rem;justify-content:center;margin:10px 0}
#${SWITCHER_ID} .switch-btn{background:#eee;border:1px solid #ccc;border-radius:20px;padding:.35rem .9rem;font-weight:600;cursor:pointer}
#${SWITCHER_ID} .switch-btn.active{background:#111;color:#fff;border-color:#111}
#${PRELOADER_ID}{display:none;align-items:center;justify-content:center;gap:.6rem;color:#fff;padding:8px 0}
#${PRELOADER_ID}.visible{display:flex}
#${PRELOADER_ID} .spinner{width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:ts-spin .8s linear infinite}
@keyframes ts-spin{to{transform:rotate(360deg)}}
#${SECTION_ID}.not-ready .lte-swiper-slider-wrapper{visibility:hidden}
`;
const style = document.createElement('style');
style.textContent = css;
document.head.appendChild(style);
}
function getSwiperInstance() {
const wrapper = document.getElementById(WRAPPER_ID);
const swiperEl = wrapper && wrapper.closest('.swiper-container');
return swiperEl && swiperEl.swiper ? { el: swiperEl, api: swiperEl.swiper } : null;
}
function setupEndlessNavigation(swiperContainerEl) {
const inst = getSwiperInstance();
if (!inst) return;
const { el, api } = inst;
// Ensure only one set of arrows remains before binding
cleanupDuplicateArrows();
// Theme uses .lte-arrow-left / .lte-arrow-right (see frontend.js init)
let nextBtn = el.parentElement && el.parentElement.querySelector('.lte-arrows .lte-arrow-right');
let prevBtn = el.parentElement && el.parentElement.querySelector('.lte-arrows .lte-arrow-left');
// Fallback to common Swiper classes if theme structure changes
if (!nextBtn) nextBtn = el.querySelector('.swiper-button-next, .lte-swiper-button-next, .lte-next, .lte-arrow-next, .lte-arrow-right');
if (!prevBtn) prevBtn = el.querySelector('.swiper-button-prev, .lte-swiper-button-prev, .lte-prev, .lte-arrow-prev, .lte-arrow-left');
// Do not create fallback arrows; rely on theme arrows only
function bind(btn, dir) {
if (!btn || btn.dataset.tsBound) return;
btn.addEventListener('click', (e) => {
e.preventDefault();
if (!api) return;
// User override: pause and schedule resume
stopAutoScroll();
scheduleAutoResume();
if (dir === 'next') {
if (typeof api.slideNext === 'function') api.slideNext(400);
else api.slideTo((api.activeIndex || 0) + 1, 400, false);
} else {
if (typeof api.slidePrev === 'function') api.slidePrev(400);
else api.slideTo(Math.max((api.activeIndex || 0) - 1, 0), 400, false);
}
});
btn.dataset.tsBound = '1';
}
bind(nextBtn, 'next');
bind(prevBtn, 'prev');
// Hover pause/resume on the whole slider area
if (el && !el.__tsHoverBound) {
el.addEventListener('mouseenter', () => stopAutoScroll());
el.addEventListener('mouseleave', () => startAutoScroll());
el.__tsHoverBound = true;
}
}
function setupDragWrap(swiper) {
if (!swiper || !swiper.on) return;
if (!swiper.__tsWrapBound) {
swiper.on('reachEnd', () => { swiper.slideTo(0, 400, false); });
swiper.on('reachBeginning', () => {
const last = (swiper.slides && swiper.slides.length ? swiper.slides.length - 1 : 0);
swiper.slideTo(last, 400, false);
});
swiper.__tsWrapBound = true;
}
// Pause autoscroll on user touch/drag and schedule resume on release
if (!swiper.__tsAutoBound) {
try {
swiper.on('touchStart', () => { stopAutoScroll(); });
swiper.on('touchEnd', () => { scheduleAutoResume(); });
swiper.on('pointerDown', () => { stopAutoScroll(); });
swiper.on('pointerUp', () => { scheduleAutoResume(); });
} catch (_) {}
swiper.__tsAutoBound = true;
}
}
function startAutoScroll() {
const inst = getSwiperInstance();
if (!inst) return;
const { api } = inst;
stopAutoScroll();
autoTimer = window.setInterval(() => {
if (!api) return;
try {
// If not looping, wrap to first when at end
const loop = api.params && api.params.loop;
if (!loop && api.isEnd) {
api.slideTo(0, 600, false);
} else if (typeof api.slideNext === 'function') {
api.slideNext(600);
}
} catch (_) {}
}, AUTO_DELAY);
}
function stopAutoScroll() {
if (autoTimer) {
clearInterval(autoTimer);
autoTimer = null;
}
if (resumeTimer) {
clearTimeout(resumeTimer);
resumeTimer = null;
}
}
function scheduleAutoResume() {
if (resumeTimer) {
clearTimeout(resumeTimer);
resumeTimer = null;
}
resumeTimer = window.setTimeout(() => {
startAutoScroll();
}, RESUME_AFTER);
}
function showPreloader() {
const el = document.getElementById(PRELOADER_ID);
if (el) el.classList.add('visible');
}
function hidePreloader() {
const el = document.getElementById(PRELOADER_ID);
if (el) el.classList.remove('visible');
}
function markNotReady() {
const sec = document.getElementById(SECTION_ID);
if (sec) sec.classList.add('not-ready');
}
function markReady() {
const sec = document.getElementById(SECTION_ID);
if (sec) sec.classList.remove('not-ready');
}
document.addEventListener('DOMContentLoaded', () => {
ensureBasicStyles();
markNotReady();
showPreloader();
bindUI();
});
// Defer initial population until all assets and theme scripts (e.g., sliders) are fully initialized
window.addEventListener('load', () => {
switchGender(currentGender);
});
})();
// team-switcher.js
// Loads team data from XML and populates the team slider. Adds a men/women switcher.
(function () {
const XML_URL = 'data/team.xml';
const SWITCHER_ID = 'gender-switcher';
const WRAPPER_ID = 'team-swiper-wrapper-1';
const PRELOADER_ID = 'team-preloader-1';
const SECTION_ID = 'team-section-1';
let teamData = null; // cached parsed XML data
let currentGender = 'men';
// Autoscroll timers
let autoTimer = null;
let resumeTimer = null;
const AUTO_DELAY = 3500; // 5s
const RESUME_AFTER = 10000; // resume 10s after user interaction
function qs(sel, root = document) { return root.querySelector(sel); }
function qsa(sel, root = document) { return Array.from(root.querySelectorAll(sel)); }
async function loadXML() {
if (teamData) return teamData;
const res = await fetch(XML_URL, { cache: 'no-cache' });
if (!res.ok) throw new Error('Failed to fetch team.xml');
const text = await res.text();
const parser = new DOMParser();
const xml = parser.parseFromString(text, 'application/xml');
const parseError = xml.querySelector('parsererror');
if (parseError) throw new Error('Invalid XML in team.xml');
teamData = xml;
return xml;
}
function getMembersByCategory(xml, categoryName) {
const cat = Array.from(xml.querySelectorAll('team > category'))
.find(c => (c.getAttribute('name') || '').toLowerCase() === categoryName);
if (!cat) return [];
return Array.from(cat.querySelectorAll('member')).map(m => ({
name: (m.querySelector('name')?.textContent || '').trim(),
number: (m.querySelector('number')?.textContent || '').trim(),
role: (m.querySelector('role')?.textContent || '').trim(),
image: (m.querySelector('image')?.textContent || '').trim(),
}));
}
function slideHTML(member) {
const numHTML = member.number ? `<div class="lte-num">${member.number}</div>` : '<div class="lte-num"></div>';
const safeImg = member.image || '';
return (
`<div class="lte-item swiper-slide">
<div class="lte-team-item">
<a class="lte-image" style="background-image: url()">
<img loading="lazy" decoding="async" width="800" height="1200" src="${safeImg}" class="attachment-full size-full" />
</a>
<div class="lte-descr">
${numHTML}
<a href="${safeImg}" target="_blank">
<h4 class="lte-header">${member.name}</h4>
</a>
<p class="lte-subheader" style="color: #c42221">${member.role}
</p>
</div>
</div>
</div>`
);
}
function renderMembers(members) {
const wrapper = document.getElementById(WRAPPER_ID);
if (!wrapper) return;
const swiperEl = wrapper.closest('.swiper-container');
const swiper = swiperEl && swiperEl.swiper;
// Use DOM-based rendering to match theme's slider expectations
wrapper.innerHTML = members.map(slideHTML).join('');
// Strong refresh
if (swiper) {
try {
if (typeof swiper.updateSlides === 'function') swiper.updateSlides();
if (typeof swiper.updateSize === 'function') swiper.updateSize();
if (typeof swiper.updateAutoHeight === 'function') swiper.updateAutoHeight(0);
if (typeof swiper.slideTo === 'function') swiper.slideTo(0, 0, false);
if (typeof swiper.update === 'function') swiper.update();
} catch (e) {}
}
// Ask the theme to re-init this slider completely so arrows/loop/order are consistent
const sliderContainer = wrapper.closest('.lte-swiper-slider');
if (sliderContainer) sliderContainer.classList.remove('lte-inited');
if (typeof window.initSwiperWrappers === 'function') {
try { window.initSwiperWrappers(); } catch (_) {}
}
// Remove any duplicate arrow bars the theme may have added on re-init
cleanupDuplicateArrows();
setTimeout(() => window.dispatchEvent(new Event('resize')), 0);
// Ensure arrows exist and are bound; manual endless wrap
setupEndlessNavigation(swiperEl);
setupDragWrap(swiper);
// Restart autoscroll on fresh render
stopAutoScroll();
startAutoScroll();
}
// Keep only one arrows bar; prefer the one whose anchors already have our data-ts-bound
function cleanupDuplicateArrows() {
const wrapper = document.getElementById(WRAPPER_ID);
if (!wrapper) return;
const slider = wrapper.closest('.lte-swiper-slider');
if (!slider) return;
// Arrows can be siblings of slider or children inside slider depending on theme config
const candidates = [];
const parent = slider.parentElement;
if (parent) {
Array.from(parent.children).forEach((el) => { if (el.classList && el.classList.contains('lte-arrows')) candidates.push(el); });
}
Array.from(slider.children).forEach((el) => { if (el.classList && el.classList.contains('lte-arrows')) candidates.push(el); });
if (candidates.length <= 1) return;
// Prefer the one that already has data-ts-bound anchors
const hasBound = candidates.find(a => a.querySelector('a[data-ts-bound="1"]'));
const keep = hasBound || candidates[0];
candidates.forEach((a) => { if (a !== keep && a.parentElement) a.parentElement.removeChild(a); });
}
async function switchGender(gender) {
currentGender = gender;
try {
showPreloader();
const xml = await loadXML();
// Keep the order as in XML so the first visible is the first listed (e.g., Janečka Martin)
const list = getMembersByCategory(xml, gender);
renderMembers(list);
updateActiveButton();
markReady();
hidePreloader();
} catch (e) {
console.error(e);
hidePreloader();
}
}
function updateActiveButton() {
const container = document.getElementById(SWITCHER_ID);
if (!container) return;
qsa('button[data-gender]', container).forEach(btn => {
btn.classList.toggle('active', btn.dataset.gender === currentGender);
});
}
function bindUI() {
const container = document.getElementById(SWITCHER_ID);
if (!container) return;
container.addEventListener('click', (e) => {
const btn = e.target.closest('button[data-gender]');
if (!btn) return;
const gender = btn.dataset.gender;
if (gender && gender !== currentGender) switchGender(gender);
});
}
function ensureBasicStyles() {
const css = `
#${SWITCHER_ID}{display:flex;gap:.5rem;justify-content:center;margin:10px 0}
#${SWITCHER_ID} .switch-btn{background:#eee;border:1px solid #ccc;border-radius:20px;padding:.35rem .9rem;font-weight:600;cursor:pointer}
#${SWITCHER_ID} .switch-btn.active{background:#111;color:#fff;border-color:#111}
#${PRELOADER_ID}{display:none;align-items:center;justify-content:center;gap:.6rem;color:#fff;padding:8px 0}
#${PRELOADER_ID}.visible{display:flex}
#${PRELOADER_ID} .spinner{width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:ts-spin .8s linear infinite}
@keyframes ts-spin{to{transform:rotate(360deg)}}
#${SECTION_ID}.not-ready .lte-swiper-slider-wrapper{visibility:hidden}
`;
const style = document.createElement('style');
style.textContent = css;
document.head.appendChild(style);
}
function getSwiperInstance() {
const wrapper = document.getElementById(WRAPPER_ID);
const swiperEl = wrapper && wrapper.closest('.swiper-container');
return swiperEl && swiperEl.swiper ? { el: swiperEl, api: swiperEl.swiper } : null;
}
function setupEndlessNavigation(swiperContainerEl) {
const inst = getSwiperInstance();
if (!inst) return;
const { el, api } = inst;
// Ensure only one set of arrows remains before binding
cleanupDuplicateArrows();
// Theme uses .lte-arrow-left / .lte-arrow-right (see frontend.js init)
let nextBtn = el.parentElement && el.parentElement.querySelector('.lte-arrows .lte-arrow-right');
let prevBtn = el.parentElement && el.parentElement.querySelector('.lte-arrows .lte-arrow-left');
// Fallback to common Swiper classes if theme structure changes
if (!nextBtn) nextBtn = el.querySelector('.swiper-button-next, .lte-swiper-button-next, .lte-next, .lte-arrow-next, .lte-arrow-right');
if (!prevBtn) prevBtn = el.querySelector('.swiper-button-prev, .lte-swiper-button-prev, .lte-prev, .lte-arrow-prev, .lte-arrow-left');
// Do not create fallback arrows; rely on theme arrows only
function bind(btn, dir) {
if (!btn || btn.dataset.tsBound) return;
btn.addEventListener('click', (e) => {
e.preventDefault();
if (!api) return;
// User override: pause and schedule resume
stopAutoScroll();
scheduleAutoResume();
if (dir === 'next') {
if (typeof api.slideNext === 'function') api.slideNext(400);
else api.slideTo((api.activeIndex || 0) + 1, 400, false);
} else {
if (typeof api.slidePrev === 'function') api.slidePrev(400);
else api.slideTo(Math.max((api.activeIndex || 0) - 1, 0), 400, false);
}
});
btn.dataset.tsBound = '1';
}
bind(nextBtn, 'next');
bind(prevBtn, 'prev');
// Hover pause/resume on the whole slider area
if (el && !el.__tsHoverBound) {
el.addEventListener('mouseenter', () => stopAutoScroll());
el.addEventListener('mouseleave', () => startAutoScroll());
el.__tsHoverBound = true;
}
}
function setupDragWrap(swiper) {
if (!swiper || !swiper.on) return;
if (!swiper.__tsWrapBound) {
swiper.on('reachEnd', () => { swiper.slideTo(0, 400, false); });
swiper.on('reachBeginning', () => {
const last = (swiper.slides && swiper.slides.length ? swiper.slides.length - 1 : 0);
swiper.slideTo(last, 400, false);
});
swiper.__tsWrapBound = true;
}
// Pause autoscroll on user touch/drag and schedule resume on release
if (!swiper.__tsAutoBound) {
try {
swiper.on('touchStart', () => { stopAutoScroll(); });
swiper.on('touchEnd', () => { scheduleAutoResume(); });
swiper.on('pointerDown', () => { stopAutoScroll(); });
swiper.on('pointerUp', () => { scheduleAutoResume(); });
} catch (_) {}
swiper.__tsAutoBound = true;
}
}
function startAutoScroll() {
const inst = getSwiperInstance();
if (!inst) return;
const { api } = inst;
stopAutoScroll();
autoTimer = window.setInterval(() => {
if (!api) return;
try {
// If not looping, wrap to first when at end
const loop = api.params && api.params.loop;
if (!loop && api.isEnd) {
api.slideTo(0, 600, false);
} else if (typeof api.slideNext === 'function') {
api.slideNext(600);
}
} catch (_) {}
}, AUTO_DELAY);
}
function stopAutoScroll() {
if (autoTimer) {
clearInterval(autoTimer);
autoTimer = null;
}
if (resumeTimer) {
clearTimeout(resumeTimer);
resumeTimer = null;
}
}
function scheduleAutoResume() {
if (resumeTimer) {
clearTimeout(resumeTimer);
resumeTimer = null;
}
resumeTimer = window.setTimeout(() => {
startAutoScroll();
}, RESUME_AFTER);
}
function showPreloader() {
const el = document.getElementById(PRELOADER_ID);
if (el) el.classList.add('visible');
}
function hidePreloader() {
const el = document.getElementById(PRELOADER_ID);
if (el) el.classList.remove('visible');
}
function markNotReady() {
const sec = document.getElementById(SECTION_ID);
if (sec) sec.classList.add('not-ready');
}
function markReady() {
const sec = document.getElementById(SECTION_ID);
if (sec) sec.classList.remove('not-ready');
}
document.addEventListener('DOMContentLoaded', () => {
ensureBasicStyles();
markNotReady();
showPreloader();
bindUI();
});
// Defer initial population until all assets and theme scripts (e.g., sliders) are fully initialized
window.addEventListener('load', () => {
switchGender(currentGender);
});
})();
+6
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full">
@@ -78,6 +79,11 @@
<span>Kontakt</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="vykonny-vybor.html">
<span>Výkonný výbor</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="index.html#tym">
<span>Tým</span>
+23 -23
View File
@@ -1,23 +1,23 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Serve static assets
location / {
try_files $uri $uri/ /index.html;
}
# Proxy data API to backend
location /data/ {
proxy_pass http://backend:8080/data/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
add_header Access-Control-Allow-Origin *;
}
location /healthz {
proxy_pass http://backend:8080/healthz;
}
}
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Serve static assets
location / {
try_files $uri $uri/ /index.html;
}
# Proxy data API to backend
location /data/ {
proxy_pass http://backend:8080/data/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
add_header Access-Control-Allow-Origin *;
}
location /healthz {
proxy_pass http://backend:8080/healthz;
}
}
+839 -805
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full">
+1
View File
@@ -32,6 +32,7 @@
<script type="text/javascript" src="js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full">
+18
View File
@@ -0,0 +1,18 @@
#!/bin/bash
# Remove local blog files and keep only remote blogs
# Run this in your bizoni directory
echo "🗑️ Removing local blog files..."
# Remove all blog files
rm -rf blog/
echo "✅ Local blog files removed!"
echo ""
echo "📝 Next steps:"
echo "1. Deploy updated backend to server"
echo "2. Backend will now work with remote blogs only"
echo "3. Admin interface will connect to server API"
echo ""
echo "🌐 Your live blogs will remain untouched on the server"
+300
View File
@@ -0,0 +1,300 @@
#!/bin/bash
# 🚀 Bizoni Remote Blog Setup - One Command Script
# Run this to setup remote blog management
set -e
echo "🚀 Bizoni Remote Blog Setup"
echo "=========================="
# Configuration - UPDATE THESE
SERVER_USER="your_username" # Your SSH username
SERVER_HOST="your_server.com" # Your server domain/IP
SERVER_BLOG_DIR="/var/www/bizoni/blog" # Blog directory on server
LOCAL_PROJECT_DIR="/home/tdvorak/Desktop/HTML_Projekty/bizoni" # Your local project
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Helper functions
print_status() {
echo -e "${BLUE}$1${NC}"
}
print_success() {
echo -e "${GREEN}$1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
print_error() {
echo -e "${RED}$1${NC}"
}
# Check if local blogs exist
check_local_blogs() {
print_status "Checking local blog files..."
if [ -d "$LOCAL_PROJECT_DIR/blog" ]; then
blog_count=$(find "$LOCAL_PROJECT_DIR/blog" -name "*.html" -type f 2>/dev/null | wc -l)
if [ "$blog_count" -gt 0 ]; then
print_warning "Found $blog_count local blog files"
read -p "Remove local blog files? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
rm -rf "$LOCAL_PROJECT_DIR/blog"
print_success "Local blog files removed"
else
print_warning "Skipping local blog removal"
fi
else
print_success "No local blog files found"
fi
else
print_success "No local blog directory found"
fi
}
# Create Ubuntu management script
create_server_script() {
print_status "Creating server management script..."
cat > /tmp/ubuntu-blog-manager.sh << 'EOF'
#!/bin/bash
# Ubuntu Server Blog Management Script
set -e
BLOG_DIR="/var/www/bizoni/blog"
BACKUP_DIR="/var/backups/bizoni-blogs"
# Create backup
create_backup() {
echo "📦 Creating backup..."
mkdir -p "$BACKUP_DIR"
timestamp=$(date +%Y%m%d_%H%M%S)
tar -czf "$BACKUP_DIR/blogs_backup_$timestamp.tar.gz" -C "$BLOG_DIR" . 2>/dev/null || echo "No files to backup"
echo "✅ Backup created"
}
# Generate slug from title
generate_slug() {
local title="$1"
echo "$title" | tr '[:upper:]' '[:lower:]' | \
sed 's/á/a/g; s/ä/a/g; s/č/c/g; s/ď/d/g; s/é/e/g; s/ě/e/g; s/í/i/g; s/ľ/l/g; s/ň/n/g; s/ó/o/g; s/ö/o/g; s/ô/o/g; s/ř/r/g; s/š/s/g; s/ť/t/g; s/ú/u/g; s/ů/u/g; s/ý/y/g; s/ž/z/g' | \
sed 's/Á/a/g; s/Ä/a/g; s/Č/c/g; s/Ď/d/g; s/É/e/g; s/Ě/e/g; s/Í/i/g; s/Ľ/l/g; s/Ň/n/g; s/Ó/o/g; s/Ö/o/g; s/Ô/o/g; s/Ř/r/g; s/Š/s/g; s/Ť/t/g; s/Ú/u/g; s/Ů/u/g; s/Ý/y/g; s/Ž/z/g' | \
sed 's/[^a-z0-9\s-]//g' | \
sed 's/[\s-]\+/ -/g' | \
sed 's/^-\|-$//g'
}
# Add slug to blog
add_slug_to_blog() {
local blog_id="$1"
local blog_file="$BLOG_DIR/$blog_id.html"
if [ ! -f "$blog_file" ]; then
echo "❌ Blog not found: $blog_id.html"
return 1
fi
# Check if slug already exists
if grep -q '<meta name="slug"' "$blog_file"; then
echo "️ $blog_id already has slug"
return 0
fi
# Extract title
title=$(grep -o '<h1[^>]*class="[^"]*lte-header[^"]*"[^>]*>.*</h1>' "$blog_file" 2>/dev/null | sed 's/<[^>]*>//g' | xargs || echo "")
if [ -z "$title" ]; then
echo "❌ Could not extract title from $blog_id"
return 1
fi
# Generate slug
slug=$(generate_slug "$title")
# Check uniqueness
counter=2
original_slug="$slug"
while [ -f "$BLOG_DIR/$slug.html" ]; do
slug="$original_slug-$counter"
((counter++))
done
echo "📝 $blog_id: $title → $slug"
# Add slug meta tag
sed -i "s|</head>|<meta name=\"slug\" content=\"$slug\">\n</head>|" "$blog_file"
# Create slug file
cp "$blog_file" "$BLOG_DIR/$slug.html"
echo "✅ Added slug: $slug.html"
}
# Migrate all blogs
migrate_all() {
echo "🔄 Migrating all blogs..."
if [ ! -d "$BLOG_DIR" ]; then
echo "❌ Blog directory not found: $BLOG_DIR"
exit 1
fi
create_backup
count=0
for blog_file in "$BLOG_DIR"/*.html; do
if [ -f "$blog_file" ]; then
filename=$(basename "$blog_file")
if [[ "$filename" =~ ^([0-9]{4})\.html$ ]]; then
blog_id="${BASH_REMATCH[1]}"
add_slug_to_blog "$blog_id"
((count++))
fi
fi
done
echo "✅ Migration completed! Processed $count blogs"
}
# List blogs
list_blogs() {
echo "📋 Blogs on server:"
if [ -d "$BLOG_DIR" ]; then
for file in "$BLOG_DIR"/*.html; do
if [ -f "$file" ]; then
filename=$(basename "$file")
if [[ "$filename" =~ ^[0-9]{4}\.html$ ]]; then
echo " 📄 $filename (numeric)"
elif [[ "$filename" =~ ^[a-z0-9-]+\.html$ ]]; then
echo " 🔗 $filename (slug)"
fi
fi
done
else
echo " ❌ Blog directory not found"
fi
}
case "${1:-}" in
"migrate")
migrate_all
;;
"list")
list_blogs
;;
"backup")
create_backup
;;
*)
echo "Ubuntu Blog Manager"
echo "=================="
echo "Usage: $0 <command>"
echo ""
echo "Commands:"
echo " migrate - Add slugs to all blogs"
echo " list - List all blogs"
echo " backup - Create backup"
echo ""
echo "Example: $0 migrate"
exit 1
;;
esac
EOF
chmod +x /tmp/ubuntu-blog-manager.sh
print_success "Server script created"
}
# Deploy to server
deploy_to_server() {
print_status "Deploying to server..."
# Upload server script
scp /tmp/ubuntu-blog-manager.sh "$SERVER_USER@$SERVER_HOST:/tmp/"
# Move script to server location and make executable
ssh "$SERVER_USER@$SERVER_HOST" "sudo mv /tmp/ubuntu-blog-manager.sh /usr/local/bin/blog-manager && sudo chmod +x /usr/local/bin/blog-manager"
print_success "Server script deployed to /usr/local/bin/blog-manager"
}
# Test server connection
test_connection() {
print_status "Testing server connection..."
if ssh "$SERVER_USER@$SERVER_HOST" "echo 'Connection successful'" 2>/dev/null; then
print_success "Server connection OK"
else
print_error "Cannot connect to server. Please check:"
echo " - Username: $SERVER_USER"
echo " - Host: $SERVER_HOST"
echo " - SSH key or password setup"
exit 1
fi
}
# Run migration on server
run_migration() {
print_status "Running migration on server..."
ssh "$SERVER_USER@$SERVER_HOST" "sudo blog-manager migrate"
print_success "Migration completed on server"
}
# Show results
show_results() {
print_status "Showing results..."
echo ""
ssh "$SERVER_USER@$SERVER_HOST" "blog-manager list"
echo ""
print_success "Setup completed!"
echo ""
echo "🌐 Your blogs now have clean URLs:"
echo " Old: /blog/0030.html"
echo " New: /blog/jdeme-do-finale"
echo ""
echo "🔧 Server commands you can use:"
echo " ssh $SERVER_USER@$SERVER_HOST 'blog-manager list'"
echo " ssh $SERVER_USER@$SERVER_HOST 'blog-manager backup'"
echo ""
}
# Main execution
main() {
echo ""
print_warning "Please update the configuration in this script:"
echo " SERVER_USER=\"$SERVER_USER\""
echo " SERVER_HOST=\"$SERVER_HOST\""
echo " SERVER_BLOG_DIR=\"$SERVER_BLOG_DIR\""
echo ""
read -p "Continue with current settings? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Please edit the script and run again"
exit 1
fi
check_local_blogs
test_connection
create_server_script
deploy_to_server
run_migration
show_results
}
# Run main function
main "$@"
+158
View File
@@ -0,0 +1,158 @@
#!/bin/bash
# Simple Server Setup Script - Run this ON YOUR SERVER after git push
# Usage: ./setup-server.sh
set -e
echo "🚀 Bizoni Server Setup Script"
echo "============================"
# Configuration - UPDATE THESE IF NEEDED
BLOG_DIR="/var/www/bizoni/blog"
IMG_DIR="/var/www/bizoni/img/blog"
BACKUP_DIR="/var/backups/bizoni"
echo "📁 Blog directory: $BLOG_DIR"
echo "🖼️ Image directory: $IMG_DIR"
echo ""
# Check if directories exist
if [ ! -d "$BLOG_DIR" ]; then
echo "❌ Blog directory not found: $BLOG_DIR"
echo "Please update BLOG_DIR in this script"
exit 1
fi
if [ ! -d "$IMG_DIR" ]; then
echo "❌ Image directory not found: $IMG_DIR"
echo "Please update IMG_DIR in this script"
exit 1
fi
echo "✅ Directories found"
echo ""
# Create backup
echo "📦 Creating backup..."
mkdir -p "$BACKUP_DIR"
timestamp=$(date +%Y%m%d_%H%M%S)
tar -czf "$BACKUP_DIR/blogs_backup_$timestamp.tar.gz" -C "$(dirname "$BLOG_DIR")" "$(basename "$BLOG_DIR")"
echo "✅ Backup created: $BACKUP_DIR/blogs_backup_$timestamp.tar.gz"
echo ""
# Count existing blogs
total_blogs=$(ls "$BLOG_DIR"/*.html 2>/dev/null | wc -l)
numeric_blogs=$(ls "$BLOG_DIR"/[0-9][0-9][0-9][0-9].html 2>/dev/null | wc -l)
slug_blogs=$(ls "$BLOG_DIR"/[a-z]*.html 2>/dev/null | wc -l)
echo "📊 Current blog status:"
echo " Total blogs: $total_blogs"
echo " Numeric files: $numeric_blogs"
echo " Slug files: $slug_blogs"
echo ""
# Function to generate slug from title
generate_slug() {
local title="$1"
echo "$title" | tr '[:upper:]' '[:lower:]' | \
sed 's/á/a/g; s/ä/a/g; s/č/c/g; s/ď/d/g; s/é/e/g; s/ě/e/g; s/í/i/g; s/ľ/l/g; s/ň/n/g; s/ó/o/g; s/ö/o/g; s/ô/o/g; s/ř/r/g; s/š/s/g; s/ť/t/g; s/ú/u/g; s/ů/u/g; s/ý/y/g; s/ž/z/g' | \
sed 's/Á/a/g; s/Ä/a/g; s/Č/c/g; s/Ď/d/g; s/É/e/g; s/Ě/e/g; s/Í/i/g; s/Ľ/l/g; s/Ň/n/g; s/Ó/o/g; s/Ö/o/g; s/Ô/o/g; s/Ř/r/g; s/Š/s/g; s/Ť/t/g; s/Ú/u/g; s/Ů/u/g; s/Ý/y/g; s/Ž/z/g' | \
iconv -c -f utf-8 -t ascii//TRANSLIT | \
sed 's/\s\+/-/g' | \
sed 's/[^a-z0-9\-]//g' | \
sed 's/-\+/-/g' | \
sed 's/^\-\|\-$//g'
}
# Function to extract title from HTML
extract_title() {
local file="$1"
grep -o '<h1[^>]*class="[^"]*lte-header[^"]*"[^>]*>.*</h1>' "$file" | sed 's/<[^>]*>//g' | xargs || echo ""
}
# Function to check if slug exists
slug_exists() {
local slug="$1"
[ -f "$BLOG_DIR/$slug.html" ]
}
# Process numeric blogs that don't have slugs yet
echo "🔄 Processing blogs without slugs..."
processed=0
for blog_file in "$BLOG_DIR"/[0-9][0-9][0-9][0-9].html; do
if [ ! -f "$blog_file" ]; then
continue
fi
filename=$(basename "$blog_file")
blog_id="${filename%.html}"
# Check if slug meta tag already exists
if grep -q '<meta name="slug"' "$blog_file"; then
echo " ⏭️ Skipping $filename (slug already exists)"
continue
fi
# Extract title
title=$(extract_title "$blog_file")
if [ -z "$title" ]; then
echo " ⚠️ Skipping $filename (no title found)"
continue
fi
# Generate slug
base_slug=$(generate_slug "$title")
slug="$base_slug"
# Make slug unique
counter=2
while slug_exists "$slug"; do
slug="${base_slug}-${counter}"
((counter++))
done
echo " 📝 $filename: '$title' → '$slug'"
# Add slug meta tag before </head>
sed -i "s|</head>|<meta name=\"slug\" content=\"$slug\">\n</head>|" "$blog_file"
# Create slug file (copy of original)
cp "$blog_file" "$BLOG_DIR/$slug.html"
((processed++))
done
echo ""
echo "✅ Migration completed!"
echo "📊 Processed $processed blogs"
echo ""
# Show final status
total_blogs=$(ls "$BLOG_DIR"/*.html 2>/dev/null | wc -l)
numeric_blogs=$(ls "$BLOG_DIR"/[0-9][0-9][0-9][0-9].html 2>/dev/null | wc -l)
slug_blogs=$(ls "$BLOG_DIR"/[a-z]*.html 2>/dev/null | wc -l)
echo "📊 Final blog status:"
echo " Total blogs: $total_blogs"
echo " Numeric files: $numeric_blogs"
echo " Slug files: $slug_blogs"
echo ""
# Show some example URLs
echo "🌐 Example URLs now available:"
echo " /blog/$(ls "$BLOG_DIR"/[a-z]*.html 2>/dev/null | head -1 | xargs basename -s .html || echo 'jdeme-do-finale')"
echo " /blog/$(ls "$BLOG_DIR"/[a-z]*.html 2>/dev/null | head -2 | tail -1 | xargs basename -s .html || echo '1-zapas-final-score')"
echo ""
echo "🎉 Setup complete! Your blogs now support:"
echo " ✅ Clean URLs (slugs)"
echo " ✅ SEO meta tags"
echo " ✅ Backward compatibility"
echo " ✅ New admin features"
echo ""
echo "📝 Next steps:"
echo " 1. Restart your backend service"
echo " 2. Test new URLs in browser"
echo " 3. Try admin interface with new features"
+11 -11
View File
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<!-- created with Free Online Sitemap Generator www.xml-sitemaps.com -->
<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<!-- created with Free Online Sitemap Generator www.xml-sitemaps.com -->
<url>
<loc>https://www.bizoniuh.cz/</loc>
@@ -166,7 +166,7 @@
<loc>https://www.bizoniuh.cz/zapasy/bizoni-hombres2.html</loc>
<lastmod>2024-11-13T09:24:05+00:00</lastmod>
<priority>0.64</priority>
</url>
</url>
</urlset>
+166
View File
@@ -0,0 +1,166 @@
package main
import (
"fmt"
"log"
"os"
"path/filepath"
"regexp"
"strings"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: ./migrate_slugs.go <site_root>")
fmt.Println("Example: ./migrate_slugs.go /home/tdvorak/Desktop/HTML_Projekty/bizoni")
os.Exit(1)
}
siteRoot := os.Args[1]
blogDir := filepath.Join(siteRoot, "blog")
// Read all blog files
entries, err := os.ReadDir(blogDir)
if err != nil {
log.Fatalf("Failed to read blog directory: %v", err)
}
// Pattern to match numeric blog files
numericPattern := regexp.MustCompile(`^(\d{4})\.html$`)
for _, entry := range entries {
if entry.IsDir() {
continue
}
filename := entry.Name()
matches := numericPattern.FindStringSubmatch(filename)
if len(matches) != 2 {
continue // Skip non-numeric files
}
blogPath := filepath.Join(blogDir, filename)
// Read the blog file
content, err := os.ReadFile(blogPath)
if err != nil {
log.Printf("Failed to read %s: %v", filename, err)
continue
}
contentStr := string(content)
// Check if slug already exists
slugPattern := regexp.MustCompile(`(?is)<meta name="slug" content="([^"]+)"`)
if slugPattern.MatchString(contentStr) {
log.Printf("Skipping %s - slug already exists", filename)
continue
}
// Extract title
titlePattern := regexp.MustCompile(`(?is)<h1[^>]*class="[^"]*\blte-header\b[^"]*"[^>]*>(.*?)</h1>`)
titleMatches := titlePattern.FindStringSubmatch(contentStr)
if len(titleMatches) < 2 {
log.Printf("Skipping %s - could not find title", filename)
continue
}
title := titleMatches[1]
// Remove any HTML tags from title
title = regexp.MustCompile(`(?is)<[^>]+>`).ReplaceAllString(title, "")
title = strings.TrimSpace(title)
// Generate slug
slug := generateSlug(title)
slug = ensureUniqueSlug(siteRoot, slug)
// Find where to insert the slug meta tag (before </head>)
headPattern := regexp.MustCompile(`(?is)</head>`)
if !headPattern.MatchString(contentStr) {
log.Printf("Skipping %s - could not find </head> tag", filename)
continue
}
// Insert slug meta tag
slugMeta := fmt.Sprintf(`<meta name="slug" content="%s">`, slug)
newContent := headPattern.ReplaceAllString(contentStr, slugMeta+"\n</head>")
// Write the updated content to both files
err = os.WriteFile(blogPath, []byte(newContent), 0644)
if err != nil {
log.Printf("Failed to write updated %s: %v", filename, err)
continue
}
// Create slug-based file
slugPath := filepath.Join(blogDir, slug+".html")
err = os.WriteFile(slugPath, []byte(newContent), 0644)
if err != nil {
log.Printf("Failed to create slug file %s: %v", slugPath, err)
continue
}
log.Printf("Processed %s: title='%s' -> slug='%s'", filename, title, slug)
}
log.Println("Migration completed!")
}
// generateSlug creates a URL-friendly slug from a title
func generateSlug(title string) string {
slug := strings.ToLower(title)
// Replace Czech characters with their ASCII equivalents
replacements := map[string]string{
"á": "a", "ä": "a", "č": "c", "ď": "d", "é": "e", "ě": "e", "í": "i", "ľ": "l",
"ň": "n", "ó": "o", "ö": "o", "ô": "o", "ř": "r", "š": "s", "ť": "t", "ú": "u",
"ů": "u", "ý": "y", "ž": "z",
"Á": "a", "Ä": "a", "Č": "c", "Ď": "d", "É": "e", "Ě": "e", "Í": "i", "Ľ": "l",
"Ň": "n", "Ó": "o", "Ö": "o", "Ô": "o", "Ř": "r", "Š": "s", "Ť": "t", "Ú": "u",
"Ů": "u", "Ý": "y", "Ž": "z",
}
for czech, ascii := range replacements {
slug = strings.ReplaceAll(slug, czech, ascii)
}
// Remove any character that isn't alphanumeric, space, or hyphen
re := regexp.MustCompile(`[^a-z0-9\s-]`)
slug = re.ReplaceAllString(slug, "")
// Replace spaces and multiple hyphens with a single hyphen
re = regexp.MustCompile(`[\s-]+`)
slug = re.ReplaceAllString(slug, "-")
// Remove leading and trailing hyphens
slug = strings.Trim(slug, "-")
return slug
}
// ensureUniqueSlug ensures the slug is unique by appending a number if needed
func ensureUniqueSlug(siteRoot, baseSlug string) string {
blogDir := filepath.Join(siteRoot, "blog")
entries, err := os.ReadDir(blogDir)
if err != nil {
return baseSlug
}
existingSlugs := make(map[string]bool)
for _, e := range entries {
if !strings.HasSuffix(e.Name(), ".html") {
continue
}
// Extract slug from filename if it follows the new pattern
name := strings.TrimSuffix(e.Name(), ".html")
// Check if it's a slug-based filename (contains letters, not just numbers)
if regexp.MustCompile(`[a-z]`).MatchString(name) {
existingSlugs[name] = true
}
}
if !existingSlugs[baseSlug] {
return baseSlug
}
// Try baseSlug-2, baseSlug-3, etc.
for i := 2; i < 100; i++ {
testSlug := fmt.Sprintf("%s-%d", baseSlug, i)
if !existingSlugs[testSlug] {
return testSlug
}
}
// Fallback to timestamp
return fmt.Sprintf("%s-%d", baseSlug, 1234567890)
}
+214
View File
@@ -0,0 +1,214 @@
#!/bin/bash
# Ubuntu Server Script: Remote Blog Management
# This script manages blogs on the remote server only
set -e
# Configuration - UPDATE THESE PATHS
SERVER_BLOG_DIR="/var/www/bizoni/blog" # Path to blogs on your server
BACKUP_DIR="/var/backups/bizoni-blogs" # Backup location
SITE_ROOT="/var/www/bizoni" # Site root on server
echo "🚀 Bizoni Remote Blog Management Script"
echo "====================================="
# Function to create backup
create_backup() {
echo "📦 Creating backup..."
mkdir -p "$BACKUP_DIR"
timestamp=$(date +%Y%m%d_%H%M%S)
tar -czf "$BACKUP_DIR/blogs_backup_$timestamp.tar.gz" -C "$SERVER_BLOG_DIR" .
echo "✅ Backup created: $BACKUP_DIR/blogs_backup_$timestamp.tar.gz"
}
# Function to list blogs
list_blogs() {
echo "📋 Current blogs on server:"
if [ -d "$SERVER_BLOG_DIR" ]; then
ls -la "$SERVER_BLOG_DIR"/*.html | while read line; do
filename=$(basename "$line")
if [[ "$filename" =~ ^[0-9]{4}\.html$ ]]; then
echo " 📄 $filename (numeric)"
elif [[ "$filename" =~ ^[a-z0-9-]+\.html$ ]]; then
echo " 🔗 $filename (slug)"
fi
done
else
echo " ❌ Blog directory not found: $SERVER_BLOG_DIR"
fi
}
# Function to add slug to existing blog
add_slug_to_blog() {
local blog_id="$1"
local blog_file="$SERVER_BLOG_DIR/$blog_id.html"
if [ ! -f "$blog_file" ]; then
echo "❌ Blog file not found: $blog_file"
return 1
fi
echo "🔧 Adding slug to blog: $blog_id"
# Extract title from blog file
title=$(grep -o '<h1[^>]*class="[^"]*lte-header[^"]*"[^>]*>.*</h1>' "$blog_file" | sed 's/<[^>]*>//g' | xargs)
if [ -z "$title" ]; then
echo "❌ Could not extract title from $blog_file"
return 1
fi
echo "📝 Title: $title"
# Generate slug
slug=$(echo "$title" | tr '[:upper:]' '[:lower:]' | \
sed 's/á/a/g; s/ä/a/g; s/č/c/g; s/ď/d/g; s/é/e/g; s/ě/e/g; s/í/i/g; s/ľ/l/g; s/ň/n/g; s/ó/o/g; s/ö/o/g; s/ô/o/g; s/ř/r/g; s/š/s/g; s/ť/t/g; s/ú/u/g; s/ů/u/g; s/ý/y/g; s/ž/z/g' | \
sed 's/Á/a/g; s/Ä/a/g; s/Č/c/g; s/Ď/d/g; s/É/e/g; s/Ě/e/g; s/Í/i/g; s/Ľ/l/g; s/Ň/n/g; s/Ó/o/g; s/Ö/o/g; s/Ô/o/g; s/Ř/r/g; s/Š/s/g; s/Ť/t/g; s/Ú/u/g; s/Ů/u/g; s/Ý/y/g; s/Ž/z/g' | \
sed 's/[^a-z0-9\s-]//g' | \
sed 's/[\s-]\+/ -/g' | \
sed 's/^-\|-$//g')
# Check if slug file already exists
slug_file="$SERVER_BLOG_DIR/$slug.html"
if [ -f "$slug_file" ]; then
# Add number suffix
i=2
while [ -f "$SERVER_BLOG_DIR/${slug}-${i}.html" ]; do
((i++))
done
slug="${slug}-${i}"
slug_file="$SERVER_BLOG_DIR/${slug}.html"
fi
echo "🔗 Generated slug: $slug"
# Check if slug meta tag already exists
if grep -q '<meta name="slug"' "$blog_file"; then
echo "️ Slug meta tag already exists"
return 0
fi
# Add slug meta tag before </head>
sed -i "s|</head>|<meta name=\"slug\" content=\"$slug\">\n</head>|" "$blog_file"
# Create slug file (copy of original)
cp "$blog_file" "$slug_file"
echo "✅ Slug added and slug file created: $slug.html"
}
# Function to migrate all blogs to slugs
migrate_all_blogs() {
echo "🔄 Migrating all blogs to slugs..."
if [ ! -d "$SERVER_BLOG_DIR" ]; then
echo "❌ Blog directory not found: $SERVER_BLOG_DIR"
echo "Please update SERVER_BLOG_DIR in this script"
exit 1
fi
create_backup
# Process all numeric blog files
for blog_file in "$SERVER_BLOG_DIR"/*.html; do
if [ -f "$blog_file" ]; then
filename=$(basename "$blog_file")
if [[ "$filename" =~ ^([0-9]{4})\.html$ ]]; then
blog_id="${BASH_REMATCH[1]}"
add_slug_to_blog "$blog_id"
echo ""
fi
fi
done
echo "✅ Migration completed!"
}
# Function to show blog info
show_blog_info() {
local blog_id="$1"
local blog_file="$SERVER_BLOG_DIR/$blog_id.html"
if [ ! -f "$blog_file" ]; then
echo "❌ Blog file not found: $blog_file"
return 1
fi
echo "📄 Blog Info for: $blog_id"
echo "========================"
# Extract title
title=$(grep -o '<h1[^>]*class="[^"]*lte-header[^"]*"[^>]*>.*</h1>' "$blog_file" | sed 's/<[^>]*>//g' | xargs)
echo "📝 Title: $title"
# Extract slug
slug=$(grep -o '<meta name="slug" content="[^"]*"' "$blog_file" | sed 's/.*content="\([^"]*\)".*/\1/')
echo "🔗 Slug: $slug"
# Extract categories
categories=$(grep -o '<meta name="category" content="[^"]*"' "$blog_file" | sed 's/.*content="\([^"]*\)".*/\1/' | tr '\n' ', ')
echo "🏷️ Categories: $categories"
# File size
size=$(du -h "$blog_file" | cut -f1)
echo "📊 Size: $size"
# Check if slug file exists
if [ -n "$slug" ] && [ -f "$SERVER_BLOG_DIR/$slug.html" ]; then
echo "✅ Slug file exists: $slug.html"
else
echo "❌ Slug file missing"
fi
}
# Main menu
case "${1:-}" in
"list")
list_blogs
;;
"migrate")
migrate_all_blogs
;;
"info")
if [ -z "${2:-}" ]; then
echo "Usage: $0 info <blog_id>"
echo "Example: $0 info 0030"
exit 1
fi
show_blog_info "$2"
;;
"add-slug")
if [ -z "${2:-}" ]; then
echo "Usage: $0 add-slug <blog_id>"
echo "Example: $0 add-slug 0030"
exit 1
fi
add_slug_to_blog "$2"
;;
"backup")
create_backup
;;
*)
echo "Bizoni Remote Blog Management"
echo "============================"
echo ""
echo "Usage: $0 <command> [options]"
echo ""
echo "Commands:"
echo " list - List all blogs on server"
echo " migrate - Migrate all blogs to use slugs"
echo " info <blog_id> - Show info about specific blog"
echo " add-slug <blog_id> - Add slug to specific blog"
echo " backup - Create backup of all blogs"
echo ""
echo "Examples:"
echo " $0 list"
echo " $0 migrate"
echo " $0 info 0030"
echo " $0 add-slug 0030"
echo ""
echo "⚠️ Make sure to update SERVER_BLOG_DIR path in this script!"
exit 1
;;
esac
+448
View File
@@ -0,0 +1,448 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>Bizoni UH - Výkonný výbor</title>
<link rel="icon" type="image/x-icon" href="img/logo.png">
<!-- Stylesheets -->
<link rel="stylesheet" id="swiper-css" href="css/swiper.css" type="text/css" media="all" />
<link rel="stylesheet" id="bootstrap-css" href="css/bootstrap.css" type="text/css" media="all" />
<link rel="stylesheet" id="atleticos-theme-style-css" href="css/bizoni.css" type="text/css" media="all" />
<link rel="stylesheet" id="elementor-icons-css" href="css/elementor-icons.min.css" type="text/css" media="all" />
<link rel="stylesheet" id="elementor-frontend-css" href="css/custom-frontend.min.css" type="text/css" media="all" />
<link rel="stylesheet" id="elementor-post-13200-css" href="css/post-13200.css" type="text/css" media="all" />
<!-- External Stylesheets -->
<link rel="stylesheet" id="elementor-post-32647-css" href="css/post-32647.css" type="text/css" media="all" />
<link rel="stylesheet" id="event-tickets-rsvp-css" href="css/rsvp.min.css" type="text/css" media="all" />
<link rel="stylesheet" id="magnific-popup-css" href="css/magnific-popup.css" type="text/css" media="all" />
<script type="text/javascript" src="js/jquery.nicescroll.js" id="nicescroll-js"></script>
<link rel="stylesheet" id="atleticos-google-fonts-css" href="//fonts.googleapis.com/css?family=Open+Sans:400,400i,600,700%7CSofia+Sans+Extra+Condensed:800,300i" type="text/css" media="all" />
<link rel="stylesheet" id="font-awesome-shims-css" href="css/v4-shims.min.css" type="text/css" media="all" />
<link rel="stylesheet" id="lte-font-css" href="css/lte-font-codes.css" type="text/css" media="all" />
<link rel="stylesheet" id="google-fonts-1-css" href="https://fonts.googleapis.com/css?family=Open+Sans%3A100%2C100italic%2C200%2C200italic%2C300%2C300italic%2C400%2C400italic%2C500%2C500italic%2C600%2C600italic%2C700%2C700italic%2C800%2C800italic%2C900%2C900italic%7CMarcellus%7CTangerine&#038;display=auto&#038;ver=6.4.5" type="text/css" media="all" />
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Scripts -->
<script type="module" src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js"></script>
<script nomodule src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"></script>
<script type="text/javascript" src="js/jquery.min.js" id="jquery-core-js"></script>
<script type="text/javascript" src="js/jquery-migrate.min.js" id="jquery-migrate-js"></script>
<script type="text/javascript" src="js/jquery.blockUI.min.js" id="jquery-blockui-js" defer="defer"></script>
<script type="text/javascript" src="js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="js/script.js"></script>
<script src="https://rybbit.tdvorak.dev/api/script.js" data-site-id="d40b7ffffffa" defer></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full">
<div class="lte-header-wrapper header-h1 header-parallax lte-header-overlay lte-layout-transparent-full lte-pageheader-disabled">
<div id="lte-nav-wrapper" class="lte-layout-transparent-full lte-nav-color-white">
<nav class="lte-navbar affix" data-spy="affix" data-offset-top="0">
<div class="container">
<!-- Logo -->
<div class="lte-navbar-logo">
<a class="lte-logo" href="index.html">
<img src="img/logo.png">
</a>
</div>
<!-- Navigation Items -->
<div class="lte-navbar-items navbar-mobile-black navbar-collapse collapse" id="navbar" data-mobile-screen-width="1198">
<div class="toggle-wrap">
<a class="lte-logo" href="index.html">
<img src="img/logo.png">
</a>
<button type="button" class="lte-navbar-toggle collapsed" id="close-button">
<span class="close">&times;</span>
</button>
<div class="clearfix"></div>
</div>
<!-- Navigation Menu -->
<ul id="menu-main-menu" class="lte-ul-nav">
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="index.html">
<span>Domů</span>
</a>
</li>
<li id="menu-item-29540" class="menu-item menu-item-type-post_type menu-item-object-page">
<a href="o-nas.html">
<span>O nás</span>
</a>
</li>
<li id="menu-item-59" class="menu-item menu-item-type-custom">
<a href="blog.html">
<span>Blog</span>
</a>
</li>
<li id="menu-item-13613" class="menu-item menu-item-type-post_type menu-item-object-page">
<a href="kontakt.html">
<span>Kontakt</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="vykonny-vybor.html">
<span>Výkonný výbor</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="index.html#tym">
<span>Tým</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="index.html#sponzori">
<span>Sponzoři</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a target="_blank" href="https://eu.zonerama.com/Fcbizoni/1419417">
<span>Fotogalerie</span>
</a>
</li>
</ul>
</div>
<!-- Mobile Menu Toggle -->
<button type="button" class="lte-navbar-toggle" id="open-button">
<span class="icon-bar top-bar"></span>
<span class="icon-bar middle-bar"></span>
<span class="icon-bar bottom-bar"></span>
</button>
</div>
</nav>
</div>
</div>
<header class="lte-page-header lte-parallax-yes">
<div class="container">
<div class="lte-header-h1-wrapper">
<h1 class="lte-header">Výkonný výbor</h1>
</div>
</div>
</header>
</div>
<!-- Content -->
<div class="lte-text-page margin-default">
<div class="row centered">
<div class="col-xl-12 col-xs-12">
<article id="post-13611" class="post-13611 page type-page status-publish has-post-thumbnail hentry">
<div class="entry-content clearfix" id="entry-div">
<div data-elementor-type="wp-page" data-elementor-id="13611" class="elementor elementor-13611">
<section class="elementor-section elementor-top-section elementor-element elementor-element-3724f34 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="3724f34" data-element_type="section">
<div class="elementor-container elementor-column-gap-no">
<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-9b8c152" data-id="9b8c152" data-element_type="column">
<div class="elementor-widget-wrap elementor-element-populated">
<div class="elementor-element elementor-element-e42573f lte-contacts-icons lte-icons-align-center lte-style-grid-disabled elementor-widget elementor-widget-lte-icons" data-id="e42573f" data-element_type="widget" data-widget_type="lte-icons.default">
<div class="elementor-widget-container">
<ul class="lte-block-icon has-descr icons-count-5 lte-icon-space-md lte-icon-shape-default lte-icon-background-disabled lte-icon-color-main lte-icon-divider-dashed lte-icon-size-medium lte-header-color-black lte-icon-type-top lte-icon-align-center layout-cols5 lte-additional-">
<li class=" col-lg-12 col-md-12 col-sm-12 col-ms-12 col-xs-12">
<div class="lte-inner">
<ion-icon name="person-outline" class="ion-icons"></ion-icon>
<span class="lte-icon-content">
<span class="lte-header lte-h5"> Předseda </span>
<span class="lte-descr">Mgr. Štěpán Stodůlka<br />775 247 633</span>
</span>
</div>
</li>
<li class=" col-lg-12 col-md-12 col-sm-12 col-ms-12 col-xs-12">
<div class="lte-inner">
<ion-icon name="person-outline" class="ion-icons"></ion-icon>
<span class="lte-icon-content">
<span class="lte-header lte-h5"> Místopředseda </span>
<span class="lte-descr">David Moravec<br />602 702 129</span>
</span>
</div>
</li>
<li class=" col-lg-12 col-md-12 col-sm-12 col-ms-12 col-xs-12">
<div class="lte-inner">
<ion-icon name="person-outline" class="ion-icons"></ion-icon>
<span class="lte-icon-content">
<span class="lte-header lte-h5"> Člen VV </span>
<span class="lte-descr">Mgr. Martin Janečka<br />605 089 558</span>
</span>
</div>
</li>
<li class=" col-lg-12 col-md-12 col-sm-12 col-ms-12 col-xs-12">
<div class="lte-inner">
<ion-icon name="person-outline" class="ion-icons"></ion-icon>
<span class="lte-icon-content">
<span class="lte-header lte-h5"> Člen VV </span>
<span class="lte-descr">Mgr. Jakub Řičica<br />721 502 700</span>
</span>
</div>
</li>
<li class=" col-lg-12 col-md-12 col-sm-12 col-ms-12 col-xs-12">
<div class="lte-inner">
<ion-icon name="person-outline" class="ion-icons"></ion-icon>
<span class="lte-icon-content">
<span class="lte-header lte-h5"> Člen VV </span>
<span class="lte-descr">Jaroslav Náplava<br />603 950 224</span>
</span>
</div>
</li>
</ul>
</div>
</div>
<div class="elementor-element elementor-element-16d0b91 elementor-widget elementor-widget-spacer" data-id="16d0b91" data-element_type="widget" data-widget_type="spacer.default">
<div class="elementor-widget-container">
<div class="elementor-spacer">
<div class="elementor-spacer-inner"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
</div>
</article>
</div>
</div>
</div>
</div>
<div class="lte-footer-wrapper lte-footer-layout-default">
<div class="footer-wrapper">
<div class="lte-container">
<div class="footer-block lte-footer-widget-area">
<div data-elementor-type="wp-post" data-elementor-id="29393" class="elementor elementor-29393">
<div class="elementor-element elementor-element-a939976 lte-background-black e-flex e-con-boxed e-con e-parent" data-id="a939976" data-element_type="container" data-settings="{&quot;background_background&quot;:&quot;classic&quot;}" data-core-v316-plus="true">
<div class="e-con-inner" style="padding-bottom: 92px;">
<div class="elementor-element elementor-element-f2b730e e-con-full e-flex e-con e-child" data-id="f2b730e" data-element_type="container">
<div class="elementor-element elementor-element-81a7a24 elementor-widget__width-initial elementor-widget elementor-widget-shortcode" data-id="81a7a24" data-element_type="widget" data-widget_type="shortcode.default">
<div class="elementor-widget-container">
<div class="elementor-shortcode">
<a class="lte-logo" href="index.html">
<img src="img/logo.png" style="filter: drop-shadow(9px -1px 23px black);">
</a>
</div>
</div>
</div>
<div class="elementor-element elementor-element-86345d3 elementor-widget__width-initial elementor-widget elementor-widget-text-editor" data-id="86345d3" data-element_type="widget" data-widget_type="text-editor.default">
<div class="elementor-widget-container">
<p>
<span class="text-sm">
<a href="https://maps.app.goo.gl/kEc9CJuXTxqNUhgj8" target="_blank">Stonky 559, 686 01 Uherské Hradiště 1</a>
<br>fcbizoni@gmail.com </span>
</p>
</div>
</div>
<div class="elementor-element elementor-element-475baf0 elementor-widget elementor-widget-lte-elements" data-id="475baf0" data-element_type="widget" data-widget_type="lte-elements.default">
<div class="elementor-widget-container">
<div class="lte-social lte-nav-second lte-type-">
<ul>
<li>
<a href="https://www.facebook.com/bizoniuh" target="_blank">
<ion-icon name="logo-facebook" style="height: 22px; width: 22px;"></ion-icon>
</a>
</li>
<li>
<a href="https://www.instagram.com/fcbizoni_uh/" target="_blank">
<ion-icon name="logo-instagram" style="height: 22px; width: 22px;"></ion-icon>
</a>
</li>
<li>
<a href="https://www.youtube.com/@FCBizoniUH" target="_blank">
<ion-icon name="logo-youtube" style="height: 22px; width: 22px;"></ion-icon>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<footer class="copyright-block copyright-layout-copyright-transparent">
<div class="container">
<p>
<a href="https://tdvorak.dev" target="_blank">TDvorak</a> © Všechna práva vyhrazena - 2024
</p>
</div>
</footer>
</div>
<a href="#" class="lte-go-top floating lte-go-top-icon">
<span class="go-top-icon-v2 icon">
<ion-icon name="football-outline" style="padding-right: 2px;"></ion-icon>
</span>
<span class="go-top-header">Nahoru</span>
</a>
<link rel='stylesheet' id='elementor-post-36123-css' href='css/post-36123.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-36124-css' href='css/post-36124.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-35532-css' href='css/post-35532.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-36129-css' href='css/post-36129.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-36131-css' href='css/post-36131.css' type='text/css' media='all' />
<link rel='stylesheet' id='lte-zoomslider-css' href='css/zoom-slider.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-20251-css' href='css/post-20251.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-29393-css' href='css/post-29393.css' type='text/css' media='all' />
<script type="text/javascript" src="js/parallax-js.js" id="parallax-js-js"></script>
<script type="text/javascript" src="js/scripts.js" id="atleticos-scripts-js"></script>
<script type="text/javascript" src="js/swiper.min.js" id="swiper-js"></script>
<script type="text/javascript" src="js/frontend.js" id="lte-frontend-js"></script>
<script type="text/javascript" src="js/jquery.zoomslider.js" id="lte-zoomslider-js"></script>
<script type="text/javascript" src="js/webpack.runtime.min.js" id="elementor-webpack-runtime-js"></script>
<script type="text/javascript" src="js/frontend-modules.min.js" id="elementor-frontend-modules-js"></script>
<script type="text/javascript" src="js/waypoints.min.js" id="elementor-waypoints-js"></script>
<script type="text/javascript" src="js/core.min.js" id="jquery-ui-core-js"></script>
<script type="text/javascript" id="elementor-frontend-js-before">
/*
<![CDATA[ */
var elementorFrontendConfig = {
"environmentMode": {
"edit": false,
"wpPreview": false,
"isScriptDebug": false
},
"i18n": {
"shareOnFacebook": "Share on Facebook",
"shareOnTwitter": "Share on Twitter",
"pinIt": "Pin it",
"download": "Download",
"downloadImage": "Download image",
"fullscreen": "Fullscreen",
"zoom": "Zoom",
"share": "Share",
"playVideo": "Play Video",
"previous": "Previous",
"next": "Next",
"close": "Close",
"a11yCarouselWrapperAriaLabel": "Carousel | Horizontal scrolling: Arrow Left & Right",
"a11yCarouselPrevSlideMessage": "Previous slide",
"a11yCarouselNextSlideMessage": "Next slide",
"a11yCarouselFirstSlideMessage": "This is the first slide",
"a11yCarouselLastSlideMessage": "This is the last slide",
"a11yCarouselPaginationBulletMessage": "Go to slide"
},
"is_rtl": false,
"breakpoints": {
"xs": 0,
"sm": 480,
"md": 768,
"lg": 1200,
"xl": 1440,
"xxl": 1600
},
"responsive": {
"breakpoints": {
"mobile": {
"label": "Mobile Portrait",
"value": 767,
"default_value": 767,
"direction": "max",
"is_enabled": true
},
"mobile_extra": {
"label": "Mobile Landscape",
"value": 991,
"default_value": 880,
"direction": "max",
"is_enabled": true
},
"tablet": {
"label": "Tablet Portrait",
"value": 1199,
"default_value": 1024,
"direction": "max",
"is_enabled": true
},
"tablet_extra": {
"label": "Tablet Landscape",
"value": 1366,
"default_value": 1200,
"direction": "max",
"is_enabled": true
},
"laptop": {
"label": "Laptop",
"value": 1599,
"default_value": 1366,
"direction": "max",
"is_enabled": true
},
"widescreen": {
"label": "Widescreen",
"value": 1900,
"default_value": 2400,
"direction": "min",
"is_enabled": true
}
}
},
"version": "3.20.1",
"is_static": false,
"experimentalFeatures": {
"e_optimized_assets_loading": true,
"additional_custom_breakpoints": true,
"container": true,
"e_swiper_latest": true,
"block_editor_assets_optimize": true,
"ai-layout": true,
"landing-pages": true,
"nested-elements": true,
"e_image_loading_optimization": true
},
"urls": {
"assets": "./js/text-editor.2c35aafbe5bf0e127950.bundle.min.js"
},
"swiperClass": "swiper",
"settings": {
"page": [],
"editorPreferences": []
},
"kit": {
"viewport_tablet": 1199,
"viewport_mobile": 767,
"active_breakpoints": ["viewport_mobile", "viewport_mobile_extra", "viewport_tablet", "viewport_tablet_extra", "viewport_laptop", "viewport_widescreen"],
"viewport_mobile_extra": 991,
"viewport_laptop": 1599,
"viewport_widescreen": 1900,
"viewport_tablet_extra": 1366,
"lightbox_enable_counter": "yes",
"lightbox_enable_fullscreen": "yes",
"lightbox_enable_zoom": "yes",
"lightbox_enable_share": "yes",
"lightbox_title_src": "title",
"lightbox_description_src": "description"
},
"post": {
"id": 32647,
"title": "",
"excerpt": "",
"featuredImage": false
}
};
/* ]]> */
</script>
<script type="text/javascript" src="js/frontend.min.js" id="elementor-frontend-js"></script>
<script>
// Ensure the DOM is fully loaded before adding event listeners
document.addEventListener("DOMContentLoaded", function() {
// Get the buttons and the navbar element
const openButton = document.getElementById('open-button');
const closeButton = document.getElementById('close-button');
const navbar = document.getElementById('navbar');
// Log to check if elements exist
console.log('Open button:', openButton);
console.log('Close button:', closeButton);
console.log('Navbar:', navbar);
// Ensure that buttons and navbar exist
if (openButton && closeButton && navbar) {
console.log('Elements found and event listeners ready.');
// Add event listener to the open button
openButton.addEventListener('click', function() {
console.log('Open button clicked');
});
// Add event listener to the close button
closeButton.addEventListener('click', function() {
console.log('Close button clicked');
});
} else {
console.error('Error: Buttons or navbar element not found.');
}
});
</script>
</body>
</html>
+369 -369
View File
@@ -1,370 +1,370 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>Bizoni UH - Zápasy</title>
<link rel="icon" type="image/x-icon" href="../img/logo.png">
<!-- Stylesheets -->
<link rel="stylesheet" id="swiper-css" href="../css/swiper.css" type="text/css" media="all" />
<link rel="stylesheet" id="bootstrap-css" href="../css/bootstrap.css" type="text/css" media="all" />
<link rel="stylesheet" id="atleticos-theme-style-css" href="../css/bizoni.css" type="text/css" media="all" />
<link rel="stylesheet" id="elementor-icons-css" href="../css/elementor-icons.min.css" type="text/css" media="all" />
<link rel="stylesheet" id="elementor-frontend-css" href="../css/custom-frontend.min.css" type="text/css" media="all" />
<link rel="stylesheet" id="elementor-post-13200-css" href="../css/post-13200.css" type="text/css" media="all" />
<!-- External Stylesheets -->
<link rel="stylesheet" id="elementor-post-32647-css" href="../css/post-32647.css" type="text/css" media="all" />
<link rel="stylesheet" id="event-tickets-rsvp-css" href="../css/rsvp.min.css" type="text/css" media="all" />
<link rel="stylesheet" id="magnific-popup-css" href="../css/magnific-popup.css" type="text/css" media="all" />
<script type="text/javascript" src="../js/jquery.nicescroll.js" id="nicescroll-js"></script>
<link rel="stylesheet" id="atleticos-google-fonts-css" href="//fonts.googleapis.com/css?family=Open+Sans:400,400i,600,700%7CSofia+Sans+Extra+Condensed:800,300i" type="text/css" media="all" />
<link rel="stylesheet" id="font-awesome-shims-css" href="../css/v4-shims.min.css" type="text/css" media="all" />
<link rel="stylesheet" id="lte-font-css" href="../css/lte-font-codes.css" type="text/css" media="all" />
<link rel="stylesheet" id="google-fonts-1-css" href="https://fonts.googleapis.com/css?family=Open+Sans%3A100%2C100italic%2C200%2C200italic%2C300%2C300italic%2C400%2C400italic%2C500%2C500italic%2C600%2C600italic%2C700%2C700italic%2C800%2C800italic%2C900%2C900italic%7CMarcellus%7CTangerine&#038;display=auto&#038;ver=6.4.5" type="text/css" media="all" />
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Scripts -->
<script type="module" src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js"></script>
<script nomodule src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"></script>
<script type="text/javascript" src="../js/jquery.min.js" id="jquery-core-js"></script>
<script type="text/javascript" src="../js/jquery-migrate.min.js" id="jquery-migrate-js"></script>
<script type="text/javascript" src="../js/jquery.blockUI.min.js" id="jquery-blockui-js" defer="defer"></script>
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full">
<div class="lte-header-wrapper header-h1 header-parallax lte-header-overlay lte-layout-transparent-full lte-pageheader-disabled">
<div id="lte-nav-wrapper" class="lte-layout-transparent-full lte-nav-color-white">
<nav class="lte-navbar affix" data-spy="affix" data-offset-top="0">
<div class="container">
<!-- Logo -->
<div class="lte-navbar-logo">
<a class="lte-logo" href="../index.html">
<img src="../img/logo.png">
</a>
</div>
<!-- Navigation Items -->
<div class="lte-navbar-items navbar-mobile-black navbar-collapse collapse" id="navbar" data-mobile-screen-width="1198">
<div class="toggle-wrap">
<a class="lte-logo" href="../index.html">
<img src="../img/logo.png">
</a>
<button type="button" class="lte-navbar-toggle collapsed" id="close-button">
<span class="close">&times;</span>
</button>
<div class="clearfix"></div>
</div>
<!-- Navigation Menu -->
<ul id="menu-main-menu" class="lte-ul-nav">
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="../index.html">
<span>Domů</span>
</a>
</li>
<li id="menu-item-29540" class="menu-item menu-item-type-post_type menu-item-object-page">
<a href="../o-nas.html">
<span>O nás</span>
</a>
</li>
<li id="menu-item-59" class="menu-item menu-item-type-custom">
<a href="../blog.html">
<span>Blog</span>
</a>
</li>
<li id="menu-item-13613" class="menu-item menu-item-type-post_type menu-item-object-page">
<a href="../kontakt.html">
<span>Kontakt</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="../index.html#tym">
<span>Tým</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="../index.html#sponzori">
<span>Sponzoři</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a target="_blank" href="https://eu.zonerama.com/Fcbizoni/1419417">
<span>Fotogalerie</span>
</a>
</li>
</ul>
</div>
<!-- Mobile Menu Toggle -->
<button type="button" class="lte-navbar-toggle" id="open-button">
<span class="icon-bar top-bar"></span>
<span class="icon-bar middle-bar"></span>
<span class="icon-bar bottom-bar"></span>
</button>
</div>
</nav>
</div>
<header class="lte-page-header lte-parallax-yes">
<div class="container">
<div class="lte-header-h1-wrapper">
<h1 class="lte-header">Všechny zápasy</h1>
</div>
</div>
</header>
</div>
<div class="container main-wrapper">
<div class="inner-page margin-default">
<div id="facr-all-matches" class="lte-football-matches inner-page"></div>
<div class="clearfix"></div>
</div>
</div>
</div>
<div class="lte-footer-wrapper lte-footer-layout-default">
<div class="footer-wrapper">
<div class="lte-container">
<div class="footer-block lte-footer-widget-area">
<div data-elementor-type="wp-post" data-elementor-id="29393" class="elementor elementor-29393">
<div class="elementor-element elementor-element-a939976 lte-background-black e-flex e-con-boxed e-con e-parent" data-id="a939976" data-element_type="container" data-settings="{&quot;background_background&quot;:&quot;classic&quot;}" data-core-v316-plus="true">
<div class="e-con-inner" style="padding-bottom: 92px;">
<div class="elementor-element elementor-element-f2b730e e-con-full e-flex e-con e-child" data-id="f2b730e" data-element_type="container">
<div class="elementor-element elementor-element-81a7a24 elementor-widget__width-initial elementor-widget elementor-widget-shortcode" data-id="81a7a24" data-element_type="widget" data-widget_type="shortcode.default">
<div class="elementor-widget-container">
<div class="elementor-shortcode">
<a class="lte-logo" href="../index.html">
<img src="../img/logo.png" style="filter: drop-shadow(9px -1px 23px black);">
</a>
</div>
</div>
</div>
<div class="elementor-element elementor-element-86345d3 elementor-widget__width-initial elementor-widget elementor-widget-text-editor" data-id="86345d3" data-element_type="widget" data-widget_type="text-editor.default">
<div class="elementor-widget-container">
<p>
<span class="text-sm">
<a href="https://maps.app.goo.gl/kEc9CJuXTxqNUhgj8" target="_blank">Stonky 559, 686 01 Uherské Hradiště 1</a>
<br>fcbizoni@gmail.com </span>
</p>
</div>
</div>
<div class="elementor-element elementor-element-475baf0 elementor-widget elementor-widget-lte-elements" data-id="475baf0" data-element_type="widget" data-widget_type="lte-elements.default">
<div class="elementor-widget-container">
<div class="lte-social lte-nav-second lte-type-">
<ul>
<li>
<a href="https://www.facebook.com/bizoniuh" target="_blank">
<ion-icon name="logo-facebook" style="height: 22px; width: 22px;"></ion-icon>
</a>
</li>
<li>
<a href="https://www.instagram.com/fcbizoni_uh/" target="_blank">
<ion-icon name="logo-instagram" style="height: 22px; width: 22px;"></ion-icon>
</a>
</li>
<li>
<a href="https://www.youtube.com/@FCBizoniUH" target="_blank">
<ion-icon name="logo-youtube" style="height: 22px; width: 22px;"></ion-icon>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<footer class="copyright-block copyright-layout-copyright-transparent">
<div class="container">
<p>
<a href="https://tdvorak.dev" target="_blank">TDvorak</a> © Všechna práva vyhrazena - 2024
</p>
</div>
</footer>
</div>
<a href="#" class="lte-go-top floating lte-go-top-icon">
<span class="go-top-icon-v2 icon">
<ion-icon name="football-outline" style="padding-right: 2px;"></ion-icon>
</span>
<span class="go-top-header">Nahoru</span>
</a>
<script src="../js/facr-frontend.js"></script>
<link rel='stylesheet' id='elementor-post-36123-css' href='../css/post-36123.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-36124-css' href='../css/post-36124.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-35532-css' href='../css/post-35532.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-36129-css' href='../css/post-36129.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-36131-css' href='../css/post-36131.css' type='text/css' media='all' />
<link rel='stylesheet' id='lte-zoomslider-css' href='../css/zoom-slider.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-20251-css' href='../css/post-20251.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-29393-css' href='../css/post-29393.css' type='text/css' media='all' />
<script type="text/javascript" src="../js/parallax-js.js" id="parallax-js-js"></script>
<script type="text/javascript" src="../js/scripts.js" id="atleticos-scripts-js"></script>
<script type="text/javascript" src="../js/swiper.min.js" id="swiper-js"></script>
<script type="text/javascript" src="../js/frontend.js" id="lte-frontend-js"></script>
<script type="text/javascript" src="../js/jquery.zoomslider.js" id="lte-zoomslider-js"></script>
<script type="text/javascript" src="../js/webpack.runtime.min.js" id="elementor-webpack-runtime-js"></script>
<script type="text/javascript" src="../js/frontend-modules.min.js" id="elementor-frontend-modules-js"></script>
<script type="text/javascript" src="../js/waypoints.min.js" id="elementor-waypoints-js"></script>
<script type="text/javascript" src="../js/core.min.js" id="jquery-ui-core-js"></script>
<script type="text/javascript" id="elementor-frontend-js-before">
/*
<![CDATA[ */
var elementorFrontendConfig = {
"environmentMode": {
"edit": false,
"wpPreview": false,
"isScriptDebug": false
},
"i18n": {
"shareOnFacebook": "Share on Facebook",
"shareOnTwitter": "Share on Twitter",
"pinIt": "Pin it",
"download": "Download",
"downloadImage": "Download image",
"fullscreen": "Fullscreen",
"zoom": "Zoom",
"share": "Share",
"playVideo": "Play Video",
"previous": "Previous",
"next": "Next",
"close": "Close",
"a11yCarouselWrapperAriaLabel": "Carousel | Horizontal scrolling: Arrow Left & Right",
"a11yCarouselPrevSlideMessage": "Previous slide",
"a11yCarouselNextSlideMessage": "Next slide",
"a11yCarouselFirstSlideMessage": "This is the first slide",
"a11yCarouselLastSlideMessage": "This is the last slide",
"a11yCarouselPaginationBulletMessage": "Go to slide"
},
"is_rtl": false,
"breakpoints": {
"xs": 0,
"sm": 480,
"md": 768,
"lg": 1200,
"xl": 1440,
"xxl": 1600
},
"responsive": {
"breakpoints": {
"mobile": {
"label": "Mobile Portrait",
"value": 767,
"default_value": 767,
"direction": "max",
"is_enabled": true
},
"mobile_extra": {
"label": "Mobile Landscape",
"value": 991,
"default_value": 880,
"direction": "max",
"is_enabled": true
},
"tablet": {
"label": "Tablet Portrait",
"value": 1199,
"default_value": 1024,
"direction": "max",
"is_enabled": true
},
"tablet_extra": {
"label": "Tablet Landscape",
"value": 1366,
"default_value": 1200,
"direction": "max",
"is_enabled": true
},
"laptop": {
"label": "Laptop",
"value": 1599,
"default_value": 1366,
"direction": "max",
"is_enabled": true
},
"widescreen": {
"label": "Widescreen",
"value": 1900,
"default_value": 2400,
"direction": "min",
"is_enabled": true
}
}
},
"version": "3.20.1",
"is_static": false,
"experimentalFeatures": {
"e_optimized_assets_loading": true,
"additional_custom_breakpoints": true,
"container": true,
"e_swiper_latest": true,
"block_editor_assets_optimize": true,
"ai-layout": true,
"landing-pages": true,
"nested-elements": true,
"e_image_loading_optimization": true
},
"urls": {
"assets": ".../js/text-editor.2c35aafbe5bf0e127950.bundle.min.js"
},
"swiperClass": "swiper",
"settings": {
"page": [],
"editorPreferences": []
},
"kit": {
"viewport_tablet": 1199,
"viewport_mobile": 767,
"active_breakpoints": ["viewport_mobile", "viewport_mobile_extra", "viewport_tablet", "viewport_tablet_extra", "viewport_laptop", "viewport_widescreen"],
"viewport_mobile_extra": 991,
"viewport_laptop": 1599,
"viewport_widescreen": 1900,
"viewport_tablet_extra": 1366,
"lightbox_enable_counter": "yes",
"lightbox_enable_fullscreen": "yes",
"lightbox_enable_zoom": "yes",
"lightbox_enable_share": "yes",
"lightbox_title_src": "title",
"lightbox_description_src": "description"
},
"post": {
"id": 32647,
"title": "",
"excerpt": "",
"featuredImage": false
}
};
/* ]]> */
</script>
<script type="text/javascript" src="../js/frontend.min.js" id="elementor-frontend-js"></script>
<script>
// Ensure the DOM is fully loaded before adding event listeners
document.addEventListener("DOMContentLoaded", function() {
// Get the buttons and the navbar element
const openButton = document.getElementById('open-button');
const closeButton = document.getElementById('close-button');
const navbar = document.getElementById('navbar');
// Log to check if elements exist
console.log('Open button:', openButton);
console.log('Close button:', closeButton);
console.log('Navbar:', navbar);
// Ensure that buttons and navbar exist
if (openButton && closeButton && navbar) {
console.log('Elements found and event listeners ready.');
// Add event listener to the open button
openButton.addEventListener('click', function() {
console.log('Open button clicked');
});
// Add event listener to the close button
closeButton.addEventListener('click', function() {
console.log('Close button clicked');
});
} else {
console.error('Error: Buttons or navbar element not found.');
}
});
</script>
</body>
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>Bizoni UH - Zápasy</title>
<link rel="icon" type="image/x-icon" href="../img/logo.png">
<!-- Stylesheets -->
<link rel="stylesheet" id="swiper-css" href="../css/swiper.css" type="text/css" media="all" />
<link rel="stylesheet" id="bootstrap-css" href="../css/bootstrap.css" type="text/css" media="all" />
<link rel="stylesheet" id="atleticos-theme-style-css" href="../css/bizoni.css" type="text/css" media="all" />
<link rel="stylesheet" id="elementor-icons-css" href="../css/elementor-icons.min.css" type="text/css" media="all" />
<link rel="stylesheet" id="elementor-frontend-css" href="../css/custom-frontend.min.css" type="text/css" media="all" />
<link rel="stylesheet" id="elementor-post-13200-css" href="../css/post-13200.css" type="text/css" media="all" />
<!-- External Stylesheets -->
<link rel="stylesheet" id="elementor-post-32647-css" href="../css/post-32647.css" type="text/css" media="all" />
<link rel="stylesheet" id="event-tickets-rsvp-css" href="../css/rsvp.min.css" type="text/css" media="all" />
<link rel="stylesheet" id="magnific-popup-css" href="../css/magnific-popup.css" type="text/css" media="all" />
<script type="text/javascript" src="../js/jquery.nicescroll.js" id="nicescroll-js"></script>
<link rel="stylesheet" id="atleticos-google-fonts-css" href="//fonts.googleapis.com/css?family=Open+Sans:400,400i,600,700%7CSofia+Sans+Extra+Condensed:800,300i" type="text/css" media="all" />
<link rel="stylesheet" id="font-awesome-shims-css" href="../css/v4-shims.min.css" type="text/css" media="all" />
<link rel="stylesheet" id="lte-font-css" href="../css/lte-font-codes.css" type="text/css" media="all" />
<link rel="stylesheet" id="google-fonts-1-css" href="https://fonts.googleapis.com/css?family=Open+Sans%3A100%2C100italic%2C200%2C200italic%2C300%2C300italic%2C400%2C400italic%2C500%2C500italic%2C600%2C600italic%2C700%2C700italic%2C800%2C800italic%2C900%2C900italic%7CMarcellus%7CTangerine&#038;display=auto&#038;ver=6.4.5" type="text/css" media="all" />
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Scripts -->
<script type="module" src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js"></script>
<script nomodule src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"></script>
<script type="text/javascript" src="../js/jquery.min.js" id="jquery-core-js"></script>
<script type="text/javascript" src="../js/jquery-migrate.min.js" id="jquery-migrate-js"></script>
<script type="text/javascript" src="../js/jquery.blockUI.min.js" id="jquery-blockui-js" defer="defer"></script>
<script type="text/javascript" src="../js/jquery.paroller.js" id="jquery-paroller-js"></script>
<script type="text/javascript" src="../js/modernizr-2.6.2.min.js" id="modernizr-js"></script>
<script type="text/javascript" src="../js/script.js"></script>
</head>
<body class="home page-template page-template-page-templates page-template-full-width page page-id-32647 theme-atleticos woocommerce-no-js tribe-no-js tec-no-tickets-on-recurring tec-no-rsvp-on-recurring full-width lte-fw-loaded lte-color-scheme-default lte-body-white lte-background-white paceloader-disabled no-sidebar elementor-default elementor-kit-13200 elementor-page elementor-page-32647 tribe-theme-atleticos">
<div class="lte-content-wrapper lte-layout-transparent-full">
<div class="lte-header-wrapper header-h1 header-parallax lte-header-overlay lte-layout-transparent-full lte-pageheader-disabled">
<div id="lte-nav-wrapper" class="lte-layout-transparent-full lte-nav-color-white">
<nav class="lte-navbar affix" data-spy="affix" data-offset-top="0">
<div class="container">
<!-- Logo -->
<div class="lte-navbar-logo">
<a class="lte-logo" href="../index.html">
<img src="../img/logo.png">
</a>
</div>
<!-- Navigation Items -->
<div class="lte-navbar-items navbar-mobile-black navbar-collapse collapse" id="navbar" data-mobile-screen-width="1198">
<div class="toggle-wrap">
<a class="lte-logo" href="../index.html">
<img src="../img/logo.png">
</a>
<button type="button" class="lte-navbar-toggle collapsed" id="close-button">
<span class="close">&times;</span>
</button>
<div class="clearfix"></div>
</div>
<!-- Navigation Menu -->
<ul id="menu-main-menu" class="lte-ul-nav">
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="../index.html">
<span>Domů</span>
</a>
</li>
<li id="menu-item-29540" class="menu-item menu-item-type-post_type menu-item-object-page">
<a href="../o-nas.html">
<span>O nás</span>
</a>
</li>
<li id="menu-item-59" class="menu-item menu-item-type-custom">
<a href="../blog.html">
<span>Blog</span>
</a>
</li>
<li id="menu-item-13613" class="menu-item menu-item-type-post_type menu-item-object-page">
<a href="../kontakt.html">
<span>Kontakt</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="../index.html#tym">
<span>Tým</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a href="../index.html#sponzori">
<span>Sponzoři</span>
</a>
</li>
<li id="menu-item-20758" class="menu-item menu-item-type-custom current-menu-ancestor current-menu-parent">
<a target="_blank" href="https://eu.zonerama.com/Fcbizoni/1419417">
<span>Fotogalerie</span>
</a>
</li>
</ul>
</div>
<!-- Mobile Menu Toggle -->
<button type="button" class="lte-navbar-toggle" id="open-button">
<span class="icon-bar top-bar"></span>
<span class="icon-bar middle-bar"></span>
<span class="icon-bar bottom-bar"></span>
</button>
</div>
</nav>
</div>
<header class="lte-page-header lte-parallax-yes">
<div class="container">
<div class="lte-header-h1-wrapper">
<h1 class="lte-header">Všechny zápasy</h1>
</div>
</div>
</header>
</div>
<div class="container main-wrapper">
<div class="inner-page margin-default">
<div id="facr-all-matches" class="lte-football-matches inner-page"></div>
<div class="clearfix"></div>
</div>
</div>
</div>
<div class="lte-footer-wrapper lte-footer-layout-default">
<div class="footer-wrapper">
<div class="lte-container">
<div class="footer-block lte-footer-widget-area">
<div data-elementor-type="wp-post" data-elementor-id="29393" class="elementor elementor-29393">
<div class="elementor-element elementor-element-a939976 lte-background-black e-flex e-con-boxed e-con e-parent" data-id="a939976" data-element_type="container" data-settings="{&quot;background_background&quot;:&quot;classic&quot;}" data-core-v316-plus="true">
<div class="e-con-inner" style="padding-bottom: 92px;">
<div class="elementor-element elementor-element-f2b730e e-con-full e-flex e-con e-child" data-id="f2b730e" data-element_type="container">
<div class="elementor-element elementor-element-81a7a24 elementor-widget__width-initial elementor-widget elementor-widget-shortcode" data-id="81a7a24" data-element_type="widget" data-widget_type="shortcode.default">
<div class="elementor-widget-container">
<div class="elementor-shortcode">
<a class="lte-logo" href="../index.html">
<img src="../img/logo.png" style="filter: drop-shadow(9px -1px 23px black);">
</a>
</div>
</div>
</div>
<div class="elementor-element elementor-element-86345d3 elementor-widget__width-initial elementor-widget elementor-widget-text-editor" data-id="86345d3" data-element_type="widget" data-widget_type="text-editor.default">
<div class="elementor-widget-container">
<p>
<span class="text-sm">
<a href="https://maps.app.goo.gl/kEc9CJuXTxqNUhgj8" target="_blank">Stonky 559, 686 01 Uherské Hradiště 1</a>
<br>fcbizoni@gmail.com </span>
</p>
</div>
</div>
<div class="elementor-element elementor-element-475baf0 elementor-widget elementor-widget-lte-elements" data-id="475baf0" data-element_type="widget" data-widget_type="lte-elements.default">
<div class="elementor-widget-container">
<div class="lte-social lte-nav-second lte-type-">
<ul>
<li>
<a href="https://www.facebook.com/bizoniuh" target="_blank">
<ion-icon name="logo-facebook" style="height: 22px; width: 22px;"></ion-icon>
</a>
</li>
<li>
<a href="https://www.instagram.com/fcbizoni_uh/" target="_blank">
<ion-icon name="logo-instagram" style="height: 22px; width: 22px;"></ion-icon>
</a>
</li>
<li>
<a href="https://www.youtube.com/@FCBizoniUH" target="_blank">
<ion-icon name="logo-youtube" style="height: 22px; width: 22px;"></ion-icon>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<footer class="copyright-block copyright-layout-copyright-transparent">
<div class="container">
<p>
<a href="https://tdvorak.dev" target="_blank">TDvorak</a> © Všechna práva vyhrazena - 2024
</p>
</div>
</footer>
</div>
<a href="#" class="lte-go-top floating lte-go-top-icon">
<span class="go-top-icon-v2 icon">
<ion-icon name="football-outline" style="padding-right: 2px;"></ion-icon>
</span>
<span class="go-top-header">Nahoru</span>
</a>
<script src="../js/facr-frontend.js"></script>
<link rel='stylesheet' id='elementor-post-36123-css' href='../css/post-36123.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-36124-css' href='../css/post-36124.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-35532-css' href='../css/post-35532.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-36129-css' href='../css/post-36129.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-36131-css' href='../css/post-36131.css' type='text/css' media='all' />
<link rel='stylesheet' id='lte-zoomslider-css' href='../css/zoom-slider.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-20251-css' href='../css/post-20251.css' type='text/css' media='all' />
<link rel='stylesheet' id='elementor-post-29393-css' href='../css/post-29393.css' type='text/css' media='all' />
<script type="text/javascript" src="../js/parallax-js.js" id="parallax-js-js"></script>
<script type="text/javascript" src="../js/scripts.js" id="atleticos-scripts-js"></script>
<script type="text/javascript" src="../js/swiper.min.js" id="swiper-js"></script>
<script type="text/javascript" src="../js/frontend.js" id="lte-frontend-js"></script>
<script type="text/javascript" src="../js/jquery.zoomslider.js" id="lte-zoomslider-js"></script>
<script type="text/javascript" src="../js/webpack.runtime.min.js" id="elementor-webpack-runtime-js"></script>
<script type="text/javascript" src="../js/frontend-modules.min.js" id="elementor-frontend-modules-js"></script>
<script type="text/javascript" src="../js/waypoints.min.js" id="elementor-waypoints-js"></script>
<script type="text/javascript" src="../js/core.min.js" id="jquery-ui-core-js"></script>
<script type="text/javascript" id="elementor-frontend-js-before">
/*
<![CDATA[ */
var elementorFrontendConfig = {
"environmentMode": {
"edit": false,
"wpPreview": false,
"isScriptDebug": false
},
"i18n": {
"shareOnFacebook": "Share on Facebook",
"shareOnTwitter": "Share on Twitter",
"pinIt": "Pin it",
"download": "Download",
"downloadImage": "Download image",
"fullscreen": "Fullscreen",
"zoom": "Zoom",
"share": "Share",
"playVideo": "Play Video",
"previous": "Previous",
"next": "Next",
"close": "Close",
"a11yCarouselWrapperAriaLabel": "Carousel | Horizontal scrolling: Arrow Left & Right",
"a11yCarouselPrevSlideMessage": "Previous slide",
"a11yCarouselNextSlideMessage": "Next slide",
"a11yCarouselFirstSlideMessage": "This is the first slide",
"a11yCarouselLastSlideMessage": "This is the last slide",
"a11yCarouselPaginationBulletMessage": "Go to slide"
},
"is_rtl": false,
"breakpoints": {
"xs": 0,
"sm": 480,
"md": 768,
"lg": 1200,
"xl": 1440,
"xxl": 1600
},
"responsive": {
"breakpoints": {
"mobile": {
"label": "Mobile Portrait",
"value": 767,
"default_value": 767,
"direction": "max",
"is_enabled": true
},
"mobile_extra": {
"label": "Mobile Landscape",
"value": 991,
"default_value": 880,
"direction": "max",
"is_enabled": true
},
"tablet": {
"label": "Tablet Portrait",
"value": 1199,
"default_value": 1024,
"direction": "max",
"is_enabled": true
},
"tablet_extra": {
"label": "Tablet Landscape",
"value": 1366,
"default_value": 1200,
"direction": "max",
"is_enabled": true
},
"laptop": {
"label": "Laptop",
"value": 1599,
"default_value": 1366,
"direction": "max",
"is_enabled": true
},
"widescreen": {
"label": "Widescreen",
"value": 1900,
"default_value": 2400,
"direction": "min",
"is_enabled": true
}
}
},
"version": "3.20.1",
"is_static": false,
"experimentalFeatures": {
"e_optimized_assets_loading": true,
"additional_custom_breakpoints": true,
"container": true,
"e_swiper_latest": true,
"block_editor_assets_optimize": true,
"ai-layout": true,
"landing-pages": true,
"nested-elements": true,
"e_image_loading_optimization": true
},
"urls": {
"assets": ".../js/text-editor.2c35aafbe5bf0e127950.bundle.min.js"
},
"swiperClass": "swiper",
"settings": {
"page": [],
"editorPreferences": []
},
"kit": {
"viewport_tablet": 1199,
"viewport_mobile": 767,
"active_breakpoints": ["viewport_mobile", "viewport_mobile_extra", "viewport_tablet", "viewport_tablet_extra", "viewport_laptop", "viewport_widescreen"],
"viewport_mobile_extra": 991,
"viewport_laptop": 1599,
"viewport_widescreen": 1900,
"viewport_tablet_extra": 1366,
"lightbox_enable_counter": "yes",
"lightbox_enable_fullscreen": "yes",
"lightbox_enable_zoom": "yes",
"lightbox_enable_share": "yes",
"lightbox_title_src": "title",
"lightbox_description_src": "description"
},
"post": {
"id": 32647,
"title": "",
"excerpt": "",
"featuredImage": false
}
};
/* ]]> */
</script>
<script type="text/javascript" src="../js/frontend.min.js" id="elementor-frontend-js"></script>
<script>
// Ensure the DOM is fully loaded before adding event listeners
document.addEventListener("DOMContentLoaded", function() {
// Get the buttons and the navbar element
const openButton = document.getElementById('open-button');
const closeButton = document.getElementById('close-button');
const navbar = document.getElementById('navbar');
// Log to check if elements exist
console.log('Open button:', openButton);
console.log('Close button:', closeButton);
console.log('Navbar:', navbar);
// Ensure that buttons and navbar exist
if (openButton && closeButton && navbar) {
console.log('Elements found and event listeners ready.');
// Add event listener to the open button
openButton.addEventListener('click', function() {
console.log('Open button clicked');
});
// Add event listener to the close button
closeButton.addEventListener('click', function() {
console.log('Close button clicked');
});
} else {
console.error('Error: Buttons or navbar element not found.');
}
});
</script>
</body>
</html>