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
@@ -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'
|