joosy 0.1.0.RC1 → 0.1.0.RC2

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 (47) hide show
  1. data/Gemfile +1 -0
  2. data/Gemfile.lock +8 -1
  3. data/MIT-LICENSE +2 -2
  4. data/README.md +89 -0
  5. data/app/assets/javascripts/joosy/core/application.js.coffee +25 -5
  6. data/app/assets/javascripts/joosy/core/form.js.coffee +212 -22
  7. data/app/assets/javascripts/joosy/core/helpers.js.coffee +11 -1
  8. data/app/assets/javascripts/joosy/core/joosy.js.coffee +22 -17
  9. data/app/assets/javascripts/joosy/core/layout.js.coffee +17 -7
  10. data/app/assets/javascripts/joosy/core/modules/container.js.coffee +19 -15
  11. data/app/assets/javascripts/joosy/core/modules/events.js.coffee +10 -9
  12. data/app/assets/javascripts/joosy/core/modules/filters.js.coffee +16 -12
  13. data/app/assets/javascripts/joosy/core/modules/log.js.coffee +8 -5
  14. data/app/assets/javascripts/joosy/core/modules/module.js.coffee +31 -21
  15. data/app/assets/javascripts/joosy/core/modules/renderer.js.coffee +114 -51
  16. data/app/assets/javascripts/joosy/core/modules/time_manager.js.coffee +2 -2
  17. data/app/assets/javascripts/joosy/core/modules/widgets_manager.js.coffee +10 -10
  18. data/app/assets/javascripts/joosy/core/page.js.coffee +31 -21
  19. data/app/assets/javascripts/joosy/core/preloader.js.coffee +3 -3
  20. data/app/assets/javascripts/joosy/core/resource/collection.js.coffee +137 -0
  21. data/app/assets/javascripts/joosy/core/resource/generic.js.coffee +178 -13
  22. data/app/assets/javascripts/joosy/core/resource/rest.js.coffee +167 -44
  23. data/app/assets/javascripts/joosy/core/resource/rest_collection.js.coffee +100 -32
  24. data/app/assets/javascripts/joosy/core/router.js.coffee +23 -25
  25. data/app/assets/javascripts/joosy/core/templaters/rails_jst.js.coffee +19 -3
  26. data/app/assets/javascripts/joosy/core/widget.js.coffee +7 -9
  27. data/app/assets/javascripts/joosy/preloaders/caching.js.coffee +117 -57
  28. data/app/assets/javascripts/joosy/preloaders/inline.js.coffee +23 -24
  29. data/app/helpers/joosy/sprockets_helper.rb +1 -1
  30. data/lib/joosy/forms.rb +2 -12
  31. data/lib/joosy/rails/version.rb +1 -1
  32. data/lib/rails/generators/joosy/templates/app/pages/template.js.coffee +1 -1
  33. data/lib/rails/generators/joosy/templates/app/resources/template.js.coffee +1 -1
  34. data/spec/javascripts/joosy/core/form_spec.js.coffee +55 -12
  35. data/spec/javascripts/joosy/core/layout_spec.js.coffee +1 -1
  36. data/spec/javascripts/joosy/core/modules/container_spec.js.coffee +0 -1
  37. data/spec/javascripts/joosy/core/modules/module_spec.js.coffee +1 -1
  38. data/spec/javascripts/joosy/core/modules/renderer_spec.js.coffee +39 -3
  39. data/spec/javascripts/joosy/core/modules/time_manager_spec.js.coffee +1 -1
  40. data/spec/javascripts/joosy/core/page_spec.js.coffee +4 -1
  41. data/spec/javascripts/joosy/core/resource/collection_spec.js.coffee +84 -0
  42. data/spec/javascripts/joosy/core/resource/generic_spec.js.coffee +86 -3
  43. data/spec/javascripts/joosy/core/resource/rest_collection_spec.js.coffee +15 -22
  44. data/spec/javascripts/joosy/core/resource/rest_spec.js.coffee +27 -4
  45. data/spec/javascripts/joosy/core/widget_spec.js.coffee +3 -14
  46. metadata +21 -19
  47. data/README.rdoc +0 -3
