pinkman 0.9.9.9.11 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 542f0294f57dc31831c1f3edf26e84eff18a8b52c12dc590a5829e4e32947ad5
4
- data.tar.gz: bd5f4831742985e4f214d7a67d4863297cacf8ec9065f8254e0e3e3d1acc0863
3
+ metadata.gz: 99be758a6c0fd2b3b91ded4b49b176b0084daa153008390ce2d7a0301b763339
4
+ data.tar.gz: 7652fe78dbacada668465d7aa3abc24789439f87b8f9d32b8e861dc9467f3dd9
5
5
  SHA512:
6
- metadata.gz: f008682f5279f37b1dfc5007cf5bf185c9dc9cac65226ac709cfd506a93e291b5a3fcd6f4c107b321a87662e38d3d33a2e5deb2d07325e0854de3b76ebf779f1
7
- data.tar.gz: 12d8a131e75349686ef9168c6290f51c22684c3900d17ce82aa06c3c605eaca36aae37d18ea2ba74f1c9be19b21eae09d07a9af521362b2f3367ac3941f07f29
6
+ metadata.gz: b200b9dc96f6cdc0ff71a583d16e21dd65d953100f465fef9e2c0716009ffdc67f5226962e4fd52b5be931988bc9834a26f68e6793e8d949a7818a115ee529fb
7
+ data.tar.gz: dcaca3c9a82cec48a1304ed40d0be1efb1ed480b0ecfeef432c611bfe764c83797a387fea888c10b121699c7a1f5789a2ee428b1f40d0cbff45ea748cc57e83a
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Pinkman
2
2
 
3
- Rails js framework.
3
+ Rails js framework. V1 RC.
4
4
 
5
5
  ## Installation
6
6
 
@@ -10,9 +10,19 @@ class window.PinkmanCache
10
10
 
11
11
  @has: (name) ->
12
12
  @_caching[name]?
13
+
14
+ @getOrInsert: (name, value) =>
15
+ if @has(name)
16
+ # console.log "has: #{name}"
17
+ return(@get(name))
18
+ else
19
+ # console.log "caching: #{name}"
20
+ return(@cache(name, value))
21
+
22
+ @get: (name, callback) ->
23
+ callback(@_caching[name]) if $p.isFunction(callback)
24
+ return(@_caching[name])
13
25
 
14
- @get: (name) ->
15
- @_caching[name]
16
26
 
17
27
  $(document).ready ->
18
28
  window.$c = window.PinkmanCache
@@ -1,6 +1,9 @@
1
1
  class window.PinkmanCollection extends window.PinkmanCommon
2
2
 
3
3
  @pinkmanType = 'collection'
4
+
5
+ @objectClass: ->
6
+ @firstInstanceOrInitialize().config.memberClass
4
7
 
5
8
  config:
6
9
  memberClass: PinkmanObject
@@ -10,7 +13,14 @@ class window.PinkmanCollection extends window.PinkmanCommon
10
13
  @isCollection = true
11
14
  @pinkmanType = 'collection'
12
15
  @collection = []
16
+ if @constructor.name? and @constructor.name!='PinkmanCollection'
17
+ if $p.isArray(@constructor.instances)
18
+ @constructor.instances.push(this)
19
+ else
20
+ @constructor.instances = [this]
21
+
13
22
  Pinkman.collections.push(this)
23
+
14
24
 
15
25
  # Desc: return an array of all members
16
26
  # this behaviour makes life easier... trust me
@@ -230,7 +240,7 @@ class window.PinkmanCollection extends window.PinkmanCommon
230
240
  i = @collection.indexOf(value)
231
241
  @collection.splice(i,1)
232
242
  else
233
- console.log 'js'
243
+ # console.log 'js'
234
244
  i = @collection.indexOf object
235
245
  @collection.splice(i,1)
236
246
  value = object
@@ -529,56 +539,40 @@ class window.PinkmanCollection extends window.PinkmanCommon
529
539
  # string: search
530
540
  # obj: select (cache) / where (server)
531
541
  # function: select
