groqnote_dev / public /notebin.js
trretretret's picture
fix accident scroll on mobile when touch keyboard popup
be3ad36
import { utils } from "./utils.js";
function getCurrentLineString(element) {
const selection = window.getSelection();
const range = selection.getRangeAt(0);
const node = range.startContainer;
const offset = range.startOffset;
// If the selection is inside a text node
if (node.nodeType === Node.TEXT_NODE) {
const text = node.textContent;
const lineStart = text.lastIndexOf('\n', offset) + 1;
const lineEnd = text.indexOf('\n', offset);
const line = lineEnd === -1 ? text.slice(lineStart) : text.slice(lineStart, lineEnd);
return line;
}
// If the selection is inside an element node
const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
let currentNode, currentLine = '';
while (currentNode = walker.nextNode()) {
const text = currentNode.textContent;
const lines = text.split('\n');
for (let i = 0; i < lines.length; i++) {
if (range.intersectsNode(currentNode)) {
currentLine = lines[i];
break;
}
}
if (currentLine !== '') {
break;
}
}
return currentLine;
}
function createLastButton(cmd, name = cmd, onclick = console.log,style={}) {
const button = document.createElement('button');
button.className = 'toastui-editor-toolbar-icons last';
button.style.backgroundImage = 'none';
button.style.margin = style.margin || '0';
button.style.fontSize = style.fontSize || 'x-large';
button.innerHTML = `${name}`;
button.addEventListener('click', () => {
onclick();
editor.exec(cmd || '');
});
return button;
}
let editorContainer = document.querySelector('#notebin_editor');
window.tuieditor = window.editor = new toastui.Editor({
el: document.querySelector('#notebin_editor'),
previewStyle: 'tab',
height: window.innerHeight * 0.8 + 'px',
initialValue: '\n\n\n\n\n\n',
customHTMLSanitizer: html => html,
toolbarItems: [
[{
el: createLastButton('undo', '⤺'),
command: 'undo',
tooltip: 'Undo'
},
{
el: createLastButton('redo', '⤻'),
command: 'redo',
tooltip: 'Redo'
},
{
el: createLastButton('', 'wrap', () => {
const element = document.querySelector('.ProseMirror');
if (element.style.overflowX === 'auto' && element.style.whiteSpace === 'nowrap') {
element.style.overflowX = '';
element.style.whiteSpace = '';
} else {
element.style.overflowX = 'auto';
element.style.whiteSpace = 'nowrap';
}
},
{
fontSize: 'medium'
}
),
command: 'wrap',
tooltip: 'wrap'
}
],
['heading'],
//[ 'bold', 'italic', 'strike'],
// ['hr', 'quote'],
// ['ul', 'ol', 'task', 'indent', 'outdent'],
// ['table', 'image', 'link'],
['image'],
['code', 'codeblock'],
],
});
setTimeout(() => {
// tuieditor.focus();
tuieditor.moveCursorToStart(true);
window.tuieditor.mdEditor.el.addEventListener('focus', (event) => {
// Log the event and the pasted data
console.log('focus event triggered:', event);
syncNote();
});
window.tuieditor.mdEditor.el.addEventListener('keydown', function (event) {
if (event.key === 'Enter' && event.ctrlKey) {
// Your code here
let currentLineString = getCurrentLineString(editorContainer);
console.log('Ctrl + Enter was pressed:', currentLineString);
let prompt = ' ';
let selectText = window.getSelection().toString();
utils.displayMarkdown(`${prompt} **${selectText.length >= 1 ? selectText : currentLineString}** ...`);
utils.AIComplete(`${prompt} **${selectText.length >= 1 ? selectText : currentLineString}** `);
}
});
document.body.addEventListener('keydown', event => {
if (event.key === 'Enter' && event.ctrlKey) {
// Your code here
tuieditor.mdEditor.focus();
console.log('body Ctrl + Enter was pressed:');
}
});
let url_div = document.querySelector('#url_div');
url_div.innerText = window.location.href;
url_div.addEventListener('pointerdown', () => {
const text = url_div.textContent;
navigator.clipboard.writeText(text);
utils.showToast('copyed url to clipboard');
})
}, 1000);
// editor.insertToolbarItem({ groupIndex: 0, itemIndex: 0 }, {
// name: 'myItem',
// tooltip: 'Custom Button',
// command: 'bold',
// text: '@',
// className: 'toastui-editor-toolbar-icons first',
// style: { backgroundImage: 'none' }
// });
let editorModel = {
value: null,
lastChangeTime: 0,
noteid: ''
}
// Create a new custom event
const editorchange = new CustomEvent('editorchange', {
detail: {
// Include any data you want to pass with the event
message: 'Editor content has changed'
},
bubbles: true,
cancelable: true
});
document.addEventListener('editorchange', () => {
console.log('editorchange');
editorModel.lastChangeTime = Date.now();
syncNote();
})
let setChangeTimeoutid = 0;
document.addEventListener('keydown', () => {
console.log('keydown');
clearTimeout(setChangeTimeoutid);
setChangeTimeoutid = setTimeout(() => {
document.body.dispatchEvent(editorchange)
}, 5000);
})
document.body.addEventListener('paste', (event) => {
// Log the event and the pasted data
console.log('Paste event triggered:', event);
console.log('Pasted data:', event.clipboardData.getData('text'));
document.body.dispatchEvent(editorchange)
});
document.body.addEventListener('pointerdown', (event) => {
// Log the event and the pasted data
console.log('pointerdown event triggered:', event);
syncNote();
});
function getUrlParameter(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
var results = regex.exec(location.search);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
}
function setUrlParameter(paramName, paramValue) {
const url = new URL(window.location.href);
url.searchParams.set(paramName, paramValue);
history.pushState({}, "", url);
}
let noteid = getUrlParameter('noteid');
console.log(noteid);
async function initEditorModel() {
editorModel.noteid = getUrlParameter('noteid') || Date.now();
setUrlParameter('noteid', editorModel.noteid);
console.log('initEditorModel', editorModel);
getNote();
}
initEditorModel();
setInterval(async () => {
// saveNote();
}, 3000)
async function getNote() {
let res = await fetch(`/kv/get?key=${editorModel.noteid}`);
res = await res.json();
console.log('getNote:', res);
if (res) {
res = res.value;
editorModel.value = res.text;
editorModel.lastChangeTime = res.lastChangeTime || 0;
tuieditor.setMarkdown(res.text)
}
}
async function saveNote() {
let form = new FormData();
form.append('key', noteid);
form.append('value', JSON.stringify({
text: tuieditor.getMarkdown(),
lastChangeTime: editorModel.lastChangeTime
}))
await fetch('/kv/set',
{
method: 'post',
body: form
}
)
console.log('note saved')
}
async function syncNote() {
try {
let res = await fetch(`/kv/get?key=${editorModel.noteid}`);
res = await res.json();
console.log('getNote in syncNote:', res);
if (res) {
res = res.value;
if (res.lastChangeTime > editorModel.lastChangeTime) {
console.log(res.lastChangeTime, editorModel.lastChangeTime);
editorModel.value = res.text;
editorModel.lastChangeTime = res.lastChangeTime || 0;
tuieditor.setMarkdown(res.text);
}
else {
saveNote();
}
}
} catch (error) {
console.log('syncNote eroor:', error);
saveNote();
}
}