joosy 1.0.0.RC4 → 1.0.0.RC5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/Gemfile +1 -1
  2. data/Gemfile.lock +99 -82
  3. data/README.md +1 -1
  4. data/app/assets/javascripts/joosy/core/application.js.coffee +2 -2
  5. data/app/assets/javascripts/joosy/core/form.js.coffee +35 -22
  6. data/app/assets/javascripts/joosy/core/helpers/form.js.coffee +38 -9
  7. data/app/assets/javascripts/joosy/core/helpers/view.js.coffee +10 -4
  8. data/app/assets/javascripts/joosy/core/helpers/widgets.js.coffee +6 -1
  9. data/app/assets/javascripts/joosy/core/joosy.js.coffee +5 -3
  10. data/app/assets/javascripts/joosy/core/layout.js.coffee +5 -5
  11. data/app/assets/javascripts/joosy/core/modules/events.js.coffee +28 -10
  12. data/app/assets/javascripts/joosy/core/modules/log.js.coffee +1 -1
  13. data/app/assets/javascripts/joosy/core/modules/module.js.coffee +2 -2
  14. data/app/assets/javascripts/joosy/core/modules/time_manager.js.coffee +1 -1
  15. data/app/assets/javascripts/joosy/core/page.js.coffee +1 -1
  16. data/app/assets/javascripts/joosy/core/resource/collection.js.coffee +18 -18
  17. data/app/assets/javascripts/joosy/core/resource/generic.js.coffee +21 -19
  18. data/app/assets/javascripts/joosy/core/resource/rest.js.coffee +26 -14
  19. data/app/assets/javascripts/joosy/core/resource/rest_collection.js.coffee +2 -2
  20. data/app/assets/javascripts/joosy/core/router.js.coffee +2 -2
  21. data/app/assets/javascripts/joosy/core/widget.js.coffee +3 -0
  22. data/app/assets/javascripts/joosy/preloaders/caching.js.coffee +7 -7
  23. data/app/assets/javascripts/joosy/preloaders/inline.js.coffee +5 -5
  24. data/lib/joosy/rails/version.rb +1 -1
  25. data/lib/rails/generators/joosy/templates/app/helpers/application.js.coffee +2 -2
  26. data/lib/rails/generators/joosy/templates/app/pages/welcome/index.js.coffee +5 -5
  27. data/lib/rails/generators/joosy/templates/app/routes.js.coffee +2 -2
  28. data/lib/rails/generators/joosy/templates/preload.html.slim +19 -0
  29. data/lib/rails/resources_with_joosy.rb +2 -2
  30. data/spec/javascripts/helpers/spec_helper.js.coffee +19 -0
  31. data/spec/javascripts/joosy/core/form_spec.js.coffee +36 -16
  32. data/spec/javascripts/joosy/core/helpers/forms_spec.js.coffee +28 -23
  33. data/spec/javascripts/joosy/core/helpers/widgets_spec.js.coffee +17 -0
  34. data/spec/javascripts/joosy/core/joosy_spec.js.coffee +2 -0
  35. data/spec/javascripts/joosy/core/modules/events_spec.js.coffee +35 -1
  36. data/spec/javascripts/joosy/core/modules/renderer_spec.js.coffee +29 -29
  37. data/spec/javascripts/joosy/core/page_spec.js.coffee +2 -2
  38. data/spec/javascripts/joosy/core/resource/collection_spec.js.coffee +14 -9
  39. data/spec/javascripts/joosy/core/resource/generic_spec.js.coffee +19 -19
  40. data/spec/javascripts/joosy/core/resource/rest_collection_spec.js.coffee +0 -1
  41. data/spec/javascripts/joosy/core/resource/rest_spec.js.coffee +9 -3
  42. data/spec/javascripts/joosy/preloaders/caching_spec.js.coffee +7 -7
  43. data/spec/javascripts/joosy/preloaders/inline_spec.js.coffee +5 -5
  44. data/spec/javascripts/support/sinon-1.3.1.js +6 -6
  45. data/spec/javascripts/support/sinon-ie-1.3.1.js +5 -5
  46. metadata +22 -20
data/Gemfile CHANGED
@@ -5,7 +5,7 @@ gemspec
5
5
 
6
6
  group :development do
7
7
  gem 'jasmine', :git => 'git://github.com/pivotal/jasmine-gem.git'
