DEV Community

artydev
artydev

Posted on

1 1

Implementing a BlocNote with Jodit

Here is the first draft of a personnal project.

It's implemented using Mithril, but you can use whatever frontend library you want (uhtml,react,vue...jquery...).

The main point is that it uses the Meiosis pattern and BrowserFS for localStorage.

For the css part I use w3css.

Actual features :

  • You can save a note
  • You can display the notes list
  • You can edit a note

more to come....

You can test it here BN

<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jodit/3.4.11/jodit.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/BrowserFS/2.0.0/browserfs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jodit/3.4.11/jodit.min.js"></script>


<div class="w3-container">
  <div id="app">

  </div>
</div>

Enter fullscreen mode Exit fullscreen mode
const merge = mergerino

const [div, span, ul, button, li] = ["div", "span", "ul", "button", "li"]

console.log(span)

const state = {
    count: 0,
    displayEditor: "block",
    displayExplorer: "none",
    contentEditor : "",
    readedFileContent: "",
    readedFileName: "",
    sesamfiles : []
}

const update = m.stream();
const states = m.stream.scan(merge, state, update)
const actions = Actions(update)

// Setup FileSystem
function setupFS() {
    BrowserFS.install(window);
    BrowserFS.configure({
        fs: "LocalStorage"
    }, function(e) {
        if (e) {
            throw e;
        }
        fs = require('fs');
    });
}

// Setup Editor
function setupEditor() {
    let saveButton = {
        text: "save",
        tooltip: "Sauvegarder le contenu de l'éditeur",
        iconURL: "https://uxwing.com/wp-content/themes/uxwing/download/03-text-editing/save.png",
        exec: actions.saveEditor
    }
    let listNotesButton = {
        text: "LIST",
        tooltip: "Lister les notes",
        exec: actions.showExplorer
    }
    let options = [
        "bold", "|", "underline", "|", ,
        "ul",
        "align", "|",
        "image", "|",
        saveButton,
        listNotesButton, "|",
        "fullsize", "|"
    ]
    editor = new Jodit("#editor", {
        sizeLG: 900,
        sizeMD: 700,
        sizeSM: 400,
        buttons: options,
        buttonsMD: options,
        buttonsSM: options,
        buttonsXS: options,
        enter: "div",
        language: "fr",
        uploader: {
            insertImageAsBase64URI: true
        },
        imageDefaultWidth: 300
    });
}

// Define all actions of the app
function Actions (update) {
  const actions = {
      showExplorer: function () {
          actions.readDir()
          update({
              displayEditor: "none",
              displayExplorer: "block",
          })
      },
      showEditor: function () {
          update({
              displayEditor: "block",
              displayExplorer: "none"
          })
      },
      saveEditor: function () {
        let content = editor.getEditorValue()                
        if (!content) return;
        let filename = prompt("nom du fichier : ")
        if (!filename) return;
        filename = `sesam-${filename}`
        update({
          contentEditor: content
        })
        fs.writeFile(filename, content, function(err) {
          fs.readFile(filename, function(err, contents) { 
            console.log(states().contentEditor);
          });
        });
      },
      readDir : function () {
         fs.readdir('/', (e, files) => {
            const sesamfiles = files.filter((f) => f.startsWith("sesam") )
            const count = sesamfiles.length
            update({ sesamfiles, count })
          })           
      },
      readFile: function (readedFileName) {
        fs.readFile(readedFileName, function(err, content) { 
            const readedFileContent = bufferToString(content)             
            update({readedFileContent, readedFileName})
            actions.showEditor()
            editor.setEditorValue(states().readedFileContent) 
        });
      }
  }
  return actions;
}

// Render a file item
function renderFileItem (filename) {
  const vnode = m("li", {onclick: () => actions.readFile(filename)}, filename)
  return vnode
}

function Explorer (state) {
  return  [ 
    m(div, "Explorer " + `nbre de fichiers : ${state.count}`),
    m(button,{onclick:actions.showEditor} ,"showeditor"),
    m(div, state.sesamfiles.map(renderFileItem))
  ]
}

function view(state, actions) {
  let style = (status) => ({style: `display:${status}`})
  m.render(app, [
   m(div, style(state.displayExplorer), Explorer(state)),
   m(div, style(state.displayEditor), m("#editor")) 
  ])
}

function main () {  
  setupFS()
  states.map(state =>  view(state, actions)) 
  setupEditor()
}

main()

/**** tools ***/
function bufferToString(buff) {
  return  String.fromCharCode.apply(null, new Uint16Array(buff)) 
}
Enter fullscreen mode Exit fullscreen mode

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

Top comments (0)

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay