Bungee.js is a declarative framework to build web applications. It is heavily inspired by QML and comes with a
- declarative language for describing elements and their relationship between each other
- compiler to JavaScript
- declarative engine, which drives the whole application in an event driven fashion
Bungee.js is not a full blown application development framework, it provides mainly an environment to create the user interface elements. It breaks with the common html/css layouting of objects and relies on the description how elements should appear on the screen by defining constraints and dynamic bindings.
This section will get you started in a few minutes.
npm:
npm install bungee
The npm
package contains modules, the compiler and all the sources. Until there is a stable release,
this is the preferred way to generate the bungee.js
library together with a minified version:
make
To pre-compile the additional modules:
make modules
To remove all generated files:
make clean
Currently there are only tokenizer and compiler tests.
npm test
A very basic purple rectangle example looks like this:
Item {
width: 100
height: 50
backgroundColor: "purple"
}
Those code snippets can be either embedded into a website and compiled on the client side or pre-compiled to save some cpu cycles.
Embedding works like having Javascript embedded, only the type
attribute differs from that.
<script type="text/javascript" src="bungee.js"></script>
...
<script type="text/jump">
Item {
}
</script>
...
<body onload="Bungee.jump();">
The first script tag includes the bungee.js library, followed by a script of type text/jump
or text/jmp
and finally to kick off the compilation as well as the declarative engine, Bungee.jump()
needs to be called.
In this case in the onload
handler.
Although embedding the scripts add some more dynamic use cases, it also has major downsides.
The compilation step is really only needed in case the source changes. In addition to that,
since the compiler renders jump
into Javascript, the generated Javascript code then can be minified offline.
cd node_modules/bungee/bin
./bungee foo.jmp foo.jmp.js
If you want to have the compiled module namespaced, so all root elements are accessable via
moduleName.elementId
, pass the -m Foo
option. To use the module, include it as any other Javascript
file in your HTML alongside the main bungee.js
library.
<script type="text/javascript" src="bungee.js"></script>
<script type="text/javascript" src="foo.jmp.js"></script>
...
<script>
Bungee.useQueryFlags();
var ui = Bungee.Foo();
Bungee.Engine.start();
</script>
// One line comment
MyElement @ Element {
property: value-expression;
}
Element {
id: identifier;
onproperty: codeline;
function(argument): {
codeblock
}
}
The Jump syntax is similar to other languages like CSS or JSON. The code consists of an element or type definition followed by a block of key-value pairs and child element definitions.
Element {
id: myElement;
Element {
id: mySecondElement;
}
Element {
}
}
The key-value pairs have different meanings, depending on the key:
foobar
Keys, which match a CSS attribute name, will be handled as such. This means that the right hand side expression will be assigned to the instantiated element in the fasion ofobj.style["width"]
. Keys, not matching a CSS attribute, are also valid and can be used as custom properties.onfoobar
All keys starting withon
are event handlers for other attributes. As a right hand side expression, they take a Javascript code block, which will be executed everytime the property, the part after theon
, in this casefoobar
, changes. This is useful to react on property changes and perform actions, which are hard to express in a declarative way.foobar(baz)
Keys with a function like signature, will create callable functions on the elements. Unlike regular properties, those won't be reevaluated everytime a binding inside the function body fires. The function argument specification is only convenience and will be simply passed down to the compiled Javascript code by the compiler.
Element {
width: 100;
height: 200;
borderStyle: "dotted";
borderWidth: 10;
weAreDone(msg): {
console.log(msg);
}
onload: this.weAreDone("element created!");
}
Element {
width: 100;
height: this.width * 2;
Element {
id: elem
width: this.parent.height;
height: this.width;
}
Element {
left: this.parent.left + 20;
top: this.elem.top + this.elem.height;
width: 20;
height: 20;
}
}
MyGreenSquare @ Element {
width: 100;
height: this.width;
backgroundColor: "#00ff00";
}
MyGreenRectangle @ MyGreenSquare {
width: 100;
height: 200;
}
Element {
id: root
MyGreenRectangle {
height: 400;
}
}
MyDelegate @ Element {
width: this.parent.width;
height: 50;
backgroundColor: "blue";
}
Element {
width: 800;
height: 700;
foobar: MyDelegate;
onload: {
for (var i = 0; i < 10; ++i) {
var child = this.createfoobar();
child.modelData = i;
this.addChild(child);
child.initializeBindings();
}
}
}
There are several examples, on how to use bungee.js in a browser and node environment, located in the examples subfolder.