8
- gem 'guard-sprockets', :git => 'git://github.com/roundlake/guard-sprockets.git'
8
+ gem 'guard-sprockets'
9
9
  gem 'thin'
10
10
  end
11
11
 
data/Gemfile.lock CHANGED
@@ -1,25 +1,17 @@
1
1
  GIT
2
2
  remote: git://github.com/pivotal/jasmine-gem.git
3
- revision: c72e8d248d49a1ebe53f31a09ac511194ad4edf1
3
+ revision: 54b37cf9a51df49a77d15640e3e0caa46a508c1d
4
4
  specs:
5
- jasmine (1.2.0.rc3)
6
- jasmine-core (>= 1.2.0.rc3)
5
+ jasmine (1.2.1)
6
+ jasmine-core (>= 1.2.0)
7
7
  rack (~> 1.0)
8
8
  rspec (>= 1.3.1)
9
9
  selenium-webdriver (>= 0.1.3)
10
10
 
11
- GIT
12
- remote: git://github.com/roundlake/guard-sprockets.git
13
- revision: 77365fbf48b2af0c93a42fcb05747c174b90d8d7
14
- specs:
15
- guard-sprockets (0.3.1)
16
- guard (~> 1.0.0)
17
- sprockets (~> 2.0)
18
-
19
11
  PATH
20
12
  remote: .
21
13
  specs:
22
- joosy (1.0.0.RC3)
14
+ joosy (1.0.0.RC4)
23
15
  coffee-rails
24
16
  haml_coffee_assets
25
17
  i18n-js
@@ -29,133 +21,158 @@ PATH
29
21
  GEM
30
22
  remote: http://rubygems.org/
31
23
  specs:
32
- actionmailer (3.2.3)
33
- actionpack (= 3.2.3)
24
+ actionmailer (3.2.9)
25
+ actionpack (= 3.2.9)
34
26
  mail (~> 2.4.4)
35
- actionpack (3.2.3)
36
- activemodel (= 3.2.3)
37
- activesupport (= 3.2.3)
27
+ actionpack (3.2.9)
28
+ activemodel (= 3.2.9)
29
+ activesupport (= 3.2.9)
38
30
  builder (~> 3.0.0)
39
31
  erubis (~> 2.7.0)
40
- journey (~> 1.0.1)
32
+ journey (~> 1.0.4)
41
33
  rack (~> 1.4.0)
42
34
  rack-cache (~> 1.2)
43
35
  rack-test (~> 0.6.1)
44
- sprockets (~> 2.1.2)
45
- activemodel (3.2.3)
46
- activesupport (= 3.2.3)
36
+ sprockets (~> 2.2.1)
37
+ activemodel (3.2.9)
38
+ activesupport (= 3.2.9)
47
39
  builder (~> 3.0.0)
48
- activerecord (3.2.3)
49
- activemodel (= 3.2.3)
50
- activesupport (= 3.2.3)
40
+ activerecord (3.2.9)
41
+ activemodel (= 3.2.9)
42
+ activesupport (= 3.2.9)
51
43
  arel (~> 3.0.2)
52
44
  tzinfo (~> 0.3.29)
53
- activeresource (3.2.3)
54
- activemodel (= 3.2.3)
55
- activesupport (= 3.2.3)
56
- activesupport (3.2.3)
45
+ activeresource (3.2.9)
46
+ activemodel (= 3.2.9)
47
+ activesupport (= 3.2.9)
48
+ activesupport (3.2.9)
57
49
  i18n (~> 0.6)
58
50
  multi_json (~> 1.0)
59
51
  arel (3.0.2)
60
- builder (3.0.0)
61
- childprocess (0.3.1)
62
- ffi (~> 1.0.6)
52
+ builder (3.0.4)
53
+ childprocess (0.3.6)
54
+ ffi (~> 1.0, >= 1.0.6)
55
+ coderay (1.0.8)
63
56
  coffee-rails (3.2.2)
64
57
  coffee-script (>= 2.2.0)
65
58
  railties (~> 3.2.0)
66
59
  coffee-script (2.2.0)
67
60
  coffee-script-source
68
61
  execjs
69
- coffee-script-source (1.2.0)
70
- daemons (1.1.8)
62
+ coffee-script-source (1.4.0)
63
+ daemons (1.1.9)
71
64
  diff-lcs (1.1.3)
