Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

thank you so much 4 the espasync littlefs fsbrowser #47

Open
ldijkman opened this issue Feb 13, 2022 · 2 comments
Open

thank you so much 4 the espasync littlefs fsbrowser #47

ldijkman opened this issue Feb 13, 2022 · 2 comments

Comments

@ldijkman
Copy link

ldijkman commented Feb 13, 2022

thank you so much 4 the espasync littlefs fsbrowser

https://www.youtube.com/watch?v=1gPBMtsRDFA

greet luberth
netherlands

@ldijkman ldijkman changed the title thank you so much 4 the espsync littlefs fsbrowser thank you so much 4 the espasync littlefs fsbrowser Feb 13, 2022
@ldijkman
Copy link
Author

still playing with the editor

would like to have html preview
and
a
colorpicker addon

https://codepen.io/ldijkman/pen/LYdZpYp

2022-07-12-203422_1920x1080_scrot

2022-07-11-205741_1920x1080_scrot

@ldijkman
Copy link
Author

html preview working a bit

2022-07-16-110355_1920x1080_scrot

<!-- 
save upload or create/copy this file (as *watheveryouwanttonameit* .html)
to your ESP8266 ESP32 espasync webserver

will give you an ace js web/cloud editor with live HTML preview

not perfect but it works a bit

function update on editor textcontent change 
shows only changes after save button is pressed
reload on every key stroke
iframe shows html result
i am not handy with divs
would be nice if the source and preview divs are resizable by mouse drag
maybe a checkbox for preview panel on / off
would like to have the colorpicker addon in the code editor
https://codepen.io/ldijkman/pen/LYdZpYp
-->


<!DOCTYPE html>
<html lang="en">
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Electra's ESP Editor</title>
<link rel="apple-touch-icon" href="/ace.ico" type="image/x-icon">
<link rel="shortcut icon" href="/ace.ico" type="image/x-icon">
<link rel="icon" href="/ace.ico" type="image/x-icon">
<style type="text/css" media="screen">
  label {
    font-size: 12px;
    font-family: sans-serif
  }

  .cm {
    z-index: 300;
    position: absolute;
    left: 5px;
    border: 1px solid #444;
    background-color: #f5f5f5;
    display: none;
    box-shadow: 0 0 10px rgba(0, 0, 0, .4);
    font-size: 12px;
    font-family: sans-serif;
    font-weight: 700
  }

  .cm ul {
    list-style: none;
    top: 0;
    left: 0;
    margin: 0;
    padding: 0
  }

  .cm li {
    position: relative;
    min-width: 60px;
    cursor: pointer
  }

  .cm span {
    color: #444;
    display: inline-block;
    padding: 6px
  }

  .cm li:hover {
    background: #444
  }

  .cm li:hover span {
    color: #eee
  }

  .tvu li,
  .tvu ul {
    padding: 0;
    margin: 0;
    list-style: none
  }

  .tvu input {
    position: absolute;
    opacity: 0
  }

  .tvu {
    font: 400 12px Verdana, Arial, Sans-serif;
    -moz-user-select: none;
    -webkit-user-select: none;
    user-select: none;
    color: #444;
    line-height: 16px
  }

  .tvu span {
    margin-bottom: 5px;
    padding: 0 0 0 18px;
    cursor: pointer;
    display: inline-block;
    height: 16px;
    vertical-align: middle;
    background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADoSURBVBgZBcExblNBGAbA2ceegTRBuIKOgiihSZNTcC5LUHAihNJR0kGKCDcYJY6D3/77MdOinTvzAgCw8ysThIvn/VojIyMjIyPP+bS1sUQIV2s95pBDDvmbP/mdkft83tpYguZq5Jh/OeaYh+yzy8hTHvNlaxNNczm+la9OTlar1UdA/+C2A4trRCnD3jS8BB1obq2Gk6GU6QbQAS4BUaYSQAf4bhhKKTFdAzrAOwAxEUAH+KEM01SY3gM6wBsEAQB0gJ+maZoC3gI6iPYaAIBJsiRmHU0AALOeFC3aK2cWAACUXe7+AwO0lc9eTHYTAAAAAElFTkSuQmCC) no-repeat;
    background-position: 0 0
  }

  .tvu span:hover {
    text-decoration: underline
  }

  @media screen and (-webkit-min-device-pixel-ratio:0) {
    .tvu {
      -webkit-animation: webkit-adjacent-element-selector-bugfix infinite 1s
    }

    @-webkit-keyframes webkit-adjacent-element-selector-bugfix {
      from {
        padding: 0
      }

      to {
        padding: 0
      }
    }
  }

  #uploader {
    position: absolute;
    top: 0;
    right: 0;
    left: 0;
    height: 28px;
    line-height: 24px;
    padding-left: 10px;
    background-color: #444;
    color: #eee
  }

  #tree {
    position: absolute;
    top: 28px;
    bottom: 0;
    left: 0;
    width: 100px;
    padding: 8px
  }

  #editor,
  #preview {
    position: absolute;
    top: 28px;
    right: 0;
    bottom: 0;
    left: 120px;
    border-left: 1px solid #eee
  }

  #preview {
    background-color: #eee;
    padding: 5px
  }

  #loader {
    position: absolute;
    top: 36%;
    right: 40%
  }

  .loader {
    z-index: 10000;
    border: 8px solid #b5b5b5;
    border-top: 8px solid #3498db;
    border-bottom: 8px solid #3498db;
    border-radius: 50%;
    width: 240px;
    height: 240px;
    animation: spin 2s linear infinite;
    display: none
  }

  @keyframes spin {
    0% {
      transform: rotate(0)
    }

    100% {
      transform: rotate(360deg)
    }
  }
