[notes] replace all the javascript

This commit is contained in:
Shish
2024-01-05 02:03:41 +00:00
parent 48b3de3c6e
commit 05a981d935
11 changed files with 393 additions and 321 deletions

View File

@@ -1,81 +1,274 @@
/*jshint bitwise:true, curly:true, forin:false, noarg:true, noempty:true, nonew:true, undef:true, strict:false, browser:true, jquery:true */
let notesContainer = null;
let noteImage = document.getElementById('main_image');
let noteBeingEdited = null;
let dragStart = null;
document.addEventListener('DOMContentLoaded', () => {
if(window.notes) {
$('#main_image').load(function(){
$('#main_image').imgNotes({notes: window.notes});
if(noteImage.complete) {
renderNotes();
} else {
noteImage.addEventListener('load', () => {
renderNotes();
});
}
//Make sure notes are always shown
$('#main_image').off('mouseenter mouseleave');
let resizeObserver = new ResizeObserver(entries => {
renderNotes();
});
resizeObserver.observe(noteImage);
}
});
function renderNotes() {
// reset the DOM to empty
if(notesContainer) {
notesContainer.remove();
}
$('#cancelnote').click(function(){
$('#main_image').imgAreaSelect({ hide: true });
$('#noteform').hide();
// check the image we're adding notes on top of
let br = noteImage.getBoundingClientRect();
let scale = br.width / noteImage.getAttribute("data-width");
// render a container full of notes
notesContainer = document.createElement('div');
notesContainer.className = 'notes-container';
notesContainer.style.left = window.scrollX + br.left + 'px';
notesContainer.style.top = window.scrollY + br.top + 'px';
notesContainer.style.width = br.width + 'px';
notesContainer.style.height = br.height + 'px';
// render each note
window.notes.forEach(note => {
let noteDiv = document.createElement('div');
noteDiv.classList.add('note');
noteDiv.style.left = note.x1 * scale + 'px';
noteDiv.style.top = note.y1 * scale + 'px';
noteDiv.style.width = note.width * scale + 'px';
noteDiv.style.height = note.height * scale + 'px';
let text = document.createElement('div');
text.innerText = note.note;
noteDiv.addEventListener('click', (e) => {
noteBeingEdited = note.note_id;
renderNotes();
});
noteDiv.appendChild(text);
notesContainer.appendChild(noteDiv);
// if the current note is being edited, render the editor
if(note.note_id == noteBeingEdited) {
let editor = renderEditor(noteDiv, note);
notesContainer.appendChild(editor);
}
});
$('#EditCancelNote').click(function() {
$('#main_image').imgAreaSelect({ hide: true });
$('#noteEditForm').hide();
});
$('#addnote').click(function(){
$('#noteEditForm').hide();
$('#main_image').imgAreaSelect({ onSelectChange: showaddnote, x1: 120, y1: 90, x2: 280, y2: 210 });
return false;
});
$('.note').click(function() {
$('#noteform').hide();
var imgOffset = $('#main_image').offset();
var x1 = parseInt(this.style.left) - imgOffset.left;
var y1 = parseInt(this.style.top) - imgOffset.top;
var width = parseInt(this.style.width);
var height = parseInt(this.style.height);
var text = $(this).next('.notep').text().replace(/([^>]?)\\n{2}/g, '$1\\n');
var id = $(this).next('.notep').next('.noteID').text();
$('#main_image').imgAreaSelect({ onSelectChange: showeditnote, x1: x1, y1: y1, x2: x1 + width, y2: y1 + height });
setEditNoteData(x1, y1, width, height, text, id);
});
});
function showaddnote (img, area) {
var imgOffset = $(img).offset();
var form_left = parseInt(imgOffset.left) + parseInt(area.x1);
var form_top = parseInt(imgOffset.top) + parseInt(area.y1) + parseInt(area.height)+5;
$('#noteform').css({ left: form_left + 'px', top: form_top + 'px'});
$('#noteform').show();
$('#noteform').css('z-index', 10000);
$('#NoteX1').val(area.x1);
$('#NoteY1').val(area.y1);
$('#NoteHeight').val(area.height);
$('#NoteWidth').val(area.width);
noteImage.parentNode.appendChild(notesContainer);
}
function showeditnote (img, area) {
var imgOffset = $(img).offset();
var form_left = parseInt(imgOffset.left) + area.x1;
var form_top = parseInt(imgOffset.top) + area.y2;
/**
*
* @param {HTMLElement} noteDiv
* @param {*} note
* @returns
*/
function renderEditor(noteDiv, note) {
// check the image we're adding notes on top of
let br = noteImage.getBoundingClientRect();
let scale = br.width / noteImage.getAttribute("data-width");
$('#noteEditForm').css({ left: form_left + 'px', top: form_top + 'px'});
$('#noteEditForm').show();
$('#noteEditForm').css('z-index', 10000);
$('#EditNoteX1').val(area.x1);
$('#EditNoteY1').val(area.y1);
$('#EditNoteHeight').val(area.height);
$('#EditNoteWidth').val(area.width);
// set the note itself into drag & resize mode
// NOTE: to avoid re-rendering the whole DOM every time the mouse
// moves, we directly edit the style of the noteDiv, and then when
// the mouse is released, we update the note object and re-render
noteDiv.classList.add('editing');
noteDiv.addEventListener('mousedown', (e) => {
dragStart = {
x: e.pageX,
y: e.pageY,
mode: getArea(e.offsetX, e.offsetY, noteDiv.offsetWidth, noteDiv.offsetHeight),
};
noteDiv.classList.add("dragging");
});
noteDiv.addEventListener('mousemove', (e) => {
if(dragStart) {
if(dragStart.mode == "c") {
noteDiv.style.left = (note.x1 * scale) + (e.pageX - dragStart.x) + 'px';
noteDiv.style.top = (note.y1 * scale) + (e.pageY - dragStart.y) + 'px';
}
if(dragStart.mode.indexOf("n") >= 0) {
noteDiv.style.top = (note.y1 * scale) + (e.pageY - dragStart.y) + 'px';
noteDiv.style.height = (note.height * scale) - (e.pageY - dragStart.y) + 'px';
}
if(dragStart.mode.indexOf("s") >= 0) {
noteDiv.style.height = (note.height * scale) + (e.pageY - dragStart.y) + 'px';
}
if(dragStart.mode.indexOf("w") >= 0) {
noteDiv.style.left = (note.x1 * scale) + (e.pageX - dragStart.x) + 'px';
noteDiv.style.width = (note.width * scale) - (e.pageX - dragStart.x) + 'px';
}
if(dragStart.mode.indexOf("e") >= 0) {
noteDiv.style.width = (note.width * scale) + (e.pageX - dragStart.x) + 'px';
}
} else {
let area = getArea(e.offsetX, e.offsetY, noteDiv.offsetWidth, noteDiv.offsetHeight);
if(area == "c") {
noteDiv.style.cursor = 'move';
} else {
noteDiv.style.cursor = area + '-resize';
}
}
});
function _commit() {
noteDiv.classList.remove("dragging");
dragStart = null;
note.x1 = noteDiv.offsetLeft / scale;
note.y1 = noteDiv.offsetTop / scale;
note.width = noteDiv.offsetWidth / scale;
note.height = noteDiv.offsetHeight / scale;
renderNotes();
}
noteDiv.addEventListener('mouseup', _commit);
noteDiv.addEventListener('mouseleave', _commit);
// add textarea / save / cancel / delete buttons
let editor = document.createElement('div');
editor.classList.add('editor');
editor.style.left = note.x1 * scale + 'px';
editor.style.top = (note.y1 + note.height) * scale + 'px';
let textarea = document.createElement('textarea');
textarea.value = note.note;
textarea.addEventListener('input', () => {
note.note = textarea.value;
});
editor.appendChild(textarea);
let save = document.createElement('button');
save.innerText = 'Save';
save.addEventListener('click', () => {
if(note.note_id == null) {
fetch('/note/create_note', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(note)
}).then(response => {
if(response.ok) {
return response.json();
} else {
throw new Error('Failed to create note');
}
}).then(data => {
note.note_id = data.note_id;
renderNotes();
}).catch(error => {
alert(error);
});
} else {
fetch('/note/update_note', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(note)
}).then(response => {
if(!response.ok) {
throw new Error('Failed to update note');
}
}).catch(error => {
alert(error);
});
}
noteBeingEdited = null;
renderNotes();
});
editor.appendChild(save);
let cancel = document.createElement('button');
cancel.innerText = 'Cancel';
cancel.addEventListener('click', () => {
noteBeingEdited = null;
if(note.note_id == null) {
// delete the un-saved note
window.notes = window.notes.filter(n => n.note_id != null);
}
renderNotes();
});
editor.appendChild(cancel);
if(window.notes_admin && note.note_id != null) {
let deleteNote = document.createElement('button');
deleteNote.innerText = 'Delete';
deleteNote.addEventListener('click', () => {
// TODO: delete note from server
fetch('/note/delete_note', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(note)
}).then(response => {
if(!response.ok) {
throw new Error('Failed to delete note');
}
}).catch(error => {
alert(error);
});
noteBeingEdited = null;
window.notes = window.notes.filter(n => n.note_id != note.note_id);
renderNotes();
});
editor.appendChild(deleteNote);
}
return editor;
}
function setEditNoteData(x1, y1, width, height, text, id) {
$('#EditNoteX1').val(x1);
$('#EditNoteY1').val(y1);
$('#EditNoteHeight').val(height);
$('#EditNoteWidth').val(width);
$('#EditNoteNote').text(text);
$('#EditNoteID').val(id);
$('#DeleteNoteNoteID').val(id);
function addNewNote() {
if(window.notes.filter(note => note.note_id == null).length > 0) {
alert("Please save all notes before adding a new one.");
return;
}
window.notes.push(
{
x1: 10,
y1: 10,
width: 100,
height: 40,
note: "new note",
note_id: null,
image_id: window.notes_image_id,
}
);
noteBeingEdited = null;
renderNotes();
}
function getArea(x, y, width, height) {
let border = 10;
if(y < border) {
if(x < border) {
return "nw";
} else if(x > width - border) {
return "ne";
} else {
return "n";
}
} else if(y > height - border) {
if(x < border) {
return "sw";
} else if(x > width - border) {
return "se";
} else {
return "s";
}
} else if(x < border) {
return "w";
} else if(x > width - border) {
return "e";
} else {
return "c";
}
}