ende 0.4.24 → 0.4.25

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,35 @@
1
+ 'use strict'
2
+
3
+ define 'aura/extensions/stamps', ->
4
+
5
+
6
+ name: 'stamps'
7
+
8
+ version: '0.1.0'
9
+
10
+ require:
11
+ paths:
12
+ stampit: 'aura/extensions/stamps/stampit'
13
+
14
+ initialize: (application) ->
15
+ {sandbox, core} = application
16
+ stampit = require 'stampit'
17
+
18
+ core.stamps = {}
19
+
20
+ # TODO store stamps on a sandbox basis too
21
+ sandbox.stamp = core.stamp = stampit.mixIn (name, params...) ->
22
+ unless typeof name == 'string'
23
+ params.unshift name
24
+ name = null
25
+
26
+ stamp = stampit.apply stampit, params
27
+
28
+ if name then core.stamps[name] = stamp else stamp
29
+
30
+ , stampit
31
+
32
+
33
+
34
+
35
+
@@ -136,31 +136,33 @@ define 'aura/extensions/states', ['states'], (states) ->
136
136
 
137
137
  get: -> state.current
138
138
 
139
- afterAppStart: (application) ->
140
- # TODO Change the application to default state in flows extension
141
- if (application.startOptions.widgets)
139
+ # TODO clearer startup sequence
140
+ application.core.metabolize = (root) ->
141
+ # If any initialized flow changed the application state
142
+ # before the widgets initialization, store its state pass
143
+ # through the default state and go back to the old state
144
+ # created by the flows
145
+ #
146
+ # TODO initialize the first flow in flows extension
147
+ current_state = application.state if application.state != 'initialization'
148
+ application.startOptions.widgets ||= root
142
149
  application.state = "default"
143
- else
144
- application.core.metabolize = ->
145
- # If any initialized flow changed the application state
146
- # before the widgets initialization, store its state pass
147
- # through the default state and go back to the old state
148
- # created by the flows
149
- #
150
- # TODO initialize the first flow in flows extension
151
- current_state = application.state if application.state != 'initialization'
152
- application.state = "default"
153
-
154
- startup = application.core.start.apply @, arguments
155
-
156
- # TODO move to domain extension
157
- # TODO let this code more legible
158
- domain_flow = application.domain.default
159
- domain_flow?.ready ||= injection.then((widgets...) ->
160
- # TODO use es6-shim promises
161
- $.Deferred().resolveWith domain_flow, widgets
162
- ).done
163
150
 
164
- application.state = current_state if current_state?
151
+ startup = application.core.start arguments...
165
152
 
166
- startup
153
+ # TODO move to domain extension
154
+ # TODO let this code more legible
155
+ domain_flow = application.domain.default
156
+ domain_flow?.ready ||= injection.then((widgets...) ->
157
+ # TODO use es6-shim promises
158
+ $.Deferred().resolveWith domain_flow, widgets
159
+ ).done
160
+
161
+ application.state = current_state if current_state?
162
+
163
+ startup
164
+
165
+
166
+ afterAppStart: (application) ->
167
+ # TODO Change the application to default state in flows extension
168
+ application.state = "default" if application.startOptions.widgets
@@ -0,0 +1,152 @@
1
+ 'use strict';
2
+
3
+ define 'aura/extensions/widget/composable', ->
4
+ stamp = extend = null
5
+
6
+ advisorable = (advisor) ->
7
+ # TODO merge advices in the composition chain
8
+ advice_names = ['before', 'after', 'around']
9
+
10
+ extract_advices = (object) ->
11
+ found = []
12
+ for key of object when key.indexOf('_') isnt -1
13
+ [name, adviced] = key.split '_'
14
+
15
+ if advice_names.indexOf(name) != -1
16
+ callbacks = if object[key].length then object[key] else [object[key]]
17
+
18
+ delete object[key]
19
+
20
+ found.push
21
+ key: key
22
+ name: name
23
+ adviced: adviced
24
+ callbacks: callbacks
25
+
26
+ found
27
+
28
+ advisor.advice = (widget) ->
29
+
30
+ advices = extract_advices widget
31
+
32
+ for advice in advices
33
+
34
+ # in order to preserve declaration order, we must reverse the callbacks order
35
+ # TODO rename advice.name to advice.type
36
+ advice.callbacks.reverse() if advice.name == 'before'
37
+
38
+ # Advice with all callbacks
39
+ widget[advice.name] advice.adviced, callback for callback in advice.callbacks
40
+
41
+ widget
42
+
43
+ advisor.advisable = (factory) ->
44
+ original = factory.compose
45
+
46
+ compose_advices = (advices, composed_advices = {}) ->
47
+ for advice in advices
48
+ composed_advices[advice.key] ||= []
49
+ composed_advices[advice.key] = composed_advices[advice.key].concat advice.callbacks
50
+
51
+ composed_advices
52
+
53
+ composable_advices = (stamps...) ->
54
+ advices = []
55
+ for stamped in stamps
56
+ {fixed: {methods: stamp_methods}} = stamped
57
+ advices = advices.concat extract_advices stamp_methods
58
+
59
+ # Create a ultimate stamp with all advices arrays or functions
60
+ # merged, that will ultimatly override the prototype chain
61
+ # definitions
62
+ #
63
+ # TODO do not store advices definitions in the prototype chain
64
+ stamps.push stamp compose_advices advices
65
+
66
+ stamps
67
+
68
+ # Move current factory composition advices to a composable form
69
+ # {fixed: {methods: composition_methods}} = factory.composition
70
+ # compose_advices extract_advices(composition_methods), composition_methods
71
+
72
+ stamp.mixIn factory,
73
+ compose: (stamps...) ->
74
+ stamps.unshift factory.composition
75
+ original.apply factory, composable_advices stamps...
76
+
77
+ advice: advisor.advice
78
+
79
+
80
+ composable = advisor.composable
81
+ advisor.composable = ->
82
+ advisor.advisable composable.apply advisor, arguments
83
+
84
+ advisor
85
+
86
+ composerable = (compositor) ->
87
+ compositor.composable = (methods, state, enclose) ->
88
+ factory = (options) ->
89
+
90
+ # Inherit defaults from widget
91
+ options = _.defaults options, factory.composition.fixed.methods.options
92
+
93
+ # Composition only will compose methods and state!
94
+ instance = factory.composition options: options
95
+ enclose.call instance, options
96
+
97
+ # TODO check if it is needed to inherit compositions
98
+ # if methods.composition
99
+ # composition = methods.composition
100
+ # delete methods.composition
101
+ # composition = stamp.compose composition, stamp methods, state
102
+ # else
103
+ # composition = stamp methods, state
104
+
105
+ stamp.mixIn factory,
106
+ composition: stamp methods, state
107
+ # Suport an extension with multiple compositions
108
+ compose: -> @composition = stamp.compose @composition, arguments...
109
+
110
+ extend: ->
111
+ `var methods, state`
112
+ {fixed} = @composition
113
+ initializers = [enclose]
114
+ methods = {}
115
+ state = {}
116
+
117
+ for definition in arguments
118
+ {methods: definition_methods, state: definition_state} = definition
119
+
120
+ methods = extend methods, fixed.methods, definition_methods or definition
121
+ state = extend state , fixed.state , definition_state
122
+
123
+ initializers = initializers.concat fixed.enclose if fixed.enclose
124
+ initializers = initializers.concat definition.enclose if definition.enclose
125
+
126
+ enclosed = (properties) ->
127
+ initializers.forEach (initializer) => initializer.call @, properties
128
+ @
129
+
130
+ compositor.composable methods, state, enclosed or enclose
131
+
132
+ compositor
133
+
134
+ version: '0.1.2'
135
+
136
+ initialize: (application) ->
137
+ advisable = require 'advisable'
138
+
139
+ {core: {Widgets, util: {extend}, stamp}} = application
140
+
141
+ Widgets = advisorable composerable Widgets
142
+
143
+ # THINK how to at the same time respect aura ways of instantiating
144
+ # widgets and preserve widget logic composability
145
+ Widgets.Default = Widgets.Base
146
+ delete Widgets.Default.extend
147
+
148
+ Widgets.Base = Widgets.advisable Widgets.composable advisable(Widgets.Default.prototype), null, (options) ->
149
+ Object.defineProperty @, 'constructor', value: Widgets.Default, enumerable: false, configurable: false, writable: false
150
+ Widgets.Default.call Widgets.advice(@), options
151
+
152
+
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- define 'aura/extensions/widget/eventable', ['es6-map-shim'], ->
3
+ define 'aura/extensions/widget/eventable', ['stampit', 'es6-map-shim'], (stampit) ->
4
4
 
