widget_selectioncontainer.js
242 lines
| 9.7 KiB
| application/javascript
|
JavascriptLexer
Jonathan Frederic
|
r14366 | //---------------------------------------------------------------------------- | ||
// Copyright (C) 2013 The IPython Development Team | ||||
// | ||||
// Distributed under the terms of the BSD License. The full license is in | ||||
// the file COPYING, distributed as part of this software. | ||||
//---------------------------------------------------------------------------- | ||||
//============================================================================ | ||||
Jonathan Frederic
|
r14578 | // SelectionContainerWidget | ||
Jonathan Frederic
|
r14366 | //============================================================================ | ||
/** | ||||
* @module IPython | ||||
* @namespace IPython | ||||
**/ | ||||
Jonathan Frederic
|
r14627 | define(["notebook/js/widgets/widget"], function(WidgetManager){ | ||
Jonathan Frederic
|
r14609 | |||
Jonathan Frederic
|
r14564 | var AccordionView = IPython.DOMWidgetView.extend({ | ||
Jonathan Frederic
|
r14284 | render: function(){ | ||
Jonathan Frederic
|
r14609 | // Called when view is rendered. | ||
Jonathan Frederic
|
r14398 | var guid = 'accordion' + IPython.utils.uuid(); | ||
Jonathan Frederic
|
r14455 | this.$el | ||
.attr('id', guid) | ||||
Jonathan Frederic
|
r14284 | .addClass('accordion'); | ||
this.containers = []; | ||||
Jonathan Frederic
|
r14598 | this.model_containers = {}; | ||
Jonathan Frederic
|
r14611 | this.update_children([], this.model.get('_children')); | ||
this.model.on('change:_children', function(model, value, options) { | ||||
this.update_children(model.previous('_children'), value); | ||||
Jonathan Frederic
|
r14507 | }, this); | ||
Jason Grout
|
r14503 | }, | ||
Jonathan Frederic
|
r14570 | update: function(options) { | ||
Jonathan Frederic
|
r14568 | // Update the contents of this view | ||
// | ||||
// Called when the model is changed. The model may have been | ||||
// changed by another view or by a state update from the back-end. | ||||
Jonathan Frederic
|
r14570 | if (options === undefined || options.updated_view != this) { | ||
// Set tab titles | ||||
var titles = this.model.get('_titles'); | ||||
Jonathan Frederic
|
r14664 | _.each(titles, function(title, page_index) { | ||
Jonathan Frederic
|
r14570 | var accordian = this.containers[page_index]; | ||
if (accordian !== undefined) { | ||||
accordian | ||||
.find('.accordion-heading') | ||||
.find('.accordion-toggle') | ||||
Jonathan Frederic
|
r14664 | .text(title); | ||
Jonathan Frederic
|
r14570 | } | ||
Jonathan Frederic
|
r14664 | }); | ||
Jonathan Frederic
|
r14284 | |||
Jonathan Frederic
|
r14570 | // Set selected page | ||
var selected_index = this.model.get("selected_index"); | ||||
if (0 <= selected_index && selected_index < this.containers.length) { | ||||
Jonathan Frederic
|
r14664 | _.each(this.containers, function(container, index) { | ||
Jonathan Frederic
|
r14570 | if (index==selected_index) { | ||
Jonathan Frederic
|
r14664 | container.find('.accordion-body').collapse('show'); | ||
Jonathan Frederic
|
r14570 | } else { | ||
Jonathan Frederic
|
r14664 | container.find('.accordion-body').collapse('hide'); | ||
Jonathan Frederic
|
r14570 | } | ||
Jonathan Frederic
|
r14664 | }); | ||
Jonathan Frederic
|
r14370 | } | ||
} | ||||
Jonathan Frederic
|
r14583 | return AccordionView.__super__.update.apply(this); | ||
Jonathan Frederic
|
r14284 | }, | ||
Jonathan Frederic
|
r14598 | |||
update_children: function(old_list, new_list) { | ||||
Jonathan Frederic
|
r14609 | // Called when the children list is modified. | ||
Jonathan Frederic
|
r14598 | this.do_diff(old_list, | ||
new_list, | ||||
$.proxy(this.remove_child_model, this), | ||||
$.proxy(this.add_child_model, this)); | ||||
}, | ||||
Jonathan Frederic
|
r14284 | |||
Jonathan Frederic
|
r14598 | remove_child_model: function(model) { | ||
Jonathan Frederic
|
r14609 | // Called when a child is removed from children list. | ||
Jonathan Frederic
|
r14598 | var accordion_group = this.model_containers[model.id]; | ||
this.containers.splice(accordion_group.container_index, 1); | ||||
delete this.model_containers[model.id]; | ||||
accordion_group.remove(); | ||||
this.delete_child_view(model); | ||||
}, | ||||
Jonathan Frederic
|
r14284 | |||
Jonathan Frederic
|
r14598 | add_child_model: function(model) { | ||
Jonathan Frederic
|
r14609 | // Called when a child is added to children list. | ||
Jonathan Frederic
|
r14598 | var view = this.create_child_view(model); | ||
Jonathan Frederic
|
r14284 | var index = this.containers.length; | ||
var uuid = IPython.utils.uuid(); | ||||
var accordion_group = $('<div />') | ||||
.addClass('accordion-group') | ||||
.appendTo(this.$el); | ||||
var accordion_heading = $('<div />') | ||||
.addClass('accordion-heading') | ||||
.appendTo(accordion_group); | ||||
Jonathan Frederic
|
r14370 | var that = this; | ||
Jonathan Frederic
|
r14284 | var accordion_toggle = $('<a />') | ||
.addClass('accordion-toggle') | ||||
.attr('data-toggle', 'collapse') | ||||
.attr('data-parent', '#' + this.$el.attr('id')) | ||||
.attr('href', '#' + uuid) | ||||
Jonathan Frederic
|
r14370 | .click(function(evt){ | ||
Jonathan Frederic
|
r14569 | |||
// Calling model.set will trigger all of the other views of the | ||||
// model to update. | ||||
Jonathan Frederic
|
r14570 | that.model.set("selected_index", index, {updated_view: this}); | ||
Jonathan Frederic
|
r14482 | that.touch(); | ||
Jonathan Frederic
|
r14370 | }) | ||
Jonathan Frederic
|
r14663 | .text('Page ' + index) | ||
Jonathan Frederic
|
r14284 | .appendTo(accordion_heading); | ||
var accordion_body = $('<div />', {id: uuid}) | ||||
Jonathan Frederic
|
r14288 | .addClass('accordion-body collapse') | ||
Jonathan Frederic
|
r14284 | .appendTo(accordion_group); | ||
var accordion_inner = $('<div />') | ||||
.addClass('accordion-inner') | ||||
.appendTo(accordion_body); | ||||
Jonathan Frederic
|
r14598 | var container_index = this.containers.push(accordion_group) - 1; | ||
accordion_group.container_index = container_index; | ||||
this.model_containers[model.id] = accordion_group; | ||||
Jonathan Frederic
|
r14284 | accordion_inner.append(view.$el); | ||
Jonathan Frederic
|
r14370 | |||
Jonathan Frederic
|
r14289 | this.update(); | ||
Jonathan Frederic
|
r14370 | |||
// Stupid workaround to close the bootstrap accordion tabs which | ||||
// open by default even though they don't have the `in` class | ||||
// attached to them. For some reason a delay is required. | ||||
// TODO: Better fix. | ||||
Jonathan Frederic
|
r14466 | setTimeout(function(){ that.update(); }, 500); | ||
Jonathan Frederic
|
r14284 | }, | ||
}); | ||||
Jonathan Frederic
|
r14627 | WidgetManager.register_widget_view('AccordionView', AccordionView); | ||
Jonathan Frederic
|
r14290 | |||
Jonathan Frederic
|
r14609 | |||
var TabView = IPython.DOMWidgetView.extend({ | ||||
Jonathan Frederic
|
r14507 | initialize: function() { | ||
Jonathan Frederic
|
r14609 | // Public constructor. | ||
Jonathan Frederic
|
r14507 | this.containers = []; | ||
Jonathan Frederic
|
r14583 | TabView.__super__.initialize.apply(this, arguments); | ||
Jonathan Frederic
|
r14507 | }, | ||
Jason Grout
|
r14486 | |||
Jonathan Frederic
|
r14290 | render: function(){ | ||
Jonathan Frederic
|
r14609 | // Called when view is rendered. | ||
Jonathan Frederic
|
r14398 | var uuid = 'tabs'+IPython.utils.uuid(); | ||
Jonathan Frederic
|
r14307 | var that = this; | ||
Jonathan Frederic
|
r14290 | this.$tabs = $('<div />', {id: uuid}) | ||
.addClass('nav') | ||||
.addClass('nav-tabs') | ||||
.appendTo(this.$el); | ||||
this.$tab_contents = $('<div />', {id: uuid + 'Content'}) | ||||
.addClass('tab-content') | ||||
.appendTo(this.$el); | ||||
Jonathan Frederic
|
r14507 | this.containers = []; | ||
Jonathan Frederic
|
r14611 | this.update_children([], this.model.get('_children')); | ||
this.model.on('change:_children', function(model, value, options) { | ||||
this.update_children(model.previous('_children'), value); | ||||
Jonathan Frederic
|
r14507 | }, this); | ||
}, | ||||
Jonathan Frederic
|
r14609 | |||
Jonathan Frederic
|
r14598 | update_children: function(old_list, new_list) { | ||
Jonathan Frederic
|
r14609 | // Called when the children list is modified. | ||
Jonathan Frederic
|
r14598 | this.do_diff(old_list, | ||
new_list, | ||||
$.proxy(this.remove_child_model, this), | ||||
$.proxy(this.add_child_model, this)); | ||||
}, | ||||
Jonathan Frederic
|
r14370 | |||
Jonathan Frederic
|
r14598 | remove_child_model: function(model) { | ||
Jonathan Frederic
|
r14609 | // Called when a child is removed from children list. | ||
Jonathan Frederic
|
r14598 | var view = this.child_views[model.id]; | ||
this.containers.splice(view.parent_tab.tab_text_index, 1); | ||||
view.parent_tab.remove(); | ||||
view.parent_container.remove(); | ||||
view.remove(); | ||||
this.delete_child_view(model); | ||||
Jonathan Frederic
|
r14290 | }, | ||
Jonathan Frederic
|
r14598 | add_child_model: function(model) { | ||
Jonathan Frederic
|
r14609 | // Called when a child is added to children list. | ||
Jonathan Frederic
|
r14598 | var view = this.create_child_view(model); | ||
Jonathan Frederic
|
r14290 | var index = this.containers.length; | ||
var uuid = IPython.utils.uuid(); | ||||
var that = this; | ||||
var tab = $('<li />') | ||||
.css('list-style-type', 'none') | ||||
.appendTo(this.$tabs); | ||||
Jonathan Frederic
|
r14598 | view.parent_tab = tab; | ||
Jonathan Frederic
|
r14290 | var tab_text = $('<a />') | ||
.attr('href', '#' + uuid) | ||||
.attr('data-toggle', 'tab') | ||||
Jonathan Frederic
|
r14663 | .text('Page ' + index) | ||
Jonathan Frederic
|
r14290 | .appendTo(tab) | ||
.click(function (e) { | ||||
Jonathan Frederic
|
r14569 | |||
// Calling model.set will trigger all of the other views of the | ||||
// model to update. | ||||
Jonathan Frederic
|
r14570 | that.model.set("selected_index", index, {updated_view: this}); | ||
Jonathan Frederic
|
r14482 | that.touch(); | ||
Jonathan Frederic
|
r14307 | that.select_page(index); | ||
Jonathan Frederic
|
r14290 | }); | ||
Jonathan Frederic
|
r14598 | tab.tab_text_index = this.containers.push(tab_text) - 1; | ||
Jonathan Frederic
|
r14290 | |||
var contents_div = $('<div />', {id: uuid}) | ||||
.addClass('tab-pane') | ||||
.addClass('fade') | ||||
.append(view.$el) | ||||
.appendTo(this.$tab_contents); | ||||
Jonathan Frederic
|
r14598 | view.parent_container = contents_div; | ||
}, | ||||
update: function(options) { | ||||
// Update the contents of this view | ||||
// | ||||
// Called when the model is changed. The model may have been | ||||
// changed by another view or by a state update from the back-end. | ||||
if (options === undefined || options.updated_view != this) { | ||||
// Set tab titles | ||||
var titles = this.model.get('_titles'); | ||||
Jonathan Frederic
|
r14664 | _.each(titles, function(title, page_index) { | ||
var tab_text = this.containers[page_index]; | ||||
Jonathan Frederic
|
r14598 | if (tab_text !== undefined) { | ||
Jonathan Frederic
|
r14664 | tab_text.text(title); | ||
} | ||||
}); | ||||
Jonathan Frederic
|
r14598 | |||
var selected_index = this.model.get('selected_index'); | ||||
if (0 <= selected_index && selected_index < this.containers.length) { | ||||
this.select_page(selected_index); | ||||
} | ||||
} | ||||
return TabView.__super__.update.apply(this); | ||||
Jonathan Frederic
|
r14290 | }, | ||
Jonathan Frederic
|
r14307 | |||
select_page: function(index) { | ||||
Jonathan Frederic
|
r14609 | // Select a page. | ||
Jonathan Frederic
|
r14307 | this.$tabs.find('li') | ||
.removeClass('active'); | ||||
this.containers[index].tab('show'); | ||||
}, | ||||
Jonathan Frederic
|
r14290 | }); | ||
Jonathan Frederic
|
r14627 | WidgetManager.register_widget_view('TabView', TabView); | ||
Jonathan Frederic
|
r14290 | }); | ||