Patch Notes

Version 25.0.0

Can use data-scope with empty string (it will have no effect)

Requires optional chaining operator support

Make scopeFromArray return empty string if something is undefined

Make scopeFromEvent return undefined if there is not .target property

Make scopeFromEvent return something appropriate even when a function plugin is used

Add keyboard plugin, deprecate move plugin

Version 24.0.0

Depend upon the global JS variable Object.hasOwn, a polyfill or es2022 is required

Version 23.1.0

Revert default input type range event to "input" to be more fluid

base url is (old url is redirected)

Version 23.0.0

Remove deprecated data-list="x-li" syntax. For a smooth upgrade install version 22.0.0 and fix warnings in the console

Dark mode support

Version 22.0.0

The examples and documentation no longer run on IE

The code is no longer transpiled to ES5

The code is no longer minified

Version 21.0.0

data-list is split into data-list and data-use

Replace data-list="x-li" with data-list="x" data-use="li"


  • dom99Script.js into dom99.iife.js
  • dom99Script.es5.js into dom99.iife.es5.js
  • dom99Script.es5.min.js into dom99.iife.es5.min.js
  • dom99Require.js into dom99.cjs.js
  • dom99Amd.js into dom99.amd.js
  • dom99ES.js into
  • dom99ES.min.js into

Version 20.0.0

start uses named parameters, drop callback

inside has been renamed into scope

data-template can be used in combination with data-list

Version 19.1.0

Allow data-template to be used on non template elements

Version 19.0.10

Build files automatically when installing from github with npm i GrosSacASac/DOM99

Version 19.0.0

FIRST_VARIABLE_FROM_USER_AGENT is the default option for firstVariableValueStrategy:

FIRST_VARIABLE_FROM_HTML, FIRST_VARIABLE_FROM_USER_AGENT, options are no longer exported by the default import entry

leafName and leafIndex are exported

Version 18.0.0

idGenerator is not exported by default. To continue using it:

import {idGenerator} from "./node_modules/dom99/source/idGenerator.js"

Version 17.0.0

Remove deleteTemplate , activate, forgetContext

Rename all path and context into scope, Rename data-inside into data-scope

Change argument order of start, options can not be accessed after initialization, instead pass wanted options to create

Move default options into a separate file source/defaultOptions.js

Version 16.0.0