532
-
533
- @get: (query, callback) ->
534
- @startCaching()
535
-
536
- # query md5
537
- query_md5 = md5(JSON.stringify(query) + @_name_md5)
538
-
539
- if $c.has(query_md5)
540
- @handleGetCollection($c.get(query_md5),callback)
541
- else
542
- # TRYING TO FIND IN CACHE
543
- $c.get(@_name_md5).select query, (cache) =>
544
- # CACHED FOUND
545
- if cache.any()
546
- # console.log 'cached'
547
- @handleGetCollection(cache,callback)
548
-
549
- # CACHED VERSION NOT FOUND -> ASK SERVER
550
- else
551
- # console.log 'server'
552
- col = new this
553
- obj = new col.config.memberClass
554
- params = new Object
555
- params.scope = Pinkman.scope(obj)
556
- params.query = query
557
- Pinkman.ajax.get
558
- url: obj.api('get')
559
- data: params
560
- complete: (response) =>
561
- col.fetchFromArray(response)
562
- # PERFOMING INSTANCES CACHE
563
- col.each (obj) =>
564
- $c.get(@_name_md5).push(obj)
565
-
566
- # CACHING THIS QUERY
567
- $c.cache(query_md5,col)
568
-
569
- callback(col) if $p.isFunction(callback)
570
- return(col)
571
542
 
572
- @handleGetCollection: (fetchedCollection,callback) ->
573
- col = new this
574
- col.collection = fetchedCollection.collection
575
- callback(col) if $p.isFunction(callback)
576
- return(col)
577
-
578
- @one: (query,callback) ->
579
- @get(query, (col) ->
580
- callback(col.first()) if col.any() and $p.isFunction(callback)
581
- ).first()
543
+ @get: (options) ->
544
+ if $p.isObject(options) and (options.query? or options.params?) and $p.isFunction(options.callback)
545
+ @startCaching()
546
+ options.cache = yes unless options.cache?
547
+ query = Pinkman.mergeObjects(options.scope, Pinkman.mergeObjects(options.query, options.params))
548
+ query_md5 = md5(JSON.stringify(query) + @_name_md5)
549
+ if options.cache and $c.has(query_md5)
550
+ $c.get(query_md5, options.callback)
551
+ else
552
+ col = new this
553
+ obj = new col.config.memberClass
554
+ params = new Object
555
+ params.scope = options.scope || Pinkman.scope(obj)
556
+ params.query = options.query
557
+ params = Pinkman.mergeObjects(params, options.params)
558
+ Pinkman.ajax.get
559
+ url: options.url || obj.api('get')
560
+ data: params
561
+ complete: (response) =>
562
+ col.fetchFromArray(response)
563
+ $c.cache(query_md5, col)
564
+ options.callback(col)
565
+ else
566
+ throw "Pinkman Error: collection.get invalid options #{options.toString()}"
567
+
568
+ @one: (options) ->
569
+ if $p.isObject(options) and $p.isFunction(options.callback)
570
+ args = Pinkman.dup(options)
571
+ args.callback = (col) ->
572
+ return(options.callback(col.first()))
573
+ @get(args)
574
+ else
575
+ return(throw("Pinkman Error: #{this.toString()}.one called with wrong arguments."))
582
576
 
583
577
  @single: (args...) ->
584
578
  @one(args...)
@@ -592,9 +586,21 @@ class window.PinkmanCollection extends window.PinkmanCommon
592
586
  # Desc: Fetch records from API_URL
593
587
  # request: get /api/API_URL/
594
588
  # in rails: api::controller#index
595
- fetch: (callback = '') ->
596
- @fetchFromUrl url: @api(), callback: callback
597
-
589
+ fetch: (args...) ->
590
+ switch args.length
591
+ when 1
592
+ if $p.isFunction(args[0])
593
+ callback = args[0]
594
+ @fetchFromUrl url: @api(), callback: callback, scope: 'public'
595
+
596
+ else if $p.isObject(args[0])
597
+ options = args[0]
598
+ @fetchFromUrl url: (options.url || @api()), callback: options.callback, scope: options.scope
599
+ when 2
600
+ scope = args[0]
601
+ callback = args[1]
602
+ @fetchFromUrl url: @api(), callback: callback, scope: scope
603
+
598
604
  # Desc: Fetch records from another action of this model api
