lanes 0.0.5 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/Gemfile +0 -1
- data/README.md +2 -0
- data/client/lanes/data/Bootstrap.coffee +2 -2
- data/client/lanes/data/Collection.coffee +4 -0
- data/client/lanes/data/Config.coffee +0 -5
- data/client/lanes/data/Model.coffee +236 -150
- data/client/lanes/data/PubSub.coffee +6 -12
- data/client/lanes/data/Sync.coffee +1 -0
- data/client/lanes/extension/Extensions.coffee +4 -2
- data/client/lanes/lib/MakeBaseClass.coffee +1 -1
- data/client/lanes/minimal.js +11 -0
- data/client/lanes/minimal.scss.erb +12 -0
- data/client/lanes/screens/Base.coffee +1 -2
- data/client/lanes/screens/Instance.coffee +52 -0
- data/client/lanes/vendor/packaged.js +1 -2
- data/client/lanes/views/Base.coffee +12 -10
- data/client/lanes/workspace.scss.erb +3 -0
- data/client/lanes/workspace/index.js +2 -12
- data/docs/command.md +111 -0
- data/docs/model.md +188 -0
- data/docs/todo-example-part-1.md +71 -0
- data/docs/view.md +275 -0
- data/{spec/client/jasmine_examples/PlayerSpec.js → docs/welcome.md} +0 -0
- data/lanes.gemspec +3 -1
- data/lib/lanes/api/helper_methods.rb +8 -0
- data/lib/lanes/api/javascript_processor.rb +14 -10
- data/lib/lanes/api/pub_sub.rb +7 -7
- data/lib/lanes/api/request_wrapper.rb +1 -0
- data/lib/lanes/api/root.rb +2 -7
- data/lib/lanes/api/sprockets_compressor.rb +6 -2
- data/lib/lanes/api/sprockets_extension.rb +25 -9
- data/lib/lanes/api/test_specs.rb +13 -9
- data/lib/lanes/command.rb +16 -6
- data/lib/lanes/command/app.rb +11 -5
- data/lib/lanes/command/generate_model.rb +4 -3
- data/lib/lanes/command/generate_screen.rb +2 -1
- data/lib/lanes/command/generate_view.rb +1 -1
- data/lib/lanes/command/named_command.rb +5 -4
- data/lib/lanes/command/templates/Gemfile +1 -2
- data/lib/lanes/command/templates/client/data/Model.coffee +3 -3
- data/lib/lanes/command/templates/client/{namespace-extension.js → index.js} +0 -0
- data/lib/lanes/command/templates/client/screens/Screen.coffee +1 -3
- data/lib/lanes/command/templates/client/{styles/styles.scss → styles.scss} +0 -0
- data/lib/lanes/command/templates/client/views/View.coffee +1 -3
- data/lib/lanes/command/templates/config/lanes.rb +1 -1
- data/lib/lanes/command/templates/gitignore +1 -0
- data/lib/lanes/command/templates/lib/namespace/screen.rb +1 -1
- data/lib/lanes/command/templates/public/.gitkeep +0 -0
- data/lib/lanes/command/templates/spec/client/Screen.coffee +7 -0
- data/lib/lanes/command/templates/spec/client/views/ViewSpec.coffee +2 -2
- data/lib/lanes/concerns/all.rb +1 -1
- data/lib/lanes/concerns/sanitize_fields.rb +32 -0
- data/lib/lanes/concerns/set_attribute_data.rb +4 -4
- data/lib/lanes/db.rb +7 -8
- data/lib/lanes/extension.rb +37 -3
- data/lib/lanes/guard_tasks.rb +2 -2
- data/lib/lanes/model.rb +2 -2
- data/lib/lanes/screens.rb +1 -0
- data/lib/lanes/spec_helper.rb +17 -6
- data/{spec → lib/lanes}/testing_models.rb +1 -1
- data/lib/lanes/version.rb +1 -1
- data/npm-build/compile.coffee +1 -6
- data/public/javascripts/jasmine_examples/Player.js +22 -0
- data/public/javascripts/jasmine_examples/Song.js +7 -0
- data/spec/api/javascript_processor_spec.rb +6 -3
- data/spec/concerns/api_path_spec.rb +1 -1
- data/spec/concerns/association_extensions_spec.rb +7 -3
- data/spec/concerns/attr_accessor_with_default_spec.rb +1 -1
- data/spec/concerns/code_identifier_spec.rb +1 -1
- data/spec/concerns/export_associations_spec.rb +1 -1
- data/spec/concerns/export_methods_spec.rb +1 -14
- data/spec/concerns/export_scope_spec.rb +7 -9
- data/spec/concerns/exported_limits_spec.rb +1 -1
- data/spec/concerns/pub_sub_spec.rb +1 -1
- data/spec/concerns/set_attribute_data_spec.rb +16 -24
- data/spec/configuration_spec.rb +1 -1
- data/spec/helpers/lanes-helpers.coffee +61 -0
- data/spec/lanes/data/ModelSpec.coffee +152 -0
- data/spec/lanes/data/PubSubSpec.coffee +21 -0
- data/spec/{client/view → lanes/views}/BaseSpec.coffee +6 -26
- data/spec/numbers_spec.rb +1 -1
- data/spec/strings_spec.rb +1 -1
- data/views/index.erb +3 -10
- data/views/specs.erb +4 -1
- metadata +62 -16
- data/client/lanes/plugins/trigger.coffee +0 -15
- data/client/lanes/workspace/Instance.es6 +0 -64
- data/lib/lanes/concerns/sanitize_api_data.rb +0 -15
- data/spec/api/user_spec.rb +0 -52
- data/spec/fixtures/lanes/users.yml +0 -13
- data/spec/locked_fields_spec.rb +0 -27
- data/spec/role_collection_spec.rb +0 -19
- data/spec/user_role_spec.rb +0 -7
- data/spec/user_spec.rb +0 -53
@@ -0,0 +1,71 @@
|
|
1
|
+
---
|
2
|
+
title: TODO MVC Example
|
3
|
+
position_after: command
|
4
|
+
---
|
5
|
+
|
6
|
+
As is required by all new frameworks, this is an example of creating a TODO application using the Lanes framework.
|
7
|
+
|
8
|
+
First install Lanes via Rubygems. `gem install lanes`
|
9
|
+
|
10
|
+
As always when using Lanes, the first thing you'll need to do is generate your application. We will name this app simply as `todo`
|
11
|
+
|
12
|
+
{% highlight bash %}
|
13
|
+
lanes new todo
|
14
|
+
{% endhighlight %}
|
15
|
+
|
16
|
+
This will create a new directory with a skeleton Lanes application. Read more about the directories and what their purposes are at {% doc_link command heading:'lanes new' %}.
|
17
|
+
|
18
|
+
[Our example app at this point](https://github.com/argosity/lanes-todo-demo/tree/2d649b314a826cbbdbf54e3f72041caeeee8e428)
|
19
|
+
|
20
|
+
# Setup
|
21
|
+
|
22
|
+
A sample database configuration file is located in `config/database.yml` which will use a postgresql database named todo_dev. For the purposes of this example, we'll just create a new postgresql database that matches the configuration: `createdb todo_dev`
|
23
|
+
|
24
|
+
Fire up the lanes testing server: `lanes serve`. The test server will start the app and you can view it at: `http://localhost:8888/`. You should see a simple "Todo" message. You can also view the Jasmine specs at `http://localhost:8888/spec`
|
25
|
+
|
26
|
+
We'll copy the styles from the [TodoMVC template](https://github.com/tastejs/todomvc/tree/master/template).
|
27
|
+
|
28
|
+
Looking at the Todo app, it has four distinct areas. A `sidebar`, `header`, `footer` and `listing` views. We can create views for them by executing `lanes generate view <name>`, where '< name >' is the view to create. [commit](https://github.com/argosity/lanes-todo-demo/commit/758d0e63359db18ee0291467656454c9fc1c3573)
|
29
|
+
|
30
|
+
First we take the TodoMVC html template and break it apart into sections and copy them to each view. We're then able to plug each view's reference into the Screen as subviews. [commit](https://github.com/argosity/lanes-todo-demo/commit/8c5178a76f2a8abc0ffadbafb1239f7a8ba113b9)
|
31
|
+
|
32
|
+
Next we'll create a data model `lanes generate model task title:string{80} completed:boolean` [commit](https://github.com/argosity/lanes-todo-demo/commit/5080c286aa4fb35a2b8372cc86ca4e9e18a18c3f)
|
33
|
+
|
34
|
+
Since a task should default to being non-completed, we'll edit the migration to default that field to `false` and add a validation to the model [commit](https://github.com/argosity/lanes-todo-demo/commit/e3f7edf9f2863f0669cccac13f7f8e2b88276b5a)
|
35
|
+
|
36
|
+
Run migration: `lanes db migrate`
|
37
|
+
|
38
|
+
We'll also create a TaskSummary model that is in charge of summarizing the state of the tasks. It will listen to the tasks collection and perform calculations when events occur. [commit](https://github.com/argosity/lanes-todo-demo/commit/65da191ee749ab749855e06ce69c3bd09662e0d5)
|
39
|
+
|
40
|
+
# Data and events
|
41
|
+
|
42
|
+
## Header View
|
43
|
+
It's responsible for interaction with the "What needs to be done?" input. When text is present and the "enter" key is pressed, it should save a record and add it to the collection. We're able to do so in [just a few lines of code](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/views/Header.coffee#L22-L25)
|
44
|
+
|
45
|
+
We can easily test that it performs as it should by [adding a few specs](https://github.com/argosity/lanes-todo-demo/blob/master/spec/todo/views/HeaderSpec.coffee#L18-L29).
|
46
|
+
|
47
|
+
## Listing View
|
48
|
+
This view is a bit more complex. It has a parent view which handles toggling all todo's between being complete and pending, and a collection of subviews that model each individual task. [ListingView](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/views/Listing.coffee)
|
49
|
+
|
50
|
+
Each TaskView is responsible for handling it's own editing state and saving value to it's model.
|
51
|
+
|
52
|
+
## Footer View
|
53
|
+
The only action this view takes is to delete any tasks that are marked as complete when the "Clear Completed" button is clicked. It also displays quite a few values from our TasksSummary. Lane's declarative bindings make these easy to wire up. [FooterView](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/views/Footer.coffee)
|
54
|
+
|
55
|
+
You might notice that Lanes makes it super easy to batch update or delete a collection. The footer simply calls destroyAll on the "completed" sub-collection provided by the TaskSummary. Since that sub-collection filters the main collection to only contain "completed" tasks, it's safe to just destroy all the model's in one go. It's so easy in fact that the FooterView demonstrates an alternative use of events. The function is directly given to the "events" property, rather than a method reference. [Save Call](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/views/Footer.coffee#L27)
|
56
|
+
|
57
|
+
# Routing
|
58
|
+
|
59
|
+
For a simple app like the this one, it's easiest to just allow the URL change to trigger what the filtered collection is displaying. We set that up when the screen is initialized. [Routing](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/Router.coffee)
|
60
|
+
|
61
|
+
# Deploying
|
62
|
+
|
63
|
+
For the example we'll host it on Heroku. Other deployments should be similar to deploying a Rails application.
|
64
|
+
|
65
|
+
Simply commit the source and add a remote per Heroku's instructions: [https://devcenter.heroku.com/articles/git](https://devcenter.heroku.com/articles/git)
|
66
|
+
|
67
|
+
When you `git push heroku`, Heroku will notice that Lanes uses sprockets and will automatically run `rake assets:precompile`, and then run the application using the puma webserver.
|
68
|
+
|
69
|
+
On first deploy and when your db schema has changed, you will have to provision and migrate the database on Heroku by running: `heroku run rake db:migrate`
|
70
|
+
|
71
|
+
|
data/docs/view.md
ADDED
@@ -0,0 +1,275 @@
|
|
1
|
+
---
|
2
|
+
title: View
|
3
|
+
heading: Lanes.Data.View
|
4
|
+
---
|
5
|
+
|
6
|
+
Lanes provides a Lanes.Views.Base class that all other views extend from.
|
7
|
+
|
8
|
+
In their simplest form, a view simply renders a string into a DOM element. They provide a mediating interface between data and the DOM.
|
9
|
+
|
10
|
+
Since both Models, Collections, and the DOM emit events, a view's job is to listen to the events and then manipulate the other parties data structures.
|
11
|
+
|
12
|
+
Lanes' base view provides numerous hooks and helper functions to make the process of responding to events and relaying them easier.
|
13
|
+
|
14
|
+
Views can also be nested inside other views and will bubble relevant events up to thier parent views.
|
15
|
+
|
16
|
+
Views inherit from [Ampersand State](http://ampersandjs.com/docs#ampersand-state), and therefore support all the same methods and declarations that it does.
|
17
|
+
|
18
|
+
<aside>
|
19
|
+
Unlike Backbone.js, when the view is rendered the old el (if present)
|
20
|
+
is discared and an new one is created at the same point in the DOM.
|
21
|
+
This prevents the doubly nested divs issue that Backbone experiences,
|
22
|
+
but can be suprising behaviour for those who aren't expecting it.
|
23
|
+
</aside>
|
24
|
+
|
25
|
+
### API Reference
|
26
|
+
|
27
|
+
# initialize
|
28
|
+
|
29
|
+
`new View({options})`
|
30
|
+
|
31
|
+
Called by the constructor after the view is initialized. initialize can be used by your views for performing initialization of the class.
|
32
|
+
|
33
|
+
Views have several options that will be copied to the view if they are given to initialize. Those options and their types are el (element), model (state), collection (collection), pubSub (boolean), parent (object), subviewId (string).
|
34
|
+
|
35
|
+
``` coffee
|
36
|
+
|
37
|
+
class MyView extends Lanes.Views.Base
|
38
|
+
|
39
|
+
initialize: (options)->
|
40
|
+
this.magic = options.answer
|
41
|
+
|
42
|
+
view = new MyView( answer: 42 )
|
43
|
+
# view.magic => 42
|
44
|
+
|
45
|
+
```
|
46
|
+
|
47
|
+
# source
|
48
|
+
|
49
|
+
The "source" property is a way for Lanes to detect where the view was loaded from. When Lanes sets up a new class it sets it to the "magic" FILE variable. Lanes Coffeescript pre-processor will set the FILE to the proper values for each file. The Base View uses the information contained in source to auto-load views and models from the correct location.
|
50
|
+
|
51
|
+
# el
|
52
|
+
|
53
|
+
A reference to a DOM element that is controlled by the view.
|
54
|
+
|
55
|
+
All views have a single DOM element. If a view does is not provided an el when it's created, it will construct one when the render method is called.
|
56
|
+
|
57
|
+
# template
|
58
|
+
|
59
|
+
Either an string or a function that returns a string. The string can be either a path to a pre-compiled template, or a HTML string.
|
60
|
+
|
61
|
+
|
62
|
+
``` coffee
|
63
|
+
class MyView extends Lanes.Views.Base
|
64
|
+
template: "<div><p>Hello World</p></div>"
|
65
|
+
|
66
|
+
view = new MyView
|
67
|
+
view.render()
|
68
|
+
|
69
|
+
# view.el.innerHTML => <div><p>Hello World</p></div>
|
70
|
+
```
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
``` coffee
|
75
|
+
class MyView extends Lanes.Views.Base
|
76
|
+
template: "views/myview"
|
77
|
+
|
78
|
+
view = new MyView
|
79
|
+
# attempt to render a template from path "views/myview"
|
80
|
+
view.render()
|
81
|
+
```
|
82
|
+
|
83
|
+
|
84
|
+
``` coffee
|
85
|
+
# Contained in file MyView.coffee
|
86
|
+
|
87
|
+
class MyApp.Views.MyView extends Lanes.Views.Base
|
88
|
+
source: FILE
|
89
|
+
|
90
|
+
view = new MyView
|
91
|
+
# will use the "source" information to render
|
92
|
+
# a template from "myapp/views/my_view"
|
93
|
+
view.render()
|
94
|
+
```
|
95
|
+
|
96
|
+
# templateName
|
97
|
+
|
98
|
+
A string (or function that returns one) that contains the name of a template. The template will be loaded from the same path but using the templateName instead of one with the same name as the file.
|
99
|
+
|
100
|
+
``` coffee
|
101
|
+
class MyApp.Views.MyView extends Lanes.Views.Base
|
102
|
+
source: FILE
|
103
|
+
templateName: "contents"
|
104
|
+
|
105
|
+
view = new MyView
|
106
|
+
# will use the "source" information to render
|
107
|
+
# a template from "myapp/views/contents"
|
108
|
+
view.render()
|
109
|
+
```
|
110
|
+
|
111
|
+
# subviews
|
112
|
+
|
113
|
+
Subviews are View classes that should be rendered at a given point on the DOM once conditions are met.
|
114
|
+
|
115
|
+
In order for a subview to render, the parent's el must have a valid reference to the DOM element to render the subview into, as well as all data for the subview being present.
|
116
|
+
|
117
|
+
When Subviews are created they are passed the parent view and any other options that were specified.
|
118
|
+
|
119
|
+
Definitions for subviews apre specified using:
|
120
|
+
|
121
|
+
* A "view" or "component" key, given either as a class or a string that contains the keypath to the object.
|
122
|
+
* Either a "container" or "hook" reference. If one is not given, it will default to a hook with the same name as the subview reference. For instace the "heading" subview below will default to `data-hook="heading"`
|
123
|
+
* A model or collection reference. If a collection reference is given, the collection will render using a collectionView.
|
124
|
+
* Options. Either a object, a function, or a reference to a class method to call.
|
125
|
+
|
126
|
+
|
127
|
+
``` coffee
|
128
|
+
class MyApp.Views.MyView extends Lanes.Views.Base
|
129
|
+
subviews:
|
130
|
+
heading:
|
131
|
+
view: MyApp.WeirdNamespace.Heading
|
132
|
+
model: 'model.person'
|
133
|
+
options: {uppercase: true}
|
134
|
+
grid:
|
135
|
+
component: "Grid"
|
136
|
+
container: 'div.grid'
|
137
|
+
options: 'gridOptions'
|
138
|
+
names:
|
139
|
+
view: "NamesItem"
|
140
|
+
container: "div.names"
|
141
|
+
collection: 'collection'
|
142
|
+
gridOptions: -> { count: this.count() }
|
143
|
+
template: "<div>
|
144
|
+
<div data-hook='heading'></div>
|
145
|
+
<div data-hook='finder'></div>
|
146
|
+
<div class='grid'></div>
|
147
|
+
<div class='names'></div>
|
148
|
+
</div>"
|
149
|
+
```
|
150
|
+
|
151
|
+
Notes:
|
152
|
+
|
153
|
+
* **heading**
|
154
|
+
* Is specified as a class object. `MyApp.WeirdNamespace.Heading` must be defined prior to the file being read and should be a "view like" object.
|
155
|
+
* It's model will be set to the value from `model.person`, and it will not be rendered until `model.person` is set to a truthy value.
|
156
|
+
* When the view is created it will be passed `{uppercase: true}` as it's options.
|
157
|
+
* No `selector` or `hook` was provided. It will default to rendering to `data-hook="heading"`
|
158
|
+
* **grid**
|
159
|
+
* is using a component named "Grid". When the subview is ready to be created, Lanes will look for a class in the "Components" namespace: `Lanes.Components.Grid`
|
160
|
+
* Will render to the "div.grid" element.
|
161
|
+
* It's options will be set from the value returned by calling the `gridOptions` method.
|
162
|
+
* **names**
|
163
|
+
* Since the "view" is given as a simple string, Lanes will search for it in the MyApp namespace, and will expect `MyApp.Views.NamesItem` to be defined
|
164
|
+
* A collection is specified. A collectionView will be created and the NamesItem class given as the child view to the collectionView. The collectionView will then handle rendering the collection whenever it has items added/removed.
|
165
|
+
|
166
|
+
|
167
|
+
# subviewOptions(name,def)
|
168
|
+
|
169
|
+
When subviews are created, they are initialized with an options object containing the parent view, and any other options that are returned by the `subviewOptions` method.
|
170
|
+
|
171
|
+
The base view's implementation simply returns any options that were given on the subview's definition.
|
172
|
+
|
173
|
+
Other views may override this method as a convienct way to specify the same options for all subviews.
|
174
|
+
|
175
|
+
In the below example, each of the subviews will be initialied with:
|
176
|
+
`{ parent: (MyView instance), model: (MyView instance).model, status: "red"}`
|
177
|
+
|
178
|
+
|
179
|
+
``` coffee
|
180
|
+
class MyApp.Views.MyView extends Lanes.Views.Base
|
181
|
+
subviews:
|
182
|
+
heading:
|
183
|
+
view: 'Heading'
|
184
|
+
footer:
|
185
|
+
view: 'Footer'
|
186
|
+
subviewOptions: ->
|
187
|
+
{model: @model, status: "red"}
|
188
|
+
|
189
|
+
```
|
190
|
+
|
191
|
+
|
192
|
+
|
193
|
+
# events
|
194
|
+
|
195
|
+
Listens for DOM events that occur within the view _(under it's el)_. Events are specified as a
|
196
|
+
hash containing "event selector" for the key and either a name of a method or function for the value.
|
197
|
+
|
198
|
+
If the selector is ommited, the event will be bound to the root element.
|
199
|
+
|
200
|
+
|
201
|
+
``` coffee
|
202
|
+
class MyApp.Views.MyView extends Lanes.Views.Base
|
203
|
+
template: "<div><a class='title'>click me!</a></div>"
|
204
|
+
events:
|
205
|
+
"click .title": "onTitleClick"
|
206
|
+
"click": -> console.log("I feel like I was clicked somewhere")
|
207
|
+
onTitleClick: ->
|
208
|
+
console.log "Title Was Clicked!"
|
209
|
+
```
|
210
|
+
|
211
|
+
# ui
|
212
|
+
|
213
|
+
A View will often need to access a given DOM element repeatedly. By specifying a the elements as part of the UI property, they will be cached when the view is rendered for speedy access.
|
214
|
+
|
215
|
+
Additionally elements cached in the UI can be refered to in bindings as a convience.
|
216
|
+
|
217
|
+
|
218
|
+
``` coffee
|
219
|
+
class MyApp.Views.MyView extends Lanes.Views.Base
|
220
|
+
ui:
|
221
|
+
title: "a.title"
|
222
|
+
template: "<div><a class='title'>click me!</a></div>"
|
223
|
+
events:
|
224
|
+
"click @ui.title": "onTitleClick"
|
225
|
+
onTitleClick: ->
|
226
|
+
console.log "Title Was Clicked!"
|
227
|
+
performOperation: ->
|
228
|
+
this.ui.title.hide()
|
229
|
+
runOperation()
|
230
|
+
this.ui.title.show()
|
231
|
+
```
|
232
|
+
|
233
|
+
### _Note:_ UI elements are not accessible until the view is rendered.
|
234
|
+
|
235
|
+
# query(selector)
|
236
|
+
|
237
|
+
Returns a single element based on CSS selector scoped to this.el
|
238
|
+
if you pass an empty string it return `this.el`.
|
239
|
+
|
240
|
+
Is more efficient that using the `$` method which calls out to jQuery
|
241
|
+
|
242
|
+
``` coffee
|
243
|
+
class MyView extends Lanes.Views.Base
|
244
|
+
template: "<div><a class='title'>click me!</a></div>"
|
245
|
+
|
246
|
+
view = new MyView
|
247
|
+
view.render()
|
248
|
+
# get the first element the class "title"
|
249
|
+
view.query('.title').click()
|
250
|
+
```
|
251
|
+
|
252
|
+
# $(selector)
|
253
|
+
|
254
|
+
The same as `query`, but uses jQuery to find the selection, and may return more than just one
|
255
|
+
element. Is essentially just a shortcut to running $el.find. It runs queries scoped within the view's element.
|
256
|
+
|
257
|
+
``` coffee
|
258
|
+
class MyView extends Lanes.Views.Base
|
259
|
+
template: "<div><a class='title'>click me!</a></div>"
|
260
|
+
|
261
|
+
view = new MyView
|
262
|
+
view.render()
|
263
|
+
# get the first element the class "title"
|
264
|
+
view.$('.title').click()
|
265
|
+
```
|
266
|
+
|
267
|
+
# parentScreen()
|
268
|
+
|
269
|
+
Walks up the parent chain, attempting to find a screen. If it's found once is returned, otherwise returns null.
|
270
|
+
|
271
|
+
It's sometimes useful to relay events up to a level where the user can make note of them. This method provides a way to obtain a reference to the owning screen.
|
272
|
+
|
273
|
+
# remove()
|
274
|
+
|
275
|
+
Recursively calls remove() on all subviews, than removes itself form the DOM and unbinds all event listeners.
|
File without changes
|
data/lanes.gemspec
CHANGED
@@ -41,13 +41,15 @@ Gem::Specification.new do |spec|
|
|
41
41
|
spec.add_dependency "hashie", "~> 3.3"
|
42
42
|
spec.add_dependency "rack-test", "~> 0.6"
|
43
43
|
spec.add_dependency "minitest-around", "~> 0.2"
|
44
|
+
spec.add_dependency "mocha", "~> 1.1"
|
44
45
|
spec.add_dependency "guard-minitest", "~> 2.3"
|
45
46
|
spec.add_dependency "yui-compressor", "~> 0.12"
|
47
|
+
spec.add_dependency "closure-compiler", "~> 1.1"
|
46
48
|
spec.add_dependency "guard-jasmine", "~> 2.0"
|
47
49
|
spec.add_dependency "rake", "~> 10.0"
|
48
50
|
spec.add_dependency "jasmine-core", "~> 2.0"
|
49
51
|
spec.add_dependency "require_all", "~> 1.3"
|
50
|
-
|
52
|
+
spec.add_dependency "sanitize", "~> 3.0"
|
51
53
|
spec.add_development_dependency "bundler", "~> 1.5"
|
52
54
|
spec.add_development_dependency "growl", "~> 1.0"
|
53
55
|
spec.add_development_dependency "pry-byebug", "~> 2.0"
|
@@ -3,6 +3,14 @@ module Lanes
|
|
3
3
|
|
4
4
|
module HelperMethods
|
5
5
|
|
6
|
+
def lanes_javascript_tag
|
7
|
+
javascript_tag( Extensions.require_workspace? ? 'lanes/workspace' : 'lanes/minimal' )
|
8
|
+
end
|
9
|
+
|
10
|
+
def lanes_stylesheet_tag
|
11
|
+
stylesheet_tag( Extensions.require_workspace? ? 'lanes/workspace' : 'lanes/minimal' )
|
12
|
+
end
|
13
|
+
|
6
14
|
def client_bootstrap_data
|
7
15
|
Oj.dump(Extensions.client_bootstrap_data(self), mode: :compat)
|
8
16
|
end
|
@@ -20,19 +20,23 @@ module Lanes
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def wrap_js(scope, js)
|
23
|
-
|
23
|
+
dirs = scope.logical_path.split(File::SEPARATOR)
|
24
|
+
ns = dirs.many? ? dirs.first.camelize : nil
|
25
|
+
file = dirs.last
|
26
|
+
# if the file is being loaded under the "lanes" directory
|
27
|
+
# it's not an extension
|
24
28
|
if ns && ns != "Lanes"
|
25
29
|
ref = "(window.Lanes ? window.Lanes['#{ns}'] : null)"
|
26
|
-
"(function(Lanes, #{ns},
|
30
|
+
"(function(Lanes, #{ns}, _, window, FILE, undefined)"\
|
31
|
+
"{\n#{js}\n})(window.Lanes,#{ref},window._, window,"\
|
32
|
+
"{namespace:#{ref},extension:'#{ns}',file:'#{file}'});"
|
27
33
|
else
|
28
|
-
"(function(Lanes,
|
34
|
+
"(function(Lanes, _, window, FILE, undefined)"\
|
35
|
+
"{\n#{js}\n})(window.Lanes,window._, window,"\
|
36
|
+
"{namespace:window.Lanes,extension:'Lanes',file:'#{file}'});"
|
29
37
|
end
|
30
38
|
end
|
31
39
|
|
32
|
-
def namespace(scope)
|
33
|
-
dirs = scope.logical_path.split(File::SEPARATOR)
|
34
|
-
return dirs.many? ? dirs.first.camelize : nil
|
35
|
-
end
|
36
40
|
end
|
37
41
|
|
38
42
|
class CoffeeScriptWrapper < JsAssetCompiler
|
@@ -41,10 +45,10 @@ module Lanes
|
|
41
45
|
CONSTRUCTOR = /constructor\s*:/
|
42
46
|
EXTENDING_CLASS = /class\s+([\w|\.]+)\s+extends\s+([\w|\.]+)\s*?\n/
|
43
47
|
|
44
|
-
# Coffeescript has two shortcomings with regards to
|
48
|
+
# Coffeescript has two shortcomings with regards to Lanes
|
45
49
|
#
|
46
|
-
# The first is that it's extends format is incompatible with
|
47
|
-
#
|
50
|
+
# The first is that it's extends format is incompatible with AmpersandState,
|
51
|
+
# State does quite a bit more via it's own .extend methods.
|
48
52
|
# Accordingly, we substitute our own "extend" call whenever we encounter a coffeescript extends
|
49
53
|
#
|
50
54
|
# The second issue is that if a constructor isn't present, coffeescript with generate it's own
|
data/lib/lanes/api/pub_sub.rb
CHANGED
@@ -1,9 +1,3 @@
|
|
1
|
-
require "oj"
|
2
|
-
|
3
|
-
require_relative "updates"
|
4
|
-
|
5
|
-
require 'message_bus'
|
6
|
-
|
7
1
|
module Lanes
|
8
2
|
module API
|
9
3
|
|
@@ -13,7 +7,13 @@ module Lanes
|
|
13
7
|
MessageBus.publish channel, data #Oj.dump(data, mode: :compat)
|
14
8
|
end
|
15
9
|
|
16
|
-
def self.initialize
|
10
|
+
def self.initialize(api)
|
11
|
+
return unless Extensions.require_pub_sub?
|
12
|
+
require "oj"
|
13
|
+
require_relative "updates"
|
14
|
+
require 'message_bus'
|
15
|
+
api.use MessageBus::Rack::Middleware
|
16
|
+
|
17
17
|
# Use OJ - it encodes dates properly as ISO 8601
|
18
18
|
# https://github.com/moment/moment/issues/1407
|
19
19
|
Oj.mimic_JSON()
|