[byoFS] looking at customizing it for my purposes.
<!DOCTYPE html>
<html>
<head>
<title>byoFS - My Diary</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="../../byoFS.js"></script>
<script src="../../byoFS-ui.js"></script>
<style>
/*http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 License: none (public domain)*/
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small,
strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas,
details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {margin:0; padding:0; border:0; font-size:100%; font:inherit; vertical-align:baseline;}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {display:block;} body {line-height: 1;} ol, ul {list-style: none;}
blockquote, q {quotes: none;} blockquote:before, blockquote:after, q:before, q:after {content:''; content:none;} table {border-collapse:collapse; border-spacing:0;}
</style>
<style>
/*App CSS goes here*/
#widget{float:right;margin:20px;}
body{font-family:Courier New, Courier New, monospace;font-size:14px;background-color:#F9F9F7;}
#header h1{padding:20px 0px 4px 20px;font-size:24px;font-weight:bold;}
#header h1 a{display:inline;color:#0000FF;font-weight:bold;text-decoration:underline;padding:0px;background-color:#F9F9F7;border-radius:0px;}
#content{padding:10px 20px;}
#message-wrapper{}
/*#message{display:inline-block;padding:10px 20px;background-color:#A4DA00;border-radius:10px;}*/
#message{display:inline-block;padding:10px 0px;}
a{display:inline-block;color:#666666;font-weight:bold;text-decoration:none;padding:10px;background-color:#EEEEEE;border-radius:10px;}
#add-toggle{margin:10px 0px;padding:10px 10px 10px 31px;background-repeat:no-repeat;background-position:left center;background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAIpwAACKcBMsYCAwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAJdEVYdFRpdGxlAEFkZAzpDSgAAAAWdEVYdEF1dGhvcgBBbmRyZWFzIE5pbHNzb24r7+SjAAAAGHRFWHRDcmVhdGlvbiBUaW1lADIwMDYtMDEtMDTXvFLIAAAAH3RFWHRTb3VyY2UAaHR0cDovL3RhbmdvLXByb2plY3Qub3Jn7+KWDQAABPFJREFUSInFlkuIZFcZx3//c+vdXdWZzKuHiBk3MSYRxE4yKipCFF0NZDEERCRIFjGEEBQfG0EQkSDoRnQRfG0HEnQQHyHgbEQzkwQjpA2SxSSOpMeeiVNd1fW85/xd3FvT1V2NmYyBfHC4cO/9zu98z/PJNu+GhHeF+v+A19dVO4sqN6qv63O1dH6TT2BOAvcBtwAHAANXgNeBPzhw5t5Dfv4dAf9lQ8ezjJ9jPmaYCHIgllAAARlQBaqGM1nky2vHfPmGwecu6SGJ75WbjoEJMDVEQaKgB+2Aa0DDsBXMo3cf9a/fFnh9U8vb5jTwSWAADIERMBadmKmDnRlEkEL0VSX+E4A6ooFpAi3g9IUjPHQKx72MfZNjYL4PfBzoAdtz8HEtfu19m3H16NgDJyJVmjpWuXxplH3rgkS9hE4pwnHq1k1e4TBPvCX4+X/r08AXgP4cuICLUSSbvjg+Wx15G4CGljhSuXMqcRXTmIMaIMA3zm/oN/es+uV5zq5yeu5NdRL8xIWFM2AP2AK2MF2ojhd9VB0X39gq/++Xa9smOvDTvaW3C5zlPCE4RBHPGbwv6GO2gC6uTBa4xbsu0PMOuAiPGAo+0Nrkq/uCz15Qw3CKIntHiBFFXAf2HNyLFkvVsaBn09NOTgwwQ5sxMFbii/uCl5p8xlCniNHYZlzCR4ihYduBLqE+XDDYtZFFN4htwdAwKvUnKksQcfzcZd0209nxe+BembwE50vpydv7qVHHIRFCTMbELJpGJbJTHYlE1C135tPT78exAimEDDk5W9ZkMsy+9E+KppOHxAngH7vAThyTSEDCxKErtWcGT7UX4rlHJh7yu+0nb97v2+daJ3sUGR6BZPGeBYuDOGiwwQqYZHfzTVpZm6oaxeEwyZFETnQkkbAjiUhyIhGxU/lPghbWbM/ieXQBbLgKIBAJpRRZ7/+pPFSGbVx0yeuW1MkJRS9XCbmyAMZsSARDQIRmWAmfP/DNsaRky0LJKCWsM90ftQepC0ArrHBy5dFeQBYOloOwbIdWdpNGkLlI4oC4uAAW/M1QQVQw1Wn4yvoH20t9k/UClS2r0suodZ0/ft+zvc6JHXCHD7fu+nus/PCP8rRj8raIbRPbOb9cBpZUcCpBvLQIrvFbTzEubplcFwcJYoIck0vkAld0zVvXJOcK03QuCXLr2rWZEMLUgKrN5tohvzjTuVbHawfclXhGRS3XAzQNTUxLgSXBMomO06SxF2xP64a2YVmwRHEzNcveXQfqEk/N6+zqn9PA41nkBRXQKZALkhJGBEQV5bUFk5XXECuGJgV4tooDwMaS+Pa8yq5e/dGD/hfw9VKhUBZti46hk2DF5PUFi8nrgpUAHUMbWJ7pC5pKPHzHYfd3nXW/QeDcJf1K4lPMX4kwxIxrfnh1Ek+sJucYE0JV9XB+YxJ+vOEyRAlapcuXZX5x91E/tuCk/cDnN7WKeRZ47xx0hBhjphQJ5MJagkwmUTPUDY0yVK0Af1Xks2vHPLguMMCrr6r+ZofvCB4RTAyjuWGvMBdABPbMXCra1HfvOcIPwPt2nbecMp+7pI9kgZ/ZHKdMOGblUsgMXAFqgpeU8eDaQb/yv/a9rrn6zxfVrNR5AHM/xVxdZ/d420f83vD0a4d5er/h7obAe1T0whscdGA1T8RGkzc+dJOvvs1NbgT8zsh/AfEUemkAg+gmAAAAAElFTkSuQmCC');}
#add-form{margin-top:10px;}
#add-title{display:inline-block;padding:5px 0px;font-size:18px;}
#add-text{padding:5px;width:400px;height:150px;border:solid #555555 1px;background-color:#FFFFFF}
.entry-text-wrapper{margin:10px 0px;}
.entry-text{display:inline-block;padding:12px;background-color:#FFFFFF;border:solid #EEEEEE 2px;}
.entry-toggle{padding:2px;border-radius:0px;background-color:#F9F9F7;}
</style>
</head>
<body>
<!--HTML Goes Here-->
<div id="header">
<div id="widget"></div>
<h1>My Diary (an example <a href="https://github.com/diafygi/byoFS" target="_blank">byoFS</a> app)</h1>
</div>
<div id="content">
<div id="message-wrapper"><p id="message"></p></div>
<a href="#" id="add-toggle" style="display:none;">Add an entry</a>
<div id="add-form" style="display:none;">
<p><div id="add-title"></div></p>
<input type="hidden" id="add-id" val=""/>
<textarea id="add-text"></textarea>
<p><a href="#" id="add-submit">Submit</a> <a href="#" id="add-back">Cancel</a></p>
<p id="add-submitting">Submitting...</p>
</div>
<div id="list"></div>
<div id="entry-template" style="display:none;">
<div class="entry-id">
<p>
<span class="entry-title"></span>
<a href="#" class="entry-toggle">[+]</a>
</p>
<div class="entry-area" style="display:none;">
<div class="entry-text-wrapper">
<div class="entry-text"></div>
</div>
<input type="hidden" class="entry-raw">
<a href="#" class="entry-edit">Edit</a>
<a href="#" class="entry-del">Delete</a>
</div>
</div>
</div>
</div>
<!--App code goes here-->
<script>
var message = {
init: "To get started, load your diary from Dropbox or localStorage!",
reg1: "Creating diary...",
reg2: "Creating diary...Done!",
empty: "You don't have any entries in your diary. How about adding one?",
add: "Entry added!",
update: "Entry updated!",
del: "Entry deleted!",
load: "Loading...",
};
var ids = [];
var fs;
function ts_to_str(timestamp){
var t = new Date(parseInt(timestamp));
var str = t.getFullYear()+"-"+('0'+(t.getMonth()+1)).slice(-2)+"-"+('0'+t.getDate()).slice(-2);
str += " "+('0'+t.getHours()).slice(-2)+":"+('0'+t.getMinutes()).slice(-2)+":"+('0'+t.getSeconds()).slice(-2);
return str;
}
function submit_addform(e){
e.preventDefault();
document.getElementById("add-submit").style.display = "none";
document.getElementById("add-submitting").style.display = "block";
//update entry
var add_txt = document.getElementById("add-text").value;
var id = document.getElementById("add-id").value;
if(id !== ""){
fs.write("entry"+id, add_txt, function(){
setup_app('update');
});
}
//new entry
else{
//id format: YYYY-MM-DD_HH:MM:SS
var new_id = new Date().getTime();
fs.write("entry"+new_id, add_txt, function(){
ids.unshift(new_id);
fs.write("index", JSON.stringify(ids), function(){
setup_app('add');
});
});
}
}
function show_addform(e, id, text){
if(e !== undefined){
e.preventDefault();
}
//update fields
document.getElementById("add-title").innerHTML = id ? "Editing entry from " + ts_to_str(id) : "New Entry";
document.getElementById("add-id").value = id ? id : "";
document.getElementById("add-text").value = text ? text : "";
//show form
document.getElementById("add-toggle").style.display = "none";
document.getElementById("add-submit").style.display = "inline-block";
document.getElementById("add-submitting").style.display = "none";
document.getElementById("add-form").style.display = "block";
//add event listeners
document.getElementById("add-back").addEventListener("click", hide_addform);
document.getElementById("add-submit").addEventListener("click", submit_addform);
}
function hide_addform(e){
if(e !== undefined){
e.preventDefault();
}
//revert to hidden form
document.getElementById("add-form").style.display = "none";
document.getElementById("add-toggle").style.display = "inline-block";
document.getElementById("add-toggle").addEventListener("click", show_addform);
}
function toggle_entry(e){
e.preventDefault();
var entry = e.target.parentNode.parentNode;
var id = entry.id;
var toggle = entry.querySelector(".entry-toggle");
var raw = entry.querySelector(".entry-raw");
var txt = entry.querySelector(".entry-text");
var area = entry.querySelector(".entry-area");
if(toggle.innerHTML === "[+]"){
if(raw.value === ""){
txt.innerHTML = "Loading...";
fs.read("entry"+id, function(pxhr){
var data = pxhr.responseText;
if(pxhr.status === 404)
data = "";
//TODO: mitigate XSS
raw.value = data;
txt.innerHTML = data.replace(/\n/g, '<br>');
});
}
area.style.display = "block";
toggle.innerHTML = "[-]";
}
else{
area.style.display = "none";
toggle.innerHTML = "[+]";
}
}
function edit_entry(e){
e.preventDefault();
var entry = e.target.parentNode.parentNode
var id = entry.id;
show_addform(undefined, id, entry.querySelector(".entry-raw").value);
window.scrollTo(0, document.getElementById("add-form").offsetTop - 10);
}
function del_entry(e){
e.preventDefault();
var id = e.target.parentNode.parentNode.id;
if(confirm("Are you sure you want to delete this entry?")){
ids.splice(ids.indexOf(parseInt(id)), 1);
fs.write("index", JSON.stringify(ids), function(){
fs.write("entry"+id, null, function(){
setup_app('del');
});
});
}
}
function load_entries(){
hide_addform();
//blank state for no entries
if(!ids.length){
document.getElementById("message").innerHTML = message['empty'];
document.getElementById("list").innerHTML = "";
}
//show list of entries and display the top one
else{
document.getElementById("list").innerHTML = "";
for(var i = 0; i < ids.length; i++){
//append entry
var template = document.getElementById("entry-template").children[0].cloneNode(true);
document.getElementById("list").appendChild(template);
//update entry contents
var entries = document.getElementById("list").children;
var last = entries[entries.length - 1];
last.id = ids[i];
last.querySelector(".entry-title").innerHTML = ts_to_str(ids[i]);
//event binders for entry expand/collapse/edit/delete
last.querySelector(".entry-toggle").addEventListener("click", toggle_entry);
last.querySelector(".entry-edit").addEventListener("click", edit_entry);
last.querySelector(".entry-del").addEventListener("click", del_entry);
}
}
}
function reset_index(e){
e.preventDefault();
document.getElementById("message").innerHTML = "Resetting...";
fs.write("index", JSON.stringify([]), function(){
setup_app();
});
}
function reload_page(e){
e.preventDefault();
document.getElementById("message").innerHTML = "Reloading...";
location.reload();
}
function setup_app(msg_key){
document.getElementById("message").innerHTML = message['load'];
//see if the index exists
fs.read("index", function(pxhr){
//no index, assume registration and create index file
if(pxhr.status === 404){
document.getElementById("message").innerHTML = message['reg1'];
fs.write("index", JSON.stringify([]), function(){
document.getElementById("message").innerHTML = message['reg2'];
setup_app();
});
return;
}
//bad password
else if(pxhr.status === 401){
document.getElementById("message").innerHTML = "Couldn't decrypt with that password :( <a href='#' id='reload-page'>Try again</a> or <a href='#' id='reset-everything'>Reset everything</a>.";
document.getElementById("reload-page").addEventListener("click", reload_page);
document.getElementById("reset-everything").addEventListener("click", reset_index);
}
//some other error occurred
else if(pxhr.status !== 200){
console.log(pxhr);
alert("Something went wrong :(")
app_init();
}
//index found
else{
if(msg_key)
document.getElementById("message").innerHTML = message[msg_key];
else
document.getElementById("message").innerHTML = "";
ids = JSON.parse(pxhr.responseText);
load_entries();
}
});
}
//initialize app
function app_init(){
document.getElementById("message").innerHTML = message['init'];
byoFS_UI("mydiary", "#widget", function(connected_fs){
fs = connected_fs;
setup_app();
});
}
app_init();
</script>
<script>
/*
//debug test
byoFS_UI("mydiary", "#widget", function(fs){
console.log("connected!");
fs.write("testfile", "testdata", function(pxhr){
console.log("write callback!");
fs.read("testfile", function(pxhr){
console.log(pxhr.responseText);
fs.write("testfile", null, function(pxhr){
console.log("deleted!");
fs.read("testfile", function(pxhr){
console.log(pxhr.responseText);
fs.write("testfile", null, function(pxhr){
console.log("deleted2!");
});
});
});
});
});
});
//*/
</script>
</body>
</html>