599
605
  # request: get /api/API_URL/:action/#id
600
606
  # in rails: api::controller#action
@@ -615,21 +621,21 @@ class window.PinkmanCollection extends window.PinkmanCommon
615
621
  fetchFromUrl: (options) ->
616
622
  if options? and typeof options == 'object' and options.url?
617
623
  options_md5 = md5(JSON.stringify(options) + @className())
618
- if $c.has(options_md5)
619
- response = $c.get(options_md5)
620
- @handleFetchResponse(response,options)
621
- else
622
- if Pinkman.hasScope(this)
623
- options.params = new Object unless options.params?
624
- options.params.scope = Pinkman.scope(this)
625
- @doneFetching = null
626
- @fetchingFrom = options.url
627
- Pinkman.ajax.get
628
- url: Pinkman.json2url(options.url,options.params)
629
- complete: (response) =>
630
- $c.cache(options_md5,response)
631
- @handleFetchResponse(response,options)
632
- return(this)
624
+ options.params = new Object unless options.params?
625
+ options.cache = yes unless options.cache?
626
+ if options.scope?
627
+ options.params.scope = options.scope
628
+ else
629
+ throw 'Pinkman Error: Trying to fetch without a specified scope'
630
+
631
+ @doneFetching = null
632
+ @fetchingFrom = options.url
633
+ Pinkman.ajax.get
634
+ url: Pinkman.json2url(options.url, options.params)
635
+ complete: (response) =>
636
+ $c.cache(options_md5, response) if options.cache
637
+ @handleFetchResponse(response, options)
638
+ return(this)
633
639
 
634
640
  handleFetchResponse: (response,options) ->
635
641
  @constructor.startCaching()
@@ -685,8 +691,17 @@ class window.PinkmanCollection extends window.PinkmanCommon
685
691
  # request: get /api/API_URL/search?query=YOUR_QUERY
686
692
  # in rails: api::controller#search
687
693
  # assume models to have a Model.search("YOUR_QUERY") method.
688
- search: (query,callback='') ->
694
+ search: (args...) ->
689
695
  @removeAll()
690
- @fetchFromUrl { url: @api() + 'search', params: {query: query}, callback: callback }
696
+ if args.length == 2
697
+ [query, callback] = args
698
+ else if args.length == 1 and $p.isObject(args[0])
699
+ options = args[0]
700
+ query = options.query
701
+ callback = options.callback
702
+ scope = options.scope || 'public'
703
+ return(@fetchFromUrl { url: @api() + 'search', params: {query: query}, callback: callback, scope: (scope || 'public') })
704
+
705
+
691
706
 
692
707
  window.Pinkman.collection = window.PinkmanCollection
@@ -22,11 +22,18 @@ class window.PinkmanCommon
22
22
  @isInstance: (object) ->
23
23
  object.constructor is this
24
24
 
25
+ @firstInstanceOrInitialize: ->
26
+ obj = if $p.isArray(@instances) and @instances.length >= 1 then @instances[0] else new this
27
+
28
+ @api: (args...) ->
29
+ @firstInstanceOrInitialize().api(args...)
30
+
25
31
  initialize: (attributesObject) ->
26
32
  if typeof attributesObject == 'object'
27
33
  for key, value of attributesObject
28
34
  @set(key,value) if PinkmanObject.privateAttributes.indexOf(key) is -1
29
-
35
+
36
+
30
37
  # Desc: return api url path
31
38
  api: (paths...) ->
32
39
  if @config? and @config.api?
@@ -145,6 +152,28 @@ class window.PinkmanCommon
145
152
  @append
146
153
  template: options + '-template'
147
154
  target: options
