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
data/package.json
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
"keywords": [
|
5
5
|
"joosy"
|
6
6
|
],
|
7
|
-
"version": "1.2.0-
|
7
|
+
"version": "1.2.0-beta.1",
|
8
8
|
"author": "Boris Staal <boris@staal.io>",
|
9
9
|
"homepage": "http://joosy.ws/",
|
10
10
|
"repository": {
|
@@ -15,15 +15,16 @@
|
|
15
15
|
"node": ">=0.4.0"
|
16
16
|
},
|
17
17
|
"dependencies": {
|
18
|
-
"grill": ">=1.0.0-alpha.
|
18
|
+
"grill": ">=1.0.0-alpha.22"
|
19
19
|
},
|
20
20
|
"devDependencies": {
|
21
21
|
"bower": "~1.2.1",
|
22
22
|
"semver": "~2.1.0",
|
23
23
|
"grunt-coffeelint": "0.0.6",
|
24
24
|
"grunt-release": "~0.3.5",
|
25
|
-
"grunt-contrib-testem": ">=0.5.
|
25
|
+
"grunt-contrib-testem": ">=0.5.3",
|
26
26
|
"grunt-gh-pages": "git+https://github.com/inossidabile/grunt-gh-pages.git",
|
27
|
-
"moment": "~2.1.0"
|
27
|
+
"moment": "~2.1.0",
|
28
|
+
"grunt-contrib-uglify": "~0.2.4"
|
28
29
|
}
|
29
30
|
}
|
@@ -1,8 +1,7 @@
|
|
1
1
|
#= require joosy/joosy
|
2
2
|
#= require joosy/router
|
3
|
-
#=
|
4
|
-
#=
|
5
|
-
#= require_tree ./helpers
|
3
|
+
#= require joosy/templaters/jst
|
4
|
+
#= require joosy/helpers
|
6
5
|
|
7
6
|
#
|
8
7
|
# Joosy Application container
|
@@ -15,7 +14,7 @@ class Joosy.Application
|
|
15
14
|
@initialized: false
|
16
15
|
@loading: true
|
17
16
|
|
18
|
-
@
|
17
|
+
@defaultConfig:
|
19
18
|
test: false
|
20
19
|
debug: false
|
21
20
|
templater:
|
@@ -36,8 +35,11 @@ class Joosy.Application
|
|
36
35
|
if @initialized
|
37
36
|
throw new Error 'Attempted to initialize Application twice'
|
38
37
|
|
39
|
-
|
40
|
-
|
38
|
+
@config = {}
|
39
|
+
|
40
|
+
Joosy.Module.merge @config, @defaultConfig, true, true
|
41
|
+
Joosy.Module.merge @config, window.JoosyEnvironment, true, true if window.JoosyEnvironment?
|
42
|
+
Joosy.Module.merge @config, options, true, true
|
41
43
|
|
42
44
|
@forceSandbox() if @config.test
|
43
45
|
|
@@ -47,7 +49,7 @@ class Joosy.Application
|
|
47
49
|
Joosy.Router.setup @config.router, (action, params) =>
|
48
50
|
if Joosy.Module.hasAncestor action, Joosy.Page
|
49
51
|
@changePage action, params
|
50
|
-
else if
|
52
|
+
else if typeof(action) == 'function'
|
51
53
|
action(params)
|
52
54
|
else
|
53
55
|
throw new Error "Unknown kind of route action: #{action}"
|
@@ -95,11 +95,10 @@ class Joosy.Form extends Joosy.Module
|
|
95
95
|
# @option options [Boolean] debounce Drop submit events while there is a pending submit request
|
96
96
|
#
|
97
97
|
constructor: (form, options={}) ->
|
98
|
-
if
|
98
|
+
if typeof(options) == 'function'
|
99
99
|
@success = options
|
100
100
|
else
|
101
|
-
|
102
|
-
@[key] = value
|
101
|
+
@[key] = value for key, value of options
|
103
102
|
|
104
103
|
@$container = $(form)
|
105
104
|
return if @$container.length == 0
|
@@ -108,7 +107,7 @@ class Joosy.Form extends Joosy.Module
|
|
108
107
|
@__delegateEvents()
|
109
108
|
|
110
109
|
method = @$container.get(0).getAttribute('method')?.toLowerCase()
|
111
|
-
if method && !['get', 'post'].
|
110
|
+
if method && !['get', 'post'].indexOf(method) != -1
|
112
111
|
@__markMethod method
|
113
112
|
@$container.attr 'method', 'POST'
|
114
113
|
|
@@ -155,7 +154,7 @@ class Joosy.Form extends Joosy.Module
|
|
155
154
|
|
156
155
|
#
|
157
156
|
# Links current form with given resource and sets values of form inputs from with it.
|
158
|
-
# Form will use
|
157
|
+
# Form will use given resource while doing invalidation routine.
|
159
158
|
#
|
160
159
|
# @param [Resource] resource Resource to fill fields with
|
161
160
|
# @param [Hash] options Options
|
@@ -166,7 +165,7 @@ class Joosy.Form extends Joosy.Module
|
|
166
165
|
# @option options [String] action Action URL for the form
|
167
166
|
#
|
168
167
|
fill: (resource, options) ->
|
169
|
-
resource = resource.build() if
|
168
|
+
resource = resource.build() if typeof(resource.build) == 'function'
|
170
169
|
@__resource = resource
|
171
170
|
|
172
171
|
if options?.decorator?
|
@@ -177,27 +176,29 @@ class Joosy.Form extends Joosy.Module
|
|
177
176
|
filler = (data, scope) =>
|
178
177
|
return if data.__joosy_form_filler_lock
|
179
178
|
data.__joosy_form_filler_lock = true
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
179
|
+
|
180
|
+
for property, val of data
|
181
|
+
do (property, val) =>
|
182
|
+
key = @concatFieldName scope, property
|
183
|
+
input = @$fields().filter("[name='#{key}']:not(:file),[name='#{inflection.underscore(key)}']:not(:file),[name='#{inflection.camelize(key, true)}']:not(:file)")
|
184
|
+
if input.length > 0
|
185
|
+
if input.is ':checkbox'
|
186
|
+
if val
|
187
|
+
input.attr 'checked', 'checked'
|
188
|
+
else
|
189
|
+
input.removeAttr 'checked'
|
190
|
+
else if input.is ':radio'
|
191
|
+
input.filter("[value='#{val}']").attr 'checked', 'checked'
|
187
192
|
else
|
188
|
-
input.
|
189
|
-
|
190
|
-
|
193
|
+
input.val val
|
194
|
+
if val instanceof Joosy.Resources.Array
|
195
|
+
for entity, i in val
|
196
|
+
filler entity.data, @concatFieldName(scope, "[#{property}_attributes][#{i}]")
|
197
|
+
else if val instanceof Joosy.Resources.REST
|
198
|
+
filler val.data, @concatFieldName(scope, "[#{property}_attributes]")
|
199
|
+
else if val?.constructor == Object || val instanceof Array
|
200
|
+
filler val, key
|
191
201
|
else
|
192
|
-
input.val val
|
193
|
-
if val instanceof Joosy.Resources.Array
|
194
|
-
for entity, i in val
|
195
|
-
filler entity.data, @concatFieldName(scope, "[#{property}_attributes][#{i}]")
|
196
|
-
else if val instanceof Joosy.Resources.REST
|
197
|
-
filler val.data, @concatFieldName(scope, "[#{property}_attributes]")
|
198
|
-
else if Object.isObject(val) || Object.isArray(val)
|
199
|
-
filler val, key
|
200
|
-
else
|
201
202
|
delete data.__joosy_form_filler_lock
|
202
203
|
|
203
204
|
filler data, resource.__entityName || options.resourceName
|
@@ -264,9 +265,10 @@ class Joosy.Form extends Joosy.Module
|
|
264
265
|
if !@error? || @error(errors) is true
|
265
266
|
errors = @__stringifyErrors(errors)
|
266
267
|
|
267
|
-
|
268
|
-
|
269
|
-
|
268
|
+
for field, notifications of errors
|
269
|
+
do (field, notifications) =>
|
270
|
+
input = @findField(field).addClass @invalidationClass
|
271
|
+
@notification? input, notifications
|
270
272
|
|
271
273
|
return errors
|
272
274
|
|
@@ -330,29 +332,30 @@ class Joosy.Form extends Joosy.Module
|
|
330
332
|
__stringifyErrors: (errors) ->
|
331
333
|
result = {}
|
332
334
|
|
333
|
-
errors = errors.errors if
|
335
|
+
errors = errors.errors if errors?.errors?.constructor == Object
|
334
336
|
|
335
|
-
|
336
|
-
|
337
|
-
|
337
|
+
for field, notifications of errors
|
338
|
+
do (field, notifications) =>
|
339
|
+
if @substitutions[field]?
|
340
|
+
field = @substitutions[field]
|
338
341
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
342
|
+
if notifications.constructor == Object || @isArrayOfObjects(notifications)
|
343
|
+
result[field+key] = value for key, value of @__foldInlineEntities(notifications)
|
344
|
+
|
345
|
+
else
|
346
|
+
if field.indexOf(".") != -1
|
347
|
+
splited = field.split '.'
|
348
|
+
field = splited.shift()
|
349
|
+
if @resourceName || @__resource
|
350
|
+
name = @resourceName || @__resource.__entityName
|
351
|
+
field = name + "[#{field}]"
|
352
|
+
field += "[#{f}]" for f in splited
|
350
353
|
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
+
else if @resourceName || @__resource
|
355
|
+
name = @resourceName || @__resource.__entityName
|
356
|
+
field = name + "[#{field}]"
|
354
357
|
|
355
|
-
|
358
|
+
result[field] = notifications
|
356
359
|
|
357
360
|
result
|
358
361
|
|
@@ -372,8 +375,8 @@ class Joosy.Form extends Joosy.Module
|
|
372
375
|
# @return [Hash]
|
373
376
|
#
|
374
377
|
__foldInlineEntities: (hash, scope="", result={}) ->
|
375
|
-
|
376
|
-
if
|
378
|
+
for key, value of hash
|
379
|
+
if value?.constructor == Object || @isArrayOfObjects(value)
|
377
380
|
@__foldInlineEntities(value, "#{scope}[#{key}]", result)
|
378
381
|
else
|
379
382
|
result["#{scope}[#{key}]"] = value
|
@@ -388,7 +391,7 @@ class Joosy.Form extends Joosy.Module
|
|
388
391
|
items = name.split('][')
|
389
392
|
first = items[0].split('[')
|
390
393
|
if first.length == 2
|
391
|
-
if first[0].
|
394
|
+
if first[0].length == 0
|
392
395
|
items.splice 0, 1, first[1]
|
393
396
|
else
|
394
397
|
items.splice 0, 1, first[0], first[1]
|
@@ -396,4 +399,8 @@ class Joosy.Form extends Joosy.Module
|
|
396
399
|
items
|
397
400
|
|
398
401
|
isArrayOfObjects: (array) ->
|
399
|
-
|
402
|
+
array instanceof Array && array.filter((elem) -> elem?.constructor != Object).length == 0
|
403
|
+
|
404
|
+
# AMD wrapper
|
405
|
+
if define?.amd?
|
406
|
+
define 'joosy/form', -> Joosy.Form
|
@@ -0,0 +1,241 @@
|
|
1
|
+
#
|
2
|
+
# @private
|
3
|
+
#
|
4
|
+
class Form
|
5
|
+
constructor: (@context, @resource, @options) ->
|
6
|
+
|
7
|
+
__extend: (options) ->
|
8
|
+
options.extendIds = @options.extendIds
|
9
|
+
options
|
10
|
+
|
11
|
+
for type in ['text', 'file', 'hidden', 'password']
|
12
|
+
do (type) =>
|
13
|
+
@::[type+'Field'] = (property, options={}) ->
|
14
|
+
@context[type+'Field'] @resource, property, @__extend(options)
|
15
|
+
|
16
|
+
label: (property, options={}, content='') ->
|
17
|
+
# (property, content) ->
|
18
|
+
if arguments.length == 2
|
19
|
+
content = options
|
20
|
+
options = {}
|
21
|
+
|
22
|
+
@context.label @resource, property, @__extend(options), content
|
23
|
+
|
24
|
+
radioButton: (property, tagValue, options={}) ->
|
25
|
+
@context.radioButton @resource, property, tagValue, @__extend(options)
|
26
|
+
|
27
|
+
textArea: (property, options={}) ->
|
28
|
+
@context.textArea @resource, property, @__extend(options)
|
29
|
+
|
30
|
+
checkBox: (property, options={}, checkedValue=1, uncheckedValue=0) ->
|
31
|
+
@context.checkBox @resource, property, @__extend(options), checkedValue, uncheckedValue
|
32
|
+
|
33
|
+
select: (property, selectOptions={}, options={}) ->
|
34
|
+
@context.select @resource, property, selectOptions, @__extend(options)
|
35
|
+
|
36
|
+
#
|
37
|
+
# Form helper
|
38
|
+
#
|
39
|
+
Joosy.helpers 'Application', ->
|
40
|
+
|
41
|
+
separateOptions = (options, keys) ->
|
42
|
+
attributes = {}
|
43
|
+
parameters = {}
|
44
|
+
|
45
|
+
for key, value of options
|
46
|
+
if keys.indexOf(key) != -1
|
47
|
+
parameters[key] = value
|
48
|
+
else
|
49
|
+
attributes[key] = value
|
50
|
+
|
51
|
+
[parameters, attributes]
|
52
|
+
|
53
|
+
#
|
54
|
+
# Generates main attributes of a single field for a form
|
55
|
+
#
|
56
|
+
# @param [String] resource Name of resource
|
57
|
+
# @param [Object] resource Instance of something that includes Joosy.Modules.Resources.Module
|
58
|
+
# @param [String] property Name of attribute the field is for
|
59
|
+
# @param [Boolean] extendIds Marks whether DOM id of a field should contain primary key of resource
|
60
|
+
# @param [String] idSuffix Suffix to append to DOM id
|
61
|
+
# @param [Hash] DOM attributes Initial set that should be extended
|
62
|
+
#
|
63
|
+
domify = (resource, property, extendIds, idSuffix, attributes) ->
|
64
|
+
if resource.__entityName? && resource.id?
|
65
|
+
resourceId = resource.id()
|
66
|
+
resource = resource.__entityName
|
67
|
+
|
68
|
+
unless attributes
|
69
|
+
attributes = {}
|
70
|
+
else
|
71
|
+
attributes = Joosy.Module.merge {}, attributes
|
72
|
+
|
73
|
+
attributes.name = resource
|
74
|
+
attributes.name += if property.match(/^\[.*\]$/) then property else "[#{property}]"
|
75
|
+
|
76
|
+
# Parameterizing property
|
77
|
+
property = property.replace(/[^a-z0-9\-_]+/gi, '_')
|
78
|
+
property = property.replace /^_+|_+$|(_)_+/g, '$1'
|
79
|
+
property = property.toLowerCase()
|
80
|
+
|
81
|
+
attributes.id = resource
|
82
|
+
attributes.id += "_#{resourceId}" if resourceId? && extendIds
|
83
|
+
attributes.id += "_#{property}"
|
84
|
+
attributes.id += "_#{idSuffix}" if idSuffix
|
85
|
+
|
86
|
+
attributes
|
87
|
+
|
88
|
+
#
|
89
|
+
# Generates input field
|
90
|
+
#
|
91
|
+
input = (type, resource, property, extendIds, idSuffix, attributes={}) =>
|
92
|
+
attributes.type = type
|
93
|
+
attributes = domify(resource, property, extendIds, idSuffix, attributes)
|
94
|
+
|
95
|
+
@tag 'input', attributes
|
96
|
+
|
97
|
+
#
|
98
|
+
# ======================================================================
|
99
|
+
#
|
100
|
+
|
101
|
+
#
|
102
|
+
# Instantiates a form builder
|
103
|
+
#
|
104
|
+
# @param [String] resource Name of resource
|
105
|
+
# @param [Object] resource Instance of something that includes Joosy.Modules.Resources.Module
|
106
|
+
# @param [Function] block Inline template that will be rendered as a form
|
107
|
+
# @param [Object] options
|
108
|
+
#
|
109
|
+
# @option options [Boolean] extendIds Marks if DOM ids of fields should include primary key of resource (default: false)
|
110
|
+
#
|
111
|
+
# @example
|
112
|
+
# != @formFor Resource, {extendIds: true}, (form) =>
|
113
|
+
# != form.textField 'property'
|
114
|
+
#
|
115
|
+
@formFor = (resource, options={}, block) ->
|
116
|
+
# (options, block) ->
|
117
|
+
if arguments.length == 2
|
118
|
+
block = options
|
119
|
+
options = {}
|
120
|
+
|
121
|
+
attributes = Joosy.Module.merge(options.html || {}, id: uuid)
|
122
|
+
uuid = Joosy.uuid()
|
123
|
+
form = new Form @, resource, options
|
124
|
+
|
125
|
+
@tag 'form', attributes, block?.call(@, form)
|
126
|
+
|
127
|
+
#
|
128
|
+
# Generates `label` tag
|
129
|
+
#
|
130
|
+
# @param [String] resource Name of resource
|
131
|
+
# @param [Object] resource Instance of something that includes Joosy.Modules.Resources.Module
|
132
|
+
# @param [String] property Attribute of a resource to use
|
133
|
+
# @param [Object] options
|
134
|
+
# @option options [Boolean] extendIds Marks if DOM ids of fields should include primary key of resource (default: false)
|
135
|
+
# @param [String] content Content of the label
|
136
|
+
#
|
137
|
+
@label = (resource, property, options={}, content='') ->
|
138
|
+
# (resource, property, content) ->
|
139
|
+
if arguments.length == 3
|
140
|
+
content = options
|
141
|
+
options = {}
|
142
|
+
|
143
|
+
[parameters, attributes] = separateOptions options, ['extendIds']
|
144
|
+
|
145
|
+
attributes.for = domify(resource, property, parameters.extendIds, '', attributes).id
|
146
|
+
|
147
|
+
@contentTag 'label', content, attributes
|
148
|
+
|
149
|
+
#
|
150
|
+
# Set of typical generators for basic inputs: textField, fileField, hiddenField, passwordField
|
151
|
+
#
|
152
|
+
for type in ['text', 'file', 'hidden', 'password']
|
153
|
+
do (type) =>
|
154
|
+
@[type+'Field'] = (resource, property, options={}) ->
|
155
|
+
[parameters, attributes] = separateOptions options, ['extendIds']
|
156
|
+
|
157
|
+
input type, resource, property, parameters.extendIds, '', attributes
|
158
|
+
|
159
|
+
#
|
160
|
+
# Generates a radio button
|
161
|
+
#
|
162
|
+
# @param [String] resource Name of resource
|
163
|
+
# @param [Object] resource Instance of something that includes Joosy.Modules.Resources.Module
|
164
|
+
# @param [String] property Attribute of a resource to use
|
165
|
+
# @param [Object] options
|
166
|
+
# @option options [Boolean] extendIds Marks if DOM ids of fields should include primary key of resource (default: false)
|
167
|
+
# @param [String] tagValue Value of the button
|
168
|
+
#
|
169
|
+
@radioButton = (resource, property, tagValue, options={}) ->
|
170
|
+
[parameters, attributes] = separateOptions(options, ['extendIds'])
|
171
|
+
|
172
|
+
attributes.value = tagValue
|
173
|
+
input 'radio', resource, property, options.extendIds, tagValue, attributes
|
174
|
+
|
175
|
+
#
|
176
|
+
# Generates a checkbox
|
177
|
+
#
|
178
|
+
# @param [String] resource Name of resource
|
179
|
+
# @param [Object] resource Instance of something that includes Joosy.Modules.Resources.Module
|
180
|
+
# @param [String] property Attribute of a resource to use
|
181
|
+
# @param [Object] options
|
182
|
+
# @option options [Boolean] extendIds Marks if DOM ids of fields should include primary key of resource (default: false)
|
183
|
+
# @param [String] checkedValue Value for the checked condition
|
184
|
+
# @param [String] uncheckedValue Value for the unchecked condition
|
185
|
+
#
|
186
|
+
@checkBox = (resource, property, options={}, checkedValue=1, uncheckedValue=0) ->
|
187
|
+
[parameters, attributes] = separateOptions(options, ['extendIds'])
|
188
|
+
|
189
|
+
spyAttributes = domify resource, property, parameters.extendIds, '', attributes
|
190
|
+
spy = @tag 'input', name: spyAttributes.name, value: uncheckedValue, type: 'hidden'
|
191
|
+
|
192
|
+
attributes.value = checkedValue
|
193
|
+
box = input 'checkbox', resource, property, parameters.extendIds, '', attributes
|
194
|
+
|
195
|
+
spy+box
|
196
|
+
|
197
|
+
#
|
198
|
+
# Generates a select
|
199
|
+
#
|
200
|
+
# @param [String] resource Name of resource
|
201
|
+
# @param [Object] resource Instance of something that includes Joosy.Modules.Resources.Module
|
202
|
+
# @param [String] property Attribute of a resource to use
|
203
|
+
# @param [Object] options
|
204
|
+
# @option options [Boolean] extendIds Marks if DOM ids of fields should include primary key of resource (default: false)
|
205
|
+
# @option options [String] value Sets current value of a select
|
206
|
+
# @option options [Boolean] includeBlank Marks if select should contain blank starting option
|
207
|
+
# @param [Object] selectOptions Options to build select with `{foo: 'bar'}`
|
208
|
+
# @param [Array] selectOptions Options to build select with `['foo', 'bar']`
|
209
|
+
#
|
210
|
+
@select = (resource, property, rawSelectOptions, options) ->
|
211
|
+
[parameters, attributes] = separateOptions(options, ['extendIds', 'value', 'includeBlank'])
|
212
|
+
|
213
|
+
if rawSelectOptions instanceof Array
|
214
|
+
selectOptions = rawSelectOptions
|
215
|
+
else
|
216
|
+
selectOptions = []
|
217
|
+
selectOptions.push [val, key] for key, val of rawSelectOptions
|
218
|
+
|
219
|
+
selectOptions.unshift ['', ''] if parameters.includeBlank
|
220
|
+
selectOptions = selectOptions.reduce (str, vals) =>
|
221
|
+
params = if (vals instanceof Array) then ['option', vals[0], { value: vals[1] }] else ['option', vals, {}]
|
222
|
+
if parameters.value == (if (vals instanceof Array) then vals[1] else vals)
|
223
|
+
params[2].selected = 'selected'
|
224
|
+
str += @contentTag.apply @, params
|
225
|
+
, ''
|
226
|
+
|
227
|
+
@contentTag 'select', selectOptions, domify(resource, property, parameters.extendIds, '', attributes)
|
228
|
+
|
229
|
+
#
|
230
|
+
# Generates a text area
|
231
|
+
#
|
232
|
+
# @param [String] resource Name of resource
|
233
|
+
# @param [Object] resource Instance of something that includes Joosy.Modules.Resources.Module
|
234
|
+
# @param [String] property Attribute of a resource to use
|
235
|
+
# @param [Object] options
|
236
|
+
# @option options [Boolean] extendIds Marks if DOM ids of fields should include primary key of resource (default: false)
|
237
|
+
# @option options [String] value Value of the text area
|
238
|
+
#
|
239
|
+
@textArea = (resource, property, options={}) ->
|
240
|
+
[parameters, attributes] = separateOptions(options, ['extendIds', 'value'])
|
241
|
+
@contentTag 'textarea', parameters.value, domify(resource, property, parameters.extendIds, '', attributes)
|
@@ -7,7 +7,9 @@
|
|
7
7
|
Joosy.helpers 'Routes', ->
|
8
8
|
|
9
9
|
@linkTo = (name='', url='', tagOptions={}) ->
|
10
|
-
|
10
|
+
|
11
|
+
# (url, tagOptions, block) ->
|
12
|
+
if typeof(tagOptions) == 'function'
|
11
13
|
block = tagOptions
|
12
14
|
[url, tagOptions] = [name, url]
|
13
15
|
name = block()
|
@@ -55,9 +55,9 @@ Joosy.helpers 'Application', ->
|
|
55
55
|
#
|
56
56
|
# Possible arguments variations:
|
57
57
|
# 1. @contentTag 'name', 'content'
|
58
|
-
# 2. @contentTag 'name',
|
59
|
-
# 3. @contentTag 'name', {},
|
60
|
-
# 4. @contentTag 'name', ->
|
58
|
+
# 2. @contentTag 'name', ->
|
59
|
+
# 3. @contentTag 'name', {}, ->
|
60
|
+
# 4. @contentTag 'name', {}, false, ->
|
61
61
|
#
|
62
62
|
# Example
|
63
63
|
# != @contentTag 'div', {class: 'foo'}, =>
|
@@ -66,20 +66,20 @@ Joosy.helpers 'Application', ->
|
|
66
66
|
@contentTag = (name, contentOrOptions=null, options=null, escape=true) ->
|
67
67
|
# This is a bit painfull but this is
|
68
68
|
# how we emulate Ruby block with lambda :(
|
69
|
-
if
|
69
|
+
if typeof(contentOrOptions) == 'string'
|
70
70
|
options ||= {}
|
71
71
|
content = contentOrOptions
|
72
|
-
else if
|
73
|
-
|
72
|
+
else if typeof(contentOrOptions) == 'function'
|
73
|
+
options = {}
|
74
|
+
content = contentOrOptions()
|
75
|
+
else
|
76
|
+
if typeof(options) == 'function'
|
74
77
|
escape = true
|
75
78
|
content = options()
|
76
79
|
else
|
77
80
|
escape = options
|
78
81
|
content = escape()
|
79
82
|
options = contentOrOptions
|
80
|
-
else
|
81
|
-
options = {}
|
82
|
-
content = contentOrOptions()
|
83
83
|
|
84
84
|
element = document.createElement name
|
85
85
|
temp = document.createElement 'div'
|
data/source/joosy/joosy.coffee
CHANGED
@@ -139,17 +139,15 @@
|
|
139
139
|
#
|
140
140
|
buildUrl: (url, params) ->
|
141
141
|
paramsString = []
|
142
|
-
|
143
|
-
Object.each params, (key, value) ->
|
144
|
-
paramsString.push "#{key}=#{value}"
|
142
|
+
paramsString.push "#{key}=#{value}" for key, value of params
|
145
143
|
|
146
144
|
hash = url.match(/(\#.*)?$/)[0]
|
147
145
|
url = url.replace /\#.*$/, ''
|
148
|
-
if
|
146
|
+
if paramsString.length != 0 && url.indexOf('?') == -1
|
149
147
|
url = url + "?"
|
150
148
|
|
151
149
|
paramsString = paramsString.join '&'
|
152
|
-
if
|
150
|
+
if paramsString.length > 0 && url[url.length-1] != '?'
|
153
151
|
paramsString = '&' + paramsString
|
154
152
|
|
155
153
|
url + paramsString + hash
|
data/source/joosy/module.coffee
CHANGED
@@ -19,7 +19,7 @@ class Joosy.Module
|
|
19
19
|
# @return [String]
|
20
20
|
#
|
21
21
|
@__className: (klass) ->
|
22
|
-
unless
|
22
|
+
unless typeof(klass) == 'function'
|
23
23
|
klass = klass.constructor
|
24
24
|
|
25
25
|
if klass.name?
|
@@ -61,7 +61,7 @@ class Joosy.Module
|
|
61
61
|
camelized = feature.charAt(0).toUpperCase() + feature.slice(1)
|
62
62
|
chained = "#{method}Without#{camelized}"
|
63
63
|
|
64
|
-
action = @::[action] unless
|
64
|
+
action = @::[action] unless typeof(action) == 'function'
|
65
65
|
|
66
66
|
@::[chained] = @::[method]
|
67
67
|
@::[method] = action
|
@@ -91,14 +91,19 @@ class Joosy.Module
|
|
91
91
|
# @param [Object] destination Object to extend
|
92
92
|
# @param [Object] source Source of new properties
|
93
93
|
# @param [Boolean] unsafe Determines if we should rewrite destination properties
|
94
|
+
# @param [Boolean] deep Whether merge should go down recursively into nested objects
|
94
95
|
#
|
95
96
|
# @return [Object] The new and mighty destination Object
|
96
97
|
#
|
97
|
-
@merge: (destination, source, unsafe=true) ->
|
98
|
+
@merge: (destination, source, unsafe=true, deep=false) ->
|
98
99
|
for key, value of source
|
99
100
|
if source.hasOwnProperty(key)
|
100
101
|
if unsafe || !destination.hasOwnProperty(key)
|
101
|
-
|
102
|
+
if deep && value.constructor == Object
|
103
|
+
destination[key] = {} unless destination[key]?.constructor == Object
|
104
|
+
Joosy.Module.merge destination[key], value
|
105
|
+
else
|
106
|
+
destination[key] = value
|
102
107
|
destination
|
103
108
|
|
104
109
|
#
|