New URL for website (now Update your bookmarks.

Generated files are not in the git anymore. Generate them with the commands defined in package.json or download pre built files with npm or use URL or

Version 15.4.0

expose d.element(string) function. It is a convenience function for d.elements[string]. It is safer to use because it cannot accidently set private variables.

Version 15.3.0

add options.firstVariableValueStrategy. It can be set to undefined which is the default with same behaviour as before, or set to d.FIRST_VARIABLE_FROM_HTML or d.FIRST_VARIABLE_FROM_USER_AGENT or a custom function (element) => value

Version 15.2.0

expose d.get(string) function. It is a convenience function for d.variables[string]. It is safer to use because it cannot accidently set private variables without explicit d.feed()

Version 15.1.0

Factory for creating independent dom99 realms is now provided. The main dom99.js interface remains unchanged and still exports a singleton. Internally dom99.js now imports dom99create.js, creates one instance and exports it. Have a look at source/dom99.js to know how to use this feature.

Version 15.0.0

The new way of importing is
import * as d from "./node_modules/dom99/built/dom99ES.js"; It is equivalent to but without runtime overhead:

import {
    getParentContext, plugin, options, createElement2
} from "./node_modules/dom99/built/dom99ES.js";
const d = {
    getParentContext, plugin, options, createElement2

Remove built/dom99.min.js

Version 14.4.0

Add built/dom99ES.min.js, deprecate built/dom99.min.js

Version 14.3.0

Add built/dom99ES.js (single file)

Version 14.2.0

Add export idGenerator

Version 14.1.0

Add plugin type clone. It allows to target a template copy just before it is inserted into the document

Version 14.0.0

Add plugin system for variables:

  • d.feed
  • data-variable="a"
  • data-list="list-li"

Refactor plugin system

Version 13.0.0

The library is now an ES module first. From that, script require and amd are built. The default export is split into 4 named exports {d, plugin, options, createElement2}

Changes required in the code:

d.plugin --> plugin

d.options --> options

d.createElement2 --> createElement2

For ES module users: built/dom99Module.js --> source/dom99.js

Replace import d from "...built/dom99Module.js"; with
import {d, plugin, options, createElement2} from ".../source/dom99.js";

For script users: js/dom99.js --> built/dom99Script.js

built/dom99.es5.min.js --> built/dom99Script.es5.min.js

Add const {d, plugin, options, createElement2} = dom99;

For browserify users

Replace const d = require("dom99"); with
const {d, plugin, options, createElement2} = require("dom99");

Add dom99Amd.js

Version 12.0.0

Components readTextFile and yesNoDialog use dependency injection. Use `useReadTextFile(d);` or `useYesNoDialog(d);` before `d.start();` or similar.

Version 11.1.4

Add dom99Module.min.js

Version 11.1.0

ReadTextFile component is available

Version 11.0.0

Remove a IE bugfix that is already resolved by template-mb

Version 10.0.0

d.feed signature is inverted to be more like JS Objects and Maps and Arrays

    feed = function (startPath, data) {
        if (data === undefined) {
            data = startPath;
            startPath = ``;

With one parameter the effect is the same as before

With two parameters the startPath is now the first argument

        d\.feed\((.+)\, (.+)\)
        d.feed($2, $1)

Version 9.1.0

Plugin: shake

Version 9.0.0

IE 9 support is maintained by external polyfills

To still support IE 9+ npm install template-mb and include it like in the file examples/index.html

Drop Bower and bower.json

Version 8.2.0

Support for cases when an element is inside another that uses data-function Ex. button > span

Version 8.1.0

Files are now built:

  • built/dom99Module.es5.js
  • built/dom99Require.es5.js

Version 8.0.0

  • forgetRemoveTemplate into deleteTemplate
  • linkJsAndDom into activate
  • options.attributeValueDoneSign into options.doneSymbol
  • options.elementsForUserInputList into options.tagNamesForUserInput
  • options.directives.directiveFunction into options.directives.function
  • options.directives.directiveVariable into options.directives.variable
  • options.directives.directiveElement into options.directives.element
  • options.directives.directiveInside into options.directives.inside
  • options.directives.directiveList into options.directives.list
  • options.directives.directiveTemplate into options.directives.template
  • options.propertyFromElement
  • options.eventNameFromElement
  • options.variablePropertyFromTagAndType
  • options.eventFromTagAndType

Version 7.2.18

add .npmignore

Version 7.2.16

Remove warnings

Version 7.2.13

fix a bug that only occurred on edge, but not IE

Version 7.2.5

Polyfill for hidden

Better CSS

prompt equivalent in yesNoDialog components folder

Version 7.2.3

Enable IE 10 again

Version 7.2.0

data-scope extension, can be used without is="" and without custom element. In this case all children will be encapsulated under the name space of the data-scope attribute. Good for encapsulation of independent components. See how it is used in components/yesNoDialog/

YesNoDialog remake, and compatible again with the last major dom99 version

dom99ConfigurationExample remake with clearer steps

added deleteTemplate

fixed a potential memory leak

Version 7.1.0

experimenting with d.start(userFunctions = {}, initialFeed = {}, startElement = document.body, callBack = undefined)

d.start does what you think, the right way

const start = function (userFunctions = {}, initialFeed = {}, startElement = document.body, callBack = undefined) {
        Object.assign(functions, userFunctions);
        if (!callBack) {
        return callBack();

Version 7.0.0

renamed dom99 variable into just d

d.getParentContext removed. To navigate through context there are now 3 functions that work together:

  • d.contextFromEvent to get the context from the event
  • d.contextFromArray to build up a direct access string to go 1 level up the tree
  • d.getParentContext to go 1 level down the tree

this model is more flexible than before but requires more code, example to change color from sister element

<button data-function="changeSister">Click Me</button>
<div data-element="div">Lorem Ipsul sister</div>

d.functions.changeSister = function (event) {
    const thisContext = d.contextFromEvent(event);
    const sisterAccessContext = d.contextFromArray([thisContext, "div"]);
    const sisterDiv = d.elements[sisterAccessContext];

This works anywhere including, deep inside other data-list="" and data-scope="" The div does not have to be a sister element html speaking, but only from dom99 point of view This would work too

<button data-function="changeSister">Click Me</button>
        <time><div data-element="div">Lorem Ipsul sister</div></time>

To go one level down use d.getParentContext(context)

Now use boost license. It is more permissive than MIT because you don't need to include (but still can if you want) the license in distributed executables or transpiled code

Getting data uses d.variables

Setting data uses d.feed({ result: "Please enter finite numbers" }); or d.feed("result", "Please enter finite numbers"); Setting data previously called a function (object setter) but it was implicit. Now it is explicit

dom variables are not always converted to Strings anymore. this makes d.bool anymore

Version 5.0.0

Rename data-vr into data-variable

Split data-el into data-element and data-template

Rename data-fx into data-function

Rename data-in into data-scope

Version 4.0.0


Version 3.0.3

Omitting the event type with data-function will now use default sane event types. See variable eventFromTag in dom99.js for more information

Version 3.0.1

Fixed a rare bug that could occur with a a property name hasOwnProperty

The es5 version and the source dom99.js will now do strictly the same except for logging errors and warnings. There will no longer be invisible checks at runtime to see if the arguments are valid, only logs, this should slightly improve performance

Version 2.0.0

Switch to SEMVER versioning

d.variables setter will not transform into a string , D.bool is removed

D.followPath, remove. The event object is not extended anymore. To get the context use D.getParentContext( instead. It returns a static context object


Change function syntax for multiple listeners data-function="event1-function1,event2-function2"

d.functions must be populated before d.start() is called

eventFromTagAndType change into eventNameFromElement

variablePropertyFromTagAndType change into variablePropertyFromElement

elementsForUserInputList change into tagNamesForUserInput

data-template="d-name" added data-element="template-d-name" removed

Version 1.23.24

dom99 components, see components/ folder for more information.

Removed event.dIn. Use D.followPath(d.variables, event.dKeys) or similar instead.

Added event.dHost for the event object for data-function. This is the host element with data-scope or document.body if there is none. It should be used instead of the old .xel hack.

Changed, the event object for data-function. It now exposes event.dKeys and event.dIn. event.dIn is a direct shortcut for d.variables and d.elements, that are at the same nested level as element with the function. D.xel does not exist anymore. Use data-element if you still need the custom elements reference.

It is now possible to use custom elements with the standard "is" attribute. Check examples/index.html and examples/main.js to see how to

data-function can now be used with just the function. If that happens the event is chosen with the dom99.options.eventFromTagAndType function, that you can customize.

You can now compose the html deeply. That means that you can now use custom elements inside custom elements. You can use data-scope in a template.

Version 1.17.0

Directive data-list to map an array as a list in the DOM, see examples. Removed it from data-variable because it was confusing and it didn't do the same thing at all. If you use use a list of objects you can customize exactly how the mapping is done. See second Lists example. The custom configuration has changed too.

Only two way data binding for input and textarea elements. Less useless eventlisteners on the page. If you want to use the contenteditable attribute(not a good idea) then add the elements tag Names to the dom99.options.elementsForUserInputList list with the push method.

Version 1.15.0

  • You can use data-variable="x-li" on a ol element for example to display the x array as multiple li elements see examples/test.html
  • Change the way to configure dom99
  • You can control what gets changed with data-variable

Version 1.12.0

function available: D.bool. When you assign a value to d.variables.x it is converted to a String. When you get a value from d.variables.x it is a string. Now with<input data-variable="x" type="checkbox"> you might want to get a boolean instead of "false" or "true". Use D.bool(d.variables.x)

input type="range" now uses the change event

Version 1.10.0

Less Confusion:

  • data-scope becomes data-scope
  • D.forgetScope becomes D.forgetKey
  • event.scope becomes event.dKey
  • dom99.directives.directiveScope becomes dom99.directives.directiveIn (if you used a custom syntax)


Abstract directions for the future or Specification

  • Freedom
  • Simplicity in system and usage
  • Encourage declarative UI programming models
  • Focus on the view
  • Built on top of web standards
  • Not bloat ware

This leaves more freedom to combine dom99 with the other needs. I encourage you to use simplified APIs for client-server communication alongside dom99 and anything else that is complementary to accelerate the development process.


The first version of dom99 was rapidly prototyped by Cyril Walle (GrosSacASac) in late 2015 for JavaScript teaching purposes to people with a designer background. It was easy to let them play with their first JavaScript functions and see result on the web page just by assigning the result in a JS variable. It took away all the headaches about DOM manipulation. It was written in ES2015 code and transpiled to ES5.

In march 2016 I decided to share dom99 after heavy code changes on GitHub and NPM in its own repository instead of some sub-folder in some other project.

Late 2017, new design decisions based on new experience acquired since then. The version is a major change. For older versions, have a look at 1.23.0 and 1.5.7 and 4.0.0.

Presentation mad in 2018