155
+
156
+ prepend: (options) ->
157
+ if options? and typeof options == 'object' and options.target?
158
+ options.template = options.target + '-template' unless options.template? and options.template != ''
159
+ newOptions = new Object
160
+ for k,v of options
161
+ newOptions[k] = v if k != 'target' and k != 'callback'
162
+ newOptions.reRender = no
163
+ target = options.target
164
+ wrapIn = options.wrapIn
165
+ newOptions.object = this
166
+ newOptions.callback = (object,content) ->
167
+ if wrapIn?
168
+ $('#'+target).prepend("<div class='#{wrapIn}'>#{content}</div>")
169
+ else
170
+ $('#'+target).prepend(content)
171
+ options.callback(object,content) if options.callback? and typeof options.callback == 'function'
172
+ Pinkman.render(newOptions)
173
+ else if options? and Pinkman.isString(options)
174
+ @prepend
175
+ template: options + '-template'
176
+ target: options
148
177
 
149
178
  _queue: (options) ->
150
179
  options.id = options.template
@@ -152,7 +181,7 @@ class window.PinkmanCommon
152
181
  @renderQueue.directPush(options)
153
182
 
154
183
  hasError: ->
155
- @errors?
184
+ return(this) if @errors?
156
185
 
157
186
  hasErrors: ->
158
187
  @hasError()
@@ -32,11 +32,8 @@ class window.PinkmanController extends window.PinkmanObject
32
32
  '#' + @id
33
33
 
34
34
  setParams: (params) ->
35
- query = location.search.substring(1);
36
- if query? and query!=''
37
- @params = JSON.parse('{"' + decodeURI(query).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}')
38
- else
39
- @params = new Object
35
+ # console.log params
36
+ @params = new Object
40
37
 
41
38
  (@params[k] = v) for k,v of params if params? and typeof params == 'object'
42
39
  @params
@@ -98,7 +95,7 @@ class window.PinkmanController extends window.PinkmanObject
98
95
  # but... in a few ocasions, the developer must have the capability to exclude certain attributes from this binding.
99
96
  # thats when the "except" option comes in
100
97
  # maybe a "only" option is going to be implemented in the near future
101
- bindAllSelector: (id,options) ->
98
+ bindAllSelector: (id, options) ->
102
99
  except = options.except if $p.isObject(options) and options.except?
103
100
  selector = "##{@id} form [data-action], ##{@id} .form [data-action]"
104
101
 
@@ -130,7 +127,7 @@ class window.PinkmanController extends window.PinkmanObject
130
127
 
131
128
  PinkmanAction.define
132
129
  id: "#{@pinkey}-bindAll"
133
- selector: @bindAllSelector(@id,options)
130
+ selector: @bindAllSelector(@id, options)
134
131
  eventName: ['change','keyup']
135
132
  controller: this
136
133
  callback: (obj,$j) ->
@@ -162,7 +159,7 @@ class window.PinkmanController extends window.PinkmanObject
162
159
 
163
160
  # === Autocomplete ===
164
161
 
165
- # -- Usage: autocomplete(input_name,options)
162
+ # -- Usage: autocomplete(input_name, options)
166
163
 
167
164
  # -- Overview
168
165
  # 1: User types something
@@ -171,7 +168,7 @@ class window.PinkmanController extends window.PinkmanObject
171
168
  # 4: Pinkman sends the selected record to callback function
172
169
 
173
170
  # -- Parameters & Options
174
- # @autocomplete(attribute,options)
171
+ # @autocomplete(attribute, options)
175
172
  # options:
176
173
  # with: [collection]
177
174
  # pinkman collection responsible for filtering/searching the results
@@ -179,9 +176,19 @@ class window.PinkmanController extends window.PinkmanObject
179
176
  # method: [search|yourCustomMethod]
180
177
  # Search is the default. Anythings that filters by a 'query'.
181
178
  # You can define a yourCustomMethod inside the collection model like this:
