Mobirise CMS 4.0

Anwendungen für Webseiten. Künstliche Intelligenz verwenden.
Volker
Moderator
Moderator
Beiträge: 2805
Registriert: Sa 12. Dez 2020, 22:35

Re: Mobirise CMS 4.0

Beitrag von Volker »

Code: Alles auswählen

 // ===== cms-core =====
    // Geschrieben von den KI´s Gemini, Claude und Chat GPT
    // Idee und Autor: Volker Niederastroth
	// Version vom 21.06.26 09:11 Uhr


document.execCommand("defaultParagraphSeparator", false, "p");

// Verhindert, dass eingebettete Videos (YouTube/Vimeo-iframes) beim Zurück-Navigieren
// einfach weiterlaufen, weil der Browser die Seite aus dem Back-Forward-Cache (bfcache)
// im exakt eingefrorenen Zustand wiederherstellt (inkl. "läuft gerade").
window.addEventListener('pageshow', function(e) {
    if (e.persisted) {
        document.querySelectorAll('iframe').forEach(function(f) {
            var src = f.getAttribute('src');
            if (src && (src.includes('youtube.com') || src.includes('youtu.be') || src.includes('vimeo.com'))) {
                f.setAttribute('src', 'about:blank');
                setTimeout(function(){ f.setAttribute('src', src); }, 10); // about:blank zwingt echten Reload, statt no-op bei identischem src
            }
        });
    }
});

function formatText(cmd) { document.execCommand(cmd, false, null); }
function formatTextColor(color) { document.execCommand('foreColor', false, color); }
function formatTextSize(size) { if(size) document.execCommand('fontSize', false, size); }
function clearTextFormatAndClose() { document.querySelector('#text-editor-tools').style.display = 'none'; window.getSelection().removeAllRanges(); }

window.setAllVideosAutoplay = function(state) {
    document.querySelectorAll('video').forEach(function(v) {
        if (state) {
            v.setAttribute('autoplay', 'autoplay');
            v.setAttribute('muted', 'muted');
            v.setAttribute('loop', 'loop');
            v.removeAttribute('controls');
            v.muted = true;
            v.play().catch(function(){});
        } else {
            v.removeAttribute('autoplay');
            v.removeAttribute('muted');
            v.removeAttribute('loop');
            v.setAttribute('controls', 'controls');
            v.muted = false;
            v.pause();
        }
    });
    alert('Autoplay für alle Videos: ' + (state ? 'AN' : 'AUS'));
};

window.repairNestedEditables = function() {
    var count = 0;
    document.querySelectorAll('[data-auto-id]').forEach(function(el) {
        var nested = el.querySelectorAll('[contenteditable]');
        if (nested.length > 1) {
            // Tiefstes verschachteltes Element finden -> dessen Inhalt ist der "echte" Text
            var deepest = nested[nested.length - 1];
            var innerHtml = deepest.innerHTML;
            var first = nested[0];
            first.outerHTML = innerHtml; // alle verschachtelten Wrapper entfernen, nur Inhalt behalten
            count++;
        }
    });
    alert(count + ' Element(e) bereinigt. Jetzt bitte auf "💾 Diese Seite speichern" klicken, um den sauberen Zustand zu sichern.');
};

