@@ -760,10 +760,10 @@ var cssTransitionsEnabled, transition, transitionend;
760
760
761
761
if ( ! this . root . lazy ) {
762
762
node . addEventListener ( 'input' , updateModel , false ) ;
763
- }
764
763
765
- if ( node . attachEvent ) {
766
- node . addEventListener ( 'keyup' , updateModel , false ) ;
764
+ if ( node . attachEvent ) {
765
+ node . addEventListener ( 'keyup' , updateModel , false ) ;
766
+ }
767
767
}
768
768
} ;
769
769
@@ -2073,7 +2073,7 @@ resolveMustache = function ( keypath ) {
2073
2073
} ;
2074
2074
( function ( ) {
2075
2075
2076
- var updateListSection , updateContextSection , updateConditionalSection ;
2076
+ var updateListSection , updateListObjectSection , updateContextSection , updateConditionalSection ;
2077
2077
2078
2078
updateSection = function ( section , value ) {
2079
2079
var fragmentOptions ;
@@ -2093,15 +2093,19 @@ resolveMustache = function ( keypath ) {
2093
2093
2094
2094
// otherwise we need to work out what sort of section we're dealing with
2095
2095
2096
- // if value is an array, iterate through
2096
+ // if value is an array, or an object with an index reference, iterate through
2097
2097
if ( isArray ( value ) ) {
2098
2098
updateListSection ( section , value , fragmentOptions ) ;
2099
2099
}
2100
2100
2101
2101
2102
2102
// if value is a hash...
2103
2103
else if ( isObject ( value ) ) {
2104
- updateContextSection ( section , fragmentOptions ) ;
2104
+ if ( section . descriptor . i ) {
2105
+ updateListObjectSection ( section , value , fragmentOptions ) ;
2106
+ } else {
2107
+ updateContextSection ( section , fragmentOptions ) ;
2108
+ }
2105
2109
}
2106
2110
2107
2111
@@ -2112,11 +2116,13 @@ resolveMustache = function ( keypath ) {
2112
2116
} ;
2113
2117
2114
2118
updateListSection = function ( section , value , fragmentOptions ) {
2115
- var i , fragmentsToRemove ;
2119
+ var i , length , fragmentsToRemove ;
2120
+
2121
+ length = value . length ;
2116
2122
2117
2123
// if the array is shorter than it was previously, remove items
2118
- if ( value . length < section . length ) {
2119
- fragmentsToRemove = section . fragments . splice ( value . length , section . length - value . length ) ;
2124
+ if ( length < section . length ) {
2125
+ fragmentsToRemove = section . fragments . splice ( length , section . length - length ) ;
2120
2126
2121
2127
while ( fragmentsToRemove . length ) {
2122
2128
fragmentsToRemove . pop ( ) . teardown ( true ) ;
@@ -2126,9 +2132,9 @@ resolveMustache = function ( keypath ) {
2126
2132
// otherwise...
2127
2133
else {
2128
2134
2129
- if ( value . length > section . length ) {
2135
+ if ( length > section . length ) {
2130
2136
// add any new ones
2131
- for ( i = section . length ; i < value . length ; i += 1 ) {
2137
+ for ( i = section . length ; i < length ; i += 1 ) {
2132
2138
// append list item to context stack
2133
2139
fragmentOptions . contextStack = section . contextStack . concat ( section . keypath + '.' + i ) ;
2134
2140
fragmentOptions . index = i ;
@@ -2142,7 +2148,35 @@ resolveMustache = function ( keypath ) {
2142
2148
}
2143
2149
}
2144
2150
2145
- section . length = value . length ;
2151
+ section . length = length ;
2152
+ } ;
2153
+
2154
+ updateListObjectSection = function ( section , value , fragmentOptions ) {
2155
+ var id , fragmentsById ;
2156
+
2157
+ fragmentsById = section . fragmentsById || ( section . fragmentsById = createFromNull ( ) ) ;
2158
+
2159
+ // remove any fragments that should no longer exist
2160
+ for ( id in fragmentsById ) {
2161
+ if ( value [ id ] === undefined ) {
2162
+ fragmentsById [ id ] . teardown ( true ) ;
2163
+ fragmentsById [ id ] = null ;
2164
+ }
2165
+ }
2166
+
2167
+ // add any that haven't been created yet
2168
+ for ( id in value ) {
2169
+ if ( value [ id ] !== undefined && ! fragmentsById [ id ] ) {
2170
+ fragmentOptions . contextStack = section . contextStack . concat ( section . keypath + '.' + id ) ;
2171
+ fragmentOptions . index = id ;
2172
+
2173
+ if ( section . descriptor . i ) {
2174
+ fragmentOptions . indexRef = section . descriptor . i ;
2175
+ }
2176
+
2177
+ fragmentsById [ id ] = section . createFragment ( fragmentOptions ) ;
2178
+ }
2179
+ }
2146
2180
} ;
2147
2181
2148
2182
updateContextSection = function ( section , fragmentOptions ) {
@@ -2731,12 +2765,26 @@ proto.fire = function ( eventName ) {
2731
2765
2732
2766
// wrap object for magic get/set
2733
2767
wrapProperty = function ( obj , prop , ractive , keypath ) {
2734
- var value , descriptor , get , set , oldGet , oldSet ;
2768
+ var value , descriptor , get , set , oldGet , oldSet , ractives , keypathsByGuid ;
2735
2769
2736
2770
descriptor = Object . getOwnPropertyDescriptor ( obj , prop ) ;
2737
2771
2738
2772
if ( descriptor ) {
2739
- if ( descriptor . set && descriptor . set [ ractive . _guid + keypath ] ) {
2773
+ if ( descriptor . set && ( ractives = descriptor . set . ractives ) ) {
2774
+ console . log ( 'here' ) ;
2775
+
2776
+ // register this ractive to this object
2777
+ if ( ractives . indexOf ( ractive ) === - 1 ) {
2778
+ ractives [ ractives . length ] = ractive ;
2779
+ }
2780
+
2781
+ // register this keypath to this object
2782
+ keypathsByGuid = descriptor . set [ ractive . _guid ] || ( descriptor . set [ ractive . _guid ] = [ ] ) ;
2783
+
2784
+ if ( keypathsByGuid . indexOf ( keypath ) === - 1 ) {
2785
+ keypathsByGuid [ keypathsByGuid . length ] = keypath ;
2786
+ }
2787
+
2740
2788
return ; // already wrapped
2741
2789
}
2742
2790
@@ -2755,17 +2803,34 @@ proto.fire = function ( eventName ) {
2755
2803
} ;
2756
2804
2757
2805
set = function ( newValue ) {
2806
+ var ractives , ractive , keypaths , i , j ;
2807
+
2758
2808
value = newValue ;
2759
2809
2760
- if ( ! ractive . muggleSet ) {
2761
- ractive . magicSet = true ;
2762
- ractive . set ( keypath , newValue ) ;
2763
- ractive . magicSet = false ;
2810
+ ractives = set . ractives ;
2811
+
2812
+ i = ractives . length ;
2813
+ while ( i -- ) {
2814
+ ractive = ractives [ i ] ;
2815
+
2816
+ if ( ! ractive . muggleSet ) {
2817
+ ractive . magicSet = true ;
2818
+
2819
+ keypaths = set [ ractive . _guid ] ;
2820
+ j = keypaths . length ;
2821
+
2822
+ while ( j -- ) {
2823
+ ractive . set ( keypaths [ j ] , newValue ) ;
2824
+ }
2825
+
2826
+ ractive . magicSet = false ;
2827
+ }
2764
2828
}
2765
2829
} ;
2766
2830
2767
2831
// prevent rewrapping
2768
- set [ ractive . _guid + keypath ] = true ;
2832
+ set . ractives = [ ractive ] ;
2833
+ set [ ractive . _guid ] = [ keypath ] ;
2769
2834
2770
2835
Object . defineProperty ( obj , prop , { get : get , set : set , enumerable : true , configurable : true } ) ;
2771
2836
}
@@ -2800,7 +2865,10 @@ proto.fire = function ( eventName ) {
2800
2865
2801
2866
return {
2802
2867
teardown : function ( ) {
2868
+ var value = obj [ prop ] ;
2869
+
2803
2870
Object . defineProperty ( obj , prop , descriptor ) ;
2871
+ obj [ prop ] = value ;
2804
2872
}
2805
2873
} ;
2806
2874
} ;
@@ -3827,7 +3895,7 @@ eventDefinitions.tap = function ( node, fire ) {
3827
3895
timeThreshold = 400 ; // maximum milliseconds between down and up before cancel
3828
3896
3829
3897
mousedown = function ( event ) {
3830
- var currentTarget , x , y , up , move , cancel ;
3898
+ var currentTarget , x , y , pointerId , up , move , cancel ;
3831
3899
3832
3900
if ( event . which != 1 ) {
3833
3901
return ;
@@ -3836,8 +3904,14 @@ eventDefinitions.tap = function ( node, fire ) {
3836
3904
x = event . clientX ;
3837
3905
y = event . clientY ;
3838
3906
currentTarget = this ;
3907
+ // This will be null for mouse events.
3908
+ pointerId = event . pointerId ;
3839
3909
3840
3910
up = function ( event ) {
3911
+ if ( event . pointerId != pointerId ) {
3912
+ return ;
3913
+ }
3914
+
3841
3915
fire ( {
3842
3916
node : currentTarget ,
3843
3917
original : event
@@ -3847,23 +3921,49 @@ eventDefinitions.tap = function ( node, fire ) {
3847
3921
} ;
3848
3922
3849
3923
move = function ( event ) {
3924
+ if ( event . pointerId != pointerId ) {
3925
+ return ;
3926
+ }
3927
+
3850
3928
if ( ( Math . abs ( event . clientX - x ) >= distanceThreshold ) || ( Math . abs ( event . clientY - y ) >= distanceThreshold ) ) {
3851
3929
cancel ( ) ;
3852
3930
}
3853
3931
} ;
3854
3932
3855
3933
cancel = function ( ) {
3934
+ node . removeEventListener ( 'MSPointerUp' , up , false ) ;
3935
+ doc . removeEventListener ( 'MSPointerMove' , move , false ) ;
3936
+ doc . removeEventListener ( 'MSPointerCancel' , cancel , false ) ;
3937
+ node . removeEventListener ( 'pointerup' , up , false ) ;
3938
+ doc . removeEventListener ( 'pointermove' , move , false ) ;
3939
+ doc . removeEventListener ( 'pointercancel' , cancel , false ) ;
3856
3940
node . removeEventListener ( 'click' , up , false ) ;
3857
3941
doc . removeEventListener ( 'mousemove' , move , false ) ;
3858
3942
} ;
3859
3943
3860
- node . addEventListener ( 'click' , up , false ) ;
3861
- doc . addEventListener ( 'mousemove' , move , false ) ;
3944
+ if ( window . navigator . pointerEnabled ) {
3945
+ node . addEventListener ( 'pointerup' , up , false ) ;
3946
+ doc . addEventListener ( 'pointermove' , move , false ) ;
3947
+ doc . addEventListener ( 'pointercancel' , cancel , false ) ;
3948
+ } else if ( window . navigator . msPointerEnabled ) {
3949
+ node . addEventListener ( 'MSPointerUp' , up , false ) ;
3950
+ doc . addEventListener ( 'MSPointerMove' , move , false ) ;
3951
+ doc . addEventListener ( 'MSPointerCancel' , cancel , false ) ;
3952
+ } else {
3953
+ node . addEventListener ( 'click' , up , false ) ;
3954
+ doc . addEventListener ( 'mousemove' , move , false ) ;
3955
+ }
3862
3956
3863
3957
setTimeout ( cancel , timeThreshold ) ;
3864
3958
} ;
3865
3959
3866
- node . addEventListener ( 'mousedown' , mousedown , false ) ;
3960
+ if ( window . navigator . pointerEnabled ) {
3961
+ node . addEventListener ( 'pointerdown' , mousedown , false ) ;
3962
+ } else if ( window . navigator . msPointerEnabled ) {
3963
+ node . addEventListener ( 'MSPointerDown' , mousedown , false ) ;
3964
+ } else {
3965
+ node . addEventListener ( 'mousedown' , mousedown , false ) ;
3966
+ }
3867
3967
3868
3968
3869
3969
touchstart = function ( event ) {
@@ -4483,13 +4583,7 @@ Ractive = function ( options ) {
4483
4583
}
4484
4584
}
4485
4585
}
4486
-
4487
- // Unpack string-based partials, if necessary
4488
- for ( key in this . partials ) {
4489
- if ( hasOwn . call ( this . partials , key ) && this . partials [ key ] . length === 1 && typeof this . partials [ key ] [ 0 ] === 'string' ) {
4490
- this . partials [ key ] = this . partials [ key ] [ 0 ] ;
4491
- }
4492
- }
4586
+
4493
4587
4494
4588
// temporarily disable transitions, if noIntro flag is set
4495
4589
this . transitionsEnabled = ( options . noIntro ? false : options . transitionsEnabled ) ;
@@ -6276,9 +6370,18 @@ DomSection.prototype = {
6276
6370
} ,
6277
6371
6278
6372
teardownFragments : function ( detach ) {
6373
+ var id ;
6374
+
6279
6375
while ( this . fragments . length ) {
6280
6376
this . fragments . shift ( ) . teardown ( detach ) ;
6281
6377
}
6378
+
6379
+ if ( this . fragmentsById ) {
6380
+ for ( id in this . fragmentsById ) {
6381
+ this . fragmentsById [ id ] . teardown ( ) ;
6382
+ this . fragmentsById [ id ] = null ;
6383
+ }
6384
+ }
6282
6385
} ,
6283
6386
6284
6387
render : function ( value ) {
0 commit comments