PHP Classes

PHP SQLite Code Vault: Manage sets of code snippets stored in SQLite

Recommend this page to a friend!
  Info   Example   Screenshots   View files Files   Install with Composer Install with Composer   Download Download   Reputation   Support forum   Blog    
Ratings Unique User Downloads Download Rankings
Not enough user ratingsTotal: 90 All time: 9,949 This week: 47Up
Version License PHP version Categories
phpsqlitesnippets 1.0.15BSD License8Databases, Content management, Projec..., A..., P..., A...
Description 

Author

This package can manage sets of code snippets stored in SQLite.

It provides a class and a simple application script that can perform several types of operations to store and retrieve code snippets using an SQLite database.

Currently, it can:

- Create an SQLite database table to store the snippets

- Perform searches for code snippets in the snippets' code, title, author, language, license, and tags, using regular searches or fuzzy searches

- Add, update, and delete snippets

- Get all snippets with the possibility to filter by language and tags

- Get a snippet by ID

- Get the count of all snippets stored in a database

Innovation Award
PHP Programming Innovation award nominee
April 2023
Number 11
Many developers have a set of code snippets that they frequently use in their projects.

Organizing those snippets in a way that is easy to find the snippet that you want to use in each project situation, is a challenge.

This package provides a solution to organize better collections of code snippets.

It provides an easy-to-use application that developers can use to manage collections of snippets with the possibility to search for snippets with names that may be misspelled and so tolerate typing mistakes.

Manuel Lemos
Picture of JImmy Bo
  Performance   Level  
Name: JImmy Bo is available for providing paid consulting. Contact JImmy Bo .
Classes: 14 packages by
Country: United States United States
Age: ???
All time rank: 1198173 in United States United States
Week rank: 12 Up2 in United States United States Up
Innovation award
Innovation award
Nominee: 8x

Winner: 1x

Example

<?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, '&lt;').replace(/>/g, '&gt;');
                    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>


Screenshots (1)  
  • thumb-snippets.png
  Files folder image Files (3)  
File Role Description
Accessible without login Plain text file sqlite-snippets-admin.php Example An example admin page for SQLiteCodeVault class to manage code snippets in a SQLite database.
Plain text file sqlite-snippets-manager.php Class A php class to manage code snippets in a SQLite database.

The PHP Classes site has supported package installation using the Composer tool since 2013, as you may verify by reading this instructions page.
Install with Composer Install with Composer
 Version Control Unique User Downloads Download Rankings  
 0%
Total:90
This week:0
All time:9,949
This week:47Up
User Comments (1)
Excellent
1 year ago (Walter Seibold)
70%StarStarStarStar