Files

548 lines
21 KiB
PHP
Executable File

<?php
/**
* Funcionalidad para el manejo de emojis en el editor Summernote
*/
// Limpiar cualquier salida previa
while (ob_get_level() > 0) {
ob_end_clean();
}
// Establecer el tipo de contenido como JavaScript
header('Content-Type: application/javascript; charset=utf-8');
// Evitar caché
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
// Iniciar sesión si no está iniciada
if (session_status() === PHP_SESSION_NONE) {
session_start(['read_and_close' => true]);
}
// Inicializar array de emojis personalizados si no existe
if (!isset($_SESSION['custom_emojis'])) {
$_SESSION['custom_emojis'] = [];
}
// Si es una petición POST para agregar un emoji personalizado
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['emoji'])) {
$emoji = trim($_POST['emoji']);
if (!empty($emoji) && !in_array($emoji, $_SESSION['custom_emojis'] ?? [])) {
array_unshift($_SESSION['custom_emojis'], $emoji);
$_SESSION['custom_emojis'] = array_slice($_SESSION['custom_emojis'], 0, 50);
echo json_encode(['success' => true, 'message' => 'Emoji guardado correctamente']);
} else {
echo json_encode(['success' => false, 'message' => 'No se pudo guardar el emoji']);
}
exit;
}
// Si llegamos aquí, es una petición GET para cargar los emojis
// Generamos el código JavaScript directamente
echo "// Asegurarse de que la función no se defina múltiples veces\n";
echo "if (typeof window.setupEmojiHandlers === 'undefined') {\n";
echo " // Función para manejar los eventos de los emojis\n";
echo " window.setupEmojiHandlers = function() {\n";
echo " console.log('Inicializando manejadores de emojis...');\n\n";
echo " // Función para manejar clics en emojis\n";
echo " function handleEmojiClick(e) {\n";
echo " const emoji = e.target.closest('.emoji-item');\n";
echo " if (!emoji) return;\n\n";
echo " e.preventDefault();\n";
echo " e.stopPropagation();\n\n";
echo " const emojiChar = emoji.getAttribute('data-emoji');\n";
echo " if (!emojiChar) return;\n\n";
echo " console.log('Emoji seleccionado:', emojiChar);\n\n";
echo " // Intentar encontrar el editor en diferentes contextos\n";
echo " const contexts = [window, window.parent, window.opener, window.top];\n";
echo " let emojiInserted = false;\n\n";
echo " for (const ctx of contexts) {\n";
echo " try {\n";
echo " if (ctx && ctx.$ && ctx.$('#messageContent').length > 0) {\n";
echo " ctx.$('#messageContent').summernote('editor.saveRange');\n";
echo " ctx.$('#messageContent').summernote('editor.restoreRange');\n";
echo " ctx.$('#messageContent').summernote('editor.focus');\n";
echo " ctx.$('#messageContent').summernote('editor.insertText', emojiChar);\n";
echo " emojiInserted = true;\n";
echo " break;\n";
echo " }\n";
echo " } catch (e) {\n";
echo " console.error('Error al insertar emoji en contexto:', e);\n";
echo " }\n";
echo " }\n\n";
echo " if (!emojiInserted) {\n";
echo " console.warn('No se pudo insertar el emoji: No se encontró el editor Summernote');\n";
echo " alert('No se pudo insertar el emoji. Asegúrate de que el editor esté disponible.');\n";
echo " }\n\n";
echo " // Cerrar el modal después de seleccionar un emoji\n";
echo " $('#emojiModal').modal('hide');\n";
echo " }\n\n";
echo " // Función para manejar clics en pestañas\n";
echo " function handleTabClick(e) {\n";
echo " const tab = e.target.closest('.emoji-tab');\n";
echo " if (!tab) return;\n\n";
echo " e.preventDefault();\n";
echo " e.stopPropagation();\n\n";
echo " const category = tab.getAttribute('data-category');\n";
echo " if (!category) return;\n\n";
echo " console.log('Cambiando a categoría:', category);\n\n";
echo " // Actualizar pestaña activa\n";
echo " document.querySelectorAll('.emoji-tab').forEach(function(t) {\n";
echo " t.classList.remove('btn-primary');\n";
echo " t.classList.add('btn-outline-secondary');\n";
echo " });\n\n";
echo " tab.classList.remove('btn-outline-secondary');\n";
echo " tab.classList.add('btn-primary');\n\n";
echo " // Mostrar la categoría seleccionada\n";
echo " document.querySelectorAll('.emoji-category').forEach(function(cat) {\n";
echo " cat.classList.add('d-none');\n";
echo " });\n\n";
echo " const targetCategory = document.getElementById('emoji-' + category);\n";
echo " if (targetCategory) {\n";
echo " targetCategory.classList.remove('d-none');\n";
echo " }\n";
echo " }\n\n";
echo " // Eliminar manejadores anteriores para evitar duplicados\n";
echo " document.removeEventListener('click', handleEmojiClick);\n";
echo " document.removeEventListener('click', handleTabClick);\n\n";
echo " // Agregar nuevos manejadores\n";
echo " document.addEventListener('click', handleEmojiClick);\n";
echo " document.addEventListener('click', handleTabClick);\n\n";
echo " // Activar la primera pestaña por defecto si no hay ninguna activa\n";
echo " const activeTab = document.querySelector('.emoji-tab.btn-primary');\n";
echo " if (!activeTab) {\n";
echo " const firstTab = document.querySelector('.emoji-tab');\n";
echo " if (firstTab) {\n";
echo " firstTab.click();\n";
echo " }\n";
echo " }\n";
echo " }; // Cierre de la función setupEmojiHandlers\n";
echo "} // Cierre del if que verifica si la función ya está definida\n\n";
// Lista de emojis organizados por categorías
$emojis = [
'caritas' => ['😀', '😃', '😄', '😁', '😆', '😅', '😂', '🤣', '😊', '😇', '🙂', '🙃', '😉', '😌', '😍', '🥰', '😘', '😗', '😙', '😚', '😋', '😛', '😝', '😜', '🤪', '🤨', '🧐', '🤓', '😎', '🤩'],
'manos' => ['👋', '🤚', '🖐️', '✋', '🖖', '👌', '🤏', '✌️', '🤞', '🤟', '🤘', '🤙', '👈', '👉', '👆', '🖕', '👇', '☝️', '👍', '👎', '✊', '👊', '🤛', '🤜', '👏', '🙌', '🤲', '🤝', '🙏'],
'simbolos' => ['❤️', '🧡', '💛', '💚', '💙', '💜', '🖤', '🤍', '🤎', '💔', '❣️', '💕', '💞', '💓', '💗', '💖', '💘', '💝', '💟', '☮️', '✝️', '☪️', '🕉️', '☸️', '✡️', '🔯', '🕎', '☯️', '☦️', '🛐'],
'objetos' => ['📱', '📲', '💻', '⌨️', '🖥️', '🖨️', '🖱️', '🖲️', '🕹️', '⌚', '📷', '📸', '📹', '🎥', '📽️', '🎞️', '📞', '☎️', '📟', '📠', '📺', '📻', '🎙️', '🎚️', '🎛️', '🧭', '⏱️', '⏲️', '⏰', '🕰️'],
'naturaleza' => ['🐵', '🐒', '🦍', '🦧', '🐶', '🐕', '🦮', '🐕‍🦺', '🐩', '🐺', '🦊', '🦝', '🐱', '🐈', '🦁', '🐯', '🐅', '🐆', '🐴', '🐎', '🦄', '🦓', '🦌', '🐮', '🐂', '🐃', '🐄', '🐷', '🐖', '🐗']
];
// Agregar emojis personalizados si existen
if (!empty($_SESSION['custom_emojis'])) {
$emojis['personalizados'] = $_SESSION['custom_emojis'];
} else {
$emojis['personalizados'] = [];
}
// Nombres de categorías más amigables
$categoryNames = [
'caritas' => 'Caritas',
'manos' => 'Manos',
'simbolos' => 'Símbolos',
'objetos' => 'Objetos',
'naturaleza' => 'Naturaleza',
'personalizados' => 'Mis Emojis'
];
// Manejar la adición de un nuevo emoji personalizado
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['emoji'])) {
// Limpiar el buffer de salida
while (ob_get_level() > 0) {
ob_end_clean();
}
// Establecer el tipo de contenido como JSON
header('Content-Type: application/json');
// Validar y limpiar el emoji
$emoji = trim($_POST['emoji']);
// Validar que el emoji no esté vacío
if (empty($emoji)) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'El emoji no puede estar vacío']);
exit;
}
// Iniciar la sesión si no está iniciada
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
// Inicializar el array de emojis personalizados si no existe
if (!isset($_SESSION['custom_emojis'])) {
$_SESSION['custom_emojis'] = [];
}
// Verificar si el emoji ya existe
if (!in_array($emoji, $_SESSION['custom_emojis'])) {
// Agregar el nuevo emoji al inicio del array
array_unshift($_SESSION['custom_emojis'], $emoji);
// Mantener solo los últimos 50 emojis
$_SESSION['custom_emojis'] = array_slice($_SESSION['custom_emojis'], 0, 50);
// Devolver éxito
echo json_encode([
'success' => true,
'message' => 'Emoji guardado correctamente',
'emoji' => $emoji
]);
} else {
// El emoji ya existe
echo json_encode([
'success' => false,
'message' => 'Este emoji ya existe en tu colección'
]);
}
// Terminar la ejecución
exit;
}
?>
<div class="container-fluid p-0">
<!-- Campo para emoji personalizado -->
<div class="p-3 border-bottom">
<div class="input-group mb-2">
<input type="text" id="customEmojiInput" class="form-control" placeholder="Pega o escribe un emoji aquí">
<button class="btn btn-primary" id="addCustomEmoji" type="button">
<i class="bi bi-plus-lg"></i> Agregar
</button>
</div>
<small class="text-muted">Puedes pegar cualquier emoji o carácter especial</small>
</div>
<!-- Pestañas de categorías -->
<div class="emoji-tabs d-flex flex-wrap border-bottom px-3 pt-2">
<?php $first = true; ?>
<?php foreach (array_keys($emojis) as $category): ?>
<button type="button"
class="emoji-tab btn btn-sm me-1 mb-1 <?php echo $first ? 'btn-primary' : 'btn-outline-secondary'; ?>"
data-category="<?php echo $category; ?>">
<?php echo $categoryNames[$category] ?? ucfirst($category); ?>
</button>
<?php $first = false; ?>
<?php endforeach; ?>
</div>
<!-- Contenido de emojis por categoría -->
<div class="emoji-categories">
<?php $first = true; ?>
<?php foreach ($emojis as $category => $emojiList): ?>
<div class="emoji-category <?php echo $first ? 'd-block' : 'd-none'; ?>" id="emoji-<?php echo $category; ?>">
<div class="d-flex flex-wrap">
<?php
foreach ($emojiList as $emoji):
// Determinar si es un emoji largo (más de 2 caracteres)
$isLongEmoji = mb_strlen($emoji) > 2;
$emojiClass = $isLongEmoji ? 'long-emoji' : '';
?>
<span class="emoji-option d-flex align-items-center justify-content-center m-1 <?php echo $emojiClass; ?>"
data-emoji="<?php echo htmlspecialchars($emoji); ?>"
title="<?php echo htmlspecialchars($emoji); ?>">
<?php echo $emoji; ?>
</span>
<?php endforeach; ?>
</div>
</div>
<?php $first = false; ?>
<?php endforeach; ?>
</div>
</div>
<style>
#customEmojiInput {
font-size: 1.2em;
height: 45px;
width: 100%;
box-sizing: border-box;
}
.emoji-option {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 40px;
max-width: 100%;
height: 40px;
font-size: 20px;
line-height: 1.2;
cursor: pointer;
border-radius: 8px;
margin: 4px;
padding: 4px;
transition: all 0.2s;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-break: break-all;
background-color: #ffffff;
border: 1px solid #e0e0e0;
box-sizing: border-box;
text-align: center;
}
.emoji-option:hover {
background-color: #f0f0f0;
transform: scale(1.1);
z-index: 10;
position: relative;
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}
/* Estilo para el contenedor de emojis */
.emoji-categories {
max-height: 300px;
overflow-y: auto;
padding: 8px;
}
/* Ajustes para emojis largos */
.emoji-option.long-emoji {
font-size: 16px;
padding: 2px;
white-space: normal;
line-height: 1.1;
word-break: break-word;
overflow-wrap: break-word;
display: inline-flex;
align-items: center;
justify-content: center;
}
</style>
<script>
// Manejar el botón de agregar emoji personalizado
document.getElementById('addCustomEmoji').addEventListener('click', async function() {
const emojiInput = document.getElementById('customEmojiInput');
const emoji = emojiInput.value.trim();
const button = this; // Mover la declaración de button al inicio
let originalText = button.innerHTML; // Usar let en lugar de const
if (emoji) {
try {
// Mostrar indicador de carga
button.disabled = true;
button.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Guardando...';
// Guardar el emoji en la sesión
const response = await fetch('includes/emojis.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'emoji=' + encodeURIComponent(emoji),
credentials: 'same-origin' // Asegurar que se envíen las cookies de sesión
});
const result = await response.json();
if (result.success) {
// Insertar el emoji
if (window.parent && window.parent.insertEmoji) {
window.parent.insertEmoji(emoji + ' ');
// Recargar solo los emojis para actualizar la lista
const emojiContainer = document.querySelector('.emoji-categories');
if (emojiContainer) {
document.addEventListener('DOMContentLoaded', function() {
// Inicializar manejadores
initEmojiHandlers();
// Enfocar el campo de entrada
const emojiInput = document.getElementById('customEmojiInput');
if (emojiInput) {
emojiInput.focus();
}
});
// Inicializar manejadores de eventos
function initEmojiHandlers() {
// Manejador para agregar emojis personalizados
const addButton = document.getElementById('addCustomEmoji');
const emojiInput = document.getElementById('customEmojiInput');
if (addButton && emojiInput) {
// Eliminar manejadores anteriores para evitar duplicados
addButton.replaceWith(addButton.cloneNode(true));
emojiInput.replaceWith(emojiInput.cloneNode(true));
// Manejador para el botón de agregar
document.getElementById('addCustomEmoji').addEventListener('click', handleAddEmoji);
// Manejador para la tecla Enter
document.getElementById('customEmojiInput').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
handleAddEmoji();
}
});
}
// Inicializar manejadores de emojis y pestañas
setupEmojiHandlers();
}
// Manejar la adición de un nuevo emoji
async function handleAddEmoji() {
const emojiInput = document.getElementById('customEmojiInput');
const button = document.getElementById('addCustomEmoji');
const emoji = emojiInput.value.trim();
if (!emoji) {
showAlert('Por favor, ingresa un emoji', 'warning');
return;
}
// Deshabilitar el botón y mostrar indicador de carga
const originalText = button.innerHTML;
button.disabled = true;
button.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Guardando...';
try {
// Usar una ruta relativa desde la ubicación actual
const response = await fetch(window.location.pathname, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'emoji=' + encodeURIComponent(emoji)
});
if (!response.ok) {
throw new Error(`Error HTTP: ${response.status}`);
foreach ($items as $emoji) {
$emojiHtml = htmlspecialchars($emoji);
$html .= "<button type=\"button\" class=\"btn btn-outline-secondary btn-sm emoji-item\" data-emoji=\"{$emojiHtml}\">{$emojiHtml}</button>";
}
$html .= '</div><hr class="my-3"></div>';
}
}
$html .= '</div>';
// Formulario para agregar emojis personalizados
$html .= '<div class="p-3 border-top">';
$html .= '<form id="addCustomEmojiForm" class="d-flex gap-2">';
$html .= '<input type="text" id="customEmojiInput" class="form-control form-control-sm" placeholder="Pega un emoji aquí..." required>';
$html .= '<button type="submit" class="btn btn-primary btn-sm">Agregar</button>';
$html .= '</form></div></div>';
// Devolver el HTML como una cadena de JavaScript
$js = "
document.getElementById('emojiContainer').innerHTML = " . json_encode($html) . ";
";
// Agregar el código JavaScript
$js .= "
// Asegurarse de que la función no se defina múltiples veces
if (typeof window.setupEmojiHandlers === 'undefined') {
// Función para manejar los eventos de los emojis
window.setupEmojiHandlers = function() {
console.log('Inicializando manejadores de emojis...');
// Función para manejar clics en emojis
function handleEmojiClick(e) {
const emoji = e.target.closest('.emoji-item');
if (!emoji) return;
e.preventDefault();
e.stopPropagation();
const emojiChar = emoji.getAttribute('data-emoji');
if (!emojiChar) return;
console.log('Emoji seleccionado:', emojiChar);
// Intentar encontrar el editor en diferentes contextos
const contexts = [window, window.parent, window.opener, window.top];
let emojiInserted = false;
for (const ctx of contexts) {
try {
if (ctx && ctx.$ && ctx.$('#messageContent').length > 0) {
ctx.$('#messageContent').summernote('editor.saveRange');
ctx.$('#messageContent').summernote('editor.restoreRange');
ctx.$('#messageContent').summernote('editor.focus');
ctx.$('#messageContent').summernote('editor.insertText', emojiChar);
emojiInserted = true;
break;
}
} catch (e) {
console.error('Error al insertar emoji en contexto:', e);
}
}
if (!emojiInserted) {
console.warn('No se pudo insertar el emoji: No se encontró el editor Summernote');
alert('No se pudo insertar el emoji. Asegúrate de que el editor esté disponible.');
}
// Cerrar el modal después de seleccionar un emoji
$('#emojiModal').modal('hide');
}
// Función para manejar clics en pestañas
function handleTabClick(e) {
const tab = e.target.closest('.emoji-tab');
if (!tab) return;
e.preventDefault();
e.stopPropagation();
const category = tab.getAttribute('data-category');
if (!category) return;
console.log('Cambiando a categoría:', category);
// Actualizar pestaña activa
document.querySelectorAll('.emoji-tab').forEach(function(t) {
t.classList.remove('btn-primary');
t.classList.add('btn-outline-secondary');
});
tab.classList.remove('btn-outline-secondary');
tab.classList.add('btn-primary');
// Mostrar la categoría seleccionada
document.querySelectorAll('.emoji-category').forEach(function(cat) {
cat.classList.add('d-none');
});
const targetCategory = document.getElementById('emoji-' + category);
if (targetCategory) {
targetCategory.classList.remove('d-none');
}
}
// Eliminar manejadores anteriores para evitar duplicados
document.removeEventListener('click', handleEmojiClick);
document.removeEventListener('click', handleTabClick);
// Agregar nuevos manejadores
document.addEventListener('click', handleEmojiClick);
document.addEventListener('click', handleTabClick);
// Activar la primera pestaña por defecto si no hay ninguna activa
const activeTab = document.querySelector('.emoji-tab.btn-primary');
if (!activeTab) {
const firstTab = document.querySelector('.emoji-tab');
if (firstTab) {
firstTab.click();
}
}
};
}
// Inicializar los manejadores de eventos
if (typeof setupEmojiHandlers === 'function') {
setupEmojiHandlers();
}";
// Devolver el código JavaScript
echo $js;