joosy 0.1.0.RC3 → 0.1.0.alpha

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