Show More
@@ -62,7 +62,7 b' define([' | |||||
62 | dummy.replaceWith(view.$el); |
|
62 | dummy.replaceWith(view.$el); | |
63 | view.trigger('displayed'); |
|
63 | view.trigger('displayed'); | |
64 | return view; |
|
64 | return view; | |
65 |
} |
|
65 | }).catch(utils.reject('Could not display view', true)); | |
66 | } |
|
66 | } | |
67 | }; |
|
67 | }; | |
68 |
|
68 | |||
@@ -103,7 +103,7 b' define([' | |||||
103 | view.listenTo(model, 'destroy', view.remove); |
|
103 | view.listenTo(model, 'destroy', view.remove); | |
104 | view.render(); |
|
104 | view.render(); | |
105 | return view; |
|
105 | return view; | |
106 |
} |
|
106 | }).catch(utils.reject("Couldn't create a view for model id '" + String(model.id) + "'", true)); | |
107 | }); |
|
107 | }); | |
108 | return model.state_change; |
|
108 | return model.state_change; | |
109 | }; |
|
109 | }; | |
@@ -178,7 +178,7 b' define([' | |||||
178 | return this.create_model({ |
|
178 | return this.create_model({ | |
179 | model_name: msg.content.data.model_name, |
|
179 | model_name: msg.content.data.model_name, | |
180 | model_module: msg.content.data.model_module, |
|
180 | model_module: msg.content.data.model_module, | |
181 | comm: comm}).catch(utils.reject("Couldn't create a model.")); |
|
181 | comm: comm}).catch(utils.reject("Couldn't create a model.", true)); | |
182 | }; |
|
182 | }; | |
183 |
|
183 | |||
184 | WidgetManager.prototype.create_model = function (options) { |
|
184 | WidgetManager.prototype.create_model = function (options) { |
@@ -95,7 +95,7 b' define(["widgets/js/manager",' | |||||
95 | } finally { |
|
95 | } finally { | |
96 | that.state_lock = null; |
|
96 | that.state_lock = null; | |
97 | } |
|
97 | } | |
98 |
} |
|
98 | }).catch(utils.reject("Couldn't set model state", true)); | |
99 | }, |
|
99 | }, | |
100 |
|
100 | |||
101 | _handle_status: function (msg, callbacks) { |
|
101 | _handle_status: function (msg, callbacks) { | |
@@ -292,8 +292,6 b' define(["widgets/js/manager",' | |||||
292 | // Public constructor. |
|
292 | // Public constructor. | |
293 | this.model.on('change',this.update,this); |
|
293 | this.model.on('change',this.update,this); | |
294 | this.options = parameters.options; |
|
294 | this.options = parameters.options; | |
295 | this.child_model_views = {}; |
|
|||
296 | this.child_views = {}; |
|
|||
297 | this.id = this.id || utils.uuid(); |
|
295 | this.id = this.id || utils.uuid(); | |
298 | this.model.views[this.id] = this; |
|
296 | this.model.views[this.id] = this; | |
299 | this.on('displayed', function() { |
|
297 | this.on('displayed', function() { | |
@@ -311,69 +309,7 b' define(["widgets/js/manager",' | |||||
311 | // Create and promise that resolves to a child view of a given model |
|
309 | // Create and promise that resolves to a child view of a given model | |
312 | var that = this; |
|
310 | var that = this; | |
313 | options = $.extend({ parent: this }, options || {}); |
|
311 | options = $.extend({ parent: this }, options || {}); | |
314 |
return this.model.widget_manager.create_view(child_model, options).th |
|
312 | return this.model.widget_manager.create_view(child_model, options).catch(utils.reject("Couldn't create child view"), true); | |
315 | // Associate the view id with the model id. |
|
|||
316 | if (that.child_model_views[child_model.id] === undefined) { |
|
|||
317 | that.child_model_views[child_model.id] = []; |
|
|||
318 | } |
|
|||
319 | that.child_model_views[child_model.id].push(child_view.id); |
|
|||
320 | // Remember the view by id. |
|
|||
321 | that.child_views[child_view.id] = child_view; |
|
|||
322 | return child_view; |
|
|||
323 | }, utils.reject("Couldn't create child view")); |
|
|||
324 | }, |
|
|||
325 |
|
||||
326 | pop_child_view: function(child_model) { |
|
|||
327 | // Delete a child view that was previously created using create_child_view. |
|
|||
328 | var view_ids = this.child_model_views[child_model.id]; |
|
|||
329 | if (view_ids !== undefined) { |
|
|||
330 |
|
||||
331 | // Only delete the first view in the list. |
|
|||
332 | var view_id = view_ids[0]; |
|
|||
333 | var view = this.child_views[view_id]; |
|
|||
334 | delete this.child_views[view_id]; |
|
|||
335 | view_ids.splice(0,1); |
|
|||
336 | delete child_model.views[view_id]; |
|
|||
337 |
|
||||
338 | // Remove the view list specific to this model if it is empty. |
|
|||
339 | if (view_ids.length === 0) { |
|
|||
340 | delete this.child_model_views[child_model.id]; |
|
|||
341 | } |
|
|||
342 | return view; |
|
|||
343 | } |
|
|||
344 | return null; |
|
|||
345 | }, |
|
|||
346 |
|
||||
347 | do_diff: function(old_list, new_list, removed_callback, added_callback) { |
|
|||
348 | // Difference a changed list and call remove and add callbacks for |
|
|||
349 | // each removed and added item in the new list. |
|
|||
350 | // |
|
|||
351 | // Parameters |
|
|||
352 | // ---------- |
|
|||
353 | // old_list : array |
|
|||
354 | // new_list : array |
|
|||
355 | // removed_callback : Callback(item) |
|
|||
356 | // Callback that is called for each item removed. |
|
|||
357 | // added_callback : Callback(item) |
|
|||
358 | // Callback that is called for each item added. |
|
|||
359 |
|
||||
360 | // Walk the lists until an unequal entry is found. |
|
|||
361 | var i; |
|
|||
362 | for (i = 0; i < new_list.length; i++) { |
|
|||
363 | if (i >= old_list.length || new_list[i] !== old_list[i]) { |
|
|||
364 | break; |
|
|||
365 | } |
|
|||
366 | } |
|
|||
367 |
|
||||
368 | // Remove the non-matching items from the old list. |
|
|||
369 | for (var j = i; j < old_list.length; j++) { |
|
|||
370 | removed_callback(old_list[j]); |
|
|||
371 | } |
|
|||
372 |
|
||||
373 | // Add the rest of the new list items. |
|
|||
374 | for (; i < new_list.length; i++) { |
|
|||
375 | added_callback(new_list[i]); |
|
|||
376 | } |
|
|||
377 | }, |
|
313 | }, | |
378 |
|
314 | |||
379 | callbacks: function(){ |
|
315 | callbacks: function(){ | |
@@ -533,11 +469,8 b' define(["widgets/js/manager",' | |||||
533 | if ($el===undefined) { |
|
469 | if ($el===undefined) { | |
534 | $el = this.$el; |
|
470 | $el = this.$el; | |
535 | } |
|
471 | } | |
536 |
|
|
472 | _.difference(old_classes, new_classes).map(function(c) {$el.removeClass(c);}) | |
537 | $el.removeClass(removed); |
|
473 | _.difference(new_classes, old_classes).map(function(c) {$el.addClass(c);}) | |
538 | }, function(added) { |
|
|||
539 | $el.addClass(added); |
|
|||
540 | }); |
|
|||
541 | }, |
|
474 | }, | |
542 |
|
475 | |||
543 | update_mapped_classes: function(class_map, trait_name, previous_trait_value, $el) { |
|
476 | update_mapped_classes: function(class_map, trait_name, previous_trait_value, $el) { | |
@@ -588,11 +521,93 b' define(["widgets/js/manager",' | |||||
588 | }, |
|
521 | }, | |
589 | }); |
|
522 | }); | |
590 |
|
523 | |||
591 |
|
524 | |||
|
525 | var ViewList = function(create_view, remove_view, context) { | |||
|
526 | // * create_view and remove_view are default functions called when adding or removing views | |||
|
527 | // * create_view takes a model and returns a view or a promise for a view for that model | |||
|
528 | // * remove_view takes a view and destroys it (including calling `view.remove()`) | |||
|
529 | // * each time the update() function is called with a new list, the create and remove | |||
|
530 | // callbacks will be called in an order so that if you append the views created in the | |||
|
531 | // create callback and remove the views in the remove callback, you will duplicate | |||
|
532 | // the order of the list. | |||
|
533 | // * the remove callback defaults to just removing the view (e.g., pass in null for the second parameter) | |||
|
534 | // * the context defaults to the created ViewList. If you pass another context, the create and remove | |||
|
535 | // will be called in that context. | |||
|
536 | ||||
|
537 | this.initialize.apply(this, arguments); | |||
|
538 | }; | |||
|
539 | ||||
|
540 | _.extend(ViewList.prototype, { | |||
|
541 | initialize: function(create_view, remove_view, context) { | |||
|
542 | this.state_change = Promise.resolve(); | |||
|
543 | this._handler_context = context || this; | |||
|
544 | this._models = []; | |||
|
545 | this.views = []; | |||
|
546 | this._create_view = create_view; | |||
|
547 | this._remove_view = remove_view || function(view) {view.remove();}; | |||
|
548 | }, | |||
|
549 | ||||
|
550 | update: function(new_models, create_view, remove_view, context) { | |||
|
551 | // the create_view, remove_view, and context arguments override the defaults | |||
|
552 | // specified when the list is created. | |||
|
553 | // returns a promise that resolves after this update is done | |||
|
554 | var remove = remove_view || this._remove_view; | |||
|
555 | var create = create_view || this._create_view; | |||
|
556 | if (create === undefined || remove === undefined){ | |||
|
557 | console.error("Must define a create a remove function"); | |||
|
558 | } | |||
|
559 | var context = context || this._handler_context; | |||
|
560 | var added_views = []; | |||
|
561 | var that = this; | |||
|
562 | this.state_change = this.state_change.then(function() { | |||
|
563 | var i; | |||
|
564 | // first, skip past the beginning of the lists if they are identical | |||
|
565 | for (i = 0; i < new_models.length; i++) { | |||
|
566 | if (i >= that._models.length || new_models[i] !== that._models[i]) { | |||
|
567 | break; | |||
|
568 | } | |||
|
569 | } | |||
|
570 | var first_removed = i; | |||
|
571 | // Remove the non-matching items from the old list. | |||
|
572 | for (var j = first_removed; j < that._models.length; j++) { | |||
|
573 | remove.call(context, that.views[j]); | |||
|
574 | } | |||
|
575 | ||||
|
576 | // Add the rest of the new list items. | |||
|
577 | for (; i < new_models.length; i++) { | |||
|
578 | added_views.push(create.call(context, new_models[i])); | |||
|
579 | } | |||
|
580 | // make a copy of the input array | |||
|
581 | that._models = new_models.slice(); | |||
|
582 | return Promise.all(added_views).then(function(added) { | |||
|
583 | Array.prototype.splice.apply(that.views, [first_removed, that.views.length].concat(added)); | |||
|
584 | return that.views; | |||
|
585 | }); | |||
|
586 | }); | |||
|
587 | return this.state_change; | |||
|
588 | }, | |||
|
589 | ||||
|
590 | remove: function() { | |||
|
591 | // removes every view in the list; convenience function for `.update([])` | |||
|
592 | // that should be faster | |||
|
593 | // returns a promise that resolves after this removal is done | |||
|
594 | var that = this; | |||
|
595 | this.state_change = this.state_change.then(function() { | |||
|
596 | for (var i = 0; i < that.views.length; i++) { | |||
|
597 | that._remove_view.call(that._handler_context, that.views[i]); | |||
|
598 | } | |||
|
599 | that._models = []; | |||
|
600 | that.views = []; | |||
|
601 | }); | |||
|
602 | return this.state_change; | |||
|
603 | }, | |||
|
604 | }); | |||
|
605 | ||||
592 | var widget = { |
|
606 | var widget = { | |
593 | 'WidgetModel': WidgetModel, |
|
607 | 'WidgetModel': WidgetModel, | |
594 | 'WidgetView': WidgetView, |
|
608 | 'WidgetView': WidgetView, | |
595 | 'DOMWidgetView': DOMWidgetView, |
|
609 | 'DOMWidgetView': DOMWidgetView, | |
|
610 | 'ViewList': ViewList, | |||
596 | }; |
|
611 | }; | |
597 |
|
612 | |||
598 | // For backwards compatability. |
|
613 | // For backwards compatability. |
@@ -12,16 +12,17 b' define([' | |||||
12 | initialize: function(){ |
|
12 | initialize: function(){ | |
13 | // Public constructor |
|
13 | // Public constructor | |
14 | BoxView.__super__.initialize.apply(this, arguments); |
|
14 | BoxView.__super__.initialize.apply(this, arguments); | |
15 | this.model.on('change:children', function(model, value) { |
|
15 | this.children_views = new widget.ViewList(this.add_child_model, null, this); | |
16 | this.update_children(model.previous('children'), value); |
|
16 | this.listenTo(this.model, 'change:children', function(model, value) { | |
|
17 | this.children_views.update(value); | |||
17 | }, this); |
|
18 | }, this); | |
18 |
this.model |
|
19 | this.listenTo(this.model, 'change:overflow_x', function(model, value) { | |
19 | this.update_overflow_x(); |
|
20 | this.update_overflow_x(); | |
20 | }, this); |
|
21 | }, this); | |
21 |
this.model |
|
22 | this.listenTo(this.model, 'change:overflow_y', function(model, value) { | |
22 | this.update_overflow_y(); |
|
23 | this.update_overflow_y(); | |
23 | }, this); |
|
24 | }, this); | |
24 |
this.model |
|
25 | this.listenTo(this.model, 'change:box_style', function(model, value) { | |
25 | this.update_box_style(); |
|
26 | this.update_box_style(); | |
26 | }, this); |
|
27 | }, this); | |
27 | }, |
|
28 | }, | |
@@ -35,7 +36,7 b' define([' | |||||
35 | // Called when view is rendered. |
|
36 | // Called when view is rendered. | |
36 | this.$box = this.$el; |
|
37 | this.$box = this.$el; | |
37 | this.$box.addClass('widget-box'); |
|
38 | this.$box.addClass('widget-box'); | |
38 |
this. |
|
39 | this.children_views.update(this.model.get('children')); | |
39 | this.update_overflow_x(); |
|
40 | this.update_overflow_x(); | |
40 | this.update_overflow_y(); |
|
41 | this.update_overflow_y(); | |
41 | this.update_box_style(''); |
|
42 | this.update_box_style(''); | |
@@ -61,18 +62,6 b' define([' | |||||
61 | this.update_mapped_classes(class_map, 'box_style', previous_trait_value, this.$box); |
|
62 | this.update_mapped_classes(class_map, 'box_style', previous_trait_value, this.$box); | |
62 | }, |
|
63 | }, | |
63 |
|
64 | |||
64 | update_children: function(old_list, new_list) { |
|
|||
65 | // Called when the children list changes. |
|
|||
66 | this.do_diff(old_list, new_list, |
|
|||
67 | $.proxy(this.remove_child_model, this), |
|
|||
68 | $.proxy(this.add_child_model, this)); |
|
|||
69 | }, |
|
|||
70 |
|
||||
71 | remove_child_model: function(model) { |
|
|||
72 | // Called when a model is removed from the children list. |
|
|||
73 | this.pop_child_view(model).remove(); |
|
|||
74 | }, |
|
|||
75 |
|
||||
76 | add_child_model: function(model) { |
|
65 | add_child_model: function(model) { | |
77 | // Called when a model is added to the children list. |
|
66 | // Called when a model is added to the children list. | |
78 | var that = this; |
|
67 | var that = this; | |
@@ -86,7 +75,15 b' define([' | |||||
86 | view.trigger('displayed'); |
|
75 | view.trigger('displayed'); | |
87 | }); |
|
76 | }); | |
88 | return view; |
|
77 | return view; | |
89 |
} |
|
78 | }).catch(utils.reject("Couldn't add child view to box", true)); | |
|
79 | }, | |||
|
80 | ||||
|
81 | remove: function() { | |||
|
82 | // We remove this widget before removing the children as an optimization | |||
|
83 | // we want to remove the entire container from the DOM first before | |||
|
84 | // removing each individual child separately. | |||
|
85 | BoxView.__super__.remove.apply(this, arguments); | |||
|
86 | this.children_views.remove(); | |||
90 | }, |
|
87 | }, | |
91 | }); |
|
88 | }); | |
92 |
|
89 | |||
@@ -94,10 +91,10 b' define([' | |||||
94 | var FlexBoxView = BoxView.extend({ |
|
91 | var FlexBoxView = BoxView.extend({ | |
95 | render: function(){ |
|
92 | render: function(){ | |
96 | FlexBoxView.__super__.render.apply(this); |
|
93 | FlexBoxView.__super__.render.apply(this); | |
97 |
this.model |
|
94 | this.listenTo(this.model, 'change:orientation', this.update_orientation, this); | |
98 |
this.model |
|
95 | this.listenTo(this.model, 'change:flex', this._flex_changed, this); | |
99 |
this.model |
|
96 | this.listenTo(this.model, 'change:pack', this._pack_changed, this); | |
100 |
this.model |
|
97 | this.listenTo(this.model, 'change:align', this._align_changed, this); | |
101 | this._flex_changed(); |
|
98 | this._flex_changed(); | |
102 | this._pack_changed(); |
|
99 | this._pack_changed(); | |
103 | this._align_changed(); |
|
100 | this._align_changed(); | |
@@ -244,10 +241,7 b' define([' | |||||
244 | this._shown_once = false; |
|
241 | this._shown_once = false; | |
245 | this.popped_out = true; |
|
242 | this.popped_out = true; | |
246 |
|
243 | |||
247 |
this. |
|
244 | this.children_views.update(this.model.get('children')) | |
248 | this.model.on('change:children', function(model, value) { |
|
|||
249 | this.update_children(model.previous('children'), value); |
|
|||
250 | }, this); |
|
|||
251 | }, |
|
245 | }, | |
252 |
|
246 | |||
253 | hide: function() { |
|
247 | hide: function() { |
@@ -9,18 +9,23 b' define([' | |||||
9 | ], function(widget, utils, $){ |
|
9 | ], function(widget, utils, $){ | |
10 |
|
10 | |||
11 | var AccordionView = widget.DOMWidgetView.extend({ |
|
11 | var AccordionView = widget.DOMWidgetView.extend({ | |
|
12 | initialize: function(){ | |||
|
13 | AccordionView.__super__.initialize.apply(this, arguments); | |||
|
14 | ||||
|
15 | this.containers = []; | |||
|
16 | this.model_containers = {}; | |||
|
17 | this.children_views = new widget.ViewList(this.add_child_view, this.remove_child_view, this); | |||
|
18 | this.listenTo(this.model, 'change:children', function(model, value) { | |||
|
19 | this.children_views.update(value); | |||
|
20 | }, this); | |||
|
21 | }, | |||
|
22 | ||||
12 | render: function(){ |
|
23 | render: function(){ | |
13 | // Called when view is rendered. |
|
24 | // Called when view is rendered. | |
14 | var guid = 'panel-group' + utils.uuid(); |
|
25 | var guid = 'panel-group' + utils.uuid(); | |
15 | this.$el |
|
26 | this.$el | |
16 | .attr('id', guid) |
|
27 | .attr('id', guid) | |
17 | .addClass('panel-group'); |
|
28 | .addClass('panel-group'); | |
18 | this.containers = []; |
|
|||
19 | this.model_containers = {}; |
|
|||
20 | this.update_children([], this.model.get('children')); |
|
|||
21 | this.model.on('change:children', function(model, value, options) { |
|
|||
22 | this.update_children(model.previous('children'), value); |
|
|||
23 | }, this); |
|
|||
24 | this.model.on('change:selected_index', function(model, value, options) { |
|
29 | this.model.on('change:selected_index', function(model, value, options) { | |
25 | this.update_selected_index(model.previous('selected_index'), value, options); |
|
30 | this.update_selected_index(model.previous('selected_index'), value, options); | |
26 | }, this); |
|
31 | }, this); | |
@@ -31,6 +36,7 b' define([' | |||||
31 | this.on('displayed', function() { |
|
36 | this.on('displayed', function() { | |
32 | this.update_titles(); |
|
37 | this.update_titles(); | |
33 | }, this); |
|
38 | }, this); | |
|
39 | this.children_views.update(this.model.get('children')); | |||
34 | }, |
|
40 | }, | |
35 |
|
41 | |||
36 | update_titles: function(titles) { |
|
42 | update_titles: function(titles) { | |
@@ -61,25 +67,18 b' define([' | |||||
61 | } |
|
67 | } | |
62 | } |
|
68 | } | |
63 | }, |
|
69 | }, | |
64 |
|
||||
65 | update_children: function(old_list, new_list) { |
|
|||
66 | // Called when the children list is modified. |
|
|||
67 | this.do_diff(old_list, |
|
|||
68 | new_list, |
|
|||
69 | $.proxy(this.remove_child_model, this), |
|
|||
70 | $.proxy(this.add_child_model, this)); |
|
|||
71 | }, |
|
|||
72 |
|
70 | |||
73 |
remove_child_ |
|
71 | remove_child_view: function(view) { | |
74 | // Called when a child is removed from children list. |
|
72 | // Called when a child is removed from children list. | |
|
73 | // TODO: does this handle two different views of the same model as children? | |||
|
74 | var model = view.model; | |||
75 | var accordion_group = this.model_containers[model.id]; |
|
75 | var accordion_group = this.model_containers[model.id]; | |
76 | this.containers.splice(accordion_group.container_index, 1); |
|
76 | this.containers.splice(accordion_group.container_index, 1); | |
77 | delete this.model_containers[model.id]; |
|
77 | delete this.model_containers[model.id]; | |
78 | accordion_group.remove(); |
|
78 | accordion_group.remove(); | |
79 | this.pop_child_view(model); |
|
|||
80 | }, |
|
79 | }, | |
81 |
|
80 | |||
82 |
add_child_ |
|
81 | add_child_view: function(model) { | |
83 | // Called when a child is added to children list. |
|
82 | // Called when a child is added to children list. | |
84 | var index = this.containers.length; |
|
83 | var index = this.containers.length; | |
85 | var uuid = utils.uuid(); |
|
84 | var uuid = utils.uuid(); | |
@@ -126,7 +125,15 b' define([' | |||||
126 | view.trigger('displayed'); |
|
125 | view.trigger('displayed'); | |
127 | }); |
|
126 | }); | |
128 | return view; |
|
127 | return view; | |
129 |
} |
|
128 | }).catch(utils.reject("Couldn't add child view to box", true)); | |
|
129 | }, | |||
|
130 | ||||
|
131 | remove: function() { | |||
|
132 | // We remove this widget before removing the children as an optimization | |||
|
133 | // we want to remove the entire container from the DOM first before | |||
|
134 | // removing each individual child separately. | |||
|
135 | AccordionView.__super__.remove.apply(this, arguments); | |||
|
136 | this.children_views.remove(); | |||
130 | }, |
|
137 | }, | |
131 | }); |
|
138 | }); | |
132 |
|
139 | |||
@@ -134,8 +141,13 b' define([' | |||||
134 | var TabView = widget.DOMWidgetView.extend({ |
|
141 | var TabView = widget.DOMWidgetView.extend({ | |
135 | initialize: function() { |
|
142 | initialize: function() { | |
136 | // Public constructor. |
|
143 | // Public constructor. | |
137 | this.containers = []; |
|
|||
138 | TabView.__super__.initialize.apply(this, arguments); |
|
144 | TabView.__super__.initialize.apply(this, arguments); | |
|
145 | ||||
|
146 | this.containers = []; | |||
|
147 | this.children_views = new widget.ViewList(this.add_child_view, this.remove_child_view, this); | |||
|
148 | this.listenTo(this.model, 'change:children', function(model, value) { | |||
|
149 | this.children_views.update(value); | |||
|
150 | }, this); | |||
139 | }, |
|
151 | }, | |
140 |
|
152 | |||
141 | render: function(){ |
|
153 | render: function(){ | |
@@ -149,11 +161,7 b' define([' | |||||
149 | this.$tab_contents = $('<div />', {id: uuid + 'Content'}) |
|
161 | this.$tab_contents = $('<div />', {id: uuid + 'Content'}) | |
150 | .addClass('tab-content') |
|
162 | .addClass('tab-content') | |
151 | .appendTo(this.$el); |
|
163 | .appendTo(this.$el); | |
152 | this.containers = []; |
|
164 | this.children_views.update(this.model.get('children')); | |
153 | this.update_children([], this.model.get('children')); |
|
|||
154 | this.model.on('change:children', function(model, value, options) { |
|
|||
155 | this.update_children(model.previous('children'), value); |
|
|||
156 | }, this); |
|
|||
157 | }, |
|
165 | }, | |
158 |
|
166 | |||
159 | update_attr: function(name, value) { |
|
167 | update_attr: function(name, value) { | |
@@ -161,24 +169,15 b' define([' | |||||
161 | this.$tabs.css(name, value); |
|
169 | this.$tabs.css(name, value); | |
162 | }, |
|
170 | }, | |
163 |
|
171 | |||
164 |
|
|
172 | remove_child_view: function(view) { | |
165 | // Called when the children list is modified. |
|
|||
166 | this.do_diff(old_list, |
|
|||
167 | new_list, |
|
|||
168 | $.proxy(this.remove_child_model, this), |
|
|||
169 | $.proxy(this.add_child_model, this)); |
|
|||
170 | }, |
|
|||
171 |
|
||||
172 | remove_child_model: function(model) { |
|
|||
173 | // Called when a child is removed from children list. |
|
173 | // Called when a child is removed from children list. | |
174 | var view = this.pop_child_view(model); |
|
|||
175 | this.containers.splice(view.parent_tab.tab_text_index, 1); |
|
174 | this.containers.splice(view.parent_tab.tab_text_index, 1); | |
176 | view.parent_tab.remove(); |
|
175 | view.parent_tab.remove(); | |
177 | view.parent_container.remove(); |
|
176 | view.parent_container.remove(); | |
178 | view.remove(); |
|
177 | view.remove(); | |
179 | }, |
|
178 | }, | |
180 |
|
179 | |||
181 |
add_child_ |
|
180 | add_child_view: function(model) { | |
182 | // Called when a child is added to children list. |
|
181 | // Called when a child is added to children list. | |
183 | var index = this.containers.length; |
|
182 | var index = this.containers.length; | |
184 | var uuid = utils.uuid(); |
|
183 | var uuid = utils.uuid(); | |
@@ -221,7 +220,7 b' define([' | |||||
221 | view.trigger('displayed'); |
|
220 | view.trigger('displayed'); | |
222 | }); |
|
221 | }); | |
223 | return view; |
|
222 | return view; | |
224 |
} |
|
223 | }).catch(utils.reject("Couldn't add child view to box", true)); | |
225 | }, |
|
224 | }, | |
226 |
|
225 | |||
227 | update: function(options) { |
|
226 | update: function(options) { | |
@@ -254,6 +253,14 b' define([' | |||||
254 | .removeClass('active'); |
|
253 | .removeClass('active'); | |
255 | this.containers[index].tab('show'); |
|
254 | this.containers[index].tab('show'); | |
256 | }, |
|
255 | }, | |
|
256 | ||||
|
257 | remove: function() { | |||
|
258 | // We remove this widget before removing the children as an optimization | |||
|
259 | // we want to remove the entire container from the DOM first before | |||
|
260 | // removing each individual child separately. | |||
|
261 | TabView.__super__.remove.apply(this, arguments); | |||
|
262 | this.children_views.remove(); | |||
|
263 | }, | |||
257 | }); |
|
264 | }); | |
258 |
|
265 | |||
259 | return { |
|
266 | return { |
General Comments 0
You need to be logged in to leave comments.
Login now