##// END OF EJS Templates
Remove the popup widget
Jonathan Frederic -
Show More
@@ -1,369 +1,153 b''
1 1 // Copyright (c) IPython Development Team.
2 2 // Distributed under the terms of the Modified BSD License.
3 3
4 4 define([
5 5 "widgets/js/widget",
6 6 "jqueryui",
7 7 "base/js/utils",
8 8 "bootstrap",
9 9 ], function(widget, $, utils){
10 10
11 11 var BoxView = widget.DOMWidgetView.extend({
12 12 initialize: function(){
13 13 /**
14 14 * Public constructor
15 15 */
16 16 BoxView.__super__.initialize.apply(this, arguments);
17 17 this.children_views = new widget.ViewList(this.add_child_model, null, this);
18 18 this.listenTo(this.model, 'change:children', function(model, value) {
19 19 this.children_views.update(value);
20 20 }, this);
21 21 this.listenTo(this.model, 'change:overflow_x', function(model, value) {
22 22 this.update_overflow_x();
23 23 }, this);
24 24 this.listenTo(this.model, 'change:overflow_y', function(model, value) {
25 25 this.update_overflow_y();
26 26 }, this);
27 27 this.listenTo(this.model, 'change:box_style', function(model, value) {
28 28 this.update_box_style();
29 29 }, this);
30 30 },
31 31
32 32 update_attr: function(name, value) {
33 33 /**
34 34 * Set a css attr of the widget view.
35 35 */
36 36 this.$box.css(name, value);
37 37 },
38 38
39 39 render: function(){
40 40 /**
41 41 * Called when view is rendered.
42 42 */
43 43 this.$box = this.$el;
44 44 this.$box.addClass('widget-box');
45 45 this.children_views.update(this.model.get('children'));
46 46 this.update_overflow_x();
47 47 this.update_overflow_y();
48 48 this.update_box_style('');
49 49 },
50 50
51 51 update_overflow_x: function() {
52 52 /**
53 53 * Called when the x-axis overflow setting is changed.
54 54 */
55 55 this.$box.css('overflow-x', this.model.get('overflow_x'));
56 56 },
57 57
58 58 update_overflow_y: function() {
59 59 /**
60 60 * Called when the y-axis overflow setting is changed.
61 61 */
62 62 this.$box.css('overflow-y', this.model.get('overflow_y'));
63 63 },
64 64
65 65 update_box_style: function(previous_trait_value) {
66 66 var class_map = {
67 67 success: ['alert', 'alert-success'],
68 68 info: ['alert', 'alert-info'],
69 69 warning: ['alert', 'alert-warning'],
70 70 danger: ['alert', 'alert-danger']
71 71 };
72 72 this.update_mapped_classes(class_map, 'box_style', previous_trait_value, this.$box);
73 73 },
74 74
75 75 add_child_model: function(model) {
76 76 /**
77 77 * Called when a model is added to the children list.
78 78 */
79 79 var that = this;
80 80 var dummy = $('<div/>');
81 81 that.$box.append(dummy);
82 82 return this.create_child_view(model).then(function(view) {
83 83 dummy.replaceWith(view.el);
84 84
85 85 // Trigger the displayed event of the child view.
86 86 that.after_displayed(function() {
87 87 view.trigger('displayed');
88 88 });
89 89 return view;
90 90 }).catch(utils.reject("Couldn't add child view to box", true));
91 91 },
92 92
93 93 remove: function() {
94 94 /**
95 95 * We remove this widget before removing the children as an optimization
96 96 * we want to remove the entire container from the DOM first before
97 97 * removing each individual child separately.
98 98 */
99 99 BoxView.__super__.remove.apply(this, arguments);
100 100 this.children_views.remove();
101 101 },
102 102 });
103 103
104 104
105 105 var FlexBoxView = BoxView.extend({
106 106 render: function(){
107 107 FlexBoxView.__super__.render.apply(this);
108 108 this.listenTo(this.model, 'change:orientation', this.update_orientation, this);
109 109 this.listenTo(this.model, 'change:flex', this._flex_changed, this);
110 110 this.listenTo(this.model, 'change:pack', this._pack_changed, this);
111 111 this.listenTo(this.model, 'change:align', this._align_changed, this);
112 112 this._flex_changed();
113 113 this._pack_changed();
114 114 this._align_changed();
115 115 this.update_orientation();
116 116 },
117 117
118 118 update_orientation: function(){
119 119 var orientation = this.model.get("orientation");
120 120 if (orientation == "vertical") {
121 121 this.$box.removeClass("hbox").addClass("vbox");
122 122 } else {
123 123 this.$box.removeClass("vbox").addClass("hbox");
124 124 }
125 125 },
126 126
127 127 _flex_changed: function(){
128 128 if (this.model.previous('flex')) {
129 129 this.$box.removeClass('box-flex' + this.model.previous('flex'));
130 130 }
131 131 this.$box.addClass('box-flex' + this.model.get('flex'));
132 132 },
133 133
134 134 _pack_changed: function(){
135 135 if (this.model.previous('pack')) {
136 136 this.$box.removeClass(this.model.previous('pack'));
137 137 }
138 138 this.$box.addClass(this.model.get('pack'));
139 139 },
140 140
141 141 _align_changed: function(){
142 142 if (this.model.previous('align')) {
143 143 this.$box.removeClass('align-' + this.model.previous('align'));
144 144 }
145 145 this.$box.addClass('align-' + this.model.get('align'));
146 146 },
147 147 });
148 148
149 var PopupView = BoxView.extend({
150
151 render: function(){
152 /**
153 * Called when view is rendered.
154 */
155 var that = this;
156
157 this.$el.on("remove", function(){
158 that.$backdrop.remove();
159 });
160 this.$backdrop = $('<div />')
161 .appendTo($('#notebook-container'))
162 .addClass('modal-dialog')
163 .css('position', 'absolute')
164 .css('left', '0px')
165 .css('top', '0px');
166 this.$window = $('<div />')
167 .appendTo(this.$backdrop)
168 .addClass('modal-content widget-modal')
169 .mousedown(function(){
170 that.bring_to_front();
171 });
172
173 // Set the elements array since the this.$window element is not child
174 // of this.$el and the parent widget manager or other widgets may
175 // need to know about all of the top-level widgets. The IPython
176 // widget manager uses this to register the elements with the
177 // keyboard manager.
178 this.additional_elements = [this.$window];
179
180 this.$title_bar = $('<div />')
181 .addClass('popover-title')
182 .appendTo(this.$window)
183 .mousedown(function(){
184 that.bring_to_front();
185 });
186 this.$close = $('<button />')
187 .addClass('close fa fa-remove')
188 .css('margin-left', '5px')
189 .appendTo(this.$title_bar)
190 .click(function(){
191 that.hide();
192 event.stopPropagation();
193 });
194 this.$minimize = $('<button />')
195 .addClass('close fa fa-arrow-down')
196 .appendTo(this.$title_bar)
197 .click(function(){
198 that.popped_out = !that.popped_out;
199 if (!that.popped_out) {
200 that.$minimize
201 .removeClass('fa-arrow-down')
202 .addClass('fa-arrow-up');
203
204 that.$window
205 .draggable('destroy')
206 .resizable('destroy')
207 .removeClass('widget-modal modal-content')
208 .addClass('docked-widget-modal')
209 .detach()
210 .insertBefore(that.$show_button);
211 that.$show_button.hide();
212 that.$close.hide();
213 } else {
214 that.$minimize
215 .addClass('fa-arrow-down')
216 .removeClass('fa-arrow-up');
217
218 that.$window
219 .removeClass('docked-widget-modal')
220 .addClass('widget-modal modal-content')
221 .detach()
222 .appendTo(that.$backdrop)
223 .draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'})
224 .resizable()
225 .children('.ui-resizable-handle').show();
226 that.show();
227 that.$show_button.show();
228 that.$close.show();
229 }
230 event.stopPropagation();
231 });
232 this.$title = $('<div />')
233 .addClass('widget-modal-title')
234 .html("&nbsp;")
235 .appendTo(this.$title_bar);
236 this.$box = $('<div />')
237 .addClass('modal-body')
238 .addClass('widget-modal-body')
239 .addClass('widget-box')
240 .addClass('vbox')
241 .appendTo(this.$window);
242
243 this.$show_button = $('<button />')
244 .html("&nbsp;")
245 .addClass('btn btn-info widget-modal-show')
246 .appendTo(this.$el)
247 .click(function(){
248 that.show();
249 });
250
251 this.$window.draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'});
252 this.$window.resizable();
253 this.$window.on('resize', function(){
254 that.$box.outerHeight(that.$window.innerHeight() - that.$title_bar.outerHeight());
255 });
256
257 this._shown_once = false;
258 this.popped_out = true;
259
260 this.children_views.update(this.model.get('children'))
261 },
262
263 hide: function() {
264 /**
265 * Called when the modal hide button is clicked.
266 */
267 this.$window.hide();
268 this.$show_button.removeClass('btn-info');
269 },
270
271 show: function() {
272 /**
273 * Called when the modal show button is clicked.
274 */
275 this.$show_button.addClass('btn-info');
276 this.$window.show();
277 if (this.popped_out) {
278 this.$window.css("positon", "absolute");
279 this.$window.css("top", "0px");
280 this.$window.css("left", Math.max(0, (($('body').outerWidth() - this.$window.outerWidth()) / 2) +
281 $(window).scrollLeft()) + "px");
282 this.bring_to_front();
283 }
284 },
285
286 bring_to_front: function() {
287 /**
288 * Make the modal top-most, z-ordered about the other modals.
289 */
290 var $widget_modals = $(".widget-modal");
291 var max_zindex = 0;
292 $widget_modals.each(function (index, el){
293 var zindex = parseInt($(el).css('z-index'));
294 if (!isNaN(zindex)) {
295 max_zindex = Math.max(max_zindex, zindex);
296 }
297 });
298
299 // Start z-index of widget modals at 2000
300 max_zindex = Math.max(max_zindex, 2000);
301
302 $widget_modals.each(function (index, el){
303 $el = $(el);
304 if (max_zindex == parseInt($el.css('z-index'))) {
305 $el.css('z-index', max_zindex - 1);
306 }
307 });
308 this.$window.css('z-index', max_zindex);
309 },
310
311 update: function(){
312 /**
313 * Update the contents of this view
314 *
315 * Called when the model is changed. The model may have been
316 * changed by another view or by a state update from the back-end.
317 */
318 var description = this.model.get('description');
319 if (description.trim().length === 0) {
320 this.$title.html("&nbsp;"); // Preserve title height
321 } else {
322 this.typeset(this.$title, description);
323 }
324
325 var button_text = this.model.get('button_text');
326 if (button_text.trim().length === 0) {
327 this.$show_button.html("&nbsp;"); // Preserve button height
328 } else {
329 this.$show_button.text(button_text);
330 }
331
332 if (!this._shown_once) {
333 this._shown_once = true;
334 this.show();
335 }
336
337 return PopupView.__super__.update.apply(this);
338 },
339
340 _get_selector_element: function(selector) {
341 /**
342 * Get an element view a 'special' jquery selector. (see widget.js)
343 *
344 * Since the modal actually isn't within the $el in the DOM, we need to extend
345 * the selector logic to allow the user to set css on the modal if need be.
346 * The convention used is:
347 * "modal" - select the modal div
348 * "modal [selector]" - select element(s) within the modal div.
349 * "[selector]" - select elements within $el
350 * "" - select the $el
351 */
352 if (selector.substring(0, 5) == 'modal') {
353 if (selector == 'modal') {
354 return this.$window;
355 } else {
356 return this.$window.find(selector.substring(6));
357 }
358 } else {
359 return PopupView.__super__._get_selector_element.apply(this, [selector]);
360 }
361 },
362 });
363
364 149 return {
365 150 'BoxView': BoxView,
366 'PopupView': PopupView,
367 151 'FlexBoxView': FlexBoxView,
368 152 };
369 153 });
@@ -1,38 +1,38 b''
1 1 from .widget import Widget, DOMWidget, CallbackDispatcher, register
2 2
3 3 from .widget_bool import Checkbox, ToggleButton
4 4 from .widget_button import Button
5 from .widget_box import Box, Popup, FlexBox, HBox, VBox
5 from .widget_box import Box, FlexBox, HBox, VBox
6 6 from .widget_float import FloatText, BoundedFloatText, FloatSlider, FloatProgress, FloatRangeSlider
7 7 from .widget_image import Image
8 8 from .widget_int import IntText, BoundedIntText, IntSlider, IntProgress, IntRangeSlider
9 9 from .widget_output import Output
10 10 from .widget_selection import RadioButtons, ToggleButtons, Dropdown, Select
11 11 from .widget_selectioncontainer import Tab, Accordion
12 12 from .widget_string import HTML, Latex, Text, Textarea
13 13 from .interaction import interact, interactive, fixed, interact_manual
14 14 from .widget_link import Link, link, DirectionalLink, dlink
15 15
16 16 # Deprecated classes
17 17 from .widget_bool import CheckboxWidget, ToggleButtonWidget
18 18 from .widget_button import ButtonWidget
19 from .widget_box import ContainerWidget, PopupWidget
19 from .widget_box import ContainerWidget
20 20 from .widget_float import FloatTextWidget, BoundedFloatTextWidget, FloatSliderWidget, FloatProgressWidget
21 21 from .widget_image import ImageWidget
22 22 from .widget_int import IntTextWidget, BoundedIntTextWidget, IntSliderWidget, IntProgressWidget
23 23 from .widget_selection import RadioButtonsWidget, ToggleButtonsWidget, DropdownWidget, SelectWidget
24 24 from .widget_selectioncontainer import TabWidget, AccordionWidget
25 25 from .widget_string import HTMLWidget, LatexWidget, TextWidget, TextareaWidget
26 26
27 27 # We use warn_explicit so we have very brief messages without file or line numbers.
28 28 # The concern is that file or line numbers will confuse the interactive user.
29 29 # To ignore this warning, do:
30 30 #
31 31 # from warnings import filterwarnings
32 32 # filterwarnings('ignore', module='IPython.html.widgets')
33 33
34 34 from warnings import warn_explicit
35 35 __warningregistry__ = {}
36 36 warn_explicit("IPython widgets are experimental and may change in the future.",
37 37 FutureWarning, '', 0, module = 'IPython.html.widgets',
38 38 registry = __warningregistry__, module_globals = globals)
@@ -1,91 +1,80 b''
1 1 """Box class.
2 2
3 3 Represents a container that can be used to group other widgets.
4 4 """
5 5
6 6 # Copyright (c) IPython Development Team.
7 7 # Distributed under the terms of the Modified BSD License.
8 8
9 9 from .widget import DOMWidget, register
10 10 from IPython.utils.traitlets import Unicode, Tuple, TraitError, Int, CaselessStrEnum
11 11 from IPython.utils.warn import DeprecatedClass
12 12
13 13 @register('IPython.Box')
14 14 class Box(DOMWidget):
15 15 """Displays multiple widgets in a group."""
16 16 _view_name = Unicode('BoxView', sync=True)
17 17
18 18 # Child widgets in the container.
19 19 # Using a tuple here to force reassignment to update the list.
20 20 # When a proper notifying-list trait exists, that is what should be used here.
21 21 children = Tuple(sync=True, allow_none=False)
22 22
23 23 _overflow_values = ['visible', 'hidden', 'scroll', 'auto', 'initial', 'inherit', '']
24 24 overflow_x = CaselessStrEnum(
25 25 values=_overflow_values,
26 26 default_value='', allow_none=False, sync=True, help="""Specifies what
27 27 happens to content that is too large for the rendered region.""")
28 28 overflow_y = CaselessStrEnum(
29 29 values=_overflow_values,
30 30 default_value='', allow_none=False, sync=True, help="""Specifies what
31 31 happens to content that is too large for the rendered region.""")
32 32
33 33 box_style = CaselessStrEnum(
34 34 values=['success', 'info', 'warning', 'danger', ''],
35 35 default_value='', allow_none=True, sync=True, help="""Use a
36 36 predefined styling for the box.""")
37 37
38 38 def __init__(self, children = (), **kwargs):
39 39 kwargs['children'] = children
40 40 super(Box, self).__init__(**kwargs)
41 41 self.on_displayed(Box._fire_children_displayed)
42 42
43 43 def _fire_children_displayed(self):
44 44 for child in self.children:
45 45 child._handle_displayed()
46 46
47 47
48 @register('IPython.Popup')
49 class Popup(Box):
50 """Displays multiple widgets in an in page popup div."""
51 _view_name = Unicode('PopupView', sync=True)
52
53 description = Unicode(sync=True)
54 button_text = Unicode(sync=True)
55
56
57 48 @register('IPython.FlexBox')
58 49 class FlexBox(Box):
59 50 """Displays multiple widgets using the flexible box model."""
60 51 _view_name = Unicode('FlexBoxView', sync=True)
61 52 orientation = CaselessStrEnum(values=['vertical', 'horizontal'], default_value='vertical', sync=True)
62 53 flex = Int(0, sync=True, help="""Specify the flexible-ness of the model.""")
63 54 def _flex_changed(self, name, old, new):
64 55 new = min(max(0, new), 2)
65 56 if self.flex != new:
66 57 self.flex = new
67 58
68 59 _locations = ['start', 'center', 'end', 'baseline', 'stretch']
69 60 pack = CaselessStrEnum(
70 61 values=_locations,
71 62 default_value='start', allow_none=False, sync=True)
72 63 align = CaselessStrEnum(
73 64 values=_locations,
74 65 default_value='start', allow_none=False, sync=True)
75 66
76 67
77 68 def VBox(*pargs, **kwargs):
78 69 """Displays multiple widgets vertically using the flexible box model."""
79 70 kwargs['orientation'] = 'vertical'
80 71 return FlexBox(*pargs, **kwargs)
81 72
82 73 def HBox(*pargs, **kwargs):
83 74 """Displays multiple widgets horizontally using the flexible box model."""
84 75 kwargs['orientation'] = 'horizontal'
85 76 return FlexBox(*pargs, **kwargs)
86 77
87 78
88 79 # Remove in IPython 4.0
89 80 ContainerWidget = DeprecatedClass(Box, 'ContainerWidget')
90 PopupWidget = DeprecatedClass(Popup, 'PopupWidget')
91
General Comments 0
You need to be logged in to leave comments. Login now