Biotech-Analysis / presentacion_colegios_biotecnologia_global.html
C2MV's picture
Upload 71 files
0615069 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PPT Presentation Viewer</title>
<style>
:root {
--text-color: #111111;
--secondary-text: #666666;
--bg-color: #ffffff;
--light-bg: #f8f8f8;
--dark-bg: #111111;
--border-color: #e0e0e0;
--hover-color: #f0f0f0;
--active-color: #000000;
--shadow: 0 1px 2px rgba(0, 0, 0, 0.05), 0 1px 4px rgba(0, 0, 0, 0.05), 0 2px 8px rgba(0, 0, 0, 0.05);
--btn-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
--card-radius: 4px;
--btn-radius: 4px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}
body {
background-color: var(--light-bg);
color: var(--text-color);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
.container {
max-width: 1800px;
margin: 0 auto;
padding: 24px;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 24px;
background-color: var(--dark-bg);
color: white;
margin-bottom: 32px;
box-shadow: var(--shadow);
}
header h1 {
font-size: 18px;
font-weight: 500;
letter-spacing: 0.2px;
display: flex;
align-items: center;
}
header h1 svg {
margin-right: 12px;
}
.controls {
display: flex;
gap: 16px;
align-items: center;
}
.view-controls {
display: flex;
background: rgba(255, 255, 255, 0.1);
border-radius: var(--btn-radius);
overflow: hidden;
}
.view-controls button {
background: none;
color: white;
border: none;
padding: 6px 12px;
cursor: pointer;
font-size: 13px;
font-weight: 500;
transition: all 0.2s ease;
}
.view-controls button.active {
background: rgba(255, 255, 255, 0.2);
}
.play-button {
background-color: white;
color: var(--dark-bg);
border: none;
padding: 8px 16px;
border-radius: var(--btn-radius);
cursor: pointer;
display: flex;
align-items: center;
transition: all 0.2s ease;
font-weight: 500;
font-size: 13px;
box-shadow: var(--btn-shadow);
}
.play-button:hover {
background-color: var(--hover-color);
transform: translateY(-1px);
}
.play-button svg {
margin-right: 8px;
}
/* Grid View */
.preview-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(480px, 1fr));
gap: 24px;
margin-top: 24px;
}
/* Grid mode specific styles */
.preview-container:not(.list-view) .slide-frame-container {
position: relative;
padding-top: 56.25%; /* 16:9 Aspect Ratio */
width: 100%;
overflow: hidden;
}
.preview-container:not(.list-view) .slide-frame {
position: absolute;
top: 50%;
left: 50%;
width: 1280px;
height: 720px;
border: none;
transform-origin: center center;
transform: translate(-50%, -50%) scale(1);
}
/* List View */
.preview-container.list-view {
display: flex;
flex-direction: column;
gap: 32px;
align-items: center;
}
.preview-container.list-view .slide-preview {
width: 1280px;
height: 720px;
max-width: 90vw;
}
.preview-container.list-view .slide-frame-container {
width: 100%;
height: 100%;
position: relative;
padding-top: 0;
}
.preview-container.list-view .slide-frame {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: none;
}
.slide-preview {
background: var(--bg-color);
border-radius: var(--card-radius);
overflow: hidden;
box-shadow: var(--shadow);
transition: transform 0.2s ease, box-shadow 0.2s ease;
cursor: pointer;
position: relative;
border: 1px solid var(--border-color);
}
.slide-preview:hover {
transform: translateY(-2px);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.08);
}
.slide-preview.active {
border: 1px solid var(--active-color);
}
.slide-number {
position: absolute;
top: 12px;
left: 12px;
background-color: rgba(0, 0, 0, 0.7);
color: white;
border-radius: 50%;
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: 600;
z-index: 2;
}
/* Presentation mode */
.presentation-mode {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #000;
z-index: 1000;
display: none;
flex-direction: column;
align-items: center;
justify-content: center;
}
/* Fullscreen mode adjustments */
.presentation-mode:fullscreen {
width: 100vw;
height: 100vh;
}
.presentation-mode:-webkit-full-screen {
width: 100vw;
height: 100vh;
}
.presentation-mode:-moz-full-screen {
width: 100vw;
height: 100vh;
}
.presentation-mode:-ms-fullscreen {
width: 100vw;
height: 100vh;
}
.presentation-slide {
width: 1280px;
height: 720px;
border: none;
transform-origin: center center;
}
.presentation-slide-container {
display: flex;
align-items: center;
justify-content: center;
flex: 1;
width: 100%;
padding: 20px;
}
.presentation-controls {
height: 48px;
background-color: rgba(0, 0, 0, 0.9);
display: flex;
justify-content: center;
align-items: center;
gap: 24px;
padding: 0 24px;
position: relative;
z-index: 1001;
}
.presentation-controls.fullscreen {
position: fixed;
bottom: 0;
left: 0;
right: 0;
opacity: 0;
transition: opacity 0.3s ease;
}
.presentation-controls.fullscreen:hover,
.presentation-controls.fullscreen.show {
opacity: 1;
}
.progress-bar {
flex: 1;
max-width: 400px;
height: 2px;
background-color: rgba(255, 255, 255, 0.2);
border-radius: 1px;
overflow: hidden;
position: relative;
}
.progress-fill {
height: 100%;
background-color: white;
width: 0%;
transition: width 0.3s ease;
}
.slide-indicators {
color: white;
font-size: 12px;
min-width: 40px;
text-align: center;
}
.presentation-controls button {
background-color: transparent;
color: white;
border: none;
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: background-color 0.2s ease;
}
.presentation-controls button:hover {
background-color: rgba(255, 255, 255, 0.1);
}
/* Responsive adjustments */
@media (max-width: 1200px) {
.preview-container:not(.list-view) {
grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
}
}
@media (max-width: 900px) {
.preview-container:not(.list-view) {
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}
}
@media (max-width: 640px) {
.container {
padding: 16px;
}
.preview-container:not(.list-view) {
grid-template-columns: 1fr;
gap: 16px;
}
header {
flex-direction: column;
align-items: flex-start;
gap: 16px;
padding: 16px;
}
.controls {
width: 100%;
justify-content: space-between;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>
Presentation Viewer
</h1>
<div class="controls">
<div class="view-controls">
<button id="grid-view-btn">Grid</button>
<button id="list-view-btn" class="active">List</button>
</div>
<button id="play-button" class="play-button">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polygon points="5 3 19 12 5 21 5 3"></polygon>
</svg>
Play Slides
</button>
</div>
</header>
<div class="preview-container list-view" id="preview-container">
<!-- Slide previews will be dynamically inserted here -->
</div>
</div>
<div class="presentation-mode" id="presentation-mode">
<div class="presentation-slide-container">
<iframe id="presentation-slide" class="presentation-slide" src="" frameborder="0"></iframe>
</div>
<div class="presentation-controls">
<button id="prev-slide">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="19" y1="12" x2="5" y2="12"></line>
<polyline points="12 19 5 12 12 5"></polyline>
</svg>
</button>
<div class="progress-bar">
<div class="progress-fill" id="progress-fill"></div>
</div>
<div class="slide-indicators">
<span id="current-slide">1</span>/<span id="total-slides">0</span>
</div>
<button id="next-slide">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</button>
<button id="fullscreen-toggle" title="Toggle Fullscreen">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"></path>
</svg>
</button>
<button id="exit-presentation">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
<line x1="9" y1="9" x2="15" y2="15"></line>
<line x1="15" y1="9" x2="9" y2="15"></line>
</svg>
</button>
</div>
</div>
<script>
// Load the slides data
const slides = ["slides/slide01_titulo.html", "slides/slide02_resumen.html", "slides/slide03_modelo1.html", "slides/slide04_modelo2.html", "slides/slide05_comparativo.html", "slides/slide06_caso_ecuador.html", "slides/slide07_ecosistema_academico.html", "slides/slide08_indicadores.html", "slides/slide09_brechas_oportunidades.html", "slides/slide10_tendencias.html", "slides/slide11_csb_argentina.html", "slides/slide12_analisis_cuantitativo_v2.html", "slides/slide13_correlacion_educacion.html", "slides/slide14_modelos_comparativos.html", "slides/slide15_america_latina.html", "slides/slide16_casos_estudio_simple.html", "slides/slide17_conclusiones.html", "slides/slide18_bibliografia.html", "slides/slide19_agradecimientos.html"];
let currentSlideIndex = 0;
let viewMode = 'list'; // 'grid' or 'list'
// DOM elements
const previewContainer = document.getElementById('preview-container');
const presentationMode = document.getElementById('presentation-mode');
const presentationSlide = document.getElementById('presentation-slide');
const playButton = document.getElementById('play-button');
const prevButton = document.getElementById('prev-slide');
const nextButton = document.getElementById('next-slide');
const exitButton = document.getElementById('exit-presentation');
const fullscreenToggle = document.getElementById('fullscreen-toggle');
const presentationControls = document.querySelector('.presentation-controls');
const progressFill = document.getElementById('progress-fill');
const currentSlideElement = document.getElementById('current-slide');
const totalSlidesElement = document.getElementById('total-slides');
const gridViewBtn = document.getElementById('grid-view-btn');
const listViewBtn = document.getElementById('list-view-btn');
// Fullscreen state
let isFullscreen = false;
let controlsTimeout;
// Initialize the viewer
function initViewer() {
// Set total slides
totalSlidesElement.textContent = slides.length;
// Generate slide previews
generatePreviews();
// Set up view mode buttons
gridViewBtn.addEventListener('click', () => setViewMode('grid'));
listViewBtn.addEventListener('click', () => setViewMode('list'));
}
// Generate slide previews
function generatePreviews() {
previewContainer.innerHTML = '';
slides.forEach((slide, index) => {
const slidePreview = document.createElement('div');
slidePreview.className = 'slide-preview';
if (index === currentSlideIndex) {
slidePreview.classList.add('active');
}
slidePreview.innerHTML = `
<div class="slide-number">${index + 1}</div>
<div class="slide-frame-container">
<iframe class="slide-frame" src="${slide}" frameborder="0"></iframe>
</div>
`;
slidePreview.addEventListener('click', () => {
startPresentation(index);
});
previewContainer.appendChild(slidePreview);
});
// Scale grid previews after generating
if (viewMode === 'grid') {
setTimeout(scaleGridPreviews, 100);
}
}
// Set view mode (grid or list)
function setViewMode(mode) {
viewMode = mode;
if (mode === 'grid') {
previewContainer.classList.remove('list-view');
gridViewBtn.classList.add('active');
listViewBtn.classList.remove('active');
// Scale grid previews after mode change
setTimeout(scaleGridPreviews, 100);
} else {
previewContainer.classList.add('list-view');
gridViewBtn.classList.remove('active');
listViewBtn.classList.add('active');
// Reset all iframe transforms for list mode
resetListPreviews();
}
}
// Reset transforms for list mode
function resetListPreviews() {
const slideFrames = document.querySelectorAll('.slide-frame');
slideFrames.forEach(frame => {
frame.style.transform = '';
});
}
// Scale grid mode previews
function scaleGridPreviews() {
if (viewMode !== 'grid') return;
const slideFrames = document.querySelectorAll('.preview-container:not(.list-view) .slide-frame');
slideFrames.forEach(frame => {
const container = frame.closest('.slide-frame-container');
if (!container) return;
const containerWidth = container.clientWidth;
const containerHeight = container.clientHeight;
// Calculate scale to fit 1280x720 within container
const scaleX = containerWidth / 1280;
const scaleY = containerHeight / 720;
const scale = Math.min(scaleX, scaleY);
frame.style.transform = `translate(-50%, -50%) scale(${scale})`;
});
}
// Start presentation mode
function startPresentation(index = 0) {
currentSlideIndex = index;
presentationMode.style.display = 'flex';
document.body.style.overflow = 'hidden';
updateSlide();
// Auto-enter fullscreen
requestFullscreen();
}
// Request fullscreen
function requestFullscreen() {
const element = presentationMode;
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullscreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.msRequestFullscreen) {
element.msRequestFullscreen();
}
}
// Exit fullscreen
function exitFullscreen() {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}
// Toggle fullscreen
function toggleFullscreen() {
if (isFullscreen) {
exitFullscreen();
} else {
requestFullscreen();
}
}
// Handle fullscreen change
function handleFullscreenChange() {
isFullscreen = !!(document.fullscreenElement ||
document.webkitFullscreenElement ||
document.mozFullScreenElement ||
document.msFullscreenElement);
if (isFullscreen) {
presentationControls.classList.add('fullscreen');
setupControlsAutoHide();
} else {
presentationControls.classList.remove('fullscreen');
clearTimeout(controlsTimeout);
}
// Re-scale slide when fullscreen changes
setTimeout(scalePresentationSlide, 100);
}
// Setup auto-hide controls in fullscreen
function setupControlsAutoHide() {
if (!isFullscreen) return;
// Show controls initially
presentationControls.classList.add('show');
// Auto-hide after 3 seconds
controlsTimeout = setTimeout(() => {
if (isFullscreen) {
presentationControls.classList.remove('show');
}
}, 3000);
}
// Show controls temporarily
function showControlsTemporarily() {
if (!isFullscreen) return;
presentationControls.classList.add('show');
clearTimeout(controlsTimeout);
controlsTimeout = setTimeout(() => {
if (isFullscreen) {
presentationControls.classList.remove('show');
}
}, 3000);
}
// Exit presentation mode
function exitPresentation() {
// Exit fullscreen if in fullscreen mode
if (isFullscreen) {
exitFullscreen();
}
presentationMode.style.display = 'none';
document.body.style.overflow = 'auto';
}
// Update current slide
function updateSlide() {
presentationSlide.src = slides[currentSlideIndex];
currentSlideElement.textContent = currentSlideIndex + 1;
// Update progress bar
const progress = ((currentSlideIndex + 1) / slides.length) * 100;
progressFill.style.width = `${progress}%`;
// Scale presentation slide to fit container
scalePresentationSlide();
// Update preview highlighting
document.querySelectorAll('.slide-preview').forEach((preview, index) => {
if (index === currentSlideIndex) {
preview.classList.add('active');
} else {
preview.classList.remove('active');
}
});
}
// Scale presentation slide to fit container
function scalePresentationSlide() {
const container = document.querySelector('.presentation-slide-container');
const containerWidth = container.clientWidth - 40; // Account for padding
const containerHeight = container.clientHeight - 40;
// In fullscreen mode, use full viewport dimensions
if (isFullscreen) {
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight - 48; // Account for controls height
const scaleX = viewportWidth / 1280;
const scaleY = viewportHeight / 720;
const scale = Math.min(scaleX, scaleY);
presentationSlide.style.transform = `scale(${scale})`;
} else {
// Calculate scale based on container size and slide dimensions (1280x720)
const scaleX = containerWidth / 1280;
const scaleY = containerHeight / 720;
const scale = Math.min(scaleX, scaleY);
presentationSlide.style.transform = `scale(${scale})`;
}
}
// Go to next slide
function nextSlide() {
if (currentSlideIndex < slides.length - 1) {
currentSlideIndex++;
updateSlide();
}
}
// Go to previous slide
function prevSlide() {
if (currentSlideIndex > 0) {
currentSlideIndex--;
updateSlide();
}
}
// Event listeners
playButton.addEventListener('click', () => startPresentation(0));
prevButton.addEventListener('click', () => {
prevSlide();
showControlsTemporarily();
});
nextButton.addEventListener('click', () => {
nextSlide();
showControlsTemporarily();
});
exitButton.addEventListener('click', exitPresentation);
fullscreenToggle.addEventListener('click', () => {
toggleFullscreen();
showControlsTemporarily();
});
// Fullscreen change listeners
document.addEventListener('fullscreenchange', handleFullscreenChange);
document.addEventListener('webkitfullscreenchange', handleFullscreenChange);
document.addEventListener('mozfullscreenchange', handleFullscreenChange);
document.addEventListener('MSFullscreenChange', handleFullscreenChange);
// Mouse movement in fullscreen mode
presentationMode.addEventListener('mousemove', showControlsTemporarily);
// Keyboard navigation
document.addEventListener('keydown', (e) => {
if (presentationMode.style.display === 'flex') {
if (e.key === 'ArrowRight' || e.key === ' ' || e.key === 'n') {
nextSlide();
showControlsTemporarily();
} else if (e.key === 'ArrowLeft' || e.key === 'p') {
prevSlide();
showControlsTemporarily();
} else if (e.key === 'Escape') {
if (isFullscreen) {
exitFullscreen();
} else {
exitPresentation();
}
} else if (e.key === 'f' || e.key === 'F') {
toggleFullscreen();
showControlsTemporarily();
}
}
});
// Initialize the viewer when the page loads
window.addEventListener('load', initViewer);
// Handle window resize for presentation mode scaling
window.addEventListener('resize', () => {
if (presentationMode.style.display === 'flex') {
scalePresentationSlide();
}
// Also scale grid previews on resize
if (viewMode === 'grid') {
scaleGridPreviews();
}
});
</script>
</body>
</html>