5
5
  extractor = /.*?\$(.*?)@(.*?)\+(.*?)/
6
6
 
@@ -24,44 +24,39 @@ define 'aura/extensions/widget/eventable', ['es6-map-shim'], ->
24
24
  event.preventDefault()
25
25
  false
26
26
 
27
- eventable =
28
- # TODO pass this extensions to the identifiable extension
29
- # TODO use widget.extend with the constructor property
30
- constructor: (options) ->
31
- matches = extractor.exec options._ref
32
- @name = matches[1]
33
- @identifier = options.identifier or options.resource or matches[2]
27
+ eventable = stampit
28
+ # TODO implement rivets compatibility, instead of generic
29
+ # binding events, alter html
30
+ handles: (event_name, widget_event_name = event_name, selector = @$el) ->
31
+ unless @name
32
+ message = "Widget name must be provided in order to use handlers, but this.name is '#{@name}' \n"
33
+ message += "Also you may have forgotten to set the type of your widget to 'Base'"
34
+ throw new TypeError message
34
35
 
35
- eventable.super.constructor.call @, options
36
+ context = @$el unless selector == @$el
36
37
 
37
- @sandbox.identifier = @identifier
38
+ event_name = translations.get(event_name) ? event_name
38
39
 
39
- @
40
+ @sandbox.dom.find(selector, context).on event_name, create_handler(@, widget_event_name || event_name)
40
41
 
42
+ before_initialize: ->
43
+ matches = extractor.exec @options._ref
44
+ @name = matches[1]
45
+ @identifier = @options.identifier or @options.resource or matches[2]
46
+ @sandbox.identifier = @identifier
41
47
 
42
48
  version: '0.1.0'
43
49
 
44
50
  initialize: (application) ->
45
- with_component = 'segmentio-extend'
46
- extend = require with_component
51
+ application.core.Widgets.Base.compose eventable
47
52
 
48
- Widgets = application.core.Widgets
53
+ {core: {mediator}} = application
54
+ application.sandbox.startListening = ->
55
+ # TODO @listening = true
56
+ mediator.on event.name, event.callback for event in @_events
49
57
 
50
- extend Widgets.Base.prototype,
51
- # TODO implement rivets compatibility, instead of generic
52
- # binding events, alter html
53
- handles: (event_name, widget_event_name = event_name, selector = @$el) ->
54
- unless @name
55
- message = "Widget name must be provided in order to use handlers, but this.name is '#{@name}' \n"
56
- message = "Also you may have forgotten to set the type of your widget to 'Base'"
57
- throw message
58
+ true
58
59
 
59
- context = @$el unless selector == @$el
60
60
 
61
- event_name = translations.get(event_name) ? event_name
62
61
 
63
- @sandbox.dom.find(selector, context).on event_name, create_handler(@, widget_event_name || event_name)
64
62
 
