##// END OF EJS Templates
Move _unpack_models to widget.js and widget serialization to widget.py
Move _unpack_models to widget.js and widget serialization to widget.py

File last commit:

r21157:3afdea41
r21157:3afdea41
Show More
widget.js
806 lines | 31.6 KiB | application/javascript | JavascriptLexer
Jonathan Frederic
Almost done!...
r17198 // Copyright (c) IPython Development Team.
// Distributed under the terms of the Modified BSD License.
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546
Jonathan Frederic
Updated require references to point to new files
r15427 define(["widgets/js/manager",
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 "underscore",
Jason Grout
Load the utils module
r18892 "backbone",
"jquery",
"base/js/utils",
Jonathan Frederic
Fix all the tests
r17216 "base/js/namespace",
Jonathan Frederic
use es6
r18907 ], function(widgetmanager, _, Backbone, $, utils, IPython){
Matthias Bussonnier
Some code cleanup in javascript and python...
r19739 "use strict";
Jonathan Frederic
Added PEP8 style comments to all of the JS code.
r14609
Sylvain Corlay
Move _unpack_models to widget.js and widget serialization to widget.py
r21157 var unpack_models = function unpack_models(value, model) {
/**
* Replace model ids with models recursively.
*/
var unpacked;
if ($.isArray(value)) {
unpacked = [];
_.each(value, function(sub_value, key) {
unpacked.push(unpack_models(sub_value, model));
});
return Promise.all(unpacked);
} else if (value instanceof Object) {
unpacked = {};
_.each(value, function(sub_value, key) {
unpacked[key] = unpack_models(sub_value, model);
});
return utils.resolve_promises_dict(unpacked);
} else if (typeof value === 'string' && value.slice(0,10) === "IPY_MODEL_") {
// get_model returns a promise already
return model.widget_manager.get_model(value.slice(10, value.length));
} else {
return Promise.resolve(value);
}
};
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 var WidgetModel = Backbone.Model.extend({
Jason Grout
More simplifications due to promises
r18888 constructor: function (widget_manager, model_id, comm) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Constructor
*
* Creates a WidgetModel instance.
*
* Parameters
* ----------
* widget_manager : WidgetManager instance
* model_id : string
* An ID unique to this model.
* comm : Comm instance (optional)
*/
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 this.widget_manager = widget_manager;
Jonathan Frederic
use es6
r18907 this.state_change = Promise.resolve();
Jonathan Frederic
Keep a running diff instead of forcing a full state update
r15280 this._buffered_state_diff = {};
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 this.pending_msgs = 0;
this.msg_buffer = null;
sylvain.corlay
optimization of WidgetModel.apply_update
r17839 this.state_lock = null;
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 this.id = model_id;
Sylvain Corlay
Make Widget.views be an object indexed by view id
r18007 this.views = {};
Jonathan Frederic
Address @jasongrout 's review comments, take 2
r19360 this._resolve_received_state = {};
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546
if (comm !== undefined) {
// Remember comm associated with the model.
this.comm = comm;
comm.model = this;
// Hook comm messages up to model.
comm.on_close($.proxy(this._handle_comm_closed, this));
comm.on_msg($.proxy(this._handle_comm_msg, this));
Jonathan Frederic
Persistence API,...
r19350
// Assume the comm is alive.
Jonathan Frederic
Address @jasongrout 's review comments, take 2
r19360 this.set_comm_live(true);
Jonathan Frederic
Persistence API,...
r19350 } else {
Jonathan Frederic
Address @jasongrout 's review comments, take 2
r19360 this.set_comm_live(false);
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 }
Jonathan Frederic
Make sure comm-dead is applied to the top widget view class...
r19566
// Listen for the events that lead to the websocket being terminated.
var that = this;
var died = function() {
that.set_comm_live(false);
};
widget_manager.notebook.events.on('kernel_disconnected.Kernel', died);
widget_manager.notebook.events.on('kernel_killed.Kernel', died);
widget_manager.notebook.events.on('kernel_restarting.Kernel', died);
widget_manager.notebook.events.on('kernel_dead.Kernel', died);
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 return Backbone.Model.apply(this);
},
Jason Grout
work-in-progress for custom js serializers
r20839 send: function (content, callbacks, buffers) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Send a custom msg over the comm.
*/
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 if (this.comm !== undefined) {
Jonathan Frederic
s/custom_content/content
r14655 var data = {method: 'custom', content: content};
Jason Grout
work-in-progress for custom js serializers
r20839 this.comm.send(data, callbacks, {}, buffers);
Jonathan Frederic
Fixed bug in throttling code.
r14741 this.pending_msgs++;
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 }
},
Jonathan Frederic
Persistence API,...
r19350 request_state: function(callbacks) {
/**
* Request a state push from the back-end.
*/
if (!this.comm) {
console.error("Could not request_state because comm doesn't exist!");
return;
}
Jonathan Frederic
Promises...
r19351
Jonathan Frederic
Address @jasongrout 's review comments, take 2
r19360 var msg_id = this.comm.send({method: 'request_state'}, callbacks || this.widget_manager.callbacks());
Jonathan Frederic
Promises...
r19351 // Promise that is resolved when a state is received
// from the back-end.
var that = this;
var received_state = new Promise(function(resolve) {
Jonathan Frederic
Address @jasongrout 's review comments, take 2
r19360 that._resolve_received_state[msg_id] = resolve;
Jonathan Frederic
Promises...
r19351 });
return received_state;
Jonathan Frederic
Persistence API,...
r19350 },
Jonathan Frederic
Address @jasongrout 's review comments, take 2
r19360 set_comm_live: function(live) {
Jonathan Frederic
Persistence API,...
r19350 /**
Jonathan Frederic
Address @jasongrout 's review comments, take 2
r19360 * Change the comm_live state of the model.
Jonathan Frederic
Persistence API,...
r19350 */
Jonathan Frederic
Address @jasongrout 's review comments, take 2
r19360 if (this.comm_live === undefined || this.comm_live != live) {
this.comm_live = live;
this.trigger(live ? 'comm:live' : 'comm:dead', {model: this});
Jonathan Frederic
Persistence API,...
r19350 }
},
close: function(comm_closed) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
Jonathan Frederic
Persistence API,...
r19350 * Close model
Jonathan Frederic
Ran function comment conversion tool
r19176 */
Jonathan Frederic
Persistence API,...
r19350 if (this.comm && !comm_closed) {
this.comm.close();
}
Sylvain Corlay
stop listening
r17857 this.stopListening();
Sylvain Corlay
simplification of trigger destroy
r17848 this.trigger('destroy', this);
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 delete this.comm.model; // Delete ref so GC will collect widget model.
delete this.comm;
delete this.model_id; // Delete id from model so widget manager cleans up.
Jason Grout
Make the model.views dict a dict of promises for views...
r19170 _.each(this.views, function(v, id, views) {
v.then(function(view) {
view.remove();
delete views[id];
});
});
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 },
Jonathan Frederic
Persistence API,...
r19350 _handle_comm_closed: function (msg) {
/**
* Handle when a widget is closed.
*/
this.trigger('comm:close');
this.close(true);
},
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 _handle_comm_msg: function (msg) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Handle incoming comm msg.
*/
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 var method = msg.content.data.method;
Jason Grout
work-in-progress for custom js serializers
r20839
Jason Grout
Fix some this vs. that errors, as well as returning some promises to wait for fulfillment
r18893 var that = this;
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 switch (method) {
case 'update':
Jonathan Frederic
Address @jasongrout 's review comments, take 2
r19360 this.state_change = this.state_change
.then(function() {
Jason Grout
work-in-progress for custom js serializers
r20839 var state = msg.content.data.state || {};
var buffer_keys = msg.content.data.buffers || [];
var buffers = msg.buffers || [];
for (var i=0; i<buffer_keys.length; i++) {
Jason Grout
Change custom serialization to use custom models, rather than transmitting the serializer name across the wire...
r20935 state[buffer_keys[i]] = buffers[i];
Jason Grout
work-in-progress for custom js serializers
r20839 }
Jason Grout
Change custom serialization to use custom models, rather than transmitting the serializer name across the wire...
r20935 // deserialize fields that have custom deserializers
var serializers = that.constructor.serializers;
if (serializers) {
for (var k in state) {
if (serializers[k] && serializers[k].deserialize) {
state[k] = (serializers[k].deserialize)(state[k], that);
}
Jason Grout
work-in-progress for custom js serializers
r20839 }
}
return utils.resolve_promises_dict(state);
}).then(function(state) {
return that.set_state(state);
Jonathan Frederic
Address @jasongrout 's review comments, take 2
r19360 }).catch(utils.reject("Couldn't process update msg for model id '" + String(that.id) + "'", true))
.then(function() {
var parent_id = msg.parent_header.msg_id;
if (that._resolve_received_state[parent_id] !== undefined) {
that._resolve_received_state[parent_id].call();
delete that._resolve_received_state[parent_id];
}
Jonathan Frederic
Rebase fixes
r19361 }).catch(utils.reject("Couldn't resolve state request promise", true));
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 break;
case 'custom':
Jason Grout
work-in-progress for custom js serializers
r20839 this.trigger('msg:custom', msg.content.data.content, msg.buffers);
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 break;
Jonathan Frederic
handle_msg a display_model method.
r14559 case 'display':
Jason Grout
Force display_message to be processed in order...
r20452 this.state_change = this.state_change.then(function() {
that.widget_manager.display_view(msg, that);
}).catch(utils.reject('Could not process display view msg', true));
Jonathan Frederic
handle_msg a display_model method.
r14559 break;
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 }
},
Jonathan Frederic
s/apply_update/set_state
r18072 set_state: function (state) {
Jason Grout
More simplifications due to promises
r18888 var that = this;
Jonathan Frederic
Added PEP8 style comments to all of the JS code.
r14609 // Handle when a widget is updated via the python side.
Jason Grout
work-in-progress for custom js serializers
r20839 return new Promise(function(resolve, reject) {
Jason Grout
More simplifications due to promises
r18888 that.state_lock = state;
try {
Jason Grout
Fix some this vs. that errors, as well as returning some promises to wait for fulfillment
r18893 WidgetModel.__super__.set.call(that, state);
Jason Grout
More simplifications due to promises
r18888 } finally {
that.state_lock = null;
Jonathan Frederic
Add Promise support to models.
r18884 }
Jason Grout
work-in-progress for custom js serializers
r20839 resolve();
Jonathan Frederic
Rebase fixes
r19361 }).catch(utils.reject("Couldn't set model state", true));
Jonathan Frederic
Persistence API,...
r19350 },
get_state: function() {
// Get the serializable state of the model.
Jason Grout
work-in-progress for custom js serializers
r20839 // Equivalent to Backbone.Model.toJSON()
return _.clone(this.attributes);
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 },
Jason Grout
work-in-progress for custom js serializers
r20839
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 _handle_status: function (msg, callbacks) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Handle status msgs.
*
* execution_state : ('busy', 'idle', 'starting')
*/
Jonathan Frederic
Fixed *almost* all of the test-detected bugs
r14596 if (this.comm !== undefined) {
if (msg.content.execution_state ==='idle') {
// Send buffer if this message caused another message to be
// throttled.
if (this.msg_buffer !== null &&
Jonathan Frederic
Added parentheses to emphasize order of op.
r15369 (this.get('msg_throttle') || 3) === this.pending_msgs) {
Jonathan Frederic
Fixed *almost* all of the test-detected bugs
r14596 var data = {method: 'backbone', sync_method: 'update', sync_data: this.msg_buffer};
MinRK
quick review pass on javascript
r14792 this.comm.send(data, callbacks);
Jonathan Frederic
Fixed *almost* all of the test-detected bugs
r14596 this.msg_buffer = null;
} else {
--this.pending_msgs;
}
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 }
}
},
Jonathan Frederic
Change the callback logic so the order makes more sense:...
r14640 callbacks: function(view) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Create msg callbacks for a comm msg.
*/
Jonathan Frederic
Change the callback logic so the order makes more sense:...
r14640 var callbacks = this.widget_manager.callbacks(view);
if (callbacks.iopub === undefined) {
callbacks.iopub = {};
}
Jason Grout
Rewrite widget syncing...
r14639 var that = this;
callbacks.iopub.status = function (msg) {
that._handle_status(msg, callbacks);
MinRK
quick review pass on javascript
r14792 };
Jason Grout
Rewrite widget syncing...
r14639 return callbacks;
},
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546
Jonathan Frederic
Only send diff message if diff isn't corrupt....
r15279 set: function(key, val, options) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Set a value.
*/
Jonathan Frederic
Keep a running diff instead of forcing a full state update
r15280 var return_value = WidgetModel.__super__.set.apply(this, arguments);
// Backbone only remembers the diff of the most recent set()
Jonathan Frederic
Fixed typo
r15281 // operation. Calling set multiple times in a row results in a
Jonathan Frederic
Keep a running diff instead of forcing a full state update
r15280 // loss of diff information. Here we keep our own running diff.
this._buffered_state_diff = $.extend(this._buffered_state_diff, this.changedAttributes() || {});
return return_value;
Jonathan Frederic
Only send diff message if diff isn't corrupt....
r15279 },
Jason Grout
Rewrite widget syncing...
r14639 sync: function (method, model, options) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Handle sync to the back-end. Called when a model.save() is called.
*
* Make sure a comm exists.
Jason Grout
work-in-progress for custom js serializers
r20839
* Parameters
* ----------
* method : create, update, patch, delete, read
* create/update always send the full attribute set
* patch - only send attributes listed in options.attrs, and if we are queuing
* up messages, combine with previous messages that have not been sent yet
* model : the model we are syncing
* will normally be the same as `this`
* options : dict
* the `attrs` key, if it exists, gives an {attr: value} dict that should be synced,
* otherwise, sync all attributes
*
Jonathan Frederic
Ran function comment conversion tool
r19176 */
Jonathan Frederic
Change the callback logic so the order makes more sense:...
r14640 var error = options.error || function() {
console.error('Backbone sync error:', arguments);
MinRK
quick review pass on javascript
r14792 };
Jason Grout
Rewrite widget syncing...
r14639 if (this.comm === undefined) {
error();
return false;
}
Jason Grout
work-in-progress for custom js serializers
r20839 var attrs = (method === 'patch') ? options.attrs : model.get_state(options);
// the state_lock lists attributes that are currently be changed right now from a kernel message
// we don't want to send these non-changes back to the kernel, so we delete them out of attrs
// (but we only delete them if the value hasn't changed from the value stored in the state_lock
sylvain.corlay
optimization of WidgetModel.apply_update
r17839 if (this.state_lock !== null) {
var keys = Object.keys(this.state_lock);
Sylvain Corlay
state_lock loop
r17925 for (var i=0; i<keys.length; i++) {
sylvain.corlay
optimization of WidgetModel.apply_update
r17839 var key = keys[i];
if (attrs[key] === this.state_lock[key]) {
delete attrs[key];
}
Jason Grout
Rewrite widget syncing...
r14639 }
}
Jason Grout
work-in-progress for custom js serializers
r20839
Jonathan Frederic
Fixed context errors and a couple of typos to get the tests working again
r14686 if (_.size(attrs) > 0) {
Jonathan Frederic
Fixed bug in throttling code.
r14741
// If this message was sent via backbone itself, it will not
// have any callbacks. It's important that we create callbacks
// so we can listen for status messages, etc...
var callbacks = options.callbacks || this.callbacks();
// Check throttle.
Jonathan Frederic
Added parentheses to emphasize order of op.
r15369 if (this.pending_msgs >= (this.get('msg_throttle') || 3)) {
Jonathan Frederic
Change the callback logic so the order makes more sense:...
r14640 // The throttle has been exceeded, buffer the current msg so
// it can be sent once the kernel has finished processing
// some of the existing messages.
// Combine updates if it is a 'patch' sync, otherwise replace updates
switch (method) {
case 'patch':
Jonathan Frederic
Prefer JQuery to Underscore
r14662 this.msg_buffer = $.extend(this.msg_buffer || {}, attrs);
Jonathan Frederic
Change the callback logic so the order makes more sense:...
r14640 break;
case 'update':
Jonathan Frederic
'create' should be handled in sync
r14661 case 'create':
Jonathan Frederic
Change the callback logic so the order makes more sense:...
r14640 this.msg_buffer = attrs;
break;
default:
error();
return false;
}
this.msg_buffer_callbacks = callbacks;
} else {
// We haven't exceeded the throttle, send the message like
Jonathan Frederic
Fixed bug in throttling code.
r14741 // normal.
Jason Grout
work-in-progress for custom js serializers
r20839 this.send_sync_message(attrs, callbacks);
Jason Grout
Increment the pending_msgs counter immediately to avoid race conditions that send more messages
r20852 this.pending_msgs++;
Jonathan Frederic
Change the callback logic so the order makes more sense:...
r14640 }
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 }
// Since the comm is a one-way communication, assume the message
Jason Grout
Rewrite widget syncing...
r14639 // arrived. Don't call success since we don't have a model back from the server
// this means we miss out on the 'sync' event.
Jonathan Frederic
Keep a running diff instead of forcing a full state update
r15280 this._buffered_state_diff = {};
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 },
Jason Grout
make the saving to python a method of the model, called with callbacks...
r14618
Jason Grout
work-in-progress for custom js serializers
r20839 send_sync_message: function(attrs, callbacks) {
// prepare and send a comm message syncing attrs
Jonathan Frederic
Done with major changes,...
r17199 var that = this;
Jason Grout
work-in-progress for custom js serializers
r20839 // first, build a state dictionary with key=the attribute and the value
// being the value or the promise of the serialized value
Jason Grout
Change custom serialization to use custom models, rather than transmitting the serializer name across the wire...
r20935 var serializers = this.constructor.serializers;
if (serializers) {
for (k in attrs) {
if (serializers[k] && serializers[k].serialize) {
attrs[k] = (serializers[k].serialize)(attrs[k], this);
Jason Grout
work-in-progress for custom js serializers
r20839 }
Jason Grout
Change custom serialization to use custom models, rather than transmitting the serializer name across the wire...
r20935 }
Jason Grout
work-in-progress for custom js serializers
r20839 }
Jason Grout
Change custom serialization to use custom models, rather than transmitting the serializer name across the wire...
r20935 utils.resolve_promises_dict(attrs).then(function(state) {
Jason Grout
work-in-progress for custom js serializers
r20839 // get binary values, then send
var keys = Object.keys(state);
var buffers = [];
var buffer_keys = [];
for (var i=0; i<keys.length; i++) {
var key = keys[i];
var value = state[key];
if (value.buffer instanceof ArrayBuffer
|| value instanceof ArrayBuffer) {
buffers.push(value);
buffer_keys.push(key);
delete state[key];
}
}
that.comm.send({method: 'backbone', sync_data: state, buffer_keys: buffer_keys}, callbacks, {}, buffers);
Jason Grout
Simplify error handling for errors in sending sync messages from js
r20863 }).catch(function(error) {
that.pending_msgs--;
return (utils.reject("Couldn't send widget sync message", true))(error);
});
Jason Grout
work-in-progress for custom js serializers
r20839 },
save_changes: function(callbacks) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
Jason Grout
work-in-progress for custom js serializers
r20839 * Push this model's state to the back-end
*
* This invokes a Backbone.Sync.
Jonathan Frederic
Ran function comment conversion tool
r19176 */
Jason Grout
work-in-progress for custom js serializers
r20839 this.save(this._buffered_state_diff, {patch: true, callbacks: callbacks});
Jonathan Frederic
Many checks off the todo list, test fixes
r14583 },
Sylvain Corlay
on_atomic_change -> on_some_change
r18008 on_some_change: function(keys, callback, context) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* on_some_change(["key1", "key2"], foo, context) differs from
* on("change:key1 change:key2", foo, context).
* If the widget attributes key1 and key2 are both modified,
* the second form will result in foo being called twice
* while the first will call foo only once.
*/
sylvain.corlay
Added on_bulk_change method in WidgetModel
r17838 this.on('change', function() {
if (keys.some(this.hasChanged, this)) {
callback.apply(context);
}
}, this);
Jason Grout
work-in-progress for custom js serializers
r20839 },
Jason Grout
Fix serialization of models from js -> kernel
r20929
toJSON: function(options) {
/**
* Serialize the model. See the types.js deserialization function
* and the kernel-side serializer/deserializer
*/
return "IPY_MODEL_"+this.id;
}
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 });
Jonathan Frederic
Fix imports of "modules",...
r17202 widgetmanager.WidgetManager.register_widget_model('WidgetModel', WidgetModel);
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546
Jonathan Frederic
s/BaseWidgetView/WidgetView and s/WidgetView/DOMWidgetView
r14564 var WidgetView = Backbone.View.extend({
Jonathan Frederic
un-nest options.options
r14565 initialize: function(parameters) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Public constructor.
*/
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 this.model.on('change',this.update,this);
Jonathan Frederic
Bubble event and implement logic in CodeCell
r19572
// Bubble the comm live events.
Jonathan Frederic
Make sure comm-dead is applied to the top widget view class...
r19566 this.model.on('comm:live', function() {
Jonathan Frederic
Bubble event and implement logic in CodeCell
r19572 this.trigger('comm:live', this);
Jonathan Frederic
Make sure comm-dead is applied to the top widget view class...
r19566 }, this);
this.model.on('comm:dead', function() {
Jonathan Frederic
Bubble event and implement logic in CodeCell
r19572 this.trigger('comm:dead', this);
Jonathan Frederic
Make sure comm-dead is applied to the top widget view class...
r19566 }, this);
Jonathan Frederic
un-nest options.options
r14565 this.options = parameters.options;
Sylvain Corlay
once-displayed
r17270 this.on('displayed', function() {
this.is_displayed = true;
}, this);
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 },
update: function(){
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Triggered on model change.
*
* Update view to be consistent with this.model
*/
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 },
Jonathan Frederic
Got containers and mutlicontainers working! Yay
r14598 create_child_view: function(child_model, options) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Create and promise that resolves to a child view of a given model
*/
Jonathan Frederic
Add Promise support to models.
r18884 var that = this;
Jason Grout
More simplifications due to promises
r18888 options = $.extend({ parent: this }, options || {});
Jason Grout
Fix two calls to utils.reject (misplaced parens)
r20855 return this.model.widget_manager.create_view(child_model, options).catch(utils.reject("Couldn't create child view", true));
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 },
callbacks: function(){
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Create msg callbacks for a comm msg.
*/
Jonathan Frederic
Change the callback logic so the order makes more sense:...
r14640 return this.model.callbacks(this);
Jonathan Frederic
Added missing comma
r14560 },
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546
render: function(){
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Render the view.
*
* By default, this is only called the first time the view is created
*/
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 },
Jonathan Frederic
Added PEP8 style comments to all of the JS code.
r14609
Jason Grout
work-in-progress for custom js serializers
r20839 send: function (content, buffers) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Send a custom msg associated with this view.
*/
Jason Grout
work-in-progress for custom js serializers
r20839 this.model.send(content, this.callbacks(), buffers);
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 },
touch: function () {
Jason Grout
Rewrite widget syncing...
r14639 this.model.save_changes(this.callbacks());
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 },
Sylvain Corlay
once-displayed
r17270
Sylvain Corlay
renaming once_displayed into after_displayed
r17329 after_displayed: function (callback, context) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Calls the callback right away is the view is already displayed
* otherwise, register the callback to the 'displayed' event.
*/
Sylvain Corlay
once-displayed
r17270 if (this.is_displayed) {
callback.apply(context);
} else {
this.on('displayed', callback, context);
}
Jonathan Frederic
Persistence API,...
r19350 },
remove: function () {
// Raise a remove event when the view is removed.
WidgetView.__super__.remove.apply(this, arguments);
this.trigger('remove');
Nicholas Bollweg (Nick)
moving, checking MathJax typesetting to WidgetView...
r19194 }
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 });
Jonathan Frederic
Added PEP8 style comments to all of the JS code.
r14609
Jonathan Frederic
s/BaseWidgetView/WidgetView and s/WidgetView/DOMWidgetView
r14564 var DOMWidgetView = WidgetView.extend({
Sylvain Corlay
making the use of options explicit
r17448 initialize: function (parameters) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Public constructor
*/
Sylvain Corlay
making the use of options explicit
r17448 DOMWidgetView.__super__.initialize.apply(this, [parameters]);
sylvain.corlay
Partial updates of css and visible + simplification of widget_container
r17347 this.model.on('change:visible', this.update_visible, this);
this.model.on('change:_css', this.update_css, this);
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727
Jonathan Frederic
Remove add/remove class methods,...
r17720 this.model.on('change:_dom_classes', function(model, new_classes) {
Jonathan Frederic
Fixed rebase bugs and other bugs.
r17731 var old_classes = model.previous('_dom_classes');
Jonathan Frederic
Remove add/remove class methods,...
r17720 this.update_classes(old_classes, new_classes);
}, this);
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727
Jonathan Frederic
s/fore_color/color...
r17860 this.model.on('change:color', function (model, value) {
Jonathan Frederic
Initial crack at using specific traits for styling.
r17722 this.update_attr('color', value); }, this);
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727
Jonathan Frederic
s/fore_color/color...
r17860 this.model.on('change:background_color', function (model, value) {
Jonathan Frederic
Initial crack at using specific traits for styling.
r17722 this.update_attr('background', value); }, this);
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727
Jonathan Frederic
Initial crack at using specific traits for styling.
r17722 this.model.on('change:width', function (model, value) {
this.update_attr('width', value); }, this);
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727
Jonathan Frederic
Initial crack at using specific traits for styling.
r17722 this.model.on('change:height', function (model, value) {
this.update_attr('height', value); }, this);
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727
Jonathan Frederic
Initial crack at using specific traits for styling.
r17722 this.model.on('change:border_color', function (model, value) {
this.update_attr('border-color', value); }, this);
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727
Jonathan Frederic
Initial crack at using specific traits for styling.
r17722 this.model.on('change:border_width', function (model, value) {
this.update_attr('border-width', value); }, this);
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727
Jonathan Frederic
Initial crack at using specific traits for styling.
r17722 this.model.on('change:border_style', function (model, value) {
this.update_attr('border-style', value); }, this);
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727
Jonathan Frederic
Initial crack at using specific traits for styling.
r17722 this.model.on('change:font_style', function (model, value) {
this.update_attr('font-style', value); }, this);
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727
Jonathan Frederic
Initial crack at using specific traits for styling.
r17722 this.model.on('change:font_weight', function (model, value) {
this.update_attr('font-weight', value); }, this);
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727
Jonathan Frederic
Initial crack at using specific traits for styling.
r17722 this.model.on('change:font_size', function (model, value) {
Jonathan Frederic
Address problems found in in-person review
r17947 this.update_attr('font-size', this._default_px(value)); }, this);
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727
Jonathan Frederic
Initial crack at using specific traits for styling.
r17722 this.model.on('change:font_family', function (model, value) {
this.update_attr('font-family', value); }, this);
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727
this.model.on('change:padding', function (model, value) {
this.update_attr('padding', value); }, this);
this.model.on('change:margin', function (model, value) {
Jonathan Frederic
Address problems found in in-person review
r17947 this.update_attr('margin', this._default_px(value)); }, this);
this.model.on('change:border_radius', function (model, value) {
this.update_attr('border-radius', this._default_px(value)); }, this);
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727
Sylvain Corlay
removing timout
r17386 this.after_displayed(function() {
this.update_visible(this.model, this.model.get("visible"));
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727 this.update_classes([], this.model.get('_dom_classes'));
Jonathan Frederic
Make sure DOMWidget _css is set after basic style traits
r18177
Jonathan Frederic
s/fore_color/color...
r17860 this.update_attr('color', this.model.get('color'));
this.update_attr('background', this.model.get('background_color'));
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727 this.update_attr('width', this.model.get('width'));
this.update_attr('height', this.model.get('height'));
this.update_attr('border-color', this.model.get('border_color'));
this.update_attr('border-width', this.model.get('border_width'));
this.update_attr('border-style', this.model.get('border_style'));
this.update_attr('font-style', this.model.get('font_style'));
this.update_attr('font-weight', this.model.get('font_weight'));
Jonathan Frederic
Fixed pre-display "pixel-like" widget attribute parsing
r19765 this.update_attr('font-size', this._default_px(this.model.get('font_size')));
Jonathan Frederic
Fix some bugs found by the widget examples,...
r17727 this.update_attr('font-family', this.model.get('font_family'));
this.update_attr('padding', this.model.get('padding'));
Jonathan Frederic
Fixed pre-display "pixel-like" widget attribute parsing
r19765 this.update_attr('margin', this._default_px(this.model.get('margin')));
this.update_attr('border-radius', this._default_px(this.model.get('border_radius')));
Jonathan Frederic
Make sure DOMWidget _css is set after basic style traits
r18177
this.update_css(this.model, this.model.get("_css"));
Sylvain Corlay
removing timout
r17386 }, this);
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 },
Sylvain Corlay
removing timout
r17386
Jonathan Frederic
Address problems found in in-person review
r17947 _default_px: function(value) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Makes browser interpret a numerical string as a pixel value.
*/
Jason Grout
Handle case when pixel values are undefined or null
r20916 if (value && /^\d+\.?(\d+)?$/.test(value.trim())) {
Jonathan Frederic
Address problems found in in-person review
r17947 return value.trim() + 'px';
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 }
Jonathan Frederic
Address problems found in in-person review
r17947 return value;
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 },
Jonathan Frederic
Initial crack at using specific traits for styling.
r17722 update_attr: function(name, value) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Set a css attr of the widget view.
*/
Jonathan Frederic
Initial crack at using specific traits for styling.
r17722 this.$el.css(name, value);
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 },
Sylvain Corlay
removing timout
r17386
sylvain.corlay
Partial updates of css and visible + simplification of widget_container
r17347 update_visible: function(model, value) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Update visibility
*/
Jason Grout
Add None as a widget visible value to allow for visiblity: hidden...
r19186 switch(value) {
case null: // python None
this.$el.show().css('visibility', 'hidden'); break;
case false:
this.$el.hide(); break;
case true:
this.$el.show().css('visibility', ''); break;
}
sylvain.corlay
Partial updates of css and visible + simplification of widget_container
r17347 },
update_css: function (model, css) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Update the css styling of this view.
*/
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 if (css === undefined) {return;}
Jonathan Frederic
Reverted strange change that I don't remember making to update method.
r17177 for (var i = 0; i < css.length; i++) {
Jonathan Frederic
Removed for () loops where necessary. Replaced with _.each
r14664 // Apply the css traits to all elements that match the selector.
Jonathan Frederic
Reverted strange change that I don't remember making to update method.
r17177 var selector = css[i][0];
var elements = this._get_selector_element(selector);
Jonathan Frederic
Removed for () loops where necessary. Replaced with _.each
r14664 if (elements.length > 0) {
Jonathan Frederic
Reverted strange change that I don't remember making to update method.
r17177 var trait_key = css[i][1];
var trait_value = css[i][2];
elements.css(trait_key ,trait_value);
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 }
Jonathan Frederic
Reverted strange change that I don't remember making to update method.
r17177 }
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 },
Jonathan Frederic
Added Bootstrap specific classes,...
r17728 update_classes: function (old_classes, new_classes, $el) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Update the DOM classes applied to an element, default to this.$el.
*/
Jonathan Frederic
Added Bootstrap specific classes,...
r17728 if ($el===undefined) {
$el = this.$el;
}
Jason Grout
reimplement the add/remove class logic to not use do_diff and remove do_diff
r19064 _.difference(old_classes, new_classes).map(function(c) {$el.removeClass(c);})
_.difference(new_classes, old_classes).map(function(c) {$el.addClass(c);})
Jonathan Frederic
Remove add/remove class methods,...
r17720 },
Jonathan Frederic
Added Bootstrap specific classes,...
r17728 update_mapped_classes: function(class_map, trait_name, previous_trait_value, $el) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Update the DOM classes applied to the widget based on a single
* trait's value.
*
* Given a trait value classes map, this function automatically
* handles applying the appropriate classes to the widget element
* and removing classes that are no longer valid.
*
* Parameters
* ----------
* class_map: dictionary
* Dictionary of trait values to class lists.
* Example:
* {
* success: ['alert', 'alert-success'],
* info: ['alert', 'alert-info'],
* warning: ['alert', 'alert-warning'],
* danger: ['alert', 'alert-danger']
* };
* trait_name: string
* Name of the trait to check the value of.
* previous_trait_value: optional string, default ''
* Last trait value
* $el: optional jQuery element handle, defaults to this.$el
* Element that the classes are applied to.
*/
Jonathan Frederic
Added Bootstrap specific classes,...
r17728 var key = previous_trait_value;
if (key === undefined) {
key = this.model.previous(trait_name);
}
var old_classes = class_map[key] ? class_map[key] : [];
key = this.model.get(trait_name);
var new_classes = class_map[key] ? class_map[key] : [];
this.update_classes(old_classes, new_classes, $el || this.$el);
},
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 _get_selector_element: function (selector) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Get the elements via the css selector.
*/
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 var elements;
MinRK
quick review pass on javascript
r14792 if (!selector) {
Jason Grout
Remove $el_to_style from the widget javascript code; '' now defaults to this.$el...
r17420 elements = this.$el;
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 } else {
Jason Grout
Remove $el_to_style from the widget javascript code; '' now defaults to this.$el...
r17420 elements = this.$el.find(selector).addBack(selector);
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 }
return elements;
},
Nicholas Bollweg (Nick)
moving typeset to DOMWidgetView
r19197
Nicholas Bollweg (Nick)
accept node or selection
r19198 typeset: function(element, text){
Nicholas Bollweg (Nick)
moving typeset to utils, usage in cell and outputarea
r19235 utils.typeset.apply(null, arguments);
Nicholas Bollweg (Nick)
moving typeset to DOMWidgetView
r19197 },
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 });
Jason Grout
Refactor the do_diff and manual child view lists into a separate ViewList object
r18996
var ViewList = function(create_view, remove_view, context) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
Jonathan Frederic
Manual fixes
r19177 * - create_view and remove_view are default functions called when adding or removing views
* - create_view takes a model and returns a view or a promise for a view for that model
* - remove_view takes a view and destroys it (including calling `view.remove()`)
* - each time the update() function is called with a new list, the create and remove
Jonathan Frederic
Ran function comment conversion tool
r19176 * callbacks will be called in an order so that if you append the views created in the
* create callback and remove the views in the remove callback, you will duplicate
* the order of the list.
Jonathan Frederic
Manual fixes
r19177 * - the remove callback defaults to just removing the view (e.g., pass in null for the second parameter)
* - the context defaults to the created ViewList. If you pass another context, the create and remove
Jonathan Frederic
Ran function comment conversion tool
r19176 * will be called in that context.
*/
Jason Grout
Refactor the do_diff and manual child view lists into a separate ViewList object
r18996
this.initialize.apply(this, arguments);
Jonathan Frederic
Implement view logic in selection containers.
r19023 };
Jason Grout
Refactor the do_diff and manual child view lists into a separate ViewList object
r18996
_.extend(ViewList.prototype, {
initialize: function(create_view, remove_view, context) {
this._handler_context = context || this;
this._models = [];
Jason Grout
Update viewlists to store a list of promises for views
r19377 this.views = []; // list of promises for views
Jason Grout
Refactor the do_diff and manual child view lists into a separate ViewList object
r18996 this._create_view = create_view;
Jason Grout
Missing semicolon
r19002 this._remove_view = remove_view || function(view) {view.remove();};
Jason Grout
Refactor the do_diff and manual child view lists into a separate ViewList object
r18996 },
update: function(new_models, create_view, remove_view, context) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* the create_view, remove_view, and context arguments override the defaults
* specified when the list is created.
Jason Grout
Update viewlists to store a list of promises for views
r19377 * after this function, the .views attribute is a list of promises for views
* if you want to perform some action on the list of views, do something like
* `Promise.all(myviewlist.views).then(function(views) {...});`
Jonathan Frederic
Ran function comment conversion tool
r19176 */
Jason Grout
Refactor the do_diff and manual child view lists into a separate ViewList object
r18996 var remove = remove_view || this._remove_view;
var create = create_view || this._create_view;
Matthias Bussonnier
Some code cleanup in javascript and python...
r19739 context = context || this._handler_context;
Jason Grout
Update viewlists to store a list of promises for views
r19377 var i = 0;
// first, skip past the beginning of the lists if they are identical
for (; i < new_models.length; i++) {
if (i >= this._models.length || new_models[i] !== this._models[i]) {
break;
Jason Grout
Refactor the do_diff and manual child view lists into a separate ViewList object
r18996 }
Jason Grout
Update viewlists to store a list of promises for views
r19377 }
var first_removed = i;
// Remove the non-matching items from the old list.
var removed = this.views.splice(first_removed, this.views.length-first_removed);
for (var j = 0; j < removed.length; j++) {
removed[j].then(function(view) {
remove.call(context, view)
Jason Grout
Refactor the do_diff and manual child view lists into a separate ViewList object
r18996 });
Jason Grout
Update viewlists to store a list of promises for views
r19377 }
// Add the rest of the new list items.
for (; i < new_models.length; i++) {
this.views.push(Promise.resolve(create.call(context, new_models[i])));
}
// make a copy of the input array
this._models = new_models.slice();
Jason Grout
Refactor the do_diff and manual child view lists into a separate ViewList object
r18996 },
remove: function() {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* removes every view in the list; convenience function for `.update([])`
* that should be faster
* returns a promise that resolves after this removal is done
*/
Jason Grout
Refactor the do_diff and manual child view lists into a separate ViewList object
r18996 var that = this;
Jason Grout
Missing return...
r19407 return Promise.all(this.views).then(function(views) {
Jason Grout
remove obsolete optimization
r19087 for (var i = 0; i < that.views.length; i++) {
Jason Grout
Update viewlists to store a list of promises for views
r19377 that._remove_view.call(that._handler_context, views[i]);
Jonathan Frederic
Implement view logic in selection containers.
r19023 }
Jason Grout
Refactor the do_diff and manual child view lists into a separate ViewList object
r18996 that.views = [];
Jason Grout
Update viewlists to store a list of promises for views
r19377 that._models = [];
Jason Grout
Refactor the do_diff and manual child view lists into a separate ViewList object
r18996 });
},
});
Jonathan Frederic
Fix all the tests
r17216 var widget = {
Sylvain Corlay
Move _unpack_models to widget.js and widget serialization to widget.py
r21157 'unpack_models': unpack_models,
Jonathan Frederic
Almost done!...
r17198 'WidgetModel': WidgetModel,
'WidgetView': WidgetView,
'DOMWidgetView': DOMWidgetView,
Jason Grout
Refactor the do_diff and manual child view lists into a separate ViewList object
r18996 'ViewList': ViewList,
Jonathan Frederic
Almost done!...
r17198 };
Jonathan Frederic
Fix all the tests
r17216
// For backwards compatability.
$.extend(IPython, widget);
return widget;
Jonathan Frederic
renamed: basic_widgets.js -> init.js...
r14546 });