@@ -24,7 +24,7 @@ define(["widgets/js/manager",
2424 this . _buffered_state_diff = { } ;
2525 this . pending_msgs = 0 ;
2626 this . msg_buffer = null ;
27- this . key_value_lock = null ;
27+ this . state_lock = null ;
2828 this . id = model_id ;
2929 this . views = [ ] ;
3030
@@ -80,15 +80,16 @@ define(["widgets/js/manager",
8080
8181 apply_update : function ( state ) {
8282 // Handle when a widget is updated via the python side.
83- var that = this ;
84- _ . each ( state , function ( value , key ) {
85- that . key_value_lock = [ key , value ] ;
86- try {
87- WidgetModel . __super__ . set . apply ( that , [ key , that . _unpack_models ( value ) ] ) ;
88- } finally {
89- that . key_value_lock = null ;
90- }
91- } ) ;
83+ this . state_lock = state ;
84+ try {
85+ var that = this ;
86+ WidgetModel . __super__ . set . apply ( this , [ Object . keys ( state ) . reduce ( function ( obj , key ) {
87+ obj [ key ] = that . _unpack_models ( state [ key ] ) ;
88+ return obj ;
89+ } , { } ) ] ) ;
90+ } finally {
91+ this . state_lock = null ;
92+ }
9293 } ,
9394
9495 _handle_status : function ( msg , callbacks ) {
@@ -151,11 +152,13 @@ define(["widgets/js/manager",
151152
152153 // Delete any key value pairs that the back-end already knows about.
153154 var attrs = ( method === 'patch' ) ? options . attrs : model . toJSON ( options ) ;
154- if ( this . key_value_lock !== null ) {
155- var key = this . key_value_lock [ 0 ] ;
156- var value = this . key_value_lock [ 1 ] ;
157- if ( attrs [ key ] === value ) {
158- delete attrs [ key ] ;
155+ if ( this . state_lock !== null ) {
156+ var keys = Object . keys ( this . state_lock ) ;
157+ for ( var i = 0 ; i < keys . length ; i ++ ) {
158+ var key = keys [ i ] ;
159+ if ( attrs [ key ] === this . state_lock [ key ] ) {
160+ delete attrs [ key ] ;
161+ }
159162 }
160163 }
161164
@@ -266,6 +269,19 @@ define(["widgets/js/manager",
266269 }
267270 } ,
268271
272+ on_atomic_change : function ( keys , callback , context ) {
273+ // on__atomic_change(["key1", "key2"], foo, context) differs from
274+ // on("change:key1 change:key2", foo, context).
275+ // If the widget attributes key1 and key2 are both modified,
276+ // the second form will result in foo being called twice
277+ // while the first will call foo only once.
278+ this . on ( 'change' , function ( ) {
279+ if ( keys . some ( this . hasChanged , this ) ) {
280+ callback . apply ( context ) ;
281+ }
282+ } , this ) ;
283+
284+ } ,
269285 } ) ;
270286 widgetmanager . WidgetManager . register_widget_model ( 'WidgetModel' , WidgetModel ) ;
271287
0 commit comments