<?php
 
    /*
 
        * SQLite Code Vault :: SQLite Snippets Manager :: Example Admin Page
 
        * 
 
        * @package SQLite Snippets Manager :: SQLiteCodeVault
 
        * @version 1.1
 
        * @author https://www.phpclasses.org/browse/author/144301.html
 
        * @link https://www.phpclasses.org/package/12863-PHP-SQLite-Code-Vault-is-a-PHP-SQLite-snippets-manager.html
 
 
        * @license BSD License
 
        * @filename sqlite-snippets-admin.php
 
        * 
 
        * please leave this comment block intact so others can find the original source.
 
        * 
 
        * description: An example admin page for SQLiteCodeVault class to manage code snippets in a SQLite database.
 
   
 
        // fixed up listing rows a bit for the add section update
 
        // added some classes to db for json
 
 
        // one day I will have to get in to clean this beast, but today isn't that day. Neither is tomorrow.
 
 
        // v1.1 has a json export/import feature
 
 
        // currently broken: using not in the search field (and/or work)
 
 
        // added copy button to copy the code to the clipboard
 
        // added syntax highlighting and theme dropdown for syntax highlighting
 
        // added copy json button to copy the json to the clipboard
 
        // added cookie storing ability to remember the last used theme
 
 
        // created a cookie management javascript class for the ace.js code editor
 
        // created a jquery plugin to:
 
        // - handle the cookie management for combo boxes
 
        // - attach the ace.js code editor to the code textarea
 
        // - this was not fun :( but hey it works.
 
        // -- adds all sorts of cool ways to edit your code with syntax highlighting, error checking, autoindent, etc. 
 
 
        // -- so using highlight.js for the listings and ace.js for the code editor. Note: only currently attached to update code section, but easy enough to add to add section which I will do if everything runs smooth in the update section, which I highly doubt, but hey, fingers crossed.        
 
        
 
        // fixed some width issues with the page.
 
 
    */
 
 
    ob_start();
 
    session_start();
 
 
    // Include SQLiteCodeVault class
 
    require_once 'sqlite-snippets-manager.php';
 
 
    // Initialize the class
 
    $snippets = new PHPSQLiteCodeVault();
 
 
    function get_snippet_data_html($snippet_row)
 
    {
 
        global $snippets;
 
 
        $html = "";
 
        
 
        // create a page anchor
 
        $html .= "<a name='" . $snippet_row['id'] . "'></a>";
 
 
        $html .= "<div class='title'>" . $snippet_row['title'] . "</div>";
 
 
        $html .= "<div class='subcontent' style='display:none'>";
 
 
            $html .= "<div class='code-snippet' data-id='" . $snippet_row['id'] . "'>" . $snippet_row['code'] . "</div>";
 
 
            $html .= "<div class='json-row'>";
 
                $html .= "<div class=' json-title'>JSON Export:</div>";
 
                $html .= "<div class=' json'><textarea class='json-textarea' data-id='" . $snippet_row['id'] . "'>" . $snippets->snippet_to_json_str($snippet_row) . "</textarea></div>";
 
            $html .= "</div><!-- end json-row -->";
 
 
            $html .= "<div class='subinfo'>";
 
                $html .= "<div class='language'>language: " . $snippet_row['language'] . "</div>";
 
                $html .= "<div class='tags'>tags: " . $snippet_row['tags'] . "</div>";
 
                $html .= "<div class='author'>author: " . $snippet_row['author'] . "</div>";
 
                $html .= "<div class='license'>license: " . $snippet_row['license'] . "</div>";
 
                $html .= "<div class='timestamp'>" . date('Y-m-d H:i:s', $snippet_row['timestamp']) . "</div>";
 
            $html .= "</div><!-- end subinfo -->";
 
 
            
 
            $html .= "<div class='actions'>";
 
                $html .= '<div><button class="copyBtn" data-id="' . $snippet_row['id'] . '">Copy</button></div>';
 
                $html .= '<div><button class="copyJsonBtn" data-id="' . $snippet_row['id'] . '">Copy JSON</button></div>';
 
                $html .= "<div><button class='editBtn' data-id='" . $snippet_row['id'] . "' data-title='" . $snippet_row['title'] . "' data-code='" . htmlentities($snippet_row['code']) . "' data-language='" . $snippet_row['language'] . "' data-tags='" . $snippet_row['tags'] . "' data-author='" . $snippet_row['author'] . "' data-license='" . $snippet_row['license'] . "'>Edit</button></div>";
 
                $html .= '<div><button class="deleteBtn" data-id="' . $snippet_row['id'] . '">Delete</button></div>';
 
 
            $html .= "</div>";
 
 
 
 
        $html .= "</div><!-- end subcontent -->";
 
 
 
        return $html;
 
    }
 
 
    function get_snippet_html($snippet_row, $evenodd="odd")
 
    {
 
        // make safe for html
 
        $snippet_row['title']       = htmlspecialchars($snippet_row['title']);
 
        $snippet_row['code']        = htmlspecialchars($snippet_row['code']);
 
        $snippet_row['language']    = htmlspecialchars($snippet_row['language']);
 
        $snippet_row['tags']        = htmlspecialchars($snippet_row['tags']);
 
        $snippet_row['author']      = htmlspecialchars($snippet_row['author']);
 
        $snippet_row['license']     = htmlspecialchars($snippet_row['license']);
 
 
 
        // Return HTML for a snippet
 
        $html = "";
 
        $html .= "<div class='snippet $evenodd' data-id='" . $snippet_row['id'] . "'>";
 
        $html .= "<div class='snippet-data' data-id='" . $snippet_row['id'] . "'>";
 
 
        $html .= get_snippet_data_html($snippet_row);
 
 
        $html .= "</div>";
 
 
 
        $html .= "</div>";
 
 
        return $html;
 
    }
 
 
    function get_snippets_html()
 
    {
 
        global $snippets;
 
 
        // Return HTML for all snippets to go in .snippets div
 
        $html = "";
 
        /*
 
            $evenodd = 'odd';
 
            foreach ($snippetsList as $snippet) { 
 
 
                echo get_snippet_html($snippet, $evenodd);
 
                if ($evenodd == 'odd') 
 
                    $evenodd = 'even';
 
                else 
 
                    $evenodd = 'odd';
 
            } 
 
        */
 
 
        // if $_SESSION['search'] is set, then search for snippets
 
        if (isset($_SESSION['search']) && !empty(trim($_SESSION['search']))) {
 
            $snippetsList = $snippets->fuzzySearch($_SESSION['search']);
 
        } else {
 
            // If no search is submitted, get all snippets from database
 
            $snippetsList = $snippets->getAllSnippets();
 
        }
 
 
        $evenodd = "odd";
 
        foreach ($snippetsList as $snippet) {
 
            $html .= get_snippet_html($snippet, $evenodd);
 
            if ($evenodd == "odd") {
 
                $evenodd = "even";
 
            } else {
 
                $evenodd = "odd";
 
            }
 
        }
 
 
        return $html;
 
    }
 
 
 
 
 
 
 
 
 
        // If the form is submitted to add a new snippet
 
        if (isset($_POST['addSnippet'])) {
 
            // Get form data and add snippet to database
 
            $snippets->addSnippet($_POST['title'], $_POST['code'], $_POST['language'], $_POST['tags'], $_POST['author'], $_POST['license'], time());
 
        }
 
 
        // If the form is submitted to update a snippet
 
        if (isset($_POST['updateSnippet'])) {
 
            // Get form data and update snippet in database
 
            $snippets->saveSnippet($_POST['id'], $_POST['title'], $_POST['code'], $_POST['language'], $_POST['tags'], $_POST['author'], $_POST['license'], time());
 
        }
 
 
        // If the form is submitted to search for snippets
 
        if (isset($_POST['searchSnippet'])&& !empty(trim($_POST['search']))) {
 
            // Get form data and search for snippets in database
 
            # $snippetsList = $snippets->getSnippetsBySearch($_POST['search']);
 
            
 
            // $snippetsList = $snippets->fuzzySearch($_POST['search']);
 
 
            $_SESSION['search'] = $_POST['search'];
 
        } else 
 
        if (isset($_POST['searchSnippet']) && empty(trim($_POST['search']))) {
 
            $_SESSION['search'] = '%';
 
        }
 
        
 
        // else {
 
        //     // If no search is submitted, get all snippets from database
 
        //     // $snippetsList = $snippets->getAllSnippets();
 
        //     $_SESSION['search'] = '';
 
        // }
 
 
 
 
 
    if (isset($_GET['cmd']) && $_GET['cmd'] == 'ajax') {
 
        // If the request is an AJAX request, return the snippets list and quit
 
        # echo $snippetsList;
 
        // $evenodd = "odd";
 
        // foreach ($snippetsList as $snippet) {
 
        //     echo get_snippet_html($snippet, $evenodd);
 
        //     if ($evenodd == "odd") {
 
        //         $evenodd = "even";
 
        //     } else {
 
        //         $evenodd = "odd";
 
        //     }
 
        // }
 
        echo get_snippets_html();
 
 
        exit;
 
    } // end if ajax
 
 
 
