manage selection

pull/13/head
Nicolas Sanchez 3 years ago
parent cf7243bf61
commit b301fcfa38

@ -2,3 +2,4 @@
# Accueil
## [Notes](notes)
## [Cuisine](cuisine)
[Page de tests pour le développement de CheezeNotes](test)

@ -1,6 +1,7 @@
[Accueil](accueil)
# CheezeNotes
L'objectif de CheezeNotes est de pouvoir saisir des notes avec un minimum de formatage le plus rapidement possible.
> Cette page est un bac à sable. Les modifications ne seront jamais enregistrées.
> Cette page est un bac à sable. Les modifications ne seront jamais enregistrées.
> Pour réinitialiser la page, il suffit de la recharger.
## Utilisation
Pour passer en mode édition, il suffit de cliquer sur le texte à modifier.
@ -21,6 +22,7 @@ Il y a 4 niveaux de titres :
|`*italic*`|*italic*||
|`__gras__`|__gras__||
|`_italic_`|_italic_||
|`~~barré~~`|~~barré~~||
|`***gras_italic***`|***gras_italic***||
|`___gras_italic___`|___gras_italic___|Non|
|`__*gras_italic*__`|__*gras_italic*__||

@ -0,0 +1,3 @@
[Accueil](accueil)
# Test pour développement CheezeNotes
test de gras au milieu d'un texte

