joosy 1.2.0.alpha.41 → 1.2.0.alpha.51
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/Gruntfile.coffee +27 -7
- data/bin/joosy +1 -1
- data/bower.json +3 -2
- data/build/joosy/extensions/preloaders.js +189 -0
- data/build/joosy/extensions/resources-form.js +588 -0
- data/build/joosy/extensions/resources.js +673 -0
- data/build/joosy.js +2395 -0
- data/{src/joosy/generators → generators}/base.coffee +2 -2
- data/{src/joosy/generators → generators/command}/command.coffee +16 -3
- data/generators/command/help.coffee +38 -0
- data/{src/joosy/generators → generators}/layout.coffee +0 -0
- data/{src/joosy/generators → generators}/page.coffee +0 -0
- data/{src/joosy/generators → generators}/project/base.coffee +2 -4
- data/{src/joosy/generators → generators}/project/standalone.coffee +4 -3
- data/{src/joosy/generators → generators}/project.coffee +0 -0
- data/generators/templates/application/base/application.coffee +13 -0
- data/{templates → generators/templates}/application/base/helpers/application.coffee +0 -0
- data/{templates → generators/templates}/application/base/layouts/application.coffee +0 -0
- data/{templates → generators/templates}/application/base/pages/application.coffee +0 -0
- data/{templates → generators/templates}/application/base/pages/welcome/index.coffee +0 -0
- data/{templates → generators/templates}/application/base/routes.coffee +0 -0
- data/{templates → generators/templates}/application/base/templates/layouts/application.jst.hamlc +0 -0
- data/{templates → generators/templates}/application/base/templates/pages/welcome/index.jst.hamlc +0 -0
- data/{templates → generators/templates}/application/standalone/Gruntfile.coffee +1 -0
- data/{templates → generators/templates}/application/standalone/Procfile +0 -0
- data/{templates → generators/templates}/application/standalone/_gitignore +0 -0
- data/generators/templates/application/standalone/bower.json +17 -0
- data/{templates → generators/templates}/application/standalone/package.json +0 -0
- data/{templates → generators/templates}/application/standalone/source/haml/index.haml +0 -0
- data/{templates → generators/templates}/application/standalone/source/stylesheets/application.styl +0 -0
- data/{templates → generators/templates}/layout/basic.coffee +0 -0
- data/{templates → generators/templates}/layout/namespaced.coffee +0 -0
- data/{templates → generators/templates}/page/basic.coffee +0 -0
- data/{templates → generators/templates}/page/namespaced.coffee +0 -0
- data/{templates → generators/templates}/widget/basic.coffee +0 -0
- data/{templates → generators/templates}/widget/namespaced.coffee +0 -0
- data/{src/joosy/generators → generators}/widget.coffee +0 -0
- data/lib/joosy.rb +3 -3
- data/package.json +2 -3
- data/source/joosy/application.coffee +95 -0
- data/source/joosy/events/namespace.coffee +24 -0
- data/{src → source}/joosy/extensions/preloaders/caching.coffee +0 -0
- data/{src → source}/joosy/extensions/preloaders/index.coffee +0 -0
- data/{src → source}/joosy/extensions/preloaders/inline.coffee +0 -0
- data/{src → source}/joosy/extensions/resources/base.coffee +16 -8
- data/{src → source}/joosy/extensions/resources/collection.coffee +0 -0
- data/{src → source}/joosy/extensions/resources/index.coffee +0 -0
- data/{src → source}/joosy/extensions/resources/rest.coffee +0 -0
- data/{src → source}/joosy/extensions/resources/rest_collection.coffee +0 -0
- data/{src → source}/joosy/extensions/resources-form/form.coffee +18 -18
- data/{src → source}/joosy/extensions/resources-form/helpers/form.coffee +6 -6
- data/{src → source}/joosy/extensions/resources-form/index.coffee +0 -0
- data/source/joosy/helpers/routes.coffee +10 -0
- data/source/joosy/helpers/view.coffee +115 -0
- data/{src/joosy/core → source/joosy}/helpers/widgets.coffee +1 -1
- data/{src/joosy/core → source/joosy}/joosy.coffee +59 -19
- data/source/joosy/layout.coffee +73 -0
- data/{src/joosy/core → source/joosy}/module.coffee +7 -2
- data/{src/joosy/core/modules/container.coffee → source/joosy/modules/dom.coffee} +24 -17
- data/source/joosy/modules/events.coffee +156 -0
- data/source/joosy/modules/filters.coffee +67 -0
- data/{src/joosy/core → source/joosy}/modules/log.coffee +7 -3
- data/source/joosy/modules/page/scrolling.coffee +51 -0
- data/source/joosy/modules/page/title.coffee +18 -0
- data/{src/joosy/core → source/joosy}/modules/renderer.coffee +12 -13
- data/{src/joosy/core → source/joosy}/modules/time_manager.coffee +5 -1
- data/{src/joosy/core → source/joosy}/modules/widgets_manager.coffee +9 -5
- data/source/joosy/page.coffee +68 -0
- data/{src/joosy/core → source/joosy}/resources/watcher.coffee +5 -1
- data/source/joosy/router.coffee +305 -0
- data/{src/joosy/core → source/joosy}/templaters/jst.coffee +10 -7
- data/source/joosy/widget.coffee +385 -0
- data/source/joosy.coffee +1 -0
- data/{src/vendor → source}/metamorph.coffee +0 -0
- data/spec/helpers/matchers.coffee +8 -1
- data/spec/joosy/core/application_spec.coffee +121 -20
- data/spec/joosy/core/helpers/view_spec.coffee +3 -3
- data/spec/joosy/core/helpers/widgets_spec.coffee +3 -6
- data/spec/joosy/core/joosy_spec.coffee +0 -5
- data/spec/joosy/core/layout_spec.coffee +2 -28
- data/spec/joosy/core/modules/dom_spec.coffee +133 -0
- data/spec/joosy/core/modules/events_spec.coffee +16 -9
- data/spec/joosy/core/modules/filters_spec.coffee +232 -89
- data/spec/joosy/core/modules/log_spec.coffee +2 -2
- data/spec/joosy/core/modules/renderer_spec.coffee +8 -4
- data/spec/joosy/core/page_spec.coffee +2 -201
- data/spec/joosy/core/router_spec.coffee +295 -233
- data/spec/joosy/core/templaters/jst_spec.coffee +1 -1
- data/spec/joosy/core/widget_spec.coffee +373 -34
- data/spec/joosy/environments/amd_spec.coffee +38 -0
- data/spec/joosy/environments/global_spec.coffee +21 -0
- data/spec/joosy/extensions/form/form_spec.coffee +18 -18
- data/spec/joosy/extensions/form/helpers/forms_spec.coffee +1 -1
- data/spec/joosy/extensions/resources/base_spec.coffee +23 -11
- data/tasks/joosy.coffee +6 -9
- metadata +75 -69
- data/lib/extensions/preloaders.js +0 -193
- data/lib/extensions/resources-form.js +0 -592
- data/lib/extensions/resources.js +0 -675
- data/lib/joosy.js +0 -2199
- data/spec/joosy/core/modules/container_spec.coffee +0 -153
- data/spec/joosy/core/modules/widget_manager_spec.coffee +0 -96
- data/src/joosy/core/application.coffee +0 -59
- data/src/joosy/core/helpers/view.coffee +0 -52
- data/src/joosy/core/layout.coffee +0 -174
- data/src/joosy/core/modules/events.coffee +0 -188
- data/src/joosy/core/modules/filters.coffee +0 -42
- data/src/joosy/core/page.coffee +0 -383
- data/src/joosy/core/router.coffee +0 -313
- data/src/joosy/core/widget.coffee +0 -88
- data/src/joosy.coffee +0 -1
- data/templates/application/base/application.coffee +0 -9
- data/templates/application/standalone/bower.json +0 -7
@@ -0,0 +1,115 @@
|
|
1
|
+
#= require joosy/joosy
|
2
|
+
|
3
|
+
#
|
4
|
+
# Rendering and string representation helpers
|
5
|
+
#
|
6
|
+
Joosy.helpers 'Application', ->
|
7
|
+
|
8
|
+
# Little helpers for HTML escaping
|
9
|
+
DOMtext = document.createTextNode("test")
|
10
|
+
DOMnative = document.createElement("span")
|
11
|
+
DOMnative.appendChild(DOMtext)
|
12
|
+
|
13
|
+
#
|
14
|
+
# Escapes HTML string
|
15
|
+
#
|
16
|
+
# @param [String] html String to escape
|
17
|
+
# @return [String] Escaped string
|
18
|
+
#
|
19
|
+
@escapeOnce = (html) ->
|
20
|
+
DOMtext.nodeValue = html
|
21
|
+
DOMnative.innerHTML
|
22
|
+
|
23
|
+
#
|
24
|
+
# Generates HTML string
|
25
|
+
#
|
26
|
+
# @param [String] name Tag name
|
27
|
+
# @param [Object] options Tag attributes
|
28
|
+
# @param [Boolean] open Marks whether standalone tags (like <br>) should be kept open
|
29
|
+
# @param [Boolean] escape Marks whether atribute values should be escaped
|
30
|
+
# @return [String] Tag HTML string
|
31
|
+
#
|
32
|
+
@tag = (name, options={}, open=false, escape=true) ->
|
33
|
+
element = document.createElement name
|
34
|
+
temp = document.createElement 'div'
|
35
|
+
|
36
|
+
for name, value of options
|
37
|
+
value = @escapeOnce(value) if escape
|
38
|
+
element.setAttribute name, value
|
39
|
+
|
40
|
+
temp.appendChild element
|
41
|
+
tag = temp.innerHTML
|
42
|
+
|
43
|
+
tag = tag.replace('/>', '>') if open
|
44
|
+
tag
|
45
|
+
|
46
|
+
#
|
47
|
+
# Generates HTML tag string with given content
|
48
|
+
#
|
49
|
+
# @param [String] name Tag name
|
50
|
+
# @param [Object] contentOrOptions Tag attributes
|
51
|
+
# @param [String] contentOrOptions String content
|
52
|
+
# @param [Object] options Tag attributes
|
53
|
+
# @param [Boolean] escape Marks whether attribute values should be escaped
|
54
|
+
# @return [String] Tag HTML string
|
55
|
+
#
|
56
|
+
# Possible arguments variations:
|
57
|
+
# 1. @contentTag 'name', 'content'
|
58
|
+
# 2. @contentTag 'name', {}, ->
|
59
|
+
# 3. @contentTag 'name', {}, false, ->
|
60
|
+
# 4. @contentTag 'name', ->
|
61
|
+
#
|
62
|
+
# Example
|
63
|
+
# != @contentTag 'div', {class: 'foo'}, =>
|
64
|
+
# != @contentTag 'hr'
|
65
|
+
#
|
66
|
+
@contentTag = (name, contentOrOptions=null, options=null, escape=true) ->
|
67
|
+
# This is a bit painfull but this is
|
68
|
+
# how we emulate Ruby block with lambda :(
|
69
|
+
if Object.isString(contentOrOptions)
|
70
|
+
options ||= {}
|
71
|
+
content = contentOrOptions
|
72
|
+
else if Object.isObject(contentOrOptions)
|
73
|
+
if Object.isFunction(options)
|
74
|
+
escape = true
|
75
|
+
content = options()
|
76
|
+
else
|
77
|
+
escape = options
|
78
|
+
content = escape()
|
79
|
+
options = contentOrOptions
|
80
|
+
else
|
81
|
+
options = {}
|
82
|
+
content = contentOrOptions()
|
83
|
+
|
84
|
+
element = document.createElement name
|
85
|
+
temp = document.createElement 'div'
|
86
|
+
|
87
|
+
for name, value of options
|
88
|
+
value = @escapeOnce(value) if escape
|
89
|
+
element.setAttribute name, value
|
90
|
+
|
91
|
+
try
|
92
|
+
element.innerHTML = content
|
93
|
+
catch e
|
94
|
+
# setting innerHTML fails in the IE for elements, which cann't have children (INPUT, for ex.)
|
95
|
+
# suppress this error unless content looks valuable
|
96
|
+
throw e if content
|
97
|
+
|
98
|
+
temp.appendChild element
|
99
|
+
temp.innerHTML
|
100
|
+
|
101
|
+
#
|
102
|
+
# Wraps the inline block into given template
|
103
|
+
# Request template will receive the inline block as @yield parameter
|
104
|
+
#
|
105
|
+
# Example
|
106
|
+
# -# foo/baz template
|
107
|
+
# != @renderWrapped 'foo/bar', ->
|
108
|
+
# %b This string will be passed to 'foo/bar'
|
109
|
+
#
|
110
|
+
# -# foo/bar template
|
111
|
+
# %h1 I'm the wrapper here!
|
112
|
+
# != @yield
|
113
|
+
#
|
114
|
+
@renderWrapped = (template, lambda) ->
|
115
|
+
@render template, Joosy.Module.merge(this, yield: lambda())
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#= require_self
|
2
|
-
#= require joosy/
|
2
|
+
#= require joosy/module
|
3
3
|
|
4
4
|
#
|
5
5
|
# All the tiny core stuff
|
@@ -22,6 +22,40 @@
|
|
22
22
|
#
|
23
23
|
Templaters: {}
|
24
24
|
|
25
|
+
#
|
26
|
+
# Helpers container
|
27
|
+
#
|
28
|
+
Helpers: {}
|
29
|
+
|
30
|
+
#
|
31
|
+
# Events namespace
|
32
|
+
#
|
33
|
+
Events: {}
|
34
|
+
|
35
|
+
|
36
|
+
### Global settings ###
|
37
|
+
|
38
|
+
#
|
39
|
+
# Debug mode
|
40
|
+
#
|
41
|
+
debug: (value) ->
|
42
|
+
if value?
|
43
|
+
@__debug = value
|
44
|
+
else
|
45
|
+
!!@__debug
|
46
|
+
|
47
|
+
#
|
48
|
+
# Templating engine
|
49
|
+
#
|
50
|
+
templater: (value) ->
|
51
|
+
if value?
|
52
|
+
@__templater = value
|
53
|
+
else
|
54
|
+
throw new Error "No templater registered" unless @__templater
|
55
|
+
@__templater
|
56
|
+
|
57
|
+
### Global helpers ###
|
58
|
+
|
25
59
|
#
|
26
60
|
# Registeres anything inside specified namespace (objects chain starting from `window`)
|
27
61
|
#
|
@@ -54,7 +88,27 @@
|
|
54
88
|
# @param [Boolean] generator Helpers content
|
55
89
|
#
|
56
90
|
helpers: (name, generator) ->
|
57
|
-
Joosy.
|
91
|
+
Joosy.Helpers[name] ||= {}
|
92
|
+
generator.apply Joosy.Helpers[name]
|
93
|
+
|
94
|
+
#
|
95
|
+
# Generates ID unique within current run
|
96
|
+
#
|
97
|
+
uid: ->
|
98
|
+
@__uid ||= 0
|
99
|
+
"__joosy#{@__uid++}"
|
100
|
+
|
101
|
+
#
|
102
|
+
# Generates UUID
|
103
|
+
#
|
104
|
+
uuid: ->
|
105
|
+
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace /[xy]/g, (c) ->
|
106
|
+
r = Math.random() * 16 | 0
|
107
|
+
v = if c is 'x' then r else r & 3 | 8
|
108
|
+
v.toString 16
|
109
|
+
.toUpperCase()
|
110
|
+
|
111
|
+
### Shortcuts ###
|
58
112
|
|
59
113
|
#
|
60
114
|
# Runs set of callbacks finializing with result callback
|
@@ -74,23 +128,6 @@
|
|
74
128
|
else
|
75
129
|
Joosy.Modules.Events.synchronize arguments...
|
76
130
|
|
77
|
-
#
|
78
|
-
# Generates ID unique within current run
|
79
|
-
#
|
80
|
-
uid: ->
|
81
|
-
@__uid ||= 0
|
82
|
-
"__joosy#{@__uid++}"
|
83
|
-
|
84
|
-
#
|
85
|
-
# Generates UUID
|
86
|
-
#
|
87
|
-
uuid: ->
|
88
|
-
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace /[xy]/g, (c) ->
|
89
|
-
r = Math.random() * 16 | 0
|
90
|
-
v = if c is 'x' then r else r & 3 | 8
|
91
|
-
v.toString 16
|
92
|
-
.toUpperCase()
|
93
|
-
|
94
131
|
#
|
95
132
|
# Basic URI builder. Joins base path with params hash
|
96
133
|
#
|
@@ -116,3 +153,6 @@
|
|
116
153
|
paramsString = '&' + paramsString
|
117
154
|
|
118
155
|
url + paramsString + hash
|
156
|
+
|
157
|
+
if define?.amd?
|
158
|
+
define 'joosy', -> Joosy
|
@@ -0,0 +1,73 @@
|
|
1
|
+
#= require joosy/joosy
|
2
|
+
#= require joosy/widget
|
3
|
+
#= require joosy/helpers/view
|
4
|
+
|
5
|
+
#
|
6
|
+
# Base class for all Joosy Layouts.
|
7
|
+
#
|
8
|
+
# @example Sample application layout
|
9
|
+
# class @ApplicationLayout extends Joosy.Layout
|
10
|
+
# @view 'application'
|
11
|
+
#
|
12
|
+
class Joosy.Layout extends Joosy.Widget
|
13
|
+
@helper 'page'
|
14
|
+
|
15
|
+
#
|
16
|
+
# @param [Hash] params Route params
|
17
|
+
# @param [Joosy.Layout] previous Layout to replace on load
|
18
|
+
#
|
19
|
+
constructor: (@params, @previous) ->
|
20
|
+
@uid = Joosy.uid()
|
21
|
+
|
22
|
+
#
|
23
|
+
# Helper that outputs container tag for the page
|
24
|
+
#
|
25
|
+
# @param [String] name Tag name
|
26
|
+
# @param [Object] options Tag attributes
|
27
|
+
#
|
28
|
+
page: (tag, options={}) ->
|
29
|
+
options.id = @uid
|
30
|
+
Joosy.Helpers.Application.tag tag, options
|
31
|
+
|
32
|
+
#
|
33
|
+
# Gets DOM element that should be used as container for nested Page
|
34
|
+
#
|
35
|
+
# @return [jQuery]
|
36
|
+
#
|
37
|
+
content: ->
|
38
|
+
$("##{@uid}")
|
39
|
+
|
40
|
+
######
|
41
|
+
###### Widget extensions
|
42
|
+
######
|
43
|
+
|
44
|
+
#
|
45
|
+
# This is required by {Joosy.Modules.Renderer}
|
46
|
+
# Sets the base template dir to app_name/templates/layouts
|
47
|
+
#
|
48
|
+
__renderSection: ->
|
49
|
+
'layouts'
|
50
|
+
|
51
|
+
#
|
52
|
+
# Extends list of registered nested widgets with page
|
53
|
+
#
|
54
|
+
__nestingMap: (page) ->
|
55
|
+
map = super()
|
56
|
+
map["##{@uid}"] =
|
57
|
+
instance: page
|
58
|
+
nested: page.__nestingMap()
|
59
|
+
|
60
|
+
map
|
61
|
+
|
62
|
+
#
|
63
|
+
# Adds page as first argument to default bootstrap
|
64
|
+
#
|
65
|
+
# @param [Joosy.Page] page Page to inject
|
66
|
+
# @param [jQuery] applicationContainer The base container for the application to paint at
|
67
|
+
#
|
68
|
+
__bootstrapDefault: (page, applicationContainer) ->
|
69
|
+
@__bootstrap @__nestingMap(page), applicationContainer
|
70
|
+
|
71
|
+
# AMD wrapper
|
72
|
+
if define?.amd?
|
73
|
+
define 'joosy/layout', -> Joosy.Layout
|
@@ -2,7 +2,7 @@
|
|
2
2
|
# Base Joosy class extending Coffee class with module-like injections
|
3
3
|
# and other tiny stuff.
|
4
4
|
#
|
5
|
-
class
|
5
|
+
class Joosy.Module
|
6
6
|
#
|
7
7
|
# Sets the default namespace for all Joosy descendants.
|
8
8
|
# This is used in {Joosy.namespace} magic.
|
@@ -43,7 +43,8 @@ class @Joosy.Module
|
|
43
43
|
unless what? && klass?
|
44
44
|
return false
|
45
45
|
|
46
|
-
|
46
|
+
what = what.prototype
|
47
|
+
klass = klass.prototype
|
47
48
|
|
48
49
|
while what
|
49
50
|
if what == klass
|
@@ -133,3 +134,7 @@ class @Joosy.Module
|
|
133
134
|
|
134
135
|
object.extended?.apply this
|
135
136
|
null
|
137
|
+
|
138
|
+
# AMD wrapper
|
139
|
+
if define?.amd?
|
140
|
+
define 'joosy/module', -> Joosy.Module
|
@@ -1,13 +1,13 @@
|
|
1
|
-
#= require joosy/
|
1
|
+
#= require joosy/joosy
|
2
2
|
|
3
3
|
#
|
4
4
|
# DOM container handling, DOM elements and DOM events bindings
|
5
5
|
#
|
6
|
-
# @note Requires implementor to contain DOM node at
|
6
|
+
# @note Requires implementor to contain DOM node at @$container propert
|
7
7
|
#
|
8
8
|
# @mixin
|
9
9
|
#
|
10
|
-
Joosy.Modules.
|
10
|
+
Joosy.Modules.DOM =
|
11
11
|
eventSplitter: /^(\S+)\s*(.*)$/
|
12
12
|
|
13
13
|
included: ->
|
@@ -41,18 +41,7 @@ Joosy.Modules.Container =
|
|
41
41
|
Object.merge @::__events, map
|
42
42
|
|
43
43
|
$: (selector) ->
|
44
|
-
$(selector,
|
45
|
-
|
46
|
-
#
|
47
|
-
# Fills container with given data removing all events
|
48
|
-
#
|
49
|
-
# @param [jQuery] container jQuery entity of container to update
|
50
|
-
# @param [String] data HTML to inject
|
51
|
-
#
|
52
|
-
swapContainer: (container, data) ->
|
53
|
-
container.unbind().off()
|
54
|
-
container.html data
|
55
|
-
container
|
44
|
+
$(selector, @$container)
|
56
45
|
|
57
46
|
#
|
58
47
|
# Converts '$...' notation to selector from 'elements'
|
@@ -127,10 +116,28 @@ Joosy.Modules.Container =
|
|
127
116
|
selector = @__extractSelector match[2]
|
128
117
|
|
129
118
|
if selector == ""
|
130
|
-
|
119
|
+
@$container.bind eventName, callback
|
131
120
|
Joosy.Modules.Log.debugAs @, "#{eventName} binded on container"
|
132
121
|
else if selector == undefined
|
133
122
|
throw new Error "Unknown element #{match[2]} in #{Joosy.Module.__className @constructor} (maybe typo?)"
|
134
123
|
else
|
135
|
-
|
124
|
+
@$container.on eventName, selector, callback
|
136
125
|
Joosy.Modules.Log.debugAs @, "#{eventName} binded on #{selector}"
|
126
|
+
|
127
|
+
__clearContainer: ->
|
128
|
+
@$container?.unbind().off()
|
129
|
+
@$container = $()
|
130
|
+
|
131
|
+
|
132
|
+
# This is not clearly related for container management
|
133
|
+
# But it will be later common for all containers
|
134
|
+
# See https://github.com/joosy/joosy/issues/102
|
135
|
+
__loadData: (done) ->
|
136
|
+
@data = {}
|
137
|
+
@__runFetchs [], =>
|
138
|
+
@dataFetched = true
|
139
|
+
done()
|
140
|
+
|
141
|
+
# AMD wrapper
|
142
|
+
if define?.amd?
|
143
|
+
define 'joosy/modules/dom', -> Joosy.Modules.DOM
|
@@ -0,0 +1,156 @@
|
|
1
|
+
#= require joosy/joosy
|
2
|
+
#= require_tree ../events
|
3
|
+
|
4
|
+
class SynchronizationContext
|
5
|
+
constructor: -> @actions = []
|
6
|
+
do: (action) -> @actions.push action
|
7
|
+
after: (@after) ->
|
8
|
+
|
9
|
+
#
|
10
|
+
# Basic events implementation
|
11
|
+
#
|
12
|
+
# @mixin
|
13
|
+
#
|
14
|
+
Joosy.Modules.Events =
|
15
|
+
|
16
|
+
#
|
17
|
+
# Waits for the list of given events to happen at least once. Then runs callback.
|
18
|
+
#
|
19
|
+
# @param [String|Array] events List of events to wait for separated by space
|
20
|
+
# @param [Function] callback Action to run when all events were triggered at least once
|
21
|
+
# @param [Hash] options Options
|
22
|
+
#
|
23
|
+
wait: (name, events, callback) ->
|
24
|
+
@__oneShotEvents = {} unless @hasOwnProperty('__oneShotEvents')
|
25
|
+
|
26
|
+
# unnamed binding
|
27
|
+
if Object.isFunction(events)
|
28
|
+
callback = events
|
29
|
+
events = name
|
30
|
+
name = Object.keys(@__oneShotEvents).length.toString()
|
31
|
+
|
32
|
+
events = @__splitEvents(events)
|
33
|
+
|
34
|
+
if events.length > 0
|
35
|
+
@__oneShotEvents[name] = [events, callback]
|
36
|
+
else
|
37
|
+
callback()
|
38
|
+
|
39
|
+
name
|
40
|
+
|
41
|
+
#
|
42
|
+
# Removes waiter action
|
43
|
+
#
|
44
|
+
# @param [Function] target Name of waiter to unbind
|
45
|
+
#
|
46
|
+
unwait: (target) ->
|
47
|
+
delete @__oneShotEvents[target] if @hasOwnProperty '__oneShotEvents'
|
48
|
+
|
49
|
+
#
|
50
|
+
# Binds action to run each time any of given event was triggered
|
51
|
+
#
|
52
|
+
# @param [String|Array] events List of events separated by space
|
53
|
+
# @param [Function] callback Action to run on trigger
|
54
|
+
# @param [Hash] options Options
|
55
|
+
#
|
56
|
+
bind: (name, events, callback) ->
|
57
|
+
@__boundEvents = {} unless @hasOwnProperty '__boundEvents'
|
58
|
+
|
59
|
+
# unnamed binding
|
60
|
+
if Object.isFunction(events)
|
61
|
+
callback = events
|
62
|
+
events = name
|
63
|
+
name = Object.keys(@__boundEvents).length.toString()
|
64
|
+
|
65
|
+
events = @__splitEvents(events)
|
66
|
+
|
67
|
+
if events.length > 0
|
68
|
+
@__boundEvents[name] = [events, callback]
|
69
|
+
else
|
70
|
+
callback()
|
71
|
+
|
72
|
+
name
|
73
|
+
|
74
|
+
#
|
75
|
+
# Unbinds action from runing on trigger
|
76
|
+
#
|
77
|
+
# @param [Function] target Name of bind to unbind
|
78
|
+
#
|
79
|
+
unbind: (target) ->
|
80
|
+
delete @__boundEvents[target] if @hasOwnProperty '__boundEvents'
|
81
|
+
|
82
|
+
#
|
83
|
+
# Triggers event for {bind} and {wait}
|
84
|
+
#
|
85
|
+
# @param [String] Name of event to trigger
|
86
|
+
#
|
87
|
+
trigger: (event, data...) ->
|
88
|
+
Joosy.Modules.Log.debugAs @, "Event #{event} triggered"
|
89
|
+
|
90
|
+
if Object.isObject event
|
91
|
+
remember = event.remember
|
92
|
+
event = event.name
|
93
|
+
else
|
94
|
+
remember = false
|
95
|
+
|
96
|
+
if @hasOwnProperty '__oneShotEvents'
|
97
|
+
fire = []
|
98
|
+
for name, [events, callback] of @__oneShotEvents
|
99
|
+
events.remove event
|
100
|
+
if events.length == 0
|
101
|
+
fire.push name
|
102
|
+
fire.each (name) =>
|
103
|
+
callback = @__oneShotEvents[name][1]
|
104
|
+
delete @__oneShotEvents[name]
|
105
|
+
callback data...
|
106
|
+
|
107
|
+
if @hasOwnProperty '__boundEvents'
|
108
|
+
for name, [events, callback] of @__boundEvents
|
109
|
+
if events.any event
|
110
|
+
callback data...
|
111
|
+
|
112
|
+
if remember
|
113
|
+
@__triggeredEvents = {} unless @hasOwnProperty '__triggeredEvents'
|
114
|
+
@__triggeredEvents[event] = true
|
115
|
+
|
116
|
+
#
|
117
|
+
# Runs set of callbacks finializing with result callback
|
118
|
+
#
|
119
|
+
# @example Basic usage
|
120
|
+
# @synchronize (context) ->
|
121
|
+
# context.do (done) -> done()
|
122
|
+
# context.do (done) -> done()
|
123
|
+
# context.after ->
|
124
|
+
# console.log 'Success!'
|
125
|
+
#
|
126
|
+
# @param [Function] block Configuration block (see example)
|
127
|
+
#
|
128
|
+
synchronize: (block) ->
|
129
|
+
context = new SynchronizationContext
|
130
|
+
counter = 0
|
131
|
+
|
132
|
+
block(context)
|
133
|
+
|
134
|
+
if context.actions.length == 0
|
135
|
+
context.after.call(@)
|
136
|
+
else
|
137
|
+
context.actions.each (action) =>
|
138
|
+
action.call @, ->
|
139
|
+
if ++counter >= context.actions.length
|
140
|
+
context.after.call(@)
|
141
|
+
|
142
|
+
__splitEvents: (events) ->
|
143
|
+
if Object.isString events
|
144
|
+
if events.isBlank()
|
145
|
+
events = []
|
146
|
+
else
|
147
|
+
events = events.trim().split /\s+/
|
148
|
+
|
149
|
+
if @hasOwnProperty '__triggeredEvents'
|
150
|
+
events = events.findAll (e) => !@__triggeredEvents[e]
|
151
|
+
|
152
|
+
events
|
153
|
+
|
154
|
+
# AMD wrapper
|
155
|
+
if define?.amd?
|
156
|
+
define 'joosy/modules/events', -> Joosy.Modules.Events
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#= require joosy/joosy
|
2
|
+
|
3
|
+
#
|
4
|
+
# Filters registration routines
|
5
|
+
#
|
6
|
+
# @mixin
|
7
|
+
#
|
8
|
+
Joosy.Modules.Filters =
|
9
|
+
|
10
|
+
#
|
11
|
+
# Defines static registration routines
|
12
|
+
#
|
13
|
+
# @example Set of methods
|
14
|
+
# class Test
|
15
|
+
# @beforeLoad -> # supposed to run before load and control loading queue
|
16
|
+
# @afterLoad -> # supposed to run after load to finalize loading
|
17
|
+
# @afterUnload -> # supposed to run after unload to collect garbage
|
18
|
+
#
|
19
|
+
# # private
|
20
|
+
#
|
21
|
+
# @__runBeforeLoads() # Runs filters registered as beforeLoad
|
22
|
+
# @__runAfterLoads() # Runs filters registered as afterLoad
|
23
|
+
# @__runAfterUnloads() # Runs filters registered as afterUnload
|
24
|
+
#
|
25
|
+
included: ->
|
26
|
+
@__registerFilterCollector = (filter) =>
|
27
|
+
@[filter] = (callback) ->
|
28
|
+
unless @::hasOwnProperty "__#{filter}s"
|
29
|
+
@::["__#{filter}s"] = [].concat @.__super__["__#{filter}s"] || []
|
30
|
+
@::["__#{filter}s"].push callback
|
31
|
+
|
32
|
+
filter.charAt(0).toUpperCase() + filter.slice(1)
|
33
|
+
|
34
|
+
@registerPlainFilters = (filters...) =>
|
35
|
+
filters.each (filter) =>
|
36
|
+
camelized = @__registerFilterCollector filter
|
37
|
+
|
38
|
+
@::["__run#{camelized}s"] = (params...) ->
|
39
|
+
return true unless @["__#{filter}s"]
|
40
|
+
|
41
|
+
@["__#{filter}s"].reduce (flag, callback) =>
|
42
|
+
callback = @[callback] unless Object.isFunction callback
|
43
|
+
flag && callback.apply(@, params) != false
|
44
|
+
, true
|
45
|
+
|
46
|
+
@registerSequencedFilters = (filters...) =>
|
47
|
+
filters.each (filter) =>
|
48
|
+
camelized = @__registerFilterCollector filter
|
49
|
+
|
50
|
+
@::["__run#{camelized}s"] = (params, callback) ->
|
51
|
+
return callback() unless @["__#{filter}s"]
|
52
|
+
|
53
|
+
runners = @["__#{filter}s"]
|
54
|
+
filterer = @
|
55
|
+
|
56
|
+
if runners.length == 1
|
57
|
+
return runners[0].apply @, params.include(callback)
|
58
|
+
|
59
|
+
Joosy.synchronize (context) ->
|
60
|
+
runners.each (runner) ->
|
61
|
+
context.do (done) ->
|
62
|
+
runner.apply filterer, params.include(done)
|
63
|
+
context.after callback
|
64
|
+
|
65
|
+
# AMD wrapper
|
66
|
+
if define?.amd?
|
67
|
+
define 'joosy/modules/filters', -> Joosy.Modules.Filters
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#= require joosy/
|
1
|
+
#= require joosy/joosy
|
2
2
|
|
3
3
|
#
|
4
4
|
# Wrappers for console.log
|
@@ -23,7 +23,7 @@ Joosy.Modules.Log =
|
|
23
23
|
# Runs `log` if debug is active
|
24
24
|
#
|
25
25
|
debug: (args...) ->
|
26
|
-
return unless Joosy.
|
26
|
+
return unless Joosy.debug()
|
27
27
|
@log args...
|
28
28
|
|
29
29
|
#
|
@@ -33,6 +33,10 @@ Joosy.Modules.Log =
|
|
33
33
|
# @param [String] string Message to log
|
34
34
|
#
|
35
35
|
debugAs: (context, string, args...) ->
|
36
|
-
return unless Joosy.
|
36
|
+
return unless Joosy.debug()
|
37
37
|
context = Joosy.Module.__className(context) || 'unknown context'
|
38
38
|
@debug "#{context}> #{string}", args...
|
39
|
+
|
40
|
+
# AMD wrapper
|
41
|
+
if define?.amd?
|
42
|
+
define 'joosy/modules/log', -> Joosy.Modules.Log
|
@@ -0,0 +1,51 @@
|
|
1
|
+
Joosy.Modules.Page_Scrolling =
|
2
|
+
|
3
|
+
included: ->
|
4
|
+
#
|
5
|
+
# Sets the position where page will be scrolled to after load.
|
6
|
+
#
|
7
|
+
# @note If you use animated scroll joosy will atempt to temporarily fix the
|
8
|
+
# height of your document while scrolling to prevent jump effect.
|
9
|
+
#
|
10
|
+
# @param [jQuery] element Element to scroll to
|
11
|
+
# @param [Hash] options
|
12
|
+
#
|
13
|
+
# @option options [Integer] speed Sets the animation duration (500 is default)
|
14
|
+
# @option options [Integer] margin Defines the margin from element position.
|
15
|
+
# Can be negative.
|
16
|
+
#
|
17
|
+
@scroll = (element, options={}) ->
|
18
|
+
@::__scrollElement = element
|
19
|
+
@::__scrollSpeed = options.speed || 500
|
20
|
+
@::__scrollMargin = options.margin || 0
|
21
|
+
|
22
|
+
@paint (complete) ->
|
23
|
+
@__fixHeight() if @__scrollElement && @__scrollSpeed != 0
|
24
|
+
complete()
|
25
|
+
|
26
|
+
@afterLoad ->
|
27
|
+
@__performScrolling() if @__scrollElement
|
28
|
+
|
29
|
+
#
|
30
|
+
# Scrolls page to stored positions
|
31
|
+
#
|
32
|
+
__performScrolling: ->
|
33
|
+
scroll = $(@__extractSelector @__scrollElement).offset()?.top + @__scrollMargin
|
34
|
+
Joosy.Modules.Log.debugAs @, "Scrolling to #{@__extractSelector @__scrollElement}"
|
35
|
+
$('html, body').animate {scrollTop: scroll}, @__scrollSpeed, =>
|
36
|
+
if @__scrollSpeed != 0
|
37
|
+
@__releaseHeight()
|
38
|
+
|
39
|
+
#
|
40
|
+
# Freezes the page height through $(html).
|
41
|
+
#
|
42
|
+
# Required to implement better {Joosy.Page.scroll} behavior.
|
43
|
+
#
|
44
|
+
__fixHeight: ->
|
45
|
+
$('html').css 'min-height', $(document).height()
|
46
|
+
|
47
|
+
#
|
48
|
+
# Undo {#__fixHeight}
|
49
|
+
#
|
50
|
+
__releaseHeight: ->
|
51
|
+
$('html').css 'min-height', ''
|