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.
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
@@ -1,282 +0,0 @@
1
- #
2
- # Basic data wrapper with triggering and entity name binding
3
- #
4
- # @example Basic usage
5
- # class R extends Joosy.Resources.Base
6
- # @entity 'r'
7
- #
8
- # @beforeLoad (data) ->
9
- # data.real = true
10
- #
11
- # r = R.build {r: {foo: {bar: 'baz'}}}
12
- #
13
- # r('foo') # {baz: 'baz'}
14
- # r('real') # true
15
- # r('foo.bar') # baz
16
- # r('foo.bar', 'fluffy') # triggers 'changed'
17
- #
18
- # @include Joosy.Modules.Log
19
- # @include Joosy.Modules.Events
20
- # @include Joosy.Modules.Filters
21
- #
22
- # @method .beforeLoad(callback)
23
- # Allows to modify data before it gets stored.
24
- # You can define several beforeLoad filters that will be chained.
25
- # @param [Function] action `(Object) -> Object` to call
26
- #
27
- #
28
- class Joosy.Resources.Base extends Joosy.Function
29
- @include Joosy.Modules.Log
30
- @include Joosy.Modules.Events
31
- @include Joosy.Modules.Filters
32
-
33
- #
34
- # Default primary key field 'id'
35
- #
36
- __primaryKey: 'id'
37
-
38
- #
39
- # Clears the identity map cache. Recomended to be called during layout switch to
40
- # ensure correct garbage collection.
41
- #
42
- @resetIdentity: ->
43
- Joosy.Resources.Base.identity = {}
44
-
45
- @registerPlainFilters 'beforeLoad'
46
-
47
- #
48
- # Sets the field containing primary key.
49
- #
50
- # @note It has no direct use inside the REST resource itself and can be omited.
51
- # But it usually should not since we have plans on adding some kind of Identity Map to Joosy.
52
- #
53
- # @param [String] primary Name of the field
54
- #
55
- @primaryKey: (primaryKey) ->
56
- @::__primaryKey = primaryKey
57
-
58
- #
59
- # Sets the entity text name:
60
- # required to do some magic like skipping the root node.
61
- #
62
- # @param [String] name Singular name of resource
63
- #
64
- @entity: (name) ->
65
- @::__entityName = name
66
-
67
- #
68
- # Dynamically creates collection of inline resources.
69
- #
70
- # Inline resources share the instance with direct data and therefore can be used
71
- # to handle inline changes with triggers and all that resources stuff
72
- #
73
- # @example Basic usage
74
- # class Zombie extends Joosy.Resources.Base
75
- # @entity 'zombie'
76
- # class Puppy extends Joosy.Resources.Base
77
- # @entity 'puppy'
78
- # @map 'zombies'
79
- #
80
- # p = Puppy.build {zombies: [{foo: 'bar'}]}
81
- #
82
- # p('zombies') # Direct access: [{foo: 'bar'}]
83
- # p.zombies # Wrapped Collection of Zombie instances
84
- # p.zombies.at(0)('foo') # bar
85
- #
86
- # @param [String] name Pluralized name of property to define
87
- # @param [Class] klass Resource class to instantiate
88
- #
89
- @map: (name, klass=false) ->
90
- unless klass
91
- klass = window[name.singularize().camelize()]
92
-
93
- if !klass
94
- throw new Error "#{Joosy.Module.__className @}> class can not be detected for '#{name}' mapping"
95
-
96
- @beforeLoad (data) ->
97
- klass = klass() unless Joosy.Module.hasAncestor(klass, Joosy.Resources.Base)
98
-
99
- @__map(data, name, klass)
100
-
101
- #
102
- # Wraps instance of resource inside shim-function allowing to track
103
- # data changes. See class example
104
- #
105
- # @return [Joosy.Resources.Base]
106
- #
107
- @build: (data={}) ->
108
- if Object.isNumber(data) || Object.isString(data)
109
- id = data
110
- data = {}
111
- data[@::__primaryKey] = id
112
-
113
- klass = @::__entityName
114
- id = data[@::__primaryKey]
115
-
116
- if klass? && id?
117
- Joosy.Resources.Base.identity ?= {}
118
- Joosy.Resources.Base.identity[klass] ?= {}
119
- Joosy.Resources.Base.identity[klass][id] ?= new @ id: id
120
-
121
- Joosy.Resources.Base.identity[klass][id].load data
122
- else
123
- new @ data
124
-
125
- #
126
- # Creates new instance of Resource using values from form
127
- #
128
- # @param [DOMElement] form Form to grab
129
- #
130
- @grab: (form) ->
131
- @build({}).grab form
132
-
133
- #
134
- # Should NOT be called directly, use {::build} instead
135
- #
136
- # @private
137
- # @param [Object] data Data to store
138
- #
139
- constructor: (data={}) ->
140
- return super ->
141
- @__fillData data, false
142
-
143
- id: ->
144
- @data?[@__primaryKey]
145
-
146
- knownAttributes: ->
147
- Object.keys @data
148
-
149
- #
150
- # Set the resource data manually
151
- #
152
- # @param [Object] data Data to store
153
- #
154
- # @return [Joosy.Resources.Base] Returns self
155
- #
156
- load: (data, clear=false) ->
157
- @data = {} if clear
158
- @__fillData data
159
- return @
160
-
161
- #
162
- # Updates the Resource with a data from given form
163
- #
164
- # @param [DOMElement] form Form to grab
165
- #
166
- grab: (form) ->
167
- data = {}
168
- for field in $(form).serializeArray()
169
- unless data[field.name]
170
- data[field.name] = field.value
171
- else
172
- data[field.name] = [data[field.name]] unless data[field.name] instanceof Array
173
- data[field.name].push field.value
174
-
175
- @load data
176
-
177
- #
178
- # Getter for wrapped data
179
- #
180
- # @param [String] path Attribute name to get. Can contain dots to get inline Objects values
181
- # @return [mixed]
182
- #
183
- __get: (path) ->
184
- target = @__callTarget path, true
185
-
186
- if !target
187
- return undefined
188
- else if target[0] instanceof Joosy.Resources.Base
189
- return target[0](target[1])
190
- else
191
- return target[0][target[1]]
192
-
193
- #
194
- # Setter for wrapped data, triggers `changed` event.
195
- #
196
- # @param [String] path Attribute name to set. Can contain dots to get inline Objects values
197
- # @param [mixed] value Value to set
198
- #
199
- __set: (path, value) ->
200
- target = @__callTarget path
201
-
202
- if target[0] instanceof Joosy.Resources.Base
203
- target[0](target[1], value)
204
- else
205
- target[0][target[1]] = value
206
-
207
- @trigger 'changed'
208
- null
209
-
210
- #
211
- # Locates the actual instance of attribute path `foo.bar` from get/set
212
- #
213
- # @param [String] path Path to the attribute (`foo.bar`)
214
- # @param [Boolean] safe Indicates whether nested hashes should not be automatically created when they don't exist
215
- # @return [Array] Instance of object containing last step of path and keyword for required field
216
- #
217
- __callTarget: (path, safe=false) ->
218
- if path.has(/\./) && !@data[path]?
219
- path = path.split '.'
220
- keyword = path.pop()
221
- target = @data
222
-
223
- for part in path
224
- return false if safe && !target[part]?
225
-
226
- target[part] ||= {}
227
- if target instanceof Joosy.Resources.Base
228
- target = target(part)
229
- else
230
- target = target[part]
231
-
232
- [target, keyword]
233
- else
234
- [@data, path]
235
-
236
- #
237
- # Wrapper for {Joosy.Resources.Base.build} magic
238
- #
239
- __call: (path, value) ->
240
- if arguments.length > 1
241
- @__set path, value
242
- else
243
- @__get path
244
-
245
- #
246
- # Defines how exactly prepared data should be saved
247
- #
248
- # @param [Object] data Raw data to store
249
- #
250
- __fillData: (data, notify=true) ->
251
- @raw = data
252
- @data = {} unless @hasOwnProperty 'data'
253
-
254
- Joosy.Module.merge @data, @__prepareData(data)
255
-
256
- @trigger 'changed' if notify
257
-
258
- null
259
-
260
- #
261
- # Prepares raw data: cuts the root node if it exists, runs before filters
262
- #
263
- # @param [Hash] data Raw data to prepare
264
- # @return [Hash]
265
- #
266
- __prepareData: (data) ->
267
- if Object.isObject(data) && Object.keys(data).length == 1 && @__entityName
268
- name = @__entityName.camelize(false)
269
- data = data[name] if data[name]
270
-
271
- @__applyBeforeLoads data
272
-
273
- __map: (data, name, klass) ->
274
- if Object.isArray data[name]
275
- entries = data[name].map (x) -> klass.build x
276
- data[name] = new Joosy.Resources.Array entries...
277
- else if Object.isObject data[name]
278
- data[name] = klass.build data[name]
279
- data
280
-
281
- toString: ->
282
- "<Resource #{@__entityName}> #{JSON.stringify(@data)}"
@@ -1 +0,0 @@
1
- #= require_tree ./
@@ -1,104 +0,0 @@
1
- #= require ../form
2
-
3
- #
4
- # Form helper
5
- #
6
- Joosy.helpers 'Application', ->
7
-
8
- description = (resource, method, extendIds, idSuffix) ->
9
- if Joosy.Module.hasAncestor resource.constructor, Joosy.Resources.Base
10
- id = resource.id()
11
- resource = resource.__entityName
12
-
13
- name: resource + "#{if method.match(/^\[.*\]$/) then method else "[#{method}]"}"
14
- id: resource + (if id && extendIds then '_'+id else '') + "_#{method.parameterize().underscore()}" + (if idSuffix then '_'+idSuffix else '')
15
-
16
- input = (type, resource, method, options={}) =>
17
- d = description(resource, method, options.extendIds, options.idSuffix)
18
- delete options.extendIds
19
- delete options.idSuffix
20
- @tag 'input', Joosy.Module.merge {type: type, name: d.name, id: d.id}, options
21
-
22
- #
23
- # @private
24
- #
25
- class Form
26
- constructor: (@context, @resource, @options) ->
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
-
35
- radioButton: (method, tagValue, options={}) -> @context.radioButton(@resource, method, tagValue, Joosy.Module.merge(extendIds: @options.extendIds, options))
36
- textArea: (method, options={}) -> @context.textArea(@resource, method, Joosy.Module.merge(extendIds: @options.extendIds, options))
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)
39
-
40
- ['text', 'file', 'hidden', 'password'].each (type) =>
41
- Form.prototype[type+'Field'] = (method, options={}) ->
42
- @context[type+'Field'] @resource, method, Joosy.Module.merge(extendIds: @options.extendIds, options)
43
-
44
- @formFor = (resource, options={}, block) ->
45
- if Object.isFunction(options)
46
- block = options
47
- options = {}
48
-
49
- uuid = Joosy.uuid()
50
- form = @tag 'form', Joosy.Module.merge(options.html || {}, id: uuid), block?.call(this, new Form(this, resource, options))
51
-
52
- @onRefresh? -> Joosy.Form.attach '#'+uuid, Joosy.Module.merge(options, resource: resource)
53
-
54
- form
55
-
56
- @label = (resource, method, options={}, content='') ->
57
- if !Object.isObject(options)
58
- content = options
59
- options = {}
60
-
61
- d = description(resource, method, options.extendIds)
62
- delete options.extendIds
63
-
64
- @contentTag 'label', content, Joosy.Module.merge(options, for: d.id)
65
-
66
- ['text', 'file', 'hidden', 'password'].each (type) =>
67
- @[type+'Field'] = (resource, method, options={}) -> input type, resource, method, options
68
-
69
- @radioButton = (resource, method, tagValue, options={}) -> input 'radio', resource, method, Joosy.Module.merge(value: tagValue, idSuffix: tagValue, options)
70
-
71
- @checkBox = (resource, method, options={}, checkedValue=1, uncheckedValue=0) ->
72
- spy = @tag 'input', Joosy.Module.merge(name: description(resource, method).name, value: uncheckedValue, type: 'hidden')
73
- box = input 'checkbox', resource, method, Joosy.Module.merge(value: checkedValue, options)
74
-
75
- spy+box
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', vals[0], { value: vals[1] }] else ['option', vals, {}]
89
- if htmlOptions.value == (if Object.isArray(vals) then vals[1] else vals)
90
- params[2].selected = 'selected'
91
- str += @contentTag.apply @, params
92
- , ''
93
- extendIds = htmlOptions.extendIds
94
- delete htmlOptions.value
95
- delete htmlOptions.extendIds
96
- @contentTag 'select', opts, Joosy.Module.merge(description(resource, method, extendIds), htmlOptions)
97
-
98
- @textArea = (resource, method, options={}) ->
99
- value = options.value
100
- extendIds = options.extendIds
101
- delete options.value
102
- delete options.extendIds
103
-
104
- @contentTag 'textarea', value, Joosy.Module.merge(description(resource, method, extendIds), options)
@@ -1 +0,0 @@
1
- #= require_tree ./