72
65
  erubis (2.7.0)
73
- eventmachine (0.12.10)
74
- eventmachine (0.12.10-java)
75
- execjs (1.3.0)
66
+ eventmachine (1.0.0)
67
+ eventmachine (1.0.0-java)
68
+ execjs (1.4.0)
76
69
  multi_json (~> 1.0)
77
- ffi (1.0.11)
78
- ffi (1.0.11-java)
79
- guard (1.0.1)
80
- ffi (>= 0.5.0)
81
- thor (~> 0.14.6)
82
- guard-coffeescript (0.5.7)
70
+ ffi (1.1.5)
71
+ ffi (1.1.5-java)
72
+ guard (1.5.4)
73
+ listen (>= 0.4.2)
74
+ lumberjack (>= 1.0.2)
75
+ pry (>= 0.9.10)
76
+ thor (>= 0.14.6)
77
+ guard-coffeescript (1.2.1)
83
78
  coffee-script (>= 2.2.0)
84
- guard (>= 0.8.3)
85
- haml_coffee_assets (0.9.3)
86
- execjs (>= 1.2.9)
79
+ guard (>= 1.1.0)
80
+ guard-sprockets (0.4.1)
81
+ guard (>= 1.1.0)
82
+ sprockets (~> 2.0)
83
+ haml_coffee_assets (1.7.2)
84
+ coffee-script (>= 1.0.0)
87
85
  sprockets (>= 2.0.3)
88
86
  tilt (>= 1.3.3)
89
87
  hike (1.2.1)
90
- i18n (0.6.0)
88
+ i18n (0.6.1)
91
89
  i18n-js (2.1.2)
92
90
  i18n
93
- jasmine-core (1.2.0.rc3)
94
- journey (1.0.3)
95
- jquery-rails (2.0.2)
96
- railties (>= 3.2.0, < 5.0)
91
+ jasmine-core (1.2.0)
92
+ journey (1.0.4)
93
+ jquery-rails (2.1.3)
94
+ railties (>= 3.1.0, < 5.0)
97
95
  thor (~> 0.14)
98
- json (1.7.3)
96
+ json (1.7.5)
97
+ json (1.7.5-java)
98
+ libwebsocket (0.1.6)
99
+ websocket
100
+ listen (0.5.3)
101
+ lumberjack (1.0.2)
99
102
  mail (2.4.4)
100
103
  i18n (>= 0.4.0)
101
104
  mime-types (~> 1.16)
102
105
  treetop (~> 1.4.8)
103
- mime-types (1.18)
104
- multi_json (1.2.0)
106
+ method_source (0.8.1)
107
+ mime-types (1.19)
108
+ multi_json (1.3.7)
105
109
  polyglot (0.3.3)
110
+ pry (0.9.10)
111
+ coderay (~> 1.0.5)
112
+ method_source (~> 0.8)
113
+ slop (~> 3.3.1)
114
+ pry (0.9.10-java)
115
+ coderay (~> 1.0.5)
116
+ method_source (~> 0.8)
117
+ slop (~> 3.3.1)
118
+ spoon (~> 0.0)
106
119
  rack (1.4.1)
107
120
  rack-cache (1.2)
108
121
  rack (>= 0.4)
109
122
  rack-ssl (1.3.2)
110
123
  rack
111
- rack-test (0.6.1)
124
+ rack-test (0.6.2)
112
125
  rack (>= 1.0)
113
- rails (3.2.3)
114
- actionmailer (= 3.2.3)
115
- actionpack (= 3.2.3)
116
- activerecord (= 3.2.3)
117
- activeresource (= 3.2.3)
118
- activesupport (= 3.2.3)
126
+ rails (3.2.9)
127
+ actionmailer (= 3.2.9)
128
+ actionpack (= 3.2.9)
129
+ activerecord (= 3.2.9)
130
+ activeresource (= 3.2.9)
131
+ activesupport (= 3.2.9)
119
132
  bundler (~> 1.0)
120
- railties (= 3.2.3)
121
- railties (3.2.3)
122
- actionpack (= 3.2.3)
123
- activesupport (= 3.2.3)
133
+ railties (= 3.2.9)
134
+ railties (3.2.9)
135
+ actionpack (= 3.2.9)
136
+ activesupport (= 3.2.9)
124
137
  rack-ssl (~> 1.3.2)
