4
\$\begingroup\$

I made a simple notepad webapp, called Notepad5. You can use it to make notes while browsing the web and don't want to open up a separate application or extension to put the notes down and don't want to store them on an external server (more). Please review the code.

/*!
 * Notepad5 v1.04
 * https://github.com/uddhabh/Notepad5
 */
(function() {
 "use strict";
 function $(id) { // shortcut for document.getElementById
 return document.getElementById(id);
 }
 // core variables
 var customStyle = $("custom-style"),
 textarea = $("textarea"),
 statusBar = $("status-bar"),
 fileInput = $("file-input"),
 appname = "Notepad5",
 isModified,
 filename;
 function skipSave() { // warning for saving doc
 if (!isModified || !textarea.value || confirm("You have unsaved changes that will be lost.")) {
 isModified = false;
 return true;
 }
 }
 function changeFilename(newFilename) {
 filename = newFilename || "untitled.txt";
 document.title = filename + " - " + appname;
 }
 function updateStatusBar() { // text stats
 var text = textarea.value;
 statusBar.value = "Words: " + (text.replace(/['";:,.?¿\-!¡]+/g, "").split(/\w+/).length - 1) +
 " Characters: " + text.replace(/\s/g, "").length + " / " + text.length;
 }
 function newDoc(text, newFilename) {
 if (skipSave()) {
 textarea.value = text || "";
 changeFilename(newFilename); // default "untitled.txt"
 updateStatusBar();
 }
 }
 function openDoc(event) {
 var files = event.target.files || event.dataTransfer.files,
 file = files[0],
 reader = new FileReader();
 if (file) {
 event.preventDefault();
 reader.addEventListener("load", function(event) {
 newDoc(event.target.result, file.name);
 });
 reader.readAsText(file);
 }
 }
 function saveDoc() {
 var newFilename = prompt("Name this document:", filename);
 if (newFilename !== null) {
 if (newFilename === "") {
 changeFilename(); // "untitled.txt"
 } else {
 changeFilename(/\.txt$/i.test(newFilename) ? newFilename : newFilename + ".txt");
 }
 var blob = new Blob([textarea.value.replace(/\n/g, "\r\n")], {
 type: "text/plain;charset=utf-8"
 }); // line ending CRLF
 saveAs(blob, filename);
 isModified = false;
 }
 }
 function showHideStatusBar(on) {
 statusBar.hidden = !on; // true/false
 textarea.className = on ? "statusBarOn" : "";
 }
 function toggleFullScreen() { // https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
 if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) {
 var elem = document.documentElement;
 if (elem.requestFullscreen) {
 elem.requestFullscreen();
 } else if (elem.msRequestFullscreen) {
 elem.msRequestFullscreen();
 } else if (elem.mozRequestFullScreen) {
 elem.mozRequestFullScreen();
 } else if (elem.webkitRequestFullscreen) {
 elem.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
 }
 } else {
 if (document.exitFullscreen) {
 document.exitFullscreen();
 } else if (document.msExitFullscreen) {
 document.msExitFullscreen();
 } else if (document.mozCancelFullScreen) {
 document.mozCancelFullScreen();
 } else if (document.webkitExitFullscreen) {
 document.webkitExitFullscreen();
 }
 }
 }
 function addCSS(rules) {
 rules = rules || prompt("Add custom CSS here:", customStyle.innerHTML);
 if (rules !== null) {
 customStyle.innerHTML = rules;
 }
 }
 function storeData() {
 var appdata = {
 filename: filename,
 text: textarea.value,
 isModified: isModified,
 statusBarOn: !statusBar.hidden,
 customCSS: customStyle.innerHTML
 };
 localStorage.setItem("appdata", JSON.stringify(appdata));
 }
 function init() {
 document.body.className = ""; // make the app visible
 if (navigator.userAgent.match(/Mobi/)) { // likely mobile
 document.body.innerHTML = "I think this app isn't useful on mobile... sorry :(";
 return; // stop
 }
 if (!window.File) { // likely unsupported browser
 document.body.innerHTML = "<p>Sorry your browser isn't supported :(<br>Please upgrade to <a href='http://google.com/chrome'>Google Chrome</a>.</p>";
 return; // stop
 }
 var appdata = JSON.parse(localStorage.getItem("appdata"));
 showHideStatusBar(!appdata || appdata.statusBarOn); // show by default
 if (appdata) {
 if (appdata.customCSS) {
 addCSS(appdata.customCSS);
 }
 if (appdata.isModified) {
 newDoc(appdata.text, appdata.filename);
 isModified = true;
 } else {
 newDoc(); // blank note
 }
 } else { // first run
 newDoc(["Welcome to " + appname + ", the online-offline notepad. All of your text is stored offline on your computer. Nothing is stored on servers.",
 "\nHere are some useful keyboard shortcuts:",
 "Ctrl + R : Create New Document",
 "Ctrl + O : Open Document",
 "Ctrl + S : Save Document",
 "Ctrl + B : Toggle Status Bar",
 "Ctrl + E : Add Custom CSS",
 "Ctrl + Enter : Toggle Full Screen",
 "\nYou can contact me at:",
 "[email protected] or twitter.com/"
 ].join("\n"), "Welcome!");
 }
 }
 fileInput.addEventListener("change", openDoc);
 textarea.addEventListener("blur", function() { // keep textarea focused
 setTimeout(function() {
 textarea.focus();
 }, 0);
 });
 textarea.addEventListener("input", function() {
 isModified = true;
 updateStatusBar();
 });
 textarea.addEventListener("keydown", function(event) {
 if (event.keyCode == 9) { // Tab: insert tab
 event.preventDefault();
 var text = textarea.value,
 sStart = textarea.selectionStart;
 textarea.value = text.substring(0, sStart) + "\t" + text.substring(textarea.selectionEnd);
 textarea.selectionEnd = sStart + 1;
 }
 });
 document.addEventListener("keydown", function(event) {
 var keys = {
 13: toggleFullScreen, // Enter: toggle fullscreen
 66: function() { // B: toggle statusBar
 showHideStatusBar(statusBar.hidden);
 },
 69: addCSS, // E: add custom CSS
 79: function() { // O: open
 if (skipSave()) fileInput.click();
 },
 82: newDoc, // R: new
 83: saveDoc // S: save
 };
 if (event.ctrlKey && keys[event.keyCode]) { // Ctrl + keys{}
 event.preventDefault();
 keys[event.keyCode]();
 }
 });
 document.addEventListener("drop", openDoc);
 window.addEventListener("unload", storeData); // store appdata locally
 window.addEventListener("load", init); // initialize
}());
ferada
11.4k25 silver badges65 bronze badges
asked Feb 4, 2015 at 20:19
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Hi! Welcome to Code Review. Please add more context to your question, such as explain what your code does. \$\endgroup\$ Commented Feb 4, 2015 at 20:21
  • 1
    \$\begingroup\$ Added more details... uddhabh.blogspot.in/2014/01/notepad5.html \$\endgroup\$ Commented Feb 4, 2015 at 20:24

1 Answer 1

2
\$\begingroup\$

using something like this would shorten up your fullscreen stuff...

var fullScreen = {
 request: elem.requestFullScreen || elem.msRequestFullScreen || elem.mozRequestFullScreen || elem.webkitRequestFullScreen,
 exit: elem.exitFullScreen || elem.msExitFullScreen || elem.mozExitFullScreen || elem.webkitExitFullScreen
}

.. other than that, I don't see anything particularly wrong with it, though. Perhaps an assumption that it can't be used on mobile, and that it can't work on a browser that doesn't have File, might be a problem, but that's not with the code.

answered Feb 6, 2015 at 9:09
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.