?><?php
 
 
/*
 
            // Cancel page reload on form submit for update snippet form
 
            $('#updateSnippetForm form').submit(function(e) {
 
 
                // Get form data
 
                var id = $('#updateSnippetForm').find('input[name="id"]').val();
 
                var title = $('#updateSnippetForm').find('input[name="title"]').val();
 
                var code = $('#updateSnippetForm').find('textarea[name="code"]').val();
 
                var language = $('#updateSnippetForm').find('input[name="language"]').val();
 
                var tags = $('#updateSnippetForm').find('input[name="tags"]').val();
 
                var author = $('#updateSnippetForm').find('input[name="author"]').val();
 
                var license = $('#updateSnippetForm').find('input[name="license"]').val();
 
                
 
                // Update snippet in database
 
                $.ajax({
 
                    url: 'sqlite-snippets-admin.php?cmd=ajax',
 
                    type: 'post',
 
                    data: {
 
                        updateSnippet: true,
 
                        id: id,
 
                        title: title,
 
                        code: code,
 
                        language: language,
 
                        tags: tags,
 
                        author: author,
 
                        license: license
 
                    },
 
                    success: function(response) {
 
                        // If snippet is updated successfully, reload the snippet list
 
                        $('#snippetsList').html(response);
 
                        alert('Snippet updated successfully!');
 
                    }
 
                });
 
            
 
                e.preventDefault();
 
                
 
            }); // end -- update snippet form submit
 
*/
 
 
// --- BEGIN --- PHP SIDE OF COMMAND PROCESSOR
 
 
if(!empty($_GET['ajax']))
 
{        
 
    switch($_GET['ajax'])
 
    {
 
        case 'add-from-json':
 
            $json = $_POST['flds']['json'];
 
            $snippets->snippet_from_json_str_to_db($json);
 
 
            $return_arr[] = array(
 
                "command"     => 'alert',
 
                "process"     => "add-from-json",
 
                "msg"         => "added from json"
 
            );
 
 
            // update snippet list
 
            $return_arr[] = array(
 
                "command"     => 'html',
 
                "selector"     => ".snippets",
 
                "msg"         => get_snippets_html()
 
            );
 
 
 
            $return_arr[] = array(
 
                "command"     => 'html',
 
                "selector"     => "#snippetCount",
 
                "msg"         => $snippets->getSnippetCount()." Snippets in DB"
 
            );
 
        
 
            break;
 
 
 
        case 'update':
 
            $id             = $_POST['flds']['id'];
 
            $title          = $_POST['flds']['title'];
 
            $code           = $_POST['flds']['code'];
 
            $language       = $_POST['flds']['language'];
 
            $tags           = $_POST['flds']['tags'];
 
            $author         = $_POST['flds']['author'];
 
            $license        = $_POST['flds']['license'];
 
 
            if(empty($id))
 
            {
 
                $return_arr[] = array(
 
                    "command"     => 'alert',
 
                    "process"     => "update",
 
                    "msg"         => "id is empty for update"
 
                );
 
            }
 
            else
 
            {
 
                // update ( saveSnippet($id, $title, $code, $language, $tags, $author, $license, $timestamp) )
 
                $snippets->saveSnippet($id, $title, $code, $language, $tags, $author, $license, time());
 
 
                $return_arr[] = array(
 
                    "command"     => 'alert',
 
                    "process"     => "update",
 
                    "msg"         => "updated id: $id"
 
                );
 
 
 
                $snippet = $snippets->getSnippetById($id);
 
                ## print_r($snippet['code']);
 
                // for sending back to a <pre></pre> fix the stripping of <html> tags
 
                $snippet['code'] = htmlspecialchars($snippet['code']);
 
 
                $return_arr[] = array(
 
                    "command"     => 'html',
 
                    "selector"     => ".snippet-data[data-id='$id']",
 
                    "msg"         => get_snippet_data_html($snippet)
 
                    // "msg"         => get_snippet_data_html($snippets->getSnippetById($id))
 
                );
 
 
 
                // $return_array[] = array(
 
                //     "command"     => 'html',
 
                //     "selector"     => '.snippet12',
 
                //     // "msg"         => get_snippet_html($snippets->getSnippetById($id))
 
                //     "msg"         => '....'
 
                // );
 
 
                // print_r($return_array);
 
            }
 
            break; // end -- update snippet
 
 
        case 'delete':
 
            $id = $_POST['flds']['id'];
 
 
            if(empty($id))
 
            {
 
                $return_arr[] = array(
 
                    "command"     => 'alert',
 
                    "process"     => "delete",
 
                    "msg"         => "id is empty for delete"
 
                );
 
            }
 
            else
 
            {
 
                // delete ( deleteSnippet($id) )
 
                $snippets->deleteSnippet($id);
 
 
                $return_arr[] = array(
 
                    "command"     => 'alert',
 
                    "process"     => "delete",
 
                    "msg"         => "deleted id: $id"
 
                );
 
 
                $return_arr[] = array(
 
                    "command"     => 'html',
 
                    "selector"     => "#snippetCount",
 
                    "msg"         => $snippets->getSnippetCount()." Snippets in DB"
 
                );
 
    
 
 
            }
 
            break; // end -- delete snippet
 
        
 
        
 
    }
 
    if(!empty($return_arr) && is_array($return_arr))
 
    die(json_encode($return_arr));
 
 
    die(); // ajax request, so just quit instead of showing a page
 
 
 
 
}
 
 
// --- END --- PHP SIDE OF COMMAND PROCESSOR
 
 
?>
 
 
 
