joosy 1.2.0.alpha.73 → 1.2.0.beta.1
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.
- 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
@@ -23,8 +23,8 @@ Joosy.Modules.DOM =
|
|
23
23
|
#
|
24
24
|
@mapElements = (map) ->
|
25
25
|
unless @::hasOwnProperty "__elements"
|
26
|
-
@::__elements =
|
27
|
-
|
26
|
+
@::__elements = Joosy.Module.merge {}, @.__super__.__elements
|
27
|
+
Joosy.Module.merge @::__elements, map
|
28
28
|
|
29
29
|
#
|
30
30
|
# Extends events mapping scheme
|
@@ -37,8 +37,8 @@ Joosy.Modules.DOM =
|
|
37
37
|
#
|
38
38
|
@mapEvents = (map) ->
|
39
39
|
unless @::hasOwnProperty "__events"
|
40
|
-
@::__events =
|
41
|
-
|
40
|
+
@::__events = Joosy.Module.merge {}, @.__super__.__events
|
41
|
+
Joosy.Module.merge @::__events, map
|
42
42
|
|
43
43
|
$: (selector, context) ->
|
44
44
|
$(selector, context || @$container)
|
@@ -77,12 +77,13 @@ Joosy.Modules.DOM =
|
|
77
77
|
return unless entries
|
78
78
|
|
79
79
|
for key,value of entries
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
80
|
+
do (key, value) =>
|
81
|
+
if typeof(value) != 'string'
|
82
|
+
@__assignElements root['$'+key]={}, value
|
83
|
+
else
|
84
|
+
value = @__extractSelector value
|
85
|
+
root['$'+key] = @__wrapElement(value)
|
86
|
+
root['$'+key].selector = value
|
86
87
|
|
87
88
|
#
|
88
89
|
# Wraps actual element closures. Required to clear context to avoid circular reference
|
@@ -110,27 +111,28 @@ Joosy.Modules.DOM =
|
|
110
111
|
|
111
112
|
return unless events
|
112
113
|
|
113
|
-
|
114
|
-
|
115
|
-
key
|
116
|
-
|
117
|
-
|
118
|
-
method
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
114
|
+
for keys, method of events
|
115
|
+
do (keys, method) =>
|
116
|
+
for key in keys.split(',')
|
117
|
+
key = key.replace(/^\s+/, '')
|
118
|
+
|
119
|
+
unless typeof(method) == 'function'
|
120
|
+
method = @[method]
|
121
|
+
callback = (event) ->
|
122
|
+
method.call module, $(this), event
|
123
|
+
|
124
|
+
match = key.match @eventSplitter
|
125
|
+
eventName = match[1]
|
126
|
+
selector = @__extractSelector match[2]
|
127
|
+
|
128
|
+
if selector == ""
|
129
|
+
@$container.bind eventName, callback
|
130
|
+
Joosy.Modules.Log.debugAs @, "#{eventName} binded on container"
|
131
|
+
else if selector == undefined
|
132
|
+
throw new Error "Unknown element #{match[2]} in #{Joosy.Module.__className @constructor} (maybe typo?)"
|
133
|
+
else
|
134
|
+
@$container.on eventName, selector, callback
|
135
|
+
Joosy.Modules.Log.debugAs @, "#{eventName} binded on #{selector}"
|
134
136
|
|
135
137
|
# @private
|
136
138
|
__clearContainer: ->
|
@@ -67,8 +67,8 @@ Joosy.Modules.Events =
|
|
67
67
|
wait: (name, events, callback) ->
|
68
68
|
@__oneShotEvents = {} unless @hasOwnProperty('__oneShotEvents')
|
69
69
|
|
70
|
-
#
|
71
|
-
if
|
70
|
+
# (events, callback) ->
|
71
|
+
if arguments.length == 2
|
72
72
|
callback = events
|
73
73
|
events = name
|
74
74
|
name = Object.keys(@__oneShotEvents).length.toString()
|
@@ -100,8 +100,8 @@ Joosy.Modules.Events =
|
|
100
100
|
bind: (name, events, callback) ->
|
101
101
|
@__boundEvents = {} unless @hasOwnProperty '__boundEvents'
|
102
102
|
|
103
|
-
#
|
104
|
-
if
|
103
|
+
# (events, callback) ->
|
104
|
+
if arguments.length == 2
|
105
105
|
callback = events
|
106
106
|
events = name
|
107
107
|
name = Object.keys(@__boundEvents).length.toString()
|
@@ -131,26 +131,29 @@ Joosy.Modules.Events =
|
|
131
131
|
trigger: (event, data...) ->
|
132
132
|
Joosy.Modules.Log.debugAs @, "Event #{event} triggered"
|
133
133
|
|
134
|
-
if
|
134
|
+
if typeof(event) == 'string'
|
135
|
+
remember = false
|
136
|
+
else
|
135
137
|
remember = event.remember
|
136
138
|
event = event.name
|
137
|
-
else
|
138
|
-
remember = false
|
139
139
|
|
140
140
|
if @hasOwnProperty '__oneShotEvents'
|
141
141
|
fire = []
|
142
142
|
for name, [events, callback] of @__oneShotEvents
|
143
|
-
events.
|
143
|
+
while (needle = events.indexOf(event)) != -1
|
144
|
+
events.splice needle, 1
|
145
|
+
|
144
146
|
if events.length == 0
|
145
147
|
fire.push name
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
148
|
+
for name in fire
|
149
|
+
do (name) =>
|
150
|
+
callback = @__oneShotEvents[name][1]
|
151
|
+
delete @__oneShotEvents[name]
|
152
|
+
callback data...
|
150
153
|
|
151
154
|
if @hasOwnProperty '__boundEvents'
|
152
155
|
for name, [events, callback] of @__boundEvents
|
153
|
-
if events.
|
156
|
+
if events.indexOf(event) != -1
|
154
157
|
callback data...
|
155
158
|
|
156
159
|
if remember
|
@@ -178,20 +181,21 @@ Joosy.Modules.Events =
|
|
178
181
|
if context.actions.length == 0
|
179
182
|
context.after.call(@)
|
180
183
|
else
|
181
|
-
context.actions
|
182
|
-
action
|
183
|
-
|
184
|
-
context.
|
184
|
+
for action in context.actions
|
185
|
+
do (action) =>
|
186
|
+
action.call @, ->
|
187
|
+
if ++counter >= context.actions.length
|
188
|
+
context.after.call(@)
|
185
189
|
|
186
190
|
__splitEvents: (events) ->
|
187
|
-
if
|
188
|
-
if events.
|
191
|
+
if typeof(events) == 'string'
|
192
|
+
if events.length == 0
|
189
193
|
events = []
|
190
194
|
else
|
191
195
|
events = events.trim().split /\s+/
|
192
196
|
|
193
197
|
if @hasOwnProperty '__triggeredEvents'
|
194
|
-
events = events.
|
198
|
+
events = events.filter (e) => !@__triggeredEvents[e]
|
195
199
|
|
196
200
|
events
|
197
201
|
|
@@ -23,7 +23,7 @@ Joosy.Modules.Filters =
|
|
23
23
|
# @__runAfterUnloads() # Runs filters registered as afterUnload
|
24
24
|
#
|
25
25
|
included: ->
|
26
|
-
@__registerFilterCollector = (filter)
|
26
|
+
@__registerFilterCollector = (filter) ->
|
27
27
|
@[filter] = (callback) ->
|
28
28
|
unless @::hasOwnProperty "__#{filter}s"
|
29
29
|
@::["__#{filter}s"] = [].concat @.__super__["__#{filter}s"] || []
|
@@ -31,52 +31,55 @@ Joosy.Modules.Filters =
|
|
31
31
|
|
32
32
|
filter.charAt(0).toUpperCase() + filter.slice(1)
|
33
33
|
|
34
|
-
@registerPlainFilters = (filters...)
|
35
|
-
|
36
|
-
|
34
|
+
@registerPlainFilters = (filters...) ->
|
35
|
+
for filter in filters
|
36
|
+
do (filter) =>
|
37
|
+
camelized = @__registerFilterCollector filter
|
37
38
|
|
38
|
-
|
39
|
-
|
39
|
+
@::["__run#{camelized}s"] = (params...) ->
|
40
|
+
return unless @["__#{filter}s"]
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
for callback in @["__#{filter}s"]
|
43
|
+
callback = @[callback] unless typeof(callback) == 'function'
|
44
|
+
callback.apply(@, params)
|
44
45
|
|
45
|
-
|
46
|
-
|
46
|
+
@::["__confirm#{camelized}s"] = (params...) ->
|
47
|
+
return true unless @["__#{filter}s"]
|
47
48
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
@["__#{filter}s"].reduce (flag, callback) =>
|
50
|
+
callback = @[callback] unless typeof(callback) == 'function'
|
51
|
+
flag && callback.apply(@, params) != false
|
52
|
+
, true
|
52
53
|
|
53
|
-
|
54
|
-
|
54
|
+
@::["__apply#{camelized}s"] = (data, params...) ->
|
55
|
+
return data unless @["__#{filter}s"]
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
57
|
+
for callback in @["__#{filter}s"]
|
58
|
+
callback = @[callback] unless typeof(callback) == 'function'
|
59
|
+
data = callback.apply(@, [data].concat params)
|
59
60
|
|
60
|
-
|
61
|
+
data
|
61
62
|
|
62
|
-
@registerSequencedFilters = (filters...)
|
63
|
-
|
64
|
-
|
63
|
+
@registerSequencedFilters = (filters...) ->
|
64
|
+
for filter in filters
|
65
|
+
do (filter) =>
|
66
|
+
camelized = @__registerFilterCollector filter
|
65
67
|
|
66
|
-
|
67
|
-
|
68
|
+
@::["__run#{camelized}s"] = (params, callback) ->
|
69
|
+
return callback() unless @["__#{filter}s"]
|
68
70
|
|
69
|
-
|
70
|
-
|
71
|
+
runners = @["__#{filter}s"]
|
72
|
+
filterer = @
|
71
73
|
|
72
|
-
|
73
|
-
|
74
|
+
if runners.length == 1
|
75
|
+
return runners[0].apply @, params.concat(callback)
|
74
76
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
77
|
+
Joosy.synchronize (context) ->
|
78
|
+
for runner in runners
|
79
|
+
do (runner) ->
|
80
|
+
context.do (done) ->
|
81
|
+
runner.apply filterer, params.concat(done)
|
82
|
+
context.after callback
|
80
83
|
|
81
84
|
# AMD wrapper
|
82
85
|
if define?.amd?
|
@@ -12,10 +12,10 @@ Joosy.Modules.Page.Title =
|
|
12
12
|
#
|
13
13
|
title: (title, separator=' / ') ->
|
14
14
|
@afterLoad ->
|
15
|
-
|
16
|
-
|
15
|
+
title = title.apply(@) if typeof(title) == 'function'
|
16
|
+
title = title.join(separator) if title instanceof Array
|
17
17
|
@__previousTitle = document.title
|
18
|
-
document.title =
|
18
|
+
document.title = title
|
19
19
|
|
20
20
|
@afterUnload ->
|
21
21
|
document.title = @__previousTitle
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#= require metamorph
|
1
|
+
#= require vendor/metamorph
|
2
2
|
#= require joosy/joosy
|
3
3
|
|
4
4
|
#
|
@@ -24,10 +24,10 @@ Joosy.Modules.Renderer =
|
|
24
24
|
|
25
25
|
@helper = (helpers...) ->
|
26
26
|
unless @::hasOwnProperty "__helpers"
|
27
|
-
@::__helpers = @.__super__.__helpers?.
|
27
|
+
@::__helpers = @.__super__.__helpers?.slice() || []
|
28
28
|
|
29
|
-
@::__helpers = @::__helpers.
|
30
|
-
|
29
|
+
@::__helpers = @::__helpers.concat(helpers).filter (value, i, array) ->
|
30
|
+
array.indexOf(value) == i
|
31
31
|
|
32
32
|
#
|
33
33
|
# Renders given template with given locals
|
@@ -60,15 +60,16 @@ Joosy.Modules.Renderer =
|
|
60
60
|
return unless @__helpers?
|
61
61
|
|
62
62
|
unless @hasOwnProperty "__helpers"
|
63
|
-
@__helpers = @__helpers.
|
63
|
+
@__helpers = @__helpers.slice()
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
unless
|
68
|
-
|
65
|
+
for helper, i in @__helpers
|
66
|
+
do (helper, i) =>
|
67
|
+
unless helper.constructor == Object
|
68
|
+
unless @[helper]?
|
69
|
+
throw new Error "Cannot find method '#{helper}' to use as helper"
|
69
70
|
|
70
|
-
|
71
|
-
|
71
|
+
@__helpers[i] = {}
|
72
|
+
@__helpers[i][helper] = => @[helper] arguments...
|
72
73
|
|
73
74
|
#
|
74
75
|
# Collects and merges all requested helpers including global scope to one cached object
|
@@ -112,14 +113,14 @@ Joosy.Modules.Renderer =
|
|
112
113
|
stack.template = template
|
113
114
|
stack.locals = locals
|
114
115
|
|
115
|
-
if
|
116
|
+
if typeof(template) == 'string'
|
116
117
|
if @__renderSection?
|
117
118
|
template = Joosy.templater().resolveTemplate @__renderSection(), template, this
|
118
119
|
template = Joosy.templater().buildView template
|
119
|
-
else if
|
120
|
+
else if typeof(template) != 'function'
|
120
121
|
throw new Error "#{Joosy.Module.__className @}> template (maybe @view) does not look like a string or lambda"
|
121
122
|
|
122
|
-
if
|
123
|
+
if locals.constructor != Object
|
123
124
|
throw new Error "#{Joosy.Module.__className @}> locals (maybe @data?) is not a hash"
|
124
125
|
|
125
126
|
context = =>
|
@@ -147,12 +148,15 @@ Joosy.Modules.Renderer =
|
|
147
148
|
|
148
149
|
# This is here to break stack tree and save from
|
149
150
|
# repeating DOM modification
|
150
|
-
|
151
|
+
timeout = null
|
152
|
+
debouncedUpdate = ->
|
153
|
+
clearTimeout timeout
|
154
|
+
timeout = setTimeout update, 0
|
151
155
|
|
152
156
|
for key, object of locals
|
153
157
|
if locals.hasOwnProperty key
|
154
158
|
if object?.bind? && object?.unbind?
|
155
|
-
binding = [object, object.bind('changed',
|
159
|
+
binding = [object, object.bind('changed', debouncedUpdate)]
|
156
160
|
stack.metamorphBindings.push binding
|
157
161
|
|
158
162
|
morph.__bindings = stack.metamorphBindings
|
@@ -202,8 +206,9 @@ Joosy.Modules.Renderer =
|
|
202
206
|
stackPointer.metamorphBindings = []
|
203
207
|
|
204
208
|
unless stackPointer
|
205
|
-
@__renderingStack
|
206
|
-
remove stackPointer
|
209
|
+
if @__renderingStack?
|
210
|
+
remove stackPointer for stackPointer in @__renderingStack
|
211
|
+
|
207
212
|
else
|
208
213
|
remove stackPointer
|
209
214
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#= require ../resources
|
2
|
+
|
3
|
+
Joosy.Modules.Resources.IdentityMap =
|
4
|
+
|
5
|
+
extended: ->
|
6
|
+
@::__identityHolder = @
|
7
|
+
|
8
|
+
#
|
9
|
+
# Clears the identity map cache. Recomended to be called during layout switch to
|
10
|
+
# ensure correct garbage collection.
|
11
|
+
#
|
12
|
+
identityReset: ->
|
13
|
+
@::__identityHolder.identity = {}
|
14
|
+
|
15
|
+
identityPath: (data) ->
|
16
|
+
[
|
17
|
+
@::__entityName, # entity name as a first-level entry to make inheritance safe
|
18
|
+
"s#{@__source || ''}", # save identity from overlaping on `@at` calls
|
19
|
+
data[@::__primaryKey] # direct identifier as a main distinguisher
|
20
|
+
]
|
21
|
+
|
22
|
+
#
|
23
|
+
# Wraps instance of resource inside shim-function allowing to track
|
24
|
+
# data changes. See class example
|
25
|
+
#
|
26
|
+
# @return [Joosy.Resources.REST]
|
27
|
+
#
|
28
|
+
build: (data={}) ->
|
29
|
+
elements = @identityPath(data)
|
30
|
+
|
31
|
+
if elements.filter((element) -> !element?).length == 0
|
32
|
+
location = @::__identityHolder.identity ?= {}
|
33
|
+
destination = elements.pop()
|
34
|
+
location = location[element] ?= {} for element in elements
|
35
|
+
|
36
|
+
# Data can be circulary referenced so we have to
|
37
|
+
# init identity cell as a first step...
|
38
|
+
preload = {}
|
39
|
+
preload[@::__primaryKey] = data[@::__primaryKey]
|
40
|
+
location[destination] ?= new @ preload
|
41
|
+
|
42
|
+
# ...and load data as a second
|
43
|
+
location[destination].load data
|
44
|
+
else
|
45
|
+
new @ data
|
@@ -0,0 +1,146 @@
|
|
1
|
+
#= require ../resources
|
2
|
+
|
3
|
+
Joosy.Modules.Resources.Model =
|
4
|
+
|
5
|
+
included: ->
|
6
|
+
#
|
7
|
+
# Sets the field containing primary key.
|
8
|
+
#
|
9
|
+
# @note It has no direct use inside the REST resource itself and can be omited.
|
10
|
+
# But it usually should not since we have plans on adding some kind of Identity Map to Joosy.
|
11
|
+
#
|
12
|
+
# @param [String] primary Name of the field
|
13
|
+
#
|
14
|
+
@primaryKey = (primaryKey) ->
|
15
|
+
@::__primaryKey = primaryKey
|
16
|
+
|
17
|
+
#
|
18
|
+
# Sets the collection to use
|
19
|
+
#
|
20
|
+
# @param [Class] klass Class to use as a collection wrapper
|
21
|
+
#
|
22
|
+
@collection = (klass) ->
|
23
|
+
@::__collection = klass
|
24
|
+
|
25
|
+
#
|
26
|
+
# Sets the entity text name:
|
27
|
+
# required to do some magic like skipping the root node.
|
28
|
+
#
|
29
|
+
# @param [String] name Singular name of resource
|
30
|
+
#
|
31
|
+
@entity = (name) ->
|
32
|
+
@::__entityName = name
|
33
|
+
|
34
|
+
#
|
35
|
+
# Dynamically creates collection of inline resources.
|
36
|
+
#
|
37
|
+
# Inline resources share the instance with direct data and therefore can be used
|
38
|
+
# to handle inline changes with triggers and all that resources stuff
|
39
|
+
#
|
40
|
+
# @example Basic usage
|
41
|
+
# class Zombie extends Joosy.Resources.REST
|
42
|
+
# @entity 'zombie'
|
43
|
+
# class Puppy extends Joosy.Resources.REST
|
44
|
+
# @entity 'puppy'
|
45
|
+
# @map 'zombies'
|
46
|
+
#
|
47
|
+
# p = Puppy.build {zombies: [{foo: 'bar'}]}
|
48
|
+
#
|
49
|
+
# p('zombies') # Direct access: [{foo: 'bar'}]
|
50
|
+
# p.zombies # Wrapped Collection of Zombie instances
|
51
|
+
# p.zombies.at(0)('foo') # bar
|
52
|
+
#
|
53
|
+
# @param [String] name Pluralized name of property to define
|
54
|
+
# @param [Class] klass Resource class to instantiate
|
55
|
+
#
|
56
|
+
@map = (name, klass=false) ->
|
57
|
+
unless klass
|
58
|
+
|
59
|
+
klass = window[inflection.camelize inflection.singularize(name)]
|
60
|
+
|
61
|
+
if !klass
|
62
|
+
throw new Error "#{Joosy.Module.__className @}> class can not be detected for '#{name}' mapping"
|
63
|
+
|
64
|
+
@beforeLoad (data) ->
|
65
|
+
klass = klass() unless klass.build?
|
66
|
+
|
67
|
+
if data[name] instanceof Array
|
68
|
+
entries = data[name].map (x) -> klass.build x
|
69
|
+
data[name] = new klass::__collection entries...
|
70
|
+
else if data[name]
|
71
|
+
data[name] = klass.build data[name]
|
72
|
+
data
|
73
|
+
|
74
|
+
#
|
75
|
+
# @return [Joosy.Resources.REST]
|
76
|
+
#
|
77
|
+
@build = (data={}) ->
|
78
|
+
new @ data
|
79
|
+
|
80
|
+
#
|
81
|
+
# Creates new instance of Resource using values from form
|
82
|
+
#
|
83
|
+
# @param [DOMElement] form Form to grab
|
84
|
+
#
|
85
|
+
@grab = (form) ->
|
86
|
+
@build({}).grab form
|
87
|
+
|
88
|
+
#
|
89
|
+
# Default primary key field 'id'
|
90
|
+
#
|
91
|
+
__primaryKey: 'id'
|
92
|
+
|
93
|
+
#
|
94
|
+
# Default collection: Joosy.Resources.Array
|
95
|
+
#
|
96
|
+
__collection: Joosy.Resources.Array
|
97
|
+
|
98
|
+
id: ->
|
99
|
+
@data?[@__primaryKey]
|
100
|
+
|
101
|
+
knownAttributes: ->
|
102
|
+
Object.keys @data
|
103
|
+
|
104
|
+
#
|
105
|
+
# Set the resource data manually
|
106
|
+
#
|
107
|
+
# @param [Object] data Data to store
|
108
|
+
#
|
109
|
+
# @return [Object] Returns self
|
110
|
+
#
|
111
|
+
load: (data, clear=false) ->
|
112
|
+
@data = {} if clear
|
113
|
+
@__fillData data
|
114
|
+
@
|
115
|
+
|
116
|
+
#
|
117
|
+
# Defines how exactly prepared data should be saved
|
118
|
+
#
|
119
|
+
# @param [Object] data Raw data to store
|
120
|
+
#
|
121
|
+
__fillData: (data, notify=true) ->
|
122
|
+
@raw = data
|
123
|
+
@data = {} unless @hasOwnProperty 'data'
|
124
|
+
|
125
|
+
Joosy.Module.merge @data, @__applyBeforeLoads(data)
|
126
|
+
@trigger 'changed' if notify
|
127
|
+
null
|
128
|
+
|
129
|
+
#
|
130
|
+
# Updates the Resource with a data from given form
|
131
|
+
#
|
132
|
+
# @param [DOMElement] form Form to grab
|
133
|
+
#
|
134
|
+
grab: (form) ->
|
135
|
+
data = {}
|
136
|
+
for field in $(form).serializeArray()
|
137
|
+
unless data[field.name]
|
138
|
+
data[field.name] = field.value
|
139
|
+
else
|
140
|
+
data[field.name] = [data[field.name]] unless data[field.name] instanceof Array
|
141
|
+
data[field.name].push field.value
|
142
|
+
|
143
|
+
@load data
|
144
|
+
|
145
|
+
toString: ->
|
146
|
+
"<Resource #{@__entityName}> #{JSON.stringify(@data)}"
|
@@ -10,8 +10,8 @@ Joosy.Modules.WidgetsManager =
|
|
10
10
|
included: ->
|
11
11
|
@mapWidgets = (map) ->
|
12
12
|
unless @::hasOwnProperty "__widgets"
|
13
|
-
@::__widgets =
|
14
|
-
|
13
|
+
@::__widgets = Joosy.Module.merge {}, @.__super__.widgets
|
14
|
+
Joosy.Module.merge @::__widgets, map
|
15
15
|
|
16
16
|
#
|
17
17
|
# Registeres and runs widget inside specified container
|
@@ -23,7 +23,7 @@ Joosy.Modules.WidgetsManager =
|
|
23
23
|
if Joosy.Module.hasAncestor widget, Joosy.Widget
|
24
24
|
widget = new widget()
|
25
25
|
|
26
|
-
if
|
26
|
+
if typeof(widget) == 'function'
|
27
27
|
widget = widget()
|
28
28
|
|
29
29
|
@__activeWidgets ||= []
|
@@ -47,16 +47,16 @@ Joosy.Modules.WidgetsManager =
|
|
47
47
|
__setupWidgets: ->
|
48
48
|
return unless @__widgets
|
49
49
|
|
50
|
-
registered =
|
50
|
+
registered = {}
|
51
51
|
|
52
|
-
|
52
|
+
for selector, widget of @__widgets
|
53
53
|
if selector == '$container'
|
54
54
|
activeSelector = @$container
|
55
55
|
else
|
56
56
|
selector = @__extractSelector(selector) if @__extractSelector?
|
57
57
|
activeSelector = $(selector, @$container)
|
58
58
|
|
59
|
-
registered[selector] =
|
59
|
+
registered[selector] = {}
|
60
60
|
|
61
61
|
activeSelector.each (index, elem) =>
|
62
62
|
if Joosy.Module.hasAncestor widget, Joosy.Widget
|
@@ -73,8 +73,8 @@ Joosy.Modules.WidgetsManager =
|
|
73
73
|
@__widgets = {}
|
74
74
|
|
75
75
|
if Joosy.debug()
|
76
|
-
|
77
|
-
|
76
|
+
for selector, value of registered
|
77
|
+
for widget, count of value
|
78
78
|
Joosy.Modules.Log.debugAs @, "Widget #{widget} registered at '#{selector}'. Elements: #{count}"
|
79
79
|
|
80
80
|
#
|
@@ -1,5 +1,3 @@
|
|
1
|
-
#= require joosy/modules/resources/cacher
|
2
|
-
|
3
1
|
class Joosy.Resources.Array extends Array
|
4
2
|
|
5
3
|
Joosy.Module.merge @, Joosy.Module
|
@@ -12,9 +10,6 @@ class Joosy.Resources.Array extends Array
|
|
12
10
|
constructor: ->
|
13
11
|
@__fillData arguments, false
|
14
12
|
|
15
|
-
get: (index) ->
|
16
|
-
@[index]
|
17
|
-
|
18
13
|
set: (index, value) ->
|
19
14
|
@[index] = value
|
20
15
|
@trigger 'changed'
|