neft
Version:
JavaScript. Everywhere.
376 lines (277 loc) • 7.37 kB
Markdown
> [Wiki](Home) ▸ [[Tour]] ▸ **Styles**
Styles
===
Neft uses his own simply language to describe how the elements looks like, therefore styles in Neft can be well organized and more dynamic (JavaScript support, views data-binding etc.).
All style files must be placed in the `/styles` folder.
The main style is named `view.js`.
## NML syntax
```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 and to describe the top object.
## 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` array 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 = require('utils');
``
Item {
id: button
}
Rectangle {
id: squareButton
}
```
## Data binding
Style item properties can reference to the item object itself (`this`), other items (by their ids), defined JavaScript variables, call functions and more.
```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` - first top level item from the `view.js` file (in other words - window item).
```javascript
Rectangle {
width: view.width
color: app.cookies.clientColor // chm..
}
```
## 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.
The first one you already know - it's absolute positioning (`x` and `y`).
### Flow
Flow element position items from left to right.
`Item::layout` gives you a possibility to change how this item behaves in his layout parent.
```javascript
Flow {
width: 400
Rectangle {
width: 100
height: 100
margin.bottom: 20
}
Rectangle {
layout.fillWidth: true
}
}
```
### Grid
Grid positions its children in 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 item line into another item. 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 fills his parent.
```javascript
Item {
background: Rectangle {}
}
```
## 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 behavior, switch the `PropertyAnimation::updateData` property.
## 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 our 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
}
```
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 HTML elements found by the given query.
```javascript
for ('span.large'){
font.pixelSize: 30
}
```
`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'
}
}
```
### Inline styles
Attached style Item on the document element is available under the `style` property. You can use it to define styles in the HTML document.
```html
<span style:font:pixelSize="30">ABC</span>
```
Inline styles also supports signals. You can attach route method, or a `neft:function`.
```html
<span style:onTextChange="${route.spanTextChange}">ABC</span>
```
Next article: [[Networking - Tour]]