pinkman 0.9.9.9.11 → 1.0.0

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.
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