@ -1,3 +1,47 @@
function insertTextAtCaret(txtBefore, txtAfter = '') {
let ret = saveSelection();
let line = ret[0];
let start = ret[1];
let end = ret[3];
let txt = line.innerText;
let before = ''
if (start == 0) {
} else {
before = txt.substring(0, start);
}
let after = txt.substring(end, txt.length);
let selection = '';
if (end > start) {
selection = txt.substring(start, end);
}
line.innerHTML = before + txtBefore + selection + txtAfter + after;
let span = document.createElement('span');
if (start == end && ret[0] == ret[2]) {
span.innerHTML = txtBefore;
ret[1] = start + span.innerText.length;
ret[3] = ret[1];
} else {
span.innerHTML = txtBefore + txtAfter;
ret[3] = end + span.innerText.length;
}
loadSelection(ret);
}
function saveSelection() {
let ret = getStartPositionInLine();
let startLine = ret[0];
let startPosition = ret[1];
ret = getEndPositionInLine();
let endLine = ret[0];
let endPosition = ret[1];
return [startLine, startPosition, endLine, endPosition];
}
function loadSelection(sel) {
setStartPositionInLine(sel[0], sel[1]);
setEndPositionInLine(sel[2], sel[3]);
}
function getStartPositionInLine() {
let selection = window.getSelection();
if (selection.rangeCount == 0) {
@ -71,4 +115,79 @@ function setStartPositionInText(obj, position) {
return 0;
}
export { getStartPositionInLine, setStartPositionInLine };
function getEndPositionInLine() {
let selection = window.getSelection();
if (selection.rangeCount == 0) {
return [null, 0];
}
let range = selection.getRangeAt(0).cloneRange();
let obj = range.endContainer;
let position = range.endOffset;
if (obj.nodeName == 'DIV' && obj.classList.contains('cheezenotes_line')) {
return [obj, position];
}
let line = null;
while (obj != null) {
if (obj.previousSibling != null) {
obj = obj.previousSibling;
if (obj.innerText != null) {
position += obj.innerText.length;
} else if (obj.length != null) {
position += obj.length;
}
} else if (obj.parentNode != null && obj.parentNode.classList != null && !obj.parentNode.classList.contains('cheezenotes_line')) {
obj = obj.parentNode;
} else if (obj.parentNode != null && obj.parentNode.classList != null && obj.parentNode.classList.contains('cheezenotes_line')) {
line = obj.parentNode;
obj = null;
} else {
obj = null;
}
}
return [line, position];
}
function setEndPositionInLine(line, position) {
setEndPositionInDiv(line, position)
}
function setEndPositionInDiv(obj, position) {
let temppos = position;
if (temppos > obj.innerText.length) {
return temppos - obj.innerText.length;
}
let children = obj.childNodes;
for (let i = 0; i < children.length; i++) {
let child = children[i];
if (child.nodeType == 3) {
temppos = setEndPositionInText(child, temppos);
} else {
temppos = setEndPositionInDiv(child, temppos);
}
if (temppos == 0) {
return temppos;
}
}
return temppos;
}
function setEndPositionInText(obj, position) {
if (position > obj.length) {
return position - obj.length;
}
let selection = window.getSelection();
let oldRange = selection.getRangeAt(0);
let range = document.createRange();
range.setStart(oldRange.startContainer, oldRange.startOffset);
range.setEnd(obj, position);
selection.removeAllRanges();
selection.addRange(range);
return 0;
}
export { saveSelection, loadSelection, insertTextAtCaret };

@ -1,4 +1,4 @@
import { getStartPositionInLine, setStartPositionInLine } from './caret.js';
import { saveSelection, loadSelection, insertTextAtCaret } from './caret.js';
import { formatLine, load, save, formatTable, redrawTables, appendData, dpwidth } from './md.js';
function timeoutSave() {
@ -17,6 +17,33 @@ function ontextarea(e) {
}
}
function onboldbutton(e) {
e.preventDefault();
let cheezenotes = document.getElementById('cheezenotes');
cheezenotes.focus();
insertTextAtCaret('**', '**');
onedit(e);
return false;
}
function onitalicbutton(e) {
e.preventDefault();
let cheezenotes = document.getElementById('cheezenotes');
cheezenotes.focus();
insertTextAtCaret('_', '_');
onedit(e);
return false;
}
function onstrikebutton(e) {
e.preventDefault();
let cheezenotes = document.getElementById('cheezenotes');
cheezenotes.focus();
insertTextAtCaret('~~', '~~');
onedit(e);
return false;
}
function onsave(e) {
let saveButton = document.getElementById('saveButton');
saveButton.disabled = true;
@ -45,7 +72,7 @@ function onedit(e) {
timeoutSave();
saveButton.disabled = false;
let ret = getStartPositionInLine();
let ret = saveSelection();
let line = ret[0];
let position = ret[1];
@ -64,7 +91,9 @@ function onedit(e) {
let newline = formatLine(line.innerText);
line.parentNode.replaceChild(newline, line);
formatTable(newline, dpwidth());
setStartPositionInLine(newline, position);
ret[0] = newline;
ret[2] = newline;
loadSelection(ret);
console.log('onedit fin');
}
@ -75,16 +104,7 @@ function onkeydown(e) {
e.preventDefault();
let key = '&emsp;';
let ret = getStartPositionInLine();
let line = ret[0];
let position = ret[1];
let txt = line.innerText;
if (position == 0) {
line.innerHTML = key + txt; // 4 espaces => &emsp;
} else {
line.innerHTML = txt.substring(0, position) + key + txt.substring(position, txt.length);
}
setStartPositionInLine(line, position + 1);
insertTextAtCaret(key);
onedit(e);
return false;
}
@ -175,6 +195,12 @@ function init(pagename = null) {
taButton.addEventListener('click', ontextarea);
let lockButton = document.getElementById('lockButton');
lockButton.addEventListener('click', onlockbutton);
let boldButton = document.getElementById('boldButton');
boldButton.addEventListener('mousedown', onboldbutton);
let italicButton = document.getElementById('italicButton');
italicButton.addEventListener('mousedown', onitalicbutton);
let strikeButton = document.getElementById('strikeButton');
strikeButton.addEventListener('mousedown', onstrikebutton);
onload();
}

@ -1,4 +1,4 @@
import { getStartPositionInLine, setStartPositionInLine } from "./caret.js";
import { saveSelection, loadSelection } from "./caret.js";
function load(textarea, div) {
div.innerHTML = '';
@ -14,7 +14,7 @@ function load(textarea, div) {
function appendData(div, data) {
const selection = window.getSelection();
selection.deleteFromDocument();
let ret = getStartPositionInLine();
let ret = saveSelection();
let line = ret[0];
let position = ret[1];
if (line == null) {
@ -41,7 +41,7 @@ function appendData(div, data) {
prevline.after(newline);
position = lines[lines.length - 1].length;
}
setStartPositionInLine(newline, position);
loadSelection([newline, position, newline, position]);
redrawTables(div, dpwidth(div));
}
@ -125,9 +125,9 @@ function formatLine(line) {
line = ret[0];
let listMono = ret[1];
// test remove link
ret = removeLink(line);
console.log('removeLink ' + ret[0]);
line = ret[0];
let listLink = ret[1];
if (line.match(/^\s*_{3,}\s*$/)) {
token = /^(\s*_{3,}\s*)$/
@ -195,10 +195,11 @@ function formatLine(line) {
if (token != null) {
line = line.replace(token, '<span class="token">$1</span>');
}
line = addLink(line);
line = addBold(line);
line = addItalic(line);
line = addStrike(line);
line = addTableLine(line);
line = addLink(line, listLink);
line = addMono(line, listMono);
elem.innerHTML = line;
if (elem.getElementsByClassName('tablerow').length > 0) {
@ -471,11 +472,33 @@ function removeLink(line) {
return [line, null];
}
line = line.replace(/(\[([^\]]*?)\]\(([^\)]*?)\))/g, "[$2]()");
line = line.replace(/(\[([^\]]*?)\]\(([^\)]*?)\))/g, "[]()");
return [line, listLink.reverse()];
}
function addLink(line) {
function addLink(line, listLink) {
if (listLink == null) {
return line;
}
let cpt = 0;
let match;
let matches = [];
let re = /\[\]\(\)/g;
while ((match = re.exec(line)) != null) {
matches[cpt] = match.index;
if (cpt > 1000) {
continue;
}
cpt++;
}
matches = matches.reverse();
for(let i=0; i<matches.length; i++) {
line = line.substring(0, matches[i]) + formatLink(listLink[i]) + line.substring(matches[i]+4, line.length);
}
return line;
}
function formatLink(line) {
line = line.replace(/(\[([^\]]+?)\]\(([^\)]+?)\))/ig, '<span class="token">[</span><a class="link" data-href="$3" href="$3">$2</a><span class="token">]($3)</span>');
line = line.replace(/(\[([^\]]+?)\]\(\))/ig, '<span class="token">[</span><a class="link" data-href="$2" href="$2">$2</a><span class="token">]()</span>');
line = line.replace(/(\[\]\(([^\)]+?)\))/ig, '<span class="token">[](</span><a class="link" data-href="$2" href="$2">$2</a><span class="token">)</span>');
@ -494,4 +517,9 @@ function addItalic(line) {
return line;
}
function addStrike(line) {
line = line.replace(/~~([^\s].*?)~~/ig, '<s><span class="token">~~</span>$1<span class="token">~~</span></s>');
return line;
}
export { load, save, formatLine, formatTable, redrawTables, dpwidth, appendData };

@ -12,7 +12,7 @@
<script type="module" src="{{ root|safe }}static/modules/cheezenotes.js"></script>
</head>
<body>
<div id="buttons"><button id="saveButton">💾</button> <input type="checkbox" id="taButton" /><label id="taButtonLabel" for="taButton">📋</label> <input type="checkbox" id="lockButton" /><label id="lockButtonLabel" for="lockButton">&#128065</label></div>
<div id="buttons"><button id="saveButton">💾</button> <input type="checkbox" id="taButton" /><label id="taButtonLabel" for="taButton">📋</label> <input type="checkbox" id="lockButton" /><label id="lockButtonLabel" for="lockButton">&#128065</label> <button id="boldButton"><b>B</b></button> <button id="italicButton"><i>I</i></button> <button id="strikeButton"><s>S</s></button></div>
<div class="ta"><textarea id="ta" class="cheezenotes" spellcheck="false">{{md}}</textarea></body><div>
<div id="cheezenotes" class="cheezenotes" contenteditable="true" spellcheck="false"></div>

Loading…
Cancel
Save