darwinjs-rails 1.1 → 1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7bd0c876edd561b19225af8ae36ccc113c469ee1
4
+ data.tar.gz: 5f343991cd9087f3b576447814be7adf2fe4971f
5
+ SHA512:
6
+ metadata.gz: d9f4f59df36f7e34893245fefbd42ccf4e1faee5378c51884774c6e972471f9a94dd9327ba4d40872a02ce6b52d282d09e031cc988f56ee5188d06d549291211
7
+ data.tar.gz: d5dc3e60ca31e95052a011dd28d5d8203fa3a29ffc2be155a5a9fd54610e3eb25a5ae9952894cef9bf616699c91914f8176f748ee3775c7d718667e2ede044ab
data/README.md CHANGED
@@ -23,6 +23,8 @@ Or install it yourself as:
23
23
 
24
24
  ## Getting Started
25
25
 
26
+ ### Autoloader
27
+
26
28
  First, as one time configuration, add autoloader in your
27
29
  application.coffee file :
28
30
 
@@ -36,11 +38,14 @@ $(->
36
38
  )
37
39
  ```
38
40
 
41
+
42
+ ### Generator
43
+
39
44
  You can now generate a javascript module using the provided
40
45
  generator :
41
46
 
42
47
  ```
43
- $ rails generate darwin:assets users/index
48
+ $ rails generate darwinjs:assets users/index
44
49
 
45
50
  create app/assets/javascripts/controllers/users.coffee
46
51
  create app/assets/javascripts/views/users.coffee
@@ -70,28 +75,34 @@ A module is composed of two files :
70
75
  * a controller that handles events
71
76
  * a view that handles DOM manipulation
72
77
 
73
- Here is a typical view :
78
+
79
+ ### Controller
80
+
81
+ The minimal controller you could write is as this :
74
82
 
75
83
  ```coffee
76
- class App.Views.Users.Index extends Darwin.View
77
- @options {
78
- selectors:
79
- show_users: 'a#show_users'
80
- user_block: '#users'
81
- user:
82
- 'sel': '.user'
83
- more: '.more a'
84
- delete: 'a[data-method="delete"]'
85
- }
84
+ class App.Controllers.MyModule extends Darwin.Controller
85
+ run: ->
86
+ alert( 'hello' )
87
+ ```
86
88
 
87
- show_info_for( $link ) ->
88
- $link.next( '.info' ).show()
89
+ And bind it to your html file :
89
90
 
90
- remove_user_for( $link ) ->
91
- $link.parent().remove()
91
+ ```html
92
+ <div id="my-block" data-module="MyModule"></div>
92
93
  ```
93
94
 
94
- And the corresponding controller :
95
+ With just that, you've already leveraged an important performance tweak from
96
+ Darwin over `if $('#my_block').length then alert( 'hello' )` : instead of
97
+ querying the dom on every page of your application to find `#my_block`, a
98
+ single query will be issued to retrieve `*[data-module]` and initialize their
99
+ module. Just think of how many DOM queries that returns nothing you fire on
100
+ your typical page. `$('#not-existing')` does not do nothing, it browses the
101
+ whole DOM to retrieve a non-existing element. That's a performance issue.
102
+
103
+ But a controller can do way more than that. Its whole purpose is to encapsulate
104
+ interruptions - events and requests.
105
+
95
106
 
96
107
  ```coffee
97
108
  class App.Controllers.Users.Index extends Darwin.Controller
@@ -120,23 +131,89 @@ class App.Controllers.Users.Index extends Darwin.Controller
120
131
  )
121
132
  ```
122
133
 