182
- # yourCustomMethod: (user_query, callback) ->
183
- # -- perform a selection based on user_query
184
- # callback(this) if $p.isFunction(callback)
179
+ # yourCustomMethod: (options) ->
180
+
181
+ # 1. perfom some filter on the collection based on options.query
182
+
183
+ # 2. don't forget to verify if user can access the requested scope in case of api comunications
184
+
185
+ # 3. call options.callback whenever the collection is ready
186
+
187
+ # options object explanation:
188
+ # options.query: what user is trying to find/search
189
+ # options.scope: scope user is trying to access (in case of api comunications)
190
+ # options.callback: call this function with the filtered collection when it's ready
191
+
185
192
 
186
193
  # template: [template-id] (optional)
187
194
  # Any template that has a 'select-attribute' action
@@ -205,6 +212,7 @@ class window.PinkmanController extends window.PinkmanObject
205
212
  # variables // user options // default options
206
213
  collection = options.with
207
214
  callback = options.call
215
+ scope = if options.scope? then options.scope else 'public'
208
216
  template = if options.template? then options.template else "#{attr_name}-autocomplete"
209
217
  target = if options.target? then options.target else "#{attr_name}-autocomplete"
210
218
  method = if options.method? then options.method else 'search'
@@ -214,6 +222,9 @@ class window.PinkmanController extends window.PinkmanObject
214
222
  wait = if options.wait? then options.wait else 0.75
215
223
  waitTimerName = "#{attr_name}AutocompleteTimer"
216
224
 
225
+
226
+ # collection.set('_autocompleting', attr_name)
227
+
217
228
  # hide initially
218
229
  $("##{target}").hide() if autoHide
219
230
 
@@ -236,23 +247,26 @@ class window.PinkmanController extends window.PinkmanObject
236
247
  window[waitTimerName] = $p.sleep wait, =>
237
248
 
238
249
  # calls the filter method (search)
239
- collection[method] obj[attr_name], (collection) ->
250
+ collection[method]
251
+ query: obj[attr_name]
252
+ scope: scope
253
+ callback: (collection) ->
240
254
 
241
- # render results
242
- collection.render
243
- template: template
244
- target: target
245
- callback: ->
246
- # Hide or show autocomplete
247
- if autoHide
248
- if obj[attr_name]? and obj[attr_name] != ''
249
- $("##{target}").fadeIn()
250
- else
251
- $("##{target}").fadeOut()
252
-
253
- # Set the autocomplete target width to same as the input
254
- if autoWidth
255
- $("##{target}").width($("input[name='#{attr_name}']").innerWidth() - ($("##{target}").innerWidth() - $("##{target}").width()))
255
+ # render results
256
+ collection.render
257
+ template: template
258
+ target: target
259
+ callback: ->
260
+ # Hide or show autocomplete
261
+ if autoHide
262
+ if obj[attr_name]? and obj[attr_name] != ''
263
+ $("##{target}").fadeIn()
264
+ else
265
+ $("##{target}").fadeOut()
266
+
267
+ # Set the autocomplete target width to same as the input
268
+ if autoWidth
269
+ $("##{target}").width($("input[name='#{attr_name}']").innerWidth() - ($("##{target}").innerWidth() - $("##{target}").width()))
256
270
 
257
271
  # user chooses something and click
258
272
  @action "select-#{attr_name}", 'click', (args...) =>
@@ -13,6 +13,9 @@ class window.PinkmanObject extends window.PinkmanCommon
13
13
  @constructor.instances = [this]
14
14
  Pinkman.objects.push(this)
15
15
 
16
+ @alias: (newFunc, existingFunc) ->
17
+ @prototype[newFunc] = @prototype[existingFunc]
18
+
16
19
  @sync: (obj,callback,each) ->
17
20
  if $p.isArray(@instances) and $p.isObject(obj) and obj.id?
18
21
  length = @instances.length
@@ -23,10 +26,10 @@ class window.PinkmanObject extends window.PinkmanCommon
23
26
  if obj.isPink then instance.assign(obj.attributes()) else instance.assign(obj)
24
27
  each(instance) if $p.isFunction(each) and obj.pinkey != instance.pinkey
25
28
  callback() if (length == i) and $p.isFunction(callback)
