joosy 0.1.0.RC3 → 0.1.0.alpha

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 (115) hide show
  1. data/.gitignore +0 -2
  2. data/Gemfile +2 -13
  3. data/Gemfile.lock +62 -80
  4. data/Guardfile +15 -21
  5. data/MIT-LICENSE +2 -2
  6. data/README.rdoc +3 -0
  7. data/app/helpers/joosy/sprockets_helper.rb +11 -23
  8. data/joosy.gemspec +3 -3
  9. data/lib/joosy/forms.rb +12 -2
  10. data/lib/joosy/rails/engine.rb +1 -9
  11. data/lib/joosy/rails/version.rb +2 -2
  12. data/lib/joosy-rails.rb +5 -0
  13. data/lib/rails/generators/joosy/application_generator.rb +3 -13
  14. data/lib/rails/generators/joosy/joosy_base.rb +2 -2
  15. data/lib/rails/generators/joosy/layout_generator.rb +1 -8
  16. data/lib/rails/generators/joosy/page_generator.rb +6 -21
  17. data/lib/rails/generators/joosy/preloader_generator.rb +7 -14
  18. data/lib/rails/generators/joosy/templates/app/layouts/application.js.coffee +0 -1
  19. data/lib/rails/generators/joosy/templates/app/layouts/template.js.coffee +1 -1
  20. data/lib/rails/generators/joosy/templates/app/pages/application.js.coffee +1 -1
  21. data/lib/rails/generators/joosy/templates/app/pages/template.js.coffee +3 -3
  22. data/lib/rails/generators/joosy/templates/app/routes.js.coffee +1 -7
  23. data/lib/rails/generators/joosy/templates/app/widgets/template.js.coffee +2 -2
  24. data/lib/rails/generators/joosy/templates/app.js.coffee +0 -3
  25. data/lib/rails/generators/joosy/templates/app_preloader.js.coffee.erb +12 -9
  26. data/lib/rails/generators/joosy/templates/preload.html.erb +6 -5
  27. data/lib/rails/generators/joosy/templates/preload.html.haml +5 -3
  28. data/lib/rails/generators/joosy/templates/preload.html.slim +21 -0
  29. data/lib/rails/generators/joosy/widget_generator.rb +1 -8
  30. data/spec/javascripts/helpers/spec_helper.js.coffee +0 -20
  31. data/spec/javascripts/joosy/core/modules/container_spec.js.coffee +27 -24
  32. data/spec/javascripts/joosy/core/modules/events_spec.js.coffee +18 -42
  33. data/spec/javascripts/joosy/core/modules/filters_spec.js.coffee +27 -27
  34. data/spec/javascripts/joosy/core/modules/log_spec.js.coffee +3 -3
  35. data/spec/javascripts/joosy/core/modules/module_spec.js.coffee +15 -6
  36. data/spec/javascripts/joosy/core/modules/time_manager_spec.js.coffee +7 -12
  37. data/spec/javascripts/joosy/core/modules/widget_manager_spec.js.coffee +17 -31
  38. data/tmp/javascripts/.gitignore +1 -0
  39. data/tmp/spec/javascripts/helpers/.gitignore +1 -0
  40. data/vendor/assets/javascripts/base64.js +135 -0
  41. data/vendor/assets/javascripts/joosy/core/application.js.coffee +26 -0
  42. data/vendor/assets/javascripts/joosy/core/form.js.coffee +87 -0
  43. data/vendor/assets/javascripts/joosy/core/joosy.js.coffee +62 -0
  44. data/vendor/assets/javascripts/joosy/core/layout.js.coffee +38 -0
  45. data/vendor/assets/javascripts/joosy/core/modules/container.js.coffee +51 -0
  46. data/vendor/assets/javascripts/joosy/core/modules/events.js.coffee +17 -0
  47. data/vendor/assets/javascripts/joosy/core/modules/filters.js.coffee +39 -0
  48. data/vendor/assets/javascripts/joosy/core/modules/log.js.coffee +12 -0
  49. data/vendor/assets/javascripts/joosy/core/modules/module.js.coffee +28 -0
  50. data/vendor/assets/javascripts/joosy/core/modules/time_manager.js.coffee +23 -0
  51. data/vendor/assets/javascripts/joosy/core/modules/widgets_manager.js.coffee +45 -0
  52. data/vendor/assets/javascripts/joosy/core/page.js.coffee +136 -0
  53. data/vendor/assets/javascripts/joosy/core/resource/rest.js.coffee +69 -0
  54. data/vendor/assets/javascripts/joosy/core/resource/rest_collection.js.coffee +42 -0
  55. data/vendor/assets/javascripts/joosy/core/router.js.coffee +75 -0
  56. data/vendor/assets/javascripts/joosy/core/widget.js.coffee +35 -0
  57. data/vendor/assets/javascripts/joosy/preloader/development.js.coffee +27 -0
  58. data/vendor/assets/javascripts/joosy/preloader/production.js.coffee +84 -0
  59. data/{app → vendor}/assets/javascripts/joosy.js.coffee +0 -0
  60. data/vendor/assets/javascripts/jquery.form.js +963 -978
  61. data/vendor/assets/javascripts/sugar.js +1 -1
  62. metadata +48 -77
  63. data/.codoopts +0 -5
  64. data/README.md +0 -95
  65. data/app/assets/javascripts/joosy/core/application.js.coffee +0 -50
  66. data/app/assets/javascripts/joosy/core/form.js.coffee +0 -304
  67. data/app/assets/javascripts/joosy/core/helpers/view.js.coffee +0 -30
  68. data/app/assets/javascripts/joosy/core/joosy.js.coffee +0 -129
  69. data/app/assets/javascripts/joosy/core/layout.js.coffee +0 -162
  70. data/app/assets/javascripts/joosy/core/modules/container.js.coffee +0 -104
  71. data/app/assets/javascripts/joosy/core/modules/events.js.coffee +0 -123
  72. data/app/assets/javascripts/joosy/core/modules/filters.js.coffee +0 -67
  73. data/app/assets/javascripts/joosy/core/modules/log.js.coffee +0 -36
  74. data/app/assets/javascripts/joosy/core/modules/module.js.coffee +0 -105
  75. data/app/assets/javascripts/joosy/core/modules/renderer.js.coffee +0 -195
  76. data/app/assets/javascripts/joosy/core/modules/time_manager.js.coffee +0 -46
  77. data/app/assets/javascripts/joosy/core/modules/widgets_manager.js.coffee +0 -84
  78. data/app/assets/javascripts/joosy/core/page.js.coffee +0 -375
  79. data/app/assets/javascripts/joosy/core/preloader.js.coffee +0 -13
  80. data/app/assets/javascripts/joosy/core/resource/collection.js.coffee +0 -174
  81. data/app/assets/javascripts/joosy/core/resource/generic.js.coffee +0 -254
  82. data/app/assets/javascripts/joosy/core/resource/rest.js.coffee +0 -197
  83. data/app/assets/javascripts/joosy/core/resource/rest_collection.js.coffee +0 -125
  84. data/app/assets/javascripts/joosy/core/router.js.coffee +0 -163
  85. data/app/assets/javascripts/joosy/core/templaters/rails_jst.js.coffee +0 -36
  86. data/app/assets/javascripts/joosy/core/widget.js.coffee +0 -80
  87. data/app/assets/javascripts/joosy/preloaders/caching.js.coffee +0 -169
  88. data/app/assets/javascripts/joosy/preloaders/inline.js.coffee +0 -56
  89. data/lib/joosy.rb +0 -9
  90. data/lib/rails/generators/joosy/resource_generator.rb +0 -29
  91. data/lib/rails/generators/joosy/templates/app/helpers/application.js.coffee +0 -4
  92. data/lib/rails/generators/joosy/templates/app/pages/welcome/index.js.coffee +0 -22
  93. data/lib/rails/generators/joosy/templates/app/resources/template.js.coffee +0 -2
  94. data/lib/rails/generators/joosy/templates/app/templates/layouts/application.jst.hamlc +0 -2
  95. data/lib/rails/generators/joosy/templates/app/templates/pages/welcome/index.jst.hamlc +0 -7
  96. data/spec/javascripts/joosy/core/application_spec.js.coffee +0 -40
  97. data/spec/javascripts/joosy/core/form_spec.js.coffee +0 -184
  98. data/spec/javascripts/joosy/core/joosy_spec.js.coffee +0 -72
  99. data/spec/javascripts/joosy/core/layout_spec.js.coffee +0 -50
  100. data/spec/javascripts/joosy/core/modules/renderer_spec.js.coffee +0 -185
  101. data/spec/javascripts/joosy/core/page_spec.js.coffee +0 -178
  102. data/spec/javascripts/joosy/core/resource/collection_spec.js.coffee +0 -84
  103. data/spec/javascripts/joosy/core/resource/generic_spec.js.coffee +0 -118
  104. data/spec/javascripts/joosy/core/resource/rest_collection_spec.js.coffee +0 -58
  105. data/spec/javascripts/joosy/core/resource/rest_spec.js.coffee +0 -129
  106. data/spec/javascripts/joosy/core/router_spec.js.coffee +0 -123
  107. data/spec/javascripts/joosy/core/templaters/rails_jst_spec.js.coffee +0 -25
  108. data/spec/javascripts/joosy/core/widget_spec.js.coffee +0 -40
  109. data/spec/javascripts/joosy/preloaders/caching_spec.js.coffee +0 -36
  110. data/spec/javascripts/joosy/preloaders/inline_spec.js.coffee +0 -16
  111. data/spec/javascripts/support/assets/coolface.jpg +0 -0
  112. data/spec/javascripts/support/assets/okay.jpg +0 -0
  113. data/spec/javascripts/support/assets/test.js +0 -1
  114. data/spec/javascripts/support/sinon-ie-1.3.1.js +0 -82
  115. data/vendor/assets/javascripts/metamorph.js +0 -409
