manage selection

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

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

@ -1,6 +1,7 @@
[Accueil](accueil)
# CheezeNotes # CheezeNotes
L'objectif de CheezeNotes est de pouvoir saisir des notes avec un minimum de formatage le plus rapidement possible. 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. > Pour réinitialiser la page, il suffit de la recharger.
## Utilisation ## Utilisation
Pour passer en mode édition, il suffit de cliquer sur le texte à modifier. 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*|| |`*italic*`|*italic*||
|`__gras__`|__gras__|| |`__gras__`|__gras__||
|`_italic_`|_italic_|| |`_italic_`|_italic_||
|`~~barré~~`|~~barré~~||
|`***gras_italic***`|***gras_italic***|| |`***gras_italic***`|***gras_italic***||
|`___gras_italic___`|___gras_italic___|Non| |`___gras_italic___`|___gras_italic___|Non|
|`__*gras_italic*__`|__*gras_italic*__|| |`__*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() { function getStartPositionInLine() {
let selection = window.getSelection(); let selection = window.getSelection();
if (selection.rangeCount == 0) { if (selection.rangeCount == 0) {
@ -71,4 +115,79 @@ function setStartPositionInText(obj, position) {
return 0; 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'; import { formatLine, load, save, formatTable, redrawTables, appendData, dpwidth } from './md.js';
function timeoutSave() { 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) { function onsave(e) {
let saveButton = document.getElementById('saveButton'); let saveButton = document.getElementById('saveButton');
saveButton.disabled = true; saveButton.disabled = true;
@ -45,7 +72,7 @@ function onedit(e) {
timeoutSave(); timeoutSave();
saveButton.disabled = false; saveButton.disabled = false;
let ret = getStartPositionInLine(); let ret = saveSelection();
let line = ret[0]; let line = ret[0];
let position = ret[1]; let position = ret[1];
@ -64,7 +91,9 @@ function onedit(e) {
let newline = formatLine(line.innerText); let newline = formatLine(line.innerText);
line.parentNode.replaceChild(newline, line); line.parentNode.replaceChild(newline, line);
formatTable(newline, dpwidth()); formatTable(newline, dpwidth());
setStartPositionInLine(newline, position); ret[0] = newline;
ret[2] = newline;
loadSelection(ret);
console.log('onedit fin'); console.log('onedit fin');
} }
@ -75,16 +104,7 @@ function onkeydown(e) {
e.preventDefault(); e.preventDefault();
let key = '&emsp;'; let key = '&emsp;';
let ret = getStartPositionInLine(); insertTextAtCaret(key);
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);
onedit(e); onedit(e);
return false; return false;
} }
@ -175,6 +195,12 @@ function init(pagename = null) {
taButton.addEventListener('click', ontextarea); taButton.addEventListener('click', ontextarea);
let lockButton = document.getElementById('lockButton'); let lockButton = document.getElementById('lockButton');
lockButton.addEventListener('click', onlockbutton); 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(); onload();
} }

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

@ -12,7 +12,7 @@
<script type="module" src="{{ root|safe }}static/modules/cheezenotes.js"></script> <script type="module" src="{{ root|safe }}static/modules/cheezenotes.js"></script>
</head> </head>
<body> <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 class="ta"><textarea id="ta" class="cheezenotes" spellcheck="false">{{md}}</textarea></body><div>
<div id="cheezenotes" class="cheezenotes" contenteditable="true" spellcheck="false"></div> <div id="cheezenotes" class="cheezenotes" contenteditable="true" spellcheck="false"></div>

Loading…
Cancel
Save