<!DOCTYPE html>
 
<html lang="en">
 
<head>
 
    <meta charset="UTF-8">
 
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 
    <title>Snippet Manager</title>
 
    <link rel="stylesheet" href="style.css">
 
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
 
    <script>
 
        $(document).ready(function() {
 
            // Show add snippet form when add button is clicked
 
            $('#addBtn').click(function() {
 
                $('#addSnippetForm').toggle();
 
            });
 
 
            // Hide add snippet form when cancel button is clicked
 
            $('#cancelBtn').click(function() {
 
                $('#addSnippetForm').hide();
 
            });
 
 
 
            // Cancel page reload on form submit for add snippet form
 
            $('#addSnippetForm form').submit(function(e) {
 
 
                // Get form data
 
                var title = $('#addSnippetForm').find('input[name="title"]').val();
 
                var code = $('#addSnippetForm').find('textarea[name="code"]').val();
 
                var language = $('#addSnippetForm').find('input[name="language"]').val();
 
                var tags = $('#addSnippetForm').find('input[name="tags"]').val();
 
                var author = $('#addSnippetForm').find('input[name="author"]').val();
 
                var license = $('#addSnippetForm').find('input[name="license"]').val();
 
                
 
                // Add snippet to database
 
                $.ajax({
 
                    url: 'sqlite-snippets-admin.php?cmd=ajax',
 
                    type: 'post',
 
                    data: {
 
                        addSnippet: true,
 
                        title: title,
 
                        code: code,
 
                        language: language,
 
                        tags: tags,
 
                        author: author,
 
                        license: license
 
                    },
 
                    success: function(response) {
 
                        // If snippet is added successfully, reload the snippet list
 
                        $('#snippetsList').html(response);
 
                        alert('Snippet added successfully!');
 
                    }
 
 
                
 
                });
 
 
                e.preventDefault();
 
 
            });
 
 
            
 
 
            // Cancel page reload on form submit for update snippet form
 
            // OBSOLETE.. Now using command processor
 
            $('#updateSnippetForm form').submit(function(e) {
 
 
                // Get form data
 
                var id = $('#updateSnippetForm').find('input[name="id"]').val();
 
                var title = $('#updateSnippetForm').find('input[name="title"]').val();
 
                var code = $('#updateSnippetForm').find('textarea[name="code"]').val();
 
                var language = $('#updateSnippetForm').find('input[name="language"]').val();
 
                var tags = $('#updateSnippetForm').find('input[name="tags"]').val();
 
                var author = $('#updateSnippetForm').find('input[name="author"]').val();
 
                var license = $('#updateSnippetForm').find('input[name="license"]').val();
 
                
 
                // Update snippet in database
 
                $.ajax({
 
                    url: 'sqlite-snippets-admin.php?cmd=ajax',
 
                    type: 'post',
 
                    data: {
 
                        updateSnippet: true,
 
                        id: id,
 
                        title: title,
 
                        code: code,
 
                        language: language,
 
                        tags: tags,
 
                        author: author,
 
                        license: license
 
                    },
 
                    success: function(response) {
 
                        // If snippet is updated successfully, reload the snippet list
 
                        $('#snippetsList').html(response);
 
                        alert('Snippet updated successfully!');
 
                    }
 
                });
 
            
 
                e.preventDefault();
 
                
 
            }); // end -- update snippet form submit
 
 
            // Show edit snippet form when edit button is clicked (handle dynamically created edit buttons too)
 
            // $('.editBtn').click(function() { // old way
 
            $(document).on('click', '.editBtn', function() {
 
                var id = $(this).data('id');
 
                var title = $(this).data('title');
 
                var code = $(this).data('code');
 
                var language = $(this).data('language');
 
                var tags = $(this).data('tags');
 
                var author = $(this).data('author');
 
                var license = $(this).data('license');
 
                
 
                // code is escaped so unescape it
 
                const parser = new DOMParser();
 
                const doc = parser.parseFromString(code, 'text/html');
 
                code = doc.documentElement.textContent;
 
 
                $('#updateSnippetForm').find('input[name="id"]').val(id);
 
                $('#updateSnippetForm').find('input[name="title"]').val(title);
 
                $('#updateSnippetForm').find('textarea[name="code"]').val(code);
 
                $('#updateSnippetForm').find('input[name="language"]').val(language);
 
                $('#updateSnippetForm').find('input[name="tags"]').val(tags);
 
                $('#updateSnippetForm').find('input[name="author"]').val(author);
 
                $('#updateSnippetForm').find('input[name="license"]').val(license);
 
 
                $('#updateSnippetForm').show();
 
                // scroll to #updateSnippetForm
 
                $('html, body').animate({
 
                    scrollTop: $("#updateSnippetForm").offset().top
 
                }, 1000);
 
            });
 
 
            // Hide edit snippet form when cancel button is clicked
 
            $('#cancelBtn').click(function() {
 
                $('#updateSnippetForm').hide();
 
            });
 
        });
 
    </script>
 
</head>
 
