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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/Gruntfile.coffee +56 -18
  3. data/bower.json +1 -1
  4. data/build/joosy/form.js +1 -0
  5. data/build/joosy/resources.js +1 -0
  6. data/build/joosy.js +2 -2774
  7. data/package.json +5 -4
  8. data/source/joosy/application.coffee +9 -7
  9. data/source/joosy/{extensions/resources-form/form.coffee → form.coffee} +58 -51
  10. data/source/joosy/helpers/form.coffee +241 -0
  11. data/source/joosy/helpers/index.coffee +3 -0
  12. data/source/joosy/helpers/routes.coffee +3 -1
  13. data/source/joosy/helpers/view.coffee +9 -9
  14. data/source/joosy/joosy.coffee +3 -5
  15. data/source/joosy/module.coffee +9 -4
  16. data/source/joosy/modules/dom.coffee +33 -31
  17. data/source/joosy/modules/events.coffee +24 -20
  18. data/source/joosy/modules/filters.coffee +38 -35
  19. data/source/joosy/modules/page/title.coffee +3 -3
  20. data/source/joosy/modules/renderer.coffee +23 -18
  21. data/source/joosy/modules/resources/identity_map.coffee +45 -0
  22. data/source/joosy/modules/resources/model.coffee +146 -0
  23. data/source/joosy/modules/widgets_manager.coffee +8 -8
  24. data/source/joosy/resources/array.coffee +0 -5
  25. data/source/joosy/resources/hash.coffee +8 -13
  26. data/source/joosy/resources/index.coffee +2 -0
  27. data/source/joosy/{extensions/resources → resources}/rest.coffee +48 -19
  28. data/source/joosy/resources/scalar.coffee +8 -10
  29. data/source/joosy/router.coffee +13 -12
  30. data/source/joosy/templaters/jst.coffee +3 -2
  31. data/source/joosy/widget.coffee +17 -15
  32. data/source/joosy.coffee +2 -0
  33. data/source/vendor/es5-shim.js +1316 -0
  34. data/source/vendor/inflections.js +598 -0
  35. data/source/vendor/metamorph.js +457 -0
  36. data/spec/helpers/matchers.coffee +4 -4
  37. data/spec/joosy/core/application_spec.coffee +1 -1
  38. data/spec/joosy/core/helpers/view_spec.coffee +2 -2
  39. data/spec/joosy/core/joosy_spec.coffee +8 -4
  40. data/spec/joosy/core/modules/dom_spec.coffee +7 -7
  41. data/spec/joosy/core/modules/events_spec.coffee +2 -2
  42. data/spec/joosy/core/modules/filters_spec.coffee +7 -8
  43. data/spec/joosy/core/modules/module_spec.coffee +5 -5
  44. data/spec/joosy/core/router_spec.coffee +3 -3
  45. data/spec/joosy/core/widget_spec.coffee +6 -6
  46. data/spec/joosy/environments/amd_spec.coffee +4 -2
  47. data/spec/joosy/environments/global_spec.coffee +1 -1
  48. data/spec/joosy/{extensions/form → form}/form_spec.coffee +9 -16
  49. data/spec/joosy/{extensions/form → form}/helpers/forms_spec.coffee +5 -5
  50. data/spec/joosy/{core/resources → resources}/array_spec.coffee +2 -2
  51. data/spec/joosy/{core/resources → resources}/hash_spec.coffee +0 -8
  52. data/spec/joosy/{core/modules/resources → resources/modules}/cacher_spec.coffee +0 -0
  53. data/spec/joosy/resources/modules/identity_map_spec.coffee +47 -0
  54. data/spec/joosy/{extensions/resources/base_spec.coffee → resources/modules/model_spec.coffee} +28 -48
  55. data/spec/joosy/{extensions/resources → resources}/rest_spec.coffee +29 -22
  56. data/spec/joosy/{core/resources → resources}/scalar_spec.coffee +8 -8
  57. data/templates/application/application.coffee.tt +0 -2
  58. data/templates/environment/app/haml/index.haml +2 -2
  59. data/templates/environment/package.json +1 -1
  60. metadata +23 -19
  61. data/build/joosy/extensions/resources-form.js +0 -590
  62. data/build/joosy/extensions/resources.js +0 -561
  63. data/source/joosy/extensions/resources/base.coffee +0 -282
  64. data/source/joosy/extensions/resources/index.coffee +0 -1
  65. data/source/joosy/extensions/resources-form/helpers/form.coffee +0 -104
  66. data/source/joosy/extensions/resources-form/index.coffee +0 -1
  67. 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 = Object.clone(@.__super__.__elements) || {}
