-
Notifications
You must be signed in to change notification settings - Fork 19
/
guide.html
162 lines (136 loc) · 48.5 KB
/
guide.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<head><title>Tower.js - Small components for building hardcore apps.</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Lato:300,400"><link rel="stylesheet" href="public/css/bootstrap.min.css"><link rel="stylesheet" href="public/css/bootstrap-responsive.min.css"><link rel="stylesheet" href="public/css/index.css"><script type="text/javascript" src="public/js/build.js"></script><script>var jQuery = $ = require("component-jquery");
var mainApp = require('tower-website/public/js/index');
mainApp();</script></head><body data-scope="body"><div id="wrapper"><header class="container-fluid"><div class="row-fluid"><ul class="span12"><li class="logo"><a href="./"><img src="public/img/logo.png" alt="Tower"></a></li><li class="pull-right"><ul><li><a href="guide" title="Guide">Guide</a></li><!--<li>
<a href="api" title="API Docs">API</a>
</li>--><li><a href="https://github.com/tower/tower" title="GitHub Repos">GitHub</a></li></ul></li></ul></div></header><section id="body" data-content="" class="container-fluid"><div><div class="row-fluid"><div class="guides content span9"><!-- data-list:guide in guides --><div><div data-id="guide.name" data-markdown="guide.content" id="resource"><h1>Resources</h1><p>A resource is a piece of data. It makes the semantic interoperability and standardization of data and web services possible.</p><p>It's like a model in traditional web MVC's, but it is more general than that. Resources can be:</p><ul><li>database records</li><li>remote API JSON responses,</li><li>files on the file system</li><li>config JSON</li><li>UI data such as x/y position</li><li>etc.</li></ul><p>You may wonder why a resource is this abstract, why not just be like an MVC model?</p><p>The reason is the way we've used models in the past (ActiveRecord in Rails for example) is just a piece of the system. It is only part of the solution. If you look into the code for great libraries such as <a href="https://github.com/fog/fog">fog</a> and <a href="https://github.com/opscode/chef">chef</a>, you realize that they are using models as well, but in a totally different way. They ended up reimplementing a version of ActiveRecord in new context (remote API resources for Fog, and install packages and other operating system config/data for Chef).</p><p>This has powerful implications. If you unify all of those different use cases, you gain the ability to query anything, anywhere, using a standard API across all the different areas.</p><p>What this means is astounding. You have one simple abstraction over <em>all</em> data.</p><p>You can transfer your knowledge of data models to completely new areas. And you can query any of this data using a robust and extensible query language in JavaScript.</p><pre><code class="lang-js">resource(<span class="string">'post'</span>)
.where(<span class="string">'likeCount'</span>).gte(<span class="number">10</span>)
.page(<span class="number">2</span>)
.all();</code></pre></div></div><div><div data-id="guide.name" data-markdown="guide.content" id="adapter"><h1>Adapters</h1><p>Adapters are an abstraction over remote services and databases. This includes pretty much everything you can think of (and if there's a case this doesn't handle, definitely point it out):</p><ul><li>Databases like MySQL, MongoDB, Cassandra, Redis, etc.</li><li>Remote services like Facebook, Twitter, and other things with API's (REST or not)</li><li>Things without APIs that you can make have an API, such as web crawling</li><li>Operating system resources like files, processes, installed packages, etc.</li></ul><p>They make it possible to have a standard interface to any data, anywhere.</p><p>You achieve one standard query API by having adapters.</p><p>To implement an adapter, simply implement the<code>exec</code>method. If you do this you can perform all the standard query actions (create/read/update/delete), and the resources your adapter abstracts become usable just like any other resource (like a <strong>m</strong>odel in traditional MVC frameworks like Rails).</p><p>Here's how the<code>exec</code>method looks for some custom adapter:</p><pre><code class="lang-js"><span class="keyword">var</span> adapter = require(<span class="string">'tower-adapter'</span>);
adapter(<span class="string">'custom'</span>).exec = <span class="keyword">function</span>(query, fn){
};</code></pre><p>All it takes is a <a href="/guides/queries">query</a> object, and a callback function (for handling async).</p><p>It is up to your specific adapter to determine how to handle the query object. To be brief (more in the <a href="/guides/queries">query section</a>), the query object has the same basic stuff you'd find in any other database query system like SQL, MongoDB, etc.:</p><ul><li><code>query.selects</code>: an array of all the tables/collections/keystores (i.e. resources) used in the query</li><li><code>query.constraints</code>: an array of<code><left> <operator> <right></code>statements like<code>likeCount >= 10</code>(as objects, so they're easy to manipulate)</li><li><code>query.paging</code>: the<code>limit</code>and<code>offset</code>values specified, if any</li><li><code>query.sorting</code>: an array of the different sorting properties/directions</li></ul><p>All of that is described in depth in the <a href="/guide#query">query section</a>. For now just know that to implement a custom adapter, you simply implement the<code>exec</code>function, which means taking those 5 query properties and converting them into the format specific to some database or service.</p><h2>Adapters and Streams</h2><p>All adapter actions are implemented as nodejs-compliant streams. Actions are executed from a<code>query</code>. So when you create/read/update/delete records, you can pipe the result to the input of another query (or query constraint), or build a complex join-like query out of multiple sub-queries. Essentially, data becomes part of the node.js stream ecosystem. It also works like this in the browser.</p><h2>Adapters are <strong>tiny</strong></h2><p>Once you start wanting to integrate data from dozens or even hundreds and thousands of data sources, size matters. Adapters are boiled down to the bare essentials to make it so you could load dozens of adapters onto the client if desired, and not have to really worry about how that'll impact performance.</p><h2>Implementing a REST adapter</h2><p>Here's how the<code>exec</code>method looks for a custom REST adapter (which saves client-side records through AJAX to your server, and allows basic searching):</p><pre><code class="lang-js"><span class="comment">/**
* Map of query actions to HTTP methods.
*/</span>
<span class="keyword">var</span> methods = {
find: <span class="string">'GET'</span>,
create: <span class="string">'POST'</span>,
update: <span class="string">'PUT'</span>,
remove: <span class="string">'DELETE'</span>
};
adapter(<span class="string">'rest'</span>).exec = <span class="keyword">function</span>(query, fn){
<span class="keyword">var</span> name = query.selects[<span class="number">0</span>].resource;
<span class="keyword">var</span> method = methods[query.type];
<span class="keyword">var</span> params = serializeParams(query);
$.ajax({
url: <span class="string">'/api/'</span> + name,
dataType: <span class="string">'json'</span>,
type: method,
data: params,
success: <span class="keyword">function</span>(data){
fn(<span class="literal">null</span>, data);
},
error: <span class="keyword">function</span>(data){
fn(data);
}
});
};
<span class="comment">/**
* Convert query constraints into query parameters.
*/</span>
<span class="function"><span class="keyword">function</span> <span class="title">serializeParams</span><span class="params">(query)</span> {</span>
<span class="keyword">var</span> constraints = query.constraints;
<span class="keyword">var</span> params = {};
constraints.forEach(<span class="keyword">function</span>(constraint){
<span class="comment">// params['likeCount'] = 10;</span>
params[constraint.left.attr] = constraint.right.value;
});
<span class="keyword">return</span> params;
}</code></pre><p>This is all it takes to hook up your resources to a backend with full search/sorting/pagination.</p><p>You can implement remote service and database adapters just as easily.</p><h2>Implementing a database adapter</h2><p>This is just like implementing the REST adapter. All you do is implement the<code>exec</code>function, and convert the<code>query</code>object into the database-specific format.</p><p>Here is a high-level example of how to create a MySQL adapter:</p><pre><code class="lang-js"><span class="keyword">var</span> adapter = require(<span class="string">'tower-adapter'</span>);
<span class="keyword">var</span> mysql = require(<span class="string">'mysql'</span>);
adapter(<span class="string">'mysql'</span>).exec = <span class="keyword">function</span>(query, fn){
<span class="keyword">var</span> table = query.selects[<span class="number">0</span>].resource;
<span class="keyword">var</span> constraint = query.constraints[<span class="number">0</span>];
<span class="keyword">var</span> condition = [constraint.left.attr, constraint.operator, constraint.right.value].join(<span class="string">' '</span>);
<span class="keyword">var</span> statement = [
<span class="string">'SELECT * FROM '</span> + table <span class="comment">// SELECT * FROM posts</span>
<span class="string">'WHERE '</span> + constraint <span class="comment">// WHERE likeCount >= 10</span>
];
mysql.execute(statement, fn);
};</code></pre><p>Tower has a simple <a href="https://github.com/tower/mysql-adapter">MySQL adapter</a> that shows how to convert a query object into a SQL statement (thanks to the <a href="https://github.com/hiddentao/squel">squel</a> repo). Have fun saving and querying any data in MySQL.</p><p>To REALLY make a database adapter robust, dig into the database's documentation and implement all it's features. Please finish and open-source an adapter! You will solve the problem for <em>everyone</em>, and you will never have to deal with it again*.</p><h2>Implementing a remote service adapter</h2><p>No guides on this yet. You can make a remote service queryable just like a database. For now, see the most complete example <a href="https://github.com/tower/ec2-adapter">EC2 adapter</a>.</p></div></div><div><div data-id="guide.name" data-markdown="guide.content" id="query"><h1>Queries</h1><p>Queries are one of the most powerful things in tower. They are the interface between resources and adapters, making it possible to find/create/update/remove records across adapters using a standard syntax.</p><p>Tower's query API is very similar to most SQL-like query languages. As it turns out, even NoSQL databases like Cassandra and Neo4j have SQL-like query languages. The reason is, when you start talking about resources with attributes, and relationships between resources, it all boils down to <a href="http://en.wikipedia.org/wiki/Set_theory">set theory</a>, or more specifically <a href="http://en.wikipedia.org/wiki/Graph_theory">graph theory</a> and <a href="http://en.wikipedia.org/wiki/Relational_algebra">relational algebra</a>. I'm not sure the formal relationship between these different areas of mathematics, but they all are required areas of study when building a query language.</p><p>In the most general sense, a query is a set of constraints applied to a graph, where the graph is all of the resources and attributes, and the constraints are <a href="http://en.wikipedia.org/wiki/Linear_inequality">linear inequalities</a> such as<code>posts.likeCount >= 10</code>. The query analyzer then figures out the most optimal way to traverse the graph of resources and attributes (across adapters) and builds a <a href="http://en.wikipedia.org/wiki/Query_plan">query plan</a>: the most optimal way to traverse the graph given those constraints.</p><p>This is what Tower's query engine does. You build a query, which get's compiled to a "topology" (the most optimal map/way to traverse your graph of resources across adapters), and then performs the queries on the adapters. You get back the final result. You don't need to worry at all about the database-specific implementations.</p><h2>Query API</h2><p>This is the basic api for the query object:</p><pre><code class="lang-js"><span class="keyword">var</span> query = require(<span class="string">'tower-query'</span>);
query()
.select(<span class="string">'post'</span>)
.where(<span class="string">'likeCount'</span>).gte(<span class="number">10</span>)
.limit(<span class="number">20</span>)
.desc(<span class="string">'createdAt'</span>)
.page(<span class="number">2</span>)
.all();</code></pre><p>It is very similar to a SQL query.</p><p>There are 4 main properties on the query object:</p><ul><li><code>query.selects</code>: an array of all the tables/collections/keystores (i.e. resources) used in the query</li><li><code>query.constraints</code>: an array of<code><left> <operator> <right></code>statements like<code>likeCount >= 10</code>(as objects, so they're easy to manipulate)</li><li><code>query.paging</code>: the<code>limit</code>and<code>offset</code>values specified, if any</li><li><code>query.sorting</code>: an array of the different sorting properties/directions</li></ul><p>These properties store the parameters passed in through the query DSL.</p><p>Queries are tied to both resources and adapters.</p><h2>Queries and Adapters</h2><p>The query module defines exports a<code>use</code>method, to which adapters are passed. By telling the query to "use adapters", you tell the query system what data it has access to.</p><p>When you define an adapter,<code>use</code>gets called automatically for you. You can also tell a specific query instance which adapters to use in the same way (so you can say, "this query only has access to this specific adapter" for example).</p><p>You can access the query object from the adapter as well. We're moving to a point where you should be able to do this on all adapters:</p><pre><code class="lang-js"><span class="keyword">var</span> facebook = require(<span class="string">'facebook-adapter'</span>);
facebook(<span class="string">'user'</span>).where(...).all();</code></pre><p>Basically, that just delegates to the following (which <em>is</em> possible now):</p><pre><code class="lang-js"><span class="keyword">var</span> facebook = require(<span class="string">'facebook-adapter'</span>);
facebook.query().select(<span class="string">'user'</span>).where(...).all();</code></pre><p>By having that simpler version, if you build a REST API for your startup or whatever, you will be able to have a simple/clean API for free, with a completely robust query API. You'd simply say "include our script tag on your site", and now customers are using your super lean, lightweight, robust JavaScript API.</p><h2>Queries and Resources</h2><p>You can also access the query object from <a href="/guides#resources">resources</a>:</p><pre><code class="lang-js"><span class="keyword">var</span> resource = require(<span class="string">'tower-resource'</span>);
resource(<span class="string">'user'</span>).where(...).all();</code></pre><p>This just adds a<code>.select(resourceName)</code>to the query object, basically just this:</p><pre><code class="lang-js"><span class="keyword">var</span> query = require(<span class="string">'tower-query'</span>);
query().select(<span class="string">'user'</span>);</code></pre><h2>Queries and Relations</h2><p>All of the theory has been fleshed out on how to robustly implement a generic query executor that works across all different types of databases (mysql, mongodb, cassandra, neo4j, etc.) and remote services (facebook, twitter, etc.). <em>And between adapters</em>, such as "fetch all facebook posts for users in our database who have signed up in the past 2 weeks" or whatever. Cross-adapter queries means you will be able to query anything, anywhere. This means that data objects everywhere can be queried and combined in new ways.</p><p>However, we're not quite finished this yet. Decided to release this early.</p><h3>The math</h3><p>Basically, we have a graph<code>G</code>with vertices<code>V</code>and edges<code>E</code>:</p><pre><code>G(V,E)</code></pre><p>The vertices are the adapters<code>A</code>, resources<code>R</code>, and resource attributes ("fields",<code>F</code>). So, they are <em>subsets of<code>V</code></em>.</p><pre><code>A,R,F ⊂ V</code></pre><p>where</p><pre><code>{ adapter('mongodb'), adapter('cassandra'), ... } ∈ A</code></pre><p>Also,<code>R</code>is a collection of subsets of<code>A</code>(don't know how to quite represent this yet).</p><p>Then<code>F</code>is the same, a collection of subsets grouped by<code>R</code>.</p><p>So then it comes down to, a <em>query</em> is just a set of edge constraints on<code>V</code>.</p><p>Simple constraints are when a property is set to a primitive value such as a string/number/etc. I'm not sure those need to be treated as nodes so I'm ignoring them for now (that is, the database natively will handle all that stuff).</p><p>Complex constraints are basically <em>joins</em>, where the value is pointing to a resource field,<code>F</code>. That is, it is an edge between 2 or more resource fields,<code>Fi</code>to<code>Fn</code>.</p><p>This really simplifies everything. So basically, a bunch of joins just mean there's a bunch of edges between members of<code>F</code>, call them<code>J</code>.</p><pre><code>J ⊂ E</code></pre><p>That means (at least for reasonably complex queries), you just have to solve the <em><a href="http://en.wikipedia.org/wiki/Max-flow_min-cut_theorem">minimum cut maximum network flow</a> problem</em> for the network<code>J</code>.</p><p>Somehow you can group<code>J</code>in an order based on the fact that they are connected to<code>F</code>, which are a subset of<code>R</code>which is a subset of<code>A</code>.</p><p>If you think of it in terms of 3 adapters,<code>facebook, twitter, mongodb</code>, and they all have their own<code>user</code>resource, and all have a<code>firstName</code>attribute, and maybe a couple more attributes each, and several of their attributes are joined together, how do you find the best way to do the query?</p><p>One issue is, there can't be any <em>directed cycles</em>. Realizing this simplified everything, because in my head I kept thinking of that case and not seeing a solution, but from what I've read they say <em>it must be a DAG</em> (directed acyclic graph), no cycles! We can come back to handling the cyclic case later (maybe the algorithm can just randomly say one goes before the other).</p><p>So to figure out the best way to do the query, you have to figure out the network flow problem on<code>J ⊂ E</code>. That's pretty much it.</p><h2>Summary</h2><p>Those are some notes on how to approach solving the problem. It's totally possible, should be able to complete soon. Would love any input.</p><p>So, the query system currently supports being infinitely extensible on individual adapters (which should be useful for you now), and in the works is making queries work cross-adapter, with relations.</p></div></div><div><div data-id="guide.name" data-markdown="guide.content" id="template"><h1>Templates</h1><p>Tower's template component is built in response to the 100's of other template engines that fall short in one or more key areas:</p><ul><li>performance</li><li>extensibility</li><li>overall file size of the implementation</li><li>simplicity</li><li>client/server compatability</li></ul><p>All an HTML template engine needs to do is map data to the DOM.</p><p>At the lowest level, this is how it's used:</p><pre><code class="lang-js"><span class="keyword">var</span> template = require(<span class="string">'tower-template'</span>);
<span class="keyword">var</span> el = document.querySelector(<span class="string">'#todos'</span>);
<span class="keyword">var</span> fn = template(el);
fn({ some: <span class="string">'data'</span> });</code></pre><p>A template function<code>fn</code>is built by passing a DOM node to<code>template</code>.</p><pre><code class="lang-js"><span class="keyword">var</span> fn = template(el);</code></pre><p>With that function you can do two things:</p><ol><li>You can apply new content to it, which will update the<code>el</code>you passed in to build the template.</li><li>Or you can call<code>fn.clone(content)</code>, which will clone the original<code>el</code>, and apply the new content to it. This is useful for creating new list items, for example.</li></ol><h3>Template Compiler Deep Dive</h3><p>The template compilation process is super simple. This is the process at a high level:</p><pre><code class="lang-js">templateFn(scope);
nodeFn(scope, node); <span class="comment">// node is the cached item from building the template, so `document.body`</span>
scope = directivesFn(scope, node); <span class="comment">// process directives for this node, returns new/old scope</span>
scope = scopeFn(scope); <span class="comment">// find the correct scope for this node, from its directives</span>
eachFn(scope, node.childNodes);
nodeFn(scope, childNode); <span class="comment">// recurse, where `scope` might be a new one from above</span></code></pre><p>So, for each node, it first processes the directives (<code>directive.exec</code>), and each<code>directive.exec</code>returns either the current scope or a new scope. The end result of processing directives is a<code>scope</code>(new or original), that then will be used to process child nodes. So then it iterates through the child nodes, and repeats the whole process.</p><p>This way, when you execute the template function with a scope:</p><pre><code class="lang-js"><span class="keyword">var</span> template = require(<span class="string">'tower-template'</span>);
<span class="keyword">var</span> fn = template(el);
fn(scope);</code></pre><p>it basically just iterates through a bunch of functions, passing scopes to directives which then apply the scope data to the DOM.</p><h2>Examples</h2><h3>Nav</h3><pre><code class="lang-html"><span class="tag"><<span class="title">ul</span> <span class="attribute">class</span>=<span class="value">"nav nav-tabs"</span>></span>
<span class="tag"><<span class="title">li</span> <span class="attribute">data-list</span>=<span class="value">"item in nav"</span> <span class="attribute">data-class</span>=<span class="value">"active"</span>></span>
<span class="tag"><<span class="title">a</span> <span class="attribute">href</span>=<span class="value">"#"</span>></span><span class="tag"></<span class="title">a</span>></span>
<span class="tag"></<span class="title">li</span>></span>
<span class="tag"></<span class="title">ul</span>></span></code></pre></div></div><div><div data-id="guide.name" data-markdown="guide.content" id="content"><h1>Content</h1><p>Data for the DOM.</p><p>When you describe the UI, you talk about the design and the content. Content is the data shown to the user.</p><p>Most frameworks allow you to bind arbitrary data to the DOM. Angular allows you to bind any plain-old JavaScript object. Ember requires you to use their own observable objects. Knockout makes you wrap your object to be "observable". In the end, they all do this sort of thing because all browsers do not yet support listening for property changes in a reliable way.</p><p>But if you really think about it, you do not need to bind plain-old JavaScript objects to the DOM. Nor do <em>all</em> the objects in the framework need to be observable. What you need is a clear way to show the user <em>content</em>, arbitrary data that is specifically meant for the DOM.</p><p>You need an API to take arbitrary data (whether it's your model, some random config properties, hardcoded menu items, the result from a remote API call, whatever), and say "expose this to the DOM". Here's how you do that:</p><pre><code class="lang-js"><span class="keyword">var</span> content = require(<span class="string">'tower-content'</span>);
content(<span class="string">'main'</span>)
.attr(<span class="string">'random'</span>, <span class="string">'string'</span>, <span class="string">'config!'</span>)
.attr(<span class="string">'items'</span>, <span class="string">'array'</span>, [ <span class="string">'Home'</span>, <span class="string">'About'</span> ]);</code></pre><p>Then you tell the DOM how to find that content:</p><pre><code class="lang-html"><span class="tag"><<span class="title">body</span> <span class="attribute">data-content</span>=<span class="value">"main"</span>></span>
...
<span class="tag"></<span class="title">body</span>></span></code></pre><p>That's it! You can put any arbitrary data into content attributes.</p><p>Why is this preferrable to the other frameworks' approaches? 2 big reasons:</p><ol><li>You don't add heavy code to all of your framework objects for handling observing. This makes your code lightweight and super fast.</li><li>You are being explicit about the content the user sees. This distinguishes where the data in your app interfaces with the DOM, so you know where to look for rendering performance issues without having to learn how the entire framework manages their observer behavior.</li></ol><h3>The parts of<code>content</code></h3><p>The<code>content</code>API has 2 methods:</p><ul><li><code>attr</code>for defining attributes and default values.</li><li><code>action</code>for defining functions that should execute when a user clicks or performs some action.</li></ul><p>So you define<code>attr</code>for every property you want to expose to the DOM, and<code>action</code>for every function you want to run when the user does something. That's it!</p><p>You might wonder if that's really all you need (<code>attr</code>and<code>action</code>), "what about arbitrary functions" or "what about this one case"? You might be right, there may be a few more cases to cover (though I doubt it). But so far based on using this it doesn't seem like you'll need anything more that this. We'll have to all figure out the exact best way as we go, but for now this is a super lean and super simple approach, and seems to cover pretty much every use case in practice.</p><p>Most use cases are covered because, other than binding data to the DOM, you want to "do stuff" when the user clicks something (emits and event). So the bulk of your code is actually in those event handlers (call them "actions"), which are independent.</p></div></div><div><div data-id="guide.name" data-markdown="guide.content" id="directive"><h1>Directives</h1><p>Directives are the API to the DOM. In a perfect world, they're the only place your app code touches the DOM.</p><p>One developer called them <a href="http://henriquat.re/directives/introduction-to-directives/introductionToDirectives.html">domain-specific extensions to HTML</a>.</p><h2>Creating a custom directive</h2><p>You know how those old-school websites sometimes have events posted where the event expired like 3 weeks ago, but it's still says "Come to our event this saturday!"? I feel bad because you know it's going to take them a bunch of time calling and emailing people to "update their site" to remove that event.</p><p>Never again.</p><p>Here is how you can solve that with directives and never have to worry about stuff like that in the future: automatically remove the event when the event passes.</p><pre><code class="lang-html"><span class="tag"><<span class="title">div</span> <span class="attribute">data-expires</span>=<span class="value">"june 30, 2013"</span>></span>
Come to our BBQ on Sunday, June 30th!
<span class="tag"></<span class="title">div</span>></span></code></pre><p>So we just added an attribute to the DOM that we just made up,<code>data-expires</code>. Now we need to define a directive for it:</p><pre><code class="lang-js"><span class="keyword">var</span> directive = require(<span class="string">'tower-directive'</span>);
directive(<span class="string">'data-expires'</span>, <span class="keyword">function</span>(scope, el, attr){
<span class="keyword">var</span> date = <span class="keyword">new</span> Date(attr.value);
<span class="keyword">var</span> now = <span class="keyword">new</span> Date;
<span class="comment">// if today is on or past the day, remove the element</span>
<span class="keyword">if</span> (date <= now) $(el).remove();
});</code></pre><p>It is as simple as that. Now when that DOM node is encountered, and the directives are parsed for it (this stuff all happens when you run a DOM node through a template), it will execute that directive, passing in the<code>scope</code>(the current<code>tower-content</code>instance which has a bunch of properties and methods on it), the actual DOM element<code>el</code>, and<code>attr</code>which has the value that the element attribute was set to, parsed using<code>tower-expression</code>. All you really need to know is that in this directive function, you get the element that had that directive on it, and some data you can use (or ignore) to manipulate the element.</p><h2>Resources</h2><ul><li><a href="http://www.bennadel.com/blog/2440-Creating-A-Custom-Show-Hide-Directive-In-AngularJS.htm">http://www.bennadel.com/blog/2440-Creating-A-Custom-Show-Hide-Directive-In-AngularJS.htm</a></li><li><a href="http://docs.angularjs.org/guide/directive">http://docs.angularjs.org/guide/directive</a></li><li><a href="http://blog.brunoscopelliti.com/use-cases-of-angularjs-directives">http://blog.brunoscopelliti.com/use-cases-of-angularjs-directives</a></li><li><a href="http://henriquat.re/directives/advanced-directives-combining-angular-with-existing-components-and-jquery/angularAndJquery.html">http://henriquat.re/directives/advanced-directives-combining-angular-with-existing-components-and-jquery/angularAndJquery.html</a></li><li><a href="http://henriquat.re/directives/introduction-to-directives/introductionToDirectives.html#transclusion">http://henriquat.re/directives/introduction-to-directives/introductionToDirectives.html#transclusion</a></li></ul></div></div><div><div data-id="guide.name" data-markdown="guide.content" id="element"><h1>Elements</h1><p>Once you start building more complex <a href="/guides/templates">templates</a> which have custom JavaScript, and maybe some configuration (like pagers, modal windows, form fields, etc.), custom <a href="https://github.com/tower/element">elements</a> are perfect for this.</p><p>In Tower, an "element" is:</p><blockquote><p>a template + some JavaScript</p></blockquote><p>That's it.</p><p>So take a pager for example. Rather than calling it a "pager view" or something that has a "pagination controller", just think of creating a "pager" which is just some HTML with a JavaScript API. Here's how that might look.</p><h2>The Element's HTML Template</h2><p>First you define the HTML template. This HTML is straight from the Twitter Bootstrap <a href="http://twitter.github.io/bootstrap/components.html#pagination">pager component</a>:</p><pre><code class="lang-html"><span class="tag"><<span class="title">ul</span> <span class="attribute">class</span>=<span class="value">"pager"</span>></span>
<span class="tag"><<span class="title">li</span>></span><span class="tag"><<span class="title">a</span> <span class="attribute">href</span>=<span class="value">"#"</span> <span class="attribute">on-click</span>=<span class="value">"prev()"</span>></span>Prev<span class="tag"></<span class="title">a</span>></span><span class="tag"></<span class="title">li</span>></span>
<span class="tag"><<span class="title">li</span>></span><span class="tag"><<span class="title">a</span> <span class="attribute">href</span>=<span class="value">"#"</span> <span class="attribute">on-click</span>=<span class="value">"next()"</span>></span>Next<span class="tag"></<span class="title">a</span>></span><span class="tag"></<span class="title">li</span>></span>
<span class="tag"></<span class="title">ul</span>></span></code></pre><p>So in there we just added the standard <a href="https://github.com/tower/event-directive">event directive</a><code>on-click</code>, which executes a function (<code>prev()</code>or<code>next()</code>). In Tower we call the 2 functions<code>prev</code>and<code>next</code>as "actions", since most of the time, from the DOM's perspective, when you execute a function it's in response to some thing the user did, so you can think about it as "a user performing an action" (also,<code>action</code>is used all throughout the core modules, so it makes having a super consistent and clean API). In addition to these "actions", you can also define "attributes" (such as configuration, or maybe to allow customizing the<code>Prev</code>and<code>Next</code>labels), but for this simple case we'll just focus on actions.</p><p>An element, like a template, gets its actions and attributes from <a href="https://github.com/tower/content">content</a>. In the DOM there is (by convention) a root/global content object, and then you can create new nested content objects (more on this in the <a href="/guides/content">content</a> section). When you create nested content like this, it's called creating a new "content scope", similar to how in JavaScript, each function creates a new "scope".</p><p>Why is this relevant for an element?</p><p>Elements create a new content scope automatically for you, so you just need to know that when you define actions and attributes on your custom<code>element</code>, all that's actually happening is those methods are being delegated to a<code>content</code>object specific to that element. You can see that <a href="https://github.com/tower/element/blob/e5a301fa63d3a04f1abc5952143cd883a08d2434/lib/statics.js#L42-L50">in the source code</a>.</p><h2>The Element's JavaScript</h2><p>Here's how we'd define the pager element that works with the above HTML template:</p><pre><code class="lang-js"><span class="keyword">var</span> element = require(<span class="string">'tower-element'</span>);
<span class="keyword">var</span> html = require(<span class="string">'./template'</span>); <span class="comment">// the template HTML from above</span>
element(<span class="string">'pager'</span>)
.template(html)
.action(<span class="string">'prev'</span>, <span class="keyword">function</span>(pager){
<span class="comment">// do something to the pager, pager.el, or pager.content</span>
})
.action(<span class="string">'next'</span>, <span class="keyword">function</span>(pager){
});</code></pre><p>Then we can instantiate the pager like this:</p><pre><code class="lang-js"><span class="keyword">var</span> pager = element(<span class="string">'pager'</span>).init();
<span class="keyword">var</span> el = pager.render();</code></pre><p>The actual DOM node is stored on the element instance as well (after<code>.render()</code>has been called):</p><pre><code class="lang-js">pager.el</code></pre><h2>Using Attributes on Elements</h2><p>Now what if we want to be able to specify the label for<code>Prev</code>and<code>Next</code>?</p><p>Easy!</p><p>We just need to make the hardcoded strings in the template into variables (like mustache/handlebars), and add those attributes to the<code>element('pager')</code>DSL (and you can set default values too):</p><pre><code class="lang-html"><span class="tag"><<span class="title">ul</span> <span class="attribute">class</span>=<span class="value">"pager"</span>></span>
<span class="tag"><<span class="title">li</span>></span><span class="tag"><<span class="title">a</span> <span class="attribute">href</span>=<span class="value">"#"</span> <span class="attribute">on-click</span>=<span class="value">"prev()"</span>></span>{{prevLabel}}<span class="tag"></<span class="title">a</span>></span><span class="tag"></<span class="title">li</span>></span>
<span class="tag"><<span class="title">li</span>></span><span class="tag"><<span class="title">a</span> <span class="attribute">href</span>=<span class="value">"#"</span> <span class="attribute">on-click</span>=<span class="value">"next()"</span>></span>{{nextLabel}}<span class="tag"></<span class="title">a</span>></span><span class="tag"></<span class="title">li</span>></span>
<span class="tag"></<span class="title">ul</span>></span></code></pre><pre><code class="lang-js">element(<span class="string">'pager'</span>)
.template(html)
.attr(<span class="string">'prevLabel'</span>, <span class="string">'string'</span>, <span class="string">'Prev'</span>)
.attr(<span class="string">'nextLabel'</span>, <span class="string">'string'</span>, <span class="string">'Next'</span>)
.action(<span class="string">'prev'</span>, <span class="keyword">function</span>(pager){
})
.action(<span class="string">'next'</span>, <span class="keyword">function</span>(pager){
});</code></pre><p>So now if you instantiated and rendered your pager, it would be rendered like it was before. But you can also customize the labels this time:</p><pre><code class="lang-js"><span class="keyword">var</span> pager = element(<span class="string">'pager'</span>).init();
document.body.addChild(pager.render({ prevLabel: <span class="string">'<'</span>, nextLabel: <span class="string">'>'</span> }));</code></pre><p>You can also pass the attribute values in on<code>init</code>, in case you wanted to set up defaults. Either way, using<code>.init</code>or<code>.render</code>works fine the first time around:</p><pre><code class="lang-js"><span class="keyword">var</span> pager = element(<span class="string">'pager'</span>).init({ prevLabel: <span class="string">'<'</span>, nextLabel: <span class="string">'>'</span> });
document.body.addChild(pager.render());</code></pre><h2>Building hardcore UI elements</h2><p>Ideally, this element API will allow for creating super robust/complex UI elements, such as forms, <a href="https://github.com/mleibman/SlickGrid">datagrids</a> and things like Pinterest's scroller (Airbnb open sourced <a href="https://github.com/airbnb/infinity">infinity</a> which is similar).</p><p>However, if you do end up creating a complex UI component like these, I recommend not building all of the logic into the<code>element</code>DSL. Instead, try to build it so it can be used independently of Tower, but then you can wrap it in a Tower<code>element</code>and release that repo too, so your component can easily hook into Tower's templating system. This way, if someone came along and wanted to use your component but they were using something like Ember or Angular, they could make it work there too.</p><p>This also goes to show, it should be easy to integrate any external UI thingy into Tower so it can be used with this standard API.</p><p>Last little note. I'd say that most of the time you won't need to build custom elements, and can instead just use plain HTML templates and the built in directives. But if the time comes where that's not enough, this is here to make life easy.</p></div></div><div><div data-id="guide.name" data-markdown="guide.content" id="expression"><h1>Expression Engine</h1><p>Within Tower, sits an incredibly powerful expression engine that powers every binding. We felt like we could create an expressive language that sits in element attributes.</p><p>Let's get started with a simple example:</p><pre><code class="lang-html"><span class="tag"><<span class="title">div</span> <span class="attribute">data-text</span>=<span class="value">""</span>></span><span class="tag"></<span class="title">div</span>></span></code></pre><p>That's cool, right? Well, it's just an empty text binding, nothing to it. So let's add a binding to a simple attribute.</p><pre><code class="lang-html"><span class="tag"><<span class="title">div</span> <span class="attribute">data-text</span>=<span class="value">"user"</span>></span><span class="tag"></<span class="title">div</span>></span></code></pre><p>This would effectively render the following, if<code>user</code>would equal to<code>Joe</code></p><pre><code class="lang-html"><span class="tag"><<span class="title">div</span> <span class="attribute">data-text</span>=<span class="value">"user"</span>></span>Joe<span class="tag"></<span class="title">div</span>></span></code></pre><p>This short example just showed you a simple expression; a string expression. Expressions do get more complicated than that, but the premise stays the same.</p><p>The expression engine is hand-built. Well, you'll probably say "Yeah, sure, just like anything else that's programmed. All by hand". No, no, no. When I say "by-hand", I mean in relation to the Lexer and Parser, and anything else related to the expression engine. We don't use some sort of magical generator that produces extremely huge Lexers, Parsers, and whatever else they have.The expression engine is small, soon-to-be modular, and fast. This makes it viable to run on the client-side, as well as the server. Oh, yes, this has no dependencies on the DOM, which means it can be used server-side.</p><p>Let's get into a more complicated example, shall we?</p><pre><code class="lang-html"><span class="tag"><<span class="title">div</span> <span class="attribute">data-list</span>=<span class="value">"user in users [buffer: 2, max: 10]"</span>></span><span class="tag"></<span class="title">div</span>></span></code></pre><p>Wow. What's that?</p><p>That's a "foreach" or "each" expression, with arguments. In this case, we want to create an additional 2 element buffer in our list, and only have a maximum of 10 elements. Super simple and concise.</p><p>The string "user in users" is probably familiar. Many languages and some frameworks have this syntax, or something similar.</p><p>Want more?</p><pre><code class="lang-html"><span class="tag"><<span class="title">div</span> <span class="attribute">data-list</span>=<span class="value">"user in users [buffer: 2, max: 10] | filter: startsWith(a) | sort: reverse()"</span>></span><span class="tag"></<span class="title">div</span>></span></code></pre><h2>Deep Dive Into Expressions</h2><p>Now that you know what expressions are, let's get a better picture on how it works.</p><p>The expression engine has the following stages:</p><pre><code>Input -> Lexer -> Parser -> Search</code></pre><p><code>tower-expression/index.js</code>exposes an<code>expression</code>function and accepts a string: an expression. It'll hand the big work of lexing and parsing the string.</p><p>We've made an extensible Lexer that's not specific to the expression system.</p><pre><code class="lang-js"><span class="keyword">var</span> lex = <span class="keyword">new</span> Lexer()
.def(<span class="string">'token1'</span>, <span class="regexp">/^\[$/</span>)
.string(<span class="string">'random string to lex'</span>)
.start();</code></pre></div></div><div><div data-id="guide.name" data-markdown="guide.content" id="route"></div></div><div><div data-id="guide.name" data-markdown="guide.content" id="cookbook"><h1>Cookbooks</h1><p>The idea of cookbooks came out of a desire to use Chef, the great automation library for Ruby, in JavaScript. So every layer in your app -- the client, the server, and also the command line -- is just plain JavaScript.</p><p>Cookbooks are an extensible system for abstracting away common tasks and commands. This includes components such as:</p><ul><li>generators</li><li>build scripts (like things you would do with Grunt/Yeoman)</li><li>making an <a href="/guides/adapters">adapter</a> useable from the command line (see <a href="https://github.com/tower/ec2-cookbook">tower-ec2-cookbook</a>)</li><li>abstracting away install scripts (such as installing node.js, git, or mongodb on EC2, like Chef cookbooks)</li><li>building aliases to commands (such as simplifying the API for ssh-ing to a remote server, or normalizing how you enter a database console)</li></ul><p>Cookbooks are super easy to write. It's just one<code>index.js</code>that<code>exports</code>"actions" (such as<code>create</code>,<code>remove</code>,<code>install</code>, etc.). Because of Tower's <a href="/guides/cli">CLI abstraction</a>, you can execute these cookbook actions ("recipes") from the command automatically. Super powerful.</p><h2>How a cookbook works</h2><p>One of the simplest cookbooks is just a generator (like one you find in Rails). Here is the <a href="https://github.com/tower/component-cookbook">tower-component-cookbook</a>, which generates a new module (with<code>package.json</code>for npm and<code>component.json</code>) with this commmand:</p><pre><code class="lang-bash">$ tower create component my-component</code></pre><p>Here's what happens when we execute that command:</p><ol><li>Goes to <a href="https://github.com/tower/cli">tower-cli</a> (since it is just using the<code>tower</code>executable), and figures out that you called the action<code>create</code>on the cookbook<code>component</code>.</li><li>Finds the cookbook<code>component</code>.</li><li>Calls the method<code>create</code>on the cookbook<code>component</code>, passing in a new <a href="https://github.com/tower/recipe">recipe</a> object (which just has some helpful methods like you'd find in a generator), and the command line arguments.</li><li>The action<code>create</code>then can parse the arguments (using any one of the many cli option parsers for node, it's agnostic), and do whatever it needs to, in this case, generating a JavaScript module.</li></ol><p>This is the structure of a cookbook action:</p><pre><code class="lang-js">exports.create = <span class="keyword">function</span>(recipe, args, fn){
<span class="comment">// fn (callback) is an optional third param</span>
};</code></pre><p>You have full control over how the arguments are parsed and what happens. Here is an example of parsing arguments with <a href="https://github.com/visionmedia/commander.js/">commander</a>:</p><pre><code class="lang-js">exports.create = <span class="keyword">function</span>(recipe, args, fn){
<span class="keyword">var</span> projectName = args[<span class="number">4</span>];
<span class="keyword">var</span> options = require(<span class="string">'commander'</span>)
.option(<span class="string">'-o, --output-directory [value]'</span>, <span class="string">'Output directory'</span>, process.cwd())
.option(<span class="string">'-b --bin [value]'</span>, <span class="string">'include executable'</span>, <span class="literal">false</span>)
.option(<span class="string">'--component [value]'</span>, <span class="string">'Add component.json'</span>, <span class="literal">false</span>)
.option(<span class="string">'--package [value]'</span>, <span class="string">'Add package.json'</span>, <span class="literal">true</span>)
.option(<span class="string">'--travis [value]'</span>, <span class="string">'Add travis.yml'</span>, <span class="literal">false</span>)
.option(<span class="string">'--namespace [value]'</span>, <span class="string">'Namespace for component'</span>)
.parse(args);
<span class="comment">// ...</span>
};</code></pre><p>Take a look at the <a href="https://github.com/tower/component-cookbook/blob/master/index.js">component-cookbook source</a> for the robust implementation.</p></div></div><div><div data-id="guide.name" data-markdown="guide.content" id="cli"><h1>Tower's Command Line Interface (CLI)</h1><pre><code class="lang-bash">$ tower <action> <object> [options]</code></pre><p>Tower's command line was built to be super fast. When you enter the tower console, it's instant (on the order of 10ms):</p><pre><code class="lang-bash">$ tower console</code></pre><p>Another big goal of the CLI was to make it infinitely extensible (but avoiding the problem of people swooping on names and whatnot). To do this, we standardized the structure of command line arguments:</p><pre><code class="lang-bash">$ tower <action> <object> [options]</code></pre><p>You can create your own commands by creating a cookbook (see the <a href="/cookbooks">cookbook</a> section).</p></div></div></div><div class="span3"><nav class="sidebar-nav"><ul class="nav nav-list"><!-- data-list:guide in guides --><li><a data-href="guide.href" data-text="guide.title" href="#resource">Resource</a></li><li><a data-href="guide.href" data-text="guide.title" href="#adapter">Adapter</a></li><li><a data-href="guide.href" data-text="guide.title" href="#query">Query</a></li><li><a data-href="guide.href" data-text="guide.title" href="#template">Template</a></li><li><a data-href="guide.href" data-text="guide.title" href="#content">Content</a></li><li><a data-href="guide.href" data-text="guide.title" href="#directive">Directive</a></li><li><a data-href="guide.href" data-text="guide.title" href="#element">Element</a></li><li><a data-href="guide.href" data-text="guide.title" href="#expression">Expression</a></li><li><a data-href="guide.href" data-text="guide.title" href="#route">Route</a></li><li><a data-href="guide.href" data-text="guide.title" href="#cookbook">Cookbook</a></li><li><a data-href="guide.href" data-text="guide.title" href="#cli">Cli</a></li></ul></nav></div></div></div></section><footer></footer></div></body>