diff --git a/IPython/html/static/services/kernels/comm.js b/IPython/html/static/services/kernels/comm.js index 91f3dc826..f25517b82 100644 --- a/IPython/html/static/services/kernels/comm.js +++ b/IPython/html/static/services/kernels/comm.js @@ -65,20 +65,40 @@ define([ CommManager.prototype.comm_open = function (msg) { var content = msg.content; - var f = this.targets[content.target_name]; - if (f === undefined) { - console.log("No such target registered: ", content.target_name); - console.log("Available targets are: ", this.targets); - return; - } - var comm = new Comm(content.target_name, content.comm_id); - this.register_comm(comm); - try { - f(comm, msg); - } catch (e) { - console.log("Exception opening new comm:", e, e.stack, msg); - comm.close(); - this.unregister_comm(comm); + var that = this; + + var instantiate_comm = function(target) { + var comm = new Comm(content.target_name, content.comm_id); + that.register_comm(comm); + try { + target(comm, msg); + } catch (e) { + console.log("Exception opening new comm:", e, e.stack, msg); + comm.close(); + that.unregister_comm(comm); + } + }; + + if (content.target_module) { + // Load requirejs module for comm target + require([content.target_module], function(mod) { + var target = mod[content.target_name]; + if (target !== undefined) { + instantiate_comm(target) + } else { + console.log("Comm target " + content.target_name + + " not found in module " + content.target_module); + } + }, function(err) { console.log(err); }); + } else { + // No requirejs module specified: look for target in registry + var f = this.targets[content.target_name]; + if (f === undefined) { + console.log("No such target registered: ", content.target_name); + console.log("Available targets are: ", this.targets); + return; + } + instantiate_comm(f) } }; diff --git a/IPython/html/static/widgets/js/manager.js b/IPython/html/static/widgets/js/manager.js index dd3472c52..944effd5a 100644 --- a/IPython/html/static/widgets/js/manager.js +++ b/IPython/html/static/widgets/js/manager.js @@ -188,13 +188,33 @@ define([ WidgetManager.prototype._handle_comm_open = function (comm, msg) { // Handle when a comm is opened. var that = this; - var model_id = comm.comm_id; + + var instantiate_model = function(ModelType) { + var model_id = comm.comm_id; + var widget_model = new ModelType(that, model_id, comm); + widget_model.on('comm:close', function () { + delete that._models[model_id]; + }); + that._models[model_id] = widget_model; + }; + var widget_type_name = msg.content.data.model_name; - var widget_model = new WidgetManager._model_types[widget_type_name](this, model_id, comm); - widget_model.on('comm:close', function () { - delete that._models[model_id]; - }); - this._models[model_id] = widget_model; + var widget_module = msg.content.data.model_module; + + if (widget_module) { + // Load the module containing the widget model + require([widget_module], function(mod) { + if (mod[widget_type_name]) { + instantiate_model(mod[widget_type_name]); + } else { + console.log("Error creating widget model: " + widget_type_name + + " not found in " + widget_module); + } + }, function(err) { console.log(err); }); + } else { + // No module specified, load from the global models registry + instantiate_model(WidgetManager._model_types[widget_type_name]); + } }; // Backwards compatability. diff --git a/IPython/html/widgets/widget.py b/IPython/html/widgets/widget.py index 86e85aa82..f1571eab4 100644 --- a/IPython/html/widgets/widget.py +++ b/IPython/html/widgets/widget.py @@ -98,6 +98,8 @@ class Widget(LoggingConfigurable): #------------------------------------------------------------------------- # Traits #------------------------------------------------------------------------- + _model_module = Unicode(None, allow_none=True, help="""A requirejs module name + in which to find _model_name. If empty, look in the global registry.""") _model_name = Unicode('WidgetModel', help="""Name of the backbone model registered in the front-end to create and sync this widget with.""") _view_module = Unicode(help="""A requirejs module in which to find _view_name. @@ -142,7 +144,9 @@ class Widget(LoggingConfigurable): def open(self): """Open a comm to the frontend if one isn't already open.""" if self.comm is None: - args = dict(target_name='ipython.widget', data={ 'model_name': self._model_name }) + args = dict(target_name='ipython.widget', + data={'model_name': self._model_name, + 'model_module': self._model_module}) if self._model_id is not None: args['comm_id'] = self._model_id self.comm = Comm(**args)