Merge pull request #6494 from takluyver/widget-comm-require

Allow widget views to be loaded from require modules
Jonathan Frederic 12 years ago
commit 79670e8afb

@ -7,7 +7,7 @@ define([
"jquery",
"base/js/namespace"
], function (_, Backbone, $, IPython) {
"use strict";
//--------------------------------------------------------------------
// WidgetManager class
//--------------------------------------------------------------------
@ -52,15 +52,14 @@ define([
console.log("Could not determine where the display" +
" message was from. Widget will not be displayed");
} else {
var view = this.create_view(model, {cell: cell});
if (view === null) {
console.error("View creation failed", model);
}
this._handle_display_view(view);
if (cell.widget_subarea) {
cell.widget_subarea.append(view.$el);
}
view.trigger('displayed');
var that = this;
this.create_view(model, {cell: cell, callback: function(view) {
that._handle_display_view(view);
if (cell.widget_subarea) {
cell.widget_subarea.append(view.$el);
}
view.trigger('displayed');
}});
}
};
@ -78,28 +77,43 @@ define([
}
}
};
WidgetManager.prototype.create_view = function(model, options, view) {
WidgetManager.prototype.create_view = function(model, options) {
// Creates a view for a particular model.
var view_name = model.get('_view_name');
var ViewType = WidgetManager._view_types[view_name];
if (ViewType) {
// If a view is passed into the method, use that view's cell as
// the cell for the view that is created.
options = options || {};
if (view !== undefined) {
options.cell = view.options.cell;
var view_mod = model.get('_view_module');
var errback = options.errback || function(err) {console.log(err);};
var instantiate_view = function(ViewType) {
if (ViewType) {
// If a view is passed into the method, use that view's cell as
// the cell for the view that is created.
options = options || {};
if (options.parent !== undefined) {
options.cell = options.parent.options.cell;
}
// Create and render the view...
var parameters = {model: model, options: options};
var view = new ViewType(parameters);
view.render();
model.on('destroy', view.remove, view);
options.callback(view);
} else {
errback({unknown_view: true, view_name: view_name,
view_module: view_mod});
}
};
// Create and render the view...
var parameters = {model: model, options: options};
view = new ViewType(parameters);
view.render();
model.on('destroy', view.remove, view);
return view;
if (view_mod) {
require([view_mod], function(module) {
instantiate_view(module[view_name]);
}, errback);
} else {
instantiate_view(WidgetManager._view_types[view_name]);
}
return null;
};
WidgetManager.prototype.get_msg_cell = function (msg_id) {

@ -317,18 +317,21 @@ define(["widgets/js/manager",
// TODO: this is hacky, and makes the view depend on this cell attribute and widget manager behavior
// it would be great to have the widget manager add the cell metadata
// to the subview without having to add it here.
options = $.extend({ parent: this }, options || {});
var child_view = this.model.widget_manager.create_view(child_model, options, this);
// Associate the view id with the model id.
if (this.child_model_views[child_model.id] === undefined) {
this.child_model_views[child_model.id] = [];
}
this.child_model_views[child_model.id].push(child_view.id);
var that = this;
var old_callback = options.callback || function(view) {};
options = $.extend({ parent: this, callback: function(child_view) {
// Associate the view id with the model id.
if (that.child_model_views[child_model.id] === undefined) {
that.child_model_views[child_model.id] = [];
}
that.child_model_views[child_model.id].push(child_view.id);
// Remember the view by id.
this.child_views[child_view.id] = child_view;
return child_view;
// Remember the view by id.
that.child_views[child_view.id] = child_view;
old_callback(child_view);
}}, options || {});
this.model.widget_manager.create_view(child_model, options);
},
pop_child_view: function(child_model) {

@ -74,13 +74,15 @@ define([
add_child_model: function(model) {
// Called when a model is added to the children list.
var view = this.create_child_view(model);
this.$box.append(view.$el);
var that = this;
this.create_child_view(model, {callback: function(view) {
that.$box.append(view.$el);
// Trigger the displayed event of the child view.
this.after_displayed(function() {
view.trigger('displayed');
});
// Trigger the displayed event of the child view.
that.after_displayed(function() {
view.trigger('displayed');
});
}});
},
});

@ -81,7 +81,6 @@ define([
add_child_model: function(model) {
// Called when a child is added to children list.
var view = this.create_child_view(model);
var index = this.containers.length;
var uuid = utils.uuid();
var accordion_group = $('<div />')
@ -114,15 +113,18 @@ define([
var container_index = this.containers.push(accordion_group) - 1;
accordion_group.container_index = container_index;
this.model_containers[model.id] = accordion_group;
accordion_inner.append(view.$el);
this.create_child_view(model, {callback: function(view) {
accordion_inner.append(view.$el);
this.update();
this.update_titles();
that.update();
that.update_titles();
// Trigger the displayed event of the child view.
this.after_displayed(function() {
view.trigger('displayed');
});
// Trigger the displayed event of the child view.
that.after_displayed(function() {
view.trigger('displayed');
});
}});
},
});
@ -176,7 +178,6 @@ define([
add_child_model: function(model) {
// Called when a child is added to children list.
var view = this.create_child_view(model);
var index = this.containers.length;
var uuid = utils.uuid();
@ -184,34 +185,37 @@ define([
var tab = $('<li />')
.css('list-style-type', 'none')
.appendTo(this.$tabs);
view.parent_tab = tab;
var tab_text = $('<a />')
.attr('href', '#' + uuid)
.attr('data-toggle', 'tab')
.text('Page ' + index)
.appendTo(tab)
.click(function (e) {
// Calling model.set will trigger all of the other views of the
// model to update.
that.model.set("selected_index", index, {updated_view: this});
that.touch();
that.select_page(index);
this.create_child_view(model, {callback: function(view) {
view.parent_tab = tab;
var tab_text = $('<a />')
.attr('href', '#' + uuid)
.attr('data-toggle', 'tab')
.text('Page ' + index)
.appendTo(tab)
.click(function (e) {
// Calling model.set will trigger all of the other views of the
// model to update.
that.model.set("selected_index", index, {updated_view: that});
that.touch();
that.select_page(index);
});
tab.tab_text_index = that.containers.push(tab_text) - 1;
var contents_div = $('<div />', {id: uuid})
.addClass('tab-pane')
.addClass('fade')
.append(view.$el)
.appendTo(that.$tab_contents);
view.parent_container = contents_div;
// Trigger the displayed event of the child view.
that.after_displayed(function() {
view.trigger('displayed');
});
tab.tab_text_index = this.containers.push(tab_text) - 1;
var contents_div = $('<div />', {id: uuid})
.addClass('tab-pane')
.addClass('fade')
.append(view.$el)
.appendTo(this.$tab_contents);
view.parent_container = contents_div;
// Trigger the displayed event of the child view.
this.after_displayed(function() {
view.trigger('displayed');
});
}});
},
update: function(options) {

@ -100,6 +100,8 @@ class Widget(LoggingConfigurable):
#-------------------------------------------------------------------------
_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.
If empty, look in the global registry.""", sync=True)
_view_name = Unicode(None, allow_none=True, help="""Default view registered in the front-end
to use to represent the widget.""", sync=True)
comm = Instance('IPython.kernel.comm.Comm')

Loading…
Cancel
Save