markdown-live-preview icon indicating copy to clipboard operation
markdown-live-preview copied to clipboard

suggestion: Toggle Editor (and also horizontal resizer)

Open DarrenSem opened this issue 1 year ago • 1 comments

Sometimes I find the "editor" div a bit distracting after I paste in the MarkDown contents, so I wrote some CSS and JS to add a new "Toggle Editor" link to the top button bar, along with a green vertical bar in the middle of the 2 divs that you can drag-resize left or right.

I have only tried this in Chrome on desktop, not yet tested this in mobile etc. But for my needs it works well, I am quite happy with it.

Extra HTML: (added "toggleButton" next to "Copy" button, and added "resizer" div between "edit" and "preview")

  <div id="toggleButton"><a href="#">Toggle Editor</a></div>
...
  <div id="edit">...</div>
  <div id="resizer"></div>
  <div id="preview">...</div>

Extra CSS:

    body {
      margin: 0; /* Remove default margin */
      height: 100vh; /* Ensure full height usage */
      overflow: hidden; /* Prevent body scrollbars */
    }
    #container {
      display: flex;
      width: 100%;
      height: 100%; /* Full height of the parent */
      overflow: hidden;
    }
    #edit, #preview {
      flex-grow: 1;
      overflow: auto; /* Enable scrolling for content overflow */
      transition: flex 0.3s ease;
    }
    #resizer {
      width: 4px; /* Updated resizer width */
      background-color: green;
      cursor: col-resize;
      flex-shrink: 0; /* Prevent shrinking */
    }
    #toggleButton {
      margin-left: 16px; /* Ensure it doesn't overflow to hide */
    }
    .shrunk {
      flex: 0 0 0px !important;
    }

Extra JavaScript:

  const container = document.getElementById("container");
  const edit = document.getElementById("edit");
  const preview = document.getElementById("preview");
  const resizer = document.getElementById("resizer");
  const toggleButton = document.getElementById("toggleButton");
  const MIN_EDIT_WIDTH = 72; // Minimum width for the editor div

  let isMouseDown = false;

  resizer.addEventListener("mousedown", (e) => {
    isMouseDown = true;
    document.addEventListener("mousemove", resize);
    document.addEventListener("mouseup", stopResize);
  });

  function resize(e) {
    if (!isMouseDown) return;
    const containerRect = container.getBoundingClientRect();
    const newEditWidth = e.clientX - containerRect.left;

    if (newEditWidth >= MIN_EDIT_WIDTH) {
      edit.classList.remove("shrunk");
      edit.style.flex = `0 0 ${newEditWidth}px`;
      preview.style.flex = `1 1 auto`;
    }
  }

  function stopResize() {
    isMouseDown = false;
    document.removeEventListener("mousemove", resize);
    document.removeEventListener("mouseup", stopResize);
  }

  function toggleEditor() {
    edit.classList.toggle("shrunk");
  }

  toggleButton.addEventListener("click", toggleEditor);

NOTE: some of the CSS is the result of some back-and-forth tweaking via ChatGPT, so I'm not sure if they are the best way or might cause problems and/or the comments are even accurate, but again it seems to work #GoodEnough for my needs.

HTH!

DarrenSem avatar May 27 '24 14:05 DarrenSem

I made a Bookmarklet, which will insert the required HTML and CSS and JavaScript (and will also redirect to MarkdownLivePreview.com if not on that page).

I also made it re-center the splitter if you double-click it.

https://gist.github.com/DarrenSem/795d8bb43687b6c771780d74542822cd

Feel free to use or adapt the code above for the main repo or your own forks.

DarrenSem avatar May 27 '24 16:05 DarrenSem

@tanabe ICYMI, do you think this would be a helpful feature? I use it often myself now.

DarrenSem avatar Sep 01 '25 14:09 DarrenSem

Update: Go here instead, works as a Bookmarklet or as an included file via

// MarkDownLivePreview.com-resizer.js -- bookmarklet to add 'Toggle Editor' (and also width-resizer) - instead of waiting for repo update that might use something like this <script src="./static/resizer.js"></script>
// (09Sep2025 938am) 2209 char  javascript:void function(){"use strict";const e="minedit",t="extra-button",i="mouse",n="width",r=document,o=e=>r.getElementById(e),s=(e,t)=>Object.assign(r.createElement(e||"div"),t),d=(e,...t)=>e.addEventListener(...t),l=(e,...t)=>e.removeEventListener(...t),a=e=>e.preventDefault(),c=setTimeout,g=40,m=window,f=(e="resizer-css")=>{if(o(e))return;const i=["\nbody {\n  margin: 0;\n  height: 100vh;\n  overflow: hidden;\n}\n#container {\n  display: flex;\n  width: 100%;\n  height: 100%;\n  overflow: hidden;\n}\n#resizer {\n  width: 4px;\n  background-color: green;\n  cursor: col-resize;\n  flex-shrink: 0;\n}\n"],n=r.head.insertAdjacentElement("afterBegin",s("style",{id:e,innerHTML:(x?"":i[0])+"#edit, #preview { flex-grow: 1; overflow: auto; transition: flex 0.02s ease; } .minedit { flex: 0 0 0px !important; } "+("."+t+" { margin-left: 16px; } ")}));return n},p=(e,t)=>{const i=e.getBoundingClientRect();return t?i[t]:i},h=(f=99,h="resizer",u="toggle-button")=>{var b=Math.abs;if(o(h))return;let E=!1,L=0,y=0;const k=200,z=o("copy-button").insertAdjacentElement("afterEnd",s(0,{id:u,innerHTML:"<a href=\"#\">Toggle Editor</a>",className:t})),B=v.insertBefore(s(0,{id:h}),w),M=o("edit"),T=()=>p(M,n),_=()=>p(v,n),j=()=>M.classList.contains(e),A=(t,i)=>{if(t>=f||i){const n=_();n-t>=f&&(i||j()||(L=t/n,O(L,!0)),M.classList.remove(e),M.style.flex="0 0 "+t+"px")}},C=e=>{E&&A(e.clientX-p(v,"left"))},D=()=>{E=!1,l(r,i+"move",C),l(r,i+"up",D),O(L)},H=w._?.Storehouse,N=w._?.localStorageNamespace,I="last_ratio",O=(e,t,i=new Date)=>{(!t||i>y)&&(H?.setItem(N,I,e,new Date(2099,1,1)),y=+i+k)},R=T()/_(),S=H?.getItem(N,I);return x||(d(x||B,"dblclick",e=>{a(e),A(R*_(),!0),O(R)}),d(B,i+"down",e=>{E=!0,a(e),d(r,i+"move",C),d(r,i+"up",D),O(L)}),d(m,"resize",()=>{if(!j()){const e=_(),t=T(),i=e-t<f;A(i?t<f?t:e-f:e*L,i)}}),S&&.01<b(S-R)&&A(_()*S,!0),c(()=>{L=T()/_(),S||O(L)},g)),B.title="drag to resize, double-click to return to center",x&&(x.title=B.title),d(z,"click",t=>{a(t),M.classList.toggle(e)}),B},u=()=>{v=o("container"),w=o("preview"),x=o("split-divider"),v&&w?(f(),h()):location="https://darrensem.github.io/markdown/"};let v,w,x;void(/loading/.test(r.readyState)?d(r,"DOMContentLoaded",u):c(u,g))}();
// original version of my [Toggle Editor] idea was this Issue: https://github.com/tanabe/markdown-live-preview/issues/56

DarrenSem avatar Sep 13 '25 01:09 DarrenSem