VikingMage
3/23/2019 - 12:43 PM

[byoFS] looking at customizing it for my purposes.

[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,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');}
            #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>