<body>
 
 
<div class='row'>
 
    <div class='col'><h1 id='pageTtl'>Snippet Manager</h1></div>
 
 
    <div class='col'><button id="addBtn">Show/Hide Add Snippet</button></div>
 
    </div>
 
 
 
 
    <style>
 
        body {
 
            font-family:arial;
 
        }
 
 
        .row {
 
            display:flex;
 
            flex-direction:row;
 
            justify-content:space-between;
 
            align-items:center;
 
            margin:2vw;
 
        }
 
 
        .col {
 
            flex:1;
 
        }
 
        
 
        #pageTtl {
 
            margin-top:12px;
 
            font-size:2min;
 
        }
 
        
 
        #addBtn {
 
            float:right;
 
            margin-top:0;
 
        }
 
 
 
 
        #snippetCount {
 
            position:fixed;
 
            /* top:0; */
 
            bottom:0px;
 
 
            /* right:10px; */
 
            left:50%;
 
            transform:translateX(-50%);
 
 
 
            background-color: #fff;
 
            padding: 10px 20px;
 
            margin-top:0px;
 
            z-index:9999;
 
 
            border:1px solid #ccc;
 
            cursor:pointer;
 
 
        }
 
    </style>
 
    <div id="snippetCount"><?php echo $snippets->getSnippetCount(); ?> Snippets in DB</div>
 
 
 
 
 
 
 
    <div id="addSnippetForm" style="display:none;">
 
 
        <style>
 
            #addSnippetFromJson {
 
                margin: 20px 0;
 
            }
 
            #addSnippetFromJson .fld {
 
                margin: 5px 0;
 
            }
 
            #addSnippetFromJson .fld input {
 
                width: 100%;
 
                padding-top:1em;
 
                padding-bottom:1em;
 
            }
 
        </style>
 
 
        <div id="addSnippetFromJson">
 
            <div class='title'><h2>Add Snippet From JSON</h2></div>
 
            <div class='fld'><input type="text" name="json" placeholder="JSON" required></div>
 
            <div class='fld'><input type="button" class="addJsonBtn" name="addSnippetFromJson" value="Add Snippet From JSON"></div>
 
        </div>
 
 
 
        <h2>Add Snippet</h2>
 
        <form>
 
            <input type="text" name="title" placeholder="Title" required>
 
            <textarea class='code-textarea' name="code" placeholder="Code" required></textarea>
 
            <input type="text" name="language" placeholder="Language" required>
 
            <input type="text" name="tags" placeholder="Tags" required>
 
            <input type="text" name="author" placeholder="Author" required>
 
            <input type="text" name="license" placeholder="License" required>
 
            <input type="submit" name="addSnippet" value="Add Snippet">
 
        </form>
 
    </div>
 
 
    <br />
 
 
    <div id="updateSnippetForm" style="display:none;">
 
        <h2>Edit Snippet</h2>
 
        <!-- just have action cancel page reload -->
 
        <form action="return false;">
 
            <input type="hidden" name="id">
 
            <input type="text" name="title" placeholder="Title" required>
 
            <textarea class='code-textarea use_ace_edit' name="code" placeholder="Code" required></textarea>
 
            <input type="text" name="language" placeholder="Language" required>
 
            <input type="text" name="tags" placeholder="Tags" required>
 
            <input type="text" name="author" placeholder="Author" required>
 
            <input type="text" name="license" placeholder="License" required>
 
            <!-- <input type="submit" name="updateSnippet" value="Update Snippet"> -->
 
            <input type="button" id="updateBtn" value="Update">
 
            <input type="button" id="cancelBtn" value="Cancel">
 
        </form>
 
 
    </div>
 
 
    <form method="post">
 
        <input type="text" name="search" placeholder="Search Snippets">
 
        <input type="submit" name="searchSnippet" value="Search">
 
    </form>
 
 
 
    
 
    <h2>Snippets List:<?php if(!empty($_SESSION['search'])) echo ' (Search: ' . $_SESSION['search']. ')'; ?></h2>
 
 
    <div id="snippetsList">
 
 
 
        <div class='snippets'>
 
 
            <?php 
 
            echo get_snippets_html();
 
            // $evenodd = 'odd';
 
            // foreach ($snippetsList as $snippet) { 
 
 
            //     echo get_snippet_html($snippet, $evenodd);
 
            //     if ($evenodd == 'odd') 
 
            //         $evenodd = 'even';
 
            //     else 
 
            //         $evenodd = 'odd';
 
            // } 
 
            ?>
 
 
        </div>
 
 
            
 
    </div>
 
 
 
    <script>
 
// BEGIN --> JAVASCRIPT COMMAND PROCESSOR //
 
 
            function do_cmd_post(url, send_data)
 
            {
 
                $.post( url, { 
 
                    flds: send_data /* in php will appear as $_POST['flds']  */ }, 
 
                    function( return_data ) { 
 
                    do_cmd_process(return_data); 
 
                    }, "json" ); // punt any returned data to processor
 
                    
 
            }
 
            // ---
 
            function do_cmd_process(data) // handle data coming back from ajax
 
            {
 
 
                if (data instanceof Array) {
 
                    data.forEach(function(entry) {
 
                        console.log(entry.command);
 
                        
 
                        //console.log(entry.message);
 
                        // handle returned commands //
 
                        switch(entry.command)
 
                        {
 
                            // generic commands //
 
                            case 'alert':
 
                                alert(entry.msg);
 
                                break;
 
                            case 'log':
 
                                console.log(entry.msg);
 
                                break;
 
                            case 'append':
 
                                $(entry.selector).append(entry.msg);
 
                                break;
 
                            case 'prepend':
 
                                $(entry.selector).prepend(entry.msg);
 
                                break;
 
                            case 'html':
 
                                $(entry.selector).html(entry.msg);
 
                                break;
 
                            case 'val':
 
                                $(entry.selector).val(entry.msg);
 
                                break;
 
                            case 'focus':
 
                                $(entry.selector).focus();
 
                                break;
 
                            case 'blur':
 
                                $(entry.selector).blur();
 
                                break;
 
                            case 'clear':
 
                                $(entry.selector).val('');
 
                                break;
 
                            case 'js':
 
                                eval(entry.msg);
 
                                break;
 
                            case 'resize_textarea_to_fit_contents':
 
                                $(entry.selector).height(0);
 
                                $(entry.selector).height($(entry.selector)[0].scrollHeight);
 
                                break;
 
                            case 'disable_input':
 
                                $(entry.selector).prop('disabled', true);
 
                                break;
 
                            case 'enable_input':
 
                                $(entry.selector).prop('disabled', false);
 
                                break;
 
 
                            case 'resize_textareas':
 
                                $(".message_content textarea").each(function(){
 
                                    $(this).css("height", ($(this).prop("scrollHeight")) + "px");
 
                                });
 
 
                                break;
 
 
                        } // end switch
 
                    });
 
                }
 
            }
 
 
