|
@@ -27,10 +27,6 @@ TODO
|
|
|
[ ] greenlist of top level elements, strip everything else
|
|
|
[ ] selection styling (bold, italic). I actually think there's contenteditable commands to apply these things?
|
|
|
|
|
|
-[ ] Insertion Points
|
|
|
- [ ] find closest block to the cursor
|
|
|
- [ ] easy if under cursor
|
|
|
- [ ] use `elementFromPoint` to find neightbors in 4 directions
|
|
|
|
|
|
[ ] drag and drop restructuring
|
|
|
[ ] generic system, will use in sidebar and document
|
|
@@ -61,14 +57,9 @@ BUGS
|
|
|
[ ] <img> are really hard to edit around, should these be wrapped in a div or something?
|
|
|
[ ] 'li' has different positioning in chrome vs firefox
|
|
|
[ ] pasting blocks picks up style as inline, which breaks things
|
|
|
-[x] drag block is covering up li bullet point
|
|
|
-[x] block dragged to original position dissapears
|
|
|
-[x] drag insertion point uses border which jostles position a bit
|
|
|
[ ] selection/insertion is triggering history states
|
|
|
-[x] bug moving h1 to end of document
|
|
|
-[x] hover target needs to bubble up
|
|
|
-[x] order of selection needs to be preserved?
|
|
|
[ ] todo blocks need mouse events for more than just the checkbox (should check bounds on the rect for toggling it)
|
|
|
+[ ] chrome - when trying to drag a block that is partially range selected the selection collapses and it fails
|
|
|
|
|
|
Today's project
|
|
|
[ ] I'm in need of a debug section that shows the current range with live update
|
|
@@ -89,6 +80,13 @@ Today's project
|
|
|
[/] insertion has 'in', 'before', 'after', 'left', 'right' detection
|
|
|
[x] drop inserts selected elements
|
|
|
[x] collapsed cursor selection shouldn't trigger 'selected'?
|
|
|
+ [ ] change 'target' and 'selection' from classes to a list of elements - this should some bugs with platform dragging and
|
|
|
+ avoids issues with history saving changes to ephemeral classes
|
|
|
+ [ ] the handles should be their own nodes outside of the note that are positioned
|
|
|
+ [x] reimplement the ondrag handler
|
|
|
+ [x] note should still have it's drag/drop prevented
|
|
|
+ [ ] single mouse target should get a handle too
|
|
|
+ [ ] SELECTION needs to include TARGET and be ordered correctly
|
|
|
|
|
|
|
|
|
|
|
@@ -259,26 +257,14 @@ Today's project
|
|
|
note > * {
|
|
|
position: relative;
|
|
|
}
|
|
|
- note > *.selected::after {
|
|
|
- content: '';
|
|
|
- display: block;
|
|
|
+
|
|
|
+ selection {
|
|
|
position: absolute;
|
|
|
- left: -16px;
|
|
|
- top: 0em;
|
|
|
- width: 12px;
|
|
|
- border-right: 4px solid white;
|
|
|
- height: 100%;
|
|
|
+ display: block;
|
|
|
cursor: grab;
|
|
|
pointer-events: auto;
|
|
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAABbmlDQ1BpY2MAACiRdZG9S0JhFIcftTDKkFAiosHBokEhCqKxbHCREDPIatHrV+DH5V4lpDVoaRAaopa+hv6DWoPWgiAogojG5r6WkNu5Kiih5/Le8/B7z+9w7rlgDeWUvN4zD/lCSYsEA57V2JrH/o4FF26GGYoruroQDofoGj+PUi3x4Dd7da/rGAPJlK6ApU94VlG1krBMQ2irpJq8J+xWsvGk8ImwT5MBhW9NPdHgN5MzDf4yWYtGFsFq9vRk2jjRxkpWywtPCnvzubLSnMf8EkeqsLIseVTOGDoRggTwkKDMJjlK+CUXZGedfVN13xJF8SjyVqmgiSNDVrw+UcvSNSU5LXpKnhwVc+//96mnZ6Yb3R0B6H01jM9xsO9DrWoYv6eGUTsD2wtcF1r+ouxp7lv0akvzHoNzBy5vWlriAK52YeRZjWvxumSTY02n4eMCBmPguof+9caumvecP0F0W37RHRwewYTUOzf+AOECZ/uSmLScAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAKklEQVQIW2P8DwQMSIAJxG5oaGA4cuQIRBikYvv27f/fv38PYv5nRNcCAFvgGrGltVmQAAAAAElFTkSuQmCC)
|
|
|
- }
|
|
|
-
|
|
|
- note > li.selected::after {
|
|
|
- left: -29px;
|
|
|
- }
|
|
|
-
|
|
|
- note.dragging .selected {
|
|
|
- opacity: 0.5;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/* note *::before, note *::after {
|
|
@@ -305,8 +291,10 @@ Today's project
|
|
|
</sidebar>
|
|
|
<document>
|
|
|
<h1 id="title" contenteditable="true">title</h1>
|
|
|
- <note draggable="true" contenteditable="true" ></note>
|
|
|
+ <note contenteditable="true" ></note>
|
|
|
</document>
|
|
|
+ <selection draggable="true"></selection>
|
|
|
+ <selection draggable="true"></selection>
|
|
|
|
|
|
<!-- https://unicode.org/emoji/charts-12.0/emoji-style.html
|
|
|
res = []; document.querySelectorAll("a.plain").forEach((el)=>res.push(el.textContent)) -->
|
|
@@ -317,6 +305,8 @@ emoji = ["☹️","☠️","❣️","❤️","🕳️","🗨️","🗯️","🖐
|
|
|
<script>
|
|
|
const DOC_VERSION = 0;
|
|
|
var note = null;
|
|
|
+ var TARGET = null;
|
|
|
+ var SELECTION = [];
|
|
|
|
|
|
Array.prototype.distinct = function(){
|
|
|
let res = []
|
|
@@ -573,7 +563,7 @@ emoji = ["☹️","☠️","❣️","❤️","🕳️","🗨️","🗯️","🖐
|
|
|
}
|
|
|
}
|
|
|
res = res.map((n)=> n.nodeName === "#text" ? n.parentNode : n)
|
|
|
- return res.distinct().filter(e=>e != document.querySelector("note"))
|
|
|
+ return res.distinct().filter(e=>document.querySelector("note").contains(e))
|
|
|
}
|
|
|
|
|
|
function SaveSelection(){
|
|
@@ -687,36 +677,56 @@ emoji = ["☹️","☠️","❣️","❤️","🕳️","🗨️","🗯️","🖐
|
|
|
|
|
|
|
|
|
// track blocks under mouse and under selection. Should probably also detect 'child' indentation blocks
|
|
|
+ addEventListener("mousemove", (e) => {window.X = e.clientX; window.Y = e.clientY})
|
|
|
|
|
|
document.querySelector("note").onmousemove = e => {
|
|
|
+
|
|
|
// TODO get top level block
|
|
|
- document.querySelectorAll(".target").forEach((el)=>el.classList.remove("target"))
|
|
|
- document.querySelectorAll(".selected").forEach((el)=>el.classList.remove("selected"))
|
|
|
let target = BubbledBlock(e.target)
|
|
|
- if (target) {
|
|
|
- target.classList.add("target")
|
|
|
- target.classList.add("selected")
|
|
|
- }
|
|
|
+ SELECTION = []
|
|
|
let r = CurrentRange()
|
|
|
if (r && !r.collapsed) {
|
|
|
for (e of SelectedElements()) {
|
|
|
- e.classList.add("selected")
|
|
|
+ SELECTION.push(e)
|
|
|
}}
|
|
|
+ TARGET = target
|
|
|
+
|
|
|
+ let a = document.querySelectorAll("selection")[0]
|
|
|
+ let b = document.querySelectorAll("selection")[1]
|
|
|
+ if (SELECTION.length > 0) {
|
|
|
+ let b1 = SELECTION[0].getBoundingClientRect()
|
|
|
+ let b2 = SELECTION[SELECTION.length-1].getBoundingClientRect()
|
|
|
+ let groupb = SELECTION[0].parentNode.getBoundingClientRect()
|
|
|
+ a.style.left = `${groupb.left-12}px`
|
|
|
+ a.style.top = `${b1.top}px`
|
|
|
+ a.style.width = `24px`
|
|
|
+ a.style.height = `${b2.bottom-b1.top}px`
|
|
|
+ } else {
|
|
|
+ a.style.top = "-100px"
|
|
|
+ a.style.height = "0px"
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
// Insertion stuff
|
|
|
INSERTING = false
|
|
|
|
|
|
function BRectDistance(rect, x, y) {
|
|
|
var dx = Math.max(rect.left - x, 0, x - rect.right);
|
|
|
var dy = Math.max(rect.top - y, 0, y - rect.bottom);
|
|
|
- return Math.sqrt(dx*dx + dy*dy);
|
|
|
+ return Math.sqrt(dx*dx + dy*dy)
|
|
|
}
|
|
|
|
|
|
function ClosestChild(el, x, y) {
|
|
|
let nodes = []
|
|
|
for (e of el.childNodes) {
|
|
|
- if (!e.classList.contains("selected")) {
|
|
|
+ if (!SELECTION.includes(e) && !(TARGET == e)) {
|
|
|
nodes.push(e)
|
|
|
}
|
|
|
}
|
|
@@ -725,6 +735,7 @@ emoji = ["☹️","☠️","❣️","❤️","🕳️","🗨️","🗯️","🖐
|
|
|
}
|
|
|
|
|
|
document.ondragover = (e) => {
|
|
|
+
|
|
|
if (INSERTING) {
|
|
|
document.querySelectorAll(".insertion").forEach((el)=>{
|
|
|
el.classList.remove("insertion")
|
|
@@ -745,22 +756,19 @@ emoji = ["☹️","☠️","❣️","❤️","🕳️","🗨️","🗯️","🖐
|
|
|
}
|
|
|
|
|
|
document.querySelector("note").ondragstart = e => {
|
|
|
- document.querySelector("note").classList.add("dragging")
|
|
|
- let target = document.querySelector(".target")
|
|
|
- if (target && ValidBlockType(target)){
|
|
|
- let bounds = target.getBoundingClientRect()
|
|
|
- let x = e.clientX
|
|
|
- let y = e.clientY
|
|
|
- if (bounds.left - 20 < x < bounds.left - 4 && bounds.top < y < bounds.bottom) {
|
|
|
- INSERTING = [... document.querySelectorAll(".selected")]
|
|
|
- e.dataTransfer.setDragImage(Render(["div", "hello"]), 0, 0);
|
|
|
- return
|
|
|
- }
|
|
|
- }
|
|
|
e.preventDefault()
|
|
|
}
|
|
|
|
|
|
- document.querySelector("note").ondragend = e => {
|
|
|
+
|
|
|
+ document.querySelector("selection").ondragstart = e => {
|
|
|
+ document.querySelector("note").classList.add("dragging")
|
|
|
+ INSERTING = [... SELECTION]
|
|
|
+ e.dataTransfer.setDragImage(Render(["div", "hello"]), 0, 0);
|
|
|
+ console.log("DRAG START", TARGET)
|
|
|
+ }
|
|
|
+
|
|
|
+ document.querySelector("selection").ondragend = e => {
|
|
|
+ console.log("DRAG END")
|
|
|
document.querySelector("note").classList.remove("dragging")
|
|
|
let point = document.querySelector(".insertion")
|
|
|
if (INSERTING && point && !INSERTING.includes(point)) {
|
|
@@ -780,12 +788,22 @@ emoji = ["☹️","☠️","❣️","❤️","🕳️","🗨️","🗯️","🖐
|
|
|
document.querySelectorAll(".insertion").forEach((el)=>el.classList.remove("insertion"))
|
|
|
INSERTING = false
|
|
|
}
|
|
|
+
|
|
|
document.querySelector("note").ondrop = e => {
|
|
|
e.preventDefault()
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
|
|
|
document.querySelector("note").addEventListener("input", ()=>{LintNote(); SyncContent()}, false)
|
|
|
document.querySelector("#title").addEventListener("input", ()=>{SyncContent(); RenderSidebar()}, false)
|