123
- As you see, a view acts as single point of configuration for selectors.
124
- Any change made then reflect to the whole javascript codebase.
134
+ Events declaration are grouped in the option hash, with a human readable
135
+ description, so that any developer can understand at a glance what the
136
+ controller is doing. An event declaration is typically made of a descriptive
137
+ string and of configuration object :
138
+
139
+ ```coffee
140
+ 'Description': { el: 'element_name', type: 'event_type' }
141
+ ```
142
+
143
+ The callback method name is inferred from event configuration, using
144
+ `<element_name>_<event_type>(ed|d)`. The element (extended with jQuery) is
145
+ passed as first argument, and the raw event is passed as second.
146
+
147
+ Beside that, declaring events that way rather than directly with jQuery has a
148
+ massive advantage : all callback functions are wrapped in a function that will
149
+ prevent them to run if a crash occurs. It means that if you have a `<a
150
+ href="/foo"></a>` with a click event on it and a crash occurs, clicking it
151
+ again will not trigger event, and link will be followed. This ensure you can
152
+ have fallback features to handle javascript errors and reload the page.
153
+
154
+
155
+ ### View
156
+
157
+ Finally, views are meant for all DOM manipulation and acts as a single point of
158
+ configuration for selectors. In previous controller example, we've used element
159
+ names "show_user", "user_more", "user_delete", "user_block", etc. Very often in
160
+ a module, you will refer an element more than one time. It means that if your
161
+ html change, you've got to track all selectors used to find what you have to
162
+ change.
125
163
 
126
- In the same way, controller acts as a single point of configuration
127
- for events. You can tell what a module does looking at the first
128
- lines of the controller file.
164
+ This is not a problem with Darwin, as selectors are all configured in the same
165
+ place, without any repeatition :
129
166
 
130
- But there is more happening under the hood, here. First, all you DOM
131
- elements retrieved by view selectors are cached. Upon further call
132
- they are retrieved without hitting the DOM again, which is very
133
- costly in term of performances.
167
+ ```coffee
168
+ class App.Views.Users.Index extends Darwin.View
169
+ @options {
170
+ selectors:
171
+ show_users: 'a#show_users'
172
+ user_block: '#users'
173
+ user:
174
+ 'sel': '.user'
175
+ more: '.more a'
176
+ delete: 'a[data-method="delete"]'
177
+ }
178
+
179
+ show_info_for( $link ) ->
180
+ $link.next( '.info' ).show()
181
+
182
+ remove_user_for( $link ) ->
183
+ $link.parent().remove()
184
+ ```
185
+
186
+ The `selectors` options hash list all selectors used by module. They can be
187
+ declared right away or through a 'sel' key, which then allow to use nested
188
+ selectors. This system also offer a performance bonus : all elements retrieved
189
+ with these selectors are cached by default, because it's the desired behavior,
190
+ most of the time (you can pass option `cache: false` to a specific selector not
191
+ to cache its result). Selectors can be used with `get()` view method :
192
+ `@get('user_more')`.
193
+
194
+ Beside selectors configuration, views are responsible for DOM manipulation. It
195
+ means that controllers call views upon interuptions to alter page content (like
196
+ the two methods in previous view, used by previous controller). It also means
197
+ that views are responsible for setting up and tearing down the page, reflecting
198
+ progressive enhancement and graceful degradation :
199
+
200
+ ```coffee
201
+ class App.Views.MyModule extends Darwin.View
202
+ @options {
203
+ selectors:
204
+ submit: 'input[type="submit"]'
205
+ }
206
+
207
+ run: ->
208
+ @get( 'submit' ).hide()
209
+
210
+
211
+ destructor: ->
212
+ @get( 'submit' ).show()
213
+ ```
134
214
 
135
- Furthermore, all event callbacks are wrapped so that they do not
136
- execute if an error occured. In case of error, events are simply
137
- deactivated and any link is followed, reloading the page and letting
138
- server side handle what has to be done, so your user doesn't even
139
- notice something got wrong.
215
+ As you would expect, `run()` is called on dom ready event, and `destructor()`
216
+ is called when a crash occurs.
140
217
 
141
218
  Ready for more ? See [introduction](doc/introduction.md).
142
219
 
@@ -71,5 +71,5 @@ class Darwin.Base
71
71
 
72
72
  trigger: ( event_name, params... ) ->
73
73
  if @_bound[ event_name ]
74
- for own callback in @_bound[ event_name ]
74
+ for callback in @_bound[ event_name ]
75
75
  callback( params... )
@@ -52,9 +52,12 @@ class Darwin.Controller extends Darwin.Base
52
52
  if el == 'root'
53
53
  sel = 'root'
54
54
  else
55
- sel = ( @view.selectors[ el ] or @view._find_alternate_name( el ) ).sel
55
+ sel = ( @view.selectors[ el ] or @view._find_alternate_name( el ) )?.sel
56
56
 
57
- $target = $target.parents( sel ).first() unless $target.is( sel )
57
+ if sel
58
+ $target = $target.parents( sel ).first() unless $target.is( sel )
59
+ else
60
+ $target = @view.get( el )
58
61
 
59
62
  args = [ $target, event ]
60
63
  args.push arguments[i] for i in [1..(arguments.length - 1)] if arguments.length > 1
@@ -6,20 +6,26 @@ errors_got = 0
6
6
  loader = Darwin.Loader =
7
7
  run: ->
8
8
  loader.module_roots().each( ( i, $module ) =>
9
- $module = $( $module )
10
- module_name = loader.compute_name( $module.attr( 'data-module' ) )
11
- path = $module.attr( 'data-module' ).split( '.' )
12
- module = App.Controllers
13
- module = module[ path.shift() ] while path.length
14
-
15
- if module
16
- controllers[ module_name ] = new module( $module )
17
- controllers[ module_name ].id = module_name
18
- else
19
- throw new Error( "Can't find module #{$module.attr( 'data-module' )}" )
9
+ $module = $( $module )
10
+ loader.load_module( $module.attr( 'data-module' ), $module )
20
11
  )
21
12
 
22
13
 
14
+ load_module: ( pathname, $root ) ->
15
+ module_name = loader.compute_name( pathname )
16
+ path = pathname.split( '.' )
17
+ module = App.Controllers
18
+ module = module[ path.shift() ] while path.length
19
+
20
+ if module
21
+ controllers[ module_name ] = new module( $root )
22
+ controllers[ module_name ].id = module_name
23
+ else
24
+ throw new Error( "Can't find module #{pathname}" )
25
+
26
+ controllers[ module_name ]
27
+
28
+
23
29
  module_roots: ->
24
30
  $( '*[data-module]' )
25
31
 
@@ -1,5 +1,5 @@
1
1
  module Darwinjs
2
2
  module Rails
3
- VERSION = "1.1"
3
+ VERSION = "1.2"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: darwinjs-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.1'
5
- prerelease:
4
+ version: '1.2'
6
5
  platform: ruby
7
6
  authors:
8
7
  - Olivier El Mekki
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-08-03 00:00:00.000000000 Z
11
+ date: 2013-11-16 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: railties
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: coffee-rails
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -46,7 +41,6 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: jquery-rails
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ~>
52
46
  - !ruby/object:Gem::Version
@@ -54,7 +48,6 @@ dependencies:
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ~>
60
53
  - !ruby/object:Gem::Version
@@ -62,7 +55,6 @@ dependencies:
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: bundler
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ~>
68
60
  - !ruby/object:Gem::Version
@@ -70,7 +62,6 @@ dependencies:
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ~>
76
67
  - !ruby/object:Gem::Version
@@ -78,17 +69,15 @@ dependencies:
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: rake
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - '>='
84
74
  - !ruby/object:Gem::Version
85
75
  version: '0'
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - '>='
92
81
  - !ruby/object:Gem::Version
93
82
  version: '0'
94
83
  description: Javascript framework with progressive enhancement in mind.
@@ -126,27 +115,26 @@ files:
126
115
  homepage: https://github.com/oelmekki/darwinjs-rails
127
116
  licenses:
128
117
  - MIT
118
+ metadata: {}
129
119
  post_install_message:
130
120
  rdoc_options: []
131
121
  require_paths:
132
122
  - lib
133
123
  required_ruby_version: !ruby/object:Gem::Requirement
134
- none: false
135
124
  requirements:
136
- - - ! '>='
125
+ - - '>='
137
126
  - !ruby/object:Gem::Version
138
127
  version: '0'
139
128
  required_rubygems_version: !ruby/object:Gem::Requirement
140
- none: false
141
129
  requirements:
142
- - - ! '>='
130
+ - - '>='
143
131
  - !ruby/object:Gem::Version
144
132
  version: '0'
145
133
  requirements: []
146
134
  rubyforge_project:
147
- rubygems_version: 1.8.24
135
+ rubygems_version: 2.0.10
148
136
  signing_key:
149
- specification_version: 3
137
+ specification_version: 4
150
138
  summary: Darwin lets create complex javascript interfaces that do not expect they
151
139
  own the application and that degrade gracefully when an error occurs
152
140
  test_files: []