##// END OF EJS Templates
Fix logic, use box where applicable
Jonathan Frederic -
Show More
@@ -1,307 +1,307
1 // Copyright (c) IPython Development Team.
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
2 // Distributed under the terms of the Modified BSD License.
3
3
4 define([
4 define([
5 "widgets/js/widget",
5 "widgets/js/widget",
6 "jqueryui",
6 "jqueryui",
7 "bootstrap",
7 "bootstrap",
8 ], function(widget, $){
8 ], function(widget, $){
9
9
10 var BoxView = widget.DOMWidgetView.extend({
10 var BoxView = widget.DOMWidgetView.extend({
11 initialize: function(){
11 initialize: function(){
12 // Public constructor
12 // Public constructor
13 BoxView.__super__.initialize.apply(this, arguments);
13 BoxView.__super__.initialize.apply(this, arguments);
14 this.update_children([], this.model.get('children'));
15 this.model.on('change:children', function(model, value) {
14 this.model.on('change:children', function(model, value) {
16 this.update_children(model.previous('children'), value);
15 this.update_children(model.previous('children'), value);
17 }, this);
16 }, this);
18 },
17 },
19
18
20 render: function(){
19 render: function(){
21 // Called when view is rendered.
20 // Called when view is rendered.
22 this.$box = this.$el;
21 this.$box = $el;
23 this.$el.addClass('widget-box');
22 this.$box.addClass('widget-box');
23 this.update_children([], this.model.get('children'));
24 },
24 },
25
25
26 update_children: function(old_list, new_list) {
26 update_children: function(old_list, new_list) {
27 // Called when the children list changes.
27 // Called when the children list changes.
28 this.do_diff(old_list, new_list,
28 this.do_diff(old_list, new_list,
29 $.proxy(this.remove_child_model, this),
29 $.proxy(this.remove_child_model, this),
30 $.proxy(this.add_child_model, this));
30 $.proxy(this.add_child_model, this));
31 },
31 },
32
32
33 remove_child_model: function(model) {
33 remove_child_model: function(model) {
34 // Called when a model is removed from the children list.
34 // Called when a model is removed from the children list.
35 this.pop_child_view(model).remove();
35 this.pop_child_view(model).remove();
36 },
36 },
37
37
38 add_child_model: function(model) {
38 add_child_model: function(model) {
39 // Called when a model is added to the children list.
39 // Called when a model is added to the children list.
40 var view = this.create_child_view(model);
40 var view = this.create_child_view(model);
41 this.$box.append(view.$el);
41 this.$box.append(view.$el);
42
42
43 // Trigger the displayed event of the child view.
43 // Trigger the displayed event of the child view.
44 this.after_displayed(function() {
44 this.after_displayed(function() {
45 view.trigger('displayed');
45 view.trigger('displayed');
46 });
46 });
47 },
47 },
48 });
48 });
49
49
50
50
51 var FlexBoxView = BoxView.extend({
51 var FlexBoxView = BoxView.extend({
52 render: function(){
52 render: function(){
53 FlexBoxView.__super__.render.apply(this);
53 FlexBoxView.__super__.render.apply(this);
54 this.model.on('change:orientation', this.update_orientation, this);
54 this.model.on('change:orientation', this.update_orientation, this);
55 this.model.on('change:flex', this._flex_changed, this);
55 this.model.on('change:flex', this._flex_changed, this);
56 this.model.on('change:pack', this._pack_changed, this);
56 this.model.on('change:pack', this._pack_changed, this);
57 this.model.on('change:align', this._align_changed, this);
57 this.model.on('change:align', this._align_changed, this);
58 this._flex_changed();
58 this._flex_changed();
59 this._pack_changed();
59 this._pack_changed();
60 this._align_changed();
60 this._align_changed();
61 that.update_orientation();
61 that.update_orientation();
62 },
62 },
63
63
64 update_orientation: function(){
64 update_orientation: function(){
65 var orientation = this.model.get("orientation");
65 var orientation = this.model.get("orientation");
66 if (orientation == "vertical") {
66 if (orientation == "vertical") {
67 this.$el.removeClass("hbox").addClass("vbox");
67 this.$box.removeClass("hbox").addClass("vbox");
68 } else {
68 } else {
69 this.$el.removeClass("vbox").addClass("hbox");
69 this.$box.removeClass("vbox").addClass("hbox");
70 }
70 }
71 },
71 },
72
72
73 _flex_changed: function(){
73 _flex_changed: function(){
74 if (this.model.previous('flex')) {
74 if (this.model.previous('flex')) {
75 this.$el.removeClass('box-flex' + this.model.previous('flex'));
75 this.$box.removeClass('box-flex' + this.model.previous('flex'));
76 }
76 }
77 this.$el.addClass('box-flex' + this.model.get('flex'));
77 this.$box.addClass('box-flex' + this.model.get('flex'));
78 },
78 },
79
79
80 _pack_changed: function(){
80 _pack_changed: function(){
81 if (this.model.previous('pack')) {
81 if (this.model.previous('pack')) {
82 this.$el.removeClass(this.model.previous('pack'));
82 this.$box.removeClass(this.model.previous('pack'));
83 }
83 }
84 this.$el.addClass(this.model.get('pack'));
84 this.$box.addClass(this.model.get('pack'));
85 },
85 },
86
86
87 _align_changed: function(){
87 _align_changed: function(){
88 if (this.model.previous('align')) {
88 if (this.model.previous('align')) {
89 this.$el.removeClass('align-' + this.model.previous('align'));
89 this.$box.removeClass('align-' + this.model.previous('align'));
90 }
90 }
91 this.$el.addClass('align-' + this.model.get('align'));
91 this.$box.addClass('align-' + this.model.get('align'));
92 },
92 },
93 });
93 });
94
94
95 var PopupView = BoxView.extend({
95 var PopupView = BoxView.extend({
96
96 render: function(){
97 render: function(){
97 // Called when view is rendered.
98 // Called when view is rendered.
98 var that = this;
99 var that = this;
99
100
100 this.$el.on("remove", function(){
101 this.$el.on("remove", function(){
101 that.$backdrop.remove();
102 that.$backdrop.remove();
102 });
103 });
103 this.$backdrop = $('<div />')
104 this.$backdrop = $('<div />')
104 .appendTo($('#notebook-container'))
105 .appendTo($('#notebook-container'))
105 .addClass('modal-dialog')
106 .addClass('modal-dialog')
106 .css('position', 'absolute')
107 .css('position', 'absolute')
107 .css('left', '0px')
108 .css('left', '0px')
108 .css('top', '0px');
109 .css('top', '0px');
109 this.$window = $('<div />')
110 this.$window = $('<div />')
110 .appendTo(this.$backdrop)
111 .appendTo(this.$backdrop)
111 .addClass('modal-content widget-modal')
112 .addClass('modal-content widget-modal')
112 .mousedown(function(){
113 .mousedown(function(){
113 that.bring_to_front();
114 that.bring_to_front();
114 });
115 });
115
116
116 // Set the elements array since the this.$window element is not child
117 // Set the elements array since the this.$window element is not child
117 // of this.$el and the parent widget manager or other widgets may
118 // of this.$el and the parent widget manager or other widgets may
118 // need to know about all of the top-level widgets. The IPython
119 // need to know about all of the top-level widgets. The IPython
119 // widget manager uses this to register the elements with the
120 // widget manager uses this to register the elements with the
120 // keyboard manager.
121 // keyboard manager.
121 this.additional_elements = [this.$window];
122 this.additional_elements = [this.$window];
122
123
123 this.$title_bar = $('<div />')
124 this.$title_bar = $('<div />')
124 .addClass('popover-title')
125 .addClass('popover-title')
125 .appendTo(this.$window)
126 .appendTo(this.$window)
126 .mousedown(function(){
127 .mousedown(function(){
127 that.bring_to_front();
128 that.bring_to_front();
128 });
129 });
129 this.$close = $('<button />')
130 this.$close = $('<button />')
130 .addClass('close fa fa-remove')
131 .addClass('close fa fa-remove')
131 .css('margin-left', '5px')
132 .css('margin-left', '5px')
132 .appendTo(this.$title_bar)
133 .appendTo(this.$title_bar)
133 .click(function(){
134 .click(function(){
134 that.hide();
135 that.hide();
135 event.stopPropagation();
136 event.stopPropagation();
136 });
137 });
137 this.$minimize = $('<button />')
138 this.$minimize = $('<button />')
138 .addClass('close fa fa-arrow-down')
139 .addClass('close fa fa-arrow-down')
139 .appendTo(this.$title_bar)
140 .appendTo(this.$title_bar)
140 .click(function(){
141 .click(function(){
141 that.popped_out = !that.popped_out;
142 that.popped_out = !that.popped_out;
142 if (!that.popped_out) {
143 if (!that.popped_out) {
143 that.$minimize
144 that.$minimize
144 .removeClass('fa fa-arrow-down')
145 .removeClass('fa fa-arrow-down')
145 .addClass('fa fa-arrow-up');
146 .addClass('fa fa-arrow-up');
146
147
147 that.$window
148 that.$window
148 .draggable('destroy')
149 .draggable('destroy')
149 .resizable('destroy')
150 .resizable('destroy')
150 .removeClass('widget-modal modal-content')
151 .removeClass('widget-modal modal-content')
151 .addClass('docked-widget-modal')
152 .addClass('docked-widget-modal')
152 .detach()
153 .detach()
153 .insertBefore(that.$show_button);
154 .insertBefore(that.$show_button);
154 that.$show_button.hide();
155 that.$show_button.hide();
155 that.$close.hide();
156 that.$close.hide();
156 } else {
157 } else {
157 that.$minimize
158 that.$minimize
158 .addClass('fa fa-arrow-down')
159 .addClass('fa fa-arrow-down')
159 .removeClass('fa fa-arrow-up');
160 .removeClass('fa fa-arrow-up');
160
161
161 that.$window
162 that.$window
162 .removeClass('docked-widget-modal')
163 .removeClass('docked-widget-modal')
163 .addClass('widget-modal modal-content')
164 .addClass('widget-modal modal-content')
164 .detach()
165 .detach()
165 .appendTo(that.$backdrop)
166 .appendTo(that.$backdrop)
166 .draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'})
167 .draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'})
167 .resizable()
168 .resizable()
168 .children('.ui-resizable-handle').show();
169 .children('.ui-resizable-handle').show();
169 that.show();
170 that.show();
170 that.$show_button.show();
171 that.$show_button.show();
171 that.$close.show();
172 that.$close.show();
172 }
173 }
173 event.stopPropagation();
174 event.stopPropagation();
174 });
175 });
175 this.$title = $('<div />')
176 this.$title = $('<div />')
176 .addClass('widget-modal-title')
177 .addClass('widget-modal-title')
177 .html("&nbsp;")
178 .html("&nbsp;")
178 .appendTo(this.$title_bar);
179 .appendTo(this.$title_bar);
179 this.$body = $('<div />')
180 this.$box = $('<div />')
180 .addClass('modal-body')
181 .addClass('modal-body')
181 .addClass('widget-modal-body')
182 .addClass('widget-modal-body')
182 .addClass('widget-box')
183 .addClass('widget-box')
183 .addClass('vbox')
184 .addClass('vbox')
184 .appendTo(this.$window);
185 .appendTo(this.$window);
185 this.$box = this.$body;
186
186
187 this.$show_button = $('<button />')
187 this.$show_button = $('<button />')
188 .html("&nbsp;")
188 .html("&nbsp;")
189 .addClass('btn btn-info widget-modal-show')
189 .addClass('btn btn-info widget-modal-show')
190 .appendTo(this.$el)
190 .appendTo(this.$el)
191 .click(function(){
191 .click(function(){
192 that.show();
192 that.show();
193 });
193 });
194
194
195 this.$window.draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'});
195 this.$window.draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'});
196 this.$window.resizable();
196 this.$window.resizable();
197 this.$window.on('resize', function(){
197 this.$window.on('resize', function(){
198 that.$body.outerHeight(that.$window.innerHeight() - that.$title_bar.outerHeight());
198 that.$box.outerHeight(that.$window.innerHeight() - that.$title_bar.outerHeight());
199 });
199 });
200
200
201 this._shown_once = false;
201 this._shown_once = false;
202 this.popped_out = true;
202 this.popped_out = true;
203
203
204 this.update_children([], this.model.get('children'));
204 this.update_children([], this.model.get('children'));
205 this.model.on('change:children', function(model, value) {
205 this.model.on('change:children', function(model, value) {
206 this.update_children(model.previous('children'), value);
206 this.update_children(model.previous('children'), value);
207 }, this);
207 }, this);
208 },
208 },
209
209
210 hide: function() {
210 hide: function() {
211 // Called when the modal hide button is clicked.
211 // Called when the modal hide button is clicked.
212 this.$window.hide();
212 this.$window.hide();
213 this.$show_button.removeClass('btn-info');
213 this.$show_button.removeClass('btn-info');
214 },
214 },
215
215
216 show: function() {
216 show: function() {
217 // Called when the modal show button is clicked.
217 // Called when the modal show button is clicked.
218 this.$show_button.addClass('btn-info');
218 this.$show_button.addClass('btn-info');
219 this.$window.show();
219 this.$window.show();
220 if (this.popped_out) {
220 if (this.popped_out) {
221 this.$window.css("positon", "absolute");
221 this.$window.css("positon", "absolute");
222 this.$window.css("top", "0px");
222 this.$window.css("top", "0px");
223 this.$window.css("left", Math.max(0, (($('body').outerWidth() - this.$window.outerWidth()) / 2) +
223 this.$window.css("left", Math.max(0, (($('body').outerWidth() - this.$window.outerWidth()) / 2) +
224 $(window).scrollLeft()) + "px");
224 $(window).scrollLeft()) + "px");
225 this.bring_to_front();
225 this.bring_to_front();
226 }
226 }
227 },
227 },
228
228
229 bring_to_front: function() {
229 bring_to_front: function() {
230 // Make the modal top-most, z-ordered about the other modals.
230 // Make the modal top-most, z-ordered about the other modals.
231 var $widget_modals = $(".widget-modal");
231 var $widget_modals = $(".widget-modal");
232 var max_zindex = 0;
232 var max_zindex = 0;
233 $widget_modals.each(function (index, el){
233 $widget_modals.each(function (index, el){
234 var zindex = parseInt($(el).css('z-index'));
234 var zindex = parseInt($(el).css('z-index'));
235 if (!isNaN(zindex)) {
235 if (!isNaN(zindex)) {
236 max_zindex = Math.max(max_zindex, zindex);
236 max_zindex = Math.max(max_zindex, zindex);
237 }
237 }
238 });
238 });
239
239
240 // Start z-index of widget modals at 2000
240 // Start z-index of widget modals at 2000
241 max_zindex = Math.max(max_zindex, 2000);
241 max_zindex = Math.max(max_zindex, 2000);
242
242
243 $widget_modals.each(function (index, el){
243 $widget_modals.each(function (index, el){
244 $el = $(el);
244 $el = $(el);
245 if (max_zindex == parseInt($el.css('z-index'))) {
245 if (max_zindex == parseInt($el.css('z-index'))) {
246 $el.css('z-index', max_zindex - 1);
246 $el.css('z-index', max_zindex - 1);
247 }
247 }
248 });
248 });
249 this.$window.css('z-index', max_zindex);
249 this.$window.css('z-index', max_zindex);
250 },
250 },
251
251
252 update: function(){
252 update: function(){
253 // Update the contents of this view
253 // Update the contents of this view
254 //
254 //
255 // Called when the model is changed. The model may have been
255 // Called when the model is changed. The model may have been
256 // changed by another view or by a state update from the back-end.
256 // changed by another view or by a state update from the back-end.
257 var description = this.model.get('description');
257 var description = this.model.get('description');
258 if (description.trim().length === 0) {
258 if (description.trim().length === 0) {
259 this.$title.html("&nbsp;"); // Preserve title height
259 this.$title.html("&nbsp;"); // Preserve title height
260 } else {
260 } else {
261 this.$title.text(description);
261 this.$title.text(description);
262 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$title.get(0)]);
262 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$title.get(0)]);
263 }
263 }
264
264
265 var button_text = this.model.get('button_text');
265 var button_text = this.model.get('button_text');
266 if (button_text.trim().length === 0) {
266 if (button_text.trim().length === 0) {
267 this.$show_button.html("&nbsp;"); // Preserve button height
267 this.$show_button.html("&nbsp;"); // Preserve button height
268 } else {
268 } else {
269 this.$show_button.text(button_text);
269 this.$show_button.text(button_text);
270 }
270 }
271
271
272 if (!this._shown_once) {
272 if (!this._shown_once) {
273 this._shown_once = true;
273 this._shown_once = true;
274 this.show();
274 this.show();
275 }
275 }
276
276
277 return PopupView.__super__.update.apply(this);
277 return PopupView.__super__.update.apply(this);
278 },
278 },
279
279
280 _get_selector_element: function(selector) {
280 _get_selector_element: function(selector) {
281 // Get an element view a 'special' jquery selector. (see widget.js)
281 // Get an element view a 'special' jquery selector. (see widget.js)
282 //
282 //
283 // Since the modal actually isn't within the $el in the DOM, we need to extend
283 // Since the modal actually isn't within the $el in the DOM, we need to extend
284 // the selector logic to allow the user to set css on the modal if need be.
284 // the selector logic to allow the user to set css on the modal if need be.
285 // The convention used is:
285 // The convention used is:
286 // "modal" - select the modal div
286 // "modal" - select the modal div
287 // "modal [selector]" - select element(s) within the modal div.
287 // "modal [selector]" - select element(s) within the modal div.
288 // "[selector]" - select elements within $el
288 // "[selector]" - select elements within $el
289 // "" - select the $el
289 // "" - select the $el
290 if (selector.substring(0, 5) == 'modal') {
290 if (selector.substring(0, 5) == 'modal') {
291 if (selector == 'modal') {
291 if (selector == 'modal') {
292 return this.$window;
292 return this.$window;
293 } else {
293 } else {
294 return this.$window.find(selector.substring(6));
294 return this.$window.find(selector.substring(6));
295 }
295 }
296 } else {
296 } else {
297 return PopupView.__super__._get_selector_element.apply(this, [selector]);
297 return PopupView.__super__._get_selector_element.apply(this, [selector]);
298 }
298 }
299 },
299 },
300 });
300 });
301
301
302 return {
302 return {
303 'BoxView': BoxView,
303 'BoxView': BoxView,
304 'PopupView': PopupView,
304 'PopupView': PopupView,
305 'FlexBoxView': FlexBoxView,
305 'FlexBoxView': FlexBoxView,
306 };
306 };
307 });
307 });
General Comments 0
You need to be logged in to leave comments. Login now