Skip to content

Instantly share code, notes, and snippets.

@addyosmani
Forked from 140bytes/LICENSE.txt
Last active April 8, 2024 20:15
Show Gist options
  • Save addyosmani/d1f3ca715ac902788c2d to your computer and use it in GitHub Desktop.
Save addyosmani/d1f3ca715ac902788c2d to your computer and use it in GitHub Desktop.
Offline Text Editor in < 140 bytes (115 bytes). Powered by localStorage & contentEditable
with({
l: localStorage // Alias for localStorage, where we'll store text content
}) with(document.body) // With the document body..
contentEditable = !0, // Turn on contentEditable
innerHTML = [l.c], // Set innerHTML of our element to the value stored in localStorage
oninput = function () { // On input..
l.c = innerHTML // store our content in localStorage
}
!function(l){with(document.body)contentEditable=!0,innerHTML=[l.c],oninput=function(){l.c=innerHTML}}(localStorage)

Edit: Thanks to help from @mathiasbynens, @subzey and @beaufortfrancois we are now down to 115 bytes from my original 136.

I use this as a JavaScript snippet or bookmarklet in Chrome to turn the current blank tab into an offline text-editor which stores what I write in localStorage. The < 140 character version can be run via console.

The original version that you can add as a bookmarklet:

(function(d){l=localStorage,k='c',q=d.body;q.contentEditable=true;q.innerHTML=l[k]||'';q.oninput=function(){l[k]=q.innerHTML;}})(document);

A demo version of this is available on JSBin.

The optimized version (115 bytes):

!function(l){with(document.body)contentEditable=!0,innerHTML=[l.c],oninput=function(){l.c=innerHTML}}(localStorage)

Pretty version

Prettier version of the implementation using document.write (hah) to write over any existing tab content, gives you some styling too:

javascript:(function(d){d.write('<body contenteditable style="font: 2rem/1.5 monospace;max-width:60rem;margin:0 auto;padding:4rem;">');var k = 'c'; var q = d.querySelector('body');q.innerHTML=localStorage[k];q.oninput=function(){localStorage[k]=q.innerHTML;}})(document);

Preview:

DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Copyright (C) 2014 ADDY OSMANI <addyosmani.com>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "offlineTextEditor",
"description": "ContentEditable-powered Offline text editor",
"keywords": [
"text",
"edit",
"editor",
"localStorage",
"offline"
]
}
<!DOCTYPE html>
<title>Offline Text Editor</title>
<style>
body { font: 2rem/1.5 monospace;max-width:60rem;margin:0 auto;padding:4rem;}
</style>
<body>
<script>
!function(l){with(document.body)contentEditable=!0,innerHTML=[l.c],oninput=function(){l.c=innerHTML}}(localStorage);
</script>
</body>
@yogendra
Copy link

Here's a extended version (slightly longer) but works offline and preserves your text, no matter which site you are on. Just make a bookmarklet of this.

javascript:window.open("javascript:'<body contentEditable oninput=localStorage.c=innerHTML>'+[localStorage.c]", "_mynotes")

UPDATE: Yikes wrote that too soon. This still is page dependent. It will open a new window but will use localStorage on a per page basis. Sad :(

@liorama
Copy link

liorama commented May 26, 2014

Change 'body' to a simple 'a':
javascript:'<a contentEditable oninput=localStorage.c=innerHTML>'+[localStorage.c]

@tsaniel
Copy link

tsaniel commented May 26, 2014

@yogendra Interesting. However it does not work for me?

@tsaniel
Copy link

tsaniel commented May 26, 2014

@liorama There are some problems not using body:

  1. The editing area's height and width are not 100%.
  2. It may not work with paragraphs (more than one line).

@tsaniel
Copy link

tsaniel commented May 26, 2014

@aemkei Actually If we count javascript: it should be +11bytes, or if we don't count javascript: mine will be -11bytes. Not sure which one to go.

@liorama
Copy link

liorama commented May 26, 2014

@tsaniel I thought about the 100% height issue, but the element takes the height of it's contents so does it really matter? (apart from the visible border around the text)
As for the paragraph, it works well for me in Chrome (as well as when using 'body'). If it is a problem we can try a div instead.

@aemkei
Copy link

aemkei commented May 26, 2014

@tsaniel: You are right: It depends on the rules. And if we follow the strict rules from 140byt.es it is still 114 bytes.

@tsaniel
Copy link

tsaniel commented May 26, 2014

@aemkei Indeed.
By the way, it's been a long time since 140bytes was created, a lot of things have changed.
Back then, Jed said the community should stick to ES3, now even ES6 is coming out. Maybe 140bytes really needs an update. For instance, arrow function.

@tsaniel
Copy link

tsaniel commented May 26, 2014

@liorama Maybe it depends on personal preference. I just find full height element handy, as I can click to focus everywhere.

@liorama
Copy link

liorama commented May 26, 2014

@tsaniel My personal preference is formatting and syntax highlighting but those might be a problem with the 140bytes restriction 😄

@xem
Copy link

xem commented May 27, 2014

Maybe 140bytes really needs an update. For instance, arrow function.
My #1 request would be to allow 140 characters instead of 140 bytes, to allow things like that:
http://xem.github.io/miniCodeEditor/tweet.html
But then the name of the site would have to change...

@tsaniel
Copy link

tsaniel commented May 28, 2014

@xem I'm afraid if 140 characters are allowed then every gist will use the same encoding trick?

@xem
Copy link

xem commented May 28, 2014

yeah... but it's not only for the encoding trick.
Twitter counts Unicode characters, 140byt.es counts bytes...
So a 140-char script containing some multibyte characters would fit in twitter but not here.

@xcislav
Copy link

xcislav commented Jul 16, 2014

89b

I don't understand:
square brackets [ ]
localStorage (the cookies of a browser)
innerHTML in quotes
.c

My understanding is:
and equals sign (=)
onload event
contentEditable
.innerHTML as a property

(for example, I understand the .innerHTML property of

when using it with contentEditable attribute - div then becomes like <input/textarea>)

Summary: Could Someone give a brief description of the editor's work?

@orschiro
Copy link

Can someone please explain to me how to use this code as a bookmarklet?

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment