diff --git a/static/css/notes2.css b/static/css/notes2.css
index f7051f3..28ee7a2 100644
--- a/static/css/notes2.css
+++ b/static/css/notes2.css
@@ -21,7 +21,8 @@ html {
}
button {
- font-size: 1e m;
+ font-size: 1em;
+ padding: 4px 8px;
}
/* ------------------------------------- *
@@ -546,7 +547,7 @@ n2-pagehistory {
padding: 32px;
margin-bottom: 32px;
border-radius: 8px;
- background-color: #f8f8f8;
+ background-color: #fafafa;
box-shadow:
rgba(0, 0, 0, 0.4) 0px 2px 4px,
@@ -585,62 +586,72 @@ n2-pagehistory {
gap: 1px;
border: 1px solid var(--line-color);
- &>div>div {
+ n2-pagehistorynode>* {
padding: 8px 12px;
background-color: #fff;
white-space: nowrap;
+ }
- &.index {
+ n2-pagehistorynode {
+
+ &.selected .el-index:after {
+ position: absolute;
+ left: -20px;
+
+ content: '>';
+ color: var(--color1);
+ font-weight: bold;
+ margin-right: 8px;
+ }
+
+ .el-index {
+ position: relative;
text-align: right;
}
- &.updated {
+ .el-updated {
white-space: initial;
}
- .date {
+ .el-date {
white-space: nowrap;
font-weight: bold;
}
- .time {
+ .el-time {
white-space: nowrap;
color: #555;
}
- &.name {
+ .el-name {
white-space: initial;
/*overflow-wrap: anywhere;*/
word-break: break-all;
color: var(--color1);
-
}
}
-
- .history-node {
- display: contents;
- }
- }
-
- .el-pagination {
- grid-column: 1 / -1;
- margin-top: 16px;
-
- display: grid;
- grid-template-columns: repeat(3, min-content);
- grid-gap: 16px;
- align-items: center;
- white-space: nowrap;
- user-select: none;
-
- .el-prev,
- .el-next {
- font-weight: bold;
- cursor: pointer;
- border: 1px solid #aaa;
- background-color: #eee;
- padding: 8px 16px;
- border-radius: 4px;
- }
}
}
+
+.el-pagination {
+ grid-column: 1 / -1;
+ margin-top: 16px;
+
+ display: grid;
+ grid-template-columns: repeat(3, min-content);
+ grid-gap: 16px;
+ align-items: center;
+ white-space: nowrap;
+ user-select: none;
+
+ .el-prev,
+ .el-next {
+ font-weight: bold;
+ cursor: pointer;
+ border: 1px solid #aaa;
+ background-color: #eee;
+ padding: 8px 16px;
+ border-radius: 4px;
+ }
+}
+}
diff --git a/static/js/page_history.mjs b/static/js/page_history.mjs
index f37cfbb..37404c7 100644
--- a/static/js/page_history.mjs
+++ b/static/js/page_history.mjs
@@ -1,5 +1,7 @@
import { CustomHTMLElement } from './lib/custom_html_element.mjs'
import { Node } from './page_node.mjs'
+import { MarkedPosition } from './marked_position.mjs'
+
export class N2PageHistory extends CustomHTMLElement {
static PAGESIZE = 15
@@ -47,11 +49,14 @@ export class N2PageHistory extends CustomHTMLElement {
>
+
+
`
}// }}}
constructor() {// {{{
super()
+ this.selectedNode = null
this.setAttribute('tabindex', '-1')
this.addEventListener('keydown', event => this.keyHandler(event))
@@ -72,6 +77,10 @@ export class N2PageHistory extends CustomHTMLElement {
await this.useNode(event.detail.data)
this.render()
})
+
+ _mbus.subscribe('HISTORY_NODE_SELECTED', (event) => {
+ this.selectedNode = event.detail.data.historyNode
+ })
}// }}}
async render(keepFetchHistoryProgress) {// {{{
this.elNodeName.innerText = this.node.get('Name')
@@ -88,24 +97,26 @@ export class N2PageHistory extends CustomHTMLElement {
let i = 0
let divs = nodes.map(n => {
i++
-
- const date = n.get('Updated').slice(0, 10)
- const time = n.get('Updated').slice(11, 19)
-
- const div = document.createElement('div')
- div.innerHTML = `
- ${1 + this.nodesTotal - (N2PageHistory.PAGESIZE * (this.page - 1) + i)}
- ${date} ${time}
- ${this.formatSize(n.get('Content').length)}
- ${n.get('Name')}
- `
- div.classList.add('history-node')
+ const index = 1 + this.nodesTotal - (N2PageHistory.PAGESIZE * (this.page - 1) + i)
+ const div = new N2PageHistoryNode(n, index)
+ div.render()
return div
})
this.elNodes.replaceChildren(...divs)
if (!keepFetchHistoryProgress)
this.elFetchHistoryProgress.innerText = ''
+
+ // Select the first node.
+ if (!this.selectedNode) {
+ this.elNodes.firstElementChild?.select()
+ }
+
+ // Any selected history node is rendered with markdown.
+ /*
+ this.marked = new MarkedPosition()
+ this.elNodeMarkdown.innerHTML = this.marked.parse(this.elNodeContent.value)
+ */
}// }}}
async useNode(node) {// {{{
@@ -124,18 +135,33 @@ export class N2PageHistory extends CustomHTMLElement {
case 'ArrowRight':
this.nextPage()
break
+ case 'ArrowUp':
+ const prevNode = this.selectedNode?.previousElementSibling
+ if (prevNode)
+ prevNode.select()
+ break
+ case 'ArrowDown':
+ const nextNode = this.selectedNode?.nextElementSibling
+ if (nextNode)
+ nextNode.select()
+ break
}
}// }}}
prevPage() {// {{{
if (this.page == 1)
return
+
+ // Selecting a node on another page is wrong.
+ this.selectedNode = null
this.page--
this.render()
}// }}}
nextPage() {// {{{
if (this.page >= this.pages)
return
+ // Selecting a node on another page is wrong.
+ this.selectedNode = null
this.page++
this.render()
}// }}}
@@ -199,6 +225,61 @@ export class N2PageHistory extends CustomHTMLElement {
return json
}// }}}
+}
+customElements.define('n2-pagehistory', N2PageHistory)
+
+
+class N2PageHistoryNode extends CustomHTMLElement {
+ static {// {{{
+ this.tmpl = document.createElement('template')
+ this.tmpl.innerHTML = `
+
+
+
+
+ `
+ }// }}}
+ constructor(node, index) {// {{{
+ super()
+
+ this.node = node
+ this.index = index
+
+ this.style.display = 'contents'
+ this.selected = false
+
+ this.addEventListener('click', () => this.select())
+
+ // Another history node has been selected.
+ _mbus.subscribe('HISTORY_NODE_SELECTED', (event) => {
+ if (this.node.get('Updated') == event.detail.data.historyNode.node.get('Updated'))
+ return
+ this.selected = false
+ this.render()
+ })
+ }// }}}
+
+ select() {// {{{
+ this.selected = true
+ // Other nodes are told to unselect and rerender.
+ _mbus.dispatch('HISTORY_NODE_SELECTED', { historyNode: this })
+ this.render()
+ }// }}}
+ render() {// {{{
+ const date = this.node.get('Updated').slice(0, 10)
+ const time = this.node.get('Updated').slice(11, 19)
+
+ if (this.selected)
+ this.classList.add('selected')
+ else
+ this.classList.remove('selected')
+
+ this.elIndex.innerText = this.index
+ this.elDate.innerText = date
+ this.elTime.innerText = time
+ this.elSize.innerText = this.node.get('Content').length
+ this.elName.innerText = this.node.get('Name')
+ }// }}}
formatSize(s) {// {{{
let div = 1
let unit = 'B'
@@ -215,4 +296,4 @@ export class N2PageHistory extends CustomHTMLElement {
}).format(Math.round(s / div)) + ' ' + unit
}// }}}
}
-customElements.define('n2-pagehistory', N2PageHistory)
+customElements.define('n2-pagehistorynode', N2PageHistoryNode)