ende 0.4.24 → 0.4.25

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.
@@ -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