// END --> JAVASCRIPT COMMAND PROCESSOR //
 
 
    $(document).ready(function() {
 
            // handle copy json button
 
            $(document).on('click', '.copyJsonBtn', function() {
 
 
                // get id from attr on button called data-id
 
                var id = $(this).attr('data-id');
 
                // get text from a dynamic element .code-snippet with a data-id of id
 
                var text_fld = $('.json-textarea[data-id="' + id + '"]').val();
 
                // now copy text_fld to clipboard
 
                // create a temporary input element
 
                var $temp = $("<input>");
 
                // add it to the document
 
                $("body").append($temp);
 
                // set the value of the input to the text_fld
 
                $temp.val(text_fld).select();
 
                // copy the text to the clipboard
 
                document.execCommand("copy");
 
                // remove the temporary input
 
                $temp.remove();
 
 
                alert('copied json to clipboard');
 
                
 
            }); // end -- handle copy json button
 
 
            // handle copy button
 
            $(document).on('click', '.copyBtn', function() {
 
 
                // get id from attr on button called data-id
 
                var id = $(this).attr('data-id');
 
                // get text from a dynamic element .code-snippet with a data-id of id
 
                var text_fld = $('.code-snippet[data-id="' + id + '"]').text();
 
                // now copy text_fld to clipboard
 
                // create a temporary input element
 
                var $temp = $("<input>");
 
                // add it to the document
 
                $("body").append($temp);
 
                // set the value of the input to the text_fld
 
                $temp.val(text_fld).select();
 
                // copy the text to the clipboard
 
                document.execCommand("copy");
 
                // remove the temporary input
 
                $temp.remove();
 
 
                alert('copied source code to clipboard');
 
                
 
            }); // end -- handle copy button
 
 
            // on click a dynamically created .addJsonBtn
 
            // add snippet from json
 
            $(document).on('click', '.addJsonBtn', function() {
 
 
                // get json from input
 
                var json = $('input[name="json"]').val();
 
 
                var send_data   = {
 
                    //"file": $('select[name="conversation_combobox"]').val()
 
                    "json": json
 
                };
 
 
                do_cmd_post('sqlite-snippets-admin.php?ajax=add-from-json', send_data);
 
 
            }); // end -- add snippet from json
 
 
            //  on click a dynamically created .deleteBtn 
 
            // delete button will alert ('hi')
 
            $(document).on('click', '.deleteBtn', function() {
 
 
                // confirm delete
 
                if(!confirm('Are you sure you want to delete this snippet?'))
 
                    return;
 
 
                // get id from attr on button called data-id
 
                var id = $(this).attr('data-id');
 
 
                var send_data   = {
 
                    //"file": $('select[name="conversation_combobox"]').val()
 
                    "id": id
 
                };
 
 
                // hide .snippet with data-id = id
 
                $('.snippet[data-id="' + id + '"]').hide();
 
 
                do_cmd_post('sqlite-snippets-admin.php?ajax=delete', send_data);
 
 
            }); // end -- delete snippet
 
 
            // updateBtn
 
            $(document).on('click', '#updateBtn', function() {
 
 
                // get id from attr on button called data-id
 
                var id = $('#updateSnippetForm').find('input[name="id"]').val();
 
 
                var send_data   = {
 
                    //"file": $('select[name="conversation_combobox"]').val()
 
                    "id": id,
 
                    "title": $('#updateSnippetForm').find('input[name="title"]').val(),
 
                    "code": $('#updateSnippetForm').find('textarea[name="code"]').val(),
 
                    "language": $('#updateSnippetForm').find('input[name="language"]').val(),
 
                    "tags": $('#updateSnippetForm').find('input[name="tags"]').val(),
 
                    "author": $('#updateSnippetForm').find('input[name="author"]').val(),
 
                    "license": $('#updateSnippetForm').find('input[name="license"]').val()
 
                };
 
 
                do_cmd_post('sqlite-snippets-admin.php?ajax=update', send_data);
 
 
            }); // end -- update snippet
 
 
 
    });
 
 
 
</script>
 
 
 
<style>
 
 
 
    .snippet {
 
        position:relative;
 
        display:block;
 
        border: 1px solid #ccc;
 
    }
 
    .snippet-data {
 
        position:relative;
 
        display:block;
 
    }
 
    
 
    .snippet .actions {
 
        position:relative;
 
        display:block;
 
        text-align:right;
 
        
 
    }
 
 
    .snippet .actions div,
 
    .snippet-data div  {
 
        display:inline-block;
 
        padding:1vw;
 
 
    }
 
 
    .snippet .actions div {
 
        cursor:pointer;
 
    }
 
 
    .snippet.even {
 
        background-color:#bbb;
 
 
    }
 
 
    .snippet.odd {
 
        background-color:#ddd;
 
    }
 
 
/* ****************************************** */
 
 
/* Container */
 
#addSnippetForm, #updateSnippetForm {
 
  background-color: #f2f2f2;
 
  border-radius: 5px;
 
  padding: 20px;
 
  width: 80%;
 
  margin: 0 auto;
 
  box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
 
}
 
 
/* Form elements */
 
input[type=text],
 
input[type=submit],
 
textarea {
 
  width: 100%;
 
  padding: 12px;
 
  border: 1px solid #ccc;
 
  border-radius: 4px;
 
  box-sizing: border-box;
 
  resize: vertical;
 
  font-size: 16px;
 
  font-family: "Arial", sans-serif;
 
  margin-bottom: 12px;
 
}
 
 
textarea {
 
  min-height: 100px;
 
}
 
 
/* Placeholder styling */
 
input[type=text]::placeholder,
 
textarea::placeholder {
 
  color: #999;
 
  font-style: italic;
 
}
 
 
/* Submit button */
 
input[type=submit] {
 
  background-color: #04AA6D;
 
  color: white;
 
  cursor: pointer;
 
  transition: background-color 0.2s;
 
}
 
 
input[type=submit]:hover {
 
  background-color: #048458;
 
}
 
 
 
/*  button */
 
input[type=button] {
 
    background-color: #007bff;
 
  border: none;
 
  border-radius: 4px;
 
  color: white;
 
  cursor: pointer;
 
  font-family: 'Roboto', sans-serif;
 
  font-size: 0.9rem;
 
  padding: 0.5rem 1rem;
 
  text-transform: uppercase;
 
}
 
 
input[type=button]:hover {
 
    background-color: #0056b3;
 
}
 
 
 
 
 
