┌────────────────────────────────┐ │ ░░░ ░░▓ ░▓▓ ███ ▓▓░ ▓░░ │ │ ~ M O O N ~ │ └────────────────────────────────┘
prd-web-01.centraldc.gr
LOCATION:
/var/www/html/adconect/wp-content/plugins/shortcode-slider
☗ ROOT
↻ REFRESH
✎ EDIT FILE
EDITING: shortcode-slider.php
<?php /** * Plugin Name: Slider Shortcode * Description: Προσθέτει ένα shortcode για εύκολη δημιουργία slider με διάφορες επιλογές. [init_slider target="#Slider" autonext="true" duration="4" stoponhover="true" arrows="true" bullets="true" columns="1" min_height="50px" height="" breakpoint="0" mobile_breakpoint="768px" mobile_width="100%" mobile_columns="1" mobile_autonext="true" mobile_duration="4" mobile_arrows="true" mobile_bullets="true" mobile_stoponhover="true" mobile_min_height="50px"] * Author: Giannis Giannopoulos / ai * Version: 3.6.2 */ function cas_slider_shortcode($atts) { $a = shortcode_atts([ // Desktop 'target' => '#slider', 'autonext' => 'true', 'duration' => '4', 'stoponhover' => 'true', 'arrows' => 'true', 'bullets' => 'true', 'columns' => '1', 'min_height' => '50px', 'height' => '', 'breakpoint' => 'none', 'mobile_breakpoint' => 'none', 'mobile_width' => '', 'mobile_columns' => '', 'mobile_autonext' => '', 'mobile_duration' => '', 'mobile_arrows' => '', 'mobile_bullets' => '', 'mobile_stoponhover' => '', 'mobile_min_height' => '', ], $atts); $target_id = ltrim($a['target'], '#'); // Desktop values $duration_ms = max(1000, floatval($a['duration']) * 1000); $cols = max(1, intval($a['columns'])); $has_fixed_height = !empty($a['height']); // Mobile values με inheritance από desktop αν δεν ορίστηκαν $mobile_duration_val = !empty($a['mobile_duration']) ? $a['mobile_duration'] : $a['duration']; $mobile_duration_ms = max(1000, floatval($mobile_duration_val) * 1000); $mobile_cols_val = !empty($a['mobile_columns']) ? $a['mobile_columns'] : $a['columns']; $mobile_cols = max(1, intval($mobile_cols_val)); $mobile_width_val = !empty($a['mobile_width']) ? $a['mobile_width'] : $a['height']; $has_mobile_fixed_height = !empty($mobile_width_val); $mobile_autonext_val = !empty($a['mobile_autonext']) ? $a['mobile_autonext'] : $a['autonext']; $mobile_stoponhover_val = !empty($a['mobile_stoponhover']) ? $a['mobile_stoponhover'] : $a['stoponhover']; $mobile_arrows_val = !empty($a['mobile_arrows']) ? $a['mobile_arrows'] : $a['arrows']; $mobile_bullets_val = !empty($a['mobile_bullets']) ? $a['mobile_bullets'] : $a['bullets']; $mobile_min_height_val = !empty($a['mobile_min_height']) ? $a['mobile_min_height'] : $a['min_height']; // Επεξεργασία stack breakpoint (παλιό) $breakpoint_raw = strtolower(trim($a['breakpoint'])); $has_stack_breakpoint = false; $stack_breakpoint_value = '0px'; if ($breakpoint_raw !== '0' && $breakpoint_raw !== 'none' && $breakpoint_raw !== '' && $breakpoint_raw !== '0px') { $has_stack_breakpoint = true; $stack_breakpoint_value = $a['breakpoint']; } // Επεξεργασία mobile breakpoint $mobile_bp_raw = strtolower(trim($a['mobile_breakpoint'])); $has_mobile_breakpoint = false; $mobile_breakpoint_value = '0px'; if ($mobile_bp_raw !== '0' && $mobile_bp_raw !== 'none' && $mobile_bp_raw !== '' && $mobile_bp_raw !== '0px') { $has_mobile_breakpoint = true; $mobile_breakpoint_value = $a['mobile_breakpoint']; } ob_start(); /* ================= CSS ONCE ================= */ static $css_printed = false; if (!$css_printed): $css_printed = true; ?> <style> .cas-container { position: relative !important; overflow: hidden !important; display: flex !important; align-items: stretch !important; transition: height 0.35s ease !important; touch-action: pan-y pinch-zoom !important; } .cas-track { display: flex !important; width: 100% !important; transition: transform 0.6s ease !important; will-change: transform; touch-action: pan-y !important; } .cas-slide { flex: 0 0 auto !important; user-select: none !important; -webkit-user-select: none !important; height: auto !important; align-self: flex-start !important; } /* arrows */ .cas-nav { position: absolute; top: 50%; width: 100%; display: flex; justify-content: space-between; transform: translateY(-50%); pointer-events: none; z-index: 10; } .cas-nav button { pointer-events: auto; background: rgba(0,0,0,0.4); color: #fff; border: none; padding: 10px; cursor: pointer; font-size: 18px; line-height: 1; transition: background 0.3s ease; } .cas-nav button:hover { background: rgba(0,0,0,0.7); } /* bullets */ .cas-bullets { position: absolute; bottom: 10px; width: 100%; text-align: center; z-index: 10; pointer-events: none; } .cas-bullet { display: inline-block; width: 10px; height: 10px; margin: 5px; border-radius: 50%; background: rgba(255,255,255,0.4); cursor: pointer; pointer-events: auto; transition: background 0.3s ease; } .cas-bullet.active { background: #fff; } .cas-bullet:hover { background: rgba(255,255,255,0.8); } </style> <?php endif; ?> <?php /* ================= STACK BREAKPOINT CSS ================= */ ?> <?php if ($has_stack_breakpoint): ?> <style id="cas-stack-<?php echo esc_attr($target_id); ?>"> @media screen and (max-width: <?php echo esc_attr($stack_breakpoint_value); ?>) { #<?php echo esc_attr($target_id); ?>.cas-container { overflow: visible !important; height: auto !important; min-height: auto !important; display: block !important; } #<?php echo esc_attr($target_id); ?> .cas-track { display: block !important; transform: none !important; transition: none !important; width: 100% !important; } #<?php echo esc_attr($target_id); ?> .cas-slide { width: 100% !important; flex: 0 0 100% !important; margin-bottom: 15px !important; } #<?php echo esc_attr($target_id); ?> .cas-nav, #<?php echo esc_attr($target_id); ?> .cas-bullets { display: none !important; } } </style> <?php endif; ?> <?php /* ================= MOBILE BREAKPOINT CSS ================= */ ?> <?php if ($has_mobile_breakpoint && !$has_stack_breakpoint): ?> <style id="cas-mobile-<?php echo esc_attr($target_id); ?>"> @media screen and (max-width: <?php echo esc_attr($mobile_breakpoint_value); ?>) { #<?php echo esc_attr($target_id); ?>.cas-container { <?php if ($has_mobile_fixed_height): ?> <?php if (strpos($mobile_width_val, '/') !== false): ?> aspect-ratio: <?php echo esc_attr($mobile_width_val); ?> !important; height: auto !important; <?php else: ?> height: <?php echo esc_attr($mobile_width_val); ?> !important; aspect-ratio: auto !important; <?php endif; ?> min-height: auto !important; <?php else: ?> min-height: <?php echo esc_attr($mobile_min_height_val); ?> !important; height: auto !important; aspect-ratio: auto !important; <?php endif; ?> } #<?php echo esc_attr($target_id); ?> .cas-slide { width: <?php echo (100 / $mobile_cols); ?>% !important; } } </style> <?php endif; ?> <script> (function(){ if (!window.__CAS__) { window.__CAS__ = { instances: {}, init: function(cfg) { if (this.instances[cfg.id]) return; const root = document.getElementById(cfg.id); if (!root) return; const inner = root.querySelector('.wp-block-group__inner-container'); const container = inner ? inner : root; /* ================= STATE MANAGEMENT ================= */ let currentMode = 'desktop'; // 'desktop', 'mobile', 'stacked' let isDragging = false; let isScrolling = null; let startX = 0; let startY = 0; let currentX = 0; let isHovering = false; let interval = null; let index = 0; let slideWidth = 100 / cfg.columns; let activeCfg = null; // Το ενεργό configuration // Τα DOM elements let track = null; const slides = []; let navEl = null; let bulletsEl = null; let bulletsArr = []; /* ================= CONFIG DETECTION ================= */ function getConfigForWidth() { const w = window.innerWidth; // Έλεγχος stack breakpoint (έχει προτεραιότητα) if (cfg.stackBreakpoint) { const bpPx = parseBreakpointToPx(cfg.stackBreakpoint); if (w <= bpPx) { return 'stacked'; } } // Έλεγχος mobile breakpoint if (cfg.mobileBreakpoint) { const bpPx = parseBreakpointToPx(cfg.mobileBreakpoint); if (w <= bpPx) { return 'mobile'; } } return 'desktop'; } function parseBreakpointToPx(bp) { const value = parseInt(bp); const unit = bp.replace(/[0-9.]/g, '').toLowerCase(); if (unit === 'px' || unit === '') { return value; } else if (unit === 'em' || unit === 'rem') { return value * 16; } else if (unit === 'vw') { return (value / 100) * window.innerWidth; } return value; } function getActiveConfig(mode) { if (mode === 'mobile') { return { columns: cfg.mobileColumns, slideWidth: 100 / cfg.mobileColumns, fixedHeight: cfg.mobileFixedHeight, height: cfg.mobileHeight, minHeight: cfg.mobileMinHeight, autonext: cfg.mobileAutonext, duration: cfg.mobileDuration, arrows: cfg.mobileArrows, bullets: cfg.mobileBullets, stopOnHover: cfg.mobileStopOnHover, }; } return { columns: cfg.columns, slideWidth: 100 / cfg.columns, fixedHeight: cfg.fixedHeight, height: cfg.height, minHeight: cfg.minHeight, autonext: cfg.autonext, duration: cfg.duration, arrows: cfg.arrows, bullets: cfg.bullets, stopOnHover: cfg.stopOnHover, }; } /* ================= MODE SWITCHING ================= */ function switchMode(newMode) { if (currentMode === newMode) return; const wasStacked = currentMode === 'stacked'; const willBeStacked = newMode === 'stacked'; // Σταμάτα το slider stop(); // Αν πάμε σε/από stacked, χρειάζεται rebuild if (wasStacked || willBeStacked) { if (willBeStacked) { applyStackedMode(); } else { // Βγαίνουμε από stacked, πρέπει να ξαναφτιάξουμε rebuildSlider(); } } currentMode = newMode; if (currentMode !== 'stacked') { activeCfg = getActiveConfig(currentMode); slideWidth = activeCfg.slideWidth; updateSliderAppearance(); update(false); updateHeight(); updateNavigation(); start(); } } function applyStackedMode() { // Έκρυψη navigation if (navEl) navEl.style.display = 'none'; if (bulletsEl) bulletsEl.style.display = 'none'; // Το CSS στο <style> tag θα χειριστεί το layout root.style.height = 'auto'; root.style.minHeight = 'auto'; // Σταμάτα όλα stop(); track.style.transition = 'none'; track.style.transform = 'none'; } function rebuildSlider() { // Επαναφορά του slider από stacked mode if (navEl) navEl.style.display = ''; if (bulletsEl) bulletsEl.style.display = ''; updateSliderAppearance(); update(false); updateHeight(); updateNavigation(); } function updateSliderAppearance() { const cfg = activeCfg; // Ύψος if (cfg.fixedHeight) { if (cfg.height.includes('/')) { root.style.aspectRatio = cfg.height; root.style.height = 'auto'; } else { root.style.height = cfg.height; root.style.aspectRatio = 'auto'; } root.style.minHeight = 'auto'; } else { root.style.minHeight = cfg.minHeight; root.style.height = 'auto'; root.style.aspectRatio = 'auto'; root.style.overflow = 'hidden'; } // Πλάτος slides slides.forEach(s => { s.style.width = cfg.slideWidth + '%'; if (cfg.fixedHeight) { s.style.height = '100%'; } else { s.style.height = 'auto'; } }); } function updateNavigation() { const cfg = activeCfg; if (navEl) { navEl.style.display = cfg.arrows ? '' : 'none'; } if (bulletsEl) { bulletsEl.style.display = cfg.bullets ? '' : 'none'; } } /* ================= INITIALIZATION ================= */ function init() { // Build track track = container.querySelector('.cas-track'); if (!track) { track = document.createElement('div'); track.className = 'cas-track'; Array.from(container.children).forEach(el => { if (!['SCRIPT','STYLE'].includes(el.tagName)) { track.appendChild(el); } }); container.appendChild(track); } root.classList.add('cas-container'); // Collect slides const slideElements = Array.from(track.children); if (!slideElements.length) return; slideElements.forEach(s => { s.classList.add('cas-slide'); slides.push(s); }); // Αρχικό mode currentMode = getConfigForWidth(); activeCfg = getActiveConfig(currentMode); slideWidth = activeCfg.slideWidth; // Εμφάνιση updateSliderAppearance(); // Φτιάξε navigation buildArrows(); buildBullets(); updateNavigation(); // Events bindEvents(); // Αν είναι stacked, μην κάνεις τίποτα άλλο if (currentMode === 'stacked') { applyStackedMode(); } else { update(false); initHeight(); start(); } // Resize handler window.addEventListener('resize', onResize); window.addEventListener('load', () => { const newMode = getConfigForWidth(); if (newMode !== currentMode) { switchMode(newMode); } if (currentMode !== 'stacked') { initHeight(); } }); } function buildArrows() { if (!cfg.arrows && !cfg.mobileArrows) return; navEl = document.createElement('div'); navEl.className = 'cas-nav'; navEl.innerHTML = '<button class="prev">❮</button><button class="next">❯</button>'; root.appendChild(navEl); navEl.querySelector('.next').onclick = (e) => { if (currentMode === 'stacked') return; e.preventDefault(); e.stopPropagation(); next(); start(); }; navEl.querySelector('.prev').onclick = (e) => { if (currentMode === 'stacked') return; e.preventDefault(); e.stopPropagation(); prev(); start(); }; } function buildBullets() { if (!cfg.bullets && !cfg.mobileBullets) return; bulletsEl = document.createElement('div'); bulletsEl.className = 'cas-bullets'; bulletsArr = slides.map((_, i) => { const b = document.createElement('span'); b.className = 'cas-bullet'; b.onclick = (e) => { if (currentMode === 'stacked') return; e.preventDefault(); e.stopPropagation(); index = i; update(); start(); }; bulletsEl.appendChild(b); return b; }); root.appendChild(bulletsEl); } /* ================= CORE FUNCTIONS ================= */ function update(animate = true) { if (currentMode === 'stacked') return; track.style.transition = animate ? '' : 'none'; track.style.transform = 'translateX(-' + (index * slideWidth) + '%)'; updateBullets(); updateHeight(); } function next() { if (currentMode === 'stacked') return; index = (index + 1) % slides.length; update(); } function prev() { if (currentMode === 'stacked') return; index = (index - 1 + slides.length) % slides.length; update(); } function start() { if (currentMode === 'stacked') return; if (!activeCfg.autonext) return; if (isHovering) return; stop(); interval = setInterval(next, activeCfg.duration); } function stop() { if (interval) { clearInterval(interval); interval = null; } } function updateHeight() { if (activeCfg.fixedHeight || currentMode === 'stacked') return; const el = slides[index]; if (!el) return; const slideHeight = el.offsetHeight; if (slideHeight === 0) { setTimeout(updateHeight, 100); return; } root.style.height = slideHeight + 'px'; } function updateBullets() { bulletsArr.forEach((b, i) => { b.classList.toggle('active', i === index); }); } function initHeight() { if (activeCfg.fixedHeight || currentMode === 'stacked') return; updateHeight(); setTimeout(updateHeight, 300); setTimeout(updateHeight, 1000); const images = track.querySelectorAll('img'); let loadedImages = 0; if (images.length > 0) { images.forEach(img => { if (img.complete) { loadedImages++; } else { img.addEventListener('load', () => { loadedImages++; if (loadedImages === images.length) { updateHeight(); } }); } }); if (loadedImages === images.length) { updateHeight(); } } } function onResize() { const newMode = getConfigForWidth(); // Update breakpoint calculations που χρησιμοποιούν vw if (newMode !== currentMode) { switchMode(newMode); } if (currentMode !== 'stacked') { updateHeight(); } } /* ================= EVENTS ================= */ function bindEvents() { // External nav document.querySelectorAll('.slider-next-' + cfg.id).forEach(el => { el.onclick = (e) => { if (currentMode === 'stacked') return; e.preventDefault(); next(); start(); }; }); document.querySelectorAll('.slider-prev-' + cfg.id).forEach(el => { el.onclick = (e) => { if (currentMode === 'stacked') return; e.preventDefault(); prev(); start(); }; }); // Touch events const touchArea = track; touchArea.addEventListener('touchstart', (e) => { if (currentMode === 'stacked') return; isDragging = true; isScrolling = null; const t = e.touches[0]; startX = t.clientX; startY = t.clientY; currentX = startX; stop(); track.style.transition = 'none'; }, {passive: true}); touchArea.addEventListener('touchmove', (e) => { if (currentMode === 'stacked' || !isDragging) return; const t = e.touches[0]; const dx = t.clientX - startX; const dy = t.clientY - startY; if (isScrolling === null) { isScrolling = Math.abs(dy) > Math.abs(dx); } if (isScrolling) { isDragging = false; start(); return; } e.preventDefault(); currentX = t.clientX; track.style.transform = 'translateX(calc(-' + (index * slideWidth) + '% + ' + dx + 'px))'; }, {passive: false}); const endTouch = () => { if (currentMode === 'stacked' || !isDragging) return; isDragging = false; const dx = currentX - startX; const threshold = 30; track.style.transition = ''; if (Math.abs(dx) > threshold) { if (dx > 0) prev(); else next(); } else { update(); } start(); }; touchArea.addEventListener('touchend', endTouch); touchArea.addEventListener('touchcancel', endTouch); // Mouse drag touchArea.addEventListener('mousedown', (e) => { if (currentMode === 'stacked') return; e.preventDefault(); isDragging = true; isScrolling = null; startX = e.clientX; currentX = startX; stop(); track.style.transition = 'none'; }); window.addEventListener('mousemove', (e) => { if (currentMode === 'stacked' || !isDragging) return; const dx = e.clientX - startX; track.style.transform = 'translateX(calc(-' + (index * slideWidth) + '% + ' + dx + 'px))'; currentX = e.clientX; }); window.addEventListener('mouseup', () => { if (currentMode === 'stacked' || !isDragging) return; endTouch(); }); // Hover if (cfg.stopOnHover || cfg.mobileStopOnHover) { root.addEventListener('mouseover', function(e) { if (currentMode === 'stacked') return; if (!root.contains(e.relatedTarget)) { isHovering = true; stop(); } }); root.addEventListener('mouseout', function(e) { if (currentMode === 'stacked') return; if (!root.contains(e.relatedTarget)) { isHovering = false; start(); } }); root.addEventListener('touchstart', function(e) { if (currentMode === 'stacked') return; if (e.target === root || e.target.closest('.cas-nav') || e.target.closest('.cas-bullets')) { isHovering = true; stop(); } }, {passive: true}); root.addEventListener('touchend', function(e) { if (currentMode === 'stacked') return; setTimeout(() => { if (!isDragging) { isHovering = false; start(); } }, 100); }); } } // Εκκίνηση init(); this.instances[cfg.id] = true; } }; } /* ================= QUEUE ================= */ if (!window.__CAS_QUEUE__) window.__CAS_QUEUE__ = []; window.__CAS_QUEUE__.push({ id: '<?php echo esc_js($target_id); ?>', // Desktop autonext: <?php echo $a['autonext'] === 'true' ? 'true' : 'false'; ?>, duration: <?php echo $duration_ms; ?>, stopOnHover: <?php echo $a['stoponhover'] === 'true' ? 'true' : 'false'; ?>, arrows: <?php echo $a['arrows'] === 'true' ? 'true' : 'false'; ?>, bullets: <?php echo $a['bullets'] === 'true' ? 'true' : 'false'; ?>, columns: <?php echo $cols; ?>, fixedHeight: <?php echo $has_fixed_height ? 'true' : 'false'; ?>, height: '<?php echo esc_js($a['height']); ?>', minHeight: '<?php echo esc_js($a['min_height']); ?>', // Stack breakpoint stackBreakpoint: '<?php echo $has_stack_breakpoint ? esc_js($a['breakpoint']) : "0"; ?>', // Mobile (με inherited values) mobileBreakpoint: '<?php echo $has_mobile_breakpoint ? esc_js($a['mobile_breakpoint']) : "0"; ?>', mobileAutonext: <?php echo $mobile_autonext_val === 'true' ? 'true' : 'false'; ?>, mobileDuration: <?php echo $mobile_duration_ms; ?>, mobileStopOnHover: <?php echo $mobile_stoponhover_val === 'true' ? 'true' : 'false'; ?>, mobileArrows: <?php echo $mobile_arrows_val === 'true' ? 'true' : 'false'; ?>, mobileBullets: <?php echo $mobile_bullets_val === 'true' ? 'true' : 'false'; ?>, mobileColumns: <?php echo $mobile_cols; ?>, mobileFixedHeight: <?php echo $has_mobile_fixed_height ? 'true' : 'false'; ?>, mobileHeight: '<?php echo esc_js($mobile_width_val); ?>', mobileMinHeight: '<?php echo esc_js($mobile_min_height_val); ?>', }); /* ================= BOOT ================= */ if (!window.__CAS_BOOT__) { window.__CAS_BOOT__ = true; const run = () => { window.__CAS_QUEUE__.forEach(cfg => window.__CAS__.init(cfg)); window.__CAS_QUEUE__ = []; }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', run); } else { run(); } } })(); </script> <?php return ob_get_clean(); } add_shortcode('init_slider', 'cas_slider_shortcode');
CANCEL
Name
Type
Size
Modified
Actions
↩ ..
DIR
—
—
📄 shortcode-slider.php
PHP
30.8 KB
2026-05-19 12:07
EDIT