nali 0.4.2 → 0.4.3
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.
- data/lib/client/javascripts/nali/application.js.coffee +4 -4
- data/lib/client/javascripts/nali/collection.js.coffee +53 -53
- data/lib/client/javascripts/nali/connection.js.coffee +39 -39
- data/lib/client/javascripts/nali/controller.js.coffee +12 -12
- data/lib/client/javascripts/nali/model.js.coffee +56 -57
- data/lib/client/javascripts/nali/nali.js.coffee +22 -22
- data/lib/client/javascripts/nali/notice.js.coffee +7 -6
- data/lib/client/javascripts/nali/router.js.coffee +11 -18
- data/lib/client/javascripts/nali/view.js.coffee +102 -93
- data/lib/nali/clients.rb +2 -2
- data/lib/nali/connection.rb +4 -4
- data/lib/nali/controller.rb +2 -2
- data/lib/nali/helpers.rb +1 -1
- data/lib/nali/model.rb +1 -1
- data/lib/nali/tasks.rb +3 -0
- data/lib/nali/version.rb +1 -1
- metadata +2 -2
@@ -5,7 +5,7 @@ window.Nali =
|
|
5
5
|
|
6
6
|
starting: ->
|
7
7
|
for name, extension of @extensions
|
8
|
-
extension.
|
8
|
+
extension._runExtensions()
|
9
9
|
extension.initialize() if extension.hasOwnProperty 'initialize'
|
10
10
|
@starting.call extension
|
11
11
|
@
|
@@ -13,19 +13,19 @@ window.Nali =
|
|
13
13
|
extend: ( params ) ->
|
14
14
|
for name, param of params
|
15
15
|
param._name = name
|
16
|
-
@[ name ] = @extensions[ name ] = @
|
16
|
+
@[ name ] = @extensions[ name ] = @_child param
|
17
17
|
@[ name ].extensions = {}
|
18
18
|
|
19
19
|
clone: ( params = {} ) ->
|
20
|
-
obj = @
|
21
|
-
obj.
|
20
|
+
obj = @_child params
|
21
|
+
obj._runCloning()
|
22
22
|
obj
|
23
23
|
|
24
|
-
|
24
|
+
_child: ( params ) ->
|
25
25
|
obj = Object.create @
|
26
26
|
obj :: = @
|
27
27
|
obj[ name ] = value for name, value of params
|
28
|
-
obj.
|
28
|
+
obj._initObservation()
|
29
29
|
obj
|
30
30
|
|
31
31
|
expand: ( obj ) ->
|
@@ -47,12 +47,12 @@ window.Nali =
|
|
47
47
|
return true if @::_name is parent
|
48
48
|
@::childOf parent
|
49
49
|
|
50
|
-
|
51
|
-
@::?.
|
50
|
+
_runExtensions: ( context = @ ) ->
|
51
|
+
@::?._runExtensions context
|
52
52
|
@extension.call context if @hasOwnProperty 'extension'
|
53
53
|
|
54
|
-
|
55
|
-
@::?.
|
54
|
+
_runCloning: ( context = @ ) ->
|
55
|
+
@::?._runCloning context
|
56
56
|
@cloning.call context if @hasOwnProperty 'cloning'
|
57
57
|
|
58
58
|
getter: ( property, callback ) ->
|
@@ -70,9 +70,9 @@ window.Nali =
|
|
70
70
|
@setter property, ( value ) -> obj[ property ] = value
|
71
71
|
@
|
72
72
|
|
73
|
-
|
74
|
-
@
|
75
|
-
@
|
73
|
+
_initObservation: ->
|
74
|
+
@_observers = []
|
75
|
+
@_observables = []
|
76
76
|
@
|
77
77
|
|
78
78
|
destroyObservation: ->
|
@@ -80,19 +80,19 @@ window.Nali =
|
|
80
80
|
@unsubscribeFromAll()
|
81
81
|
@
|
82
82
|
|
83
|
-
|
83
|
+
_addObservationItem: ( to, obj, event, callback ) ->
|
84
84
|
return @ for item in @[ to ] when item[0] is obj and item[1] is event and item[2] in [ undefined, callback ]
|
85
85
|
@[ to ].push if callback then [ obj, event, callback ] else [ obj, event ]
|
86
86
|
@
|
87
87
|
|
88
|
-
|
88
|
+
_removeObservationItem: ( from, obj, event ) ->
|
89
89
|
for item in @[ from ][..] when item[0] is obj and ( item[1] is event or not event )
|
90
90
|
@[ from ].splice @[ from ].indexOf( item ), 1
|
91
91
|
@
|
92
92
|
|
93
93
|
subscribe: ( observer, event, callback ) ->
|
94
|
-
@
|
95
|
-
observer.
|
94
|
+
@_addObservationItem '_observers', observer, event, callback
|
95
|
+
observer._addObservationItem '_observables', @, event, callback
|
96
96
|
@
|
97
97
|
|
98
98
|
subscribeTo: ( observable, event, callback ) ->
|
@@ -111,8 +111,8 @@ window.Nali =
|
|
111
111
|
@
|
112
112
|
|
113
113
|
unsubscribe: ( observer, event ) ->
|
114
|
-
@
|
115
|
-
observer.
|
114
|
+
@_removeObservationItem '_observers', observer, event
|
115
|
+
observer._removeObservationItem '_observables', @, event
|
116
116
|
@
|
117
117
|
|
118
118
|
unsubscribeFrom: ( observable, event ) ->
|
@@ -120,13 +120,13 @@ window.Nali =
|
|
120
120
|
@
|
121
121
|
|
122
122
|
unsubscribeAll: ( event ) ->
|
123
|
-
@unsubscribe item[0], event for item in @
|
123
|
+
@unsubscribe item[0], event for item in @_observers[..]
|
124
124
|
@
|
125
125
|
|
126
126
|
unsubscribeFromAll: ( event ) ->
|
127
|
-
@unsubscribeFrom item[0], event for item in @
|
127
|
+
@unsubscribeFrom item[0], event for item in @_observables[..]
|
128
128
|
@
|
129
129
|
|
130
130
|
trigger: ( event, args... ) ->
|
131
|
-
item[2].call item[0], args... for item in @
|
131
|
+
item[2].call item[0], args... for item in @_observers[..] when item[1] is event
|
132
132
|
@
|
@@ -2,16 +2,17 @@ Nali.Model.extend Notice:
|
|
2
2
|
|
3
3
|
initialize: ->
|
4
4
|
@::::expand Notice: @
|
5
|
-
@
|
5
|
+
@_addMethods()
|
6
6
|
|
7
|
-
|
7
|
+
_addMethods: ->
|
8
|
+
for name of @_views
|
9
|
+
do ( name ) =>
|
10
|
+
@[ name ] = ( params ) => @new( @_prepare params ).show name
|
11
|
+
|
12
|
+
_prepare: ( params ) ->
|
8
13
|
params = message: params if typeof params is 'string'
|
9
14
|
params
|
10
15
|
|
11
|
-
addMethods: ->
|
12
|
-
for name of @views
|
13
|
-
do ( name ) =>
|
14
|
-
@[ name ] = ( params ) => @new( @prepare params ).show name
|
15
16
|
|
16
17
|
|
17
18
|
Nali.View.extend
|
@@ -4,29 +4,29 @@ Nali.extend Router:
|
|
4
4
|
@::expand redirect: ( args... ) => @redirect args...
|
5
5
|
@
|
6
6
|
|
7
|
-
|
7
|
+
_routes: {}
|
8
8
|
|
9
9
|
start: ->
|
10
|
-
@
|
10
|
+
@_scanRoutes()
|
11
11
|
@_( window ).on 'popstate', ( event ) =>
|
12
12
|
event.preventDefault()
|
13
13
|
event.stopPropagation()
|
14
|
-
@
|
14
|
+
@_saveHistory = false
|
15
15
|
@redirect event.target.location.pathname
|
16
16
|
@
|
17
17
|
|
18
|
-
|
18
|
+
_scanRoutes: ->
|
19
19
|
for name, controller of @Controller.extensions when controller.actions?
|
20
20
|
route = '^'
|
21
21
|
route += name.lower().replace /s$/, 's*(\/|$)'
|
22
22
|
route += '('
|
23
23
|
route += Object.keys( controller._actions ).join '|'
|
24
24
|
route += ')?'
|
25
|
-
@
|
25
|
+
@_routes[ route ] = controller
|
26
26
|
@
|
27
27
|
|
28
28
|
redirect: ( url = window.location.pathname, options = {} ) ->
|
29
|
-
if found = @
|
29
|
+
if found = @_findRoute @_prepare( url ) or @_prepare( @Application.defaultUrl )
|
30
30
|
{ controller, action, filters, params } = found
|
31
31
|
params[ name ] = value for name, value in options
|
32
32
|
controller.run action, filters, params
|
@@ -35,14 +35,14 @@ Nali.extend Router:
|
|
35
35
|
else console.warn "Not exists route to the address %s", url
|
36
36
|
@
|
37
37
|
|
38
|
-
|
38
|
+
_prepare: ( url ) ->
|
39
39
|
url = url.replace "http://#{ window.location.host }", ''
|
40
40
|
url = url[ 1.. ] or '' if url and url[ 0...1 ] is '/'
|
41
41
|
url = url[ ...-1 ] or '' if url and url[ -1.. ] is '/'
|
42
42
|
url
|
43
43
|
|
44
|
-
|
45
|
-
for route, controller of @
|
44
|
+
_findRoute: ( url ) ->
|
45
|
+
for route, controller of @_routes when match = url.match new RegExp route, 'i'
|
46
46
|
segments = ( @routedUrl = url ).split( '/' )[ 1... ]
|
47
47
|
if segments[0] in Object.keys( controller._actions )
|
48
48
|
action = segments.shift()
|
@@ -57,16 +57,9 @@ Nali.extend Router:
|
|
57
57
|
return controller: controller, action: action, filters: filters, params: params
|
58
58
|
false
|
59
59
|
|
60
|
-
saveHistory: ( value ) ->
|
61
|
-
@_saveHistory ?= true
|
62
|
-
if value in [ true, false ]
|
63
|
-
@_saveHistory = value
|
64
|
-
@
|
65
|
-
else @_saveHistory
|
66
|
-
|
67
60
|
changeUrl: ( url = null ) ->
|
68
|
-
if @
|
61
|
+
if @_saveHistory
|
69
62
|
@routedUrl = url if url?
|
70
63
|
history.pushState null, null, '/' + ( @url = @routedUrl ) if @routedUrl isnt @url
|
71
|
-
else @
|
64
|
+
else @_saveHistory = true
|
72
65
|
@
|
@@ -3,19 +3,20 @@ Nali.extend View:
|
|
3
3
|
extension: ->
|
4
4
|
if @_name isnt 'View'
|
5
5
|
@_shortName = @_name.underscore().split( '_' )[ 1.. ].join( '_' ).camel()
|
6
|
-
@
|
7
|
-
@
|
6
|
+
@_parseTemplate()
|
7
|
+
@_parseEvents()
|
8
8
|
@
|
9
9
|
|
10
10
|
cloning: ->
|
11
11
|
@my = @model
|
12
|
+
@_prepareElement()
|
12
13
|
@
|
13
14
|
|
14
15
|
layout: -> null
|
15
16
|
|
16
|
-
|
17
|
+
_onSourceUpdated: -> @_draw()
|
17
18
|
|
18
|
-
|
19
|
+
_onSourceDestroyed: -> @hide()
|
19
20
|
|
20
21
|
getOf: ( source, property ) ->
|
21
22
|
@redrawOn source, "update.#{ property }"
|
@@ -25,80 +26,80 @@ Nali.extend View:
|
|
25
26
|
@getOf @model, property
|
26
27
|
|
27
28
|
redrawOn: ( source, event ) ->
|
28
|
-
@subscribeTo source, event, @
|
29
|
+
@subscribeTo source, event, @_onSourceUpdated
|
29
30
|
|
30
31
|
insertTo: ->
|
31
32
|
if ( layout = @layout() )?.childOf? 'View' then layout.show().yield
|
32
33
|
else @Application.htmlContainer
|
33
34
|
|
34
|
-
|
35
|
-
@
|
35
|
+
_draw: ->
|
36
|
+
@_runAssistants 'draw'
|
36
37
|
@onDraw?()
|
37
38
|
@
|
38
39
|
|
39
40
|
show: ( insertTo = @insertTo() ) ->
|
40
|
-
@prepareElement()
|
41
41
|
unless @visible
|
42
|
-
@
|
43
|
-
@
|
44
|
-
@
|
45
|
-
@subscribeTo @model, 'destroy', @
|
42
|
+
@_runModelCallback 'beforeShow'
|
43
|
+
@_draw()._bindEvents()
|
44
|
+
@_runAssistants 'show'
|
45
|
+
@subscribeTo @model, 'destroy', @_onSourceDestroyed
|
46
46
|
@element.appendTo insertTo
|
47
47
|
setTimeout ( => @onShow() ), 5 if @onShow?
|
48
48
|
@trigger 'show'
|
49
49
|
@visible = true
|
50
|
-
@
|
50
|
+
@_runModelCallback 'afterShow'
|
51
51
|
@
|
52
52
|
|
53
53
|
hide: ( delay = 0 ) ->
|
54
54
|
if @visible
|
55
|
-
@
|
55
|
+
@_runModelCallback 'beforeHide'
|
56
56
|
@onHide?()
|
57
|
+
@_unbindEvents()
|
57
58
|
@trigger 'hide'
|
58
|
-
@
|
59
|
-
@
|
59
|
+
@_runAssistants 'hide'
|
60
|
+
@_hideElement if delay and typeof( delay ) is 'number' then delay else @hideDelay
|
60
61
|
@destroyObservation()
|
61
62
|
@visible = false
|
62
|
-
@
|
63
|
+
@_runModelCallback 'afterHide'
|
63
64
|
@
|
64
65
|
|
65
|
-
|
66
|
-
if delay then setTimeout ( => @
|
67
|
-
else @
|
66
|
+
_hideElement: ( delay ) ->
|
67
|
+
if delay then setTimeout ( => @_removeElement() ), delay
|
68
|
+
else @_removeElement()
|
68
69
|
@
|
69
70
|
|
70
|
-
|
71
|
+
_removeElement: ->
|
71
72
|
@element[0].parentNode.removeChild @element[0]
|
72
73
|
@
|
73
74
|
|
74
|
-
|
75
|
+
_runModelCallback: ( type ) ->
|
75
76
|
@model[ type ]?[ @_shortName ]?.call @model
|
76
77
|
@
|
77
78
|
|
78
|
-
|
79
|
+
_runLink: ( event ) ->
|
79
80
|
event.preventDefault()
|
80
|
-
@
|
81
|
+
@_runUrl event.currentTarget.getAttribute 'href'
|
81
82
|
@
|
82
83
|
|
83
|
-
|
84
|
+
_runForm: ( event ) ->
|
84
85
|
event.preventDefault()
|
85
|
-
@
|
86
|
+
@_runUrl event.currentTarget.getAttribute( 'action' ), form2js event.currentTarget, '.', false
|
86
87
|
@
|
87
88
|
|
88
|
-
|
89
|
+
_runUrl: ( url, params ) ->
|
89
90
|
if match = url.match /^(@@?)(.+)/
|
90
91
|
[ chain, segments... ] = match[2].split '/'
|
91
|
-
if result = @
|
92
|
+
if result = @_analizeChain chain, ( if match[1].length is 1 then @ else @model )
|
92
93
|
[ source, method ] = result
|
93
94
|
if method of source
|
94
|
-
args = @
|
95
|
+
args = @_parseUrlSegments segments
|
95
96
|
args.unshift params if params
|
96
97
|
source[ method ] args...
|
97
98
|
else console.warn "Method %s not exists of %O", method, source
|
98
99
|
else @redirect url, params
|
99
100
|
@
|
100
101
|
|
101
|
-
|
102
|
+
_parseUrlSegments: ( segments ) ->
|
102
103
|
params = []
|
103
104
|
for segment in segments when segment isnt ''
|
104
105
|
[ name, value ] = segment.split ':'
|
@@ -109,8 +110,8 @@ Nali.extend View:
|
|
109
110
|
else params.push name
|
110
111
|
params
|
111
112
|
|
112
|
-
|
113
|
-
@
|
113
|
+
_parseEvents: ->
|
114
|
+
@_eventsMap = []
|
114
115
|
if @events
|
115
116
|
@events = [ @events ] if typeof @events is 'string'
|
116
117
|
for event in @events
|
@@ -123,109 +124,117 @@ Nali.extend View:
|
|
123
124
|
catch
|
124
125
|
console.warn "Events parsing error: \"%s\" of %O", event, @
|
125
126
|
error = true
|
126
|
-
if error then error = false else @
|
127
|
+
if error then error = false else @_eventsMap.push [ selector, type, events, handlers ]
|
127
128
|
@
|
128
129
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
for handler in handlers
|
137
|
-
do ( selector, type, events, handler ) =>
|
138
|
-
@element[ type ] events, selector, ( event ) => @[ handler ] event
|
139
|
-
@_eventsBinded = true
|
130
|
+
_bindEvents: ->
|
131
|
+
@_bindRoutedElements 'a', 'href', 'click', ( event ) => @_runLink event
|
132
|
+
@_bindRoutedElements 'form', 'action', 'submit', ( event ) => @_runForm event
|
133
|
+
for [ selector, type, events, handlers ] in @_eventsMap
|
134
|
+
for handler in handlers
|
135
|
+
do ( selector, type, events, handler ) =>
|
136
|
+
@element[ type ] events, selector, ( event ) => @[ handler ] event
|
140
137
|
@
|
141
138
|
|
142
|
-
|
139
|
+
_bindRoutedElements: ( selector, urlProp, event, callback ) ->
|
140
|
+
finded = ( el for el in @element.find( selector ) when el[ urlProp ].indexOf( window.location.origin ) >= 0 )
|
141
|
+
finded.push @element[0] if @element.is selector
|
142
|
+
( @_routedElements ?= {} )[ selector ] = @_( finded ).on event, callback
|
143
|
+
@
|
144
|
+
|
145
|
+
_unbindEvents: ->
|
146
|
+
@element.off()
|
147
|
+
@_routedElements.a.off()
|
148
|
+
@_routedElements.form.off()
|
149
|
+
@
|
150
|
+
|
151
|
+
_prepareElement: ->
|
143
152
|
unless @element
|
144
153
|
@element = @_ @template
|
145
154
|
@element[0].view = @
|
146
|
-
@
|
155
|
+
@_addAssistants()
|
147
156
|
@
|
148
157
|
|
149
|
-
|
158
|
+
_getNode: ( path ) ->
|
150
159
|
node = @element[0]
|
151
160
|
node = node[ sub ] for sub in path
|
152
161
|
node
|
153
162
|
|
154
|
-
|
163
|
+
_parseTemplate: ->
|
155
164
|
if container = document.querySelector '#' + @_name.underscore()
|
156
165
|
@template = container.innerHTML.trim().replace( /\s+/g, ' ' )
|
157
166
|
.replace( /({\s*\+.+?\s*})/g, ' <assist>$1</assist>' )
|
158
167
|
unless RegExp( "^<[^>]+" + @_name ).test @template
|
159
168
|
@template = "<div class=\"#{ @_name }\">#{ @template }</div>"
|
160
|
-
@
|
169
|
+
@_parseAssistants()
|
161
170
|
container.parentNode.removeChild container
|
162
171
|
else console.warn 'Template %s not exists', @_name
|
163
172
|
@
|
164
173
|
|
165
|
-
|
166
|
-
@
|
174
|
+
_parseAssistants: ->
|
175
|
+
@_assistantsMap = []
|
167
176
|
if /{\s*.+?\s*}|bind=".+?"/.test @template
|
168
177
|
tmp = document.createElement 'div'
|
169
178
|
tmp.innerHTML = @template
|
170
|
-
@
|
179
|
+
@_scanAssistants tmp.children[0]
|
171
180
|
@
|
172
181
|
|
173
|
-
|
182
|
+
_scanAssistants: ( node, path = [] ) ->
|
174
183
|
if node.nodeType is 3
|
175
184
|
if /{\s*yield\s*}/.test( node.textContent.trim() ) and node.parentNode.childNodes.length is 1
|
176
|
-
@
|
185
|
+
@_assistantsMap.push nodepath: path, type: 'Yield'
|
177
186
|
else if /^{\s*\w+ of @\w*\s*}$/.test( node.textContent.trim() ) and node.parentNode.childNodes.length is 1
|
178
|
-
@
|
187
|
+
@_assistantsMap.push nodepath: path, type: 'Relation'
|
179
188
|
else if /{\s*.+?\s*}/.test node.textContent
|
180
|
-
@
|
189
|
+
@_assistantsMap.push nodepath: path, type: 'Text'
|
181
190
|
else if node.nodeName is 'ASSIST'
|
182
|
-
@
|
191
|
+
@_assistantsMap.push nodepath: path, type: 'Html'
|
183
192
|
else
|
184
193
|
if node.attributes
|
185
194
|
for attribute, index in node.attributes
|
186
195
|
if attribute.name is 'bind'
|
187
|
-
@
|
196
|
+
@_assistantsMap.push nodepath: path, type: 'Form'
|
188
197
|
else if /{\s*.+?\s*}/.test attribute.value
|
189
|
-
@
|
190
|
-
@
|
198
|
+
@_assistantsMap.push nodepath: path.concat( 'attributes', index ), type: 'Attr'
|
199
|
+
@_scanAssistants child, path.concat 'childNodes', index for child, index in node.childNodes
|
191
200
|
@
|
192
201
|
|
193
|
-
|
194
|
-
@
|
195
|
-
@[ "
|
202
|
+
_addAssistants: ->
|
203
|
+
@_assistants = show: [], draw: [], hide: []
|
204
|
+
@[ "_add#{ type }Assistant" ] @_getNode nodepath for { nodepath, type } in @_assistantsMap
|
196
205
|
@
|
197
206
|
|
198
|
-
|
199
|
-
assistant.call @ for assistant in @
|
207
|
+
_runAssistants: ( type ) ->
|
208
|
+
assistant.call @ for assistant in @_assistants[ type ]
|
200
209
|
@
|
201
210
|
|
202
|
-
|
211
|
+
_addTextAssistant: ( node ) ->
|
203
212
|
initialValue = node.textContent
|
204
|
-
@
|
213
|
+
@_assistants[ 'draw' ].push -> node.textContent = @_analize initialValue
|
205
214
|
@
|
206
215
|
|
207
|
-
|
216
|
+
_addAttrAssistant: ( node ) ->
|
208
217
|
initialValue = node.value
|
209
|
-
@
|
218
|
+
@_assistants[ 'draw' ].push -> node.value = @_analize initialValue
|
210
219
|
@
|
211
220
|
|
212
|
-
|
221
|
+
_addHtmlAssistant: ( node ) ->
|
213
222
|
parent = node.parentNode
|
214
223
|
initialValue = node.innerHTML
|
215
224
|
index = Array::indexOf.call parent.childNodes, node
|
216
225
|
after = parent.childNodes[ index - 1 ] or null
|
217
226
|
before = parent.childNodes[ index + 1 ] or null
|
218
|
-
@
|
227
|
+
@_assistants[ 'draw' ].push ->
|
219
228
|
start = if after then Array::indexOf.call( parent.childNodes, after ) + 1 else 0
|
220
229
|
end = if before then Array::indexOf.call parent.childNodes, before else parent.childNodes.length
|
221
230
|
parent.removeChild node for node in Array::slice.call( parent.childNodes, start, end )
|
222
|
-
parent.insertBefore element, before for element in @_( @
|
231
|
+
parent.insertBefore element, before for element in @_( @_analize initialValue )
|
223
232
|
@
|
224
233
|
|
225
|
-
|
226
|
-
if bind = @
|
234
|
+
_addFormAssistant: ( node ) ->
|
235
|
+
if bind = @_analizeChain node.attributes.removeNamedItem( 'bind' ).value
|
227
236
|
[ source, property ] = bind
|
228
|
-
|
237
|
+
$node = @_ node
|
229
238
|
|
230
239
|
updateSource = ->
|
231
240
|
( params = {} )[ property ] = if node.type is 'checkbox' and !node.checked then null else if node.value is '' then null else node.value
|
@@ -236,37 +245,37 @@ Nali.extend View:
|
|
236
245
|
when node.type in [ 'text', 'textarea', 'color', 'date', 'datetime', 'datetime-local', 'email', 'number', 'range', 'search', 'tel', 'time', 'url', 'month', 'week' ]
|
237
246
|
[
|
238
247
|
-> node.value = source[ property ] or ''
|
239
|
-
->
|
248
|
+
-> $node.on 'change', => updateSource.call @
|
240
249
|
]
|
241
250
|
when node.type in [ 'checkbox', 'radio' ]
|
242
251
|
[
|
243
252
|
-> node.checked = source[ property ] + '' is node.value
|
244
|
-
->
|
253
|
+
-> $node.on 'change', => updateSource.call @ if node.type is 'checkbox' or node.checked is true
|
245
254
|
]
|
246
255
|
when node.type is 'select-one'
|
247
256
|
[
|
248
257
|
-> option.selected = true for option in node when source[ property ] + '' is option.value
|
249
|
-
->
|
258
|
+
-> $node.on 'change', => updateSource.call @
|
250
259
|
]
|
251
260
|
|
252
|
-
@
|
261
|
+
@_assistants[ 'show' ].push ->
|
253
262
|
setValue.call @
|
254
263
|
bindChange.call @
|
255
264
|
source.subscribe @, "update.#{ property }", => setValue.call @
|
256
265
|
|
257
|
-
@
|
258
|
-
|
266
|
+
@_assistants[ 'hide' ].push ->
|
267
|
+
$node.off 'change'
|
259
268
|
@
|
260
269
|
|
261
|
-
|
270
|
+
_addYieldAssistant: ( node ) ->
|
262
271
|
( @yield = @_ node.parentNode )[0].removeChild node
|
263
272
|
|
264
|
-
|
273
|
+
_addRelationAssistant: ( node ) ->
|
265
274
|
[ match, name, chain ] = node.textContent.match /{\s*(\w+) of @(\w*)\s*}/
|
266
275
|
( insertTo = node.parentNode ).removeChild node
|
267
276
|
segments = if chain.length then chain.split '.' else []
|
268
|
-
@
|
269
|
-
if relation = @
|
277
|
+
@_assistants[ 'show' ].push ->
|
278
|
+
if relation = @_getSource segments
|
270
279
|
if relation.childOf 'Collection'
|
271
280
|
relation.show name, insertTo, true
|
272
281
|
relation.subscribeTo @, 'hide', relation.reset
|
@@ -274,14 +283,14 @@ Nali.extend View:
|
|
274
283
|
view = relation.show name, insertTo
|
275
284
|
view.subscribeTo @, 'hide', view.hide
|
276
285
|
|
277
|
-
|
278
|
-
value.replace /{\s*(.+?)\s*}/g, ( match, sub ) => @
|
286
|
+
_analize: ( value ) ->
|
287
|
+
value.replace /{\s*(.+?)\s*}/g, ( match, sub ) => @_analizeMatch sub
|
279
288
|
|
280
|
-
|
289
|
+
_analizeMatch: ( sub ) ->
|
281
290
|
if match = sub.match /^@([\w\.]+)(\?)?$/
|
282
|
-
if result = @
|
291
|
+
if result = @_analizeChain match[1]
|
283
292
|
[ source, property ] = result
|
284
|
-
source.subscribe? @, "update.#{ property }", @
|
293
|
+
source.subscribe? @, "update.#{ property }", @_onSourceUpdated
|
285
294
|
if match[2] is '?'
|
286
295
|
if source[ property ] then property else ''
|
287
296
|
else if source[ property ]? then source[ property ] else ''
|
@@ -290,7 +299,7 @@ Nali.extend View:
|
|
290
299
|
@helpers?[ match[1] ]?.call @
|
291
300
|
else sub
|
292
301
|
|
293
|
-
|
302
|
+
_getSource: ( segments, source = @model ) ->
|
294
303
|
for segment in segments
|
295
304
|
if segment of source then source = source[ segment ]
|
296
305
|
else
|
@@ -298,8 +307,8 @@ Nali.extend View:
|
|
298
307
|
return null
|
299
308
|
source
|
300
309
|
|
301
|
-
|
310
|
+
_analizeChain: ( chain, source = @model ) ->
|
302
311
|
segments = chain.split '.'
|
303
312
|
property = segments.pop()
|
304
|
-
return null unless source = @
|
313
|
+
return null unless source = @_getSource segments, source
|
305
314
|
[ source, property ]
|