TypeScript HTML CSS JavaScript
Clone or download
Latest commit 0b2a662 Aug 8, 2018
Permalink
Failed to load latest commit information.
app Typo fixed Aug 8, 2018
assert Update readme.md Apr 9, 2018
atom $mol_atom: prevent self update on destroy, simplify $mol_atom_wait Dec 22, 2017
atom2 $mol_atom2: $mol_conform from context. Mar 17, 2018
attach $mol_attach_demo: fixed thumbs Jun 29, 2018
bar $mol app studio #173 (#250) Aug 28, 2017
bench $mol_bench: right sorting of rows Nov 5, 2017
bind $mol_bind_having: Test for unidirectional bind. Mar 8, 2018
book $mol_book: ignore placeholder for title selection. Oct 30, 2017
build $mol_build: webpack compat May 29, 2018
button $mol_button: right back compat. Nov 7, 2017
calendar $mol_date: uses $mol_calendar now for better crossplatforming. Oct 17, 2017
card namespace $.$mol is deprecated. Use namespace $.$$ instead. Sep 5, 2017
chart $mol_chart: no centering legend title Nov 7, 2017
chat Hide $mol_chat, because it has many issues. Dec 2, 2017
check Minor fixes. Sep 12, 2017
code Added `debounce` property for controls. Sep 8, 2017
colors Style fixes. Jan 27, 2017
compare Added $mol_compare_text: generic text comparator Nov 5, 2017
conform $mol_conform: compat with readonly fields in nodejs. Mar 1, 2018
const Some docs improvements. Feb 8, 2017
cordova TSX syntax compat. Sep 8, 2017
cost namespace $.$mol is deprecated. Use namespace $.$$ instead. Sep 5, 2017
csv Right naming: module -> namespace Oct 30, 2016
date $mol_date: inherit font family Jan 19, 2018
deck $mol_mem: use decorators instead decorators factory for better typing Sep 16, 2017
defer Grouped logging Nov 7, 2017
demo $mol_demo_small: no limit max height Oct 30, 2017
deprecated TSX syntax compat. Sep 8, 2017
dict More docs Jul 26, 2018
dimmer $mol_mem: use decorators instead decorators factory for better typing Sep 16, 2017
dom $mol_mem: support keys by ref through $mol_dict Jul 25, 2018
embed Using $mol_atom_force_cache instead of $mol_atom_force Oct 25, 2017
exec Right naming: module -> namespace Oct 30, 2016
expander Reduce GPU memory usage of large scroll panes. Sep 11, 2017
fiber $mol_fiber: micro optimization May 21, 2018
file $mol_file: fixed file adding watching Jun 25, 2018
filler $mol app studio #173 (#250) Aug 28, 2017
float $mol_float: hide only when scrolling axis same with float axis. Sep 27, 2017
form $mol_form: no center buttons Jun 29, 2018
func $mol_func_sandbox: Prevent access to AsyncFunction and GeneratorFunct… Jan 13, 2018
ghost $mol_ghost: use title from sub component. Oct 30, 2017
github $mol_github: enlarge limits. Nov 1, 2017
global Added support of third party libraries. ie $lib_ramda. Oct 29, 2016
graph Right naming: module -> namespace Oct 30, 2016
grid Contexts definition moved from $mol_view to $mol_object. Oct 21, 2017
hint Lamps improvements (#231) Jul 25, 2017
html Added $mol_app_questions - client for stackoverflow.com. Apr 5, 2017
http $mol_http: fallback with status code when satusText isn't provided Jun 25, 2018
hyperhive Using $mol_atom_force_cache instead of $mol_atom_force Oct 25, 2017
icon $mol_icon_edit added Jun 26, 2018
image Using var() instead of @apply in css. Better mol/select styles. Jun 1, 2017
import Using $mol_atom_force_cache instead of $mol_atom_force Oct 25, 2017
keyboard $mol_keyboard_code: constants inlining Dec 11, 2017
labeler $mol app studio #173 (#250) Aug 28, 2017
link $mol_link: faster navigation Jun 25, 2018
list Contexts definition moved from $mol_view to $mol_object. Oct 21, 2017
locale $mol_task bases $mol_dom_jsx. Bundle relative $mol_file base. Dec 6, 2017
log $mol_log_group: collapse only when filter is empty, optimization when… Nov 8, 2017
logo mol logos Jun 24, 2018
map/yandex Using $mol_atom_force_cache instead of $mol_atom_force Oct 25, 2017
match $mol app studio #173 (#250) Aug 28, 2017
math/round/expand Added $mol_math_round_expand - round to easy numbers greater then taked. Mar 2, 2017
maybe Right naming: module -> namespace Oct 30, 2016
mem More docs Jul 26, 2018
merge/dict TSX syntax compat. Sep 8, 2017
message $mol_message: no hardcode minimal_height. Oct 12, 2017
meter Grouped logging Nov 7, 2017
model $mol_model_prop: fixed default gen. Jan 16, 2018
nav Added $mol_app_calc - simple spreedsheet. Sep 25, 2017
number $mol_date: uses $mol_calendar now for better crossplatforming. Oct 17, 2017
object $mol_object: static context added Jun 30, 2018
object2 $mol_object2 added Apr 28, 2018
owning $mol_owning - ownership ability. Mar 2, 2018
page $mol_page: head not depends on title Jun 25, 2018
perf $mol_pref_uibench: refactoring Nov 1, 2017
plot Added mol/plot/all bundle. Jan 15, 2018
plugin $mol_plugin: fixed compatibility with strict mode. Sep 25, 2017
pop Fixed $mol_pop_bubble background. Oct 15, 2017
portion namespace $.$mol is deprecated. Use namespace $.$$ instead. Sep 5, 2017
range Added $mol_func_sandbox for restricted evaluation of user defined code. Sep 25, 2017
range2 $mol_range2: minor fixes Mar 10, 2018
row $mol_mem: use decorators instead decorators factory for better typing Sep 16, 2017
rpc Grouped logging Nov 7, 2017
scroll Grouped logging Nov 7, 2017
search $mol_mem: use decorators instead decorators factory for better typing Sep 16, 2017
section $mol app studio #173 (#250) Aug 28, 2017
select $mol_select: support Filter disabling Oct 9, 2017
server $mol_mem: use decorators instead decorators factory for better typing Sep 16, 2017
set Removed shims for Map and Set. Jun 27, 2017
skin Added $mol_app_calc - simple spreedsheet. Sep 25, 2017
speck More interoperable beta symbol. Oct 9, 2017
speech $mol_mem: use decorators instead decorators factory for better typing Sep 16, 2017
stack Cache stores in global WeakMaps instead of host objects. Multilevel B… Aug 30, 2017
state $mol_test: automatic mocking in tests. Apr 12, 2018
status namespace $.$mol is deprecated. Use namespace $.$$ instead. Sep 5, 2017
store $mol_store: snapshots support. Feb 7, 2018
string $mol_string: fixed recovery after error Dec 8, 2017
stub Added mol/time as port of jin/time. Jun 18, 2017
suggest $mol_suggest deprecated by $mol_search. Feb 2, 2017
svg $mol_svg: separate classes to modules. Nov 4, 2017
switch Header layout refactoring. Nov 5, 2017
syntax markdown support improvements May 22, 2018
test $mol_test: Fixed node failing. Apr 12, 2018
text markdown support improvements May 22, 2018
textarea $mol_textarea: fixed doc title Jun 26, 2018
tiler $mol_mem: use decorators instead decorators factory for better typing Sep 16, 2017
time Update readme.md Mar 17, 2018
touch $mol_touch: fixed wheel handling on ff. Nov 10, 2017
tree Update readme.md Jun 23, 2018
try temp hide error test Nov 21, 2016
typeof Added mol/typeof as port of jin/type. Jun 18, 2017
unit $mol_unit: fixed test Nov 4, 2017
view $mol_view_selection: right position receiving Jun 26, 2018
webdav Refactoring of object model. Sep 23, 2017
window Grouped logging Nov 7, 2017
.gitignore .DS_Store ignore Dec 28, 2016
.travis.yml $mol_app_report: build on push Jun 27, 2018
CNAME Added CNAME=mol.js.org Mar 13, 2017
LICENSE Initial commit May 10, 2016
index.html Right redirect to demo app. Sep 27, 2017
manifest.json Only black colors for pwa. Jul 19, 2017
mol.jam.js prefer module.exports May 29, 2018
mol.ts rollup compat Mar 20, 2018
readme.md $mol_dict - usefull native `Map` extension Jul 25, 2018

readme.md

$mol Build Status eigenmethod.github.io Maintanance status

Reactive micro-modular ui framework. Very simple, but very powerful!

Contents

Features

Demo applications

Benchmarks

Organizations using $mol

SAPRUN

Articles

Quick start

Video of this process

Create MAM project

Easy way is checkout this preconfigured MAM repository and start dev server:

git config --global core.autocrlf input
git clone https://github.com/eigenmethod/mam.git ./mam && cd mam
npm install && npm start

Setup your editor

  • Use MAM directory as root of your project in editor
  • Install plugins for *.tree files
  • If your editor ignores .editorconfig use this preferences: TABs for indents, LF for line endings.

Create your application component

In examples we will use namespace my and application name hello, but you could use your own namespace and application name.

Add web entry point at ./my/hello/index.html:

<!-- Disable quirks mode -->
<!doctype html>

<!-- Allow height:100% in body -->
<html style=" height: 100% ">

<!-- Force utf-8 encoding -->
<meta charset="utf-8" />
	
<!-- Disable mobile browser auto zoom, $mol is adaptive -->
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1" />
	
<!-- link to autogenerated css bundle -->
<link rel="stylesheet" href="-/web.css" />

<!-- link to autogenerated js bundle -->
<script src="-/web.js"></script>

<!-- link to optional autogenerated test js bundle -->
<script src="-/web.test.js"></script>

<!-- build, load and run tests when page loaded -->
<script>
	addEventListener( 'load' , function() {
		var script = document.createElement( 'script' )
		script.src = '-/web.test.js'
		document.body.appendChild( script )
	} )
</script>

<!-- autobind component to element on load -->
<body mol_view_root="$my_hello">

Your application will be served at http://localhost:8080/my/hello/. Open it. You should refresh page to view your changes.

Add declarative component description at ./my/hello/hello.view.tree with string input field and greeting message:

$my_hello $mol_view
	sub /
		<= Name $mol_string
			hint \Name
			value?val <=> name?val \
		<= message \

Same code with comments:

- Create `$my_hello` component by extending `$mol_view` base component
$my_hello $mol_view
	-
	- Overload base property `sub` by custom that returns two sub components: `Name` view and `message` string
	sub /
		-
		- Define property `Name` that returns `$mol_string` with overloaded two properties: `hint` and `name`
		<= Name $mol_string
			-
			- Define constant value for `hint` property
			hint \Name
			-
			- Overload `value` property of `$mol_string` by property `name` with empty string as default value.
			value?val <=> name?val \
		-
		- Outputs value of `message` property with empty string as default value.
		<= message \

That will be compiled to typescript code like this:

namespace $ { export class $my_hello extends $mol_view {

	/// name?val \
	@ $mol_mem
	name( next? : any ) {
		return ( next !== void 0 ) ? next : ""
	}

	/// Name $mol_string 
	/// 	hint \Name
	/// 	value?val <=> name?val
	@ $mol_mem
	Name() {
		return $mol_string.make({ 
			hint : () => "Name" ,
			value : ( next? ) => this.name( next ) ,
		})
	}

	/// message \
	message() {
		return ""
	}

	/// sub / 
	/// 	<= Name
	/// 	<= message
	sub() {
		return [].concat( this.Name() , this.message() )
	}

} }

Add your behaviour at ./my/hello/hello.view.ts by extending generated class:

namespace $.$$ {
	export class $my_hello extends $.$my_hello {
		
		message() {
			let name = this.name()
			return name && `Hello, ${name}!`
		}
		
	}
}

Add tests for your behaviour at ./my/hello/hello.test.ts

namespace $.$$ {

	$mol_test({

		'Generating greeting message'() {

			const app = new $my_hello
			app.name( 'Jin' )

			$mol_assert_equal( app.message() , 'Hello, Jin!' )
		}

	})

}

Add styles at ./my/hello/hello.view.css:

/* Styling BEM-block by autogenerated attribute */
[my_hello] {
	display: flex;
	flex-direction: column;
	align-items: center;
	font: 1.5rem/1 sans-serif;
	box-shadow: var(--mol_skin_light_outline);
	flex: 1 1 auto;
	align-self: stretch;
	margin: 0;
}

/* Styling BEM-element by autogenerated attribute */
[my_hello_name] {
	flex-grow: 0;
	margin: 1rem;
	width: 14rem;
}

That is all!

Tutorials

Rationale

Zero configuration

Instead of ensuring configurable under any wanting, we better concentrate on, that all would worked good directly from the box and does not bother $mol's developer by a typical configure. (But, nevertheless it does not excludes setup for your needs if it is required)

For example if you download base MAM-project you'd have got that:

Building of JS and CSS bundles for different platforms. A bundle can be built for any module. In this bundle would be sources of that module and sources all other modules from which the module depends on. Also there would not redundant modules in the bundle.

There are the full set of supports bundles:

  • -/web.js - JS for browser
  • -/web.d.ts - TypeScript definitions
  • -/web.test.js - JS with tests for a browser
  • -/web.css - CSS styles for a browser
  • -/web.deps.json - map of dependencies modules for browser
  • -/web.locale=en.json - strings pulled from *.view.tree and *.locale=en.json sources
  • -/node.js - JS for NodeJS
  • -/node.test.js - JS with tests for NodeJS
  • -/node.deps.json - a map of dependencies modules for NodeJS

Support of Source Maps. Sources are compiled and integrate to maps, they are fully self-sufficient.

Development server, witch would be compile bundles as needed. For example, when requested http://localhost:8080/mol/app/todomvc/-/web.js the js bundle is being built of mol/app/todomvc for web environment. Rebuilding would be occur only if some source file would be changed.

Transpilling of modern CSS into CSS supported by browsers (postcss-cssnext): vendor prefixes and variables etc.

Transpilling TypeScript into JS. In TS configuration enabled support decorators and disabled implicit any type, for prevent missing typing by change.

Watching dependencies by fact of using and inclusion the needed modules automatically at further bundle. You don't need to write include and require everything you need is to refer for essence by full name like $mol_state_arg and $mol.state.arg (looking at its definition) in *.ts, *.view.ts, *.view.tree and *.jam.js files. At CSS files its dependencies are looked for by entries like [mol_check_checked] , [mol_check_checked= and .mol_check_checked.

Lego components

At $mol is used the component approach to the building of interface, however every component is self-sufficient and can be used as the self-sufficient application. Small components are aggregated inside of larger components etc.

Unlike another frameworks the $mol does not seek to isolate the insides of the components. Vice versa, there is comfortable mechanism is provided for developers for configuration them, it is not required from the creator of the component to do any additional gestures.

For example, to set the list of sub components you need to redefine sub property in view.tree

Confirm_delte $mol_row sub /
	<= Yes $mol_button_minor title \Yes
	<= No $mol_button_danger title \No

Or the same code through TypeScript would be:

@ $mol_mem
Confirm_delete() {
	return $mol_row.make({
		sub : ()=> [ this.Yes() , this.No() ] ,
	})
}

In both variants the compiler would verify existence of the property and accordance of the signature. In normal mode you don't need to work with fields of the object directly, so all definable properties are public and can be safely overloaded.

Details about viewers and view.tree language: $mol_view.

Lazyness

$mol_view implements lazy rendering. $mol_scroll is watching scroll's position and suggest to the embedded components about the view height. $mol_list knowing about the view height and minimal sizes of the embedded components, it excludes from rendering process the components that is not got into viewport for sure. And all other components can suggest it about their minimal size through minimal_height property.

$my_icon $mol_view
	minimal_height 16

At the result it come out than opening any window occur while instant time. It's independent of output data size. And since data would not be rendered, then any requests would not be proceeded. It's allowed us to download them partly, when they are needed. That features are possible due to reactive architecture, that are penetrated all layers of application.

Reactivity

Unlike the control-flow architectures, in $mol was implemented the data-flow architecture. All applications are described as a set of classes, having properties. Every property is described as some function from another property (and properties of another classes too). Properties, to which were appealed while function processing were saved as dependencies of our property. In case of changing their values, all dependant on them properties would be invalidated cascaded. And appealing to non relevant property would lead to its pre-actualization.

In this way the whole application at the execution stage represents a huge tree of dependencies, at the root of the tree is located the special property, which in case of invalidation would actualize itself automatically. And as any property always knows, whether something depends from it or not, then it is given a simple and reliable mechanism of controlling lifecycle of objects - they creates if the dependence appears and are destroyed when nothing depend from it. It's solved two fundamental problem: resources leaks and cache invalidation.

Besides, the reactive architecture allows us to abstract code elegantly from asynchronous operations. If the function can't return value at once, it can throws the exception $mol_atom_wait, it is marked part of the tree of states as "waiting of results". When the result would be retrieved - it could be inserted into property directly and application would be reconstructed for the new state.

namespace $ {
	export class $my_greeter {
		
		// Define memoized property with push support
		@ $mol_mem
		greeting( next? : string , force? : $mol_atom_force ) : string {
			
			// Defered push value to property
			setTimeout( () => {
				this.greeting( 'Hello!' , $mol_atom_force_cache )
			} , 1000 )
			
			// throw special error to notify about waiting
			throw new $mol_atom_wait( 'Wait!' )
		}
		
		// Define memoized property without push support
		@ $mol_mem
		greeting_length() {
			// Using other properties in synchronous style
			return this.greeting().length
		}
		
	}
}

Details: $mol_mem, $mol_atom.

Debugging

A special attention is payed while developing $mol to debugging possibilities and researching of code's working process. For example for handling exceptions we don't using (try-catch-throw), because it masks the true place where exceptions were thrown, it complicates debugging.

For every DOM-element is formed a people friendly id automatically like $mol_app_todomvc.root(0).taskRow(0).titler(), which is valid javascript code, this one could be executed at a console, received a link to the component, whom the component is corresponds to. Unfolding the content of the component you'd see names and values its fields like:

$mol_app_todomvc
    dom_node() : div#$mol_app_todomvc.root(0)
    task(1474385802391) : Object
    task(1474386443175) : Object
    taskRow(0) : $mol_app_todomvc_task_rowRow
    taskRow(1) : $mol_app_todomvc_task_rowRow
    taskrows() : Array[2]

The name of the field corresponds to calling the property, the content of the field would be available through. And thanks to naming classes and functions through underscoring you'd always get to know which class instance in front of you and could briefly find it at code by default searching by the substring.

Modules

Flow

Object model

Functions

Collections

State modules

Communication modules

Simple components

Simple controls

Layout components

Plugin components

Complex components

Widgets

  • $mol_chat - GitHub based comments everywere

Charts

Data formats

Math

Resources

Testing

API

Time

Maps

Web Services

Building

Cool stuff

Donate