npm.nicfv.com
    Preparing search index...

    Save Data

    We can save data to our browser's localStorage object, which persists through browser and system restarts, and has no built-in expiration date. This type of storage is good for small data objects such as user preferences, settings, or high scores.

    Note 2: localStorage is not shared between different browsers or systems. Additionally, incognito browser tabs will use a different localStorage which automatically clears when the tab or window is closed.

    We can use graphico's built-in functions to save data, load data, or clear data from localStorage. We can assign a "namespace" to differentiate our data from basic browser local storage and from different data sets that we define. For example, we can have multiple user profiles, where each user profile lives in its own namespace. For safety, we can only clear namespaces that we define when saving data.

    Note 1: localStorage can be completely cleared by clearing your browser's data.

    In this example we do just that - we define a set of user profiles, each containing data of the amount of time each key was pressed. (The canvas must be focused in order to capture keyboard input.) We can switch between different user profiles to see that a unique dataset was saved under each profile.

    Security Enhancements

    If you use the Inspect Element tool (on any website or web app), you can see your local storage by typing localStorage in the console, and you'll notice that most of these are stored in readable text. For slightly better security, graphico automatically encodes and decodes this data with a base64 encoding so it cannot be directly read and edited as easily using Inspect Element.

    Follow these steps to create a new webpack project and install the graphico dependency to run this example.

    # Create and open project folder
    mkdir Save_Data_demo
    cd Save_Data_demo
    # Initialize project and install dependencies
    npm init -y
    npm pkg set type="module"
    npm i graphico@1.3.0 webpack-cli
    # Create source files
    touch index.html
    mkdir src
    touch src/index.js
    # Open new files
    open index.html
    open src/index.js

    Copy and paste the following source code blocks into the newly created files.

    <html>

    <head>
    <script type="text/javascript" src="dist/main.js" defer></script>
    </head>

    <body></body>

    </html>
    import { Canvas } from 'graphico';

    class Text {
    #text;
    #x;
    #y;
    #size;
    #color;
    #align;
    #baseline;
    constructor(x = 0, y = 0, size = 12, color = 'black', align = 'center', baseline = 'middle') {
    this.#x = x;
    this.#y = y;
    this.#size = size;
    this.#color = color;
    this.#align = align;
    this.#baseline = baseline;
    }
    setText(text = '') {
    this.#text = text;
    }
    draw(graphics) {
    graphics.fillStyle = this.#color;
    graphics.font = `bold ${this.#size}px monospace`;
    graphics.textAlign = this.#align;
    graphics.textBaseline = this.#baseline;
    this.#text.split('\n').forEach((line, num) => {
    graphics.fillText(line, this.#x, this.#y + num * this.#size * 1.5);
    });
    }
    }

    // Define the signed-in user and their data
    let user = 'none';
    let data = {};

    // Create text elements
    const profile = new Text(10, 10, 24, 'black', 'left', 'top');
    const action = new Text(10, 50, 20, 'gray', 'left', 'top');
    const instruct = new Text(10, 100, 20, 'orange', 'left', 'top');
    const raw = new Text(300, 350);

    // Set static text for action and instructions
    action.setText('No action taken');
    instruct.setText(`Instructions:
    1-9 = Load user profile.
    0 = Log out.
    s = Save data.
    x = Clear data for current profile.
    <any key> = Count # of times pressed.`);

    const canv = new Canvas({
    border: 'black',
    borderBlur: 'lightgray',
    width: 600,
    height: 400,
    keydown(key) {
    if (/[1-9]/.test(key)) {
    // Pull up a user's profile
    user = `user${key}`;
    data = canv.loadData(user) ?? {}; // loadData may be undefined, so default to empty object
    action.setText(`Loaded data for ${user}!`);
    } else if (key === '0') {
    // Log out of the current user
    user = 'none';
    data = {};
    action.setText('Logged out.');
    } else if (key === 's' && user !== 'none') {
    // Save user data
    canv.saveData(data, user);
    action.setText(`Saved data for ${user}!`);
    } else if (key === 'x') {
    // Clear user data
    data = {};
    canv.clearData(user);
    action.setText('Cleared all data.');
    } else if (user !== 'none') {
    // Count up the number of times pressed
    if (typeof data[key] === 'number') {
    data[key]++;
    } else {
    data[key] = 1;
    }
    action.setText(`Pressed key: ${key}. Total = ${data[key]}`);
    }
    },
    loop(dt) {
    profile.setText(`Current profile: ${user}.`);
    raw.setText(JSON.stringify(data));
    canv.clear();
    canv.draw(profile);
    canv.draw(action);
    canv.draw(instruct);
    canv.draw(raw);
    },
    });

    In the base project directory Save_Data_demo/, run the following command. If changes are made in the source files, the demo will automatically be recompiled. Press CTRL+C to stop running.

    npx webpack --mode development --watch
    

    Open the index.html file in any web browser of your choice! You should see a page similar to the one below.