';
});
}
if (domCache.notesTableBody) {
domCache.notesTableBody.innerHTML = tbody;
// After rendering, initialize table elements
initializeTableElements();
}
updateSortIndicators();
}
// Modal confirmation for delete and duplicate
window.confirmDeleteNote = function(noteId) {
showBootstrapModal(lang_notes_delete, lang_notes_delete_confirmation, function() {
deleteNote(noteId);
});
};
window.confirmDuplicateNote = function(noteId) {
var note = (window.lastNotesData || []).find(function(n) { return n.id == noteId; });
if (note && note.cat === 'Contacts') {
showBootstrapModal(lang_notes_duplication_disabled_short, lang_notes_duplication_disabled, function(){});
return;
}
showBootstrapModal(lang_notes_duplicate, lang_notes_duplicate_confirmation, function() {
duplicateNote(noteId);
});
};
// Actions for delete and duplicate
function deleteNote(noteId) {
fetch(base_url + 'index.php/notes/delete/' + noteId, { method: 'POST' })
.then(() => {
// Check if we need to go to previous page after deletion
// If we're on the last page and it only has 1 item, go back one page
var currentPageItemCount = window.lastNotesData ? window.lastNotesData.length : 0;
if (currentPage > 1 && currentPageItemCount === 1) {
currentPage = currentPage - 1;
}
performNotesSearch();
reloadCategoryCounters();
});
}
// Duplicate note via POST with timestamp
function duplicateNote(noteId) {
// Get local timestamp
var now = new Date();
var timestamp = now.toLocaleString();
var formData = new FormData();
formData.append('timestamp', timestamp);
fetch(base_url + 'index.php/notes/duplicate/' + noteId, {
method: 'POST',
body: formData
})
.then(() => {
performNotesSearch();
reloadCategoryCounters();
});
}
// Bootstrap modal helper
function showBootstrapModal(title, message, onConfirm) {
var modalId = 'confirmModal_' + Math.random().toString(36).substr(2, 9);
var modalHtml = '
' +
'
' +
'
' +
'
' + title + '
' +
'
' + message + '
' +
'
';
var modalDiv = document.createElement('div');
modalDiv.innerHTML = modalHtml;
document.body.appendChild(modalDiv);
var modalEl = modalDiv.querySelector('.modal');
var modal;
try {
modal = new bootstrap.Modal(modalEl, { backdrop: 'static' });
modal.show();
} catch (e) {
document.body.removeChild(modalDiv);
if (confirm(message)) {
onConfirm();
}
return;
}
modalDiv.querySelector('#confirmModalBtn_' + modalId).onclick = function() {
modal.hide();
setTimeout(function() { document.body.removeChild(modalDiv); }, 300);
onConfirm();
};
modalDiv.querySelector('[data-bs-dismiss="modal"]').onclick = function() {
modal.hide();
setTimeout(function() { document.body.removeChild(modalDiv); }, 300);
};
}
// Patch performNotesSearch to use server-side pagination and sorting
performNotesSearch = function() {
var searchTerm = domCache.searchBox ? domCache.searchBox.value.trim() : '';
var selectedCat = getActiveCategory();
var sortColIdx = sortState.column;
var sortDir = sortState.direction;
var sortCol = (sortColIdx !== null && SORT_COLUMN_MAP[sortColIdx]) ? SORT_COLUMN_MAP[sortColIdx] : null;
var formData = new FormData();
formData.append('cat', selectedCat);
formData.append('search', searchTerm.length >= SEARCH_MIN_LENGTH ? searchTerm : '');
formData.append('page', currentPage);
formData.append('per_page', NOTES_PER_PAGE);
formData.append('sort_col', sortCol || '');
formData.append('sort_dir', sortDir || '');
fetch(base_url + 'index.php/notes/search', {
method: 'POST',
body: formData
})
.then(response => {
if (!response.ok) throw new Error('Network response was not ok');
return response.json();
})
.then(resp => {
var data = (resp && Array.isArray(resp.notes)) ? resp.notes : [];
window.lastNotesData = data;
lastResponseTotal = resp.total || 0;
totalPages = Math.max(1, Math.ceil(lastResponseTotal / NOTES_PER_PAGE));
if (currentPage > totalPages) currentPage = totalPages;
renderNotesTable(data);
renderPagination();
reloadCategoryCounters();
})
.catch(error => {
if (domCache.notesTableBody) {
domCache.notesTableBody.innerHTML = '
';
}
if (domCache.paginationContainer) {
domCache.paginationContainer.innerHTML = '';
}
});
};
// Reset to first page on search, sort, or category change
if (domCache.categoryButtons && domCache.notesTableBody) {
domCache.categoryButtons.forEach(function(btn) {
btn.addEventListener('click', function() {
domCache.categoryButtons.forEach(function(b) { b.classList.remove('active'); });
btn.classList.add('active');
currentPage = 1;
performNotesSearch();
});
});
}
if (domCache.searchBox) {
domCache.searchBox.addEventListener('input', function() {
currentPage = 1;
performNotesSearch();
});
}
if (domCache.resetBtn) {
domCache.resetBtn.addEventListener('click', function() {
if (domCache.searchBox) domCache.searchBox.value = '';
currentPage = 1;
performNotesSearch();
});
}
// Initial render - only if we have the necessary elements
if (domCache.notesTableBody) {
performNotesSearch();
}
// Add stroked zero (Ø) to search box
var addStrokedZeroBtn = document.getElementById('notesAddStrokedZero');
if (addStrokedZeroBtn) {
addStrokedZeroBtn.addEventListener('click', function() {
var searchBox = domCache.searchBox;
if (searchBox) {
var currentValue = searchBox.value;
var cursorPos = searchBox.selectionStart;
// Insert Ø at cursor position
var newValue = currentValue.slice(0, cursorPos) + 'Ø' + currentValue.slice(cursorPos);
searchBox.value = newValue;
// Set cursor position after the inserted character
searchBox.focus();
searchBox.setSelectionRange(cursorPos + 1, cursorPos + 1);
// Trigger search if minimum length is met
if (newValue.length >= SEARCH_MIN_LENGTH) {
performNotesSearch();
}
}
});
}
});