125
138
  rake (>= 0.8.7)
126
139
  rdoc (~> 3.4)
127
- thor (~> 0.14.6)
128
- rake (0.9.2.2)
140
+ thor (>= 0.14.6, < 2.0)
141
+ rake (10.0.1)
129
142
  rdoc (3.12)
130
143
  json (~> 1.4)
131
- rspec (2.9.0)
132
- rspec-core (~> 2.9.0)
133
- rspec-expectations (~> 2.9.0)
134
- rspec-mocks (~> 2.9.0)
135
- rspec-core (2.9.0)
136
- rspec-expectations (2.9.1)
144
+ rspec (2.12.0)
145
+ rspec-core (~> 2.12.0)
146
+ rspec-expectations (~> 2.12.0)
147
+ rspec-mocks (~> 2.12.0)
148
+ rspec-core (2.12.0)
149
+ rspec-expectations (2.12.0)
137
150
  diff-lcs (~> 1.1.3)
138
- rspec-mocks (2.9.0)
139
- rubyzip (0.9.6.1)
140
- selenium-webdriver (2.20.0)
151
+ rspec-mocks (2.12.0)
152
+ rubyzip (0.9.9)
153
+ selenium-webdriver (2.26.0)
141
154
  childprocess (>= 0.2.5)
142
- ffi (~> 1.0)
155
+ libwebsocket (~> 0.1.3)
143
156
  multi_json (~> 1.0)
144
157
  rubyzip
145
- sprockets (2.1.2)
158
+ slop (3.3.3)
159
+ spoon (0.0.1)
160
+ sprockets (2.2.1)
146
161
  hike (~> 1.2)
162
+ multi_json (~> 1.0)
147
163
  rack (~> 1.0)
148
164
  tilt (~> 1.1, != 1.3.0)
149
- thin (1.3.1)
165
+ thin (1.5.0)
150
166
  daemons (>= 1.0.9)
151
167
  eventmachine (>= 0.12.6)
152
168
  rack (>= 1.0.0)
153
- thor (0.14.6)
169
+ thor (0.16.0)
154
170
  tilt (1.3.3)
155
- treetop (1.4.10)
171
+ treetop (1.4.12)
156
172
  polyglot
157
173
  polyglot (>= 0.3.1)
158
- tzinfo (0.3.33)
174
+ tzinfo (0.3.35)
175
+ websocket (1.0.3)
159
176
 
160
177
  PLATFORMS
161
178
  java
@@ -164,7 +181,7 @@ PLATFORMS
164
181
  DEPENDENCIES
165
182
  guard
166
183
  guard-coffeescript
167
- guard-sprockets!
184
+ guard-sprockets
168
185
  jasmine!
169
186
  joosy!
170
187
  thin
data/README.md CHANGED
@@ -48,7 +48,7 @@ Credits
48
48
  <img src="http://roundlake.ru/assets/logo.png" align="right" />
49
49
 
