darwinjs-rails 1.1 → 1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []