mailn
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* VH Flickr Mosaic - Styles
|
||||
* Beautiful photo mosaic with fade animations
|
||||
*/
|
||||
|
||||
.vh-flickr-mosaic {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(180deg, transparent 0%, rgba(0,0,0,0.03) 100%);
|
||||
padding: 20px 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.vh-mosaic-container {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
padding: 0 20px;
|
||||
justify-content: center;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.vh-mosaic-item {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
background: #f0f0f0;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.vh-mosaic-item:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 8px 25px rgba(0,0,0,0.15);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.vh-mosaic-item a {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.vh-mosaic-item img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: opacity 0.8s ease-in-out;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Fade animation for image swap */
|
||||
.vh-mosaic-item img.vh-fading-out {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.vh-mosaic-item img.vh-fading-in {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
animation: vhFadeIn 0.8s ease-in-out forwards;
|
||||
}
|
||||
|
||||
@keyframes vhFadeIn {
|
||||
0% { opacity: 0; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
/* Loading state */
|
||||
.vh-mosaic-item.vh-loading {
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: vhShimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes vhShimmer {
|
||||
0% { background-position: 200% 0; }
|
||||
100% { background-position: -200% 0; }
|
||||
}
|
||||
|
||||
/* Title overlay on hover */
|
||||
.vh-mosaic-item .vh-photo-title {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 8px 10px;
|
||||
background: linear-gradient(transparent, rgba(0,0,0,0.7));
|
||||
color: white;
|
||||
font-size: 12px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.vh-mosaic-item:hover .vh-photo-title {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.vh-flickr-mosaic {
|
||||
padding: 15px 0;
|
||||
}
|
||||
|
||||
.vh-mosaic-container {
|
||||
gap: 6px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.vh-mosaic-item {
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.vh-mosaic-container {
|
||||
gap: 4px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.vh-mosaic-item {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.vh-mosaic-item .vh-photo-title {
|
||||
font-size: 10px;
|
||||
padding: 5px 8px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dark mode support */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.vh-flickr-mosaic {
|
||||
background: linear-gradient(180deg, transparent 0%, rgba(255,255,255,0.03) 100%);
|
||||
}
|
||||
|
||||
.vh-mosaic-item {
|
||||
background: #2a2a2a;
|
||||
}
|
||||
|
||||
.vh-mosaic-item.vh-loading {
|
||||
background: linear-gradient(90deg, #2a2a2a 25%, #3a3a3a 50%, #2a2a2a 75%);
|
||||
background-size: 200% 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reduce motion for accessibility */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.vh-mosaic-item,
|
||||
.vh-mosaic-item img {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.vh-mosaic-item img.vh-fading-in {
|
||||
animation: none;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.vh-mosaic-item.vh-loading {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
* VH Flickr Mosaic - JavaScript
|
||||
* Beautiful photo mosaic with fade animations
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
class VHFlickrMosaic {
|
||||
constructor(container) {
|
||||
this.container = container;
|
||||
this.mosaicEl = container.querySelector('.vh-mosaic-container');
|
||||
this.photos = [];
|
||||
this.displayedPhotos = [];
|
||||
this.rows = parseInt(container.dataset.rows) || vhMosaicConfig.rows || 2;
|
||||
this.photoSize = parseInt(container.dataset.size) || vhMosaicConfig.photoSize || 150;
|
||||
this.animationSpeed = parseFloat(container.dataset.speed) || vhMosaicConfig.animationSpeed || 5;
|
||||
this.apiUrl = vhMosaicConfig.apiUrl;
|
||||
this.animationInterval = null;
|
||||
this.isVisible = false;
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
async init() {
|
||||
// Set up intersection observer for lazy loading
|
||||
this.setupVisibilityObserver();
|
||||
|
||||
// Load photos
|
||||
await this.loadPhotos();
|
||||
|
||||
// Initial render
|
||||
this.render();
|
||||
|
||||
// Start animation when visible
|
||||
if (this.isVisible) {
|
||||
this.startAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
setupVisibilityObserver() {
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
this.isVisible = entry.isIntersecting;
|
||||
if (this.isVisible && this.photos.length > 0) {
|
||||
this.startAnimation();
|
||||
} else {
|
||||
this.stopAnimation();
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.1 });
|
||||
|
||||
observer.observe(this.container);
|
||||
}
|
||||
|
||||
async loadPhotos() {
|
||||
if (!this.apiUrl) {
|
||||
console.error('VH Flickr Mosaic: API URL not configured');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(this.apiUrl);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.photos) {
|
||||
this.photos = data.photos;
|
||||
} else {
|
||||
console.error('VH Flickr Mosaic: Failed to load photos', data.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('VH Flickr Mosaic: API error', error);
|
||||
}
|
||||
}
|
||||
|
||||
calculateGrid() {
|
||||
const containerWidth = this.mosaicEl.offsetWidth || window.innerWidth;
|
||||
const cols = Math.floor(containerWidth / (this.photoSize + 8)); // 8px gap
|
||||
return {
|
||||
cols: Math.max(cols, 3),
|
||||
total: Math.max(cols, 3) * this.rows
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.photos.length === 0) {
|
||||
this.mosaicEl.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const { cols, total } = this.calculateGrid();
|
||||
|
||||
// Set grid columns
|
||||
this.mosaicEl.style.gridTemplateColumns = `repeat(${cols}, ${this.photoSize}px)`;
|
||||
|
||||
// Select random photos for display
|
||||
this.displayedPhotos = this.getRandomPhotos(total);
|
||||
|
||||
// Create HTML
|
||||
this.mosaicEl.innerHTML = this.displayedPhotos.map((photo, index) => `
|
||||
<div class="vh-mosaic-item" data-index="${index}" style="width:${this.photoSize}px;height:${this.photoSize}px;">
|
||||
<a href="${photo.page_url || '#'}" target="_blank" rel="noopener noreferrer">
|
||||
<img src="${photo.medium || photo.thumb}" alt="${this.escapeHtml(photo.title || '')}" loading="lazy">
|
||||
${photo.title ? `<span class="vh-photo-title">${this.escapeHtml(photo.title)}</span>` : ''}
|
||||
</a>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
getRandomPhotos(count) {
|
||||
const shuffled = [...this.photos].sort(() => Math.random() - 0.5);
|
||||
return shuffled.slice(0, Math.min(count, shuffled.length));
|
||||
}
|
||||
|
||||
startAnimation() {
|
||||
if (this.animationInterval) return;
|
||||
if (this.photos.length <= this.displayedPhotos.length) return;
|
||||
|
||||
this.animationInterval = setInterval(() => {
|
||||
this.swapRandomPhoto();
|
||||
}, this.animationSpeed * 1000);
|
||||
}
|
||||
|
||||
stopAnimation() {
|
||||
if (this.animationInterval) {
|
||||
clearInterval(this.animationInterval);
|
||||
this.animationInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
swapRandomPhoto() {
|
||||
if (!this.isVisible || this.photos.length === 0) return;
|
||||
|
||||
const items = this.mosaicEl.querySelectorAll('.vh-mosaic-item');
|
||||
if (items.length === 0) return;
|
||||
|
||||
// Pick random item to swap
|
||||
const randomIndex = Math.floor(Math.random() * items.length);
|
||||
const item = items[randomIndex];
|
||||
|
||||
// Find a photo not currently displayed
|
||||
const currentIds = this.displayedPhotos.map(p => p.id);
|
||||
const availablePhotos = this.photos.filter(p => !currentIds.includes(p.id));
|
||||
|
||||
if (availablePhotos.length === 0) return;
|
||||
|
||||
const newPhoto = availablePhotos[Math.floor(Math.random() * availablePhotos.length)];
|
||||
|
||||
// Animate the swap
|
||||
this.animatePhotoSwap(item, newPhoto, randomIndex);
|
||||
}
|
||||
|
||||
animatePhotoSwap(item, newPhoto, index) {
|
||||
const oldImg = item.querySelector('img');
|
||||
const link = item.querySelector('a');
|
||||
|
||||
if (!oldImg || !link) return;
|
||||
|
||||
// Create new image
|
||||
const newImg = document.createElement('img');
|
||||
newImg.src = newPhoto.medium || newPhoto.thumb;
|
||||
newImg.alt = newPhoto.title || '';
|
||||
newImg.className = 'vh-fading-in';
|
||||
newImg.loading = 'lazy';
|
||||
|
||||
// Start fade out of old image
|
||||
oldImg.classList.add('vh-fading-out');
|
||||
|
||||
// Add new image
|
||||
link.appendChild(newImg);
|
||||
|
||||
// Update link href
|
||||
link.href = newPhoto.page_url || '#';
|
||||
|
||||
// Update title
|
||||
let titleEl = item.querySelector('.vh-photo-title');
|
||||
if (newPhoto.title) {
|
||||
if (titleEl) {
|
||||
titleEl.textContent = newPhoto.title;
|
||||
} else {
|
||||
titleEl = document.createElement('span');
|
||||
titleEl.className = 'vh-photo-title';
|
||||
titleEl.textContent = newPhoto.title;
|
||||
link.appendChild(titleEl);
|
||||
}
|
||||
} else if (titleEl) {
|
||||
titleEl.remove();
|
||||
}
|
||||
|
||||
// After animation, clean up
|
||||
setTimeout(() => {
|
||||
oldImg.remove();
|
||||
newImg.classList.remove('vh-fading-in');
|
||||
}, 800);
|
||||
|
||||
// Update displayed photos array
|
||||
this.displayedPhotos[index] = newPhoto;
|
||||
}
|
||||
|
||||
escapeHtml(text) {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize all mosaics on page
|
||||
function initMosaics() {
|
||||
document.querySelectorAll('.vh-flickr-mosaic').forEach(container => {
|
||||
new VHFlickrMosaic(container);
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize when DOM is ready
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initMosaics);
|
||||
} else {
|
||||
initMosaics();
|
||||
}
|
||||
|
||||
// Handle window resize
|
||||
let resizeTimeout;
|
||||
window.addEventListener('resize', () => {
|
||||
clearTimeout(resizeTimeout);
|
||||
resizeTimeout = setTimeout(() => {
|
||||
document.querySelectorAll('.vh-flickr-mosaic').forEach(container => {
|
||||
const mosaic = container._vhMosaic;
|
||||
if (mosaic) {
|
||||
mosaic.render();
|
||||
}
|
||||
});
|
||||
}, 250);
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: VH Flickr Mosaic
|
||||
* Plugin URI: https://github.com/vesnushka/vh-flickr-mosaic
|
||||
* Description: Beautiful photo mosaic widget with fade animations, powered by VH Posting System
|
||||
* Version: 1.0.0
|
||||
* Author: VH Posting System
|
||||
* License: GPL v2 or later
|
||||
* Text Domain: vh-flickr-mosaic
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class VH_Flickr_Mosaic {
|
||||
|
||||
private static $instance = null;
|
||||
private $options;
|
||||
|
||||
public static function get_instance() {
|
||||
if (null === self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
private function __construct() {
|
||||
$this->options = get_option('vh_flickr_mosaic_options', [
|
||||
'api_url' => '',
|
||||
'position' => 'footer',
|
||||
'rows' => 2,
|
||||
'photo_size' => 150,
|
||||
'animation_speed' => 5,
|
||||
'enabled' => true,
|
||||
]);
|
||||
|
||||
add_action('admin_menu', [$this, 'add_admin_menu']);
|
||||
add_action('admin_init', [$this, 'settings_init']);
|
||||
add_action('wp_enqueue_scripts', [$this, 'enqueue_scripts']);
|
||||
add_action('wp_footer', [$this, 'render_mosaic']);
|
||||
add_shortcode('flickr_mosaic', [$this, 'shortcode_mosaic']);
|
||||
}
|
||||
|
||||
public function add_admin_menu() {
|
||||
add_options_page(
|
||||
'VH Flickr Mosaic',
|
||||
'VH Flickr Mosaic',
|
||||
'manage_options',
|
||||
'vh-flickr-mosaic',
|
||||
[$this, 'options_page']
|
||||
);
|
||||
}
|
||||
|
||||
public function settings_init() {
|
||||
register_setting('vh_flickr_mosaic', 'vh_flickr_mosaic_options');
|
||||
|
||||
add_settings_section(
|
||||
'vh_flickr_mosaic_section',
|
||||
__('Настройки мозаики', 'vh-flickr-mosaic'),
|
||||
null,
|
||||
'vh-flickr-mosaic'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'api_url',
|
||||
__('API URL', 'vh-flickr-mosaic'),
|
||||
[$this, 'api_url_render'],
|
||||
'vh-flickr-mosaic',
|
||||
'vh_flickr_mosaic_section'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'enabled',
|
||||
__('Включить', 'vh-flickr-mosaic'),
|
||||
[$this, 'enabled_render'],
|
||||
'vh-flickr-mosaic',
|
||||
'vh_flickr_mosaic_section'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'position',
|
||||
__('Позиция', 'vh-flickr-mosaic'),
|
||||
[$this, 'position_render'],
|
||||
'vh-flickr-mosaic',
|
||||
'vh_flickr_mosaic_section'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'rows',
|
||||
__('Количество рядов', 'vh-flickr-mosaic'),
|
||||
[$this, 'rows_render'],
|
||||
'vh-flickr-mosaic',
|
||||
'vh_flickr_mosaic_section'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'photo_size',
|
||||
__('Размер фото (px)', 'vh-flickr-mosaic'),
|
||||
[$this, 'photo_size_render'],
|
||||
'vh-flickr-mosaic',
|
||||
'vh_flickr_mosaic_section'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'animation_speed',
|
||||
__('Скорость анимации (сек)', 'vh-flickr-mosaic'),
|
||||
[$this, 'animation_speed_render'],
|
||||
'vh-flickr-mosaic',
|
||||
'vh_flickr_mosaic_section'
|
||||
);
|
||||
}
|
||||
|
||||
public function api_url_render() {
|
||||
?>
|
||||
<input type='url' name='vh_flickr_mosaic_options[api_url]'
|
||||
value='<?php echo esc_attr($this->options['api_url'] ?? ''); ?>'
|
||||
class='regular-text' placeholder='https://your-site.com/vh/widget_api.php?action=get_photos'>
|
||||
<p class="description"><?php _e('URL API из VH Posting System (вкладка Виджет)', 'vh-flickr-mosaic'); ?></p>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function enabled_render() {
|
||||
?>
|
||||
<label>
|
||||
<input type='checkbox' name='vh_flickr_mosaic_options[enabled]'
|
||||
<?php checked($this->options['enabled'] ?? true); ?> value='1'>
|
||||
<?php _e('Показывать мозаику', 'vh-flickr-mosaic'); ?>
|
||||
</label>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function position_render() {
|
||||
?>
|
||||
<select name='vh_flickr_mosaic_options[position]'>
|
||||
<option value='footer' <?php selected($this->options['position'] ?? 'footer', 'footer'); ?>>
|
||||
<?php _e('В футере', 'vh-flickr-mosaic'); ?>
|
||||
</option>
|
||||
<option value='shortcode' <?php selected($this->options['position'] ?? 'footer', 'shortcode'); ?>>
|
||||
<?php _e('Только шорткод [flickr_mosaic]', 'vh-flickr-mosaic'); ?>
|
||||
</option>
|
||||
</select>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function rows_render() {
|
||||
?>
|
||||
<input type='number' name='vh_flickr_mosaic_options[rows]'
|
||||
value='<?php echo esc_attr($this->options['rows'] ?? 2); ?>'
|
||||
min='1' max='5' style='width: 60px;'>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function photo_size_render() {
|
||||
?>
|
||||
<input type='number' name='vh_flickr_mosaic_options[photo_size]'
|
||||
value='<?php echo esc_attr($this->options['photo_size'] ?? 150); ?>'
|
||||
min='80' max='300' style='width: 80px;'>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function animation_speed_render() {
|
||||
?>
|
||||
<input type='number' name='vh_flickr_mosaic_options[animation_speed]'
|
||||
value='<?php echo esc_attr($this->options['animation_speed'] ?? 5); ?>'
|
||||
min='2' max='15' step='0.5' style='width: 80px;'>
|
||||
<p class="description"><?php _e('Время между сменой фото', 'vh-flickr-mosaic'); ?></p>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function options_page() {
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php _e('VH Flickr Mosaic', 'vh-flickr-mosaic'); ?></h1>
|
||||
<form action='options.php' method='post'>
|
||||
<?php
|
||||
settings_fields('vh_flickr_mosaic');
|
||||
do_settings_sections('vh-flickr-mosaic');
|
||||
submit_button();
|
||||
?>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
<h2><?php _e('Использование', 'vh-flickr-mosaic'); ?></h2>
|
||||
<p><?php _e('Используйте шорткод для вставки мозаики в любое место:', 'vh-flickr-mosaic'); ?></p>
|
||||
<code>[flickr_mosaic]</code>
|
||||
<p><?php _e('С параметрами:', 'vh-flickr-mosaic'); ?></p>
|
||||
<code>[flickr_mosaic rows="3" size="120" speed="4"]</code>
|
||||
|
||||
<hr>
|
||||
<h2><?php _e('Предпросмотр', 'vh-flickr-mosaic'); ?></h2>
|
||||
<div id="vh-mosaic-preview">
|
||||
<button type="button" class="button" onclick="vhMosaicPreview()">
|
||||
<?php _e('Загрузить предпросмотр', 'vh-flickr-mosaic'); ?>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function vhMosaicPreview() {
|
||||
const apiUrl = document.querySelector('input[name="vh_flickr_mosaic_options[api_url]"]').value;
|
||||
if (!apiUrl) {
|
||||
alert('Укажите API URL');
|
||||
return;
|
||||
}
|
||||
|
||||
const preview = document.getElementById('vh-mosaic-preview');
|
||||
preview.innerHTML = '<p>Загрузка...</p>';
|
||||
|
||||
fetch(apiUrl)
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success && data.photos) {
|
||||
let html = '<div style="display:flex;flex-wrap:wrap;gap:8px;max-width:600px;">';
|
||||
data.photos.slice(0, 12).forEach(photo => {
|
||||
html += `<img src="${photo.thumb}" style="width:80px;height:80px;object-fit:cover;border-radius:4px;">`;
|
||||
});
|
||||
html += '</div>';
|
||||
html += `<p>Загружено ${data.photos.length} фото</p>`;
|
||||
preview.innerHTML = html;
|
||||
} else {
|
||||
preview.innerHTML = '<p style="color:red;">Ошибка: ' + (data.error || 'Неизвестная ошибка') + '</p>';
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
preview.innerHTML = '<p style="color:red;">Ошибка подключения: ' + err.message + '</p>';
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function enqueue_scripts() {
|
||||
if (empty($this->options['enabled']) || empty($this->options['api_url'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_style(
|
||||
'vh-flickr-mosaic',
|
||||
plugin_dir_url(__FILE__) . 'assets/css/mosaic.css',
|
||||
[],
|
||||
'1.0.0'
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'vh-flickr-mosaic',
|
||||
plugin_dir_url(__FILE__) . 'assets/js/mosaic.js',
|
||||
[],
|
||||
'1.0.0',
|
||||
true
|
||||
);
|
||||
|
||||
wp_localize_script('vh-flickr-mosaic', 'vhMosaicConfig', [
|
||||
'apiUrl' => $this->options['api_url'],
|
||||
'rows' => intval($this->options['rows'] ?? 2),
|
||||
'photoSize' => intval($this->options['photo_size'] ?? 150),
|
||||
'animationSpeed' => floatval($this->options['animation_speed'] ?? 5),
|
||||
]);
|
||||
}
|
||||
|
||||
public function render_mosaic() {
|
||||
if (empty($this->options['enabled']) || empty($this->options['api_url'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (($this->options['position'] ?? 'footer') !== 'footer') {
|
||||
return;
|
||||
}
|
||||
|
||||
echo $this->get_mosaic_html();
|
||||
}
|
||||
|
||||
public function shortcode_mosaic($atts) {
|
||||
if (empty($this->options['api_url'])) {
|
||||
return '<!-- VH Flickr Mosaic: API URL not configured -->';
|
||||
}
|
||||
|
||||
$atts = shortcode_atts([
|
||||
'rows' => $this->options['rows'] ?? 2,
|
||||
'size' => $this->options['photo_size'] ?? 150,
|
||||
'speed' => $this->options['animation_speed'] ?? 5,
|
||||
], $atts);
|
||||
|
||||
return $this->get_mosaic_html($atts);
|
||||
}
|
||||
|
||||
private function get_mosaic_html($atts = []) {
|
||||
$rows = intval($atts['rows'] ?? $this->options['rows'] ?? 2);
|
||||
$size = intval($atts['size'] ?? $this->options['photo_size'] ?? 150);
|
||||
$speed = floatval($atts['speed'] ?? $this->options['animation_speed'] ?? 5);
|
||||
|
||||
return sprintf(
|
||||
'<div class="vh-flickr-mosaic" data-rows="%d" data-size="%d" data-speed="%s">
|
||||
<div class="vh-mosaic-container"></div>
|
||||
</div>',
|
||||
$rows,
|
||||
$size,
|
||||
$speed
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize
|
||||
VH_Flickr_Mosaic::get_instance();
|
||||
Reference in New Issue
Block a user