@@ -0,0 +1,135 @@
1
+ var Base64 = {
2
+
3
+ // private property
4
+ _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
5
+
6
+ // public method for encoding
7
+ encode : function (input) {
8
+ var output = "";
9
+ var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
10
+ var i = 0;
11
+
12
+ input = Base64._utf8_encode(input);
13
+
14
+ while (i < input.length) {
15
+
16
+ chr1 = input.charCodeAt(i++);
17
+ chr2 = input.charCodeAt(i++);
18
+ chr3 = input.charCodeAt(i++);
19
+
20
+ enc1 = chr1 >> 2;
21
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
22
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
23
+ enc4 = chr3 & 63;
24
+
25
+ if (isNaN(chr2)) {
26
+ enc3 = enc4 = 64;
27
+ } else if (isNaN(chr3)) {
28
+ enc4 = 64;
29
+ }
30
+
31
+ output = output +
32
+ this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
33
+ this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
34
+
35
+ }
36
+
37
+ return output;
38
+ },
39
+
40
+ // public method for decoding
41
+ decode : function (input) {
42
+ var output = "";
43
+ var chr1, chr2, chr3;
44
+ var enc1, enc2, enc3, enc4;
45
+ var i = 0;
46
+
47
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
48
+
49
+ while (i < input.length) {
50
+
51
+ enc1 = this._keyStr.indexOf(input.charAt(i++));
52
+ enc2 = this._keyStr.indexOf(input.charAt(i++));
53
+ enc3 = this._keyStr.indexOf(input.charAt(i++));
54
+ enc4 = this._keyStr.indexOf(input.charAt(i++));
55
+
56
+ chr1 = (enc1 << 2) | (enc2 >> 4);
57
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
58
+ chr3 = ((enc3 & 3) << 6) | enc4;
59
+
60
+ output = output + String.fromCharCode(chr1);
61
+
62
+ if (enc3 != 64) {
63
+ output = output + String.fromCharCode(chr2);
64
+ }
65
+ if (enc4 != 64) {
66
+ output = output + String.fromCharCode(chr3);
67
+ }
68
+
69
+ }
70
+
71
+ output = Base64._utf8_decode(output);
72
+
73
+ return output;
74
+
75
+ },
76
+
77
+ // private method for UTF-8 encoding
78
+ _utf8_encode : function (string) {
79
+ string = string.replace(/\r\n/g,"\n");
80
+ var utftext = "";
81
+
82
+ for (var n = 0; n < string.length; n++) {
83
+
84
+ var c = string.charCodeAt(n);
85
+
86
+ if (c < 128) {
87
+ utftext += String.fromCharCode(c);
88
+ }
89
+ else if((c > 127) && (c < 2048)) {
90
+ utftext += String.fromCharCode((c >> 6) | 192);
91
+ utftext += String.fromCharCode((c & 63) | 128);
92
+ }
93
+ else {
94
+ utftext += String.fromCharCode((c >> 12) | 224);
95
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
96
+ utftext += String.fromCharCode((c & 63) | 128);
97
+ }
98
+
99
+ }
100
+
101
+ return utftext;
102
+ },
103
+
104
+ // private method for UTF-8 decoding
105
+ _utf8_decode : function (utftext) {
106
+ var string = "";
107
+ var i = 0;
108
+ var c = c1 = c2 = 0;
109
+
110
+ while ( i < utftext.length ) {
111
+
112
+ c = utftext.charCodeAt(i);
113
+
114
+ if (c < 128) {
115
+ string += String.fromCharCode(c);
116
+ i++;
117
+ }
118
+ else if((c > 191) && (c < 224)) {
119
+ c2 = utftext.charCodeAt(i+1);
120
+ string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
121
+ i += 2;
122
+ }
123
+ else {
124
+ c2 = utftext.charCodeAt(i+1);
125
+ c3 = utftext.charCodeAt(i+2);
126
+ string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
127
+ i += 3;
128
+ }
129
+
130
+ }
131
+
132
+ return string;
133
+ }
134
+
135
+ }
@@ -0,0 +1,26 @@
1
+ #= require joosy/core/joosy
2
+
3
+ Joosy.Application =
4
+ Pages: {}
5
+ Layouts: {}
6
+ Controls: {}
7
+
8
+ selector: false
9
+
10
+ initialize: (selector) ->
11
+ @selector = selector
12
+ Joosy.Router.setupRoutes()
13
+
14
+ @sandboxSelector = Joosy.uuid()
15
+ @content().after("<div id='#{@sandboxSelector}' style='display:none'></div>")
16
+ @sandboxSelector = '#'+@sandboxSelector
17
+
18
+ content: ->
19
+ $(@selector)
20
+
21
+ sandbox: ->
22
+ $(@sandboxSelector)
23
+
24
+ setCurrentPage: (page, params) ->
25
+ #if @page not instanceof page
26
+ @page = new page(params, @page)
@@ -0,0 +1,87 @@
1
+ #= require joosy/core/joosy
2
+ #= require joosy/core/modules/module
3
+ #= require joosy/core/modules/log
4
+ #= require joosy/core/modules/events
5
+ #= require joosy/core/modules/container
6
+
7
+ class Joosy.Form extends Joosy.Module
8
+ @include Joosy.Modules.Log
9
+ @include Joosy.Modules.Events
10
+ @include Joosy.Modules.Container
11
+
12
+ invalidationClass: 'field_with_errors'
13
+ substitutions: {}
14
+
15
+ elements:
16
+ 'fields': 'input,select,textarea'
17
+
18
+ constructor: (form, opts={}) ->
19
+ if Object.isFunction opts
20
+ @success = opts
21
+ else
22
+ Object.extended(opts).each (key, value) =>
23
+ @[key] = value
24
+
25
+ @container = $(form)
26
+ @refreshElements()
27
+ @__delegateEvents()
28
+
29
+ if (method = @container.attr('method')?.toLowerCase()) && !['get', 'post'].has(method)
30
+ @__markMethod method
31
+ @container.attr 'method', 'POST'
32
+
33
+ @container.ajaxForm
34
+ dataType: 'json'
35
+ beforeSend: => @__before(arguments...)
36
+ success: => @__success(arguments...)
37
+ error: => @__error(arguments...)
38
+ xhr: =>
39
+ xhr = $.ajaxSettings.xhr()
40
+ if xhr.upload? && @progress
41
+ xhr.upload.onprogress = (event) =>
42
+ @progress (event.position/event.total*100).round(2) if event.lengthComputable
43
+ xhr
44
+
45
+ fill: (resource, decorator) ->
46
+ e = if decorator? then decorator(resource.e) else resource.e
47
+ Object.each e, (key, val) =>
48
+ key = resource.constructor.entityName()+"[#{key}]"
49
+ @fields.filter("[name='#{key.underscore()}']:not(:file),[name='#{key.camelize(false)}']:not(:file)").val(val)
50
+
51
+ @container.attr 'action', resource.constructor.__buildSource(extension: resource.id)
52
+ @__markMethod() if resource.id
53
+ @container.attr 'method', 'POST'
54
+
55
+ __success: (response, status, xhr) ->
56
+ if xhr
57
+ @success(response)
58
+ else if response.status == 200
59
+ @success(response.json)
60
+ else
61
+ @__error(response.json)
62
+
63
+ __before: (xhr, settings) ->
64
+ if !@before? || @before(arguments...) is true
65
+ @fields.removeClass(@invalidationClass)
66
+
67
+ __error: (data) ->
68
+ errors = if data.responseText
69
+ try
70
+ Object.extended(jQuery.parseJSON(data.responseText))
71
+ catch error
72
+ Object.extended()
73
+ else
74
+ Object.extended(data)
75
+
76
+ if !@error? || @error(errors) is true
77
+ errors.each (field, notifications) =>
78
+ field = @substitutions[field] if @substitutions[field]?
79
+ input = @fields.filter("[name='#{field}']").addClass(@invalidationClass)
80
+ @notification?(input, notifications)
81
+
82
+ __markMethod: (method='PUT') ->
83
+ method = $ '<input/>',
84
+ type: 'hidden'
85
+ name: '_method'
86
+ value: method
87
+ @container.append(method)
@@ -0,0 +1,62 @@
1
+ @Joosy = Object.extended(if @Joosy? then @Joosy else {})
2
+
3
+ @Joosy.merge
4
+ debug: false
5
+ Modules: {}
6
+ Resource: {}
7
+
8
+ Joosy.Beautifier =
9
+ beautifiers: []
10
+
11
+ add: (callback) -> @beautifiers.push(callback)
12
+ go: -> b() for b in @beautifiers
13
+
14
+ Joosy.namespace = (name, generator=false) ->
15
+ name = name.split('.')
16
+ space = window
17
+ space = space[part] ?= {} for part in name
18
+
19
+ generator = generator.apply(space) if generator?
20
+
21
+ Joosy.test = ->
22
+ text = "Hi :). I'm Joosy. And everything is just fine!"
23
+
24
+ if console
25
+ console.log text
26
+ else
27
+ alert text
28
+
29
+ Joosy.uuid = ->
30
+ 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace /[xy]/g, (c) ->
31
+ r = Math.random() * 16 | 0
32
+ v = if c is 'x' then r else r & 3 | 8
33
+ v.toString 16
34
+ .toUpperCase()
35
+
36
+ Joosy.preloadImages = (images, callback) ->
37
+ callback() if images.length == 0
38
+
39
+ ticks = images.length
40
+ result = []
41
+
42
+ for p in images
43
+ result.push $('<img/>').load(->
44
+ callback?() if (ticks -= 1) == 0
45
+ ).attr('src', p)
46
+
47
+ return result
48
+
49
+ Joosy.buildUrl = (url, params) ->
50
+ paramsString = []
51
+ Object.each params, (key, value) -> paramsString.push("#{key}=#{value}")
52
+ paramsString = paramsString.join('&')
53
+
54
+ hash = url.match(/(\#.*)?$/)[0]
55
+
56
+ url = url.replace(/\#.*$/, '')
57
+
58
+ url = url + "?" if paramsString != '' && url.indexOf("?") == -1
59
+
60
+ url = (if paramsString == '' || url.last() == '?' then url+paramsString else url+'&'+paramsString) + hash
61
+
62
+ return url
@@ -0,0 +1,38 @@
1
+ #= require joosy/core/joosy
2
+ #= require joosy/core/modules/module
3
+ #= require joosy/core/modules/log
4
+ #= require joosy/core/modules/events
5
+ #= require joosy/core/modules/container
6
+ #= require joosy/core/modules/time_manager
7
+ #= require joosy/core/modules/widgets_manager
8
+ #= require joosy/core/modules/filters
9
+
10
+ class Joosy.Layout extends Joosy.Module
11
+ @include Joosy.Modules.Log
12
+ @include Joosy.Modules.Events
13
+ @include Joosy.Modules.Container
14
+ @include Joosy.Modules.TimeManager
15
+ @include Joosy.Modules.WidgetsManager
16
+ @include Joosy.Modules.Filters
17
+
18
+ constructor: ->
19
+ @view ||= JST['app/templates/layouts/default']
20
+
21
+ navigate: (args...) -> Joosy.Router.navigate(args...)
22
+
23
+ __load: (@container) ->
24
+ @refreshElements()
25
+ @__delegateEvents()
26
+ @__setupWidgets()
27
+ @__runAfterLoads()
28
+
29
+ __unload: ->
30
+ @clearTime()
31
+ @__unloadWidgets()
32
+ @__runAfterUnloads()
33
+
34
+ yield: ->
35
+ @uuid = Joosy.uuid()
36
+
37
+ content: ->
38
+ $("##{@uuid}")
@@ -0,0 +1,51 @@
1
+ Joosy.Modules.Container =
2
+ events: false
3
+ elements: false
4
+
5
+ eventSplitter: /^(\S+)\s*(.*)$/
6
+
7
+ $: (selector) -> $(selector, @container)
8
+
9
+ refreshElements: ->
10
+ @__collectElements().each (key, value) => @[key] = @$(value)
11
+
12
+ swapContainer: (container, data) ->
13
+ realContainer = container.clone().html(data)
14
+ container.replaceWith realContainer
15
+ return realContainer
16
+
17
+ __collectElements: ->
18
+ elements = Object.extended(@elements || {})
19
+ klass = @
20
+ while klass = klass.constructor.__super__
21
+ elements.merge(klass.elements, false)
22
+ elements
23
+
24
+ __collectEvents: ->
25
+ events = Object.extended(@events || {})
26
+ klass = @
27
+ while klass = klass.constructor.__super__
28
+ events.merge(klass.events, false)
29
+ events
30
+
31
+ __extractSelector: (selector) ->
32
+ if r = selector.match(/\$([A-z]+)/)
33
+ selector = @__collectElements()[r[1]]
34
+ selector
35
+
36
+ __delegateEvents: ->
37
+ module = @
38
+ events = @__collectEvents()
39
+
40
+ events.each (key, method) =>
41
+ method = @[method] unless typeof(method) is 'function'
42
+ callback = (event) -> method.call(module, @, event)
43
+
44
+ match = key.match(@eventSplitter)
45
+ eventName = match[1]
46
+ selector = @__extractSelector(match[2])
47
+
48
+ if selector is ''
49
+ @container.bind(eventName, callback)
50
+ else
51
+ @container.on(eventName, selector, callback)
@@ -0,0 +1,17 @@
1
+ Joosy.Modules.Events =
2
+ wait: (events, callback) ->
3
+ events = events.split(' ')
4
+ @__eventWaiters ||= []
5
+
6
+ @__eventWaiters.push [events, callback]
7
+
8
+ trigger: (event) ->
9
+ return unless @__eventWaiters
10
+
11
+ @__eventWaiters.each (entry, i) =>
12
+ index = entry[0].indexOf(event)
13
+ delete entry[0][index] if index >= 0
14
+
15
+ if entry[0].compact().length == 0
16
+ delete @__eventWaiters[i] and @__eventWaiters = @__eventWaiters.compact()
17
+ entry[1].call()
@@ -0,0 +1,39 @@
1
+ Joosy.Modules.Filters =
2
+ included: ->
3
+ @beforeLoad = (callback) ->
4
+ unless @::hasOwnProperty('__beforeLoads')
5
+ @::__beforeLoads = [].concat @.__super__.__beforeLoads || []
6
+ @::__beforeLoads.push callback
7
+
8
+ @afterLoad = (callback) ->
9
+ unless @::hasOwnProperty('__afterLoads')
10
+ @::__afterLoads = [].concat @.__super__.__afterLoads || []
11
+ @::__afterLoads.push callback
12
+
13
+ @afterUnload = (callback) ->
14
+ unless @::hasOwnProperty('__afterUnloads')
15
+ @::__afterUnloads = [].concat @.__super__.__afterUnloads || []
16
+ @::__afterUnloads.push callback
17
+
18
+ __runBeforeLoads: (opts...) ->
19
+ return true unless @__beforeLoads?.length > 0
20
+
21
+ flag = true
22
+
23
+ for filter in @__beforeLoads
24
+ filter = @[filter] unless typeof(filter) is 'function'
25
+ flag = flag && filter.apply(@, opts)
26
+
27
+ return flag
28
+
29
+ __runAfterLoads: (opts...) ->
30
+ if @__afterLoads?
31
+ for filter in @__afterLoads
32
+ filter = @[filter] unless typeof(filter) is 'function'
33
+ filter.apply(@, opts)
34
+
35
+ __runAfterUnloads: (opts...) ->
36
+ if @__afterUnloads?
37
+ for filter in @__afterUnloads
38
+ filter = @[filter] unless typeof(filter) is 'function'
39
+ filter.apply(@, opts)
@@ -0,0 +1,12 @@
1
+ Joosy.Modules.Log =
2
+ log: (args...) ->
3
+ return if typeof console is 'undefined'
4
+
5
+ if console.log.apply?
6
+ args.unshift "Joosy>"
7
+ console.log(args...)
8
+ else
9
+ console.log(args.first())
10
+
11
+ debug: (args...) ->
12
+ @log(args...) if Joosy.debug
@@ -0,0 +1,28 @@
1
+ moduleKeywords = ['included', 'extended']
2
+
3
+ class Joosy.Module
4
+ @hasAncestor = (what, klass) ->
5
+ [ what, klass ] = [ what.prototype, klass.prototype ]
6
+ while what
7
+ return true if what == klass
8
+ what = what.constructor?.__super__
9
+ false
10
+
11
+ @include: (obj) ->
12
+ throw('include(obj) requires obj') unless obj
13
+ Object.extended(obj).each (key, value) =>
14
+ if key not in moduleKeywords
15
+ @::[key] = value
16
+ obj.included?.apply(@)
17
+ @
18
+
19
+ @extend: (obj) ->
20
+ throw('extend(obj) requires obj') unless obj
21
+ Object.extended(obj).each (key, value) =>
22
+ if key not in moduleKeywords
23
+ @[key] = value
24
+ obj.extended?.apply(@)
25
+ @
26
+
27
+ constructor: ->
28
+ @init?(arguments...)
@@ -0,0 +1,23 @@
1
+ Joosy.Modules.TimeManager =
2
+ setTimeout: (timeout, action) ->
3
+ @__timeouts ||= []
4
+
5
+ timer = window.setTimeout (=> action()), timeout
6
+ @__timeouts.push timer
7
+ timer
8
+
9
+ setInterval: (delay, action) ->
10
+ @__intervals ||= []
11
+
12
+ timer = window.setInterval (=> action()), delay
13
+ @__intervals.push timer
14
+ timer
15
+
16
+ clearTime: ->
17
+ if @__intervals
18
+ for entry in @__intervals
19
+ window.clearInterval entry
20
+
21
+ if @__timeouts
22
+ for entry in @__timeouts
23
+ window.clearTimeout entry
@@ -0,0 +1,45 @@
1
+ Joosy.Modules.WidgetsManager =
2
+ registerWidget: (container, widget) ->
3
+ @__activeWidgets ||= []
4
+
5
+ if Joosy.Module.hasAncestor(widget, Joosy.Widget)
6
+ widget = new widget()
7
+
8
+ @__activeWidgets.push widget.__load(@, container)
9
+ return widget
10
+
11
+ unregisterWidget: (widget) ->
12
+ widget.__unload()
13
+ delete @__activeWidgets[@__activeWidgets.indexOf(widget)]
14
+
15
+ __collectWidgets: ->
16
+ widgets = Object.extended(@widgets || {})
17
+ klass = @
18
+ while klass = klass.constructor.__super__
19
+ widgets.merge(klass.widgets, false)
20
+ widgets
21
+
22
+ __setupWidgets: ->
23
+ widgets = @__collectWidgets()
24
+
25
+ widgets.each (selector, widget) =>
26
+ if selector == '$container'
27
+ selector = @container
28
+ else
29
+ if r = selector.match(/\$([A-z]+)/)
30
+ selector = @elements[r[1]]
31
+ selector = $(selector, @container)
32
+
33
+ Joosy.Modules.Log.debug "Widget registered at '#{selector.selector}'. Elements: #{selector.length}"
34
+
35
+ selector.each (elem) =>
36
+ if Joosy.Module.hasAncestor(widget, Joosy.Widget)
37
+ w = new widget(@)
38
+ else
39
+ w = widget.apply(@, [elem])
40
+
41
+ @registerWidget($(elem), w)
42
+
43
+ __unloadWidgets: ->
44
+ if @__activeWidgets
45
+ widget?.__unload() for widget in @__activeWidgets