diff --git a/docs/legacy/0.3/api.md b/docs/legacy/0.3/api.md new file mode 100644 index 0000000..c069c98 --- /dev/null +++ b/docs/legacy/0.3/api.md @@ -0,0 +1,27 @@ +# API + +# Mustaches + +# Data Binding + +# Directives + +# Keypath Prefixes + +# Special References + +# Initialization Options + +# Static Properties + +# Static Methods + +# Instance Properties + +# Instance Methods + +# Context Object + +# Parse Object + +# Transition Object diff --git a/docs/legacy/0.3/concepts.md b/docs/legacy/0.3/concepts.md new file mode 100644 index 0000000..4a19d11 --- /dev/null +++ b/docs/legacy/0.3/concepts.md @@ -0,0 +1,11 @@ +# Architecture + +# Data Management + +# Event Management + +# Rendering + +# Security + +# Templates diff --git a/docs/legacy/0.3/get-started.md b/docs/legacy/0.3/get-started.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/legacy/0.3/plugins.md b/docs/legacy/0.3/plugins.md new file mode 100644 index 0000000..609e087 --- /dev/null +++ b/docs/legacy/0.3/plugins.md @@ -0,0 +1,15 @@ +# Adaptors + +# Components + +# Decorators + +# Easings + +# Events + +# Interpolators + +# Partials + +# Transitions diff --git a/docs/legacy/0.4/api.md b/docs/legacy/0.4/api.md new file mode 100644 index 0000000..c069c98 --- /dev/null +++ b/docs/legacy/0.4/api.md @@ -0,0 +1,27 @@ +# API + +# Mustaches + +# Data Binding + +# Directives + +# Keypath Prefixes + +# Special References + +# Initialization Options + +# Static Properties + +# Static Methods + +# Instance Properties + +# Instance Methods + +# Context Object + +# Parse Object + +# Transition Object diff --git a/docs/legacy/0.4/concepts.md b/docs/legacy/0.4/concepts.md new file mode 100644 index 0000000..4a19d11 --- /dev/null +++ b/docs/legacy/0.4/concepts.md @@ -0,0 +1,11 @@ +# Architecture + +# Data Management + +# Event Management + +# Rendering + +# Security + +# Templates diff --git a/docs/legacy/0.4/get-started.md b/docs/legacy/0.4/get-started.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/legacy/0.4/plugins.md b/docs/legacy/0.4/plugins.md new file mode 100644 index 0000000..609e087 --- /dev/null +++ b/docs/legacy/0.4/plugins.md @@ -0,0 +1,15 @@ +# Adaptors + +# Components + +# Decorators + +# Easings + +# Events + +# Interpolators + +# Partials + +# Transitions diff --git a/docs/legacy/0.5/api.md b/docs/legacy/0.5/api.md new file mode 100644 index 0000000..c069c98 --- /dev/null +++ b/docs/legacy/0.5/api.md @@ -0,0 +1,27 @@ +# API + +# Mustaches + +# Data Binding + +# Directives + +# Keypath Prefixes + +# Special References + +# Initialization Options + +# Static Properties + +# Static Methods + +# Instance Properties + +# Instance Methods + +# Context Object + +# Parse Object + +# Transition Object diff --git a/docs/legacy/0.5/concepts.md b/docs/legacy/0.5/concepts.md new file mode 100644 index 0000000..4a19d11 --- /dev/null +++ b/docs/legacy/0.5/concepts.md @@ -0,0 +1,11 @@ +# Architecture + +# Data Management + +# Event Management + +# Rendering + +# Security + +# Templates diff --git a/docs/legacy/0.5/get-started.md b/docs/legacy/0.5/get-started.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/legacy/0.5/plugins.md b/docs/legacy/0.5/plugins.md new file mode 100644 index 0000000..609e087 --- /dev/null +++ b/docs/legacy/0.5/plugins.md @@ -0,0 +1,15 @@ +# Adaptors + +# Components + +# Decorators + +# Easings + +# Events + +# Interpolators + +# Partials + +# Transitions diff --git a/docs/legacy/0.6/api.md b/docs/legacy/0.6/api.md new file mode 100644 index 0000000..c069c98 --- /dev/null +++ b/docs/legacy/0.6/api.md @@ -0,0 +1,27 @@ +# API + +# Mustaches + +# Data Binding + +# Directives + +# Keypath Prefixes + +# Special References + +# Initialization Options + +# Static Properties + +# Static Methods + +# Instance Properties + +# Instance Methods + +# Context Object + +# Parse Object + +# Transition Object diff --git a/docs/legacy/0.6/concepts.md b/docs/legacy/0.6/concepts.md new file mode 100644 index 0000000..4a19d11 --- /dev/null +++ b/docs/legacy/0.6/concepts.md @@ -0,0 +1,11 @@ +# Architecture + +# Data Management + +# Event Management + +# Rendering + +# Security + +# Templates diff --git a/docs/legacy/0.6/get-started.md b/docs/legacy/0.6/get-started.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/legacy/0.6/plugins.md b/docs/legacy/0.6/plugins.md new file mode 100644 index 0000000..609e087 --- /dev/null +++ b/docs/legacy/0.6/plugins.md @@ -0,0 +1,15 @@ +# Adaptors + +# Components + +# Decorators + +# Easings + +# Events + +# Interpolators + +# Partials + +# Transitions diff --git a/docs/legacy/0.7/api.md b/docs/legacy/0.7/api.md new file mode 100644 index 0000000..c069c98 --- /dev/null +++ b/docs/legacy/0.7/api.md @@ -0,0 +1,27 @@ +# API + +# Mustaches + +# Data Binding + +# Directives + +# Keypath Prefixes + +# Special References + +# Initialization Options + +# Static Properties + +# Static Methods + +# Instance Properties + +# Instance Methods + +# Context Object + +# Parse Object + +# Transition Object diff --git a/docs/legacy/0.7/concepts.md b/docs/legacy/0.7/concepts.md new file mode 100644 index 0000000..4a19d11 --- /dev/null +++ b/docs/legacy/0.7/concepts.md @@ -0,0 +1,11 @@ +# Architecture + +# Data Management + +# Event Management + +# Rendering + +# Security + +# Templates diff --git a/docs/legacy/0.7/get-started.md b/docs/legacy/0.7/get-started.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/legacy/0.7/plugins.md b/docs/legacy/0.7/plugins.md new file mode 100644 index 0000000..609e087 --- /dev/null +++ b/docs/legacy/0.7/plugins.md @@ -0,0 +1,15 @@ +# Adaptors + +# Components + +# Decorators + +# Easings + +# Events + +# Interpolators + +# Partials + +# Transitions diff --git a/docs/legacy/0.8/api.md b/docs/legacy/0.8/api.md new file mode 100644 index 0000000..3a78dca --- /dev/null +++ b/docs/legacy/0.8/api.md @@ -0,0 +1,42 @@ +# API + +# Mustaches + +# Data Binding + +# Directives + +# Keypath Prefixes + +# Special References + +# Initialization Options + +# Static Properties + +# Static Methods + +# Instance Properties + +# Instance Methods + +## ractive.getNodeInfo() + +This is an instance specific version of {{{createLink 'Ractive.getNodeInfo()'}}} that will only search the local instance DOM for a matching node when a selector is given. If the given value is not a string, then it is passed directly through to the static version of this method. + +> ### ractive.getNodeInfo( node ) +> Returns an object with helper methods to interact with the Ractive instance and context associated with the given node. See {{{createLink 'Ractive.getNodeInfo()' 'helpers' 'helpers'}}}. + +> > #### **node** *`DOMNode`* +> > The DOM node for which you wish to retrieve the Ractive instance or view details. This is passed through directly to the static method. + +> > #### **node** *`String`* +> > A css selector that will be passed to {{{createLink 'ractive.find()'}}}. The resulting node will then be passed to the static method.. + + + +# Context Object + +# Parse Object + +# Transition Object diff --git a/docs/legacy/0.8/concepts.md b/docs/legacy/0.8/concepts.md new file mode 100644 index 0000000..f8a9572 --- /dev/null +++ b/docs/legacy/0.8/concepts.md @@ -0,0 +1,1008 @@ +# Architecture + +## Expressions + +Expressions allow you to use logic within a template. At their simplest, that may just mean a basic arithmetic operation, such as converting to percentages, or making your {{{createLink 'mustaches' 'index references' 'index-references'}}} start at 1 rather than 0: + +```html +
+``` + +Or it could mean formatting a currency so that `1.79` renders as `£1.79p`: + +```html +Price: \{{ format( price ) }}
+``` + +Or it could mean adding a class based on some condition: + +```html +switch +``` + +Or it could mean filtering a list to exclude certain records: + +```html +\{{ formattedName() }}
+``` + +```js +var ractive = new Ractive({ + template: template, + el: output, + data: { + user: { firstName: 'John', lastName: 'Public' }, + formattedName: function() { + return this.get('user.lastName') + ', ' + this.get('user.firstName'); + } + } +}; +``` + +Result: +```html +Public, John
+``` + +In this example, the function ```formattedName``` will depend on both ```user.firstName``` and ```user.lastName```, and updating either (or ```user```) will cause any expressions referencing ```formattedName``` to be re-evaluated as well. + +```js +ractive.set('user.firstName', 'Jane') +``` + +Result: +```html +Public, Jane
+``` + +### Functions on helper objects and third-party libraries + +You can also add helper objects to your data and call functions on those objects in expressions. For example, you could add a reference to [underscore.js](http://underscorejs.org/): + +```js +var ractive = new Ractive({ + template: template, + el: output, + data: { + items: [ 2, 10, 200, 3, 1, 4], + _: _ + } +}; +``` + +And use that to sort an array in your template: + +```html +\{{# _.sortBy(items) }}\{{.}}, \{{/}} + + +1, 2, 3, 4, 10, 200, +``` + + +# Data Management + +## Dependants + +Ractive maintains a *dependency graph* in order to do the minimum amount of work necessary to keep the DOM up-to-date. + +If you inspect a Ractive instance in your console, you'll see a property called `_deps`. This is where all dependants are listed, indexed by their dependency. + +There is also a concept of 'priority', which exists to save us some work. If, for example, a section needs to be removed (perhaps it's a conditional section, and the condition just went from truthy to falsy), there is no point in updating all its children, so we make sure that we teardown the section first. As part of that teardown process, the children - which all have lower priority - unregister themselves as dependants before they get a chance to update. + +### Indirect dependencies + +If you have a mustache which depends on `foo.bar`, and `foo` changes, it's quite possible that the mustache needs to re-render. We say that the mustache has an *indirect dependency* on `foo`, or that it has a *direct dependency on a downstream keypath* of `foo`. + +This relationship is expressed through the `_depsMap` property of a Ractive instance - whenever `foo` changes, as well as dealing with direct `foo` dependants we check the map for those indirect dependants. + +In the case of {{{createLink 'expressions'}}} and {{{createLink 'observers'}}}, we also need to consider dependants of *upstream keypaths*. For example, suppose we have a section based on a sorted array - if we modify one of the members of the array, we need to see if the sort order has changed or not as a result: + +```html +\{{#( sort( list, 'name' ) )}} +\{{name}}
+\{{/()}} +``` + +```js +ractive = new Ractive({ + el: myContainer, + template: myTemplate, + data: { + list: [{ name: 'Bob' }, { name: 'Charles' }, { name: 'Alice' }], + sort: function ( list, property ) { + return list.slice().sort( function ( a, b ) { + return a[ property ] < b[ property ] ? -1 : 1; + }); + } + } +}); + +// renders Alice, Bob, Charles + +ractive.set( 'list[0].name', 'Zebediah' ); + +// updates to Alice, Charles, Zebediah +``` + +In the example, setting `list[0].name` causes dependants of `list` to be updated. + +As well as {{{createLink 'expressions'}}}, {{{createLink 'Observers'}}} respond to both upstream and downstream changes. + + +### Expressions with multiple dependencies + +The expression `\{{ a + b }}` has two dependencies - `a` and `b` (or more accurately, whatever those {{{createLink 'references'}}} resolve to). The `_deps` graph actually includes objects representing those individual references, rather than the expression itself - the reference objects then notify the expression (if their value has changed) that it will need to re-evaluate itself. + +Because the expression has multiple dependencies, it won't trigger an update straight away - it will wait until all the new data has come in first. So doing `ractive.set({ a: 1, b: 2 })` will only trigger one update, not two. + +## Array modification + + +Ractive can intercept the *mutator methods* (`pop`, `push`, `shift`, `unshift`, `splice`, `sort` and `reverse`) of arrays that it [depends on](dependants) for more convenient data binding. + +Consider the following: + +```html +foo is \{{foo}}
+ +``` + +In this case, because {{{createLink 'ractive.toggle()'}}} is a built-in method, clicking the button will toggle the value of `foo` between `true` and `false` ([demo](http://jsfiddle.net/rich_harris/xxg93vw8/)). + +This also works with custom methods: + +```js +var ractive = new Ractive({ + el: 'body', + template: '', + audio: new Audio( 'klaxon.mp3' ), + klaxon: function () { + this.audio.play(); + } +}); +``` + +You can pass as many arguments to the method as you like, including data references: + +```html +\{{#each items :i}} + +\{{/each}} +``` + +Notice that mustaches are __not__ used with data reference in method calls, i.e. `\{{i}}` and will cause errors if they are. String literals need to be in quotes: + +```html + +``` + +You can also pass the `event` object, or properties thereof (`event.original` is the original DOM event) ([demo](http://jsfiddle.net/rich_harris/9ecvjjtm/)): + +```html +current mouse position: \{{x}} x \{{y}}
+\{{greeting}}, \{{recipient}}!
', + data: { greeting: 'Hello', recipient: 'world' } +}); +``` + +While there are no _required_ options, the three shown above - __target__, __template__ and __data__ - are the most common. They specify __what data__ to bind to __what template__ and __where__ it should be placed in the __html document__. + +A good way to get up and running is with the [60 second setup](http://ractivejs.org/60-second-setup). After that, working your way through the [interactive tutorials](http://learn.ractivejs.org) will familiarise you with the various ways you can use Ractive. + +Checkout the {{{createLink 'Options' 'Configuration Options'}}} to learn more about +all the available options. + +If you get stuck at any point, visit the {{{createLink 'Get support'}}} page to find help. + + +# Get started with node.js + +Using Ractive.js with node is straightforward once [node.js is installed](http://nodejs.org/): +``` +$ npm install ractive +``` + +## Using Ractive within a node app + +Here's a simple "hello world" example that covers the basics of getting started + with ractive and node: +```sh +$ mkdir mynodeapp +$ cd mynodeapp +$ npm install ractive +$ touch test.js +$ open test.js +``` + +In `test.js`: +```js +var Ractive = require('ractive'); +var ractive = new Ractive({ + template: 'hello from \{{who}}' +}); +ractive.set('who', 'node'); +console.log(ractive.toHTML()); +``` + +Running the file using node: +```sh +$ node test.js +hello from node +``` + +## Limitations of using Ractive in node + +There is no two-way binding in node as there is no DOM. + +Data manipulation _can_ be done in node. Use methods like +{{{createLink 'ractive.set()'}}} to modify data, and {{{createLink 'ractive.toHTML()'}}} +to output the current template state as HTML. + +### Precompiling templates with node + +Use {{{createLink 'ractive.parse()'}}} to precompile templates in node. Here is an +example grunt task: + +```js +var Ractive = require('ractive'), + path = require('path'); + +module.exports = function(grunt){ + + var desc = 'Compile ractive.js templates'; + grunt.registerMultiTask('compile', desc, make); + + function make(){ + this.files.forEach(function(file){ + var templates = file.src.map(parse); + grunt.file.write(file.dest, + 'var templates = {\n' + templates.join(',\n') + '\n}'); + }); + } + + function parse(template){ + var name = path.basename(template, '.mustache'), + html = grunt.file.read(template), + parsed = Ractive.parse(html); + + return '\t' + name + ': ' + JSON.stringify(parsed); + } + +}; +``` + +If the above file was in folder `/tasks/`, it could be used like: + +```js +module.exports = function(grunt) { + + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + compile: { + ractive: { + src: 'templates/*.mustache', + dest: 'templates/templates.js' + } + } + }); + + grunt.loadTasks('./tasks'); + + grunt.registerTask('default', ['compile']); + +}; +``` + +## Debugging on node + +Check out [node-inspector](https://github.com/node-inspector/node-inspector) +for information on debugging node modules from the Chrome Web Inspector. +```sh +$ npm install -g node-inspector +$ node-debug test.js +``` + + + +# Advanced Configuration + +In addition to supplying static values for configurations options, some of the Ractive options +can be specified using a function that will resolve when the ractive instance is instantiated, +and re-evaluated upon {{{createLink 'ractive.reset()'}}}. + +An option function may be supplied to either {{{createLink 'Ractive.extend()'}}} or {{{createLink 'new Ractive()'}}}. + +Option functions receive the post-configured `data` option as the first argument and `this` in +the function refers to the ractive instance being instantiated. +Bear in mind that the ractive instance is in the process of being configured, so not all options +are necessarily configured yet, and functional methods like `observe` or `set` should not be called. + +## Template + +The template can be specified using the return value of an option function: + +```js +new Ractive({ + template: function ( data ) { + return data.foo ? 'hello world
' : '