integrate ydb client and adapt some demos
This commit is contained in:
@@ -2,7 +2,16 @@
|
||||
<html>
|
||||
</head>
|
||||
<script src="./index.js" type="module"></script>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
</head>
|
||||
<body contenteditable="true">
|
||||
<body>
|
||||
<div class="sidebar">
|
||||
<h3 id="createNoteButton">+ Create Note</h3>
|
||||
<div class="notelist"></div>
|
||||
</div>
|
||||
<div class="main">
|
||||
<h1 id="headline"></h1>
|
||||
<div id="editor" contenteditable="true"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
88
examples/notes/index.js
Normal file
88
examples/notes/index.js
Normal file
@@ -0,0 +1,88 @@
|
||||
/* eslint-env browser */
|
||||
|
||||
import { createYdbClient } from '../../YdbClient/index.js'
|
||||
import Y from '../../src/Y.dist.js'
|
||||
import * as ydb from '../../YdbClient/YdbClient.js'
|
||||
import DomBinding from '../../src/Bindings/DomBinding/DomBinding.js'
|
||||
|
||||
const uuidv4 = () => 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
||||
const r = Math.random() * 16 | 0
|
||||
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16)
|
||||
})
|
||||
|
||||
createYdbClient('ws://localhost:8899/ws').then(ydbclient => {
|
||||
const y = ydbclient.getY('notelist')
|
||||
let ynotelist = y.define('notelist', Y.Array)
|
||||
const domNoteList = document.querySelector('.notelist')
|
||||
|
||||
// utils
|
||||
const addEventListener = (element, eventname, f) => element.addEventListener(eventname, f)
|
||||
|
||||
// create note button
|
||||
const createNoteButton = event => {
|
||||
ynotelist.insert(0, [{
|
||||
guid: uuidv4(),
|
||||
title: 'Note #' + ynotelist.length
|
||||
}])
|
||||
}
|
||||
addEventListener(document.querySelector('#createNoteButton'), 'click', createNoteButton)
|
||||
window.createNote = createNoteButton
|
||||
window.createNotes = n => {
|
||||
y.transact(() => {
|
||||
for (let i = 0; i < n; i++) {
|
||||
createNoteButton()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// clear note list function
|
||||
window.clearNotes = () => ynotelist.delete(0, ynotelist.length)
|
||||
|
||||
// update editor and editor title
|
||||
let domBinding = null
|
||||
const updateEditor = () => {
|
||||
domNoteList.querySelectorAll('a').forEach(a => a.classList.remove('selected'))
|
||||
const domNote = document.querySelector('.notelist').querySelector(`[href="${location.hash}"]`)
|
||||
if (domNote !== null) {
|
||||
domNote.classList.add('selected')
|
||||
const note = ynotelist.toArray().find(note => note.guid === location.hash.slice(1))
|
||||
if (note !== undefined) {
|
||||
const ydoc = ydbclient.getY(note.guid)
|
||||
const ycontent = ydoc.define('content', Y.XmlFragment)
|
||||
if (domBinding !== null) {
|
||||
domBinding.destroy()
|
||||
}
|
||||
domBinding = new DomBinding(ycontent, document.querySelector('#editor'))
|
||||
document.querySelector('#headline').innerText = note.title
|
||||
document.querySelector('#editor').focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// listen to url-hash changes
|
||||
addEventListener(window, 'hashchange', updateEditor)
|
||||
updateEditor()
|
||||
|
||||
// render note list
|
||||
const renderNoteList = addedElements => {
|
||||
const fragment = document.createDocumentFragment()
|
||||
addedElements.forEach(note => {
|
||||
const a = document.createElement('a')
|
||||
a.setAttribute('href', '#' + note.guid)
|
||||
a.innerText = note.title
|
||||
fragment.insertBefore(a, null)
|
||||
})
|
||||
domNoteList.insertBefore(fragment, domNoteList.firstChild)
|
||||
}
|
||||
renderNoteList(ynotelist.toArray())
|
||||
ydb.subscribeRooms(ydbclient, ynotelist.map(note => note.guid))
|
||||
ynotelist.observe(event => {
|
||||
const addedNotes = []
|
||||
event.addedElements.forEach(itemJson => itemJson._content.forEach(json => addedNotes.push(json)))
|
||||
// const arr = ynotelist.toArray().filter(note => event.addedElements.has(note))
|
||||
renderNoteList(addedNotes.reverse())
|
||||
if (domBinding === null) {
|
||||
updateEditor()
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -1,48 +0,0 @@
|
||||
|
||||
import IndexedDBPersistence from '../../src/Persistences/IndexeddbPersistence.js'
|
||||
import YWebsocketsConnector from '../../src/Connectors/WebsocketsConnector/WebsocketsConnector.js'
|
||||
import Y from '../../src/Y.js'
|
||||
import YXmlFragment from '../../src/Types/YXml/YXmlFragment.js'
|
||||
|
||||
const yCollection = new YCollection(new YWebsocketsConnector(), new IndexedDBPersistence())
|
||||
|
||||
const y = yCollection.getDocument('my-notes')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
persistence.addConnector(persistence)
|
||||
|
||||
const y = new Y()
|
||||
await persistence.persistY(y)
|
||||
|
||||
|
||||
connector.connectY('html-editor', y)
|
||||
persistence.connectY('html-editor', y)
|
||||
|
||||
|
||||
|
||||
|
||||
window.connector = connector
|
||||
|
||||
window.onload = function () {
|
||||
window.domBinding = new DomBinding(window.yXmlType, document.body, { scrollingElement: document.scrollingElement })
|
||||
}
|
||||
|
||||
window.y = y
|
||||
window.yXmlType = y.define('xml', YXmlFragment)
|
||||
window.undoManager = new UndoManager(window.yXmlType, {
|
||||
captureTimeout: 500
|
||||
})
|
||||
|
||||
document.onkeydown = function interceptUndoRedo (e) {
|
||||
if (e.keyCode === 90 && (e.metaKey || e.ctrlKey)) {
|
||||
if (!e.shiftKey) {
|
||||
window.undoManager.undo()
|
||||
} else {
|
||||
window.undoManager.redo()
|
||||
}
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
57
examples/notes/style.css
Normal file
57
examples/notes/style.css
Normal file
@@ -0,0 +1,57 @@
|
||||
.sidebar {
|
||||
height: 100%; /* Full-height: remove this if you want "auto" height */
|
||||
width: 180px; /* Set the width of the sidebar */
|
||||
position: fixed; /* Fixed Sidebar (stay in place on scroll) */
|
||||
z-index: 1; /* Stay on top */
|
||||
top: 0; /* Stay at the top */
|
||||
left: 0;
|
||||
background-color: #111; /* Black */
|
||||
overflow-x: hidden; /* Disable horizontal scroll */
|
||||
padding-top: 20px;
|
||||
color: #50abff;
|
||||
}
|
||||
|
||||
#createNoteButton {
|
||||
padding-left: .5em;
|
||||
padding-top: .5em;
|
||||
padding-bottom: .7em;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sidebar a {
|
||||
padding: 6px 8px 6px 16px;
|
||||
text-decoration: none;
|
||||
font-size: 13px;
|
||||
color: #818181;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sidebar a.selected {
|
||||
border-style: outset;
|
||||
}
|
||||
|
||||
/* When you mouse over the navigation links, change their color */
|
||||
.sidebar a:hover {
|
||||
color: #f1f1f1;
|
||||
}
|
||||
|
||||
/* Style page content */
|
||||
.main {
|
||||
margin-left: 180px; /* Same as the width of the sidebar */
|
||||
padding: 0px 10px;
|
||||
}
|
||||
|
||||
/* On smaller screens, where height is less than 450px, change the style of the sidebar (less padding and a smaller font size) */
|
||||
@media screen and (max-height: 450px) {
|
||||
.sidebar {padding-top: 15px;}
|
||||
.sidebar a {font-size: 18px;}
|
||||
}
|
||||
|
||||
#editor {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
[contenteditable]:focus {
|
||||
outline: 0px solid transparent;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { createYdbClient } from '../../ydb/index.js'
|
||||
import { createYdbClient } from '../../YdbClient/index.js'
|
||||
import Y from '../../src/Y.dist.js'
|
||||
|
||||
createYdbClient('ws://localhost:8899/ws').then(ydbclient => {
|
||||
|
||||
Reference in New Issue
Block a user