26
-
27
29
  else
28
30
  true
29
-
31
+
32
+
30
33
  # Desc: assign attributes from a pure javascript object
31
34
  # Usage: a.assign( {attribute: value} )
32
35
  assign: (obj) ->
@@ -42,7 +45,7 @@ class window.PinkmanObject extends window.PinkmanCommon
42
45
 
43
46
  # Desc: returns a javascript object version of this
44
47
  # Usage: a.attributes() #-> {key: value, key: value, ...}
45
- attributes: () ->
48
+ attributes: ->
46
49
  a = new Object
47
50
  for k,v of this
48
51
  if PinkmanObject.privateAttributes.indexOf(k) == -1 and typeof v != 'function'
@@ -54,16 +57,22 @@ class window.PinkmanObject extends window.PinkmanCommon
54
57
 
55
58
  # Desc: json version of this
56
59
  # desc: used in api comunications
57
- json: () ->
60
+ json: ->
61
+ (@pack(toBePacked) for toBePacked in @_pack_list) if $p.isArray(@_pack_list)
58
62
  a = new Object
59
63
  for k,v of this
60
- if PinkmanObject.privateAttributes.indexOf(k) == -1 and typeof v != 'function'
61
- if (v? and typeof v == 'object' and v.isPink)
62
- # do not include collections in json format since they are supposed to have their own model/api
63
- a[k] = v.json() unless v.isCollection
64
- else
65
- a[k] = v
64
+ a[k] = v if PinkmanObject.privateAttributes.indexOf(k) == -1 and not $p.isFunction(v) and not $p.isObject(v)
66
65
  return a
66
+
67
+ # Desc: prepare for rails accept nested attributes
68
+ pack: (attr) ->
69
+ @_pack_list = [] unless @_pack_list?
70
+ @_pack_list.push(attr) if @_pack_list.indexOf(attr) == -1
71
+ if $p.isPink(this[attr])
72
+ pack = this[attr]
73
+ attrs = pack.json()
74
+ @set("#{attr}_attributes[#{k}]", v) for k,v of attrs
75
+ attrs
67
76
 
68
77
  # Desc: returns a array of attributes keys
69
78
  # Usage:
@@ -73,7 +82,7 @@ class window.PinkmanObject extends window.PinkmanCommon
73
82
  Object.keys(@attributes())
74
83
 
75
84
  # Desc: Alias for attributesKeys
76
- keys: () ->
85
+ keys: ->
77
86
  @attributesKeys()
78
87
 
79
88
  extract: (args...) ->
@@ -82,7 +91,7 @@ class window.PinkmanObject extends window.PinkmanCommon
82
91
  return(a)
83
92
 
84
93
 
85
- toString: () ->
94
+ toString: ->
86
95
  array = []
87
96
  array.push("(#{@className()})")
88
97
  for a in @attributesKeys()
@@ -14,6 +14,9 @@ class window.Pinkman
14
14
 
15
15
  # --- predicate
16
16
 
17
+ @isPink: (obj) ->
18
+ @isObject(obj) && obj.isPink
19
+
17
20
  @isNumber: (n) ->
18
21
  !isNaN(parseFloat(n)) && isFinite(n)
19
22
 
@@ -38,8 +41,25 @@ class window.Pinkman
38
41
  @sleep = (s,callback) ->
39
42
  ms = s*1000
40
43
  window['_sleeping'] = setTimeout(callback,ms)
41
-
42
-
44
+
45
+
46
+ @mergeObjects: (a, b) ->
47
+ if a? and @isObject(a)
48
+ clone = @dup(a)
49
+ else
50
+ clone = new Object
51
+ if b? and @isObject(b)
52
+ for k,v of b
53
+ clone[k] = v
54
+ return(clone)
55
+
56
+ @dup: (a) ->
57
+ if @isFunction(Object.assign)
58
+ if @isObject(a) then Object.assign({}, a) else throw("Pinkman Error: can't dup #{a.toString()}. It is not an object.")
59
+ else
60
+ if @isObject(a) then jQuery.extend({}, a) else throw("Pinkman Error: can't dup #{a.toString()}. It is not an object.")
61
+
62
+
43
63
  # --- tools and facilities
