Spaces:
Running
Running
const inputText = document.getElementById('input-text'); | |
const bubbleContainer = document.getElementById('bubble-container'); | |
const replaceSpacesButton = document.getElementById('replace-spaces-button'); | |
const replaceUnderscoreButton = document.getElementById('replace-underscore-button'); | |
const revertUnderscoreButton = document.getElementById('revert-underscore-button'); | |
const replaceLineBreaksButton = document.getElementById('replace-linebreaks-button'); | |
const replaceCommasButton = document.getElementById('replace-commas-button'); | |
const removeDuplicatesButton = document.getElementById('remove-duplicates-button'); | |
const revertSpacesButton = document.getElementById('revert-spaces-button'); | |
const copyButton = document.getElementById('copy-button'); | |
const undoButton = document.getElementById('undo-button'); | |
const redoButton = document.getElementById('redo-button'); | |
const deleteModeButton = document.getElementById('delete-mode-button'); | |
const emphasisModeButton = document.getElementById('emphasis-mode-button'); | |
const mitigateModeButton = document.getElementById('mitigate-mode-button'); | |
const literalParenthesisButton = document.getElementById('literal-parenthesis-button'); | |
const fictionalParenthesisButton = document.getElementById('fictional-parenthesis-button'); | |
const bubbleColors = {}; | |
let history = []; | |
let historyIndex = -1; | |
let deleteModeEnabled = false; | |
let emphasisModeEnabled = false; | |
let mitigateModeEnabled = false; | |
inputText.addEventListener('input', handleTextChange); | |
replaceSpacesButton.addEventListener('click', replaceSpaces); | |
replaceUnderscoreButton.addEventListener('click', replaceUnderscores); | |
revertUnderscoreButton.addEventListener('click', revertUnderscores); | |
replaceLineBreaksButton.addEventListener('click', replaceLineBreaks); | |
replaceCommasButton.addEventListener('click', replaceCommas); | |
removeDuplicatesButton.addEventListener('click', removeDuplicates); | |
revertSpacesButton.addEventListener('click', revertSpaces); | |
copyButton.addEventListener('click', copyToClipboard); | |
undoButton.addEventListener('click', undoChanges); | |
redoButton.addEventListener('click', redoChanges); | |
deleteModeButton.addEventListener('click', toggleDeleteMode); | |
emphasisModeButton.addEventListener('click', toggleEmphasisMode); | |
mitigateModeButton.addEventListener('click', toggleMitigateMode); | |
literalParenthesisButton.addEventListener('click', literalParenthesis); | |
fictionalParenthesisButton.addEventListener('click', fictionalParenthesis); | |
const sortable = new Sortable(bubbleContainer, { | |
animation: 250, | |
ghostClass: 'ghost', | |
onEnd: handleBubbleChange, | |
disabled: deleteModeEnabled || emphasisModeEnabled || mitigateModeEnabled | |
}); | |
function handleTextChange() { | |
const text = inputText.value; | |
if (history.length === 0) { | |
history.push(''); | |
historyIndex++; | |
} | |
if (text !== history[historyIndex]) { | |
if (historyIndex < history.length - 1) { | |
history.splice(historyIndex + 1); | |
} | |
history.push(text); | |
historyIndex++; | |
updateBubbles(); | |
updateButtonStates(); | |
} | |
} | |
function handleBubbleChange() { | |
const conceptList = Array.from(bubbleContainer.getElementsByClassName('bubble')).map(bubble => bubble.textContent.trim()); | |
inputText.value = conceptList.join(', '); | |
handleTextChange(); | |
} | |
function updateBubbles() { | |
bubbleContainer.innerHTML = ''; | |
const text = inputText.value.trim(); | |
if (text === '') return; | |
const concepts = text.split(', '); | |
concepts.forEach(concept => { | |
const bubble = createBubble(concept); | |
bubbleContainer.appendChild(bubble); | |
}); | |
} | |
function createBubble(text) { | |
const bubble = document.createElement('div'); | |
bubble.classList.add('bubble'); | |
if (!bubbleColors.hasOwnProperty(text)) { | |
bubbleColors[text] = getRandomColor(); | |
} | |
bubble.style.backgroundColor = bubbleColors[text]; | |
const bubbleText = document.createElement('span'); | |
bubbleText.classList.add('bubble-text'); | |
bubbleText.innerText = text; | |
bubble.appendChild(bubbleText); | |
if (deleteModeEnabled) { | |
bubble.classList.add('delete-mode'); | |
bubble.addEventListener('click', deleteBubble); | |
} | |
if (emphasisModeEnabled) { | |
bubble.classList.add('emphasis-mode'); | |
bubble.addEventListener('click', emphasizeBubble); | |
} | |
if (mitigateModeEnabled) { | |
bubble.classList.add('mitigate-mode'); | |
bubble.addEventListener('click', mitigateBubble); | |
} | |
return bubble; | |
} | |
function getRandomColor() { | |
const h = Math.floor(Math.random() * 360); | |
const s = Math.floor(Math.random() * 30) + 50; | |
const l = Math.floor(Math.random() * 40) + 30; | |
return `hsl(${h}, ${s}%, ${l}%)`; | |
} | |
function updateButtonStates() { | |
undoButton.disabled = historyIndex === 0; | |
redoButton.disabled = historyIndex === history.length - 1; | |
} | |
function replaceSpaces() { | |
const text = inputText.value; | |
const replacedText = text.replace(/ /g, ', '); | |
inputText.value = replacedText; | |
handleTextChange(); | |
} | |
function revertSpaces() { | |
const text = inputText.value; | |
const replacedText = text.replace(/, /g, ' '); | |
inputText.value = replacedText; | |
handleTextChange(); | |
} | |
function replaceUnderscores() { | |
const text = inputText.value; | |
const replacedText = text.replace(/_/g, ' '); | |
inputText.value = replacedText; | |
handleTextChange(); | |
} | |
function revertUnderscores() { | |
const text = inputText.value; | |
const replacedText = text.replace(/([^,]) /g, '$1_'); | |
inputText.value = replacedText; | |
handleTextChange(); | |
} | |
function replaceLineBreaks() { | |
const text = inputText.value; | |
const replacedText = text.replace(/\n/g, ', '); | |
inputText.value = replacedText; | |
handleTextChange(); | |
} | |
function replaceCommas() { | |
const text = inputText.value; | |
const step1 = text.replace(/,,/g, ','); | |
const step2 = step1.replace(/, ,/g, ', '); | |
const step3 = step2.trimRight(); | |
const step4 = step3.replace(/,$/, ''); | |
const step5 = step4.replace(/^,/, ''); | |
const step6 = step5.replace(/, /g, ', '); | |
const replacedText = step6.replace(/^ /, ''); | |
inputText.value = replacedText; | |
handleTextChange(); | |
} | |
function removeDuplicates() { | |
const text = inputText.value; | |
const concepts = text.split(', '); | |
const uniqueConcepts = [...new Set(concepts)]; | |
inputText.value = uniqueConcepts.join(', '); | |
handleTextChange(); | |
} | |
function copyToClipboard() { | |
inputText.select(); | |
inputText.setSelectionRange(0, 99999); | |
document.execCommand('copy'); | |
} | |
function literalParenthesis() { | |
const inputText = document.getElementById('input-text'); | |
const text = inputText.value; | |
// Reemplazar ' (' que no estén precedidos por una ',' y el paréntesis de cierre siguiente más cercano | |
let replacedText = text.replace(/([^,]) \((.*?)\)/g, '$1 /($2/)'); | |
// Reemplazar '_(' y el paréntesis de cierre siguiente más cercano | |
replacedText = replacedText.replace(/_\((.*?)\)/g, '_/($1/)'); | |
inputText.value = replacedText; | |
handleTextChange(); | |
} | |
function fictionalParenthesis() { | |
const inputText = document.getElementById('input-text'); | |
const text = inputText.value; | |
// Reemplazar '/(' por '(' | |
let replacedText = text.replace(/\/\(/g, '('); | |
// Reemplazar '/)' por ')' | |
replacedText = replacedText.replace(/\/\)/g, ')'); | |
inputText.value = replacedText; | |
handleTextChange(); | |
} | |
document.getElementById('download-text-file-button').addEventListener('click', showFilenameInput); | |
function showFilenameInput() { | |
const inputText = document.getElementById('input-text').value; | |
const currentDate = new Date(); | |
const year = currentDate.getFullYear(); | |
const month = String(currentDate.getMonth() + 1).padStart(2, '0'); | |
const day = String(currentDate.getDate()).padStart(2, '0'); | |
const hours = String(currentDate.getHours()).padStart(2, '0'); | |
const minutes = String(currentDate.getMinutes()).padStart(2, '0'); | |
const formattedDate = `${year}-${month}-${day}_${hours}-${minutes}`; | |
const defaultFileName = `Bubble Prompter_${formattedDate}.txt`; | |
let container = document.getElementById('custom-filename-container'); | |
if (!container) { | |
container = document.createElement('div'); | |
container.id = 'custom-filename-container'; | |
document.body.appendChild(container); | |
const input = document.createElement('input'); | |
input.type = 'text'; | |
input.id = 'custom-filename'; | |
container.appendChild(input); | |
const confirmButton = document.createElement('button'); | |
confirmButton.innerText = '✅'; | |
confirmButton.classList.add('confirm-button'); // Agregar clase | |
confirmButton.addEventListener('click', downloadTextFile); | |
container.appendChild(confirmButton); | |
const cancelButton = document.createElement('button'); | |
cancelButton.innerText = '❌'; | |
cancelButton.classList.add('cancel-button'); // Agregar clase | |
cancelButton.addEventListener('click', hideFilenameInput); | |
container.appendChild(cancelButton); | |
document.addEventListener('click', function(event) { | |
if (!container.contains(event.target) && event.target !== document.getElementById('download-text-file-button')) { | |
hideFilenameInput(); | |
} | |
}); | |
input.addEventListener('keydown', function(event) { | |
if (event.key === 'Enter') { | |
downloadTextFile(); | |
} | |
}); | |
} | |
container.style.display = 'block'; | |
container.style.top = `${document.getElementById('download-text-file-button').offsetTop + document.getElementById('download-text-file-button').offsetHeight}px`; | |
container.style.left = `${document.getElementById('download-text-file-button').offsetLeft}px`; | |
const input = document.getElementById('custom-filename'); | |
input.value = defaultFileName; | |
input.select(); | |
input.focus(); | |
} | |
function hideFilenameInput() { | |
const container = document.getElementById('custom-filename-container'); | |
if (container) { | |
container.style.display = 'none'; | |
} | |
} | |
function downloadTextFile() { | |
const inputText = document.getElementById('input-text').value; | |
let customFilename = document.getElementById('custom-filename').value.trim(); | |
// Añadir .txt si no está presente | |
if (!customFilename.endsWith('.txt')) { | |
customFilename += '.txt'; | |
} | |
const fileName = customFilename ? customFilename : 'Bubble Prompter.txt'; | |
const blob = new Blob([inputText], { type: 'text/plain' }); | |
const link = document.createElement('a'); | |
link.href = URL.createObjectURL(blob); | |
link.download = fileName; | |
document.body.appendChild(link); | |
link.click(); | |
document.body.removeChild(link); | |
hideFilenameInput(); | |
} | |
document.getElementById('load-text-file-button').addEventListener('click', loadTextFile); | |
function loadTextFile() { | |
const fileInput = document.createElement('input'); | |
fileInput.type = 'file'; | |
fileInput.accept = '.txt'; | |
fileInput.addEventListener('change', (event) => { | |
const file = event.target.files[0]; | |
if (file) { | |
const reader = new FileReader(); | |
reader.onload = (e) => { | |
const inputText = document.getElementById('input-text'); | |
let currentText = inputText.value; | |
// Añadir una coma y un espacio si el campo de texto no está vacío | |
if (currentText) { | |
currentText += ', '; | |
} | |
// Añadir el contenido del archivo | |
inputText.value = currentText + e.target.result; | |
handleTextChange(); | |
}; | |
reader.readAsText(file); | |
} | |
}); | |
// Simular un clic en el input de archivo para abrir el cuadro de diálogo de archivo | |
fileInput.click(); | |
} | |
document.addEventListener('DOMContentLoaded', function() { | |
const inputText = document.getElementById('input-text'); | |
// Evitar comportamiento por defecto de arrastrar y soltar | |
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { | |
inputText.addEventListener(eventName, preventDefaults, false); | |
document.body.addEventListener(eventName, preventDefaults, false); | |
}); | |
// Añadir clases para los estilos de arrastrar y soltar | |
['dragenter', 'dragover'].forEach(eventName => { | |
inputText.addEventListener(eventName, () => inputText.classList.add('highlight'), false); | |
}); | |
['dragleave', 'drop'].forEach(eventName => { | |
inputText.addEventListener(eventName, () => inputText.classList.remove('highlight'), false); | |
}); | |
// Manejar el evento de soltar | |
inputText.addEventListener('drop', handleDrop, false); | |
function preventDefaults(e) { | |
e.preventDefault(); | |
e.stopPropagation(); | |
} | |
function handleDrop(e) { | |
const dt = e.dataTransfer; | |
const files = dt.files; | |
if (files.length) { | |
const file = files[0]; | |
if (file.type === "text/plain") { | |
const reader = new FileReader(); | |
reader.onload = (e) => { | |
let currentText = inputText.value; | |
// Añadir una coma y un espacio si el campo de texto no está vacío | |
if (currentText) { | |
currentText += ', '; | |
} | |
// Añadir el contenido del archivo | |
inputText.value = currentText + e.target.result; | |
handleTextChange(); | |
}; | |
reader.readAsText(file); | |
} else { | |
alert("Please drop a valid .txt file."); | |
} | |
} | |
} | |
}); | |
function undoChanges() { | |
if (historyIndex > 0) { | |
historyIndex--; | |
inputText.value = history[historyIndex]; | |
updateBubbles(); | |
updateButtonStates(); | |
} | |
} | |
function redoChanges() { | |
if (historyIndex < history.length - 1) { | |
historyIndex++; | |
inputText.value = history[historyIndex]; | |
updateBubbles(); | |
updateButtonStates(); | |
} | |
} | |
function toggleDeleteMode() { | |
deleteModeEnabled = !deleteModeEnabled; | |
deleteModeButton.classList.toggle('active'); | |
if (deleteModeEnabled) { | |
emphasisModeEnabled = false; | |
emphasisModeButton.classList.remove('active'); | |
mitigateModeEnabled = false; | |
mitigateModeButton.classList.remove('active'); | |
} | |
sortable.option('disabled', deleteModeEnabled); | |
bubbleContainer.classList.toggle('delete-mode-container'); | |
const bubbles = bubbleContainer.getElementsByClassName('bubble'); | |
for (let i = 0; i < bubbles.length; i++) { | |
const bubble = bubbles[i]; | |
bubble.classList.remove('emphasis-mode'); | |
bubble.classList.remove('mitigate-mode'); | |
if (deleteModeEnabled) { | |
bubble.classList.add('delete-mode'); | |
bubble.removeEventListener('click', emphasizeBubble); | |
bubble.removeEventListener('click', mitigateBubble); | |
bubble.addEventListener('click', deleteBubble); | |
} else { | |
bubble.classList.remove('delete-mode'); | |
bubble.removeEventListener('click', deleteBubble); | |
} | |
} | |
} | |
function toggleEmphasisMode() { | |
emphasisModeEnabled = !emphasisModeEnabled; | |
emphasisModeButton.classList.toggle('active'); | |
if (emphasisModeEnabled) { | |
deleteModeEnabled = false; | |
deleteModeButton.classList.remove('active'); | |
mitigateModeEnabled = false; | |
mitigateModeButton.classList.remove('active'); | |
} | |
sortable.option('disabled', emphasisModeEnabled); | |
bubbleContainer.classList.toggle('emphasis-mode-container'); | |
const bubbles = bubbleContainer.getElementsByClassName('bubble'); | |
for (let i = 0; i < bubbles.length; i++) { | |
const bubble = bubbles[i]; | |
bubble.classList.remove('delete-mode'); | |
bubble.classList.remove('mitigate-mode'); | |
if (emphasisModeEnabled) { | |
bubble.classList.add('emphasis-mode'); | |
bubble.removeEventListener('click', deleteBubble); | |
bubble.removeEventListener('click', mitigateBubble); | |
bubble.addEventListener('click', emphasizeBubble); | |
} else { | |
bubble.classList.remove('emphasis-mode'); | |
bubble.removeEventListener('click', emphasizeBubble); | |
} | |
} | |
} | |
function toggleMitigateMode() { | |
mitigateModeEnabled = !mitigateModeEnabled; | |
mitigateModeButton.classList.toggle('active'); | |
if (mitigateModeEnabled) { | |
deleteModeEnabled = false; | |
deleteModeButton.classList.remove('active'); | |
emphasisModeEnabled = false; | |
emphasisModeButton.classList.remove('active'); | |
} | |
sortable.option('disabled', mitigateModeEnabled); | |
bubbleContainer.classList.toggle('mitigate-mode-container'); | |
const bubbles = bubbleContainer.getElementsByClassName('bubble'); | |
for (let i = 0; i < bubbles.length; i++) { | |
const bubble = bubbles[i]; | |
bubble.classList.remove('delete-mode'); | |
bubble.classList.remove('emphasis-mode'); | |
if (mitigateModeEnabled) { | |
bubble.classList.add('mitigate-mode'); | |
bubble.removeEventListener('click', deleteBubble); | |
bubble.removeEventListener('click', emphasizeBubble); | |
bubble.addEventListener('click', mitigateBubble); | |
} else { | |
bubble.classList.remove('mitigate-mode'); | |
bubble.removeEventListener('click', mitigateBubble); | |
} | |
} | |
} | |
function deleteBubble(event) { | |
const bubble = event.target.closest('.bubble'); | |
const bubbleText = bubble.querySelector('.bubble-text'); | |
const nextComma = bubbleText.nextSibling; | |
bubble.remove(); | |
if (nextComma && nextComma.nodeType === Node.TEXT_NODE && nextComma.textContent.trim() === ',') { | |
nextComma.remove(); | |
} | |
handleBubbleChange(); | |
} | |
function emphasizeBubble(event) { | |
const bubble = event.target.closest('.bubble'); | |
const bubbleText = bubble.querySelector('.bubble-text'); | |
const text = bubbleText.innerText.trim(); | |
if (text.startsWith('[') && text.endsWith(']')) { | |
bubbleText.innerText = text.slice(1, -1); | |
} else { | |
bubbleText.innerText = `(${text})`; | |
} | |
handleBubbleChange(); | |
} | |
function mitigateBubble(event) { | |
const bubble = event.target.closest('.bubble'); | |
const bubbleText = bubble.querySelector('.bubble-text'); | |
const text = bubbleText.innerText.trim(); | |
if (text.startsWith('(') && text.endsWith(')')) { | |
bubbleText.innerText = text.slice(1, -1); | |
} else { | |
bubbleText.innerText = `[${text}]`; | |
} | |
handleBubbleChange(); | |
} | |
document.addEventListener('DOMContentLoaded', function() { | |
let words = []; | |
let categoriesData = {}; | |
// Datos de respaldo | |
const backupData = { | |
'Composition and Style': { | |
'Style': [ | |
{ | |
type: 'subcategory', | |
name: 'Classic', | |
items: [ | |
{ type: 'word', name: 'Elegant' }, | |
{ type: 'word', name: 'Traditional' } | |
] | |
}, | |
{ | |
type: 'subcategory', | |
name: 'Modern', | |
items: [ | |
{ type: 'word', name: 'Sleek' }, | |
{ type: 'word', name: 'Minimalist' } | |
] | |
} | |
], | |
'Composition': [ | |
{ type: 'word', name: 'Balanced' }, | |
{ type: 'word', name: 'Dynamic' } | |
] | |
}, | |
'Body': { | |
'Head': [ | |
{ | |
type: 'subcategory', | |
name: 'Facial Features', | |
items: [ | |
{ type: 'word', name: 'Eyes' }, | |
{ type: 'word', name: 'Nose' } | |
] | |
}, | |
{ | |
type: 'subcategory', | |
name: 'Hair', | |
items: [ | |
{ type: 'word', name: 'Curly' }, | |
{ type: 'word', name: 'Straight' } | |
] | |
} | |
], | |
'Torso': [ | |
{ type: 'word', name: 'Chest' }, | |
{ type: 'word', name: 'Back' } | |
] | |
} | |
}; | |
// Archivos CSV a cargar | |
const csvFiles = [ | |
'Composition.csv', | |
'Body.csv', | |
'Clothes.csv', | |
'Activity.csv', | |
'Objects.csv', | |
'Creatures.csv', | |
'Plants.csv', | |
'World.csv', | |
'NSFW.csv', | |
'More.csv' | |
]; | |
const categoryEmojis = { | |
'Composition': '🖼️', | |
'Body': '🧏🏻♀️', | |
'Clothes': '👒', | |
'Activity': '🤺', | |
'Objects': '🎸', | |
'Creatures': '🐈', | |
'Plants': '☘️', | |
'World': '🌍', | |
'NSFW': '🍑', | |
'More': '📚' | |
}; | |
const categoryDropdownButton = document.getElementById('category-dropdown-button'); | |
const categoryDropdown = document.getElementById('category-dropdown'); | |
const randomWordButton = document.getElementById('random-word-button'); | |
categoryDropdownButton.addEventListener('click', toggleCategoryDropdown); | |
randomWordButton.addEventListener('click', addRandomWordToInput); | |
document.addEventListener('click', closeDropdownOutsideClick); | |
function toggleCategoryDropdown() { | |
categoryDropdown.classList.toggle('hidden'); | |
} | |
function closeDropdownOutsideClick(event) { | |
if (!categoryDropdown.contains(event.target) && event.target !== categoryDropdownButton) { | |
categoryDropdown.classList.add('hidden'); | |
} | |
} | |
async function loadCSVFiles() { | |
for (const file of csvFiles) { | |
try { | |
const response = await fetch(file); | |
if (!response.ok) throw new Error(`Error al cargar ${file}`); | |
const text = await response.text(); | |
processCSVData(file.split('.csv')[0], text); | |
} catch (error) { | |
console.error(error); | |
// Usa datos de respaldo en caso de error | |
const categoryName = file.split('.csv')[0]; | |
if (backupData[categoryName]) { | |
categoriesData[categoryName] = backupData[categoryName]; | |
} | |
} | |
} | |
renderCategories(); | |
populateWordsForAutocomplete(); | |
} | |
function processCSVData(categoryName, csvText) { | |
const lines = csvText.split('\n').map(line => line.trim()).filter(line => line.length > 0); | |
const headers = lines[0].split(','); | |
if (!categoriesData[categoryName]) { | |
categoriesData[categoryName] = {}; | |
} | |
headers.forEach((header, index) => { | |
if (!categoriesData[categoryName][header]) { | |
categoriesData[categoryName][header] = []; | |
} | |
let currentSubcategory = null; | |
let currentSubSubcategory = null; | |
for (let i = 1; i < lines.length; i++) { | |
const wordsInLine = lines[i].split(','); | |
const word = wordsInLine[index].trim(); | |
if (word) { | |
// Si la palabra tiene una celda vacía directamente sobre ella en la misma columna | |
if (i > 1 && lines[i - 1].split(',')[index].trim() === '') { | |
if (currentSubcategory) { | |
currentSubSubcategory = { type: 'subsubcategory', name: word, items: [] }; | |
currentSubcategory.items.push(currentSubSubcategory); | |
} else { | |
currentSubcategory = { type: 'subcategory', name: word, items: [] }; | |
categoriesData[categoryName][header].push(currentSubcategory); | |
} | |
} else if (currentSubSubcategory) { | |
currentSubSubcategory.items.push({ type: 'word', name: word }); | |
} else if (currentSubcategory) { | |
currentSubcategory.items.push({ type: 'word', name: word }); | |
} else { | |
categoriesData[categoryName][header].push({ type: 'word', name: word }); | |
} | |
} else { | |
if (currentSubSubcategory) { | |
currentSubSubcategory = null; | |
} else { | |
currentSubcategory = null; | |
} | |
} | |
} | |
}); | |
} | |
function renderCategories() { | |
categoryDropdown.innerHTML = ''; | |
for (const [categoryName, subcategories] of Object.entries(categoriesData)) { | |
const categoryItem = document.createElement('div'); | |
categoryItem.classList.add('category-item'); | |
const emojiSpan = document.createElement('span'); | |
emojiSpan.classList.add('category-emoji'); | |
emojiSpan.innerText = categoryEmojis[categoryName] || ''; | |
const nameSpan = document.createElement('span'); | |
nameSpan.innerText = categoryName; | |
categoryItem.appendChild(emojiSpan); | |
categoryItem.appendChild(nameSpan); | |
categoryItem.addEventListener('click', () => toggleSubcategory(categoryItem, subcategories)); | |
categoryDropdown.appendChild(categoryItem); | |
} | |
} | |
function toggleSubcategory(categoryItem, subcategories) { | |
if (categoryItem.nextElementSibling && categoryItem.nextElementSibling.classList.contains('subcategory-container')) { | |
categoryItem.nextElementSibling.remove(); | |
} else { | |
const subcategoryContainer = document.createElement('div'); | |
subcategoryContainer.classList.add('subcategory-container'); | |
for (const [subcategoryName, items] of Object.entries(subcategories)) { | |
const subcategoryItem = document.createElement('div'); | |
subcategoryItem.classList.add('subcategory-item'); | |
subcategoryItem.innerText = subcategoryName; | |
// Crear botón para añadir palabra aleatoria | |
const randomButton = document.createElement('button'); | |
randomButton.innerText = '🎲'; | |
randomButton.classList.add('random-word-button'); | |
randomButton.addEventListener('click', (e) => { | |
e.stopPropagation(); | |
addRandomWordFromSubcategory(items); | |
handleTextChange(); | |
}); | |
subcategoryItem.appendChild(randomButton); | |
subcategoryItem.addEventListener('click', (e) => { | |
e.stopPropagation(); | |
toggleItems(subcategoryItem, items); | |
}); | |
subcategoryContainer.appendChild(subcategoryItem); | |
} | |
categoryItem.insertAdjacentElement('afterend', subcategoryContainer); | |
} | |
} | |
function toggleItems(subcategoryItem, items) { | |
if (subcategoryItem.nextElementSibling && subcategoryItem.nextElementSibling.classList.contains('item-container')) { | |
subcategoryItem.nextElementSibling.remove(); | |
} else { | |
const itemContainer = document.createElement('div'); | |
itemContainer.classList.add('item-container'); | |
items.forEach(item => { | |
const itemElement = document.createElement('div'); | |
itemElement.classList.add(item.type === 'subcategory' || item.type === 'subsubcategory' ? 'subcategory-item' : 'word-item'); | |
itemElement.innerText = item.name; | |
// Si es subcategoría o sub-subcategoría, añadir botón de palabra aleatoria | |
if (item.type === 'subcategory' || item.type === 'subsubcategory') { | |
const randomButton = document.createElement('button'); | |
randomButton.innerText = '🎲'; | |
randomButton.classList.add('random-word-button'); | |
randomButton.addEventListener('click', (e) => { | |
e.stopPropagation(); | |
addRandomWordFromSubcategory(item.items); | |
handleTextChange(); | |
}); | |
itemElement.appendChild(randomButton); | |
} | |
if (item.type === 'subcategory' || item.type === 'subsubcategory') { | |
itemElement.addEventListener('click', (e) => { | |
e.stopPropagation(); | |
toggleItems(itemElement, item.items); | |
}); | |
} else { | |
itemElement.addEventListener('click', () => addItemToInput(item.name)); | |
} | |
itemContainer.appendChild(itemElement); | |
}); | |
subcategoryItem.insertAdjacentElement('afterend', itemContainer); | |
} | |
} | |
function addItemToInput(word) { | |
const inputText = document.getElementById('input-text'); | |
inputText.value += (inputText.value ? ', ' : '') + word; | |
updateBubbles(); | |
} | |
function populateWordsForAutocomplete() { | |
words = []; | |
for (const category of Object.values(categoriesData)) { | |
for (const subcategory of Object.values(category)) { | |
for (const item of subcategory) { | |
if (item.type === 'word') { | |
words.push(item.name); | |
} else if (item.type === 'subcategory' || item.type === 'subsubcategory') { | |
item.items.forEach(subItem => { | |
if (subItem.type === 'word') { | |
words.push(subItem.name); | |
} | |
}); | |
} | |
} | |
} | |
} | |
console.log('Palabras cargadas para autocompletador:', words); | |
} | |
function addRandomWordToInput() { | |
if (words.length === 0) return; | |
const randomWord = words[Math.floor(Math.random() * words.length)]; | |
addItemToInput(randomWord); | |
} | |
function addRandomWordFromSubcategory(subcategoryItems) { | |
const subcategoryWords = subcategoryItems.flatMap(item => item.type === 'word' ? [item.name] : item.items.map(subItem => subItem.name)); | |
if (subcategoryWords.length === 0) return; | |
const randomWord = subcategoryWords[Math.floor(Math.random() * subcategoryWords.length)]; | |
addItemToInput(randomWord); | |
} | |
const input = document.getElementById('autocomplete-input'); | |
const autocompleteList = document.getElementById('autocomplete-list'); | |
// Función que maneja tanto el evento de 'input' como de 'focus' | |
function handleAutocomplete() { | |
const value = input.value.toLowerCase(); | |
console.log('Valor de entrada:', value); // Verifica el valor de entrada | |
if (!value) { | |
autocompleteList.innerHTML = ''; | |
return; | |
} | |
// Filtra y ordena las palabras que empiezan con el valor ingresado, sin distinguir mayúsculas | |
const startsWith = words | |
.filter(word => word.toLowerCase().startsWith(value)) | |
.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())); | |
// Filtra y ordena las palabras que contienen el valor ingresado pero no empiezan con él, sin distinguir mayúsculas | |
const contains = words | |
.filter(word => word.toLowerCase().includes(value) && !word.toLowerCase().startsWith(value)) | |
.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())); | |
// Crear un conjunto para filtrar palabras únicas | |
const uniqueSuggestions = new Set([...startsWith, ...contains]); | |
// Convertir el conjunto a un array y tomar las primeras 20 sugerencias | |
const suggestions = Array.from(uniqueSuggestions).slice(0, 20); | |
console.log('Sugerencias encontradas:', suggestions); // Verifica las sugerencias encontradas | |
autocompleteList.innerHTML = suggestions.map(suggestion => `<div>${suggestion}</div>`).join(''); | |
autocompleteList.querySelectorAll('div').forEach(item => { | |
item.addEventListener('click', function() { | |
const selectedWord = this.textContent; | |
const inputText = document.getElementById('input-text'); | |
inputText.value += (inputText.value ? ', ' : '') + selectedWord; | |
updateBubbles(); | |
input.value = ''; // Limpia el campo de autocompletado | |
autocompleteList.innerHTML = ''; // Limpia las sugerencias | |
input.focus(); // Enfoca el campo de autocompletado | |
}); | |
}); | |
} | |
// Escucha tanto al evento de 'input' como al de 'focus' | |
input.addEventListener('input', handleAutocomplete); | |
input.addEventListener('focus', handleAutocomplete); | |
document.addEventListener('click', function(event) { | |
if (event.target !== input) { | |
autocompleteList.innerHTML = ''; | |
handleTextChange(); | |
} | |
}); | |
loadCSVFiles(); | |
}); |