65
- # TODO replace Base.extend inheritance to stampit composition
66
- Widgets.Base = Widgets.Base.extend eventable
67
- eventable.super = Widgets.Base.__super__
@@ -0,0 +1,65 @@
1
+ 'use strict'
2
+
3
+ define 'aura/extensions/widget/flowable', ->
4
+
5
+ # The purpose of this extension is have a formalized widget type to
6
+ # put domain comunication logic between other widgets
7
+ (application) ->
8
+
9
+ instantiation =
10
+ composite_with: ->
11
+
12
+ stampit = require 'stampit/stampit'
13
+
14
+ # TODO Move each composable to its file
15
+ eventable = stampit().enclose ->
16
+ @on = @sandbox.on
17
+ @off = @sandbox.off
18
+ @once = @sandbox.once
19
+ @many = @sandbox.many
20
+ @emit = @sandbox.emit
21
+ @unlisten = @sandbox.removeAllListeners
22
+
23
+ @
24
+
25
+ filterable = stampit()
26
+
27
+ routeable = stampit()
28
+
29
+ stateable = stampit(transit: (state) -> application.state = state).enclose ->
30
+ Object.defineProperty @, 'state',
31
+ set: @transit
32
+ get: -> application.state
33
+ configurable: false
34
+
35
+ @stateless()
36
+
37
+ elementless = stampit ->
38
+ marker = " #{@name}.#{@identifier} flow "
39
+ node = document.createComment marker
40
+ @$el.replaceWith node
41
+ @$el = $ node
42
+
43
+ stampit.compose filterable, routeable, eventable, stateable, elementless
44
+
45
+ create_widget_type: (flowable, application) ->
46
+ {core: {Widgets}} = application
47
+
48
+ Widgets.Flow = Widgets.composable Widgets.Default.prototype, null, (options) -> Widgets.Default.call @, options
49
+ Widgets.Flow.compose flowable
50
+
51
+ version: '0.1.0'
52
+
53
+ initialize: (application) ->
54
+ flowable = instantiation.composite_with application
55
+ instantiation.create_widget_type flowable, application
56
+
57
+ afterAppStart: (application) ->
58
+ application.components.addSource 'flow', 'flows'
59
+
60
+
61
+
62
+
63
+
64
+
65
+
@@ -6,8 +6,12 @@ define 'aura/extensions/widget/lifecycleable', ->
6
6
  with_component = 'jquery'
7
7
  jQuery = require with_component
8
8
 
9
+ with_component = 'stampit/stampit'
10
+ stampit = require with_component
11
+
9
12
  core = null
10
13
 
14
+ # TODO transform into a composable
11
15
  lifecycleable =
12
16
  injection: (definition) ->
13
17
  options = definition.options
@@ -50,7 +54,7 @@ define 'aura/extensions/widget/lifecycleable', ->
50
54
  options.require.packages.push name: options.ref, location: widgetsPath + "/" + widgetName
51
55
  options.name = widgetName
52
56
 
53
- unless options.el
57
+ unless options.el?
54
58
  options.el = jQuery '<div class="widget"></div>'
55
59
  @root.append options.el
56
60
 
@@ -58,24 +62,27 @@ define 'aura/extensions/widget/lifecycleable', ->
58
62
 
59
63
  definition
60
64
 
61
- recyclable =
62
- constructor: (options) ->
65
+ recyclable = stampit(
66
+ inject: (name, options) ->
67
+ core.inject name, options
68
+
69
+ injection: -> lifecycleable.injection arguments...
63
70
 
71
+ before_initialize: ->
64
72
  # TODO only listen to this specific sandbox stop
65
- @sandbox.on 'aura.sandbox.stop', (sandbox) =>
73
+ # TODO stop listening when sandbox starts or stops
74
+ @sandbox.on 'aura.sandbox.stop', (sandbox) ->
66
75
  @stopped() if @sandbox.ref == sandbox.ref
76
+ , @
67
77
 
68
- @sandbox.on 'aura.sandbox.start', (sandbox) =>
78
+ @sandbox.on 'aura.sandbox.start', (sandbox) ->
69
79
  @started() if @sandbox.ref == sandbox.ref
70
-
71
- recyclable.super.constructor.call @, options
72
-
73
- @initialized()
74
-
75
- inject: (name, options) ->
76
- core.inject name, options
80
+ , @
77
81
 
78
82
  initialized: ->
83
+ # TODO think how to access parent widget in children ones
84
+ @sandbox._widget ||= @
85
+
79
86
  @sandbox.emit "#{@name}.#{@identifier}.initialized", @
80
87
 
81
88
  started: ->
@@ -85,6 +92,8 @@ define 'aura/extensions/widget/lifecycleable', ->
85
92
  stopped: ->
86
93
  @$el.remove()
87
94
 
95
+ ).enclose -> @initialized()
96
+
88
97
  (application) ->
89
98
 
90
99
  version: '0.2.0'
@@ -100,12 +109,19 @@ define 'aura/extensions/widget/lifecycleable', ->
100
109
  lifecycleable.sources = application.config.widgets.sources
101
110
  lifecycleable.find = core.dom.find
102
111
 
103
- # TODO Keep searching for root until found, and only throw
104
- # exception if someone tries to initialize widgets in root
105
- # without a valid root selector
106
- lifecycleable.root = core.dom.find app.startOptions.widgets || 'body'
112
+ Object.defineProperty lifecycleable, 'root',
113
+ get: ->
114
+ root = core.dom.find app.startOptions.widgets
115
+ throw new TypeError "No root node found for selector '#{app.startOptions.widgets}'." unless root.length != 0
116
+
117
+ # TODO Cache and override root when found
118
+ # TODO check how this will integrate with mocha specs
119
+ # Object.defineProperty lifecycleable, 'root', value: root
120
+
121
+ root
122
+
123
+ configurable: true
107
124
 
108
- throw new TypeError "No root node found for selector '#{app.startOptions.widgets}'." unless lifecycleable.root.length != 0
109
125
 
110
126
  lifecycleable.decamelize = core.util.decamelize
111
127
  lifecycleable.capitalize = core.util.capitalize
@@ -141,7 +157,4 @@ define 'aura/extensions/widget/lifecycleable', ->
141
157
  params[2] = @ if params.length < 3
142
158
  core.inject params...
143
159
 
144
- # Add support for element removal after stoping widget
145
- # TODO replace Base.extend inheritance to stampit composition
146
- core.Widgets.Base = core.Widgets.Base.extend recyclable
147
- recyclable.super = core.Widgets.Base.__super__
160
+ core.Widgets.Base.compose recyclable
@@ -1,33 +1,29 @@
1
- define 'aura/extensions/widget/napable', ->
1
+ 'use strict'
2
2
 
3
- 'use strict'
3
+ define 'aura/extensions/widget/napable', ['stampit/stampit'], (stampit) ->
4
4
 
5
- napable =
6
- bind: ->
7
- @sandbox.on "#{@name}.#{@identifier}.sleep", napable.sleep, @
8
- @sandbox.on "#{@name}.#{@identifier}.wake" , napable.wake , @
5
+ # TODO think about adding rivets bindings to the element
6
+ napable = stampit
7
+ tired: ->
8
+ @sandbox.on "#{@name}.#{@identifier}.sleep", @sleep, @
9
+ @sandbox.on "#{@name}.#{@identifier}.wake" , @wake , @
10
+ @
9
11
  sleep: ->
10
12
  @$el.addClass 'asleep'
11
13
  @$el.removeClass 'awake'
12
14
  wake: ->
13
15
  @$el.addClass 'awake'
14
16
  @$el.removeClass 'asleep'
15
-
16
- napable_extensions =
17
- constructor: ->
18
- napable_extensions["super"].constructor.apply @, arguments
19
- napable.bind.call @
17
+ ,
18
+ naping: false
19
+ , -> @tired()
20
20
 
21
21
  # The purpose of this extension is allow parent widget to save
22
22
  # memory by sending a sleep command to the child widgets
23
23
  (application) ->
24
24
 
25
- version: '0.1.0'
25
+ version: '0.1.2'
26
26
 
27
27
  initialize: (application) ->
28
28
  {core} = application
29
-
30
- # Add support for element removal after stoping widget
31
- # TODO replace Base.extend inheritance to stampit composition
32
- core.Widgets.Base = core.Widgets.Base.extend napable_extensions
33
- napable_extensions.super = core.Widgets.Base.__super__
29
+ core.Widgets.Base.compose napable
@@ -165,7 +165,8 @@ define ->
165
165
  extract_options: ->
166
166
  options = _.omit @options, 'el', 'ref', '_ref', 'name', 'require', 'baseUrl', 'theme', 'resource'
167
167
 
168
- dynamic_options = _.omit options, Object.keys(@constructor.__super__.options)
168
+ # TODO merge default options in prototype
169
+ dynamic_options = _.omit options, Object.keys(@__proto__.options)
169
170
 
170
171
  keys = Object.keys dynamic_options
171
172
  throw new TypeError "Too many keys on options object! #{keys.join(', ')}" unless keys.length == 1