Versión inicial del plugin FP Genocide Maps (v1.5.2)
CPT geep_map + shortcode [geep_maps] para la sección Architecture of Genocide de la home: acordeón exclusivo con imagen por mapa, lightbox con botón de compartir y enlaces #map-<slug>. Soporte WPML (EN/AR) con herencia de la imagen del idioma original y CSS RTL.
This commit is contained in:
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* FP Genocide Maps — front-end styles.
|
||||
*
|
||||
* Replicates 1:1 the CSS Divi 5 generated for the original "texto mapa" row
|
||||
* (row_3 / column_5 / column_6 / image_2 / toggle_0..7 on page 1834), so the
|
||||
* section looks identical to the hand-built Divi version it replaces.
|
||||
* Color/radius values reference the site's Divi global variables with their
|
||||
* current values as fallbacks.
|
||||
*/
|
||||
|
||||
/* --- Layout: replicates row_3's two flex columns (14/24 + 2/5, 2% gap). --- */
|
||||
.geep-maps {
|
||||
display: flex;
|
||||
column-gap: 2%;
|
||||
row-gap: 10px;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.geep-maps-col-map {
|
||||
width: calc(58.3333% - 2% * 0.41667); /* .et_flex_column_14_24 with 2% gap */
|
||||
}
|
||||
|
||||
.geep-maps-col-toggles {
|
||||
width: calc(40% - 2% * 0.6); /* .et_flex_column_2_5 with 2% gap */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 15px;
|
||||
padding-left: 10px; /* column_6 */
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
.geep-maps {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.geep-maps-col-map,
|
||||
.geep-maps-col-toggles {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Map image: replicates the Divi image module (image_2). --- */
|
||||
.geep-maps-image {
|
||||
display: flex;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
.geep-maps-image-wrap {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
border-radius: var(--gvid-4up6riitl2, 40px);
|
||||
}
|
||||
|
||||
.geep-map-img {
|
||||
position: relative;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: none;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.geep-map-img.is-active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.geep-map-img.is-active.is-shown {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* --- Toggles: replicates the 8 Divi toggle modules (toggle_0..7). --- */
|
||||
.geep-toggle {
|
||||
background-color: var(--gcid-primary-color, #d96c5d);
|
||||
padding: 10px 2px 0 5px;
|
||||
border: 0 solid #333;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.geep-toggle.geep-toggle--first {
|
||||
padding: 0 2px 2px 5px; /* toggle_0 had slightly different padding */
|
||||
}
|
||||
|
||||
.geep-toggle-title {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
padding: 0 0 0 40px;
|
||||
word-wrap: break-word;
|
||||
/* Same line spacing as the intro paragraph above the section. */
|
||||
line-height: var(--gvid-pfs7jbw9ep, 1.4em);
|
||||
}
|
||||
|
||||
.geep-toggle--close .geep-toggle-title {
|
||||
color: var(--gcid-mpn8tovm4t, #fff5f0) !important;
|
||||
}
|
||||
|
||||
.geep-toggle--open .geep-toggle-title {
|
||||
color: var(--gcid-heading-color, #424242) !important;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checkbox-style marker: identical size and position in both states so
|
||||
* nothing shifts when a map is selected; the open one is filled white.
|
||||
*/
|
||||
.geep-toggle-title::before {
|
||||
content: "";
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -9px;
|
||||
left: 0;
|
||||
right: auto;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: 2px solid var(--gcid-secondary-color, #ffffff);
|
||||
border-radius: 4px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.geep-toggle--open .geep-toggle-title::before {
|
||||
background: var(--gcid-secondary-color, #ffffff);
|
||||
}
|
||||
|
||||
.geep-toggle-content {
|
||||
position: relative;
|
||||
padding-top: 20px;
|
||||
/* Align the excerpt with the title text (which sits after the marker). */
|
||||
padding-left: 40px;
|
||||
color: var(--gcid-secondary-color, #ffffff);
|
||||
word-wrap: break-word;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.geep-toggle--close .geep-toggle-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Keep content visible while the open/close animation is running. */
|
||||
.geep-toggle .geep-toggle-content.geep-animating {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.geep-toggle-content p:last-of-type {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
/* --- RTL (Arabic): mirror icon and paddings. --- */
|
||||
.rtl .geep-maps-col-toggles {
|
||||
padding-left: 0;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.rtl .geep-toggle-title {
|
||||
padding: 0 40px 0 0;
|
||||
}
|
||||
|
||||
.rtl .geep-toggle-title::before {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.rtl .geep-toggle-content {
|
||||
padding-left: 0;
|
||||
padding-right: 40px;
|
||||
}
|
||||
|
||||
/* --- Lightbox: click the map to view it larger + share its URL. --- */
|
||||
.geep-maps-image-wrap {
|
||||
cursor: zoom-in;
|
||||
}
|
||||
|
||||
.geep-lightbox {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 999999;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 3vh 3vw;
|
||||
}
|
||||
|
||||
.geep-lightbox.is-open {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.geep-lightbox-noscroll,
|
||||
.geep-lightbox-noscroll body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.geep-lightbox-backdrop {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(20, 20, 20, 0.85);
|
||||
cursor: zoom-out;
|
||||
}
|
||||
|
||||
.geep-lightbox-inner {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
max-width: 94vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 12px;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
.geep-lightbox-img {
|
||||
max-width: 100%;
|
||||
max-height: calc(94vh - 60px);
|
||||
width: auto;
|
||||
height: auto;
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
.geep-lightbox-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.geep-lightbox-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: var(--gcid-mpn8tovm4t, #fff5f0);
|
||||
color: var(--gcid-heading-color, #424242);
|
||||
border: 0;
|
||||
border-radius: 40px;
|
||||
padding: 10px 18px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.geep-lightbox-btn:hover {
|
||||
background: var(--gcid-secondary-color, #ffffff);
|
||||
}
|
||||
|
||||
.geep-lightbox-close {
|
||||
padding: 10px 14px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.geep-lightbox-toast {
|
||||
position: absolute;
|
||||
bottom: 18px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: var(--gcid-heading-color, #424242);
|
||||
color: var(--gcid-secondary-color, #ffffff);
|
||||
border-radius: 40px;
|
||||
padding: 10px 20px;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
/**
|
||||
* FP Genocide Maps — front-end behavior.
|
||||
*
|
||||
* - Exclusive accordion with one map always open (700 ms slide, Divi's
|
||||
* default speed); opening a map swaps the image with a fade.
|
||||
* - Clicking the map image opens it in a lightbox with a share button.
|
||||
* - Each map has a shareable URL (#map-<slug>): visiting it opens that map
|
||||
* and scrolls the section into view.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var DURATION = 700;
|
||||
var HASH_PREFIX = '#map-';
|
||||
|
||||
function slideDown(el) {
|
||||
el.classList.add('geep-animating');
|
||||
el.style.overflow = 'hidden';
|
||||
el.style.height = '0px';
|
||||
var target = el.scrollHeight;
|
||||
el.style.transition = 'height ' + DURATION + 'ms ease-in-out';
|
||||
requestAnimationFrame(function () {
|
||||
el.style.height = target + 'px';
|
||||
});
|
||||
window.setTimeout(function () {
|
||||
el.style.transition = '';
|
||||
el.style.height = '';
|
||||
el.style.overflow = '';
|
||||
el.classList.remove('geep-animating');
|
||||
}, DURATION);
|
||||
}
|
||||
|
||||
function slideUp(el, done) {
|
||||
el.classList.add('geep-animating');
|
||||
el.style.overflow = 'hidden';
|
||||
el.style.height = el.scrollHeight + 'px';
|
||||
el.style.transition = 'height ' + DURATION + 'ms ease-in-out';
|
||||
requestAnimationFrame(function () {
|
||||
el.style.height = '0px';
|
||||
});
|
||||
window.setTimeout(function () {
|
||||
el.style.transition = '';
|
||||
el.style.height = '';
|
||||
el.style.overflow = '';
|
||||
el.classList.remove('geep-animating');
|
||||
done();
|
||||
}, DURATION);
|
||||
}
|
||||
|
||||
function init(root) {
|
||||
var labels;
|
||||
try {
|
||||
labels = JSON.parse(root.getAttribute('data-labels') || '{}');
|
||||
} catch (e) {
|
||||
labels = {};
|
||||
}
|
||||
var images = root.querySelectorAll('.geep-map-img');
|
||||
// The first map is rendered open by the shortcode.
|
||||
var current = root.querySelector('.geep-toggle--open');
|
||||
|
||||
function showMap(key) {
|
||||
// No fallback: a map without its own image leaves the gap empty.
|
||||
var target = null;
|
||||
if (key) {
|
||||
images.forEach(function (img) {
|
||||
if (img.getAttribute('data-map') === key) {
|
||||
target = img;
|
||||
}
|
||||
});
|
||||
}
|
||||
images.forEach(function (img) {
|
||||
if (img !== target) {
|
||||
img.classList.remove('is-active', 'is-shown');
|
||||
}
|
||||
});
|
||||
if (target && !target.classList.contains('is-active')) {
|
||||
target.classList.add('is-active');
|
||||
requestAnimationFrame(function () {
|
||||
requestAnimationFrame(function () {
|
||||
target.classList.add('is-shown');
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function close(toggle) {
|
||||
var content = toggle.querySelector('.geep-toggle-content');
|
||||
toggle.classList.remove('geep-toggle--open');
|
||||
slideUp(content, function () {
|
||||
toggle.classList.add('geep-toggle--close');
|
||||
});
|
||||
}
|
||||
|
||||
function open(toggle) {
|
||||
var content = toggle.querySelector('.geep-toggle-content');
|
||||
toggle.classList.remove('geep-toggle--close');
|
||||
toggle.classList.add('geep-toggle--open');
|
||||
slideDown(content);
|
||||
}
|
||||
|
||||
function select(toggle) {
|
||||
if (toggle === current) {
|
||||
return;
|
||||
}
|
||||
if (current) {
|
||||
close(current);
|
||||
}
|
||||
open(toggle);
|
||||
current = toggle;
|
||||
showMap(toggle.getAttribute('data-map'));
|
||||
}
|
||||
|
||||
root.querySelectorAll('.geep-toggle').forEach(function (toggle) {
|
||||
var title = toggle.querySelector('.geep-toggle-title');
|
||||
var content = toggle.querySelector('.geep-toggle-content');
|
||||
if (!title || !content) {
|
||||
return;
|
||||
}
|
||||
title.addEventListener('click', function () {
|
||||
if (content.classList.contains('geep-animating')) {
|
||||
return;
|
||||
}
|
||||
select(toggle);
|
||||
});
|
||||
});
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
* Shareable URLs: #map-<slug> selects that map on page load.
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
function shareUrl() {
|
||||
var base = window.location.href.split('#')[0];
|
||||
if (!current) {
|
||||
return base;
|
||||
}
|
||||
return base + HASH_PREFIX + encodeURIComponent(current.getAttribute('data-slug'));
|
||||
}
|
||||
|
||||
function openFromHash() {
|
||||
if (window.location.hash.indexOf(HASH_PREFIX) !== 0) {
|
||||
return;
|
||||
}
|
||||
var slug = decodeURIComponent(window.location.hash.slice(HASH_PREFIX.length));
|
||||
var target = null;
|
||||
root.querySelectorAll('.geep-toggle').forEach(function (t) {
|
||||
if (t.getAttribute('data-slug') === slug) {
|
||||
target = t;
|
||||
}
|
||||
});
|
||||
if (!target || target === current) {
|
||||
if (target) {
|
||||
root.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Switch instantly (no slide) — the page is just loading.
|
||||
if (current) {
|
||||
current.classList.remove('geep-toggle--open');
|
||||
current.classList.add('geep-toggle--close');
|
||||
}
|
||||
target.classList.remove('geep-toggle--close');
|
||||
target.classList.add('geep-toggle--open');
|
||||
current = target;
|
||||
showMap(target.getAttribute('data-map'));
|
||||
root.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
|
||||
openFromHash();
|
||||
window.addEventListener('hashchange', openFromHash);
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
* Lightbox with share button.
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
var lightbox = null;
|
||||
var toastTimer = null;
|
||||
|
||||
function buildLightbox() {
|
||||
var lb = document.createElement('div');
|
||||
lb.className = 'geep-lightbox';
|
||||
lb.setAttribute('role', 'dialog');
|
||||
lb.setAttribute('aria-modal', 'true');
|
||||
lb.innerHTML =
|
||||
'<div class="geep-lightbox-backdrop"></div>' +
|
||||
'<figure class="geep-lightbox-inner">' +
|
||||
'<div class="geep-lightbox-actions">' +
|
||||
'<button type="button" class="geep-lightbox-btn geep-lightbox-share">' +
|
||||
'<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.6" y1="10.6" x2="15.4" y2="6.4"/><line x1="8.6" y1="13.4" x2="15.4" y2="17.6"/></svg>' +
|
||||
'<span>' + (labels.share || 'Share map') + '</span>' +
|
||||
'</button>' +
|
||||
'<button type="button" class="geep-lightbox-btn geep-lightbox-close" aria-label="' + (labels.close || 'Close') + '">×</button>' +
|
||||
'</div>' +
|
||||
'<img class="geep-lightbox-img" alt="">' +
|
||||
'<div class="geep-lightbox-toast" hidden>' + (labels.copied || 'Link copied!') + '</div>' +
|
||||
'</figure>';
|
||||
document.body.appendChild(lb);
|
||||
|
||||
lb.querySelector('.geep-lightbox-backdrop').addEventListener('click', closeLightbox);
|
||||
lb.querySelector('.geep-lightbox-close').addEventListener('click', closeLightbox);
|
||||
lb.querySelector('.geep-lightbox-share').addEventListener('click', share);
|
||||
return lb;
|
||||
}
|
||||
|
||||
function openLightbox() {
|
||||
var active = root.querySelector('.geep-map-img.is-active');
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
if (!lightbox) {
|
||||
lightbox = buildLightbox();
|
||||
}
|
||||
var img = lightbox.querySelector('.geep-lightbox-img');
|
||||
var key = active.getAttribute('data-map');
|
||||
var full = active.src; // src attribute holds the full-size file.
|
||||
|
||||
// Show instantly whatever variant the page already downloaded for
|
||||
// this map (it is in cache), instead of leaving the previous map
|
||||
// on screen while the big file downloads.
|
||||
img.dataset.map = key;
|
||||
img.src = active.currentSrc || full;
|
||||
img.alt = current ? current.querySelector('.geep-toggle-title').textContent : '';
|
||||
|
||||
// Then upgrade to the full-size file in the background.
|
||||
if (img.src !== full) {
|
||||
var pre = new Image();
|
||||
pre.onload = function () {
|
||||
// Only swap if the lightbox still shows this same map.
|
||||
if (lightbox.classList.contains('is-open') && img.dataset.map === key) {
|
||||
img.src = full;
|
||||
}
|
||||
};
|
||||
pre.src = full;
|
||||
}
|
||||
|
||||
lightbox.classList.add('is-open');
|
||||
document.documentElement.classList.add('geep-lightbox-noscroll');
|
||||
document.addEventListener('keydown', onKeydown);
|
||||
}
|
||||
|
||||
function closeLightbox() {
|
||||
if (!lightbox) {
|
||||
return;
|
||||
}
|
||||
lightbox.classList.remove('is-open');
|
||||
document.documentElement.classList.remove('geep-lightbox-noscroll');
|
||||
document.removeEventListener('keydown', onKeydown);
|
||||
}
|
||||
|
||||
function onKeydown(e) {
|
||||
if (e.key === 'Escape') {
|
||||
closeLightbox();
|
||||
}
|
||||
}
|
||||
|
||||
function toast() {
|
||||
var t = lightbox.querySelector('.geep-lightbox-toast');
|
||||
t.hidden = false;
|
||||
window.clearTimeout(toastTimer);
|
||||
toastTimer = window.setTimeout(function () {
|
||||
t.hidden = true;
|
||||
}, 2200);
|
||||
}
|
||||
|
||||
function share() {
|
||||
var url = shareUrl();
|
||||
var title = current ? current.querySelector('.geep-toggle-title').textContent : document.title;
|
||||
if (navigator.share) {
|
||||
navigator.share({ title: title, url: url }).catch(function () {});
|
||||
return;
|
||||
}
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(url).then(toast, function () {
|
||||
fallbackCopy(url);
|
||||
});
|
||||
} else {
|
||||
fallbackCopy(url);
|
||||
}
|
||||
}
|
||||
|
||||
function fallbackCopy(url) {
|
||||
var ta = document.createElement('textarea');
|
||||
ta.value = url;
|
||||
ta.style.position = 'fixed';
|
||||
ta.style.opacity = '0';
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
toast();
|
||||
} catch (e) {}
|
||||
document.body.removeChild(ta);
|
||||
}
|
||||
|
||||
var wrap = root.querySelector('.geep-maps-image-wrap');
|
||||
if (wrap) {
|
||||
wrap.addEventListener('click', openLightbox);
|
||||
wrap.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
openLightbox();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function ready(fn) {
|
||||
if (document.readyState !== 'loading') {
|
||||
fn();
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', fn);
|
||||
}
|
||||
}
|
||||
|
||||
ready(function () {
|
||||
document.querySelectorAll('.geep-maps').forEach(init);
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user