diff --git a/IPython/html/static/widgets/js/widget.js b/IPython/html/static/widgets/js/widget.js index 1e785d6..3deeea3 100644 --- a/IPython/html/static/widgets/js/widget.js +++ b/IPython/html/static/widgets/js/widget.js @@ -661,10 +661,9 @@ define(["widgets/js/manager", _.extend(ViewList.prototype, { initialize: function(create_view, remove_view, context) { - this.state_change = Promise.resolve(); this._handler_context = context || this; this._models = []; - this.views = []; + this.views = []; // list of promises for views this._create_view = create_view; this._remove_view = remove_view || function(view) {view.remove();}; }, @@ -673,42 +672,36 @@ define(["widgets/js/manager", /** * the create_view, remove_view, and context arguments override the defaults * specified when the list is created. - * returns a promise that resolves after this update is done + * 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) {...});` */ var remove = remove_view || this._remove_view; var create = create_view || this._create_view; - if (create === undefined || remove === undefined){ - console.error("Must define a create a remove function"); - } var context = context || this._handler_context; - var added_views = []; - var that = this; - this.state_change = this.state_change.then(function() { - var i; - // first, skip past the beginning of the lists if they are identical - for (i = 0; i < new_models.length; i++) { - if (i >= that._models.length || new_models[i] !== that._models[i]) { - break; - } - } - var first_removed = i; - // Remove the non-matching items from the old list. - for (var j = first_removed; j < that._models.length; j++) { - remove.call(context, that.views[j]); - } - - // Add the rest of the new list items. - for (; i < new_models.length; i++) { - added_views.push(create.call(context, new_models[i])); + 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; } - // make a copy of the input array - that._models = new_models.slice(); - return Promise.all(added_views).then(function(added) { - Array.prototype.splice.apply(that.views, [first_removed, that.views.length].concat(added)); - return that.views; + } + + 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) }); - }); - return this.state_change; + } + + // 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(); }, remove: function() { @@ -718,14 +711,13 @@ define(["widgets/js/manager", * returns a promise that resolves after this removal is done */ var that = this; - this.state_change = this.state_change.then(function() { + return Promise.all(this.views).then(function(views) { for (var i = 0; i < that.views.length; i++) { - that._remove_view.call(that._handler_context, that.views[i]); + that._remove_view.call(that._handler_context, views[i]); } - that._models = []; that.views = []; + that._models = []; }); - return this.state_change; }, });