</style>

<style>
    body {
      font-family: 'Roboto', sans-serif;
      background-color: whitesmoke;
    }

    .p1,
    .header {
      font-size: 32px;
      text-align: center;
    }

    .button {
      text-align: center;
      font-size: 16px;
      justify-content: center;
      align-items: center;
    }

    .p2 {
      text-align: left;
      font-size: 24px;
    }

    html,
    body {
      margin: 0;
      padding: 0;
      height: 100%;
      width: 100%;
      ooverflow: hidden;
    }

    #editor {
      height: 95%;
      width: 50%;
      display: inline-block;
      border:1px solid black;
    }

    #container {
      height: 100%;
      width: auto;
      white-space: nowrap;
      ooverflow: hidden;
      position: relative;
    }



    #iframediv {
      float: right;
      margin-top: 28px;
      height: 100%; 
      width: 38%;
      display: inline-block;
      border:1px solid black;

    }
    
#iframe {
 
      top: 28px;
      height: 100%; 
      width: 100%;
      display: inline-block;
  
      
    }
    .ace_editor .ace_marker-layer .ace_bracket {
      display: none
    }
     .color {
        color: orange;   
      }
    
  </style>

<!--
AceEditor ColorPicker AddOn
https://codepen.io/easylogic/pen/RwVOGed
I made a colorpicker for ace editor. #4725
easylogic started this conversation in Ideas
https://github.com/ajaxorg/ace/discussions/4725
-->

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ace-colorpicker@0.0.12/addon/ace-colorpicker.css" />
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ace-colorpicker@0.0.12/addon/ace-colorpicker.min.js" ></script> 

