From 3e64bca676eda847180a66b492b430bf9c84b232 Mon Sep 17 00:00:00 2001 From: brian Date: Mon, 12 Apr 2021 08:36:22 -0400 Subject: [PATCH] dblclick for new note; immediately-cancellable notes --- nginx/public_html/App.js | 3 ++- nginx/public_html/Note.js | 2 +- nginx/public_html/handlers/App.js | 9 ++++++++- nginx/public_html/handlers/Note.js | 10 ++++++++-- nginx/public_html/index.js | 10 ++++++++-- 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/nginx/public_html/App.js b/nginx/public_html/App.js index 0e6b8a0..e87f318 100644 --- a/nginx/public_html/App.js +++ b/nginx/public_html/App.js @@ -1,5 +1,6 @@ import Note from './Note.js'; import { + preventDblClickSelection, new_note_handler, new_note_by_dblclick_handler, search_term_change_handler, @@ -67,7 +68,7 @@ function App(vnode_init){ ]) ]), m('.main', {key: 'main'}, [ - m('.notes', {ondblclick: o(new_note_by_dblclick_handler)}, s.notes.map(note_state => + m('.notes', {ondblclick: o(new_note_by_dblclick_handler), onmousedown:preventDblClickSelection}, s.notes.map(note_state => m(Note, {state:s, note_state, dispatch, key: note_state.note_id}) )) ]) diff --git a/nginx/public_html/Note.js b/nginx/public_html/Note.js index 7e9e779..9dc39ba 100644 --- a/nginx/public_html/Note.js +++ b/nginx/public_html/Note.js @@ -11,7 +11,7 @@ function Note(vnode_init){ return m('.note', [ m('textarea', {key: 'textarea', onchange: text_change_handler.bind(null, note_state, dispatch), oncreate: is_focused?({dom})=>{ dom.focus(); delete note_state.is_focused; }:null }, note_state.temp_text), m('.buttons', {key: 'editing-buttons'}, [ - m('button', {key: 'cancel-button', onclick: cancel_handler.bind(null, note_state, dispatch) }, 'Cancel'), + m('button', {key: 'cancel-button', onclick: cancel_handler.bind(null, state, note_state, dispatch) }, 'Cancel'), m('button', {key: 'save-button', onclick: save_handler.bind(null, note_state, dispatch) }, 'Save') ]) ]); diff --git a/nginx/public_html/handlers/App.js b/nginx/public_html/handlers/App.js index 3f53a9b..ea034bc 100644 --- a/nginx/public_html/handlers/App.js +++ b/nginx/public_html/handlers/App.js @@ -1,6 +1,12 @@ import nanoid from '../nanoid.min.js'; import api from '../api.js'; +const preventDblClickSelection = function(e){ + // as per [https://stackoverflow.com/a/43321596] + if(e.detail>1){ + e.preventDefault(); + } + } const load_notes = function(state, dispatch){ api.post('/load-notes', {bin_id: state.bin_id}) .then(res=>{ @@ -88,7 +94,8 @@ const choose_bin_handler = function(state, dispatch, bin_id){ }); }; -export {new_note_handler, +export {preventDblClickSelection, + new_note_handler, new_note_by_dblclick_handler, search_term_change_handler, sorting_change_handler, diff --git a/nginx/public_html/handlers/Note.js b/nginx/public_html/handlers/Note.js index 8db6e58..0842c73 100644 --- a/nginx/public_html/handlers/Note.js +++ b/nginx/public_html/handlers/Note.js @@ -3,8 +3,14 @@ import api from '../api.js'; const edit_handler = function(note_state, dispatch){ dispatch('update-note-editing', {id: note_state.note_id, is_editing: true}); }; -const cancel_handler = function(note_state, dispatch){ - dispatch('update-note-editing', {id: note_state.note_id, is_editing: false}); +const cancel_handler = function(state, note_state, dispatch){ + // TODO: this `if` may cause glitches; keep in mind + if(note_state.is_new===true){ + dispatch('immediately-cancel-note', note_state.note_id); + } + else{ + dispatch('update-note-editing', {id: note_state.note_id, is_editing: false}); + } }; const text_change_handler = function(note_state, dispatch, e){ note_state.temp_text = e.target.value; diff --git a/nginx/public_html/index.js b/nginx/public_html/index.js index 376d6c4..11c3d91 100644 --- a/nginx/public_html/index.js +++ b/nginx/public_html/index.js @@ -78,6 +78,11 @@ const refAll = function(s, o, key, new_model_ids){ This routine would need to be called for state.notes, which contains refs of the form: `state.notes[n].note_id` */ +// TODO: doesn't update anything that references the deleted record; results in dangling pointers: +const disintegrate = function(s, id){ + delete s.db[id]; + }; + function addToBinListIfLoggedIn(state){ const s = state; // if user is logged in: @@ -98,9 +103,10 @@ const reducer = handleActions({ 'bin-loaded': (s, bin) => { i(s,bin); ref(s,s,'bin_id',bin.id); s.temp_bin_name=bin.name; }, 'update-search-term': (s, search_term) => { s.search_term=search_term; }, 'update-search-results': (s, _notes) => { integrateAll(s,s.notes,'note_id',_notes); s.notes =_notes.map(n=>({is_editing: false, temp_text: '', bin_id: s.bin_id, note_id:n.id})); }, - 'add-note': (s, {id, date}) => { i(s, {id: id, text: '', modified: date}); s.notes.unshift({is_editing: true, temp_text: '', bin_id: s.bin_id, is_focused:true, note_id: id}); }, + 'add-note': (s, {id, date}) => { i(s, {id: id, text: '', modified: date}); s.notes.unshift({is_editing: true, temp_text: '', bin_id: s.bin_id, is_focused:true, is_new: true, note_id: id}); }, 'notes-loaded': (s, _notes) => { integrateAll(s,_notes); s.notes = _notes.map(n=>({is_editing: false, temp_text: n.text, bin_id: s.bin_id, note_id:n.id})); }, - 'update-note-text': (s, {id, text}) => { const note_s=s.notes.find(n=>n.note_id===id); s.db[note_s.note_id].model.text=text; }, // updates underlying note text (i.e. the "model", not the app note_state) "in the background" (e.g. from a server-pushed update), regardless of whether it's being edited; "save" is a separate action, below + 'immediately-cancel-note': (s, note_id) => { disintegrate(s,note_id); s.notes.splice(s.notes.findIndex(n=>n.note_id===note_id), 1); }, + 'update-note-text': (s, {id, text}) => { const note_s=s.notes.find(n=>n.note_id===id); note_s.is_new=false; s.db[note_s.note_id].model.text=text; }, // updates underlying note text (i.e. the "model", not the app note_state) "in the background" (e.g. from a server-pushed update), regardless of whether it's being edited; "save" is a separate action, below 'update-note-editing': (s, {id, is_editing}) => { const note_s=s.notes.find(n=>n.note_id===id); note_s.is_editing=is_editing; note_s.temp_text=s.db[note_s.note_id].model.text; }, 'save-note-edit': (s, {id, text}) => { const note_s=s.notes.find(n=>n.note_id===id); s.db[note_s.note_id].model.text=text; note_s.temp_text=text; note_s.is_editing=false; }, 'update-sorting': (s, sorting) => { s.sorting=sorting; },