@@ -2634,41 +2634,33 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
2634
2634
parent . replaceChild ( newNode , firstElementToRemove ) ;
2635
2635
}
2636
2636
2637
- // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it?
2637
+ // Append all the `elementsToRemove` to a fragment. This will...
2638
+ // - remove them from the DOM
2639
+ // - allow them to still be traversed with .nextSibling
2640
+ // - allow a single fragment.qSA to fetch all elements being removed
2638
2641
var fragment = document . createDocumentFragment ( ) ;
2639
- fragment . appendChild ( firstElementToRemove ) ;
2642
+ for ( i = 0 ; i < removeCount ; i ++ ) {
2643
+ fragment . appendChild ( elementsToRemove [ i ] ) ;
2644
+ }
2640
2645
2641
2646
if ( jqLite . hasData ( firstElementToRemove ) ) {
2642
2647
// Copy over user data (that includes Angular's $scope etc.). Don't copy private
2643
2648
// data here because there's no public interface in jQuery to do that and copying over
2644
2649
// event listeners (which is the main use of private data) wouldn't work anyway.
2645
2650
jqLite . data ( newNode , jqLite . data ( firstElementToRemove ) ) ;
2646
2651
2647
- // Remove data of the replaced element. We cannot just call .remove()
2648
- // on the element it since that would deallocate scope that is needed
2649
- // for the new node. Instead, remove the data "manually".
2650
- if ( ! jQuery ) {
2651
- delete jqLite . cache [ firstElementToRemove [ jqLite . expando ] ] ;
2652
- } else {
2653
- // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after
2654
- // the replaced element. The cleanData version monkey-patched by Angular would cause
2655
- // the scope to be trashed and we do need the very same scope to work with the new
2656
- // element. However, we cannot just cache the non-patched version and use it here as
2657
- // that would break if another library patches the method after Angular does (one
2658
- // example is jQuery UI). Instead, set a flag indicating scope destroying should be
2659
- // skipped this one time.
2660
- skipDestroyOnNextJQueryCleanData = true ;
2661
- jQuery . cleanData ( [ firstElementToRemove ] ) ;
2662
- }
2652
+ // Remove $destroy event listeners from `firstElementToRemove`
2653
+ jqLite ( firstElementToRemove ) . off ( '$destroy' ) ;
2663
2654
}
2664
2655
2665
- for ( var k = 1 , kk = elementsToRemove . length ; k < kk ; k ++ ) {
2666
- var element = elementsToRemove [ k ] ;
2667
- jqLite ( element ) . remove ( ) ; // must do this way to clean up expando
2668
- fragment . appendChild ( element ) ;
2669
- delete elementsToRemove [ k ] ;
2670
- }
2656
+ // Cleanup any data/listeners on the elements and children.
2657
+ // This includes invoking the $destroy event on any elements with listeners.
2658
+ jqLite . cleanData ( fragment . querySelectorAll ( '*' ) ) ;
2671
2659
2660
+ // Update the jqLite collection to only contain the `newNode`
2661
+ for ( i = 1 ; i < removeCount ; i ++ ) {
2662
+ delete elementsToRemove [ i ] ;
2663
+ }
2672
2664
elementsToRemove [ 0 ] = newNode ;
2673
2665
elementsToRemove . length = 1 ;
2674
2666
}
0 commit comments