Hi all,
In my NodeJS app I have a number of text-area’s that I’m trying to force bullet-points. Currently I have a custom JS file (below) that references the class on the text-areas.
If I navigate to the page these text-areas exist and I call the functions:
convertContentToBullets('bullet-textarea'); initializeBulletTextareas();
Everything works as expected (albeit still needs improving as the user can still workaround the bullets if they wish).
However, if I then refresh this page, the bullets will not initialize within the text-area. Even if I manually call the above functions.
Logging shows that the text-areas are found, and that the functions are being called - but on the front-end the textarea bullets just won’t initialize.
Here is the JS (it’s a little bloated due to trying to find solutions):
// JavaScript Document
document.addEventListener('DOMContentLoaded', function () {
console.log("Document ready. Initializing bullet textareas...");
// Check if the elements exist and initialize them
if (document.querySelectorAll('.bullet-textarea').length) {
initializeBulletTextareas();
} else {
// If not, start observing the DOM for changes
observeBulletTextareas();
}
});
function initializeBulletTextareas() {
const bulletTextareas = document.querySelectorAll('.bullet-textarea');
console.log("Found", bulletTextareas.length, "bullet textareas");
bulletTextareas.forEach(textarea => {
textarea.removeEventListener('focus', onTextareaFocus);
textarea.removeEventListener('keyup', onTextareaKeyup);
textarea.addEventListener('focus', onTextareaFocus);
textarea.addEventListener('keyup', onTextareaKeyup);
});
}
// Define the focus event listener function separately
function onTextareaFocus() {
console.log("Focus event on textarea with id:", this.id);
if (this.value === '') {
this.value += '• ';
}
}
// Define the keyup event listener function separately
function onTextareaKeyup(event) {
console.log("Keyup event on textarea with id:", this.id, "Key:", event.key);
handleEnterAndBackspace(this, event);
}
function handleEnterAndBackspace(textarea, event) {
const keycode = event.keyCode || event.which;
console.log("Handling Enter/Backspace. Keycode:", keycode);
if (keycode === 13) {
insertBulletAfterEnter(textarea);
} else if (keycode === 8) {
handleBackspace(textarea, event);
}
}
function insertBulletAfterEnter(textarea) {
let txtval = textarea.value;
console.log("Inserting bullet after Enter. Current value:", txtval);
if (txtval.substr(txtval.length - 1) === '\n') {
textarea.value = txtval + '• ';
}
}
function handleBackspace(textarea, event) {
const cursorPosition = textarea.selectionStart;
console.log("Handling Backspace. Cursor position:", cursorPosition);
if (cursorPosition === 0 || textarea.value.substring(cursorPosition - 2, cursorPosition) === '• ') {
event.preventDefault();
if (cursorPosition > 2) {
textarea.selectionStart = cursorPosition - 2;
textarea.selectionEnd = cursorPosition - 2;
}
}
}
function htmlToListFormat(html) {
console.log("Converting HTML to list format. HTML:", html);
const div = document.createElement('div');
div.innerHTML = html;
const items = div.querySelectorAll('li');
return Array.from(items).map(item => '• ' + item.textContent).join('\n');
}
function convertContentToBullets(textareaClass) {
const textareas = document.querySelectorAll('.' + textareaClass);
console.log("Converting content to bullets for class:", textareaClass);
textareas.forEach(textarea => {
// Check if the content already starts with a bullet point
if (!textarea.value.startsWith('• ')) {
console.log("Original value for textarea with id:", textarea.id, "is being converted");
textarea.value = htmlToListFormat(textarea.value);
} else {
console.log("Textarea with id:", textarea.id, "already has bullets, skipping conversion");
}
});
}
window.convertContentToBullets = convertContentToBullets;
function observeBulletTextareas() {
const observer = new MutationObserver((mutations, obs) => {
const bulletTextareas = document.querySelectorAll('.bullet-textarea');
if (bulletTextareas.length) {
console.log("Bullet textareas detected through MutationObserver.");
initializeBulletTextareas();
// Optionally, disconnect the observer once the elements are found and initialized
obs.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
Troubleshooting with our friendly AI donesn’t come up with a solution and instead points towards how states are managed in the code.
I know this is a long-shot but does anyone have any ideas here? @patrick sorry for the tag but just want to raise this in case I’m missing something specific to how AC2 / Wappler works in this regard.
Appreciate any help.