data-context logo

data-context

Watch data changes in the browser and node.js

πŸ“š Table of contents

Back to top ↑


✨ Features

Back to top ↑


πŸ“‹ Description

The 'data-context' module provides a way to create a data context that can watch for changes in the data.

It is a simple and easy-to-use library that can be used in the browser or in node.js. You can create a context from the data, then listen for change events and stringify changes. Included event-emitter functions. Automatically detects changes in the data and emits events. Designed for module 'data-context-binding' for binding data to the DOM and for module 'fs-broker' for working with files. Using a single-page application (SPA) with the 'data-context-binding' module gives very good results. This module is part of the 'conextra' framework, which is a simple and easy-to-use single-page application (SPA) framework. You have to try it! A different solution than MVC (model–view–controller).

Please note, this version is not backward compatible with version 1.x
Please note that JSON string is not 100% compatible.
It has been extended to allow for incremental updates of JSON files.
Added the ability to include metadata and comments.
Parsing of JSON files is enabled.

The code in 'data-context' provides a robust mechanism for creating data contexts that can track changes, emit events, and support serialization/deserialization. It leverages JavaScript proxies to intercept and manage property operations, making it a powerful tool for managing state in complex applications.

The data context library implemented in 'data-context' can be used in various scenarios where tracking changes to data, emitting events, and managing state are essential. Here are some potential use cases:

1. State Management in Single Page Applications (SPAs)

2. Data Binding

3. Form Handling

4. Real-time Collaboration

5. Undo/Redo Functionality

6. Data Synchronization

7. Configuration Management

8. Logging and Auditing

9. Testing and Debugging

10. Incremental JSON Updates

Back to top ↑


πŸ“¦ Installation

Available on npm

nodejs:

npm install data-context

browser:

or use CDN (for an HTML page hosted on the server):

<script src="./node_modules/data-context/borwser.js" type="text/javascript"></script>

or use CDN (for a standalone HTML page):

<script src="https://cdn.jsdelivr.net/npm/data-context" type="text/javascript"></script>

or use 'tiny-https-server':

<script async src="node_modules/data-context@2"></script>

Back to top ↑


πŸ§ͺ Testing

You can test data-context on your system using this command:

node ./node_modules/data-context/index.test

or in the data-context project directory:

npm test

or open in your browser:

./node_modules/data-context/index.test.html

Back to top ↑


πŸš€ Usage

nodejs example:

'use strict';

//Import the required modules.
const { createDataContext, parse } = require('data-context');
//import { createDataContext, parse } from "data-context";

//Create a JSON string.
var strJSON = `{
    "count": 0
}`;

//Interval id.
var intervalId = null;

//Create data context.
const context = parse(
    //Parse the JSON string.
    strJSON,
    //Reviver function. Create data context.
    createDataContext
);

//Listen to the count property.
context.on('count', (event) => {

    console.log('event:', event);

    if (event.newValue > 10) {

        console.log('I am dead.');
        clearInterval(intervalId);

        //I am dead. Remove listener.
        return false;
    }

    //I am live. Continue listening.
    return true;
});

context.on('-change', (event) => {

    //Stringify the changes.
    var str = context.stringifyChanges(
        //Reviver function. Default is null.
        null,
        //Indentation. Default is 0.
        4,
        //Include only modified data. Default is true.
        true,
        //Set data to unmodified after stringification. Default is true.
        true
    );
    console.log('changes:', str);

    //I am live. Continue listening.
    return true;
});

//Start the interval.
intervalId = setInterval(() => {

    //Increment the count property.
    context.count++;
}, 1000);

browser example:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>data-context</title>
    <!-- STEP 1. Import the module. Import for an HTML page hosted on the server. -->
    <script type="text/javascript" src="./index.js"></script>
    <!-- STEP 1. Import the module. Import for a standalone HTML page. -->
    <!--<script src="https://cdn.jsdelivr.net/npm/data-context"></script>-->
    <script>

        'use strict';

        // STEP 3. Import the module.
        importModules(['data-context'], function (DC) {

            var { createDataContext, parse } = DC;

            //Create a JSON string.
            var strJSON = `{
                "count": 0
            }`;

            //Interval id.
            var intervalId = null;

            //Create data context.
            const context = parse(
                //Parse the JSON string.
                strJSON,
                //Reviver function. Create data context.
                createDataContext
            );

            //Listen to the count property.
            context.on('count', (event) => {

                console.log('event:', event);

                if (event.newValue > 10) {

                    console.log('I am dead.');
                    clearInterval(intervalId);

                    //I am dead. Remove listener.
                    return false;
                }

                //I am live. Continue listening.
                return true;
            });

            context.on('-change', (event) => {

                //Stringify the changes.
                var str = context.stringifyChanges(
                    //Reviver function. Default is null.
                    null,
                    //Indentation. Default is 0.
                    4,
                    //Include only modified data. Default is true.
                    true,
                    //Set data to unmodified after stringification. Default is true.
                    true
                );
                console.log('changes:', str);

                //I am live. Continue listening.
                return true;
            });

            //Start the interval.
            intervalId = setInterval(() => {

                //Increment the count property.
                context.count++;
            }, 1000);
        });

        // STEP 2. Add module import function.
        /**
         * Module import function.
         * @param {string[]} importIdentifierArray Modules to import.
         * @param {(...importModules:any[]) => void} callback Callback function.
         */
        function importModules(importIdentifierArray, callback) {

            var thisScope = "undefined" != typeof globalThis
                ? globalThis
                : "undefined" != typeof window
                    ? window
                    : "undefined" != typeof global
                        ? global : "undefined" != typeof self
                            ? self
                            : {};

            if (!thisScope.modules) { thisScope.modules = {}; }

            waitModules();


            function waitModules() {

                if (importIdentifierArray.length) {

                    for (let i = 0; i < importIdentifierArray.length; i++) {

                        if (!thisScope.modules[importIdentifierArray[i]]) { return setTimeout(waitModules, 10); }
                    }
                }

                callback.call(thisScope, ...importIdentifierArray.map(function (id) { return thisScope.modules[id]; }));
            }
        }
    </script>
</head>
<body>
    <h3>Example 'data-context'</h3>
    <p>Press F12. Console results.</p>
</body>
</html>

πŸ“– API Reference

Back to top ↑

createDataContext(data, propertyName, parent)

Create a data context from the data.

Type: function

Parameters:

Returns:

Static Properties:

Back to API Reference ↑

Back to top ↑


DataContext

The data context Proxy object.

Type: Proxy

Properties:

Methods:

Back to API Reference ↑

Back to top ↑


EventListener(event)

The event listener function.

Type: function

Parameters:

Returns:

Back to API Reference ↑

Back to top ↑


EventObject

The event object.

Type: object

Properties:

Back to API Reference ↑

Back to top ↑


PropertyName

The property name.

Type: string

Back to API Reference ↑

Back to top ↑


Reviver

The reviver function.

Type: reviver or createDataContext or null

Back to API Reference ↑

Back to top ↑


πŸ“œ License

This project is licensed under the MIT License.
Copyright Β© Manuel LΓ΅hmus

Back to top ↑