feat(js): implement intersection observer lazy loading for adsense
- Add per-slot lazy loading with Intersection Observer API - Implement fill detection via MutationObserver and data-ad-status - Add configurable rootMargin and fillTimeout from database - Generate dynamic CSS based on lazy_loading_enabled setting - Add legacy mode fallback for browsers without IO support - Include backup of previous implementation (adsense-loader.legacy.js) - Add OpenSpec documentation with test plan (72 tests verified) Schema changes: - Add lazy_loading_enabled (boolean, default: true) - Add lazy_rootmargin (select: 0-500px, default: 200) - Add lazy_fill_timeout (select: 3000-10000ms, default: 5000) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -56,6 +56,11 @@ final class AdsensePlacementFieldMapper implements FieldMapperInterface
|
||||
'adsense-placementRailFormat' => ['group' => 'behavior', 'attribute' => 'rail_format'],
|
||||
'adsense-placementRailTopOffset' => ['group' => 'behavior', 'attribute' => 'rail_top_offset'],
|
||||
|
||||
// BEHAVIOR (Lazy Loading)
|
||||
'adsense-placementLazyLoadingEnabled' => ['group' => 'behavior', 'attribute' => 'lazy_loading_enabled'],
|
||||
'adsense-placementLazyRootmargin' => ['group' => 'behavior', 'attribute' => 'lazy_rootmargin'],
|
||||
'adsense-placementLazyFillTimeout' => ['group' => 'behavior', 'attribute' => 'lazy_fill_timeout'],
|
||||
|
||||
// LAYOUT (Archive/Global locations + formats)
|
||||
'adsense-placementArchiveTopEnabled' => ['group' => 'layout', 'attribute' => 'archive_top_enabled'],
|
||||
'adsense-placementArchiveBetweenEnabled' => ['group' => 'layout', 'attribute' => 'archive_between_enabled'],
|
||||
|
||||
@@ -1182,6 +1182,55 @@ final class AdsensePlacementFormBuilder
|
||||
$delayTimeout = $this->renderer->getFieldValue($cid, 'forms', 'delay_timeout', '5000');
|
||||
$html .= $this->buildTextInput($cid . 'DelayTimeout', 'Timeout de delay (ms)', $delayTimeout);
|
||||
|
||||
// Lazy Loading settings
|
||||
$html .= '<hr class="my-3">';
|
||||
$html .= '<p class="small fw-semibold mb-2">';
|
||||
$html .= ' <i class="bi bi-eye me-1" style="color: #198754;"></i>';
|
||||
$html .= ' Lazy Loading (Intersection Observer)';
|
||||
$html .= ' <span class="badge bg-success ms-1">Nuevo</span>';
|
||||
$html .= '</p>';
|
||||
$html .= '<div class="alert alert-info small py-2 mb-2">';
|
||||
$html .= ' <i class="bi bi-lightbulb me-1"></i>';
|
||||
$html .= ' Carga anuncios individualmente al entrar al viewport. Mejora fill rate y reduce CLS.';
|
||||
$html .= '</div>';
|
||||
|
||||
$lazyEnabled = $this->renderer->getFieldValue($cid, 'behavior', 'lazy_loading_enabled', true);
|
||||
$html .= $this->buildSwitch($cid . 'LazyLoadingEnabled', 'Activar Lazy Loading', $lazyEnabled, 'bi-eye');
|
||||
|
||||
$html .= '<div class="row g-2">';
|
||||
$html .= ' <div class="col-md-6">';
|
||||
$lazyRootmargin = $this->renderer->getFieldValue($cid, 'behavior', 'lazy_rootmargin', '200');
|
||||
$html .= $this->buildSelect($cid . 'LazyRootmargin', 'Pre-carga (px)',
|
||||
(string)$lazyRootmargin,
|
||||
[
|
||||
'0' => '0px (sin pre-carga)',
|
||||
'100' => '100px',
|
||||
'200' => '200px (recomendado)',
|
||||
'300' => '300px',
|
||||
'400' => '400px',
|
||||
'500' => '500px'
|
||||
]
|
||||
);
|
||||
$html .= ' </div>';
|
||||
$html .= ' <div class="col-md-6">';
|
||||
$lazyFillTimeout = $this->renderer->getFieldValue($cid, 'behavior', 'lazy_fill_timeout', '5000');
|
||||
$html .= $this->buildSelect($cid . 'LazyFillTimeout', 'Timeout fill (ms)',
|
||||
(string)$lazyFillTimeout,
|
||||
[
|
||||
'3000' => '3 segundos',
|
||||
'5000' => '5 segundos (recomendado)',
|
||||
'7000' => '7 segundos',
|
||||
'10000' => '10 segundos'
|
||||
]
|
||||
);
|
||||
$html .= ' </div>';
|
||||
$html .= '</div>';
|
||||
|
||||
$html .= '<div class="alert alert-warning small py-2 mt-2 mb-0">';
|
||||
$html .= ' <i class="bi bi-exclamation-triangle me-1"></i>';
|
||||
$html .= ' <strong>Nota:</strong> Cambios requieren vaciar cache (Redis, W3TC) para aplicarse.';
|
||||
$html .= '</div>';
|
||||
|
||||
$html .= ' </div>';
|
||||
$html .= '</div>';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user