11"use strict" ;
2- /* jshint -W079 */
32
43// # can-component.js
54// This implements the `Component` which allows you to create widgets
@@ -17,7 +16,6 @@ var stache = require("can-stache");
1716var stacheBindings = require ( "can-stache-bindings" ) ;
1817var Scope = require ( "can-view-scope" ) ;
1918var viewCallbacks = require ( "can-view-callbacks" ) ;
20- var nodeLists = require ( "can-view-nodelist" ) ;
2119var canReflect = require ( "can-reflect" ) ;
2220var SimpleObservable = require ( "can-simple-observable" ) ;
2321var SimpleMap = require ( "can-simple-map" ) ;
@@ -28,7 +26,6 @@ var assign = require('can-assign');
2826var ObservationRecorder = require ( "can-observation-recorder" ) ;
2927var queues = require ( "can-queues" ) ;
3028var domData = require ( 'can-dom-data' ) ;
31- var getChildNodes = require ( 'can-child-nodes' ) ;
3229var string = require ( "can-string" ) ;
3330var domEvents = require ( 'can-dom-events' ) ;
3431var domMutate = require ( 'can-dom-mutate' ) ;
@@ -57,7 +54,7 @@ var viewModelSymbol = canSymbol.for('can.viewModel');
5754
5855
5956// ## Helpers
60- var noop = function ( ) { } ;
57+
6158// ### addContext
6259// For replacement elements like `<can-slot>` and `<context>`, this is used to
6360// figure out what data they should render with. Slots can have bindings like
@@ -176,19 +173,31 @@ function makeReplacementTagCallback(tagName, componentTagData, shadowTagData, le
176173 // Now we need to render the right template and insert its result in the page.
177174 // We need to teardown any bindings created too so we create a nodeList
178175 // to do this.
176+ var fragment = template ( tagData . scope , tagData . options ) ;
177+ if ( tagData . teardown ) {
179178
179+ var placeholder = el . ownerDocument . createComment ( tagName ) ;
180+ fragment . insertBefore ( placeholder , fragment . firstChild ) ;
181+ domMutate . onNodeRemoved ( placeholder , tagData . teardown ) ;
182+ }
180183
181-
184+ el . parentNode . replaceChild (
185+ fragment ,
186+ el
187+ ) ;
188+ /*
182189 var nodeList = nodeLists.register([el], tagData.teardown || noop,
183190 insertionElementTagData.parentNodeList || true,
184191 insertionElementTagData.directlyNested);
185192
186193 nodeList.expression = "<can-slot name='"+el.getAttribute('name')+"'/>";
187194
188- var frag = template ( tagData . scope , tagData . options , nodeList ) ;
195+ var frag = template(tagData.scope, tagData.options);
196+
197+
189198 var newNodes = canReflect.toArray( getChildNodes(frag) );
190199 var oldNodes = nodeLists.update(nodeList, newNodes);
191- nodeLists . replace ( oldNodes , frag ) ;
200+ nodeLists.replace(oldNodes, frag);*/
192201
193202 // Restore the proper tag function so it could potentially be used again (as in lists)
194203 options . tags [ tagName ] = replacementTag ;
@@ -236,7 +245,8 @@ function getSetupFunctionForComponentVM(componentInitVM) {
236245 var canBinding = new Bind ( {
237246 child : child ,
238247 parent : parent ,
239- queue : "domUI" ,
248+ queue : "dom" ,
249+ element : el ,
240250
241251 //!steal-remove-start
242252 // For debugging: the names that will be assigned to the updateChild
@@ -539,13 +549,30 @@ var Component = Construct.extend(
539549 el . viewModel = viewModel ;
540550 domData . set ( el , "preventDataBindings" , true ) ;
541551
542- // an array of teardown stuff that should happen when the element is removed
543- var teardownFunctions = [ ] ;
544- var callTeardownFunctions = function ( ) {
545- for ( var i = 0 , len = teardownFunctions . length ; i < len ; i ++ ) {
546- teardownFunctions [ i ] ( ) ;
547- }
548- } ;
552+ // TEARDOWN SETUP
553+ var removedDisposal ,
554+ connectedDisposal ,
555+ viewModelDisconnectedCallback ;
556+ function teardownComponent ( ) {
557+ if ( removedDisposal ) {
558+ removedDisposal ( ) ;
559+ removedDisposal = null ;
560+ }
561+ component . _torndown = true ;
562+ domEvents . dispatch ( el , "beforeremove" , false ) ;
563+ if ( teardownBindings ) {
564+ teardownBindings ( ) ;
565+ }
566+ if ( viewModelDisconnectedCallback ) {
567+ viewModelDisconnectedCallback ( el ) ;
568+ } else if ( typeof viewModel . stopListening === "function" ) {
569+ viewModel . stopListening ( ) ;
570+ }
571+ if ( connectedDisposal ) {
572+ connectedDisposal ( ) ;
573+ connectedDisposal = null ;
574+ }
575+ }
549576
550577 // #### Helpers
551578 // TODO: remove in next release
@@ -558,33 +585,25 @@ var Component = Construct.extend(
558585 } ) ;
559586 }
560587
561-
562588 // #### `events` control
563589 // TODO: remove in next release
564590 // Create a control to listen to events
565591 if ( this . constructor . Control ) {
566592 this . _control = new this . constructor . Control ( el , {
567593 // Pass the viewModel to the control so we can listen to it's changes from the controller.
568594 scope : this . viewModel ,
569- viewModel : this . viewModel ,
570- destroy : callTeardownFunctions
571- } ) ;
572- } else {
573- var removalDisposal = domMutate . onNodeRemoval ( el , function ( ) {
574- var doc = el . ownerDocument ;
575- var rootNode = doc . contains ? doc : doc . documentElement ;
576- if ( ! rootNode || ! rootNode . contains ( el ) ) {
577- if ( removalDisposal ) {
578- nodeRemoved = true ;
579- removalDisposal ( ) ;
580- callTeardownFunctions ( ) ;
581- removalDisposal = null ;
582- callTeardownFunctions = null ;
583- }
584- }
595+ viewModel : this . viewModel
585596 } ) ;
586597 }
587598
599+ removedDisposal = domMutate . onNodeRemoved ( el , function ( ) {
600+ var doc = el . ownerDocument ;
601+ var rootNode = doc . contains ? doc : doc . documentElement ;
602+ if ( ! rootNode || ! rootNode . contains ( el ) ) {
603+ teardownComponent ( ) ;
604+ }
605+ } ) ;
606+
588607 // #### Rendering
589608
590609 var leakScope = {
@@ -644,61 +663,32 @@ var Component = Construct.extend(
644663 betweenTagsTagData = lightTemplateTagData ;
645664 betweenTagsView = componentTagData . subtemplate || el . ownerDocument . createDocumentFragment . bind ( el . ownerDocument ) ;
646665 }
647- var viewModelDisconnectedCallback ,
648- insertionDisposal ,
649- componentInPage ,
650- nodeRemoved ;
666+
667+
668+
651669
652670 // Keep a nodeList so we can kill any directly nested nodeLists within this component
653- var nodeList = nodeLists . register ( [ ] , function ( ) {
654- if ( removalDisposal && ! nodeRemoved ) {
655- removalDisposal ( ) ;
656- callTeardownFunctions ( ) ;
657- removalDisposal = null ;
658- callTeardownFunctions = null ;
659- }
660- component . _torndown = true ;
661- domEvents . dispatch ( el , "beforeremove" , false ) ;
662- if ( teardownBindings ) {
663- teardownBindings ( ) ;
664- }
665- if ( viewModelDisconnectedCallback ) {
666- viewModelDisconnectedCallback ( el ) ;
667- } else if ( typeof viewModel . stopListening === "function" ) {
668- viewModel . stopListening ( ) ;
669- }
670- if ( insertionDisposal ) {
671- insertionDisposal ( ) ;
672- insertionDisposal = null ;
673- }
674- } , componentTagData . parentNodeList || true , false ) ;
675- nodeList . expression = "<" + this . tag + ">" ;
676- teardownFunctions . push ( function ( ) {
677- nodeLists . unregister ( nodeList ) ;
678- } ) ;
679- this . nodeList = nodeList ;
680671
681- shadowFragment = betweenTagsView ( betweenTagsTagData . scope , betweenTagsTagData . options , nodeList ) ;
672+
673+
674+ shadowFragment = betweenTagsView ( betweenTagsTagData . scope , betweenTagsTagData . options ) ;
682675
683676 // TODO: afterRender
684677
685678 // Append the resulting document fragment to the element
686679 domMutateNode . appendChild . call ( el , shadowFragment ) ;
687680
688- // update the nodeList with the new children so the mapping gets applied
689- nodeLists . update ( nodeList , getChildNodes ( el ) ) ;
690-
691681 // Call connectedCallback
692682 if ( viewModel && viewModel . connectedCallback ) {
693683 var body = DOCUMENT ( ) . body ;
694- componentInPage = body && body . contains ( el ) ;
684+ var componentInPage = body && body . contains ( el ) ;
695685
696686 if ( componentInPage ) {
697687 viewModelDisconnectedCallback = viewModel . connectedCallback ( el ) ;
698688 } else {
699- insertionDisposal = domMutate . onNodeInsertion ( el , function ( ) {
700- insertionDisposal ( ) ;
701- insertionDisposal = null ;
689+ connectedDisposal = domMutate . onNodeConnected ( el , function ( ) {
690+ connectedDisposal ( ) ;
691+ connectedDisposal = null ;
702692 viewModelDisconnectedCallback = viewModel . connectedCallback ( el ) ;
703693 } ) ;
704694 }
@@ -713,7 +703,6 @@ Component.prototype[viewInsertSymbol] = function(viewData) {
713703 if ( this . _torndown ) {
714704 this . setup . apply ( this , this . _initialArgs ) ;
715705 }
716- viewData . nodeList . newDeepChildren . push ( this . nodeList ) ;
717706 return this . element ;
718707} ;
719708
0 commit comments