/* Form headings */
 
 h2 {
 
  font-size: 24px;
 
  font-weight: bold;
 
  margin-bottom: 20px;
 
}
 
 
 
 
/* --- */
 
 
 
 
.snippets {
 
  display: grid;
 
  /* grid-template-columns: repeat(auto-fill, minmax(1400px, 1fr)); */
 
  grid-gap: 1rem;
 
  margin: 1rem;
 
}
 
 
.snippet {
 
  background-color: #f9f9f9;
 
  border: 1px solid #e0e0e0;
 
  border-radius: 4px;
 
  padding: 1rem;
 
  font-family: 'Roboto', sans-serif;
 
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
 
}
 
 
.snippet-data {
 
  display: flex;
 
  flex-direction: column;
 
}
 
 
.title,
 
.language,
 
.tags,
 
.author,
 
.license,
 
.timestamp {
 
  font-size: 0.9rem;
 
  margin-bottom: 0.5rem;
 
}
 
 
 
 
.title {
 
  font-weight: bold;
 
  font-size: 1.1rem;
 
  margin-bottom: 0.8rem;
 
  /* border-bottom: 1px solid #e0e0e0; */
 
  /* make nicer */
 
    padding-bottom: 0.5rem;
 
 
    cursor:pointer;
 
}
 
 
.code-snippet {
 
  background-color: #f0f0f0;
 
  border: 1px solid #e0e0e0;
 
  border-radius: 4px;
 
  padding: 0.5rem;
 
  font-family: 'Courier', monospace;
 
  white-space: pre-wrap;
 
  overflow-x: auto;
 
}
 
 
.actions {
 
  display: flex;
 
  justify-content: space-between;
 
  margin-top: 1rem;
 
}
 
 
button {
 
  background-color: #007bff;
 
  border: none;
 
  border-radius: 4px;
 
  color: white;
 
  cursor: pointer;
 
  font-family: 'Roboto', sans-serif;
 
  font-size: 0.9rem;
 
  padding: 0.5rem 1rem;
 
  text-transform: uppercase;
 
}
 
 
button:hover {
 
  background-color: #0056b3;
 
}
 
 
.code-snippet .subinfo {
 
  display: flex;
 
  justify-content: space-between;
 
  margin-top: 1rem;
 
}
 
 
.code-snippet .subinfo .left {
 
  display: flex;
 
  flex-direction: column;
 
}
 
 
.code-snippet .subinfo .right {
 
  display: flex;
 
  flex-direction: column;
 
  align-items: flex-end;
 
}
 
 
.code-snippet .subinfo .left .language,
 
.code-snippet .subinfo .left .tags,
 
.code-snippet .subinfo .left .author,
 
.code-snippet .subinfo .left .license {
 
  font-size: 0.9rem;
 
  margin-bottom: 0.5rem;
 
}
 
 
.code-snippet .subinfo .right .timestamp {
 
  font-size: 0.9rem;
 
  margin-bottom: 0.5rem;
 
}
 
 
 
 
 
 
.json-row {
 
    position:relative;
 
    display: block;
 
    justify-content: space-between;
 
    margin-top: 1rem;
 
    width:100%;
 
    
 
}
 
.json-row div 
 
{
 
    position:relative;
 
    display:block;
 
    width:97%;
 
    margin:0;
 
    padding:0;
 
}
 
 
.json-row textarea {
 
    width:100%;
 
}
 
 
 
 
/* --- */
 
 
 
</style>
 
 
 
<script>
 
    /* when snippet-data .title is clicked, toggle the code snippet (nearest .subcontent section) */
 
    $(document).ready(function(){
 
        // $(".snippet-data .title").click(function(){
 
        //     $(this).next(".subcontent").slideToggle("slow");
 
        // });
 
        /* handle dynamic */
 
        $(document).on('click', '.snippet-data .title', function(){
 
            $(this).next(".subcontent").slideToggle("fast");
 
        });
 
    });
 
</script>
 
 
            
 
 
 
 
 
 
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
 
 
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/default.min.css"> -->
 
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/monokai.min.css">
 
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/github.min.css">
 
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/atom-one-dark.min.css"> -->
 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script>
 
 
 
<style>
 
    .highlight-theme {
 
        position:fixed;
 
        bottom:0px;
 
        left:0px;
 
        margin:2px;
 
 
    }
 
 
    .highlight-theme-label {
 
        position:fixed;
 
        bottom:22px;
 
        left:0px;
 
        margin:2px;
 
        font-size:0.8rem;
 
        font-weight:bold;
 
    }
 
 
</style>
 
 
<!-- label for select -->
 
<label class='highlight-theme-label' for="highlight-theme">Highlight.js theme:</label>
 
<select name='highlight-theme' class='highlight-theme' onchange="switch_highlight_theme(this.value)">    
 
    <option value='github' SELECTED>github</option>
 
    <!-- <option value='default'>default</option> -->
 
    <!-- <option value='monokai'>monokai</option> -->
 
    <!-- <option value='atom-one-dark'>atom-one-dark</option> -->
 
    <!-- <option value='nord'>nord</option> -->
 
    <!-- a11y-dark,a11y-light,agate,an-old-hope,androidstudio,arduino-light,arta,ascetic,atom-one-dark-reasonable,atom-one-light,brown-paper,dark,github-dark-dimmed,github-dark --> 
 
    <!-- <option value='github-dark'>github-dark</option> -->
 
    <!-- <option value='a11y-dark'>a11y-dark</option> -->
 
    <option value='a11y-light'>a11y-light</option>
 
    <!-- <option value='agate'>agate</option> -->
 
    <option value='arduino-light'>arduino-light</option>
 
    <!-- <option value='arta'>arta</option> -->
 
    <!-- <option value='atom-one-dark-reasonable'>atom-one-dark-reasonable</option> -->
 
    <option value='googlecode'>googlecode</option>
 
    <option value='intellij-light'>intellij-light</option>
 
    <!-- <option value='kimbie-light'>kimbie-light</option> -->
 
 
