123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- /**
- * Loads a JavaScript file and returns a Promise for when it is loaded
- */
- const loadScript = async (src, id = undefined) => {
- return new Promise((resolve, reject) => {
- src = String(src)
- id = id || src.substring(src.lastIndexOf('/') + 1)
- const oldScript = document.getElementById(id);
- const newScript = document.createElement('script')
- newScript.id = id
- newScript.type = 'text/javascript'
- newScript.onload = resolve
- newScript.onerror = reject
- newScript.src = src
- if ((oldScript === undefined) || (oldScript === null)) {
- document.body.appendChild(newScript)
- } else {
- document.body.replaceChild(newScript, oldScript)
- }
- })
- }
- let icon = (name, width = 16, height = 16, color = 'currentColor') => {
- return `
- <svg class="bi" width="${width}" height="${height}" fill="${color}">
- <use xlink:href="/icons/icons.svg#${name}"/>
- </svg>
- `;
- }
- // Fetch Post content via AJAX
- document.querySelectorAll('.item').forEach((el) => {
- el.addEventListener('click', (event) => {
- document.querySelector('.item-selected').classList.remove('item-selected');
- event.currentTarget/*.querySelector('.item')*/.classList.add('item-selected');
- document.cookie = `currentId=${event.currentTarget.id}`
- fetch(`/posts/${event.currentTarget.id}/view`)
- .then(response => response.text())
- .then(
- data => {
- document.getElementById('main').innerHTML = data;
- loadScript('/javascripts/view.js', 'view.js');
- }
- );
- });
- });
- // POST method implementation:
- async function postData(url = '', formData) {
- let headers = new Headers();
- // headers.append('Content-Type', 'application/x-www-form-urlencoded');
- headers.append('X-Requested-With', 'XMLHttpRequest');
- // Default options are marked with *
- const response = await fetch(url, {
- method: 'POST', // *GET, POST, PUT, DELETE, etc.
- mode: 'same-origin', // no-cors, *cors, same-origin
- cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
- credentials: 'same-origin', // include, *same-origin, omit
- headers: headers,
- redirect: 'follow', // manual, *follow, error
- referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
- body: formData // body data type must match "Content-Type" header
- });
- return response.json(); // parses JSON response into native JavaScript objects
- };
- const createObjectStore = async (transaction, objectStoreName) => {
- return new Promise((resolve, reject) => {
- try {
- const objectStore = transaction.objectStore(objectStoreName)
- resolve(objectStore)
- } catch (error) {
- reject(error)
- }
- })
- }
- const createTransaction = async (db, objectStoreName, mode = 'read') => {
- return new Promise((resolve, reject) => {
- try {
- const transaction = db.transaction(objectStoreName, mode)
- console.log(`${transaction.mode} transaction has been created sucessfuly on database: ${transaction.db.name} and object store(s): ` + Array.from(transaction.objectStoreNames).join(', '))
- resolve(transaction)
- } catch (error) {
- reject(error)
- }
- })
- }
- const createDataBase = async (dbName, dbVersion = 1, onupgradeneeded = () => { }) => {
- return new Promise((resolve, reject) => {
- if (!dbName) {
- throw new Error('Param: dbName is mandatory!')
- }
- if (!window.indexedDB) {
- throw new Error('Your browser doesn\'t support a stable version of IndexedDB.')
- }
- const dbRequest = window.indexedDB.open(dbName, dbVersion)
- dbRequest.onsuccess = resolve
- dbRequest.onerror = reject
- dbRequest.onupgradeneeded = onupgradeneeded
- })
- }
- let dbExec = (documentDB, document, method = 'get') => {
- return new Promise((resolve, reject) => {
- documentDB.then(event => {
- const db = event.target.result
- createTransaction(db, 'document', 'readwrite').then(transaction => {
- createObjectStore(transaction, 'document').then(objectStore => {
- let req
- switch (method) {
- case 'put':
- req = objectStore.put(document)
- break;
- default:
- req = objectStore.get(document._id)
- break;
- }
- req.onsuccess = resolve
- req.onerror = reject
- })
- transaction.oncomplete = event => {
- console.log('Transaction completed!')
- }
- transaction.onerror = event => {
- console.log('Transaction error!')
- }
- transaction.onabort = event => {
- console.log('Transaction aborted!')
- }
- })
- }).catch(error => { throw error })
- })
- }
- const doFetch = endPoint => {
- fetch(endPoint)
- .then(response => response.text())
- .then(
- async data => {
- document.getElementById('main').innerHTML = data;
- loadScript('https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.5/codemirror.min.js')
- .then(
- () => {
- loadScript('https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.5/mode/markdown/markdown.min.js')
- .then(
- () => {
- let editor = CodeMirror.fromTextArea(
- document.getElementById('editor'),
- {
- lineNumbers: true,
- mode: 'markdown',
- lineWrapping: true
- }
- );
- editor.setSize('100%', '100%');
- editor.on('change', instance => { instance.save() })
- }
- )
- .then(
- async () => {
- fetch('/config/AUTOSAVE_FREQ')
- .then(response => response.text())
- .then(autosaveFreq => {
- if (autosaveFreq > 0) {
- const documentDB = createDataBase(
- 'markdowns',
- 1,
- // On upgrade needed
- event => {
- const db = event.target.result
- if (!db.objectStoreNames.contains('document')) {
- db.createObjectStore('document', { keyPath: '_id' })
- }
- }
- )
- let formData = new FormData(document.querySelector('form'))
- let currentContent = JSON.stringify(Array.from(formData.entries()))
- dbExec(documentDB, {
- _id: 1,
- content: currentContent
- },
- 'put'
- ).then(event => console.log(event.target.result))
- intervalId = setInterval(
- () => {
- dbExec(
- documentDB,
- {
- _id: 1
- },
- 'get'
- ).then(event => {
- let formData = new FormData(document.querySelector('form'))
- let data = {}
- // Convert Iterator to Javascript Object
- for (const key of formData.keys()) {
- data[key] = formData.get(key)
- }
- // Convert Object to JSON
- let currentContent = JSON.stringify(data)
- savedContent = event.target.result.content
- if (savedContent != currentContent) {
- const headers = new Headers({
- "Content-Type": "application/json"
- })
- const request = new Request(
- '/posts', {
- headers: headers,
- method: formData.get('id') && 'PUT' || 'POST',
- body: currentContent
- }
- )
- fetch(request).then(response => console.log(response))
- } else {
- console.log('Content are identical no autosaving!!!')
- }
- })
- },
- autosaveFreq * 1000
- )
- }
- })
- }
- )
- }
- );
- }
- ).then(() => {
- document.getElementById('post').addEventListener('submit', (e) => {
- e.preventDefault()
- })
- })
- }
- // Edit Post form
- document.querySelector('#new').addEventListener('click', event => {
- const endPoint = event.currentTarget.id == 'new' ? '/posts/new' : `/posts/${event.currentTarget.dataset.id}/${event.currentTarget.id}`
- doFetch(endPoint)
- })
|