@@ -4,37 +4,39 @@ Joosy.Modules.Container =
4
4
 
5
5
  eventSplitter: /^(\S+)\s*(.*)$/
6
6
 
7
- $: (selector) -> $(selector, @container)
7
+ $: (selector) ->
8
+ $(selector, @container)
8
9
 
9
10
  refreshElements: ->
10
11
  @__collectElements().each (key, value) =>
12
+ # TODO: Check for possible collisions?
11
13
  @[key] = @$(value)
12
14
 
13
15
  swapContainer: (container, data) ->
14
- realContainer = container.clone().html(data)
15
- container.replaceWith realContainer
16
- realContainer
16
+ container.unbind().off()
17
+ container.html data
18
+ container
17
19
 
18
20
  __collectElements: ->
19
- elements = Object.extended(@elements || {})
21
+ elements = Object.extended @elements || {}
20
22
 
21
23
  klass = this
22
24
  while klass = klass.constructor.__super__
23
- elements.merge(klass.elements, false)
25
+ Joosy.Module.merge elements, klass.elements, false
24
26
 
25
27
  elements
26
28
 
27
29
  __collectEvents: ->
28
- events = Object.extended(@events || {})
30
+ events = Object.extended @events || {}
29
31
 
30
32
  klass = this
31
33
  while klass = klass.constructor.__super__
32
- events.merge(klass.events, false)
34
+ Joosy.Module.merge events, klass.events, false
33
35
 
34
36
  events
35
37
 
36
38
  __extractSelector: (selector) ->
37
- if r = selector.match(/\$([A-z]+)/)
39
+ if r = selector.match /\$([A-z]+)/
38
40
  selector = @__collectElements()[r[1]]
39
41
 
40
42
  selector
@@ -44,16 +46,18 @@ Joosy.Modules.Container =
44
46
  events = @__collectEvents()
45
47
 
46
48
  events.each (key, method) =>
47
- method = @[method] unless typeof(method) == 'function'
48
- callback = (event) -> method.call(module, this, event)
49
+ unless Object.isFunction method
50
+ method = @[method]
51
+ callback = (event) ->
52
+ method.call module, this, event
49
53
 
50
- match = key.match(@eventSplitter)
54
+ match = key.match @eventSplitter
51
55
  eventName = match[1]
52
- selector = @__extractSelector(match[2])
56
+ selector = @__extractSelector match[2]
53
57
 
54
58
  if selector == ""
55
- @container.bind(eventName, callback)
59
+ @container.bind eventName, callback
56
60
  Joosy.Modules.Log.debugAs @, "#{eventName} binded on container"
57
61
  else
58
- @container.on(eventName, selector, callback)
62
+ @container.on eventName, selector, callback
59
63
  Joosy.Modules.Log.debugAs @, "#{eventName} binded on #{selector}"
@@ -1,12 +1,12 @@
1
1
  Joosy.Modules.Events =
2
2
  wait: (events, callback) ->
3
- events = events.split(/\s+/)
3
+ events = events.split /\s+/
4
4
 
5
5
  @__oneShotEvents ||= []
6
6
  @__oneShotEvents.push [events, callback]
7
7
 
8
8
  bind: (events, callback) ->
9
- events = events.split(/\s+/)
9
+ events = events.split /\s+/
10
10
 
11
11
  @__boundEvents ||= []
12
12
  @__boundEvents.push [events, callback]
@@ -14,22 +14,23 @@ Joosy.Modules.Events =
14
14
  unbind: (target) ->
15
15
  for [events, callback], index in @__boundEvents
16
16
  if callback == target
17
- @__boundEvents.splice(index, 1)
17
+ @__boundEvents.splice index, 1
18
18
  return
19
19
 
20
20
  trigger: (event) ->
21
21
  Joosy.Modules.Log.debugAs @, "Event #{event} triggered"
22
22
  if @__oneShotEvents
23
23
  for [events, callback], index in @__oneShotEvents
24
- position = events.indexOf(event)
25
- events.splice(position, 1) if position >= 0
24
+ position = events.indexOf event
25
+ if position >= 0
26
+ events.splice position, 1
26
27
 
27
28
  if events.length == 0
28
- @__oneShotEvents.splice(index, 1)
29
+ @__oneShotEvents.splice index, 1
29
30
 
30
31
  callback()
31
32
 
32
33
  if @__boundEvents
33
- for [ events, callback ] in @__boundEvents
34
- if events.has(event)
35
- callback()
34
+ for [events, callback] in @__boundEvents
35
+ if events.has event
36
+ callback()
@@ -1,39 +1,43 @@
1
1
  Joosy.Modules.Filters =
2
2
  included: ->
3
3
  @beforeLoad = (callback) ->
4
- unless @::hasOwnProperty('__beforeLoads')
4
+ unless @::hasOwnProperty '__beforeLoads'
5
5
  @::__beforeLoads = [].concat @.__super__.__beforeLoads || []
6
6
  @::__beforeLoads.push callback
7
7
 
8
8
  @afterLoad = (callback) ->
9
- unless @::hasOwnProperty('__afterLoads')
9
+ unless @::hasOwnProperty '__afterLoads'
10
10
  @::__afterLoads = [].concat @.__super__.__afterLoads || []
11
11
  @::__afterLoads.push callback
12
12
 
13
13
  @afterUnload = (callback) ->
14
- unless @::hasOwnProperty('__afterUnloads')
14
+ unless @::hasOwnProperty '__afterUnloads'
15
15
  @::__afterUnloads = [].concat @.__super__.__afterUnloads || []
16
16
  @::__afterUnloads.push callback
17
17
 
18
18
  __runBeforeLoads: (opts...) ->
19
- return true unless @__beforeLoads?.length > 0
19
+ unless @__beforeLoads?.length > 0
20
+ return true
20
21
 
21
22
  flag = true
22
23
 
23
24
  for filter in @__beforeLoads
24
- filter = @[filter] unless typeof(filter) is 'function'
25
- flag = flag && filter.apply(@, opts)
25
+ unless Object.isFunction filter
26
+ filter = @[filter]
27
+ flag = flag && filter.apply @, opts
26
28
 
27
29
  return flag
28
30
 
29
31
  __runAfterLoads: (opts...) ->
30
- if @__afterLoads?
32
+ if @__afterLoads?.length > 0
31
33
  for filter in @__afterLoads
32
- filter = @[filter] unless typeof(filter) is 'function'
33
- filter.apply(@, opts)
34
+ unless Object.isFunction filter
35
+ filter = @[filter]
36
+ filter.apply @, opts
34
37
 
35
38
  __runAfterUnloads: (opts...) ->
36
- if @__afterUnloads?
39
+ if @__afterUnloads?.length > 0
37
40
  for filter in @__afterUnloads
38
- filter = @[filter] unless typeof(filter) is 'function'
39
- filter.apply(@, opts)
41
+ unless Object.isFunction filter
42
+ filter = @[filter]
43
+ filter.apply @, opts
@@ -1,15 +1,18 @@
1
1
  Joosy.Modules.Log =
2
2
  log: (args...) ->
3
- return if typeof console is 'undefined'
3
+ return unless console?
4
4
 
5
5
  if console.log.apply?
6
6
  args.unshift "Joosy>"
7
- console.log(args...)
7
+ console.log args...
8
8
  else
9
- console.log(args.first())
9
+ console.log args.first()
10
10
 
11
11
  debug: (args...) ->
12
- @log(args...) if Joosy.debug
12
+ return unless Joosy.debug
13
+ @log args...
13
14
 
14
15
  debugAs: (context, string, args...) ->
15
- @debug "#{Joosy.Module.__className__(context) || 'unknown context'}> #{string}", args...
16
+ return unless Joosy.debug
17
+ context = Joosy.Module.__className(context) || 'unknown context'
18
+ @debug "#{context}> #{string}", args...
@@ -3,41 +3,51 @@ moduleKeywords = ['included', 'extended']
3
3
  class Joosy.Module
4
4
  @__namespace__: []
5
5
 
6
- @__className__ = (klass) ->
7
- klass = klass.constructor unless Object.isFunction(klass)
6
+ @__className = (klass) ->
7
+ unless Object.isFunction(klass)
8
+ klass = klass.constructor
8
9
 
9
10
  if klass.name?
10
11
  klass.name
11
12
  else
12
- klass.toString().replace(/^function ([a-zA-Z]+)\([\s\S]+/, '$1')
13
+ klass.toString().replace /^function ([a-zA-Z]+)\([\s\S]+/, '$1'
13
14
 
14
- @hasAncestor = (what, klass) ->
15
- return false unless what?
15
+ @hasAncestor: (what, klass) ->
16
+ unless what? && klass?
17
+ return false
16
18
 
17
- [ what, klass ] = [ what.prototype, klass.prototype ]
19
+ [what, klass] = [what.prototype, klass.prototype]
18
20
 
19
21
  while what
20
- return true if what == klass
22
+ if what == klass
23
+ return true
21
24
  what = what.constructor?.__super__
22
25
 
23
26
  false
24
-
25
- @include: (obj) ->
26
- throw new Error 'include(obj) requires obj' unless obj
27
-
28
- Object.extended(obj).each (key, value) =>
27
+
28
+ @merge: (destination, source, unsafe=true) ->
29
+ for key, value of source
30
+ if source.hasOwnProperty(key)
31
+ if unsafe || !destination.hasOwnProperty(key)
32
+ destination[key] = value
33
+ destination
34
+
35
+ @include: (object) ->
36
+ unless object
37
+ throw new Error 'include(object) requires obj'
38
+
39
+ Object.each object, (key, value) =>
29
40
  if key not in moduleKeywords
30
41
  this::[key] = value
31
42
 
32
- obj.included?.apply(this)
33
- this
43
+ object.included?.apply this
44
+ null
34
45
 
35
- @extend: (obj) ->
36
- throw new Error 'extend(obj) requires obj' unless obj
46
+ @extend: (object) ->
47
+ unless object
48
+ throw new Error 'extend(object) requires object'
37
49
 
38
- Object.extended(obj).each (key, value) =>
39
- if key not in moduleKeywords
40
- this[key] = value
50
+ @merge this, object
41
51
 
42
- obj.extended?.apply(this)
43
- this
52
+ object.extended?.apply this
53
+ null
@@ -4,17 +4,20 @@
4
4
  Joosy.Modules.Renderer =
5
5
 
6
6
  __renderer: ->
7
- throw new Error "#{@constructor.name} does not have an attached template"
7
+ throw new Error "#{Joosy.Module.__className @constructor} does not have an attached template"
8
8
 
9
9
  __helpers: null
10
10
 
11
11
  included: ->
12
- @view = (template) ->
13
- if Object.isFunction(template)
12
+ @view = (template, options={}) ->
13
+ if Object.isFunction template
14
14
  @::__renderer = template
15
15
  else
16
16
  @::__renderer = (locals={}) ->
17
- @render(template, locals)
17
+ if options.dynamic
18
+ @renderDynamic template, locals
19
+ else
20
+ @render template, locals
18
21
 
19
22
  @helpers = (helpers...) ->
20
23
  @::__helpers ||= []
@@ -30,26 +33,23 @@ Joosy.Modules.Renderer =
30
33
  __instantiateHelpers: ->
31
34
  unless @__helpersInstance
32
35
  @__helpersInstance = Object.extended Joosy.Helpers.Application
33
-
34
- @__helpersInstance.render = =>
35
- @render(arguments...)
36
36
 
37
37
  @__helpersInstance.widget = (element, widget) =>
38
38
  @widgets ||= {}
39
39
 
40
40
  uuid = Joosy.uuid()
41
- element = document.createElement(element)
42
- temp = document.createElement("div")
41
+ element = document.createElement element
42
+ temp = document.createElement 'div'
43
43
 
44
- element.id = uuid
44
+ element.id = uuid
45
45
  @widgets['#'+uuid] = widget
46
46
 
47
- temp.appendChild(element)
47
+ temp.appendChild element
48
48
  temp.innerHTML
49
49
 
50
50
  if @__helpers
51
51
  for helper in @__helpers
52
- @__helpersInstance.merge helper
52
+ Joosy.Module.merge @__helpersInstance, helper
53
53
 
54
54
  @__helpersInstance
55
55
 
@@ -57,60 +57,123 @@ Joosy.Modules.Renderer =
57
57
  __proxifyHelpers: (locals) ->
58
58
  if locals.hasOwnProperty '__proto__'
59
59
  locals.__proto__ = @__instantiateHelpers()
60
-
61
60
  locals
62
61
  else
63
62
  unless @__helpersProxyInstance
64
63
  @__helpersProxyInstance = (locals) ->
65
- Object.merge(this, locals)
64
+ Joosy.Module.merge this, locals
66
65
 
67
66
  @__helpersProxyInstance.prototype = @__instantiateHelpers()
68
67
 
69
- new @__helpersProxyInstance(locals)
68
+ new @__helpersProxyInstance locals
70
69
 
71
- render: (template, locals={}) ->
72
- isResource = Joosy.Module.hasAncestor(locals.constructor, Joosy.Resource.Generic)
70
+ render: (template, locals={}, parentStackPointer=false) ->
71
+ @__render false, template, locals, parentStackPointer
72
+
73
+ renderDynamic: (template, locals={}, parentStackPointer=false) ->
74
+ @__render true, template, locals, parentStackPointer
75
+
76
+ __render: (dynamic, template, locals={}, parentStackPointer=false) ->
77
+ stack = @__renderingStackChildFor parentStackPointer
78
+
79
+ stack.template = template
80
+
81
+ isResource = Joosy.Module.hasAncestor locals.constructor, Joosy.Resource.Generic
82
+ isCollection = Joosy.Module.hasAncestor locals.constructor, Joosy.Resource.Collection
73
83
 
74
84
  if Object.isString template
75
85
  if @__renderSection?
76
86
  template = Joosy.Application.templater.resolveTemplate @__renderSection(), template, this
77
87
 
78
88
  template = Joosy.Application.templater.buildView template
79
- else if !Object.isFunction(template)
80
- throw new Error "#{Joosy.Module.__className__ @}> template (maybe @view) does not look like a string or lambda"
81
-
82
- if !Object.isObject(locals) && !isResource
83
- throw new Error "#{Joosy.Module.__className__ @}> locals (maybe @data?) can only be dumb hash or Resource"
84
-
85
- # Small code dup due to the fact we sometimes
86
- # actually CLONE object when proxying helpers
87
- if !isResource
88
- locals = @__proxifyHelpers(locals)
89
- morph = Metamorph template(locals)
90
- update = => morph.html template(locals)
89
+ else if !Object.isFunction template
90
+ throw new Error "#{Joosy.Module.__className @}> template (maybe @view) does not look like a string or lambda"
91
+
92
+ if !Object.isObject(locals) && !isResource && !isCollection
93
+ throw new Error "#{Joosy.Module.__className @}> locals (maybe @data?) not in: dumb hash, Resource, Collection"
94
+
95
+ if isResource
96
+ stack.locals = locals.e
91
97
  else
92
- locals.e = @__proxifyHelpers(locals.e)
93
- morph = Metamorph template(locals.e)
94
- update = => morph.html template(locals.e)
98
+ stack.locals = locals
95
99
 
96
- # This is here to break stack tree and save from
97
- # repeating DOM handling
98
- update = update.debounce(0)
99
-
100
- @__metamorphs ||= []
100
+ renderers =
101
+ render: (template, locals={}) =>
102
+ @render template, locals, stack
103
+ renderDynamic: (template, locals={}) =>
104
+ @renderDynamic template, locals, stack
105
+
106
+ context = =>
107
+ data = {}
108
+ Joosy.Module.merge data, stack.locals
109
+ Joosy.Module.merge data, @__instantiateHelpers(), false
110
+ Joosy.Module.merge data, renderers
111
+ data
112
+
113
+ if dynamic
114
+ morph = Metamorph template(context())
115
+ update = =>
116
+ for child in stack.children
117
+ @__removeMetamorphs child
118
+ stack.children = []
119
+ morph.html template(context())
120
+ @refreshElements?()
121
+
122
+ # This is here to break stack tree and save from
123
+ # repeating DOM handling
124
+ update = update.debounce 0
125
+
126
+ if isCollection
127
+ for resource in locals.data
128
+ resource.bind 'changed', update
129
+ stack.metamorphBindings.push [resource, update]
130
+ if isResource || isCollection
131
+ locals.bind 'changed', update
132
+ stack.metamorphBindings.push [locals, update]
133
+ else
134
+ for key, object of locals
135
+ if locals.hasOwnProperty key
136
+ if object?.bind? && object?.unbind?
137
+ object.bind 'changed', update
138
+ stack.metamorphBindings.push [object, update]
101
139
 
102
- if isResource
103
- locals.bind 'changed', update
140
+ morph.outerHTML()
141
+ else
142
+ template context()
143
+
144
+ __renderingStackElement: (parent=null) ->
145
+ metamorphBindings: []
146
+ locals: null
147
+ template: null
148
+ children: []
149
+ parent: parent
150
+
151
+ __renderingStackChildFor: (parentPointer) ->
152
+ if !@__renderingStack
153
+ @__renderingStack = []
154
+
155
+ if !parentPointer
156
+ element = @__renderingStackElement()
157
+ @__renderingStack.push element
158
+ element
159
+ else
160
+ element = @__renderingStackElement parentPointer
161
+ parentPointer.children.push element
162
+ element
163
+
164
+ __removeMetamorphs: (stackPointer=false) ->
165
+ remove = (stackPointer) =>
166
+ if stackPointer?.children
167
+ for child in stackPointer.children
168
+ @__removeMetamorphs child
169
+
170
+ if stackPointer?.metamorphBindings
171
+ for [object, callback] in stackPointer.metamorphBindings
172
+ object.unbind callback
173
+ stackPointer.metamorphBindings = []
174
+
175
+ unless stackPointer
176
+ @__renderingStack?.each (stackPointer) ->
177
+ remove stackPointer
104
178
  else
105
- for key, object of locals
106
- if locals.hasOwnProperty key
107
- if object?.bind? && object?.unbind?
108
- object.bind 'changed', update
109
- @__metamorphs.push [object, update]
110
-
111
- morph.outerHTML()
112
-
113
- __removeMetamorphs: ->
114
- if @__metamorphs
115
- for [object, callback] in @__metamorphs
116
- object.unbind callback
179
+ remove stackPointer
@@ -15,11 +15,11 @@ Joosy.Modules.TimeManager =
15
15
 
16
16
  timer
17
17
 
18
- clearTime: ->
18
+ __clearTime: ->
19
19
  if @__intervals
20
20
  for entry in @__intervals
21
21
  window.clearInterval entry
22
22
 
23
23
  if @__timeouts
24
24
  for entry in @__timeouts
25
- window.clearTimeout entry
25
+ window.clearTimeout entry
@@ -1,6 +1,6 @@
1
1
  Joosy.Modules.WidgetsManager =
2
2
  registerWidget: (container, widget) ->
3
- if Joosy.Module.hasAncestor(widget, Joosy.Widget)
3
+ if Joosy.Module.hasAncestor widget, Joosy.Widget
4
4
  widget = new widget()
5
5
 
6
6
  @__activeWidgets ||= []
@@ -11,14 +11,14 @@ Joosy.Modules.WidgetsManager =
11
11
  unregisterWidget: (widget) ->
12
12
  widget.__unload()
13
13
 
14
- @__activeWidgets.splice(@__activeWidgets.indexOf(widget), 1)
14
+ @__activeWidgets.splice @__activeWidgets.indexOf(widget), 1
15
15
 
16
16
  __collectWidgets: ->
17
- widgets = Object.extended(@widgets || {})
17
+ widgets = Object.extended @widgets || {}
18
18
 
19
19
  klass = this
20
20
  while klass = klass.constructor.__super__
21
- widgets.merge(klass.widgets, false)
21
+ Joosy.Module.merge widgets, klass.widgets, false
22
22
 
23
23
  widgets
24
24
 
@@ -30,7 +30,7 @@ Joosy.Modules.WidgetsManager =
30
30
  if selector == '$container'
31
31
  activeSelector = @container
32
32
  else
33
- if r = selector.match(/\$([A-z_]+)/)
33
+ if r = selector.match /\$([A-z_]+)/
34
34
  selector = @elements[r[1]]
35
35
 
36
36
  activeSelector = $(selector, @container)
@@ -38,15 +38,15 @@ Joosy.Modules.WidgetsManager =
38
38
  registered[selector] = Object.extended()
39
39
 
40
40
  activeSelector.each (index, elem) =>
41
- if Joosy.Module.hasAncestor(widget, Joosy.Widget)
41
+ if Joosy.Module.hasAncestor widget, Joosy.Widget
42
42
  instance = new widget
43
43
  else
44
44
  instance = widget.call this, index
45
45
 
46
- registered[selector][Joosy.Module.__className__ instance] ||= 0
47
- registered[selector][Joosy.Module.__className__ instance] += 1
46
+ registered[selector][Joosy.Module.__className instance] ||= 0
47
+ registered[selector][Joosy.Module.__className instance] += 1
48
48
 
49
- @registerWidget($(elem), instance)
49
+ @registerWidget $(elem), instance
50
50
 
51
51
  registered.each (selector, value) =>
52
52
  value.each (widget, count) =>
@@ -55,4 +55,4 @@ Joosy.Modules.WidgetsManager =
55
55
  __unloadWidgets: ->
56
56
  if @__activeWidgets
57
57
  for widget in @__activeWidgets
58
- widget.__unload()
58
+ widget.__unload()
@@ -33,21 +33,26 @@ class Joosy.Page extends Joosy.Module
33
33
  @layout: (layoutClass) ->
34
34
  @::__layoutClass = layoutClass
35
35
 
36
- @beforePaint: (callback) -> @::__beforePaint = callback
37
- @paint: (callback) -> @::__paint = callback
38
- @afterPaint: (callback) -> @::__afterPaint = callback
39
- @erase: (callback) -> @::__erase = callback
36
+ @beforePaint: (callback) ->
37
+ @::__beforePaint = callback
38
+ @paint: (callback) ->
39
+ @::__paint = callback
40
+ @afterPaint: (callback) ->
41
+ @::__afterPaint = callback
42
+ @erase: (callback) ->
43
+ @::__erase = callback
40
44
 
41
45
  constructor: (@params, @previous) ->
42
46
  @__layoutClass ||= ApplicationLayout
43
47
 
44
- if @__runBeforeLoads(@params, @previous)
48
+ if @__runBeforeLoads @params, @previous
45
49
  if !@previous?.layout?.uuid? || @previous?.__layoutClass != @__layoutClass
46
50
  @__bootstrapLayout()
47
51
  else
48
52
  @__bootstrap()
49
53
 
50
- navigate: (args...) -> Joosy.Router.navigate(args...)
54
+ navigate: (args...) ->
55
+ Joosy.Router.navigate(args...)
51
56
 
52
57
  __renderSection: ->
53
58
  'pages'
@@ -62,23 +67,23 @@ class Joosy.Page extends Joosy.Module
62
67
  @refreshElements()
63
68
  @__delegateEvents()
64
69
  @__setupWidgets()
65
- @__runAfterLoads(@params, @previous)
70
+ @__runAfterLoads @params, @previous
66
71
  if @__scrollElement
67
- scroll = $(@__extractSelector(@__scrollElement)).offset()?.top + @__scrollMargin
68
- Joosy.Modules.Log.debugAs @, "Scrolling to #{@__extractSelector(@__scrollElement)}"
72
+ scroll = $(@__extractSelector @__scrollElement).offset()?.top + @__scrollMargin
73
+ Joosy.Modules.Log.debugAs @, "Scrolling to #{@__extractSelector @__scrollElement}"
69
74
  $('html, body').animate {scrollTop: scroll}, @__scrollSpeed, =>
70
- @__releaseHeight() if @__scrollSpeed != 0
75
+ if @__scrollSpeed != 0
76
+ @__releaseHeight()
71
77
 
72
78
  Joosy.Modules.Log.debugAs @, "Page loaded"
73
79
 
74
80
  __unload: ->
75
- @clearTime()
81
+ @__clearTime()
76
82
  @__unloadWidgets()
77
83
  @__removeMetamorphs()
78
- @__runAfterUnloads(@params, @previous)
84
+ @__runAfterUnloads @params, @previous
79
85
  delete @previous
80
86
 
81
-
82
87
  __callSyncedThrough: (entity, receiver, params, callback) ->
83
88
  if entity?[receiver]?
84
89
  entity[receiver].apply entity, params.clone().add(callback)
@@ -99,7 +104,8 @@ class Joosy.Page extends Joosy.Module
99
104
 
100
105
  callbacksParams = [@layout.content()]
101
106
 
102
- @__fixHeight() if @__scrollElement && @__scrollSpeed != 0
107
+ if @__scrollElement && @__scrollSpeed != 0
108
+ @__fixHeight()
103
109
 
104
110
  @wait "stageClear dataReceived", =>
105
111
  @__callSyncedThrough this, '__paint', callbacksParams, =>
@@ -123,17 +129,20 @@ class Joosy.Page extends Joosy.Module
123
129
 
124
130
  __bootstrapLayout: ->
125
131
  Joosy.Modules.Log.debugAs @, "Boostraping page with layout"
126
- @layout = new @__layoutClass
132
+ @layout = new @__layoutClass(@params)
127
133
 
128
134
  callbacksParams = [Joosy.Application.content(), this]
129
135
 
130
- @__fixHeight() if @__scrollElement && @__scrollSpeed != 0
136
+ if @__scrollElement && @__scrollSpeed != 0
137
+ @__fixHeight()
131
138
 
132
139
  @wait "stageClear dataReceived", =>
133
140
  @__callSyncedThrough @layout, '__paint', callbacksParams, =>
134
141
  # Layout HTML
135
- @swapContainer Joosy.Application.content(), @layout.__renderer
136
- yield: => @layout.yield()
142
+ data = Joosy.Module.merge {}, @layout.data || {}
143
+ data = Joosy.Module.merge data, yield: => @layout.yield()
144
+
145
+ @swapContainer Joosy.Application.content(), @layout.__renderer data
137
146
 
138
147
  # Page HTML
139
148
  @swapContainer @layout.content(), @__renderer(@data || {})
@@ -151,6 +160,7 @@ class Joosy.Page extends Joosy.Module
151
160
  @__callSyncedThrough @layout, '__beforePaint', callbacksParams, =>
152
161
  @trigger 'stageClear'
153
162
 
154
- @__callSyncedThrough this, '__fetch', [], =>
155
- Joosy.Modules.Log.debugAs @, "Fetch complete"
156
- @trigger 'dataReceived'
163
+ @__callSyncedThrough @layout, '__fetch', [], =>
164
+ @__callSyncedThrough this, '__fetch', [], =>
165
+ Joosy.Modules.Log.debugAs @, "Fetch complete"
166
+ @trigger 'dataReceived'