</select>
 
 
<script>
 
    function getCookie(cname) 
 
    {
 
        var name = cname + "=";
 
        var decodedCookie = decodeURIComponent(document.cookie);
 
        var ca = decodedCookie.split(';');
 
        // console.log(ca);
 
        for(var i = 0; i <ca.length; i++) 
 
        {
 
            var c = ca[i];
 
            // console.log(c);
 
            while (c.charAt(0) == ' ') 
 
            {
 
                c = c.substring(1);
 
            }
 
            if (c.indexOf(name) == 0) 
 
            {
 
                return c.substring(name.length, c.length);
 
            }
 
        }
 
        return "";
 
    }
 
 
    // if there is a cookie set, switch to that theme
 
    // on document ready
 
    $(document).ready(function(){
 
        var highlight_theme = getCookie('highlight-theme');
 
        if (highlight_theme != "") {
 
            switch_highlight_theme(highlight_theme);
 
        }
 
    });
 
 
 
    function switch_highlight_theme(themename)
 
    {
 
        /* save a cookie with current highlight */
 
        document.cookie = "highlight-theme="+themename+"; path=/; SameSite=None; Secure";
 
        // remove all highlight.js stylesheets
 
        $('link[href*="highlight.js"]').remove();
 
        // add the new one
 
        $('head').append('<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/'+themename+'.min.css">');
 
        // update the highlights
 
        update_highlights();
 
    }
 
</script>
 
 
 
<style>
 
/* for highlights */
 
.code-snippet {
 
    background-color:#fff;
 
        /* color:#fff; */
 
        padding:1rem;
 
        border:1px solid #333;
 
 
}
 
</style>
 
 
<script>
 
 
    function update_highlights()
 
    {
 
        $(document).ready(function() {
 
            // update_highlights();
 
            document.querySelectorAll('#code-textarea,.code-snippet').forEach(el => {
 
                // if we do not already have a highlit element then..
 
                if (!el.classList.contains('hljs')) 
 
                {
 
                    // escape the text //
 
                    el.innerHTML = el.innerHTML.replace(/</g, '<').replace(/>/g, '>');
 
                    hljs.highlightElement(el);
 
                }
 
            });
 
        });
 
    };
 
 
    update_highlights();
 
 
    // when a .title is clicked, update_highlights
 
    $(document).ready(function(){
 
        $(document).on('click', '.snippet-data .title', function(){
 
            update_highlights();
 
        });
 
    });
 
 
 
</script>
 
 
 
 
 
<!-- BEGIN BEGIN BEGIN BEGIN -- ace.js code editor (my js cookie class and jq plugin) -->
 
 
                        <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> -->
 
                        <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.19.0/ace.js"></script>
 
                    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.19.0/ext-language_tools.js"></script>
 
                    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.19.0/ext-beautify.js"></script>
 
                    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.19.0/ext-settings_menu.js"></script>
 
                    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.19.0/ext-spellcheck.js"></script>
 
                    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.19.0/ext-whitespace.js"></script>
 
                    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.19.0/ext-split.js"></script>
 
                    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.19.0/ext-searchbox.js"></script>
 
                    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.19.0/ext-statusbar.js"></script>
 
                    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.19.0/ext-textarea.js"></script>
 
 
                    <script>
 
  // simple cookie class in javascript
 
  class Cookie {
 
    constructor() {
 
      this.cookie = document.cookie;
 
    }
 
 
    get(name) {
 
      const value = this.cookie.match(`(^|;)\\s*${name}\\s*=\\s*([^;]+)`);
 
      return value ? value.pop() : '';
 
    }
 
 
    set(name, value, days) {
 
      let expires = '';
 
      if (days) {
 
        const date = new Date();
 
        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
 
        expires = `; expires=${date.toUTCString()}`;
 
      }
 
      // set for SameSite=None; 
 
 
      document.cookie = `${name}=${value || ''}${expires}; path=/; SameSite=None; Secure`;
 
 
      // document.cookie = `${name}=${value || ''}${expires}; path=/`;
 
    }
 
 
    delete(name) {
 
      this.set(name, '', -1);
 
    }
 
  } // end my cookie class
 
 
  // example usage:
 
  // const cookie = new Cookie();
 
  // cookie.set('name', 'value', 7);
 
  // cookie.get('name');
 
  // cookie.delete('name');
 
 
</script>
 
                    <!-- the plugin -->
 
                    <script>
 