44
64
 
45
65
  @top: ->
@@ -100,6 +120,12 @@ class window.Pinkman
100
120
  else
101
121
  ''
102
122
 
123
+ @padNum: (number, size=2) ->
124
+ output = number.toString()
125
+ output = '0' + output while (output.length < size)
126
+ output
127
+
128
+
103
129
  @objToArray: (obj) ->
104
130
  i = 0
105
131
  a = []
@@ -123,6 +149,28 @@ class window.Pinkman
123
149
 
124
150
  @calledFunctions = []
125
151
 
152
+
153
+ @each: (array, exec, callback) ->
154
+ if @isArray(array) and @isFunction(exec)
155
+ l = array.length
156
+ i = 0
157
+ for item in array
158
+ exec(item)
159
+ i++
160
+ callback(array) if i == l and @isFunction(callback)
161
+
162
+ else
163
+ throw "Pinkman.each: wrong args: expect a array, apply function and a callback function. Got #{arguments}."
164
+
165
+ @map: (array, exec, callback) ->
166
+ if @isArray(array) and @isFunction(exec)
167
+ outputArray = []
168
+ @each array, (item) =>
169
+ outputArray.push(exec(item))
170
+ , =>
171
+ callback(outputArray) if @isFunction(callback)
172
+ return(outputArray)
173
+
126
174
  # --- Scope
127
175
 
128
176
  @scope: (obj) ->
@@ -80,7 +80,12 @@ Pinkman.template_engines =
80
80
  partialAdapter: (templateBody) ->
81
81
  if templateBody? and templateBody != ''
82
82
  partialRegex = /{{(?:\s)*partial\((?:\s)*((?:\w|-)*)(?:\s)*\)(?:\s)*}}/gm
83
- templateBody.replace(partialRegex,@partialInception)
83
+ i = 0
84
+ while partialRegex.test(templateBody)
85
+ # i++
86
+ # console.log("partial-inception level: #{i}")
87
+ templateBody = templateBody.replace(partialRegex, @partialInception)
88
+ return(templateBody)
84
89
  else
85
90
  ''
86
91
 
@@ -92,7 +97,7 @@ Pinkman.template_engines =
92
97
  if p.length
93
98
  p.html()
94
99
  else
95
- match
100
+ throw "Pinkman: Partial Error - Could not find partial named #{id}."
96
101
 
97
102
  context: (options) ->
98
103
  options.object = options.context if options.context?
@@ -110,10 +115,28 @@ Pinkman.template_engines =
110
115
  $('#' + options.target).html(content)
111
116
  $('#' + options.target).attr('data-pinkey',options.object.pinkey) if options.object? and typeof options.object == 'object' and options.object.isPink
112
117
 
113
- # checks and sync select options with the pinkman object
118
+ # checks and sync select, checkboxes and radiobuttons options with the pinkman object
119
+ # select
114
120
  $("##{options.target} select").each (i,el) ->
115
121
  obj = Pinkman.get($(el).data('pinkey'))
116
122
  $(el).find("option[value='#{obj[$(el).attr('name')]}']").attr('selected','selected')
123
+
124
+ # checkboxes and radios
125
+ $("##{options.target} input[type='checkbox'], ##{options.target} input[type='radio']").each (i,el) ->
126
+ obj = Pinkman.get($(el).data('pinkey'))
127
+ $el = $(el)
128
+ attr = $el.attr('name')
129
+ value = $el.attr('value')
130
+ # console.log attr
131
+ # console.log value.toString()
132
+ # console.log obj[attr].toString()
133
+
134
+ if attr? and value? and obj? and obj[attr]? and obj[attr] and obj[attr].toString() == value.toString()
135
+ $el.attr('checked', yes)
136
+ else
137
+ $el.attr('checked', no)
138
+
139
+
117
140
 
118
141
  render: (options) ->
119
142