https://github.com/jooher/dap

Dap.js: for data-driven web applications

Lightweight and powerful javascript framework for interactive data-driven web applications.

Unlike some other frameworks relying on Javascript expressive means, dap offers a higher level of abstraction — a declarative "superscript" language for reactivity rules. These rules are dense, compact, and human-readable at the same time. Dap code is parsed, compiled and executed by a small (less than 9kiB gzipped) client-side script, and does not require any transpilation.

	'DIV.hello'.d("! greeting")
	.DICT({
		greeting:"Hello, world!"
	})
	

... where 'DIV.hello' designates an HTML element rendered as <DIV class="hello"> and .d() method specifies the generation rule for its content. The generation rule, literally "print greeting", consists of ! — the "print" operator — and a greeting constant, which is defined in the .DICT (dictionary) section.

Why not simply write <DIV class="hello">Hello, world!</DIV>, you may ask? Well, if you're writing not a static document, but an application (otherwise, you don't need dap), it is a common rule of thumb to avoid "hard-coded" strings or numbers in your programs. Instead, use constants and define them in a "dictionary". This way, your code will be cleaner and maintainance of your program easier. Not even to mention localization, when you need to translate all texts in your program to another language. And of course, dap rules can do much more than just printing constants!

Why dap?

Clear, concise and observable

Dap allows to focus on data and logic, instead of syntactic decoration. Dap code tends to be times smaller than equivalent solutions for other environments. It is clean and observable, without sparse lines of curly brackets and boilerplate code.

Natively reactive

Reactivity is the base concept of dap. No need to manually track state changes, or even bother binding update events — all dependencies are resolved naturally under the hood. Dap renders and updates all the dependent elements automatically, based on their dap-rules.

Fast and lightweight

Dap will not introduce any noticeable latency to your Web UI. The dap runtime script is tiny, dap-rules are parsed lazily, DOM manipulations are precise and deterministic, and only involve affected elements.

Simple to start, easy to advance

A whole lot of magic can be done with the few "core" dap operations. But when it's time to go beyond — you can easily expand dap with your own custom operations or use third party extensions.

Is it better than React?

Why go dap if there's React? Well, to my taste, React and similar frameworks are too verbose and cumbersome. Dap code is far, far cleaner. In dap code, you can clearly see the structure and logic of your program, often "one element = one line of code". Below are a couple of simple examples inspired by the canonical tutorials from React and Angular. You're welcome to compare the ideas and approaches behind dap and other frameworks.

Dap code example, explained

The example below shows a very basic pattern of selecting an option from a list.

'favorite-fruit'.d("$choice=" // a <DIV class="favorite-fruit"> element, with $choice status variable defined in its scope 
	,'B.selected'.d("! title ($choice not-yet)?") // a <B class="selected"> with textual content involving $choice value
	,'UL.options'.d("* fruit" // The * operator repeats the rule for each row in the fruit dataset
		,'LI'	.d("! .fruit") // each LI element shows fruit value from its associated data row, and
			.ui("$choice=.fruit") // on UI event (click by default) will update $choice with the fruit from its data
	)
	,'BUTTON'.d("? $choice; ! `Reset").ui("$choice=") // if $choice is set, show a reset button
	,'nothing'.d("? $choice:!; ! nothing") // if $choice is not set, print a message
)
.DICT({ // strings and other constants are defined here in dictionary, not inside the rules
	title:"My favorite fruit is ", // textual messages gathered in one place are easier to maintain and localize if needed
	nothing:"Nothing selected",
	"not-yet":"what?", // hyphens and other symbols are okay for entry names, as long as they are quoted
	fruit:["apple","orange","tomato","banana"] // datasets can be ordinary arrays containing any kind of data
})

Dap code may seem a little bit unusual, but it is a pure Javascript, with slightly uncommon formatting to better reflex dap program structure. All you need to run dap in an .html document is a <script src="https://dap.js.org/0.4.js"></script> somewhere before actual dap code (usually, in the head section).

From this example you can see DOM-element templates being denoted by single quoted strings (in a slightly shorter notation than used in HTML). Single quotes are just a matter of style, they help to tell templates from other strings and facilitate code highlighting.

Templates are rendered into actual DOM elements, from parent down to child elements, according to their d-rules ("down"-phase rules) specified by .d() method. Some templates have u-rules for "up"-phase, when events bubble up through the node towards the root. In the example above, the LI element is given its u-rule by means of .ui() method, which also binds a default UI event (usually, click) listener.

Rules in the example are very simple. You can see the three most common dap operators here:

And you can see arguments of several kinds in the rules above:

So far, so simple, isn't it?

But we need to go deeper

Now, let's go deeper with Understanding dap!