(function($) {
 
  $.fn.customAceEditor = function(removeyn='no', themeselect_id='#theme-selector', modeselect_id='#mode-selector') {
 
    // removeyn = 'destroy' to remove the editor
 
 
    // make an editors array
 
    var editors = [];
 
 
    if (removeyn == 'destroy') {
 
      return this.each(function() {
 
        const textarea = $(this);
 
        const editorDiv = textarea.prev();
 
        editorDiv.remove();
 
        textarea.show();
 
        textarea.removeClass('hascodearea');
 
      });
 
    }
 
 
    if (this.hasClass('hascodearea')) {
 
      this.customAceEditor('destroy');
 
    }
 
 
    this.each(function() {
 
 
      const textarea = $(this);
 
      const editorDiv = $('<div class="hascodearea">').insertBefore(textarea).width(textarea.width()).height(textarea.height());
 
      
 
      const textarea_content = textarea.val();
 
      
 
      textarea.addClass('hascodearea');
 
      textarea.hide();
 
 
      /* to autoresize the Ace editor first you need to set the height of the editor to auto and then call the resize() method on the editor instance. */
 
      /* example calling the resize method on the editor instance:
 
      var editor = ace.edit("editor");
 
      editor.resize();
 
      */
 
 
 
      const editor = ace.edit(editorDiv[0], {
 
        autoScrollEditorIntoView: false,
 
        width: '100%',
 
        height: 'auto',
 
        fontSize: '16px',
 
        tabSize: 4,
 
        useSoftTabs: true,
 
        showPrintMargin: false,
 
        showGutter: true,
 
        highlightActiveLine: true,
 
        wrap: true,
 
        enableBasicAutocompletion: true,
 
        enableLiveAutocompletion: true,
 
        enableSnippets: true,
 
        maxLines: Infinity,
 
        minLines: 5,
 
        maxLines: 900000,
 
        scrollPastEnd: 1, /* fixed line 1 disappearing */
 
      });
 
 
      // add to editors array
 
      editors.push(editor);
 
 
 
      /* when window resizes, resize this editor */
 
      editor.setAutoScrollEditorIntoView(true);
 
      editor.setValue(textarea_content, 1); // 1 = moves cursor to end
 
 
// localstorage
 
//    use themeselect_id and modeselect_id to prefix the localstorage keys
 
      // revamped to use cookies, however have some variables still sharing localstorage name
 
    
 
      localstorage_prefix_theme   =  themeselect_id;
 
      localstorage_prefix_mode    =  modeselect_id;
 
      // clean the . and # out of the id's
 
      localstorage_prefix_theme   =  localstorage_prefix_theme.replace(/\.|#/, '');
 
      localstorage_prefix_mode    =  localstorage_prefix_mode.replace(/\.|#/, '');
 
 
      cookie_name_theme = localstorage_prefix_theme+'_theme';
 
      cookie_name_mode  = localstorage_prefix_mode+'_mode';
 
 
      const cookie = new Cookie();
 
 
      console.log('cookie theme:',cookie_name_theme,"::",cookie.get(cookie_name_theme));
 
      console.log('cookie mode:',cookie_name_mode,"::",cookie.get(cookie_name_mode));
 
 
      const defaultTheme = cookie.get(cookie_name_theme) || 'monokai';
 
      const defaultMode = cookie.get(cookie_name_mode) || 'text';
 
 
 
// ^^ localstorage
 
 
      editor.setTheme(`ace/theme/${defaultTheme}`);
 
      editor.session.setMode(`ace/mode/${defaultMode}`);
 
 
    //   editor.session.on('change input', function() {
 
    //     textarea.val(editor.getValue());
 
    //   });
 
 
      const themes = [
 
        "monokai", 
 
            "ambiance", "chaos", "chrome", "clouds", "clouds_midnight", "cobalt",
 
            "crimson_editor", "dawn", "dracula", "dreamweaver", "eclipse", "github",
 
            "gob", "gruvbox", "idle_fingers", "iplastic", "katzenmilch", "kr_theme",
 
            "kuroir", "merbivore", "merbivore_soft", "mono_industrial", "monokai",
 
            "pastel_on_dark", "solarized_dark", "solarized_light", "sqlserver",
 
            "terminal", "textmate", "tomorrow", "tomorrow_night", "tomorrow_night_blue",
 
            "tomorrow_night_bright", "tomorrow_night_eighties", "twilight", "vibrant_ink",
 
            "xcode"
 
        // ... (other themes)
 
      ];
 
 
      const themeSelector = $(themeselect_id);
 
// add attr data-cookie=cookie_name_theme
 
      themeSelector.attr('data-cookietheme', cookie_name_theme);
 
      themeSelector.attr('test', 'testthemmmme');
 
 
      themes.forEach(theme => {
 
        themeSelector.append($('<option>').val(theme).text(theme));
 
      });
 
 
      themeSelector.val(defaultTheme);
 
 
      themeSelector.on('change', function() {
 
        editor.setTheme(`ace/theme/${this.value}`);
 
// localstorage
 
        // localStorage.setItem(localstorage_prefix_theme+'defaultTheme', this.value);
 
        // get cookie name from attr data-cookie
 
        cookie_name = $(this).attr('data-cookietheme')
 
        const cookie = new Cookie();
 
        cookie.delete(cookie_name);
 
        cookie.set(cookie_name, this.value, 7);
 
        // alert(this.value);
 
      });
 
 
      const modes = [
 
            "text",
 
            "javascript", "php", "python", "ruby", "html", "css", "php", "java", "c_cpp",
 
            "markdown", "json", "xml", "yaml", "typescript", "sql", "go", "lua",
 
            "swift", "perl", "csharp", "rust", "r"
 
        // ... (other modes)
 
      ];
 
 
      const modeSelector = $(modeselect_id);
 
// add attr data-cookie=cookie_name_mode
 
      modeSelector.attr('data-cookiemode', cookie_name_mode);
 
 
 
      modes.forEach(mode => {
 
        modeSelector.append($('<option>').val(mode).text(mode));
 
      });
 
 
      modeSelector.val(defaultMode);
 
 
      modeSelector.on('change', function() {
 
        editor.session.setMode(`ace/mode/${this.value}`);
 
// localstorage
 
        // localStorage.setItem(localstorage_prefix_mode+'defaultMode', this.value);
 
        // get cookie name from attr data-cookie
 
        cookie_name = $(this).attr('data-cookiemode')
 
        const cookie = new Cookie();
 
        cookie.delete(cookie_name);
 
        cookie.set(cookie_name, this.value, 7);
 
      });
 
 
    //   editor.setValue(textarea.val(), 1);
 
    // set editor value to textarea
 
 
    }); // end each
 
 
    return editors;
 
 
 
 
 
  };
 
})(jQuery); // end jquery plugin
 
                    </script>
 
 
<script>
 
    // use use use
 
 
    // after the .code-textarea, append a row containing two blank select boxes with a class of .theme-selector and .mode-selector
 
    // the code for the jquery append
 
    $('.use_ace_edit').after('<div class="row"><div class="col-sm-6"><select class="theme-selector"></select></div><div class="col-sm-6"><select class="mode-selector"></select></div></div>');
 
 
 
    // $('.code-editor-1').customAceEditor('no', '.theme-selector-1', '.mode-selector-1');
 
    // document ready
 
 
    
 
    // $('.code-textarea').customAceEditor('no', '.theme-selector', '.mode-selector');
 
 
    // document ready first
 
    $(document).ready(function() {
 
 
        var the_editors = [];
 
 
 
        $(document).on('click', '.editBtn', function() {
 
            // when form done showing execute this
 
            // show and when complete showing do $('#updateSnippetForm')
 
            // after showing #updateSnippetForm, execute this
 
            var code = $(this).data('code');
 
            console.log(code);
 
            // code is escaped so unescape it
 
            const parser = new DOMParser();
 
            const doc = parser.parseFromString(code, 'text/html');
 
            code = doc.documentElement.textContent;
 
            console.log(code);
 
 
            the_editors = $('.use_ace_edit').customAceEditor('no', '.theme-selector', '.mode-selector');
 
            // find ace editor kind of like
 
            // editor = document.querySelector('.ace_editor')
 
            // the_editors should contain an array of ace editors
 
            // loop through an set their value to code
 
            the_editors.forEach(editor => {
 
                editor.setValue(code, 1);
 
            });
 
 
            console.log(the_editors);
 
            
 
        });
 
 
        // when a key down is clicked while an ace code editor is focused
 
        // set the textarea value to the ace editor value
 
        $(document).on('keydown', function() {
 
            the_editors.forEach(editor => {
 
                $('.use_ace_edit').val(editor.getValue());
 
                console.log(editor.getValue());
 
            });
 
 
        });
 
            
 
    });
 
 
</script>
 
 
 
 
                    <script>
 
                        // get all ace.js code editors on page, and set them to 100% width (fixed an autoresize issue)
 
                        const editors = document.querySelectorAll('.ace_editor');
 
                        editors.forEach(editor => {
 
                            editor.style.width = '100%';
 
                        });
 
                    </script>
 
 
<!-- END END END -- ace.js code editor -->
 
 
 
 
</body>
 
</html>
 
 |