<script>


   function loadpick() {  
       // does not work
      console.log("load colorpicker function loadpick");
    AceColorPicker.load(ace.edit,editor);  
    }


   function update() {  
     if(document.getElementById("Preview").checked){
        var idoc = document.getElementById('iframe').contentWindow.document;
        idoc.open();
        idoc.write(ace.edit("editor").getValue()); 
        //console.log(ace.edit("editor").getValue());
        idoc.close();
     }
    }
    
    function updatefrombutton() {  
        var idoc = document.getElementById('iframe').contentWindow.document;
        idoc.open();
        idoc.write(ace.edit("editor").getValue()); 
        //console.log(ace.edit("editor").getValue());
        idoc.close();
         document.getElementById("save").setAttribute("title", "Save file to ESP LittleFS"); 
    }
    
  function ge(e) {
    return document.getElementById(e)
  }

  function ce(e) {
    return document.createElement(e)
  }

  function sortByKey(e, t) {
    return e.sort((function(e, n) {
      var a = e[t],
        i = n[t];
      return i > a ? -1 : a > i ? 1 : 0
    }))
  }

  function createFileUploader(e, t, n) {
    var a = /(iPhone)*(OS ([7-9]|1[0-1])_)/i.test(navigator.userAgent);

    function i(e, n) {
      200 != e ? alert("ERROR[" + e + "]: " + n) : t.refreshPath(d.value)
    }
    var o = ce("button");
    o.innerHTML = "Root Dir", ge(e).appendChild(o);
    var c = ce("input");
    c.type = "file", c.multiple = !1, c.name = "data", c.id = "upload-select", ge(e).appendChild(c);
    var d = ce("input");
    d.id = "upload-path", d.type = "text", d.name = "path", d.defaultValue = "/", ge(e).appendChild(d);
    var s = ce("button");
    s.innerHTML = "Upload", ge(e).appendChild(s);
    var r = ce("button");
    r.innerHTML = "Create", ge(e).appendChild(r);
    var l = ce("input");
    l.id = "editor-filename", l.type = "text", l.disabled = !0, l.size = 20, ge(e).appendChild(l);
    var u = ce("input");
    u.id = "ipad-fix", u.title="i have no idea what this checkbox does", u.name = "ipad-fix", u.type = "checkbox", u.checked = !!a;
    var p = ce("label");
    p.for = u.id, p.innerHTML = " Alt.";
    var m = ce("button");
    m.innerHTML = " Save ",m.id = "save",m.title="Save file to ESP LittleFS", ge(e).appendChild(m), ge(e).appendChild(p), ge(e).appendChild(u), r.onclick = function(e) {
      (function(e) {
        var t = new FormData;
        t.append("path", e), requests.add("PUT", "/edit", t, i)
      })(d.value), n.loadUrl(d.value), d.value = "/"
    }, m.onclick = function(e) {
      if (u.checked) {
        var t = ace.edit("editor").getValue(),
          a = new FormData;
        a.append("rawname", l.value);
        var o = 0;
        const e = 4096;
        for (var c = 0; c < t.length; c += e) {
          var d = t.substring(c, c + e);
          a.append("raw" + o, d), o++
        }
        requests.add("POST", "/edit", a, i)
      } else n.execCommand("saveCommand")
    }, o.onclick = function(e) {
      t.refreshPath(d.value)
    }, s.onclick = function(e) {
      if (0 !== c.files.length) {
        var t = new FormData;
        t.append("data", c.files[0], d.value), requests.add("POST", "/edit", t, i), ge("upload-path").value = "/", ge("upload-select").value = ""
      }
    }, c.onchange = function(e) {
      if (0 !== c.files.length) {
        var t = c.files[0].name,
          n = /(?:\.([^.]+))?$/.exec(t)[1],
          a = /(.*)\.[^.]+$/.exec(t)[1];
        void 0 !== typeof a && (t = a), d.value = "/" + t + "." + n
      }
    }
    
     
  }

  function createTree(e, t) {
    function n(e) {
      ge("editor-filename").value = e, ge("editor").style.display = "none", p.style.display = "block", p.innerHTML = '<img src="/edit?edit=' + e + "&_cb=" + Date.now() + '" style="max-width:100%; max-height:100%; margin:auto; display:block;" />'
    }

    function a(e, a) {
      var i = ce("ul");
      e.appendChild(i);
      var o = ce("li");
      i.appendChild(o), s(a) ? (o.innerHTML = "<span>Preview</span>", o.onclick = function(t) {
        n(a), document.body.getElementsByClassName("cm").length > 0 && document.body.removeChild(e)
      }) : d(a) && (o.innerHTML = "<span>Edit</span>", o.onclick = function(n) {
        t.loadUrl(a), document.body.getElementsByClassName("cm").length > 0 && document.body.removeChild(e)
      });
      var l = ce("li");
      i.appendChild(l), d(a) || s(a) || function(e) {
        var t = /(?:.([^.]+))?$/.exec(e)[1];
        if (void 0 !== typeof t) switch (t) {
          case "ico":
          case "gz":
          case "zip":
          case "wav":
          case "mp3":
          case "pdf":
            return !0
        }
        return !1
      }(a) ? (l.innerHTML = "<span>Download</span>", l.onclick = function(t) {
        (function(e) {
          ge("download-frame").src = "/edit?download=" + e
        })(a), document.body.getElementsByClassName("cm").length > 0 && document.body.removeChild(e)
      }) : c(a) && (i.appendChild(l), l.innerHTML = "<span>ChDir</span>", l.onclick = function(t) {
        m.removeChild(m.childNodes[0]), u(m, a), document.body.getElementsByClassName("cm").length > 0 && document.body.removeChild(e)
      });
      var p = ce("li");
      i.appendChild(p), p.innerHTML = "<span>Delete</span>", p.onclick = function(t) {
        r(a), document.body.getElementsByClassName("cm").length > 0 && document.body.removeChild(e)
      }
    }

    function i(e, t, n) {
      var i = ce("div"),
        o = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop,
        c = document.body.scrollLeft ? document.body.scrollLeft : document.documentElement.scrollLeft,
        d = e.clientX + c,
        s = e.clientY + o;
      i.className = "cm", i.style.display = "block", i.style.left = d + "px", i.style.top = s + "px", a(i, t), document.body.appendChild(i);
      var r = i.offsetWidth,
        l = i.offsetHeight;
      i.onmouseout = function(e) {
        (e.clientX < d || e.clientX > d + r || e.clientY < s || e.clientY > s + l) && document.body.getElementsByClassName("cm").length > 0 && document.body.removeChild(i)
      }
    }

    function o(e, a, o) {
      var r = ce("li");
      r.id = a;
      var l = ce("span");
      return l.innerHTML = a, r.appendChild(l), r.onclick = function(e) {
        d(r.id.toLowerCase()) ? t.loadUrl(r.id) : s(r.id.toLowerCase()) ? n(r.id) : c(r.id) && (m.removeChild(m.childNodes[0]) && u(m, r.id.toLowerCase()))
      }, r.oncontextmenu = function(e) {
        e.preventDefault(), e.stopPropagation(), i(e, r.id)
      }, r
    }

    function c(e) {
      return -1 == e.indexOf(".")
    }
    
 

    function d(e) {
      var t = /(?:.([^.]+))?$/.exec(e)[1];
      if (void 0 !== typeof t) switch (t) {
        case "txt":
        case "htm":
        case "html":
        case "js":
        case "css":
        case "xml":
        case "json":
        case "conf":
        case "ini":
        case "h":
        case "c":
        case "cpp":
        case "php":
        case "hex":
        case "ino":
        case "pde":
          return !0
      }
      return !1
    }

    function s(e) {
      var t = /(?:.([^.]+))?$/.exec(e)[1];
      if (void 0 !== typeof t) switch (t) {
        case "png":
        case "jpg":
        case "gif":
        case "bmp":
          return !0
      }
      return !1
    }

    function r(e) {
      var t = new FormData;
      t.append("path", e), requests.add("DELETE", "/edit", t, (function(e, t) {
        200 != e ? alert("ERROR[" + e + "]: " + t) : (m.removeChild(m.childNodes[0]), u(m, "/"))
      }))
    }

    function l(e, t) {
      return function(t, n) {
        200 == t && function(e, t, n) {
          sortByKey(n, "name");
          var a = ce("ul");
          e.appendChild(a);
          for (var i = n.length, c = 0; i > c; c++) "file" === n[c].type && a.appendChild(o(0, n[c].name, n[c].size))
        }(e, 0, JSON.parse(n))
      }
    }

    function u(e, t) {
      requests.add("GET", "/edit", {
        list: t
      }, l(e))
    }
    var p = ge("preview"),
      m = ce("div");
    return m.className = "tvu", ge(e).appendChild(m), this.refreshPath = function(e) {
      m.removeChild(m.childNodes[0]), u(m, "/")
    }, u(m, "/"), this
  }

  function createEditor(e, t, n, a, i) {
    function o(e) {
      var t = "plain",
        n = /(?:.([^.]+))?$/.exec(e)[1];
      if (void 0 !== typeof n) switch (n) {
        case "txt":
        case "hex":
        case "conf":
          t = "plain";
          break;
        case "htm":
          t = "html";
          break;
        case "js":
          t = "javascript";
          break;
        case "h":
        case "c":
        case "cpp":
          t = "c_cpp";
          break;
        case "css":
        case "scss":
        case "php":
        case "html":
        case "json":
        case "xml":
        case "ini":
          t = n
      }
      return t
    }

    function c(e, t) {
      200 != e && alert("ERROR[" + e + "]: " + t)
    }



    function d(e, t) {
      ge("preview").style.display = "none", 
      ge("editor").style.display = "block", 
      200 == e ? s.setValue(t) : s.setValue(""), s.clearSelection()
    }
    void 0 === t && (t = "/schedule.html"), 
    void 0 === n && (n = o(t)), 
    void 0 === a && (a = "monokai"), 
    void 0 === i && (i = "text/" + n, "c_cpp" === n && (i = "text/plain"));
    var s = ace.edit(e);
    return "plain" !== n && 
    //s.session.setMode("ace/mode/"+n, () => { AceColorPicker.load(ace.edit, editor))}),
s.session.setMode("ace/mode/"+n, function() {loadpick()}),

    s.setTheme("ace/theme/" + a), 
    s.$blockScrolling = 1 / 0, 
    s.getSession().setUseSoftTabs(!0), 
    s.getSession().setTabSize(2), 
    s.getSession().setUseWorker(!0), 
    s.setHighlightActiveLine(!0), 
    s.setShowPrintMargin(!1), 
    s.getSession().on('change', function() {update()}),
    s.commands.addCommand({
      name: "saveCommand",
      bindKey: {
        win: "Ctrl-S",
        mac: "Command-S"
      },
      exec: function(e) {
        ! function(e, t, n) {
          var a = new FormData;
          a.append("data", new Blob([t], {
            type: n
          }), e), requests.add("POST", "/edit", a, c)
        }(t, e.getValue() + "", i)
      },
      readOnly: !1
    }), s.commands.addCommand({
      name: "undoCommand",
      bindKey: {
        win: "Ctrl-Z",
        mac: "Command-Z"
      },
      exec: function(e) {
        e.getSession().getUndoManager().undo(!1)
      },
      readOnly: !1
    }), s.commands.addCommand({
      name: "redoCommand",
      bindKey: {
        win: "Ctrl-Shift-Z",
        mac: "Command-Shift-Z"
      },
      exec: function(e) {
        e.getSession().getUndoManager().redo(!1)
      },
      readOnly: !1
    }), s.loadUrl = function(e) {
      ge("editor-filename").value = e, n = o(t = e), i = "text/" + n, "plain" !== n && s.getSession().setMode("ace/mode/" + n),
        function(e) {
          requests.add("GET", "/edit", {
            edit: e
          }, d)
        }(t)
    }, s
  }

  function onBodyLoad() {
    var e = {},
      t = (window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, (function(t, n, a) {
        e[n] = a
      })), createEditor("editor", e.file, e.lang, e.theme)),
      n = createTree("tree", t);
    window.define = ace.define, window.require = ace.require, ace.config.set("basePath", "/"), ace.config.set("workerPath", "/"), createFileUploader("uploader", n, t), void 0 === e.file && (e.file = "/schedule.html"), t.loadUrl(e.file)
  }
  "undefined" == typeof XMLHttpRequest && (XMLHttpRequest = function() {
    try {
      return new ActiveXObject("Msxml2.XMLHTTP.6.0")
    } catch (e) {}
    try {
      return new ActiveXObject("Msxml2.XMLHTTP.3.0")
    } catch (e) {}
    try {
      return new ActiveXObject("Microsoft.XMLHTTP")
    } catch (e) {}
    throw new Error("This browser does not support XMLHttpRequest.")
  });
  var QueuedRequester = function() {
    this.queue = [], this.running = !1, this.xmlhttp = null
  };
  QueuedRequester.prototype = {
    _request: function(e) {
      if (this.running = !0, !(!e instanceof Object)) {
        var t = this;
        ge("loader").style.display = "block";
        var n = "";
        if (e.params instanceof FormData) n = e.params;
        else if (e.params instanceof Object)
          for (var a in e.params) n += "" === n ? "GET" === e.method ? "?" : "" : "&", n += encodeURIComponent(a) + "=" + encodeURIComponent(e.params[a]);
        this.xmlhttp = new XMLHttpRequest, this.xmlhttp.onreadystatechange = function(e, n) {
          return function() {
            4 == e.readyState && (ge("loader").style.display = "none", n.callback(e.status, e.responseText), 0 === t.queue.length && (t.running = !1), t.running && t._request(t.queue.shift()))
          }
        }(this.xmlhttp, e), "GET" === e.method ? (this.xmlhttp.open(e.method, e.url + n, !0), this.xmlhttp.send()) : (this.xmlhttp.open(e.method, e.url, !0), n instanceof String && this.xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"), this.xmlhttp.send(n))
      }
    },
    stop: function() {
      this.running && (this.running = !1), this.xmlhttp && this.xmlhttp.readyState < 4 && this.xmlhttp.abort()
    },
    add: function(e, t, n, a) {
      this.queue.push({
        url: t,
        method: e,
        params: n,
        callback: a
      }), this.running || this._request(this.queue.shift())
    }
  };
  var requests = new QueuedRequester
</script>
 <script type="text/javascript" src="https://ajaxorg.github.io/ace-builds/src/ace.js"></script> 
<script>
  if (void 0 === ace.edit) {
    var script = document.createElement("script");
    script.src = "/ace.js", script.async = !1, document.head.appendChild(script)
  }
</script>

<body onload="onBodyLoad()">
<!--
would like to use / have another the colorpicker addon in the code editor
active on edited text
but i do not know how to implement it in this html/script code
https://codepen.io/ldijkman/pen/LYdZpYp
-->
  <script type="text/javascript" src="https://jscolor.com/release/2.4/jscolor-2.4.8/jscolor.js" ></script>   




<div id="container">
   <div id="loader" class="loader"></div>
    <div id="uploader">
        <div style="float:right;">
             <input type="checkbox" class="Preview" id ="Preview" name="Preview" title="reload preview on every keystroke on/off" checked>
             <input type="button" value="Preview" onClick="updatefrombutton();" title="reload by button if checkbox is off" ></label>&nbsp;&nbsp;&nbsp;
             Color: <input id="to-select-text" onClick="this.select();" value="#3399FF80" data-jscolor="{}" title="colorpicker" >
             <button id="copy-button" title="maybe copy works" >Copy</button>
        </div>
    </div>

    <div id="tree"></div>
 
    <div id="editor"></div> 
    <div id="iframediv"><iframe id="iframe" frameborder="0"></iframe></div>
  
    <div id="preview" style="display:none"></div>
    
    <iframe id="download-frame" style="display:none"></iframe>
</div>

<script>
// https://codepen.io/fabean/pen/GprQJa
let button = document.getElementById('copy-button');

button.addEventListener('click', function(e) {
  e.preventDefault();
  document.execCommand('copy', false, document.getElementById('to-select-text').select());
});
</script>

<!--  https://ldijkman.github.io/Electra/    -->

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant