1
+ /*can-component@3.3.10#can-component*/
2
+ define ( [
3
+ 'require' ,
4
+ 'exports' ,
5
+ 'module' ,
6
+ './control/control' ,
7
+ 'can-namespace' ,
8
+ 'can-construct' ,
9
+ 'can-stache-bindings' ,
10
+ 'can-view-scope' ,
11
+ 'can-view-callbacks' ,
12
+ 'can-view-nodelist' ,
13
+ 'can-compute' ,
14
+ 'can-util/dom/data' ,
15
+ 'can-util/dom/mutate' ,
16
+ 'can-util/dom/child-nodes' ,
17
+ 'can-util/dom/dispatch' ,
18
+ 'can-types' ,
19
+ 'can-util/js/string' ,
20
+ 'can-reflect' ,
21
+ 'can-util/js/each' ,
22
+ 'can-util/js/assign' ,
23
+ 'can-util/js/is-function' ,
24
+ 'can-util/js/log' ,
25
+ 'can-util/js/dev' ,
26
+ 'can-util/js/make-array' ,
27
+ 'can-util/js/is-empty-object' ,
28
+ 'can-util/dom/events/inserted' ,
29
+ 'can-util/dom/events/removed' ,
30
+ 'can-view-model'
31
+ ] , function ( require , exports , module ) {
32
+ var ComponentControl = require ( './control/control' ) ;
33
+ var namespace = require ( 'can-namespace' ) ;
34
+ var Construct = require ( 'can-construct' ) ;
35
+ var stacheBindings = require ( 'can-stache-bindings' ) ;
36
+ var Scope = require ( 'can-view-scope' ) ;
37
+ var viewCallbacks = require ( 'can-view-callbacks' ) ;
38
+ var nodeLists = require ( 'can-view-nodelist' ) ;
39
+ var compute = require ( 'can-compute' ) ;
40
+ var domData = require ( 'can-util/dom/data' ) ;
41
+ var domMutate = require ( 'can-util/dom/mutate' ) ;
42
+ var getChildNodes = require ( 'can-util/dom/child-nodes' ) ;
43
+ var domDispatch = require ( 'can-util/dom/dispatch' ) ;
44
+ var types = require ( 'can-types' ) ;
45
+ var string = require ( 'can-util/js/string' ) ;
46
+ var canReflect = require ( 'can-reflect' ) ;
47
+ var canEach = require ( 'can-util/js/each' ) ;
48
+ var assign = require ( 'can-util/js/assign' ) ;
49
+ var isFunction = require ( 'can-util/js/is-function' ) ;
50
+ var canLog = require ( 'can-util/js/log' ) ;
51
+ var canDev = require ( 'can-util/js/dev' ) ;
52
+ var makeArray = require ( 'can-util/js/make-array' ) ;
53
+ var isEmptyObject = require ( 'can-util/js/is-empty-object' ) ;
54
+ require ( 'can-util/dom/events/inserted' ) ;
55
+ require ( 'can-util/dom/events/removed' ) ;
56
+ require ( 'can-view-model' ) ;
57
+ function addContext ( el , tagData , insertionElementTagData ) {
58
+ var vm ;
59
+ domData . set . call ( el , 'preventDataBindings' , true ) ;
60
+ var teardown = stacheBindings . behaviors . viewModel ( el , insertionElementTagData , function ( initialData ) {
61
+ return vm = compute ( initialData ) ;
62
+ } , undefined , true ) ;
63
+ if ( ! teardown ) {
64
+ return tagData ;
65
+ } else {
66
+ return assign ( assign ( { } , tagData ) , {
67
+ teardown : teardown ,
68
+ scope : tagData . scope . add ( vm )
69
+ } ) ;
70
+ }
71
+ }
72
+ function makeInsertionTagCallback ( tagName , componentTagData , shadowTagData , leakScope , getPrimaryTemplate ) {
73
+ var options = shadowTagData . options . _context ;
74
+ return function hookupFunction ( el , insertionElementTagData ) {
75
+ var template = getPrimaryTemplate ( el ) || insertionElementTagData . subtemplate , renderingLightContent = template !== insertionElementTagData . subtemplate ;
76
+ if ( template ) {
77
+ delete options . tags [ tagName ] ;
78
+ var tagData ;
79
+ if ( renderingLightContent ) {
80
+ if ( leakScope . toLightContent ) {
81
+ tagData = addContext ( el , {
82
+ scope : insertionElementTagData . scope . cloneFromRef ( ) ,
83
+ options : insertionElementTagData . options
84
+ } , insertionElementTagData ) ;
85
+ } else {
86
+ tagData = addContext ( el , componentTagData , insertionElementTagData ) ;
87
+ }
88
+ } else {
89
+ tagData = addContext ( el , insertionElementTagData , insertionElementTagData ) ;
90
+ }
91
+ var nodeList = nodeLists . register ( [ el ] , function ( ) {
92
+ if ( tagData . teardown ) {
93
+ tagData . teardown ( ) ;
94
+ }
95
+ } , insertionElementTagData . parentNodeList || true , false ) ;
96
+ nodeList . expression = '<can-slot name=\'' + el . getAttribute ( 'name' ) + '\'/>' ;
97
+ var frag = template ( tagData . scope , tagData . options , nodeList ) ;
98
+ var newNodes = makeArray ( getChildNodes ( frag ) ) ;
99
+ nodeLists . replace ( nodeList , frag ) ;
100
+ nodeLists . update ( nodeList , newNodes ) ;
101
+ options . tags [ tagName ] = hookupFunction ;
102
+ }
103
+ } ;
104
+ }
105
+ var Component = Construct . extend ( {
106
+ setup : function ( ) {
107
+ Construct . setup . apply ( this , arguments ) ;
108
+ if ( Component ) {
109
+ var self = this ;
110
+ if ( ! isEmptyObject ( this . prototype . events ) ) {
111
+ this . Control = ComponentControl . extend ( this . prototype . events ) ;
112
+ }
113
+ var protoViewModel = this . prototype . viewModel || this . prototype . scope ;
114
+ if ( protoViewModel && this . prototype . ViewModel ) {
115
+ throw new Error ( 'Cannot provide both a ViewModel and a viewModel property' ) ;
116
+ }
117
+ var vmName = string . capitalize ( string . camelize ( this . prototype . tag ) ) + 'VM' ;
118
+ if ( this . prototype . ViewModel ) {
119
+ if ( typeof this . prototype . ViewModel === 'function' ) {
120
+ this . ViewModel = this . prototype . ViewModel ;
121
+ } else {
122
+ this . ViewModel = types . DefaultMap . extend ( vmName , this . prototype . ViewModel ) ;
123
+ }
124
+ } else {
125
+ if ( protoViewModel ) {
126
+ if ( typeof protoViewModel === 'function' ) {
127
+ if ( canReflect . isObservableLike ( protoViewModel . prototype ) && canReflect . isMapLike ( protoViewModel . prototype ) ) {
128
+ this . ViewModel = protoViewModel ;
129
+ } else {
130
+ this . viewModelHandler = protoViewModel ;
131
+ }
132
+ } else {
133
+ if ( canReflect . isObservableLike ( protoViewModel ) && canReflect . isMapLike ( protoViewModel ) ) {
134
+ this . viewModelInstance = protoViewModel ;
135
+ } else {
136
+ this . ViewModel = types . DefaultMap . extend ( vmName , protoViewModel ) ;
137
+ }
138
+ }
139
+ } else {
140
+ this . ViewModel = types . DefaultMap . extend ( vmName , { } ) ;
141
+ }
142
+ }
143
+ if ( this . prototype . template ) {
144
+ this . renderer = this . prototype . template ;
145
+ }
146
+ if ( this . prototype . view ) {
147
+ this . renderer = this . prototype . view ;
148
+ }
149
+ viewCallbacks . tag ( this . prototype . tag , function ( el , options ) {
150
+ new self ( el , options ) ;
151
+ } ) ;
152
+ }
153
+ }
154
+ } , {
155
+ setup : function ( el , componentTagData ) {
156
+ var component = this ;
157
+ var teardownFunctions = [ ] ;
158
+ var initialViewModelData = { } ;
159
+ var callTeardownFunctions = function ( ) {
160
+ for ( var i = 0 , len = teardownFunctions . length ; i < len ; i ++ ) {
161
+ teardownFunctions [ i ] ( ) ;
162
+ }
163
+ } ;
164
+ var setupBindings = ! domData . get . call ( el , 'preventDataBindings' ) ;
165
+ var viewModel , frag ;
166
+ var teardownBindings ;
167
+ if ( setupBindings ) {
168
+ var setupFn = componentTagData . setupBindings || function ( el , callback , data ) {
169
+ return stacheBindings . behaviors . viewModel ( el , componentTagData , callback , data ) ;
170
+ } ;
171
+ teardownBindings = setupFn ( el , function ( initialViewModelData ) {
172
+ var ViewModel = component . constructor . ViewModel , viewModelHandler = component . constructor . viewModelHandler , viewModelInstance = component . constructor . viewModelInstance ;
173
+ if ( viewModelHandler ) {
174
+ var scopeResult = viewModelHandler . call ( component , initialViewModelData , componentTagData . scope , el ) ;
175
+ if ( canReflect . isObservableLike ( scopeResult ) && canReflect . isMapLike ( scopeResult ) ) {
176
+ viewModelInstance = scopeResult ;
177
+ } else if ( canReflect . isObservableLike ( scopeResult . prototype ) && canReflect . isMapLike ( scopeResult . prototype ) ) {
178
+ ViewModel = scopeResult ;
179
+ } else {
180
+ ViewModel = types . DefaultMap . extend ( scopeResult ) ;
181
+ }
182
+ }
183
+ if ( ViewModel ) {
184
+ viewModelInstance = new ViewModel ( initialViewModelData ) ;
185
+ }
186
+ viewModel = viewModelInstance ;
187
+ return viewModelInstance ;
188
+ } , initialViewModelData ) ;
189
+ }
190
+ this . viewModel = viewModel ;
191
+ domData . set . call ( el , 'viewModel' , viewModel ) ;
192
+ domData . set . call ( el , 'preventDataBindings' , true ) ;
193
+ var options = {
194
+ helpers : { } ,
195
+ tags : { }
196
+ } ;
197
+ canEach ( this . helpers || { } , function ( val , prop ) {
198
+ if ( isFunction ( val ) ) {
199
+ options . helpers [ prop ] = val . bind ( viewModel ) ;
200
+ }
201
+ } ) ;
202
+ if ( this . constructor . Control ) {
203
+ this . _control = new this . constructor . Control ( el , {
204
+ scope : this . viewModel ,
205
+ viewModel : this . viewModel ,
206
+ destroy : callTeardownFunctions
207
+ } ) ;
208
+ }
209
+ var leakScope = {
210
+ toLightContent : this . leakScope === true ,
211
+ intoShadowContent : this . leakScope === true
212
+ } ;
213
+ var hasShadowTemplate = ! ! this . constructor . renderer ;
214
+ var betweenTagsRenderer ;
215
+ var betweenTagsTagData ;
216
+ if ( hasShadowTemplate ) {
217
+ var shadowTagData ;
218
+ if ( leakScope . intoShadowContent ) {
219
+ shadowTagData = {
220
+ scope : componentTagData . scope . add ( new Scope . Refs ( ) ) . add ( this . viewModel , { viewModel : true } ) ,
221
+ options : componentTagData . options . add ( options )
222
+ } ;
223
+ } else {
224
+ shadowTagData = {
225
+ scope : Scope . refsScope ( ) . add ( this . viewModel , { viewModel : true } ) ,
226
+ options : new Scope . Options ( options )
227
+ } ;
228
+ }
229
+ options . tags [ 'can-slot' ] = makeInsertionTagCallback ( 'can-slot' , componentTagData , shadowTagData , leakScope , function ( el ) {
230
+ var templates = componentTagData . templates ;
231
+ if ( templates ) {
232
+ return templates [ el . getAttribute ( 'name' ) ] ;
233
+ }
234
+ } ) ;
235
+ options . tags . content = makeInsertionTagCallback ( 'content' , componentTagData , shadowTagData , leakScope , function ( ) {
236
+ return componentTagData . subtemplate ;
237
+ } ) ;
238
+ betweenTagsRenderer = this . constructor . renderer ;
239
+ betweenTagsTagData = shadowTagData ;
240
+ } else {
241
+ var lightTemplateTagData = {
242
+ scope : componentTagData . scope . add ( this . viewModel , { viewModel : true } ) ,
243
+ options : componentTagData . options . add ( options )
244
+ } ;
245
+ betweenTagsTagData = lightTemplateTagData ;
246
+ betweenTagsRenderer = componentTagData . subtemplate || el . ownerDocument . createDocumentFragment . bind ( el . ownerDocument ) ;
247
+ }
248
+ var nodeList = nodeLists . register ( [ ] , function ( ) {
249
+ domDispatch . call ( el , 'beforeremove' , [ ] , false ) ;
250
+ if ( teardownBindings ) {
251
+ teardownBindings ( ) ;
252
+ }
253
+ } , componentTagData . parentNodeList || true , false ) ;
254
+ nodeList . expression = '<' + this . tag + '>' ;
255
+ teardownFunctions . push ( function ( ) {
256
+ nodeLists . unregister ( nodeList ) ;
257
+ } ) ;
258
+ frag = betweenTagsRenderer ( betweenTagsTagData . scope , betweenTagsTagData . options , nodeList ) ;
259
+ domMutate . appendChild . call ( el , frag ) ;
260
+ nodeLists . update ( nodeList , getChildNodes ( el ) ) ;
261
+ }
262
+ } ) ;
263
+ module . exports = namespace . Component = Component ;
264
+ } ) ;
0 commit comments