neft
Version:
Universal Platform
394 lines (292 loc) • 7.75 kB
Markdown
# Views Integration
Neft uses his own language to describe how the elements looks like, therefore styles in Neft can be well organized and more dynamic, because the JavaScript support, views data-binding and more.
All style files must be placed in the `/styles` folder.
## NML syntax
NML *(Neft Marked Language)* is a simple but powerful language inspired by QML.
```javascript
TypeName {
id: optionalItemId
property: 'value' // comment
namespace.property: 'value'
onEvent: function(){
}
// children
TypeName {
}
}
```
`TypeName` is a class name provided by Neft: an Item, Column, Rectangle, FontLoader and more. `TypeName` can be also a reference to your custom style.
`id` is optional and it's used for data-binding.
## Main style
The main style must be returned as a first element from the `__view__.js` file.
It's a starting point of your application.
## Base item
All visible types in Neft extends the `Item` type.
It contains various properties (e.g. `x`, `y`, `scale`, `width`, `nextSibling`), `keys` and `pointer` support, `children` list and more. Check later the API Reference for the `Renderer` module.
```javascript
Item {
width: 100
height: 100
scale: Math.PI / 2
}
```
## Style file
Style file can contains custom JavaScript code and top level items (items with no parent).
```javascript
// styles/button.js
`
var utils = Neft.utils;
`
Item {
id: button
}
Rectangle {
id: squareButton
}
```
## Data binding
Item properties can reference to the item object itself (`this`), other items (by their ids), defined JavaScript variables and call functions.
```javascript
Item {
x: Math.random()
y: this.x
width: child.width * 2
Rectangle {
id: child
width: 100
}
}
```
`parent`, `previousSibling` and `nextSibling` don't have to be prefixed by `this`.
## Global access
In style files you have access to the `app` object and to the `view` main style globally.
```javascript
Rectangle {
width: view.width
color: app.cookies.clientColor
}
```
## Signals
Renderer emits signals in various places:
- on property value change (`onWidthChange(oldValue)`),
- on namespace property change (`onMarginChange(property, oldValue)`),
- on children change (`onChildrenChange(added, removed)`),
- on pointer click (`pointer.onClick(event)`),
- and more...
Items with defined ids are available in the signal listener.
```javascript
Item {
width: 100
height: 100
pointer.onClick: function(event){
this.x = event.x;
rect.color = 'green';
}
Rectangle {
id: rect
width: 100
height: 100
color: 'red'
}
}
```
## Conditions
```javascript
Rectangle {
x: 50
color: 'red'
if (this.x < 70 && Device.mobile){
color: 'green'
}
}
```
## Custom properties
```javascript
Item {
property $.health: 100
signal $.onAttack
signal $.onLowHealth
$.onAttack: function(target){
this.$.health -= target.$.attack;
if (this.$.health < 40){
this.$.onLowHealth.emit();
}
}
}
```
Custom properties and signals must be created in the `$` object.
Custom properties have their corresponding signals (e.g. `$.onHealthChange`).
## Type extending
Top level objects are available in the `exports` object under their ids.
```javascript
Item {
id: button
}
exports.button {
width: 100
}
```
This also works across files.
```javascript
// styles/button.js
Item {
id: sampleButton
}
// styles/complexButton.js
``
var button = require('./button.js');
``
button.sampleButton {
}
```
## Layout
To position children in an item, you can use few methods:
- absolute positioning (`x` and `y` properties),
- from left to right - `Flow` type,
- on a grid - `Grid`, `Column`, `Row` types,
- anchors.
### Flow
Flow element position items from left to right.
```javascript
Flow {
width: 400
Rectangle {
width: 100
height: 100
margin.bottom: 20
}
Rectangle {
layout.fillWidth: true
}
}
```
### Grid
Grid positions its children in a grid formation.
Other elements similar to `Grid` are `Column` and `Row`.
```javascript
Grid {
columns: 2
spacing: 20
Rectangle {
width: 100
height: 100
}
Rectangle {
width: 100
height: 100
}
}
```
### Anchor
`Item::anchor` describes relation between two items.
Each item has few lines: top, verticalCenter, bottom, left, horizontalCenter and bottom.
You can stick an item line into another item line. For the performance reasons, you can anchor only to siblings or to the item parent.
```javascript
Item {
Rectangle {
id: rect1
}
Rectangle {
anchors.left: rect1.right
margin.left: 20
}
}
```
## Background
`Item::background` gives a possibility to use any item as a background.
By default, *background` is a `Rectangle` filling his parent.
```javascript
Item {
background: Rectangle {
color: 'red'
}
// .. or just
background.color: 'red'
}
```
## Number animation
Neft supports animating number properties.
Use `NumberAnimation` to achieve this goal.
By default animator animates item, in which it was created.
```javascript
Item {
NumberAnimation {
property: 'x'
from: 0
to: 1000
loop: true
}
}
```
By default animators don't update the property during animation (it's much faster).
To change this behaviour, switch the `PropertyAnimation::updateProperty` boolean.
## Transitions
Transition type automatically animate all updates on the given property.
```javascript
Item {
width: 205
if (this.pointer.hover){
x: 100
}
Transition {
when: this.target.width > 200
property: 'x'
animation: NumberAnimation {
startDelay: 500
easing: 'OutSine'
}
}
}
```
## Views integration
You can draw styles just putting them into the `__view__.js` top level item, but, for the better organization, we need to integrate our HTML documents with created styles.
`Item::document::query` will use an item on all elements found by the given query. `document::query` can't be changed in runtime.
```javascript
Text {
document.query: 'span'
// this item will be used for all 'span' elements from views
}
```
Because the `document::query` can be also attached to the item children, you can create complex custom elements based on more than one HTML elements
```javascript
Item {
document.query: 'avatar'
Text {
document.query: '> nick'
}
}
```
### Runtime changes
For more dynamic behaviors you can use the `for (query) {}` syntax.
It works like `if () {}` but uses a query and modifies all found HTML elements in runtime.
```javascript
for ('header.large'){
width: parent.width * 0.8
}
```
`for` can be a top level definition or an `Item` children.
`for`s can be nested.
```javascript
for ('body[page=docs]'){
for ('header'){
background.color: 'green'
}
}
```
### Text styling
All HTML texts are rendered by default as Renderer `Text` items. You can modify how the texts looks like using the `#text` query. In Neft, text styles are not inherited like in CSS.
```javascript
for ('span.large #text') {
font.pixelSize: 30
}
```
### Inline styles
Attached style Item on the document element is available under the `style` property. You can use it to define inline styles in the HTML document.
```html
<span style:font:pixelSize="30">ABC</span>
```
Inline styles also supports signals.
```html
<span style:pointer:onClick="${this.onSpanClick}">ABC</span>
```
Next article: [[Networking - Tour]]