50
50
  * Boris Staal ([@_inossidabile](http://twitter.com/#!/_inossidabile))
51
- * Andrew Shaydurov
51
+ * Andrew Shaydurov ([@ImGearHead](http://twitter.com/#!/ImGearHead))
52
52
  * Alexander Pavlenko ([@alerticus](http://twitter.com/#!/alerticus))
53
53
  * Peter Zotov ([@whitequark](http://twitter.com/#!/whitequark))
54
54
 
@@ -9,7 +9,7 @@ Joosy.Application =
9
9
  Pages: {}
10
10
  Layouts: {}
11
11
  Controls: {}
12
-
12
+
13
13
  loading: true
14
14
  identity: true
15
15
  debug: false
@@ -51,4 +51,4 @@ Joosy.Application =
51
51
  #
52
52
  setCurrentPage: (page, params) ->
53
53
  #if @page not instanceof page
54
- @page = new page params, @page
54
+ @page = new page params, @page
@@ -8,7 +8,7 @@
8
8
  # AJAXifies form including file uploads and stuff. Built on top of jQuery.Form.
9
9
  #
10
10
  # Joosy.Form automatically cares of form validation highlights. It can
11
- # read common server error responses and add .field_with_errors class to proper
11
+ # read common server error responses and add .field_with_errors class to proper
12
12
  # field.
13
13
  #
14
14
  # If you don't have resource associated with form (#fill), it will try to find fields
@@ -17,7 +17,7 @@
17
17
  # @example Joosy.Form usage
18
18
  # form = new Joosy.Form, -> (response)
19
19
  # console.log "Saved and got some: #{response}"
20
- #
20
+ #
21
21
  # form.progress = (percent) -> console.log "Uploaded by #{percent}%"
22
22
  # form.fill @resource
23
23
  #
@@ -34,7 +34,7 @@ class Joosy.Form extends Joosy.Module
34
34
  # Marks the CSS class to use to mark invalidated fields
35
35
  #
36
36
  invalidationClass: 'field_with_errors'
37
-
37
+
38
38
  #
39
39
  # List of mappings for fields of invalidated data which comes from server
40
40
  #
@@ -84,12 +84,12 @@ class Joosy.Form extends Joosy.Module
84
84
  # by returning false from your own before callback. Both of callbacks will run if
85
85
  # you return true.
86
86
  #
87
- # @option options [Function] success `(Object) -> null` triggers on 200 HTTP code from server.
87
+ # @option options [Function] success `(Object) -> null` triggers on 2xx HTTP code from server.
88
88
  # Pases in the parsed JSON.
89
89
  #
90
90
  # @option options [Function] progress `(Float) -> null` runs periodically while form is uploading
91
91
  #
92
- # @option options [Function] error `(Object) -> Boolean` triggers if server responded with anything but 200.
92
+ # @option options [Function] error `(Object) -> Boolean` triggers if server responded with anything but 2xx.
93
93
  # By default will run form invalidation routine. This behavior can be canceled
94
94
  # by returning false from your own error callback. Both of callbacks will run if
95
95
  # you return true.
@@ -97,6 +97,7 @@ class Joosy.Form extends Joosy.Module
97
97
  # @option options [Joosy.Resource.Generic] resource The resource to fill the form with
98
98
  # @option options [String] resourceName The string to use as a resource name prefix for fields to match invalidation
99
99
  # @option options [String] action Action URL for the form
100
+ # @option options [String] method HTTP method, for example PUT, that will passed in _method param
100
101
  #
101
102
  constructor: (form, options={}) ->
102
103
  if Object.isFunction options
@@ -136,6 +137,13 @@ class Joosy.Form extends Joosy.Module
136
137
  @fill(options.resource, options)
137
138
  delete @resource
138
139
 
140
+ if options.action?
141
+ @container.attr 'action', options.action
142
+ @container.attr 'method', 'POST'
143
+
144
+ if options.method?
145
+ @__markMethod options.method
146
+
139
147
  #
140
148
  # Resets form submit behavior to default
141
149
  #
@@ -170,14 +178,16 @@ class Joosy.Form extends Joosy.Module
170
178
  key = @concatFieldName scope, property
171
179
  input = @fields.filter("[name='#{key}']:not(:file),[name='#{key.underscore()}']:not(:file),[name='#{key.camelize(false)}']:not(:file)")
172
180
  if input.length > 0
173
- unless input.is ':checkbox'
174
- input.val val
175
- else
181
+ if input.is ':checkbox'
176
182
  if val
177
183
  input.attr 'checked', 'checked'
178
184
  else
179
185
  input.removeAttr 'checked'
180
- if Object.isObject val
186
+ else if input.is ':radio'
187
+ input.filter("[value='#{val}']").attr 'checked', 'checked'
188
+ else
189
+ input.val val
190
+ if Object.isObject(val) || Object.isArray(val)
181
191
  filler val, key
182
192
  else if val instanceof Joosy.Resource.REST
183
193
  filler val.data, @concatFieldName(scope, "[#{property}_attributes][0]")
@@ -186,7 +196,7 @@ class Joosy.Form extends Joosy.Module
186
196
  filler entity.data, @concatFieldName(scope, "[#{property}_attributes][#{i}]")
187
197
  delete data.__joosy_form_filler_lock
188
198
 
189
- filler data, resource.__entityName
199
+ filler data, resource.__entityName || options.resourceName
190
200
 
191
201
  @__markMethod(options?.method || 'PUT') if resource.id()
192
202
 
@@ -200,7 +210,7 @@ class Joosy.Form extends Joosy.Module
200
210
  #
201
211
  submit: ->
202
212
  @container.submit()
203
-
213
+
204
214
  #
205
215
  # Serializes form into query string.
206
216
  #
@@ -211,7 +221,7 @@ class Joosy.Form extends Joosy.Module
211
221
  serialize: (skipMethod=true) ->
212
222
  data = @container.serialize()
213
223
  data = data.replace /\&?\_method\=put/i, '' if skipMethod
214
-
224
+
215
225
  data
216
226
 
217
227
  #
@@ -220,7 +230,7 @@ class Joosy.Form extends Joosy.Module
220
230
  __success: (response, status, xhr) ->
221
231
  if xhr
222
232
  @success? response
223
- else if response.status == 200
233
+ else if 200 <= response.status < 300
224
234
  @success response.json
225
235
  else
226
236
  @__error response.json
@@ -248,7 +258,7 @@ class Joosy.Form extends Joosy.Module
248
258
 
249
259
  if !@error? || @error(errors) is true
250
260
  errors = @__stringifyErrors(errors)
251
-
261
+
252
262
  Object.each errors, (field, notifications) =>
253
263
  input = @findField(field).addClass @invalidationClass
254
264
  @notification? input, notifications
@@ -256,7 +266,7 @@ class Joosy.Form extends Joosy.Module
256
266
  return errors
257
267
 
258
268
  return false
259
-
269
+
260
270
  #
261
271
  # Finds field by field name.
262
272
  # This is not inlined since we want to override
@@ -280,7 +290,7 @@ class Joosy.Form extends Joosy.Module
280
290
  value: method
281
291
  )
282
292
  @container.append method
283
-
293
+
284
294
  #
285
295
  # Prepares server response for default error handler
286
296
  # Turns all possible response notations into form notation (foo[bar])
@@ -297,17 +307,17 @@ class Joosy.Form extends Joosy.Module
297
307
  #
298
308
  # @param [Object] errors Data to prepare
299
309
  #
300
- # @return [Hash<String, Array>] Flat hash with field names in keys and arrays
310
+ # @return [Hash<String, Array>] Flat hash with field names in keys and arrays
301
311
  # of errors in values
302
312
  #
303
313
  __stringifyErrors: (errors) ->
304
314
  result = {}
305
-
315
+
306
316
  Object.each errors, (field, notifications) =>
307
317
  if @substitutions[field]?
308
318
  field = @substitutions[field]
309
319
 
310
- if Object.isObject notifications
320
+ if Object.isObject(notifications) || @isArrayOfObjects(notifications)
311
321
  Object.each @__foldInlineEntities(notifications), (key, value) ->
312
322
  result[field+key] = value
313
323
  else
@@ -318,7 +328,7 @@ class Joosy.Form extends Joosy.Module
318
328
  name = @resourceName || @__resource.__entityName
319
329
  field = name + "[#{field}]"
320
330
  field += "[#{f}]" for f in splited
321
-
331
+
322
332
  else if @resourceName || @__resource
323
333
  name = @resourceName || @__resource.__entityName
324
334
  field = name + "[#{field}]"
@@ -333,7 +343,7 @@ class Joosy.Form extends Joosy.Module
333
343
  # @example Basic flattening
334
344
  # data = foo: { bar: { baz: [] } }
335
345
  # inner = @__foldInlineEntities(data.foo, 'foo')
336
- #
346
+ #
337
347
  # inner # { "foo[bar][baz]": [] }
338
348
  #
339
349
  # @param [Object] hash Structure to fold
@@ -344,7 +354,7 @@ class Joosy.Form extends Joosy.Module
344
354
  #
345
355
  __foldInlineEntities: (hash, scope="", result={}) ->
346
356
  Object.each hash, (key, value) =>
347
- if Object.isObject(value)
357
+ if Object.isObject(value) || @isArrayOfObjects(value)
348
358
  @__foldInlineEntities(value, "#{scope}[#{key}]", result)
349
359
  else
350
360
  result["#{scope}[#{key}]"] = value
@@ -365,3 +375,6 @@ class Joosy.Form extends Joosy.Module
365
375
  items.splice 0, 1, first[0], first[1]
366
376
  items[items.length - 1] = items[items.length - 1].split(']')[0]
367
377
  items
378
+
379
+ isArrayOfObjects: (array) ->
380
+ Object.isArray(array) && array.every((elem) -> Object.isObject(elem))
@@ -5,17 +5,18 @@
5
5
  #
6
6
  Joosy.helpers 'Application', ->
7
7
 
8
- description = (resource, method, extendIds) ->
9
- if resource instanceof Joosy.Resource.Generic
8
+ description = (resource, method, extendIds, idSuffix) ->
9
+ if Joosy.Module.hasAncestor resource.constructor, Joosy.Resource.Generic
10
10
  id = resource.id()
11
11
  resource = resource.__entityName
12
12
 
13
13
  name: resource + "#{if method.match(/^\[.*\]$/) then method else "[#{method}]"}"
14
- id: resource + (if id && extendIds then '_'+id else '') + "_#{method.parameterize().underscore()}"
14
+ id: resource + (if id && extendIds then '_'+id else '') + "_#{method.parameterize().underscore()}" + (if idSuffix then '_'+idSuffix else '')
15
15
 
16
16
  input = (type, resource, method, options={}) =>
17
- d = description(resource, method, options.extendIds)
17
+ d = description(resource, method, options.extendIds, options.idSuffix)
18
18
  delete options.extendIds
19
+ delete options.idSuffix
19
20
  @tag 'input', Joosy.Module.merge {type: type, name: d.name, id: d.id}, options
20
21
 
21
22
  #
@@ -23,11 +24,18 @@ Joosy.helpers 'Application', ->
23
24
  #
24
25
  class Form
25
26
  constructor: (@context, @resource, @options) ->
26
- label: (method, options={}, content='') -> @context.label(@resource, method, Joosy.Module.merge(extendIds: @options.extendIds, options), content)
27
+
28
+ label: (method, options={}, content='') ->
29
+ if !Object.isObject(options)
30
+ content = options
31
+ options = {}
32
+
33
+ @context.label(@resource, method, Joosy.Module.merge(extendIds: @options.extendIds, options), content)
34
+
27
35
  radioButton: (method, tagValue, options={}) -> @context.radioButton(@resource, method, tagValue, Joosy.Module.merge(extendIds: @options.extendIds, options))
28
36
  textArea: (method, options={}) -> @context.textArea(@resource, method, Joosy.Module.merge(extendIds: @options.extendIds, options))
29
- checkBox: (method, options={}, checkedValue=1, uncheckedValue=0) ->
30
- @context.checkBox(@resource, method, Joosy.Module.merge(extendIds: @options.extendIds, options), checkedValue, uncheckedValue)
37
+ checkBox: (method, options={}, checkedValue=1, uncheckedValue=0) -> @context.checkBox(@resource, method, Joosy.Module.merge(extendIds: @options.extendIds, options), checkedValue, uncheckedValue)
38
+ select: (method, options={}, htmlOptions={}) -> @context.select @resource, method, options, Joosy.Module.merge(extendIds: @options.extendIds, htmlOptions)
31
39
 
32
40
  ['text', 'file', 'hidden', 'password'].each (type) =>
33
41
  Form.prototype[type+'Field'] = (method, options={}) ->
@@ -58,7 +66,7 @@ Joosy.helpers 'Application', ->
58
66
  ['text', 'file', 'hidden', 'password'].each (type) =>
59
67
  @[type+'Field'] = (resource, method, options={}) -> input type, resource, method, options
60
68
 
61
- @radioButton = (resource, method, tagValue, options={}) -> input 'radio', resource, method, Joosy.Module.merge(value: tagValue, options)
69
+ @radioButton = (resource, method, tagValue, options={}) -> input 'radio', resource, method, Joosy.Module.merge(value: tagValue, idSuffix: tagValue, options)
62
70
 
63
71
  @checkBox = (resource, method, options={}, checkedValue=1, uncheckedValue=0) ->
64
72
  spy = @tag 'input', Joosy.Module.merge(name: description(resource, method).name, value: uncheckedValue, type: 'hidden')
@@ -66,10 +74,31 @@ Joosy.helpers 'Application', ->
66
74
 
67
75
  spy+box
68
76
 
77
+ @select = (resource, method, options, htmlOptions) ->
78
+ if Object.isObject options
79
+ opts = []
80
+ for key, val of options
81
+ opts.push [val, key]
82
+ else
83
+ opts = options
84
+ if htmlOptions.includeBlank
85
+ delete htmlOptions.includeBlank
86
+ opts.unshift ['', '']
87
+ opts = opts.reduce (str, vals) =>
88
+ params = if Object.isArray vals then ['option', { value: vals[1] }, vals[0]] else ['option', {}, vals]
89
+ if htmlOptions.value == (if Object.isArray(vals) then vals[1] else vals)
90
+ params[1].selected = 'selected'
91
+ str += @.tag.apply @, params
92
+ , ''
93
+ extendIds = htmlOptions.extendIds
94
+ delete htmlOptions.value
95
+ delete htmlOptions.extendIds
96
+ @tag 'select', Joosy.Module.merge(description(resource, method, extendIds), htmlOptions), opts
97
+
69
98
  @textArea = (resource, method, options={}) ->
70
99
  value = options.value
71
100
  extendIds = options.extendIds
72
101
  delete options.value
73
102
  delete options.extendIds
74
103
 
75
- @tag 'textarea', Joosy.Module.merge(description(resource, method, extendIds), options), value
104
+ @tag 'textarea', Joosy.Module.merge(description(resource, method, extendIds), options), value
@@ -4,7 +4,7 @@
4
4
  # Rendering and string representation helpers
5
5
  #
6
6
  Joosy.helpers 'Application', ->
7
-
7
+
8
8
  @tag = (name, options={}, content='') ->
9
9
  content = content() if Object.isFunction(content)
10
10
 
@@ -12,7 +12,13 @@ Joosy.helpers 'Application', ->
12
12
  temp = document.createElement 'div'
13
13
 
14
14
  Object.each options, (name, value) -> element.setAttribute name, value
15
- element.innerHTML = content
15
+
16
+ try
17
+ element.innerHTML = content
18
+ catch e
19
+ # setting innerHTML fails in the IE for elements, which cann't have children (INPUT, for ex.)
20
+ # suppress this error unless content looks valuable
21
+ throw e if content
16
22
 
17
23
  temp.appendChild element
18
24
  temp.innerHTML
@@ -28,7 +34,7 @@ Joosy.helpers 'Application', ->
28
34
  #
29
35
  # Wraps the inline block into given template
30
36
  # Request template will receive the inline block as @yield parameter
31
- #
37
+ #
32
38
  # Example
33
39
  # -# foo/baz template
34
40
  # != @renderWrapped 'foo/bar', ->
@@ -39,4 +45,4 @@ Joosy.helpers 'Application', ->
39
45
  # != @yield
40
46
  #
41
47
  @renderWrapped = (template, lambda) ->
42
- @render template, Joosy.Module.merge(this, yield: lambda())
48
+ @render template, Joosy.Module.merge(this, yield: lambda())
@@ -7,7 +7,12 @@ Joosy.helpers 'Application', ->
7
7
 
8
8
  @widget = (element, widget) ->
9
9
  uuid = Joosy.uuid()
10
- element = @tag element, id: uuid
10
+ params = id: uuid
11
+ parts = element.split '.'
12
+ if parts[1]
13
+ params.class = parts.from(1).join ' '
14
+
15
+ element = @tag parts[0], params
11
16
 
12
17
  @onRefresh -> @registerWidget '#'+uuid, widget
13
18
 
@@ -8,12 +8,12 @@
8
8
  # Core modules container
9
9
  #
10
10
  Modules: {}
11
-
11
+
12
12
  #
13
13
  # Resources container
14
14
  #
15
15
  Resource: {}
16
-
16
+
17
17
  #
18
18
  # Templaters container
19
19
  #
@@ -25,7 +25,7 @@
25
25
  # @example Basic usage
26
26
  # Joosy.namespace 'foobar', ->
27
27
  # class @RealThing
28
- #
28
+ #
29
29
  # foo = new foobar.RealThing
30
30
  #
31
31
  # @param [String] name Namespace keyword
@@ -173,6 +173,8 @@
173
173
  space[className] = class extends Joosy.Resource.REST
174
174
  @entity resource
175
175
  @source path
176
+ __collection: ->
177
+ space[collectionName]
176
178
  unless space[collectionName]
177
179
  Joosy.Modules.Log.debugAs space, "Define #{collectionName}"
178
180
  space[collectionName] = class extends Joosy.Resource.RESTCollection