Skip to content

Commit

Permalink
Editor document add text and delete work
Browse files Browse the repository at this point in the history
  • Loading branch information
Zekiah-A committed Mar 27, 2024
1 parent a5ed013 commit 09cb31d
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 153 deletions.
207 changes: 113 additions & 94 deletions editor-document.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ class EditorDocument {

formatToHtml(baseElement=document.createElement("div")) {
const root = baseElement
const cssFontSize = this.fontSize / this.scale
// Wrapping poems should generally be discouraged, as formatting changes may affect how it is paced
const cssFontSize = this.fontSize / this.scale
// Wrapping poems should generally be discouraged, as formatting changes may affect how it is paced
// and read, however we do not want to cut off content either so such compromise must be made...
root.style.overflow = "auto"
root.style.fontFamily = "Arial, Helvetica, sans-serif"
Expand Down Expand Up @@ -167,6 +167,8 @@ class EditorDocument {
context.clearRect(0, 0, canvas.width, canvas.height)

let line = 1
const positionContainer = this.getPositionContainer()
const containerNode = positionContainer.node
function renderFragment(data, _this) {
switch (data.type) {
case "fragment": {
Expand Down Expand Up @@ -217,6 +219,18 @@ class EditorDocument {
context.font = font.join(" ")
context.fillStyle = colour
context.fillText(data.content, 0, line * _this.fontSize)

if (data === containerNode) {
// Draw cursor (x, y, width, height)
const thisLeft = context.measureText(data.content.slice(0, positionContainer.relativePosition))
// TODO: Maintain measure width for currently line
context.fillStyle = _this.colourHex
context.fillRect(
thisLeft.width,
(line - 1) * _this.fontSize + 2,
1.5 * _this.scale,
_this.fontSize + 4)
}
break
}
case "newline": {
Expand Down Expand Up @@ -578,94 +592,98 @@ class EditorDocument {
+ '\uE002'
+ this.data.slice(this.position)
}
}

getText() {
let text = ""
function visitNode(data) {
switch (data.type) {
case "fragment":
for (let i = 0; i < data.children.length; i++) {
const child = data.children[i]
visitNode(child)
}
break
case "text":
text += data.content
break
}
}
visitNode(this.data)
return text
}

// Finds the node which contains the cursor currently
getPositionContainer() {
let currentlyAt = 0
function visitNode(data, _this) {
switch (data.type) {
case "fragment":
for (let i = 0; i < data.children.length; i++) {
const child = data.children[i]
const found = visitNode(child, _this)
if (found) {
return found
}
}
return data
case "text":
currentlyAt += data.content.length
if (currentlyAt >= _this.position) {
return data
}
break
}

return null
}
return visitNode(this.data, this)
}

// Creates a new text node at cursor position containing given text
addText(value) {
if (this.hasSelection()) {
this.deleteSelection()
}

const container = this.getPositionContainer()
if (container === null) {
return new Error("Couldn't add text, cursor position outside of document nodes range")
}
// Empty fragment, create new text node
if (container.type === "fragment") {
const textContainer = new Text(value)
container.children.push(textContainer)
}
else {
// TODO: Split current text in half? Put new text node inbetween?
}
this.position += value.length
}

}

getText() {
let text = ""
function visitNode(data) {
switch (data.type) {
case "fragment":
for (let i = 0; i < data.children.length; i++) {
const child = data.children[i]
visitNode(child)
}
break
case "text":
text += data.content
break
}
}
visitNode(this.data)
return text
}

// Finds the node which contains the cursor currently
getPositionContainer() {
let nodeStart = 0
let currentlyAt = 0
function visitNode(data, _this) {
switch (data.type) {
case "fragment":
for (let i = 0; i < data.children.length; i++) {
const child = data.children[i]
const found = visitNode(child, _this)
if (found) {
return found
}
}
return data
case "text":
nodeStart = currentlyAt
currentlyAt += data.content.length
if (currentlyAt >= _this.position) {
return data
}
break
}

return null
}
return {
node: visitNode(this.data, this),
relativePosition: this.position - nodeStart
}
}

getParentNode(targetNode) {
function visitNode(data, _this) {
if (data.type === "fragment") {
for (const child of data.children) {
if (child === targetNode) {
return child
}
return visitNode(child, _this)
}
}

return null
}

return visitNode(this.data, _this)
}

// Attempts to create or append to text node at cursor position containing given text
appendText(value) {
insertText(value) {
if (this.hasSelection()) {
this.deleteSelection()
}

const container = this.getPositionContainer()
if (container === null) {
return new Error("Couldn't add text, cursor position outside of document nodes range")
}
// Empty fragment, create new text node
if (container.type === "fragment") {
const textContainer = new Text(value)
container.children.push(textContainer)
}
else {
container.content += value
}
this.position += value.length

const container = this.getPositionContainer()
if (container.node === null) {
return new Error("Couldn't add text, cursor position outside of document nodes range")
}
// Empty fragment, create new text node
if (container.node.type === "fragment") {
const textContainer = new Text(value)
container.node.children.push(textContainer)
}
else if (container.node.type === "text") {
container.node.content += value
}
else {
throw new Error("Not implemented")
}
this.position += value.length
}

addNewLine() {
Expand All @@ -688,15 +706,16 @@ class EditorDocument {
if (this.hasSelection()) {
this.deleteSelection()
}
else {
// TODO: This will be painful to handle across node boundaries
if (count > 0) {
this.data = this.data.slice(0, this.position - count) + this.data.slice(this.position)
this.position = Math.max(0, this.position - count)
}
else {
this.data = this.data.slice(0, this.position) + this.data.slice(this.position - count)
else {
// TODO: This will be painful to handle across node boundaries
const container = this.getPositionContainer()
const node = container.node
if (node === null) {
return new Error("Couldn't delete text, cursor position outside of document nodes range")
}

node.content = node.content.slice(0, this.position - count) + node.content.slice(this.position)
this.position = Math.max(0, this.position - count)
}
}

Expand Down
16 changes: 13 additions & 3 deletions poem-editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
max-width: 100%;
overflow-x: visible;
}
#formattingToolbar > div {
.toolbar-item {
height: 32px;
width: 32px;
min-width: 32px;
Expand All @@ -107,15 +107,18 @@
border-radius: 4px;
user-select: none;
padding: 1px;
border: none;
transition: .05 transform;
}
#formattingToolbar > div:active {
.toolbar-item:active {
transform: scale(0.98);
}
#formattingToolbar > div > div {
.toolbar-item > div {
background-color: var(--button-transparent);
border-radius: 4px;
pointer-events: none;
font-family: Arial, Helvetica, sans-serif;
font-size: 16px;
}
.separator {
background: transparent;
Expand All @@ -127,6 +130,13 @@
margin-right: 8px;
flex-grow: 1;
}
#formattingColourRect {
background-color: black;
width: calc(100% - 2px);
height: calc(100% - 2px);
margin: 1px;
border-radius: 4px;
}
#poem-tags button {
border-radius: 4px;
margin: 2px;
Expand Down
Loading

0 comments on commit 09cb31d

Please sign in to comment.