joosy 1.2.0.alpha.73 → 1.2.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gruntfile.coffee +56 -18
- data/bower.json +1 -1
- data/build/joosy/form.js +1 -0
- data/build/joosy/resources.js +1 -0
- data/build/joosy.js +2 -2774
- data/package.json +5 -4
- data/source/joosy/application.coffee +9 -7
- data/source/joosy/{extensions/resources-form/form.coffee → form.coffee} +58 -51
- data/source/joosy/helpers/form.coffee +241 -0
- data/source/joosy/helpers/index.coffee +3 -0
- data/source/joosy/helpers/routes.coffee +3 -1
- data/source/joosy/helpers/view.coffee +9 -9
- data/source/joosy/joosy.coffee +3 -5
- data/source/joosy/module.coffee +9 -4
- data/source/joosy/modules/dom.coffee +33 -31
- data/source/joosy/modules/events.coffee +24 -20
- data/source/joosy/modules/filters.coffee +38 -35
- data/source/joosy/modules/page/title.coffee +3 -3
- data/source/joosy/modules/renderer.coffee +23 -18
- data/source/joosy/modules/resources/identity_map.coffee +45 -0
- data/source/joosy/modules/resources/model.coffee +146 -0
- data/source/joosy/modules/widgets_manager.coffee +8 -8
- data/source/joosy/resources/array.coffee +0 -5
- data/source/joosy/resources/hash.coffee +8 -13
- data/source/joosy/resources/index.coffee +2 -0
- data/source/joosy/{extensions/resources → resources}/rest.coffee +48 -19
- data/source/joosy/resources/scalar.coffee +8 -10
- data/source/joosy/router.coffee +13 -12
- data/source/joosy/templaters/jst.coffee +3 -2
- data/source/joosy/widget.coffee +17 -15
- data/source/joosy.coffee +2 -0
- data/source/vendor/es5-shim.js +1316 -0
- data/source/vendor/inflections.js +598 -0
- data/source/vendor/metamorph.js +457 -0
- data/spec/helpers/matchers.coffee +4 -4
- data/spec/joosy/core/application_spec.coffee +1 -1
- data/spec/joosy/core/helpers/view_spec.coffee +2 -2
- data/spec/joosy/core/joosy_spec.coffee +8 -4
- data/spec/joosy/core/modules/dom_spec.coffee +7 -7
- data/spec/joosy/core/modules/events_spec.coffee +2 -2
- data/spec/joosy/core/modules/filters_spec.coffee +7 -8
- data/spec/joosy/core/modules/module_spec.coffee +5 -5
- data/spec/joosy/core/router_spec.coffee +3 -3
- data/spec/joosy/core/widget_spec.coffee +6 -6
- data/spec/joosy/environments/amd_spec.coffee +4 -2
- data/spec/joosy/environments/global_spec.coffee +1 -1
- data/spec/joosy/{extensions/form → form}/form_spec.coffee +9 -16
- data/spec/joosy/{extensions/form → form}/helpers/forms_spec.coffee +5 -5
- data/spec/joosy/{core/resources → resources}/array_spec.coffee +2 -2
- data/spec/joosy/{core/resources → resources}/hash_spec.coffee +0 -8
- data/spec/joosy/{core/modules/resources → resources/modules}/cacher_spec.coffee +0 -0
- data/spec/joosy/resources/modules/identity_map_spec.coffee +47 -0
- data/spec/joosy/{extensions/resources/base_spec.coffee → resources/modules/model_spec.coffee} +28 -48
- data/spec/joosy/{extensions/resources → resources}/rest_spec.coffee +29 -22
- data/spec/joosy/{core/resources → resources}/scalar_spec.coffee +8 -8
- data/templates/application/application.coffee.tt +0 -2
- data/templates/environment/app/haml/index.haml +2 -2
- data/templates/environment/package.json +1 -1
- metadata +23 -19
- data/build/joosy/extensions/resources-form.js +0 -590
- data/build/joosy/extensions/resources.js +0 -561
- data/source/joosy/extensions/resources/base.coffee +0 -282
- data/source/joosy/extensions/resources/index.coffee +0 -1
- data/source/joosy/extensions/resources-form/helpers/form.coffee +0 -104
- data/source/joosy/extensions/resources-form/index.coffee +0 -1
- data/source/metamorph.coffee +0 -410
@@ -1,5 +1,3 @@
|
|
1
|
-
#= require joosy/modules/resources/cacher
|
2
|
-
|
3
1
|
class Joosy.Resources.Hash extends Joosy.Function
|
4
2
|
|
5
3
|
@include Joosy.Modules.Events
|
@@ -11,7 +9,11 @@ class Joosy.Resources.Hash extends Joosy.Function
|
|
11
9
|
return super ->
|
12
10
|
@__fillData data, false
|
13
11
|
|
14
|
-
|
12
|
+
load: (data) ->
|
13
|
+
@__fillData data
|
14
|
+
@
|
15
|
+
|
16
|
+
__get: (path) ->
|
15
17
|
[instance, property] = @__callTarget path, true
|
16
18
|
|
17
19
|
return undefined unless instance
|
@@ -21,7 +23,7 @@ class Joosy.Resources.Hash extends Joosy.Function
|
|
21
23
|
else
|
22
24
|
instance[property]
|
23
25
|
|
24
|
-
|
26
|
+
__set: (path, value) ->
|
25
27
|
[instance, property] = @__callTarget path
|
26
28
|
|
27
29
|
if instance instanceof Joosy.Resources.Hash
|
@@ -32,18 +34,11 @@ class Joosy.Resources.Hash extends Joosy.Function
|
|
32
34
|
@trigger 'changed'
|
33
35
|
value
|
34
36
|
|
35
|
-
load: (data) ->
|
36
|
-
@__fillData data
|
37
|
-
@
|
38
|
-
|
39
|
-
clone: (callback) ->
|
40
|
-
new @constructor Object.clone(@data, true)
|
41
|
-
|
42
37
|
__call: (path, value) ->
|
43
38
|
if arguments.length > 1
|
44
|
-
@
|
39
|
+
@__set path, value
|
45
40
|
else
|
46
|
-
@
|
41
|
+
@__get path
|
47
42
|
|
48
43
|
#
|
49
44
|
# Locates the actual instance of attribute path `foo.bar` from get/set
|
@@ -1,9 +1,22 @@
|
|
1
|
-
#= require ./
|
1
|
+
#= require ./hash
|
2
|
+
#= require joosy/modules/resources/model
|
2
3
|
|
3
4
|
#
|
4
5
|
# Resource with REST/JSON backend
|
5
6
|
#
|
6
|
-
class Joosy.Resources.REST extends Joosy.Resources.
|
7
|
+
class Joosy.Resources.REST extends Joosy.Resources.Hash
|
8
|
+
|
9
|
+
@include Joosy.Modules.Resources.Model
|
10
|
+
|
11
|
+
@registerPlainFilters 'beforeSave'
|
12
|
+
|
13
|
+
@beforeLoad (data) ->
|
14
|
+
if data.constructor == Object && Object.keys(data).length == 1 && @__entityName
|
15
|
+
name = inflection.camelize(@__entityName, true)
|
16
|
+
data = data[name] if data[name]
|
17
|
+
|
18
|
+
data
|
19
|
+
|
7
20
|
|
8
21
|
@requestOptions: (options) ->
|
9
22
|
@::__requestOptions = options
|
@@ -23,7 +36,7 @@ class Joosy.Resources.REST extends Joosy.Resources.Base
|
|
23
36
|
# Makes needed changes with clone/wrapper for @at method to extend its' path
|
24
37
|
#
|
25
38
|
@__atWrapper: (definer, args...) ->
|
26
|
-
if args.length == 1 &&
|
39
|
+
if args.length == 1 && args[0] instanceof Array
|
27
40
|
@__atWrapper(definer, args[0]...)
|
28
41
|
else
|
29
42
|
definer (clone) =>
|
@@ -33,7 +46,7 @@ class Joosy.Resources.REST extends Joosy.Resources.Base
|
|
33
46
|
else
|
34
47
|
arg.replace(/^\/?/, '/')
|
35
48
|
, ''
|
36
|
-
clone.__source += '/' +
|
49
|
+
clone.__source += '/' + inflection.pluralize(@::__entityName)
|
37
50
|
|
38
51
|
#
|
39
52
|
# Creates the proxy of current resource binded as a child of given entity
|
@@ -45,11 +58,11 @@ class Joosy.Resources.REST extends Joosy.Resources.Base
|
|
45
58
|
#
|
46
59
|
# @note accepts both array notation (Comment.at(['admin', @blog, @post])) and args notation (Comment.at('admin', @blog, @post))
|
47
60
|
#
|
48
|
-
@at:
|
61
|
+
@at: ->
|
49
62
|
@__atWrapper (callback) =>
|
50
63
|
class Clone extends @
|
51
64
|
callback(@)
|
52
|
-
,
|
65
|
+
, arguments...
|
53
66
|
|
54
67
|
|
55
68
|
#
|
@@ -69,7 +82,7 @@ class Joosy.Resources.REST extends Joosy.Resources.Base
|
|
69
82
|
# Interpolates path with masks by given array of params
|
70
83
|
#
|
71
84
|
__interpolatePath: (source, ids) ->
|
72
|
-
ids = [ids] unless
|
85
|
+
ids = [ids] unless ids instanceof Array
|
73
86
|
ids.reduce (path, id) ->
|
74
87
|
id = id.id() if id instanceof Joosy.Resources.REST
|
75
88
|
path.replace /:[^\/]+/, id
|
@@ -98,7 +111,8 @@ class Joosy.Resources.REST extends Joosy.Resources.Base
|
|
98
111
|
# Resource.collectionPath(['admin', Resource.build 1]) # /admin/resources/1/resources
|
99
112
|
#
|
100
113
|
collectionPath: (ids=[], options={}) ->
|
101
|
-
|
114
|
+
# (options) ->
|
115
|
+
if ids.constructor == Object
|
102
116
|
options = ids
|
103
117
|
ids = []
|
104
118
|
|
@@ -111,7 +125,7 @@ class Joosy.Resources.REST extends Joosy.Resources.Base
|
|
111
125
|
else
|
112
126
|
path = '/'
|
113
127
|
path += @constructor.__namespace__.map(String::underscore).join('/') + '/' if @constructor.__namespace__.length > 0
|
114
|
-
path +=
|
128
|
+
path += inflection.pluralize(@__entityName)
|
115
129
|
|
116
130
|
path += "/#{options.action}" if options.action
|
117
131
|
path
|
@@ -140,19 +154,19 @@ class Joosy.Resources.REST extends Joosy.Resources.Base
|
|
140
154
|
# Resource.memberPath(['admin', Resource.build 1]) # /admin/resources/1/resources/2
|
141
155
|
#
|
142
156
|
memberPath: (ids=[], options={}) ->
|
143
|
-
if Object
|
157
|
+
if ids.constructor == Object
|
144
158
|
options = ids
|
145
159
|
ids = []
|
146
160
|
|
147
161
|
return options.url if options.url
|
148
162
|
|
149
|
-
ids = [ids] unless
|
163
|
+
ids = [ids] unless ids instanceof Array
|
150
164
|
id = @id() || ids.pop()
|
151
165
|
|
152
166
|
action = options.action
|
153
167
|
|
154
168
|
ids.push @id()
|
155
|
-
path = @collectionPath(ids,
|
169
|
+
path = @collectionPath(ids, Joosy.Module.merge(options, action: undefined)) + "/#{id}"
|
156
170
|
path += "/#{action}" if action?
|
157
171
|
path
|
158
172
|
|
@@ -281,12 +295,13 @@ class Joosy.Resources.REST extends Joosy.Resources.Base
|
|
281
295
|
@find: (where, options={}, callback=false) ->
|
282
296
|
[options, callback] = @::__extractOptionsAndCallback(options, callback)
|
283
297
|
|
284
|
-
|
298
|
+
result = {}
|
299
|
+
result[@::__primaryKey] = if where instanceof Array
|
285
300
|
where[where.length-1]
|
286
301
|
else
|
287
302
|
where
|
288
303
|
|
289
|
-
result = @build
|
304
|
+
result = @build result
|
290
305
|
|
291
306
|
# Substitute interpolation mask with actual path
|
292
307
|
if where instanceof Array && where.length > 1
|
@@ -312,17 +327,17 @@ class Joosy.Resources.REST extends Joosy.Resources.Base
|
|
312
327
|
# @option options [Hash] params Passes the given params to the query
|
313
328
|
#
|
314
329
|
@all: (where, options={}, callback=false) ->
|
315
|
-
if
|
330
|
+
if typeof(where) == 'function' || where.constructor == Object
|
316
331
|
[options, callback] = @::__extractOptionsAndCallback(where, options)
|
317
332
|
where = []
|
318
333
|
else
|
319
334
|
[options, callback] = @::__extractOptionsAndCallback(options, callback)
|
320
335
|
|
321
|
-
result = new
|
336
|
+
result = new @::__collection
|
322
337
|
|
323
338
|
@__query @collectionPath(where, options), 'GET', options.params, (error, rawData, xhr) =>
|
324
339
|
if (data = rawData)?
|
325
|
-
if
|
340
|
+
if data.constructor == Object && !(data = data[inflection.pluralize(@::__entityName)])
|
326
341
|
throw new Error "Invalid data for `all` received: #{JSON.stringify(data)}"
|
327
342
|
|
328
343
|
data = data.map (x) =>
|
@@ -337,6 +352,16 @@ class Joosy.Resources.REST extends Joosy.Resources.Base
|
|
337
352
|
|
338
353
|
result
|
339
354
|
|
355
|
+
save: (callback) ->
|
356
|
+
if @id()
|
357
|
+
@put {params: @__applyBeforeSaves(@data)}, (error, data) =>
|
358
|
+
@load data unless error
|
359
|
+
callback? error, @
|
360
|
+
else
|
361
|
+
@constructor.post {params: @__applyBeforeSaves(@data)}, (error, data) =>
|
362
|
+
@load data unless error
|
363
|
+
callback? error, @
|
364
|
+
|
340
365
|
#
|
341
366
|
# Wrapper for AJAX request
|
342
367
|
#
|
@@ -348,7 +373,7 @@ class Joosy.Resources.REST extends Joosy.Resources.Base
|
|
348
373
|
cache: false
|
349
374
|
dataType: 'json'
|
350
375
|
|
351
|
-
if
|
376
|
+
if typeof(callback) == 'function'
|
352
377
|
options.success = (data, _, xhr) -> callback(false, data, xhr)
|
353
378
|
options.error = (xhr) -> callback(xhr)
|
354
379
|
else
|
@@ -365,7 +390,11 @@ class Joosy.Resources.REST extends Joosy.Resources.Base
|
|
365
390
|
# utility function for better API support for unrequired first options parameter
|
366
391
|
#
|
367
392
|
__extractOptionsAndCallback: (options, callback) ->
|
368
|
-
if
|
393
|
+
if typeof(options) == 'function'
|
369
394
|
callback = options
|
370
395
|
options = {}
|
371
396
|
[options, callback]
|
397
|
+
|
398
|
+
# AMD wrapper
|
399
|
+
if define?.amd?
|
400
|
+
define 'joosy/resources/rest', -> Joosy.Resources.REST
|
@@ -1,5 +1,3 @@
|
|
1
|
-
#= require joosy/modules/resources/cacher
|
2
|
-
|
3
1
|
class Joosy.Resources.Scalar extends Joosy.Function
|
4
2
|
|
5
3
|
@include Joosy.Modules.Events
|
@@ -11,12 +9,6 @@ class Joosy.Resources.Scalar extends Joosy.Function
|
|
11
9
|
return super ->
|
12
10
|
@load value
|
13
11
|
|
14
|
-
get: ->
|
15
|
-
@value
|
16
|
-
|
17
|
-
set: (@value) ->
|
18
|
-
@trigger 'changed'
|
19
|
-
|
20
12
|
load: (value) ->
|
21
13
|
@value = @__applyBeforeLoads(value)
|
22
14
|
@trigger 'changed'
|
@@ -27,9 +19,15 @@ class Joosy.Resources.Scalar extends Joosy.Function
|
|
27
19
|
|
28
20
|
__call: ->
|
29
21
|
if arguments.length > 0
|
30
|
-
@
|
22
|
+
@__set arguments[0]
|
31
23
|
else
|
32
|
-
@
|
24
|
+
@__get()
|
25
|
+
|
26
|
+
__get: ->
|
27
|
+
@value
|
28
|
+
|
29
|
+
__set: (@value) ->
|
30
|
+
@trigger 'changed'
|
33
31
|
|
34
32
|
valueOf: ->
|
35
33
|
@value.valueOf()
|
data/source/joosy/router.coffee
CHANGED
@@ -93,7 +93,8 @@ class Joosy.Router extends Joosy.Module
|
|
93
93
|
# @option [Hash] options "as", prefixes all other "as" commands
|
94
94
|
# @param [Function] block callback for child commands
|
95
95
|
namespace: (name, options={}, block) ->
|
96
|
-
|
96
|
+
# (name, block) ->
|
97
|
+
if arguments.length == 2
|
97
98
|
block = options
|
98
99
|
options = {}
|
99
100
|
|
@@ -106,9 +107,9 @@ class Joosy.Router extends Joosy.Module
|
|
106
107
|
# @param [Object] routes Set of routes in inner format (see class description)
|
107
108
|
#
|
108
109
|
@map: (routes, namespace) ->
|
109
|
-
|
110
|
+
for path, to of routes
|
110
111
|
path = namespace + '/' + path if namespace?
|
111
|
-
if
|
112
|
+
if typeof(to) == 'function' || to.prototype
|
112
113
|
@compileRoute path, to
|
113
114
|
else
|
114
115
|
@map to, path
|
@@ -118,7 +119,7 @@ class Joosy.Router extends Joosy.Module
|
|
118
119
|
#
|
119
120
|
# @param [Function] block callback for child commands
|
120
121
|
#
|
121
|
-
@draw: (block)->
|
122
|
+
@draw: (block) ->
|
122
123
|
Drawer.run block
|
123
124
|
|
124
125
|
#
|
@@ -276,8 +277,9 @@ class Joosy.Router extends Joosy.Module
|
|
276
277
|
helper = (options) ->
|
277
278
|
result = path
|
278
279
|
|
279
|
-
path.match(/\/:[^\/]+/g)
|
280
|
-
|
280
|
+
if match = path.match(/\/:[^\/]+/g)
|
281
|
+
for param in match
|
282
|
+
result = result.replace(param.substr(1), options[param.substr(2)])
|
281
283
|
|
282
284
|
if Joosy.Router.config.html5
|
283
285
|
"#{Joosy.Router.config.prefix}#{result}"
|
@@ -299,14 +301,13 @@ class Joosy.Router extends Joosy.Module
|
|
299
301
|
# Collect parameters from route placeholers
|
300
302
|
match.shift() # First entry is full route regexp match that should be just skipped
|
301
303
|
|
302
|
-
route?.capture
|
303
|
-
params[key] = decodeURIComponent match.shift()
|
304
|
+
if captures = route?.capture
|
305
|
+
params[key] = decodeURIComponent match.shift() for key in captures
|
304
306
|
|
305
307
|
# Collect parameters from URL query section
|
306
|
-
query
|
307
|
-
|
308
|
-
|
309
|
-
params[key] = value
|
308
|
+
for entry in query when entry.length > 0
|
309
|
+
[key, value] = entry.split '='
|
310
|
+
params[key] = value
|
310
311
|
|
311
312
|
params
|
312
313
|
|
@@ -39,10 +39,11 @@ class Joosy.Templaters.JST
|
|
39
39
|
# @param [String] entity Entity to lookup template path by its namespace
|
40
40
|
#
|
41
41
|
resolveTemplate: (section, template, entity) ->
|
42
|
-
if template
|
42
|
+
if template[0] == '/'
|
43
43
|
return template.substr 1
|
44
44
|
|
45
|
-
path = entity.constructor?.__namespace__?.map(
|
45
|
+
path = entity.constructor?.__namespace__?.map (x) -> inflection.underscore(x)
|
46
|
+
path ||= []
|
46
47
|
path.unshift section
|
47
48
|
|
48
49
|
"#{path.join '/'}/#{template}"
|
data/source/joosy/widget.coffee
CHANGED
@@ -130,8 +130,8 @@ class Joosy.Widget extends Joosy.Module
|
|
130
130
|
#
|
131
131
|
@mapWidgets: (map) ->
|
132
132
|
unless @::hasOwnProperty "__widgets"
|
133
|
-
@::__widgets =
|
134
|
-
|
133
|
+
@::__widgets = Joosy.Module.merge {}, @.__super__.__widgets
|
134
|
+
Joosy.Module.merge @::__widgets, map
|
135
135
|
|
136
136
|
#
|
137
137
|
# Declares widget as indepent changing the way it behaves during the bootstrap
|
@@ -156,7 +156,7 @@ class Joosy.Widget extends Joosy.Module
|
|
156
156
|
# @param [Joosy.Widget] widget Class or object of Joosy.Widget to register
|
157
157
|
#
|
158
158
|
registerWidget: ($container, widget) ->
|
159
|
-
if
|
159
|
+
if typeof($container) == 'string'
|
160
160
|
$container = @__normalizeSelector($container)
|
161
161
|
|
162
162
|
widget = @__normalizeWidget(widget)
|
@@ -251,12 +251,13 @@ class Joosy.Widget extends Joosy.Module
|
|
251
251
|
@data = {}
|
252
252
|
|
253
253
|
@synchronize (context) =>
|
254
|
-
|
255
|
-
|
254
|
+
for selector, section of nestingMap
|
255
|
+
do (selector, section) ->
|
256
|
+
section.instance.__fetch(section.nested)
|
256
257
|
|
257
|
-
|
258
|
-
|
259
|
-
|
258
|
+
if !section.instance.__independent
|
259
|
+
context.do (done) ->
|
260
|
+
section.instance.wait 'section:fetched', done
|
260
261
|
|
261
262
|
context.do (done) =>
|
262
263
|
@__runFetchs [], done
|
@@ -287,13 +288,14 @@ class Joosy.Widget extends Joosy.Module
|
|
287
288
|
|
288
289
|
@__load()
|
289
290
|
|
290
|
-
|
291
|
-
|
291
|
+
for selector, section of nestingMap
|
292
|
+
do (selector, section) =>
|
293
|
+
$container = @__normalizeSelector(selector)
|
292
294
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
295
|
+
if !section.instance.__independent || section.instance.__triggeredEvents?['section:fetched']
|
296
|
+
section.instance.__paint @, section.nested, $container
|
297
|
+
else
|
298
|
+
section.instance.__bootstrap @, section.nested, $container, false
|
297
299
|
|
298
300
|
#
|
299
301
|
# Initializes section that was injected into DOM
|
@@ -347,7 +349,7 @@ class Joosy.Widget extends Joosy.Module
|
|
347
349
|
# Besides already being instance it cann be either class or lambda
|
348
350
|
#
|
349
351
|
__normalizeWidget: (widget) ->
|
350
|
-
if
|
352
|
+
if typeof(widget) == 'function' && !Joosy.Module.hasAncestor(widget, Joosy.Widget)
|
351
353
|
widget = widget.call(@)
|
352
354
|
|
353
355
|
if Joosy.Module.hasAncestor widget, Joosy.Widget
|
data/source/joosy.coffee
CHANGED