function addTextLink() {
    var sel = window.getSelection(); if (!sel.toString().trim()) return;
    var anchorA = sel.anchorNode.parentNode.closest('a');
    var cur = anchorA ? anchorA.getAttribute('href') : "";
    var url = prompt("Ziel-URL:", cur || "");
    if (url && url.trim() !== "") { 
        var finalUrl = url.trim();
        if (/^www\./i.test(finalUrl)) { finalUrl = "https://" + finalUrl; }
        else if (!/^https?:\/\//i.test(finalUrl) && !/^\//.test(finalUrl) && !/^#/.test(finalUrl) && !/\.html$/i.test(finalUrl)) { finalUrl = "https://" + finalUrl; }
        document.execCommand("createLink", false, finalUrl); 
        var newA = sel.anchorNode.parentNode.closest('a');
        if (newA) {
            newA.classList.add('text-primary'); 
            var t = prompt("In neuem Tab öffnen?\n'y' = JA | 'n' = NEIN:", newA.getAttribute('target') === '_blank' ? 'y' : 'n');
            if (t !== null) { if (t.toLowerCase() === 'y') newA.setAttribute('target', '_blank'); else newA.removeAttribute('target'); }
        }
    }
}

document.addEventListener("DOMContentLoaded", function() {
    try { initCMS(); } catch(e) { console.error("CMS Startfehler:", e); document.documentElement.classList.add('cms-ready'); }
});

function initCMS() {
    var handlerUrl = 'save_content.php';
    var overlay      = document.querySelector('.global-admin-overlay');
    var closeBtn     = document.querySelector('.global-admin-close');
    var loginForm    = document.querySelector('#global-login-form');
    var loginFormEl  = document.querySelector('#volkers-ajax-login-form'); 
    var loginPw      = document.querySelector('#global-admin-password');
    var panel        = document.querySelector('#global-admin-panel');
    var saveBtn      = document.querySelector('#global-save-btn');
    var logoutBtn    = document.querySelector('#global-logout-btn');
    var toolbar      = document.querySelector('#text-editor-tools');
    var fileUploader = document.querySelector('#cms-file-uploader');
    var blockColorpicker = document.querySelector('#cms-block-colorpicker');
    var backupList   = document.querySelector('#global-backup-list');
    var restoreBtn   = document.querySelector('#global-restore-btn');
    var stickySelect = document.querySelector('#global-menu-sticky-select');
    var navColorsSection   = document.getElementById('cms-nav-colors-section');
    var navLinkColorPicker = document.getElementById('cms-nav-link-color');
    var navBtnColorPicker  = document.getElementById('cms-nav-btn-color');
    var navBrandColorPicker = document.getElementById('cms-nav-brand-color');
    var navBgColorPicker   = document.getElementById('cms-nav-bg-color');
    var overlayPanel       = document.getElementById('cms-overlay-panel');
    var overlayColorPicker = document.getElementById('cms-overlay-color-picker');
    var overlayOpacityRange = document.getElementById('cms-overlay-opacity-range');
    var overlayOpacityLabel = document.getElementById('cms-overlay-opacity-label');
    var overlayApplyBtn    = document.getElementById('cms-overlay-apply');
    var overlayCloseBtn    = document.getElementById('cms-overlay-close');

    var pageName = window.location.pathname.split("/").pop().replace(".html", "") || "index";
    var jsonUrl       = 'content_' + pageName + '.json'; 
    var jsonGlobalUrl = 'content_global_nav.json'; 
    var jsonFooterUrl = 'content_global_footer.json'; 
    var editableTexts = []; var editableMedias = []; var editableLinks = []; var editableColors = []; 
    var isAdminActive = false; var activeMediaElementToUpload = null; var activeSectionToColor = null;
    var menuElementNode = null;
    var activeOverlaySection = null;

    // ===== DOWNGRADE-SCHALTER =====
    // false = Menü & Footer sind NICHT editierbar (kein Text, kein Bild, keine Farbe, keine Menüfarben-Buttons)
    // true  = volle Funktion wie bisher
    var ALLOW_MENU_FOOTER_EDIT = true;

    var sections = document.querySelectorAll('section, nav, footer');
    sections.forEach(function(section, sectionIndex) {
        if (!section) return;
        var isMenu   = (sectionIndex === 0 || section.tagName === 'NAV' || section.classList.contains('menu') || section.classList.contains('navbar'));
        var isFooter = (sectionIndex === (sections.length - 1) || section.tagName === 'FOOTER' || section.classList.contains('footer'));

        // Downgrade: Menü/Footer-Sektion komplett überspringen -> keine Buttons, kein editierbarer Text/Bild/Farbe
        if (!ALLOW_MENU_FOOTER_EDIT && (isMenu || isFooter)) {
            if (isMenu) menuElementNode = section; // bleibt für Sticky-Logik nötig, aber ohne Edit-Buttons
            return;
        }

        var scopeType = 'page'; var scopeKey = 'block_' + sectionIndex + '_';
        if (isMenu)   { scopeType = 'menu';   scopeKey = 'global_nav_';    menuElementNode = section; }
        else if (isFooter) { scopeType = 'footer'; scopeKey = 'global_footer_'; }

        section.setAttribute('data-block-idx', sectionIndex);
        section.classList.add('cms-bg-section-active');
        var controlContainer = document.createElement('div');
        controlContainer.className = 'cms-control-container';
        section.appendChild(controlContainer);

        var computedBg = window.getComputedStyle(section).backgroundImage;
        var hasBgImage = (computedBg && computedBg !== 'none' && computedBg.includes('url('));
        if (hasBgImage) {
            var cleanUrl = computedBg.replace(/url\(['"]?(.*?)['"]?\)/, '$1');
            section.setAttribute('data-original-bg', cleanUrl);
            var editBgBtn = document.createElement('button'); editBgBtn.type = 'button'; editBgBtn.className = 'cms-bg-edit-trigger'; editBgBtn.innerText = '🖼️ Bild';
            editBgBtn.setAttribute('data-bg-id', scopeKey + 'bg_image'); editBgBtn.setAttribute('data-cms-scope', scopeType);
            controlContainer.appendChild(editBgBtn);
            editableMedias.push({ el: editBgBtn, type: 'section-bg', parentSection: section });
        }
        
        var editColorBtn = document.createElement('button'); editColorBtn.type = 'button'; editColorBtn.className = 'cms-color-edit-trigger'; editColorBtn.innerText = '🎨 Farbe';
        editColorBtn.setAttribute('data-color-id', scopeKey + 'bg_color'); editColorBtn.setAttribute('data-cms-scope', scopeType);
        controlContainer.appendChild(editColorBtn);
        editableColors.push({ el: editColorBtn, parentSection: section });
        
        var textSelectors = ['.mbr-section-title','.mbr-section-subtitle','.card-title','.panel-title-edit','.item-title','.item-title a','.item-subtitle','.icon-title','.icon-text','.mbr-text','p'];
        textSelectors.forEach(function(selector) {
            section.querySelectorAll(selector).forEach(function(el, elIndex) {
                if (!el || el.hasAttribute('data-auto-id') || el.tagName === 'IMG' || el.tagName === 'VIDEO' || el.tagName === 'IFRAME') return;
                el.setAttribute('data-auto-id', scopeKey + selector.replace('.','').replace(' ','_') + '_' + elIndex);
                el.setAttribute('data-cms-scope', scopeType); editableTexts.push(el);
            });
        });
        
        section.querySelectorAll('.btn, .nav-link, .navbar-brand, .navbar-logo a, .navbar-caption, footer a').forEach(function(link, linkIndex) {
            if (!link || link.closest('.global-admin-overlay')) return;
            link.setAttribute('data-link-id', scopeKey + 'link_' + linkIndex);
            link.setAttribute('data-cms-scope', scopeType); editableLinks.push(link);
        });

section.querySelectorAll('img, video, iframe, [data-bg-video]').forEach(function(media, mediaIndex) {
            // Nur Bilder innerhalb der Modals/Lightbox komplett überspringen
            if (media.closest('.modal.mbr-slider')) return;
            
            var mediaType = media.tagName.toLowerCase();
            if (media.hasAttribute('data-bg-video')) { mediaType = 'bg-video'; }
            
            // Markierung für alle Nicht-Lightbox-Bilder
            media.setAttribute('data-media-id', scopeKey + mediaType + '_' + mediaIndex); 
            media.setAttribute('data-cms-scope', scopeType); 
            
            // Jetzt wird jedes Bild/Video, das kein Lightbox-Slider-Element ist, editierbar gemacht
            if (mediaType === 'video' || mediaType === 'iframe' || mediaType === 'bg-video') {
                if (mediaType === 'video') { media.pause(); } 
                var wrapper = document.createElement('div'); wrapper.className = 'cms-video-wrapper';
                media.parentNode.insertBefore(wrapper, media); wrapper.appendChild(media);
                var shield = document.createElement('div'); shield.className = 'cms-video-shield';
                shield.setAttribute('data-target-id', scopeKey + mediaType + '_' + mediaIndex); wrapper.appendChild(shield);
                editableMedias.push({ el: media, shield: shield, type: mediaType });
            } else { 
                // Hier fehlte in deiner Version evtl. die Zuweisung für normale Bilder
                editableMedias.push({ el: media, type: mediaType }); 
            }
        });
    });

    // --- Lightbox-Galerie: Vorschaubild & Popup-Carousel-Bild koppeln ---
    var lightboxPairs = new WeakMap(); // thumbnailImg -> carouselImg
    (function setupLightboxPairs() {
        document.querySelectorAll('.modal.mbr-slider').forEach(function(modal) {
            var carousel = modal.querySelector('.carousel[id]');
            if (!carousel) return;
            var carouselId = carousel.id;
            var slideImgs = carousel.querySelectorAll('.carousel-item img');
            document.querySelectorAll(
                '[data-bs-target="#' + carouselId + '"][data-slide-to], ' +
                '[data-target="#' + carouselId + '"][data-slide-to]'
            ).forEach(function(thumb) {
                if (thumb.tagName !== 'IMG') return;
                var idx = parseInt(thumb.getAttribute('data-bs-slide-to') || thumb.getAttribute('data-slide-to'), 10);
                var slideImg = slideImgs[idx];
                if (slideImg) lightboxPairs.set(thumb, slideImg);
            });
        });
    })();

    // Setzt eine neue Bild-URL auf ein <img> und hält ein eventuell gekoppeltes Lightbox-Bild synchron.
    // Sucht innerhalb eines Links/Textelements das tatsächliche Text-Element (span/b/strong/i),
    // überspringt dabei aber Icon-Elemente (Mobirise-Iconfont, FontAwesome, Bootstrap-Icons etc.),
    // damit Icons nicht versehentlich als "Text-Ziel" missbraucht werden (führte zu verschachtelten/doppelten Icons).
    // Gibt null zurück, wenn kein eigener Text-Wrapper existiert (Text liegt dann direkt als Textknoten im Element).
    function getTextEditTarget(el) {
        var candidates = el.querySelectorAll('span, b, strong, i');
        for (var i = 0; i < candidates.length; i++) {
            var c = candidates[i];
            if (/icon|mbri|fa-|bi-/i.test(c.className)) continue;
            return c;
        }
        return null;
    }

    // Liest den sichtbaren Text eines Links aus, ohne Icon-Inhalte mitzunehmen.
    function getLinkText(el) {
        var t = getTextEditTarget(el);
        if (t) return t.innerText;
        var txt = '';
        el.childNodes.forEach(function(n){ if (n.nodeType === 3) txt += n.textContent; });
        return txt.trim();
    }

    // Setzt den sichtbaren Text eines Links, OHNE vorhandene Icon-Elemente zu entfernen.
    function setLinkText(el, text) {
        var t = getTextEditTarget(el);
        if (t) { t.innerText = text; return; }
        // Kein Text-Wrapper vorhanden: nur reine Textknoten entfernen/ersetzen, Icon-Elemente bleiben unangetastet.
        Array.prototype.slice.call(el.childNodes).forEach(function(n){ if (n.nodeType === 3) el.removeChild(n); });
        el.appendChild(document.createTextNode(text));
    }

    function setImageSrcSynced(imgEl, newSrc) {
        if (!imgEl) return;
        imgEl.setAttribute('src', newSrc);
        var pairedImg = lightboxPairs.get(imgEl);
        if (pairedImg) pairedImg.setAttribute('src', newSrc);
    }

    function loadJsonData(url) { return fetch(url + '?v=' + Date.now()).then(function(r){ if(r.ok) return r.json(); }).catch(function(){ return null; }); }
    Promise.all([loadJsonData(jsonUrl), loadJsonData(jsonGlobalUrl), loadJsonData(jsonFooterUrl)]).then(function(results) {
        var d = Object.assign({}, results[0]||{}, results[1]||{}, results[2]||{});

        editableTexts.forEach(function(el) {
            var key = el.getAttribute('data-auto-id');
            if (d[key]) { el.innerHTML = d[key]; }
        });
        editableColors.forEach(function(item) {
            if (d[item.el.getAttribute('data-color-id')]) item.parentSection.style.backgroundColor = d[item.el.getAttribute('data-color-id')];
        });
        
        if (menuElementNode) {
            var sticky = d['cms_menu_sticky_style'] || 'sticky';
            if (sticky === 'static') {
                menuElementNode.style.setProperty('position', 'relative', 'important');
                menuElementNode.style.setProperty('top', 'auto', 'important');
                menuElementNode.classList.remove('cms-force-sticky', 'fixed-top', 'navbar-fixed-top');
                menuElementNode.classList.add('cms-force-static');
                if(stickySelect) stickySelect.value = 'static';
            } else {
                menuElementNode.style.setProperty('position', 'fixed', 'important');
                menuElementNode.style.setProperty('top', '0', 'important');
                menuElementNode.classList.remove('cms-force-static');
                menuElementNode.classList.add('cms-force-sticky');
                if(stickySelect) stickySelect.value = 'sticky';
            }
        }

        if (menuElementNode) {
            if (d['cms_nav_link_color']) {
                menuElementNode.style.setProperty('--nav-link-color', d['cms_nav_link_color']);
            }
            if (d['cms_nav_btn_color']) {
                menuElementNode.style.setProperty('--nav-btn-color', d['cms_nav_btn_color']);
            }
            if (d['cms_nav_brand_color']) {
                menuElementNode.style.setProperty('--nav-brand-color', d['cms_nav_brand_color']);
            }
            if (d['cms_nav_bg_color']) {
                menuElementNode.style.setProperty('--nav-bg-color', d['cms_nav_bg_color']);
            }
        }

        editableMedias.forEach(function(item) {
            if (item.type === 'section-bg') {
                var key = item.el.getAttribute('data-bg-id');
                var bgUrl = d[key] || item.parentSection.getAttribute('data-original-bg');
                if (bgUrl) { item.parentSection.classList.add('cms-has-bg'); item.parentSection.style.setProperty('--cms-bg-image',"url('"+bgUrl+"')"); item.parentSection.style.backgroundImage='none'; }
                var opVal = (d[key+'_opacity'] !== undefined) ? d[key+'_opacity'] : "1";
                item.parentSection.style.setProperty('--cms-bg-opacity', opVal);
                var idx = item.parentSection.getAttribute('data-block-idx');
                if (d['overlay_color_'+idx]) { item.parentSection.style.setProperty('--cms-bg-overlay-color', d['overlay_color_'+idx]); item.parentSection.classList.add('cms-has-bg-overlay'); }
                if (d['overlay_opacity_'+idx] !== undefined) { item.parentSection.style.setProperty('--cms-bg-overlay-opacity', d['overlay_opacity_'+idx]); }
            }
            else if (item.type === 'bg-video') { var key = item.el.getAttribute('data-media-id'); if(d[key]) item.el.setAttribute('data-bg-video', d[key]); }
            else if (item.type === 'video') {
                var key = item.el.getAttribute('data-media-id');
                if (d[key] && typeof d[key] === 'object') {
                    item.el.setAttribute('src', d[key].src);
                    if (d[key].autoplay === true || d[key].autoplay === 'true') {
                        item.el.setAttribute('autoplay','autoplay'); item.el.setAttribute('muted','muted'); item.el.setAttribute('loop','loop'); item.el.removeAttribute('controls');
                        item.el.muted = true; setTimeout(function(){ item.el.play().catch(function(){}); }, 150);
                    } else {
                        item.el.removeAttribute('autoplay'); item.el.removeAttribute('muted'); item.el.removeAttribute('loop'); item.el.setAttribute('controls','controls'); item.el.muted = false;
                        item.el.pause(); // Stoppt ein bereits durch Race-Condition gestartetes Autoplay
                    }
                } else if (d[key]) { item.el.setAttribute('src', d[key]); }
            }
            else { var key = item.el.getAttribute('data-media-id'); if(d[key]) setImageSrcSynced(item.el, d[key]); }
        });

        editableLinks.forEach(function(el) {
            var key = el.getAttribute('data-link-id');
            if (d[key]) {
                if (d[key].url) el.setAttribute('href', d[key].url);
                if (d[key].target) el.setAttribute('target', d[key].target); else el.removeAttribute('target');
                if (!el.querySelector('img') && d[key].text) { setLinkText(el, d[key].text); }
            }
        });
        document.documentElement.classList.add('cms-ready');
    }).catch(function() { document.documentElement.classList.add('cms-ready'); });

    if (stickySelect) {
        stickySelect.addEventListener('change', function() {
            if (!menuElementNode) return;
            if (stickySelect.value === 'static') {
                menuElementNode.classList.remove('cms-force-sticky'); menuElementNode.classList.add('cms-force-static');
                menuElementNode.classList.remove('fixed-top','navbar-fixed-top');
            } else {
                menuElementNode.classList.remove('cms-force-static'); menuElementNode.classList.add('cms-force-sticky');
            }
        });
    }

    var tapCount = 0; var tapTimer = null;
    document.addEventListener('touchstart', function(e) {
        if (e.target.closest('.global-admin-box')) return;
        tapCount++; clearTimeout(tapTimer);
        if (tapCount === 4) { overlay.style.display = 'flex'; tapCount = 0; }
        tapTimer = setTimeout(function(){ tapCount = 0; }, 1000);
    });
    document.addEventListener('dblclick', function(e) { if (e.ctrlKey && !e.target.closest('.global-admin-box')) { overlay.style.display = 'flex'; } });
    closeBtn.addEventListener('click', function() { overlay.style.display = 'none'; });
    if (loginFormEl) { loginFormEl.addEventListener('submit', function(e) { e.preventDefault(); executeLogin(); }); }

    function executeLogin() {
        fetch(handlerUrl, { method:'POST', headers:{'Content-Type':'application/x-www-form-urlencoded'}, body:'action=login&password='+encodeURIComponent(loginPw.value), credentials:'include' })
        .then(function(r){ return r.json(); }).then(function(data) {
            if (data && data.success) { loginForm.style.display='none'; panel.style.display='block'; isAdminActive=true; document.body.classList.add('admin-active'); enablePageEditing(true); fetchBackupList(); }
            else { alert('Falsches Passwort!'); }
        });
    }
    function fetchBackupList() {
        fetch(handlerUrl, { method:'POST', headers:{'Content-Type':'application/x-www-form-urlencoded'}, body:'action=list_backups&prefix=content_'+pageName, credentials:'include' })
        .then(function(r){ return r.json(); }).then(function(backups) {
            backupList.innerHTML = '<option value="" selected disabled>Wähle ein Backup...</option>';
            if (backups) backups.forEach(function(b){ var o=document.createElement('option'); o.value=b.file; o.innerText=b.label; backupList.appendChild(o); });
        });
    }
    restoreBtn.addEventListener('click', function() {
        if (!backupList.value || !confirm('Backup einspielen?')) return;
        fetch(handlerUrl, { method:'POST', headers:{'Content-Type':'application/x-www-form-urlencoded'}, body:'action=restore_backup&backup_file='+encodeURIComponent(backupList.value), credentials:'include' })
        .then(function(r){ return r.json(); }).then(function(d){ if(d.success) window.location.reload(); });
    });

    function handleColorInteraction(e) { e.preventDefault(); activeSectionToColor = e.currentTarget.parentElement.parentElement; blockColorpicker.click(); }
    blockColorpicker.addEventListener('input', function() { if (activeSectionToColor) activeSectionToColor.style.backgroundColor = blockColorpicker.value; });

    overlayOpacityRange.addEventListener('input', function() {
        overlayOpacityLabel.textContent = overlayOpacityRange.value + '%';
        if (activeOverlaySection) {
            activeOverlaySection.style.setProperty('--cms-bg-overlay-color', overlayColorPicker.value);
            activeOverlaySection.style.setProperty('--cms-bg-overlay-opacity', overlayOpacityRange.value / 100);
            activeOverlaySection.classList.add('cms-has-bg-overlay');
        }
    });
    overlayColorPicker.addEventListener('input', function() {
        if (activeOverlaySection) {
            activeOverlaySection.style.setProperty('--cms-bg-overlay-color', overlayColorPicker.value);
            activeOverlaySection.classList.add('cms-has-bg-overlay');
        }
    });
    overlayApplyBtn.addEventListener('click', function() {
        overlayPanel.style.display = 'none';
        activeOverlaySection = null;
    });
    overlayCloseBtn.addEventListener('click', function() {
        overlayPanel.style.display = 'none';
        activeOverlaySection = null;
    });

    function openOverlayPanel(sTarget, triggerBtn) {
        activeOverlaySection = sTarget;
        var curColor = sTarget.style.getPropertyValue('--cms-bg-overlay-color') || '#000000';
        var curOp    = parseFloat(sTarget.style.getPropertyValue('--cms-bg-overlay-opacity') || '0');
        overlayColorPicker.value = curColor;
        overlayOpacityRange.value = Math.round(curOp * 100);
        overlayOpacityLabel.textContent = Math.round(curOp * 100) + '%';
        var rect = triggerBtn.getBoundingClientRect();
        overlayPanel.style.left = Math.min(rect.left, window.innerWidth - 220) + 'px';
        overlayPanel.style.top  = (rect.bottom + 6) + 'px';
        overlayPanel.style.display = 'block';
    }

    function applyNavLinkColor(color) {
        if (menuElementNode) menuElementNode.style.setProperty('--nav-link-color', color);
    }
    
    function applyNavBtnColor(color) {
        if (menuElementNode) menuElementNode.style.setProperty('--nav-btn-color', color);
    }

    function applyNavBrandColor(color) {
        if (menuElementNode) menuElementNode.style.setProperty('--nav-brand-color', color);
    }

    function applyNavBgColor(color) {
        if (menuElementNode) menuElementNode.style.setProperty('--nav-bg-color', color);
    }

    function initNavColorPickers() {
        if (!menuElementNode) return;

        var currentLinkColor = menuElementNode.style.getPropertyValue('--nav-link-color');
        var currentBtnColor = menuElementNode.style.getPropertyValue('--nav-btn-color');
        var currentBrandColor = menuElementNode.style.getPropertyValue('--nav-brand-color');
        var currentBgColor = menuElementNode.style.getPropertyValue('--nav-bg-color');

        if (!currentLinkColor || currentLinkColor === 'inherit') currentLinkColor = '#ffffff';
        if (!currentBtnColor || currentBtnColor === 'inherit') currentBtnColor = '#ffffff';
        if (!currentBrandColor || currentBrandColor === 'inherit') currentBrandColor = '#ffffff';
        if (!currentBgColor || currentBgColor === 'inherit') currentBgColor = '#1e222b';

        if (navLinkColorPicker) navLinkColorPicker.value = currentLinkColor.trim();
        if (navBtnColorPicker) navBtnColorPicker.value = currentBtnColor.trim();
        if (navBrandColorPicker) navBrandColorPicker.value = currentBrandColor.trim();
        if (navBgColorPicker) navBgColorPicker.value = currentBgColor.trim();

        navColorsSection.style.display = 'block';
    }

    if (navLinkColorPicker) {
        navLinkColorPicker.addEventListener('input', function() { applyNavLinkColor(navLinkColorPicker.value); });
        navLinkColorPicker.addEventListener('change', function() { applyNavLinkColor(navLinkColorPicker.value); });
    }

    if (navBtnColorPicker) {
        navBtnColorPicker.addEventListener('input', function() { applyNavBtnColor(navBtnColorPicker.value); });
        navBtnColorPicker.addEventListener('change', function() { applyNavBtnColor(navBtnColorPicker.value); });
    }

    if (navBrandColorPicker) {
        navBrandColorPicker.addEventListener('input', function() { applyNavBrandColor(navBrandColorPicker.value); });
        navBrandColorPicker.addEventListener('change', function() { applyNavBrandColor(navBrandColorPicker.value); });
    }

    if (navBgColorPicker) {
        navBgColorPicker.addEventListener('input', function() { applyNavBgColor(navBgColorPicker.value); });
        navBgColorPicker.addEventListener('change', function() { applyNavBgColor(navBgColorPicker.value); });
    }

    function enablePageEditing(active) {
        if (active) {
            editableTexts.forEach(function(el) { el.contentEditable = true; el.classList.add('global-editing-active'); });
            editableMedias.forEach(function(item) {
                if (item.type === 'section-bg') { item.el.addEventListener('click', handleMediaInteraction); }
                else if (item.shield) { item.shield.style.display = 'block'; item.shield.addEventListener('click', handleMediaInteraction); }
                else { item.el.classList.add('global-img-editable'); item.el.addEventListener('click', handleMediaInteraction); }
            });
            document.querySelectorAll('.cms-control-container').forEach(function(c){ c.style.display='flex'; });
            editableColors.forEach(function(item) { item.el.addEventListener('click', handleColorInteraction); });
            editableLinks.forEach(function(el) { el.classList.add('cms-link-editable'); });
            initNavColorPickers();
            document.addEventListener('selectionchange', handleTextSelection);
        } else {
            document.querySelectorAll('.global-editing-active, .cms-link-editable, [contenteditable], a, h4, h5, h6').forEach(function(el) {
                el.contentEditable = false;
                el.removeAttribute('contenteditable');
                el.blur();
                el.classList.remove('global-editing-active','cms-link-editable');
                if (el.tagName.toLowerCase() === 'a') el.onclick = null;
            });
            editableMedias.forEach(function(item) { if(item.shield){ item.shield.style.display='none'; } else { item.el.classList.remove('global-img-editable'); } });
            document.querySelectorAll('.cms-control-container').forEach(function(c){ c.style.display='none'; });
            navColorsSection.style.display = 'none';
            overlayPanel.style.display = 'none';
            toolbar.style.display = 'none';
            document.removeEventListener('selectionchange', handleTextSelection);
        }
    }

    window.addEventListener('mousedown', function(e) {
        if (!isAdminActive) return;
        if (e.target.closest('#cms-overlay-panel') || e.target.closest('#cms-nav-colors-section')) return;
        var linkEl = e.target.closest('.cms-link-editable');
        if (linkEl) { e.preventDefault(); e.stopPropagation(); linkEl.onclick = function(ev){ ev.preventDefault(); return false; }; handleLinkClickDirect(linkEl); }
    }, true);

    function handleTextSelection() {
        var sel = window.getSelection();
        if (sel.rangeCount > 0 && sel.toString().trim().length > 0) {
            var rect = sel.getRangeAt(0).getBoundingClientRect();
            toolbar.style.display = 'flex'; toolbar.style.top = (rect.top + window.scrollY - 45) + 'px'; toolbar.style.left = (rect.left + window.scrollX) + 'px';
        } else { toolbar.style.display = 'none'; }
    }

    function showVideoMenu(el, anchorEl) {
        var old = document.getElementById('cms-video-menu'); if (old) old.remove();
        var menu = document.createElement('div');
        menu.id = 'cms-video-menu';
        menu.style.cssText = 'position:fixed;z-index:999999;background:#1e222b;border:1px solid rgba(255,255,255,0.15);border-radius:10px;padding:10px;box-shadow:0 4px 16px rgba(0,0,0,0.6);font-family:sans-serif;min-width:220px;';
        var rect = anchorEl.getBoundingClientRect();
        var top = rect.top + rect.height/2 - 80; if (top < 10) top = 10; if (top > window.innerHeight - 200) top = window.innerHeight - 200;
        var left = rect.left + rect.width/2 - 110; if (left < 10) left = 10; if (left > window.innerWidth - 230) left = window.innerWidth - 230;
        menu.style.top = top + 'px'; menu.style.left = left + 'px';

        function btn(label, handler) {
            var b = document.createElement('button'); b.type = 'button'; b.innerText = label;
            b.style.cssText = 'display:block;width:100%;text-align:left;background:#16181b;color:#fff;border:1px solid #3a3f47;padding:8px 10px;border-radius:6px;margin-bottom:6px;font-size:13px;cursor:pointer;';
            b.addEventListener('click', function(ev){ ev.stopPropagation(); menu.remove(); handler(); });
            return b;
        }

        menu.appendChild(btn('📤 MP4 hochladen', function(){ activeMediaElementToUpload = el; fileUploader.click(); }));
        menu.appendChild(btn('🔗 YouTube-Link einfügen', function(){
            var rawInput = prompt("YouTube-Link einfügen:", el.getAttribute('src') || el.getAttribute('data-bg-video') || '');
            if (rawInput !== null && rawInput.trim() !== '') {
                var finalUrl = rawInput.trim();
                if (finalUrl.includes('<iframe') && finalUrl.includes('src=')) { var m = finalUrl.match(/src=["'](.*?)["']/); if(m) finalUrl=m[1]; }
                if (el.hasAttribute('data-bg-video')) el.setAttribute('data-bg-video', finalUrl); else el.setAttribute('src', finalUrl);
            }
        }));
        menu.appendChild(btn('⏯️ Autoplay AN/AUS', function(){ setVideoAutoplayState(el, confirm("Autoplay AN?\n[OK]=JA | [Abbrechen]=NEIN")); }));
        menu.appendChild(btn('✏️ Manueller Pfad', function(){
            var src = prompt("Pfad:", el.getAttribute('src')||'');
            if(src&&src.trim()) { if(el.hasAttribute('data-bg-video')) el.setAttribute('data-bg-video',src.trim()); else el.setAttribute('src',src.trim()); setVideoAutoplayState(el, confirm("Autoplay?")); }
        }));
        var cancelBtn = document.createElement('button'); cancelBtn.type='button'; cancelBtn.innerText='✕ Abbrechen';
        cancelBtn.style.cssText = 'display:block;width:100%;text-align:center;background:none;color:#aaa;border:1px solid #3a3f47;padding:6px 10px;border-radius:6px;font-size:12px;cursor:pointer;';
        cancelBtn.addEventListener('click', function(ev){ ev.stopPropagation(); menu.remove(); });
        menu.appendChild(cancelBtn);

        document.body.appendChild(menu);
        setTimeout(function(){
            document.addEventListener('click', function closeOnOutside(ev){
                if (!menu.contains(ev.target)) { menu.remove(); document.removeEventListener('click', closeOnOutside); }
            });
        }, 0);
    }

    function showImageMenu(el, anchorEl) {
        var old = document.getElementById('cms-image-menu'); if (old) old.remove();
        var menu = document.createElement('div');
        menu.id = 'cms-image-menu';
        menu.style.cssText = 'position:fixed;z-index:999999;background:#1e222b;border:1px solid rgba(255,255,255,0.15);border-radius:10px;padding:10px;box-shadow:0 4px 16px rgba(0,0,0,0.6);font-family:sans-serif;min-width:220px;';
        var rect = anchorEl.getBoundingClientRect();
        var top = rect.top + rect.height/2 - 60; if (top < 10) top = 10; if (top > window.innerHeight - 160) top = window.innerHeight - 160;
        var left = rect.left + rect.width/2 - 110; if (left < 10) left = 10; if (left > window.innerWidth - 230) left = window.innerWidth - 230;
        menu.style.top = top + 'px'; menu.style.left = left + 'px';

        function btn(label, handler) {
            var b = document.createElement('button'); b.type = 'button'; b.innerText = label;
            b.style.cssText = 'display:block;width:100%;text-align:left;background:#16181b;color:#fff;border:1px solid #3a3f47;padding:8px 10px;border-radius:6px;margin-bottom:6px;font-size:13px;cursor:pointer;';
            b.addEventListener('click', function(ev){ ev.stopPropagation(); menu.remove(); handler(); });
            return b;
        }

        menu.appendChild(btn('📤 Bild hochladen', function(){ activeMediaElementToUpload = el; fileUploader.click(); }));
        menu.appendChild(btn('✏️ Manueller Pfad', function(){
            var src = prompt("Pfad:", el.getAttribute('src')||'');
            if (src !== null && src.trim() !== '') setImageSrcSynced(el, src.trim());
        }));
        var cancelBtn = document.createElement('button'); cancelBtn.type='button'; cancelBtn.innerText='✕ Abbrechen';
        cancelBtn.style.cssText = 'display:block;width:100%;text-align:center;background:none;color:#aaa;border:1px solid #3a3f47;padding:6px 10px;border-radius:6px;font-size:12px;cursor:pointer;';
        cancelBtn.addEventListener('click', function(ev){ ev.stopPropagation(); menu.remove(); });
        menu.appendChild(cancelBtn);

        document.body.appendChild(menu);
        setTimeout(function(){
            document.addEventListener('click', function closeOnOutside(ev){
                if (!menu.contains(ev.target)) { menu.remove(); document.removeEventListener('click', closeOnOutside); }
            });
        }, 0);
    }

    function handleMediaInteraction(e) {
        e.preventDefault();
        e.stopPropagation();
        if (e.stopImmediatePropagation) e.stopImmediatePropagation();
        var clickedEl = e.currentTarget;
        var el = clickedEl.classList.contains('cms-video-shield') ? clickedEl.parentNode.querySelector('video, iframe, [data-bg-video]') : clickedEl;
        if (!el) { console.error('CMS: Ziel-Medienelement nicht gefunden für', clickedEl); return; }
        activeMediaElementToUpload = el;
        var isBgTrigger   = clickedEl.classList.contains('cms-bg-edit-trigger');
        var isVideoElement = (el && (el.tagName==='VIDEO' || el.tagName==='IFRAME' || el.hasAttribute('data-bg-video')));

        if (isBgTrigger) {
            var sTarget = clickedEl.parentElement.parentElement;
            var mode = prompt("Hintergrundbild-Optionen:\n'1' = Bild hochladen/ändern\n'2' = Deckkraft einstellen\n'3' = Overlay-Farbe wählen", "1");
            if (mode === "2") {
                var curOp = sTarget.style.getPropertyValue('--cms-bg-opacity') || "1";
                var newOp = prompt("Deckkraft (0–100):\n100 = voll sichtbar | 20 = fast transparent", Math.round(curOp * 100));
                if (newOp !== null && !isNaN(newOp)) { sTarget.style.setProperty('--cms-bg-opacity', Math.min(Math.max(parseInt(newOp)/100,0),1)); }
                return;
            }
            if (mode === "3") {
                openOverlayPanel(sTarget, clickedEl);
                return;
            }
            if (confirm("Neues Bild hochladen?\n[Abbrechen] für manuelle Pfadeingabe.")) { activeMediaElementToUpload = clickedEl; fileUploader.click(); }
            else { var src = prompt("Pfad eintragen:"); if (src !== null && src.trim() !== '') { sTarget.classList.add('cms-has-bg'); sTarget.style.setProperty('--cms-bg-image',"url('"+src.trim()+"')"); sTarget.style.backgroundImage='none'; } }
            return;
        }

        if (isVideoElement) {
            showVideoMenu(el, clickedEl);
            return;
        } else {
            showImageMenu(el, clickedEl);
        }
    }

    function setVideoAutoplayState(videoEl, shouldAutoplay) {
        if (!videoEl || videoEl.tagName !== 'VIDEO') { alert("Gilt nur für MP4-Videos."); return; }
        if (shouldAutoplay) {
            videoEl.setAttribute('autoplay','autoplay');
            videoEl.setAttribute('muted','muted');
            videoEl.setAttribute('loop','loop');
            videoEl.removeAttribute('controls');
            videoEl.muted = true;
            videoEl.play().catch(function(){});
        } else {
            videoEl.removeAttribute('autoplay');
            videoEl.removeAttribute('muted');
            videoEl.removeAttribute('loop');
            videoEl.setAttribute('controls','controls');
            videoEl.muted = false;
            videoEl.pause();
        }
        var mediaId = videoEl.getAttribute('data-media-id');
        if (mediaId) videoEl.setAttribute('data-autoplay-state', shouldAutoplay ? '1' : '0');
        alert(shouldAutoplay ? 'Autoplay AKTIVIERT!' : 'Autoplay AUSGESCHALTET!');
    }

fileUploader.addEventListener('change', function(e) {
    console.log("Upload gestartet..."); // Debug-Log
    if (!e.target.files[0] || !activeMediaElementToUpload) {
        console.log("Abbruch: Keine Datei oder kein Ziel-Element.");
        return;
    }
    
    var file = e.target.files[0];
    var formData = new FormData(); 
    formData.append('action','upload'); 
    formData.append('file', file);
    
    fetch(handlerUrl, { 
        method:'POST', 
        body:formData, 
        credentials:'include' 
    })
    .then(function(r) { 
        if (!r.ok) throw new Error('Server-Fehler: ' + r.status);
        return r.json(); 
    })
    .then(function(d) {
        console.log("Server-Antwort erhalten:", d); // Debug-Log
        if (d.success) {
            var newPath = d.filepath || d.path || d.url || d.filename; // save_content.php liefert "filepath"
            var el = activeMediaElementToUpload;
            if (el) {
                if (el.classList && el.classList.contains('cms-bg-edit-trigger')) {
                    // Hintergrundbild eines Abschnitts
                    var sTarget = el.parentElement.parentElement;
                    sTarget.classList.add('cms-has-bg');
                    sTarget.style.setProperty('--cms-bg-image', "url('" + newPath + "')");
                    sTarget.style.backgroundImage = 'none';
                } else if (el.tagName === 'VIDEO') {
                    el.setAttribute('src', newPath);
                } else if (el.hasAttribute('data-bg-video')) {
                    el.setAttribute('data-bg-video', newPath);
                } else {
                    // normales <img> inkl. Lightbox-Vorschaubild -> Lightbox-Bild mitsynchronisieren
                    setImageSrcSynced(el, newPath);
                }
            }
            alert('Erfolgreich hochgeladen!');
            fileUploader.value = ''; // Reset für das nächste Mal
            activeMediaElementToUpload = null;
        } else { 
            alert('Upload-Fehler: ' + d.error); 
        }
    })
    .catch(function(err) {
        console.error("Upload-Fehler:", err);
        alert('Ein Fehler ist aufgetreten: ' + err.message);
    });
});

    function handleLinkClickDirect(el) {
        var txt = prompt("Text:", getLinkText(el));
        var url = prompt("Ziel-URL:", el.getAttribute('href') || '');
        if (txt !== null && url !== null) {
            var finalUrl = url.trim();
            if (finalUrl !== "") {
                if (/^www\./i.test(finalUrl)) { finalUrl = "https://" + finalUrl; }
                else if (!/^https?:\/\//i.test(finalUrl) && !/^\//.test(finalUrl) && !/^#/.test(finalUrl) && !/\.html$/i.test(finalUrl)) { finalUrl = "https://" + finalUrl; }
            }
            if (!el.querySelector('img')) setLinkText(el, txt);
            el.setAttribute('href', finalUrl);
            var t = prompt("In neuem Tab?\n'y'=JA | 'n'=NEIN:", el.getAttribute('target')==='_blank' ? 'y' : 'n');
            if (t !== null) { if (t.toLowerCase()==='y') el.setAttribute('target','_blank'); else el.removeAttribute('target'); }
        }
        el.onclick = null;
    }

    if (saveBtn) {
        saveBtn.addEventListener('click', function() {
            var pLoad = {}, gLoad = {}, fLoad = {};

            if (stickySelect) gLoad['cms_menu_sticky_style'] = stickySelect.value;
            if (navLinkColorPicker) gLoad['cms_nav_link_color'] = navLinkColorPicker.value;
            if (navBtnColorPicker) gLoad['cms_nav_btn_color']  = navBtnColorPicker.value;
            if (navBrandColorPicker) gLoad['cms_nav_brand_color'] = navBrandColorPicker.value;
            if (navBgColorPicker) gLoad['cms_nav_bg_color'] = navBgColorPicker.value;

            editableTexts.forEach(function(el) { 
                var k = el.getAttribute('data-auto-id'), s = el.getAttribute('data-cms-scope');
                var c = el.cloneNode(true);
                c.classList.remove('global-editing-active'); c.removeAttribute('contenteditable');
                c.querySelectorAll('[contenteditable]').forEach(function(sub){ sub.removeAttribute('contenteditable'); sub.classList.remove('cms-link-editable','global-editing-active'); });
                var html = c.innerHTML.trim();
                if(s==='menu') gLoad[k]=html; else if(s==='footer') fLoad[k]=html; else pLoad[k]=html;
            });

            editableColors.forEach(function(item) {
                var k = item.el.getAttribute('data-color-id'), s = item.el.getAttribute('data-cms-scope');
                var v = item.parentSection.style.backgroundColor;
                if(v && v!=='') { if(s==='menu') gLoad[k]=v; else if(s==='footer') fLoad[k]=v; else pLoad[k]=v; }
            });

            editableMedias.forEach(function(item) {
                var s = item.el.getAttribute('data-cms-scope');
                if (item.type === 'section-bg') {
                    var k = item.el.getAttribute('data-bg-id');
                    var rawImg = item.parentSection.style.getPropertyValue('--cms-bg-image');
                    var path = rawImg ? rawImg.replace(/url\(['"]?(.*?)['"]?\)/,'$1') : "";
                    var opVal = item.parentSection.style.getPropertyValue('--cms-bg-opacity') || "1";
                    var idx = item.parentSection.getAttribute('data-block-idx');
                    var ovColor = item.parentSection.style.getPropertyValue('--cms-bg-overlay-color');
                    var ovOpacity = item.parentSection.style.getPropertyValue('--cms-bg-overlay-opacity');
                    if (ovColor) {
                        if(s==='menu') gLoad['overlay_color_'+idx]=ovColor;
                        else if(s==='footer') fLoad['overlay_color_'+idx]=ovColor;
                        else pLoad['overlay_color_'+idx]=ovColor;
                    }
                    if (ovOpacity !== '') {
                        if(s==='menu') gLoad['overlay_opacity_'+idx]=ovOpacity;
                        else if(s==='footer') fLoad['overlay_opacity_'+idx]=ovOpacity;
                        else pLoad['overlay_opacity_'+idx]=ovOpacity;
                    }
                    
                    if(s==='menu') { gLoad[k]=path; gLoad[k+'_opacity']=opVal; } 
                    else if(s==='footer') { fLoad[k]=path; fLoad[k+'_opacity']=opVal; } 
                    else { pLoad[k]=path; pLoad[k+'_opacity']=opVal; }
                } else if (item.type === 'bg-video') {
                    var k = item.el.getAttribute('data-media-id'), path = item.el.getAttribute('data-bg-video');
                    if(s==='menu') gLoad[k]=path; else if(s==='footer') fLoad[k]=path; else pLoad[k]=path;
                } else if (item.type === 'video') {
                    var k = item.el.getAttribute('data-media-id');
                    var videoData = {
                        src: item.el.getAttribute('src') || '',
                        autoplay: item.el.hasAttribute('autoplay')
                    };
                    if(s==='menu') gLoad[k]=videoData; else if(s==='footer') fLoad[k]=videoData; else pLoad[k]=videoData;
                } else {
                    var k = item.el.getAttribute('data-media-id'), path = item.el.getAttribute('src');
                    if(s==='menu') gLoad[k]=path; else if(s==='footer') fLoad[k]=path; else pLoad[k]=path;
                }
            });

            editableLinks.forEach(function(el) {
                var k = el.getAttribute('data-link-id'), s = el.getAttribute('data-cms-scope');
                var data = { text: el.querySelector('img') ? "" : getLinkText(el), url: el.getAttribute('href'), target: el.getAttribute('target')||'' };
                if(s==='menu') gLoad[k]=data; else if(s==='footer') fLoad[k]=data; else pLoad[k]=data;
            });

            function send(f,p){ return fetch(handlerUrl,{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body:'action=save&filename='+encodeURIComponent(f)+'&data='+encodeURIComponent(JSON.stringify(p)),credentials:'include'}); }
            Promise.all([send(jsonUrl,pLoad), send(jsonGlobalUrl,gLoad), send(jsonFooterUrl,fLoad)]).then(function(){
                if (!ALLOW_MENU_FOOTER_EDIT) {
                    alert('Gespeichert!\n\nHinweis: Menü und Footer wurden NICHT gespeichert (Bearbeitung ist aktuell auf dieser Seite gesperrt).');
                } else {
                    alert('Gespeichert!');
                }
                fetchBackupList();
            });
        });
    }

    if (logoutBtn) {
        logoutBtn.addEventListener('click', function() {
            fetch(handlerUrl,{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body:'action=logout',credentials:'include'})
            .then(function(){ document.body.classList.remove('admin-active'); window.location.reload(); });
        });
    }
}
Genau die läuft bei mir
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 8829
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Mobirise CMS 4.0

Beitrag von Tommy Herrmann »

OK - ich kopiere die auf den Server.

Mache Du mal jetzt bitte nichts, sonst kann man nicht testen. Ich gebe dann Bescheid.
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 8829
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Mobirise CMS 4.0

Beitrag von Tommy Herrmann »

Im Moment ist es so.

Ich ändere die Startseite und das geht.

Dann versuche ich die Unterseite "Bilder" zu ändern und es geht dort gar nichts, auch kein einfaches Textfeld.

Nachdem ich diese Unterseite erfolglos gespeichert habe, gehe ich nun zurück zur Startseite, ist diese auch wieder leer gesetzt.
Volker
Moderator
Moderator
Beiträge: 2805
Registriert: Sa 12. Dez 2020, 22:35

Re: Mobirise CMS 4.0

Beitrag von Volker »

https://www.niederastroth.de/0cms/index.html

Hier kannst du mal alles testen Tommy. Da geht komischer Weise immer noch alles.
Eventuell mal die json bei dir löschen
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 8829
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Mobirise CMS 4.0

Beitrag von Tommy Herrmann »

Alles schon x Mal gelöscht. Ist ja schön wenn Deine Seite funktioniert - aber warte ich teste.

Rufe ich mit einer neuen Browser-Session meine Seite auf:

https://www.mobirise-tutorials.com/CMS-4/

sehe ich die Änderungen. Wechsele ich dann über die Navi auf meine Unterseite und zurück zur Startseite ist alles weg.
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 8829
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Mobirise CMS 4.0

Beitrag von Tommy Herrmann »

Ich habe alles gelöscht - alles neu installiert - ich kann die Startseite auch ändern aber die Änderungen sind nach dem Aufruf einer anderen Seite weg.

Solange keine JSON von einer Unterseite angelegt wird, kann das ja nicht funktionieren.

Wenn Du alle Dateien nochmals in funktionierender Form am Server hast, versuche ich es vielleicht nochmals.

Ich gebe jetzt erst einmal auf.
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 8829
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Mobirise CMS 4.0

Beitrag von Tommy Herrmann »

Hier mein Problem als Video und warum ich nicht weiter komme:

Volker
Moderator
Moderator
Beiträge: 2805
Registriert: Sa 12. Dez 2020, 22:35

Re: Mobirise CMS 4.0

Beitrag von Volker »

Ich hab das Problem gesehen und eine neue cms-core.js hoch geladen, die bitte testen.
ich weiß ist sehr mühsam alles, aber anders bekomme ich das ja nicht in den Griff. Testen, Testen,.... :D

Das sagt die KI zu dem Probelm:
Warum das für dich und Tommy wichtig ist:
Umgehung des "Einfrierens": Wenn man auf index.php zurückgeht, sieht der Browser die Seite als "fertig geladen" an und führt das DOMContentLoaded Event nicht erneut aus.

event.persisted: Dieser Wert ist nur dann true, wenn die Seite aus dem Cache geholt wurde. Genau in diesem Moment springt unsere Funktion ein und sorgt dafür, dass die JSON-Daten neu geladen und in das DOM injiziert werden.

Konsistenz: Damit wird sichergestellt, dass auch nach dem Hin- und Her-Navigieren die aktuellsten Daten (die ihr gespeichert habt) angezeigt werden.

Ein wichtiger technischer Hinweis für die Umsetzung:
Da Tommy und du das CMS auf verschiedenen Seiten testet, achtet darauf, dass in der initCMS() Funktion die JSON-Dateien über loadJsonData mit einem Zeitstempel geladen werden:
fetch(url + '?v=' + Date.now()). Das ist die "Cache-Busting"-Versicherung. Wenn ihr den pageshow-Block einbaut, sollte das CMS beim Zurückkehren die aktuellen Daten von Tommy's oder deinem Server erzwingen.

Hast du den pageshow-Block bereits an der entsprechenden Stelle in deine Datei kopiert? Wenn ja, sollte das Problem mit dem "alten Text" beim Zurückgehen sofort behoben sein.
ok, aber warum geht das bei meiner seite, die nur html seiten hat, da ist immer die änderung sofort zu sehen

Der Grund, warum das auf deinen HTML-Seiten so reibungslos funktioniert, ist der fundamentale Unterschied, wie der Browser mit statischen Dokumenten im Vergleich zu dynamischen Inhalten umgeht.

Warum es auf deinen HTML-Seiten "sofort" geht
Deine HTML-Seiten sind für den Browser "fertige Produkte". Wenn du eine .html-Seite lädst, ist das DOM (der Aufbau der Seite) fest definiert. Wenn du von einer anderen Seite zurückkehrst:

Statische Kontrolle: Der Browser hat das HTML im Speicher. Da sich am HTML selbst nichts ändert (es ist kein Skript nötig, um den Text zu "bauen"), zeigt er genau das an, was er als letztes "gesehen" hat.

Keine Abhängigkeit: Dein CMS muss auf diesen Seiten nicht erst eine JSON-Datei lesen, um den Inhalt zusammenzusetzen. Der Text steht bereits im HTML-Quelltext. Der Browser muss also nicht auf den Abschluss einer Promise oder eines fetch-Aufrufs warten.

Warum es bei der index.php bei Tommy (und dir) anders ist
Bei der index.php mit dem CMS-Skript ist die Seite ein "lebender Organismus":

Timing-Problem: Wenn du zurückkehrst, wird das Skript initCMS() oft vor oder während des Seitenaufbaus ausgeführt. Wenn der Browser den Cache ("bfcache") nutzt, ist das Skript "eingefroren". Die JSON-Daten, die eigentlich die aktuellen Texte enthalten, werden dann nicht erneut vom Server geholt, und das Skript "weiß" nicht, dass es die Inhalte aktualisieren muss.

Daten-Schnittstelle: Bei deiner HTML-Seite ist der Inhalt "hardcodiert". Bei der CMS-Seite ist der Inhalt "geliehen" (aus der JSON-Datei). Wenn die "Leihgabe" (die JSON-Datei) nicht frisch geladen wird, weil der Browser das Skript beim "Zurück" überspringt, siehst du den alten oder gar keinen Zustand.

Zusammenfassung: Der "HTML-Vorteil"
Deine reinen HTML-Seiten sind cache-resistent, weil sie keine Logik brauchen, um ihren eigenen Inhalt zu verstehen. Das CMS-System auf der index.php hingegen ist cache-anfällig, weil es erst eine externe Datenquelle (JSON) abfragen muss, bevor es weiß, was auf der Seite stehen soll.

Die Strategie:
Indem wir das pageshow-Event (wie oben besprochen) einbauen, zwingen wir das Skript auf der index.php dazu, sich genau wie deine HTML-Seiten zu verhalten: Es übernimmt die Verantwortung, den Inhalt sofort zu aktualisieren, sobald die Seite wieder in den Sichtbereich des Benutzers kommt, anstatt sich auf den (veralteten) Zustand des Browsers zu verlassen.

Hast du das pageshow-Event in der cms-core.js schon eingebaut? Das sollte das Verhalten der index.php sofort an das "sofortige" Gefühl deiner HTML-Seiten angleichen.




Gemini ist eine KI und kann Fehler machen, auch bei Informationen über Personen. Datenschutz und Gemini
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 8829
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Mobirise CMS 4.0

Beitrag von Tommy Herrmann »

puh - funktioniert :tu:

https://www.mobirise-tutorials.com/CMS-4/

... auch Unterseite.

Die .js gehört dann aber in den Download für alle User - oder wie?


P.S.:

Die Beschriftung der 4 Bilder ist nicht im CMS möglich (aber egal), wollte es nur mitteilen.
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 8829
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Mobirise CMS 4.0

Beitrag von Tommy Herrmann »

Das die Original-Bilder von meiner Lightbox-Galerie beim Laden aufblitzen liegt wahrscheinlich daran, dass das CMS diesen Block noch nicht kennt - oder?

Das sieht immer noch scheiße aus, vielleicht findet die KI eine Lösung, das grundsätzlich jedes Bild mit einem weißen Platzhalter (SVG) beim Laden überdeckt wird?

https://www.mobirise-tutorials.com/CMS- ... allery5-16
Volker
Moderator
Moderator
Beiträge: 2805
Registriert: Sa 12. Dez 2020, 22:35

Re: Mobirise CMS 4.0

Beitrag von Volker »

Tommy Herrmann hat geschrieben: So 21. Jun 2026, 10:41 Das die Original-Bilder von meiner Lightbox-Galerie beim Laden aufblitzen liegt wahrscheinlich daran, dass das CMS diesen Block noch nicht kennt - oder?

Das sieht immer noch scheiße aus, vielleicht findet die KI eine Lösung, das grundsätzlich jedes Bild mit einem weißen Platzhalter (SVG) beim Laden überdeckt wird?

https://www.mobirise-tutorials.com/CMS- ... allery5-16

Hast du das nicht rein gemacht?

Code: Alles auswählen

<style>
  /* Verhindert das Zeichnen der Sektionen ab Frame 1 auf der Live-Seite */
  html:not(.cms-ready):not(.is-builder) section,
  html:not(.cms-ready):not(.is-builder) nav,
  html:not(.cms-ready):not(.is-builder) footer {
    opacity: 0 !important;
  }
</style>
DAs muss doch auch in die seiteneigenschaften Before </head>
Volker
Moderator
Moderator
Beiträge: 2805
Registriert: Sa 12. Dez 2020, 22:35

Re: Mobirise CMS 4.0

Beitrag von Volker »

Tommy Herrmann hat geschrieben: So 21. Jun 2026, 10:29
P.S.:

Die Beschriftung der 4 Bilder ist nicht im CMS möglich (aber egal), wollte es nur mitteilen.
Auch das muss das Script "lernen" kann ich auch einbauen (lassen) ;)
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 8829
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Mobirise CMS 4.0

Beitrag von Tommy Herrmann »

Nee - das ist ja nicht möglich, dass Du da jede Kleinigkeit ins Script einbaust - das ist auch nicht nötig.

Das scheint jetzt ganz gut zu funktionieren.

Einzig, ich habe den Footer in der PHP-Datei gesperrt - er kann aber weiterhin editiert werden (seit der neuen JS Datei).
Volker
Moderator
Moderator
Beiträge: 2805
Registriert: Sa 12. Dez 2020, 22:35

Re: Mobirise CMS 4.0

Beitrag von Volker »

Tommy Herrmann hat geschrieben: So 21. Jun 2026, 11:07 Nee - das ist ja nicht möglich, dass Du da jede Kleinigkeit ins Script einbaust - das ist auch nicht nötig.

Das scheint jetzt ganz gut zu funktionieren.

Einzig, ich habe den Footer in der PHP-Datei gesperrt - er kann aber weiterhin editiert werden (seit der neuen JS Datei).
Ne Tommy kann nicht editiert werden :D Es speichert ja nicht, kannst da schreiben was Du willst ;)
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 8829
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Mobirise CMS 4.0

Beitrag von Tommy Herrmann »

Volker hat geschrieben: So 21. Jun 2026, 10:54 Hast du das nicht rein gemacht?

Code: Alles auswählen

<style>
  /* Verhindert das Zeichnen der Sektionen ab Frame 1 auf der Live-Seite */
  html:not(.cms-ready):not(.is-builder) section,
  html:not(.cms-ready):not(.is-builder) nav,
  html:not(.cms-ready):not(.is-builder) footer {
    opacity: 0 !important;
  }
</style>
DAs muss doch auch in die seiteneigenschaften Before </head>

Das gehört dann aber zwingend mit in den Download der Anwendung !!!
Volker
Moderator
Moderator
Beiträge: 2805
Registriert: Sa 12. Dez 2020, 22:35

Re: Mobirise CMS 4.0

Beitrag von Volker »

Volker hat geschrieben: So 21. Jun 2026, 11:15
Tommy Herrmann hat geschrieben: So 21. Jun 2026, 11:14
Volker hat geschrieben: So 21. Jun 2026, 10:54 Hast du das nicht rein gemacht?

Code: Alles auswählen

<style>
  /* Verhindert das Zeichnen der Sektionen ab Frame 1 auf der Live-Seite */
  html:not(.cms-ready):not(.is-builder) section,
  html:not(.cms-ready):not(.is-builder) nav,
  html:not(.cms-ready):not(.is-builder) footer {
    opacity: 0 !important;
  }
</style>
DAs muss doch auch in die seiteneigenschaften Before </head>

Das gehört dann aber zwingend mit in den Download der Anwendung !!!
DAS Steht doch in dem Extra Feld !!!
feld1.png
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 8829
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Mobirise CMS 4.0

Beitrag von Tommy Herrmann »

ach Du meine Güte - das habe ich nur als Fliegenschiss wahrgenommen, das gehört mit in eine Datei style.css oder so mit der entprechenden Anweisung.
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 8829
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Mobirise CMS 4.0

Beitrag von Tommy Herrmann »

Volker hat geschrieben: So 21. Jun 2026, 11:12
Tommy Herrmann hat geschrieben: So 21. Jun 2026, 11:07 Nee - das ist ja nicht möglich, dass Du da jede Kleinigkeit ins Script einbaust - das ist auch nicht nötig.

Das scheint jetzt ganz gut zu funktionieren.

Einzig, ich habe den Footer in der PHP-Datei gesperrt - er kann aber weiterhin editiert werden (seit der neuen JS Datei).
Ne Tommy kann nicht editiert werden :D Es speichert ja nicht, kannst da schreiben was Du willst ;)

Ah - OK - vorher konnte man da gar nicht drin schreiben - war schon schöner (aber egal).
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 8829
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Mobirise CMS 4.0

Beitrag von Tommy Herrmann »

Langsam wird es - bitte schreibe mir noch, wenn Du das alles als finalen Download für ALLE am Server hast. Dann teste ich alles nochmals :angst:
Volker
Moderator
Moderator
Beiträge: 2805
Registriert: Sa 12. Dez 2020, 22:35

Re: Mobirise CMS 4.0

Beitrag von Volker »

Tommy Herrmann hat geschrieben: So 21. Jun 2026, 11:17 ach Du meine Güte - das habe ich nur als Fliegenschiss wahrgenommen, das gehört mit in eine Datei style.css oder so mit der entprechenden Anweisung.
Nein das darf nicht ins CSS das muss zwingend da rein wo ich sagte ;)
DAs verhindert das Durchflackern der alten Inhalte. DAs hatte ich aber auch in einem Beitrag hier bereits mal geschrieben ;) Ich kann diesen code auch als Datei noch dazu legen und ich mache, wenn ich fertig bin, dann auch noch eine saubere Anleitung.

Wir sind aber noch im Test Stadium Tommy ;)
Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste