joosy 0.1.0.RC1 → 0.1.0.RC2

Sign up to get free protection for your applications and to get access to all the features.
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'