27
- Object.merge @::__elements, map
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 = Object.clone(@.__super__.__events) || {}
41
- Object.merge @::__events, map
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
- if Object.isObject(value)
81
- @__assignElements root['$'+key]={}, value
82
- else
83
- value = @__extractSelector value
84
- root['$'+key] = @__wrapElement(value)
85
- root['$'+key].selector = value
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
- Object.each events, (keys, method) =>
114
- for key in keys.split(',')
115
- key = key.replace(/^\s+/, '')
116
-
117
- unless Object.isFunction method
118
- method = @[method]
119
- callback = (event) ->
120
- method.call module, $(this), event
121
-
122
- match = key.match @eventSplitter
123
- eventName = match[1]
124
- selector = @__extractSelector match[2]
125
-
126
- if selector == ""
127
- @$container.bind eventName, callback
128
- Joosy.Modules.Log.debugAs @, "#{eventName} binded on container"
129
- else if selector == undefined
130
- throw new Error "Unknown element #{match[2]} in #{Joosy.Module.__className @constructor} (maybe typo?)"
131
- else
132
- @$container.on eventName, selector, callback
133
- Joosy.Modules.Log.debugAs @, "#{eventName} binded on #{selector}"
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
- # unnamed binding
71
- if Object.isFunction(events)
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
- # unnamed binding
104
- if Object.isFunction(events)
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 Object.isObject event
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.remove event
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
- fire.each (name) =>
147
- callback = @__oneShotEvents[name][1]
148
- delete @__oneShotEvents[name]
149
- callback data...
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.any event
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.each (action) =>
182
- action.call @, ->
183
- if ++counter >= context.actions.length
184
- context.after.call(@)
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 Object.isString events
188
- if events.isBlank()
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.findAll (e) => !@__triggeredEvents[e]
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
- filters.each (filter) =>
36
- camelized = @__registerFilterCollector filter
34
+ @registerPlainFilters = (filters...) ->
35
+ for filter in filters
36
+ do (filter) =>
37
+ camelized = @__registerFilterCollector filter
37
38
 
38
- @::["__run#{camelized}s"] = (params...) ->
39
- return unless @["__#{filter}s"]
39
+ @::["__run#{camelized}s"] = (params...) ->
40
+ return unless @["__#{filter}s"]
40
41
 
41
- for callback in @["__#{filter}s"]
42
- callback = @[callback] unless typeof(callback) == 'function'
43
- callback.apply(@, params)
42
+ for callback in @["__#{filter}s"]
43
+ callback = @[callback] unless typeof(callback) == 'function'
44
+ callback.apply(@, params)
44
45
 
45
- @::["__confirm#{camelized}s"] = (params...) ->
46
- return true unless @["__#{filter}s"]
46
+ @::["__confirm#{camelized}s"] = (params...) ->
47
+ return true unless @["__#{filter}s"]
47
48
 
48
- @["__#{filter}s"].reduce (flag, callback) =>
49
- callback = @[callback] unless typeof(callback) == 'function'
50
- flag && callback.apply(@, params) != false
51
- , true
49
+ @["__#{filter}s"].reduce (flag, callback) =>
50
+ callback = @[callback] unless typeof(callback) == 'function'
51
+ flag && callback.apply(@, params) != false
52
+ , true
52
53
 
53
- @::["__apply#{camelized}s"] = (data, params...) ->
54
- return data unless @["__#{filter}s"]
54
+ @::["__apply#{camelized}s"] = (data, params...) ->
55
+ return data unless @["__#{filter}s"]
55
56
 
56
- for callback in @["__#{filter}s"]
57
- callback = @[callback] unless typeof(callback) == 'function'
58
- data = callback.apply(@, [data].concat params)
57
+ for callback in @["__#{filter}s"]
58
+ callback = @[callback] unless typeof(callback) == 'function'
59
+ data = callback.apply(@, [data].concat params)
59
60
 
60
- data
61
+ data
61
62
 
62
- @registerSequencedFilters = (filters...) =>
63
- filters.each (filter) =>
64
- camelized = @__registerFilterCollector filter
63
+ @registerSequencedFilters = (filters...) ->
64
+ for filter in filters
65
+ do (filter) =>
66
+ camelized = @__registerFilterCollector filter
65
67
 
66
- @::["__run#{camelized}s"] = (params, callback) ->
67
- return callback() unless @["__#{filter}s"]
68
+ @::["__run#{camelized}s"] = (params, callback) ->
69
+ return callback() unless @["__#{filter}s"]
68
70
 
69
- runners = @["__#{filter}s"]
70
- filterer = @
71
+ runners = @["__#{filter}s"]
72
+ filterer = @
71
73
 
72
- if runners.length == 1
73
- return runners[0].apply @, params.include(callback)
74
+ if runners.length == 1
75
+ return runners[0].apply @, params.concat(callback)
74
76
 
75
- Joosy.synchronize (context) ->
76
- runners.each (runner) ->
77
- context.do (done) ->
78
- runner.apply filterer, params.include(done)
79
- context.after callback
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
- titleStr = if Object.isFunction(title) then title.apply(@) else title
16
- titleStr = titleStr.join(separator) if Object.isArray(titleStr)
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 = titleStr
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?.clone() || []
27
+ @::__helpers = @.__super__.__helpers?.slice() || []
28
28
 
29
- @::__helpers = @::__helpers.add(helpers).unique()
30
- @::__helpers = @::__helpers.unique()
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.clone()
63
+ @__helpers = @__helpers.slice()
64
64
 
65
- @__helpers.each (helper, i) =>
66
- unless Object.isObject(helper)
67
- unless @[helper]?
68
- throw new Error "Cannot find method '#{helper}' to use as helper"
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
- @__helpers[i] = {}
71
- @__helpers[i][helper] = => @[helper] arguments...
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 Object.isString template
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 !Object.isFunction template
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 !Object.isObject(locals) && Object.extended().constructor != locals.constructor
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
- update = update.debounce 0
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', update)]
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?.each (stackPointer) ->
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 = Object.clone(@.__super__.__widgets) || {}
14
- Object.merge @::__widgets, map
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 Object.isFunction(widget)
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 = Object.extended()
50
+ registered = {}
51
51
 
52
- Object.each @__widgets, (selector, widget) =>
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] = Object.extended()
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
- registered.each (selector, value) =>
77
- value.each (widget, count) =>
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'